অ্যান্ড্রয়েডে বিটম্যাপগুলি পুনরায় আকার দেওয়ার বেশিরভাগ মেমরির দক্ষ উপায়?


115

আমি একটি চিত্র-নিবিড় সামাজিক অ্যাপ্লিকেশন তৈরি করছি যেখানে সার্ভার থেকে ডিভাইসে চিত্রগুলি প্রেরণ করা হয়। ডিভাইসে যখন ছোট স্ক্রিন রেজোলিউশন রয়েছে, তখন ডিটেক্ট ডিসপ্লে মাপের সাথে মেলে আমার ডিভাইসে বিটম্যাপগুলি আকার দিতে হবে।

সমস্যাটি হ'ল ক্রিয়েটস্কেলবিটম্যাপ ব্যবহার করা ফলে থাম্বনেইল চিত্রগুলির একটি বাহিনীকে পুনরায় আকার দেওয়ার পরে আমার প্রচুর স্মৃতি যায় errors

অ্যান্ড্রয়েডে বিটম্যাপগুলি পুনরায় আকার দেওয়ার সবচেয়ে মেমরি দক্ষ উপায় কী?


7
আপনার সার্ভারটি কি সঠিক আকারটি প্রেরণ করতে পারে না যাতে আপনি আপনার গ্রাহকের র‌্যাম এবং ব্যান্ডউইথ সংরক্ষণ করেন !?
জেমস

