Android实战技巧之五十一:libjpeg与Android

libjpeg是一个被广泛使用的JPEG解码、JPEG编码和其他的JPEG功能的实现库。

说它使用广泛,是因为它跨了很多平台。比如Linux平台、JDK、Android和其他库如tess-two等等。

最近正在研究Android中直接用C/C++将图片的字节数组保存成图片,libjpeg库十分擅长。

官网www.ijg.org下载最新的版本9b,解压后会看到数量众多makefile,足以见得其对多平台的支持。

获取libjpeg.so

1、libjpeg库在安卓源码路径为/external/jpeg,编译源码时libjpeg.so就已经生成,我们可以直接拿过来使用。

/out/target/product/generic/system/lib/libjpeg.so

2、可以直接用源码编译,这也是本文的重点,请看下一节。

Android下编译libjpeg

安卓源码中自带的jpeg版本很可能不是最新的,我们去www.ijg.org下载最新的源码,解压后将所有文件放到jni目录中,准备用ndk编译。

1、新建config.sh,将ndk中的交叉编译工具加入其中,内容如下:

NDK=/opt/ndk/android-ndk-r10e/
PLATFORM=$NDK/platforms/android-15/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86/
CC=$PREBUILT/bin/arm-linux-androideabi-gcc
./configure --prefix=/home/linc/jpeg-9b/jni/dist --host=arm CC="$CC --sysroot=$PLATFORM"

2、执行此脚本

$ sh config.sh
...
checking whether to build shared libraries... no
checking whether to build static libraries... yes
...
config.status: creating Makefile
config.status: creating jconfig.h

首先,它生成了Makefile,我们可以直接使用此Makefile进行编译;其次,它生成了重要的头文件,jconfig.h.

遗憾的是,这个Makefile是编译static库而不是共享库的。

此时,我们可以执行构建命令进行编译:

jni$ make install-libLTLIBRARIES
libtool: install: ranlib /home/linc/jpeg-9b/jni/dist/lib/libjpeg.a

3、Android.mk

使用ndk-build指令编译,需要手动编写Android.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm

LOCAL_SRC_FILES :=jaricom.c jcapimin.c jcapistd.c jcarith.c jccoefct.c jccolor.c         jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c         jcomapi.c jcparam.c jcprepct.c jcsample.c jctrans.c jdapimin.c         jdapistd.c jdarith.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c         jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c         jdmerge.c jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c         jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jquant1.c         jquant2.c jutils.c jmemmgr.c jmemnobs.c

LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays     -DANDROID -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT

LOCAL_MODULE := libjpeg

LOCAL_MODULE_TAGS := optional

# unbundled branch, built against NDK.
LOCAL_SDK_VERSION := 17

include $(BUILD_SHARED_LIBRARY)

其中LOCAL_SRC_FILES后面的源文件可以参考刚刚生成的Makefile。

在jni目录上一级使用ndk-build编译即可。

$ ndk-build
[armeabi] Compile arm    : jpeg <= jaricom.c
...
[armeabi] Compile arm    : jpeg <= jmemnobs.c
[armeabi] SharedLibrary  : libjpeg.so
[armeabi] Install        : libjpeg.so => libs/armeabi/libjpeg.so

用一个例子来测试

为了快速测试,我们用C编写一个可执行程序,新建一个jni目录,将jconfig.h jmorecfg.h jpeglib.h及libjpeg.so拷进来,

新建jpeg_test.c,借鉴网友的生成jpg图片的例子,如下:

#include <string.h>
#include <stdlib.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; 

    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;
    if (nComponent==1)
        jcs.in_color_space = JCS_GRAYSCALE;
    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;      

    while (jcs.next_scanline < jcs.image_height) {
        row_pointer[0] = & data[jcs.next_scanline*row_stride];
        jpeg_write_scanlines(&jcs, row_pointer, 1);
    } 

    jpeg_finish_compress(&jcs);
    jpeg_destroy_compress(&jcs);
    fclose(f); 

    return 1;
} 

BYTE*  generateRGB24Data()
{
    struct {
        BYTE r;
        BYTE g;
        BYTE b;
    } pRGB[100][199];

    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;
} 

int main(void)
{
    BYTE* data = generateRGB24Data();
    generateJPEG(data,199, 100, "/sdcard/test.jpg"); 

    free(data);
    return 0;
}

新建Android.mk,生成可执行文件:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= jpeg_test.c

LOCAL_MODULE:= jtest

LOCAL_LDLIBS :=-llog
LOCAL_LDLIBS += $(LOCAL_PATH)/libjpeg.so
LOCAL_C_INCLUDES := $(LOCAL_PATH)

LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := debug 

include $(BUILD_EXECUTABLE)

执行ndk-build编译,将jtest和libjpeg.so push到安卓设备的/data/data下(需要有root权限),

/data/data # ./jtest

执行后会在sdcard下生成一个test.jpg.

后记

大功告成后,下一步就将测试其App中在C/C++层将视频流直接保存成图片。

借着libjpeg.so,我将测试JNA调用其功能。

敬请期待。

参考:

