libpngをAndroid NDKの標準ライブラリに登録する
![]()
以前扱った「Android NDK用にlibpngをビルドして利用する」では、libpngをそのソースコードからビルドして利用した。毎回libpngをビルドするのは面倒なので、そのときにビルドしてできたバイナリファイルを、Android NDKの標準ライブラリとして登録してしまう。
まずはlibpngのソースコードに含まれていたpng.hとpngconf.hを"C:\android-ndk\platforms\android-xxx\arch-arm\usr\include\"へコピーする。
![]()
次に「Android NDK用にlibpngをビルドして利用する」のプロジェクトをビルドして得られたlibpng.aを"C:\android-ndk\platforms\android-xxx\arch-arm\usr\lib\"へコピーする。これでAndroid NDK標準ライブラリへの登録作業は終りだ。
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := Test110jni LOCAL_SRC_FILES := Test110jni.c LOCAL_LDLIBS := -lz -lpng -llog -ljnigraphics include $(BUILD_SHARED_LIBRARY)
#include <jni.h>
#include <android/bitmap.h>
#include <stdlib.h>
#include <png.h>
/* 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) );
}
static int DrawBitmap(AndroidBitmapInfo* pBitmapInfo, void* pPixels, const char* pszImageFile)
{
FILE *fp;
//画像ファイルの読み込み
fp = fopen(pszImageFile,"r");
if(fp == NULL)
return 0;
int bSucceeded = 0;
png_bytepp ppRowImage = NULL;
png_structp pPng = NULL;
png_infop pInfo = NULL;
while(1)
{
pPng = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
if(pPng == NULL)
break;
pInfo = png_create_info_struct(pPng);
if(pInfo == NULL)
break;
//ファイルポインタの設定
png_init_io(pPng,fp);
png_uint_32 nWidth;
png_uint_32 nHeight;
int nBitDepth;
int nColorType;
int nIntMethod;
int nCompMethod;
int nFilterMethod;
png_uint_32 nImageBytes;
png_uint_32 nRowBytes;
//画像情報取得
png_read_info(pPng,pInfo);
png_get_IHDR(pPng,pInfo,&nWidth,&nHeight,&nBitDepth,&nColorType,&nIntMethod,&nCompMethod,&nFilterMethod);
nRowBytes = png_get_rowbytes(pPng,pInfo);
nImageBytes = nHeight * nRowBytes;
//画像データ用バッファーの確保
ppRowImage = (png_bytepp)malloc(sizeof(png_bytep) * nHeight + nImageBytes);
if(ppRowImage == NULL)
break;
int yy;
//画像データ用バッファーの初期化
{
png_bytep pRowImage;
pRowImage = (png_bytep)&(ppRowImage[nHeight]);
for(yy = 0; yy < nHeight; yy++)
{
ppRowImage[yy] = pRowImage;
pRowImage += nRowBytes;
}
}
//画像ファイル読み込み
png_read_image(pPng,ppRowImage);
//描画
for(yy = 0; yy < pBitmapInfo->height && yy < nHeight; yy++)
{
int xx;
uint16_t* pLine;
char* pImagePixel;
pLine = (uint16_t*)pPixels; //ビットマップの行データ
pImagePixel = (char*)(ppRowImage[yy]); //画像ファイルの行データ
for(xx = 0; xx < pBitmapInfo->width && xx < nWidth; xx++)
{
//■■注意■■1ピクセル3バイト前提で処理している。しかも画像ファイルが1ピクセル3バイトかどうかはチェックしていない!
pLine[xx] = make565(pImagePixel[0],pImagePixel[1],pImagePixel[2]);
pImagePixel += 3;
}
pPixels = (char*)pPixels + pBitmapInfo->stride;
}
bSucceeded = 1;
break; //必須忘れないこと!
}
if(ppRowImage)
{
free(ppRowImage);
ppRowImage = NULL;
}
if(pPng)
{
if(pInfo)
png_destroy_read_struct(&pPng,&pInfo,NULL);
else
png_destroy_read_struct(&pPng,NULL,NULL);
pPng = NULL;
pInfo = NULL;
}
fclose(fp);
return bSucceeded;
}
JNIEXPORT void JNICALL Java_com_Test110_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.png");
AndroidBitmap_unlockPixels(env, bitmap);
}
本当はAndroid NDKの標準ライブラリとしての登録は避けて、LOCAL_PREBUILT_LIBSを利用したmakefileで済ませたかったのですが、方法が分かりませんでした。今回の方法はかなり苦肉の策です。
プロジェクトファイルをダウンロード
