使用 Glide,是否有可能在实际解码和保存到位图中之前获得输出图像分辨率?
Using Glide, is it possible to get output image resolution, before the actual decoding and saving into a bitmap?
背景
我正在尝试对动态壁纸应用程序中的任何给定图像文件产生水平滚动效果。
为此,我应该按照这些规则来工作,我认为:
- 输入是任何分辨率的图像文件
- 我应该scale/crop这样高度就会有一个特定的值。
- 宽度应至少为特定值
- 输出位图要有一定的宽度,因为我不想做太大的位图,占用大量内存
- 无论如何都要保持纵横比。
问题
我发现很难找到正确的函数和参数以使其生成输出位图的正确宽度和高度。
我试过的
我试过各种变换(例如:centerCropTransform、fitCenterTransform),但是 none 达到了我想要的,所以我认为 none 可以工作,除非我做一些在决定如何处理 Glide 之前,我这边的特殊数学。
目前我做的是这样的:
val result = Glide.with(context).asBitmap()
.load(imageFile)
.apply(RequestOptions.noTransformation()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE))
.submit(reqWidth, reqHeight).get()
这是可行的,因为它生成(至少根据我的测试)位图至少达到我要求的大小。然而,这意味着我有额外的像素,这些像素对于高度来说并不是真正需要的。它也不能防止我生成太大的位图。
但我认为让 Glide 为上述目的使用各种技术可能会更容易,然后决定可能的输出分辨率,这是最好的。
问题
是否可以在实际解码和存储到位图之前获得输出分辨率,然后再决定应该使用哪种技术?
我是否应该考虑更好的选择?也许在我这边做计算,然后决定用 Glide 做什么?如果是,怎么做?
- I should scale/crop so that the height will be of a specific value.
- The width should be at least of a specific value
- Keep the aspect ratio no matter what.
你不能真的认为所有这些都是真的,因为如果你有保证的最小高度和保证的最小宽度,那么你可能不得不扭曲纵横比,这违反了第三个条件。
我建议改为满足以下三个条件:
- 将输出的最大高度设置为设备屏幕的高度(纵向)
- 设置输出位图的最大分配内存
- 无论如何保持原始宽高比
Glide 可以为您完成 1 和 3,但 2 您可能需要先解码位图而不分配内存(查看 BitmapFactory.Options.inJustDecodeBounds
)以获得源宽高比,然后使用数学计算出高度和要设置的宽度,这样您就不会超过每个位图的内存上限。
最后一件事,根据您的用例(如果您需要在短时间内渲染多个位图),您可能需要考虑裁剪为标准输出纵横比,以便您可以利用 Glide 的位图回收功能,有助于避免 OOM 崩溃。
好的,我想我明白了。
我计算了如果我适应宽度和高度会发生什么,并相应地在计算结果上使用居中裁剪:
val bitmapOptions = Utils.getBitmapOptions(savedImageFileForWallpaperBackground.absolutePath)
//newWidth/newHeight=oldWidth/oldHeight
val widthIfScaledToHeight = reqHeight * bitmapOptions.outWidth / bitmapOptions.outHeight
val heightIfScaledToWidth = reqWidth * bitmapOptions.outHeight / bitmapOptions.outWidth
val result: Bitmap
if (widthIfScaledToHeight >= reqWidth) {
result = Glide.with(wallpaperService).asBitmap()
.load(savedImageFileForWallpaperBackground)
.apply(RequestOptions.centerCropTransform().skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE))
.submit(widthIfScaledToHeight, reqHeight).get()
} else {
result = Glide.with(wallpaperService).asBitmap()
.load(savedImageFileForWallpaperBackground)
.apply(RequestOptions.centerCropTransform().skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE))
.submit(reqWidth, heightIfScaledToWidth).get()
}
背景
我正在尝试对动态壁纸应用程序中的任何给定图像文件产生水平滚动效果。
为此,我应该按照这些规则来工作,我认为:
- 输入是任何分辨率的图像文件
- 我应该scale/crop这样高度就会有一个特定的值。
- 宽度应至少为特定值
- 输出位图要有一定的宽度,因为我不想做太大的位图,占用大量内存
- 无论如何都要保持纵横比。
问题
我发现很难找到正确的函数和参数以使其生成输出位图的正确宽度和高度。
我试过的
我试过各种变换(例如:centerCropTransform、fitCenterTransform),但是 none 达到了我想要的,所以我认为 none 可以工作,除非我做一些在决定如何处理 Glide 之前,我这边的特殊数学。
目前我做的是这样的:
val result = Glide.with(context).asBitmap()
.load(imageFile)
.apply(RequestOptions.noTransformation()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE))
.submit(reqWidth, reqHeight).get()
这是可行的,因为它生成(至少根据我的测试)位图至少达到我要求的大小。然而,这意味着我有额外的像素,这些像素对于高度来说并不是真正需要的。它也不能防止我生成太大的位图。
但我认为让 Glide 为上述目的使用各种技术可能会更容易,然后决定可能的输出分辨率,这是最好的。
问题
是否可以在实际解码和存储到位图之前获得输出分辨率,然后再决定应该使用哪种技术?
我是否应该考虑更好的选择?也许在我这边做计算,然后决定用 Glide 做什么?如果是,怎么做?
- I should scale/crop so that the height will be of a specific value.
- The width should be at least of a specific value
- Keep the aspect ratio no matter what.
你不能真的认为所有这些都是真的,因为如果你有保证的最小高度和保证的最小宽度,那么你可能不得不扭曲纵横比,这违反了第三个条件。
我建议改为满足以下三个条件:
- 将输出的最大高度设置为设备屏幕的高度(纵向)
- 设置输出位图的最大分配内存
- 无论如何保持原始宽高比
Glide 可以为您完成 1 和 3,但 2 您可能需要先解码位图而不分配内存(查看 BitmapFactory.Options.inJustDecodeBounds
)以获得源宽高比,然后使用数学计算出高度和要设置的宽度,这样您就不会超过每个位图的内存上限。
最后一件事,根据您的用例(如果您需要在短时间内渲染多个位图),您可能需要考虑裁剪为标准输出纵横比,以便您可以利用 Glide 的位图回收功能,有助于避免 OOM 崩溃。
好的,我想我明白了。
我计算了如果我适应宽度和高度会发生什么,并相应地在计算结果上使用居中裁剪:
val bitmapOptions = Utils.getBitmapOptions(savedImageFileForWallpaperBackground.absolutePath)
//newWidth/newHeight=oldWidth/oldHeight
val widthIfScaledToHeight = reqHeight * bitmapOptions.outWidth / bitmapOptions.outHeight
val heightIfScaledToWidth = reqWidth * bitmapOptions.outHeight / bitmapOptions.outWidth
val result: Bitmap
if (widthIfScaledToHeight >= reqWidth) {
result = Glide.with(wallpaperService).asBitmap()
.load(savedImageFileForWallpaperBackground)
.apply(RequestOptions.centerCropTransform().skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE))
.submit(widthIfScaledToHeight, reqHeight).get()
} else {
result = Glide.with(wallpaperService).asBitmap()
.load(savedImageFileForWallpaperBackground)
.apply(RequestOptions.centerCropTransform().skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE))
.submit(reqWidth, heightIfScaledToWidth).get()
}