Android中Gif播放

来源:互联网 发布:windows连不上aws 编辑:程序博客网 时间:2024/05/21 18:44

DEMO地址:https://github.com/zhaopingfu/GifPlayerDemo

Gif 格式图片详细解析:http://blog.csdn.net/wzy198852/article/details/17266507

Android中Gif播放一般有三种方式

自定义View

    这里用了一个开源库提供的自定义gifview    https://code.google.com/archive/p/gifview/downloads

NDK方式

这里以android-gif-drawable为例,但是不是用的这个库,是用的系统的代码
系统代码在\android-6.0.0_r1\external\giflib
先将gif放在外置卡的根目录下
final File file = newFile(Environment.getExternalStorageDirectory(), “demo.gif”);

    还需要自己写一些    #include <jni.h>    #include <string>    #include "gif_lib.h"    #include <android/log.h>    #include <android/bitmap.h>    #include <malloc.h>    #define LOG_TAG "pf"    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)    #define argb(a, r, g, b)(((a) & 0xff) << 24) | ((r) & 0xff)| (((g) & 0xff) << 8)| (((b) & 0xff) << 16)    typedef struct GifBean {        int current_frame;        int total_frame;        int *delayed;    } GifBean;    extern "C"    {    JNIEXPORT jlong JNICALL    Java_com_pf_gifplayerdemo_ndk_GifHandler_loadPath(JNIEnv *env, jobject instance, jstring path_) {        const char *path = env->GetStringUTFChars(path_, NULL);        int err;        //用系统函数打开一个gif文件,返回一个结构体,这个结构体为句柄        GifFileType *gifFileType = DGifOpenFileName(path, &err);        DGifSlurp(gifFileType);        //封装成自己想要的        GifBean *gifBean = (GifBean *) malloc(sizeof(struct GifBean));        //清空内存地址        memset(gifBean, 0, sizeof(struct GifBean));        //相当于view.setTag        gifFileType->UserData = gifBean;        gifBean->delayed = (int *) malloc(sizeof(int) * gifFileType->ImageCount);        memset(gifBean->delayed, 0, (sizeof(int) * gifFileType->ImageCount));        gifBean->total_frame = gifFileType->ImageCount;        ExtensionBlock *ext;        int i, j;        for (i = 0; i < gifFileType->ImageCount; i++) {            SavedImage frame = gifFileType->SavedImages[i];            for (j = 0; j < frame.ExtensionBlockCount; j++) {                if (frame.ExtensionBlocks[j].Function == GRAPHICS_EXT_FUNC_CODE) {                    ext = &frame.ExtensionBlocks[j];                    break;                }            }            if (ext) {                int frame_delay = 10 * (ext->Bytes[2] << 8 | ext->Bytes[1]);                LOGE("时间:%d", frame_delay);                gifBean->delayed[i] = frame_delay;            }        }        LOGE("gif长度大小:%d", gifFileType->ImageCount);        env->ReleaseStringUTFChars(path_, path);        return (jlong) gifFileType;    }    JNIEXPORT jint JNICALL    Java_com_pf_gifplayerdemo_ndk_GifHandler_getWidth(JNIEnv *env, jobject instance, jlong ndkGif) {        return ((GifFileType *) ndkGif)->SWidth;    }    JNIEXPORT jint JNICALL    Java_com_pf_gifplayerdemo_ndk_GifHandler_getHeight(JNIEnv *env, jobject instance, jlong ndkGif) {        return ((GifFileType *) ndkGif)->SHeight;    }    //绘制一张图片        void drawFrame(GifFileType *gifFileType, GifBean *gifBean, AndroidBitmapInfo androidBitmapInfo,                       void *pixels) {            //拿到当前帧            SavedImage savedImage = gifFileType->SavedImages[gifBean->current_frame];            GifImageDesc gifImageDesc = savedImage.ImageDesc;            //整幅图片的首地址            int *px = (int *) pixels;            //每一行的首地址            int *line;            //其中一个像素的位置,不是指针,在颜色表中的索引            int pointPixel;            GifByteType gifByteType;            GifColorType gifColorType;            ColorMapObject *colorMapObject = gifImageDesc.ColorMap;            px = (int *) ((char *) px + androidBitmapInfo.stride * gifImageDesc.Top);            int x, y;            for (y = gifImageDesc.Top; y < gifImageDesc.Top + gifImageDesc.Height; ++y) {                line = px;                for (x = gifImageDesc.Left; x < gifImageDesc.Left + gifImageDesc.Width; ++x) {                    pointPixel = (y - gifImageDesc.Top) * gifImageDesc.Width + (x - gifImageDesc.Left);                    gifByteType = savedImage.RasterBits[pointPixel];                    gifColorType = colorMapObject->Colors[gifByteType];                    line[x] = argb(255, gifColorType.Red, gifColorType.Green, gifColorType.Blue);                }                px = (int *) ((char *) px + androidBitmapInfo.stride);            }        }        JNIEXPORT jint JNICALL        Java_com_pf_gifplayerdemo_ndk_GifHandler_updateFrame(JNIEnv *env, jobject instance, jobject bitmap,                                                             jlong ndkGif) {            GifFileType *gifFileType = (GifFileType *) ndkGif;            GifBean *gifBean = (GifBean *) gifFileType->UserData;            AndroidBitmapInfo androidBitmapInfo;            //代表一幅图片的像素数组            void *pixels;            AndroidBitmap_getInfo(env, bitmap, &androidBitmapInfo);            //锁定bitmap 一幅图片->二维数组            AndroidBitmap_lockPixels(env, bitmap, &pixels);            //TODO            drawFrame(gifFileType, gifBean, androidBitmapInfo, pixels);            //播放完之后,循环到下一帧            gifBean->current_frame += 1;            LOGE("当前帧:%d", gifBean->current_frame);            if (gifBean->current_frame >= gifBean->total_frame - 1) {                gifBean->current_frame = 0;                LOGE("重新来过,当前帧:%d", gifBean->current_frame);            }            AndroidBitmap_unlockPixels(env, bitmap);            return gifBean->delayed[gifBean->current_frame];        }    }

