You are viewing a plain text version of this content. The canonical link for it is here.
Posted to sanselan-commits@incubator.apache.org by cm...@apache.org on 2008/01/23 04:45:09 UTC
svn commit: r614420 [1/3] - in /incubator/sanselan/trunk/src:
main/java/org/apache/sanselan/ main/java/org/apache/sanselan/common/
main/java/org/apache/sanselan/common/byteSources/
main/java/org/apache/sanselan/formats/bmp/ main/java/org/apache/sansela...
Author: cmchen
Date: Tue Jan 22 20:44:55 2008
New Revision: 614420
URL: http://svn.apache.org/viewvc?rev=614420&view=rev
Log:
All of the unit tests are passing. I found many bugs and closed them. I've cleaned up a great deal of the code. I've elaborated the exif write functionality and added sample code that demonstrates it.
Added:
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/util/CachingOutputStream.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/GpsTest.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/MakerNoteFieldTest.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/SpecificExifTagTest.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/TextFieldTest.java (with props)
Removed:
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/ExifLosslessRewriteTest.java
Modified:
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/FormatCompliance.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageReadException.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumber.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumberUtilities.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSource.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceArray.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceFile.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceInputStream.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkzTXt.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageMetadata.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffReader.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/ExifTagConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/GPSTagConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagConstantsUtils.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagInfo.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffDirectoryConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffTagConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldType.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldTypeByte.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldTypeDouble.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldTypeFloat.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldTypeLong.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldTypeRational.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldTypeShort.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldTypeUnknown.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/photometricinterpreters/PhotometricInterpreterBiLevel.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/photometricinterpreters/PhotometricInterpreterLogLUV.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterBase.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossless.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputDirectory.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputField.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputItem.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSet.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSummary.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/util/Debug.java
incubator/sanselan/trunk/src/test/data/images/ (props changed)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/SanselanTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/common/RationalNumberTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/common/byteSources/ByteSourceDataTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/common/byteSources/ByteSourceImageTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/common/byteSources/ByteSourceTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/JpegBaseTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/JpegReadTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/ExifBaseTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/ExifDumpTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/ExifRewriteTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/exif/WriteExifMetadataExampleTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/png/PngReadTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/png/PngWriteReadTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/tiff/TiffReadTest.java
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/FormatCompliance.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/FormatCompliance.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/FormatCompliance.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/FormatCompliance.java Tue Jan 22 20:44:55 2008
@@ -43,7 +43,7 @@
{
return new FormatCompliance("ignore", false);
}
-
+
public void addComment(String s) throws ImageReadException
{
comments.add(s);
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java Tue Jan 22 20:44:55 2008
@@ -101,22 +101,28 @@
return getMetadata(new ByteSourceFile(file), params);
}
- public abstract ImageInfo getImageInfo(ByteSource byteSource)
+ public abstract ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException;
- public final ImageInfo getImageInfo(byte bytes[])
+ public final ImageInfo getImageInfo(ByteSource byteSource)
throws ImageReadException, IOException
{
- return getImageInfo(new ByteSourceArray(bytes));
+ return getImageInfo(byteSource, null);
}
- public final ImageInfo getImageInfo(File file) throws ImageReadException,
- IOException
+ public final ImageInfo getImageInfo(byte bytes[], Map params)
+ throws ImageReadException, IOException
+ {
+ return getImageInfo(new ByteSourceArray(bytes), params);
+ }
+
+ public final ImageInfo getImageInfo(File file, Map params)
+ throws ImageReadException, IOException
{
if (!canAcceptExtension(file))
return null;
- return getImageInfo(new ByteSourceFile(file));
+ return getImageInfo(new ByteSourceFile(file), params);
}
public FormatCompliance getFormatCompliance(ByteSource byteSource)
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageReadException.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageReadException.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageReadException.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageReadException.java Tue Jan 22 20:44:55 2008
@@ -24,4 +24,9 @@
{
super(s);
}
+
+ public ImageReadException(String s, Exception e)
+ {
+ super(s, e);
+ }
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java Tue Jan 22 20:44:55 2008
@@ -326,13 +326,33 @@
* <p>
* @param filename String.
* @param bytes Byte array containing an image file.
+ * @param params Map of optional parameters, defined in SanselanConstants.
+ * @return An instance of ImageInfo.
+ * @see ImageInfo
+ */
+ public static ImageInfo getImageInfo(String filename, byte bytes[],
+ Map params) throws ImageReadException, IOException
+ {
+ return getImageInfo(new ByteSourceArray(filename, bytes), params);
+ }
+
+ /**
+ * Parses the "image info" of an image.
+ * <p>
+ * "Image info" is a summary of basic information about the image such as:
+ * width, height, file format, bit depth, color type, etc.
+ * <p>
+ * Not to be confused with "image metadata."
+ * <p>
+ * @param filename String.
+ * @param bytes Byte array containing an image file.
* @return An instance of ImageInfo.
* @see ImageInfo
*/
public static ImageInfo getImageInfo(String filename, byte bytes[])
throws ImageReadException, IOException
{
- return getImageInfo(new ByteSourceArray(filename, bytes));
+ return getImageInfo(new ByteSourceArray(filename, bytes), null);
}
/**
@@ -351,7 +371,27 @@
public static ImageInfo getImageInfo(InputStream is, String filename)
throws ImageReadException, IOException
{
- return getImageInfo(new ByteSourceInputStream(is, filename));
+ return getImageInfo(new ByteSourceInputStream(is, filename), null);
+ }
+
+ /**
+ * Parses the "image info" of an image.
+ * <p>
+ * "Image info" is a summary of basic information about the image such as:
+ * width, height, file format, bit depth, color type, etc.
+ * <p>
+ * Not to be confused with "image metadata."
+ * <p>
+ * @param is InputStream from which to read image data.
+ * @param filename Filename associated with image data (optional).
+ * @param params Map of optional parameters, defined in SanselanConstants.
+ * @return An instance of ImageInfo.
+ * @see ImageInfo
+ */
+ public static ImageInfo getImageInfo(InputStream is, String filename,
+ Map params) throws ImageReadException, IOException
+ {
+ return getImageInfo(new ByteSourceInputStream(is, filename), params);
}
/**
@@ -369,7 +409,45 @@
public static ImageInfo getImageInfo(byte bytes[])
throws ImageReadException, IOException
{
- return getImageInfo(new ByteSourceArray(bytes));
+ return getImageInfo(new ByteSourceArray(bytes), null);
+ }
+
+ /**
+ * Parses the "image info" of an image.
+ * <p>
+ * "Image info" is a summary of basic information about the image such as:
+ * width, height, file format, bit depth, color type, etc.
+ * <p>
+ * Not to be confused with "image metadata."
+ * <p>
+ * @param bytes Byte array containing an image file.
+ * @param params Map of optional parameters, defined in SanselanConstants.
+ * @return An instance of ImageInfo.
+ * @see ImageInfo
+ */
+ public static ImageInfo getImageInfo(byte bytes[], Map params)
+ throws ImageReadException, IOException
+ {
+ return getImageInfo(new ByteSourceArray(bytes), params);
+ }
+
+ /**
+ * Parses the "image info" of an image file.
+ * <p>
+ * "Image info" is a summary of basic information about the image such as:
+ * width, height, file format, bit depth, color type, etc.
+ * <p>
+ * Not to be confused with "image metadata."
+ * <p>
+ * @param file File containing image data.
+ * @param params Map of optional parameters, defined in SanselanConstants.
+ * @return An instance of ImageInfo.
+ * @see ImageInfo
+ */
+ public static ImageInfo getImageInfo(File file, Map params)
+ throws ImageReadException, IOException
+ {
+ return getImageInfo(new ByteSourceFile(file), params);
}
/**
@@ -387,15 +465,15 @@
public static ImageInfo getImageInfo(File file) throws ImageReadException,
IOException
{
- return getImageInfo(new ByteSourceFile(file));
+ return getImageInfo(file, null);
}
- private static ImageInfo getImageInfo(ByteSource byteSource)
+ private static ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
ImageParser imageParser = getImageParser(byteSource);
- ImageInfo imageInfo = imageParser.getImageInfo(byteSource);
+ ImageInfo imageInfo = imageParser.getImageInfo(byteSource, params);
return imageInfo;
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java Tue Jan 22 20:44:55 2008
@@ -63,15 +63,15 @@
public static final String BUFFERED_IMAGE_FACTORY = "BUFFERED_IMAGE_FACTORY";
-// /**
-// * Parameter key. Indicates whether to read embedded thumbnails.
-// * <p>
-// * Only applies to read EXIF metadata from JPEG/JFIF files.
-// * <p>
-// * Valid values: Boolean.TRUE and Boolean.FALSE.
-// * <p>
-// * @see TiffConstants
-// */
-// public static final String PARAM_KEY_READ_THUMBNAILS = "READ_THUMBNAILS";
+ /**
+ * Parameter key. Indicates whether to read embedded thumbnails.
+ * <p>
+ * Only applies to read EXIF metadata from JPEG/JFIF files.
+ * <p>
+ * Valid values: Boolean.TRUE and Boolean.FALSE.
+ * <p>
+ * @see TiffConstants
+ */
+ public static final String PARAM_KEY_READ_THUMBNAILS = "READ_THUMBNAILS";
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java Tue Jan 22 20:44:55 2008
@@ -103,6 +103,18 @@
return true;
}
+ public final byte[] readBytes(InputStream is, int count)
+ throws ImageReadException, IOException
+ {
+ byte result[] = new byte[count];
+ for (int i = 0; i < count; i++)
+ {
+ int data = is.read();
+ result[i] = (byte) data;
+ }
+ return result;
+ }
+
public final void readAndVerifyBytes(InputStream is, byte expected[],
String exception) throws ImageReadException, IOException
{
@@ -115,8 +127,8 @@
{
// System.out.println("i" + ": " + i);
-// this.debugByteArray("expected", expected);
-// debugNumber("data[" + i + "]", b);
+ // this.debugByteArray("expected", expected);
+ // debugNumber("data[" + i + "]", b);
// debugNumber("expected[" + i + "]", expected[i]);
throw new ImageReadException(exception);
@@ -134,9 +146,9 @@
{
if (bytes[i] != expected[i])
{
-// System.out.println("i" + ": " + i);
-// debugNumber("bytes[" + i + "]", bytes[i]);
-// debugNumber("expected[" + i + "]", expected[i]);
+ // System.out.println("i" + ": " + i);
+ // debugNumber("bytes[" + i + "]", bytes[i]);
+ // debugNumber("expected[" + i + "]", expected[i]);
throw new ImageReadException(exception);
}
@@ -408,26 +420,30 @@
}
protected final int convertByteArrayToShort(String name, byte bytes[],
- int byteOrder)
+ int byteOrder) throws ImageReadException
{
return convertByteArrayToShort(name, 0, bytes, byteOrder);
}
- protected final int convertByteArrayToShort(String name, int start,
- byte bytes[], int byteOrder)
+ protected final int convertByteArrayToShort(String name, int index,
+ byte bytes[], int byteOrder) throws ImageReadException
{
- byte byte0 = bytes[start + 0];
- byte byte1 = bytes[start + 1];
+ if (index + 1 >= bytes.length)
+ throw new ImageReadException("Index out of bounds. Array size: "
+ + bytes.length + ", index: " + index);
+
+ int byte0 = 0xff & bytes[index + 0];
+ int byte1 = 0xff & bytes[index + 1];
// return convert2BytesToShort(name, byte0, byte1, byteOrder);
int result;
if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
- result = ((0xff & byte0) << 8) + ((0xff & byte1) << 0);
+ result = (byte0 << 8) | byte1;
else
// intel, little endian
- result = ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
+ result = (byte1 << 8) | byte0;
if (debug)
debugNumber(name, result, 2);
@@ -437,6 +453,8 @@
protected final int[] convertByteArrayToShortArray(String name,
byte bytes[], int start, int length, int byteOrder)
+ throws ImageReadException
+
{
int expectedLength = start + length * 2;
@@ -558,8 +576,8 @@
{
if (a.length != b.length)
{
- System.out.println("length mismatch: " + a.length + " != "
- + b.length);
+// System.out.println("length mismatch: " + a.length + " != "
+// + b.length);
return false;
}
@@ -580,11 +598,36 @@
{
if (a[aStart + i] != b[bStart + i])
{
- debugNumber("\t" + "a[" + (aStart + i) + "]", a[aStart + i]);
- debugNumber("\t" + "b[" + (bStart + i) + "]", b[bStart + i]);
+// debugNumber("\t" + "a[" + (aStart + i) + "]", a[aStart + i]);
+// debugNumber("\t" + "b[" + (bStart + i) + "]", b[bStart + i]);
return false;
}
+ }
+
+ return true;
+ }
+
+ public static final boolean compareBytes(byte a[], byte b[])
+ {
+ if (a.length != b.length)
+ return false;
+
+ return compareBytes(a, 0, b, 0, a.length);
+ }
+
+ public static final boolean compareBytes(byte a[], int aStart, byte b[],
+ int bStart, int length)
+ {
+ if (a.length < (aStart + length))
+ return false;
+ if (b.length < (bStart + length))
+ return false;
+
+ for (int i = 0; i < length; i++)
+ {
+ if (a[aStart + i] != b[bStart + i])
+ return false;
}
return true;
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileParser.java Tue Jan 22 20:44:55 2008
@@ -69,12 +69,13 @@
}
public final int convertByteArrayToShort(String name, byte bytes[])
+ throws ImageReadException
{
return convertByteArrayToShort(name, bytes, byteOrder);
}
public final int convertByteArrayToShort(String name, int start,
- byte bytes[])
+ byte bytes[]) throws ImageReadException
{
return convertByteArrayToShort(name, start, bytes, byteOrder);
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java Tue Jan 22 20:44:55 2008
@@ -71,7 +71,7 @@
this.byteOrder = byteOrder;
}
- protected int getByteOrder()
+ public int getByteOrder()
{
return byteOrder;
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumber.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumber.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumber.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumber.java Tue Jan 22 20:44:55 2008
@@ -19,8 +19,6 @@
import java.text.DecimalFormat;
import java.text.NumberFormat;
-import org.apache.sanselan.util.Debug;
-
public class RationalNumber extends Number
{
private static final long serialVersionUID = -1;
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumberUtilities.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumberUtilities.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumberUtilities.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/RationalNumberUtilities.java Tue Jan 22 20:44:55 2008
@@ -16,7 +16,6 @@
*/
package org.apache.sanselan.common;
-
public abstract class RationalNumberUtilities extends Number
{
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSource.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSource.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSource.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSource.java Tue Jan 22 20:44:55 2008
@@ -45,7 +45,13 @@
public abstract byte[] getAll() throws IOException;
- // public abstract long getLength();
+ /*
+ * This operation can be VERY expensive; for inputstream
+ * byte sources, the entire stream must be drained to
+ * determine its length.
+ */
+ public abstract long getLength() throws IOException;
+
//
// public byte[] getAll() throws IOException
// {
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceArray.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceArray.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceArray.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceArray.java Tue Jan 22 20:44:55 2008
@@ -53,10 +53,10 @@
return result;
}
- // public long getLength()
- // {
- // return bytes.length;
- // }
+ public long getLength()
+ {
+ return bytes.length;
+ }
public byte[] getAll() throws IOException
{
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceFile.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceFile.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceFile.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceFile.java Tue Jan 22 20:44:55 2008
@@ -70,12 +70,10 @@
}
}
- // public long getLength()
- // {
- // // System.out.println("file.length(): " + file.length());
- //
- // return file.length();
- // }
+ public long getLength()
+ {
+ return file.length();
+ }
public byte[] getAll() throws IOException
{
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceInputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceInputStream.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceInputStream.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/byteSources/ByteSourceInputStream.java Tue Jan 22 20:44:55 2008
@@ -185,12 +185,21 @@
}
}
- // public long getLength()
- // {
- // // System.out.println("file.length(): " + file.length());
- //
- // return file.length();
- // }
+ private Long length = null;
+
+ public long getLength() throws IOException
+ {
+ if (length != null)
+ return length.longValue();
+
+ InputStream is = getInputStream();
+ long result = 0;
+ long skipped;
+ while ((skipped = is.skip(1024)) > 0)
+ result += skipped;
+ length = new Long(result);
+ return result;
+ }
public byte[] getAll() throws IOException
{
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java Tue Jan 22 20:44:55 2008
@@ -455,7 +455,7 @@
return "Unknown";
}
- public ImageInfo getImageInfo(ByteSource byteSource)
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
ImageContents ic = readImageContents(byteSource.getInputStream(),
@@ -524,7 +524,7 @@
{
pw.println("bmp.dumpImageFile");
- ImageInfo imageData = getImageInfo(byteSource);
+ ImageInfo imageData = getImageInfo(byteSource, null);
if (imageData == null)
return false;
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java Tue Jan 22 20:44:55 2008
@@ -482,8 +482,8 @@
boolean stop_before_image_data) throws ImageReadException,
IOException
{
- return readFile(byteSource, stop_before_image_data,
- FormatCompliance.getDefault());
+ return readFile(byteSource, stop_before_image_data, FormatCompliance
+ .getDefault());
}
private ImageContents readFile(ByteSource byteSource,
@@ -578,7 +578,7 @@
return result;
}
- public ImageInfo getImageInfo(ByteSource byteSource)
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
ImageContents blocks = readFile(byteSource, false);
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java Tue Jan 22 20:44:55 2008
@@ -85,7 +85,7 @@
return null;
}
- public ImageInfo getImageInfo(ByteSource byteSource)
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
return null;
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java Tue Jan 22 20:44:55 2008
@@ -20,7 +20,18 @@
{
public static final byte JFIF0_SIGNATURE[] = new byte[]{
- (byte) 'J', (byte) 'F', (byte) 'I', (byte) 'F', (byte) 0,
+ 0x4a, // J
+ 0x46, // F
+ 0x49, // I
+ 0x46, // F
+ 0x0, //
+ };
+ public static final byte JFIF0_SIGNATURE_ALTERNATIVE[] = new byte[]{
+ 0x4a, // J
+ 0x46, // F
+ 0x49, // I
+ 0x46, // F
+ 0x20, //
};
public static final byte ExifIdentifierCode[] = {
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java Tue Jan 22 20:44:55 2008
@@ -23,8 +23,8 @@
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.common.ImageMetadata;
-import org.apache.sanselan.formats.tiff.TiffImageData;
import org.apache.sanselan.formats.tiff.TiffField;
+import org.apache.sanselan.formats.tiff.TiffImageData;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.tiff.constants.TagInfo;
import org.apache.sanselan.util.Debug;
@@ -73,7 +73,8 @@
return null;
}
- public BufferedImage getEXIFThumbnail() throws ImageReadException, IOException
+ public BufferedImage getEXIFThumbnail() throws ImageReadException,
+ IOException
{
ArrayList dirs = exif.getDirectories();
for (int i = 0; i < dirs.size(); i++)
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java Tue Jan 22 20:44:55 2008
@@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.sanselan.ImageFormat;
@@ -43,9 +44,13 @@
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.tiff.TiffImageParser;
+import org.apache.sanselan.formats.tiff.constants.TiffTagConstants;
import org.apache.sanselan.util.Debug;
-public class JpegImageParser extends ImageParser implements JpegConstants
+public class JpegImageParser extends ImageParser
+ implements
+ JpegConstants,
+ TiffTagConstants
{
public JpegImageParser()
{
@@ -130,11 +135,16 @@
if (marker == 0xffd9)
return false;
+ // Debug.debug("visitSegment marker", marker);
+ //// Debug.debug("visitSegment keepMarker(marker, markers)", keepMarker(marker, markers));
+ // Debug.debug("visitSegment keepMarker(marker, markers)", keepMarker(marker, markers));
+
if (!keepMarker(marker, markers))
return true;
if (marker == JPEG_APP13_Marker)
{
+ // Debug.debug("app 13 segment data", segmentData.length);
result.add(new App13Segment(parser, marker, segmentData));
}
else if (marker == JPEG_APP2_Marker)
@@ -332,6 +342,21 @@
return result;
}
+ private ArrayList filterSegments(ArrayList v, List markers)
+ {
+ ArrayList result = new ArrayList();
+
+ for (int i = 0; i < v.size(); i++)
+ {
+ Segment segment = (Segment) v.get(i);
+ Integer marker = new Integer(segment.marker);
+ if (markers.contains(marker))
+ result.add(segment);
+ }
+
+ return result;
+ }
+
public TiffImageMetadata getExifMetadata(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
@@ -339,10 +364,14 @@
if (null == bytes)
return null;
- if(params==null)
+ if (params == null)
params = new HashMap();
-// if (!params.containsKey(PARAM_KEY_READ_THUMBNAILS))
-// params.put(PARAM_KEY_READ_THUMBNAILS, Boolean.TRUE);
+ if (!params.containsKey(PARAM_KEY_READ_THUMBNAILS))
+ params.put(PARAM_KEY_READ_THUMBNAILS, Boolean.TRUE);
+
+ // Debug.debug("read thumbs?", params.get(PARAM_KEY_READ_THUMBNAILS));
+
+ // Debug.debug("exif bytes", bytes.length);
return (TiffImageMetadata) new TiffImageParser().getMetadata(bytes,
params);
@@ -363,7 +392,12 @@
System.out.println("exif_segments.size" + ": "
+ exifSegments.size());
+ // Debug.debug("segments", segments);
+ // Debug.debug("exifSegments", exifSegments);
+
// TODO: concatenate if multiple segments, need example.
+ if (exifSegments.size() < 1)
+ return null;
if (exifSegments.size() > 1)
throw new ImageReadException(
"Sanselan currently can't parse EXIF metadata split across multiple APP1 segments. "
@@ -379,6 +413,52 @@
return getByteArrayTail("trimmed exif bytes", bytes, 6);
}
+ public boolean hasExifSegment(ByteSource byteSource)
+ throws ImageReadException, IOException
+ {
+ final boolean result[] = {
+ false,
+ };
+
+ JpegUtils.Visitor visitor = new JpegUtils.Visitor()
+ {
+ // return false to exit before reading image data.
+ public boolean beginSOS()
+ {
+ return false;
+ }
+
+ public void visitSOS(int marker, byte markerBytes[],
+ byte imageData[])
+ {
+ }
+
+ // return false to exit traversal.
+ public boolean visitSegment(int marker, byte markerBytes[],
+ int markerLength, byte markerLengthBytes[],
+ byte segmentData[]) throws ImageReadException, IOException
+ {
+ if (marker == 0xffd9)
+ return false;
+
+ if (marker == JPEG_APP1_Marker)
+ {
+ if (byteArrayHasPrefix(segmentData, ExifIdentifierCode))
+ {
+ result[0] = true;
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+
+ new JpegUtils().traverseJFIF(byteSource, visitor);
+
+ return result[0];
+ }
+
private JpegImageMetadata.Photoshop getPhotoshopMetadata(
ByteSource byteSource) throws ImageReadException, IOException
{
@@ -441,9 +521,10 @@
return false;
}
- public ImageInfo getImageInfo(ByteSource byteSource)
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
+ // ArrayList allSegments = readSegments(byteSource, null, false);
ArrayList SOF_segments = readSegments(byteSource, new int[]{
// kJFIFMarker,
@@ -461,7 +542,7 @@
// System.out.println("Incoherent SOFN Data Found: "
// + SOF_segments.size());
- ArrayList JFIF_segments = readSegments(byteSource, new int[]{
+ ArrayList jfifSegments = readSegments(byteSource, new int[]{
JFIFMarker,
}, true);
@@ -474,10 +555,10 @@
int Width = fSOFNSegment.width;
int Height = fSOFNSegment.height;
- JFIFSegment fTheJFIFSegment = null;
+ JFIFSegment jfifSegment = null;
- if ((JFIF_segments != null) && (JFIF_segments.size() > 0))
- fTheJFIFSegment = (JFIFSegment) JFIF_segments.get(0);
+ if ((jfifSegments != null) && (jfifSegments.size() > 0))
+ jfifSegment = (JFIFSegment) jfifSegments.get(0);
// JFIFSegment fTheJFIFSegment = (JFIFSegment) findSegment(segments,
// kJFIFMarker);
@@ -489,16 +570,16 @@
// int JFIF_minor_version;
String FormatDetails;
- if (fTheJFIFSegment != null)
+ if (jfifSegment != null)
{
- x_density = fTheJFIFSegment.xDensity;
- y_density = fTheJFIFSegment.yDensity;
- int density_units = fTheJFIFSegment.densityUnits;
+ x_density = jfifSegment.xDensity;
+ y_density = jfifSegment.yDensity;
+ int density_units = jfifSegment.densityUnits;
// JFIF_major_version = fTheJFIFSegment.JFIF_major_version;
// JFIF_minor_version = fTheJFIFSegment.JFIF_minor_version;
- FormatDetails = "Jpeg/JFIF v." + fTheJFIFSegment.jfifMajorVersion
- + "." + fTheJFIFSegment.jfifMinorVersion;
+ FormatDetails = "Jpeg/JFIF v." + jfifSegment.jfifMajorVersion + "."
+ + jfifSegment.jfifMinorVersion;
switch (density_units)
{
@@ -516,46 +597,47 @@
}
else
{
- JpegImageMetadata metadata = (JpegImageMetadata) getMetadata(byteSource);
-
- {
- TiffField field = metadata
- .findEXIFValue(TiffField.TIFF_TAG_XRESOLUTION);
- if (field == null)
- throw new ImageReadException("No XResolution");
-
- x_density = ((Number) field.getValue()).doubleValue();
- }
- {
- TiffField field = metadata
- .findEXIFValue(TiffField.TIFF_TAG_YRESOLUTION);
- if (field == null)
- throw new ImageReadException("No YResolution");
+ JpegImageMetadata metadata = (JpegImageMetadata) getMetadata(
+ byteSource, params);
- y_density = ((Number) field.getValue()).doubleValue();
- }
+ if (metadata != null)
{
- TiffField field = metadata
- .findEXIFValue(TiffField.TIFF_TAG_RESOLUTION_UNIT);
- if (field == null)
- throw new ImageReadException("No ResolutionUnits");
-
- int density_units = ((Number) field.getValue()).intValue();
-
- switch (density_units)
{
- case 1 :
- break;
- case 2 : // inches
- units_per_inch = 1.0;
- break;
- case 3 : // cms
- units_per_inch = 2.54;
- break;
- default :
- break;
+ TiffField field = metadata
+ .findEXIFValue(TIFF_TAG_XRESOLUTION);
+ if (field != null)
+ x_density = ((Number) field.getValue()).doubleValue();
+ }
+ {
+ TiffField field = metadata
+ .findEXIFValue(TIFF_TAG_YRESOLUTION);
+ if (field != null)
+ y_density = ((Number) field.getValue()).doubleValue();
}
+ {
+ TiffField field = metadata
+ .findEXIFValue(TIFF_TAG_RESOLUTION_UNIT);
+ if (field != null)
+ {
+ int density_units = ((Number) field.getValue())
+ .intValue();
+
+ switch (density_units)
+ {
+ case 1 :
+ break;
+ case 2 : // inches
+ units_per_inch = 1.0;
+ break;
+ case 3 : // cms
+ units_per_inch = 2.54;
+ break;
+ default :
+ break;
+ }
+ }
+ }
}
FormatDetails = "Jpeg/DCM";
@@ -581,14 +663,14 @@
// TODO: comments...
int Number_of_components = fSOFNSegment.numberOfComponents;
- int Precision = fSOFNSegment.Precision;
+ int Precision = fSOFNSegment.precision;
int BitsPerPixel = Number_of_components * Precision;
ImageFormat Format = ImageFormat.IMAGE_FORMAT_JPEG;
String FormatName = "JPEG (Joint Photographic Experts Group) Format";
String MimeType = "image/jpeg";
// we ought to count images, but don't yet.
- int NumberOfImages = -1;
+ int NumberOfImages = 1;
// not accurate ... only reflects first
boolean isProgressive = fSOFNSegment.marker == SOF2Marker;
@@ -614,6 +696,172 @@
return result;
}
+
+ // public ImageInfo getImageInfo(ByteSource byteSource, Map params)
+ // throws ImageReadException, IOException
+ // {
+ //
+ // ArrayList allSegments = readSegments(byteSource, null, false);
+ //
+ // final int SOF_MARKERS[] = new int[]{
+ // SOF0Marker, SOF1Marker, SOF2Marker, SOF3Marker, SOF5Marker,
+ // SOF6Marker, SOF7Marker, SOF9Marker, SOF10Marker, SOF11Marker,
+ // SOF13Marker, SOF14Marker, SOF15Marker,
+ // };
+ //
+ // ArrayList sofMarkers = new ArrayList();
+ // for(int i=0;i<SOF_MARKERS.length;i++)
+ // sofMarkers.add(new Integer(SOF_MARKERS[i]));
+ // ArrayList SOFSegments = filterSegments(allSegments, sofMarkers);
+ // if (SOFSegments == null || SOFSegments.size()<1)
+ // throw new ImageReadException("No SOFN Data Found.");
+ //
+ // List jfifMarkers = new ArrayList();
+ // jfifMarkers.add(new Integer(JFIFMarker));
+ // ArrayList jfifSegments = filterSegments(allSegments, jfifMarkers);
+ //
+ // SOFNSegment firstSOFNSegment = (SOFNSegment) SOFSegments.get(0);
+ //
+ // int Width = firstSOFNSegment.width;
+ // int Height = firstSOFNSegment.height;
+ //
+ // JFIFSegment jfifSegment = null;
+ //
+ // if (jfifSegments != null && jfifSegments.size() > 0)
+ // jfifSegment = (JFIFSegment) jfifSegments.get(0);
+ //
+ // double x_density = -1.0;
+ // double y_density = -1.0;
+ // double units_per_inch = -1.0;
+ // // int JFIF_major_version;
+ // // int JFIF_minor_version;
+ // String FormatDetails;
+ //
+ // if (jfifSegment != null)
+ // {
+ // x_density = jfifSegment.xDensity;
+ // y_density = jfifSegment.yDensity;
+ // int density_units = jfifSegment.densityUnits;
+ // // JFIF_major_version = fTheJFIFSegment.JFIF_major_version;
+ // // JFIF_minor_version = fTheJFIFSegment.JFIF_minor_version;
+ //
+ // FormatDetails = "Jpeg/JFIF v." + jfifSegment.jfifMajorVersion
+ // + "." + jfifSegment.jfifMinorVersion;
+ //
+ // switch (density_units)
+ // {
+ // case 0 :
+ // break;
+ // case 1 : // inches
+ // units_per_inch = 1.0;
+ // break;
+ // case 2 : // cms
+ // units_per_inch = 2.54;
+ // break;
+ // default :
+ // break;
+ // }
+ // }
+ // else
+ // {
+ // JpegImageMetadata metadata = (JpegImageMetadata) getMetadata(byteSource, params);
+ //
+ // {
+ // TiffField field = metadata
+ // .findEXIFValue(TiffField.TIFF_TAG_XRESOLUTION);
+ // if (field == null)
+ // throw new ImageReadException("No XResolution");
+ //
+ // x_density = ((Number) field.getValue()).doubleValue();
+ // }
+ // {
+ // TiffField field = metadata
+ // .findEXIFValue(TiffField.TIFF_TAG_YRESOLUTION);
+ // if (field == null)
+ // throw new ImageReadException("No YResolution");
+ //
+ // y_density = ((Number) field.getValue()).doubleValue();
+ // }
+ // {
+ // TiffField field = metadata
+ // .findEXIFValue(TiffField.TIFF_TAG_RESOLUTION_UNIT);
+ // if (field == null)
+ // throw new ImageReadException("No ResolutionUnits");
+ //
+ // int density_units = ((Number) field.getValue()).intValue();
+ //
+ // switch (density_units)
+ // {
+ // case 1 :
+ // break;
+ // case 2 : // inches
+ // units_per_inch = 1.0;
+ // break;
+ // case 3 : // cms
+ // units_per_inch = 2.54;
+ // break;
+ // default :
+ // break;
+ // }
+ //
+ // }
+ //
+ // FormatDetails = "Jpeg/DCM";
+ //
+ // }
+ //
+ // int PhysicalHeightDpi = -1;
+ // float PhysicalHeightInch = -1;
+ // int PhysicalWidthDpi = -1;
+ // float PhysicalWidthInch = -1;
+ //
+ // if (units_per_inch > 0)
+ // {
+ // PhysicalWidthDpi = (int) Math.round((double) x_density
+ // / units_per_inch);
+ // PhysicalWidthInch = (float) ((double) Width / (x_density * units_per_inch));
+ // PhysicalHeightDpi = (int) Math.round((double) y_density
+ // * units_per_inch);
+ // PhysicalHeightInch = (float) ((double) Height / (y_density * units_per_inch));
+ // }
+ //
+ // ArrayList Comments = new ArrayList();
+ // // TODO: comments...
+ //
+ // int Number_of_components = firstSOFNSegment.numberOfComponents;
+ // int Precision = firstSOFNSegment.precision;
+ //
+ // int BitsPerPixel = Number_of_components * Precision;
+ // ImageFormat Format = ImageFormat.IMAGE_FORMAT_JPEG;
+ // String FormatName = "JPEG (Joint Photographic Experts Group) Format";
+ // String MimeType = "image/jpeg";
+ // // we ought to count images, but don't yet.
+ // int NumberOfImages = -1;
+ // // not accurate ... only reflects first
+ // boolean isProgressive = firstSOFNSegment.marker == SOF2Marker;
+ //
+ // boolean isTransparent = false; // TODO: inaccurate.
+ // boolean usesPalette = false; // TODO: inaccurate.
+ // int ColorType;
+ // if (Number_of_components == 1)
+ // ColorType = ImageInfo.COLOR_TYPE_BW;
+ // else if (Number_of_components == 3)
+ // ColorType = ImageInfo.COLOR_TYPE_RGB;
+ // else if (Number_of_components == 4)
+ // ColorType = ImageInfo.COLOR_TYPE_CMYK;
+ // else
+ // ColorType = ImageInfo.COLOR_TYPE_UNKNOWN;
+ //
+ // String compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_JPEG;
+ //
+ // ImageInfo result = new ImageInfo(FormatDetails, BitsPerPixel, Comments,
+ // Format, FormatName, Height, MimeType, NumberOfImages,
+ // PhysicalHeightDpi, PhysicalHeightInch, PhysicalWidthDpi,
+ // PhysicalWidthInch, Width, isProgressive, isTransparent,
+ // usesPalette, ColorType, compressionAlgorithm);
+ //
+ // return result;
+ // }
public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource)
throws ImageReadException, IOException
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java Tue Jan 22 20:44:55 2008
@@ -89,6 +89,8 @@
markerLength - 2, is,
"Invalid Segment: insufficient data");
+ // Debug.debug("markerLength", markerLength);
+
if (!visitor.visitSegment(marker, markerBytes, markerLength,
markerLengthBytes, segmentData))
return;
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.java Tue Jan 22 20:44:55 2008
@@ -22,6 +22,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.List;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.ImageWriteException;
@@ -32,8 +33,6 @@
import org.apache.sanselan.common.byteSources.ByteSourceInputStream;
import org.apache.sanselan.formats.jpeg.JpegConstants;
import org.apache.sanselan.formats.jpeg.JpegUtils;
-import org.apache.sanselan.formats.jpeg.segments.GenericSegment;
-import org.apache.sanselan.formats.jpeg.segments.UnknownSegment;
import org.apache.sanselan.formats.tiff.write.TiffImageWriterBase;
import org.apache.sanselan.formats.tiff.write.TiffImageWriterLossless;
import org.apache.sanselan.formats.tiff.write.TiffImageWriterLossy;
@@ -72,14 +71,73 @@
private static class JFIFPieces
{
- public final ArrayList pieces;
- public final GenericSegment exifSegment;
+ public final List pieces;
+ public final List exifPieces;
- public JFIFPieces(final ArrayList pieces,
- final GenericSegment exifSegment)
+ public JFIFPieces(final List pieces, final List exifPieces)
{
this.pieces = pieces;
- this.exifSegment = exifSegment;
+ this.exifPieces = exifPieces;
+ }
+
+ }
+
+ private abstract static class JFIFPiece
+ {
+ protected abstract void write(OutputStream os) throws IOException;
+ }
+
+ private static class JFIFPieceSegment extends JFIFPiece
+ {
+ public final int marker;
+ public final byte markerBytes[];
+ public final byte markerLengthBytes[];
+ public final byte segmentData[];
+
+ public JFIFPieceSegment(final int marker, final byte[] markerBytes,
+ final byte[] markerLengthBytes, final byte[] segmentData)
+ {
+ this.marker = marker;
+ this.markerBytes = markerBytes;
+ this.markerLengthBytes = markerLengthBytes;
+ this.segmentData = segmentData;
+ }
+
+ protected void write(OutputStream os) throws IOException
+ {
+ os.write(markerBytes);
+ os.write(markerLengthBytes);
+ os.write(segmentData);
+ }
+ }
+
+ private static class JFIFPieceSegmentExif extends JFIFPieceSegment
+ {
+
+ public JFIFPieceSegmentExif(final int marker, final byte[] markerBytes,
+ final byte[] markerLengthBytes, final byte[] segmentData)
+ {
+ super(marker, markerBytes, markerLengthBytes, segmentData);
+ }
+ }
+
+ private static class JFIFPieceImageData extends JFIFPiece
+ {
+ public final byte markerBytes[];
+ public final byte imageData[];
+
+ public JFIFPieceImageData(final byte[] markerBytes,
+ final byte[] imageData)
+ {
+ super();
+ this.markerBytes = markerBytes;
+ this.imageData = imageData;
+ }
+
+ protected void write(OutputStream os) throws IOException
+ {
+ os.write(markerBytes);
+ os.write(imageData);
}
}
@@ -88,9 +146,7 @@
// , ImageWriteException
{
final ArrayList pieces = new ArrayList();
- final GenericSegment exifSegmentArray[] = new GenericSegment[]{
- null,
- };
+ final List exifPieces = new ArrayList();
JpegUtils.Visitor visitor = new JpegUtils.Visitor()
{
@@ -103,8 +159,7 @@
public void visitSOS(int marker, byte markerBytes[],
byte imageData[])
{
- pieces.add(markerBytes);
- pieces.add(imageData);
+ pieces.add(new JFIFPieceImageData(markerBytes, imageData));
}
// return false to exit traversal.
@@ -116,29 +171,26 @@
{
if (marker != JPEG_APP1_Marker)
{
- pieces.add(markerBytes);
- pieces.add(markerLengthBytes);
- pieces.add(segmentData);
+ pieces.add(new JFIFPieceSegment(marker, markerBytes,
+ markerLengthBytes, segmentData));
}
else if (!byteArrayHasPrefix(segmentData, ExifIdentifierCode))
{
- pieces.add(markerBytes);
- pieces.add(markerLengthBytes);
- pieces.add(segmentData);
- }
- else if (exifSegmentArray[0] != null)
- {
- // TODO: add support for multiple segments
- throw new ImageReadException(
- "More than one APP1 EXIF segment.");
+ pieces.add(new JFIFPieceSegment(marker, markerBytes,
+ markerLengthBytes, segmentData));
}
+ // else if (exifSegmentArray[0] != null)
+ // {
+ // // TODO: add support for multiple segments
+ // throw new ImageReadException(
+ // "More than one APP1 EXIF segment.");
+ // }
else
{
- UnknownSegment segment = new UnknownSegment(marker,
- segmentData);
-
- exifSegmentArray[0] = segment;
- pieces.add(segment);
+ JFIFPiece piece = new JFIFPieceSegmentExif(marker,
+ markerBytes, markerLengthBytes, segmentData);
+ pieces.add(piece);
+ exifPieces.add(piece);
}
return true;
}
@@ -146,14 +198,14 @@
new JpegUtils().traverseJFIF(byteSource, visitor);
- GenericSegment exifSegment = exifSegmentArray[0];
- if (exifSegment == null)
- {
- // TODO: add support for adding, not just replacing.
- throw new ImageReadException("No APP1 EXIF segment found.");
- }
+ // GenericSegment exifSegment = exifSegmentArray[0];
+ // if (exifSegments.size() < 1)
+ // {
+ // // TODO: add support for adding, not just replacing.
+ // throw new ImageReadException("No APP1 EXIF segment found.");
+ // }
- return new JFIFPieces(pieces, exifSegment);
+ return new JFIFPieces(pieces, exifPieces);
}
/**
@@ -214,9 +266,13 @@
throws ImageReadException, IOException, ImageWriteException
{
JFIFPieces jfifPieces = analyzeJFIF(byteSource);
- ArrayList pieces = jfifPieces.pieces;
+ List pieces = jfifPieces.pieces;
- pieces.remove(jfifPieces.exifSegment);
+ // Debug.debug("pieces", pieces);
+
+ // pieces.removeAll(jfifPieces.exifSegments);
+
+ // Debug.debug("pieces", pieces);
writeSegmentsReplacingExif(os, pieces, null);
}
@@ -303,10 +359,16 @@
{
// List outputDirectories = outputSet.getDirectories();
JFIFPieces jfifPieces = analyzeJFIF(byteSource);
- ArrayList pieces = jfifPieces.pieces;
- GenericSegment exifSegment = jfifPieces.exifSegment;
+ List pieces = jfifPieces.pieces;
+
+ JFIFPieceSegment exifPiece = null;
+
+ // Just use first APP1 segment for now.
+ // Multiple APP1 segments are rare and poorly supported.
+ if (jfifPieces.exifPieces.size() > 0)
+ exifPiece = (JFIFPieceSegment) jfifPieces.exifPieces.get(0);
- byte exifBytes[] = exifSegment.bytes;
+ byte exifBytes[] = exifPiece.segmentData;
exifBytes = getByteArrayTail("trimmed exif bytes", exifBytes, 6);
TiffImageWriterBase writer = new TiffImageWriterLossless(
@@ -387,7 +449,7 @@
ImageWriteException
{
JFIFPieces jfifPieces = analyzeJFIF(byteSource);
- ArrayList pieces = jfifPieces.pieces;
+ List pieces = jfifPieces.pieces;
TiffImageWriterBase writer = new TiffImageWriterLossy(
outputSet.byteOrder);
@@ -398,9 +460,8 @@
writeSegmentsReplacingExif(os, pieces, newBytes);
}
- private void writeSegmentsReplacingExif(OutputStream os,
- ArrayList segments, byte newBytes[]) throws ImageWriteException,
- IOException
+ private void writeSegmentsReplacingExif(OutputStream os, List segments,
+ byte newBytes[]) throws ImageWriteException, IOException
{
int byteOrder = getByteOrder();
@@ -408,33 +469,67 @@
{
os.write(SOI);
+ boolean hasExif = false;
+
for (int i = 0; i < segments.size(); i++)
{
- Object o = segments.get(i);
- if (o instanceof byte[])
- {
- byte bytes[] = (byte[]) o;
- os.write(bytes);
- }
- else if (o instanceof GenericSegment)
+ JFIFPiece piece = (JFIFPiece) segments.get(i);
+ if (piece instanceof JFIFPieceSegmentExif)
+ hasExif = true;
+ }
+
+ if (!hasExif && newBytes != null)
+ {
+ byte markerBytes[] = convertShortToByteArray(JPEG_APP1_Marker,
+ byteOrder);
+ if (newBytes.length > 0xffff)
+ throw new ExifOverflowException(
+ "APP1 Segment is too long: " + newBytes.length);
+ int markerLength = newBytes.length + 2;
+ byte markerLengthBytes[] = convertShortToByteArray(
+ markerLength, byteOrder);
+
+ int index = 0;
+ JFIFPieceSegment firstSegment = (JFIFPieceSegment) segments
+ .get(index);
+ if (firstSegment.marker == JFIFMarker)
+ index = 1;
+ segments.add(0, new JFIFPieceSegmentExif(JPEG_APP1_Marker,
+ markerBytes, markerLengthBytes, newBytes));
+ }
+
+ boolean APP1Written = false;
+
+ for (int i = 0; i < segments.size(); i++)
+ {
+ JFIFPiece piece = (JFIFPiece) segments.get(i);
+ if (piece instanceof JFIFPieceSegmentExif)
{
+ // only replace first APP1 segment; skips others.
+ if (APP1Written)
+ continue;
+ APP1Written = true;
+
+ if (newBytes == null)
+ continue;
+
byte markerBytes[] = convertShortToByteArray(
JPEG_APP1_Marker, byteOrder);
- os.write(markerBytes);
-
if (newBytes.length > 0xffff)
throw new ExifOverflowException(
"APP1 Segment is too long: " + newBytes.length);
-
int markerLength = newBytes.length + 2;
byte markerLengthBytes[] = convertShortToByteArray(
markerLength, byteOrder);
- os.write(markerLengthBytes);
+ os.write(markerBytes);
+ os.write(markerLengthBytes);
os.write(newBytes);
}
else
- throw new ImageWriteException("Unknown data: " + o);
+ {
+ piece.write(os);
+ }
}
}
finally
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java Tue Jan 22 20:44:55 2008
@@ -45,10 +45,6 @@
super(marker, marker_length, is);
this.parser = parser;
- // InputStream bais = new ByteArrayInputStream(bytes);
- // dump();
-
- // Debug.debug("bytes", bytes);
boolean verbose = false;
if (!compareByteArrays(bytes, 0,
@@ -72,7 +68,7 @@
int segmentType = convertByteArrayToShort("SegmentType", index,
bytes);
if (verbose)
- debugNumber("SegmentType", segmentType, 2);
+ debugNumber("segmentType", segmentType, 2);
index += 2;
// padding
@@ -81,21 +77,19 @@
int segmentSize = convertByteArrayToShort("SegmentSize", index,
bytes);
if (verbose)
- debugNumber("fSegmentSize", segmentSize, 2);
+ debugNumber("segmentSize", segmentSize, 2);
index += 2;
int index2 = index;
index += segmentSize;
- if ((segmentSize % 2) != 0)
- index++;
- while (index2 < index)
+ while (index2 + 1 < index)
{
int iptcPrefix = convertByteArrayToShort("IPTCPrefix", index2,
bytes);
if (verbose)
- debugNumber("fIPTCPrefix", iptcPrefix, 2);
+ debugNumber("IPTCPrefix", iptcPrefix, 2);
index2 += 2;
if (iptcPrefix == 0x1c02)
@@ -131,6 +125,8 @@
elements.add(element);
}
+ if ((segmentSize % 2) != 0)
+ index++;
}
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java Tue Jan 22 20:44:55 2008
@@ -57,7 +57,7 @@
}
else
{
- debugByteArray("Unknown APP2 Segment Type", bytes);
+ // debugByteArray("Unknown APP2 Segment Type", bytes);
cur_marker = -1;
num_markers = -1;
icc_bytes = null;
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java Tue Jan 22 20:44:55 2008
@@ -23,7 +23,7 @@
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.formats.jpeg.JpegConstants;
-public class JFIFSegment extends Segment
+public class JFIFSegment extends Segment implements JpegConstants
{
public final int jfifMajorVersion;
public final int jfifMinorVersion;
@@ -51,8 +51,11 @@
{
super(marker, marker_length);
- readAndVerifyBytes(is, JpegConstants.JFIF0_SIGNATURE,
- "Not a Valid JPEG File: missing JFIF string");
+ byte signature[] = readBytes(is, JFIF0_SIGNATURE.length);
+ if (!compareByteArrays(signature, JFIF0_SIGNATURE)
+ && !compareByteArrays(signature, JFIF0_SIGNATURE_ALTERNATIVE))
+ throw new ImageReadException(
+ "Not a Valid JPEG File: missing JFIF string");
jfifMajorVersion = readByte("JFIF_major_version", is,
"Not a Valid JPEG File");
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java Tue Jan 22 20:44:55 2008
@@ -27,7 +27,7 @@
{
public final int width, height;
public final int numberOfComponents;
- public final int Precision;
+ public final int precision;
public SOFNSegment(int marker, byte segmentData[])
throws ImageReadException, IOException
@@ -44,7 +44,7 @@
System.out.println("SOF0Segment marker_length: " + marker_length);
{
- Precision = readByte("Data_precision", is, "Not a Valid JPEG File");
+ precision = readByte("Data_precision", is, "Not a Valid JPEG File");
height = read2Bytes("Image_height", is, "Not a Valid JPEG File");
width = read2Bytes("Image_Width", is, "Not a Valid JPEG File");
numberOfComponents = readByte("Number_of_components", is,
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java Tue Jan 22 20:44:55 2008
@@ -39,6 +39,11 @@
public abstract String getDescription();
+ public String toString()
+ {
+ return "[Segment: " + getDescription() + "]";
+ }
+
public String getSegmentType()
{
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java Tue Jan 22 20:44:55 2008
@@ -459,7 +459,7 @@
}
}
- public ImageInfo getImageInfo(ByteSource byteSource)
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
ArrayList chunks = readChunks(byteSource, new int[]{
@@ -746,7 +746,7 @@
// throw new ImageReadException("PNG: unknown bit depth: " + BitDepth);
// }
-// ColorModel cm = null;
+ // ColorModel cm = null;
int samplesPerPixel = samplesPerPixel(pngChunkIHDR.colorType);
boolean isGrayscale = isGrayscale(pngChunkIHDR.colorType);
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java Tue Jan 22 20:44:55 2008
@@ -94,7 +94,7 @@
public abstract void drive() throws ImageReadException, IOException;
-// private long count = 0;
+ // private long count = 0;
protected int getRGB(BitParser bitParser, int pixel_index_in_scanline)
throws ImageReadException, IOException
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkzTXt.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkzTXt.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkzTXt.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkzTXt.java Tue Jan 22 20:44:55 2008
@@ -43,7 +43,7 @@
System.arraycopy(bytes, 0, Keyword_bytes, 0, index);
Keyword = new String(Keyword_bytes);
-// int CompressionMethod = bytes[index + 1];
+ // int CompressionMethod = bytes[index + 1];
int CompressedTextLength = bytes.length - (index + 1 + 1);
byte CompressedText[] = new byte[CompressedTextLength];
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java Tue Jan 22 20:44:55 2008
@@ -188,7 +188,7 @@
return null;
}
- public ImageInfo getImageInfo(ByteSource byteSource)
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
FileInfo info = readHeader(byteSource);
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java Tue Jan 22 20:44:55 2008
@@ -544,7 +544,7 @@
}
}
- public ImageInfo getImageInfo(ByteSource byteSource)
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
ImageContents imageContents = readImageContents(byteSource);
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java Tue Jan 22 20:44:55 2008
@@ -35,7 +35,7 @@
return TiffDirectory.description(type);
}
- public String getElementDescription(boolean verbose)
+ public String getElementDescription(boolean verbose)
{
if (!verbose)
return "TIFF Directory (" + description() + ")";
@@ -188,6 +188,8 @@
return null;
}
+
+
public final class ImageDataElement extends TiffElement
{
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java?rev=614420&r1=614419&r2=614420&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java Tue Jan 22 20:44:55 2008
@@ -21,8 +21,10 @@
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
+import java.util.List;
import java.util.Map;
import org.apache.sanselan.ImageReadException;
@@ -62,11 +64,19 @@
tagInfo = getTag(directoryType, tag);
}
+ private int sortHint = -1;
+
+
public boolean isLocalValue()
{
return fieldType.isLocalValue(this);
}
+ public int getBytesLength() throws ImageReadException
+ {
+ return fieldType.getBytesLength(this);
+ }
+
public final class OversizeValueElement extends TiffElement
{
public OversizeValueElement(int offset, int length)
@@ -109,29 +119,132 @@
return FIELD_TYPE_UNKNOWN;
}
- private static TagInfo getTag(int directoryType, int value)
+ private static TagInfo getTag(int directoryType, int tag,
+ List possibleMatches)
{
- Object key = new Integer(value);
+ if (possibleMatches.size() < 1)
+ return null;
+ // else if (possibleMatches.size() == 1)
+ // {
+ // TagInfo tagInfo = (TagInfo) possibleMatches.get(0);
+ // return tagInfo;
+ // }
- if (directoryType == DIRECTORY_TYPE_EXIF
- || directoryType == DIRECTORY_TYPE_INTEROPERABILITY)
- {
- if (EXIF_TAG_MAP.containsKey(key))
- return (TagInfo) EXIF_TAG_MAP.get(key);
- }
- else if (directoryType == DIRECTORY_TYPE_GPS)
+ // first search for exact match.
+ for (int i = 0; i < possibleMatches.size(); i++)
{
- if (GPS_TAG_MAP.containsKey(key))
- return (TagInfo) GPS_TAG_MAP.get(key);
- }
- else
+ TagInfo tagInfo = (TagInfo) possibleMatches.get(i);
+ if (tagInfo.directoryType == EXIF_DIRECTORY_UNKNOWN)
+ // pass
+ continue;
+ else if (directoryType == DIRECTORY_TYPE_EXIF
+ && tagInfo.directoryType == EXIF_DIRECTORY_EXIF_IFD)
+ return tagInfo;
+ else if (directoryType == DIRECTORY_TYPE_INTEROPERABILITY
+ && tagInfo.directoryType == EXIF_DIRECTORY_INTEROP_IFD)
+ return tagInfo;
+ else if (directoryType == DIRECTORY_TYPE_GPS
+ && tagInfo.directoryType == EXIF_DIRECTORY_GPS)
+ return tagInfo;
+ else if (directoryType == DIRECTORY_TYPE_MAKER_NOTES
+ && tagInfo.directoryType == EXIF_DIRECTORY_MAKER_NOTES)
+ return tagInfo;
+ else if (directoryType == DIRECTORY_TYPE_DIR_0
+ && tagInfo.directoryType == TIFF_DIRECTORY_IFD0)
+ return tagInfo;
+ else if (directoryType == DIRECTORY_TYPE_DIR_1
+ && tagInfo.directoryType == TIFF_DIRECTORY_IFD1)
+ return tagInfo;
+ else if (directoryType == DIRECTORY_TYPE_DIR_2
+ && tagInfo.directoryType == TIFF_DIRECTORY_IFD2)
+ return tagInfo;
+ else if (directoryType == DIRECTORY_TYPE_DIR_3
+ && tagInfo.directoryType == TIFF_DIRECTORY_IFD3)
+ return tagInfo;
+ }
+
+ // accept an inexact match.
+ for (int i = 0; i < possibleMatches.size(); i++)
+ {
+ TagInfo tagInfo = (TagInfo) possibleMatches.get(i);
+
+ if (tagInfo.directoryType == EXIF_DIRECTORY_UNKNOWN)
+ // pass
+ continue;
+ else if (directoryType >= 0
+ && tagInfo.directoryType.isImageDirectory())
+ return tagInfo;
+ else if (directoryType < 0
+ && !tagInfo.directoryType.isImageDirectory())
+ return tagInfo;
+ }
+
+ // accept a wildcard match.
+ for (int i = 0; i < possibleMatches.size(); i++)
{
- if (TIFF_TAG_MAP.containsKey(key))
- return (TagInfo) TIFF_TAG_MAP.get(key);
+ TagInfo tagInfo = (TagInfo) possibleMatches.get(i);
+
+ if (tagInfo.directoryType == EXIF_DIRECTORY_UNKNOWN)
+ return tagInfo;
}
- if (ALL_TAG_MAP.containsKey(key))
- return (TagInfo) ALL_TAG_MAP.get(key);
+ // // accept a very rough match.
+ // for (int i = 0; i < possibleMatches.size(); i++)
+ // {
+ // TagInfo tagInfo = (TagInfo) possibleMatches.get(i);
+ // if (tagInfo.exifDirectory == EXIF_DIRECTORY_UNKNOWN)
+ // return tagInfo;
+ // else if (directoryType == DIRECTORY_TYPE_EXIF
+ // && tagInfo.exifDirectory == EXIF_DIRECTORY_EXIF_IFD)
+ // return tagInfo;
+ // else if (directoryType == DIRECTORY_TYPE_INTEROPERABILITY
+ // && tagInfo.exifDirectory == EXIF_DIRECTORY_INTEROP_IFD)
+ // return tagInfo;
+ // else if (directoryType == DIRECTORY_TYPE_GPS
+ // && tagInfo.exifDirectory == EXIF_DIRECTORY_GPS)
+ // return tagInfo;
+ // else if (directoryType == DIRECTORY_TYPE_MAKER_NOTES
+ // && tagInfo.exifDirectory == EXIF_DIRECTORY_MAKER_NOTES)
+ // return tagInfo;
+ // else if (directoryType >= 0
+ // && tagInfo.exifDirectory.isImageDirectory())
+ // return tagInfo;
+ // else if (directoryType < 0
+ // && !tagInfo.exifDirectory.isImageDirectory())
+ // return tagInfo;
+ // }
+
+ return TIFF_TAG_UNKNOWN;
+
+ // if (true)
+ // throw new Error("Why didn't this algorithm work?");
+ //
+ // {
+ // TagInfo tagInfo = (TagInfo) possibleMatches.get(0);
+ // return tagInfo;
+ // }
+
+ // Object key = new Integer(tag);
+ //
+ // if (directoryType == DIRECTORY_TYPE_EXIF
+ // || directoryType == DIRECTORY_TYPE_INTEROPERABILITY)
+ // {
+ // if (EXIF_TAG_MAP.containsKey(key))
+ // return (TagInfo) EXIF_TAG_MAP.get(key);
+ // }
+ // else if (directoryType == DIRECTORY_TYPE_GPS)
+ // {
+ // if (GPS_TAG_MAP.containsKey(key))
+ // return (TagInfo) GPS_TAG_MAP.get(key);
+ // }
+ // else
+ // {
+ // if (TIFF_TAG_MAP.containsKey(key))
+ // return (TagInfo) TIFF_TAG_MAP.get(key);
+ // }
+ //
+ // if (ALL_TAG_MAP.containsKey(key))
+ // return (TagInfo) ALL_TAG_MAP.get(key);
// public static final int DIRECTORY_TYPE_EXIF = -2;
// // public static final int DIRECTORY_TYPE_SUB = 5;
@@ -150,7 +263,76 @@
// return tag;
// }
- return TIFF_TAG_UNKNOWN;
+ // return TIFF_TAG_UNKNOWN;
+ }
+
+ private static TagInfo getTag(int directoryType, int tag)
+ {
+ // Debug.debug();
+ // Debug
+ // .debug("getTag tag", tag + " (0x" + Integer.toHexString(tag)
+ // + ")");
+ // Debug.debug("getTag directoryType", directoryType + " (0x"
+ // + Integer.toHexString(directoryType) + ")");
+
+ Object key = new Integer(tag);
+
+ List possibleMatches = (List) EXIF_TAG_MAP.get(key);
+
+ if (null == possibleMatches)
+ {
+// if (tag == 0x8769)
+// Debug.debug("exif offset field is unknown.1");
+ return TIFF_TAG_UNKNOWN;
+ }
+
+ TagInfo result = getTag(directoryType, tag, possibleMatches);
+ // if (tag == 0x8769)
+ // {
+ // Debug.debug("exif offset possibleMatches", possibleMatches);
+ // Debug.debug("exif offset field", result);
+ // }
+ // Debug.debug("result", result);
+ return result;
+
+ // if (directoryType == DIRECTORY_TYPE_EXIF
+ // || directoryType == DIRECTORY_TYPE_INTEROPERABILITY)
+ // {
+ // if (EXIF_TAG_MAP.containsKey(key))
+ // return (TagInfo) EXIF_TAG_MAP.get(key);
+ // }
+ // else if (directoryType == DIRECTORY_TYPE_GPS)
+ // {
+ // if (GPS_TAG_MAP.containsKey(key))
+ // return (TagInfo) GPS_TAG_MAP.get(key);
+ // }
+ // else
+ // {
+ // if (TIFF_TAG_MAP.containsKey(key))
+ // return (TagInfo) TIFF_TAG_MAP.get(key);
+ // }
+ //
+ // if (ALL_TAG_MAP.containsKey(key))
+ // return (TagInfo) ALL_TAG_MAP.get(key);
+ //
+ // // public static final int DIRECTORY_TYPE_EXIF = -2;
+ // // // public static final int DIRECTORY_TYPE_SUB = 5;
+ // // public static final int DIRECTORY_TYPE_GPS = -3;
+ // // public static final int DIRECTORY_TYPE_INTEROPERABILITY = -4;
+ // //
+ // // private static final Map GPS_TAG_MAP = makeTagMap(ALL_GPS_TAGS, false);
+ // // private static final Map TIFF_TAG_MAP = makeTagMap(ALL_TIFF_TAGS, false);
+ // // private static final Map EXIF_TAG_MAP = makeTagMap(ALL_EXIF_TAGS, false);
+ // // private static final Map ALL_TAG_MAP = makeTagMap(ALL_TAGS, true);
+ // //
+ // // for (int i = 0; i < ALL_TAGS.length; i++)
+ // // {
+ // // TagInfo2 tag = ALL_TAGS[i];
+ // // if (tag.tag == value)
+ // // return tag;
+ // // }
+ //
+ // return TIFF_TAG_UNKNOWN;
}
private int getValueLengthInBytes()
@@ -168,9 +350,9 @@
int valueLength = getValueLengthInBytes();
- // Debug.debug("fillInValue tagInfo", tagInfo);
- // Debug.debug("fillInValue valueOffset", valueOffset);
- // Debug.debug("fillInValue valueLength", valueLength);
+ // Debug.debug("fillInValue tagInfo", tagInfo);
+ // Debug.debug("fillInValue valueOffset", valueOffset);
+ // Debug.debug("fillInValue valueLength", valueLength);
byte bytes[] = byteSource.getBlock(valueOffset, valueLength);
setOversizeValue(bytes);
@@ -178,7 +360,14 @@
public String getValueDescription()
{
- return getValueDescription(getValue());
+ try
+ {
+ return getValueDescription(getValue());
+ }
+ catch (ImageReadException e)
+ {
+ return "Invalid value: " + e.getMessage();
+ }
}
private String getValueDescription(Object o)
@@ -189,19 +378,6 @@
if (o instanceof Number)
{
return o.toString();
- // try
- // {
- // return o.toString();
- // }
- // catch (ArithmeticException e)
- // {
- // errorDump();
- //
- // // Debug.debug(toString());
- // // Debug.debug(e);
- //
- // throw e;
- // }
}
else if (o instanceof String)
{
@@ -430,7 +606,7 @@
result.append(tag + " (0x" + Integer.toHexString(tag) + ": "
+ tagInfo.name + "): ");
- result.append(getValueDescription(getValue()) + " (" + length + " "
+ result.append(getValueDescription() + " (" + length + " "
+ fieldType.name + ")");
return result.toString();
@@ -450,12 +626,23 @@
public static final String Attribute_Tag = "Tag";
- public Object getValue()
+ public Object getValue() throws ImageReadException
{
// System.out.print("getValue");
return tagInfo.getValue(this);
}
+ public String getStringValue() throws ImageReadException
+ {
+ Object o = getValue();
+ if (o == null)
+ return null;
+ if (!(o instanceof String))
+ throw new ImageReadException("Expected String value("
+ + tagInfo.getDescription() + "): " + o);
+ return (String) o;
+ }
+
private static final Map makeTagMap(TagInfo tags[],
boolean ignoreDuplicates, String name)
{
@@ -467,16 +654,24 @@
TagInfo tag = tags[i];
Object key = new Integer(tag.tag);
- if (map.get(key) == null)
- map.put(key, tag);
- else if (!ignoreDuplicates)
+ List tagList = (List) map.get(key);
+ if (tagList == null)
{
- System.out.println("Duplicate tag in " + name + ": " + tag.tag
- + " (0x" + Integer.toHexString(tag.tag) + ")");
- System.out.println("\t" + "New name: " + tag.name);
- System.out.println("\t" + "Old name: "
- + ((TagInfo) map.get(key)).name);
+ tagList = new ArrayList();
+ map.put(key, tagList);
}
+ tagList.add(tag);
+
+ // if (map.get(key) == null)
+ // map.put(key, tag);
+ // else if (!ignoreDuplicates)
+ // {
+ // System.out.println("Duplicate tag in " + name + ": " + tag.tag
+ // + " (0x" + Integer.toHexString(tag.tag) + ")");
+ // System.out.println("\t" + "New name: " + tag.name);
+ // System.out.println("\t" + "Old name: "
+ // + ((TagInfo) map.get(key)).name);
+ // }
}
return map;
@@ -647,5 +842,15 @@
+ tagInfo.getDescription());
return ((Number) o).doubleValue();
+ }
+
+ public int getSortHint()
+ {
+ return sortHint;
+ }
+
+ public void setSortHint(int sortHint)
+ {
+ this.sortHint = sortHint;
}
}