| /* |
| * 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.sanselan.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.sanselan.ImageWriteException; |
| import org.apache.commons.sanselan.common.BinaryOutputStream; |
| import org.apache.commons.sanselan.formats.tiff.JpegImageData; |
| import org.apache.commons.sanselan.formats.tiff.TiffDirectory; |
| import org.apache.commons.sanselan.formats.tiff.TiffElement; |
| import org.apache.commons.sanselan.formats.tiff.TiffImageData; |
| import org.apache.commons.sanselan.formats.tiff.constants.TagConstantsUtils; |
| import org.apache.commons.sanselan.formats.tiff.constants.TagInfo; |
| import org.apache.commons.sanselan.formats.tiff.constants.TiffConstants; |
| import org.apache.commons.sanselan.formats.tiff.fieldtypes.FieldType; |
| |
| public final class TiffOutputDirectory extends TiffOutputItem implements |
| TiffConstants |
| { |
| public final int type; |
| private final ArrayList fields = new ArrayList(); |
| |
| private TiffOutputDirectory nextDirectory = null; |
| |
| public void setNextDirectory(TiffOutputDirectory nextDirectory) |
| { |
| this.nextDirectory = nextDirectory; |
| } |
| |
| public TiffOutputDirectory(final int type) |
| { |
| this.type = type; |
| } |
| |
| public void add(TiffOutputField field) |
| { |
| fields.add(field); |
| } |
| |
| public ArrayList getFields() |
| { |
| return new ArrayList(fields); |
| } |
| |
| public void removeField(TagInfo tagInfo) |
| { |
| removeField(tagInfo.tag); |
| } |
| |
| public void removeField(int tag) |
| { |
| ArrayList matches = new ArrayList(); |
| for (int i = 0; i < fields.size(); i++) |
| { |
| TiffOutputField field = (TiffOutputField) fields.get(i); |
| if (field.tag == tag) |
| matches.add(field); |
| } |
| fields.removeAll(matches); |
| } |
| |
| public TiffOutputField findField(TagInfo tagInfo) |
| { |
| return findField(tagInfo.tag); |
| } |
| |
| public TiffOutputField findField(int tag) |
| { |
| for (int i = 0; i < fields.size(); i++) |
| { |
| TiffOutputField field = (TiffOutputField) fields.get(i); |
| if (field.tag == tag) |
| return field; |
| } |
| return null; |
| } |
| |
| public void sortFields() |
| { |
| Comparator comparator = new Comparator() { |
| public int compare(Object o1, Object o2) |
| { |
| TiffOutputField e1 = (TiffOutputField) o1; |
| TiffOutputField e2 = (TiffOutputField) o2; |
| |
| 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); |
| } |
| |
| public void writeItem(BinaryOutputStream bos) throws IOException, |
| ImageWriteException |
| { |
| // Write Directory Field Count |
| bos.write2Bytes(fields.size()); // DirectoryFieldCount |
| |
| // Write Fields |
| for (int i = 0; i < fields.size(); i++) |
| { |
| TiffOutputField field = (TiffOutputField) 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); |
| } |
| |
| int nextDirectoryOffset = 0; |
| if (nextDirectory != null) |
| nextDirectoryOffset = nextDirectory.getOffset(); |
| |
| // Write nextDirectoryOffset |
| if (nextDirectoryOffset == UNDEFINED_VALUE) |
| bos.write4Bytes(0); |
| else |
| bos.write4Bytes(nextDirectoryOffset); |
| } |
| |
| private JpegImageData jpegImageData = null; |
| |
| public void setJpegImageData(JpegImageData rawJpegImageData) |
| { |
| this.jpegImageData = rawJpegImageData; |
| } |
| |
| public JpegImageData getRawJpegImageData() |
| { |
| return jpegImageData; |
| } |
| |
| private TiffImageData tiffImageData = null; |
| |
| public void setTiffImageData(TiffImageData rawTiffImageData) |
| { |
| this.tiffImageData = rawTiffImageData; |
| } |
| |
| public TiffImageData getRawTiffImageData() |
| { |
| return tiffImageData; |
| } |
| |
| public int getItemLength() |
| { |
| return TIFF_ENTRY_LENGTH * fields.size() + TIFF_DIRECTORY_HEADER_LENGTH |
| + TIFF_DIRECTORY_FOOTER_LENGTH; |
| } |
| |
| public String getItemDescription() |
| { |
| ExifDirectoryType dirType = TagConstantsUtils |
| .getExifDirectoryType(type); |
| return "Directory: " + dirType.name + " (" + type + ")"; |
| } |
| |
| private void removeFieldIfPresent(TagInfo tagInfo) |
| { |
| TiffOutputField field = findField(tagInfo); |
| if (null != field) |
| fields.remove(field); |
| } |
| |
| protected List getOutputItems(TiffOutputSummary outputSummary) |
| throws ImageWriteException |
| { |
| // first validate directory fields. |
| |
| removeFieldIfPresent(TIFF_TAG_JPEG_INTERCHANGE_FORMAT); |
| removeFieldIfPresent(TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); |
| |
| TiffOutputField jpegOffsetField = null; |
| if (null != jpegImageData) |
| { |
| jpegOffsetField = new TiffOutputField( |
| TIFF_TAG_JPEG_INTERCHANGE_FORMAT, FIELD_TYPE_LONG, 1, |
| FieldType.getStubLocalValue()); |
| add(jpegOffsetField); |
| |
| byte lengthValue[] = FIELD_TYPE_LONG.writeData( |
| new int[] { jpegImageData.length, }, |
| outputSummary.byteOrder); |
| |
| TiffOutputField jpegLengthField = new TiffOutputField( |
| TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, FIELD_TYPE_LONG, |
| 1, lengthValue); |
| add(jpegLengthField); |
| |
| } |
| |
| // -------------------------------------------------------------- |
| |
| removeFieldIfPresent(TIFF_TAG_STRIP_OFFSETS); |
| removeFieldIfPresent(TIFF_TAG_STRIP_BYTE_COUNTS); |
| removeFieldIfPresent(TIFF_TAG_TILE_OFFSETS); |
| removeFieldIfPresent(TIFF_TAG_TILE_BYTE_COUNTS); |
| |
| TiffOutputField imageDataOffsetField; |
| ImageDataOffsets imageDataInfo = null; |
| if (null != tiffImageData) |
| { |
| boolean stripsNotTiles = tiffImageData.stripsNotTiles(); |
| |
| TagInfo offsetTag; |
| TagInfo byteCountsTag; |
| if (stripsNotTiles) |
| { |
| offsetTag = TIFF_TAG_STRIP_OFFSETS; |
| byteCountsTag = TIFF_TAG_STRIP_BYTE_COUNTS; |
| } else |
| { |
| offsetTag = TIFF_TAG_TILE_OFFSETS; |
| byteCountsTag = TIFF_TAG_TILE_BYTE_COUNTS; |
| } |
| |
| // -------- |
| |
| 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, |
| FIELD_TYPE_LONG, imageDataOffsets.length, FIELD_TYPE_LONG |
| .writeData(imageDataOffsets, |
| outputSummary.byteOrder)); |
| add(imageDataOffsetField); |
| |
| // -------- |
| |
| byte data[] = FIELD_TYPE_LONG.writeData(imageDataByteCounts, |
| outputSummary.byteOrder); |
| TiffOutputField byteCountsField = new TiffOutputField( |
| byteCountsTag, FIELD_TYPE_LONG, imageDataByteCounts.length, |
| data); |
| add(byteCountsField); |
| |
| // -------- |
| |
| imageDataInfo = new ImageDataOffsets(imageData, imageDataOffsets, |
| imageDataOffsetField); |
| } |
| |
| // -------------------------------------------------------------- |
| |
| List result = new ArrayList(); |
| result.add(this); |
| sortFields(); |
| |
| for (int i = 0; i < fields.size(); i++) |
| { |
| TiffOutputField field = (TiffOutputField) fields.get(i); |
| if (field.isLocalValue()) |
| continue; |
| |
| TiffOutputItem item = field.getSeperateValue(); |
| result.add(item); |
| // outputSummary.add(item, field); |
| } |
| |
| if (null != imageDataInfo) |
| { |
| for (int i = 0; i < imageDataInfo.outputItems.length; i++) |
| result.add(imageDataInfo.outputItems[i]); |
| |
| outputSummary.addTiffImageData(imageDataInfo); |
| } |
| |
| if (null != jpegImageData) |
| { |
| TiffOutputItem item = new TiffOutputItem.Value("JPEG image data", |
| jpegImageData.data); |
| result.add(item); |
| outputSummary.add(item, jpegOffsetField); |
| } |
| |
| return result; |
| } |
| } |