2
এটি কেবলমাত্র বৈধ যদি আমার সার্ভার সংস্থানটির মালিকানা থাকে, এটির সাথে এটির একটি গণনা উপাদান উপস্থিত ছিল এবং সমস্ত ক্ষেত্রে এটি চিত্রটি অনুপাতের সঠিক মাত্রাগুলি পূর্বাভাস দিতে পারে যা এটি এখনও দেখা যায় নি। সুতরাং আপনি যদি কোনও তৃতীয় পক্ষের সিডিএন (যেমন আমি আছি) থেকে রিসোর্স সামগ্রী লোড করে থাকেন তবে এটি কাজ করে না :(
কল্ট ম্যাকআনলিস

উত্তর:


168

এই উত্তরটি সংক্ষিপ্ত আকারে বড় বিটম্যাপগুলি দক্ষতার সাথে লোড করা হচ্ছে যা ডাউন-স্কেল বিটম্যাপ সংস্করণটি লোড করতে কীভাবে ইনস্যাম্পল সাইজ ব্যবহার করবেন তা ব্যাখ্যা করে।

বিশেষত প্রাক-স্কেলিং বিটম্যাপগুলি বিভিন্ন পদ্ধতির বিশদ ব্যাখ্যা করে, কীভাবে তাদের একত্রিত করা যায় এবং কোনটি সবচেয়ে স্মৃতিশক্তি দক্ষ।

অ্যান্ড্রয়েডে বিটম্যাপের আকার পরিবর্তন করার জন্য তিনটি প্রভাবশালী উপায় রয়েছে যার মেমরির বিভিন্ন বৈশিষ্ট্য রয়েছে:

createScaledBitmap API

এই এপিআইটি একটি বিদ্যমান বিটম্যাপ নেবে এবং আপনি যে সঠিক মাত্রাটি নির্বাচন করেছেন তার সাথে একটি নতুন বিটম্যাপ তৈরি করবে।

প্লাস পাশে আপনি যে চিত্রটির সন্ধান করছেন তা হুবহু দেখতে পাবেন (এটি দেখতে কেমন লাগে)। তবে নেতিবাচক দিকটি হ'ল এই API এ কাজ করার জন্য একটি বিদ্যমান বিটম্যাপ দরকার । অর্থ একটি নতুন, ছোট সংস্করণ তৈরি করতে সক্ষম হবার আগে চিত্রটি লোড, ডিকোডিং এবং একটি বিটম্যাপ তৈরি করতে হবে। এটি আপনার সঠিক মাত্রা পাওয়ার ক্ষেত্রে আদর্শ তবে অতিরিক্ত মেমরির ওভারহেডের ক্ষেত্রে ভয়াবহ। এর মতো, বেশিরভাগ অ্যাপ বিকাশকারী যারা মেমরি সচেতন হওয়ার প্রবণতা পোষণ করে এটি একটি ধরণের চুক্তি

inSampleSize পতাকা flag

BitmapFactory.OptionsinSampleSizeঅস্থায়ী বিটম্যাপে ডিকোড করার প্রয়োজন এড়াতে আপনার সম্পত্তিটিকে ডিকোড করার সময় পুনরায় আকার দেবে বলে চিহ্নিত একটি সম্পত্তি রয়েছে । এখানে ব্যবহৃত এই পূর্ণসংখ্যা মানটি 1 / x হ্রাস আকারে একটি চিত্র লোড করবে। উদাহরণস্বরূপ, inSampleSize2 এ সেট করা অর্ধেক মাপের একটি চিত্র দেয় এবং 4 এ সেট করে এমন এক চিত্র দেয় যা 1/4 ম আকারের আকার দেয়। মূলত চিত্রের মাপগুলি সর্বদা আপনার উত্সের আকারের চেয়ে দুটো শক্তির ছোট হবে।

স্মৃতি দৃষ্টিকোণ থেকে, ব্যবহার inSampleSizeকরা সত্যিই দ্রুত অপারেশন is কার্যকরভাবে, এটি কেবল আপনার ফলাফলের বিটম্যাপে আপনার চিত্রের প্রতি দশম পিক্সেল ডিকোড করবে। inSampleSizeযদিও দুটি প্রধান সমস্যা আছে :

  • এটি আপনাকে সঠিক রেজোলিউশন দেয় না । এটি কেবলমাত্র 2 এর পাওয়ার দ্বারা আপনার বিটম্যাপের আকার হ্রাস করে।

  • এটি সেরা মানের আকার পরিবর্তন করে না । সর্বাধিক আকার পরিবর্তনকারী ফিল্টারগুলি পিক্সেলগুলির ব্লকগুলি পড়ার পরে এবং পুনরায় আকারযুক্ত পিক্সেলটিকে প্রশ্নের আকারে ওজন করে ভারসাম্যযুক্ত চিত্র তৈরি করে। inSampleSizeকেবলমাত্র কয়েকটি পিক্সেল পড়ে এগুলি এড়ানো হয়। ফলাফলটি বেশ পারফরম্যান্সযুক্ত এবং স্বল্প স্মৃতিযুক্ত তবে মানটি ভোগে।

আপনি যদি কেবল নিজের ইমেজটিকে কিছু পাউ 2 আকার দ্বারা সঙ্কুচিত করার বিষয়ে আলোচনা করছেন এবং ফিল্টারিং কোনও সমস্যা নয় তবে আপনি এর চেয়ে বেশি মেমরি দক্ষ (বা পারফরম্যান্স দক্ষ) পদ্ধতি খুঁজে পাবেন না inSampleSize

ইনস্কেলড, ইনডেনসিটি, ইন টার্গেটডেনসিটি পতাকা

আপনি যদি একটি মাত্রা দুই একটি ক্ষমতা সমান নয় এর একটি চিত্র আকার পরিবর্তন করার প্রয়োজন হলে, তারপর আপনি প্রয়োজন হবে inScaled, inDensityএবং inTargetDensityপতাকা BitmapOptions। যখন inScaledপতাকা নির্ধারণ করা হয়েছে, সিস্টেম স্কেলিং মান আহরণ করবে বিভাজক দ্বারা আপনার বিটম্যাপ প্রয়োগ করতে inTargetDensityদ্বারা inDensityমান।

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

আপনি প্রথমে আকারটি ডিকোড করতে এই পতাকাটি ব্যবহার করতে পারেন এবং তারপরে আপনার টার্গেট রেজোলিউশনে স্কেলিংয়ের জন্য যথাযথ মানগুলি গণনা করতে পারেন।


1
এটি দুর্দান্ত ছিল যদি আপনি আমাদের বলতে পারেন ডিএসটিউইথ কী?
k0sh

@ k0sh dstWIdth হ'ল ইমেজভিউর প্রস্থ যেখানে তার destination widthসংক্ষিপ্তসার বা ডিএসটিউইথের সংক্ষিপ্তসার হতে
চলেছে

@tyczj উত্তরের জন্য ধন্যবাদ, আমি জানি এটি কী, তবে কিছু লোক হয়তো এটি জানেন না এবং যেহেতু কোল্ট যিনি আসলে এই প্রশ্নের উত্তর দিয়েছেন, সম্ভবত তিনি এটি ব্যাখ্যা করতে পেরেছিলেন যাতে লোকেরা বিভ্রান্ত না হয়।
k0sh

ভাল পোস্ট ... ইনসেস্কেলড, ইনডেনসিটি, ইন টার্গেটডেনসিটির ফ্ল্যাগগুলি সম্পর্কে আগে জানতেন না ...
ম্যাভেরয়েড

আমি অ্যান্ড্রয়েড পারফরম্যান্সের প্যাটার্ন সিরিজটি দেখছি এবং আমি অনেক কিছু শিখেছি!
আনিস

13

এই উত্তরটি হিসাবে দুর্দান্ত (এবং নির্ভুল), এটিও খুব জটিল। চাকাটি পুনরায় উদ্ভাবন করার পরিবর্তে গ্লাইড , পিকাসো , ইউআইএল , আয়ন বা অন্য যে কোনও সংখ্যক গ্রন্থাগার বিবেচনা করুন যা আপনার জন্য এই জটিল এবং ত্রুটি প্রবণ যুক্তিকে বাস্তবায়ন করে।

কোল্ট নিজে এমনকি প্রাক-স্কেলিং বিটম্যাপ পারফরম্যান্স প্যাটার্নস ভিডিওতে গ্লাইড এবং পিকাসো একবার দেখার পরামর্শ দিয়েছিলেন ।

লাইব্রেরি ব্যবহার করে, আপনি কোল্টের উত্তরে উল্লিখিত প্রতিটি দক্ষতা পেতে পারেন, তবে অ্যান্ড্রয়েডের প্রতিটি সংস্করণ জুড়ে ধারাবাহিকভাবে কাজ করা বিশাল সরল এপিআই সহ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.