文档章节

gifflen 调用以及错误处理

拉风的道长
 拉风的道长
发布于 2014/05/04 22:52
字数 993
阅读 590
收藏 0
/*

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里面调用,上我写的代码:

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<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了,不会出问题了。

© 著作权归作者所有

共有 人打赏支持
拉风的道长
粉丝 52
博文 106
码字总数 53731
作品 0
昌平
程序员
加载中

评论(3)

r
r00t-123

引用来自“拉风的道长”的评论

引用来自“leepood”的评论

居然看到了我啊

是的。转帖注明出处。哈哈
哈哈,幸会幸会
拉风的道长
拉风的道长

引用来自“leepood”的评论

居然看到了我啊

是的。转帖注明出处。哈哈
r
r00t-123
居然看到了我啊
Java之Checked Exception和Unchecked Exception使用的个人理解

摘要:最近一个人在搭程序后台框架,碰到了一个问题,就是Exception类型的使用。于是我有了以下的一些想法。 一、 为什么需要使用异常 个人理解:在面向对象程序的开发过程中,我们需要对函数...

BaronChen
2016/11/28
21
0
如何处理Express异常

译者按:根据墨菲定律:“有可能出错的事情,就会出错”。那么,既然代码必然会出错,我们就应该处理好异常。 原文: How to handle errors in Express 译者:Fundebug 为了保证可读性,本文采...

2017/12/26
0
0
智能合约语言 Solidity 教程系列9 - 错误处理

这是Solidity教程系列文章第9篇介绍Solidity 错误处理。 Solidity系列完整的文章列表请查看分类-Solidity。 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能...

熊丽兵
04/08
0
0
用异常来处理错误----第一节 Java异常的概念

我们总是试图避免在软件程序中错误的发生,但是它的存在却是不幸的实事。无论怎样,如果你能适当的处理错误,将会极大的改善程序的可读性、可靠性以及可维护性。Java编程语言使用异常来处理错...

长平狐
2012/10/16
37
0
150行实现Promise 90%的功能

Promise的实现也算是一个老话题了,网上同类型的文章和示例代码不少,其中不乏许多优秀的实现。但因为Promise“魔幻”的API,以及背后包含的异步处理的独特思想,使得实现一个Promise仍旧是一...

lqt0223
03/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

最全最强解析:支付宝钱包系统架构内部剖析(架构图)

支付宝系统架构概况 典型处理默认 资金处理平台 财务会计 支付清算 核算中心 交易 柔性事务 支付宝的开源分布式消息中间件–Metamorphosis(MetaQ) Metamorphosis (MetaQ) 是一个高性能、高可...

晨猫
30分钟前
4
0
竞品分析

那什么样的场景需要用关键纬度分析法分析竞品呢? 竞品分析的目的是为了看竞品们和自己产品重合的业务都具备哪些功能点,以及这些功能是怎么做的,以此确定自己产品的优化方向。 竞品们的业务...

于谦老师
37分钟前
1
0
OSChina 周三乱弹 —— 公司女同事约我

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:分享水木年华的单曲《蝴蝶花(2002年大提琴版)》 《蝴蝶花(2002年大提琴版)》- 水木年华 手机党少年们想听歌,请使劲儿戳(这里) ...

小小编辑
今天
1K
16
Linux环境搭建 | VMware下共享文件夹的实现

在进行程序开发的过程中,我们经常要在主机与虚拟机之间传递文件,比如说,源代码位于虚拟机,而在主机下阅读或修改源代码,这里就需要使用到 「共享文件」 这个机制了。本文介绍了两种共享文...

良许Linux
今天
9
0
JUC锁框架——AQS源码分析

JUC锁介绍 Java的并发框架JUC(java.util.concurrent)中锁是最重要的一个工具。因为锁,才能实现正确的并发访问。而AbstractQueuedSynchronizer(AQS)是一个用来构建锁和同步器的框架,使用A...

长头发-dawn
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部