ریز عکسهای رسانه پیشنمایش بصری سریع تصاویر و ویدیوها را در اختیار کاربران قرار میدهند که امکان مرور سریعتر را فراهم میکند و در عین حال رابط برنامه را از نظر بصری جذابتر و جذابتر میکند. از آنجایی که تصاویر کوچکتر از رسانه های با اندازه کامل هستند، به صرفه جویی در حافظه، فضای ذخیره سازی و پهنای باند کمک می کنند و در عین حال عملکرد مرور رسانه را بهبود می بخشند.
بسته به نوع فایل و دسترسی به فایلی که در برنامه و دارایی های رسانه خود دارید، می توانید تصاویر کوچک را به روش های مختلف ایجاد کنید.
یک تصویر کوچک با استفاده از کتابخانه بارگذاری تصویر ایجاد کنید
کتابخانه های بارگذاری تصویر کارهای سنگین را برای شما انجام می دهند. آنها می توانند کش را همراه با منطق واکشی رسانه منبع از منبع محلی یا شبکه مبتنی بر 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
)
در صورت امکان، ریز عکسها را در سمت سرور ایجاد کنید . برای اطلاعات بیشتر در مورد نحوه بارگیری تصاویر با استفاده از Compose و بارگیری نقشه های بیتی بزرگ به طور موثر برای راهنمایی در مورد نحوه کار با تصاویر بزرگ به بارگیری تصاویر مراجعه کنید.
یک تصویر کوچک از یک فایل تصویر محلی ایجاد کنید
گرفتن تصاویر کوچک شامل کاهش مقیاس کارآمد در عین حفظ کیفیت بصری، اجتناب از استفاده بیش از حد از حافظه، برخورد با انواع فرمتهای تصویر و استفاده صحیح از دادههای Exif است.
متد createImageThumbnail
همه اینها را انجام می دهد و به شما امکان می دهد به مسیر فایل تصویر دسترسی داشته باشید.
val bitmap = ThumbnailUtils.createImageThumbnail(File(file_path), Size(640, 480), null)
اگر فقط Uri
دارید، میتوانید از روش loadThumbnail
در ContentResolver با Android 10، سطح API 29 استفاده کنید.
val thumbnail: Bitmap =
applicationContext.contentResolver.loadThumbnail(
content-uri, Size(640, 480), null)
ImageDecoder که با اندروید 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);
میتوانید از BitmapFactory برای ایجاد تصاویر کوچک برای برنامههایی که نسخههای قبلی اندروید را هدف قرار میدهند، استفاده کنید. BitmapFactory.Options تنظیماتی برای رمزگشایی فقط مرزهای یک تصویر به منظور نمونه برداری مجدد دارد.
ابتدا فقط مرزهای بیت مپ را در 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()
برای تنظیم اندازه نمونه از width
و height
از BitmapFactory.Options
استفاده کنید:
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
}