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