দক্ষতার সাথে বড় বিটম্যাপ লোড হচ্ছে
সেভ করা পৃষ্ঠা গুছিয়ে রাখতে 'সংগ্রহ' ব্যবহার করুন
আপনার পছন্দ অনুযায়ী কন্টেন্ট সেভ করুন ও সঠিক বিভাগে রাখুন।
দ্রষ্টব্য: বেশ কয়েকটি লাইব্রেরি রয়েছে যা ছবি লোড করার জন্য সর্বোত্তম অনুশীলন অনুসরণ করে। আপনি সবচেয়ে অপ্টিমাইজড পদ্ধতিতে ছবি লোড করতে আপনার অ্যাপে এই লাইব্রেরিগুলি ব্যবহার করতে পারেন৷ আমরা গ্লাইড লাইব্রেরির সুপারিশ করি, যেটি যত দ্রুত সম্ভব এবং মসৃণভাবে ছবি লোড করে এবং প্রদর্শন করে। অন্যান্য জনপ্রিয় ইমেজ লোডিং লাইব্রেরির মধ্যে রয়েছে স্কয়ার থেকে পিকাসো , ইন্সটাকার্ট থেকে কয়েল এবং ফেসবুক থেকে ফ্রেসকো । এই লাইব্রেরিগুলি অ্যান্ড্রয়েডে বিটম্যাপ এবং অন্যান্য ধরণের চিত্রগুলির সাথে যুক্ত বেশিরভাগ জটিল কাজকে সহজ করে তোলে৷
ছবি সব আকার এবং আকার আসে. অনেক ক্ষেত্রে এগুলি একটি সাধারণ অ্যাপ্লিকেশন ইউজার ইন্টারফেসের (UI) জন্য প্রয়োজনের চেয়ে বড়। উদাহরণস্বরূপ, সিস্টেম গ্যালারি অ্যাপ্লিকেশনটি আপনার অ্যান্ড্রয়েড ডিভাইসের ক্যামেরা ব্যবহার করে তোলা ফটোগুলি প্রদর্শন করে যা সাধারণত আপনার ডিভাইসের স্ক্রিনের ঘনত্বের তুলনায় অনেক বেশি রেজোলিউশন।
প্রদত্ত যে আপনি সীমিত মেমরির সাথে কাজ করছেন, আদর্শভাবে আপনি শুধুমাত্র মেমরিতে একটি নিম্ন রেজোলিউশন সংস্করণ লোড করতে চান। নিম্ন রেজোলিউশন সংস্করণটি UI উপাদানের আকারের সাথে মেলে যা এটি প্রদর্শন করে। উচ্চতর রেজোলিউশনের একটি চিত্র কোনো দৃশ্যমান সুবিধা প্রদান করে না, কিন্তু তবুও মূল্যবান মেমরি গ্রহণ করে এবং ফ্লাই স্কেলিং-এর অতিরিক্ত কারণে অতিরিক্ত কর্মক্ষমতা ওভারহেড বহন করে।
এই পাঠটি আপনাকে মেমরিতে একটি ছোট সাবস্যাম্পল সংস্করণ লোড করার মাধ্যমে প্রতি অ্যাপ্লিকেশন মেমরির সীমা অতিক্রম না করে বড় বিটম্যাপগুলি ডিকোড করার মাধ্যমে নিয়ে যায়।
বিটম্যাপের মাত্রা এবং প্রকার পড়ুন
BitmapFactory
ক্লাস বিভিন্ন উৎস থেকে একটি Bitmap
তৈরি করার জন্য বিভিন্ন ডিকোডিং পদ্ধতি ( decodeByteArray()
, decodeFile()
, decodeResource()
ইত্যাদি প্রদান করে। আপনার ইমেজ ডেটা উৎসের উপর ভিত্তি করে সবচেয়ে উপযুক্ত ডিকোড পদ্ধতি বেছে নিন। এই পদ্ধতিগুলি নির্মিত বিটম্যাপের জন্য মেমরি বরাদ্দ করার চেষ্টা করে এবং তাই সহজেই একটি OutOfMemory
ব্যতিক্রম হতে পারে। প্রতিটি ধরনের ডিকোড পদ্ধতিতে অতিরিক্ত স্বাক্ষর রয়েছে যা আপনাকে BitmapFactory.Options
ক্লাসের মাধ্যমে ডিকোডিং বিকল্পগুলি নির্দিষ্ট করতে দেয়। ডিকোডিং করার সময় inJustDecodeBounds
প্রপার্টিটিকে true
হিসাবে সেট করা মেমরি বরাদ্দ এড়িয়ে যায়, বিটম্যাপ অবজেক্টের জন্য null
রিটার্ন করে কিন্তু outWidth
, outHeight
এবং outMimeType
সেট করে। এই কৌশলটি আপনাকে বিটম্যাপের নির্মাণ (এবং মেমরি বরাদ্দকরণ) পূর্বে চিত্র ডেটার মাত্রা এবং প্রকার পড়তে দেয়।
কোটলিন
val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeResource(resources, R.id.myimage, options)
val imageHeight: Int = options.outHeight
val imageWidth: Int = options.outWidth
val imageType: String = options.outMimeType
জাভা
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
java.lang.OutOfMemory
ব্যতিক্রমগুলি এড়াতে, একটি বিটম্যাপ ডিকোড করার আগে এর মাত্রাগুলি পরীক্ষা করে দেখুন, যদি না আপনি উপলব্ধ মেমরির মধ্যে আরামদায়কভাবে ফিট করে এমন পূর্বাভাসযোগ্য আকারের ইমেজ ডেটা সরবরাহ করার জন্য উত্সটিকে পুরোপুরি বিশ্বাস করেন৷
মেমরিতে একটি স্কেল ডাউন সংস্করণ লোড করুন
এখন যেহেতু ইমেজ ডাইমেনশন জানা আছে, সেগুলি স্থির করতে ব্যবহার করা যেতে পারে যে সম্পূর্ণ ইমেজটি মেমরিতে লোড করা উচিত নাকি এর পরিবর্তে একটি সাবস্যাম্পলড সংস্করণ লোড করা উচিত। এখানে বিবেচনা করার জন্য কিছু কারণ রয়েছে:
- মেমরিতে সম্পূর্ণ ছবি লোড করার জন্য আনুমানিক মেমরি ব্যবহার।
- আপনার অ্যাপ্লিকেশনের অন্য কোনো মেমরি প্রয়োজনীয়তা প্রদত্ত মেমরির পরিমাণ আপনি এই ছবিটি লোড করতে প্রতিশ্রুতিবদ্ধ।
- টার্গেট
ImageView
বা UI কম্পোনেন্টের মাত্রা যেখানে ছবি লোড করা হবে। - বর্তমান ডিভাইসের স্ক্রিনের আকার এবং ঘনত্ব।
উদাহরণস্বরূপ, একটি 1024x768 পিক্সেল ছবি মেমরিতে লোড করা মূল্যবান নয় যদি এটি শেষ পর্যন্ত একটি ImageView
এ 128x96 পিক্সেল থাম্বনেইলে প্রদর্শিত হয়।
ডিকোডারকে ইমেজ সাবস্যাম্পল করতে বলতে, মেমরিতে একটি ছোট সংস্করণ লোড করা হচ্ছে, আপনার BitmapFactory.Options
অবজেক্টে inSampleSize
সেট true
। উদাহরণস্বরূপ, 2048x1536 রেজোলিউশনের একটি চিত্র যা 4 এর একটি inSampleSize
দিয়ে ডিকোড করা হয় তা প্রায় 512x384 এর একটি বিটম্যাপ তৈরি করে। মেমরিতে এটি লোড করা সম্পূর্ণ চিত্রের জন্য 12MB এর পরিবর্তে 0.75MB ব্যবহার করে ( ARGB_8888
এর একটি বিটম্যাপ কনফিগারেশন ধরে নেওয়া)। এখানে একটি নমুনা আকারের মান গণনা করার একটি পদ্ধতি রয়েছে যা একটি লক্ষ্য প্রস্থ এবং উচ্চতার উপর ভিত্তি করে দুটি শক্তি:
কোটলিন
fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
// Raw height and width of image
val (height: Int, width: Int) = options.run { outHeight to outWidth }
var inSampleSize = 1
if (height > reqHeight || width > reqWidth) {
val halfHeight: Int = height / 2
val halfWidth: Int = width / 2
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
inSampleSize *= 2
}
}
return inSampleSize
}
জাভা
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
দ্রষ্টব্য: দুটি মানের একটি পাওয়ার গণনা করা হয় কারণ inSampleSize
ডকুমেন্টেশন অনুসারে ডিকোডার দুটির নিকটতম শক্তিতে রাউন্ডিং করে একটি চূড়ান্ত মান ব্যবহার করে।
এই পদ্ধতিটি ব্যবহার করার জন্য, প্রথমে inJustDecodeBounds
এর সাথে ডিকোড করুন true
সেট করুন, বিকল্পগুলি পাস করুন এবং তারপরে নতুন inSampleSize
মান ব্যবহার করে আবার ডিকোড করুন এবং inJustDecodeBounds
false
সেট করুন:
কোটলিন
fun decodeSampledBitmapFromResource(
res: Resources,
resId: Int,
reqWidth: Int,
reqHeight: Int
): Bitmap {
// First decode with inJustDecodeBounds=true to check dimensions
return BitmapFactory.Options().run {
inJustDecodeBounds = true
BitmapFactory.decodeResource(res, resId, this)
// Calculate inSampleSize
inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight)
// Decode bitmap with inSampleSize set
inJustDecodeBounds = false
BitmapFactory.decodeResource(res, resId, this)
}
}
জাভা
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
এই পদ্ধতিটি একটি ImageView
ইচ্ছামত বড় আকারের একটি বিটম্যাপ লোড করা সহজ করে যা একটি 100x100 পিক্সেল থাম্বনেইল প্রদর্শন করে, যেমনটি নিম্নলিখিত উদাহরণ কোডে দেখানো হয়েছে:
কোটলিন
imageView.setImageBitmap(
decodeSampledBitmapFromResource(resources, R.id.myimage, 100, 100)
)
জাভা
imageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
আপনি প্রয়োজন অনুসারে উপযুক্ত BitmapFactory.decode*
পদ্ধতি প্রতিস্থাপন করে অন্যান্য উত্স থেকে বিটম্যাপ ডিকোড করার জন্য অনুরূপ প্রক্রিয়া অনুসরণ করতে পারেন।
এই পৃষ্ঠার কন্টেন্ট ও কোডের নমুনাগুলি Content License-এ বর্ণিত লাইসেন্সের অধীনস্থ। Java এবং OpenJDK হল Oracle এবং/অথবা তার অ্যাফিলিয়েট সংস্থার রেজিস্টার্ড ট্রেডমার্ক।
2025-07-29 UTC-তে শেষবার আপডেট করা হয়েছে।
[[["সহজে বোঝা যায়","easyToUnderstand","thumb-up"],["আমার সমস্যার সমাধান হয়েছে","solvedMyProblem","thumb-up"],["অন্যান্য","otherUp","thumb-up"]],[["এতে আমার প্রয়োজনীয় তথ্য নেই","missingTheInformationINeed","thumb-down"],["খুব জটিল / অনেক ধাপ","tooComplicatedTooManySteps","thumb-down"],["পুরনো","outOfDate","thumb-down"],["অনুবাদ সংক্রান্ত সমস্যা","translationIssue","thumb-down"],["নমুনা / কোড সংক্রান্ত সমস্যা","samplesCodeIssue","thumb-down"],["অন্যান্য","otherDown","thumb-down"]],["2025-07-29 UTC-তে শেষবার আপডেট করা হয়েছে।"],[],[],null,["# Loading Large Bitmaps Efficiently\n\n**Note:** There are several libraries that follow\nbest practices for loading images. You can use these libraries in your app to\nload images in the most optimized manner. We recommend the\n[Glide](https://github.com/bumptech/glide)\nlibrary, which loads and displays images as quickly and smoothly as possible.\nOther popular image loading libraries include [Picasso](http://square.github.io/picasso/) from Square, [Coil](https://github.com/coil-kt/coil) from Instacart, and\n[Fresco](https://github.com/facebook/fresco)\nfrom Facebook. These libraries simplify most of the complex tasks associated\nwith bitmaps and other types of images on Android.\n\nImages come in all shapes and sizes. In many cases they are larger than required for a typical\napplication user interface (UI). For example, the system Gallery application displays photos taken\nusing your Android devices's camera which are typically much higher resolution than the screen\ndensity of your device.\n\nGiven that you are working with limited memory, ideally you only want to load a lower resolution\nversion in memory. The lower resolution version should match the size of the UI component that\ndisplays it. An image with a higher resolution does not provide any visible benefit, but still takes\nup precious memory and incurs additional performance overhead due to additional on the fly\nscaling.\n\nThis lesson walks you through decoding large bitmaps without exceeding the per application\nmemory limit by loading a smaller subsampled version in memory.\n\nRead Bitmap Dimensions and Type\n-------------------------------\n\nThe [BitmapFactory](/reference/android/graphics/BitmapFactory) class provides several decoding methods ([decodeByteArray()](/reference/android/graphics/BitmapFactory#decodeByteArray(byte[], int, int, android.graphics.BitmapFactory.Options)), [decodeFile()](/reference/android/graphics/BitmapFactory#decodeFile(java.lang.String, android.graphics.BitmapFactory.Options)), [decodeResource()](/reference/android/graphics/BitmapFactory#decodeResource(android.content.res.Resources, int, android.graphics.BitmapFactory.Options)), etc.) for creating a [Bitmap](/reference/android/graphics/Bitmap) from various sources. Choose\nthe most appropriate decode method based on your image data source. These methods attempt to\nallocate memory for the constructed bitmap and therefore can easily result in an `OutOfMemory`\nexception. Each type of decode method has additional signatures that let you specify decoding\noptions via the [BitmapFactory.Options](/reference/android/graphics/BitmapFactory.Options) class. Setting the [inJustDecodeBounds](/reference/android/graphics/BitmapFactory.Options#inJustDecodeBounds) property to `true` while decoding\navoids memory allocation, returning `null` for the bitmap object but setting [outWidth](/reference/android/graphics/BitmapFactory.Options#outWidth), [outHeight](/reference/android/graphics/BitmapFactory.Options#outHeight) and [outMimeType](/reference/android/graphics/BitmapFactory.Options#outMimeType). This technique allows you to read the\ndimensions and type of the image data prior to construction (and memory allocation) of the\nbitmap. \n\n### Kotlin\n\n```kotlin\nval options = BitmapFactory.Options().apply {\n inJustDecodeBounds = true\n}\nBitmapFactory.decodeResource(resources, R.id.myimage, options)\nval imageHeight: Int = options.outHeight\nval imageWidth: Int = options.outWidth\nval imageType: String = options.outMimeType\n```\n\n### Java\n\n```java\nBitmapFactory.Options options = new BitmapFactory.Options();\noptions.inJustDecodeBounds = true;\nBitmapFactory.decodeResource(getResources(), R.id.myimage, options);\nint imageHeight = options.outHeight;\nint imageWidth = options.outWidth;\nString imageType = options.outMimeType;\n```\n\nTo avoid `java.lang.OutOfMemory` exceptions, check the dimensions of a bitmap before\ndecoding it, unless you absolutely trust the source to provide you with predictably sized image data\nthat comfortably fits within the available memory.\n\nLoad a Scaled Down Version into Memory\n--------------------------------------\n\nNow that the image dimensions are known, they can be used to decide if the full image should be\nloaded into memory or if a subsampled version should be loaded instead. Here are some factors to\nconsider:\n\n- Estimated memory usage of loading the full image in memory.\n- Amount of memory you are willing to commit to loading this image given any other memory requirements of your application.\n- Dimensions of the target [ImageView](/reference/android/widget/ImageView) or UI component that the image is to be loaded into.\n- Screen size and density of the current device.\n\nFor example, it's not worth loading a 1024x768 pixel image into memory if it will eventually be\ndisplayed in a 128x96 pixel thumbnail in an [ImageView](/reference/android/widget/ImageView).\n\nTo tell the decoder to subsample the image, loading a smaller version into memory, set [inSampleSize](/reference/android/graphics/BitmapFactory.Options#inSampleSize) to `true` in your [BitmapFactory.Options](/reference/android/graphics/BitmapFactory.Options) object. For example, an image with resolution 2048x1536 that\nis decoded with an [inSampleSize](/reference/android/graphics/BitmapFactory.Options#inSampleSize) of 4 produces a\nbitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full\nimage (assuming a bitmap configuration of [ARGB_8888](/reference/android/graphics/Bitmap.Config)). Here's\na method to calculate a sample size value that is a power of two based on a target width and\nheight: \n\n### Kotlin\n\n```kotlin\nfun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {\n // Raw height and width of image\n val (height: Int, width: Int) = options.run { outHeight to outWidth }\n var inSampleSize = 1\n\n if (height \u003e reqHeight || width \u003e reqWidth) {\n\n val halfHeight: Int = height / 2\n val halfWidth: Int = width / 2\n\n // Calculate the largest inSampleSize value that is a power of 2 and keeps both\n // height and width larger than the requested height and width.\n while (halfHeight / inSampleSize \u003e= reqHeight && halfWidth / inSampleSize \u003e= reqWidth) {\n inSampleSize *= 2\n }\n }\n\n return inSampleSize\n}\n```\n\n### Java\n\n```java\npublic static int calculateInSampleSize(\n BitmapFactory.Options options, int reqWidth, int reqHeight) {\n // Raw height and width of image\n final int height = options.outHeight;\n final int width = options.outWidth;\n int inSampleSize = 1;\n\n if (height \u003e reqHeight || width \u003e reqWidth) {\n\n final int halfHeight = height / 2;\n final int halfWidth = width / 2;\n\n // Calculate the largest inSampleSize value that is a power of 2 and keeps both\n // height and width larger than the requested height and width.\n while ((halfHeight / inSampleSize) \u003e= reqHeight\n && (halfWidth / inSampleSize) \u003e= reqWidth) {\n inSampleSize *= 2;\n }\n }\n\n return inSampleSize;\n}\n```\n\n**Note:** A power of two value is calculated because the decoder uses\na final value by rounding down to the nearest power of two, as per the [inSampleSize](/reference/android/graphics/BitmapFactory.Options#inSampleSize) documentation.\n\nTo use this method, first decode with [inJustDecodeBounds](/reference/android/graphics/BitmapFactory.Options#inJustDecodeBounds) set to `true`, pass the options\nthrough and then decode again using the new [inSampleSize](/reference/android/graphics/BitmapFactory.Options#inSampleSize) value and [inJustDecodeBounds](/reference/android/graphics/BitmapFactory.Options#inJustDecodeBounds) set to `false`: \n\n### Kotlin\n\n```kotlin\nfun decodeSampledBitmapFromResource(\n res: Resources,\n resId: Int,\n reqWidth: Int,\n reqHeight: Int\n): Bitmap {\n // First decode with inJustDecodeBounds=true to check dimensions\n return BitmapFactory.Options().run {\n inJustDecodeBounds = true\n BitmapFactory.decodeResource(res, resId, this)\n\n // Calculate inSampleSize\n inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight)\n\n // Decode bitmap with inSampleSize set\n inJustDecodeBounds = false\n\n BitmapFactory.decodeResource(res, resId, this)\n }\n}\n```\n\n### Java\n\n```java\npublic static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,\n int reqWidth, int reqHeight) {\n\n // First decode with inJustDecodeBounds=true to check dimensions\n final BitmapFactory.Options options = new BitmapFactory.Options();\n options.inJustDecodeBounds = true;\n BitmapFactory.decodeResource(res, resId, options);\n\n // Calculate inSampleSize\n options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);\n\n // Decode bitmap with inSampleSize set\n options.inJustDecodeBounds = false;\n return BitmapFactory.decodeResource(res, resId, options);\n}\n```\n\nThis method makes it easy to load a bitmap of arbitrarily large size into an [ImageView](/reference/android/widget/ImageView) that displays a 100x100 pixel thumbnail, as shown in the following example\ncode: \n\n### Kotlin\n\n```kotlin\nimageView.setImageBitmap(\n decodeSampledBitmapFromResource(resources, R.id.myimage, 100, 100)\n)\n```\n\n### Java\n\n```java\nimageView.setImageBitmap(\n decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));\n```\n\nYou can follow a similar process to decode bitmaps from other sources, by substituting the\nappropriate [BitmapFactory.decode*](/reference/android/graphics/BitmapFactory#decodeByteArray(byte[], int, int, android.graphics.BitmapFactory.Options)) method as needed."]]