001 /* 002 * Invert 003 * 004 * Copyright (c) 2000, 2001, 2002, 2003 Marco Schmidt. 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.color; 009 010 import net.sourceforge.jiu.data.PixelImage; 011 import net.sourceforge.jiu.data.Palette; 012 import net.sourceforge.jiu.data.Paletted8Image; 013 import net.sourceforge.jiu.data.IntegerImage; 014 import net.sourceforge.jiu.ops.ImageToImageOperation; 015 import net.sourceforge.jiu.ops.MissingParameterException; 016 import net.sourceforge.jiu.ops.WrongParameterException; 017 018 /** 019 * Creates an inverted (negated) version of an image. 020 * This is done by subtracting each sample value of a channel 021 * from the maximum sample for that channel. 022 * The maximum sample for a channel is given by 023 * {@link net.sourceforge.jiu.data.IntegerImage#getMaxSample}. 024 * For paletted images, just the palette is treated that way. 025 * Supported image types: {@link net.sourceforge.jiu.data.IntegerImage}. 026 * Input and output image can be the same object. 027 * @author Marco Schmidt 028 */ 029 public class Invert extends ImageToImageOperation 030 { 031 private void prepare(PixelImage in) throws 032 MissingParameterException, 033 WrongParameterException 034 { 035 if (in == null) 036 { 037 throw new MissingParameterException("Missing input image."); 038 } 039 PixelImage out = getOutputImage(); 040 if (out == null) 041 { 042 setOutputImage(in.createCompatibleImage(in.getWidth(), in.getHeight())); 043 } 044 else 045 { 046 if (in.getClass() != out.getClass()) 047 { 048 throw new WrongParameterException("Specified output image type must be the same as input image type."); 049 } 050 if (in.getWidth() != out.getWidth()) 051 { 052 throw new WrongParameterException("Specified output image must have same width as input image."); 053 } 054 if (in.getHeight() != out.getHeight()) 055 { 056 throw new WrongParameterException("Specified output image must have same height as input image."); 057 } 058 } 059 } 060 061 private void process(Paletted8Image in) 062 { 063 // prepare(PixelImage) has made sure that we have a compatible output image 064 Paletted8Image out = (Paletted8Image)getOutputImage(); 065 066 // invert palette of output image 067 Palette pal = out.getPalette(); 068 final int MAX = pal.getMaxValue(); 069 for (int entryIndex = 0; entryIndex < pal.getNumEntries(); entryIndex++) 070 { 071 for (int channelIndex = 0; channelIndex < 3; channelIndex++) 072 { 073 pal.putSample(channelIndex, entryIndex, MAX - pal.getSample(channelIndex, entryIndex)); 074 } 075 } 076 077 // copy image content 078 final int WIDTH = in.getWidth(); 079 final int HEIGHT = in.getHeight(); 080 for (int y = 0; y < HEIGHT; y++) 081 { 082 for (int x = 0; x < WIDTH; x++) 083 { 084 out.putSample(0, x, y, in.getSample(0, x, y)); 085 } 086 setProgress(y, HEIGHT); 087 } 088 } 089 090 private void process(IntegerImage in) 091 { 092 IntegerImage out = (IntegerImage)getOutputImage(); 093 final int WIDTH = in.getWidth(); 094 final int HEIGHT = in.getHeight(); 095 final int CHANNELS = in.getNumChannels(); 096 final int TOTAL_ITEMS = CHANNELS * HEIGHT; 097 int processedItems = 0; 098 for (int channel = 0; channel < CHANNELS; channel++) 099 { 100 final int MAX = in.getMaxSample(channel); 101 for (int y = 0; y < HEIGHT; y++) 102 { 103 for (int x = 0; x < WIDTH; x++) 104 { 105 out.putSample(channel, x, y, MAX - in.getSample(channel, x, y)); 106 } 107 setProgress(processedItems++, TOTAL_ITEMS); 108 } 109 } 110 } 111 112 /** 113 * Inverts the input image, reusing an output image if one has been specified. 114 * For paletted images, inverts the palette. 115 * For all other types, subtracts each sample of each channel from the maximum 116 * value of that channel. 117 * @throws MissingParameterException if the input image is missing 118 * @throws WrongParameterException if any of the specified image parameters are unsupported or of the wrong width or height 119 */ 120 public void process() throws 121 MissingParameterException, 122 WrongParameterException 123 { 124 PixelImage in = getInputImage(); 125 prepare(in); 126 if (in instanceof Paletted8Image) 127 { 128 process((Paletted8Image)in); 129 } 130 else 131 if (in instanceof IntegerImage) 132 { 133 process((IntegerImage)in); 134 } 135 else 136 { 137 throw new WrongParameterException("Input image type unsupported: " + in.toString()); 138 } 139 } 140 }