1 : /******************************************************************************
2 : * $Id: gdal_rat.cpp 16570 2009-03-14 11:42:31Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Implementation of GDALRasterAttributeTable and related classes.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2005, 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 : #include "gdal_rat.h"
32 :
33 : CPL_CVSID("$Id: gdal_rat.cpp 16570 2009-03-14 11:42:31Z rouault $");
34 :
35 : /**
36 : * \class GDALRasterAttributeTable
37 : *
38 : * The GDALRasterAttributeTable (or RAT) class is used to encapsulate a table
39 : * used to provide attribute information about pixel values. Each row
40 : * in the table applies to a range of pixel values (or a single value in
41 : * some cases), and might have attributes such as the histogram count for
42 : * that range, the color pixels of that range should be drawn names of classes
43 : * or any other generic information.
44 : *
45 : * Raster attribute tables can be used to represent histograms, color tables,
46 : * and classification information.
47 : *
48 : * Each column in a raster attribute table has a name, a type (integer,
49 : * floating point or string), and a GDALRATFieldUsage. The usage distinguishes
50 : * columns with particular understood purposes (such as color, histogram
51 : * count, name) and columns that have specific purposes not understood by
52 : * the library (long label, suitability_for_growing_wheat, etc).
53 : *
54 : * In the general case each row has a column indicating the minimum pixel
55 : * values falling into that category, and a column indicating the maximum
56 : * pixel value. These are indicated with usage values of GFU_Min, and
57 : * GFU_Max. In other cases where each row is a discrete pixel value, one
58 : * column of usage GFU_MinMax can be used.
59 : *
60 : * In other cases all the categories are of equal size and regularly spaced
61 : * and the categorization information can be determine just by knowing the
62 : * value at which the categories start, and the size of a category. This
63 : * is called "Linear Binning" and the information is kept specially on
64 : * the raster attribute table as a whole.
65 : *
66 : * RATs are normally associated with GDALRasterBands and be be queried
67 : * using the GDALRasterBand::GetDefaultRAT() method.
68 : */
69 :
70 : /************************************************************************/
71 : /* GDALRasterAttributeTable() */
72 : /* */
73 : /* Simple initialization constructor. */
74 : /************************************************************************/
75 :
76 : //! Construct empty table.
77 :
78 52 : GDALRasterAttributeTable::GDALRasterAttributeTable()
79 :
80 : {
81 52 : bColumnsAnalysed = FALSE;
82 52 : nMinCol = -1;
83 52 : nMaxCol = -1;
84 52 : bLinearBinning = FALSE;
85 52 : dfRow0Min = -0.5;
86 52 : dfBinSize = 1.0;
87 52 : nRowCount = 0;
88 52 : }
89 :
90 : /************************************************************************/
91 : /* GDALCreateRasterAttributeTable() */
92 : /************************************************************************/
93 :
94 : /**
95 : * \brief Construct empty table.
96 : *
97 : * This function is the same as the C++ method GDALRasterAttributeTable::GDALRasterAttributeTable()
98 : */
99 2 : GDALRasterAttributeTableH CPL_STDCALL GDALCreateRasterAttributeTable()
100 :
101 : {
102 2 : return (GDALRasterAttributeTableH) (new GDALRasterAttributeTable());
103 : }
104 :
105 : /************************************************************************/
106 : /* GDALRasterAttributeTable() */
107 : /************************************************************************/
108 :
109 : //! Copy constructor.
110 :
111 : GDALRasterAttributeTable::GDALRasterAttributeTable(
112 5 : const GDALRasterAttributeTable &oOther )
113 :
114 : {
115 : // We have tried to be careful to allow wholesale assignment
116 5 : *this = oOther;
117 5 : }
118 :
119 : /************************************************************************/
120 : /* ~GDALRasterAttributeTable() */
121 : /* */
122 : /* All magic done by magic by the container destructors. */
123 : /************************************************************************/
124 :
125 57 : GDALRasterAttributeTable::~GDALRasterAttributeTable()
126 :
127 : {
128 57 : }
129 :
130 : /************************************************************************/
131 : /* GDALDestroyRasterAttributeTable() */
132 : /************************************************************************/
133 :
134 : /**
135 : * \brief Destroys a RAT.
136 : *
137 : * This function is the same as the C++ method GDALRasterAttributeTable::~GDALRasterAttributeTable()
138 : */
139 : void CPL_STDCALL
140 3 : GDALDestroyRasterAttributeTable( GDALRasterAttributeTableH hRAT )
141 :
142 : {
143 3 : if( hRAT != NULL )
144 3 : delete static_cast<GDALRasterAttributeTable *>(hRAT);
145 3 : }
146 :
147 : /************************************************************************/
148 : /* AnalyseColumns() */
149 : /* */
150 : /* Internal method to work out which column to use for various */
151 : /* tasks. */
152 : /************************************************************************/
153 :
154 2 : void GDALRasterAttributeTable::AnalyseColumns()
155 :
156 : {
157 2 : bColumnsAnalysed = TRUE;
158 :
159 2 : nMinCol = GetColOfUsage( GFU_Min );
160 2 : if( nMinCol == -1 )
161 2 : nMinCol = GetColOfUsage( GFU_MinMax );
162 :
163 2 : nMaxCol = GetColOfUsage( GFU_Max );
164 2 : if( nMaxCol == -1 )
165 2 : nMaxCol = GetColOfUsage( GFU_MinMax );
166 2 : }
167 :
168 : /************************************************************************/
169 : /* GetColumnCount() */
170 : /************************************************************************/
171 :
172 : /**
173 : * \brief Fetch table column count.
174 : *
175 : * This method is the same as the C function GDALRATGetColumnCount().
176 : *
177 : * @return the number of columns.
178 : */
179 :
180 11117 : int GDALRasterAttributeTable::GetColumnCount() const
181 :
182 : {
183 11117 : return aoFields.size();
184 : }
185 :
186 : /************************************************************************/
187 : /* GDALRATGetColumnCount() */
188 : /************************************************************************/
189 :
190 : /**
191 : * \brief Fetch table column count.
192 : *
193 : * This function is the same as the C++ method GDALRasterAttributeTable::GetColumnCount()
194 : */
195 4 : int CPL_STDCALL GDALRATGetColumnCount( GDALRasterAttributeTableH hRAT )
196 :
197 : {
198 4 : VALIDATE_POINTER1( hRAT, "GDALRATGetColumnCount", 0 );
199 :
200 4 : return ((GDALRasterAttributeTable *) hRAT)->GetColumnCount();
201 : }
202 :
203 : /************************************************************************/
204 : /* GetNameOfCol() */
205 : /************************************************************************/
206 :
207 : /**
208 : * \brief Fetch name of indicated column.
209 : *
210 : * This method is the same as the C function GDALRATGetNameOfCol().
211 : *
212 : * @param iCol the column index (zero based).
213 : *
214 : * @return the column name or an empty string for invalid column numbers.
215 : */
216 :
217 0 : const char *GDALRasterAttributeTable::GetNameOfCol( int iCol ) const
218 :
219 : {
220 0 : if( iCol < 0 || iCol >= (int) aoFields.size() )
221 0 : return "";
222 :
223 : else
224 0 : return aoFields[iCol].sName;
225 : }
226 :
227 : /************************************************************************/
228 : /* GDALRATGetNameOfCol() */
229 : /************************************************************************/
230 :
231 : /**
232 : * \brief Fetch name of indicated column.
233 : *
234 : * This function is the same as the C++ method GDALRasterAttributeTable::GetNameOfCol()
235 : */
236 : const char *CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH hRAT,
237 4 : int iCol )
238 :
239 : {
240 4 : VALIDATE_POINTER1( hRAT, "GDALRATGetNameOfCol", NULL );
241 :
242 : // we don't just wrap the normal operator because we don't want to
243 : // return a temporary string, we want to return a pointer to the
244 : // internal column name.
245 :
246 4 : GDALRasterAttributeTable *poRAT = (GDALRasterAttributeTable *) hRAT;
247 :
248 4 : if( iCol < 0 || iCol >= (int) poRAT->aoFields.size() )
249 0 : return "";
250 :
251 : else
252 4 : return poRAT->aoFields[iCol].sName.c_str();
253 : }
254 :
255 : /************************************************************************/
256 : /* GetUsageOfCol() */
257 : /************************************************************************/
258 :
259 : /**
260 : * \brief Fetch column usage value.
261 : *
262 : * This method is the same as the C function GDALRATGetUsageOfCol().
263 : *
264 : * @param iCol the column index (zero based).
265 : *
266 : * @return the column usage, or GFU_Generic for improper column numbers.
267 : */
268 :
269 5 : GDALRATFieldUsage GDALRasterAttributeTable::GetUsageOfCol( int iCol ) const
270 :
271 : {
272 5 : if( iCol < 0 || iCol >= (int) aoFields.size() )
273 0 : return GFU_Generic;
274 :
275 : else
276 5 : return aoFields[iCol].eUsage;
277 : }
278 :
279 : /************************************************************************/
280 : /* GDALRATGetUsageOfCol() */
281 : /************************************************************************/
282 :
283 : /**
284 : * \brief Fetch column usage value.
285 : *
286 : * This function is the same as the C++ method GDALRasterAttributeTable::GetUsageOfColetNameOfCol()
287 : */
288 : GDALRATFieldUsage CPL_STDCALL
289 5 : GDALRATGetUsageOfCol( GDALRasterAttributeTableH hRAT, int iCol )
290 :
291 : {
292 5 : VALIDATE_POINTER1( hRAT, "GDALRATGetUsageOfCol", GFU_Generic );
293 :
294 5 : return ((GDALRasterAttributeTable *) hRAT)->GetUsageOfCol( iCol );
295 : }
296 :
297 : /************************************************************************/
298 : /* GetTypeOfCol() */
299 : /************************************************************************/
300 :
301 : /**
302 : * \brief Fetch column type.
303 : *
304 : * This method is the same as the C function GDALRATGetTypeOfCol().
305 : *
306 : * @param iCol the column index (zero based).
307 : *
308 : * @return column type or GFT_Integer if the column index is illegal.
309 : */
310 :
311 5 : GDALRATFieldType GDALRasterAttributeTable::GetTypeOfCol( int iCol ) const
312 :
313 : {
314 5 : if( iCol < 0 || iCol >= (int) aoFields.size() )
315 0 : return GFT_Integer;
316 :
317 : else
318 5 : return aoFields[iCol].eType;
319 : }
320 :
321 : /************************************************************************/
322 : /* GDALRATGetTypeOfCol() */
323 : /************************************************************************/
324 :
325 : /**
326 : * \brief Fetch column type.
327 : *
328 : * This function is the same as the C++ method GDALRasterAttributeTable::GetTypeOfCol()
329 : */
330 : GDALRATFieldType CPL_STDCALL
331 5 : GDALRATGetTypeOfCol( GDALRasterAttributeTableH hRAT, int iCol )
332 :
333 : {
334 5 : VALIDATE_POINTER1( hRAT, "GDALRATGetTypeOfCol", GFT_Integer );
335 :
336 5 : return ((GDALRasterAttributeTable *) hRAT)->GetTypeOfCol( iCol );
337 : }
338 :
339 : /************************************************************************/
340 : /* GetColOfUsage() */
341 : /************************************************************************/
342 :
343 : /**
344 : * \brief Fetch column index for given usage.
345 : *
346 : * Returns the index of the first column of the requested usage type, or -1
347 : * if no match is found.
348 : *
349 : * This method is the same as the C function GDALRATGetUsageOfCol().
350 : *
351 : * @param eUsage usage type to search for.
352 : *
353 : * @return column index, or -1 on failure.
354 : */
355 :
356 8 : int GDALRasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
357 :
358 : {
359 : unsigned int i;
360 :
361 16 : for( i = 0; i < aoFields.size(); i++ )
362 : {
363 12 : if( aoFields[i].eUsage == eUsage )
364 4 : return i;
365 : }
366 :
367 4 : return -1;
368 : }
369 :
370 : /************************************************************************/
371 : /* GDALRATGetColOfUsage() */
372 : /************************************************************************/
373 :
374 : /**
375 : * \brief Fetch column index for given usage.
376 : *
377 : * This function is the same as the C++ method GDALRasterAttributeTable::GetColOfUsage()
378 : */
379 : int CPL_STDCALL
380 : GDALRATGetColOfUsage( GDALRasterAttributeTableH hRAT,
381 0 : GDALRATFieldUsage eUsage )
382 :
383 : {
384 0 : VALIDATE_POINTER1( hRAT, "GDALRATGetColOfUsage", 0 );
385 :
386 0 : return ((GDALRasterAttributeTable *) hRAT)->GetColOfUsage( eUsage );
387 : }
388 :
389 : /************************************************************************/
390 : /* GetRowCount() */
391 : /************************************************************************/
392 :
393 : /**
394 : * \brief Fetch row count.
395 : *
396 : * This method is the same as the C function GDALRATGetRowCount().
397 : *
398 : * @return the number of rows.
399 : */
400 :
401 7 : int GDALRasterAttributeTable::GetRowCount() const
402 :
403 : {
404 7 : return (int) nRowCount;
405 : }
406 :
407 : /************************************************************************/
408 : /* GDALRATGetUsageOfCol() */
409 : /************************************************************************/
410 : /**
411 : * \brief Fetch row count.
412 : *
413 : * This function is the same as the C++ method GDALRasterAttributeTable::GetRowCount()
414 : */
415 : int CPL_STDCALL
416 3 : GDALRATGetRowCount( GDALRasterAttributeTableH hRAT )
417 :
418 : {
419 3 : VALIDATE_POINTER1( hRAT, "GDALRATGetRowCount", 0 );
420 :
421 3 : return ((GDALRasterAttributeTable *) hRAT)->GetRowCount();
422 : }
423 :
424 : /************************************************************************/
425 : /* GetValueAsString() */
426 : /************************************************************************/
427 :
428 : /**
429 : * \brief Fetch field value as a string.
430 : *
431 : * The value of the requested column in the requested row is returned
432 : * as a string. If the field is numeric, it is formatted as a string
433 : * using default rules, so some precision may be lost.
434 : *
435 : * This method is the same as the C function GDALRATGetValueAsString().
436 : *
437 : * @param iRow row to fetch (zero based).
438 : * @param iField column to fetch (zero based).
439 : *
440 : * @return field value
441 : */
442 :
443 : const char *
444 0 : GDALRasterAttributeTable::GetValueAsString( int iRow, int iField ) const
445 :
446 : {
447 0 : if( iField < 0 || iField >= (int) aoFields.size() )
448 : {
449 : CPLError( CE_Failure, CPLE_AppDefined,
450 0 : "iField (%d) out of range.", iField );
451 :
452 0 : return "";
453 : }
454 :
455 0 : if( iRow < 0 || iRow >= nRowCount )
456 : {
457 : CPLError( CE_Failure, CPLE_AppDefined,
458 0 : "iRow (%d) out of range.", iRow );
459 :
460 0 : return "";
461 : }
462 :
463 0 : switch( aoFields[iField].eType )
464 : {
465 : case GFT_Integer:
466 : {
467 : ((GDALRasterAttributeTable *) this)->
468 0 : osWorkingResult.Printf( "%d", aoFields[iField].anValues[iRow] );
469 0 : return osWorkingResult;
470 : }
471 :
472 : case GFT_Real:
473 : {
474 : ((GDALRasterAttributeTable *) this)->
475 0 : osWorkingResult.Printf( "%.16g", aoFields[iField].adfValues[iRow]);
476 0 : return osWorkingResult;
477 : }
478 :
479 : case GFT_String:
480 : {
481 0 : return aoFields[iField].aosValues[iRow];
482 : }
483 : }
484 :
485 0 : return "";
486 : }
487 :
488 : /************************************************************************/
489 : /* GDALRATGetValueAsString() */
490 : /************************************************************************/
491 : /**
492 : * \brief Fetch field value as a string.
493 : *
494 : * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsString()
495 : */
496 : const char * CPL_STDCALL
497 0 : GDALRATGetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField )
498 :
499 : {
500 0 : VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsString", NULL );
501 :
502 0 : GDALRasterAttributeTable *poRAT = (GDALRasterAttributeTable *) hRAT;
503 :
504 0 : poRAT->osWorkingResult = poRAT->GetValueAsString( iRow, iField );
505 :
506 0 : return poRAT->osWorkingResult.c_str();
507 : }
508 :
509 : /************************************************************************/
510 : /* GetValueAsInt() */
511 : /************************************************************************/
512 :
513 : /**
514 : * \brief Fetch field value as a integer.
515 : *
516 : * The value of the requested column in the requested row is returned
517 : * as an integer. Non-integer fields will be converted to integer with
518 : * the possibility of data loss.
519 : *
520 : * This method is the same as the C function GDALRATGetValueAsInt().
521 : *
522 : * @param iRow row to fetch (zero based).
523 : * @param iField column to fetch (zero based).
524 : *
525 : * @return field value
526 : */
527 :
528 : int
529 4 : GDALRasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
530 :
531 : {
532 4 : if( iField < 0 || iField >= (int) aoFields.size() )
533 : {
534 : CPLError( CE_Failure, CPLE_AppDefined,
535 0 : "iField (%d) out of range.", iField );
536 :
537 0 : return 0;
538 : }
539 :
540 4 : if( iRow < 0 || iRow >= nRowCount )
541 : {
542 : CPLError( CE_Failure, CPLE_AppDefined,
543 0 : "iRow (%d) out of range.", iRow );
544 :
545 0 : return 0;
546 : }
547 :
548 4 : switch( aoFields[iField].eType )
549 : {
550 : case GFT_Integer:
551 4 : return aoFields[iField].anValues[iRow];
552 :
553 : case GFT_Real:
554 0 : return (int) aoFields[iField].adfValues[iRow];
555 :
556 : case GFT_String:
557 0 : return atoi( aoFields[iField].aosValues[iRow].c_str() );
558 : }
559 :
560 0 : return 0;
561 : }
562 :
563 : /************************************************************************/
564 : /* GDALRATGetValueAsInt() */
565 : /************************************************************************/
566 :
567 : /**
568 : * \brief Fetch field value as a integer.
569 : *
570 : * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsInt()
571 : */
572 : int CPL_STDCALL
573 4 : GDALRATGetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField )
574 :
575 : {
576 4 : VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsInt", 0 );
577 :
578 4 : return ((GDALRasterAttributeTable *) hRAT)->GetValueAsInt( iRow, iField );
579 : }
580 :
581 : /************************************************************************/
582 : /* GetValueAsDouble() */
583 : /************************************************************************/
584 :
585 : /**
586 : * \brief Fetch field value as a double.
587 : *
588 : * The value of the requested column in the requested row is returned
589 : * as a double. Non double fields will be converted to double with
590 : * the possibility of data loss.
591 : *
592 : * This method is the same as the C function GDALRATGetValueAsDouble().
593 : *
594 : * @param iRow row to fetch (zero based).
595 : * @param iField column to fetch (zero based).
596 : *
597 : * @return field value
598 : */
599 :
600 : double
601 0 : GDALRasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
602 :
603 : {
604 0 : if( iField < 0 || iField >= (int) aoFields.size() )
605 : {
606 : CPLError( CE_Failure, CPLE_AppDefined,
607 0 : "iField (%d) out of range.", iField );
608 :
609 0 : return 0;
610 : }
611 :
612 0 : if( iRow < 0 || iRow >= nRowCount )
613 : {
614 : CPLError( CE_Failure, CPLE_AppDefined,
615 0 : "iRow (%d) out of range.", iRow );
616 :
617 0 : return 0;
618 : }
619 :
620 0 : switch( aoFields[iField].eType )
621 : {
622 : case GFT_Integer:
623 0 : return aoFields[iField].anValues[iRow];
624 :
625 : case GFT_Real:
626 0 : return aoFields[iField].adfValues[iRow];
627 :
628 : case GFT_String:
629 0 : return atof( aoFields[iField].aosValues[iRow].c_str() );
630 : }
631 :
632 0 : return 0;
633 : }
634 :
635 : /************************************************************************/
636 : /* GDALRATGetValueAsDouble() */
637 : /************************************************************************/
638 :
639 : /**
640 : * \brief Fetch field value as a double.
641 : *
642 : * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsDouble()
643 : */
644 : double CPL_STDCALL
645 0 : GDALRATGetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField )
646 :
647 : {
648 0 : VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsDouble", 0 );
649 :
650 0 : return ((GDALRasterAttributeTable *) hRAT)->GetValueAsDouble(iRow,iField);
651 : }
652 :
653 : /************************************************************************/
654 : /* SetRowCount() */
655 : /************************************************************************/
656 :
657 : /**
658 : * \brief Set row count.
659 : *
660 : * Resizes the table to include the indicated number of rows. Newly created
661 : * rows will be initialized to their default values - "" for strings,
662 : * and zero for numeric fields.
663 : *
664 : * This method is the same as the C function GDALRATSetRowCount().
665 : *
666 : * @param nNewCount the new number of rows.
667 : */
668 :
669 11054 : void GDALRasterAttributeTable::SetRowCount( int nNewCount )
670 :
671 : {
672 11054 : if( nNewCount == nRowCount )
673 0 : return;
674 :
675 : unsigned int iField;
676 24987 : for( iField = 0; iField < aoFields.size(); iField++ )
677 : {
678 13933 : switch( aoFields[iField].eType )
679 : {
680 : case GFT_Integer:
681 7872 : aoFields[iField].anValues.resize( nNewCount );
682 7872 : break;
683 :
684 : case GFT_Real:
685 6061 : aoFields[iField].adfValues.resize( nNewCount );
686 6061 : break;
687 :
688 : case GFT_String:
689 0 : aoFields[iField].aosValues.resize( nNewCount );
690 : break;
691 : }
692 : }
693 :
694 11054 : nRowCount = nNewCount;
695 : }
696 :
697 : /************************************************************************/
698 : /* GDALRATSetRowCount() */
699 : /************************************************************************/
700 :
701 : /**
702 : * \brief Set row count.
703 : *
704 : * This function is the same as the C++ method GDALRasterAttributeTable::SetRowCount()
705 : */
706 : void CPL_STDCALL
707 1 : GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
708 :
709 : {
710 1 : VALIDATE_POINTER0( hRAT, "GDALRATSetRowCount" );
711 :
712 1 : ((GDALRasterAttributeTable *) hRAT)->SetRowCount( nNewCount );
713 : }
714 :
715 : /************************************************************************/
716 : /* SetValue() */
717 : /************************************************************************/
718 :
719 : /**
720 : * \brief Set field value from string.
721 : *
722 : * The indicated field (column) on the indicated row is set from the
723 : * passed value. The value will be automatically converted for other field
724 : * types, with a possible loss of precision.
725 : *
726 : * This method is the same as the C function GDALRATSetValueAsString().
727 : *
728 : * @param iRow row to fetch (zero based).
729 : * @param iField column to fetch (zero based).
730 : * @param pszValue the value to assign.
731 : */
732 :
733 : void GDALRasterAttributeTable::SetValue( int iRow, int iField,
734 690 : const char *pszValue )
735 :
736 : {
737 690 : if( iField < 0 || iField >= (int) aoFields.size() )
738 : {
739 : CPLError( CE_Failure, CPLE_AppDefined,
740 0 : "iField (%d) out of range.", iField );
741 :
742 0 : return;
743 : }
744 :
745 690 : if( iRow == nRowCount )
746 236 : SetRowCount( nRowCount+1 );
747 :
748 690 : if( iRow < 0 || iRow >= nRowCount )
749 : {
750 : CPLError( CE_Failure, CPLE_AppDefined,
751 0 : "iRow (%d) out of range.", iRow );
752 :
753 0 : return;
754 : }
755 :
756 690 : switch( aoFields[iField].eType )
757 : {
758 : case GFT_Integer:
759 242 : aoFields[iField].anValues[iRow] = atoi(pszValue);
760 242 : break;
761 :
762 : case GFT_Real:
763 230 : aoFields[iField].adfValues[iRow] = atof(pszValue);
764 230 : break;
765 :
766 : case GFT_String:
767 218 : aoFields[iField].aosValues[iRow] = pszValue;
768 : break;
769 : }
770 : }
771 :
772 : /************************************************************************/
773 : /* GDALRATSetValueAsString() */
774 : /************************************************************************/
775 :
776 : /**
777 : * \brief Set field value from string.
778 : *
779 : * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
780 : */
781 : void CPL_STDCALL
782 : GDALRATSetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField,
783 0 : const char *pszValue )
784 :
785 : {
786 0 : VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsString" );
787 :
788 0 : ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, pszValue );
789 : }
790 :
791 : /************************************************************************/
792 : /* SetValue() */
793 : /************************************************************************/
794 :
795 : /**
796 : * \brief Set field value from integer.
797 : *
798 : * The indicated field (column) on the indicated row is set from the
799 : * passed value. The value will be automatically converted for other field
800 : * types, with a possible loss of precision.
801 : *
802 : * This method is the same as the C function GDALRATSetValueAsInteger().
803 : *
804 : * @param iRow row to fetch (zero based).
805 : * @param iField column to fetch (zero based).
806 : * @param nValue the value to assign.
807 : */
808 :
809 : void GDALRasterAttributeTable::SetValue( int iRow, int iField,
810 7022 : int nValue )
811 :
812 : {
813 7022 : if( iField < 0 || iField >= (int) aoFields.size() )
814 : {
815 : CPLError( CE_Failure, CPLE_AppDefined,
816 0 : "iField (%d) out of range.", iField );
817 :
818 0 : return;
819 : }
820 :
821 7022 : if( iRow == nRowCount )
822 4156 : SetRowCount( nRowCount+1 );
823 :
824 7022 : if( iRow < 0 || iRow >= nRowCount )
825 : {
826 : CPLError( CE_Failure, CPLE_AppDefined,
827 0 : "iRow (%d) out of range.", iRow );
828 :
829 0 : return;
830 : }
831 :
832 7022 : switch( aoFields[iField].eType )
833 : {
834 : case GFT_Integer:
835 7022 : aoFields[iField].anValues[iRow] = nValue;
836 7022 : break;
837 :
838 : case GFT_Real:
839 0 : aoFields[iField].adfValues[iRow] = nValue;
840 0 : break;
841 :
842 : case GFT_String:
843 : {
844 : char szValue[100];
845 :
846 0 : sprintf( szValue, "%d", nValue );
847 0 : aoFields[iField].aosValues[iRow] = szValue;
848 : }
849 : break;
850 : }
851 : }
852 :
853 : /************************************************************************/
854 : /* GDALRATSetValueAsInt() */
855 : /************************************************************************/
856 :
857 : /**
858 : * \brief Set field value from integer.
859 : *
860 : * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
861 : */
862 : void CPL_STDCALL
863 : GDALRATSetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField,
864 6 : int nValue )
865 :
866 : {
867 6 : VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsInt" );
868 :
869 6 : ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, nValue);
870 : }
871 :
872 : /************************************************************************/
873 : /* SetValue() */
874 : /************************************************************************/
875 :
876 : /**
877 : * \brief Set field value from double.
878 : *
879 : * The indicated field (column) on the indicated row is set from the
880 : * passed value. The value will be automatically converted for other field
881 : * types, with a possible loss of precision.
882 : *
883 : * This method is the same as the C function GDALRATSetValueAsDouble().
884 : *
885 : * @param iRow row to fetch (zero based).
886 : * @param iField column to fetch (zero based).
887 : * @param dfValue the value to assign.
888 : */
889 :
890 : void GDALRasterAttributeTable::SetValue( int iRow, int iField,
891 9159 : double dfValue )
892 :
893 : {
894 9159 : if( iField < 0 || iField >= (int) aoFields.size() )
895 : {
896 : CPLError( CE_Failure, CPLE_AppDefined,
897 0 : "iField (%d) out of range.", iField );
898 :
899 0 : return;
900 : }
901 :
902 9159 : if( iRow == nRowCount )
903 6661 : SetRowCount( nRowCount+1 );
904 :
905 9159 : if( iRow < 0 || iRow >= nRowCount )
906 : {
907 : CPLError( CE_Failure, CPLE_AppDefined,
908 0 : "iRow (%d) out of range.", iRow );
909 :
910 0 : return;
911 : }
912 :
913 9159 : switch( aoFields[iField].eType )
914 : {
915 : case GFT_Integer:
916 830 : aoFields[iField].anValues[iRow] = (int) dfValue;
917 830 : break;
918 :
919 : case GFT_Real:
920 8329 : aoFields[iField].adfValues[iRow] = dfValue;
921 8329 : break;
922 :
923 : case GFT_String:
924 : {
925 : char szValue[100];
926 :
927 0 : sprintf( szValue, "%.15g", dfValue );
928 0 : aoFields[iField].aosValues[iRow] = szValue;
929 : }
930 : break;
931 : }
932 : }
933 :
934 : /************************************************************************/
935 : /* GDALRATSetValueAsDouble() */
936 : /************************************************************************/
937 :
938 : /**
939 : * \brief Set field value from double.
940 : *
941 : * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
942 : */
943 : void CPL_STDCALL
944 : GDALRATSetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField,
945 0 : double dfValue )
946 :
947 : {
948 0 : VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsDouble" );
949 :
950 0 : ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, dfValue );
951 : }
952 :
953 : /************************************************************************/
954 : /* GetRowOfValue() */
955 : /************************************************************************/
956 :
957 : /**
958 : * \brief Get row for pixel value.
959 : *
960 : * Given a raw pixel value, the raster attribute table is scanned to
961 : * determine which row in the table applies to the pixel value. The
962 : * row index is returned.
963 : *
964 : * This method is the same as the C function GDALRATGetRowOfValue().
965 : *
966 : * @param dfValue the pixel value.
967 : *
968 : * @return the row index or -1 if no row is appropriate.
969 : */
970 :
971 2 : int GDALRasterAttributeTable::GetRowOfValue( double dfValue ) const
972 :
973 : {
974 : /* -------------------------------------------------------------------- */
975 : /* Handle case of regular binning. */
976 : /* -------------------------------------------------------------------- */
977 2 : if( bLinearBinning )
978 : {
979 0 : int iBin = (int) floor((dfValue - dfRow0Min) / dfBinSize);
980 0 : if( iBin < 0 || iBin >= nRowCount )
981 0 : return -1;
982 : else
983 0 : return iBin;
984 : }
985 :
986 : /* -------------------------------------------------------------------- */
987 : /* Do we have any information? */
988 : /* -------------------------------------------------------------------- */
989 : const GDALRasterAttributeField *poMin, *poMax;
990 :
991 2 : if( !bColumnsAnalysed )
992 2 : ((GDALRasterAttributeTable *) this)->AnalyseColumns();
993 :
994 2 : if( nMinCol == -1 && nMaxCol == -1 )
995 0 : return -1;
996 :
997 2 : if( nMinCol != -1 )
998 2 : poMin = &(aoFields[nMinCol]);
999 : else
1000 0 : poMin = NULL;
1001 :
1002 2 : if( nMaxCol != -1 )
1003 2 : poMax = &(aoFields[nMaxCol]);
1004 : else
1005 0 : poMax = NULL;
1006 :
1007 : /* -------------------------------------------------------------------- */
1008 : /* Search through rows for match. */
1009 : /* -------------------------------------------------------------------- */
1010 : int iRow;
1011 :
1012 4 : for( iRow = 0; iRow < nRowCount; iRow++ )
1013 : {
1014 4 : if( poMin != NULL )
1015 : {
1016 4 : if( poMin->eType == GFT_Integer )
1017 : {
1018 8 : while( iRow < nRowCount && dfValue < poMin->anValues[iRow] )
1019 0 : iRow++;
1020 : }
1021 0 : else if( poMin->eType == GFT_Real )
1022 : {
1023 0 : while( iRow < nRowCount && dfValue < poMin->adfValues[iRow] )
1024 0 : iRow++;
1025 : }
1026 :
1027 4 : if( iRow == nRowCount )
1028 0 : break;
1029 : }
1030 :
1031 4 : if( poMax != NULL )
1032 : {
1033 4 : if( (poMax->eType == GFT_Integer
1034 : && dfValue > poMax->anValues[iRow] )
1035 : || (poMax->eType == GFT_Real
1036 : && dfValue > poMax->adfValues[iRow] ) )
1037 2 : continue;
1038 : }
1039 :
1040 2 : return iRow;
1041 : }
1042 :
1043 0 : return -1;
1044 : }
1045 :
1046 : /************************************************************************/
1047 : /* GetRowOfValue() */
1048 : /* */
1049 : /* Int arg for now just converted to double. Perhaps we will */
1050 : /* handle this in a special way some day? */
1051 : /************************************************************************/
1052 :
1053 0 : int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
1054 :
1055 : {
1056 0 : return GetRowOfValue( (double) nValue );
1057 : }
1058 :
1059 : /************************************************************************/
1060 : /* GDALRATGetRowOfValue() */
1061 : /************************************************************************/
1062 :
1063 : /**
1064 : * \brief Get row for pixel value.
1065 : *
1066 : * This function is the same as the C++ method GDALRasterAttributeTable::GetRowOfValue()
1067 : */
1068 : int CPL_STDCALL
1069 2 : GDALRATGetRowOfValue( GDALRasterAttributeTableH hRAT, double dfValue )
1070 :
1071 : {
1072 2 : VALIDATE_POINTER1( hRAT, "GDALRATGetRowOfValue", 0 );
1073 :
1074 2 : return ((GDALRasterAttributeTable *) hRAT)->GetRowOfValue( dfValue );
1075 : }
1076 :
1077 : /************************************************************************/
1078 : /* SetLinearBinning() */
1079 : /************************************************************************/
1080 :
1081 : /**
1082 : * \brief Set linear binning information.
1083 : *
1084 : * For RATs with equal sized categories (in pixel value space) that are
1085 : * evenly spaced, this method may be used to associate the linear binning
1086 : * information with the table.
1087 : *
1088 : * This method is the same as the C function GDALRATSetLinearBinning().
1089 : *
1090 : * @param dfRow0MinIn the lower bound (pixel value) of the first category.
1091 : * @param dfBinSizeIn the width of each category (in pixel value units).
1092 : *
1093 : * @return CE_None on success or CE_Failure on failure.
1094 : */
1095 :
1096 : CPLErr GDALRasterAttributeTable::SetLinearBinning( double dfRow0MinIn,
1097 31 : double dfBinSizeIn )
1098 :
1099 : {
1100 31 : bLinearBinning = TRUE;
1101 31 : dfRow0Min = dfRow0MinIn;
1102 31 : dfBinSize = dfBinSizeIn;
1103 :
1104 31 : return CE_None;
1105 : }
1106 :
1107 : /************************************************************************/
1108 : /* GDALRATSetLinearBinning() */
1109 : /************************************************************************/
1110 :
1111 : /**
1112 : * \brief Set linear binning information.
1113 : *
1114 : * This function is the same as the C++ method GDALRasterAttributeTable::SetLinearBinning()
1115 : */
1116 : CPLErr CPL_STDCALL
1117 : GDALRATSetLinearBinning( GDALRasterAttributeTableH hRAT,
1118 0 : double dfRow0Min, double dfBinSize )
1119 :
1120 : {
1121 0 : VALIDATE_POINTER1( hRAT, "GDALRATSetLinearBinning", CE_Failure );
1122 :
1123 : return ((GDALRasterAttributeTable *) hRAT)->SetLinearBinning(
1124 0 : dfRow0Min, dfBinSize );
1125 : }
1126 :
1127 : /************************************************************************/
1128 : /* GetLinearBinning() */
1129 : /************************************************************************/
1130 :
1131 : /**
1132 : * \brief Get linear binning information.
1133 : *
1134 : * Returns linear binning information if any is associated with the RAT.
1135 : *
1136 : * This method is the same as the C function GDALRATGetLinearBinning().
1137 : *
1138 : * @param pdfRow0Min (out) the lower bound (pixel value) of the first category.
1139 : * @param pdfBinSize (out) the width of each category (in pixel value units).
1140 : *
1141 : * @return TRUE if linear binning information exists or FALSE if there is none.
1142 : */
1143 :
1144 : int GDALRasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
1145 0 : double *pdfBinSize ) const
1146 :
1147 : {
1148 0 : if( !bLinearBinning )
1149 0 : return FALSE;
1150 :
1151 0 : *pdfRow0Min = dfRow0Min;
1152 0 : *pdfBinSize = dfBinSize;
1153 :
1154 0 : return TRUE;
1155 : }
1156 :
1157 : /************************************************************************/
1158 : /* GDALRATGetLinearBinning() */
1159 : /************************************************************************/
1160 :
1161 : /**
1162 : * \brief Get linear binning information.
1163 : *
1164 : * This function is the same as the C++ method GDALRasterAttributeTable::GetLinearBinning()
1165 : */
1166 : int CPL_STDCALL
1167 : GDALRATGetLinearBinning( GDALRasterAttributeTableH hRAT,
1168 0 : double *pdfRow0Min, double *pdfBinSize )
1169 :
1170 : {
1171 0 : VALIDATE_POINTER1( hRAT, "GDALRATGetLinearBinning", 0 );
1172 :
1173 : return ((GDALRasterAttributeTable *) hRAT)->GetLinearBinning(
1174 0 : pdfRow0Min, pdfBinSize );
1175 : }
1176 :
1177 : /************************************************************************/
1178 : /* CreateColumn() */
1179 : /************************************************************************/
1180 :
1181 : /**
1182 : * \brief Create new column.
1183 : *
1184 : * If the table already has rows, all row values for the new column will
1185 : * be initialized to the default value ("", or zero). The new column is
1186 : * always created as the last column, can will be column (field)
1187 : * "GetColumnCount()-1" after CreateColumn() has completed successfully.
1188 : *
1189 : * This method is the same as the C function GDALRATCreateColumn().
1190 : *
1191 : * @param pszFieldName the name of the field to create.
1192 : * @param eFieldType the field type (integer, double or string).
1193 : * @param eFieldUsage the field usage, GFU_Generic if not known.
1194 : *
1195 : * @return CE_None on success or CE_Failure if something goes wrong.
1196 : */
1197 :
1198 : CPLErr GDALRasterAttributeTable::CreateColumn( const char *pszFieldName,
1199 : GDALRATFieldType eFieldType,
1200 78 : GDALRATFieldUsage eFieldUsage )
1201 :
1202 : {
1203 78 : int iNewField = aoFields.size();
1204 :
1205 78 : aoFields.resize( iNewField+1 );
1206 :
1207 156 : aoFields[iNewField].sName = pszFieldName;
1208 78 : aoFields[iNewField].eType = eFieldType;
1209 78 : aoFields[iNewField].eUsage = eFieldUsage;
1210 :
1211 78 : if( eFieldType == GFT_Integer )
1212 26 : aoFields[iNewField].anValues.resize( nRowCount );
1213 52 : else if( eFieldType == GFT_Real )
1214 51 : aoFields[iNewField].adfValues.resize( nRowCount );
1215 1 : else if( eFieldType == GFT_String )
1216 1 : aoFields[iNewField].aosValues.resize( nRowCount );
1217 :
1218 78 : return CE_None;
1219 : }
1220 :
1221 : /************************************************************************/
1222 : /* GDALRATCreateColumn() */
1223 : /************************************************************************/
1224 :
1225 : /**
1226 : * \brief Create new column.
1227 : *
1228 : * This function is the same as the C++ method GDALRasterAttributeTable::CreateColumn()
1229 : */
1230 : CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT,
1231 : const char *pszFieldName,
1232 : GDALRATFieldType eFieldType,
1233 2 : GDALRATFieldUsage eFieldUsage )
1234 :
1235 : {
1236 2 : VALIDATE_POINTER1( hRAT, "GDALRATCreateColumn", CE_Failure );
1237 :
1238 : return ((GDALRasterAttributeTable *) hRAT)->CreateColumn( pszFieldName,
1239 : eFieldType,
1240 2 : eFieldUsage );
1241 : }
1242 :
1243 : /************************************************************************/
1244 : /* InitializeFromColorTable() */
1245 : /************************************************************************/
1246 :
1247 : /**
1248 : * \brief Initialize from color table.
1249 : *
1250 : * This method will setup a whole raster attribute table based on the
1251 : * contents of the passed color table. The Value (GFU_MinMax),
1252 : * Red (GFU_Red), Green (GFU_Green), Blue (GFU_Blue), and Alpha (GFU_Alpha)
1253 : * fields are created, and a row is set for each entry in the color table.
1254 : *
1255 : * The raster attribute table must be empty before calling
1256 : * InitializeFromColorTable().
1257 : *
1258 : * The Value fields are set based on the implicit assumption with color
1259 : * tables that entry 0 applies to pixel value 0, 1 to 1, etc.
1260 : *
1261 : * This method is the same as the C function GDALRATInitializeFromColorTable().
1262 : *
1263 : * @param poTable the color table to copy from.
1264 : *
1265 : * @param CE_None on success or CE_Failure if something goes wrong.
1266 : */
1267 :
1268 : CPLErr GDALRasterAttributeTable::InitializeFromColorTable(
1269 0 : const GDALColorTable *poTable )
1270 :
1271 : {
1272 : int iRow;
1273 :
1274 0 : if( GetRowCount() > 0 || GetColumnCount() > 0 )
1275 : {
1276 : CPLError( CE_Failure, CPLE_AppDefined,
1277 0 : "Raster Attribute Table not empty in InitializeFromColorTable()" );
1278 0 : return CE_Failure;
1279 : }
1280 :
1281 0 : SetLinearBinning( 0.0, 1.0 );
1282 0 : CreateColumn( "Value", GFT_Integer, GFU_MinMax );
1283 0 : CreateColumn( "Red", GFT_Integer, GFU_Red );
1284 0 : CreateColumn( "Green", GFT_Integer, GFU_Green );
1285 0 : CreateColumn( "Blue", GFT_Integer, GFU_Blue );
1286 0 : CreateColumn( "Alpha", GFT_Integer, GFU_Alpha );
1287 :
1288 0 : SetRowCount( poTable->GetColorEntryCount() );
1289 :
1290 0 : for( iRow = 0; iRow < poTable->GetColorEntryCount(); iRow++ )
1291 : {
1292 : GDALColorEntry sEntry;
1293 :
1294 0 : poTable->GetColorEntryAsRGB( iRow, &sEntry );
1295 :
1296 0 : SetValue( iRow, 0, iRow );
1297 0 : SetValue( iRow, 1, sEntry.c1 );
1298 0 : SetValue( iRow, 2, sEntry.c2 );
1299 0 : SetValue( iRow, 3, sEntry.c3 );
1300 0 : SetValue( iRow, 4, sEntry.c4 );
1301 : }
1302 :
1303 0 : return CE_None;
1304 : }
1305 :
1306 : /************************************************************************/
1307 : /* GDALRATInitializeFromColorTable() */
1308 : /************************************************************************/
1309 :
1310 : /**
1311 : * \brief Initialize from color table.
1312 : *
1313 : * This function is the same as the C++ method GDALRasterAttributeTable::InitializeFromColorTable()
1314 : */
1315 : CPLErr CPL_STDCALL
1316 : GDALRATInitializeFromColorTable( GDALRasterAttributeTableH hRAT,
1317 0 : GDALColorTableH hCT )
1318 :
1319 :
1320 : {
1321 0 : VALIDATE_POINTER1( hRAT, "GDALRATInitializeFromColorTable", CE_Failure );
1322 :
1323 : return ((GDALRasterAttributeTable *) hRAT)->
1324 0 : InitializeFromColorTable( (GDALColorTable *) hCT );
1325 : }
1326 :
1327 : /************************************************************************/
1328 : /* TranslateToColorTable() */
1329 : /************************************************************************/
1330 :
1331 : /**
1332 : * \brief Translate to a color table.
1333 : *
1334 : * This method will attempt to create a corresponding GDALColorTable from
1335 : * this raster attribute table.
1336 : *
1337 : * This method is the same as the C function GDALRATTranslateToColorTable().
1338 : *
1339 : * @param nEntryCount The number of entries to produce (0 to nEntryCount-1), or -1 to auto-determine the number of entries.
1340 : *
1341 : * @return the generated color table or NULL on failure.
1342 : */
1343 :
1344 : GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable(
1345 0 : int nEntryCount )
1346 :
1347 : {
1348 : /* -------------------------------------------------------------------- */
1349 : /* Establish which fields are red, green, blue and alpha. */
1350 : /* -------------------------------------------------------------------- */
1351 : int iRed, iGreen, iBlue, iAlpha;
1352 :
1353 0 : iRed = GetColOfUsage( GFU_Red );
1354 0 : iGreen = GetColOfUsage( GFU_Green );
1355 0 : iBlue = GetColOfUsage( GFU_Blue );
1356 0 : iAlpha = GetColOfUsage( GFU_Alpha );
1357 :
1358 0 : if( iRed == -1 || iGreen == -1 || iBlue == -1 )
1359 0 : return NULL;
1360 :
1361 : /* -------------------------------------------------------------------- */
1362 : /* If we aren't given an explicit number of values to scan for, */
1363 : /* search for the maximum "max" value. */
1364 : /* -------------------------------------------------------------------- */
1365 0 : if( nEntryCount == -1 )
1366 : {
1367 : int iRow;
1368 : int iMaxCol;
1369 :
1370 0 : iMaxCol = GetColOfUsage( GFU_Max );
1371 0 : if( iMaxCol == -1 )
1372 0 : iMaxCol = GetColOfUsage( GFU_MinMax );
1373 :
1374 0 : if( iMaxCol == -1 || nRowCount == 0 )
1375 0 : return NULL;
1376 :
1377 0 : for( iRow = 0; iRow < nRowCount; iRow++ )
1378 0 : nEntryCount = MAX(nEntryCount,GetValueAsInt(iRow,iMaxCol)+1);
1379 :
1380 0 : if( nEntryCount < 0 )
1381 0 : return NULL;
1382 :
1383 : // restrict our number of entries to something vaguely sensible
1384 0 : nEntryCount = MIN(65535,nEntryCount);
1385 : }
1386 :
1387 : /* -------------------------------------------------------------------- */
1388 : /* Assign values to color table. */
1389 : /* -------------------------------------------------------------------- */
1390 0 : GDALColorTable *poCT = new GDALColorTable();
1391 : int iEntry;
1392 :
1393 0 : for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
1394 : {
1395 : GDALColorEntry sColor;
1396 0 : int iRow = GetRowOfValue( iEntry );
1397 :
1398 0 : if( iRow == -1 )
1399 : {
1400 0 : sColor.c1 = sColor.c2 = sColor.c3 = sColor.c4 = 0;
1401 : }
1402 : else
1403 : {
1404 0 : sColor.c1 = GetValueAsInt( iRow, iRed );
1405 0 : sColor.c2 = GetValueAsInt( iRow, iGreen );
1406 0 : sColor.c3 = GetValueAsInt( iRow, iBlue );
1407 0 : if( iAlpha == -1 )
1408 0 : sColor.c4 = 255;
1409 : else
1410 0 : sColor.c4 = GetValueAsInt( iRow, iAlpha );
1411 : }
1412 :
1413 0 : poCT->SetColorEntry( iEntry, &sColor );
1414 : }
1415 :
1416 0 : return poCT;
1417 : }
1418 :
1419 : /************************************************************************/
1420 : /* GDALRATInitializeFromColorTable() */
1421 : /************************************************************************/
1422 :
1423 : /**
1424 : * \brief Translate to a color table.
1425 : *
1426 : * This function is the same as the C++ method GDALRasterAttributeTable::TranslateToColorTable()
1427 : */
1428 : GDALColorTableH CPL_STDCALL
1429 : GDALRATTranslateToColorTable( GDALRasterAttributeTableH hRAT,
1430 0 : int nEntryCount )
1431 :
1432 :
1433 : {
1434 0 : VALIDATE_POINTER1( hRAT, "GDALRATTranslateToColorTable", NULL );
1435 :
1436 : return ((GDALRasterAttributeTable *) hRAT)->
1437 0 : TranslateToColorTable( nEntryCount );
1438 : }
1439 :
1440 : /************************************************************************/
1441 : /* XMLInit() */
1442 : /************************************************************************/
1443 :
1444 : CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree,
1445 4 : const char * /*pszVRTPath*/ )
1446 :
1447 : {
1448 4 : CPLAssert( GetRowCount() == 0 && GetColumnCount() == 0 );
1449 :
1450 : /* -------------------------------------------------------------------- */
1451 : /* Linear binning. */
1452 : /* -------------------------------------------------------------------- */
1453 4 : if( CPLGetXMLValue( psTree, "Row0Min", NULL )
1454 : && CPLGetXMLValue( psTree, "BinSize", NULL ) )
1455 : {
1456 : SetLinearBinning( atof(CPLGetXMLValue( psTree, "Row0Min","" )),
1457 0 : atof(CPLGetXMLValue( psTree, "BinSize","" )) );
1458 : }
1459 :
1460 : /* -------------------------------------------------------------------- */
1461 : /* Column definitions */
1462 : /* -------------------------------------------------------------------- */
1463 : CPLXMLNode *psChild;
1464 :
1465 248 : for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
1466 : {
1467 244 : if( psChild->eType == CXT_Element
1468 : && EQUAL(psChild->pszValue,"FieldDefn") )
1469 : {
1470 : CreateColumn(
1471 : CPLGetXMLValue( psChild, "Name", "" ),
1472 : (GDALRATFieldType) atoi(CPLGetXMLValue( psChild, "Type", "1" )),
1473 8 : (GDALRATFieldUsage) atoi(CPLGetXMLValue( psChild, "Usage","0")));
1474 : }
1475 : }
1476 :
1477 : /* -------------------------------------------------------------------- */
1478 : /* Row data. */
1479 : /* -------------------------------------------------------------------- */
1480 248 : for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
1481 : {
1482 244 : if( psChild->eType == CXT_Element
1483 : && EQUAL(psChild->pszValue,"Row") )
1484 : {
1485 236 : int iRow = atoi(CPLGetXMLValue(psChild,"index","0"));
1486 236 : int iField = 0;
1487 : CPLXMLNode *psF;
1488 :
1489 944 : for( psF = psChild->psChild; psF != NULL; psF = psF->psNext )
1490 : {
1491 708 : if( psF->eType != CXT_Element || !EQUAL(psF->pszValue,"F") )
1492 236 : continue;
1493 :
1494 944 : if( psF->psChild != NULL && psF->psChild->eType == CXT_Text )
1495 472 : SetValue( iRow, iField++, psF->psChild->pszValue );
1496 : else
1497 0 : SetValue( iRow, iField++, "" );
1498 : }
1499 : }
1500 : }
1501 :
1502 4 : return CE_None;
1503 : }
1504 :
1505 : /************************************************************************/
1506 : /* Serialize() */
1507 : /************************************************************************/
1508 :
1509 4 : CPLXMLNode *GDALRasterAttributeTable::Serialize() const
1510 :
1511 : {
1512 4 : CPLXMLNode *psTree = NULL;
1513 4 : CPLXMLNode *psRow = NULL;
1514 :
1515 4 : psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALRasterAttributeTable" );
1516 :
1517 : /* -------------------------------------------------------------------- */
1518 : /* Add attributes with regular binning info if appropriate. */
1519 : /* -------------------------------------------------------------------- */
1520 : char szValue[128];
1521 :
1522 4 : if( bLinearBinning )
1523 : {
1524 2 : sprintf( szValue, "%.16g", dfRow0Min );
1525 : CPLCreateXMLNode(
1526 : CPLCreateXMLNode( psTree, CXT_Attribute, "Row0Min" ),
1527 2 : CXT_Text, szValue );
1528 :
1529 2 : sprintf( szValue, "%.16g", dfBinSize );
1530 : CPLCreateXMLNode(
1531 : CPLCreateXMLNode( psTree, CXT_Attribute, "BinSize" ),
1532 2 : CXT_Text, szValue );
1533 : }
1534 :
1535 : /* -------------------------------------------------------------------- */
1536 : /* Define each column. */
1537 : /* -------------------------------------------------------------------- */
1538 : int iCol;
1539 :
1540 10 : for( iCol = 0; iCol < (int) aoFields.size(); iCol++ )
1541 : {
1542 : CPLXMLNode *psCol;
1543 :
1544 6 : psCol = CPLCreateXMLNode( psTree, CXT_Element, "FieldDefn" );
1545 :
1546 6 : sprintf( szValue, "%d", iCol );
1547 : CPLCreateXMLNode(
1548 : CPLCreateXMLNode( psCol, CXT_Attribute, "index" ),
1549 6 : CXT_Text, szValue );
1550 :
1551 : CPLCreateXMLElementAndValue( psCol, "Name",
1552 6 : aoFields[iCol].sName.c_str() );
1553 :
1554 6 : sprintf( szValue, "%d", (int) aoFields[iCol].eType );
1555 6 : CPLCreateXMLElementAndValue( psCol, "Type", szValue );
1556 :
1557 6 : sprintf( szValue, "%d", (int) aoFields[iCol].eUsage );
1558 6 : CPLCreateXMLElementAndValue( psCol, "Usage", szValue );
1559 : }
1560 :
1561 : /* -------------------------------------------------------------------- */
1562 : /* Write out each row. */
1563 : /* -------------------------------------------------------------------- */
1564 : int iRow;
1565 4 : CPLXMLNode *psTail = NULL;
1566 :
1567 595 : for( iRow = 0; iRow < nRowCount; iRow++ )
1568 : {
1569 591 : psRow = CPLCreateXMLNode( NULL, CXT_Element, "Row" );
1570 591 : if( psTail == NULL )
1571 4 : CPLAddXMLChild( psTree, psRow );
1572 : else
1573 587 : psTail->psNext = psRow;
1574 591 : psTail = psRow;
1575 :
1576 591 : sprintf( szValue, "%d", iRow );
1577 : CPLCreateXMLNode(
1578 : CPLCreateXMLNode( psRow, CXT_Attribute, "index" ),
1579 591 : CXT_Text, szValue );
1580 :
1581 1300 : for( iCol = 0; iCol < (int) aoFields.size(); iCol++ )
1582 : {
1583 709 : const char *pszValue = szValue;
1584 :
1585 709 : if( aoFields[iCol].eType == GFT_Integer )
1586 121 : sprintf( szValue, "%d", aoFields[iCol].anValues[iRow] );
1587 588 : else if( aoFields[iCol].eType == GFT_Real )
1588 588 : sprintf( szValue, "%.16g", aoFields[iCol].adfValues[iRow] );
1589 : else
1590 0 : pszValue = aoFields[iCol].aosValues[iRow].c_str();
1591 :
1592 709 : CPLCreateXMLElementAndValue( psRow, "F", pszValue );
1593 : }
1594 : }
1595 :
1596 4 : return psTree;
1597 : }
1598 :
1599 : /************************************************************************/
1600 : /* DumpReadable() */
1601 : /************************************************************************/
1602 :
1603 : /**
1604 : * \brief Dump RAT in readable form.
1605 : *
1606 : * Currently the readable form is the XML encoding ... only barely
1607 : * readable.
1608 : *
1609 : * This method is the same as the C function GDALRATDumpReadable().
1610 : *
1611 : * @param fp file to dump to or NULL for stdout.
1612 : */
1613 :
1614 1 : void GDALRasterAttributeTable::DumpReadable( FILE * fp )
1615 :
1616 : {
1617 1 : CPLXMLNode *psTree = Serialize();
1618 1 : char *pszXMLText = CPLSerializeXMLTree( psTree );
1619 :
1620 1 : CPLDestroyXMLNode( psTree );
1621 :
1622 1 : if( fp == NULL )
1623 1 : fp = stdout;
1624 :
1625 1 : fprintf( fp, "%s\n", pszXMLText );
1626 :
1627 1 : CPLFree( pszXMLText );
1628 1 : }
1629 :
1630 : /************************************************************************/
1631 : /* GDALRATDumpReadable() */
1632 : /************************************************************************/
1633 :
1634 : /**
1635 : * \brief Dump RAT in readable form.
1636 : *
1637 : * This function is the same as the C++ method GDALRasterAttributeTable::DumpReadable()
1638 : */
1639 : void CPL_STDCALL
1640 1 : GDALRATDumpReadable( GDALRasterAttributeTableH hRAT, FILE *fp )
1641 :
1642 : {
1643 1 : VALIDATE_POINTER0( hRAT, "GDALRATDumpReadable" );
1644 :
1645 1 : ((GDALRasterAttributeTable *) hRAT)->DumpReadable( fp );
1646 : }
1647 :
1648 : /************************************************************************/
1649 : /* Clone() */
1650 : /************************************************************************/
1651 :
1652 : /**
1653 : * \brief Copy Raster Attribute Table
1654 : *
1655 : * Creates a new copy of an existing raster attribute table. The new copy
1656 : * becomes the responsibility of the caller to destroy.
1657 : *
1658 : * This method is the same as the C function GDALRATClone().
1659 : *
1660 : * @return new copy of the RAT.
1661 : */
1662 :
1663 5 : GDALRasterAttributeTable *GDALRasterAttributeTable::Clone() const
1664 :
1665 : {
1666 5 : return new GDALRasterAttributeTable( *this );
1667 : }
1668 :
1669 : /************************************************************************/
1670 : /* GDALRATClone() */
1671 : /************************************************************************/
1672 :
1673 : /**
1674 : * \brief Copy Raster Attribute Table
1675 : *
1676 : * This function is the same as the C++ method GDALRasterAttributeTable::Clone()
1677 : */
1678 : GDALRasterAttributeTableH CPL_STDCALL
1679 1 : GDALRATClone( GDALRasterAttributeTableH hRAT )
1680 :
1681 : {
1682 1 : VALIDATE_POINTER1( hRAT, "GDALRATClone", NULL );
1683 :
1684 1 : return ((GDALRasterAttributeTable *) hRAT)->Clone();
1685 : }
|