इस उत्तर Loading large bitmaps Efficiently जो बताते हैं एक नीचे बढ़ाया बिटमैप संस्करण लोड करने के लिए inSampleSize उपयोग करने के लिए कैसे से संक्षेप है।
विशेष रूप से Pre-scaling bitmaps विभिन्न तरीकों, उन्हें कैसे गठबंधन करने के लिए के विवरण बताते हैं, और जो सबसे अधिक स्मृति कुशल हैं।
वहाँ जो विभिन्न स्मृति गुण होते हैं Android पर एक बिटमैप आकार बदलने के लिए तीन प्रमुख तरीके हैं:
createScaledBitmap API
यह API एक मौजूदा बिटमैप में ले जाएगा, और के साथ एक नया बिटमैप बनाने आपके द्वारा चुने गए सटीक आयाम।
प्लस तरफ, आप वास्तव में उस छवि आकार को प्राप्त कर सकते हैं जिसे आप ढूंढ रहे हैं (चाहे यह कैसा दिखता है)। लेकिन नकारात्मक, यह है कि इस API को काम करने के लिए मौजूदा बिटमैप की आवश्यकता है। एक नया, छोटा संस्करण बनाने में सक्षम होने से पहले, छवि को लोड, डीकोडेड और बिटमैप बनाया जाना होगा। यह आपके सटीक आयाम प्राप्त करने के मामले में आदर्श है, लेकिन अतिरिक्त मेमोरी ओवरहेड के मामले में भयानक है। जैसे, इस जिन्होंने स्मृति के प्रति जागरूक होने के लिए
inSampleSize flag
BitmapFactory.Options
एक संपत्ति inSampleSize
कि आपकी छवि का आकार होगा, जबकि इसे डीकोड के रूप में उल्लेख किया गया है, से बचने के लिए करते हैं सबसे एप्लिकेशन डेवलपर के लिए एक सौदा ब्रेकर तरह-की है अस्थायी बिटमैप को डीकोड करने की आवश्यकता। यहां उपयोग किया गया यह पूर्णांक मान एक छवि को 1/x कम आकार पर लोड करेगा। उदाहरण के लिए, inSampleSize
से 2 को सेट करने वाली छवि उस आधे आकार को लौटाती है, और इसे 4 पर सेट करने से उस छवि को 1/4 वां आकार मिलता है। असल में छवि आकार हमेशा आपके स्रोत आकार की तुलना में कुछ पावर-ऑफ-छोटे होंगे।
मेमोरी परिप्रेक्ष्य से, inSampleSize
का उपयोग करना वास्तव में तेज़ ऑपरेशन है। प्रभावी रूप से, यह आपके परिणामस्वरूप बिटमैप में आपकी छवि के प्रत्येक Xth पिक्सेल को केवल डीकोड करेगा।
यह आप सटीक संकल्प नहीं देता: वहाँ inSampleSize
हालांकि साथ दो मुख्य मुद्दों है। यह केवल 2 बिट की कुछ शक्ति द्वारा आपके बिटमैप के आकार को कम करता है।
यह सर्वोत्तम गुणवत्ता का आकार का उत्पादन नहीं करता है। अधिकांश आकार देने वाले फ़िल्टर पिक्सेल के ब्लॉक को पढ़कर अच्छी दिखने वाली छवियां उत्पन्न करते हैं, और फिर प्रश्न में आकार वाले पिक्सेल का उत्पादन करने के लिए उन्हें वज़न देते हैं।inSampleSize
बस हर कुछ पिक्सल को पढ़ कर यह सब बचा जाता है। परिणाम काफी performant है, और कम स्मृति है, लेकिन गुणवत्ता ग्रस्त है।
आप केवल कुछ pow2 आकार से अपनी छवि को सिकुड़ने के साथ काम कर रहे हैं, और छानने कोई मुद्दा नहीं है, तो आप inSampleSize
तुलना में एक अधिक स्मृति कुशल (या प्रदर्शन कुशल) विधि नहीं मिल रहा।
inScaled, inDensity, inTargetDensity flags
आप एक आयाम है कि दोनों में से एक शक्ति के बराबर नहीं है के लिए एक छवि पैमाने पर करने की जरूरत है, तो आप BitmapOptions
की inScaled
, inDensity
और inTargetDensity
झंडे की आवश्यकता होगी। जब inScaled
ध्वज स्थापित किया गया है, प्रणाली inDensity
मूल्यों से inTargetDensity
विभाजित करके अपने बिटमैप को लागू करने के लिए स्केलिंग मूल्य व्युत्पन्न होगा।
mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeResources(getResources(),
mImageIDs, mBitmapOptions);
इस विधि का उपयोग अपनी छवि को आकार फिर से होगा, और यह भी आकार बदलने चरण के दौरान यह करने के लिए एक 'आकार बदलने फिल्टर' लागू होते हैं, जो है, अंतिम परिणाम बेहतर दिखेगा क्योंकि कुछ अतिरिक्त गणित को ध्यान में रखा जा चुका है । लेकिन चेतावनी दी: कि अतिरिक्त फिल्टर कदम, अतिरिक्त संसाधन समय लेता है, और जल्दी से, बड़ी छवियों के लिए जोड़ सकते हैं धीमी गति से आकार बदलता है, जिसके परिणामस्वरूप और फिल्टर खुद के लिए अतिरिक्त स्मृति आवंटन।
अतिरिक्त फ़िल्टरिंग ओवरहेड के कारण, इस तकनीक को उस छवि पर लागू करने का एक अच्छा विचार नहीं है जो आपके वांछित आकार से काफी बड़ा है।
जादू संयोजन
एक स्मृति और प्रदर्शन के दृष्टिकोण से, आप सबसे अच्छा परिणाम के लिए इन विकल्पों को जोड़ सकते हैं। (inSampleSize
, inScaled
, inDensity
और inTargetDensity
झंडे की स्थापना)
inSampleSize
पहले, छवि को लागू किया जाएगा यह करने के लिए हो रही है अगले अपने लक्ष्य आकार की तुलना में बिजली के- दो बड़े। फिर, inDensity
& inTargetDensity
परिणाम पैमाने पर करने के आयाम है कि आप चाहते हैं सटीक, छवि को साफ करने के लिए एक फिल्टर आपरेशन लागू करने के लिए उपयोग किया जाता।
इन दोनों को जोड़ना एक तेज़ ऑपरेशन है, क्योंकि inSampleSize
चरण पिक्सल की संख्या को कम करेगा जिससे परिणामी घनत्व-आधारित चरण को इसके आकार बदलने वाले फ़िल्टर को लागू करने की आवश्यकता होगी।
mBitmapOptions.inScaled = true;
mBitmapOptions.inSampleSize = 4;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth * mBitmapOptions.inSampleSize;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeFile(fileName, mBitmapOptions);
आप विशिष्ट आयाम, और कुछ अच्छे छानने के लिए एक छवि फिट करने के लिए की आवश्यकता होगी, रहे हैं, तो इस तकनीक का सही आकार प्राप्त करने के लिए सबसे अच्छा पुल है, लेकिन एक तेजी से, कम स्मृति पदचिह्न में किया ऑपरेशन।
हो रही छवि आयाम
संपूर्ण चित्र डिकोडिंग के लिए अपने बिटमैप का आकार बदलने के लिए बिना छवि का आकार हो रही है, आप आने वाले आयामों की जानकारी होनी चाहिए। आप चित्र के आयाम मिलता है, डब्ल्यू/मदद करने के लिए वास्तव में पिक्सेल डेटा को डिकोड करने की आवश्यकता होगी, ओ inJustDecodeBounds
ध्वज का उपयोग कर सकते हैं।
// Decode just the boundaries
mBitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fileName, mBitmapOptions);
srcWidth = mBitmapOptions.outWidth;
srcHeight = mBitmapOptions.outHeight;
//now go resize the image to the size you want
आप इस फ़्लैग का उपयोग पहले आकार को डिकोड करने के कर सकते हैं और तब अपने लक्षित समाधान करने के लिए स्केलिंग के लिए उचित मूल्यों की गणना।
अपने सर्वर तो आप अपने ग्राहक के रैम और बैंडविड्थ को बचा नहीं सही आकार भेज सकते हैं !? – James
कि वैध अगर मैं सर्वर संसाधन स्वामित्व है, यह एक गणना घटक इसके साथ उपलब्ध था, और सभी मामलों में, यह अभी तक इसे नहीं देखा था पहलू अनुपात के लिए छवियों की सटीक आयामों का अनुमान लगा सकते। इसलिए यदि आप किसी तृतीय पक्ष सीडीएन से संसाधन सामग्री लोड कर रहे हैं (जैसे मैं हूं) यह काम नहीं करता है :( –