Android NDK में PNG और JPEG चित्र डाउनलोड करें

सभी पाठकों को नमस्कार!
यह आलेख चर्चा करेगा कि एंड्रॉइड एनडीके में पीएनजी और जेपीईजी छवियों को एक फ़ाइल या मेमोरी से कैसे लोड किया जाए, साथ ही इन ओपन इमेज को खिलाने के लिए कुछ उपयोगी कोड।

डाउनलोड


छवियों को डाउनलोड करने के लिए, हम निम्नलिखित पुस्तकालयों का उपयोग करेंगे:

खोलना


हम सब कुछ फ़ोल्डरों में बड़े करीने से विघटित करते हैं, उदाहरण के लिए, प्रोजेक्ट रूट में मॉड्यूल फ़ोल्डर बनाएं, जहां जेनी फ़ोल्डर स्थित है । खोल:
इस प्रकार ऐसी संरचना प्राप्त करें
परियोजना / जानी
परियोजना / मॉड्यूल / पीएनजी
परियोजना / मॉड्यूल / जेपीईजी
परियोजना / मॉड्यूल / zlib

धुन



Android.mk संपादित करें


Android.mk में हम सभी पुस्तकालयों को एक साथ जोड़ते हैं
LOCAL_PATH: = $ (my-dir को कॉल करें)
हेडर्स: =
STATICLIBS: =

$ (CLEAR_VARS) शामिल करें
LOCAL_MODULE: = png
FILE_LIST: = $ (वाइल्डकार्ड $ (LOCAL_PATH) /../ मॉड्यूल / png / * C।)।
LOCAL_SRC_FILES: = $ (FILE_LIST: $ (LOCAL_PATH) /% =%)
LOCAL_EXPORT_C_INCLUDES: = $ (LOCAL_PATH) /../ मॉड्यूल / पीएनजी
हेडर्स + = $ (LOCAL_EXPORT_C_INCLUDES)
STATICLIBS + = $ (LOCAL_MODULE)
$ (BUILD_STATIC_LIBRARY) शामिल करें

$ (CLEAR_VARS) शामिल करें
LOCAL_MODULE: = zlib
FILE_LIST: = $ (वाइल्डकार्ड $ (LOCAL_PATH) /../ मॉड्यूल / zlib / *। C *)
LOCAL_SRC_FILES: = $ (FILE_LIST: $ (LOCAL_PATH) /% =%)
LOCAL_EXPORT_C_INCLUDES: = $ (LOCAL_PATH) /../ मॉड्यूल / ज़ीब
हेडर्स + = $ (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) /../ मॉड्यूल / एमपीईजी
STATICLIBS + = $ (LOCAL_MODULE)
हेडर्स + = $ (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 -fsign-char -Wno-write -Wno-psabi
LOCAL_LDLIBS: = -llog -lGLESv1_CM
LOCAL_STATIC_LIBRARIES: = $ (STATICLIBS)
LOCAL_C_INCLUDES = $ (HEADERS)
$ (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; } 

परीक्षण


मेमोरी कार्ड से पीएनजी छवियों का परीक्षण करना:
 // 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; 

इसी तरह, हम जेपीईजी के साथ करते हैं, यह देखते हुए कि जेपीईजी हमेशा पारदर्शिता के बिना होता है
 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; 

एन्क्रिप्शन के साथ चित्र पढ़ना


यदि आपको सरल चित्र एन्क्रिप्शन लागू करने की आवश्यकता है, तो आप डिक्रिप्शन फ़ंक्शन को सीधे चित्र पढ़ने की प्रक्रिया में सम्मिलित कर सकते हैं:

स्मृति से चित्र पढ़ना


उदाहरण के लिए, एप्लिकेशन को नेटवर्क पर एक चित्र प्राप्त हुआ और चित्र पूरी तरह से मेमोरी में लटका हुआ है।

ओपेंगल बन्स


 //   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 बनावट बनाने के बाद हमें इसकी आवश्यकता नहीं होती है।

मुझे यकीन है कि किसी को ये घटनाक्रम उपयोगी लगेगा। किसी भी स्थिति में, इससे पहले मुझे जेएनआई जावा के माध्यम से डाउनलोड की गई फ़ाइलों को फेंकना था, वहां एक बिटमैप बनाएं, पिक्सल पढ़ें और उन्हें एनडीके को वापस भेजें, जो कि समय और मेमोरी दोनों में अधिक महंगा परिमाण का एक आदेश था। इसके अलावा, इन सभी कार्यों का उपयोग न केवल एंड्रॉइड एनडीके में, बल्कि आईओएस / मैकओएस में भी किया जा सकता है।
बस के मामले में, यहाँ libjpeg-टर्बो संकलित करने के आदेश हैं (libpng को बिना किसी समस्या के केवल Xcode में फ़ोल्डर जोड़कर संकलित किया जा सकता है):
छिपा हुआ पाठ
सीडी {source_directory}
autoreconf -fiv
mkdir का निर्माण
सीडी का निर्माण

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 -एप्पल-डार्विन 10-llvm-gcc-4.2 "LD =" / Applications / Xcode.app / Contents / Developer / Platforms / iPhoneOS.platform / Developer / usr / bin / arm-apple-darv10-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 = cortex-a8 -mfpu = नियॉन "LDFLAGS =" - mfloat-abi = softfp -isysroot /Applications/Xcode.app/Contents/Developer/dlatforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1s.sf -mcpu = cortex-a8 -mtune = cortex-a8 -mfpu = नियॉन "

अपडेट:
Zlib लाइब्रेरी को NDK से देशी जोड़ा जा सकता है। ऐसा करने के लिए, Android.mk में आपको उस ब्लॉक को हटाने की जरूरत है जो zlib और रजिस्टर की चिंता करता है:
 LOCAL_LDLIBS := -llog -lGLESv1_CM -lz 

Source: https://habr.com/ru/post/In173303/


All Articles