Blog Details

Home活动日历生成媒体缩略图

生成媒体缩略图

媒体缩略图可为用户提供图片和视频的快速可视预览,

加快浏览速度,同时让应用界面更加直观

富有吸引力由于缩略图比完整尺寸的媒体要小,

它们有助于节省内存、存储空间和带宽

浏览性能

您可以通过多种不同的方式创建缩略图,具体取决于文件类型以及您在应用和媒体资源中的文件访问权限。

使用图片加载库创建缩略图

图片加载库会为您完成许多繁杂的工作;他们可以处理

缓存以及从本地或网络提取源媒体的逻辑

根据 Uri 创建资源。以下代码演示了如何使用

Coil 图片加载库同时适用于图片和视频,

并适用于本地或网络资源

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

从 Android 9(API 级别 28)开始提供的 ImageDecoder 具有一些

在解码时对图像进行重新采样的可靠选项,以避免产生额外的内存

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 为之前以较早版本为目标平台的应用创建缩略图

Android 版本。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()

使用 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

}

}

解码流。所生成图像的大小为 2 的次方

(基于 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

}

Copyright © 2088 霹雳侠职业教学与活动专题 All Rights Reserved.
友情链接