2011-11-28 9 views
10

मेरे पास एक ऐप है जो उपयोगकर्ता के लिए कुछ छवियां प्रदर्शित करता है, और हमें OutOfMemoryError अपवाद के साथ बहुत सारी त्रुटि रिपोर्ट दिखाई दे रही हैं। इस स्मृति के लिए काफी महंगा हैएंड्रॉइड पर छवियों को घूर्णन करना। क्या कोई बेहतर तरीका है?

// Check if image is a landscape image 
if (bmp.getWidth() > bmp.getHeight()) { 
    // Rotate it to show as a landscape 
    Matrix m = image.getImageMatrix(); 
    m.postRotate(90); 
    bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true); 
} 
image.setImageBitmap(bmp); 

इस के साथ स्पष्ट समस्या हम स्मृति पर छवि से बिटमैप से बनाना और मैट्रिक्स बारी बारी से जो है,:

क्या हम वर्तमान में ऐसा करते हैं है।

मेरा प्रश्न सरल है:

वहाँ OutOfMemoryError पैदा करने के बिना छवियों को घुमाने के लिए एक बेहतर तरीका है?

+0

http://www.twintechs.com/2008/06/frame-by-frame-xml-animation-with-google-android/ –

+0

कौन सी रेखा अपवाद को फेंक रही है – ingsaurabh

+0

@ डॉनिक तो, आप सुझाव दे रहे हैं कि मैं एक एनीमेशन के साथ छवि को घुमाता हूं, भले ही यह एनिमेटेड रोटेशन न हो? – Draiken

उत्तर

0

तुम कोशिश कर सकते हैं:

image.setImageBitmap(null); 
// Check if image is a landscape image 
if (bmp.getWidth() > bmp.getHeight()) { 
    // Rotate it to show as a landscape 
    Matrix m = image.getImageMatrix(); 
    m.postRotate(90); 
    bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true); 
} 
BitmapDrawable bd = new BitmapDrawable(mContext.getResources(), bmp); 
bmp.recycle(); 
bmp = null; 
setImageDrawable(bd); 
bd = null; 
+0

जैसा कि सवाल में एक टिप्पणी पर बताया गया है, त्रुटि 'Bitmap.createBitmap' लाइन में खुश है। – Draiken

+0

धन्यवाद, मैंने नहीं देखा कि – Caner

0

जब बिटमैप के बहुत सारे के साथ काम रीसायकल() उन पर जैसे ही वे आवश्यक नहीं हैं के रूप में कॉल करने के लिए सुनिश्चित करें। यह कॉल तुरंत एक विशेष बिटमैप से जुड़ी मेमोरी मुक्त होगी।

यदि आपके पास घूर्णन के बाद मूल बिटमैप की आवश्यकता नहीं है, तो इसे रीसायकल करें। की तर्ज पर कुछ:

Bitmap result = bmp; 

// Check if image is a landscape image 
if (bmp.getWidth() > bmp.getHeight()) { 
    // Rotate it to show as a landscape 
    Matrix m = image.getImageMatrix(); 
    m.postRotate(90); 
    result = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true); 
    // rotating done, original not needed => recycle() 
    bmp.recycle(); 
} 

image.setImageBitmap(result); 
+0

अच्छा, इसके बारे में नहीं पता था। समस्या यह है कि मुझे इसे घुमाने के लिए मूल बिटमैप की आवश्यकता है और इससे पहले कि मैं उसे स्मृति से मुक्त कर सकूं, त्रुटि उत्पन्न होती है:/ – Draiken

+0

वास्तव में मैंने रीसायकल की कोशिश की और यह अब बिटमैप की बजाय एक ब्लैक स्क्रीन दिखाता है। मुझे लगता है कि आंतरिक रूप से यह एक सूचक है और मैं वास्तव में इसके साथ गड़बड़ नहीं कर सकता। – Draiken

+0

