in src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffImageWriterLossless.java [156:231]
private long updateOffsetsStep(final List<AbstractTiffElement> analysis, final List<AbstractTiffOutputItem> outputItems) {
// items we cannot fit into a gap, we shall append to tail.
long overflowIndex = exifBytes.length;
// make copy.
final List<AbstractTiffElement> unusedElements = new ArrayList<>(analysis);
// should already be in order of offset, but make sure.
unusedElements.sort(AbstractTiffElement.COMPARATOR);
Collections.reverse(unusedElements);
// any items that represent a gap at the end of the exif segment, can be
// discarded.
while (!unusedElements.isEmpty()) {
final AbstractTiffElement element = unusedElements.get(0);
final long elementEnd = element.offset + element.length;
if (elementEnd != overflowIndex) {
break;
}
// discarding a tail element. should only happen once.
overflowIndex -= element.length;
unusedElements.remove(0);
}
unusedElements.sort(ELEMENT_SIZE_COMPARATOR);
Collections.reverse(unusedElements);
// make copy.
final List<AbstractTiffOutputItem> unplacedItems = new ArrayList<>(outputItems);
unplacedItems.sort(ITEM_SIZE_COMPARATOR);
Collections.reverse(unplacedItems);
while (!unplacedItems.isEmpty()) {
// pop off largest unplaced item.
final AbstractTiffOutputItem outputItem = unplacedItems.remove(0);
final int outputItemLength = outputItem.getItemLength();
// search for the smallest possible element large enough to hold the
// item.
AbstractTiffElement bestFit = null;
for (final AbstractTiffElement element : unusedElements) {
if (element.length < outputItemLength) {
break;
}
bestFit = element;
}
if (null == bestFit) {
// we couldn't place this item. overflow.
if ((overflowIndex & 1L) != 0) {
overflowIndex += 1;
}
outputItem.setOffset(overflowIndex);
overflowIndex += outputItemLength;
} else {
long offset = bestFit.offset;
int length = bestFit.length;
if ((offset & 1L) != 0) {
// offsets have to be at a multiple of 2
offset += 1;
length -= 1;
}
outputItem.setOffset(offset);
unusedElements.remove(bestFit);
if (length > outputItemLength) {
// not a perfect fit.
final long excessOffset = offset + outputItemLength;
final int excessLength = length - outputItemLength;
unusedElements.add(new AbstractTiffElement.Stub(excessOffset, excessLength));
// make sure the new element is in the correct order.
unusedElements.sort(ELEMENT_SIZE_COMPARATOR);
Collections.reverse(unusedElements);
}
}
}
return overflowIndex;
}