মিডিয়া থাম্বনেল তৈরি করুন

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

ফাইলের ধরন এবং আপনার অ্যাপ্লিকেশন এবং আপনার মিডিয়া সম্পদের ফাইল অ্যাক্সেসের উপর নির্ভর করে, আপনি বিভিন্ন উপায়ে থাম্বনেইল তৈরি করতে পারেন।

একটি ইমেজ লোডিং লাইব্রেরি ব্যবহার করে একটি থাম্বনেইল তৈরি করুন

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

// Use Coil to create and display a thumbnail of a video or image with a specific height
// ImageLoader has its own memory and storage cache, and this one is configured to also
// load frames from videos
val videoEnabledLoader = ImageLoader.Builder(context)
    .components {
        add(VideoFrameDecoder.Factory())
    }.build()
// Coil requests images that match the size of the AsyncImage composable, but this allows
// for precise control of the height
val request = ImageRequest.Builder(context)
    .data(mediaUri)
    .size(Int.MAX_VALUE, THUMBNAIL_HEIGHT)
    .build()
AsyncImage(
    model = request,
    imageLoader = videoEnabledLoader,
    modifier = Modifier
        .clip(RoundedCornerShape(20))    ,
    contentDescription = null
)

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

স্থানীয় ইমেজ ফাইল থেকে একটি থাম্বনেইল তৈরি করুন

থাম্বনেইল ইমেজ পাওয়ার ক্ষেত্রে ভিজ্যুয়াল কোয়ালিটি সংরক্ষণ, অত্যধিক মেমরি ব্যবহার এড়ানো, বিভিন্ন ইমেজ ফরম্যাটের সাথে ডিল করা এবং Exif ডেটার সঠিক ব্যবহার করার সময় দক্ষ ডাউনস্কেলিং জড়িত।

createImageThumbnail পদ্ধতি এই সব করে, আপনাকে ইমেজ ফাইলের পাথে অ্যাক্সেস প্রদান করে।

val bitmap = ThumbnailUtils.createImageThumbnail(File(file_path), Size(640, 480), null)

আপনার কাছে শুধুমাত্র Uri থাকলে, আপনি Android 10, API স্তর 29 থেকে শুরু করে ContentResolver-loadThumbnail পদ্ধতি ব্যবহার করতে পারেন।

val thumbnail: Bitmap =
        applicationContext.contentResolver.loadThumbnail(
        content-uri, Size(640, 480), null)

ইমেজডিকোডার , Android 9, API স্তর 28 থেকে শুরু করে উপলব্ধ, অতিরিক্ত মেমরির ব্যবহার রোধ করতে আপনি এটিকে ডিকোড করার সাথে সাথে চিত্রটিকে পুনরায় নমুনা করার জন্য কিছু শক্ত বিকল্প রয়েছে।

class DecodeResampler(val size: Size, val signal: CancellationSignal?) : OnHeaderDecodedListener {
    private val size: Size

   override fun onHeaderDecoded(decoder: ImageDecoder, info: ImageInfo, source:
       // sample down if needed.
        val widthSample = info.size.width / size.width
        val heightSample = info.size.height / size.height
        val sample = min(widthSample, heightSample)
        if (sample > 1) {
            decoder.setTargetSampleSize(sample)
        }
    }
}

val resampler = DecoderResampler(size, null)
val source = ImageDecoder.createSource(context.contentResolver, imageUri)
val bitmap = ImageDecoder.decodeBitmap(source, resampler);

আপনি বিটম্যাপফ্যাক্টরি ব্যবহার করতে পারেন অ্যাপ্লিকেশানগুলির জন্য থাম্বনেইল তৈরি করতে যা পূর্বের Android প্রকাশগুলিকে লক্ষ্য করে। বিটম্যাপফ্যাক্টরি. অপশনের রিস্যাম্পলিং এর উদ্দেশ্যে একটি ইমেজের সীমানা ডিকোড করার একটি সেটিং আছে।

প্রথমে, BitmapFactory.Options এ বিটম্যাপের সীমানা ডিকোড করুন:

