in src/main/java/org/apache/commons/imaging/formats/jpeg/iptc/IptcParser.java [114:213]
protected List<IptcBlock> parseAllBlocks(final byte[] bytes,
final boolean strict) throws ImagingException, IOException {
final List<IptcBlock> blocks = new ArrayList<>();
try (InputStream bis = new ByteArrayInputStream(bytes)) {
// Note that these are unsigned quantities. Name is always an even
// number of bytes (including the 1st byte, which is the size.)
final byte[] idString = readBytes("", bis,
JpegConstants.PHOTOSHOP_IDENTIFICATION_STRING.size(),
"App13 Segment missing identification string");
if (!JpegConstants.PHOTOSHOP_IDENTIFICATION_STRING.equals(idString)) {
throw new ImagingException("Not a Photoshop App13 Segment");
}
// int index = PHOTOSHOP_IDENTIFICATION_STRING.length;
while (true) {
final int imageResourceBlockSignature;
try {
imageResourceBlockSignature = read4Bytes("", bis,
"Image Resource Block missing identification string", APP13_BYTE_ORDER);
} catch (final IOException ioEx) {
break;
}
if (imageResourceBlockSignature != JpegConstants.CONST_8BIM) {
throw new ImagingException(
"Invalid Image Resource Block Signature");
}
final int blockType = read2Bytes("", bis, "Image Resource Block missing type", APP13_BYTE_ORDER);
Debug.debug("blockType: " + blockType + " (0x" + Integer.toHexString(blockType) + ")");
// skip blocks that the photoshop spec recommends to, see IMAGING-246
if (PHOTOSHOP_IGNORED_BLOCK_TYPE.contains(blockType)) {
Debug.debug("Skipping blockType: " + blockType + " (0x" + Integer.toHexString(blockType) + ")");
// if there is still data in this block, before the next image resource block
// (8BIM), then we must consume these bytes to leave a pointer ready to read
// the next block
BinaryFunctions.searchQuad(JpegConstants.CONST_8BIM, bis);
continue;
}
final int blockNameLength = readByte("Name length", bis, "Image Resource Block missing name length");
if (blockNameLength > 0) {
Debug.debug("blockNameLength: " + blockNameLength + " (0x"
+ Integer.toHexString(blockNameLength) + ")");
}
byte[] blockNameBytes;
if (blockNameLength == 0) {
readByte("Block name bytes", bis, "Image Resource Block has invalid name");
blockNameBytes = ImagingConstants.EMPTY_BYTE_ARRAY;
} else {
try {
blockNameBytes = readBytes("", bis, blockNameLength,
"Invalid Image Resource Block name");
} catch (final IOException ioEx) {
if (strict) {
throw ioEx;
}
break;
}
if (blockNameLength % 2 == 0) {
readByte("Padding byte", bis, "Image Resource Block missing padding byte");
}
}
final int blockSize = read4Bytes("", bis, "Image Resource Block missing size", APP13_BYTE_ORDER);
Debug.debug("blockSize: " + blockSize + " (0x" + Integer.toHexString(blockSize) + ")");
/*
* doesn't catch cases where blocksize is invalid but is still less
* than bytes.length but will at least prevent OutOfMemory errors
*/
if (blockSize > bytes.length) {
throw new ImagingException("Invalid Block Size : " + blockSize + " > " + bytes.length);
}
final byte[] blockData;
try {
blockData = readBytes("", bis, blockSize, "Invalid Image Resource Block data");
} catch (final IOException ioEx) {
if (strict) {
throw ioEx;
}
break;
}
blocks.add(new IptcBlock(blockType, blockNameBytes, blockData));
if ((blockSize % 2) != 0) {
readByte("Padding byte", bis, "Image Resource Block missing padding byte");
}
}
return blocks;
}
}