Medya küçük resimleri oluşturma

Medya küçük resimleri, kullanıcılara görsellerin ve videoların görsel önizlemesinin hızlı bir şekilde gösterilmesini sağlar. hem daha hızlı göz atmanızı sağlar hem de uygulama arayüzünü görsel açıdan daha zengin hale getirir ve ilgi çekici olmasını sağlayın. Küçük resimler tam boyutlu medyadan daha küçük olduğu için bellekten, depolama alanından ve bant genişliğinden tasarruf edilmesine ve medya içeriğinin iyileştirilmesine göz atma performansı.

Dosya türüne ve başvurunuzdaki dosya erişimine bağlı olarak küçük resimleri oluşturmak için farklı yöntemler kullanabilirsiniz.

Resim yükleme kitaplığı kullanarak küçük resim oluşturma

Resim yükleme kitaplıkları, işin büyük bir kısmını sizin yerinize halleder. ele alabilirler. kaynak medyayı yerelden veya ağdan getirme mantığıyla birlikte önbelleğe alma Uri'ye dayalı kaynaktır. Aşağıdaki kod, Coil resim yükleme kitaplığı hem resimlerde hem de videolarda çalışır. ve yerel kaynak veya ağ kaynağında çalışır.

// 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
)

Mümkünse sunucu tarafında küçük resimler oluşturun. Resim yükleme konusuna bakın oluşturma ve Büyük bit eşlemler yükleme hakkında ayrıntılı bilgi için başlıklı makalemize göz atın.

Yerel bir görüntü dosyasından küçük resim oluşturma

Küçük resim görselleri elde etmek, görselliği korurken etkili bir küçültme işlemi içerir kalitesinden ödün vermeden, aşırı bellek kullanımından kaçınarak ve Exif verilerini doğru şekilde kullanmak.

createImageThumbnail yöntemi bunların tümünü yapar ve resim dosyasının yoluna erişme olanağı sunar.

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

Yalnızca Uri varsa Android 10 (API düzeyi 29) ve sonraki sürümlerde ContentResolver'da loadThumbnail yöntemini kullanabilirsiniz.

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

Android 9, API düzeyi 28'den itibaren sunulan ImageDecoder'da ise bazı özellikler kod çözerken resmin yeniden örneklenmesi için sabit seçenekler sunar. pek de iyi olmadığını unutmayın.

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);

Erken hedefleyen uygulamalar için küçük resimler oluşturmak üzere BitmapFactory'yi kullanabilirsiniz Android sürümleri BitmapFactory.Options bölümünde yalnızca sınırlarına dikkat edin.

İlk olarak bit eşlemin sınırlarının kodunu çözüp BitmapFactory.Options içine alın:

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()

Örnek boyutunu ayarlamak için BitmapFactory.Options'deki width ve height öğelerini kullanın:

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
        }
    }

Akıştan kod çözme işlemi yapın. Ortaya çıkan görüntünün boyutu, iki kuvvet ile örneklenir (inSampleSize) daha önemlidir.

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

Yerel video dosyasından küçük resim oluşturma

Video küçük resimleri elde etmek, resim küçük resimleri elde etmekle aynı zorlukların çoğunu içerir ancak dosya boyutları çok daha büyük olabilir ve temsili bir video karesi elde etmek her zaman videonun ilk karesini seçmek kadar kolay değildir.

Aşağıdakilere erişiminiz varsa createVideoThumbnail yöntemi doğru bir seçimdir video dosyasının yolunu ekler.

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

Yalnızca bir içerik URI'sına erişebiliyorsanız MediaMetadataRetriever.

Öncelikle videonun yerleşik bir küçük resmi olup olmadığını kontrol edin ve mümkün:

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));
    }

Videonun MediaMetadataRetriever genişliği ve yüksekliğini al ve ölçeklendirme faktörünü hesaplayın:

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 ve sonraki sürümlerde (API düzeyi 28) MediaMetadataRetriever, ölçeklendirilmiş çerçeve:

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
        }
    }

Aksi takdirde, ilk kareyi ölçeklenmemiş olarak döndürün:

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