libpng版本:lpng1233.zip
说明:有了前面zlib的经验,这里编译的时候就尽量简略描述了。
注意:libpng库依赖与zlib库,所以需要连接zlib或者和zlib一起编译,但是由于android的NDK本身是自带了zlib的,所以可以直接使用系统的zlib库来链接。
下面是Android.mk的内容:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := png.c pngerror.c pnggccrd.c pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c pngset.c pngtrans.c pngvcrd.c pngwio.c pngwrite.c pngwtran.c pngwutil.c LOCAL_LDLIBS := -lz LOCAL_MODULE:= libmypng include $(BUILD_SHARED_LIBRARY)下面是目录结构以及编译过程:
$tree . ├── lpng1233.zip └── prj_libpng └── jni ├── Android.mk ├── png.c ├── pngconf.h ├── pngerror.c ├── pnggccrd.c ├── pngget.c ├── png.h ├── pngmem.c ├── pngpread.c ├── pngread.c ├── pngrio.c ├── pngrtran.c ├── pngrutil.c ├── pngset.c ├── pngtest.c ├── pngtrans.c ├── pngvcrd.c ├── pngwio.c ├── pngwrite.c ├── pngwtran.c └── pngwutil.c 2 directories, 22 files $cd prj_libpng/ $NDK/ndk-build Compile thumb : mypng <= png.c Compile thumb : mypng <= pngerror.c Compile thumb : mypng <= pnggccrd.c Compile thumb : mypng <= pngget.c Compile thumb : mypng <= pngmem.c Compile thumb : mypng <= pngpread.c Compile thumb : mypng <= pngread.c Compile thumb : mypng <= pngrio.c Compile thumb : mypng <= pngrtran.c Compile thumb : mypng <= pngrutil.c Compile thumb : mypng <= pngset.c Compile thumb : mypng <= pngtrans.c Compile thumb : mypng <= pngvcrd.c Compile thumb : mypng <= pngwio.c Compile thumb : mypng <= pngwrite.c Compile thumb : mypng <= pngwtran.c Compile thumb : mypng <= pngwutil.c SharedLibrary : libmypng.so Install : libmypng.so => libs/armeabi/libmypng.so $
下面是测试获取libpng版本的JNI封装,可以在上面的Android.mk中添加一起进行编译:
#include <jni.h> #include "png.h" #include <stdlib.h> #include <android/log.h> #include <errno.h> jstring chartojstring( JNIEnv* env, const char* pat) { return (*env) -> NewStringUTF(env, pat); } void get_version(char* ret) { unsigned long versionNum = (unsigned long)png_access_version_number(); char * version = png_get_header_version(NULL); sprintf(ret, "Version Number: %lu \n %s", versionNum, version); } jstring Java_com_hello_png_PngActivity_getVersion(JNIEnv* env, jobject thiz) { char versionInfo[1000]; get_version(versionInfo); return chartojstring(env, versionInfo); } void logcat(char* str) { __android_log_print(ANDROID_LOG_INFO, "MyLog", str); } void set_palette(png_colorp palette, int type) { if (type == 0) { int i; for (i = 0; i < PNG_MAX_PALETTE_LENGTH; ++i ) { palette[i].red = palette[i].green = palette[i].blue = i; } } if (type == 1) { int i; for (i = 0; i < PNG_MAX_PALETTE_LENGTH; ++i ) { palette[i].red = 255*i/PNG_MAX_PALETTE_LENGTH; palette[i].green = 0; palette[i].blue = 0; } } if (type == 2) { int i; for (i = 0; i < PNG_MAX_PALETTE_LENGTH; ++i ) { palette[i].red = 255*i/PNG_MAX_PALETTE_LENGTH; palette[i].green = 0; palette[i].blue = 255 - 255*i/PNG_MAX_PALETTE_LENGTH; } } } void generatePNG(char* filename, int type) { logcat(filename); // Define the variables. FILE *fp; png_structp png_ptr; png_infop info_ptr; png_colorp palette; logcat("1"); // Open the file. fp = fopen(filename, "wb"); logcat("2"); // Init png struct. png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info_ptr = png_create_info_struct(png_ptr); if (setjmp(png_jmpbuf(png_ptr))) { // . . . } png_init_io(png_ptr, fp); const int width = 120; const int height = 512; png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color)); // set_palette(palette, RED_BLACK); set_palette(palette, type); png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); png_write_info(png_ptr, info_ptr); png_uint_32 k; png_byte image[height][width]; png_bytep row_pointers[height]; for (k = 0; k < height; k++) { memset(image[k], k / 2, width); row_pointers[k] = image[k]; } png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); png_free(png_ptr, palette); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); } char* jstringTostring(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = (*env)->FindClass(env, "java/lang/String"); jstring strencode = (*env)->NewStringUTF(env, "utf-8"); jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); jsize alen = (*env)->GetArrayLength(env, barr); jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE); if (alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } (*env)->ReleaseByteArrayElements(env, barr, ba, 0); return rtn; } void Java_com_hello_png_PngActivity_generateJniPng(JNIEnv* env, jobject thiz, jstring filename,jint type) { generatePNG(jstringTostring(env, filename), type); }注意:除了在Android.mk中添加此源文件的文件名(如test.c)之外,添加-llog给LOCAL_LDLIBS,因为上面的测试代码中有log函数的使用。这里实现了getVersion()获取libpng的版本和generateJniPng()生成一幅PNG图片的测试,至于在java中的调用就不再贴代码了(调用生成图片的时候,记得添加SDCARD的写权限,参考下一篇)。