使用NDK移植/编译开源库(4)libjpeg的编译

来源:互联网 发布:江苏快三遗漏数据 编辑:程序博客网 时间:2024/06/08 02:32

说明:libjpeg下载http://www.ijg.org/,jpegsrc.v8c.tar.gz。(下面是用的是Linux环境NDKr7版本)

(1)使用NDK的GCC编译

1. 解压jpeg包

2. 建立两个文件夹,用于存储编译后的头文件和库文件等(下面的configure用到)。

3. 在终端设置NDK的GCC路径如下:

export SYSROOT=$NDK/platforms/android-14/arch-arm  export CC="$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT"
4. configure

./configure --prefix=/home/sgeng2/Desktop/ndk_lab/libjpeg/prefix/ --exec-prefix=/home/sgeng2/Desktop/ndk_lab/libjpeg/exec_prefix/ --host=arm
注意:要指定--host,否则configure会有错误。

5. make和make install

makemake install
完成后,在configure中指定的prefix和exec-prefix的文件夹中可以找到编译后得到的头文件和库文件。


总结:jpeg的编译过程很顺利,configure的时候没遇到什么错误,make的时候也不需要修改代码,比较容易的了。

(2)测试

为了测试如何使用编译后的jpeg,写了一个简单的测试代码。建立一个test_prj的文件夹,在其下新建一个jni文件夹,将上面生成的prefix下的include文件夹中的头文件和exec-prefix下的libs文件夹中的libjpeg.a复制到jni文件夹中,在jni中新建Android.mk和test.c文件,最终目录树如下:

NDK#tree.└── jni    ├── Android.mk    ├── jconfig.h    ├── jerror.h    ├── jmorecfg.h    ├── jpeglib.h    ├── libjpeg.a    └── test.c1 directory, 7 filesNDK#
其中,Android.mk的写法如下:

