1 /******************************************************************************
2  *
3  * Name:     georaster_rasterband.cpp
4  * Project:  Oracle Spatial GeoRaster Driver
5  * Purpose:  Implement GeoRasterRasterBand methods
6  * Author:   Ivan Lucena [ivan.lucena at oracle.com]
7  *
8  ******************************************************************************
9  * Copyright (c) 2008, Ivan Lucena
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 #include <string.h>
33 
34 #include "georaster_priv.h"
35 #include "cpl_vsi.h"
36 #include "cpl_error.h"
37 
38 CPL_CVSID("$Id: georaster_rasterband.cpp fa752ad6eabafaf630a704e1892a9d837d683cb3 2021-03-06 17:04:38 +0100 Even Rouault $")
39 
40 //  ---------------------------------------------------------------------------
41 //                                                        GeoRasterRasterBand()
42 //  ---------------------------------------------------------------------------
43 
GeoRasterRasterBand(GeoRasterDataset * poGDS,int nBandIn,int nLevel,GDALDataset * poJP2DatasetIn)44 GeoRasterRasterBand::GeoRasterRasterBand( GeoRasterDataset *poGDS,
45                                           int nBandIn,
46                                           int nLevel,
47                                           GDALDataset* poJP2DatasetIn )
48 {
49     poDS                = (GDALDataset*) poGDS;
50     poGeoRaster         = poGDS->poGeoRaster;
51     this->nBand         = nBandIn;
52     this->eDataType     = OWGetDataType( poGeoRaster->sCellDepth.c_str() );
53     poColorTable        = new GDALColorTable();
54     poDefaultRAT        = nullptr;
55     pszVATName          = nullptr;
56     nRasterXSize        = poGeoRaster->nRasterColumns;
57     nRasterYSize        = poGeoRaster->nRasterRows;
58     nBlockXSize         = poGeoRaster->nColumnBlockSize;
59     nBlockYSize         = poGeoRaster->nRowBlockSize;
60     dfNoData            = 0.0;
61     bValidStats         = false;
62     nOverviewLevel      = nLevel;
63     papoOverviews       = nullptr;
64     nOverviewCount      = 0;
65     pahNoDataArray      = nullptr;
66     nNoDataArraySz      = 0;
67     bHasNoDataArray     = false;
68     dfMin               = 0.0;
69     dfMax               = 0.0;
70     dfMean              = 0.0;
71     dfMedian            = 0.0;
72     dfMode              = 0.0;
73     dfStdDev            = 0.0;
74 
75     poJP2Dataset        = poJP2DatasetIn;
76 
77     //  -----------------------------------------------------------------------
78     //  Initialize overview list
79     //  -----------------------------------------------------------------------
80 
81     if( nLevel == 0 && poGeoRaster->nPyramidMaxLevel > 0 )
82     {
83         nOverviewCount  = poGeoRaster->nPyramidMaxLevel;
84         papoOverviews   = (GeoRasterRasterBand**) VSIMalloc(
85                 sizeof(GeoRasterRasterBand*) * nOverviewCount );
86         for( int i = 0; i < nOverviewCount; i++ )
87         {
88           papoOverviews[i] = new GeoRasterRasterBand(
89                 (GeoRasterDataset*) poDS, nBand, i + 1, poJP2Dataset );
90         }
91     }
92 
93     //  -----------------------------------------------------------------------
94     //  Initialize this band as an overview
95     //  -----------------------------------------------------------------------
96 
97     if( nLevel )
98     {
99         double dfScale  = pow( (double) 2.0, (double) nLevel );
100 
101         nRasterXSize    = (int) floor( nRasterXSize / dfScale );
102         nRasterYSize    = (int) floor( nRasterYSize / dfScale );
103 
104         if( nRasterXSize <= ( nBlockXSize / 2.0 ) &&
105             nRasterYSize <= ( nBlockYSize / 2.0 ) )
106         {
107             nBlockXSize = nRasterXSize;
108             nBlockYSize = nRasterYSize;
109         }
110     }
111 
112     //  -----------------------------------------------------------------------
113     //  Load NoData values and value ranges for this band (layer)
114     //  -----------------------------------------------------------------------
115 
116     if( ( (GeoRasterDataset*) poDS)->bApplyNoDataArray )
117     {
118         CPLList* psList = nullptr;
119         int nLayerCount = 0;
120         int nObjCount = 0;
121 
122         /*
123          *  Count the number of NoData values and value ranges
124          */
125 
126         for( psList = poGeoRaster->psNoDataList; psList ; psList = psList->psNext )
127         {
128             hNoDataItem* phItem = (hNoDataItem*) psList->pData;
129 
130             if( phItem->nBand == nBand )
131             {
132                 nLayerCount++;
133             }
134 
135             if( phItem->nBand == 0 )
136             {
137                 nObjCount++;
138             }
139 
140             if( phItem->nBand > nBand )
141             {
142                 break;
143             }
144         }
145 
146         /*
147          * Join the object nodata values to layer NoData values
148          */
149 
150         nNoDataArraySz = nLayerCount + nObjCount;
151 
152         pahNoDataArray = (hNoDataItem*) VSIMalloc2( sizeof(hNoDataItem),
153                 nNoDataArraySz );
154 
155         int i = 0;
156         bool bFirst = true;
157 
158         for( psList = poGeoRaster->psNoDataList ; psList && i < nNoDataArraySz;
159              psList = psList->psNext )
160         {
161             hNoDataItem* phItem = (hNoDataItem*) psList->pData;
162 
163             if( phItem->nBand == nBand || phItem->nBand == 0 )
164             {
165                 pahNoDataArray[i].nBand = nBand;
166                 pahNoDataArray[i].dfLower = phItem->dfLower;
167                 pahNoDataArray[i].dfUpper = phItem->dfUpper;
168                 i++;
169 
170                 if( bFirst )
171                 {
172                     bFirst = false;
173 
174                     /*
175                      * Use the first value to assigned pixel values
176                      * on method ApplyNoDataArray()
177                      */
178 
179                     dfNoData = phItem->dfLower;
180                 }
181             }
182         }
183 
184         bHasNoDataArray = nNoDataArraySz > 0;
185     }
186 }
187 
188 //  ---------------------------------------------------------------------------
189 //                                                       ~GeoRasterRasterBand()
190 //  ---------------------------------------------------------------------------
191 
~GeoRasterRasterBand()192 GeoRasterRasterBand::~GeoRasterRasterBand()
193 {
194     delete poColorTable;
195     delete poDefaultRAT;
196 
197     CPLFree( pszVATName );
198     CPLFree( pahNoDataArray );
199 
200     if( nOverviewCount && papoOverviews )
201     {
202         for( int i = 0; i < nOverviewCount; i++ )
203         {
204             delete papoOverviews[i];
205         }
206 
207         CPLFree( papoOverviews );
208     }
209 }
210 
211 //  ---------------------------------------------------------------------------
212 //                                                                 IReadBlock()
213 //  ---------------------------------------------------------------------------
214 
IReadBlock(int nBlockXOff,int nBlockYOff,void * pImage)215 CPLErr GeoRasterRasterBand::IReadBlock( int nBlockXOff,
216                                         int nBlockYOff,
217                                         void *pImage )
218 {
219     if( poJP2Dataset )
220     {
221         int nXOff      = nBlockXOff * poGeoRaster->nColumnBlockSize;
222         int nYOff      = nBlockYOff * poGeoRaster->nRowBlockSize;
223         int nXSize     = poGeoRaster->nColumnBlockSize;
224         int nYSize     = poGeoRaster->nRowBlockSize;
225         int nBufXSize  = nBlockXSize;
226         int nBufYSize  = nBlockYSize;
227 
228         return GDALDatasetRasterIO( poJP2Dataset, GF_Read,
229                     nXOff, nYOff, nXSize, nYSize, pImage,
230                     nBufXSize, nBufYSize, eDataType,
231                     1, &nBand, 0, 0, 0 );
232     }
233 
234     if( poGeoRaster->GetDataBlock( nBand,
235                                    nOverviewLevel,
236                                    nBlockXOff,
237                                    nBlockYOff,
238                                    pImage ) )
239     {
240         if( bHasNoDataArray )
241         {
242             ApplyNoDataArray( pImage );
243         }
244 
245         return CE_None;
246     }
247     else
248     {
249         CPLError( CE_Failure, CPLE_AppDefined,
250                   "Error reading GeoRaster offset X (%d) offset Y (%d) "
251                   "band (%d)",
252                   nBlockXOff, nBlockYOff, nBand );
253         return CE_Failure;
254     }
255 }
256 
257 //  ---------------------------------------------------------------------------
258 //                                                                IWriteBlock()
259 //  ---------------------------------------------------------------------------
260 
IWriteBlock(int nBlockXOff,int nBlockYOff,void * pImage)261 CPLErr GeoRasterRasterBand::IWriteBlock( int nBlockXOff,
262                                          int nBlockYOff,
263                                          void *pImage )
264 {
265     if( poJP2Dataset )
266     {
267         int nXOff      = nBlockXOff * poGeoRaster->nColumnBlockSize;
268         int nYOff      = nBlockYOff * poGeoRaster->nRowBlockSize;
269         int nXSize     = poGeoRaster->nColumnBlockSize;
270         int nYSize     = poGeoRaster->nRowBlockSize;
271         int nBufXSize  = nBlockXSize;
272         int nBufYSize  = nBlockYSize;
273 
274         return GDALDatasetRasterIO( poJP2Dataset, GF_Write,
275                     nXOff, nYOff, nXSize, nYSize, pImage,
276                     nBufXSize, nBufYSize, eDataType,
277                     1, &nBand, 0, 0, 0 );
278     }
279 
280     if( poGeoRaster->SetDataBlock( nBand,
281                                    nOverviewLevel,
282                                    nBlockXOff,
283                                    nBlockYOff,
284                                    pImage ) )
285     {
286         return CE_None;
287     }
288     else
289     {
290         CPLError( CE_Failure, CPLE_AppDefined,
291                   "Error writing GeoRaster offset X (%d) offset Y (%d) "
292                   "band (%d)",
293                   nBlockXOff, nBlockYOff, nBand );
294         return CE_Failure;
295     }
296 }
297 //  ---------------------------------------------------------------------------
298 //                                                     GetColorInterpretation()
299 //  ---------------------------------------------------------------------------
300 
GetColorInterpretation()301 GDALColorInterp GeoRasterRasterBand::GetColorInterpretation()
302 {
303     GeoRasterDataset* poGDS = (GeoRasterDataset*) poDS;
304 
305     if( eDataType == GDT_Byte && poGDS->nBands > 2 )
306     {
307         if( nBand == poGeoRaster->iDefaultRedBand )
308         {
309             return GCI_RedBand;
310         }
311         else if ( nBand == poGeoRaster->iDefaultGreenBand )
312         {
313             return GCI_GreenBand;
314         }
315         else if ( nBand == poGeoRaster->iDefaultBlueBand )
316         {
317             return GCI_BlueBand;
318         }
319         else
320         {
321             if( nBand == 4 && poGDS->nBands == 4 &&
322                 poGeoRaster->iDefaultRedBand == 1 &&
323                 poGeoRaster->iDefaultGreenBand == 2 &&
324                 poGeoRaster->iDefaultBlueBand == 3 )
325             {
326                 return GCI_AlphaBand;
327             }
328             else
329             {
330                 return GCI_Undefined;
331             }
332         }
333     }
334 
335     if( poGeoRaster->HasColorMap( nBand ) )
336     {
337         return GCI_PaletteIndex;
338     }
339     else
340     {
341         return GCI_GrayIndex;
342     }
343 }
344 
345 //  ---------------------------------------------------------------------------
346 //                                                              GetColorTable()
347 //  ---------------------------------------------------------------------------
348 
GetColorTable()349 GDALColorTable *GeoRasterRasterBand::GetColorTable()
350 {
351     poGeoRaster->GetColorMap( nBand, poColorTable );
352 
353     if( poColorTable->GetColorEntryCount() == 0 )
354     {
355         return nullptr;
356     }
357 
358     return poColorTable;
359 }
360 
361 //  ---------------------------------------------------------------------------
362 //                                                              SetColorTable()
363 //  ---------------------------------------------------------------------------
364 
SetColorTable(GDALColorTable * poInColorTable)365 CPLErr GeoRasterRasterBand::SetColorTable( GDALColorTable *poInColorTable )
366 {
367     if( poInColorTable == nullptr )
368     {
369         return CE_None;
370     }
371 
372     if( poInColorTable->GetColorEntryCount() == 0 )
373     {
374         return CE_None;
375     }
376 
377     delete poColorTable;
378 
379     poColorTable = poInColorTable->Clone();
380 
381     poGeoRaster->SetColorMap( nBand, poColorTable );
382 
383     return CE_None;
384 }
385 
386 //  ---------------------------------------------------------------------------
387 //                                                                 GetMinimum()
388 //  ---------------------------------------------------------------------------
389 
GetMinimum(int * pbSuccess)390 double GeoRasterRasterBand::GetMinimum( int *pbSuccess )
391 {
392     *pbSuccess = (int) bValidStats;
393 
394     return dfMin;
395 }
396 
397 //  ---------------------------------------------------------------------------
398 //                                                                 GetMaximum()
399 //  ---------------------------------------------------------------------------
400 
GetMaximum(int * pbSuccess)401 double GeoRasterRasterBand::GetMaximum( int *pbSuccess )
402 {
403     *pbSuccess = (int) bValidStats;
404 
405     return dfMax;
406 }
407 
408 //  ---------------------------------------------------------------------------
409 //                                                              GetStatistics()
410 //  ---------------------------------------------------------------------------
411 
GetStatistics(int bApproxOK,int bForce,double * pdfMin,double * pdfMax,double * pdfMean,double * pdfStdDev)412 CPLErr GeoRasterRasterBand::GetStatistics( int bApproxOK, int bForce,
413                                            double *pdfMin, double *pdfMax,
414                                            double *pdfMean, double *pdfStdDev )
415 {
416     (void) bForce;
417     (void) bApproxOK;
418 
419     char szMin[MAX_DOUBLE_STR_REP + 1];
420     char szMax[MAX_DOUBLE_STR_REP + 1];
421     char szMean[MAX_DOUBLE_STR_REP + 1];
422     char szMedian[MAX_DOUBLE_STR_REP + 1];
423     char szMode[MAX_DOUBLE_STR_REP + 1];
424     char szStdDev[MAX_DOUBLE_STR_REP + 1];
425     char szSampling[MAX_DOUBLE_STR_REP + 1];
426 
427     if( ! bValidStats )
428     {
429         bValidStats = poGeoRaster->GetStatistics( nBand,
430                                                   szMin,  szMax,
431                                                   szMean, szMedian,
432                                                   szMode, szStdDev,
433                                                   szSampling );
434     }
435 
436     if( bValidStats )
437     {
438         dfMin        = CPLScanDouble( szMin,    MAX_DOUBLE_STR_REP );
439         dfMax        = CPLScanDouble( szMax,    MAX_DOUBLE_STR_REP );
440         dfMean       = CPLScanDouble( szMean,   MAX_DOUBLE_STR_REP );
441         dfMedian     = CPLScanDouble( szMedian, MAX_DOUBLE_STR_REP );
442         dfMode       = CPLScanDouble( szMode,   MAX_DOUBLE_STR_REP );
443         dfStdDev     = CPLScanDouble( szStdDev, MAX_DOUBLE_STR_REP );
444 
445         SetMetadataItem( "STATISTICS_MINIMUM",     szMin );
446         SetMetadataItem( "STATISTICS_MAXIMUM",     szMax );
447         SetMetadataItem( "STATISTICS_MEAN",        szMean );
448         SetMetadataItem( "STATISTICS_MEDIAN",      szMedian );
449         SetMetadataItem( "STATISTICS_MODE",        szMode );
450         SetMetadataItem( "STATISTICS_STDDEV",      szStdDev );
451         SetMetadataItem( "STATISTICS_SKIPFACTORX", szSampling );
452         SetMetadataItem( "STATISTICS_SKIPFACTORY", szSampling );
453 
454         *pdfMin     = dfMin;
455         *pdfMax     = dfMax;
456         *pdfMean    = dfMean;
457         *pdfStdDev  = dfStdDev;
458 
459         return CE_None;
460     }
461 
462     return CE_Failure;
463 }
464 
465 //  ---------------------------------------------------------------------------
466 //                                                              SetStatistics()
467 //  ---------------------------------------------------------------------------
468 
SetStatistics(double dfMinIn,double dfMaxIn,double dfMeanIn,double dfStdDevIn)469 CPLErr GeoRasterRasterBand::SetStatistics( double dfMinIn, double dfMaxIn,
470                                            double dfMeanIn, double dfStdDevIn )
471 {
472     this->dfMin       = dfMinIn;
473     this->dfMax       = dfMaxIn;
474     this->dfMean      = dfMeanIn;
475     this->dfStdDev    = dfStdDevIn;
476 
477     return CE_None;
478 }
479 
480 //  ---------------------------------------------------------------------------
481 //                                                             GetNoDataValue()
482 //  ---------------------------------------------------------------------------
483 
GetNoDataValue(int * pbSuccess)484 double GeoRasterRasterBand::GetNoDataValue( int *pbSuccess )
485 {
486     if( pbSuccess )
487     {
488         if( nNoDataArraySz )
489         {
490             *pbSuccess = true;
491         }
492         else
493         {
494             *pbSuccess = (int) poGeoRaster->GetNoData( nBand, &dfNoData );
495         }
496     }
497 
498     return dfNoData;
499 }
500 
501 //  ---------------------------------------------------------------------------
502 //                                                             SetNoDataValue()
503 //  ---------------------------------------------------------------------------
504 
SetNoDataValue(double dfNoDataValue)505 CPLErr GeoRasterRasterBand::SetNoDataValue( double dfNoDataValue )
506 {
507     const char* pszFormat =
508         (eDataType == GDT_Float32 || eDataType == GDT_Float64) ? "%f" : "%.0f";
509 
510     poGeoRaster->SetNoData( (poDS->GetRasterCount() == 1) ? 0 : nBand,
511         CPLSPrintf( pszFormat, dfNoDataValue ) );
512 
513     return CE_None;
514 }
515 
516 //  ---------------------------------------------------------------------------
517 //                                                              SetDefaultRAT()
518 //  ---------------------------------------------------------------------------
519 
SetDefaultRAT(const GDALRasterAttributeTable * poRAT)520 CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
521 {
522     GeoRasterDataset* poGDS = (GeoRasterDataset*) poDS;
523 
524     if( ! poRAT )
525     {
526         return CE_Failure;
527     }
528 
529     if( poDefaultRAT )
530     {
531         delete poDefaultRAT;
532     }
533 
534     poDefaultRAT = poRAT->Clone();
535 
536     // ----------------------------------------------------------
537     // Check if RAT is just colortable and/or histogram
538     // ----------------------------------------------------------
539 
540     int  nColCount = poRAT->GetColumnCount();
541 
542     for( int iCol = 0; iCol < poRAT->GetColumnCount(); iCol++ )
543     {
544         const CPLString sColName = poRAT->GetNameOfCol( iCol );
545 
546         if( EQUAL( sColName, "histogram" ) ||
547             EQUAL( sColName, "red" ) ||
548             EQUAL( sColName, "green" ) ||
549             EQUAL( sColName, "blue" ) ||
550             EQUAL( sColName, "opacity" ) )
551         {
552             nColCount--;
553         }
554     }
555 
556     if( nColCount < 2 )
557     {
558         delete poDefaultRAT;
559 
560         poDefaultRAT = nullptr;
561 
562         return CE_None;
563     }
564 
565     // ----------------------------------------------------------
566     // Format Table description
567     // ----------------------------------------------------------
568 
569     CPLString osDescription = "( ID NUMBER";
570 
571     for( int iCol = 0; iCol < poRAT->GetColumnCount(); iCol++ )
572     {
573         osDescription += ", ";
574         osDescription += poRAT->GetNameOfCol( iCol );
575 
576         if( poRAT->GetTypeOfCol( iCol ) == GFT_Integer )
577         {
578             osDescription += " NUMBER";
579         }
580         if( poRAT->GetTypeOfCol( iCol ) == GFT_Real )
581         {
582             osDescription += " NUMBER";
583         }
584         if( poRAT->GetTypeOfCol( iCol ) == GFT_String )
585         {
586             osDescription += CPLSPrintf(" VARCHAR2(%d)", MAXLEN_VATSTR);
587         }
588     }
589     osDescription += " )";
590 
591     // ----------------------------------------------------------
592     // Create VAT named based on RDT and RID and Layer (nBand)
593     // ----------------------------------------------------------
594 
595     if ( poGeoRaster->sValueAttributeTab.length() > 0 )
596     {
597         pszVATName = CPLStrdup( poGeoRaster->sValueAttributeTab.c_str() );
598     }
599 
600     if( ! pszVATName )
601     {
602         pszVATName = CPLStrdup( CPLSPrintf(
603             "RAT_%s_%lld_%d",
604             poGeoRaster->sDataTable.c_str(),
605             poGeoRaster->nRasterId,
606             nBand ) );
607     }
608 
609     // ----------------------------------------------------------
610     // Create VAT table
611     // ----------------------------------------------------------
612 
613     OWStatement* poStmt = poGeoRaster->poConnection->CreateStatement( CPLSPrintf(
614         "DECLARE\n"
615         "  TAB VARCHAR2(68)  := UPPER(:1);\n"
616         "  CNT NUMBER        := 0;\n"
617         "BEGIN\n"
618         "  EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM USER_TABLES\n"
619         "    WHERE TABLE_NAME = :1' INTO CNT USING TAB;\n"
620         "\n"
621         "  IF NOT CNT = 0 THEN\n"
622         "    EXECUTE IMMEDIATE 'DROP TABLE '||TAB||' PURGE';\n"
623         "  END IF;\n"
624         "\n"
625         "  EXECUTE IMMEDIATE 'CREATE TABLE '||TAB||' %s';\n"
626         "END;", osDescription.c_str() ) );
627 
628     poStmt->Bind( pszVATName );
629 
630     if( ! poStmt->Execute() )
631     {
632         delete poStmt;
633         CPLError( CE_Failure, CPLE_AppDefined, "Create VAT Table Error!" );
634         return CE_Failure;
635     }
636 
637     delete poStmt;
638 
639     // ----------------------------------------------------------
640     // Insert Data to VAT
641     // ----------------------------------------------------------
642 
643     int iEntry       = 0;
644     int nEntryCount  = poRAT->GetRowCount();
645     int nColunsCount = poRAT->GetColumnCount();
646     int nVATStrSize  = MAXLEN_VATSTR * poGeoRaster->poConnection->GetCharSize();
647 
648     // ---------------------------
649     // Allocate array of buffers
650     // ---------------------------
651 
652     void** papWriteFields = (void**) VSIMalloc2(sizeof(void*), nColunsCount + 1);
653 
654     papWriteFields[0] =
655         (void*) VSIMalloc3(sizeof(int), sizeof(int), nEntryCount ); // ID field
656 
657     for(int iCol = 0; iCol < nColunsCount; iCol++)
658     {
659         if( poRAT->GetTypeOfCol( iCol ) == GFT_String )
660         {
661             papWriteFields[iCol + 1] =
662                 (void*) VSIMalloc3(sizeof(char), nVATStrSize, nEntryCount );
663         }
664         if( poRAT->GetTypeOfCol( iCol ) == GFT_Integer )
665         {
666             papWriteFields[iCol + 1] =
667                 (void*) VSIMalloc3(sizeof(int), sizeof(int), nEntryCount );
668         }
669         if( poRAT->GetTypeOfCol( iCol ) == GFT_Real )
670         {
671             papWriteFields[iCol + 1] =
672                  (void*) VSIMalloc3(sizeof(double), sizeof(double), nEntryCount );
673         }
674     }
675 
676     // ---------------------------
677     // Load data to buffers
678     // ---------------------------
679 
680     for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
681     {
682         ((int *)(papWriteFields[0]))[iEntry] = iEntry; // ID field
683 
684         for(int iCol = 0; iCol < nColunsCount; iCol++)
685         {
686             if( poRAT->GetTypeOfCol( iCol ) == GFT_String )
687             {
688 
689                 int nOffset = iEntry * nVATStrSize;
690                 char* pszTarget = ((char*)papWriteFields[iCol + 1]) + nOffset;
691                 const char *pszStrValue = poRAT->GetValueAsString(iEntry, iCol);
692                 int nLen = static_cast<int>(strlen( pszStrValue ));
693                 nLen = nLen > ( nVATStrSize - 1 ) ? nVATStrSize : ( nVATStrSize - 1 );
694                 strncpy( pszTarget, pszStrValue, nLen );
695                 pszTarget[nLen] = '\0';
696             }
697             if( poRAT->GetTypeOfCol( iCol ) == GFT_Integer )
698             {
699                 ((int *)(papWriteFields[iCol + 1]))[iEntry] =
700                     poRAT->GetValueAsInt(iEntry, iCol);
701             }
702             if( poRAT->GetTypeOfCol( iCol ) == GFT_Real )
703             {
704                 ((double *)(papWriteFields[iCol + 1]))[iEntry] =
705                     poRAT->GetValueAsDouble(iEntry, iCol);
706             }
707         }
708     }
709 
710     // ---------------------------
711     // Prepare insert statement
712     // ---------------------------
713 
714     CPLString osInsert = CPLSPrintf( "INSERT INTO %s VALUES (", pszVATName );
715 
716     for( int iCol = 0; iCol < ( nColunsCount + 1); iCol++ )
717     {
718         if( iCol > 0 )
719         {
720             osInsert.append(", ");
721         }
722         osInsert.append( CPLSPrintf(":%d", iCol + 1) );
723     }
724     osInsert.append(")");
725 
726     poStmt = poGeoRaster->poConnection->CreateStatement( osInsert.c_str() );
727 
728     // ---------------------------
729     // Bind buffers to columns
730     // ---------------------------
731 
732     poStmt->Bind((int*) papWriteFields[0]); // ID field
733 
734     for(int iCol = 0; iCol < nColunsCount; iCol++)
735     {
736         if( poRAT->GetTypeOfCol( iCol ) == GFT_String )
737         {
738             poStmt->Bind( (char*) papWriteFields[iCol + 1], nVATStrSize );
739         }
740         if( poRAT->GetTypeOfCol( iCol ) == GFT_Integer )
741         {
742             poStmt->Bind( (int*) papWriteFields[iCol + 1]);
743         }
744         if( poRAT->GetTypeOfCol( iCol ) == GFT_Real )
745         {
746             poStmt->Bind( (double*) papWriteFields[iCol + 1]);
747         }
748     }
749 
750     if( poStmt->Execute( iEntry ) )
751     {
752         poGDS->poGeoRaster->SetVAT( nBand, pszVATName );
753     }
754     else
755     {
756         CPLError( CE_Failure, CPLE_AppDefined, "Insert VAT Error!" );
757     }
758 
759     // ---------------------------
760     // Clean up
761     // ---------------------------
762 
763     for(int iCol = 0; iCol < ( nColunsCount + 1); iCol++)
764     {
765         CPLFree( papWriteFields[iCol] );
766     }
767 
768     CPLFree( papWriteFields );
769 
770     delete poStmt;
771 
772     return CE_None;
773 }
774 
775 //  ---------------------------------------------------------------------------
776 //                                                              GetDefaultRAT()
777 //  ---------------------------------------------------------------------------
778 
GetDefaultRAT()779 GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
780 {
781     if( poDefaultRAT )
782     {
783         return poDefaultRAT;
784     }
785     else
786     {
787         poDefaultRAT = new GDALDefaultRasterAttributeTable();
788     }
789 
790     GeoRasterDataset* poGDS = (GeoRasterDataset*) poDS;
791 
792     // ----------------------------------------------------------
793     // Get the name of the VAT Table
794     // ----------------------------------------------------------
795 
796     char* l_pszVATName = poGDS->poGeoRaster->GetVAT( nBand );
797 
798     if( l_pszVATName == nullptr )
799     {
800         return nullptr;
801     }
802 
803     OCIParam* phDesc = poGDS->poGeoRaster->poConnection->GetDescription( l_pszVATName );
804 
805     if( phDesc == nullptr )
806     {
807         return nullptr;
808     }
809 
810     // ----------------------------------------------------------
811     // Create the RAT and the SELECT statement based on fields description.
812     // ----------------------------------------------------------
813 
814     int   iCol = 0;
815     char  szField[OWNAME];
816     int   hType = 0;
817     int   nSize = 0;
818     int   nPrecision = 0;
819     signed short nScale = 0;
820 
821     CPLString osColumnList;
822 
823     while( poGDS->poGeoRaster->poConnection->GetNextField(
824                 phDesc, iCol, szField, &hType, &nSize, &nPrecision, &nScale ) )
825     {
826         switch( hType )
827         {
828             case SQLT_FLT:
829                 poDefaultRAT->CreateColumn( szField, GFT_Real, GFU_Generic );
830                 break;
831             case SQLT_NUM:
832                 if( nPrecision == 0 )
833                 {
834                     poDefaultRAT->CreateColumn( szField, GFT_Integer,
835                         GFU_Generic );
836                 }
837                 else
838                 {
839                     poDefaultRAT->CreateColumn( szField, GFT_Real,
840                         GFU_Generic );
841                 }
842                 break;
843             case SQLT_CHR:
844             case SQLT_AFC:
845             case SQLT_DAT:
846             case SQLT_DATE:
847             case SQLT_TIMESTAMP:
848             case SQLT_TIMESTAMP_TZ:
849             case SQLT_TIMESTAMP_LTZ:
850             case SQLT_TIME:
851             case SQLT_TIME_TZ:
852                     poDefaultRAT->CreateColumn( szField, GFT_String,
853                         GFU_Generic );
854                 break;
855             default:
856                 CPLDebug("GEORASTER", "VAT (%s) Column (%s) type (%d) not supported"
857                     "as GDAL RAT", l_pszVATName, szField, hType );
858                 continue;
859         }
860         osColumnList += CPLSPrintf(
861                   "substr(%s,1,%d),",
862                   szField, MIN(nSize,OWNAME));
863 
864         iCol++;
865     }
866 
867     if( !osColumnList.empty() )
868         osColumnList.resize(osColumnList.size()-1); // remove the last comma
869 
870     // ----------------------------------------------------------
871     // Read VAT and load RAT
872     // ----------------------------------------------------------
873 
874     OWStatement* poStmt = poGeoRaster->poConnection->CreateStatement( CPLSPrintf (
875         "SELECT %s FROM %s", osColumnList.c_str(), l_pszVATName ) );
876 
877     char** papszValue = (char**) CPLCalloc( sizeof(char*), iCol + 1 );
878 
879     int i = 0;
880 
881     for( i = 0; i < iCol; i++ )
882     {
883         papszValue[i] = (char*) CPLCalloc( 1, OWNAME + 1 );
884         poStmt->Define( papszValue[i] );
885     }
886 
887     if( ! poStmt->Execute() )
888     {
889         CPLError( CE_Failure, CPLE_AppDefined, "Error reading VAT %s",
890             l_pszVATName );
891         CSLDestroy(papszValue);
892         delete poStmt;
893         return nullptr;
894     }
895 
896     int iRow = 0;
897 
898     while( poStmt->Fetch() )
899     {
900         for( i = 0; i < iCol; i++ )
901         {
902            poDefaultRAT->SetValue( iRow, i, papszValue[i] );
903         }
904         iRow++;
905     }
906 
907     CSLDestroy(papszValue);
908 
909     delete poStmt;
910 
911     CPLFree( l_pszVATName );
912 
913     return poDefaultRAT;
914 }
915 
916 //  ---------------------------------------------------------------------------
917 //                                                           GetOverviewCount()
918 //  ---------------------------------------------------------------------------
919 
GetOverviewCount()920 int GeoRasterRasterBand::GetOverviewCount()
921 {
922     return nOverviewCount;
923 }
924 
925 //  ---------------------------------------------------------------------------
926 //                                                           GetOverviewCount()
927 //  ---------------------------------------------------------------------------
928 
GetOverview(int nLevel)929 GDALRasterBand* GeoRasterRasterBand::GetOverview( int nLevel )
930 {
931     if( nLevel < nOverviewCount && papoOverviews[ nLevel ] )
932     {
933         return (GDALRasterBand*) papoOverviews[ nLevel ];
934     }
935     return (GDALRasterBand*) nullptr;
936 }
937 
938 //  ---------------------------------------------------------------------------
939 //                                                             CreateMaskBand()
940 //  ---------------------------------------------------------------------------
941 
CreateMaskBand(int)942 CPLErr GeoRasterRasterBand::CreateMaskBand( int /*nFlags*/ )
943 {
944     if( ! poGeoRaster->bHasBitmapMask )
945     {
946         return CE_Failure;
947     }
948 
949     return CE_None;
950 }
951 
952 //  ---------------------------------------------------------------------------
953 //                                                                GetMaskBand()
954 //  ---------------------------------------------------------------------------
955 
GetMaskBand()956 GDALRasterBand* GeoRasterRasterBand::GetMaskBand()
957 {
958     GeoRasterDataset* poGDS = (GeoRasterDataset*) this->poDS;
959 
960     if( poGDS->poMaskBand != nullptr )
961     {
962         return (GDALRasterBand*) poGDS->poMaskBand;
963     }
964 
965     return (GDALRasterBand*) nullptr;
966 }
967 
968 //  ---------------------------------------------------------------------------
969 //                                                               GetMaskFlags()
970 //  ---------------------------------------------------------------------------
971 
GetMaskFlags()972 int GeoRasterRasterBand::GetMaskFlags()
973 {
974     GeoRasterDataset* poGDS = (GeoRasterDataset*) this->poDS;
975 
976     if( poGDS->poMaskBand != nullptr )
977     {
978         return GMF_PER_DATASET;
979     }
980 
981     return GMF_ALL_VALID;
982 }
983 
984 //  ---------------------------------------------------------------------------
985 //                                                            ApplyNoDataArray()
986 //  ---------------------------------------------------------------------------
987 
ApplyNoDataArray(void * pBuffer) const988 void GeoRasterRasterBand::ApplyNoDataArray(void* pBuffer) const
989 {
990     int i = 0;
991     int j = 0;
992     long n = nBlockXSize * nBlockYSize;
993 
994     switch( eDataType )
995     {
996         case GDT_Byte:
997         {
998             GByte* pbBuffer = (GByte*) pBuffer;
999 
1000             for( i = 0; i < n; i++ )
1001             {
1002                 for( j = 0; j < nNoDataArraySz; j++ )
1003                 {
1004                     if( pbBuffer[i] == (GByte) pahNoDataArray[j].dfLower ||
1005                       ( pbBuffer[i] >  (GByte) pahNoDataArray[j].dfLower &&
1006                         pbBuffer[i] <  (GByte) pahNoDataArray[j].dfUpper ) )
1007                     {
1008                         pbBuffer[i] = (GByte) dfNoData;
1009                     }
1010                 }
1011             }
1012 
1013             break;
1014         }
1015         case GDT_Float32:
1016         case GDT_CFloat32:
1017         {
1018             float* pfBuffer = (float*) pBuffer;
1019 
1020             for( i = 0; i < n; i++ )
1021             {
1022                 for( j = 0; j < nNoDataArraySz; j++ )
1023                 {
1024                     if( pfBuffer[i] == (float) pahNoDataArray[j].dfLower ||
1025                       ( pfBuffer[i] >  (float) pahNoDataArray[j].dfLower &&
1026                         pfBuffer[i] <  (float) pahNoDataArray[j].dfUpper ) )
1027                     {
1028                         pfBuffer[i] = (float) dfNoData;
1029                     }
1030                 }
1031             }
1032 
1033             break;
1034         }
1035         case GDT_Float64:
1036         case GDT_CFloat64:
1037         {
1038             double* pdfBuffer = (double*) pBuffer;
1039 
1040             for( i = 0; i < n; i++ )
1041             {
1042                 for( j = 0; j < nNoDataArraySz; j++ )
1043                 {
1044                     if( pdfBuffer[i] == (double) pahNoDataArray[j].dfLower ||
1045                       ( pdfBuffer[i] >  (double) pahNoDataArray[j].dfLower &&
1046                         pdfBuffer[i] <  (double) pahNoDataArray[j].dfUpper ) )
1047                     {
1048                         pdfBuffer[i] = (double) dfNoData;
1049                     }
1050                 }
1051             }
1052 
1053             break;
1054         }
1055         case GDT_Int16:
1056         case GDT_CInt16:
1057         {
1058             GInt16* pnBuffer = (GInt16*) pBuffer;
1059 
1060             for( i = 0; i < n; i++ )
1061             {
1062                 for( j = 0; j < nNoDataArraySz; j++ )
1063                 {
1064                     if( pnBuffer[i] == (GInt16) pahNoDataArray[j].dfLower ||
1065                       ( pnBuffer[i] >  (GInt16) pahNoDataArray[j].dfLower &&
1066                         pnBuffer[i] <  (GInt16) pahNoDataArray[j].dfUpper ) )
1067                     {
1068                         pnBuffer[i] = (GInt16) dfNoData;
1069                     }
1070                 }
1071             }
1072 
1073             break;
1074         }
1075         case GDT_Int32:
1076         case GDT_CInt32:
1077         {
1078             GInt32* pnBuffer = (GInt32*) pBuffer;
1079 
1080             for( i = 0; i < n; i++ )
1081             {
1082                 for( j = 0; j < nNoDataArraySz; j++ )
1083                 {
1084                     if( pnBuffer[i] == (GInt32) pahNoDataArray[j].dfLower ||
1085                       ( pnBuffer[i] >  (GInt32) pahNoDataArray[j].dfLower &&
1086                         pnBuffer[i] <  (GInt32) pahNoDataArray[j].dfUpper ) )
1087                     {
1088                         pnBuffer[i] = (GInt32) dfNoData;
1089                     }
1090                 }
1091             }
1092 
1093             break;
1094         }
1095         case GDT_UInt16:
1096         {
1097             GUInt16* pnBuffer = (GUInt16*) pBuffer;
1098 
1099             for( i = 0; i < n; i++ )
1100             {
1101                 for( j = 0; j < nNoDataArraySz; j++ )
1102                 {
1103                     if( pnBuffer[i] == (GUInt16) pahNoDataArray[j].dfLower ||
1104                       ( pnBuffer[i] >  (GUInt16) pahNoDataArray[j].dfLower &&
1105                         pnBuffer[i] <  (GUInt16) pahNoDataArray[j].dfUpper ) )
1106                     {
1107                         pnBuffer[i] = (GUInt16) dfNoData;
1108                     }
1109                 }
1110             }
1111 
1112             break;
1113         }
1114         case GDT_UInt32:
1115         {
1116             GUInt32* pnBuffer = (GUInt32*) pBuffer;
1117 
1118             for( i = 0; i < n; i++ )
1119             {
1120                 for( j = 0; j < nNoDataArraySz; j++ )
1121                 {
1122                     if( pnBuffer[i] == (GUInt32) pahNoDataArray[j].dfLower ||
1123                       ( pnBuffer[i] >  (GUInt32) pahNoDataArray[j].dfLower &&
1124                         pnBuffer[i] <  (GUInt32) pahNoDataArray[j].dfUpper ) )
1125                     {
1126                         pnBuffer[i] = (GUInt32) dfNoData;
1127                     }
1128                 }
1129             }
1130 
1131             break;
1132         }
1133         default:
1134             ;
1135     }
1136 }
1137