2013-04-29 8 views
6

onPictureTaken में, मैं निम्नलिखित करना चाहते हैं:बिटमैप प्रोसेसिंग करते समय "मेमोरी अपवाद से बाहर" कैसे बचें?

Bitmap decodedPicture = BitmapFactory.decodeByteArray(data, 0, data.length); 
Matrix matrix = new Matrix(); 
matrix.preScale(-1.0f, 1.0f); 
Bitmap picture = Bitmap.createBitmap(decodedPicture, 0, 0, decodedPicture.getWidth(), decodedPicture.getHeight(), matrix, false); 

View v1 = mainLayout.getRootView(); 
v1.setDrawingCacheEnabled(true); 
Bitmap screenshot = Bitmap.createBitmap(v1.getDrawingCache()); 
v1.setDrawingCacheEnabled(false); 

Bitmap scaledPicture = Bitmap.createScaledBitmap(picture, screenshot.getWidth(), screenshot.getHeight(), true); 

Bitmap compos = Bitmap.createBitmap(scaledPicture.getWidth(), scaledPicture.getHeight(), Bitmap.Config.ARGB_8888); 

Canvas canvas = new Canvas(compos); 
canvas.drawBitmap(scaledPicture, new Matrix(), null); 
canvas.drawBitmap(screenshot, new Matrix(), null); 

MediaStore.Images.Media.insertImage(getContentResolver(), compos, "name" , "description"); 
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 

मेरी केवल आवश्यकता है कि मैं एक उच्च गुणवत्ता वाले तस्वीर को बचाने के लिए करना चाहते हैं ... लगता है मुझे लगता है कि बलिदान करने के लिए हो सकता है।

मेरे नेक्सस 4 और नए उपकरणों पर, यह कोड ठीक चलता है और अपेक्षित है। लेकिन पुराने उपकरणों पर कम स्मृति है, मैं राम से बाहर चला रहा हूँ! :(

मेमोरी सीमा के बिना चलने के बिना मैं वही छवि मैनिपुलेशन कैसे करूं ?? मैं प्रदर्शित करने की कोशिश नहीं कर रहा हूं स्क्रीन पर इन छवियों को प्रदर्शित करें, इसलिए समाधानों को स्केल किए गए चित्र डॉन के साथ करना है वास्तव में यहां लागू नहीं है ...

+0

आप कुछ संदर्भों को शून्य कर सकते हैं, और फिर एक जीसी संकेत पर है? इसे कुछ अनावश्यक डेटा हटा देना चाहिए ... – tilpner

उत्तर

3

आपको एक बढ़ते नमूना आकार के साथ बिटमैप पढ़ने की जरूरत है। चाल सही नमूना आकार ढूंढ रही है जिसके परिणामस्वरूप आप अंततः छवि को स्केल करते समय संकल्प को कम नहीं करेंगे। इसके बारे में एक ब्लॉग एंट्री जिसमें स्केलिंग के लिए एक अच्छी उपयोगिता कक्षा शामिल है,

http://zerocredibility.wordpress.com/2011/01/27/android-bitmap-scaling/

आप शायद उस वर्ग अपने विशिष्ट जरूरतों के आधार पर काफ़ी आसान बनाने में कर सकता है।

जिस्ट बस बिटमैप के आकार को पढ़ने के लिए है। अपने वांछित स्केल किए गए आकार के आधार पर इष्टतम नमूना आकार की गणना करें, उस नमूना आकार का उपयोग करने में बिटमैप पढ़ें, फिर इसे ठीक आकार में ठीक से स्केल करें।

0

आपके पास इतने सारे बिटमैप ऑब्जेक्ट हैं जो आसपास झूठ बोल रहे हैं। इनमें से कुछ रीसाइक्लिंग/पुन: उपयोग करने का प्रयास करें।

बिल्कुल सुनिश्चित नहीं है कि आपकी आवश्यकता क्या है लेकिन मैं देख सकता हूं कि आप इसे आसानी से कुछ स्मृति बचा सकते हैं।

 Bitmap decodedPicture = BitmapFactory.decodeByteArray(data, 0, data.length); 
     Matrix matrix = new Matrix(); 
     matrix.preScale(-1.0f, 1.0f); 
     Bitmap picture = Bitmap.createBitmap(decodedPicture, 0, 0, decodedPicture.getWidth(), decodedPicture.getHeight(), matrix, false); 

     decodedPicture.recycle(); 
     decodedPicture=null; 

     View v1 = mainLayout.getRootView(); 
     v1.setDrawingCacheEnabled(true); 
     Bitmap screenshot = Bitmap.createBitmap(v1.getDrawingCache()); 
     v1.setDrawingCacheEnabled(false); 

     Bitmap scaledPicture = Bitmap.createScaledBitmap(picture, screenshot.getWidth(), screenshot.getHeight(), true); 

     picture.recycle(); 
     picture=null; 

     Bitmap compos = Bitmap.createBitmap(scaledPicture.getWidth(), scaledPicture.getHeight(), Bitmap.Config.ARGB_8888); 

     Canvas canvas = new Canvas(compos); 
     canvas.drawBitmap(scaledPicture, new Matrix(), null); 
     canvas.drawBitmap(screenshot, new Matrix(), null); 

     MediaStore.Images.Media.insertImage(getContentResolver(), compos, "name" , "description"); 
     sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 

अपनी मेमोरी पदचिह्न को भी देखें, सुनिश्चित करें कि आप जिस डिवाइस की मेमोरी मेमोरी का उपयोग कर रहे हैं वह बहुत बड़ा नहीं है।

एफवाईआई, पोस्ट हनीकॉम डिवाइस पर बिटमैप पिक्सेल छवि मूल परत पर आवंटित। आप recycle() या finalizer() जरूरत स्मृति बहाल करने के लिए

+0

'अंतिमकरण()' का उपयोग करना एक बुरा विचार है। http://stackoverflow.com/questions/2506488/java-finalize-method-call। 'रीसायकल()' पर एंड्रॉइड प्रलेखन से भी: 'यह एक उन्नत कॉल है, और आम तौर पर इसे कॉल करने की आवश्यकता नहीं है, क्योंकि सामान्य जीसी प्रक्रिया इस स्मृति को मुक्त कर देगी जब इस बिटमैप के कोई और संदर्भ नहीं हैं।' –

0

आप को ध्यान में रखते अपने बिटमैप आकार बदलने के लिए नहीं करना चाहते हैं और यह प्रदर्शित करने के लिए नहीं करना चाहते, मैं इस तरह कुछ करना चाहते हैं:

  1. लोड बिटमैप के साथ inJustDecodeBounds अपने मूल ऊंचाई और चौड़ाई (here से कोड)

    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 
    
    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 
    
  2. देखने के लिए आकार और स्मृति आप पर निर्भर करता है, आप सीधे वहाँ से इसे संसाधित (यानी बिटमैप लोड) या आगे बढ़ सकते हैं Bitmap.createBitmap विधि के साथ बिटकमैप के कई हिस्सों को लोड करने के लिए जो आपको डेटा का एक हिस्सा लोड करने की अनुमति देता है। वैकल्पिक रूप से: खंड को संसाधित करने से पहले इसे बाइट सरणी में परिवर्तित करें (नीचे कोड देखें) और शून्य + recycle() पर विचार करें।

कोड

ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream(); 
bitmapPicture.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, byteArrayBitmapStream); 
byte[] b = byteArrayBitmapStream.toByteArray(); 
0

