2012-10-11 19 views
5

से बिटमैप का आकार बदलना मैं इनपुटस्ट्रीम से एक छवि का आकार बदलने का प्रयास कर रहा हूं, इसलिए मैं Strange out of memory issue while loading an image to a Bitmap object में कोड का उपयोग करता हूं लेकिन मुझे नहीं पता कि यह कोड हमेशा छवि के बिना ड्रायबल क्यों लौटाता है।इनपुटस्ट्रीम

यह एक अच्छी तरह से काम करता है:

private Drawable decodeFile(InputStream f){ 
    try { 
     InputStream in2 = new BufferedInputStream(f); 
     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inSampleSize=2; 
     return new BitmapDrawable(BitmapFactory.decodeStream(in2, null, o2)); 
    } catch (Exception e) { 
     return null; 
    } 
} 

यह एक काम नहीं करता:

private Drawable decodeFile(InputStream f){ 
    try { 
     InputStream in1 = new BufferedInputStream(f); 
     InputStream in2 = new BufferedInputStream(f); 
     //Decode image size 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(in1,null,o); 

     //The new size we want to scale to 
     final int IMAGE_MAX_SIZE=90; 

     //Find the correct scale value. It should be the power of 2. 
     int scale = 2; 
     if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) { 
      scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE/
       (double) Math.max(o.outHeight, o.outWidth))/Math.log(0.5))); 
     } 

     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inJustDecodeBounds = false; 
     o2.inSampleSize=scale; 
     return new BitmapDrawable(BitmapFactory.decodeStream(in2, null, o2)); 
    } catch (Exception e) { 
     return null; 
    } 
} 

क्यों एक ही विकल्प दूसरे को प्रभावित? यदि मैं दो अलग इनपुटस्ट्रीम और विकल्पों का उपयोग करता हूं तो यह कैसे संभव है?

संपादित

समाधान:

private Drawable decodeFile(InputStream in){ 
    try { 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     byte[] buffer = new byte[1024]; 
     int len; 
     while ((len = in.read(buffer)) > -1) { 
      baos.write(buffer, 0, len); 
     } 
     baos.flush(); 
     InputStream is1 = new ByteArrayInputStream(baos.toByteArray()); 
     InputStream is2 = new ByteArrayInputStream(baos.toByteArray()); 

     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(is1,null,o); 

     final int IMAGE_MAX_SIZE=90; 

     System.out.println("h:" + o.outHeight + " w:" + o.outWidth); 
     int scale = 1; 
     if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) { 
      scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE/
       (double) Math.max(o.outHeight, o.outWidth))/Math.log(0.5))); 
     } 

     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inSampleSize=scale; 
     return new BitmapDrawable(BitmapFactory.decodeStream(is2, null, o2)); 
    } catch (Exception e) { 
     return null; 
    } 
} 

उत्तर

7

वास्तव में आप दो अलग अलग BufferedInputStream है, लेकिन वे आंतरिक रूप से केवल एक ही InputStream वस्तु का उपयोग करें क्योंकि BufferedInputStream केवल InputStream के लिए एक आवरण है।

तो आप एक ही स्ट्रीम पर दो बार BitmapFactory.decodeStream विधि को कॉल नहीं कर सकते हैं, यह निश्चित रूप से विफल हो जाएगा क्योंकि दूसरी बार यह स्ट्रीम की शुरुआत से डीकोडिंग शुरू नहीं करेगा। यदि आपको समर्थित है या इसे फिर से खोल दिया गया है तो आपको अपनी स्ट्रीम रीसेट करने की आवश्यकता है।

+0

समझते हैं .. लेकिन मुझे यह स्ट्रीम HttpURLConnection से प्राप्त होती है, मैं यह कैसे कर सकता हूं? – kavain

+0

आप सही हैं, मेरे पास दो इनपुटस्ट्रीम नहीं हैं, जैसा कि आपने कहा था, और मैं सीखता हूं कि यहां इनपुट इनपुट कैसे डुप्लिकेट करें: http://stackoverflow.com/questions/5923817/how-to-clone-an-inputstream आपको बहुत धन्यवाद बहुत। – kavain

+2

आपको एहसास है कि आप स्मृति सुधार के लिए बिटमैप का आकार बदल रहे हैं? लेकिन वह लिंक आपको पूरे बिटमैप की बैकिंग बाइट सरणी को स्मृति में दो बार रखेगा ... मैं केवल FileInputStream को फिर से खोलूंगा या जो भी आप फिर से उपयोग कर रहे हैं। – HandlerExploit

1

यह मेरा कोड है कि अच्छी तरह से काम करता है, मुझे आशा है कि यह मदद मिलेगी

//Decode image size 
    BitmapFactory.Options optionsIn = new BitmapFactory.Options(); 
    optionsIn.inJustDecodeBounds = true; // the trick is HERE, avoiding memory leaks 
    BitmapFactory.decodeFile(filePath, optionsIn); 

    BitmapFactory.Options optionsOut = new BitmapFactory.Options(); 
    int requiredWidth = ECameraConfig.getEntryById(Preferences.I_CAMERA_IMAGE_RESOLUTION.get()).getyAxe(); 
    float bitmapWidth = optionsIn.outWidth; 
    int scale = Math.round(bitmapWidth/requiredWidth); 
    optionsOut.inSampleSize = scale; 
    optionsOut.inPurgeable = true;//avoiding memory leaks 
    return BitmapFactory.decodeFile(filePath, optionsOut); 

और मैं तुम्हें न 2 InputStream जरूरत belive।

+1

यह केवल फाइलों के लिए काम करता है .. लेकिन धन्यवाद। – kavain