दिलचस्प पोस्ट
SSH कनेक्शन की जांच करने के लिए एक बाश स्क्रिप्ट कैसे बनाएं? Google मैप्स एंड्रॉइड एपीआई वी 2 जांच करें कि क्या GoogleMaps डिवाइस पर स्थापित है या नहीं क्यों json_encode बैकस्लैश जोड़ रहा है? एंड्रॉइड में ड्रायेट करने के लिए बिटमैप कन्वर्ट कैसे करें? Xcode इंस्ट्रूमेंट्स .trace फ़ाइल को पढ़ने की कोशिश कर रहा है। .trace फ़ाइल का फ़ाइल स्वरूप क्या है? Android में Google Places API का उपयोग करना मीडियाविकि पेज से एपीआई के माध्यम से पाठ सामग्री प्राप्त करें जावा में मौजूदा कार्यरत निर्देशिका को बदलना? Seedable जावास्क्रिप्ट यादृच्छिक संख्या जनरेटर क्या जावा में स्टॉपवॉच है? स्विफ्ट भाषा में विस्मयादिबोधक चिह्न का क्या अर्थ है? आईफोन पर वर्तमान स्थानीय समय प्राप्त करना? JSON प्रतिक्रिया में ZF2 दृश्य कैसे प्रस्तुत करना है? AppCompat v.7 के साथ ActionBar दिखाने और छिपाने के लिए जावास्क्रिप्ट चेतावनी फ़ायरफ़ॉक्स 6 में काम नहीं कर रहा है

बड़े चित्रों का उपयोग करते समय ओओएम को टालने में मदद करने के लिए जेएनआई बिटमैप संचालन

पृष्ठभूमि

ज्यादातर समय, एंड्रॉइड पर ओओएम होने के कारण बहुत सारे बिटमैप्स का इस्तेमाल होता है और / या बड़े बिटमैप का निर्माण होता है

हाल ही में मैंने जेएनआई को बाहर करने की कोशिश करने का फैसला किया है ताकि जेएमआई साइड पर डेटा खुद संग्रहीत करके ओओएम से बचा जा सके।

थोड़ी देर के लिए जेएनआई के साथ घूमने के बाद, मैंने कुछ पदों की मदद की है और अपने ज्ञान को बांटने के लिए कहा है, और अब मैंने आपके साथ कुछ और कोड साझा करने का फैसला किया है। यहां पद हैं, किसी व्यक्ति को निष्कर्ष पढ़ने या योगदान करने में रुचि है:

  • मूल स्मृति में बिटमैप कैश कैसे करें

  • एंड्रॉइड पर जेएनआई का उपयोग करते हुए छवि डिकोडिंग और हेरफेर

  • जेएनआई – विभिन्न क्षेत्रों के साथ कई जेनी आवरण उदाहरणों का उपयोग कैसे करें?

  • जेएनआई और एनडीके का उपयोग करते हुए एक बिटमैप घूम रहा है

इस समय, मैंने स्टोर, बहाल, फसल और बिटमैप को घुमाने की क्षमता जोड़ दी है I इसे और अधिक विकल्प जोड़ना आसान होना चाहिए और यदि अन्य लोग यहां अपने स्वयं के कोड को अधिक उपयोगी कार्यों में जोड़ देंगे तो मुझे खुशी होगी

इसलिए जो कोड मैं दिखा रहा हूँ वह वास्तव में मैंने बनाई गई सभी चीजों का मर्ज है

उपयोग के नमूना कोड:

Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher); final int width=bitmap.getWidth(),height=bitmap.getHeight(); // store the bitmap in the JNI "world" final JniBitmapHolder bitmapHolder=new JniBitmapHolder(bitmap); // no need for the bitmap on the java "world", since the operations are done on the JNI "world" bitmap.recycle(); // crop a center square from the bitmap, from (0.25,0.25) to (0.75,0.75) of the bitmap. bitmapHolder.cropBitmap(width/4,height/4,width*3/4,height*3/4); //rotate the bitmap: bitmapHolder.rotateBitmapCcw90(); //get the output java bitmap , and free the one on the JNI "world" bitmap=bitmapHolder.getBitmapAndFree(); 

यह परियोजना गिथूब पर उपलब्ध है

  • परियोजना पृष्ठ गिटूब पर यहां उपलब्ध है

  • सलाह देने और योगदान देने के लिए स्वतंत्र महसूस करें

महत्वपूर्ण लेख

