blob: 5c5d4896271edf81a40445a8ed69135b39e27b54 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.imaging.formats.jpeg;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.common.BinaryFileParser;
import org.apache.commons.imaging.common.bytesource.ByteSource;
import org.apache.commons.imaging.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 = new byte[2];
do {
markerBytes[0] = markerBytes[1];
markerBytes[1] = readByte("marker", is, "Could not read marker");
} while ((0xff & markerBytes[0]) != 0xff || (0xff & markerBytes[1]) == 0xff);
int marker = ((0xff & markerBytes[0]) << 8) | (0xff & markerBytes[1]);
// Debug.debug("marker", marker + " (0x" + Integer.toHexString(marker) + ")");
// Debug.debug("markerBytes", markerBytes);
if (marker == EOIMarker || 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 DHTMarker:
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 DACMarker:
return "DACMarker";
case SOF13Marker:
return "SOF13Marker";
case SOF14Marker:
return "SOF14Marker";
case SOF15Marker:
return "SOF15Marker";
case DQTMarker:
return "DQTMarker";
default:
return "Unknown";
}
}
public void dumpJFIF(ByteSource byteSource) throws ImageReadException,
IOException
{
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);
}
}