http://blog.csdn.net/cyq1028/article/details/7229158

http://www.cnblogs.com/hrlnw/p/4403334.html

http://blog.csdn.net/gengshenghong/article/details/7016617

时间: 2024-11-05 23:27:52

Android实战技巧之五十一:libjpeg与Android的相关文章

Android实战技巧之十一:Android Studio和Gradle

经过两个多月的AS体验,我认为是时候将Android的开发环境迁移到AS上了.目前最新版本是1.0.2,除了UI控件拖拽偶尔崩溃的问题(Ubuntu),其他功能用来还是十分流畅和高效.打动我的有如下几个特色: 智能感知体验特好,堪比VS 布局预览,手写布局后预览页面即时显示,便于布局调整和优化 编辑速度飞快流畅,毫无eclipse的卡顿 布局或源码中有图标和颜色的预览,十分直观 调试时体验极佳 集成了Terminal,喜欢命令行操作的伙伴不用额外启动终端了. 总之一句话,就是用起来特别爽! An

Android实战技巧之九:最新Android开发环境(Eclipse+ADT+Android 5.0)

一.一切由运行时错误引起 dalvikvm Could not find class '引用包.类', referenced from method... 其实在编译时也会见到如下错误:       [dx]        [dx] trouble processing:       [dx] bad class file magic (cafebabe) or version (0033.0000)       [dx] ...while parsing com/novell/sasl/cli

Android实战技巧之四十一:制作自己的Android SDK

编译自己的SDK 特种设备会有一些额外的功能,这样就需要给应用层提供特定的API,从而需要定制自己的SDK. 编译自己的sdk还是很简单的,因为google帮我们做好基础工作,步骤如下: $ source build/envsetup.sh $launch 'what you want' $ make update-api $ make PRODUCT-sdk-sdk -j8 如果一切顺利的编译完成,那么恭喜你.如果遇到错误也不要紧,因为这是正常的.下面列出我遇到的主要错误:tools/base

Android实战技巧之三十一:拍照和录像 with Camera

Developer Guides中有一篇是专门讲Camera的,而且讲的特别细.千万别以为有了这么好的文档就可以轻松的使用android.hardware.Camera这个包去拍照和录像了,各种坑在前面等着你呢.好了,下面将要讲述我们如何像辽宁队在常规赛中填坑的经历. 一.借助intent 这就十分easy了,发个intent就有人帮你搞定拍照和录像. 拍照: public void onTakePhoto(View view) { // create Intent to take a pict

Android实战技巧之五十二:fastjson

1.JSON JSON全称为JavaScript Object Notation,是一种轻量级的数据交换格式. 正因为数据格式简单,所以占用带宽小,网络传输的速度更快些.这一点是老前辈xml的硬伤. JSON的语法也很简单: 数据在键值对中 数据由逗号分隔 花括号保存对象 方括号保存数组 下面是微信公众帐号开发中获取token的JSON返回值 {"access_token":"I73NddJk_1GPgvVSrYC13w5omdanuiVdj7zvf8YDj1x0IYUDmQ

Android实战技巧之十二:Android Studio导入第三方类库、jar包和so库

第三方类库源码 将一网友的XMPP代码从ADT转到AS时,发现其使用了第三方类库,源码放在了lib下,直接在AS中Import project,第三方类库并没有自动导入进来,看来需要自己动手了. 项目的目录结构如下: XMPP$ ls app build.gradle gradlew import-summary.txt XMPP.iml build gradle gradlew.bat local.properties settings.gradle 1 2 3 1 2 3 将第三方源码qqE

Android实战技巧之三十二:Android Studio中的源代码管理

Android Studio最近经过了两次升级到了Android Studio 1.2.1.1, 用起来是越来越顺手了.AS中加入了主流的源码管理工具,让开发者不用离开AS就可以提交和管理代码. 下面就演示一下在AS中使用git管理代码. 选择要提交的代码 右键->commit 编写commit message 可以选择commit and push一起完成提交的动作 确认后push 查看提交历史和对比文件 总结: 玩git的都知道在命令行下有些版本历史信息的显示是不方便的,我们需要借助gitk

Android实战技巧之二十三:Android Studio的NDK开发

较新的NDK版本是r10b,Android Studio对NDK开发的支持还处于构思阶段,所以很多工作比如用javah生成头文件等工作还要自己做.今天用一个例子来演示AS中的NDK开发. 新建一个项目SecondNdkTest 在此项目中新建一个Module叫ndklibrary,作为so库单独划出来.在library中新建一个java类SecondLib,内容如下: package com.linc.ndklibrary; /** * Created by linc on 15-3-29. *

Android实战技巧之十二:Android Studio导入第三方类库

将一网友的XMPP代码从ADT转到AS时,发现其使用了第三方类库,源码放在了lib下,直接在AS中Import project,第三方类库并没有自动导入进来,看来需要自己动手了. 项目的目录结构如下: XMPP$ ls app build.gradle gradlew import-summary.txt XMPP.iml build gradle gradlew.bat local.properties settings.gradle 将第三方源码qqEmoji-lib拷到此目录,修改sett