private long updateOffsetsStep()

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;
    }