एचएम। Bitmap.createBitmap() को पूरी तरह से नया बिटमैप बनाना चाहिए, इसलिए मूल को मुक्त करना सुरक्षित होना चाहिए। असल में मैं इस दृष्टिकोण का अपने कोड में बहुत कुछ उपयोग करता हूं और यह काफी अच्छा काम करता है। क्या आप सुनिश्चित हैं कि आप सही बिटमैप रीसाइक्लिंग कर रहे हैं और केवल * * * बिटबैप() को अन्य संदर्भ (जैसे मेरे उदाहरण में) द्वारा लौटाए गए घुमावदार बिटमैप के संदर्भ को निर्दिष्ट करने के बाद। अगर आप पहले से ही सभी मेमोरी का इस्तेमाल करते हैं तो यह createBitmap() में त्रुटि फेंक सकता है। लेकिन अगर हर बार जब आप इसे रीसायकल के साथ सही तरीके से मुक्त करते हैं() यह अगले आमंत्रणों पर ठीक होना चाहिए ... – dimsuz

6

2 एक बड़ी छवि घूर्णन के तरीके:

  1. JNI का उपयोग कर, on this post की तरह।

  2. फ़ाइल का उपयोग करके: यह बहुत धीमा तरीका है (इनपुट और डिवाइस के आधार पर, लेकिन अभी भी बहुत धीमा), जो इसे डीकोडेड घुमावदार छवि को पहले डिस्क में डालने की बजाय डिस्क में रखता है। एक फ़ाइल का उपयोग करने का

कोड के नीचे है:

private void rotateCw90Degrees() 
    { 
    Bitmap bitmap=BitmapFactory.decodeResource(getResources(),INPUT_IMAGE_RES_ID); 
    // 12 => 7531 
    // 34 => 8642 
    // 56 => 
    // 78 => 
    final int height=bitmap.getHeight(); 
    final int width=bitmap.getWidth(); 
    try 
    { 
    final DataOutputStream outputStream=new DataOutputStream(new BufferedOutputStream(openFileOutput(ROTATED_IMAGE_FILENAME,Context.MODE_PRIVATE))); 
    for(int x=0;x<width;++x) 
     for(int y=height-1;y>=0;--y) 
     { 
     final int pixel=bitmap.getPixel(x,y); 
     outputStream.writeInt(pixel); 
     } 
    outputStream.flush(); 
    outputStream.close(); 
    bitmap.recycle(); 
    final int newWidth=height; 
    final int newHeight=width; 
    bitmap=Bitmap.createBitmap(newWidth,newHeight,bitmap.getConfig()); 
    final DataInputStream inputStream=new DataInputStream(new BufferedInputStream(openFileInput(ROTATED_IMAGE_FILENAME))); 
    for(int y=0;y<newHeight;++y) 
     for(int x=0;x<newWidth;++x) 
     { 
     final int pixel=inputStream.readInt(); 
     bitmap.setPixel(x,y,pixel); 
     } 
    inputStream.close(); 
    new File(getFilesDir(),ROTATED_IMAGE_FILENAME).delete(); 
    saveBitmapToFile(bitmap); //for checking the output 
    } 
    catch(final IOException e) 
    { 
    e.printStackTrace(); 
    } 
    } 
+0

@android_developer आपका प्यार करता है फ़ाइल समाधान, मुझे लगता है कि यह सभी स्मृति मुद्दों से बचने के लिए समय के लायक है। –

+0

@ पीटरफाइल मुझे लगता है कि आपको इसे धीमे (अभी तक सबसे खतरनाक) से धीमे (अभी तक सबसे खतरनाक) से कई फ़ॉलबैक में करना चाहिए: पहले सामान्य तरीके (ढेर का उपयोग करके) का उपयोग करके प्रयास करें। अगर वह विफल रहता है (पर्याप्त स्मृति नहीं), जेएनआई समाधान का उपयोग करें। अगर वह विफल रहता है (पर्याप्त स्मृति नहीं), भंडारण समाधान का उपयोग करें। भंडारण समाधान भी असफल हो सकता है (पर्याप्त भंडारण नहीं), क्योंकि बनाई गई फ़ाइल डीकोडेड बिटमैप है, और संपीड़ित नहीं है, लेकिन ऐसा होने वाली दुर्लभ बात हो सकती है। –

+0

@androiddeveloper क्या आप मूल छवि आकार और गुणवत्ता को हल करते हैं? –

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

  • कोई संबंधित समस्या नहीं^_^