}
System.out.println();
}
// Destination type, if there is one
ImageTypeSpecifier destType = null;
if (param != null) {
destType = param.getDestinationType();
// Ignore dest type if we are writing a complete image
if ((fullImage) && (destType != null)) {
warningOccurred(WARNING_DEST_IGNORED);
destType = null;
}
}
// Examine the param
sourceXOffset = srcRas.getMinX();
sourceYOffset = srcRas.getMinY();
int imageWidth = srcRas.getWidth();
int imageHeight = srcRas.getHeight();
sourceWidth = imageWidth;
sourceHeight = imageHeight;
int periodX = 1;
int periodY = 1;
int gridX = 0;
int gridY = 0;
JPEGQTable [] qTables = null;
JPEGHuffmanTable[] DCHuffmanTables = null;
JPEGHuffmanTable[] ACHuffmanTables = null;
boolean optimizeHuffman = false;
JPEGImageWriteParam jparam = null;
int progressiveMode = ImageWriteParam.MODE_DISABLED;
if (param != null) {
Rectangle sourceRegion = param.getSourceRegion();
if (sourceRegion != null) {
Rectangle imageBounds = new Rectangle(sourceXOffset,
sourceYOffset,
sourceWidth,
sourceHeight);
sourceRegion = sourceRegion.intersection(imageBounds);
sourceXOffset = sourceRegion.x;
sourceYOffset = sourceRegion.y;
sourceWidth = sourceRegion.width;
sourceHeight = sourceRegion.height;
}
if (sourceWidth + sourceXOffset > imageWidth) {
sourceWidth = imageWidth - sourceXOffset;
}
if (sourceHeight + sourceYOffset > imageHeight) {
sourceHeight = imageHeight - sourceYOffset;
}
periodX = param.getSourceXSubsampling();
periodY = param.getSourceYSubsampling();
gridX = param.getSubsamplingXOffset();
gridY = param.getSubsamplingYOffset();
switch(param.getCompressionMode()) {
case ImageWriteParam.MODE_DISABLED:
throw new IIOException("JPEG compression cannot be disabled");
case ImageWriteParam.MODE_EXPLICIT:
float quality = param.getCompressionQuality();
quality = JPEG.convertToLinearQuality(quality);
qTables = new JPEGQTable[2];
qTables[0] = JPEGQTable.K1Luminance.getScaledInstance
(quality, true);
qTables[1] = JPEGQTable.K2Chrominance.getScaledInstance
(quality, true);
break;
case ImageWriteParam.MODE_DEFAULT:
qTables = new JPEGQTable[2];
qTables[0] = JPEGQTable.K1Div2Luminance;
qTables[1] = JPEGQTable.K2Div2Chrominance;
break;
// We'll handle the metadata case later
}
progressiveMode = param.getProgressiveMode();
if (param instanceof JPEGImageWriteParam) {
jparam = (JPEGImageWriteParam)param;
optimizeHuffman = jparam.getOptimizeHuffmanTables();
}
}
// Now examine the metadata
IIOMetadata mdata = image.getMetadata();
if (mdata != null) {
if (mdata instanceof JPEGMetadata) {
metadata = (JPEGMetadata) mdata;
if (debug) {
System.out.println
("We have metadata, and it's JPEG metadata");
}
} else {
if (!rasterOnly) {
ImageTypeSpecifier type = destType;
if (type == null) {
type = new ImageTypeSpecifier(rimage);
}
metadata = (JPEGMetadata) convertImageMetadata(mdata,
type,
param);
} else {
warningOccurred(WARNING_METADATA_NOT_JPEG_FOR_RASTER);
}
}
}
// First set a default state
ignoreJFIF = false; // If it's there, use it
ignoreAdobe = false; // If it's there, use it
newAdobeTransform = JPEG.ADOBE_IMPOSSIBLE; // Change if needed
writeDefaultJFIF = false;
writeAdobe = false;
// By default we'll do no conversion:
int inCsType = JPEG.JCS_UNKNOWN;
int outCsType = JPEG.JCS_UNKNOWN;
JFIFMarkerSegment jfif = null;
AdobeMarkerSegment adobe = null;
SOFMarkerSegment sof = null;
if (metadata != null) {
jfif = (JFIFMarkerSegment) metadata.findMarkerSegment
(JFIFMarkerSegment.class, true);
adobe = (AdobeMarkerSegment) metadata.findMarkerSegment
(AdobeMarkerSegment.class, true);
sof = (SOFMarkerSegment) metadata.findMarkerSegment
(SOFMarkerSegment.class, true);
}
iccProfile = null; // By default don't write one
convertTosRGB = false; // PhotoYCC does this
converted = null;
if (destType != null) {
if (numBandsUsed != destType.getNumBands()) {
throw new IIOException
("Number of source bands != number of destination bands");
}
cs = destType.getColorModel().getColorSpace();
// Check the metadata against the destination type
if (metadata != null) {
checkSOFBands(sof, numBandsUsed);
checkJFIF(jfif, destType, false);
// Do we want to write an ICC profile?
if ((jfif != null) && (ignoreJFIF == false)) {
if (JPEG.isNonStandardICC(cs)) {
iccProfile = ((ICC_ColorSpace) cs).getProfile();
}
}
checkAdobe(adobe, destType, false);
} else { // no metadata, but there is a dest type
// If we can add a JFIF or an Adobe marker segment, do so
if (JPEG.isJFIFcompliant(destType, false)) {
writeDefaultJFIF = true;
// Do we want to write an ICC profile?
if (JPEG.isNonStandardICC(cs)) {
iccProfile = ((ICC_ColorSpace) cs).getProfile();
}
} else {
int transform = JPEG.transformForType(destType, false);
if (transform != JPEG.ADOBE_IMPOSSIBLE) {
writeAdobe = true;
newAdobeTransform = transform;
}
}
// re-create the metadata
metadata = new JPEGMetadata(destType, null, this);
}
inCsType = getSrcCSType(destType);
outCsType = getDefaultDestCSType(destType);
} else { // no destination type
if (metadata == null) {
if (fullImage) { // no dest, no metadata, full image
// Use default metadata matching the image and param
metadata = new JPEGMetadata(new ImageTypeSpecifier(rimage),
param, this);
if (metadata.findMarkerSegment
(JFIFMarkerSegment.class, true) != null) {
cs = rimage.getColorModel().getColorSpace();
if (JPEG.isNonStandardICC(cs)) {
iccProfile = ((ICC_ColorSpace) cs).getProfile();
}
}
inCsType = getSrcCSType(rimage);
outCsType = getDefaultDestCSType(rimage);
}
// else no dest, no metadata, not an image,
// so no special headers, no color conversion
} else { // no dest type, but there is metadata
checkSOFBands(sof, numBandsUsed);
if (fullImage) { // no dest, metadata, image
// Check that the metadata and the image match
ImageTypeSpecifier inputType =
new ImageTypeSpecifier(rimage);
inCsType = getSrcCSType(rimage);
if (cm != null) {
boolean alpha = cm.hasAlpha();