001 /* 002 * RGBColorList 003 * 004 * Copyright (c) 2001, 2002, 2003 Marco Schmidt. 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.color.quantization; 009 010 import net.sourceforge.jiu.color.data.Histogram3D; 011 import net.sourceforge.jiu.data.RGBIndex; 012 import net.sourceforge.jiu.util.ComparatorInterface; 013 import net.sourceforge.jiu.util.Sort; 014 015 /** 016 * Holds an array of {@link RGBColor} objects. 017 * @author Marco Schmidt 018 */ 019 public class RGBColorList implements RGBIndex 020 { 021 private RGBColor[] list; 022 private final int numEntries; 023 024 /** 025 * Creates a color list with room for a fixed number of entries. 026 * @param numberOfEntries the number of entries in the new list (must be larger than zero) 027 * @throws IllegalArgumentException if the argument is smaller than one 028 */ 029 private RGBColorList(final int NUM_ENTRIES) 030 { 031 if (NUM_ENTRIES < 1) 032 { 033 throw new IllegalArgumentException("RGBColorList must have at least one entry; got " + NUM_ENTRIES); 034 } 035 numEntries = NUM_ENTRIES; 036 list = new RGBColor[NUM_ENTRIES]; 037 } 038 039 /** 040 * Creates a new list and initializes it with the argument histogram. 041 * All values from the histogram with a counter larger than zero will 042 * be added to the list (which will include all colors that appear at least 043 * once in the image on which the histogram was created). 044 * @param hist the histogram from which the list will be initialized 045 * @throws IllegalArgumentException thrown if no histogram entry has a non-zero counter 046 */ 047 public RGBColorList(Histogram3D hist) 048 { 049 this(hist.getNumUsedEntries()); 050 int i = 0; 051 final int MAX_RED = hist.getMaxValue(INDEX_RED); 052 final int MAX_GREEN = hist.getMaxValue(INDEX_GREEN); 053 final int MAX_BLUE = hist.getMaxValue(INDEX_BLUE); 054 for (int r = 0; r <= MAX_RED; r++) 055 { 056 for (int g = 0; g <= MAX_GREEN; g++) 057 { 058 for (int b = 0; b <= MAX_BLUE; b++) 059 { 060 int counter = hist.getEntry(r, g, b); 061 if (counter > 0) 062 { 063 list[i++] = new RGBColor(r, g, b, counter); 064 } 065 } 066 } 067 } 068 } 069 070 /** 071 * In a given interval of the list this method searches for the color axis 072 * that has the largest distribution of values. 073 * Returns a pair of int values; 074 * the first value is the component (0, 1 or 2), 075 * the second value is the difference between the minimum and maximum value found in the list. 076 * Only checks colors from index i1 to i2 of the list. 077 */ 078 public int[] findExtrema(int i1, int i2) 079 { 080 if (i1 < 0 || i1 >= numEntries || i2 < 0 || i2 >= numEntries || i1 > i2) 081 { 082 return null; 083 } 084 int[] max = new int[3]; 085 int[] min = new int[3]; 086 RGBColor c = list[i1]; 087 for (int i = 0; i < 3; i++) 088 { 089 min[i] = max[i] = c.getSample(i); 090 } 091 int i = i1 + 1; 092 while (i < i2) 093 { 094 c = list[i++]; 095 for (int j = 0; j < 3; j++) 096 { 097 int cSample = c.getSample(j); 098 if (cSample < min[j]) 099 { 100 min[j] = cSample; 101 } 102 else 103 { 104 if (cSample > max[j]) 105 { 106 max[j] = cSample; 107 } 108 } 109 } 110 } 111 // first value: sample index (0 - 2); second value: difference 112 int[] result = new int[2]; 113 result[0] = result[1] = -1; 114 for (i = 0; i < 3; i++) 115 { 116 int newDiff = max[i] - min[i]; 117 if (newDiff > result[1]) 118 { 119 result[0] = i; 120 result[1] = newDiff; 121 } 122 } 123 return result; 124 } 125 126 /** 127 * Returns an {@link RGBColor} object from this list, given by its zero-based 128 * index value. 129 * @param index zero-based index into the list; must be smaller than {@link #getNumEntries()} 130 * @return the color object 131 */ 132 public RGBColor getColor(int index) 133 { 134 return list[index]; 135 } 136 137 /** 138 * Returns the number of color objects in this list. 139 * @return number of colors in the list 140 */ 141 public int getNumEntries() 142 { 143 return list.length; 144 } 145 146 /** 147 * Sorts an interval of the array of colors by one of the three components (RGB). 148 * @param index1 the index of the first element in the interval 149 * @param index2 the index of the last element in the interval 150 * @param axis the color component by which the interval is to be sorted, {@link #INDEX_RED}, {@link #INDEX_GREEN} or {@link #INDEX_BLUE} 151 */ 152 public void sortByAxis(int index1, int index2, int axis) 153 { 154 Sort.sort(list, index1, index2, new RGBColorComparator(axis)); 155 } 156 157 /** 158 * Sorts an interval of the array of colors by their counters. 159 * @param index1 the index of the first element in the interval 160 * @param index2 the index of the last element in the interval 161 */ 162 public void sortByCounter(int index1, int index2) 163 { 164 Sort.sort(list, index1, index2, new ComparatorInterface() 165 { 166 public int compare(Object obj1, Object obj2) 167 { 168 RGBColor col1 = (RGBColor)obj1; 169 RGBColor col2 = (RGBColor)obj2; 170 return col1.getCounter() - col2.getCounter(); 171 } 172 }); 173 } 174 }