1.概述
在选择图片的功能实现中,发现某些图片存在缩略图过于小,因而展示模糊的问题。经分析确认确实查询到的图片尺寸特别小。
2.代码
获取缩略图
fun getImageThumbnail(context: Context, id: Int, int width, int height): Bitmap? {
return try {
var bitmap: Bitmap? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
try {
bitmap = context.contentResolver.loadThumbnail(
ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id.toLong()),
Size(width, height),
CancellationSignal()
)
} catch (e: Exception) {
}
} else {
bitmap = MediaStore.Images.Thumbnails.getThumbnail(
context.contentResolver,
id.toLong(),
MediaStore.Images.Thumbnails.MINI_KIND,
null
)
}
bitmap
} catch (e: Exception) {
null
}
阅读源码:
ContentResolver.java中
public static Bitmap loadThumbnail(@NonNull ContentInterface content, @NonNull Uri uri,
@NonNull Size size, @Nullable CancellationSignal signal, int allocator)
throws IOException {
Objects.requireNonNull(content);
Objects.requireNonNull(uri);
Objects.requireNonNull(size);
// Convert to Point, since that's what the API is defined as
final Bundle opts = new Bundle();
opts.putParcelable(EXTRA_SIZE, new Point(size.getWidth(), size.getHeight()));
final Int64Ref orientation = new Int64Ref(0);
Bitmap bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> {
final AssetFileDescriptor afd = content.openTypedAssetFile(uri, "image/*", opts,
signal);
final Bundle extras = afd.getExtras();
orientation.value = (extras != null) ? extras.getInt(EXTRA_ORIENTATION, 0) : 0;
return afd;
}), (ImageDecoder decoder, ImageInfo info, Source source) -> {
decoder.setAllocator(allocator);
// One last-ditch check to see if we've been canceled.
if (signal != null) signal.throwIfCanceled();
// We requested a rough thumbnail size, but the remote size may have
// returned something giant, so defensively scale down as needed.
final int widthSample = info.getSize().getWidth() / size.getWidth();
final int heightSample = info.getSize().getHeight() / size.getHeight();
final int sample = Math.max(widthSample, heightSample);
if (sample > 1) {
decoder.setTargetSampleSize(sample);
}
});
// Transform the bitmap if requested. We use a side-channel to
// communicate the orientation, since EXIF thumbnails don't contain
// the rotation flags of the original image.
if (orientation.value != 0) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
final Matrix m = new Matrix();
m.setRotate(orientation.value, width / 2, height / 2);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, false);
}
return bitmap;
}
此处info的尺寸就非常小,后续的操作是如果尺寸大于传入的size的时候,进行缩小。但是由于info的尺寸本身就非常小了,所以不会进行后续处理,返回的bitmap的宽高就非常小。
而且我发现,就算是其他的正常尺寸的图片,读到的bitmap的尺寸也是小于传入的尺寸的。至于这个的原因,未找到。
代码0中另一个版本方法去获取的尺寸也是一样,怎么修改都不会增大。
3.解决方案
想到的是异常的解决方案,当目标尺寸和实际尺寸差异太大,比如5倍的时候,采用其他方式去获取缩略图。此处的5倍是临时决定的,缺乏科学依据。