Android中Gif播放

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);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值