private fun decodeResizedBitmap(context: Context, uri: Uri, size: Size): Bitmap?{
    val boundsStream = context.contentResolver.openInputStream(uri)
    val options = BitmapFactory.Options()
    options.inJustDecodeBounds = true
    BitmapFactory.decodeStream(boundsStream, null, options)
    boundsStream?.close()

নমুনা আকার সেট করতে BitmapFactory.Options থেকে width এবং height ব্যবহার করুন:

if ( options.outHeight != 0 ) {
        // we've got bounds
        val widthSample = options.outWidth / size.width
        val heightSample = options.outHeight / size.height
        val sample = min(widthSample, heightSample)
        if (sample > 1) {
            options.inSampleSize = sample
        }
    }

স্ট্রীম ডিকোড করুন। inSampleSize উপর ভিত্তি করে দুটি শক্তির দ্বারা ফলিত চিত্রের আকার নমুনা করা হয়।

    options.inJustDecodeBounds = false
    val decodeStream = context.contentResolver.openInputStream(uri)
    val bitmap =  BitmapFactory.decodeStream(decodeStream, null, options)
    decodeStream?.close()
    return bitmap
}

একটি স্থানীয় ভিডিও ফাইল থেকে একটি থাম্বনেইল তৈরি করুন

ভিডিও থাম্বনেইল ইমেজ পাওয়ার ক্ষেত্রে ইমেজ থাম্বনেইল পাওয়ার মতো একই চ্যালেঞ্জ রয়েছে, কিন্তু ফাইলের আকার অনেক বড় হতে পারে এবং একটি প্রতিনিধি ভিডিও ফ্রেম পাওয়া সবসময় ভিডিওর প্রথম ফ্রেম বাছাই করার মতো সহজ নয়।

ভিডিও ফাইলের পাথে আপনার অ্যাক্সেস থাকলে createVideoThumbnail পদ্ধতিটি একটি কঠিন পছন্দ।

val bitmap = ThumbnailUtils.createVideoThumbnail(File(file_path), Size(640, 480), null)

আপনার যদি শুধুমাত্র একটি কন্টেন্ট Uri-এ অ্যাক্সেস থাকে, তাহলে আপনি MediaMetadataRetriever ব্যবহার করতে পারেন।

প্রথমে, ভিডিওটিতে একটি এম্বেড করা থাম্বনেইল আছে কিনা তা পরীক্ষা করুন এবং সম্ভব হলে সেটি ব্যবহার করুন:

private suspend fun getVideoThumbnailFromMediaMetadataRetriever(context: Context, uri: Uri, size: Size): Bitmap? {
    val mediaMetadataRetriever = MediaMetadataRetriever()
    mediaMetadataRetriever.setDataSource(context, uri)
    val thumbnailBytes = mediaMetadataRetriever.embeddedPicture
    val resizer = Resizer(size, null)
    ImageDecoder.createSource(context.contentResolver, uri)
    // use a built-in thumbnail if the media file has it
    thumbnailBytes?.let {
        return ImageDecoder.decodeBitmap(ImageDecoder.createSource(it));
    }

স্কেলিং ফ্যাক্টর গণনা করতে MediaMetadataRetriever থেকে ভিডিওর প্রস্থ এবং উচ্চতা আনুন:

val width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)
            ?.toFloat() ?: size.width.toFloat()
    val height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)
            ?.toFloat() ?: size.height.toFloat()
    val widthRatio = size.width.toFloat() / width
    val heightRatio = size.height.toFloat() / height
    val ratio = max(widthRatio, heightRatio)

Android 9+ (API স্তর 28) এ, MediaMetadataRetriever একটি স্কেল করা ফ্রেম ফিরিয়ে দিতে পারে:

if (ratio > 1) {
        val requestedWidth = width * ratio
        val requestedHeight = height * ratio
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            val frame = mediaMetadataRetriever.getScaledFrameAtTime(
                -1, OPTION_PREVIOUS_SYNC,
                requestedWidth.toInt(), requestedHeight.toInt())
            mediaMetadataRetriever.close()
            return frame
        }
    }

অন্যথায়, প্রথম ফ্রেমটি আনস্কেল না করে ফেরত দিন:

    // consider scaling this after the fact
    val frame = mediaMetadataRetriever.frameAtTime
    mediaMetadataRetriever.close()
    return frame
}