2010-04-14 15 views
59

के साथ बिटमैप डीकोडिंग मैं BitmapFactory.decodeFile का उपयोग कर एसडी कार्ड से बिटमैप्स डीकोड करता हूं। कभी-कभी बिटमैप एप्लिकेशन की ज़रूरतों के मुकाबले बड़े होते हैं या ढेर की अनुमति देता है, इसलिए मैं subsampled (छोटे) बिटमैप का अनुरोध करने के लिए BitmapFactory.Options.inSampleSize का उपयोग करता हूं।एंड्रॉइड में सही आकार

समस्या यह है कि प्लेटफ़ॉर्म SampleSize के सटीक मान को लागू नहीं करता है, और मैं कभी-कभी बिटमैप के साथ समाप्त होता हूं, या तो उपलब्ध स्मृति के लिए बहुत छोटा या फिर भी बड़ा होता है।

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize से

:

नोट: डिकोडर इस अनुरोध को पूरा करने की कोशिश करेंगे, लेकिन जिसके परिणामस्वरूप बिटमैप विभिन्न आयामों कि ठीक क्या अनुरोध किया गया है हो सकता है। इसके अलावा, 2 की शक्तियां अक्सर डिकोडर के लिए सम्मान के लिए तेज़/आसान होती हैं।

मैं कैसे डिकोड चाहिए एसडी कार्ड से बिटमैप्स सटीक आकार यथासंभव कम स्मृति लेने वाली, जबकि यह डिकोड करने की आवश्यकता का एक बिटमैप पाने के लिए?

संपादित करें:

वर्तमान स्रोत कोड:

