package org.hipi.image.io;
import org.hipi.image.HipiImageHeader;
import org.hipi.image.HipiImageHeader.HipiImageFormat;
import org.hipi.image.HipiImageHeader.HipiColorSpace;
import org.hipi.image.HipiImage;
import org.hipi.image.HipiImage.HipiImageType;
import org.hipi.image.RasterImage;
import org.hipi.image.HipiImageFactory;
import org.hipi.image.PixelArray;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.HashMap;
import javax.imageio.IIOImage;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
/**
* Abstract base class for objects that serve as both an {@link ImageDecoder} and
* {@link ImageEncoder} for a particular storage format (e.g., JPEG, PNG, etc.).
*/
public abstract class ImageCodec implements ImageDecoder, ImageEncoder {
public HipiImageHeader decodeHeader(InputStream inputStream)
throws IOException {
return decodeHeader(inputStream, false);
}
public HipiImage decodeHeaderAndImage(InputStream inputStream,
HipiImageFactory imageFactory, boolean includeExifData)
throws IOException, IllegalArgumentException
{
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
bufferedInputStream.mark(Integer.MAX_VALUE);
HipiImageHeader header = decodeHeader(bufferedInputStream, includeExifData);
bufferedInputStream.reset();
return decodeImage(bufferedInputStream, header, imageFactory, false);
}
/**
* Default image decode method that uses the available ImageIO plugins.
*
* @see ImageDecoder#decodeImage
*/
public HipiImage decodeImage(InputStream inputStream, HipiImageHeader imageHeader,
HipiImageFactory imageFactory, boolean includeExifData)
throws IllegalArgumentException, IOException {
// Verify image factory
if (!(imageFactory.getType() == HipiImageType.FLOAT || imageFactory.getType() == HipiImageType.BYTE)) {
throw new IllegalArgumentException("Image decoder supports only FloatImage and ByteImage output types.");
}
DataInputStream dis = new DataInputStream(new BufferedInputStream(inputStream));
dis.mark(Integer.MAX_VALUE);
// Find suitable ImageIO plugin (should be TwelveMonkeys)
BufferedImage javaImage = ImageIO.read(dis);//inputStream);
int w = javaImage.getWidth();
int h = javaImage.getHeight();
// Check that image dimensions in header match those in JPEG
if (w != imageHeader.getWidth() || h != imageHeader.getHeight()) {
System.out.println(String.format("Dimensions read from JPEG: %d x %d", w, h));
System.out.println(imageHeader);
throw new IllegalArgumentException("Image dimensions in header do not match those in JPEG.");
}
// Create output image
RasterImage image = null;
try {
image = (RasterImage)imageFactory.createImage(imageHeader);
} catch (Exception e) {
System.err.println(String.format("Fatal error while creating image object [%s]", e.getMessage()));
e.printStackTrace();
System.exit(1);
}
PixelArray pa = image.getPixelArray();
for (int j=0; j<h; j++) {
for (int i=0; i<w; i++) {
// Retrieve 8-bit non-linear sRGB value packed into int
int pixel = javaImage.getRGB(i,j);
int red = (pixel >> 16) & 0xff;
int grn = (pixel >> 8) & 0xff;
int blu = (pixel ) & 0xff;
// Set value in pixel array using routine designed for sRGB values
pa.setElemNonLinSRGB((j*w+i)*3+0, red);
pa.setElemNonLinSRGB((j*w+i)*3+1, grn);
pa.setElemNonLinSRGB((j*w+i)*3+2, blu);
}
}
if (includeExifData) {
// Extract EXIF data from image stream and store in image header
dis.reset();
try {
imageHeader.setExifData(ExifDataReader.extractAndFlatten(dis));
} catch (IOException ex) {
System.err.println("Failed to extract EXIF data for image record.");
}
}
return image;
}
/**
* Default method for encoding raster images that uses the available ImageIO plugins.
*/
protected void encodeRasterImage(RasterImage image, ImageWriter writer,
ImageWriteParam writeParams) throws IOException {
int w = image.getWidth();
int h = image.getHeight();
BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
PixelArray pa = image.getPixelArray();
int[] rgb = new int[w*h];
for (int i=0; i<w*h; i++) {
int r = pa.getElemNonLinSRGB(i*3+0);
int g = pa.getElemNonLinSRGB(i*3+1);
int b = pa.getElemNonLinSRGB(i*3+2);
rgb[i] = (r << 16) | (g << 8) | b;
}
bufferedImage.setRGB(0, 0, w, h, rgb, 0, w);
IIOImage iioImage = new IIOImage(bufferedImage, null, null);
writer.write(null, iioImage, writeParams);
}
}