Android NDKでPNGおよびJPEG画像をダウンロードする

すべての読者へのご挨拶!

この記事では、PNGおよびJPEGイメージをファイルまたはメモリからAndroid NDKにロードする方法と、これらのOpenGLイメージをフィードするための便利なコードについて説明します。



ダウンロードする



画像をダウンロードするには、次のライブラリを使用します。



開梱



すべてを適切にフォルダーに分解します。たとえば、プロジェクトルートにあるモジュールフォルダーを作成しますこのフォルダーにはjniフォルダーがあります。 開梱:

かくして そのような構造を得る

プロジェクト/ jni

プロジェクト/モジュール/ png

プロジェクト/モジュール/ jpeg

プロジェクト/モジュール/ zlib



カスタマイズする





Android.mkを編集します



Android.mkで、すべてのライブラリを一緒に接続します
LOCAL_PATH:= $(my-dirを呼び出す)

ヘッダー:=

STATICLIBS:=



含む$(CLEAR_VARS)

LOCAL_MODULE:= png

FILE_LIST:= $(ワイルドカード$(LOCAL_PATH)/../ modules / png / *。C *)

LOCAL_SRC_FILES:= $(FILE_LIST:$(LOCAL_PATH)/%=%)

LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/../ modules / png

HEADERS + = $(LOCAL_EXPORT_C_INCLUDES)

STATICLIBS + = $(LOCAL_MODULE)

インクルード$(BUILD_STATIC_LIBRARY)



含む$(CLEAR_VARS)

LOCAL_MODULE:= zlib

FILE_LIST:= $(ワイルドカード$(LOCAL_PATH)/../ modules / zlib / *。C *)

LOCAL_SRC_FILES:= $(FILE_LIST:$(LOCAL_PATH)/%=%)

LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/../ modules / zlib

HEADERS + = $(LOCAL_EXPORT_C_INCLUDES)

STATICLIBS + = $(LOCAL_MODULE)

インクルード$(BUILD_STATIC_LIBRARY)



含む$(CLEAR_VARS)

LOCAL_MODULE:= jpeg

LOCAL_SRC_FILES:= ../modules/jpeg/obj/local/$(TARGET_ARCH_ABI)/libjpeg.a

LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/../ modules / jpeg

STATICLIBS + = $(LOCAL_MODULE)

HEADERS + = $(LOCAL_EXPORT_C_INCLUDES)

インクルード$(PREBUILT_STATIC_LIBRARY)



#------------------------------------------------- ---------



含む$(CLEAR_VARS)

LOCAL_ARM_MODE:=アーム

LOCAL_MODULE:= LoadImage

LOCAL_SRC_FILES:= loadimage.cpp

LOCAL_CFLAGS:= -Werror -DGL_GLEXT_PROTOTYPES = 1 -fsigned-char -Wno-write-strings -Wno-psabi

LOCAL_LDLIBS:= -llog -lGLESv1_CM

LOCAL_STATIC_LIBRARIES:= $(STATICLIBS)

LOCAL_C_INCLUDES = $(ヘッダー)

インクルード$(BUILD_SHARED_LIBRARY)



写真を読む



C ++コード(このファイルloadimage.cppがあります)では、次のことを行います。

コメント付きのコード
 #include <jni.h> #include <android/log.h> #include <GLES/gl.h> #include <GLES/glext.h> //  extern "C" { #include "png.h" #include <setjmp.h> #include "jpeglib.h" } #define LOG(...) __android_log_print(ANDROID_LOG_VERBOSE, "NDK",__VA_ARGS__) //   struct image { png_uint_32 imWidth, imHeight; //   png_uint_32 glWidth, glHeight; //    OpenGL int bit_depth, color_type; char* data; // RGB/RGBA }; //-       OpenGL static int reNpot(int w) { //  OpenGL      //            //String s = gl.glGetString(GL10.GL_EXTENSIONS); //NON_POWER_OF_TWO_SUPPORTED = s.contains("texture_2D_limited_npot") || s.contains("texture_npot") || s.contains("texture_non_power_of_two"); bool NON_POWER_OF_TWO_SUPPORTED = false; if (NON_POWER_OF_TWO_SUPPORTED) { if (w % 2) w++; } else { if (w <= 4) w = 4; else if (w <= 8) w = 8; else if (w <= 16) w = 16; else if (w <= 32) w = 32; else if (w <= 64) w = 64; else if (w <= 128) w = 128; else if (w <= 256) w = 256; else if (w <= 512) w = 512; else if (w <= 1024) w = 1024; else if (w <= 2048) w = 2048; else if (w <= 4096) w = 4096; } return w; } //-  PNG  static image readPng(const char* fileName) { image im; FILE* file = fopen(fileName, "rb"); // ,       PNG   JPEG,  -      fseek(file, 8, SEEK_CUR); png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); png_init_io(png_ptr, file); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); //    png_get_IHDR(png_ptr, info_ptr, &im.imWidth, &im.imHeight, &im.bit_depth, &im.color_type, NULL, NULL, NULL); //     OpenGL im.glWidth = reNpot(im.imWidth); im.glHeight = reNpot(im.imHeight); //        4  (RGBA),  3 (RGB) int row = im.glWidth * (im.color_type == PNG_COLOR_TYPE_RGBA ? 4 : 3); im.data = new char[row * im.glHeight]; //         png_bytep * row_pointers = new png_bytep[im.imHeight]; for(int i = 0; i < im.imHeight; ++i) row_pointers[i] = (png_bytep) (im.data + i * row); //  png_read_image(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, 0); delete[] row_pointers; return im; } //   libjpeg-turbo struct my_error_mgr { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer; }; typedef struct my_error_mgr * my_error_ptr; METHODDEF(void) my_error_exit(j_common_ptr cinfo) { my_error_ptr myerr = (my_error_ptr) cinfo->err; (*cinfo->err->output_message)(cinfo); longjmp(myerr->setjmp_buffer, 1); } //-  JPEG  static image readJpeg(const char* fileName) { image im; FILE* file = fopen(fileName, "rb"); struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return im; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, file); //    jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); im.imWidth = cinfo.image_width; im.imHeight = cinfo.image_height; im.glWidth = reNpot(im.imWidth); im.glHeight = reNpot(im.imHeight); //JPEG        3- (RGB) int row = im.glWidth * 3; im.data = new char[row * im.glHeight]; //   unsigned char* line = (unsigned char*) (im.data); while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, &line, 1); line += row; } // jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return im; }
      
      





