org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.imaging.formats.tiff.write;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.common.BinaryOutputStream;
import org.apache.commons.imaging.common.ByteOrder;
import org.apache.commons.imaging.common.RationalNumber;
import org.apache.commons.imaging.formats.tiff.JpegImageData;
import org.apache.commons.imaging.formats.tiff.TiffDirectory;
import org.apache.commons.imaging.formats.tiff.TiffElement;
import org.apache.commons.imaging.formats.tiff.TiffImageData;
import org.apache.commons.imaging.formats.tiff.constants.TagConstantsUtils;
import org.apache.commons.imaging.formats.tiff.constants.TiffConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffDirectoryType;
import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
import org.apache.commons.imaging.formats.tiff.fieldtypes.FieldType;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfo;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoAscii;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoAsciiOrByte;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoAsciiOrRational;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoByte;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoByteOrShort;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoDouble;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoFloat;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoGpsText;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoLong;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoRational;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSByte;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSLong;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSRational;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSShort;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShort;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShortOrLong;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShortOrLongOrRational;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShortOrRational;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoXpString;

public final class TiffOutputDirectory extends TiffOutputItem implements TiffConstants {
    public final int type;
    private final List<TiffOutputField> fields = new ArrayList<TiffOutputField>();
    private final ByteOrder byteOrder;
    private TiffOutputDirectory nextDirectory = null;
    public static final Comparator<TiffOutputDirectory> COMPARATOR = new Comparator<TiffOutputDirectory>() {
        public int compare(final TiffOutputDirectory o1, final TiffOutputDirectory o2) {
            if (o1.type < o2.type) {
                return -1;
            } else if (o1.type > o2.type) {
                return 1;
            } else {
                return 0;
            }
        }
    };

    public void setNextDirectory(final TiffOutputDirectory nextDirectory) {
        this.nextDirectory = nextDirectory;
    }

    public TiffOutputDirectory(final int type, final ByteOrder byteOrder) {
        this.type = type;
        this.byteOrder = byteOrder;
    }

