今回はIJGのJPEGライブラリ(libjpeg、jpeglib)をAndroid NDKから利用してJpgファイルを表示する。
まずIndependent JPEG GroupからJPEGライブラリのソースファイルをダウンロードする。「jpegsr8c.zip」というファイルだった。
EasyProjectGenerator for Androidで雛形となるAndroidプロジェクトを作成する。今回はC++でNativeViewを利用する。
ダウンロードしたJPEGライブラリのソースファイル一式をAndroidプロジェクトのjniフォルダへ解凍する。
さらにjniフォルダにあったソースファイルやmakefileを「Test118」というフォルダを作成してその中へ移動する。
include $(call all-subdir-makefiles)

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libjpeg 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 jmemname.c include $(BUILD_STATIC_LIBRARY)
次にlibjpegの「jpeg-8c」フォルダの中にある「jconfig.txt」ファイルを選択した状態で[F2]キーを押して、ファイル名を「jconfig.h」に変更する。これでJPEGライブラリのビルド準備が整った。

#if(true) #define LOCAL_LOG #define LOCAL_LOGD #endif #include <jni.h> #include <android/bitmap.h> #ifdef LOCAL_LOG #include <android/log.h> #endif /* this function is from Android NDK bitmap-plasma , and modify for green color bug */ static uint16_t make565(int red, int green, int blue) { return (uint16_t)( ((red << 8) & 0xf800) | ((green << 3) & 0x07e0) | ((blue >> 3) & 0x001f) ); } #include <stdio.h> extern "C" { #define XMD_H #include "../jpeg-8c/jpeglib.h" #include "../jpeg-8c/jerror.h" } static void _JpegError(j_common_ptr cinfo) { char pszMessage[JMSG_LENGTH_MAX]; (*cinfo->err->format_message)(cinfo,pszMessage); __android_log_print(ANDROID_LOG_INFO,"Test118","error! %s",pszMessage); } static int DrawBitmap(AndroidBitmapInfo* pBitmapInfo, void* pPixels,const char* pszJpegFile) { int yy; int nJpegLineBytes; //JPEG1ラインのバイト数 char* lpbtBits; JSAMPLE* pSample; FILE* fp; JSAMPROW buffer[1]; JSAMPLE tmp; jpeg_decompress_struct cInfo; jpeg_error_mgr jError; fp = fopen(pszJpegFile,"rb"); if(fp == NULL) return 0; cInfo.err = jpeg_std_error(&jError); //エラーハンドラ設定 jError.error_exit = _JpegError; //エラーハンドラ設定 jpeg_create_decompress(&cInfo); // jpeg_stdio_src(&cInfo,fp); //読込ファイル設定 jpeg_read_header(&cInfo,TRUE); //ヘッダー読込 jpeg_start_decompress(&cInfo); //デコードスタート nJpegLineBytes = cInfo.output_width * cInfo.output_components; //JPEG 1ラインのバイト数 pSample = new JSAMPLE[nJpegLineBytes + 10]; // ラインバッファ確保 buffer[0] = pSample; yy = 0; while(cInfo.output_scanline < cInfo.output_height) { if(yy >= pBitmapInfo->height) break; jpeg_read_scanlines(&cInfo,buffer,1); //Jpegを1ライン読み込む int xx; int x3; uint16_t* pLine = (uint16_t*)pPixels; for(xx = 0, x3 = 0; xx < pBitmapInfo->width && x3 < nJpegLineBytes; xx++, x3 += 3) { //JPEGはBGRの順 pLine[xx] = make565(buffer[0][x3 + 0],buffer[0][x3 + 1],buffer[0][x3 + 2]); } // go to next line pPixels = (char*)pPixels + pBitmapInfo->stride; yy++; } delete pSample; jpeg_finish_decompress(&cInfo); // 読み込み終了処理 jpeg_destroy_decompress(&cInfo); fclose(fp); return 1; } extern "C" JNIEXPORT void JNICALL Java_com_Test118_NativeView_RenderBitmap(JNIEnv * env, jobject obj, jobject bitmap) { AndroidBitmapInfo info; void* pixels; int ret; if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) return; if (info.format != ANDROID_BITMAP_FORMAT_RGB_565) return; if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) return; DrawBitmap(&info,pixels,"/sdcard/test.jpg"); AndroidBitmap_unlockPixels(env, bitmap); }

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := Test118 LOCAL_SRC_FILES := Test118.cpp LOCAL_LDLIBS := -lz -ljnigraphics LOCAL_STATIC_LIBRARIES += libjpeg LOCAL_IS_SUPPORT_LOG := true ifeq ($(LOCAL_IS_SUPPORT_LOG),true) LOCAL_LDLIBS += -llog endif include $(BUILD_SHARED_LIBRARY)
これでビルドをかけると、libjpeg.aとそれを利用したバイナリが生成される。
テスト表示用のjpgファイル「test.jpg」をAndroidエミュレーターのSDカードへと転送する。
そしてプロジェクトを実行すると、jpgファイルが表示された。
プロジェクトファイルをダウンロード