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播放框架的主要内容,如果未能解决你的问题,请参考以下文章