View Javadoc

1   package de.desy.video.sw;
2   
3   /**
4   * <code>CColorLookupTable</code> creates, prepares and maintains a false colour table 
5   * necessary to decode pure grayscale image data to true colour display. Three false colour
6   * tables (mappings) are supported at the moment:
7   * <ul>
8   * <li>PITZ false colour (was invented at PITZ Video System v2, Velizar Miltchev)
9   * <li>MATLAB jet false colour (taken from Matlab)
10  * <li>GRAYSCALE simple grayscale conversion 
11  * </ul>
12  * 
13  * An important criteria to mention is that these mappings support scaling to physical and 
14  * effective bits per pixel settings. For example if source grayscale data is 16bpp physically 
15  * encoded (for performance reason) but only 12 of these bits are effectively used, the false 
16  * colour table is designed to support 0 as darkest and 4195 (12 bit max) as brightest value. 
17  * All other value (for 16 bit: 4096 to 65535) are encoded in magenta to easily detect them as 
18  * being illegal. In comparison to that, the output format is always java TYPE_INT_ARGB for 
19  * sake of simplicity.<br>
20  * The main use is to generate a 1-dimensional false-colour-mapping table that accepts as 
21  * index any physically valid grayscale number and returns the matched pixel ready for being
22  * placed to the output drawing buffer.    
23  *    
24  * @author <a href="mailto:stefan.weisse@desy.de">Stefan Weisse</a>
25  * @version $Id: Templates.xml,v 1.10 2008/06/20 16:31:13 sweisse Exp $
26  *
27  */
28  
29  public final class CColorLookupTable 
30  {
31  	/**
32  	 * array for currently used false colour mapping table 
33  	 */
34  	private int [] m_ColorLookupTable=null;
35  	/**
36  	 * buffer currently used false colour mode inside (caching)
37  	 */
38  	private int m_iColorMode = FALSEPITZ;
39  	/**
40  	 * buffer currently used maximum number of colours inside (caching), reflects
41  	 * bytes per pixel setting (1 => 255, 2 => 65535, 3 => 16777215)
42  	 */
43  	private int m_iCurMaxColors=0;
44  	/**
45  	 * buffer currently used effective bits per pixel inside (caching)
46  	 */
47  	private int m_iEBitPP = 0;
48  		
49  	/** grayscale mode id */
50  	public static final int GRAYSCALE=1;
51  	/** PITZ false colour mode id */
52  	public static final int FALSEPITZ=2;
53  	/** MATLAB JET false colour mode id */
54  	public static final int FALSEJET=3;		
55  	
56  	/**
57  	 * initializes default false colour table (1 byte per pixel, 8 effective bits, 
58  	 * PITZ false colour) 
59  	 * 
60  	 */
61  	public CColorLookupTable()
62  	{
63  		AdjustTable( FALSEPITZ, 1, 8);
64  	}
65  
66  	/**
67  	 * user code can obtain a reference to the internal memory buffer that contains 
68  	 * the current false colour mapping
69  	 * 
70  	 * @return reference to internal memory buffer
71  	 */
72  	public int[] getColorLookupTable()
73  	{
74  		return m_ColorLookupTable;		
75  	}
76  
77  	/**
78  	 *  performs recalculation of the mapped false colour table in case the parameters have
79  	 *  been changed. If no parameters change in between, nothing is done for sake of caching.
80  	 *  
81  	 *  @param aMode false colour mode CColorLookupTable.GRAYSCALE, CColorLookupTable.FALSEPITZ 
82  	 *  or CColorLookupTable.FALSEJET
83  	 *  @param aByPP bytes per pixel setting for new table to calculate 
84  	 *  (allowed values are 1, 2, 3)
85  	 *  @param aEBitPP effective bits per pixel setting (effective bits must fit inside 
86  	 *  bytes per pixel)
87  	 *  @return true  mapping table recalculated<br>
88  	 *          false mapping table not recalculated (parameters have not changed)
89  	 *          
90  	 */
91  	public boolean AdjustTable( int aMode, int aByPP, int aEBitPP)
92  	{
93  		int numColors = aByPP << 8;
94  		
95  		if ((m_iCurMaxColors != numColors) || (m_iEBitPP != aEBitPP) || (aMode != m_iColorMode))
96  		{
97  			// update private class variables	
98  			m_iCurMaxColors = numColors;
99  			m_iEBitPP = aEBitPP;
100 			m_iColorMode = aMode;
101 			m_ColorLookupTable = new int[1 << (aByPP*8)];
102     			
103 			if (m_iColorMode == FALSEPITZ) 
104 				fillColorLookupTablePITZFalseColors();
105 			else if (m_iColorMode == FALSEJET)
106 				fillColorLookupTableJETFalseColors();
107 			else 
108 				fillColorLookupTableGrayscale();
109 
110     		// fill left colours (if effective bpp < physical bpp)
111     		// with magenta for easy spotting of illegal values
112     		int maxval = 1 << aEBitPP;
113     		int maxval_total = 1 << (aByPP*8);
114     		int left = maxval_total-maxval;
115 
116     		if (left > 0)
117     		{
118     			try 
119     			{
120     			for (int i=0;i<left;i++)
121     			{
122     				// put magenta for bad colors that must not happen!
123     				// 	alpha24 Red16 Green8 Blue
124     				m_ColorLookupTable[i+maxval] = (255 << 24) | (255 << 16) | (255);
125     			}
126     			}
127     			catch( ArrayIndexOutOfBoundsException ex) {}
128     			
129     		}
130     		
131     		return true;
132 		}
133 		return false;
134 	}
135 	
136 	/* no_java_doc
137 	 * 
138 	 * fills the lookup table using PITZ false colours based on current private class
139 	 * variables 
140 	 */
141 	private void fillColorLookupTablePITZFalseColors()
142 	{
143 		// fill in PITZ false colors
144 
145 		int dec = (int) (1 << m_iEBitPP);
146 		double decdbl = (double) dec;
147 		int i;
148 
149 		// 	alpha24 Red16 Green8 Blue
150 		m_ColorLookupTable[0] = (255 << 24); // black 0-0-0
151 
152 		// 	alpha24 Red16 Green8 Blue // white 255-255-255
153 		m_ColorLookupTable[dec-1] = (255 << 24) | (255 << 16) | (255 << 8) | (255); 
154 		
155 		int step1min = 1;
156 		int step1max = (int) (decdbl/3);
157 		
158 		int step2min = step1max + 1;
159 		int step2max = (int) ((decdbl*293)/500);
160 		
161 		int step3min = step2max + 1;
162 		int step3max = (int) ((decdbl*2)/3);
163 		
164 		int step4min = step3max + 1;
165 		int step4max = (int) decdbl-1;
166 
167 		for (i=step1min;i<step2min;i++)
168 		{
169 			double m = -0.5608 / (dec/3-1.0);
170 			double n = 1.0 - m*1.0;
171 
172 			m_ColorLookupTable[i] = (255 << 24) | ((int)((m*i+n)*255.0));
173 		}
174 
175 		for (i=step2min;i<step3min;i++)
176 		{
177 			double m1= 0.561 / ( (dec*293/500)-(dec/3));
178 			double n1 = 0.263 - (m1 * (dec/3));
179 		
180 			double m2= -0.4314 / ( (dec*293/500)-(dec/3));
181 			double n2 = 0 - (m2 * (dec*293/500));
182 
183 			//	alpha24 Red16 Green8 Blue
184 			m_ColorLookupTable[i] = (255 << 24) | (((int)((m1*i+n1)*255.0))<<8) | ((int)((m2*i+n2)*255.0));
185 		}
186 
187 		for (i=step3min;i<step4min;i++)
188 		{
189 			double m1= 0.176 / ( (dec*2/3)-(dec*293/500));
190 			double n1 = 1 - (m1 * (dec*2/3));
191 
192 			m_ColorLookupTable[i] = (255 << 24) | (((int)((m1*i+n1)*255.0))<<8);
193 		}
194 		
195 		for (i=step4min;i<step4max;i++)
196 		{
197 			double m1= 0.737 / (dec-(dec*2/3));
198 			double n1 = 1 - (m1 * dec);
199 
200 			m_ColorLookupTable[i] = (255 << 24) | (((int)((m1*i+n1)*255.0))<<16);
201 		}
202 		
203 	}
204 	
205 	
206 	/* no_java_doc
207 	 * 
208 	 * fills the lookup table using MATLAB Jet false colours based on current private class
209 	 * variables
210 	 *  
211 	 */
212 	private void fillColorLookupTableJETFalseColors()
213 	{
214 		int dec = (int) (1 << m_iEBitPP);
215 		int i;
216 		
217 		int step1min = 0;
218 		int step1max = (int) ((dec/8)-1);
219 		
220 		int step2min = step1max + 1;
221 		int step2max = (int) (((dec*3)/8)-1);
222 		
223 		int step3min = step2max + 1;
224 		int step3max = (int) (((dec*5)/8)-1);
225 		
226 		int step4min = step3max + 1;
227 		int step4max = (int) (((dec*7)/8)-1);
228 		
229 		int step5min = step4max + 1;
230 		int step5max = (int) (dec-1);
231 
232 		// 	alpha24 Red16 Green8 Blue // white 255-255-255
233 		m_ColorLookupTable[dec-1] = (255 << 24) | (255 << 16) | (255 << 8) | (255);
234 
235 		double Dstep2min = (double) step2min;
236 		
237 		for (i=step1min;i<step2min;i++)
238 		{
239 			double Di= (double) i;
240 			double blue = (((Di/2.0)/Dstep2min)+0.5)*255.0;
241 
242 			// 	alpha24 Red16 Green8 Blue			
243 			m_ColorLookupTable[i] = (255 << 24) | (int) blue;
244 		}
245 
246 		for (i=step2min;i<step3min;i++)
247 		{
248 			double Di = (double) i;
249 			double green = ((Di/(Dstep2min*2.0))-0.5)*255.0;
250 			
251 			// alpha24 Red16 Green8 Blue
252 			m_ColorLookupTable[i] = (255 << 24) | (((int)green)<<8) | 255;
253 		}
254 
255 		for (i=step3min;i<step4min;i++)
256 		{
257 			double Di = (double) i;
258 			double red = ((Di/(Dstep2min*2.0))-1.5) *255.0;
259 			double blue = ((1.0-((Di/(Dstep2min*2.0))-1.5))*255.0);
260 			
261 			// alpha24 Red16 Green8 Blue
262 			m_ColorLookupTable[i] = (255 << 24) | (((int)red)<<16) | (255<<8) | ((int) blue);
263 		}
264 		
265 		for (i=step4min;i<step5min;i++)
266 		{
267 			double Di = (double) i;
268 			double green = (((Di/(-(Dstep2min*2.0)))+3.5) *255.0);
269 
270 			// alpha24 Red16 Green8 Blue
271 			m_ColorLookupTable[i] = (255 << 24) | (255<<16) | (((int)green)<<8);
272 		}
273 
274 		for (i=step5min;i<step5max;i++)
275 		{
276 			double Di = (double) i;
277 			double red = (((Di/(-(Dstep2min*2.0)))+4.5) *255.0); 
278 
279 			// alpha24 Red16 Green8 Blue			
280 			m_ColorLookupTable[i] = (255 << 24) | (((int)red)<<16);
281 		}
282 		
283 	}
284 
285 	
286 	/* no_java_doc
287 	 * 
288 	 * fills the lookup table using grayscales based on current private class
289 	 * variables
290 	 * 
291 	 */
292 	private void fillColorLookupTableGrayscale()
293 	{
294 		int maxval = (int) (1 << m_iEBitPP);
295 		
296 		try 
297 		{
298 		for (int i=0;i<maxval;i++)
299 		{
300 			int gray = (int) ((255.0*i)/maxval);
301 			// 	alpha24 Green16 Red8 Blue
302 			m_ColorLookupTable[i] = (255 << 24) | (gray << 16) | (gray << 8) | (gray);
303 		}
304 		}
305 		catch( ArrayIndexOutOfBoundsException ex) {}
306 		
307 	}	
308 }