All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.image.ImageModel Maven / Gradle / Ivy

There is a newer version: 0.11-ALPHA-1
Show newest version
/***********************************************************************************************************************
 *
 * Mistral - open source imaging engine
 * Copyright (C) 2003-2011 by Tidalwave s.a.s.
 *
 ***********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://mistral.tidalwave.it
 * SCM: https://kenai.com/hg/mistral~src
 *
 **********************************************************************************************************************/
package it.tidalwave.image;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.awt.image.ColorModel;
import it.tidalwave.image.op.ImplementationFactory;
import java.awt.image.RenderedImage;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;

/*******************************************************************************
 *
 * @author Fabrizio Giudici
 * @version $Id$
 *
 ******************************************************************************/
public abstract class ImageModel implements Externalizable
  {
    private Serializable id;
    private String nickName;
    protected transient Object model;

    /*******************************************************************************
     *
     * Default constructor for serialization. DO NOT CALL.
     *
     ******************************************************************************/
    public ImageModel()
      {
        // Just deserialized. There's no model, so it should not go in cache
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public ImageModel (final Object model)
      {
        if (model == null)
          {
            throw new IllegalArgumentException("model is null");  
          }
        
        id = "" + (System.nanoTime() - 1182021416080087000L); // FIXME: use UUID
//        System.err.println("CREATED ImageModel " + id);
        this.model = model;
//        ImageModelCache.getInstance().add(this);
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public void dispose()
      {
        ImageModelCache.getInstance().remove(id, true);
        // model = null; FIXME??
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public final Serializable getId()
      {
        return id;
      }

    public void setNickName (final String nickName)
      {
        this.nickName = nickName;
      }
    
    public String getNickName()
      {
        return nickName;
      }
    
    /*******************************************************************************
     *
     *
     ******************************************************************************/
    @Override
    public final int hashCode()
      {
        return (id != null) ? id.hashCode() : 0;
      }
    
    /*******************************************************************************
     *
     *
     ******************************************************************************/
    @Override
    public final boolean equals (final Object object)
      {
        if (!(object instanceof ImageModel))
          {
            return false;
          }  
        
        final ImageModel imageModel = (ImageModel)object;
        
        if ((id == null) || (imageModel.id == null))
          {
            return false;  
          }
        
        return id.equals(imageModel.id);
      }
    
    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public void setImage (final Object image)
      {
        ImageModelCache.getInstance().update(this);
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public final Object getImage ()
      {
        return model;
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public abstract int getWidth();

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public abstract int getHeight();

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public abstract EditableImage.DataType getDataType();

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public abstract int getBandCount();

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public abstract ImplementationFactory getFactory();

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public abstract ColorModel getColorModel();

    /*******************************************************************************
     *
     * Creates a similar image, that is a blank image with the same characteristics
     * of this image (width, height, data type, sample model, color model).
     *
     * @return  a new, similar image
     *
     ******************************************************************************/
    public abstract EditableImage createCopy (boolean copyContents);

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public abstract  T getInnerProperty (Class propertyClass);
    
    /*******************************************************************************
     *
     * Returns an estimate of the memory allocated by this image. The default
     * implementation returns the number of pixels multiplied by the number of bands
     * multiplied the size in bytes of each pixel. Can be overridden for more 
     * accurate implementations.
     * 
     * @return  the memory allocated for this image
     *
     ******************************************************************************/
    public long getMemorySize()
      {
        final EditableImage.DataType dataType = getDataType();
        return (dataType == null) ? 0 : ((long)dataType.getSize() * getWidth() * getHeight() * getBandCount()) / 8;
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public final void writeExternal (final ObjectOutput out)
        throws IOException
      {
        out.writeObject(id);
        out.writeObject((nickName != null) ? nickName : "NULL"); // FIXME: needed? Can writeObject(null)?
        
        final boolean notNull = model != null;
        out.writeBoolean(notNull);

        if (notNull)
          {
            writeRaster(new OutputStream() 
              {
                @Override
                public void write (byte buffer[], int off, int len) throws IOException 
                  {
                    out.write(buffer, off, len);
                  }
                
                @Override
                public void write (int b) throws IOException 
                  {
                    out.write(b);
                  }
              });
          }
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    public final void readExternal (final ObjectInput in)
        throws IOException, ClassNotFoundException
      {
        id = (Serializable)in.readObject();
        nickName = (String)in.readObject();
        
        if (nickName.equals("NULL"))
          {
            nickName = null;
          }

        if (in.readBoolean())
          {
            readRaster(new InputStream() 
              {
                @Override
                public int read(byte b[], int off, int len) throws IOException 
                  {
                    return in.read(b, off, len);
                  }
                
                @Override
                public int read() throws IOException 
                  {
                    return in.read();
                  }
            });
          }
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    protected abstract RenderedImage toRenderedImageForSerialization();

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    protected abstract Object toObjectForDeserialization (final RenderedImage renderedImage);
    
    /*******************************************************************************
     *
     * TODO: check performance
     *
     ******************************************************************************/
    protected void writeRaster (final OutputStream out)
        throws IOException
      {
//        System.err.println(CLASS + ".writeExternal() - model: " + model);
/*            ImageWriter imageWriter = null;
            
            for (final Iterator i = ImageIO.getImageWritersByFormatName("TIFF"); i.hasNext(); )
              {
                final ImageWriter testImageWriter = i.next();
                
                if ((testImageWriter != null) && testImageWriter.getClass().getName().equals("com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter"))
                  {
                    imageWriter = testImageWriter;
                    break;  
                  }
              }
            
            if (imageWriter == null)
              {
                throw new RuntimeException("No JAI ImageIO ImageWriter for TIFF format! Can't serialize ImageModel");  
              }  
            
            System.err.println("SERIALIZING WITH " + imageWriter);
            final ImageOutputStream ios = ImageIO.createImageOutputStream(out);
            imageWriter.setOutput(ios);
            imageWriter.write(toRenderedImageForSerialization());
            imageWriter.dispose();*/
        ImageIO.write(toRenderedImageForSerialization(), "TIFF", out);
      }

    /*******************************************************************************
     *
     * TODO: check performance
     *
     ******************************************************************************/
    protected void readRaster (final InputStream in)
        throws IOException
      {
        try 
          {
            Class.forName("com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter");
          } 
        catch (ClassNotFoundException ex) 
          {
            throw new RuntimeException("Can't deserialize ImageModels since JAI ImageIO is not in the classpath");
          }
        
        model = toObjectForDeserialization(ImageIO.read(in));
      }

    /*******************************************************************************
     *
     *
     ******************************************************************************/
    @Override
    public final String toString ()
      {
        return getClass().getName() + "[id: " + getId() + 
               ((nickName != null) ? (", nickName: " + nickName) : "") +
               //", model: " + model +
                "]";
      }
    
    /*******************************************************************************
     *
     *
     ******************************************************************************/
    protected void finalize()
      {
        // FIXME: not sure about this - for sure should only remove from the local cache
      }
  }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy