Android端压缩DNG文件体积时生成损坏文件的问题咨询
问题原因
你生成的文件损坏并非只是缺失元数据,核心是当前实现逻辑完全不符合DNG格式规范:
- DNG是Adobe公开的RAW原始图像标准,属于TIFF格式的扩展,必须包含标准文件头、IFD图像文件目录结构、完整的拍摄/传感器元数据、原始像素数据才能被识别,不是把任意像素数据存为.dng后缀就能正常打开。
- 你的代码流程存在本质错误:用
BitmapFactory解码DNG的过程,已经把原始RAW格式的拜耳阵列传感器数据、色彩校准参数、黑电平等所有RAW专属信息全部丢弃,转成了供屏幕显示用的ARGB_8888格式普通位图;后续直接把这个位图的内存裸数据写入文件,输出的是没有任何文件头、格式信息的裸像素流,既不是DNG,也不是任何常规图片格式,自然无法打开。 - 额外代码bug:第一次调用
BitmapFactory.decodeFile时设置了inJustDecodeBounds = true,这个模式下方法返回值永远为null,你给bmp赋值的这行代码是无效的,还存在空指针风险。
实现方案
根据你的需求二选一即可:
方案1:不需要保留RAW属性,仅需压缩图片体积
不要输出DNG格式,直接用Android原生支持的压缩图片格式输出,实现简单兼容性好:
直接替换原有写入裸像素的逻辑,用Bitmap自带的压缩方法输出JPEG/WEBP等格式即可,压缩质量可按需调整:
// 替换原代码中写入byteArray的文件写入逻辑 try { // 输出为JPG格式,不需要强行用dng后缀 File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/compressed_pic.jpg"); if (!file.exists()) { file.createNewFile(); } FileOutputStream fos = new FileOutputStream(file); // 第二个参数为压缩质量,取值0-100,数值越小体积越小,画质越低 scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos); fos.flush(); fos.close(); } catch (Exception e) { Log.d(TAG, "compressImage: " + e.getMessage()); }
方案2:必须输出标准合法的DNG文件
这个场景下不能使用普通Bitmap解码、重绘的流程,否则会丢失RAW数据不可逆:
- 不要将原DNG解码为普通RGB位图,需要先完整读取原DNG的所有元数据:包括TIFF文件头、IFD结构、EXIF信息、传感器校准参数、黑/白电平、色彩矩阵等所有标准DNG标签。
- 如果需要缩放,要直接对原始拜耳阵列RAW数据做缩放处理,不能做去马赛克转RGB的操作——一旦转成普通ARGB位图,就无法还原为DNG要求的原始传感器数据,不可能生成合法DNG。
- 按照DNG规范组装文件:按顺序写入对齐的TIFF头、各IFD块(主图IFD、缩略图IFD、DNG专属IFD)、像素数据,确保所有标签的偏移量计算正确。
- Android系统从API21开始提供了
DngCreator工具类可以直接生成标准DNG,但这个类只接收相机输出的RawImage类型原始传感器数据,不支持传入普通RGB位图生成DNG。
注意:如果你手里只有已经解码完成的普通Bitmap对象,没有原始RAW传感器数据,没有任何方法可以生成可用的DNG文件,这种情况直接选择方案1输出普通压缩图片即可。
内容的提问来源于stack exchange,提问作者danny
相关产品推荐
相关产品推荐

