001 /* 002 * Histogram3DCreator 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.Histogram3D; 011 import net.sourceforge.jiu.color.data.NaiveHistogram3D; 012 import net.sourceforge.jiu.color.data.OnDemandHistogram3D; 013 import net.sourceforge.jiu.data.IntegerImage; 014 import net.sourceforge.jiu.ops.Operation; 015 import net.sourceforge.jiu.ops.MissingParameterException; 016 import net.sourceforge.jiu.ops.WrongParameterException; 017 018 /** 019 * This class creates three-dimensional histograms for images with integer samples. 020 * Only {@link net.sourceforge.jiu.data.IntegerImage} is supported. 021 * Existing histogram objects can be given to this operation to be reused. 022 * <p> 023 * <em>Note: Before JIU 0.10.0 there was a single HistogramCreator class.</em> 024 * @author Marco Schmidt 025 * @since 0.10.0 026 */ 027 public class Histogram3DCreator extends Operation 028 { 029 private Histogram3D hist; 030 private IntegerImage image; 031 private int index1; 032 private int index2; 033 private int index3; 034 private boolean naive; 035 036 private void createHistogramIfNecessary() 037 { 038 if (hist == null) 039 { 040 if (naive) 041 { 042 hist = new NaiveHistogram3D(image.getMaxSample(index1) + 1, 043 image.getMaxSample(index2) + 1, 044 image.getMaxSample(index3) + 1); 045 } 046 else 047 { 048 hist = new OnDemandHistogram3D(image.getMaxSample(index1) + 1, 049 image.getMaxSample(index2) + 1, 050 image.getMaxSample(index3) + 1); 051 } 052 } 053 } 054 055 /** 056 * Returns the histogram initialized in this operation. 057 */ 058 public Histogram3D getHistogram() 059 { 060 return hist; 061 } 062 063 public void process() throws 064 MissingParameterException, 065 WrongParameterException 066 { 067 if (image == null) 068 { 069 throw new MissingParameterException("Image parameter missing."); 070 } 071 createHistogramIfNecessary(); 072 if (hist.getMaxValue(0) < image.getMaxSample(index1) || 073 hist.getMaxValue(1) < image.getMaxSample(index2) || 074 hist.getMaxValue(2) < image.getMaxSample(index3)) 075 { 076 throw new WrongParameterException("Histogram is not large enough for image (hist max value / image max samples)."); 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( 086 image.getSample(index1, x, y), 087 image.getSample(index2, x, y), 088 image.getSample(index3, x, y)); 089 } 090 setProgress(y, HEIGHT); 091 } 092 } 093 094 /** 095 * Sets the histogram object to be reused for this operation. 096 * If this method is not called, a new histogram will be created. 097 * @param histogram the histogram object to be used in this operation 098 */ 099 public void setHistogram3D(Histogram3D histogram) 100 { 101 hist = histogram; 102 } 103 104 /** 105 * The image for which a histogram will be initialized. 106 * Simply calls {@link #setImage(IntegerImage, int, int, int)} 107 * with 0, 1 and 2 as parameters. 108 * @param newImage the image for the histogram initialization 109 */ 110 public void setImage(IntegerImage newImage) 111 { 112 setImage(newImage, 0, 1, 2); 113 } 114 115 /** 116 * The image for which a histogram will be initialized. 117 * Simply calls {@link #setImage(IntegerImage, int, int, int)} 118 * with 0, 1 and 2 as parameters. 119 * @param newImage 120 */ 121 public void setImage(IntegerImage newImage, int channelIndex1, int channelIndex2, int channelIndex3) 122 { 123 if (newImage == null) 124 { 125 throw new IllegalArgumentException("Image argument must not be null."); 126 } 127 128 if (channelIndex1 < 0 || channelIndex1 >= newImage.getNumChannels() || 129 channelIndex2 < 0 || channelIndex2 >= newImage.getNumChannels() || 130 channelIndex3 < 0 || channelIndex3 >= newImage.getNumChannels()) 131 { 132 throw new IllegalArgumentException("The three index arguments must be >= 0 and < the number of channels."); 133 } 134 if (channelIndex1 == channelIndex2 || channelIndex2 == channelIndex3 || channelIndex1 == channelIndex3) 135 { 136 throw new IllegalArgumentException("The three index arguments must be different from each other."); 137 } 138 image = newImage; 139 index1 = channelIndex1; 140 index2 = channelIndex2; 141 index3 = channelIndex3; 142 } 143 }