package com.idega.block.image.business;
import java.awt.Canvas;
import java.awt.Image;
import java.awt.image.ImageProducer;
import java.awt.image.renderable.ParameterBlock;
import java.awt.image.renderable.RenderableImage;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import com.idega.business.IBOServiceBean;
import com.idega.graphics.encoder.gif.Gif89Encoder;
import com.sun.jimi.core.Jimi;
import com.sun.jimi.core.JimiException;
import com.sun.jimi.core.JimiReader;
import com.sun.jimi.core.options.GIFOptions;
import com.sun.jimi.core.raster.JimiRasterImage;
import com.sun.media.jai.codec.BMPEncodeParam;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncodeParam;
import com.sun.media.jai.codec.JPEGEncodeParam;
import com.sun.media.jai.codec.MemoryCacheSeekableStream;
import com.sun.media.jai.codec.PNGEncodeParam;
import com.sun.media.jai.codec.PNMEncodeParam;
import com.sun.media.jai.codec.TIFFEncodeParam;
/*
public static void main(String[] args) {
//Collection coll = Arrays.asList(RegistryMode.getModeNames());
Collection coll = Arrays.asList(JAI.getDefaultInstance().getOperationRegistry().getDescriptorNames("rendered"));
Iterator iterator = coll.iterator();
while (iterator.hasNext()) {
System.out.println((String)iterator.next());
}
}
/**
* *
*
* Title: idegaWeb
* Description: This class provides methodes to encode images.
*
* Copyright: Copyright (c) 2003
* Company: idega software
* @author <a href="mailto:thomas@idega.is">Thomas Hilbig</a>
* @version 1.0
*/
public class ImageEncoderBean extends IBOServiceBean implements com.idega.block.image.business.ImageEncoder {
// for gif images we have a special encoder
private final static String GIF = "gif";
private final static String PNG = "png";
private final static String PNM = "pnm";
private final static String TIFF = "tiff";
private final static String BMP = "bmp";
private final static String JPEG = "jpeg";
private static final String[] FILE_EXTENSIONS = {
GIF, "gif",
PNG, "png",
JPEG, "jpg",
TIFF, "tif",
BMP, "bmp"
};
private static final String[] MIME_TYPES_FOR_JAI = {
PNG, JPEG, TIFF, BMP };
private static final String[] IMAGES_TYPES = {
// description,
// mime type, mimetype, converted to mimetype
"GIF",
"image/gif", GIF, GIF,
// "X-Windows bitmap (b/w) xbm",
// "image/x-xbitmap", "xbm", "",
// "X-Windows pixelmap (8-bit color) xpm",
// "image/x-xpix", "xpm", "",
"Portable Network Graphics png",
"image/x-png", PNG, PNG,
"Portable Network Graphics png",
"image/png", PNG, PNG,
// "Image Exchange Format (RFC 1314) ief",
// "image/ief", "ief", "", "", "",
"JPEG jpeg jpg jpe pjpeg",
"image/jpeg", JPEG, JPEG,
"JPEG jpeg jpg jpe pjpeg",
"image/pjpeg", JPEG, JPEG,
"JPEG jpeg jpg jpe pjpeg",
"image/jpg", JPEG, JPEG,
"JPEG jpeg jpg jpe pjpeg",
"image/jpe", JPEG, JPEG,
"TIFF tiff tif",
"image/tiff", TIFF, TIFF,
// "Macintosh PICT format pict",
// "image/x-pict"
// "Macintosh PICT format pict",
// "image/pict",
"Microsoft Windows bitmap bmp",
"image/x-ms-bmp", BMP, JPEG,
"Microsoft Windows bitmap bmp",
"image/bmp", BMP, JPEG,
"Microsoft Windows bitmap bmp",
"image/x-bmp", BMP, JPEG
// "pcx image", "image/pcx",
// "iff image", "image/iff",
// "ras image", "image/ras",
// "portable-bitmap image", "image/x-portable-bitmap",
// "portable-graymap image", "image/x-portable-graymap",
// "portable-pixmap image", "image/x-portable-pixmap"
};
//1.0 best quality 0.75 high quality 0.5 medium quality 0.25 low quality 0.10 crappy quality
private final static float JPEG_QUALITY = 1.00f;
private HashMap mimeTypes;
private HashMap extensionTypes;
private HashMap mimeTypesForJai;
public ImageEncoderBean() {
this.extensionTypes = initializeFileExtension();
this.mimeTypes = initializeMimeTypes();
this.mimeTypesForJai = initializeJaiMimeValues();
}
private HashMap initializeJaiMimeValues() {
HashMap mimeTypeForJai = new HashMap();
ArrayList list = new ArrayList();
Enumeration enumer = ImageCodec.getCodecs();
while (enumer.hasMoreElements()) {
ImageCodec codec = (ImageCodec) enumer.nextElement();
list.add(codec.getFormatName());
}
int i;
String mimeTypeKey;
String jaiMimeType;
for (i= 0; i < MIME_TYPES_FOR_JAI.length; i++) {
mimeTypeKey = MIME_TYPES_FOR_JAI[i];
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
jaiMimeType = (String) iterator.next();
if (jaiMimeType.indexOf(mimeTypeKey) > -1) {
mimeTypeForJai.put(mimeTypeKey, jaiMimeType);
break;
}
}
}
return mimeTypeForJai;
}
private HashMap initializeMimeTypes() {
int size = IMAGES_TYPES.length;
HashMap map = new HashMap(size);
int i = 0;
while (i < size) {
i++; // skip description
int key = i++; // get mime type as key
String[] shortArray = new String[2];
shortArray[0] = IMAGES_TYPES[i++]; // get mime type for this class
shortArray[1] = IMAGES_TYPES[i++]; // get converted to this mime type
map.put(IMAGES_TYPES[key], shortArray);
}
return map;
}
private HashMap initializeFileExtension() {
int size = FILE_EXTENSIONS.length;
HashMap map = new HashMap(size);
int i = 0;
while (i < size) {
map.put(FILE_EXTENSIONS[i++],FILE_EXTENSIONS[i++]);
}
return map;
}
public void encode(String mimeType, InputStream input, OutputStream output, int width, int heigth) throws IOException {
String resultMime = getResultMimeTypeForInputMimeType(mimeType);
String formatedInputMime = getFormatedMimeType(mimeType);
if (ImageEncoder.UNKNOWN_MIME_TYPE.equals(resultMime) ||
ImageEncoder.UNKNOWN_MIME_TYPE.equals(formatedInputMime)) {
throw new IOException("Mime type "+ mimeType + " is not recognized");
}
else if (GIF.equals(formatedInputMime)) {
handleSpecialMimeTypGIF(input, output, width, heigth);
}
else {
handleMimeType(formatedInputMime, resultMime, input, output, width, heigth);
}
output.flush();
}
/**
* Method getFormatedMimeType.
* @param mimeType
* @return String
*/
private String getFormatedMimeType(String mimeType) {
return getValueForMimeType(mimeType, 0, ImageEncoder.UNKNOWN_MIME_TYPE );
}
public boolean isInputTypeEqualToResultType(String mimeType) {
String formatedMimeType = getFormatedMimeType(mimeType);
if (UNKNOWN_MIME_TYPE.equals(formatedMimeType)) {
return false;
}
return formatedMimeType.equals(getResultMimeTypeForInputMimeType(mimeType));
}
public String getResultMimeTypeForInputMimeType(String inputMimeType) {
return getValueForMimeType(inputMimeType, 1, ImageEncoder.UNKNOWN_MIME_TYPE );
}
public String getResultFileExtensionForInputMimeType(String inputMimeType) {
return getExtensionForFormatedMimeType( getResultMimeTypeForInputMimeType(inputMimeType));
}
private String getValueForMimeType(String mimeType, int index, String errorString) {
String[] shortArray = (String[]) this.mimeTypes.get(mimeType);
if (shortArray == null) {
return errorString;
}
return shortArray[index];
}
private String getExtensionForFormatedMimeType(String formatedMimeType) {
String extension = (String)this.extensionTypes.get(formatedMimeType);
if (extension == null) {
return ImageEncoder.INVALID_FILE_EXTENSION;
}
return extension;
}
private String getMimeTypeForJai(String formatedMimeType) {
String result = (String) this.mimeTypesForJai.get(formatedMimeType);
if (result == null) {
return ImageEncoder.UNKNOWN_MIME_TYPE;
}
return result;
}
public static void main(String[] args) {
//Collection coll = Arrays.asList(RegistryMode.getModeNames());
//Collection coll = Arrays.asList(JAI.getDefaultInstance().getOperationRegistry().getDescriptorNames("rendered"));
Enumeration enumer = ImageCodec.getCodecs();
while (enumer.hasMoreElements()) {
ImageCodec codec = (ImageCodec) enumer.nextElement();
String name = codec.getFormatName();
System.out.println(name);
}
}
/**
* Creates new image with the desired width and height and encodes it into a image using the
* passed mime type. Writes it to the passed output stream.
* The input stream should be a image with the same mimetype.
* The implementation uses the JAI library.
* @param mimeType
* @param outputMimeType
* @param input
* @param output
* @param width
* @param heigth
*/
private void handleMimeType (String inputMimeType,
String outputMimeType,
InputStream input,
OutputStream output,
int width,
int heigth) throws IOException {
PlanarImage image = JAI.create("stream",new MemoryCacheSeekableStream(new BufferedInputStream(input)));
// scale image
PlanarImage modifiedImage = createImageWithSize(image,width, heigth);
ImageEncodeParam encodeParam = getEncoderParam(inputMimeType, outputMimeType, image);
com.sun.media.jai.codec.ImageEncoder imageEncoder;
String jaiMimeType = getMimeTypeForJai(outputMimeType);
if (ImageEncoder.UNKNOWN_MIME_TYPE.equals(jaiMimeType)) {
throw new IOException("Mime type "+ outputMimeType + " not recognized by JAI");
}
imageEncoder = ImageCodec.createImageEncoder(jaiMimeType , output, encodeParam);
imageEncoder.encode(modifiedImage);
}
private PlanarImage createImageWithSize(PlanarImage originalImage, int width, int height) {
ParameterBlock pb = new ParameterBlock();
pb.addSource(originalImage);
//WTF??
pb.add(null).add(null).add(null).add(null).add(null);
RenderableImage ren = JAI.createRenderable("renderable", pb);
return (PlanarImage) ren.createScaledRendering(width, height, null);
}
/**
* Creates new image with the desired width and height and encodes it into a GIF image and writes
* it to the passed output stream. The input stream must be a GIF image.
* Animation and transparency are preserved.
* The implementation uses the Jimi library and the jmge library.
* @param input
* @param output
* @param width
* @param heigth
*/
private void handleSpecialMimeTypGIF(InputStream input, OutputStream output, int width, int height) throws IOException {
// open the animated picture with a JimiReader for control of individual frames
JimiReader reader;
try {
reader = Jimi.createJimiReader(input);
}
catch (JimiException jimiException) {
System.err.println("Error while reading source " + jimiException.getMessage());
return;
}
Gif89Encoder gifenc = new Gif89Encoder();
Canvas cv = new Canvas();
Enumeration enumer = reader.getRasterImageEnumeration();
JimiRasterImage rasterImage;
ImageProducer imageProducer;
Image image;
Image scaledImage;
GIFOptions options;
int loops = 1;
int delay = 1;
boolean notSetYet = true;
while (enumer.hasMoreElements()) {
rasterImage = (JimiRasterImage) enumer.nextElement();
imageProducer = rasterImage.getImageProducer();
image = cv.createImage(imageProducer);
scaledImage = image.getScaledInstance(width,height,Image.SCALE_DEFAULT);
gifenc.addFrame(scaledImage);
if (notSetYet) {
options = (GIFOptions) rasterImage.getOptions();
loops = options.getNumberOfLoops();
delay = options.getFrameDelay();
notSetYet = false;
}
}
gifenc.setLoopCount(loops);
gifenc.setUniformDelay(delay);
gifenc.encode(output);
}
private ImageEncodeParam getEncoderParam(String inputMimeType, String outputMimeType, PlanarImage image) {
ImageEncodeParam para = null;
if (JPEG.equals(outputMimeType)) {
para = new JPEGEncodeParam();
// if the image is converted to jpeg set quality
if (! JPEG.equals(inputMimeType)) {
((JPEGEncodeParam) para).setQuality(JPEG_QUALITY);
}
}
else if (PNG.equals(outputMimeType)) {
para = PNGEncodeParam.getDefaultEncodeParam(image);
}
else if (PNM.equals(outputMimeType)) {
para = new PNMEncodeParam();
}
else if (TIFF.equals(outputMimeType)) {
para = new TIFFEncodeParam();
}
else if (BMP.equals(outputMimeType)) {
para = new BMPEncodeParam();
}
return para;
}
}