LOCAL_PATH := $(call my-dir)## prebuilt the static libsinclude $(CLEAR_VARS)LOCAL_MODULE := jpegLOCAL_SRC_FILES := libjpeg.ainclude $(PREBUILT_STATIC_LIBRARY)## to call the static libsinclude $(CLEAR_VARS)LOCAL_MODULE    := testLOCAL_SRC_FILES := test.cLOCAL_STATIC_LIBRARIES += jpeginclude $(BUILD_SHARED_LIBRARY)
(注意:关于如何调用第三方静态库动态库等的Android.mk的写法,可以参考http://hi.baidu.com/joec3/blog/item/687cf98913065dae0e244442.html的文章)

其中,test.c的内容如下:

#include <string.h>#include <jni.h>#include <math.h>#include <stdio.h>#include <stdint.h>typedef uint8_t BYTE;#define true 1#define false 0#include "jpeglib.h"int generateJPEG(BYTE* data,int w, int h, const char* outfilename){int nComponent = 3;struct jpeg_compress_struct jcs;// ÉùÃ÷ŽíÎóŽŠÀíÆ÷£¬²¢ž³Öµžøjcs.errÓò struct jpeg_error_mgr jem; jcs.err = jpeg_std_error(&jem);  jpeg_create_compress(&jcs);FILE* f=fopen(outfilename,"wb");if (f==NULL) {free(data);return 0;}jpeg_stdio_dest(&jcs, f);jcs.image_width = w; // Ϊ͌µÄ¿íºÍžß£¬µ¥Î»ÎªÏñËØ jcs.image_height = h;jcs.input_components = nComponent;// 1,±íÊŸ»Ò¶ÈÍŒ£¬ Èç¹ûÊDzÊɫλ͌£¬ÔòΪ3 if (nComponent==1)jcs.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE±íÊŸ»Ò¶ÈÍŒ£¬JCS_RGB±íÊŸ²ÊÉ«ÍŒÏñ else jcs.in_color_space = JCS_RGB;jpeg_set_defaults(&jcs);jpeg_set_quality (&jcs, 60, true);jpeg_start_compress(&jcs, TRUE);JSAMPROW row_pointer[1];// Ò»ÐÐλ͌int row_stride;// ÿһÐеÄ×ÖœÚÊý row_stride = jcs.image_width*nComponent;// Èç¹û²»ÊÇË÷ÒýÍŒ,ŽËŽŠÐèÒª³ËÒÔ3// ¶ÔÿһÐÐœøÐÐѹËõwhile (jcs.next_scanline < jcs.image_height) {    row_pointer[0] = & data[jcs.next_scanline*row_stride];//×¢Ò⣺row_pointer[0]±íÃ÷ÿһžöÉšÃèÐеÄÖžÕ룬עÒâ¶ÔdataœøÐзÖÎö¡£//Èç¹ûdataÊÇÖ±œÓŽÓ24λλ͌¶ÁÈ¡£¬ÒªœøÐÐ×֜ڶÔÆ뎊Àí£¬// ÕâÀïÓÉÓÚÉÏÃæµÄread24BMP±ŸÉíŸÍŽŠÀíÁËÕâЩÎÊÌ⣬ËùÒÔÖ±œÓŸÍÊÇÕý³£µÄÍ·Ïñ×ø±êϵºÍÐеij€¶È¡£    jpeg_write_scanlines(&jcs, row_pointer, 1);}jpeg_finish_compress(&jcs);jpeg_destroy_compress(&jcs);fclose(f);return 1;}/*Éú³ÉRGB24ÊýŸÝ£¬žùŸÝÐèÒªœøÐÐÐÞžÄ*/BYTE*  generateRGB24Data(){struct {BYTE r;BYTE g;BYTE b;} pRGB[100][199];  // ÐÞžÄ˳Ðò£¬ŽÓ¶ø±íÊŸ²»Í¬µÄžñÊœ£¬RGB¡¢BGRµÈµÈ¡£memset( pRGB, 0, sizeof(pRGB) ); // ÉèÖñ³Ÿ°ÎªºÚÉ«int i=0, j=0;// ÔÚÖЌ仭À¶É«ÇøÓòfor(  i=50;i<70;i++ ){for( j=70;j<140;j++ ){pRGB[i][j].b = 0xff;}}// ÔÚÖЌ仭ºìÉ«ÇøÓòfor(  i=0;i<10;i++ ){for( j=0;j<199;j++ ){pRGB[i][j].r = 0xff;}}BYTE* ret = (BYTE*)malloc(sizeof(BYTE)*100*199*3);memcpy(ret, (BYTE*)pRGB, sizeof(pRGB));return ret;}void Java_com_example_TestjpegActivity_generateJPG(JNIEnv* env, jobject thiz ){    BYTE* data = generateRGB24Data();generateJPEG(data,199, 100, "/sdcard/test.jpg");free(data);}
注意:这里的代码是我以前写的,里面的乱码是中文注释,弄到虚拟机里面变成了乱码,也不管了,libjpeg的用法也不属于这里要讨论的内容。这里只关注最后一个JNI封装的函数,generateJPG,最后要在Android的Java中调用的就是这个函数,这里实现的功能是,在sdcard下生成一张JPG图片test.jpg,生成的数据也是generateRGB24Data来生成的RGB数据。

最后,在test_prj下编译:

NDK#$NDK/ndk-buildCompile thumb  : test <= test.cPrebuilt       : libjpeg.a <= jni/SharedLibrary  : libtest.soInstall        : libtest.so => libs/armeabi/libtest.soNDK#
得到libtest.so,然后将此.so文件放到Eclipse中Android工程中去(<prj>/libs/armeabi/libtest.so),java代码如下:

package com.example;import android.app.Activity;import android.os.Bundle;import android.util.Log;public class TestjpegActivity extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Log.d("MyLog", "Generating JPG file to /sdardc/test.jpg");generateJPG();Log.d("MyLog", "Done");}public native void generateJPG();static {System.loadLibrary("test");}}
注意:给工程添加如下权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
然后就可以运行Android程序了,最后的结果是运行后会在sdcard下生成一张JPG图片,用DDMS中的File Explorer可以看到,导出文件后可以打开JPG图片。

如果没有意外,最后生成的JPG图片如下:



更新:

下载Linux:http://dl.dbank.com/c0pp14j2ei (dbank,用QQ号就可以登录)

下载Cywin:http://dl.dbank.com/c0a1d42ujk

说明:这里的编译的方式是利用NDK中的gcc进行交叉编译,NDK for windows里面的工具链可能不太规范,所以容易出错。更好的一种方式是,NDK的build/tools下面提供了一个脚本make-standalone-toolchain.sh,其用于从NDK中提取出一个独立的交叉工具链,使用这个提取出来的工具链是更好的方法。这里的Cygwin的测试,就是先提取交叉工具链然后使用的(因为按照前面Linux的方法,发现有很多问题,最终也没有完全解决,用提取的工具链很容易就解决了)。

另外,使用NDK进行交叉编译,个人还是推荐使用Linux上编译,使用Cygwin麻烦而且有可能有一些问题。反正,Linux和windows上编译,都是一样的。

原创粉丝点击