package org.imixs.marty.ejb;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.PropertyService;
/**
* This Intercepter class provides a mechanism to resize new uploaded images
* (.jpg).
* The behavior can be configured through the imixs.property file.
*
*
* image.maxWidth = maximal width of a image, indicates if a image should be resized.
* image.fileExtension = indicates the file extension for images and photos
*
*
* @version 1.0
* @author rsoika
*
*/
public class ImageInterceptor {
private static Logger logger = Logger.getLogger(ImageInterceptor.class.getName());
private int imageMaxWidth;
@EJB
PropertyService propertyService;
/**
* The interceptor method tests if new files were uploaded.
*
* The interceptor runns only in a save method
*
* @param ctx
* @return
* @throws Exception
*/
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
// test method name
String sMethod = ctx.getMethod().getName();
if ("save".equals(sMethod)) {
// get workitem....
Object[] params = ctx.getParameters();
ItemCollection workitem = (ItemCollection) params[0];
if (workitem != null
&& "workitemlob"
.equals(workitem.getItemValueString("Type"))) {
Properties prop = propertyService.getProperties();
String sMaxWidth = prop.getProperty("image.maxWidth",
"1024");
try {
imageMaxWidth = Integer.parseInt(sMaxWidth);
} catch (NumberFormatException ne) {
logger.warning("ImageInterceptor can not parse property 'image.maxwidth'! "
+ ne.getMessage());
imageMaxWidth = 1024;
}
logger.finest("Image Interceptor started");
List<String> filenames = workitem.getFileNames();
for (String fileName : filenames) {
if (isPhoto(fileName)) {
// photolist.add(filename);
logger.fine("ImageInterceptor testing new photo: " + fileName);
BufferedImage originalImage = getImageFromWorkitem(
workitem, fileName);
// test if max with is extended?
if (originalImage.getWidth() > imageMaxWidth) {
logger.info("ImageInterceptor rezise new photo: " + fileName);
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB
: originalImage.getType();
// resize Image
BufferedImage resizeImageHintJpg = resizeImageWithHint(
originalImage, type);
if (resizeImageHintJpg != null) {
// write image back...
/*
ImageIO.write(
resizeImageHintJpg,
getFormatName(fileName),
new File(
"/home/rsoika/Downloads/mkyong_hint_jpg.jpg"));
*/
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( resizeImageHintJpg, getFormatName(fileName), baos );
baos.flush();
byte[] imageInByte = baos.toByteArray();
baos.close();
// update workitem
replaceImage(workitem, fileName,imageInByte) ;
}
}
}
}
}
}
return ctx.proceed();
}
/**
* Retruns true if name ends of a known extension. Default is 'jpg'
*
* @param aname
* @return
*/
public boolean isPhoto(String aname) {
if (aname == null)
return false;
Properties prop = propertyService.getProperties();
String fileExtentions = prop.getProperty("image.fileExtension",
"jpg,JPEG");
StringTokenizer st = new StringTokenizer(fileExtentions, ",");
while (st.hasMoreElements()) {
String sExtention = st.nextToken().toLowerCase();
if (aname.toLowerCase().endsWith(sExtention))
return true;
}
return false;
}
private BufferedImage resizeImageWithHint(BufferedImage originalImage,
int type) {
// compute hight...
float width = originalImage.getWidth();
float height = originalImage.getHeight();
float factor = (float) width / (float) imageMaxWidth;
int newHeight = (int) (height / factor);
BufferedImage resizedImage = new BufferedImage(imageMaxWidth,
newHeight, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, imageMaxWidth, newHeight, null);
g.dispose();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
return resizedImage;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private BufferedImage getImageFromWorkitem(ItemCollection workItem,
String file) {
Map mapFiles = null;
List vFiles = workItem.getItemValue("$file");
if (vFiles != null && vFiles.size() > 0) {
mapFiles = (Map) vFiles.get(0);
List<Object> fileInfoList = new Vector<Object>();
fileInfoList = (List<Object>) mapFiles.get(file);
if (fileInfoList != null) {
@SuppressWarnings("unused")
String sContentType = fileInfoList.get(0).toString();
byte[] fileContent = (byte[]) fileInfoList.get(1);
try {
Iterator<ImageReader> inReaders = ImageIO
.getImageReadersByFormatName(getFormatName(file));
ImageReader imageReader = (ImageReader) inReaders.next();
ImageInputStream iis = ImageIO
.createImageInputStream(new ByteArrayInputStream(
fileContent));
imageReader.setInput(iis);
BufferedImage originalImage = imageReader.read(0);
return originalImage;
} catch (IOException e) {
logger.severe("ImageInerceptor - unable to load image from workitem : "
+ e.getMessage());
e.printStackTrace();
}
}
}
return null;
}
private String getFormatName(String aFilename) {
if (aFilename.indexOf('.')==-1)
return null;
String inFormat = aFilename.substring(aFilename.lastIndexOf('.') + 1);
return inFormat.toLowerCase();
}
/**
* This method replace the content of an image
* @param workItem
* @param file
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private void replaceImage(ItemCollection workItem,
String file, byte[] content) {
if (content==null)
return;
Map mapFiles = null;
List vFiles = workItem.getItemValue("$file");
if ( vFiles != null && vFiles.size() > 0) {
mapFiles = (Map) vFiles.get(0);
List<Object> fileInfoList = new Vector<Object>();
fileInfoList = (List<Object>) mapFiles.get(file);
if (fileInfoList != null) {
// replace new content...
fileInfoList.set(1, content);
mapFiles.put(file, fileInfoList);
}
}
// update file property...
Vector vNew=new Vector();
vNew.add(mapFiles);
workItem.replaceItemValue("$file", vNew);
}
}