/*
* ImageToImageOperation
*
* Copyright (c) 2001, 2002 Marco Schmidt.
* All rights reserved.
*/
package net.sourceforge.jiu.ops;
import net.sourceforge.jiu.data.PixelImage;
import net.sourceforge.jiu.ops.MissingParameterException;
import net.sourceforge.jiu.ops.Operation;
import net.sourceforge.jiu.ops.WrongParameterException;
/**
* An operation that acesses an input image and produces data for an output image.
* This abstract class only provides methods to get and set those images.
* <p>
* Normally, an operation creates the output image itself.
* However, an output image can be specified by the user with
* {@link #setOutputImage}.
* This could be done when existing image objects are to be reused.
* <p>
* An operation extending ImageToImageOperation must check if
* (1) a user-defined output image is available and
* (2) whether that image matches the required criteria.
* The criteria depend on the operation - example: for an operation that
* rotates an image by 180 degrees, an output image must have the same resolution
* as the input image and be of the same type.
* <p>
* If an output image is not available (case #1), the operation must create
* the matching output image itself.
* It should know best what is required.
* Very generic methods (like rotation of images by 90 degrees) must know
* relatively little about the image.
* They can make use of PixelImage.createCompatibleImage(int, int) and provide
* width and height.
* That way, the operation works for all kinds of images, like BilevelImage,
* Paletted8Image, Gray8Image, RGB24Image etc.
* <p>
* If a user-provided image does not match the required criteria, an appropriate
* exception (most of the time {@link WrongParameterException} will do) with a
* descriptive error message must be thrown.
* In the example of the 90-degree rotation, the width of the output image must
* be equal to the height of the input image and vice versa.
* The types of input and output must be equal.
* <p>
* However, there are limits to the checks on user-provided output images.
* As an example, a generic test could not check if a paletted output image
* has the same palette as the input counterpart because it treats all images
* based on IntegerImage the same.
* <p>
* When performing an image-to-image-operation, the input image can possibly be
* used as the output image.
* This can be done
* <ul>
* <li>if input and output are of the same type and resolution and</li>
* <li>if the operation needs only one input pixel to compute the output pixel
* at any given position.</li>
* </ul>
* <p>
* Mirroring the image horizontally is an example of an operation that can be
* implemented that way - the operation starts at the top left and at the bottom
* right pixel, swaps them and proceeds one pixel to the right of the top left
* pixel (and one to the left of the bottom right pixel).
*
* @author Marco Schmidt
* @since 0.6.0
*/
public abstract class ImageToImageOperation extends Operation
{
private PixelImage inputImage;
private PixelImage outputImage;
private boolean canInAndOutBeEqual;
/**
* Creates an object of this class and sets input image
* and output image to the argument values.
*/
public ImageToImageOperation(PixelImage in, PixelImage out)
{
super();
setInputImage(in);
setOutputImage(out);
canInAndOutBeEqual = false;
}
/**
* Creates an object of this class and sets the input image
* to the argument value, output image to <code>null</code>.
*/
public ImageToImageOperation(PixelImage in)
{
this(in, null);
}
/**
* Creates an object of this class and sets both input image
* and output image to <code>null</code>.
*/
public ImageToImageOperation()
{
this(null, null);
}
/**
* Returns if input and output image are allowed to be the same object.
* @see #setCanInputAndOutputBeEqual
*/
public boolean canInputAndOutputBeEqual()
{
return canInAndOutBeEqual;
}
/**
* If both an input and an output image have been specified (both non-null),
* this method compares their width and height properties and throws
* an exception if the two images do not have the same resolution.
* @throws WrongParameterException if input and output images exist and their
* resolutions differ
*/
public void ensureImagesHaveSameResolution() throws WrongParameterException
{
PixelImage in = getInputImage();
PixelImage out = getOutputImage();
if (in != null && out != null)
{
if (in.getWidth() != out.getWidth())
{
throw new WrongParameterException("Input and output image must have the same width.");
}
if (in.getHeight() != out.getHeight())
{
throw new WrongParameterException("Input and output image must have the same height.");
}
}
}
/**
* If {@link #getInputImage} returns <code>null</code> this
* method throws a {@link net.sourceforge.jiu.ops.MissingParameterException}
* complaining that an input image is missing.
* @throws MissingParameterException if no input image is available
*/
public void ensureInputImageIsAvailable() throws MissingParameterException
{
if (getInputImage() == null)
{
throw new MissingParameterException("Input image missing.");
}
}
/**
* If an output image has been specified this method will compare
* its resolution with the argument resolution and throw an exception if the
* resolutions differ.
* If no output image has been specified nothing happens.
* @param width the horizontal pixel resolution that the output image must have
* @param height the vertical pixel resolution that the output image must have
* @throws WrongParameterException if the resolutions differ
*/
public void ensureOutputImageResolution(int width, int height) throws WrongParameterException
{
PixelImage out = getOutputImage();
if (out != null)
{
if (out.getWidth() != width)
{
throw new WrongParameterException("Output image must have width " + width + " (got: " + out.getWidth() + ").");
}
if (out.getHeight() != height)
{
throw new WrongParameterException("Output image must have height " + height + " (got: " + out.getHeight() + ").");
}
}
}
/**
* Returns the input image stored in this object.
* @return input image, possibly <code>null</code>
*/
public PixelImage getInputImage()
{
return inputImage;
}
/**
* Returns the output image stored in this object.
* @return output image, possibly <code>null</code>
*/
public PixelImage getOutputImage()
{
return outputImage;
}
/**
* Specify if input and output image are allowed to be the same object.
* @see #canInputAndOutputBeEqual
*/
public void setCanInputAndOutputBeEqual(boolean newValue)
{
canInAndOutBeEqual = newValue;
}
/**
* Sets the input image stored in this object to the argument.
* Argument can be <code>null</code>.
* @param in the new input image of this object
*/
public void setInputImage(PixelImage in)
{
inputImage = in;
}
/**
* Sets the output image stored in this object to the argument.
* Argument can be <code>null</code>.
* @param out the new output image of this object
*/
public void setOutputImage(PixelImage out)
{
outputImage = out;
}
}