001 /* 002 * @(#)NaiveHistogram3D 0.6.0 2001/06/28 003 * 004 * Copyright (c) 2001 Marco Schmidt <marcoschmidt@users.sourceforge.net> 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.color.data; 009 010 import net.sourceforge.jiu.color.data.Histogram3D; 011 012 /** 013 * A class for a three-dimensional histogram that allocates one <code>int</code> value 014 * per counter at construction time. 015 * This means that a histogram with 8 bits for each channel will have 016 * 2<sup>8 + 8 + 8</sup> = 2<sup>24</sup> = 16,777,216 int values, 017 * making it 64 MB large. 018 * 019 * @author Marco Schmidt 020 */ 021 public class NaiveHistogram3D implements 022 Histogram3D 023 { 024 private int[][][] data; 025 private int[] values; 026 027 /** 028 * Creates a histogram 029 */ 030 public NaiveHistogram3D(int numValuesLevel1, int numValuesLevel2, int numValuesLevel3) throws 031 IllegalArgumentException, 032 OutOfMemoryError 033 { 034 if (numValuesLevel1 < 1) 035 { 036 throw new IllegalArgumentException("The number of values for " + 037 "level 1 must be at least 1; got " + numValuesLevel1); 038 } 039 if (numValuesLevel2 < 1) 040 { 041 throw new IllegalArgumentException("The number of values for " + 042 "level 2 must be at least 1; got " + numValuesLevel2); 043 } 044 if (numValuesLevel3 < 1) 045 { 046 throw new IllegalArgumentException("The number of values for " + 047 "level 3 must be at least 1; got " + numValuesLevel3); 048 } 049 values = new int[3]; 050 values[0] = numValuesLevel1; 051 values[1] = numValuesLevel2; 052 values[2] = numValuesLevel3; 053 data = new int[values[0]][][]; 054 for (int i1 = 0; i1 < values[0]; i1++) 055 { 056 data[i1] = new int[values[1]][]; 057 for (int i2 = 0; i2 < values[1]; i1++) 058 { 059 data[i1][i2] = new int[values[2]]; 060 } 061 } 062 clear(); 063 } 064 065 /** 066 * Creates a histogram with the same number of values for all three dimensions. 067 * Calls {@link NaiveHistogram3D (int, int, int)}, repeating <code>numValues</code> 068 * three times. 069 * @param numValues the number of levels for all three dimensions 070 */ 071 public NaiveHistogram3D(int numValues) throws IllegalArgumentException, OutOfMemoryError 072 { 073 this(numValues, numValues, numValues); 074 } 075 076 /** 077 * Sets all counters to zero. 078 */ 079 public void clear() 080 { 081 for (int i1 = 0; i1 < values[0]; i1++) 082 for (int i2 = 0; i2 < values[1]; i2++) 083 for (int i3 = 0; i3 < values[2]; i3++) 084 data[i1][i2][i3] = 0; 085 } 086 087 /** 088 * Returns the counter value of (index1, index2, index3). 089 * @param index1 first of the three values forming the threedimensional index 090 * @param index2 second of the three values forming the threedimensional index 091 * @param index3 three of the three values forming the threedimensional index 092 * @return the counter value of the desired index 093 * @throws IllegalArgumentException could be (read: need not necessarily) be 094 * thrown if the index formed by the arguments is invalid 095 */ 096 public int getEntry(int index1, int index2, int index3) throws 097 IllegalArgumentException 098 { 099 try 100 { 101 return data[index1][index2][index3]; 102 } 103 catch (ArrayIndexOutOfBoundsException aioobe) 104 { 105 throw new IllegalArgumentException("Not a valid index (" + index1 + 106 ", " + index2 + ", " + index3 + ")"); 107 } 108 } 109 110 public int getMaxValue(int index) throws 111 IllegalArgumentException 112 { 113 if (index >= 0 && index <= 2) 114 { 115 return values[index] - 1; 116 } 117 else 118 { 119 throw new IllegalArgumentException("The index argument must be " + 120 "from 0 to 2; got " + index); 121 } 122 } 123 124 /** 125 * Returns the number of used entries (those entries with 126 * a counter value larger than zero). 127 * @return number of non-zero counter values 128 */ 129 public int getNumUsedEntries() 130 { 131 int result = 0; 132 for (int i1 = 0; i1 < values[0]; i1++) 133 for (int i2 = 0; i2 < values[1]; i2++) 134 for (int i3 = 0; i3 < values[2]; i3++) 135 if (data[i1][i2][i3] > 0) 136 result++; 137 return result; 138 } 139 140 /** 141 * Increases the counter value of (index1, index2, index3) by one. 142 * This method can easily be implemented by the one-liner 143 * <code>setEntry(index1, index2, index3, getEntry(index1, index2, index3) + 1);</code> 144 * However, this method is expected to be faster in some contexts. 145 * 146 * @param index1 first of the three values forming the threedimensional index 147 * @param index2 second of the three values forming the threedimensional index 148 * @param index3 three of the three values forming the threedimensional index 149 * @return the counter value of the desired index 150 * @throws IllegalArgumentException could be (read: need not necessarily) be 151 * thrown if the index formed by the arguments is invalid 152 */ 153 public void increaseEntry(int index1, int index2, int index3) throws IllegalArgumentException 154 { 155 try 156 { 157 data[index1][index2][index3]++; 158 } 159 catch (ArrayIndexOutOfBoundsException aioobe) 160 { 161 throw new IllegalArgumentException("Not a valid index (" + index1 + 162 ", " + index2 + ", " + index3 + ")"); 163 } 164 } 165 166 /** 167 * Sets the counter value of (index1, index2, index3) to newValue. 168 * 169 * @param index1 first of the three values forming the threedimensional index 170 * @param index2 second of the three values forming the threedimensional index 171 * @param index3 three of the three values forming the threedimensional index 172 * @param newValue the counter value that is assigned to the argument index 173 * @throws IllegalArgumentException could be (read: need not necessarily) be 174 * thrown if the index formed by the first three arguments is invalid 175 */ 176 public void setEntry(int index1, int index2, int index3, int newValue) throws IllegalArgumentException 177 { 178 try 179 { 180 data[index1][index2][index3] = newValue; 181 } 182 catch (ArrayIndexOutOfBoundsException aioobe) 183 { 184 throw new IllegalArgumentException("Not a valid index (" + index1 + 185 ", " + index2 + ", " + index3 + ")"); 186 } 187 } 188 }