    public void add(final TagInfoByte tagInfo, final byte... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.BYTE,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoAscii tagInfo, final String... values) throws ImageWriteException {
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        if (tagInfo.length > 0 && tagInfo.length != bytes.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " byte(s), not " + values.length);
        }
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.ASCII,
                bytes.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoShort tagInfo, final short... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SHORT,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoLong tagInfo, final int... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.LONG,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoRational tagInfo, final RationalNumber... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.RATIONAL,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoSByte tagInfo, final byte... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SBYTE,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoSShort tagInfo, final short... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SSHORT,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoSLong tagInfo, final int... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SLONG,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoSRational tagInfo, final RationalNumber... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SRATIONAL,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoFloat tagInfo, final float... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.FLOAT,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoDouble tagInfo, final double... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.DOUBLE,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoByteOrShort tagInfo, final byte... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.BYTE,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoByteOrShort tagInfo, final short... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SHORT,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoShortOrLong tagInfo, final short... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SHORT,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoShortOrLong tagInfo, final int... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.LONG,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoShortOrLongOrRational tagInfo, final short... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SHORT,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoShortOrLongOrRational tagInfo, final int... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.LONG,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoShortOrLongOrRational tagInfo, final RationalNumber... values)
            throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.RATIONAL,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoShortOrRational tagInfo, final short... values) throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.SHORT,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoShortOrRational tagInfo, final RationalNumber... values)
            throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(byteOrder, values);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.RATIONAL,
                values.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoGpsText tagInfo, final String value) throws ImageWriteException {
        final byte[] bytes = tagInfo.encodeValue(FieldType.UNDEFINED, value, byteOrder);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, tagInfo.dataTypes.get(0),
                bytes.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoXpString tagInfo, final String value) throws ImageWriteException {
        final byte[] bytes = tagInfo.encodeValue(FieldType.BYTE, value, byteOrder);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.BYTE,
                bytes.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoAsciiOrByte tagInfo, final String... values) throws ImageWriteException {
        final byte[] bytes = tagInfo.encodeValue(FieldType.ASCII, values, byteOrder);
        if (tagInfo.length > 0 && tagInfo.length != bytes.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " byte(s), not " + values.length);
        }
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.ASCII,
                bytes.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoAsciiOrRational tagInfo, final String... values) throws ImageWriteException {
        final byte[] bytes = tagInfo.encodeValue(FieldType.ASCII, values, byteOrder);
        if (tagInfo.length > 0 && tagInfo.length != bytes.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " byte(s), not " + values.length);
        }
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.ASCII,
                bytes.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TagInfoAsciiOrRational tagInfo, final RationalNumber... values)
            throws ImageWriteException {
        if (tagInfo.length > 0 && tagInfo.length != values.length) {
            throw new ImageWriteException("Tag expects " + tagInfo.length + " value(s), not " + values.length);
        }
        final byte[] bytes = tagInfo.encodeValue(FieldType.RATIONAL, values, byteOrder);
        final TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo, FieldType.RATIONAL,
                bytes.length, bytes);
        add(tiffOutputField);
    }

    public void add(final TiffOutputField field) {
        fields.add(field);
    }

    public List<TiffOutputField> getFields() {
        return new ArrayList<TiffOutputField>(fields);
    }

    public void removeField(final TagInfo tagInfo) {
        removeField(tagInfo.tag);
    }

    public void removeField(final int tag) {
        final List<TiffOutputField> matches = new ArrayList<TiffOutputField>();
        for (int i = 0; i < fields.size(); i++) {
            final TiffOutputField field = fields.get(i);
            if (field.tag == tag) {
                matches.add(field);
            }
        }
        fields.removeAll(matches);
    }

    public TiffOutputField findField(final TagInfo tagInfo) {
        return findField(tagInfo.tag);
    }

    public TiffOutputField findField(final int tag) {
        for (int i = 0; i < fields.size(); i++) {
            final TiffOutputField field = fields.get(i);
            if (field.tag == tag) {
                return field;
            }
        }
        return null;
    }

    public void sortFields() {
        final Comparator<TiffOutputField> comparator = new Comparator<TiffOutputField>() {
            public int compare(final TiffOutputField e1, final TiffOutputField e2) {
                if (e1.tag != e2.tag) {
                    return e1.tag - e2.tag;
                }
                return e1.getSortHint() - e2.getSortHint();
            }
        };
        Collections.sort(fields, comparator);
    }

    public String description() {
        return TiffDirectory.description(type);
    }

    @Override
    public void writeItem(final BinaryOutputStream bos) throws IOException, ImageWriteException {
        // Write Directory Field Count
        bos.write2Bytes(fields.size()); // DirectoryFieldCount

        // Write Fields
        for (int i = 0; i < fields.size(); i++) {
            final TiffOutputField field = fields.get(i);
            field.writeField(bos);

            // Debug.debug("\t" + "writing field (" + field.tag + ", 0x" +
            // Integer.toHexString(field.tag) + ")", field.tagInfo);
            // if(field.tagInfo.isOffset())
            // Debug.debug("\t\tOFFSET!", field.bytes);
        }

        long nextDirectoryOffset = 0;
        if (nextDirectory != null) {
            nextDirectoryOffset = nextDirectory.getOffset();
        }

        // Write nextDirectoryOffset
        if (nextDirectoryOffset == UNDEFINED_VALUE) {
            bos.write4Bytes(0);
        } else {
            bos.write4Bytes((int) nextDirectoryOffset);
        }
    }

    private JpegImageData jpegImageData = null;

    public void setJpegImageData(final JpegImageData rawJpegImageData) {
        this.jpegImageData = rawJpegImageData;
    }

    public JpegImageData getRawJpegImageData() {
        return jpegImageData;
    }

    private TiffImageData tiffImageData = null;

    public void setTiffImageData(final TiffImageData rawTiffImageData) {
        this.tiffImageData = rawTiffImageData;
    }

    public TiffImageData getRawTiffImageData() {
        return tiffImageData;
    }

    @Override
    public int getItemLength() {
        return TIFF_ENTRY_LENGTH * fields.size() + TIFF_DIRECTORY_HEADER_LENGTH + TIFF_DIRECTORY_FOOTER_LENGTH;
    }

    @Override
    public String getItemDescription() {
        final TiffDirectoryType dirType = TagConstantsUtils.getExifDirectoryType(type);
        return "Directory: " + dirType.name + " (" + type + ")";
    }

    private void removeFieldIfPresent(final TagInfo tagInfo) {
        final TiffOutputField field = findField(tagInfo);
        if (null != field) {
            fields.remove(field);
        }
    }

    protected List<TiffOutputItem> getOutputItems(final TiffOutputSummary outputSummary)
            throws ImageWriteException {
        // first validate directory fields.

        removeFieldIfPresent(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT);
        removeFieldIfPresent(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);

        TiffOutputField jpegOffsetField = null;
        if (null != jpegImageData) {
            jpegOffsetField = new TiffOutputField(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT, FieldType.LONG,
                    1, new byte[TIFF_ENTRY_MAX_VALUE_LENGTH]);
            add(jpegOffsetField);

            final byte lengthValue[] = FieldType.LONG.writeData(jpegImageData.length, outputSummary.byteOrder);

            final TiffOutputField jpegLengthField = new TiffOutputField(
                    TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, FieldType.LONG, 1, lengthValue);
            add(jpegLengthField);

        }

        // --------------------------------------------------------------

        removeFieldIfPresent(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS);
        removeFieldIfPresent(TiffTagConstants.TIFF_TAG_STRIP_BYTE_COUNTS);
        removeFieldIfPresent(TiffTagConstants.TIFF_TAG_TILE_OFFSETS);
        removeFieldIfPresent(TiffTagConstants.TIFF_TAG_TILE_BYTE_COUNTS);

        TiffOutputField imageDataOffsetField;
        ImageDataOffsets imageDataInfo = null;
        if (null != tiffImageData) {
            final boolean stripsNotTiles = tiffImageData.stripsNotTiles();

            TagInfo offsetTag;
            TagInfo byteCountsTag;
            if (stripsNotTiles) {
                offsetTag = TiffTagConstants.TIFF_TAG_STRIP_OFFSETS;
                byteCountsTag = TiffTagConstants.TIFF_TAG_STRIP_BYTE_COUNTS;
            } else {
                offsetTag = TiffTagConstants.TIFF_TAG_TILE_OFFSETS;
                byteCountsTag = TiffTagConstants.TIFF_TAG_TILE_BYTE_COUNTS;
            }

            // --------

            final TiffElement.DataElement imageData[] = tiffImageData.getImageData();

            int imageDataOffsets[] = null;
            int imageDataByteCounts[] = null;
            // TiffOutputField imageDataOffsetsField = null;

            imageDataOffsets = new int[imageData.length];
            imageDataByteCounts = new int[imageData.length];
            for (int i = 0; i < imageData.length; i++) {
                imageDataByteCounts[i] = imageData[i].length;
            }

            // --------

            // Append imageData-related fields to first directory
            imageDataOffsetField = new TiffOutputField(offsetTag, FieldType.LONG, imageDataOffsets.length,
                    FieldType.LONG.writeData(imageDataOffsets, outputSummary.byteOrder));
            add(imageDataOffsetField);

            // --------

            final byte data[] = FieldType.LONG.writeData(imageDataByteCounts, outputSummary.byteOrder);
            final TiffOutputField byteCountsField = new TiffOutputField(byteCountsTag, FieldType.LONG,
                    imageDataByteCounts.length, data);
            add(byteCountsField);

            // --------

            imageDataInfo = new ImageDataOffsets(imageData, imageDataOffsets, imageDataOffsetField);
        }

        // --------------------------------------------------------------

        final List<TiffOutputItem> result = new ArrayList<TiffOutputItem>();
        result.add(this);
        sortFields();

        for (int i = 0; i < fields.size(); i++) {
            final TiffOutputField field = fields.get(i);
            if (field.isLocalValue()) {
                continue;
            }

            final TiffOutputItem item = field.getSeperateValue();
            result.add(item);
            // outputSummary.add(item, field);
        }

        if (null != imageDataInfo) {
            for (final TiffOutputItem outputItem : imageDataInfo.outputItems) {
                result.add(outputItem);
            }

            outputSummary.addTiffImageData(imageDataInfo);
        }

        if (null != jpegImageData) {
            final TiffOutputItem item = new TiffOutputItem.Value("JPEG image data", jpegImageData.data);
            result.add(item);
            outputSummary.add(item, jpegOffsetField);
        }

        return result;
    }
}