WebView方式

    直接将gif放在assets路径下    webview = (WebView) findViewById(R.id.webview);        String url = "file:///android_asset/demo.gif";        WebSettings webSettings = webview.getSettings();        webSettings.setJavaScriptEnabled(true);         // User settings        webSettings.setJavaScriptEnabled(true);        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);        webSettings.setUseWideViewPort(true);//关键点        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);        webSettings.setDisplayZoomControls(false);        webSettings.setJavaScriptEnabled(true); // 设置支持javascript脚本        webSettings.setAllowFileAccess(true); // 允许访问文件        webSettings.setBuiltInZoomControls(true); // 设置显示缩放按钮        webSettings.setSupportZoom(true); // 支持缩放        webSettings.setLoadWithOverviewMode(true);        DisplayMetrics metrics = new DisplayMetrics();        getWindowManager().getDefaultDisplay().getMetrics(metrics);        int mDensity = metrics.densityDpi;        Log.d("maomao", "densityDpi = " + mDensity);        if (mDensity == 240) {            webSettings.setDefaultZoom(WebSettings.ZoomDensity.FAR);        } else if (mDensity == 160) {            webSettings.setDefaultZoom(WebSettings.ZoomDensity.MEDIUM);        } else if(mDensity == 120) {            webSettings.setDefaultZoom(WebSettings.ZoomDensity.CLOSE);        }else if(mDensity == DisplayMetrics.DENSITY_XHIGH){            webSettings.setDefaultZoom(WebSettings.ZoomDensity.FAR);        }else if (mDensity == DisplayMetrics.DENSITY_TV){            webSettings.setDefaultZoom(WebSettings.ZoomDensity.FAR);        }else{            webSettings.setDefaultZoom(WebSettings.ZoomDensity.MEDIUM);        }        /**         * 用WebView显示图片,可使用这个参数 设置网页布局类型:         * 1、LayoutAlgorithm.NARROW_COLUMNS 适应内容大小         * 2、LayoutAlgorithm.SINGLE_COLUMN:适应屏幕,内容将自动缩放         */        //webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);          webview.loadUrl(url);
原创粉丝点击