我的midlet正在显示一些图像,但不是其他图像。
它们都是8位PNG,但那些没有显示的是我在PhotoShop中创建的那些。
所以我想也许我的PhotoShop(CS6)设置错了......
PNG-8,Selective,Diffusion,颜色:256,Dither:100%,Matte:None,Web 捕捉:0%,转换为sRGB:勾选,宽度:48,高度:48,百分比:100%, 质量:双立方。
我已尝试过其中一些设置,但无济于事。
有什么想法吗?
有一个similar problem here,但这与我的相反,因为PhotoShop在这种情况下修补了东西,而不是破坏了东西...
我的代码是......
image = Image.createImage("/img/loading1.png");
...这是我的堆栈跟踪:
java.io.EOFException
at javax.imageio.stream.ImageInputStreamImpl.readFully(
ImageInputStreamImpl.java:353)
at java.io.DataInputStream.readUTF(DataInputStream.java:609)
at javax.imageio.stream.ImageInputStreamImpl.readUTF(ImageInputStreamImpl.java:332)
at com.sun.kvem.png.PNGImageReader.parse_iTXt_chunk(PNGImageReader.java:447)
at com.sun.kvem.png.PNGImageReader.readMetadata(PNGImageReader.java:650)
at com.sun.kvem.png.PNGImageReader.readImage(PNGImageReader.java:1312)
at com.sun.kvem.png.PNGImageReader.read(PNGImageReader.java:1582)
at com.sun.kvem.midp.GraphicsBridge.loadImage(GraphicsBridge.java:2602)
at com.sun.kvem.midp.GraphicsBridge.createImageFromData(GraphicsBridge.java:2511)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.kvem.sublime.MethodExecution.process(MethodExecution.java:42)
at com.sun.kvem.sublime.SublimeExecutor.processRequest(SublimeExecutor.java:63)
at javax.microedition.lcdui.Image.createImage(Image.java:315)
有问题的图像确实存在 - 无论是在项目中还是在构建的jar中。
以下是相关图片:
答案 0 :(得分:3)
根据崩溃日志,J2ME中的PNG解码器在非关键块iTXt
内失败: 1
> com.sun.kvem.png.PNGImageReader.readMetadata
> com.sun.kvem.png.PNGImageReader.parse_iTXt_chunk
> javax.imageio.stream.ImageInputStreamImpl.readUTF
> java.io.DataInputStream.readUTF
根据libpng documentation,iTXt
块的文本部分必须是有效的UTF8:
...根据压缩标志,剩余的块数据是主要的UTF-8文本,无论是zlib压缩还是非压缩。由于其长度可以从块长度确定,因此它不是以空值终止的。与其他两个文本块一样,换行符应由单个换行符(十进制10)表示,并且不鼓励所有其他控制字符(1-9,11-31和127-159)。
通常这表示读取的流不是有效的UTF8文本 - 它包含' raw'高于普通ASCII范围0..127
的字节,不符合UTF8规则。
我发现样本图像不是这种情况。只有一组连续字节构成UTF8代码序列,它是有效的:
<?xpacket begin="EFBBBF" id=" ..
(粗体部分以十六进制表示法表示3个数据字节)。我首先怀疑这是错误:
如果BOM字符出现在数据流的中间,Unicode表示它应该被解释为&#34;零宽度不间断空格&#34; (禁止单词字形之间的换行)。在Unicode 3.2中,不推荐使用此用法以支持&#34; Word Joiner&#34;字符,U + 2060。[1]这允许U + FEFF仅用作BOM (http://en.wikipedia.org/wiki/Byte_order_mark)
..所以一个完全符合标准的UTF8读取器应检查其字节,并在遇到BOM时抛出UTFDataFormatException
,而不是作为第一个值。令人惊讶的是,这似乎不是问题所在!首先,没有任何迹象表明任何readUTF
来源除了仅验证UTF8代码是否在其自身的上之外还做其他任何事情,无论其价值如何。有很多&#39;无效&#39; Unicode 代码点(不代表有效的Unicode字符或指令的值),但在我看来它们都被默默地忽略了。但我注意到常见的readUTF
函数只实现了UTF8 / Unicode的一小部分(参见Oracle文档中的Modified UTF-8)。
所以问题出在其他地方。另一个线索是,抛出的错误是不是 UTFDataFormatException
而是EOFException
,表明读缓冲区已经超出了它承诺包含的字节数。
(警告:纯粹的猜想如下)
查看DataInputStream
的来源,我找到了这段代码:
588 public final static String readUTF(DataInput in) throws IOException {
589 int utflen = in.readUnsignedShort();
后跟循环读取utflen
字节(不是&#34; Unicode字符&#34;)。这对iTXt
块来说是错误的,因为它没有第一个单词&#39;表明它的长度。纯文本中的字节数可以从块长度(根据PNG约定,不包括长度长字的总数据长度,iTXt
签名本身和最终CRC32代码)中导出。零终止关键字名称,语言和&#34;翻译关键字&#34;的长度字符串,以及表示完整纯文本压缩的两个字节。
作为解决方法,请从PNG图像中删除iTXt
块。数据本身 - XMP元数据 - 很可能根本不适合您的目的(但请随时阅读what benefits Adobe thinks it has)。如果你的工作流程没有使用它,它只是一个无用的未压缩文本块,在你的样本图像中占用总共981个字节的814个字节 - 高达83%!
您可以使用外部实用程序删除无关的数据块;例如,流行的pngcrush
的命令行是
pngcrush -rem alla -rem text InputFile.png OutputFile.png
(来自en.wikipedia.org/wiki/Pngcrush)。
或直接来自Photoshop:如果您保存PNG&#39;通常的方式&#39;与&#34;另存为&#34;菜单选项,元数据进入,没有复选框来摆脱它。如果你使用&#34; Save for Web&amp;装置&#34;相反,你得到一个包含许多方便选项的大型对话框,例如标有&#34;元数据&#34;的下拉列表。
选择&#34;全部&#34;我有一个更大的档案;我的Photoshop版本创建了一个大量 3K块的XMP元数据,其中包括一个2K完全空的填充程序&#39;块...
选择&#34;版权所有&#34;或&#34;无&#34;终于摆脱了所有的crud(大概是因为我没有填写任何版权信息),然后你得到一个漂亮的169字节长的PNG,其中唯一的元数据是所使用的软件称为&#34; Adobe ImageReady&#34 ;
1 这是具有讽刺意味的。根据PNG规范,
..遇到未知块(其中辅助位为1)的解码器可以安全地忽略该块并继续显示图像。
(source)
这个&#34;辅助位&#34;是块ID的第一个字节的第5位:0(大写)=临界,1(小写)=辅助,即,如果块ID的第一个字符是大写,则PNG读取器必须正确读取和解释其数据,如果不正确,则可以静默跳过。
从技术上讲,J2ME的编写者可以安全地忽略整个块。但是他们搞砸了,尝试来阅读它,现在代码崩溃了所有程序只是试图读取恰好包含iTXt
块的PNG中的图像数据。