BitmapFactory.Options bounds = new BitmapFactory.Options(); 
this.bounds.inJustDecodeBounds = true; 
BitmapFactory.decodeFile(filePath, bounds); 
if (bounds.outWidth == -1) { // TODO: Error } 
int width = bounds.outWidth; 
int height = bounds.outHeight; 
boolean withinBounds = width <= maxWidth && height <= maxHeight; 
if (!withinBounds) { 
    int newWidth = calculateNewWidth(int width, int height); 
    float sampleSizeF = (float) width/(float) newWidth; 
    int sampleSize = Math.round(sampleSizeF); 
    BitmapFactory.Options resample = new BitmapFactory.Options(); 
    resample.inSampleSize = sampleSize; 
    bitmap = BitmapFactory.decodeFile(filePath, resample); 
} 
+4

क्या आप केवल 2 शक्तियों का उपयोग कर रहे हैं? मैं पूरी तरह से समझ सकता हूं कि ऐसा कुछ क्यों पसंद करेगा, लेकिन मुझे यकीन नहीं है कि मैंने कभी ऐसा एपीआई संदर्भ देखा है - "हम आपको जो कुछ भी मांगते हैं उसे देने का प्रयास करेंगे, लेकिन यह पूरी तरह से कुछ और हो सकता है "। – MusiGenesis

+0

आकार को नियंत्रित करने के लिए आप भी अपने बिटमैप के आउटविड्थ और आउटहाइट गुणों को सेट करना चाहते हैं। – MusiGenesis

+0

मैं 2 शक्तियों का उपयोग नहीं कर रहा हूं। दो की शक्तियां बहुत सीमित हैं और परिणामस्वरूप बिटमैप या तो बहुत छोटे या बहुत बड़े हैं। शायद मुझे एक और एपीआई का उपयोग करना चाहिए? – hpique

उत्तर

44

आप सही रास्ते पर हैं, हालांकि आप एक बार में दो चीजें करने की कोशिश कर रहे हैं: फ़ाइल को पढ़ें और इसे उचित आकार में स्केल करें।

पहला कदम बिटमैप को फ़ाइल को पढ़ने के लिए बिटमैप को पढ़ने के लिए थोड़ा बड़ा है, BitmapFactory.Options.inSampleSize का उपयोग करके यह सुनिश्चित करने के लिए कि आप एक बड़ी बिटमैप पढ़ने की अत्यधिक मेमोरी का उपभोग नहीं करते हैं, जब आप चाहते हैं कि एक छोटा थंबनेल या स्क्रीन हो संकल्प छवि।

दूसरा चरण Bitmap.createScaledBitmap() को सटीक रिज़ॉल्यूशन के लिए एक नया बिटमैप बनाने के लिए कॉल करना है।

सुनिश्चित करें कि आप अस्थायी बिटमैप के बाद इसकी मेमोरी पुनः प्राप्त करने के बाद साफ़ करें। (या तो चर को दायरे से बाहर जाने दें और जीसी को इसके साथ सौदा करने दें, या उस पर .recycle() को कॉल करें यदि आप बहुत सारी छवियां लोड कर रहे हैं और मेमोरी पर तंग चल रहे हैं।)

+3

Carefull के लिए अनुकूलित करने के लिए अतिरिक्त स्थान का उपयोग करने के, u'll पहले चौड़ाई अनुपात करने के लिए ऊंचाई को खोजने की जरूरत है, नहीं तो उसके एवज में छवि फैला दिया जाएगा। – usman

15

आप inJustDecodeBounds उपयोग कर सकते हैं। इसे TRUE पर सेट करें और फ़ाइल को लोड करें।

छवि को स्मृति में लोड नहीं किया जाएगा। लेकिन आउटहाइट और आउटविड्थगुणों बिटमैपफ़ैक्टरी.ऑप्शन में निर्दिष्ट छवि के वास्तविक आकार पैराम होंगे। गणना करें कि आप इसे कितना सब्सक्राइब करना चाहते हैं। यानी 1/2 या 1/4 या 1/8 इत्यादि और के अनुसार नमूना आकार के अनुसार 2/4/8 आदि असाइन करें।

अब FALSE को inJustDecodeBounds सेट और BitmapFactory.decodeFile() फोन के रूप में ऊपर गणना की सटीक आकार की छवि को लोड करने।

+0

यही वह है जो मैं पहले से कर रहा हूं। समस्या को SampleSize के लिए सही मान नहीं मिल रहा है। समस्या यह है कि नमूना आकार को हमेशा मंच द्वारा सम्मानित नहीं किया जाता है, इसलिए मुझे वैसे भी एक छोटा या बड़ा बिटमैप प्राप्त हो सकता है। – hpique

+0

inSampleSize को यू को उप-नमूना छवि वापस करनी चाहिए। यानी सटीक आयाम मूल छवि यू पर निर्भर होंगे। यह मूल छवि के सापेक्ष आधा/चौथाई/एक-आठवां आदि होगा। यू छवि-सबसमूह लोड कर सकता है जो आपकी आवश्यकताओं के सबसे नज़दीक है और इसे प्रदर्शित करते समय उचित रूप से फैलाएं। छवि प्रदर्शित करने के बगल में यू क्या कर रहे हैं ?? शायद मैं वहां मदद कर सकता था। हमम ?? ... – TheCodeArtist

+0

यह वही है जो मैं अभी कर रहा हूं, और क्योंकि नमूना आकार हमेशा सम्मानित नहीं होता है, परिणाम हमेशा अनुकूल नहीं होते हैं। यदि संभव हो तो मैं एक विकल्प की तलाश में हूं। – hpique

1

के बाद से पहले से ही एपीआई कहा गया है कि नमूने का आकार या सम्मानित नहीं किया जा सकता। तो BitmapFactory का उपयोग करते समय मुझे भाग्य से बाहर लगता है।

लेकिन जिस तरह से बाहर अपने खुद के बिटमैप रीडर का उपयोग किया जाएगा। लेकिन मैं सुझाव दूंगा कि आप बिटमैप फैक्ट्री के साथ चिपके रहें क्योंकि यह काफी अच्छी तरह से परीक्षण और मानकीकृत है।

मैं थोड़ा अतिरिक्त मेमोरी खपत के बारे में बहुत ज्यादा चिंता करने की कोशिश नहीं करता, लेकिन कोशिश करता हूं और पता लगाता हूं कि यह मूल्यों का सम्मान क्यों नहीं कर रहा है। दुख की बात है मुझे लगता है कि :(

+0

शायद बिटमैप फैक्टरी का उपयोग करके एक विकल्प है, लेकिन एक अलग तरीके से। क्या टुकड़ों में बिटमैप लोड करना संभव है, उन्हें स्मृति में पुन: सहेजना और फिर उनसे जुड़ना संभव है? यह धीमा, निश्चित होगा, लेकिन यह एक सटीक परिणाम प्रदान करेगा। – hpique

+0

आप अनुकूलित, स्थान या संकल्प को अनुकूलित करना चाहते हैं ?? – the100rabh

+0

संकल्प और ढेर स्मृति मुख्य चिंता कर रहे हैं। वांछित बिटमैप प्राप्त (बिटमैप से अलग, निश्चित रूप से) यथासंभव कम स्मृति लेना चाहिए। – hpique

0

जब से मैं inSampleSize का उपयोग मैं कभी नहीं किसी भी अधिक स्मृति मुद्दों से बाहर का सामना के बारे में विचार नहीं किया है। तो inSampleSize मेरे लिए काफी स्थिर काम करता है। मैं तुम्हें दोगुना मुद्दे की जांच करने की सिफारिश करेंगे। आकार नहीं हो सकता है जैसा आपने अनुरोध किया था उतना ही उतना ही। लेकिन इसे किसी भी तरह से कम किया जाना चाहिए और अब "स्मृति से बाहर" नहीं होना चाहिए। मैं यहां अपना कोड स्निपेट पोस्ट करने की भी सिफारिश करता हूं, शायद इसमें कुछ गड़बड़ है।

0

जैसा कि 100rabh ने कहा, यदि आप बिटमैप फैक्ट्री का उपयोग करते हैं तो आपके पास वास्तव में बहुत पसंद नहीं है। हालांकि, बिटमैप डिकोडिंग वास्तव में सरल है, और स्केलिंग एल्गोरिदम के आधार पर आप इसका उपयोग करना चाहते हैं, मूल रूप से मूल बिटमैप के बड़े हिस्सों को स्मृति में पढ़ने के बिना इसे सामान्य रूप से स्केल करना काफी आसान होता है (सामान्यतः, आप केवल मूल बिटमैप की 1-2 लाइनों के लिए आवश्यक स्मृति को दोगुना करने की आवश्यकता है)।

6

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

// This function taking care of sampling 
backImage =decodeSampledBitmapFromResource(getResources(),R.drawable.back, width, height); 

// This will scale it to your screen width and height. you need to pass screen width and height. 
backImage = Bitmap.createScaledBitmap(backImage, width, height, false); 
1
ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filesPath), THUMBSIZE, THUMBSIZE)) 

