libpng for Android
swfファイルから画像ファイルを抽出する際に, タグの内部にJPEGで内蔵されて透明チャンネルをzlibで圧縮したものが付属されている.
透明色を表現することはJPEGでも可能ですが, JPEGのライブラリは扱いが少し厄介なのでPNGで保存されるようにするため今回はlibpngについてです.
Android NDKには, libpngがないため, github
julienr/libpng-android · GitHub
とかlibpng
libpng Home Page
本家からダウンロードして, NDKにライブラリを追加します.
NDKのAndroid.mkに追加した状態を記述すると
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libpng LOCAL_SRC_FILES :=\ libpng/png.c \ libpng/pngerror.c \ libpng/pngget.c \ libpng/pngmem.c \ libpng/pngpread.c \ libpng/pngread.c \ libpng/pngrio.c \ libpng/pngrtran.c \ libpng/pngrutil.c \ libpng/pngset.c \ libpng/pngtest.c \ libpng/pngtrans.c \ libpng/pngwio.c \ libpng/pngwrite.c \ libpng/pngwtran.c \ libpng/pngwutil.c #LOCAL_LDLIBS := -lz #include $(BUILD_SHARED_LIBRARY) include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := buildpng LOCAL_SRC_FILES := buildpng.c LOCAL_LDLIBS := -llog -lz LOCAL_C_INCLUDES += $(LOCAL_PATH)/libpng LOCAL_STATIC_LIBRARIES := libpng include $(BUILD_SHARED_LIBRARY)
必要なファイルをコピーしてコンパイルをしています.
ちなみにC言語のコードは,
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <png.h> #include <jni.h> #include <android/log.h> #define TAG "buildpng" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) #define PATH_LENGTH (1024) /* jni/build_png.c */ int build_png(const char *path); int Java_com_archmint_pngbuild_PNGActiv_createpng( JNIEnv *env, jobject thiz, jstring path) { const char *external_path = (*env)->GetStringUTFChars( env, path, NULL); if(build_png(external_path) == (-1)) { return (-1); } (*env)->ReleaseStringUTFChars( env, path, external_path); return 1; } int build_png(const char *path) { png_structp png_ptr; png_infop info_ptr; int i, j; const int width = 256, height = 256; unsigned char **src; FILE *fp; char png_path[PATH_LENGTH]; memset(png_path, '\0', PATH_LENGTH); sprintf(png_path, "%s/%s", path, "png_path.png"); if((fp = fopen(png_path, "wb")) == NULL) { LOGD("fopen(3)"); return (-1); } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info_ptr = png_create_info_struct(png_ptr); png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE); src = (unsigned char **)calloc(height, sizeof(unsigned char **)); for(i = 0; i < height; i++) { src[i] = (unsigned char *)calloc(width, sizeof(unsigned char *)); for(j = 0; j < width; j++) { src[i][j * 4 + 0] = 200; src[i][j * 4 + 1] = j; src[i][j * 4 + 2] = i; src[i][j * 4 + 3] = 0xFF; } } png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, src); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); for(i = 0; i < height; i++) { free(src[i]); } free(src); fclose(fp); return 1; }
エラー処理がまともにされていない, 危険なコードです.
が, 今回はこのまま使用しました.
そして,
パッケージ名:com.archmint.pngbuild
アクティビティ名: PNGActiv
のソースコード内に,
static { System.loadLibrary("buildpng"); } static native createpng(String path);
圧縮したファイルをGoogle Driveに保存をさせました.
https://drive.google.com/folderview?id=0B4z92cYyh2opV1h6cTFtV1JDX0E&usp=sharing
Androidで実行した結果は,
こうなりました.