package is.idega.idegaweb.golf.block.image.business;
import is.idega.idegaweb.golf.block.image.data.ImageEntity;
import is.idega.idegaweb.golf.block.image.data.ImageEntityHome;
import java.awt.RenderingHints;
import java.awt.image.renderable.ParameterBlock;
import java.awt.image.renderable.RenderableImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.media.jai.JAI;
import javax.media.jai.KernelJAI;
import javax.media.jai.PlanarImage;
import com.idega.data.IDOLegacyEntity;
import com.idega.data.IDOLookup;
import com.idega.io.ImageSave;
import com.idega.presentation.IWContext;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.JPEGEncodeParam;
import com.sun.media.jai.codec.MemoryCacheSeekableStream;
/**
* Title: ImageHandler
* Description:
* Copyright: Copyright (c) 2000
* Company: idega
* @author Eirikur Hrafnsson
* @version 1.0
*
* Must seperate reading the image and resizing it for streams in the next version
*/
public class ImageHandler{
private PlanarImage originalImage = null;
private PlanarImage modifiedImage = null;
//private ImageDisplay canvas = null;
private boolean state = false;
private int imageId = -1;
private int modifiedImageId = -1;
private String contentType = null;
private String imageName = null;
private int width;
private int height;
private int scale = 1;
private int modifiedWidth = -1;
private int modifiedHeight = -1;
private float quality = 0.75f;
private boolean keepProportions = false;
private int brightness = 30;
private KernelJAI kernel;
private float sum = 9.0F;
private String modifiedImageURL="";
private int modifiedsize = 0;
private int modifiedImageCounter=1;
public ImageHandler( int imageId ) throws Exception{
setImageId(imageId);
getImageFromDatabase();
updateOriginalInfo();
setModifiedImageAsOriginal();
}
public ImageHandler( String fileName ) throws Exception{
getImageFromFile(fileName);
setModifiedImageAsOriginal();
}
public ImageHandler( PlanarImage originalImage, int ParentId ) throws Exception{
setImageId(ParentId);
setOriginalImage(originalImage);
setModifiedImageAsOriginal();
}
//crappy constructor fix this!
public ImageHandler( ImageEntity imageEntity ) throws Exception{
setImageId( imageEntity.getID() );
getImageFromDatabase();
updateOriginalInfo();
setModifiedImageAsOriginal();
}
private void getImageFromFile(String fileName) throws Exception{
File f = new File(fileName);
if ( f.exists() && f.canRead() ) {
originalImage = JAI.create("fileload", fileName);
} else {
System.err.println("The image \""+fileName+"\" does not exist or can't be read");
}
}
private void getImageFromDatabase() throws Exception{
//BlobWrapper wrapper = imageInfo.getImageValue();
/* BlobWrapper wrapper = new BlobWrapper(imageInfo,"image_value");
if( wrapper== null) System.out.println("ImageHandler: BlobWrapper is NULL!");
BlobInputStream inputStream = wrapper.getBlobInputStream();
*/
Connection Conn = null;
Statement Stmt;
ResultSet RS;
InputStream inputStream = null;
Conn = ((IDOLegacyEntity)IDOLookup.instanciateEntity(ImageEntity.class)).getConnection();
Stmt = Conn.createStatement();
RS = Stmt.executeQuery("select image_value from image where image_id="+getImageId());
while(RS.next()){
inputStream = RS.getBinaryStream("image_value");
}
modifiedsize = inputStream.available();
BufferedInputStream bufStream = getBufferedInputStream(inputStream);
MemoryCacheSeekableStream memStream = getMemoryCacheSeekableStream(bufStream);
originalImage = getPlanarImageFromStream(memStream);
System.out.println("ImageHandler: After JAI.create!");
setWidth(originalImage.getWidth());
setHeight(originalImage.getHeight());
System.out.println("ImageHandler: Before closing memStream");
memStream.close();
System.out.println("ImageHandler: Before closing bufferstream");
bufStream.close();
System.out.println("ImageHandler: Before closing inputstream");
inputStream.close();//closes the blobinputstream and closes misc stmt and connections
if( RS!=null ) RS.close();
if( Stmt!=null ) Stmt.close();
if( Conn!=null ) ((IDOLegacyEntity)IDOLookup.instanciateEntity(ImageEntity.class)).freeConnection(Conn);
System.out.println("ImageHandler: DONE!");
}
protected void updateOriginalInfo() throws SQLException{
ImageEntity imageInfo = (ImageEntity)((ImageEntityHome)IDOLookup.getHomeLegacy(ImageEntity.class)).findByPrimaryKeyLegacy( imageId );
setContentType( imageInfo.getContentType() );
setImageName( imageInfo.getName() );
imageInfo.setWidth(Integer.toString(originalImage.getWidth()));
imageInfo.setHeight(Integer.toString(originalImage.getHeight()));
imageInfo.setSize(modifiedsize);
// imageInfo.update();
}
private synchronized BufferedInputStream getBufferedInputStream(InputStream inputStream){
return (new BufferedInputStream(inputStream));
}
private synchronized MemoryCacheSeekableStream getMemoryCacheSeekableStream(BufferedInputStream bufStream){
return (new MemoryCacheSeekableStream(bufStream));
}
private synchronized PlanarImage getPlanarImageFromStream(MemoryCacheSeekableStream memStream){
return (JAI.create("stream", memStream));
}
protected void setOriginalImage(PlanarImage originalImage){
this.originalImage = originalImage;
setWidth(originalImage.getWidth());
setHeight(originalImage.getHeight());
}
private void setImageId( int imageId ){
this.imageId = imageId;
}
protected int getImageId(){
return this.imageId;
}
protected int getOriginalImageId(){
return getImageId();
}
protected void setBrightness( int brightness ){
this.brightness = brightness;
}
private int getBrightness(){
return this.brightness;
}
private void setModifiedImageId( int modifiedImageId ){
this.modifiedImageId = modifiedImageId;
}
public int getModifiedImageId(){
return this.modifiedImageId;
}
protected void setContentType( String contentType ){
this.contentType = contentType;
}
protected String getContentType(){
return this.contentType;
}
protected void setImageName( String imageName ){
this.imageName = imageName;
}
protected String getImageName(){
return this.imageName;
}
protected void setWidth( int width ){
this.width = width;
}
protected int getWidth(){
return this.width;
}
protected void setHeight( int height ){
this.height = height;
}
protected int getHeight(){
return this.height;
}
protected void setModifiedWidth( int modifiedWidth ){
this.modifiedWidth = modifiedWidth;
}
/*
*@todo make this protected and fix in ImageViewer
*/
public int getModifiedWidth(){
return this.modifiedWidth;
}
protected void setModifiedHeight( int modifiedHeight ){
this.modifiedHeight = modifiedHeight;
}
/*
*@todo make this protected and fix in ImageViewer
*/
public int getModifiedHeight(){
return this.modifiedHeight;
}
protected boolean keepProportions(){
return this.keepProportions;
}
protected void keepProportions(boolean keepProportions){
this.keepProportions = keepProportions;
}
private void setModifiedImageAttributes(){
int tempWidth = getModifiedWidth();
int tempHeight = getModifiedHeight();
//if tempWidth and tempHeight =-1 then we are scaling
if ( (tempWidth==-1) && (tempHeight ==-1) ){
setModifiedWidth(getWidth()*getScale());
setModifiedHeight(getHeight()*getScale());
}
else if( (tempWidth!=-1) && (tempHeight !=-1) ){//changed both
setModifiedWidth(tempWidth);
setModifiedHeight(tempHeight);
}
else {//we changed either the width or height
if ( tempWidth == -1 ){//missing width
if ( keepProportions() ) setModifiedWidth( (getWidth()*tempHeight)/getHeight());
else setModifiedWidth( getWidth() );
setModifiedHeight( tempHeight );
}
if( tempHeight == -1 ){//missing height
if ( keepProportions() ) setModifiedHeight( (getHeight()*tempWidth)/getWidth() );
else setModifiedHeight( getHeight() );
setModifiedWidth( tempWidth );
}
}
}
protected void resizeImage() throws Exception{
ParameterBlock pb = new ParameterBlock();
//pb.addSource(originalImage);
pb.addSource(getModifiedImage());
RenderableImage ren = JAI.createRenderable("renderable", pb);
setModifiedImageAttributes();
RenderingHints effect = new RenderingHints(RenderingHints.KEY_INTERPOLATION , RenderingHints.VALUE_INTERPOLATION_BILINEAR );
setModifiedImage((PlanarImage)ren.createScaledRendering(getModifiedWidth(), getModifiedHeight(), effect ));
/*
//try some rendering options
//RenderingHints effect = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//RenderingHints effect = new RenderingHints(RenderingHints.KEY_DITHERING , RenderingHints.VALUE_DITHER_ENABLE );
// RenderingHints effect = new RenderingHints(RenderingHints.KEY_DITHERING , RenderingHints.VALUE_DITHER_DISABLE );
*/
}
protected void convertModifiedImageToGrayscale(){
setModifiedImage(convertColorToGray(getModifiedImage(), getBrightness() ));
}
protected void convertModifiedImageToColor(){
setModifiedImage(convertGrayToColor(getModifiedImage(), getBrightness() ));
}
protected int getScale(){
return this.scale;
}
protected void setScale(int scale){
this.scale = scale;
}
protected void setModifiedImage( PlanarImage modifiedImage ){
this.modifiedImage = modifiedImage;
setModifiedWidth(modifiedImage.getWidth());
setModifiedHeight(modifiedImage.getHeight());
}
protected void setModifiedImageAsOriginal(){
this.setModifiedImage(originalImage);
setModifiedWidth(originalImage.getWidth());
setModifiedHeight(originalImage.getHeight());
}
protected PlanarImage getModifiedImage(){
return this.modifiedImage;
}
protected PlanarImage getOriginalImage(){
return this.originalImage;
}
/*
* 1.0 best quality 0.75 high quality 0.5 medium quality 0.25 low quality 0.10 crappy quality
*
*/
protected void setQuality(float quality){
this.quality = quality;
}
protected float getQuality(){
return this.quality;
}
public com.idega.presentation.Image getModifiedImageAsImageObject(IWContext modinfo) throws Exception{
if( modifiedImageCounter != 1 ) ImageBusiness.deleteImageFile(modifiedImageURL);
String seperator = System.getProperty("file.separator");
modifiedImageURL = modinfo.getServletContext().getRealPath(seperator)+seperator+"pics"+seperator+modinfo.getSession().getId()+"ModifiedImagetemp"+modifiedImageCounter+".jpg";
writeModifiedImageToFile(modifiedImageURL);//temporary storage
com.idega.presentation.Image image = new com.idega.presentation.Image(modifiedImageURL,getImageName(),getModifiedWidth(),getModifiedHeight());
modifiedImageCounter++;
return image;
}
protected void writeModifiedImageToDatabase(boolean update) throws Exception{
writeModifiedImageToFile(modifiedImageURL);//temporary storage
InputStream input = new FileInputStream(modifiedImageURL);
modifiedsize = input.available();
if(update){
ImageSave.saveImageToDataBase(getImageId(),-1,input,getContentType(),getImageName(),Integer.toString(getModifiedWidth()),Integer.toString(getModifiedHeight()), false);
}
else ImageSave.saveImageToDataBase(-1,getImageId(),input,getContentType(),getImageName(),Integer.toString(getModifiedWidth()),Integer.toString(getModifiedHeight()), true);
}
protected void writeModifiedImageToFile(String filename) throws Exception{
if ( filename.equalsIgnoreCase("")) filename = getImageName();
OutputStream output = new FileOutputStream(filename);
ImageEncoder imageEncoder;
if( getContentType().indexOf("bmp") != -1 ){
imageEncoder = ImageCodec.createImageEncoder("BMP", output, null);
}
else{
JPEGEncodeParam jpgParam = new JPEGEncodeParam();
jpgParam.setQuality(getQuality());
imageEncoder = ImageCodec.createImageEncoder("JPEG",output,jpgParam);
}
PlanarImage modified = getModifiedImage();
if ( modified != null) imageEncoder.encode( getModifiedImage() );
else System.out.println("getModifiedImage() returned null!");
output.flush();
output.close();
}
protected static PlanarImage convertColorToGray(PlanarImage src, int brightness) {
PlanarImage dst = null;
double b = (double) brightness;
double[][] matrix = {
{ .114D, 0.587D, 0.299D, b },
{ .114D, 0.587D, 0.299D, b },
{ .114D, 0.587D, 0.299D, b }
/* { .114D, 0.200D, 0.100D, b },//red
{ 0.05D, 0.700D, 0.050D, b },//green
{ .114D, 0.200D, 0.100D, b }//blue
//{HUE,SATURATION,CONTRAST,BRIGHTNESS)*/
};
if ( src != null ) {
ParameterBlock pb = new ParameterBlock();
pb.addSource(src);
pb.add(matrix);
dst = JAI.create("bandcombine", pb, null);
}
return dst;
}
/** produce a 3 band image from a single band gray scale image */
protected static PlanarImage convertGrayToColor(PlanarImage src, int brightness) {
PlanarImage dst = null;
double b = (double) brightness;
double[][] matrix = {
{ 1.0D, b },
{ 1.0D, b },
{ 1.0D, b }
};
if ( src != null ) {
int nbands = src.getSampleModel().getNumBands();
// MUST check color model here
if ( nbands == 1 ) {
ParameterBlock pb = new ParameterBlock();
pb.addSource(src);
pb.add(matrix);
dst = JAI.create("bandcombine", pb, null);
} else {
dst = src;
}
}
return dst;
}
protected void embossModifiedImage(){
loadKernel(8);
setModifiedImage( convolve(getModifiedImage(),8));
}
protected void blurModifiedImage(){
loadKernel(9);
setModifiedImage( convolve(getModifiedImage(),9));
}
protected void sharpenModifiedImage(){
loadKernel(2);
setModifiedImage( convolve(getModifiedImage(),2));
}
protected void invertModifiedImage(){
setModifiedImage( invert(getModifiedImage()));
}
protected PlanarImage invert(PlanarImage source) {
ParameterBlock pb = new ParameterBlock();
pb.addSource(source);
RenderableImage ren = JAI.createRenderable("renderable", pb);
pb = new ParameterBlock();
pb.addSource(ren);
RenderableImage inv = JAI.createRenderable("invert", pb);
PlanarImage dst = (PlanarImage)inv.createScaledRendering(source.getWidth(), source.getHeight(), null);
return dst;
}
private PlanarImage convolve(PlanarImage source, int k) {
ParameterBlock pb = new ParameterBlock();
pb.addSource(source);
pb.add(kernel);
PlanarImage target = JAI.create("convolve", pb, null);
// emboss (special case)
if ( k == 8 ) {
double[] constants = new double[3];
constants[0] = 128.0;
constants[1] = 128.0;
constants[2] = 128.0;
pb = new ParameterBlock();
pb.addSource(target);
pb.add(constants);
target = JAI.create("addconst", pb, null);
}
return target;
}
private void loadKernel(int choice) {
float[] data = new float[9];
switch( choice ) {
case 0:
data[0] = 0.0F; data[1] =-1.0F; data[2] = 0.0F;
data[3] =-1.0F; data[4] = 5.0F; data[5] =-1.0F;
data[6] = 0.0F; data[7] =-1.0F; data[8] = 0.0F;
break;
case 1:
data[0] =-1.0F; data[1] =-1.0F; data[2] =-1.0F;
data[3] =-1.0F; data[4] = 9.0F; data[5] =-1.0F;
data[6] =-1.0F; data[7] =-1.0F; data[8] =-1.0F;
break;
//sharpen very good
case 2:
data[0] = 1.0F; data[1] =-2.0F; data[2] = 1.0F;
data[3] =-2.0F; data[4] = 5.0F; data[5] =-2.0F;
data[6] = 1.0F; data[7] =-2.0F; data[8] = 1.0F;
break;
case 3:
data[0] =-1.0F; data[1] = 1.0F; data[2] =-1.0F;
data[3] = 1.0F; data[4] = 1.0F; data[5] = 1.0F;
data[6] =-1.0F; data[7] = 1.0F; data[8] =-1.0F;
break;
case 4:
data[0] =-1.0F; data[1] =-1.0F; data[2] =-1.0F;
data[3] =-1.0F; data[4] = 8.0F; data[5] =-1.0F;
data[6] =-1.0F; data[7] =-1.0F; data[8] =-1.0F;
break;
case 5:
data[0] = 0.0F; data[1] =-1.0F; data[2] = 0.0F;
data[3] =-1.0F; data[4] = 4.0F; data[5] =-1.0F;
data[6] = 0.0F; data[7] =-1.0F; data[8] = 0.0F;
break;
case 6:
data[0] = 1.0F; data[1] = 1.0F; data[2] = 1.0F;
data[3] = 1.0F; data[4] = 1.0F; data[5] = 1.0F;
data[6] = 1.0F; data[7] = 1.0F; data[8] = 1.0F;
break;
case 7:
data[0] = 1.0F; data[1] = 2.0F; data[2] = 1.0F;
data[3] = 2.0F; data[4] = 4.0F; data[5] = 2.0F;
data[6] = 1.0F; data[7] = 2.0F; data[8] = 1.0F;
break;
//emboss
case 9:
data[0] =-1.0F; data[1] =-2.0F; data[2] = 0.0F;
data[3] =-2.0F; data[4] = 0.0F; data[5] = 2.0F;
data[6] = 0.0F; data[7] = 2.0F; data[8] = 1.0F;
break;
//tilraun til blurs
case 8:
data[0] = 1/9F; data[1] = 1/9F; data[2] = 1/9F;
data[3] = 1/9F; data[4] = 1/9F; data[5] = 1/9F;
data[6] = 1/9F; data[7] = 1/9F; data[8] = 1/9F;
break;
}
normalize(data);
kernel = new KernelJAI(3, 3, data);
}
private void normalize(float[] data) {
sum = 0.0F;
for ( int i = 0; i < data.length; i++ ) {
sum += data[i];
}
if ( sum > 0.0F ) {
for ( int i = 0; i < data.length; i++ ) {
data[i] = data[i] / sum;
}
} else {
sum = 1.0F;
}
}
}//end of class