android gif 处理,gifflen 调用以及错误处理

博客讲述了在Android项目中利用NDK合成GIF动画的需求及实现过程。作者通过修改下载的源码并进行编译,成功生成libgifflen.so库。在Java代码中调用 native 方法添加帧并编码为GIF,但在运行时出现SIGSEGV错误。通过调试发现错误发生在循环学习过程中,通过对代码的调整解决了问题。
摘要由CSDN通过智能技术生成

/*

http://my.oschina.net/lifj/blog/233670

*/

最近做项目有个需求就是将若干张图片合成Gif动画,大家都知道在Android平台上目前是不支持Gif的,所以利用本地的Api是不可能达到目的的,于是上网查资料,得知用NDK可以达到目的OK,折腾一番搞定,下面分享下:

下载到源码之后我们要做的就是修改下方法名称,NDK里面书写方法的名称需同你native 类的包名相同,举个例子我的native方法类的完整路径是:

com.leepood.gifmaker.GifUtil

那么我需要将下载回来的源码里面的jni call的方法名称改为以Java_com_leepood_gifmaker_GitUtil_开头,这样一切就OK拉,于是NDK编译得到libgifflen.so文件。(注意:修改有六个地方:声明和实现总共6处,都要修改)

于是在java里面调用,上我写的代码:

package com.leepood.gifmaker;

import android.graphics.Bitmap;

import android.util.Log;

public class GifUtil {

private final String TAG=this.getClass().getName();

static

{

System.loadLibrary("gifflen");

}

/**

* Init the gif file

* @param gifName name

* @param w width

* @param h height

* @param numColors colors

* @param quality

* @param frameDelay times

* @return

*/

public native int Init(String gifName, int w, int h, int numColors, int quality,

int frameDelay);

public native void Close();

public native int AddFrame(int[] pixels);

/**

* encode the bitmaps to gif

* @param fileName

* @param bitmaps

* @param delay

*/

public void Encode(String fileName,Bitmap[] bitmaps,int delay)

{

if(bitmaps==null||bitmaps.length==0)

{

throw new NullPointerException("Bitmaps should have content!!!");

}

int width=bitmaps[0].getWidth();

int height=bitmaps[0].getHeight();

if(Init(fileName,width,height,256,100,delay)!=0)

{

Log.e(TAG, "GifUtil init failed");

return;

}

for(Bitmap bp:bitmaps)

{

int pixels[]=new int[width*height];

bp.getPixels(pixels, 0, width, 0, 0, width, height);

AddFrame(pixels);

}

Close();

}

}

以上是原文。

但是在具体运行的时候,会发现有如下错误:

Fatal signal 11 (SIGSEGV) at 0x5c1f2258 (code=2), thread 12065 (Thread-99423)

致命的信号 11 和在应用程序重新启动。

日志如下:

I/DEBUG(95): backtrace:

I/DEBUG(95):     #00  pc 00002a04  /lib/libgifflen.so (NeuQuant::learn()+239)

I/DEBUG(95):     #01  pc 00002b9d  /lib/libgifflen.so (NeuQuant::quantise(DIB*, DIB*, int, int, int)+84)

I/DEBUG(95):     #02  pc 00002d41  lib/libgifflen.so (Java_com_stay_gif_GifEncoder_addFrame+208)

I/DEBUG(95):     #03  pc 0001deb0  /system/lib/libdvm.so (dvmPlatformInvoke+112)

I/DEBUG(95):     #04  pc 0004d103  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+394)

I/DEBUG(95):     #05  pc 0004f21f  /system/lib/libdvm.so (dvmResolveNativeMethod(unsigned int const*, JValue*, Method const*, Thread*)+174)

I/DEBUG(95):     #06  pc 000272e0  /system/lib/libdvm.so

I/DEBUG(95):     #07  pc 0002bbe8  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)

I/DEBUG(95):     #08  pc 0005fb37  /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+374)

I/DEBUG(95):     #09  pc 000670e5  /system/lib/libdvm.so

I/DEBUG(95):     #10  pc 000272e0  /system/lib/libdvm.so

I/DEBUG(95):     #11  pc 0002bbe8  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)

I/DEBUG(95):     #12  pc 0005f871  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)

I/DEBUG(95):     #13  pc 000496f3  /system/lib/libdvm.so

I/DEBUG(95):     #14  pc 00048581  /system/lib/libandroid_runtime.so

I/DEBUG(95):     #15  pc 00049637  /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+390)

I/DEBUG(95):     #16  pc 00000dcf  /system/bin/app_process

看到是在learn中出了问题:

/* Main Learning Loop

------------------ */

void NeuQuant::learn()

{

int i,j,b,g,r;

int radius,rad,alpha,step,delta,samplepixels;

//unsigned char *p;

unsigned int *p;

unsigned char *lim;

alphadec = 30 + ((samplefac-1)/3);

p = (unsigned int*)thepicture;

lim = thepicture + lengthcount;

samplepixels = lengthcount/(PIXEL_SIZE*samplefac);

delta = samplepixels/ncycles;

alpha = initalpha;

radius = initradius;

rad = radius >> radiusbiasshift;

if (rad <= 1) rad = 0;

for (i=0; i

radpower[i] = alpha*(((rad*rad - i*i)*radbias)/(rad*rad));

//fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad);

sprintf(s, "samplepixels = %d, rad = %d, a=%d, ad=%d, d=%d", samplepixels, rad, alpha, alphadec, delta);

__android_log_write(ANDROID_LOG_VERBOSE, "gifflen",s);

if ((lengthcount%prime1) != 0) step = prime1;

else {

if ((lengthcount%prime2) !=0) step = prime2;

else {

if ((lengthcount%prime3) !=0) step = prime3;

else step = prime4;

}

}

i = 0;

while (i 

/*b = p[0] <

g = p[1] <

r = p[2] <

b = (((*p)) & 0xff) <

g = (((*p) >> 8) & 0xff) <

r = (((*p) >> 16) & 0xff) <

j = contest(b,g,r);

altersingle(alpha,j,b,g,r);

if (rad) alterneigh(rad,j,b,g,r);   /* alter neighbours */

p += step;

if (p >= (unsigned int *)lim) p -= lengthcount; //这里有问题

i++;

if (i%delta == 0) {

alpha -= alpha / alphadec;

radius -= radius / radiusdec;

rad = radius >> radiusbiasshift;

if (rad <= 1) rad = 0;

for (j=0; j

radpower[j] = alpha*(((rad*rad - j*j)*radbias)/(rad*rad));

}

}

sprintf(s, "final alpha = %f", ((float)alpha)/initalpha);

__android_log_write(ANDROID_LOG_VERBOSE, "gifflen",s);

}

我改变了:

if (p >= (unsigned int *)lim)

p -= lengthcount;

变为:

if (p >= (unsigned int *)lim)

p = (unsigned int*)thepicture;

这样就OK了,不会出问题了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值