मैं बिटमैप वर्ग WeakReference साथ काम करने के लिए इस्तेमाल करते हैं और बाद मैं हमेशा उदाहरण वस्तु WeakReference, घुमाने छवि के लिए स्निपेट कोड पर रीसायकल फोन:

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inScaled = false; 
options.inPurgeable = true; 
options.inInputShareable = true; 
options.inPreferredConfig = Bitmap.Config.RGB_565; 
WeakReference<Bitmap> imageBitmapReference = new WeakReference<Bitmap>(BitmapFactory.decodeByteArray(params[0], 0, params[0].length, options)); 

Matrix mat = new Matrix(); 
mat.postRotate(90.0f); 
imageBitmapReference = new WeakReference<Bitmap (Bitmap.createBitmap(imageBitmapReference.get(), 0, 0, resolution[0], resolution[1], mat, true)); 

FileOutputStream fos = new FileOutputStream(filename); 
imageBitmapReference.get().compress(Bitmap.CompressFormat.PNG, 100, fos); 
fos.flush(); 
fos.close(); 
imageBitmapReference.get().recycle(); 

और दूसरा समाधान बिटमैप के साथ कैसे काम करता है और आउटऑफमेमरी अपवाद नहीं मिलता है लाइब्रेरी Universal Image Loader

का उपयोग करता है

(बेशक यह आपके AndroidManifest प्रॉपर्टी एंड्रॉइड में तीसरा समाधान सेट है: bigHeap = "true" और वास्तव में इस संपत्ति का उपयोग न करें)।

सही सामग्री http://developer.android.com/training/displaying-bitmaps/index.html और वीडियो https://www.youtube.com/watch?v=_CruQY55HOk

संबंधित मुद्दे