1 : /******************************************************************************
2 : * $Id: gdalcolortable.cpp 16573 2009-03-14 12:34:17Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Color table implementation.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : **********************************************************************
9 : * Copyright (c) 2000, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdal_priv.h"
31 :
32 : CPL_CVSID("$Id: gdalcolortable.cpp 16573 2009-03-14 12:34:17Z rouault $");
33 :
34 : /************************************************************************/
35 : /* GDALColorTable() */
36 : /************************************************************************/
37 :
38 : /**
39 : * \brief Construct a new color table.
40 : *
41 : * This constructor is the same as the C GDALCreateColorTable() function.
42 : *
43 : * @param eInterpIn the interpretation to be applied to GDALColorEntry
44 : * values.
45 : */
46 :
47 365 : GDALColorTable::GDALColorTable( GDALPaletteInterp eInterpIn )
48 :
49 : {
50 365 : eInterp = eInterpIn;
51 365 : }
52 :
53 : /************************************************************************/
54 : /* GDALCreateColorTable() */
55 : /************************************************************************/
56 :
57 : /**
58 : * \brief Construct a new color table.
59 : *
60 : * This function is the same as the C++ method GDALColorTable::GDALColorTable()
61 : */
62 14 : GDALColorTableH CPL_STDCALL GDALCreateColorTable( GDALPaletteInterp eInterp )
63 :
64 : {
65 14 : return (GDALColorTableH) (new GDALColorTable( eInterp ));
66 : }
67 :
68 :
69 : /************************************************************************/
70 : /* ~GDALColorTable() */
71 : /************************************************************************/
72 :
73 : /**
74 : * \brief Destructor.
75 : *
76 : * This descructor is the same as the C GDALDestroyColorTable() function.
77 : */
78 :
79 2013 : GDALColorTable::~GDALColorTable()
80 :
81 : {
82 2013 : }
83 :
84 : /************************************************************************/
85 : /* GDALDestroyColorTable() */
86 : /************************************************************************/
87 :
88 : /**
89 : * \brief Destroys a color table.
90 : *
91 : * This function is the same as the C++ method GDALColorTable::~GDALColorTable()
92 : */
93 27 : void CPL_STDCALL GDALDestroyColorTable( GDALColorTableH hTable )
94 :
95 : {
96 27 : delete (GDALColorTable *) hTable;
97 27 : }
98 :
99 : /************************************************************************/
100 : /* GetColorEntry() */
101 : /************************************************************************/
102 :
103 : /**
104 : * \brief Fetch a color entry from table.
105 : *
106 : * This method is the same as the C function GDALGetColorEntry().
107 : *
108 : * @param i entry offset from zero to GetColorEntryCount()-1.
109 : *
110 : * @return pointer to internal color entry, or NULL if index is out of range.
111 : */
112 :
113 1125128 : const GDALColorEntry *GDALColorTable::GetColorEntry( int i ) const
114 :
115 : {
116 1125128 : if( i < 0 || i >= static_cast<int>(aoEntries.size()) )
117 0 : return NULL;
118 : else
119 1125128 : return &aoEntries[i];
120 : }
121 :
122 : /************************************************************************/
123 : /* GDALGetColorEntry() */
124 : /************************************************************************/
125 :
126 :
127 : /**
128 : * \brief Fetch a color entry from table.
129 : *
130 : * This function is the same as the C++ method GDALColorTable::GetColorEntry()
131 : */
132 : const GDALColorEntry * CPL_STDCALL
133 48 : GDALGetColorEntry( GDALColorTableH hTable, int i )
134 :
135 : {
136 48 : VALIDATE_POINTER1( hTable, "GDALGetColorEntry", NULL );
137 :
138 48 : return ((GDALColorTable *) hTable)->GetColorEntry( i );
139 : }
140 :
141 :
142 : /************************************************************************/
143 : /* GetColorEntryAsRGB() */
144 : /************************************************************************/
145 :
146 : /**
147 : * \brief Fetch a table entry in RGB format.
148 : *
149 : * In theory this method should support translation of color palettes in
150 : * non-RGB color spaces into RGB on the fly, but currently it only works
151 : * on RGB color tables.
152 : *
153 : * This method is the same as the C function GDALGetColorEntryAsRGB().
154 : *
155 : * @param i entry offset from zero to GetColorEntryCount()-1.
156 : *
157 : * @param poEntry the existing GDALColorEntry to be overrwritten with the RGB
158 : * values.
159 : *
160 : * @return TRUE on success, or FALSE if the conversion isn't supported.
161 : */
162 :
163 71123 : int GDALColorTable::GetColorEntryAsRGB( int i, GDALColorEntry *poEntry ) const
164 :
165 : {
166 71123 : if( eInterp != GPI_RGB || i < 0 || i >= static_cast<int>(aoEntries.size()) )
167 0 : return FALSE;
168 :
169 71123 : *poEntry = aoEntries[i];
170 71123 : return TRUE;
171 : }
172 :
173 : /************************************************************************/
174 : /* GDALGetColorEntryAsRGB() */
175 : /************************************************************************/
176 :
177 : /**
178 : * \brief Fetch a table entry in RGB format.
179 : *
180 : * This function is the same as the C++ method GDALColorTable::GetColorEntryAsRGB()
181 : */
182 24 : int CPL_STDCALL GDALGetColorEntryAsRGB( GDALColorTableH hTable, int i,
183 : GDALColorEntry *poEntry )
184 :
185 : {
186 24 : VALIDATE_POINTER1( hTable, "GDALGetColorEntryAsRGB", 0 );
187 24 : VALIDATE_POINTER1( poEntry, "GDALGetColorEntryAsRGB", 0 );
188 :
189 24 : return ((GDALColorTable *) hTable)->GetColorEntryAsRGB( i, poEntry );
190 : }
191 :
192 : /************************************************************************/
193 : /* SetColorEntry() */
194 : /************************************************************************/
195 :
196 : /**
197 : * \brief Set entry in color table.
198 : *
199 : * Note that the passed in color entry is copied, and no internal reference
200 : * to it is maintained. Also, the passed in entry must match the color
201 : * interpretation of the table to which it is being assigned.
202 : *
203 : * The table is grown as needed to hold the supplied offset.
204 : *
205 : * This function is the same as the C function GDALSetColorEntry().
206 : *
207 : * @param i entry offset from zero to GetColorEntryCount()-1.
208 : * @param poEntry value to assign to table.
209 : */
210 :
211 361408 : void GDALColorTable::SetColorEntry( int i, const GDALColorEntry * poEntry )
212 :
213 : {
214 361408 : if( i < 0 )
215 0 : return;
216 :
217 : try
218 : {
219 361408 : if( i >= static_cast<int>(aoEntries.size()) )
220 : {
221 : GDALColorEntry oBlack;
222 20113 : oBlack.c1 = oBlack.c2 = oBlack.c3 = oBlack.c4 = 0;
223 20113 : aoEntries.resize(i+1, oBlack);
224 : }
225 :
226 361408 : aoEntries[i] = *poEntry;
227 : }
228 0 : catch(std::exception &e)
229 : {
230 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
231 : }
232 : }
233 :
234 : /************************************************************************/
235 : /* GDALSetColorEntry() */
236 : /************************************************************************/
237 :
238 : /**
239 : * \brief Set entry in color table.
240 : *
241 : * This function is the same as the C++ method GDALColorTable::SetColorEntry()
242 : */
243 51 : void CPL_STDCALL GDALSetColorEntry( GDALColorTableH hTable, int i,
244 : const GDALColorEntry * poEntry )
245 :
246 : {
247 51 : VALIDATE_POINTER0( hTable, "GDALSetColorEntry" );
248 51 : VALIDATE_POINTER0( poEntry, "GDALSetColorEntry" );
249 :
250 51 : ((GDALColorTable *) hTable)->SetColorEntry( i, poEntry );
251 : }
252 :
253 :
254 : /************************************************************************/
255 : /* Clone() */
256 : /************************************************************************/
257 :
258 : /**
259 : * \brief Make a copy of a color table.
260 : *
261 : * This method is the same as the C function GDALCloneColorTable().
262 : */
263 :
264 1649 : GDALColorTable *GDALColorTable::Clone() const
265 :
266 : {
267 1649 : return new GDALColorTable(*this);
268 : }
269 :
270 : /************************************************************************/
271 : /* GDALCloneColorTable() */
272 : /************************************************************************/
273 :
274 : /**
275 : * \brief Make a copy of a color table.
276 : *
277 : * This function is the same as the C++ method GDALColorTable::Clone()
278 : */
279 1 : GDALColorTableH CPL_STDCALL GDALCloneColorTable( GDALColorTableH hTable )
280 :
281 : {
282 1 : VALIDATE_POINTER1( hTable, "GDALCloneColorTable", NULL );
283 :
284 1 : return (GDALColorTableH) ((GDALColorTable *) hTable)->Clone();
285 : }
286 :
287 : /************************************************************************/
288 : /* GetColorEntryCount() */
289 : /************************************************************************/
290 :
291 : /**
292 : * \brief Get number of color entries in table.
293 : *
294 : * This method is the same as the function GDALGetColorEntryCount().
295 : *
296 : * @return the number of color entries.
297 : */
298 :
299 136113 : int GDALColorTable::GetColorEntryCount() const
300 :
301 : {
302 136113 : return aoEntries.size();
303 : }
304 :
305 : /************************************************************************/
306 : /* GDALGetColorEntryCount() */
307 : /************************************************************************/
308 :
309 : /**
310 : * \brief Get number of color entries in table.
311 : *
312 : * This function is the same as the C++ method GDALColorTable::GetColorEntryCount()
313 : */
314 34 : int CPL_STDCALL GDALGetColorEntryCount( GDALColorTableH hTable )
315 :
316 : {
317 34 : VALIDATE_POINTER1( hTable, "GDALGetColorEntryCount", 0 );
318 :
319 34 : return ((GDALColorTable *) hTable)->GetColorEntryCount();
320 : }
321 :
322 : /************************************************************************/
323 : /* GetPaletteInterpretation() */
324 : /************************************************************************/
325 :
326 : /**
327 : * \brief Fetch palette interpretation.
328 : *
329 : * The returned value is used to interprete the values in the GDALColorEntry.
330 : *
331 : * This method is the same as the C function GDALGetPaletteInterpretation().
332 : *
333 : * @return palette interpretation enumeration value, usually GPI_RGB.
334 : */
335 :
336 8 : GDALPaletteInterp GDALColorTable::GetPaletteInterpretation() const
337 :
338 : {
339 8 : return eInterp;
340 : }
341 :
342 : /************************************************************************/
343 : /* GDALGetPaltteInterpretation() */
344 : /************************************************************************/
345 :
346 : /**
347 : * \brief Fetch palette interpretation.
348 : *
349 : * This function is the same as the C++ method GDALColorTable::GetPaletteInterpretation()
350 : */
351 : GDALPaletteInterp CPL_STDCALL
352 2 : GDALGetPaletteInterpretation( GDALColorTableH hTable )
353 :
354 : {
355 2 : VALIDATE_POINTER1( hTable, "GDALGetPaletteInterpretation", GPI_Gray );
356 :
357 2 : return ((GDALColorTable *) hTable)->GetPaletteInterpretation();
358 : }
359 :
360 : /**
361 : * \brief Create color ramp
362 : *
363 : * Automatically creates a color ramp from one color entry to
364 : * another. It can be called several times to create multiples ramps
365 : * in the same color table.
366 : *
367 : * This function is the same as the C function GDALCreateColorRamp().
368 : *
369 : * @param nStartIndex index to start the ramp on the color table [0..255]
370 : * @param psStartColor a color entry value to start the ramp
371 : * @param nEndIndex index to end the ramp on the color table [0..255]
372 : * @param psEndColor a color entry value to end the ramp
373 : * @return total number of entries, -1 to report error
374 : */
375 :
376 1 : int GDALColorTable::CreateColorRamp(
377 : int nStartIndex, const GDALColorEntry *psStartColor,
378 : int nEndIndex, const GDALColorEntry *psEndColor )
379 : {
380 : /* validate indexes */
381 :
382 1 : if( nStartIndex < 0 || nStartIndex > 255 ||
383 : nEndIndex < 0 || nEndIndex > 255 ||
384 : nStartIndex > nEndIndex )
385 : {
386 0 : return -1;
387 : }
388 :
389 : /* validate color entries */
390 :
391 1 : if( psStartColor == NULL || psEndColor == NULL )
392 : {
393 0 : return -1;
394 : }
395 :
396 : /* calculate number of colors in-between */
397 :
398 1 : int nColors = nEndIndex - nStartIndex;
399 :
400 : /* set starting color */
401 :
402 1 : SetColorEntry( nStartIndex, psStartColor );
403 :
404 1 : if( nColors == 0 )
405 : {
406 0 : return GetColorEntryCount(); /* it should not proceed */
407 : }
408 :
409 : /* set ending color */
410 :
411 1 : SetColorEntry( nEndIndex, psEndColor );
412 :
413 : /* calculate the slope of the linear transformation */
414 :
415 : double dfSlope1, dfSlope2, dfSlope3, dfSlope4;
416 :
417 1 : dfSlope1 = ( psEndColor->c1 - psStartColor->c1 ) / (double) nColors;
418 1 : dfSlope2 = ( psEndColor->c2 - psStartColor->c2 ) / (double) nColors;
419 1 : dfSlope3 = ( psEndColor->c3 - psStartColor->c3 ) / (double) nColors;
420 1 : dfSlope4 = ( psEndColor->c4 - psStartColor->c4 ) / (double) nColors;
421 :
422 : /* loop through the new colors */
423 :
424 1 : GDALColorEntry sColor = *psStartColor;
425 :
426 : int i;
427 :
428 255 : for( i = 1; i < nColors; i++ )
429 : {
430 254 : sColor.c1 = (short) ( i * dfSlope1 + (double) psStartColor->c1 );
431 254 : sColor.c2 = (short) ( i * dfSlope2 + (double) psStartColor->c2 );
432 254 : sColor.c3 = (short) ( i * dfSlope3 + (double) psStartColor->c3 );
433 254 : sColor.c4 = (short) ( i * dfSlope4 + (double) psStartColor->c4 );
434 :
435 254 : SetColorEntry( nStartIndex + i, &sColor );
436 : }
437 :
438 : /* return the total number of colors */
439 :
440 1 : return GetColorEntryCount();
441 : }
442 :
443 : /************************************************************************/
444 : /* GDALCreateColorRamp() */
445 : /************************************************************************/
446 :
447 : /**
448 : * \brief Create color ramp
449 : *
450 : * This function is the same as the C++ method GDALColorTable::CreateColorRamp()
451 : */
452 : void CPL_STDCALL
453 1 : GDALCreateColorRamp( GDALColorTableH hTable,
454 : int nStartIndex, const GDALColorEntry *psStartColor,
455 : int nEndIndex, const GDALColorEntry *psEndColor )
456 : {
457 1 : VALIDATE_POINTER0( hTable, "GDALCreateColorRamp" );
458 :
459 : ((GDALColorTable *) hTable)->CreateColorRamp( nStartIndex, psStartColor,
460 1 : nEndIndex, psEndColor );
461 : }
|