Android中将Bitmap调整到指定高度1000实际尺寸异常如何解决
问题原因
尺寸不符合预期主要由三个问题导致:
- Bitmap解码阶段系统默认根据设备密度自动缩放,初始Bitmap尺寸和YUV原始帧尺寸不一致
- YUV转JPEG时使用YuvImage对齐后的宽度作为压缩边界,引入无效像素,导致比例偏差
- 缩放生成的Bitmap未显式指定密度,后续获取尺寸时可能出现换算偏差
修复步骤
1. 关闭Bitmap解码的自动缩放
修改解码逻辑,禁用系统默认的密度缩放:
// Convert jpeg to Bitmap byte[] imageBytes = stream.toByteArray(); Bitmap bitmap = null; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){ ByteBuffer buffer = ByteBuffer.wrap(imageBytes); ImageDecoder.Source src = ImageDecoder.createSource(buffer); try { bitmap = ImageDecoder.decodeBitmap(src, (decoder, info, source) -> { decoder.setTargetDensity(DisplayMetrics.DENSITY_DEFAULT); decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); } catch (IOException e) { e.printStackTrace(); return null; } } else { BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options); }
2. 修正YUV转JPEG的压缩边界
使用YUV帧的实际有效宽高作为压缩范围,不要用YuvImage的对齐宽高:
// 替换原有Rect构造逻辑,使用i420Buffer的实际有效宽高 Rect rect = new Rect(0, 0, i420Buffer.getWidth(), i420Buffer.getHeight()); // Compress YuvImage to jpeg yuvImage.compressToJpeg(rect, 100, stream);
3. 可选优化:避免精度损失
如果需要更精准的宽度适配,修改resizeToWidthRatio里的宽度计算逻辑:
public static Bitmap resizeToWidthRatio(Bitmap bm, int height) { float ratio = (float)bm.getWidth() / (float)bm.getHeight(); // 用四舍五入替代强制转换,减少精度损失 int width = Math.round(height * ratio); return resize(bm, width, height); }
4. 可选优化:显式指定输出Bitmap密度
确保后续获取尺寸时不会出现换算偏差,修改resize函数:
public static Bitmap resize(Bitmap bm, int width, int height) { int oldWidth = bm.getWidth(); int oldHeight = bm.getHeight(); float scaleWidth = ((float)width) / oldWidth; float scaleHeight = ((float)height) / oldHeight; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, oldWidth, oldHeight, matrix, true); // 显式设置密度为默认值,避免后续尺寸换算偏差 resizedBitmap.setDensity(DisplayMetrics.DENSITY_DEFAULT); return resizedBitmap; }
内容的提问来源于stack exchange,提问作者mayur.pancholi
相关产品推荐
相关产品推荐

