001 /* 002 * ScaleReplication 003 * 004 * Copyright (c) 2001, 2002 Marco Schmidt <marcoschmidt@users.sourceforge.net> 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.geometry; 009 010 import net.sourceforge.jiu.data.PixelImage; 011 import net.sourceforge.jiu.data.IntegerImage; 012 import net.sourceforge.jiu.ops.ImageToImageOperation; 013 import net.sourceforge.jiu.ops.MissingParameterException; 014 import net.sourceforge.jiu.ops.WrongParameterException; 015 016 /** 017 * Changes the pixel resolution of an image by replicating (or dropping) pixels. 018 * A fast but low quality scaling algorithm that works with all kinds 019 * of image types. 020 * {@link Resample} provides better quality, but is slower and works with 021 * intensity-based image data types only. 022 * 023 * <h3>Usage example</h3> 024 * 025 * The input image will be scaled to an image that is twice as wide as 026 * itself and three times as high. 027 * 028 * <pre> 029 * ScaleReplication scale = new ScaleReplication(); 030 * scale.setInputImage(image); // something implementing IntegerImage 031 * scale.setSize(image.getWidth() * 2, image.getHeight() * 2); 032 * scale.process(); 033 * PixelImage scaledImage = scale.getOutputImage(); 034 * </pre> 035 * @author Marco Schmidt 036 */ 037 public class ScaleReplication extends ImageToImageOperation 038 { 039 private Integer outWidth; 040 private Integer outHeight; 041 042 private void process(IntegerImage in, IntegerImage out) 043 { 044 if (out == null) 045 { 046 out = (IntegerImage)in.createCompatibleImage(outWidth.intValue(), outHeight.intValue()); 047 setOutputImage(out); 048 } 049 int IN_MAX_X = in.getWidth() - 1; 050 int IN_MAX_Y = in.getHeight() - 1; 051 int OUT_WIDTH = outWidth.intValue(); 052 int OUT_HEIGHT = outHeight.intValue(); 053 int totalItems = in.getNumChannels() * in.getHeight(); 054 int processedItems = 0; 055 for (int y = 0; y < OUT_HEIGHT; y++) 056 { 057 final int SRC_Y = (int)(IN_MAX_Y * (y + 1) / OUT_HEIGHT); 058 for (int x = 0; x < OUT_WIDTH; x++) 059 { 060 final int SRC_X = (int)(IN_MAX_X * (x + 1) / OUT_WIDTH); 061 for (int c = 0; c < in.getNumChannels(); c++) 062 { 063 out.putSample(c, x, y, in.getSample(c, SRC_X, SRC_Y)); 064 } 065 } 066 setProgress(y, OUT_HEIGHT); 067 } 068 } 069 070 public void process() throws 071 MissingParameterException, 072 WrongParameterException 073 { 074 PixelImage pin = getInputImage(); 075 if (pin == null) 076 { 077 throw new MissingParameterException("Input image object missing."); 078 } 079 if (!(pin instanceof IntegerImage)) 080 { 081 throw new WrongParameterException("ScaleReplication only works on IntegerImage objects."); 082 } 083 if (outWidth == null) 084 { 085 throw new MissingParameterException("Output width value missing."); 086 } 087 if (outHeight == null) 088 { 089 throw new MissingParameterException("Output height value missing."); 090 } 091 ensureImagesHaveSameResolution(); 092 process((IntegerImage)pin, (IntegerImage)getOutputImage()); 093 } 094 095 /** 096 * Specify the resolution to be used for the image to be created. 097 * @param width horizontal resolution of the new image 098 * @param height vertical resolution of the new image 099 * @throws IllegalArgumentException if any of the arguments is smaller than 1 100 */ 101 public void setSize(int width, int height) 102 { 103 if (width < 1) 104 { 105 throw new IllegalArgumentException("Output width must be larger than 0."); 106 } 107 if (height < 1) 108 { 109 throw new IllegalArgumentException("Output height must be larger than 0."); 110 } 111 outWidth = new Integer(width); 112 outHeight = new Integer(height); 113 } 114 }