001 /* 002 * ImageToImageOperation 003 * 004 * Copyright (c) 2001, 2002 Marco Schmidt. 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.ops; 009 010 import net.sourceforge.jiu.data.PixelImage; 011 import net.sourceforge.jiu.ops.MissingParameterException; 012 import net.sourceforge.jiu.ops.Operation; 013 import net.sourceforge.jiu.ops.WrongParameterException; 014 015 /** 016 * An operation that acesses an input image and produces data for an output image. 017 * This abstract class only provides methods to get and set those images. 018 * <p> 019 * Normally, an operation creates the output image itself. 020 * However, an output image can be specified by the user with 021 * {@link #setOutputImage}. 022 * This could be done when existing image objects are to be reused. 023 * <p> 024 * An operation extending ImageToImageOperation must check if 025 * (1) a user-defined output image is available and 026 * (2) whether that image matches the required criteria. 027 * The criteria depend on the operation - example: for an operation that 028 * rotates an image by 180 degrees, an output image must have the same resolution 029 * as the input image and be of the same type. 030 * <p> 031 * If an output image is not available (case #1), the operation must create 032 * the matching output image itself. 033 * It should know best what is required. 034 * Very generic methods (like rotation of images by 90 degrees) must know 035 * relatively little about the image. 036 * They can make use of PixelImage.createCompatibleImage(int, int) and provide 037 * width and height. 038 * That way, the operation works for all kinds of images, like BilevelImage, 039 * Paletted8Image, Gray8Image, RGB24Image etc. 040 * <p> 041 * If a user-provided image does not match the required criteria, an appropriate 042 * exception (most of the time {@link WrongParameterException} will do) with a 043 * descriptive error message must be thrown. 044 * In the example of the 90-degree rotation, the width of the output image must 045 * be equal to the height of the input image and vice versa. 046 * The types of input and output must be equal. 047 * <p> 048 * However, there are limits to the checks on user-provided output images. 049 * As an example, a generic test could not check if a paletted output image 050 * has the same palette as the input counterpart because it treats all images 051 * based on IntegerImage the same. 052 * <p> 053 * When performing an image-to-image-operation, the input image can possibly be 054 * used as the output image. 055 * This can be done 056 * <ul> 057 * <li>if input and output are of the same type and resolution and</li> 058 * <li>if the operation needs only one input pixel to compute the output pixel 059 * at any given position.</li> 060 * </ul> 061 * <p> 062 * Mirroring the image horizontally is an example of an operation that can be 063 * implemented that way - the operation starts at the top left and at the bottom 064 * right pixel, swaps them and proceeds one pixel to the right of the top left 065 * pixel (and one to the left of the bottom right pixel). 066 * 067 * @author Marco Schmidt 068 * @since 0.6.0 069 */ 070 public abstract class ImageToImageOperation extends Operation 071 { 072 private PixelImage inputImage; 073 private PixelImage outputImage; 074 private boolean canInAndOutBeEqual; 075 076 /** 077 * Creates an object of this class and sets input image 078 * and output image to the argument values. 079 */ 080 public ImageToImageOperation(PixelImage in, PixelImage out) 081 { 082 super(); 083 setInputImage(in); 084 setOutputImage(out); 085 canInAndOutBeEqual = false; 086 } 087 088 /** 089 * Creates an object of this class and sets the input image 090 * to the argument value, output image to <code>null</code>. 091 */ 092 public ImageToImageOperation(PixelImage in) 093 { 094 this(in, null); 095 } 096 097 /** 098 * Creates an object of this class and sets both input image 099 * and output image to <code>null</code>. 100 */ 101 public ImageToImageOperation() 102 { 103 this(null, null); 104 } 105 106 /** 107 * Returns if input and output image are allowed to be the same object. 108 * @see #setCanInputAndOutputBeEqual 109 */ 110 public boolean canInputAndOutputBeEqual() 111 { 112 return canInAndOutBeEqual; 113 } 114 115 /** 116 * If both an input and an output image have been specified (both non-null), 117 * this method compares their width and height properties and throws 118 * an exception if the two images do not have the same resolution. 119 * @throws WrongParameterException if input and output images exist and their 120 * resolutions differ 121 */ 122 public void ensureImagesHaveSameResolution() throws WrongParameterException 123 { 124 PixelImage in = getInputImage(); 125 PixelImage out = getOutputImage(); 126 if (in != null && out != null) 127 { 128 if (in.getWidth() != out.getWidth()) 129 { 130 throw new WrongParameterException("Input and output image must have the same width."); 131 } 132 if (in.getHeight() != out.getHeight()) 133 { 134 throw new WrongParameterException("Input and output image must have the same height."); 135 } 136 } 137 } 138 139 /** 140 * If {@link #getInputImage} returns <code>null</code> this 141 * method throws a {@link net.sourceforge.jiu.ops.MissingParameterException} 142 * complaining that an input image is missing. 143 * @throws MissingParameterException if no input image is available 144 */ 145 public void ensureInputImageIsAvailable() throws MissingParameterException 146 { 147 if (getInputImage() == null) 148 { 149 throw new MissingParameterException("Input image missing."); 150 } 151 } 152 153 /** 154 * If an output image has been specified this method will compare 155 * its resolution with the argument resolution and throw an exception if the 156 * resolutions differ. 157 * If no output image has been specified nothing happens. 158 * @param width the horizontal pixel resolution that the output image must have 159 * @param height the vertical pixel resolution that the output image must have 160 * @throws WrongParameterException if the resolutions differ 161 */ 162 public void ensureOutputImageResolution(int width, int height) throws WrongParameterException 163 { 164 PixelImage out = getOutputImage(); 165 if (out != null) 166 { 167 if (out.getWidth() != width) 168 { 169 throw new WrongParameterException("Output image must have width " + width + " (got: " + out.getWidth() + ")."); 170 } 171 if (out.getHeight() != height) 172 { 173 throw new WrongParameterException("Output image must have height " + height + " (got: " + out.getHeight() + ")."); 174 } 175 } 176 } 177 178 /** 179 * Returns the input image stored in this object. 180 * @return input image, possibly <code>null</code> 181 */ 182 public PixelImage getInputImage() 183 { 184 return inputImage; 185 } 186 187 /** 188 * Returns the output image stored in this object. 189 * @return output image, possibly <code>null</code> 190 */ 191 public PixelImage getOutputImage() 192 { 193 return outputImage; 194 } 195 196 /** 197 * Specify if input and output image are allowed to be the same object. 198 * @see #canInputAndOutputBeEqual 199 */ 200 public void setCanInputAndOutputBeEqual(boolean newValue) 201 { 202 canInAndOutBeEqual = newValue; 203 } 204 205 /** 206 * Sets the input image stored in this object to the argument. 207 * Argument can be <code>null</code>. 208 * @param in the new input image of this object 209 */ 210 public void setInputImage(PixelImage in) 211 { 212 inputImage = in; 213 } 214 215 /** 216 * Sets the output image stored in this object to the argument. 217 * Argument can be <code>null</code>. 218 * @param out the new output image of this object 219 */ 220 public void setOutputImage(PixelImage out) 221 { 222 outputImage = out; 223 } 224 }