gifflen 在出现 b = (((*p)) & 0xff) << netbiasshift; 问题时的解决办法

gifflen 调用以及错误处理

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

这句话在gifflen中经常出错,发现原来是源码的一个bug,修正如下:


if (p >= (unsigned int *)lim)
    p -= lengthcount;

变为:

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

原文:http://blog.leepood.com/the-android-gif-maker


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

首先NDK的环境搭建我就不讲了,这些可以查网上的,首选去http://jiggawatt.org/badc0de/android/index.html#gifflen下载gifflen的源码来编译。

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

?
1
com.leepood.gifmaker.GifUtil

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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();
 
     }
 
}


以上是原文。


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

?
1
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中出了问题:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/* 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<rad; 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 < samplepixels) {
/*b = p[0] << netbiasshift;
g = p[1] << netbiasshift;
r = p[2] << netbiasshift;*/
b = (((*p)) & 0xff) << netbiasshift;
g = (((*p) >> 8) & 0xff) << netbiasshift;
r = (((*p) >> 16) & 0xff) << netbiasshift;
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<rad; 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了,不会出问题了。


你可能感兴趣的:(gifflen 在出现 b = (((*p)) & 0xff) << netbiasshift; 问题时的解决办法)