You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2010/09/10 18:33:42 UTC
svn commit: r995859 [11/30] - in
/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan: ./ color/
common/ common/byteSources/ common/mylzw/ formats/bmp/
formats/bmp/pixelparsers/ formats/bmp/writers/ formats/gif/ formats/ico/
formats/jpeg/ f...
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java Fri Sep 10 16:33:35 2010
@@ -51,987 +51,987 @@ import org.apache.sanselan.formats.tiff.
import org.apache.sanselan.util.Debug;
public class JpegImageParser extends ImageParser implements JpegConstants,
- TiffTagConstants
+ TiffTagConstants
{
- public JpegImageParser()
- {
- setByteOrder(BYTE_ORDER_NETWORK);
- // setDebug(true);
- }
-
- protected ImageFormat[] getAcceptedTypes()
- {
- return new ImageFormat[] { ImageFormat.IMAGE_FORMAT_JPEG, //
- };
- }
-
- public String getName()
- {
- return "Jpeg-Custom";
- }
-
- public String getDefaultExtension()
- {
- return DEFAULT_EXTENSION;
- }
-
- private static final String DEFAULT_EXTENSION = ".jpg";
-
- public static final String AcceptedExtensions[] = { ".jpg", ".jpeg", };
-
- protected String[] getAcceptedExtensions()
- {
- return AcceptedExtensions;
- }
-
- public final BufferedImage getBufferedImage(ByteSource byteSource,
- Map params) throws ImageReadException, IOException
- {
- throw new ImageReadException(
- "Sanselan cannot read or write JPEG images.");
- }
-
- private boolean keepMarker(int marker, int markers[])
- {
- if (markers == null)
- return true;
-
- for (int i = 0; i < markers.length; i++)
- {
- if (markers[i] == marker)
- return true;
- }
-
- return false;
- }
-
- public ArrayList readSegments(ByteSource byteSource, final int markers[],
- final boolean returnAfterFirst, boolean readEverything)
- throws ImageReadException, IOException
- {
- final ArrayList result = new ArrayList();
- final JpegImageParser parser = this;
-
- 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;
-
- // 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)
- {
- result.add(new App2Segment(marker, segmentData));
- } else if (marker == JFIFMarker)
- {
- result.add(new JFIFSegment(marker, segmentData));
- } else if ((marker >= SOF0Marker) && (marker <= SOF15Marker))
- {
- result.add(new SOFNSegment(marker, segmentData));
- } else if ((marker >= JPEG_APP1_Marker)
- && (marker <= JPEG_APP15_Marker))
- {
- result.add(new UnknownSegment(marker, segmentData));
- }
-
- if (returnAfterFirst)
- return false;
-
- return true;
- }
- };
-
- new JpegUtils().traverseJFIF(byteSource, visitor);
-
- return result;
- }
-
- public static final boolean permissive = true;
-
- private byte[] assembleSegments(ArrayList v) throws ImageReadException
- {
- try
- {
- return assembleSegments(v, false);
- } catch (ImageReadException e)
- {
- return assembleSegments(v, true);
- }
- }
-
- private byte[] assembleSegments(ArrayList v, boolean start_with_zero)
- throws ImageReadException
- {
- if (v.size() < 1)
- throw new ImageReadException("No App2 Segments Found.");
-
- int markerCount = ((App2Segment) v.get(0)).num_markers;
-
- // if (permissive && (markerCount == 0))
- // markerCount = v.size();
-
- if (v.size() != markerCount)
- throw new ImageReadException("App2 Segments Missing. Found: "
- + v.size() + ", Expected: " + markerCount + ".");
-
- Collections.sort(v);
-
- int offset = start_with_zero ? 0 : 1;
-
- int total = 0;
- for (int i = 0; i < v.size(); i++)
- {
- App2Segment segment = (App2Segment) v.get(i);
-
- if ((i + offset) != segment.cur_marker)
- {
- dumpSegments(v);
- throw new ImageReadException(
- "Incoherent App2 Segment Ordering. i: " + i
- + ", segment[" + i + "].cur_marker: "
- + segment.cur_marker + ".");
- }
-
- if (markerCount != segment.num_markers)
- {
- dumpSegments(v);
- throw new ImageReadException(
- "Inconsistent App2 Segment Count info. markerCount: "
- + markerCount + ", segment[" + i
- + "].num_markers: " + segment.num_markers + ".");
- }
-
- total += segment.icc_bytes.length;
- }
-
- byte result[] = new byte[total];
- int progress = 0;
-
- for (int i = 0; i < v.size(); i++)
- {
- App2Segment segment = (App2Segment) v.get(i);
-
- System.arraycopy(segment.icc_bytes, 0, result, progress,
- segment.icc_bytes.length);
- progress += segment.icc_bytes.length;
- }
-
- return result;
- }
-
- private void dumpSegments(ArrayList v)
- {
- Debug.debug();
- Debug.debug("dumpSegments", v.size());
-
- for (int i = 0; i < v.size(); i++)
- {
- App2Segment segment = (App2Segment) v.get(i);
-
- Debug.debug((i) + ": " + segment.cur_marker + " / "
- + segment.num_markers);
- }
- Debug.debug();
- }
-
- public ArrayList readSegments(ByteSource byteSource, int markers[],
- boolean returnAfterFirst) throws ImageReadException, IOException
- {
- return readSegments(byteSource, markers, returnAfterFirst, false);
- }
-
- public byte[] getICCProfileBytes(ByteSource byteSource, Map params)
- throws ImageReadException, IOException
- {
- ArrayList segments = readSegments(byteSource,
- new int[] { JPEG_APP2_Marker, }, false);
-
- if (segments != null)
- {
- // throw away non-icc profile app2 segments.
- ArrayList filtered = new ArrayList();
- for (int i = 0; i < segments.size(); i++)
- {
- App2Segment segment = (App2Segment) segments.get(i);
- if (segment.icc_bytes != null)
- filtered.add(segment);
- }
- segments = filtered;
- }
-
- if ((segments == null) || (segments.size() < 1))
- return null;
-
- byte bytes[] = assembleSegments(segments);
-
- if (debug)
- System.out.println("bytes" + ": "
- + ((bytes == null) ? null : "" + bytes.length));
-
- if (debug)
- System.out.println("");
-
- return (bytes);
- }
-
- public IImageMetadata getMetadata(ByteSource byteSource, Map params)
- throws ImageReadException, IOException
- {
- TiffImageMetadata exif = getExifMetadata(byteSource, params);
-
- JpegPhotoshopMetadata photoshop = getPhotoshopMetadata(byteSource,
- params);
-
- if (null == exif && null == photoshop)
- return null;
-
- JpegImageMetadata result = new JpegImageMetadata(photoshop, exif);
-
- return result;
- }
-
- public static boolean isExifAPP1Segment(GenericSegment segment)
- {
- return byteArrayHasPrefix(segment.bytes, EXIF_IDENTIFIER_CODE);
- }
-
- private ArrayList filterAPP1Segments(ArrayList v)
- {
- ArrayList result = new ArrayList();
-
- for (int i = 0; i < v.size(); i++)
- {
- GenericSegment segment = (GenericSegment) v.get(i);
- if (isExifAPP1Segment(segment))
- result.add(segment);
- }
-
- return result;
- }
-
- // TODO unused
- 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
- {
- byte bytes[] = getExifRawData(byteSource);
- if (null == bytes)
- return null;
-
- if (params == null)
- params = new HashMap();
- if (!params.containsKey(PARAM_KEY_READ_THUMBNAILS))
- params.put(PARAM_KEY_READ_THUMBNAILS, Boolean.TRUE);
-
- return (TiffImageMetadata) new TiffImageParser().getMetadata(bytes,
- params);
- }
-
- public byte[] getExifRawData(ByteSource byteSource)
- throws ImageReadException, IOException
- {
- ArrayList segments = readSegments(byteSource,
- new int[] { JPEG_APP1_Marker, }, false);
-
- if ((segments == null) || (segments.size() < 1))
- return null;
-
- ArrayList exifSegments = filterAPP1Segments(segments);
- if (debug)
- 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. "
- + "Please send this image to the Sanselan project.");
-
- GenericSegment segment = (GenericSegment) exifSegments.get(0);
- byte bytes[] = segment.bytes;
-
- // byte head[] = readBytearray("exif head", bytes, 0, 6);
- //
- // Debug.debug("head", head);
-
- 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, EXIF_IDENTIFIER_CODE))
- {
- result[0] = true;
- return false;
- }
- }
-
- return true;
- }
- };
-
- new JpegUtils().traverseJFIF(byteSource, visitor);
-
- return result[0];
- }
-
- public boolean hasIptcSegment(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_APP13_Marker)
- {
- if (new IPTCParser().isPhotoshopJpegSegment(segmentData))
- {
- result[0] = true;
- return false;
- }
- }
-
- return true;
- }
- };
-
- new JpegUtils().traverseJFIF(byteSource, visitor);
-
- 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];
- }
-
- /**
- * Extracts embedded XML metadata as XML string.
- * <p>
- *
- * @param byteSource
- * File containing image data.
- * @param params
- * Map of optional parameters, defined in SanselanConstants.
- * @return Xmp Xml as String, if present. Otherwise, returns null.
- */
- public String getXmpXml(ByteSource byteSource, Map params)
- 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);
- }
-
- public JpegPhotoshopMetadata getPhotoshopMetadata(ByteSource byteSource,
- Map params) throws ImageReadException, IOException
- {
- ArrayList segments = readSegments(byteSource,
- new int[] { JPEG_APP13_Marker, }, false);
-
- if ((segments == null) || (segments.size() < 1))
- return null;
-
- PhotoshopApp13Data photoshopApp13Data = null;
-
- for (int i = 0; i < segments.size(); i++)
- {
- App13Segment segment = (App13Segment) segments.get(i);
-
- PhotoshopApp13Data data = segment.parsePhotoshopSegment(params);
- if (data != null && photoshopApp13Data != null)
- throw new ImageReadException(
- "Jpeg contains more than one Photoshop App13 segment.");
-
- photoshopApp13Data = data;
- }
-
- if(null==photoshopApp13Data)
- return null;
- return new JpegPhotoshopMetadata(photoshopApp13Data);
- }
-
- public Dimension getImageSize(ByteSource byteSource, Map params)
- throws ImageReadException, IOException
- {
- ArrayList segments = readSegments(byteSource, new int[] {
- // kJFIFMarker,
- SOF0Marker,
-
- SOF1Marker, SOF2Marker, SOF3Marker, SOF5Marker, SOF6Marker,
- SOF7Marker, SOF9Marker, SOF10Marker, SOF11Marker, SOF13Marker,
- SOF14Marker, SOF15Marker,
-
- }, true);
-
- if ((segments == null) || (segments.size() < 1))
- throw new ImageReadException("No JFIF Data Found.");
-
- if (segments.size() > 1)
- throw new ImageReadException("Redundant JFIF Data Found.");
-
- SOFNSegment fSOFNSegment = (SOFNSegment) segments.get(0);
-
- return new Dimension(fSOFNSegment.width, fSOFNSegment.height);
- }
-
- public byte[] embedICCProfile(byte image[], byte profile[])
- {
- return null;
- }
-
- public boolean embedICCProfile(File src, File dst, byte profile[])
- {
- return false;
- }
-
- public ImageInfo getImageInfo(ByteSource byteSource, Map params)
- throws ImageReadException, IOException
- {
- // ArrayList allSegments = readSegments(byteSource, null, false);
-
- ArrayList SOF_segments = readSegments(byteSource, new int[] {
- // kJFIFMarker,
-
- SOF0Marker, SOF1Marker, SOF2Marker, SOF3Marker, SOF5Marker,
- SOF6Marker, SOF7Marker, SOF9Marker, SOF10Marker, SOF11Marker,
- SOF13Marker, SOF14Marker, SOF15Marker,
-
- }, false);
-
- 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());
-
- ArrayList jfifSegments = readSegments(byteSource,
- new int[] { JFIFMarker, }, true);
-
- SOFNSegment fSOFNSegment = (SOFNSegment) SOF_segments.get(0);
- // SOFNSegment fSOFNSegment = (SOFNSegment) findSegment(segments,
- // SOFNmarkers);
-
- if (fSOFNSegment == null)
- throw new ImageReadException("No SOFN Data Found.");
-
- int Width = fSOFNSegment.width;
- int Height = fSOFNSegment.height;
-
- JFIFSegment jfifSegment = null;
-
- if ((jfifSegments != null) && (jfifSegments.size() > 0))
- jfifSegment = (JFIFSegment) jfifSegments.get(0);
-
- // 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;
- 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);
-
- if (metadata != null)
- {
- {
- 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";
-
- }
-
- int PhysicalHeightDpi = -1;
- float PhysicalHeightInch = -1;
- int PhysicalWidthDpi = -1;
- float PhysicalWidthInch = -1;
-
- if (units_per_inch > 0)
- {
- PhysicalWidthDpi = (int) Math.round(x_density / units_per_inch);
- PhysicalWidthInch = (float) (Width / (x_density * units_per_inch));
- PhysicalHeightDpi = (int) Math.round(y_density * units_per_inch);
- PhysicalHeightInch = (float) (Height / (y_density * units_per_inch));
- }
-
- ArrayList Comments = new ArrayList();
- // TODO: comments...
-
- int Number_of_components = fSOFNSegment.numberOfComponents;
- 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;
- // not accurate ... only reflects first
- boolean isProgressive = fSOFNSegment.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 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
- {
- pw.println("tiff.dumpImageFile");
-
- {
- ImageInfo imageInfo = getImageInfo(byteSource);
- if (imageInfo == null)
- return false;
-
- imageInfo.toString(pw, "");
- }
-
- pw.println("");
-
- {
- ArrayList segments = readSegments(byteSource, null, false);
-
- if (segments == null)
- throw new ImageReadException("No Segments Found.");
-
- for (int d = 0; d < segments.size(); d++)
- {
-
- Segment segment = (Segment) segments.get(d);
-
- NumberFormat nf = NumberFormat.getIntegerInstance();
- // this.debugNumber("found, marker: ", marker, 4);
- pw.println(d + ": marker: "
- + Integer.toHexString(segment.marker) + ", "
- + segment.getDescription() + " (length: "
- + nf.format(segment.length) + ")");
- segment.dump(pw);
- }
+ public JpegImageParser()
+ {
+ setByteOrder(BYTE_ORDER_NETWORK);
+ // setDebug(true);
+ }
+
+ protected ImageFormat[] getAcceptedTypes()
+ {
+ return new ImageFormat[] { ImageFormat.IMAGE_FORMAT_JPEG, //
+ };
+ }
+
+ public String getName()
+ {
+ return "Jpeg-Custom";
+ }
+
+ public String getDefaultExtension()
+ {
+ return DEFAULT_EXTENSION;
+ }
+
+ private static final String DEFAULT_EXTENSION = ".jpg";
+
+ public static final String AcceptedExtensions[] = { ".jpg", ".jpeg", };
+
+ protected String[] getAcceptedExtensions()
+ {
+ return AcceptedExtensions;
+ }
+
+ public final BufferedImage getBufferedImage(ByteSource byteSource,
+ Map params) throws ImageReadException, IOException
+ {
+ throw new ImageReadException(
+ "Sanselan cannot read or write JPEG images.");
+ }
+
+ private boolean keepMarker(int marker, int markers[])
+ {
+ if (markers == null)
+ return true;
+
+ for (int i = 0; i < markers.length; i++)
+ {
+ if (markers[i] == marker)
+ return true;
+ }
+
+ return false;
+ }
+
+ public ArrayList readSegments(ByteSource byteSource, final int markers[],
+ final boolean returnAfterFirst, boolean readEverything)
+ throws ImageReadException, IOException
+ {
+ final ArrayList result = new ArrayList();
+ final JpegImageParser parser = this;
+
+ 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;
+
+ // 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)
+ {
+ result.add(new App2Segment(marker, segmentData));
+ } else if (marker == JFIFMarker)
+ {
+ result.add(new JFIFSegment(marker, segmentData));
+ } else if ((marker >= SOF0Marker) && (marker <= SOF15Marker))
+ {
+ result.add(new SOFNSegment(marker, segmentData));
+ } else if ((marker >= JPEG_APP1_Marker)
+ && (marker <= JPEG_APP15_Marker))
+ {
+ result.add(new UnknownSegment(marker, segmentData));
+ }
+
+ if (returnAfterFirst)
+ return false;
+
+ return true;
+ }
+ };
+
+ new JpegUtils().traverseJFIF(byteSource, visitor);
+
+ return result;
+ }
+
+ public static final boolean permissive = true;
+
+ private byte[] assembleSegments(ArrayList v) throws ImageReadException
+ {
+ try
+ {
+ return assembleSegments(v, false);
+ } catch (ImageReadException e)
+ {
+ return assembleSegments(v, true);
+ }
+ }
+
+ private byte[] assembleSegments(ArrayList v, boolean start_with_zero)
+ throws ImageReadException
+ {
+ if (v.size() < 1)
+ throw new ImageReadException("No App2 Segments Found.");
+
+ int markerCount = ((App2Segment) v.get(0)).num_markers;
+
+ // if (permissive && (markerCount == 0))
+ // markerCount = v.size();
+
+ if (v.size() != markerCount)
+ throw new ImageReadException("App2 Segments Missing. Found: "
+ + v.size() + ", Expected: " + markerCount + ".");
+
+ Collections.sort(v);
+
+ int offset = start_with_zero ? 0 : 1;
+
+ int total = 0;
+ for (int i = 0; i < v.size(); i++)
+ {
+ App2Segment segment = (App2Segment) v.get(i);
+
+ if ((i + offset) != segment.cur_marker)
+ {
+ dumpSegments(v);
+ throw new ImageReadException(
+ "Incoherent App2 Segment Ordering. i: " + i
+ + ", segment[" + i + "].cur_marker: "
+ + segment.cur_marker + ".");
+ }
+
+ if (markerCount != segment.num_markers)
+ {
+ dumpSegments(v);
+ throw new ImageReadException(
+ "Inconsistent App2 Segment Count info. markerCount: "
+ + markerCount + ", segment[" + i
+ + "].num_markers: " + segment.num_markers + ".");
+ }
+
+ total += segment.icc_bytes.length;
+ }
+
+ byte result[] = new byte[total];
+ int progress = 0;
+
+ for (int i = 0; i < v.size(); i++)
+ {
+ App2Segment segment = (App2Segment) v.get(i);
+
+ System.arraycopy(segment.icc_bytes, 0, result, progress,
+ segment.icc_bytes.length);
+ progress += segment.icc_bytes.length;
+ }
+
+ return result;
+ }
+
+ private void dumpSegments(ArrayList v)
+ {
+ Debug.debug();
+ Debug.debug("dumpSegments", v.size());
+
+ for (int i = 0; i < v.size(); i++)
+ {
+ App2Segment segment = (App2Segment) v.get(i);
+
+ Debug.debug((i) + ": " + segment.cur_marker + " / "
+ + segment.num_markers);
+ }
+ Debug.debug();
+ }
+
+ public ArrayList readSegments(ByteSource byteSource, int markers[],
+ boolean returnAfterFirst) throws ImageReadException, IOException
+ {
+ return readSegments(byteSource, markers, returnAfterFirst, false);
+ }
+
+ public byte[] getICCProfileBytes(ByteSource byteSource, Map params)
+ throws ImageReadException, IOException
+ {
+ ArrayList segments = readSegments(byteSource,
+ new int[] { JPEG_APP2_Marker, }, false);
+
+ if (segments != null)
+ {
+ // throw away non-icc profile app2 segments.
+ ArrayList filtered = new ArrayList();
+ for (int i = 0; i < segments.size(); i++)
+ {
+ App2Segment segment = (App2Segment) segments.get(i);
+ if (segment.icc_bytes != null)
+ filtered.add(segment);
+ }
+ segments = filtered;
+ }
+
+ if ((segments == null) || (segments.size() < 1))
+ return null;
+
+ byte bytes[] = assembleSegments(segments);
+
+ if (debug)
+ System.out.println("bytes" + ": "
+ + ((bytes == null) ? null : "" + bytes.length));
+
+ if (debug)
+ System.out.println("");
+
+ return (bytes);
+ }
+
+ public IImageMetadata getMetadata(ByteSource byteSource, Map params)
+ throws ImageReadException, IOException
+ {
+ TiffImageMetadata exif = getExifMetadata(byteSource, params);
+
+ JpegPhotoshopMetadata photoshop = getPhotoshopMetadata(byteSource,
+ params);
+
+ if (null == exif && null == photoshop)
+ return null;
+
+ JpegImageMetadata result = new JpegImageMetadata(photoshop, exif);
+
+ return result;
+ }
+
+ public static boolean isExifAPP1Segment(GenericSegment segment)
+ {
+ return byteArrayHasPrefix(segment.bytes, EXIF_IDENTIFIER_CODE);
+ }
+
+ private ArrayList filterAPP1Segments(ArrayList v)
+ {
+ ArrayList result = new ArrayList();
+
+ for (int i = 0; i < v.size(); i++)
+ {
+ GenericSegment segment = (GenericSegment) v.get(i);
+ if (isExifAPP1Segment(segment))
+ result.add(segment);
+ }
+
+ return result;
+ }
+
+ // TODO unused
+ 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
+ {
+ byte bytes[] = getExifRawData(byteSource);
+ if (null == bytes)
+ return null;
+
+ if (params == null)
+ params = new HashMap();
+ if (!params.containsKey(PARAM_KEY_READ_THUMBNAILS))
+ params.put(PARAM_KEY_READ_THUMBNAILS, Boolean.TRUE);
+
+ return (TiffImageMetadata) new TiffImageParser().getMetadata(bytes,
+ params);
+ }
+
+ public byte[] getExifRawData(ByteSource byteSource)
+ throws ImageReadException, IOException
+ {
+ ArrayList segments = readSegments(byteSource,
+ new int[] { JPEG_APP1_Marker, }, false);
+
+ if ((segments == null) || (segments.size() < 1))
+ return null;
+
+ ArrayList exifSegments = filterAPP1Segments(segments);
+ if (debug)
+ 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. "
+ + "Please send this image to the Sanselan project.");
+
+ GenericSegment segment = (GenericSegment) exifSegments.get(0);
+ byte bytes[] = segment.bytes;
+
+ // byte head[] = readBytearray("exif head", bytes, 0, 6);
+ //
+ // Debug.debug("head", head);
+
+ 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, EXIF_IDENTIFIER_CODE))
+ {
+ result[0] = true;
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+
+ new JpegUtils().traverseJFIF(byteSource, visitor);
+
+ return result[0];
+ }
+
+ public boolean hasIptcSegment(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_APP13_Marker)
+ {
+ if (new IPTCParser().isPhotoshopJpegSegment(segmentData))
+ {
+ result[0] = true;
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+
+ new JpegUtils().traverseJFIF(byteSource, visitor);
+
+ 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];
+ }
+
+ /**
+ * Extracts embedded XML metadata as XML string.
+ * <p>
+ *
+ * @param byteSource
+ * File containing image data.
+ * @param params
+ * Map of optional parameters, defined in SanselanConstants.
+ * @return Xmp Xml as String, if present. Otherwise, returns null.
+ */
+ public String getXmpXml(ByteSource byteSource, Map params)
+ 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);
+ }
+
+ public JpegPhotoshopMetadata getPhotoshopMetadata(ByteSource byteSource,
+ Map params) throws ImageReadException, IOException
+ {
+ ArrayList segments = readSegments(byteSource,
+ new int[] { JPEG_APP13_Marker, }, false);
+
+ if ((segments == null) || (segments.size() < 1))
+ return null;
+
+ PhotoshopApp13Data photoshopApp13Data = null;
+
+ for (int i = 0; i < segments.size(); i++)
+ {
+ App13Segment segment = (App13Segment) segments.get(i);
+
+ PhotoshopApp13Data data = segment.parsePhotoshopSegment(params);
+ if (data != null && photoshopApp13Data != null)
+ throw new ImageReadException(
+ "Jpeg contains more than one Photoshop App13 segment.");
+
+ photoshopApp13Data = data;
+ }
+
+ if(null==photoshopApp13Data)
+ return null;
+ return new JpegPhotoshopMetadata(photoshopApp13Data);
+ }
+
+ public Dimension getImageSize(ByteSource byteSource, Map params)
+ throws ImageReadException, IOException
+ {
+ ArrayList segments = readSegments(byteSource, new int[] {
+ // kJFIFMarker,
+ SOF0Marker,
+
+ SOF1Marker, SOF2Marker, SOF3Marker, SOF5Marker, SOF6Marker,
+ SOF7Marker, SOF9Marker, SOF10Marker, SOF11Marker, SOF13Marker,
+ SOF14Marker, SOF15Marker,
+
+ }, true);
+
+ if ((segments == null) || (segments.size() < 1))
+ throw new ImageReadException("No JFIF Data Found.");
+
+ if (segments.size() > 1)
+ throw new ImageReadException("Redundant JFIF Data Found.");
+
+ SOFNSegment fSOFNSegment = (SOFNSegment) segments.get(0);
+
+ return new Dimension(fSOFNSegment.width, fSOFNSegment.height);
+ }
+
+ public byte[] embedICCProfile(byte image[], byte profile[])
+ {
+ return null;
+ }
+
+ public boolean embedICCProfile(File src, File dst, byte profile[])
+ {
+ return false;
+ }
+
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
+ throws ImageReadException, IOException
+ {
+ // ArrayList allSegments = readSegments(byteSource, null, false);
+
+ ArrayList SOF_segments = readSegments(byteSource, new int[] {
+ // kJFIFMarker,
+
+ SOF0Marker, SOF1Marker, SOF2Marker, SOF3Marker, SOF5Marker,
+ SOF6Marker, SOF7Marker, SOF9Marker, SOF10Marker, SOF11Marker,
+ SOF13Marker, SOF14Marker, SOF15Marker,
+
+ }, false);
+
+ 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());
+
+ ArrayList jfifSegments = readSegments(byteSource,
+ new int[] { JFIFMarker, }, true);
+
+ SOFNSegment fSOFNSegment = (SOFNSegment) SOF_segments.get(0);
+ // SOFNSegment fSOFNSegment = (SOFNSegment) findSegment(segments,
+ // SOFNmarkers);
+
+ if (fSOFNSegment == null)
+ throw new ImageReadException("No SOFN Data Found.");
+
+ int Width = fSOFNSegment.width;
+ int Height = fSOFNSegment.height;
+
+ JFIFSegment jfifSegment = null;
+
+ if ((jfifSegments != null) && (jfifSegments.size() > 0))
+ jfifSegment = (JFIFSegment) jfifSegments.get(0);
+
+ // 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;
+ 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);
+
+ if (metadata != null)
+ {
+ {
+ 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";
+
+ }
+
+ int PhysicalHeightDpi = -1;
+ float PhysicalHeightInch = -1;
+ int PhysicalWidthDpi = -1;
+ float PhysicalWidthInch = -1;
+
+ if (units_per_inch > 0)
+ {
+ PhysicalWidthDpi = (int) Math.round(x_density / units_per_inch);
+ PhysicalWidthInch = (float) (Width / (x_density * units_per_inch));
+ PhysicalHeightDpi = (int) Math.round(y_density * units_per_inch);
+ PhysicalHeightInch = (float) (Height / (y_density * units_per_inch));
+ }
+
+ ArrayList Comments = new ArrayList();
+ // TODO: comments...
+
+ int Number_of_components = fSOFNSegment.numberOfComponents;
+ 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;
+ // not accurate ... only reflects first
+ boolean isProgressive = fSOFNSegment.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 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
+ {
+ pw.println("tiff.dumpImageFile");
+
+ {
+ ImageInfo imageInfo = getImageInfo(byteSource);
+ if (imageInfo == null)
+ return false;
+
+ imageInfo.toString(pw, "");
+ }
+
+ pw.println("");
+
+ {
+ ArrayList segments = readSegments(byteSource, null, false);
+
+ if (segments == null)
+ throw new ImageReadException("No Segments Found.");
+
+ for (int d = 0; d < segments.size(); d++)
+ {
+
+ Segment segment = (Segment) segments.get(d);
+
+ NumberFormat nf = NumberFormat.getIntegerInstance();
+ // this.debugNumber("found, marker: ", marker, 4);
+ pw.println(d + ": marker: "
+ + Integer.toHexString(segment.marker) + ", "
+ + segment.getDescription() + " (length: "
+ + nf.format(segment.length) + ")");
+ segment.dump(pw);
+ }
- pw.println("");
- }
+ pw.println("");
+ }
- return true;
- }
+ return true;
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java Fri Sep 10 16:33:35 2010
@@ -26,28 +26,28 @@ import org.apache.sanselan.formats.jpeg.
import org.apache.sanselan.util.Debug;
public class JpegPhotoshopMetadata extends ImageMetadata implements
- IPTCConstants
+ IPTCConstants
{
- public final PhotoshopApp13Data photoshopApp13Data;
+ public final PhotoshopApp13Data photoshopApp13Data;
- public JpegPhotoshopMetadata(final PhotoshopApp13Data photoshopApp13Data)
- {
- this.photoshopApp13Data = photoshopApp13Data;
-
- List records = photoshopApp13Data.getRecords();
- Collections.sort(records, IPTCRecord.COMPARATOR);
- for (int j = 0; j < records.size(); j++)
- {
- IPTCRecord element = (IPTCRecord) records.get(j);
- if (element.iptcType.type != IPTC_TYPE_RECORD_VERSION.type)
- add(element.getIptcTypeName(), element.getValue());
- }
- }
-
- public void dump()
- {
- Debug.debug(this.toString());
- }
+ public JpegPhotoshopMetadata(final PhotoshopApp13Data photoshopApp13Data)
+ {
+ this.photoshopApp13Data = photoshopApp13Data;
+
+ List records = photoshopApp13Data.getRecords();
+ Collections.sort(records, IPTCRecord.COMPARATOR);
+ for (int j = 0; j < records.size(); j++)
+ {
+ IPTCRecord element = (IPTCRecord) records.get(j);
+ if (element.iptcType.type != IPTC_TYPE_RECORD_VERSION.type)
+ add(element.getIptcTypeName(), element.getValue());
+ }
+ }
+
+ public void dump()
+ {
+ Debug.debug(this.toString());
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegUtils.java Fri Sep 10 16:33:35 2010
@@ -27,184 +27,184 @@ import org.apache.sanselan.util.Debug;
public class JpegUtils extends BinaryFileParser implements JpegConstants
{
- public JpegUtils()
- {
- setByteOrder(BYTE_ORDER_NETWORK);
- }
-
- public static interface Visitor
- {
- // return false to exit before reading image data.
- public boolean beginSOS();
-
- public void visitSOS(int marker, byte markerBytes[], byte imageData[]);
-
- // return false to exit traversal.
- public boolean visitSegment(int marker, byte markerBytes[],
- int segmentLength, byte segmentLengthBytes[],
- byte segmentData[]) throws ImageReadException,
- // ImageWriteException,
- IOException;
- }
-
- public void traverseJFIF(ByteSource byteSource, Visitor visitor)
- throws ImageReadException,
- // ImageWriteException,
- IOException
- {
- InputStream is = null;
-
- try
- {
- is = byteSource.getInputStream();
-
- readAndVerifyBytes(is, SOI,
- "Not a Valid JPEG File: doesn't begin with 0xffd8");
-
- int byteOrder = getByteOrder();
-
- for (int markerCount = 0; true; markerCount++)
- {
- byte markerBytes[] = readByteArray("markerBytes", 2, is,
- "markerBytes");
- int marker = convertByteArrayToShort("marker", markerBytes,
- byteOrder);
-
-// Debug.debug("marker", marker + " (0x" + Integer.toHexString(marker) + ")");
-// Debug.debug("markerBytes", markerBytes);
-
- if (marker == 0xffd9 || marker == SOS_Marker)
- {
- if (!visitor.beginSOS())
- return;
-
- byte imageData[] = getStreamBytes(is);
- visitor.visitSOS(marker, markerBytes, imageData);
- break;
- }
-
- byte segmentLengthBytes[] = readByteArray("segmentLengthBytes",
- 2, is, "segmentLengthBytes");
- int segmentLength = convertByteArrayToShort("segmentLength",
- segmentLengthBytes, byteOrder);
-
-// Debug.debug("segmentLength", segmentLength + " (0x" + Integer.toHexString(segmentLength) + ")");
-// Debug.debug("segmentLengthBytes", segmentLengthBytes);
-
- byte segmentData[] = readByteArray("Segment Data",
- segmentLength - 2, is,
- "Invalid Segment: insufficient data");
-
- // Debug.debug("segmentLength", segmentLength);
-
- if (!visitor.visitSegment(marker, markerBytes, segmentLength,
- segmentLengthBytes, segmentData))
- return;
- }
-
- } finally
- {
- try
- {
- if (is != null) {
- is.close();
- }
- } catch (Exception e)
- {
- Debug.debug(e);
- }
- }
- }
-
- public static String getMarkerName(int marker)
- {
- switch (marker)
- {
- case SOS_Marker:
- return "SOS_Marker";
- // case JPEG_APP0 :
- // return "JPEG_APP0";
- // case JPEG_APP0_Marker :
- // return "JPEG_APP0_Marker";
- case JPEG_APP1_Marker:
- return "JPEG_APP1_Marker";
- case JPEG_APP2_Marker:
- return "JPEG_APP2_Marker";
- case JPEG_APP13_Marker:
- return "JPEG_APP13_Marker";
- case JPEG_APP14_Marker:
- return "JPEG_APP14_Marker";
- case JPEG_APP15_Marker:
- return "JPEG_APP15_Marker";
- case JFIFMarker:
- return "JFIFMarker";
- case SOF0Marker:
- return "SOF0Marker";
- case SOF1Marker:
- return "SOF1Marker";
- case SOF2Marker:
- return "SOF2Marker";
- case SOF3Marker:
- return "SOF3Marker";
- case SOF4Marker:
- return "SOF4Marker";
- case SOF5Marker:
- return "SOF5Marker";
- case SOF6Marker:
- return "SOF6Marker";
- case SOF7Marker:
- return "SOF7Marker";
- case SOF8Marker:
- return "SOF8Marker";
- case SOF9Marker:
- return "SOF9Marker";
- case SOF10Marker:
- return "SOF10Marker";
- case SOF11Marker:
- return "SOF11Marker";
- case SOF12Marker:
- return "SOF12Marker";
- case SOF13Marker:
- return "SOF13Marker";
- case SOF14Marker:
- return "SOF14Marker";
- case SOF15Marker:
- return "SOF15Marker";
- default:
- return "Unknown";
- }
- }
-
- public void dumpJFIF(ByteSource byteSource) throws ImageReadException,
- IOException, ImageWriteException
- {
- Visitor visitor = new Visitor() {
- // return false to exit before reading image data.
- public boolean beginSOS()
- {
- return true;
- }
-
- public void visitSOS(int marker, byte markerBytes[],
- byte imageData[])
- {
- Debug.debug("SOS marker. " + imageData.length
- + " bytes of image data.");
- Debug.debug("");
- }
-
- // return false to exit traversal.
- public boolean visitSegment(int marker, byte markerBytes[],
- int segmentLength, byte segmentLengthBytes[],
- byte segmentData[])
- {
- Debug.debug("Segment marker: " + Integer.toHexString(marker)
- + " (" + getMarkerName(marker) + "), "
- + segmentData.length + " bytes of segment data.");
- return true;
- }
- };
+ public JpegUtils()
+ {
+ setByteOrder(BYTE_ORDER_NETWORK);
+ }
+
+ public static interface Visitor
+ {
+ // return false to exit before reading image data.
+ public boolean beginSOS();
+
+ public void visitSOS(int marker, byte markerBytes[], byte imageData[]);
+
+ // return false to exit traversal.
+ public boolean visitSegment(int marker, byte markerBytes[],
+ int segmentLength, byte segmentLengthBytes[],
+ byte segmentData[]) throws ImageReadException,
+ // ImageWriteException,
+ IOException;
+ }
+
+ public void traverseJFIF(ByteSource byteSource, Visitor visitor)
+ throws ImageReadException,
+ // ImageWriteException,
+ IOException
+ {
+ InputStream is = null;
+
+ try
+ {
+ is = byteSource.getInputStream();
+
+ readAndVerifyBytes(is, SOI,
+ "Not a Valid JPEG File: doesn't begin with 0xffd8");
+
+ int byteOrder = getByteOrder();
+
+ for (int markerCount = 0; true; markerCount++)
+ {
+ byte markerBytes[] = readByteArray("markerBytes", 2, is,
+ "markerBytes");
+ int marker = convertByteArrayToShort("marker", markerBytes,
+ byteOrder);
+
+// Debug.debug("marker", marker + " (0x" + Integer.toHexString(marker) + ")");
+// Debug.debug("markerBytes", markerBytes);
+
+ if (marker == 0xffd9 || marker == SOS_Marker)
+ {
+ if (!visitor.beginSOS())
+ return;
+
+ byte imageData[] = getStreamBytes(is);
+ visitor.visitSOS(marker, markerBytes, imageData);
+ break;
+ }
+
+ byte segmentLengthBytes[] = readByteArray("segmentLengthBytes",
+ 2, is, "segmentLengthBytes");
+ int segmentLength = convertByteArrayToShort("segmentLength",
+ segmentLengthBytes, byteOrder);
+
+// Debug.debug("segmentLength", segmentLength + " (0x" + Integer.toHexString(segmentLength) + ")");
+// Debug.debug("segmentLengthBytes", segmentLengthBytes);
+
+ byte segmentData[] = readByteArray("Segment Data",
+ segmentLength - 2, is,
+ "Invalid Segment: insufficient data");
+
+ // Debug.debug("segmentLength", segmentLength);
+
+ if (!visitor.visitSegment(marker, markerBytes, segmentLength,
+ segmentLengthBytes, segmentData))
+ return;
+ }
+
+ } finally
+ {
+ try
+ {
+ if (is != null) {
+ is.close();
+ }
+ } catch (Exception e)
+ {
+ Debug.debug(e);
+ }
+ }
+ }
+
+ public static String getMarkerName(int marker)
+ {
+ switch (marker)
+ {
+ case SOS_Marker:
+ return "SOS_Marker";
+ // case JPEG_APP0 :
+ // return "JPEG_APP0";
+ // case JPEG_APP0_Marker :
+ // return "JPEG_APP0_Marker";
+ case JPEG_APP1_Marker:
+ return "JPEG_APP1_Marker";
+ case JPEG_APP2_Marker:
+ return "JPEG_APP2_Marker";
+ case JPEG_APP13_Marker:
+ return "JPEG_APP13_Marker";
+ case JPEG_APP14_Marker:
+ return "JPEG_APP14_Marker";
+ case JPEG_APP15_Marker:
+ return "JPEG_APP15_Marker";
+ case JFIFMarker:
+ return "JFIFMarker";
+ case SOF0Marker:
+ return "SOF0Marker";
+ case SOF1Marker:
+ return "SOF1Marker";
+ case SOF2Marker:
+ return "SOF2Marker";
+ case SOF3Marker:
+ return "SOF3Marker";
+ case SOF4Marker:
+ return "SOF4Marker";
+ case SOF5Marker:
+ return "SOF5Marker";
+ case SOF6Marker:
+ return "SOF6Marker";
+ case SOF7Marker:
+ return "SOF7Marker";
+ case SOF8Marker:
+ return "SOF8Marker";
+ case SOF9Marker:
+ return "SOF9Marker";
+ case SOF10Marker:
+ return "SOF10Marker";
+ case SOF11Marker:
+ return "SOF11Marker";
+ case SOF12Marker:
+ return "SOF12Marker";
+ case SOF13Marker:
+ return "SOF13Marker";
+ case SOF14Marker:
+ return "SOF14Marker";
+ case SOF15Marker:
+ return "SOF15Marker";
+ default:
+ return "Unknown";
+ }
+ }
+
+ public void dumpJFIF(ByteSource byteSource) throws ImageReadException,
+ IOException, ImageWriteException
+ {
+ Visitor visitor = new Visitor() {
+ // return false to exit before reading image data.
+ public boolean beginSOS()
+ {
+ return true;
+ }
+
+ public void visitSOS(int marker, byte markerBytes[],
+ byte imageData[])
+ {
+ Debug.debug("SOS marker. " + imageData.length
+ + " bytes of image data.");
+ Debug.debug("");
+ }
+
+ // return false to exit traversal.
+ public boolean visitSegment(int marker, byte markerBytes[],
+ int segmentLength, byte segmentLengthBytes[],
+ byte segmentData[])
+ {
+ Debug.debug("Segment marker: " + Integer.toHexString(marker)
+ + " (" + getMarkerName(marker) + "), "
+ + segmentData.length + " bytes of segment data.");
+ return true;
+ }
+ };
- traverseJFIF(byteSource, visitor);
- }
+ traverseJFIF(byteSource, visitor);
+ }
}
\ No newline at end of file