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/07/27 17:42:06 UTC
svn commit: r680158 - in /incubator/sanselan/trunk/src:
main/java/org/apache/sanselan/formats/jpeg/
main/java/org/apache/sanselan/formats/jpeg/xmp/
test/java/org/apache/sanselan/formats/jpeg/xmp/
Author: cmchen
Date: Sun Jul 27 10:42:05 2008
New Revision: 680158
URL: http://svn.apache.org/viewvc?rev=680158&view=rev
Log:
Began work on xmp support. Added xmp-extraction to Jpeg parser.
Added:
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpParser.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpBaseTest.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java (with props)
Modified:
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
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=680158&r1=680157&r2=680158&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 Sun Jul 27 10:42:05 2008
@@ -41,27 +41,25 @@
import org.apache.sanselan.formats.jpeg.segments.SOFNSegment;
import org.apache.sanselan.formats.jpeg.segments.Segment;
import org.apache.sanselan.formats.jpeg.segments.UnknownSegment;
+import org.apache.sanselan.formats.jpeg.xmp.JpegXmpParser;
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,
- TiffTagConstants
+public class JpegImageParser extends ImageParser implements JpegConstants,
+ TiffTagConstants
{
public JpegImageParser()
{
setByteOrder(BYTE_ORDER_NETWORK);
- // setDebug(true);
+ // setDebug(true);
}
protected ImageFormat[] getAcceptedTypes()
{
- return new ImageFormat[]{
- ImageFormat.IMAGE_FORMAT_JPEG, //
+ return new ImageFormat[] { ImageFormat.IMAGE_FORMAT_JPEG, //
};
}
@@ -77,9 +75,7 @@
private static final String DEFAULT_EXTENSION = ".jpg";
- public static final String AcceptedExtensions[] = {
- ".jpg", ".jpeg",
- };
+ public static final String AcceptedExtensions[] = { ".jpg", ".jpeg", };
protected String[] getAcceptedExtensions()
{
@@ -114,8 +110,7 @@
final ArrayList result = new ArrayList();
final JpegImageParser parser = this;
- JpegUtils.Visitor visitor = new JpegUtils.Visitor()
- {
+ JpegUtils.Visitor visitor = new JpegUtils.Visitor() {
// return false to exit before reading image data.
public boolean beginSOS()
{
@@ -135,31 +130,29 @@
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));
+ // 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);
+ // Debug.debug("app 13 segment data", segmentData.length);
result.add(new App13Segment(parser, marker, segmentData));
- }
- else if (marker == JPEG_APP2_Marker)
+ } else if (marker == JPEG_APP2_Marker)
{
result.add(new App2Segment(marker, segmentData));
- }
- else if (marker == JFIFMarker)
+ } else if (marker == JFIFMarker)
{
result.add(new JFIFSegment(marker, segmentData));
- }
- else if ((marker >= SOF0Marker) && (marker <= SOF15Marker))
+ } else if ((marker >= SOF0Marker) && (marker <= SOF15Marker))
{
result.add(new SOFNSegment(marker, segmentData));
- }
- else if ((marker >= JPEG_APP1_Marker)
+ } else if ((marker >= JPEG_APP1_Marker)
&& (marker <= JPEG_APP15_Marker))
{
result.add(new UnknownSegment(marker, segmentData));
@@ -185,8 +178,7 @@
try
{
return assembleSegments(v, false);
- }
- catch (ImageReadException e)
+ } catch (ImageReadException e)
{
return assembleSegments(v, true);
}
@@ -200,8 +192,8 @@
int markerCount = ((App2Segment) v.get(0)).num_markers;
- // if (permissive && (markerCount == 0))
- // markerCount = v.size();
+ // if (permissive && (markerCount == 0))
+ // markerCount = v.size();
if (v.size() != markerCount)
throw new ImageReadException("App2 Segments Missing. Found: "
@@ -276,9 +268,8 @@
public byte[] getICCProfileBytes(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
- ArrayList segments = readSegments(byteSource, new int[]{
- JPEG_APP2_Marker,
- }, false);
+ ArrayList segments = readSegments(byteSource,
+ new int[] { JPEG_APP2_Marker, }, false);
if (segments != null)
{
@@ -369,9 +360,9 @@
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("read thumbs?", params.get(PARAM_KEY_READ_THUMBNAILS));
- // Debug.debug("exif bytes", bytes.length);
+ // Debug.debug("exif bytes", bytes.length);
return (TiffImageMetadata) new TiffImageParser().getMetadata(bytes,
params);
@@ -380,9 +371,8 @@
public byte[] getExifRawData(ByteSource byteSource)
throws ImageReadException, IOException
{
- ArrayList segments = readSegments(byteSource, new int[]{
- JPEG_APP1_Marker,
- }, false);
+ ArrayList segments = readSegments(byteSource,
+ new int[] { JPEG_APP1_Marker, }, false);
if ((segments == null) || (segments.size() < 1))
return null;
@@ -392,8 +382,8 @@
System.out.println("exif_segments.size" + ": "
+ exifSegments.size());
- // Debug.debug("segments", segments);
- // Debug.debug("exifSegments", exifSegments);
+ // Debug.debug("segments", segments);
+ // Debug.debug("exifSegments", exifSegments);
// TODO: concatenate if multiple segments, need example.
if (exifSegments.size() < 1)
@@ -406,9 +396,9 @@
GenericSegment segment = (GenericSegment) exifSegments.get(0);
byte bytes[] = segment.bytes;
- // byte head[] = readBytearray("exif head", bytes, 0, 6);
+ // byte head[] = readBytearray("exif head", bytes, 0, 6);
//
- // Debug.debug("head", head);
+ // Debug.debug("head", head);
return getByteArrayTail("trimmed exif bytes", bytes, 6);
}
@@ -416,12 +406,9 @@
public boolean hasExifSegment(ByteSource byteSource)
throws ImageReadException, IOException
{
- final boolean result[] = {
- false,
- };
+ final boolean result[] = { false, };
- JpegUtils.Visitor visitor = new JpegUtils.Visitor()
- {
+ JpegUtils.Visitor visitor = new JpegUtils.Visitor() {
// return false to exit before reading image data.
public boolean beginSOS()
{
@@ -459,12 +446,106 @@
return result[0];
}
+ public boolean hasXmpSegment(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 (new JpegXmpParser().isXmpJpegSegment(segmentData))
+ {
+ result[0] = true;
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+ new JpegUtils().traverseJFIF(byteSource, visitor);
+
+ return result[0];
+ }
+
+ /*
+ * Locates the XMP XML if present.
+ *
+ * returns null if no XMP segment is found.
+ */
+ public String getXmpXml(ByteSource byteSource) throws ImageReadException,
+ IOException
+ {
+ final List result = new ArrayList();
+
+ 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 (new JpegXmpParser().isXmpJpegSegment(segmentData))
+ {
+ result.add(new JpegXmpParser()
+ .parseXmpJpegSegment(segmentData));
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+ new JpegUtils().traverseJFIF(byteSource, visitor);
+
+ if (result.size() < 1)
+ return null;
+ if (result.size() > 1)
+ throw new ImageReadException(
+ "Jpeg file contains more than one XMP segment.");
+ return (String) result.get(0);
+ }
+
private JpegImageMetadata.Photoshop getPhotoshopMetadata(
ByteSource byteSource) throws ImageReadException, IOException
{
- ArrayList segments = readSegments(byteSource, new int[]{
- JPEG_APP13_Marker,
- }, false);
+ ArrayList segments = readSegments(byteSource,
+ new int[] { JPEG_APP13_Marker, }, false);
if ((segments == null) || (segments.size() < 1))
return null;
@@ -487,12 +568,11 @@
return result;
}
- public Dimension getImageSize(ByteSource byteSource,
- Map params)
+ public Dimension getImageSize(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
- ArrayList segments = readSegments(byteSource, new int[]{
- // kJFIFMarker,
+ ArrayList segments = readSegments(byteSource, new int[] {
+ // kJFIFMarker,
SOF0Marker,
SOF1Marker, SOF2Marker, SOF3Marker, SOF5Marker, SOF6Marker,
@@ -525,10 +605,10 @@
public ImageInfo getImageInfo(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
- // ArrayList allSegments = readSegments(byteSource, null, false);
+ // ArrayList allSegments = readSegments(byteSource, null, false);
- ArrayList SOF_segments = readSegments(byteSource, new int[]{
- // kJFIFMarker,
+ ArrayList SOF_segments = readSegments(byteSource, new int[] {
+ // kJFIFMarker,
SOF0Marker, SOF1Marker, SOF2Marker, SOF3Marker, SOF5Marker,
SOF6Marker, SOF7Marker, SOF9Marker, SOF10Marker, SOF11Marker,
@@ -539,16 +619,16 @@
if (SOF_segments == null)
throw new ImageReadException("No SOFN Data Found.");
- // if (SOF_segments.size() != 1)
- // System.out.println("Incoherent SOFN Data Found: "
- // + SOF_segments.size());
+ // if (SOF_segments.size() != 1)
+ // System.out.println("Incoherent SOFN Data Found: "
+ // + SOF_segments.size());
- ArrayList jfifSegments = readSegments(byteSource, new int[]{
- JFIFMarker,
- }, true);
+ ArrayList jfifSegments = readSegments(byteSource,
+ new int[] { JFIFMarker, }, true);
SOFNSegment fSOFNSegment = (SOFNSegment) SOF_segments.get(0);
- // SOFNSegment fSOFNSegment = (SOFNSegment) findSegment(segments, SOFNmarkers);
+ // SOFNSegment fSOFNSegment = (SOFNSegment) findSegment(segments,
+ // SOFNmarkers);
if (fSOFNSegment == null)
throw new ImageReadException("No SOFN Data Found.");
@@ -561,14 +641,14 @@
if ((jfifSegments != null) && (jfifSegments.size() > 0))
jfifSegment = (JFIFSegment) jfifSegments.get(0);
- // JFIFSegment fTheJFIFSegment = (JFIFSegment) findSegment(segments,
- // kJFIFMarker);
+ // JFIFSegment fTheJFIFSegment = (JFIFSegment) findSegment(segments,
+ // kJFIFMarker);
double x_density = -1.0;
double y_density = -1.0;
double units_per_inch = -1.0;
- // int JFIF_major_version;
- // int JFIF_minor_version;
+ // int JFIF_major_version;
+ // int JFIF_minor_version;
String FormatDetails;
if (jfifSegment != null)
@@ -576,27 +656,26 @@
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;
+ // 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;
+ case 0:
+ break;
+ case 1: // inches
+ units_per_inch = 1.0;
+ break;
+ case 2: // cms
+ units_per_inch = 2.54;
+ break;
+ default:
+ break;
}
- }
- else
+ } else
{
JpegImageMetadata metadata = (JpegImageMetadata) getMetadata(
byteSource, params);
@@ -625,16 +704,16 @@
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;
+ case 1:
+ break;
+ case 2: // inches
+ units_per_inch = 1.0;
+ break;
+ case 3: // cms
+ units_per_inch = 2.54;
+ break;
+ default:
+ break;
}
}
@@ -698,171 +777,174 @@
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);
+ // 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;
- // }
+ // return result;
+ // }
public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource)
throws ImageReadException, IOException
@@ -891,7 +973,7 @@
Segment segment = (Segment) segments.get(d);
NumberFormat nf = NumberFormat.getIntegerInstance();
- // this.debugNumber("found, marker: ", marker, 4);
+ // this.debugNumber("found, marker: ", marker, 4);
pw.println(d + ": marker: "
+ Integer.toHexString(segment.marker) + ", "
+ segment.getDescription() + " (length: "
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpParser.java?rev=680158&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpParser.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpParser.java Sun Jul 27 10:42:05 2008
@@ -0,0 +1,115 @@
+/*
+ * 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.sanselan.formats.jpeg.xmp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.SanselanConstants;
+import org.apache.sanselan.common.BinaryFileParser;
+import org.apache.sanselan.common.BinaryOutputStream;
+import org.apache.sanselan.util.Debug;
+import org.apache.sanselan.util.ParamMap;
+
+public class JpegXmpParser extends BinaryFileParser
+{
+
+ public JpegXmpParser()
+ {
+ setByteOrder(BYTE_ORDER_NETWORK);
+ }
+
+ public static final String XMP_NAMESPACE_URI = "http://ns.adobe.com/xap/1.0/";
+
+ public static final byte XMP_IDENTIFIER[] = { //
+ 0x68, // h
+ 0x74, // t
+ 0x74, // t
+ 0x70, // p
+ 0x3A, // :
+ 0x2F, // /
+ 0x2F, // /
+ 0x6E, // n
+ 0x73, // s
+ 0x2E, // .
+ 0x61, // a
+ 0x64, // d
+ 0x6F, // o
+ 0x62, // b
+ 0x65, // e
+ 0x2E, // .
+ 0x63, // c
+ 0x6F, // o
+ 0x6D, // m
+ 0x2F, // /
+ 0x78, // x
+ 0x61, // a
+ 0x70, // p
+ 0x2F, // /
+ 0x31, // 1
+ 0x2E, // .
+ 0x30, // 0
+ 0x2F, // /
+ 0, // 0-terminated us-ascii string.
+ };
+
+ public boolean isXmpJpegSegment(byte segmentData[])
+ {
+ int index = 0;
+
+ if (segmentData.length < XMP_IDENTIFIER.length)
+ return false;
+ for (; index < XMP_IDENTIFIER.length; index++)
+ if (segmentData[index] < XMP_IDENTIFIER[index])
+ return false;
+
+ return true;
+ }
+
+ public String parseXmpJpegSegment(byte segmentData[])
+ throws ImageReadException
+ {
+ int index = 0;
+
+ if (segmentData.length < XMP_IDENTIFIER.length)
+ throw new ImageReadException("Invalid JPEG XMP Segment.");
+ for (; index < XMP_IDENTIFIER.length; index++)
+ if (segmentData[index] < XMP_IDENTIFIER[index])
+ throw new ImageReadException("Invalid JPEG XMP Segment.");
+
+ try
+ {
+ // segment data is UTF-8 encoded xml.
+ String xml = new String(segmentData, index, segmentData.length
+ - index, "utf-8");
+ return xml;
+ } catch (UnsupportedEncodingException e)
+ {
+ throw new ImageReadException("Invalid JPEG XMP Segment.");
+ }
+ }
+
+}
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpBaseTest.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpBaseTest.java?rev=680158&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpBaseTest.java (added)
+++ incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpBaseTest.java Sun Jul 27 10:42:05 2008
@@ -0,0 +1,107 @@
+/*
+ * 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.sanselan.formats.jpeg.xmp;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.SanselanTest;
+import org.apache.sanselan.common.byteSources.ByteSource;
+import org.apache.sanselan.common.byteSources.ByteSourceFile;
+import org.apache.sanselan.formats.jpeg.JpegImageParser;
+
+public abstract class JpegXmpBaseTest extends SanselanTest
+{
+
+ protected static boolean hasJpegXmpData(File file) throws IOException,
+ ImageReadException
+ {
+ if (!file.getName().toLowerCase().endsWith(".jpg"))
+ return false;
+ //ImageFormat format = Sanselan.guessFormat(file);
+ //if (format != ImageFormat.IMAGE_FORMAT_JPEG)
+ // return false;
+
+ // Debug.debug("possible file", file);
+
+ try
+ {
+ ByteSource byteSource = new ByteSourceFile(file);
+ return new JpegImageParser().hasXmpSegment(byteSource);
+ }
+ catch (Exception e)
+ {
+ // Debug.debug("Error file", file.getAbsoluteFile());
+ // Debug.debug(e, 4);
+ return false;
+ }
+ }
+
+ private static final ImageFilter HAS_JPEG_XMP_IMAGE_FILTER = new ImageFilter()
+ {
+ public boolean accept(File file) throws IOException, ImageReadException
+ {
+ return hasJpegXmpData(file);
+ }
+ };
+
+// private static final ImageFilter JPEG_IMAGE_FILTER = new ImageFilter()
+// {
+// public boolean accept(File file) throws IOException, ImageReadException
+// {
+// return file.getName().toLowerCase().endsWith(".jpg");
+// }
+// };
+
+ protected File getImageWithIptcData() throws IOException,
+ ImageReadException
+ {
+ return getTestImage(HAS_JPEG_XMP_IMAGE_FILTER);
+ }
+
+ protected List getImagesWithIptcData() throws IOException,
+ ImageReadException
+ {
+ return getTestImages(HAS_JPEG_XMP_IMAGE_FILTER);
+ }
+
+ protected List getImagesWithIptcData(int max) throws IOException,
+ ImageReadException
+ {
+ return getTestImages(HAS_JPEG_XMP_IMAGE_FILTER, max);
+ }
+
+// protected File getJpegImage() throws IOException, ImageReadException
+// {
+// return getTestImage(JPEG_IMAGE_FILTER);
+// }
+//
+// protected List getJpegImages() throws IOException, ImageReadException
+// {
+// return getTestImages(JPEG_IMAGE_FILTER);
+// }
+//
+// protected List getJpegImages(int max) throws IOException,
+// ImageReadException
+// {
+// return getTestImages(JPEG_IMAGE_FILTER, max);
+// }
+
+}
Propchange: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpBaseTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java?rev=680158&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java (added)
+++ incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java Sun Jul 27 10:42:05 2008
@@ -0,0 +1,56 @@
+/*
+ * 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.sanselan.formats.jpeg.xmp;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.common.byteSources.ByteSource;
+import org.apache.sanselan.common.byteSources.ByteSourceFile;
+import org.apache.sanselan.formats.jpeg.JpegImageParser;
+import org.apache.sanselan.util.Debug;
+
+public class JpegXmpDumpTest extends JpegXmpBaseTest
+{
+
+ public void test() throws IOException, ImageReadException,
+ ImageWriteException
+ {
+ List images = getImagesWithIptcData();
+ for (int i = 0; i < images.size(); i++)
+ {
+ if (i % 10 == 0)
+ Debug.purgeMemory();
+
+ File imageFile = (File) images.get(i);
+ Debug.debug("imageFile", imageFile);
+ Debug.debug();
+
+ ByteSource byteSource = new ByteSourceFile(imageFile);
+ String xmpXml = new JpegImageParser().getXmpXml(byteSource);
+ assertNotNull(xmpXml);
+
+ Debug.debug("xmpXml", xmpXml);
+ Debug.debug();
+ }
+ }
+
+}
Propchange: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java
------------------------------------------------------------------------------
svn:eol-style = native