我正在使用Android自定义相机捕捉JPG图像,但无法在Windows照片查看器上预览它们。任何人都可以请建议。图像是可见的使用其他应用程序,如Ms Paint,Office,Windows 10照片应用程序。
uplii1fm1#
这显然是由Android将添加到位图的ICC颜色配置文件导致的。Windows照片查看器无法显示具有该ICC颜色配置文件的图像。我还没有发现这个ICC配置文件是如何生成的,我假设这是由Android Bitmap.compress函数完成的。删除配置文件,例如ImageMagick将“修复”文件,他们将在照片查看器中打开太。
63lcw9qa2#
从Android 10开始,Bitmap.compress()似乎添加了一个ICC配置文件。这个问题是由添加的ICC配置文件中的错误版本值引起的。这个问题在skia问题跟踪器上报告并修复。我不知道什么时候会在Android上修复。https://bugs.chromium.org/p/skia/issues/detail?id=12491因此,从Bitmap.compress()生成的jpeg图像中删除ICC配置文件似乎是目前最好的方法。要通过编程解决此问题,您需要解析Bitmap.compress()生成的JPEG数据,以删除ICC配置文件段。
2022年9月7日更新:此问题已在Android 13中修复。(SKIA SkICC.cpp)
这是一个删除ICC配置文件段的示例代码。请参考Exiv2的“JPEG文件中的元数据”,了解ICC配置文件如何嵌入到jpeg文件中。
更新日期:2022年10月28日:修复了不正确的APP2段复制
public class JpegFixer { private static final int MARKER = 0xff; private static final int MARKER_SOI = 0xd8; private static final int MARKER_SOS = 0xda; private static final int MARKER_APP2 = 0xe2; private static final int MARKER_EOI = 0xd9; public void removeIccProfile(InputStream inputStream, String outputPath) throws IOException { FileOutputStream outputStream = new FileOutputStream( outputPath ); if ( inputStream.read() != MARKER || inputStream.read() != MARKER_SOI ) { throw new IOException( "Not a JPEG image" ); } outputStream.write( MARKER ); outputStream.write( MARKER_SOI ); while ( true ) { int marker0 = inputStream.read(); int marker1 = inputStream.read(); if ( marker0 != MARKER ) { throw new IOException( "Invalid marker:" + Integer.toHexString( marker0 & 0xff ) ); } int length0 = inputStream.read(); int length1 = inputStream.read(); final int segmentLength = (length0 << 8 & 0xFF00) | (length1 & 0xFF); final int length = segmentLength - 2; if ( length < 0 ) { throw new IOException( "Invalid length" ); } if ( marker1 == MARKER_EOI || marker1 == MARKER_SOS ) { outputStream.write( marker0 ); outputStream.write( marker1 ); outputStream.write( length0 ); outputStream.write( length1 ); copy( inputStream, outputStream ); break; } // ICC_PROFILE\0" if ( marker1 == MARKER_APP2 && length >= 12 + 2 ) { byte[] buffer = new byte[12]; read( inputStream, buffer ); if ( buffer[0] == 'I' && buffer[1] == 'C' && buffer[2] == 'C' && buffer[3] == '_' && buffer[4] == 'P' && buffer[5] == 'R' && buffer[6] == 'O' && buffer[7] == 'F' && buffer[8] == 'I' && buffer[9] == 'L' && buffer[10] == 'E' && buffer[11] == 0 ) { // skip segment inputStream.skip( length - buffer.length ); } else { // copy segment outputStream.write( marker0 ); outputStream.write( marker1 ); outputStream.write( length0 ); outputStream.write( length1 ); outputStream.write( buffer ); copy( inputStream, outputStream, length - buffer.length ); } } else { // copy segment outputStream.write( marker0 ); outputStream.write( marker1 ); outputStream.write( length0 ); outputStream.write( length1 ); copy( inputStream, outputStream, length ); } } } public void read(InputStream is, byte[] buffer) throws IOException { int totalBytesRead = 0; while ( totalBytesRead != buffer.length ) { final int bytesRead = is.read( buffer, totalBytesRead, buffer.length - totalBytesRead ); if ( bytesRead == -1 ) { throw new EOFException( "End of data reached." ); } totalBytesRead += bytesRead; } } private int copy(InputStream is, OutputStream out, int numBytes) throws IOException { int remainder = numBytes; byte[] buffer = new byte[8192]; while ( remainder > 0 ) { int n = is.read( buffer, 0, Math.min( remainder, buffer.length ) ); if ( n == -1 ) { break; } remainder -= n; out.write( buffer, 0, n ); } return numBytes; } private int copy(InputStream is, OutputStream os) throws IOException { int total = 0; byte[] buffer = new byte[8192]; int c; while ( (c = is.read(buffer)) != -1 ) { total += c; os.write( buffer, 0, c ); } return total; } }
yvgpqqbh3#
此问题的其他答案已经解释了可能由Android采用的图像压缩技术相关的一些错误导致的问题,阻止图像在Windows照片查看器中打开。我已经多次向谷歌和Android社区报告了这个问题,但即使在进行了多次Android升级后,这个问题仍然存在。我知道这个问题是令人恼火的,在没有直接的解决方案之后,我希望分享一个简单可靠的周转这个问题与开源软件是可靠的。1.对于单个图像,使用GIMP打开图像,然后在替换现有文件时按原样导出(CTRL+SHIFT+E)图像。
1.对于多个图像,请使用CAESIUM图像压缩程序,并将“质量”设置为100%。
3条答案
按热度按时间uplii1fm1#
这显然是由Android将添加到位图的ICC颜色配置文件导致的。Windows照片查看器无法显示具有该ICC颜色配置文件的图像。
我还没有发现这个ICC配置文件是如何生成的,我假设这是由Android Bitmap.compress函数完成的。
删除配置文件,例如ImageMagick将“修复”文件,他们将在照片查看器中打开太。
63lcw9qa2#
从Android 10开始,Bitmap.compress()似乎添加了一个ICC配置文件。
这个问题是由添加的ICC配置文件中的错误版本值引起的。这个问题在skia问题跟踪器上报告并修复。我不知道什么时候会在Android上修复。
https://bugs.chromium.org/p/skia/issues/detail?id=12491
因此,从Bitmap.compress()生成的jpeg图像中删除ICC配置文件似乎是目前最好的方法。要通过编程解决此问题,您需要解析Bitmap.compress()生成的JPEG数据,以删除ICC配置文件段。
2022年9月7日更新:此问题已在Android 13中修复。(SKIA SkICC.cpp)
这是一个删除ICC配置文件段的示例代码。请参考Exiv2的“JPEG文件中的元数据”,了解ICC配置文件如何嵌入到jpeg文件中。
更新日期:2022年10月28日:修复了不正确的APP2段复制
yvgpqqbh3#
此问题的其他答案已经解释了可能由Android采用的图像压缩技术相关的一些错误导致的问题,阻止图像在Windows照片查看器中打开。
我已经多次向谷歌和Android社区报告了这个问题,但即使在进行了多次Android升级后,这个问题仍然存在。
我知道这个问题是令人恼火的,在没有直接的解决方案之后,我希望分享一个简单可靠的周转这个问题与开源软件是可靠的。
1.对于单个图像,使用GIMP打开图像,然后在替换现有文件时按原样导出(CTRL+SHIFT+E)图像。
1.对于多个图像,请使用CAESIUM图像压缩程序,并将“质量”设置为100%。