我正在使用Apache Commons Imaging(Sanselan)将EXIF元数据写入JPEG,至少在Sanselan的0.97版本中,有一些与charset / encoding相关的错误。 EXIF 2.2标准要求UNDEFINED
类型的编码以8字节ASCII“签名”作为前缀,描述以下内容的编码。我正在写的字段/标记是UserComment
EXIF标记。
Windows期望内容以UTF16编码,因此写入JPEG的字节必须包含(单字节)ASCII字符的组合,后跟(双字节)Unicode字符。此外,尽管UserComment
似乎并不需要它,但我注意到内容通常是“空填充”到均匀长度。
这是我用来创建和编写标签的代码:
String textToSet = "Test";
byte[] ASCIIMarker = new byte[]{ 0x55, 0x4E, 0x49, 0x43, 0x4F, 0x44, 0x45, 0x00 }; // spells out "UNICODE"
byte[] comment = textToSet.getBytes("UnicodeLittle");
// pad with \0 if (total) length is odd (or is \0 byte automatically added by arraycopy?)
int pad = (ASCIIMarker.length + comment.length) % 2;
byte[] bytesComment = new byte[ASCIIMarker.length + comment.length + pad];
System.arraycopy(ASCIIMarker, 0, bytesComment, 0, ASCIIMarker.length);
System.arraycopy(comment, 0, bytesComment, ASCIIMarker.length, comment.length);
if (pad > 0) bytesComment[bytesComment.length-1] = 0x00;
TiffOutputField exif_comment = new TiffOutputField(TiffConstants.EXIF_TAG_USER_COMMENT,
TiffFieldTypeConstants.FIELD_TYPE_UNDEFINED, bytesComment.length - pad, bytesComment);
然后当我从JPEG中读回标签时,我会执行以下操作:
String textRead;
TiffField field = jpegMetadata.findEXIFValue(TiffConstants.EXIF_TAG_USER_COMMENT);
if (field != null) {
textRead= new String(field.getByteArrayValue(), "UnicodeLittle");
}
令我困惑的是:写入JPEG的字节以8个ASCII字节为前缀,显然需要“剥离”以便比较写入的内容:
if (textRead != null) {
if (textToSet.equals(textRead)) { // expecting this to FAIL
print "Equal";
} else {
print "Not equal";
if (textToSet.equals(textRead.substring(5))) { // this works
print "Equal after all...";
}
}
}
但为什么substring(5)
,而不是...... substring(8)
?如果它是4,我可能认为4个双字节(UTF-16)符号总共8个字节,但只有当我剥离 5个字节时它才有效。这表明我没有创建有效负载(字节数组bytesComment
)是否正确?
PS!我将更新到2016年推出的Apache Commons Imaging RC 1.0,并希望修复这些错误,但我仍然想知道为什么一旦我得到这个错误到目前为止0.97: - )