テスト



メモリカードからのPNG画像の読み込みのテスト:

 // OpenGL  GLuint texture1; glGenTextures(1, &texture1); glBindTexture(GL_TEXTURE_2D, texture1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // PNG  image im = readPng("/mnt/sdcard/scrrihs.png"); LOG("PNG: %dx%d (%dx%d) bit:%d type:%d", im.imWidth, im.imHeight, im.glWidth, im.glHeight, im.bit_depth, im.color_type); //       OpenGL if (im.color_type == PNG_COLOR_TYPE_RGBA) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.glWidth, im.glHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, im.data); } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, im.glWidth, im.glHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, im.data); } delete[] im.data;
      
      





同様に、JPEGは常に透過性がないため、 JPEGを使用します

 GLuint texture2; glGenTextures(1, &texture2); glBindTexture(GL_TEXTURE_2D, texture1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); image imJpeg = readJpeg("/mnt/sdcard/test.jpg"); LOG("JPEG: %dx%d (%dx%d)", imJpeg.imWidth, imJpeg.imHeight, imJpeg.glWidth, imJpeg.glHeight); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imJpeg.glWidth, imJpeg.glHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, imJpeg.data); delete[] imJpeg.data;
      
      





暗号化して写真を読む



単純な画像暗号化を適用する必要がある場合は、復号化機能を画像読み取りプロセスに直接挿入できます。



メモリから画像を読み取る



たとえば、アプリケーションがネットワーク経由で画像を受信し、画像が完全にメモリにハングアップします。



Openglパン



 //   RGBA  RGBA4444 int len = im.glWidth * im.glHeight; unsigned short* tmp = (unsigned short*) im.data; for(int i = 0; i < len; i++) tmp[i] = ((im.data[i * 4] >> 4) << 12) | ((im.data[i * 4 + 1] >> 4) << 8) | ((im.data[i * 4 + 2] >> 4) << 4) | (im.data[i * 4 + 3] >> 4); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.glWidth, im.glHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, im.data); // RGB   RGB565 int len = im.glWidth * im.glHeight; unsigned short* tmp = (unsigned short*) im.data; for(int i = 0; i < len; i++) tmp[i] = ((im.data[i * row] >> 3) << 11) | ((im.data[i * row + 1] >> 2) << 5) | (im.data[i * row + 2] >> 3); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, im.glWidth, im.glHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, im.data); //  RGB/RGBA   GL_LUMINANCE  GL_ALPHA int row = HAS_ALPHA?4:3; int len = im.glWidth * im.glHeight * row; for(int i = 0, a = 0; i < len; i += row, a++) im.data[a] = im.data[i]; glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, im.glWidth, im.glHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, im.data);
      
      





ループ内で配列が自分自身に書き込むことは大丈夫です 最終的な配列は常に元の配列よりも小さく、OpenGLテクスチャを作成した後は不要になります。



私は誰かがこれらの開発が役立つと確信しています。 いずれにせよ、その前に、JNIを介してダウンロードしたファイルを投げ、そこにビットマップを作成し、ピクセルを読み取ってNDKに送り返さなければなりませんでした。 さらに、これらすべての機能は、Android NDKだけでなく、iOS / MacOSでも使用できます。

念のため、以下はlibjpeg-turboをコンパイルするためのコマンドです(libpngはXcodeにフォルダーを追加するだけで問題なくコンパイルできます)。

非表示のテキスト
cd {source_directory}

autoreconf -fiv

mkdirビルド

cdビルド



MacOS

sh ../configure --host i686-apple-darwin CFLAGS = '-O3 -m32' LDFLAGS = -m32



iOS ARM v7のみ

sh ../configure --host arm-apple-darwin10 --enable-static --disable-shared CC = "/ Applications / Xcode.app / Contents / Developer / Platforms / iPhoneOS.platform / Developer / usr / bin / arm -apple-darwin10-llvm-gcc-4.2 "LD =" / Applications / Xcode.app / Contents / Developer / Platforms / iPhoneOS.platform / Developer / usr / bin / arm-apple-darwin10-llvm-gcc-4.2 "CFLAGS = "-mfloat-abi = softfp -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk -O3 -march = armv7 -mcpu = cortex-a8 -mtune = cortex-a8 -mfpu = neon "LDFLAGS ="-mfloat-abi = softfp -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk -march = armv7 -mcpu = cortex-a8 -mtune = cortex-a8 -mfpu = neon "



更新:

zlibライブラリは、NDKからネイティブに接続できます。 これを行うには、Android.mkで、zlibに関係するブロックを削除して登録する必要があります。

 LOCAL_LDLIBS := -llog -lGLESv1_CM -lz
      
      








All Articles