वही नोट्स जैसा कि यहां दिखाया गया है , प्लस:

  • वर्तमान विशेषताएं जो यहां लिखी गई हैं (प्रोजेक्ट पेज पर अधिक अद्यतन):

    • दुकान

    • बहाल

    • 90 डिग्री सीसीडब्ल्यू बारी बारी से

    • फसल।

  • मैंने इस कोड के लिए जो दृष्टिकोण लिया है, वह स्मृति क्षमता है (केवल मेमोरी का उपयोग करें जो मुझे ज़रूरत है, और इसे तब आवश्यक नहीं है जब जरूरत नहीं है), और CPU दक्षता (जब भी संभव हो मैं पॉइंटर्स और CPU मेमोरी कैश अनुकूलन का उपयोग करने की कोशिश की)।

  • सर्वोत्तम प्रदर्शन के लिए, मैंने वास्तव में कुछ मान्यताओं को किया है, खासकर जेएनआई भाग पर। जावा "विश्व" पर मान्यताओं का प्रबंधन करना सबसे अच्छा हो सकता है

  • अब भी कई लापता विशेषताएं हैं जिन्हें मुझे लगता है कि जोड़ा जाना चाहिए, और मुझे उम्मीद है कि मेरे पास उन्हें जोड़ने का समय होगा। अगर कोई भी योगदान करना चाहता है, तो मैं उन्हें भी कोड जोड़ने में खुशी होगी यहाँ कार्य है जो मुझे लगता है कि उपयोगी हो सकता है:

    • वर्तमान बिटमैप जानकारी प्राप्त करें

    • स्केल बिटमैप, जिसमें एल्गोरिथम का चयन करने के लिए विकल्प शामिल है (निकटतम पड़ोसी और बायलाइनर प्रक्षेपण पर्याप्त होना चाहिए)।

    • अलग बिटमैप प्रारूपों का उपयोग करें

    • जेएनआई के भीतर डीकोडिंग करना, शुरुआत से जावा बिटमैप (और जावा वर्ल्ड पर ढेर का इस्तेमाल न करने) से बचने के लिए, केवल अंत में, जब आप सभी कार्यों के साथ समाप्त हो जाएंगे

    • चेहरा पहचानना

    • किसी भी कोण में रोटेशन, या कम से कम स्पष्ट वाले वर्तमान में मैंने केवल 90 डिग्री काउंटर घड़ी के अनुसार रोटेशन जोड़ा।

Solutions Collecting From Web of "बड़े चित्रों का उपयोग करते समय ओओएम को टालने में मदद करने के लिए जेएनआई बिटमैप संचालन"

नोट: यह थोड़ा पुराना कोड है सबसे अद्यतित एक के लिए, github पर प्रोजेक्ट पेज देखें।

JNI / Android.mk

 LOCAL_PATH := $(call my-dir) #bitmap operations module include $(CLEAR_VARS) LOCAL_MODULE := JniBitmapOperations LOCAL_SRC_FILES := JniBitmapOperations.cpp LOCAL_LDLIBS := -llog LOCAL_LDFLAGS += -ljnigraphics include $(BUILD_SHARED_LIBRARY) APP_OPTIM := debug LOCAL_CFLAGS := -g #if you need to add more module, do the same as the one we started with (the one with the CLEAR_VARS) 

