Android NDK实现Gif播放框架

Posted nullZgy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android NDK实现Gif播放框架相关的知识,希望对你有一定的参考价值。

 android中实现GIF播放,目前大多数的方法是通过获取到GIT资源后转为流,再通过ImageView.setBitMap .下面我通过JNI调用Android系统里的代码进行播放。代码结构如下图:

 

下面一步一步的贴代码讲解。

首先在MainActivity里有一个ImageView用于显示GIF。这里的比较简单,获取内存卡里的Gif文件,通过GiFHandler调用SO。

package zgy.gitcode;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import java.io.File;

public class MainActivity extends Activity 
    private ImageView imageView;
    private GifHandler gifHandler;
    private Bitmap bitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = findViewById(R.id.image_view);
    

    public void JniLoad(View view) 
        File f = new File(Environment.getExternalStorageState(), "demo.gif");

        gifHandler = GifHandler.loadGit(f.getAbsolutePath());

       int w = gifHandler.getWidth();
       int h = gifHandler.getHeight();
        Log.d("zgy", "w = " + w + " , h = " + h);

        bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

        imageView.setImageBitmap(bitmap);

        int delay = gifHandler.updateFream(bitmap);
        mHandler.sendEmptyMessageAtTime(1, delay);
    

    private Handler mHandler = new Handler(Looper.getMainLooper())
        @Override
        public void handleMessage(@NonNull Message msg) 
            int delay = gifHandler.updateFream(bitmap);
            mHandler.sendEmptyMessageAtTime(1, delay);

            imageView.setImageBitmap(bitmap);
        
    ;

    public void JacaLoad(View view) 
    
package zgy.gitcode;

import android.graphics.Bitmap;

public class GifHandler 
     long gitHandler;

    static 
        System.loadLibrary("native-lib");
    

    public static GifHandler loadGit(String path)
        long gitHandler = load(path);
        return new GifHandler(gitHandler);
    

    public GifHandler(long gitHandler)
        this.gitHandler = gitHandler;
    

   public int getWidth()
        return getWidth(gitHandler);
    

    public int getHeight()
        return getHeight(gitHandler);
    

    public int updateFream(Bitmap bitmap)
        return updateFream(gitHandler, bitmap);
    

    public static native long load(String path);

    public static native int getWidth(long handler);

    public static native int getHeight(long handler);

    public static native int updateFream(long handler, Bitmap bitmap);

#include <jni.h>
#include <string>
#include <android/bitmap.h>

extern "C"
#include "gif_lib.h"

#define  argb(a,r,g,b) ( ((a) & 0xff) << 24 ) | ( ((b) & 0xff) << 16 ) | ( ((g) & 0xff) << 8 ) | ((r) & 0xff)

struct GifBean
    int current_fream;
    int total_fream;
    int *delays;
;

extern "C"
JNIEXPORT jint JNICALL Java_zgy_gitcode_GifHandler_getWidth(JNIEnv* env, jclass jcls, jlong handler)
       GifFileType *gifFileType =  reinterpret_cast<GifFileType *>(handler);
       return gifFileType->SWidth;


extern "C" JNIEXPORT jint
JNICALL Java_zgy_gitcode_GifHandler_getHeight(JNIEnv* env, jclass jcls, jlong handler)
        GifFileType *gifFileType =  reinterpret_cast<GifFileType *>(handler);
        return gifFileType->SHeight;


extern "C" JNIEXPORT jlong JNICALL Java_zgy_gitcode_GifHandler_load(JNIEnv* env, jclass jcls, jstring path_)
        const char *path = env->GetStringUTFChars(path_, 0);
        int Erro;//打开失败还是成功
//        GifFileType * gifFileType = DGifOpenFileName(path, &Erro);
          GifFileType * gifFileType= DGifOpenFileName(path, &Erro);
        DGifSlurp(gifFileType);

        GifBean *gifBean = static_cast<GifBean*>(malloc(sizeof(GifBean)));
        memset(gifBean, 0, sizeof(GifBean)); //初始化

        gifFileType->UserData = gifBean;
        gifBean->current_fream = 0;
        gifBean->total_fream = gifFileType->ImageCount;

        env->ReleaseStringUTFChars(path_, path);

        return (long)(gifFileType);


void drawFrameGif(GifFileType *gifFileType, AndroidBitmapInfo info, void *pixels) 
    GifBean *gifBean = static_cast<GifBean *>(gifFileType->UserData);
    //当前帧 一定要拿到         拿到当前帧   直接
    SavedImage savedImage = gifFileType->SavedImages[gifBean->current_fream];
//    图像分成两部分  像素   一部分是 描述
    GifImageDesc frameInfo=savedImage.ImageDesc;
    ColorMapObject *colorMapObject = frameInfo.ColorMap;
//    像素
//    savedImage.RasterBits[i];
//记录每一行的首地址
//bitmap
    int* px = (int *)pixels;

//    临时 索引
    int *line;
//    索引
    int  pointPixel;
    GifByteType  gifByteType;
//操作   解压
    GifColorType gifColorType;
    for (int y =frameInfo.Top ; y<frameInfo.Top+frameInfo.Height; ++y) 
//每次遍历行    首地址 传给line
        line = px;
        for (int x =  frameInfo.Left; x < frameInfo.Left + frameInfo.Width ; ++x) 
//            定位像素  索引
            pointPixel = (y - frameInfo.Top) * frameInfo.Width + (x - frameInfo.Left);
//            是 1不是2  压缩
            gifByteType=savedImage.RasterBits[pointPixel];
            gifColorType= colorMapObject->Colors[gifByteType];
//line 进行复制   0  255  屏幕有颜色 line
            line[x] = argb(255, gifColorType.Red, gifColorType.Green, gifColorType.Blue);
        
//遍历条件     转到下一行
        px = (int *) ((char *) px + info.stride);
    


extern "C" JNIEXPORT jint JNICALL Java_zgy_gitcode_GifHandler_updateFream(JNIEnv* env, jclass jcls, jlong gif_point, jobject bitmap) 
//    bitmap.get
    GifFileType *gifFileType = reinterpret_cast<GifFileType *>(gif_point);
    int width = gifFileType->SWidth;

    int height = gifFileType->SHeight;
//    还有另外一种    根据bitmap 获取
    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, bitmap, &info);

//    ------------
    width = info.width;
    height = info.height;

    void *pixels;
    AndroidBitmap_lockPixels(env, bitmap, &pixels);
    drawFrameGif(gifFileType, info, pixels);
    AndroidBitmap_unlockPixels(env, bitmap);
    GifBean *gifBean = static_cast<GifBean *>(gifFileType->UserData);
    gifBean->current_fream++;
    if (gifBean->current_fream >= gifBean->total_fream - 1) 
        gifBean->current_fream = 0;
    
    return 100;

代码下载地址:https://download.csdn.net/download/u011694328/18394673

以上是关于Android NDK实现Gif播放框架的主要内容,如果未能解决你的问题,请参考以下文章

Android NDK实现Gif播放框架

Android 实现Gif播放的七种方法

Android ndk 加载简单的gif 图像

Android-Glide 4.0+ 加载GIF并控制播放次数

Android加载Gif动画

Android开发之ImageView播放GIF动画实例