001 /* 002 * Histogram1DCreator 003 * 004 * Copyright (c) 2002 Marco Schmidt. 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.color.analysis; 009 010 import net.sourceforge.jiu.color.data.ArrayHistogram1D; 011 import net.sourceforge.jiu.color.data.Histogram1D; 012 import net.sourceforge.jiu.data.IntegerImage; 013 import net.sourceforge.jiu.ops.Operation; 014 import net.sourceforge.jiu.ops.MissingParameterException; 015 import net.sourceforge.jiu.ops.WrongParameterException; 016 017 /** 018 * This class creates one-dimensional histograms for images with integer samples. 019 * Only {@link net.sourceforge.jiu.data.IntegerImage} objects are supported. 020 * <p> 021 * Existing histogram objects can be given to this operation to be reused. 022 * Give an existing {@link net.sourceforge.jiu.color.data.Histogram1D} object to this operation via 023 * {@link #setHistogram(Histogram1D)}. 024 * <p> 025 * The histogram can be created for any channel of an IntegerImage. 026 * The first channel (index 0) is the default channel. 027 * Use {@link #setImage(IntegerImage, int)} to specify another one. 028 * <p> 029 * <em>Note: Before JIU 0.10.0 there was a single HistogramCreator class.</em> 030 * <h3>Usage example</h3> 031 * Creates a histogram for the third channel of an image. 032 * <pre> 033 * Histogram1DCreator hc = new Histogram1DCreator(); 034 * hc.setImage(image, 2); 035 * hc.process(); 036 * Histogram1D hist = hc.getHistogram(); 037 * </pre> 038 * @author Marco Schmidt 039 * @since 0.10.0 040 */ 041 public class Histogram1DCreator extends Operation 042 { 043 private Histogram1D hist; 044 private int channelIndex; 045 private IntegerImage image; 046 047 private void createHistogramIfNecessary() 048 { 049 if (hist == null) 050 { 051 hist = new ArrayHistogram1D(image.getMaxSample(0) + 1); 052 } 053 } 054 055 /** 056 * Returns the histogram used in this operation. 057 * @return histogram object, newly-created or reused one 058 * @see #setHistogram 059 */ 060 public Histogram1D getHistogram() 061 { 062 return hist; 063 } 064 065 public void process() throws 066 MissingParameterException, 067 WrongParameterException 068 { 069 if (image == null) 070 { 071 throw new MissingParameterException("Image parameter missing."); 072 } 073 createHistogramIfNecessary(); 074 if (hist.getMaxValue() < image.getMaxSample(channelIndex)) 075 { 076 throw new WrongParameterException("Histogram does not have enough entries."); 077 } 078 hist.clear(); 079 final int WIDTH = image.getWidth(); 080 final int HEIGHT = image.getHeight(); 081 for (int y = 0; y < HEIGHT; y++) 082 { 083 for (int x = 0; x < WIDTH; x++) 084 { 085 hist.increaseEntry(image.getSample(channelIndex, x, y)); 086 } 087 setProgress(y, HEIGHT); 088 } 089 } 090 091 /** 092 * Sets a histogram object to be used for this operation. 093 * Within {@link #process} it will be checked if this histogram is large enough 094 * for the image. 095 * @see #getHistogram 096 */ 097 public void setHistogram(Histogram1D histogram) 098 { 099 hist = histogram; 100 } 101 102 /** 103 * Set the image for which the histogram is to be initialized. 104 * The first channel (index 0) is used by default. 105 * @param newImage image object to be used 106 * @see #setImage(IntegerImage, int) 107 */ 108 public void setImage(IntegerImage newImage) 109 { 110 setImage(newImage, 0); 111 } 112 113 /** 114 * Set the image and the channel index for which the histogram is to be initialized. 115 * @param newImage image object to be used 116 * @param imageChannelIndex must not be negative and must be smaller than newImage.getNumChannels() 117 * @see #setImage(IntegerImage) 118 */ 119 public void setImage(IntegerImage newImage, int imageChannelIndex) 120 { 121 if (newImage == null) 122 { 123 throw new IllegalArgumentException("Image argument must be non-null."); 124 } 125 if (imageChannelIndex < 0 || imageChannelIndex >= newImage.getNumChannels()) 126 { 127 throw new IllegalArgumentException("Invalid channel for given image."); 128 } 129 image = newImage; 130 channelIndex = imageChannelIndex; 131 } 132 }