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


原文: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方法类的完整路径是:

com.leepood.gifmaker.GifUtil

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

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

packagecom.leepood.gifmaker;importandroid.graphics.Bitmap;importandroid.util.Log;publicclassGifUtil{privatefinalStringTAG=this.getClass().getName();static{System.loadLibrary("gifflen");}/***Initthegiffile*@paramgifNamename*@paramwwidth*@paramhheight*@paramnumColorscolors*@paramquality*@paramframeDelaytimes*@return*/publicnativeintInit(StringgifName,intw,inth,intnumColors,intquality,intframeDelay);publicnativevoidClose();publicnativeintAddFrame(int[]pixels);/***encodethebitmapstogif*@paramfileName*@parambitmaps*@paramdelay*/publicvoidEncode(StringfileName,Bitmap[]bitmaps,intdelay){if(bitmaps==null||bitmaps.length==0){thrownewNullPointerException("Bitmapsshouldhavecontent!!!");}intwidth=bitmaps[0].getWidth();intheight=bitmaps[0].getHeight();if(Init(fileName,width,height,256,100,delay)!=0){Log.e(TAG,"GifUtilinitfailed");return;}for(Bitmapbp:bitmaps){intpixels[]=newint[width*height];bp.getPixels(pixels,0,width,0,0,width,height);AddFrame(pixels);}Close();}}


以上是原文。


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

Fatalsignal11(SIGSEGV)at0x5c1f2258(code=2),thread12065(Thread-99423)

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

日志如下:


I/DEBUG(95):backtrace:I/DEBUG(95):#00pc00002a04/lib/libgifflen.so(NeuQuant::learn()+239)I/DEBUG(95):#01pc00002b9d/lib/libgifflen.so(NeuQuant::quantise(DIB*,DIB*,int,int,int)+84)I/DEBUG(95):#02pc00002d41lib/libgifflen.so(Java_com_stay_gif_GifEncoder_addFrame+208)I/DEBUG(95):#03pc0001deb0/system/lib/libdvm.so(dvmPlatformInvoke+112)I/DEBUG(95):#04pc0004d103/system/lib/libdvm.so(dvmCallJNIMethod(unsignedintconst*,JValue*,Methodconst*,Thread*)+394)I/DEBUG(95):#05pc0004f21f/system/lib/libdvm.so(dvmResolveNativeMethod(unsignedintconst*,JValue*,Methodconst*,Thread*)+174)I/DEBUG(95):#06pc000272e0/system/lib/libdvm.soI/DEBUG(95):#07pc0002bbe8/system/lib/libdvm.so(dvmInterpret(Thread*,Methodconst*,JValue*)+180)I/DEBUG(95):#08pc0005fb37/system/lib/libdvm.so(dvmInvokeMethod(Object*,Methodconst*,ArrayObject*,ArrayObject*,ClassObject*,bool)+374)I/DEBUG(95):#09pc000670e5/system/lib/libdvm.soI/DEBUG(95):#10pc000272e0/system/lib/libdvm.soI/DEBUG(95):#11pc0002bbe8/system/lib/libdvm.so(dvmInterpret(Thread*,Methodconst*,JValue*)+180)I/DEBUG(95):#12pc0005f871/system/lib/libdvm.so(dvmCallMethodV(Thread*,Methodconst*,Object*,bool,JValue*,std::__va_list)+272)I/DEBUG(95):#13pc000496f3/system/lib/libdvm.soI/DEBUG(95):#14pc00048581/system/lib/libandroid_runtime.soI/DEBUG(95):#15pc00049637/system/lib/libandroid_runtime.so(android::AndroidRuntime::start(charconst*,charconst*)+390)I/DEBUG(95):#16pc00000dcf/system/bin/app_process


看到是在learn中出了问题:

/*MainLearningLoop------------------*/voidNeuQuant::learn(){inti,j,b,g,r;intradius,rad,alpha,step,delta,samplepixels;//unsignedchar*p;unsignedint*p;unsignedchar*lim;alphadec=30+((samplefac-1)/3);p=(unsignedint*)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,"beginning1Dlearning:initialradius=%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;elsestep=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);/*alterneighbours*/p+=step;if(p>=(unsignedint*)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,"finalalpha=%f",((float)alpha)/initalpha);__android_log_write(ANDROID_LOG_VERBOSE,"gifflen",s);}

我改变了:

if(p>=(unsignedint*)lim)p-=lengthcount;

变为:

if(p>=(unsignedint*)lim)p=(unsignedint*)thepicture;


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

更多相关文章

  1. Android中Fragment的使用,切换和返回等问题-刘宇
  2. Activity Lifecycle
  3. Android(安卓)EditText 点击时不弹出键盘但显示光标
  4. Picasso源码解析
  5. 【Android】onInterceptTouchEvent 方法收不到ACTION_MOVE事件
  6. Android(安卓)C++智能指针
  7. Android获取设备唯一ID的方法
  8. Android导入导出txt通讯录工具(源码共享)
  9. 生成appcompat_v7(兼容包)并报错的解决方法

随机推荐

  1. android - anim translate中 fromXDelta
  2. Android(安卓)说说EditText里面的属性
  3. android获取NetworkMode
  4. How to set Android camera orientation
  5. Android跳转浏览器打开URL
  6. 如何取Android设备日志
  7. android:windowSoftInputMode 不生效
  8. Android:Google Play services and OAuth
  9. Android基础开发文档汇总
  10. android samsung note3  device not fou