You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by da...@apache.org on 2013/01/31 06:28:15 UTC
svn commit: r1440856 - in /commons/proper/imaging/trunk/src:
main/java/org/apache/commons/imaging/formats/tiff/write/
test/java/org/apache/commons/imaging/formats/jpeg/exif/
Author: damjan
Date: Thu Jan 31 05:28:14 2013
New Revision: 1440856
URL: http://svn.apache.org/viewvc?rev=1440856&view=rev
Log:
Improved EXIF lossless rewriting by allowing some TIFF fields to be frozen
in place (ie. they don't change address in the new file). This saves
a lot of space when rewriting maker notes, since we previously duplicated
them within the already small 64k EXIT size limit.
Modified:
commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffImageWriterLossless.java
commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffOutputField.java
commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/ExifRewriteTest.java
Modified: commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffImageWriterLossless.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffImageWriterLossless.java?rev=1440856&r1=1440855&r2=1440856&view=diff
==============================================================================
--- commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffImageWriterLossless.java (original)
+++ commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffImageWriterLossless.java Thu Jan 31 05:28:14 2013
@@ -21,6 +21,7 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -40,7 +41,6 @@ import org.apache.commons.imaging.format
import org.apache.commons.imaging.formats.tiff.TiffField;
import org.apache.commons.imaging.formats.tiff.TiffImageData;
import org.apache.commons.imaging.formats.tiff.TiffReader;
-import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.imaging.util.Debug;
public class TiffImageWriterLossless extends TiffImageWriterBase {
@@ -87,8 +87,8 @@ public class TiffImageWriterLossless ext
}
Debug.debug();
}
-
- private List<TiffElement> analyzeOldTiff() throws ImageWriteException,
+
+ private List<TiffElement> analyzeOldTiff(Map<Integer,TiffOutputField> frozenFields) throws ImageWriteException,
IOException {
try {
final ByteSource byteSource = new ByteSourceArray(exifBytes);
@@ -108,22 +108,16 @@ public class TiffImageWriterLossless ext
final List<TiffField> fields = directory.getDirectoryEntrys();
for (int f = 0; f < fields.size(); f++) {
final TiffField field = fields.get(f);
- if (field.tag == ExifTagConstants.EXIF_TAG_MAKER_NOTE.tag) {
- // Some maker notes reference values stored
- // inside the maker note itself
- // using addresses relative to the beginning
- // of the TIFF file, making it impossible
- // to move the note to a different location.
- // To avoid corrupting these maker notes,
- // pretend all maker notes are a gap in the file
- // that must be preserved, so the copy that
- // will be written later will reference
- // the old copy's values. Happy days.
- continue;
- }
final TiffElement oversizeValue = field.getOversizeValueElement();
if (oversizeValue != null) {
- elements.add(oversizeValue);
+ final TiffOutputField frozenField = frozenFields.get(field.tag);
+ if (frozenField != null &&
+ frozenField.getSeperateValue() != null &&
+ frozenField.bytesEqual(field.getByteArrayValue())) {
+ frozenField.getSeperateValue().setOffset(field.valueOffset);
+ } else {
+ elements.add(oversizeValue);
+ }
}
}
@@ -146,7 +140,7 @@ public class TiffImageWriterLossless ext
// dumpElements(byteSource, elements);
- final List<TiffElement> result = new ArrayList<TiffElement>();
+ final List<TiffElement> rewritableElements = new ArrayList<TiffElement>();
{
final int TOLERANCE = 3;
// int last = TIFF_HEADER_SIZE;
@@ -159,7 +153,7 @@ public class TiffImageWriterLossless ext
start = element;
index = lastElementByte;
} else if (element.offset - index > TOLERANCE) {
- result.add(new TiffElement.Stub(start.offset, index
+ rewritableElements.add(new TiffElement.Stub(start.offset, index
- start.offset));
start = element;
index = lastElementByte;
@@ -168,14 +162,14 @@ public class TiffImageWriterLossless ext
}
}
if (null != start) {
- result.add(new TiffElement.Stub(start.offset, index
+ rewritableElements.add(new TiffElement.Stub(start.offset, index
- start.offset));
}
}
// dumpElements(byteSource, result);
- return result;
+ return rewritableElements;
} catch (final ImageReadException e) {
throw new ImageWriteException(e.getMessage(), e);
}
@@ -184,13 +178,19 @@ public class TiffImageWriterLossless ext
@Override
public void write(final OutputStream os, final TiffOutputSet outputSet)
throws IOException, ImageWriteException {
- final List<TiffElement> analysis = analyzeOldTiff();
+ // There are some fields whose address in the file must not change,
+ // unless of course their value is changed.
+ final Map<Integer,TiffOutputField> frozenFields = new HashMap<Integer,TiffOutputField>();
+ final TiffOutputField makerNoteField = outputSet.findField(EXIF_TAG_MAKER_NOTE);
+ if (makerNoteField != null && makerNoteField.getSeperateValue() != null) {
+ frozenFields.put(EXIF_TAG_MAKER_NOTE.tag, makerNoteField);
+ }
+ List<TiffElement> analysis = analyzeOldTiff(frozenFields);
final int oldLength = exifBytes.length;
if (analysis.size() < 1) {
throw new ImageWriteException("Couldn't analyze old tiff data.");
} else if (analysis.size() == 1) {
final TiffElement onlyElement = analysis.get(0);
- // Debug.debug("onlyElement", onlyElement.getElementDescription());
if (onlyElement.offset == TIFF_HEADER_SIZE
&& onlyElement.offset + onlyElement.length
+ TIFF_HEADER_SIZE == oldLength) {
@@ -199,19 +199,26 @@ public class TiffImageWriterLossless ext
return;
}
}
-
- // if (true)
- // throw new ImageWriteException("hahah");
-
- // List directories = outputSet.getDirectories();
+ final Map<Integer,TiffOutputField> frozenFieldOffsets = new HashMap<Integer, TiffOutputField>();
+ for (Map.Entry<Integer,TiffOutputField> entry : frozenFields.entrySet()) {
+ final TiffOutputField frozenField = entry.getValue();
+ if (frozenField.getSeperateValue().getOffset() != TiffOutputItem.UNDEFINED_VALUE) {
+ frozenFieldOffsets.put(frozenField.getSeperateValue().getOffset(), frozenField);
+ }
+ }
final TiffOutputSummary outputSummary = validateDirectories(outputSet);
- final List<TiffOutputItem> outputItems = outputSet
+ final List<TiffOutputItem> allOutputItems = outputSet
.getOutputItems(outputSummary);
+ final List<TiffOutputItem> outputItems = new ArrayList<TiffOutputItem>();
+ for (TiffOutputItem outputItem : allOutputItems) {
+ if (!frozenFieldOffsets.containsKey(outputItem.getOffset())) {
+ outputItems.add(outputItem);
+ }
+ }
final int outputLength = updateOffsetsStep(analysis, outputItems);
- // Debug.debug("outputLength", outputLength);
outputSummary.updateOffsets(byteOrder);
@@ -259,9 +266,6 @@ public class TiffImageWriterLossless ext
Collections.sort(unusedElements, ELEMENT_SIZE_COMPARATOR);
Collections.reverse(unusedElements);
- // Debug.debug("unusedElements");
- // dumpElements(unusedElements);
-
// make copy.
final List<TiffOutputItem> unplacedItems = new ArrayList<TiffOutputItem>(
outputItems);
@@ -272,10 +276,6 @@ public class TiffImageWriterLossless ext
// pop off largest unplaced item.
final TiffOutputItem outputItem = unplacedItems.remove(0);
final int outputItemLength = outputItem.getItemLength();
- // Debug.debug("largest unplaced item: "
- // + outputItem.getItemDescription() + " (" + outputItemLength
- // + ")");
-
// search for the smallest possible element large enough to hold the
// item.
TiffElement bestFit = null;
@@ -309,24 +309,6 @@ public class TiffImageWriterLossless ext
}
return overflowIndex;
- //
- // if (true)
- // throw new IOException("mew");
- //
- // // int offset = TIFF_HEADER_SIZE;
- // int offset = exifBytes.length;
- //
- // for (int i = 0; i < outputItems.size(); i++)
- // {
- // TiffOutputItem outputItem = (TiffOutputItem) outputItems.get(i);
- //
- // outputItem.setOffset(offset);
- // int itemLength = outputItem.getItemLength();
- // offset += itemLength;
- //
- // int remainder = imageDataPaddingLength(itemLength);
- // offset += remainder;
- // }
}
private static class BufferOutputStream extends OutputStream {
Modified: commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffOutputField.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffOutputField.java?rev=1440856&r1=1440855&r2=1440856&view=diff
==============================================================================
--- commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffOutputField.java (original)
+++ commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/write/TiffOutputField.java Thu Jan 31 05:28:14 2013
@@ -17,6 +17,7 @@
package org.apache.commons.imaging.formats.tiff.write;
import java.io.IOException;
+import java.util.Arrays;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.common.BinaryOutputStream;
@@ -101,6 +102,10 @@ public class TiffOutputField implements
protected boolean isLocalValue() {
return bytes.length <= TIFF_ENTRY_MAX_VALUE_LENGTH;
}
+
+ public boolean bytesEqual(final byte[] data) {
+ return Arrays.equals(bytes, data);
+ }
protected void setData(final byte bytes[]) throws ImageWriteException {
// if(tagInfo.isUnknown())
Modified: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/ExifRewriteTest.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/ExifRewriteTest.java?rev=1440856&r1=1440855&r2=1440856&view=diff
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/ExifRewriteTest.java (original)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/ExifRewriteTest.java Thu Jan 31 05:28:14 2013
@@ -247,13 +247,6 @@ public class ExifRewriteTest extends Exi
} catch (final ImageWriteException e) {
Debug.debug("imageFile", imageFile.getAbsoluteFile());
Debug.debug(e);
- // FIXME: this image has 28kB of Maker Notes, causing the APP1
- // segment
- // to go beyond 64kB, so ignore the exception this throws.
- if (!imageFile.getName().equalsIgnoreCase(
- "Nikon D50 - 2007.12.19.n.DSC_3656.JPG")) {
- throw e;
- }
}
}