文档章节

gifflen 调用以及错误处理

拉风的道长
 拉风的道长
发布于 2014/05/04 22:52
字数 993
阅读 586
收藏 0
点赞 0
评论 3
/*

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

© 著作权归作者所有

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

评论(3)

r
r00t-123

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

引用来自“leepood”的评论

居然看到了我啊

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

引用来自“leepood”的评论

居然看到了我啊

是的。转帖注明出处。哈哈
r
r00t-123
居然看到了我啊
如何处理Express异常

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

⋅ 2017/12/26 ⋅ 0

Java之Checked Exception和Unchecked Exception使用的个人理解

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

BaronChen ⋅ 2016/11/28 ⋅ 0

用异常来处理错误----第一节 Java异常的概念

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

长平狐 ⋅ 2012/10/16 ⋅ 0

智能合约语言 Solidity 教程系列9 - 错误处理

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

熊丽兵 ⋅ 04/08 ⋅ 0

150行实现Promise 90%的功能

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

lqt0223 ⋅ 03/02 ⋅ 0

为什么我希望用C而不是C++来实现ZeroMQ

开始前我要先做个澄清:这篇文章同Linus Torvalds这种死忠C程序员吐槽C++的观点是不同的。在我的整个职业生涯里我都在使用C++,而且现在C++依然是我做大多数项目时的首选编程语言。自然的,当...

鉴客 ⋅ 2012/05/18 ⋅ 38

手机话费充值SDK为例调用第三方服务API的编写思路

思路 通过将SDK方法中返回的数据划分为正常返回数据以及错误返回的数据两部分,让调用者更简单的对接口调用错误进行处理。 将SDK调用第三方服务接口的流程划分为: 数据准备,http请求,结果处...

是我的名字啊 ⋅ 2016/12/07 ⋅ 0

调用第三方服务API的SDK编写思路

思路 通过将SDK方法中返回的数据划分为正常返回数据以及错误返回的数据两部分,让调用者更简单的对接口调用错误进行处理。 将SDK调用第三方服务接口的流程划分为: 数据准备,http请求,结果处...

熊babi ⋅ 2016/12/20 ⋅ 0

为什么我希望用C而不是C++来实现ZeroMQ(一)

开始前我要先做个澄清:这篇文章同Linus Torvalds这种死忠C程序员吐槽C++的观点是不同的。在我的整个职业生涯里我都在使用C++,而且现在C++依然是我做大多数项目时的首选编程语言。自然的,当...

开心303 ⋅ 2012/09/12 ⋅ 0

异常处理

抛出异常 异常处理使得程序可以处理非预期的情景,并且能够继续正常的操作 在java中,运行时错误会作为异常抛出。异常就是一种对象,表示阻止正常进行程序执行的错误或者情况。 异常是从方法...

承思 ⋅ 2017/10/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Springboot2 之 Spring Data Redis 实现消息队列——发布/订阅模式

一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式,这里利用redis消息“发布/订阅”来简单实现订阅者模式。 实现之前先过过 redis 发布订阅的一些基础概念和操...

Simonton ⋅ 15分钟前 ⋅ 0

error:Could not find gradle

一.更新Android Studio后打开Project,报如下错误: Error: Could not find com.android.tools.build:gradle:2.2.1. Searched in the following locations: file:/D:/software/android/andro......

Yao--靠自己 ⋅ 昨天 ⋅ 0

Spring boot 项目打包及引入本地jar包

Spring Boot 项目打包以及引入本地Jar包 [TOC] 上篇文章提到 Maven 项目添加本地jar包的三种方式 ,本篇文章记录下在实际项目中的应用。 spring boot 打包方式 我们知道,传统应用可以将程序...

Os_yxguang ⋅ 昨天 ⋅ 0

常见数据结构(二)-树(二叉树,红黑树,B树)

本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自coursera上普林斯顿的课程《Algorithms, Part I》中的Slides 相关命题的证明可参考《算法(第...

浮躁的码农 ⋅ 昨天 ⋅ 0

android -------- 混淆打包报错 (warning - InnerClass ...)

最近做Android混淆打包遇到一些问题,Android Sdutio 3.1 版本打包的 错误如下: Android studio warning - InnerClass annotations are missing corresponding EnclosingMember annotation......

切切歆语 ⋅ 昨天 ⋅ 0

eclipse酷炫大法之设置主题、皮肤

eclipse酷炫大法 目前两款不错的eclipse 1.系统设置 Window->Preferences->General->Appearance 2.Eclipse Marketplace下载【推荐】 Help->Eclipse Marketplace->搜索‘theme’进行安装 比如......

anlve ⋅ 昨天 ⋅ 0

vim编辑模式、vim命令模式、vim实践

vim编辑模式 编辑模式用来输入或修改文本内容,编辑模式除了Esc外其他键几乎都是输入 如何进入编辑模式 一般模式输入以下按键,均可进入编辑模式,左下角提示 insert(中文为插入) 字样 i ...

蛋黄Yolks ⋅ 昨天 ⋅ 0

大数据入门基础:SSH介绍

什么是ssh 简单说,SSH是一种网络协议,用于计算机之间的加密登录。 如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码...

董黎明 ⋅ 昨天 ⋅ 0

web3j教程

web3j是一个轻量级、高度模块化、响应式、类型安全的Java和Android类库提供丰富API,用于处理以太坊智能合约及与以太坊网络上的客户端(节点)进行集成。 汇智网最新发布的web3j教程,详细讲解...

汇智网教程 ⋅ 昨天 ⋅ 0

谷歌:安全问题机制并不如你想象中安全

腾讯科技讯 5月25日,如今的你或许已经对许多网站所使用的“安全问题机制”习以为常了,但你真的认为包括“你第一个宠物的名字是什么?”这些问题能够保障你的帐户安全吗? 根据谷歌(微博)安...

问题终结者 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部