आप सीधे आपकी आवश्यकता पर निर्भर करता है THUMBSIZE सेट कर सकते हैं, हालांकि मैं निचले स्तर कार्यान्वयन विवरण, उत्पादन छवि गुणवत्ता और उसके प्रदर्शन के बारे में निश्चित नहीं हूँ, लेकिन मैं आम तौर पर इसे पसंद करते जब मैं झलक दिखाने के लिए की जरूरत है ।

+0

इस के लिए बिटमैप मुक्त कर सकते हैं 'ThumbnailUtils.extractThumbnail (BitmapFactory.decodeFile (filesPath), THUMBSIZE, THUMBSIZE), ThumbnailUtils.OPTIONS_RECYCLE_INPUT)' – Arst

1

उन लोगों के लिए जो संसाधनों से सटीक आकार की छवि ढूंढ रहे हैं।

सटीक चौड़ाई के लिए reqHight = 0 और सटीक ऊंचाई के लिए पारित पारित reqWidth = 0

public static Bitmap decodeBitmapResource(Context context, int resId, int reqWidth, int reqHeight) 
{ 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(context.getResources(), resId, options); 
    float scale = 1; 
    if (reqWidth != 0 && reqHeight == 0) 
    { 
     options.inSampleSize = (int) Math.ceil(options.outWidth/(float) reqWidth); 
     scale = (float) options.outWidth/(float) reqWidth; 
    } 
    else if (reqHeight != 0 && reqWidth == 0) 
    { 
     options.inSampleSize = (int) Math.ceil(options.outHeight/(float) reqHeight); 
     scale = (float) options.outHeight/(float) reqHeight; 
    } 
    else if (reqHeight != 0 && reqWidth != 0) 
    { 
     float x = (float) options.outWidth/(float) reqWidth; 
     float y = (float) options.outHeight/(float) reqHeight; 
     scale = x > y ? x : y; 
    } 
    reqWidth = (int) ((float) options.outWidth/scale); 
    reqHeight = (int) ((float) options.outHeight/scale); 
    options.inJustDecodeBounds = false; 
    Bitmap tmp = BitmapFactory.decodeResource(context.getResources(), resId, options); 
    Bitmap out = Bitmap.createScaledBitmap(tmp, reqWidth, reqHeight, false); 
    tmp.recycle(); 
    tmp = null; 
    return out; 
} 
0

जब inScaled ध्वज (डिफ़ॉल्ट यह सच है) के द्वारा सेट किया गया है, अगर inDensity और inTargetDensity 0 नहीं हैं, बिटमैप होगा ग्राफ़िक्स सिस्टम पर भरोसा करने के बजाए लोड किए जाने पर लक्ष्यितता में मिलान करने के लिए स्केल किया जाए, इसे प्रत्येक बार कैनवास के लिए खींचा जाता है। तो बस गलत करने के लिए inScaled सेट करें।

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inScaled = false; 
0

मैं डीकोडेड छवि फ़ाइल को 70% बिटमैप आकार में सहेजकर "सही आकार" प्राप्त करने में सक्षम था।

Bitmap myBitmap = BitmapFactory.decodeFile(path); 
if(myBitmap != null) 
{ 
    //reduce to 70% size; bitmaps produce larger than actual image size 
    Bitmap rescaledMyBitmap = Bitmap.createScaledBitmap(
                myBitmap, 
                myBitmap.getWidth()/10*7, 
                myBitmap.getHeight()/10*7, 
                false); 

    image.setImageBitmap(rescaledMyBitmap); 
}     

मुझे उम्मीद है कि यह आपको किसी भी तरह से मदद करता है! शांति!

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