JNI / JniBitmapOperations.cpp

 #include <jni.h> #include <jni.h> #include <android/log.h> #include <stdio.h> #include <android/bitmap.h> #include <cstring> #include <unistd.h> #define LOG_TAG "DEBUG" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) extern "C" { JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap); JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle); JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle); JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle); JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom); } class JniBitmap { public: uint32_t* _storedBitmapPixels; AndroidBitmapInfo _bitmapInfo; JniBitmap() { _storedBitmapPixels = NULL; } }; /**crops the bitmap within to be smaller. note that no validations are done*/ // JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom) { JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle); if (jniBitmap->_storedBitmapPixels == NULL) return; uint32_t* previousData = jniBitmap->_storedBitmapPixels; uint32_t oldWidth = jniBitmap->_bitmapInfo.width; uint32_t newWidth = right - left, newHeight = bottom - top; uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight]; uint32_t* whereToGet = previousData + left + top * oldWidth; uint32_t* whereToPut = newBitmapPixels; for (int y = top; y < bottom; ++y) { memcpy(whereToPut, whereToGet, sizeof(uint32_t) * newWidth); whereToGet += oldWidth; whereToPut += newWidth; } //done copying , so replace old data with new one delete[] previousData; jniBitmap->_storedBitmapPixels = newBitmapPixels; jniBitmap->_bitmapInfo.width = newWidth; jniBitmap->_bitmapInfo.height = newHeight; } /**rotates the inner bitmap data by 90 degress counter clock wise*/ // JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle) { JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle); if (jniBitmap->_storedBitmapPixels == NULL) return; uint32_t* previousData = jniBitmap->_storedBitmapPixels; AndroidBitmapInfo bitmapInfo = jniBitmap->_bitmapInfo; uint32_t* newBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width]; int whereToPut = 0; // AD DC // ...>... // BC AB for (int x = bitmapInfo.width - 1; x >= 0; --x) for (int y = 0; y < bitmapInfo.height; ++y) { uint32_t pixel = previousData[bitmapInfo.width * y + x]; newBitmapPixels[whereToPut++] = pixel; } delete[] previousData; jniBitmap->_storedBitmapPixels = newBitmapPixels; uint32_t temp = bitmapInfo.width; bitmapInfo.width = bitmapInfo.height; bitmapInfo.height = temp; } /**free bitmap*/ // JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle) { JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle); if (jniBitmap->_storedBitmapPixels == NULL) return; delete[] jniBitmap->_storedBitmapPixels; jniBitmap->_storedBitmapPixels = NULL; delete jniBitmap; } /**restore java bitmap (from JNI data)*/ // JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle) { JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle); if (jniBitmap->_storedBitmapPixels == NULL) { LOGD("no bitmap data was stored. returning null..."); return NULL; } // //creating a new bitmap to put the pixels into it - using Bitmap Bitmap.createBitmap (int width, int height, Bitmap.Config config) : // //LOGD("creating new bitmap..."); jclass bitmapCls = env->FindClass("android/graphics/Bitmap"); jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;"); jstring configName = env->NewStringUTF("ARGB_8888"); jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config"); jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;"); jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass, valueOfBitmapConfigFunction, configName); jobject newBitmap = env->CallStaticObjectMethod(bitmapCls, createBitmapFunction, jniBitmap->_bitmapInfo.width, jniBitmap->_bitmapInfo.height, bitmapConfig); // // putting the pixels into the new bitmap: // int ret; void* bitmapPixels; if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &bitmapPixels)) < 0) { LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret); return NULL; } uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels; int pixelsCount = jniBitmap->_bitmapInfo.height * jniBitmap->_bitmapInfo.width; memcpy(newBitmapPixels, jniBitmap->_storedBitmapPixels, sizeof(uint32_t) * pixelsCount); AndroidBitmap_unlockPixels(env, newBitmap); //LOGD("returning the new bitmap"); return newBitmap; } /**store java bitmap as JNI data*/ // JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap) { AndroidBitmapInfo bitmapInfo; uint32_t* storedBitmapPixels = NULL; //LOGD("reading bitmap info..."); int ret; if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0) { LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret); return NULL; } LOGD("width:%d height:%d stride:%d", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride); if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { LOGE("Bitmap format is not RGBA_8888!"); return NULL; } // //read pixels of bitmap into native memory : // //LOGD("reading bitmap pixels..."); void* bitmapPixels; if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0) { LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret); return NULL; } uint32_t* src = (uint32_t*) bitmapPixels; storedBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width]; int pixelsCount = bitmapInfo.height * bitmapInfo.width; memcpy(storedBitmapPixels, src, sizeof(uint32_t) * pixelsCount); AndroidBitmap_unlockPixels(env, bitmap); JniBitmap *jniBitmap = new JniBitmap(); jniBitmap->_bitmapInfo = bitmapInfo; jniBitmap->_storedBitmapPixels = storedBitmapPixels; return env->NewDirectByteBuffer(jniBitmap, 0); } 

src / com / JNI / bitmap_operations / JniBitmapHolder.java

 package com.jni.bitmap_operations; import java.nio.ByteBuffer; import android.graphics.Bitmap; import android.util.Log; public class JniBitmapHolder { ByteBuffer _handler =null; static { System.loadLibrary("JniBitmapOperations"); } private native ByteBuffer jniStoreBitmapData(Bitmap bitmap); private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler); private native void jniFreeBitmapData(ByteBuffer handler); private native void jniRotateBitmapCcw90(ByteBuffer handler); private native void jniCropBitmap(ByteBuffer handler,final int left,final int top,final int right,final int bottom); public JniBitmapHolder() {} public JniBitmapHolder(final Bitmap bitmap) { storeBitmap(bitmap); } public void storeBitmap(final Bitmap bitmap) { if(_handler!=null) freeBitmap(); _handler=jniStoreBitmapData(bitmap); } public void rotateBitmapCcw90() { if(_handler==null) return; jniRotateBitmapCcw90(_handler); } public void cropBitmap(final int left,final int top,final int right,final int bottom) { if(_handler==null) return; jniCropBitmap(_handler,left,top,right,bottom); } public Bitmap getBitmap() { if(_handler==null) return null; return jniGetBitmapFromStoredBitmapData(_handler); } public Bitmap getBitmapAndFree() { final Bitmap bitmap=getBitmap(); freeBitmap(); return bitmap; } public void freeBitmap() { if(_handler==null) return; jniFreeBitmapData(_handler); _handler=null; } @Override protected void finalize() throws Throwable { super.finalize(); if(_handler==null) return; Log.w("DEBUG","JNI bitmap wasn't freed nicely.please rememeber to free the bitmap as soon as you can"); freeBitmap(); } }