IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    lincyang发表于 2016-04-07 14:33:45
    love 0

    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



沪ICP备19023445号-2号
友情链接