1 /******************************************************************************
2 *
3 * Name: georaster_wrapper.cpp
4 * Project: Oracle Spatial GeoRaster Driver
5 * Purpose: Implement GeoRasterWrapper 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 <string.h>
31
32 #include "georaster_priv.h"
33 #include "cpl_error.h"
34 #include "cpl_string.h"
35 #include "cpl_minixml.h"
36
37 CPL_CVSID("$Id: georaster_wrapper.cpp 453a032f70e60f749c4d05678374363748a59d2c 2021-07-14 06:36:36 -0400 fechen123 $")
38
39 // ---------------------------------------------------------------------------
40 // GeoRasterWrapper()
41 // ---------------------------------------------------------------------------
42
GeoRasterWrapper()43 GeoRasterWrapper::GeoRasterWrapper() :
44 sPyramidResampling ( "NN" ),
45 sCompressionType ( "NONE" ),
46 sInterleaving ( "BSQ" )
47 {
48 nRasterId = -1;
49 phMetadata = nullptr;
50 nRasterRows = 0;
51 nRasterColumns = 0;
52 nRasterBands = 0;
53 nRowBlockSize = 0;
54 nColumnBlockSize = 0;
55 nBandBlockSize = 0;
56 nTotalColumnBlocks = 0;
57 nTotalRowBlocks = 0;
58 nTotalBandBlocks = 0;
59 nCellSizeBits = 0;
60 nGDALCellBytes = 0;
61 dfXCoefficient[0] = 1.0;
62 dfXCoefficient[1] = 0.0;
63 dfXCoefficient[2] = 0.0;
64 dfYCoefficient[0] = 0.0;
65 dfYCoefficient[1] = 1.0;
66 dfYCoefficient[2] = 0.0;
67 nCompressQuality = 75;
68 bGenPyramid = false;
69 nPyramidLevels = 0;
70 pahLocator = nullptr;
71 pabyBlockBuf = nullptr;
72 pabyCompressBuf = nullptr;
73 bIsReferenced = false;
74 poBlockStmt = nullptr;
75 nCacheBlockId = -1;
76 nCurrentLevel = -1;
77 pahLevels = nullptr;
78 nLevelOffset = 0L;
79 bUpdate = false;
80 bInitializeIO = false;
81 bFlushMetadata = false;
82 nSRID = DEFAULT_CRS;;
83 nExtentSRID = 0;
84 bGenSpatialExtent = false;
85 bCreateObjectTable = false;
86 nPyramidMaxLevel = 0;
87 nBlockCount = 0L;
88 nGDALBlockBytes = 0L;
89 sDInfo.global_state = 0;
90 sCInfo.global_state = 0;
91 bHasBitmapMask = false;
92 nBlockBytes = 0L;
93 bFlushBlock = false;
94 nFlushBlockSize = 0L;
95 bUniqueFound = false;
96 psNoDataList = nullptr;
97 bWriteOnly = false;
98 bBlocking = true;
99 bAutoBlocking = false;
100 eModelCoordLocation = MCL_DEFAULT;
101 phRPC = nullptr;
102 poConnection = nullptr;
103 iDefaultRedBand = 0;
104 iDefaultGreenBand = 0;
105 iDefaultBlueBand = 0;
106 anULTCoordinate[0] = 0;
107 anULTCoordinate[1] = 0;
108 anULTCoordinate[2] = 0;
109 pasGCPList = nullptr;
110 nGCPCount = 0;
111 bFlushGCP = false;
112 memset(&sCInfo, 0, sizeof(sCInfo));
113 memset(&sDInfo, 0, sizeof(sDInfo));
114 memset(&sJErr, 0, sizeof(sJErr));
115 }
116
117 // ---------------------------------------------------------------------------
118 // GeoRasterDataset()
119 // ---------------------------------------------------------------------------
120
~GeoRasterWrapper()121 GeoRasterWrapper::~GeoRasterWrapper()
122 {
123 FlushMetadata();
124
125 if( pahLocator && nBlockCount )
126 {
127 OWStatement::Free( pahLocator, static_cast<int>(nBlockCount) );
128 }
129
130 CPLFree( pahLocator );
131 CPLFree( pabyBlockBuf );
132 CPLFree( pabyCompressBuf );
133 CPLFree( pahLevels );
134
135 if( bFlushGCP )
136 {
137 FlushGCP();
138 GDALDeinitGCPs( nGCPCount, pasGCPList );
139 CPLFree( pasGCPList );
140 pasGCPList = nullptr;
141 nGCPCount = 0;
142 }
143
144 if( CPLListCount( psNoDataList ) )
145 {
146 CPLList* psList = nullptr;
147
148 for( psList = psNoDataList; psList ; psList = psList->psNext )
149 {
150 CPLFree( psList->pData );
151 }
152
153 CPLListDestroy( psNoDataList );
154 }
155
156 if( poBlockStmt )
157 {
158 delete poBlockStmt;
159 }
160
161 CPLDestroyXMLNode( phMetadata );
162
163 if( sDInfo.global_state )
164 {
165 jpeg_destroy_decompress( &sDInfo );
166 }
167
168 if( sCInfo.global_state )
169 {
170 jpeg_destroy_compress( &sCInfo );
171 }
172
173 if( poConnection )
174 {
175 delete poConnection;
176 }
177
178 if( phRPC )
179 {
180 CPLFree( phRPC );
181 }
182 }
183
184 // ---------------------------------------------------------------------------
185 // ParseIdentificator()
186 // ---------------------------------------------------------------------------
187 //
188 // StringID:
189 // {georaster,geor}:<name>{/,,}<password>{/,@}<db>,<tab>,<col>,<where>
190 // {georaster,geor}:<name>{/,,}<password>{/,@}<db>,<rdt>,<rid>
191 //
192 // ---------------------------------------------------------------------------
193
ParseIdentificator(const char * pszStringID)194 char** GeoRasterWrapper::ParseIdentificator( const char* pszStringID )
195 {
196
197 char* pszStartPos = (char*) strstr( pszStringID, ":" ) + 1;
198
199 char** papszParam = CSLTokenizeString2( pszStartPos, ",@",
200 CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS |
201 CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
202
203 // -------------------------------------------------------------------
204 // The "/" should not be catch on the previous parser
205 // -------------------------------------------------------------------
206
207 if( CSLCount( papszParam ) > 0 )
208 {
209 char** papszFirst2 = CSLTokenizeString2( papszParam[0], "/",
210 CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
211 if( CSLCount( papszFirst2 ) == 2 )
212 {
213 papszParam = CSLInsertStrings( papszParam, 0, papszFirst2 );
214 papszParam = CSLRemoveStrings( papszParam, 2, 1, nullptr );
215 }
216 CSLDestroy( papszFirst2 );
217 }
218
219 return papszParam;
220 }
221
222 // ---------------------------------------------------------------------------
223 // Open()
224 // ---------------------------------------------------------------------------
225
Open(const char * pszStringId,bool bUpdate)226 GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate )
227 {
228 char** papszParam = ParseIdentificator( pszStringId );
229
230 // ---------------------------------------------------------------
231 // Validate identificator
232 // ---------------------------------------------------------------
233
234 int nArgc = CSLCount( papszParam );
235
236 for( ; nArgc < 3; nArgc++ )
237 {
238 papszParam = CSLAddString( papszParam, "" );
239 }
240
241 // ---------------------------------------------------------------
242 // Create a GeoRasterWrapper object
243 // ---------------------------------------------------------------
244
245 GeoRasterWrapper* poGRW = new GeoRasterWrapper();
246
247 if( ! poGRW )
248 {
249 CSLDestroy(papszParam);
250 return nullptr;
251 }
252
253 poGRW->bUpdate = bUpdate;
254
255 // ---------------------------------------------------------------
256 // Get a connection with Oracle server
257 // ---------------------------------------------------------------
258
259 if( strlen( papszParam[0] ) == 0 &&
260 strlen( papszParam[1] ) == 0 &&
261 strlen( papszParam[2] ) == 0 )
262 {
263 /* In an external procedure environment, before opening any
264 * dataset, the caller must pass the with_context as an
265 * string metadata item OCI_CONTEXT_PTR to the driver. */
266
267 OCIExtProcContext* with_context = nullptr;
268
269 const char* pszContext = GDALGetMetadataItem(
270 GDALGetDriverByName("GEORASTER"),
271 "OCI_CONTEXT_PTR", nullptr );
272
273 if( pszContext )
274 {
275 sscanf( pszContext, "%p", &with_context );
276
277 poGRW->poConnection = new OWConnection( with_context );
278 }
279 }
280 else
281 {
282 poGRW->poConnection = new OWConnection( papszParam[0],
283 papszParam[1],
284 papszParam[2] );
285 }
286
287 if( ! poGRW->poConnection ||
288 ! poGRW->poConnection->Succeeded() )
289 {
290 CSLDestroy( papszParam );
291 delete poGRW;
292 return nullptr;
293 }
294
295 // -------------------------------------------------------------------
296 // Extract schema name
297 // -------------------------------------------------------------------
298
299 if( poGRW->poConnection->IsExtProc() )
300 {
301 poGRW->sOwner = poGRW->poConnection->GetExtProcUser();
302 poGRW->sSchema = poGRW->poConnection->GetExtProcSchema();
303 }
304 else
305 {
306 char** papszSchema = CSLTokenizeString2( papszParam[3], ".",
307 CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
308
309 if( CSLCount( papszSchema ) == 2 )
310 {
311 poGRW->sOwner = papszSchema[0];
312 poGRW->sSchema = CPLSPrintf( "%s.", poGRW->sOwner.c_str() );
313
314 papszParam = CSLRemoveStrings( papszParam, 3, 1, nullptr );
315
316 if( ! EQUAL( papszSchema[1], "" ) )
317 {
318 papszParam = CSLInsertString( papszParam, 3, papszSchema[1] );
319 }
320
321 nArgc = CSLCount( papszParam );
322 }
323 else
324 {
325 poGRW->sSchema = "";
326 poGRW->sOwner = poGRW->poConnection->GetUser();
327 }
328
329 CSLDestroy( papszSchema );
330 }
331
332 // -------------------------------------------------------------------
333 // Assign parameters from Identification string
334 // -------------------------------------------------------------------
335
336 switch( nArgc )
337 {
338 case 6 :
339 poGRW->sTable = papszParam[3];
340 poGRW->sColumn = papszParam[4];
341 poGRW->sWhere = papszParam[5];
342 break;
343 case 5 :
344 if( OWIsNumeric( papszParam[4] ) )
345 {
346 poGRW->sDataTable = papszParam[3];
347 poGRW->nRasterId = (long long) CPLAtoGIntBig( papszParam[4]);
348 break;
349 }
350 else
351 {
352 poGRW->sTable = papszParam[3];
353 poGRW->sColumn = papszParam[4];
354 CSLDestroy(papszParam);
355 return poGRW;
356 }
357 case 4 :
358 poGRW->sTable = papszParam[3];
359 CSLDestroy(papszParam);
360 return poGRW;
361 default :
362 CSLDestroy(papszParam);
363 return poGRW;
364 }
365
366 CSLDestroy( papszParam );
367
368 // -------------------------------------------------------------------
369 // Query all the basic information at once to reduce round trips
370 // -------------------------------------------------------------------
371
372 char szOwner[OWCODE];
373 char szTable[OWCODE];
374 char szColumn[OWTEXT];
375 char szDataTable[OWCODE];
376 char szWhere[OWTEXT];
377 long long nRasterId = -1;
378 OCILobLocator* phLocator = nullptr;
379
380 szOwner[0] = '\0';
381 szTable[0] = '\0';
382 szColumn[0] = '\0';
383 szDataTable[0] = '\0';
384 szWhere[0] = '\0';
385
386 if( ! poGRW->sOwner.empty() )
387 {
388 snprintf( szOwner, sizeof(szOwner), "%s", poGRW->sOwner.c_str() );
389 }
390
391 if( ! poGRW->sTable.empty() )
392 {
393 snprintf( szTable, sizeof(szTable), "%s", poGRW->sTable.c_str() );
394 }
395
396 if( ! poGRW->sColumn.empty() )
397 {
398 snprintf( szColumn, sizeof(szColumn), "%s", poGRW->sColumn.c_str() );
399 }
400
401 if( ! poGRW->sDataTable.empty() )
402 {
403 snprintf( szDataTable, sizeof(szDataTable), "%s", poGRW->sDataTable.c_str() );
404 }
405
406 nRasterId = poGRW->nRasterId;
407
408 if( ! poGRW->sWhere.empty() )
409 {
410 snprintf( szWhere, sizeof(szWhere), "%s", poGRW->sWhere.c_str() );
411 }
412
413 OWStatement* poStmt = poGRW->poConnection->CreateStatement(
414 "BEGIN\n"
415 "\n"
416 " IF :datatable IS NOT NULL AND :rasterid IS NOT NULL THEN\n"
417 "\n"
418 " EXECUTE IMMEDIATE\n"
419 " 'SELECT OWNER, TABLE_NAME, COLUMN_NAME\n"
420 " FROM ALL_SDO_GEOR_SYSDATA\n"
421 " WHERE RDT_TABLE_NAME = UPPER(:1)\n"
422 " AND RASTER_ID = :2'\n"
423 " INTO :owner, :table, :column\n"
424 " USING :datatable, :rasterid;\n"
425 "\n"
426 " EXECUTE IMMEDIATE\n"
427 " 'SELECT T.'||:column||'.METADATA.getClobVal()\n"
428 " FROM '||:owner||'.'||:table||' T\n"
429 " WHERE T.'||:column||'.RASTERDATATABLE = UPPER(:1)\n"
430 " AND T.'||:column||'.RASTERID = :2'\n"
431 " INTO :metadata\n"
432 " USING :datatable, :rasterid;\n"
433 " :counter := 1;\n"
434 "\n"
435 " ELSE\n"
436 "\n"
437 " EXECUTE IMMEDIATE\n"
438 " 'SELECT T.'||:column||'.RASTERDATATABLE,\n"
439 " T.'||:column||'.RASTERID,\n"
440 " T.'||:column||'.METADATA.getClobVal()\n"
441 " FROM '||:owner||'.'||:table||' T\n"
442 " WHERE '||:where\n"
443 " INTO :datatable, :rasterid, :metadata;\n"
444 " :counter := 1;\n"
445 "\n"
446 " END IF;\n"
447 "\n"
448 " EXCEPTION\n"
449 " WHEN no_data_found THEN :counter := 0;\n"
450 " WHEN too_many_rows THEN :counter := 2;\n"
451 "END;" );
452
453 int nCounter = 0;
454
455 poStmt->BindName( ":datatable", szDataTable );
456 poStmt->BindName( ":rasterid", &nRasterId );
457 poStmt->BindName( ":owner", szOwner );
458 poStmt->BindName( ":table", szTable );
459 poStmt->BindName( ":column", szColumn );
460 poStmt->BindName( ":where", szWhere );
461 poStmt->BindName( ":counter", &nCounter );
462 poStmt->BindName( ":metadata", &phLocator );
463
464 CPLErrorReset();
465
466 if( ! poStmt->Execute() )
467 {
468 delete poStmt;
469 delete poGRW;
470 return nullptr;
471 }
472
473 if( nCounter < 1 )
474 {
475 delete poStmt;
476 delete poGRW;
477 return nullptr;
478 }
479
480 poGRW->sSchema = CPLSPrintf( "%s.", szOwner );
481 poGRW->sOwner = szOwner;
482 poGRW->sTable = szTable;
483 poGRW->sColumn = szColumn;
484
485 if( nCounter == 1 )
486 {
487 poGRW->bUniqueFound = true;
488 }
489 else
490 {
491 poGRW->bUniqueFound = false;
492
493 delete poStmt;
494 return poGRW;
495 }
496
497 poGRW->sDataTable = szDataTable;
498 poGRW->nRasterId = nRasterId;
499 poGRW->sWhere = CPLSPrintf(
500 "T.%s.RASTERDATATABLE = UPPER('%s') AND T.%s.RASTERID = %lld",
501 poGRW->sColumn.c_str(),
502 poGRW->sDataTable.c_str(),
503 poGRW->sColumn.c_str(),
504 poGRW->nRasterId );
505
506 // -------------------------------------------------------------------
507 // Read Metadata XML in text
508 // -------------------------------------------------------------------
509
510 CPLPushErrorHandler( CPLQuietErrorHandler );
511
512 char* pszXML = poStmt->ReadCLob( phLocator );
513
514 CPLPopErrorHandler();
515
516 if( pszXML )
517 {
518 // -----------------------------------------------------------
519 // Get basic information from xml metadata
520 // -----------------------------------------------------------
521
522 poGRW->phMetadata = CPLParseXMLString( pszXML );
523 poGRW->GetRasterInfo();
524 poGRW->GetSpatialReference();
525 }
526 else
527 {
528 poGRW->sDataTable = "";
529 poGRW->nRasterId = 0;
530 }
531
532 // -------------------------------------------------------------------
533 // Clean up
534 // -------------------------------------------------------------------
535
536 poStmt->FreeLob(phLocator);
537 CPLFree( pszXML );
538 delete poStmt;
539
540 // -------------------------------------------------------------------
541 // Return a GeoRasterWrapper object
542 // -------------------------------------------------------------------
543
544 return poGRW;
545 }
546
547 // ---------------------------------------------------------------------------
548 // Create()
549 // ---------------------------------------------------------------------------
550
Create(char * pszDescription,char * pszInsert,bool bUpdateIn)551 bool GeoRasterWrapper::Create( char* pszDescription,
552 char* pszInsert,
553 bool bUpdateIn )
554 {
555 CPLString sValues;
556 CPLString sFormat;
557
558 if( sTable.empty() ||
559 sColumn.empty() )
560 {
561 return false;
562 }
563
564 // -------------------------------------------------------------------
565 // Parse RDT/RID from the current szValues
566 // -------------------------------------------------------------------
567
568 char szRDT[OWNAME];
569 char szRID[OWCODE];
570
571 if( ! sDataTable.empty() )
572 {
573 snprintf( szRDT, sizeof(szRDT), "'%s'", sDataTable.c_str() );
574 }
575 else
576 {
577 snprintf( szRDT, sizeof(szRDT), "%s",
578 OWParseSDO_GEOR_INIT( sValues.c_str(), 1 ).c_str() );
579 }
580
581 if ( nRasterId > 0 )
582 {
583 snprintf( szRID, sizeof(szRID), "%lld", nRasterId );
584 }
585 else
586 {
587 snprintf( szRID, sizeof(szRID), "%s",
588 OWParseSDO_GEOR_INIT( sValues.c_str(), 2 ).c_str() );
589
590 if ( EQUAL( szRID, "" ) )
591 {
592 strcpy( szRID, "NULL" );
593 }
594 }
595
596 // -------------------------------------------------------------------
597 // Description parameters
598 // -------------------------------------------------------------------
599
600 char szDescription[OWTEXT];
601
602 if( bUpdateIn == false )
603 {
604
605 if ( pszDescription )
606 {
607 snprintf( szDescription, sizeof(szDescription), "%s", pszDescription );
608 }
609 else
610 {
611 snprintf( szDescription, sizeof(szDescription),
612 "(%s MDSYS.SDO_GEORASTER)", sColumn.c_str() );
613 }
614
615 // ---------------------------------------------------------------
616 // Insert parameters
617 // ---------------------------------------------------------------
618
619 if( pszInsert )
620 {
621 sValues = pszInsert;
622
623 if( pszInsert[0] == '(' && sValues.ifind( "VALUES" ) == std::string::npos )
624 {
625 sValues = CPLSPrintf( "VALUES %s", pszInsert );
626 }
627 }
628 else
629 {
630 sValues = CPLSPrintf( "VALUES (SDO_GEOR.INIT(%s,%s))", szRDT, szRID );
631 }
632 }
633
634 // -----------------------------------------------------------
635 // Storage parameters
636 // -----------------------------------------------------------
637
638 nColumnBlockSize = nColumnBlockSize == 0 ? DEFAULT_BLOCK_COLUMNS : nColumnBlockSize;
639 nRowBlockSize = nRowBlockSize == 0 ? DEFAULT_BLOCK_ROWS : nRowBlockSize;
640 nBandBlockSize = nBandBlockSize == 0 ? 1 : nBandBlockSize;
641
642 // -----------------------------------------------------------
643 // Blocking storage parameters
644 // -----------------------------------------------------------
645
646 CPLString sBlocking;
647
648 if( bBlocking == true )
649 {
650 if( bAutoBlocking == true )
651 {
652 int nBlockXSize = nColumnBlockSize;
653 int nBlockYSize = nRowBlockSize;
654 int nBlockBSize = nBandBlockSize;
655
656 OWStatement* poStmt = poConnection->CreateStatement(
657 "DECLARE\n"
658 " dimensionSize sdo_number_array;\n"
659 " blockSize sdo_number_array;\n"
660 "BEGIN\n"
661 " dimensionSize := sdo_number_array(:1, :2, :3);\n"
662 " blockSize := sdo_number_array(:4, :5, :6);\n"
663 " sdo_geor_utl.calcOptimizedBlockSize(dimensionSize,blockSize);\n"
664 " :4 := blockSize(1);\n"
665 " :5 := blockSize(2);\n"
666 " :6 := blockSize(3);\n"
667 "END;" );
668
669 poStmt->Bind( &nRasterColumns );
670 poStmt->Bind( &nRasterRows );
671 poStmt->Bind( &nRasterBands );
672 poStmt->Bind( &nBlockXSize );
673 poStmt->Bind( &nBlockYSize );
674 poStmt->Bind( &nBlockBSize );
675
676 if( poStmt->Execute() )
677 {
678 nColumnBlockSize = nBlockXSize;
679 nRowBlockSize = nBlockYSize;
680 nBandBlockSize = nBlockBSize;
681 }
682
683 delete poStmt;
684 }
685
686 if( nRasterBands == 1 )
687 {
688 sBlocking = CPLSPrintf(
689 "blockSize=(%d, %d)",
690 nRowBlockSize,
691 nColumnBlockSize );
692 }
693 else
694 {
695 sBlocking = CPLSPrintf(
696 "blockSize=(%d, %d, %d)",
697 nRowBlockSize,
698 nColumnBlockSize,
699 nBandBlockSize );
700 }
701 }
702 else
703 {
704 sBlocking = "blocking=FALSE";
705
706 nColumnBlockSize = nRasterColumns;
707 nRowBlockSize = nRasterRows;
708 nBandBlockSize = nRasterBands;
709 }
710
711 // -----------------------------------------------------------
712 // Complete format parameters
713 // -----------------------------------------------------------
714
715 if( poConnection->GetVersion() > 10 )
716 {
717 if( nRasterBands == 1 )
718 {
719 sFormat = CPLSPrintf(
720 "20001, '"
721 "dimSize=(%d,%d) ",
722 nRasterRows, nRasterColumns );
723 }
724 else
725 {
726 sFormat = CPLSPrintf(
727 "21001, '"
728 "dimSize=(%d,%d,%d) ",
729 nRasterRows, nRasterColumns, nRasterBands );
730 }
731
732 if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
733 {
734 sFormat.append( CPLSPrintf(
735 "%s "
736 "cellDepth=%s "
737 "interleaving=%s "
738 "compression=%s "
739 "quality=%d'",
740 sBlocking.c_str(),
741 sCellDepth.c_str(),
742 sInterleaving.c_str(),
743 sCompressionType.c_str(),
744 nCompressQuality) );
745 }
746 else
747 {
748 sFormat.append( CPLSPrintf(
749 "%s "
750 "cellDepth=%s "
751 "interleaving=%s "
752 "compression=%s'",
753 sBlocking.c_str(),
754 sCellDepth.c_str(),
755 sInterleaving.c_str(),
756 sCompressionType.c_str() ) );
757 }
758 }
759 else
760 {
761 // -------------------------------------------------------
762 // For versions 10g or older
763 // -------------------------------------------------------
764
765 sFormat = CPLSPrintf(
766 "%s "
767 "cellDepth=%s "
768 "interleaving=%s "
769 "pyramid=FALSE "
770 "compression=NONE",
771 sBlocking.c_str(),
772 sCellDepth.c_str(),
773 sInterleaving.c_str() );
774 }
775
776 nTotalColumnBlocks = (int)
777 ( ( nRasterColumns + nColumnBlockSize - 1 ) / nColumnBlockSize );
778
779 nTotalRowBlocks = (int)
780 ( ( nRasterRows + nRowBlockSize - 1 ) / nRowBlockSize );
781
782 nTotalBandBlocks = (int)
783 ( ( nRasterBands + nBandBlockSize - 1) / nBandBlockSize );
784
785 // -------------------------------------------------------------------
786 // Create Georaster Table if needed
787 // -------------------------------------------------------------------
788
789 OWStatement* poStmt;
790
791 if( ! bUpdateIn )
792 {
793 poStmt = poConnection->CreateStatement( CPLSPrintf(
794 "DECLARE\n"
795 " TAB VARCHAR2(68) := UPPER('%s');\n"
796 " COL VARCHAR2(68) := UPPER('%s');\n"
797 " OWN VARCHAR2(68) := UPPER('%s');\n"
798 " CNT NUMBER := 0;\n"
799 "BEGIN\n"
800 " EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ALL_TABLES\n"
801 " WHERE TABLE_NAME = :1 AND OWNER = UPPER(:2)'\n"
802 " INTO CNT USING TAB, OWN;\n"
803 "\n"
804 " IF CNT = 0 THEN\n"
805 " EXECUTE IMMEDIATE 'CREATE TABLE %s%s %s';\n"
806 " SDO_GEOR_UTL.createDMLTrigger( TAB, COL );\n"
807 " END IF;\n"
808 "END;",
809 sTable.c_str(),
810 sColumn.c_str(),
811 sOwner.c_str(),
812 sSchema.c_str(),
813 sTable.c_str(),
814 szDescription ) );
815
816 if( ! poStmt->Execute() )
817 {
818 delete ( poStmt );
819 return false;
820 }
821
822 delete poStmt;
823 }
824
825 // -----------------------------------------------------------
826 // Prepare UPDATE or INSERT command
827 // -----------------------------------------------------------
828
829 CPLString sCommand;
830
831 if( bUpdateIn )
832 {
833 sCommand = CPLSPrintf(
834 "SELECT %s INTO GR1 FROM %s%s T WHERE %s FOR UPDATE;",
835 sColumn.c_str(),
836 sSchema.c_str(),
837 sTable.c_str(),
838 sWhere.c_str() );
839 }
840 else
841 {
842 sCommand = CPLSPrintf(
843 "INSERT INTO %s%s %s RETURNING %s INTO GR1;",
844 sSchema.c_str(),
845 sTable.c_str(),
846 sValues.c_str(),
847 sColumn.c_str() );
848 }
849
850 // -----------------------------------------------------------
851 // Create RTD if needed and insert/update GeoRaster
852 // -----------------------------------------------------------
853
854 char szBindRDT[OWNAME];
855 long long nBindRID = 0;
856 szBindRDT[0] = '\0';
857
858 CPLString sObjectTable;
859 CPLString sSecureFile;
860
861 // For version > 11 create RDT as relational table by default,
862 // if it is not specified by create-option OBJECTTABLE=TRUE
863
864 if( poConnection->GetVersion() <= 11 || bCreateObjectTable )
865 {
866 sObjectTable = "OF MDSYS.SDO_RASTER\n (";
867 }
868 else
869 {
870 sObjectTable = CPLSPrintf("(\n"
871 " RASTERID NUMBER,\n"
872 " PYRAMIDLEVEL NUMBER,\n"
873 " BANDBLOCKNUMBER NUMBER,\n"
874 " ROWBLOCKNUMBER NUMBER,\n"
875 " COLUMNBLOCKNUMBER NUMBER,\n"
876 " BLOCKMBR SDO_GEOMETRY,\n"
877 " RASTERBLOCK BLOB,\n"
878 " CONSTRAINT '||:rdt||'_RDT_PK ");
879 }
880
881 // For version >= 11 create RDT rasterBlock as securefile
882
883 if( poConnection->GetVersion() >= 11 )
884 {
885 sSecureFile = "SECUREFILE(CACHE)";
886 }
887 else
888 {
889 sSecureFile = "(NOCACHE NOLOGGING)";
890 }
891
892 if( poConnection->GetVersion() > 10 )
893 {
894 poStmt = poConnection->CreateStatement( CPLSPrintf(
895 "DECLARE\n"
896 " TAB VARCHAR2(68) := UPPER('%s');\n"
897 " COL VARCHAR2(68) := UPPER('%s');\n"
898 " OWN VARCHAR2(68) := UPPER('%s');\n"
899 " CNT NUMBER := 0;\n"
900 " GR1 SDO_GEORASTER := NULL;\n"
901 "BEGIN\n"
902 "\n"
903 " %s\n"
904 "\n"
905 " GR1.spatialExtent := NULL;\n"
906 "\n"
907 " SELECT GR1.RASTERDATATABLE INTO :rdt FROM DUAL;\n"
908 " SELECT GR1.RASTERID INTO :rid FROM DUAL;\n"
909 "\n"
910 " EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ALL_OBJECT_TABLES\n"
911 " WHERE TABLE_NAME = :1 AND OWNER = UPPER(:2)'\n"
912 " INTO CNT USING :rdt, OWN;\n"
913 "\n"
914 " IF CNT = 0 THEN\n"
915 " EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ALL_TABLES\n"
916 " WHERE TABLE_NAME = :1 AND OWNER = UPPER(:2)'\n"
917 " INTO CNT USING :rdt, OWN;\n"
918 " END IF;\n"
919 "\n"
920 " IF CNT = 0 THEN\n"
921 " EXECUTE IMMEDIATE 'CREATE TABLE %s'||:rdt||' %s"
922 "PRIMARY KEY (RASTERID, PYRAMIDLEVEL,\n"
923 " BANDBLOCKNUMBER, ROWBLOCKNUMBER, COLUMNBLOCKNUMBER))\n"
924 " LOB(RASTERBLOCK) STORE AS %s';\n"
925 " END IF;\n"
926 "\n"
927 " SDO_GEOR.createTemplate(GR1, %s, null, 'TRUE');\n"
928 "\n"
929 " UPDATE %s%s T SET %s = GR1 WHERE\n"
930 " T.%s.RasterDataTable = :rdt AND\n"
931 " T.%s.RasterId = :rid;\n"
932 "\n"
933 " EXECUTE IMMEDIATE\n"
934 " 'SELECT T.%s.METADATA.getClobVal()\n"
935 " FROM %s%s T\n"
936 " WHERE T.%s.RASTERDATATABLE = UPPER(:1)\n"
937 " AND T.%s.RASTERID = :2'\n"
938 " INTO :metadata\n"
939 " USING :rdt, :rid;\n"
940 "\n"
941 "END;\n",
942 sTable.c_str(),
943 sColumn.c_str(),
944 sOwner.c_str(),
945 sCommand.c_str(),
946 sSchema.c_str(),
947 sObjectTable.c_str(),
948 sSecureFile.c_str(),
949 sFormat.c_str(),
950 sSchema.c_str(),
951 sTable.c_str(),
952 sColumn.c_str(),
953 sColumn.c_str(),
954 sColumn.c_str(),
955 sColumn.c_str(),
956 sSchema.c_str(),
957 sTable.c_str(),
958 sColumn.c_str(),
959 sColumn.c_str() ) );
960
961 OCILobLocator* phLocator = nullptr;
962
963 poStmt->BindName( ":metadata", &phLocator );
964 poStmt->BindName( ":rdt", szBindRDT );
965 poStmt->BindName( ":rid", &nBindRID );
966
967 CPLErrorReset();
968
969 if( ! poStmt->Execute() )
970 {
971 delete poStmt;
972 return false;
973 }
974
975 sDataTable = szBindRDT;
976 nRasterId = nBindRID;
977
978 poStmt->FreeLob(phLocator);
979
980 delete poStmt;
981
982 return true;
983 }
984
985 // -----------------------------------------------------------
986 // Procedure for Server version older than 11
987 // -----------------------------------------------------------
988
989 char szCreateBlank[OWTEXT];
990
991 if( nRasterBands == 1 )
992 {
993 snprintf( szCreateBlank, sizeof(szCreateBlank),
994 "SDO_GEOR.createBlank(20001, "
995 "SDO_NUMBER_ARRAY(0, 0), "
996 "SDO_NUMBER_ARRAY(%d, %d), 0, :rdt, :rid)",
997 nRasterRows, nRasterColumns );
998 }
999 else
1000 {
1001 snprintf( szCreateBlank, sizeof(szCreateBlank),
1002 "SDO_GEOR.createBlank(21001, "
1003 "SDO_NUMBER_ARRAY(0, 0, 0), "
1004 "SDO_NUMBER_ARRAY(%d, %d, %d), 0, :rdt, :rid)",
1005 nRasterRows, nRasterColumns, nRasterBands );
1006 }
1007
1008 poStmt = poConnection->CreateStatement( CPLSPrintf(
1009 "DECLARE\n"
1010 " W NUMBER := :1;\n"
1011 " H NUMBER := :2;\n"
1012 " BB NUMBER := :3;\n"
1013 " RB NUMBER := :4;\n"
1014 " CB NUMBER := :5;\n"
1015 " OWN VARCHAR2(68) := UPPER('%s');\n"
1016 " X NUMBER := 0;\n"
1017 " Y NUMBER := 0;\n"
1018 " CNT NUMBER := 0;\n"
1019 " GR1 SDO_GEORASTER := NULL;\n"
1020 " GR2 SDO_GEORASTER := NULL;\n"
1021 " STM VARCHAR2(1024) := '';\n"
1022 "BEGIN\n"
1023 "\n"
1024 " %s\n"
1025 "\n"
1026 " SELECT GR1.RASTERDATATABLE INTO :rdt FROM DUAL;\n"
1027 " SELECT GR1.RASTERID INTO :rid FROM DUAL;\n"
1028 "\n"
1029 " SELECT %s INTO GR2 FROM %s%s T WHERE"
1030 " T.%s.RasterDataTable = :rdt AND"
1031 " T.%s.RasterId = :rid FOR UPDATE;\n"
1032 "\n"
1033 " GR1 := %s;\n"
1034 "\n"
1035 " SDO_GEOR.changeFormatCopy(GR1, '%s', GR2);\n"
1036 "\n"
1037 " UPDATE %s%s T SET %s = GR2 WHERE"
1038 " T.%s.RasterDataTable = :rdt AND"
1039 " T.%s.RasterId = :rid;\n"
1040 "\n"
1041 " EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ALL_OBJECT_TABLES\n"
1042 " WHERE TABLE_NAME = :1 AND OWNER = UPPER(:2)'\n"
1043 " INTO CNT USING :rdt, OWN;\n"
1044 "\n"
1045 " IF CNT = 0 THEN\n"
1046 " EXECUTE IMMEDIATE 'CREATE TABLE %s'||:rdt||' OF MDSYS.SDO_RASTER\n"
1047 " (PRIMARY KEY (RASTERID, PYRAMIDLEVEL, BANDBLOCKNUMBER,\n"
1048 " ROWBLOCKNUMBER, COLUMNBLOCKNUMBER))\n"
1049 " LOB(RASTERBLOCK) STORE AS (NOCACHE NOLOGGING)';\n"
1050 " ELSE\n"
1051 " EXECUTE IMMEDIATE 'DELETE FROM %s'||:rdt||' WHERE RASTERID ='||:rid||' ';\n"
1052 " END IF;\n"
1053 "\n"
1054 " STM := 'INSERT INTO %s'||:rdt||' VALUES (:1,0,:2-1,:3-1,:4-1,\n"
1055 " SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 3),\n"
1056 " SDO_ORDINATE_ARRAY(:5,:6,:7-1,:8-1)), EMPTY_BLOB() )';\n\n"
1057 " FOR b IN 1..BB LOOP\n"
1058 " Y := 0;\n"
1059 " FOR r IN 1..RB LOOP\n"
1060 " X := 0;\n"
1061 " FOR c IN 1..CB LOOP\n"
1062 " EXECUTE IMMEDIATE STM USING :rid, b, r, c, Y, X, (Y+H), (X+W);\n"
1063 " X := X + W;\n"
1064 " END LOOP;\n"
1065 " Y := Y + H;\n"
1066 " END LOOP;\n"
1067 " END LOOP;\n"
1068 "\n"
1069 " SDO_GEOR.georeference(GR1, %d, %d,"
1070 " SDO_NUMBER_ARRAY(1.0, 0.0, 0.0),"
1071 " SDO_NUMBER_ARRAY(0.0, 1.0, 0.0));\n"
1072 "\n"
1073 " UPDATE %s%s T SET %s = GR1 WHERE"
1074 " T.%s.RasterDataTable = :rdt AND"
1075 " T.%s.RasterId = :rid;\n"
1076 "\n"
1077 "END;",
1078 sOwner.c_str(),
1079 sCommand.c_str(),
1080 sColumn.c_str(), sSchema.c_str(), sTable.c_str(),
1081 sColumn.c_str(), sColumn.c_str(),
1082 szCreateBlank,
1083 sFormat.c_str(),
1084 sSchema.c_str(), sTable.c_str(),
1085 sColumn.c_str(), sColumn.c_str(), sColumn.c_str(),
1086 sSchema.c_str(), sSchema.c_str(), sSchema.c_str(),
1087 DEFAULT_CRS, MCL_DEFAULT,
1088 sSchema.c_str(), sTable.c_str(),
1089 sColumn.c_str(), sColumn.c_str(), sColumn.c_str() ) );
1090
1091 poStmt->Bind( &nColumnBlockSize );
1092 poStmt->Bind( &nRowBlockSize );
1093 poStmt->Bind( &nTotalBandBlocks );
1094 poStmt->Bind( &nTotalRowBlocks );
1095 poStmt->Bind( &nTotalColumnBlocks );
1096
1097 poStmt->BindName( ":rdt", szBindRDT );
1098 poStmt->BindName( ":rid", &nBindRID );
1099
1100 if( ! poStmt->Execute() )
1101 {
1102 delete poStmt;
1103 return false;
1104 }
1105
1106 sDataTable = szBindRDT;
1107 nRasterId = nBindRID;
1108
1109 delete poStmt;
1110
1111 return true;
1112 }
1113
1114 // ---------------------------------------------------------------------------
1115 // PrepareToOverwrite()
1116 // ---------------------------------------------------------------------------
1117
PrepareToOverwrite(void)1118 void GeoRasterWrapper::PrepareToOverwrite( void )
1119 {
1120 nTotalColumnBlocks = 0;
1121 nTotalRowBlocks = 0;
1122 nTotalBandBlocks = 0;
1123 if( sscanf( sCellDepth.c_str(), "%dBIT", &nCellSizeBits ) )
1124 {
1125 nGDALCellBytes = GDALGetDataTypeSize(
1126 OWGetDataType( sCellDepth.c_str() ) ) / 8;
1127 }
1128 else
1129 {
1130 nGDALCellBytes = 1;
1131 }
1132 dfXCoefficient[0] = 1.0;
1133 dfXCoefficient[1] = 0.0;
1134 dfXCoefficient[2] = 0.0;
1135 dfYCoefficient[0] = 0.0;
1136 dfYCoefficient[1] = 1.0;
1137 dfYCoefficient[2] = 0.0;
1138 sCompressionType = "NONE";
1139 nCompressQuality = 75;
1140 bGenPyramid = false;
1141 nPyramidLevels = 0;
1142 sPyramidResampling = "NN";
1143 bIsReferenced = false;
1144 nCacheBlockId = -1;
1145 nCurrentLevel = -1;
1146 pahLevels = nullptr;
1147 nLevelOffset = 0L;
1148 sInterleaving = "BSQ";
1149 bUpdate = false;
1150 bInitializeIO = false;
1151 bFlushMetadata = false;
1152 nSRID = DEFAULT_CRS;;
1153 nExtentSRID = 0;
1154 bGenSpatialExtent = false;
1155 bCreateObjectTable = false;
1156 nPyramidMaxLevel = 0;
1157 nBlockCount = 0L;
1158 sDInfo.global_state = 0;
1159 sCInfo.global_state = 0;
1160 bHasBitmapMask = false;
1161 bWriteOnly = false;
1162 bBlocking = true;
1163 bAutoBlocking = false;
1164 eModelCoordLocation = MCL_DEFAULT;
1165 bFlushBlock = false;
1166 nFlushBlockSize = 0L;
1167 phRPC = nullptr;
1168 }
1169
1170 // ---------------------------------------------------------------------------
1171 // Delete()
1172 // ---------------------------------------------------------------------------
1173
Delete(void)1174 bool GeoRasterWrapper::Delete( void )
1175 {
1176 if( ! bUniqueFound )
1177 {
1178 return false;
1179 }
1180
1181 OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
1182 "UPDATE %s%s T SET %s = NULL WHERE %s\n",
1183 sSchema.c_str(),
1184 sTable.c_str(),
1185 sColumn.c_str(),
1186 sWhere.c_str() ) );
1187
1188 bool bReturn = poStmt->Execute();
1189
1190 delete poStmt;
1191
1192 return bReturn;
1193 }
1194
1195 // ---------------------------------------------------------------------------
1196 // SetGeoReference()
1197 // ---------------------------------------------------------------------------
1198
SetGeoReference(long long nSRIDIn)1199 void GeoRasterWrapper::SetGeoReference( long long nSRIDIn )
1200 {
1201 nSRID = nSRIDIn;
1202
1203 bIsReferenced = true;
1204
1205 bFlushMetadata = true;
1206 }
1207
1208 // ---------------------------------------------------------------------------
1209 // GetRasterInfo()
1210 // ---------------------------------------------------------------------------
1211
GetRasterInfo(void)1212 void GeoRasterWrapper::GetRasterInfo( void )
1213 {
1214 // -------------------------------------------------------------------
1215 // Get dimensions
1216 // -------------------------------------------------------------------
1217
1218 int nCount = atoi( CPLGetXMLValue( phMetadata,
1219 "rasterInfo.totalDimensions", "0" ) );
1220 CPLXMLNode* phDimSize = CPLGetXMLNode( phMetadata, "rasterInfo.dimensionSize" );
1221
1222 int i = 0;
1223
1224 for( i = 0; i < nCount; i++ )
1225 {
1226 const char* pszType = CPLGetXMLValue( phDimSize, "type", "0" );
1227
1228 if( EQUAL( pszType, "ROW" ) )
1229 {
1230 nRasterRows = atoi( CPLGetXMLValue( phDimSize, "size", "0" ) );
1231 }
1232
1233 if( EQUAL( pszType, "COLUMN" ) )
1234 {
1235 nRasterColumns = atoi( CPLGetXMLValue( phDimSize, "size", "0" ) );
1236 }
1237
1238 if( EQUAL( pszType, "BAND" ) )
1239 {
1240 nRasterBands = atoi( CPLGetXMLValue( phDimSize, "size", "0" ) );
1241 }
1242
1243 phDimSize = phDimSize->psNext;
1244 }
1245
1246 if( nRasterBands == 0 )
1247 {
1248 nRasterBands = 1;
1249 }
1250
1251 // -------------------------------------------------------------------
1252 // Load NoData Values
1253 // -------------------------------------------------------------------
1254
1255 LoadNoDataValues();
1256
1257 // -------------------------------------------------------------------
1258 // Get ULTCoordinate values
1259 // -------------------------------------------------------------------
1260
1261 anULTCoordinate[0] = atoi(CPLGetXMLValue(
1262 phMetadata, "rasterInfo.ULTCoordinate.column", "0"));
1263
1264 anULTCoordinate[1] = atoi(CPLGetXMLValue(
1265 phMetadata, "rasterInfo.ULTCoordinate.row", "0"));
1266
1267 anULTCoordinate[2] = atoi(CPLGetXMLValue(
1268 phMetadata, "rasterInfo.ULTCoordinate.band", "0"));
1269
1270 // -------------------------------------------------------------------
1271 // Get Interleaving mode
1272 // -------------------------------------------------------------------
1273
1274 sInterleaving = CPLGetXMLValue( phMetadata,
1275 "rasterInfo.interleaving", "BSQ" );
1276
1277 // -------------------------------------------------------------------
1278 // Get blocking
1279 // -------------------------------------------------------------------
1280
1281 nRowBlockSize = atoi( CPLGetXMLValue( phMetadata,
1282 "rasterInfo.blocking.rowBlockSize",
1283 CPLSPrintf( "%d", nRasterRows ) ) );
1284
1285 nColumnBlockSize = atoi( CPLGetXMLValue( phMetadata,
1286 "rasterInfo.blocking.columnBlockSize",
1287 CPLSPrintf( "%d", nRasterColumns ) ) );
1288
1289 nBandBlockSize = atoi( CPLGetXMLValue( phMetadata,
1290 "rasterInfo.blocking.bandBlockSize",
1291 CPLSPrintf( "%d", nRasterBands ) ) );
1292
1293 nTotalColumnBlocks = atoi( CPLGetXMLValue( phMetadata,
1294 "rasterInfo.blocking.totalColumnBlocks","1") );
1295
1296 nTotalRowBlocks = atoi( CPLGetXMLValue( phMetadata,
1297 "rasterInfo.blocking.totalRowBlocks", "1" ) );
1298
1299 nTotalBandBlocks = atoi( CPLGetXMLValue( phMetadata,
1300 "rasterInfo.blocking.totalBandBlocks", "1" ) );
1301
1302 if( nBandBlockSize == -1 )
1303 {
1304 nBandBlockSize = nRasterBands;
1305 }
1306
1307 // -------------------------------------------------------------------
1308 // Get data type
1309 // -------------------------------------------------------------------
1310
1311 sCellDepth = CPLGetXMLValue( phMetadata, "rasterInfo.cellDepth", "8BIT_U" );
1312
1313 if( sscanf( sCellDepth.c_str(), "%dBIT", &nCellSizeBits ) )
1314 {
1315 nGDALCellBytes = GDALGetDataTypeSize(
1316 OWGetDataType( sCellDepth.c_str() ) ) / 8;
1317 }
1318 else
1319 {
1320 nGDALCellBytes = 1;
1321 }
1322
1323 sCompressionType = CPLGetXMLValue( phMetadata,
1324 "rasterInfo.compression.type", "NONE" );
1325
1326 if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
1327 {
1328 nCompressQuality = atoi( CPLGetXMLValue( phMetadata,
1329 "rasterInfo.compression.quality", "75" ) );
1330 }
1331
1332 if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
1333 {
1334 sInterleaving = "BIP";
1335 }
1336
1337 // -------------------------------------------------------------------
1338 // Get default RGB Bands
1339 // -------------------------------------------------------------------
1340
1341 iDefaultRedBand = atoi( CPLGetXMLValue( phMetadata,
1342 "objectInfo.defaultRed", "-1" ) );
1343
1344 iDefaultGreenBand = atoi( CPLGetXMLValue( phMetadata,
1345 "objectInfo.defaultGreen", "-1" ) );
1346
1347 iDefaultBlueBand = atoi( CPLGetXMLValue( phMetadata,
1348 "objectInfo.defaultBlue", "-1" ) );
1349
1350 // -------------------------------------------------------------------
1351 // Get Pyramid details
1352 // -------------------------------------------------------------------
1353
1354 char szPyramidType[OWCODE];
1355
1356 snprintf( szPyramidType, sizeof(szPyramidType), "%s",
1357 CPLGetXMLValue( phMetadata,
1358 "rasterInfo.pyramid.type", "None" ) );
1359
1360 if( EQUAL( szPyramidType, "DECREASE" ) )
1361 {
1362 nPyramidMaxLevel = atoi( CPLGetXMLValue( phMetadata,
1363 "rasterInfo.pyramid.maxLevel", "0" ) );
1364 }
1365
1366 // -------------------------------------------------------------------
1367 // Check for RPCs
1368 // -------------------------------------------------------------------
1369
1370 CPLXMLNode* phModelType = CPLGetXMLNode( phMetadata,
1371 "spatialReferenceInfo.modelType");
1372
1373 for( int n = 1 ; phModelType ; phModelType = phModelType->psNext, n++ )
1374 {
1375 const char* pszModelType = CPLGetXMLValue( phModelType, ".", "None" );
1376
1377 if( EQUAL( pszModelType, "StoredFunction" ) )
1378 {
1379 GetGCP();
1380 }
1381
1382 if( EQUAL( pszModelType, "FunctionalFitting" ) )
1383 {
1384 GetRPC();
1385 }
1386 }
1387
1388 // -------------------------------------------------------------------
1389 // Prepare to get Spatial reference system
1390 // -------------------------------------------------------------------
1391
1392 bIsReferenced = EQUAL( "TRUE", CPLGetXMLValue( phMetadata,
1393 "spatialReferenceInfo.isReferenced", "FALSE" ) );
1394
1395 nSRID = (long long) CPLAtoGIntBig( CPLGetXMLValue( phMetadata,
1396 "spatialReferenceInfo.SRID", "0" ) );
1397
1398 if( bIsReferenced == false || nSRID == 0 || nSRID == UNKNOWN_CRS )
1399 {
1400 return;
1401 }
1402
1403 }
1404
1405 // ---------------------------------------------------------------------------
1406 // QueryWKText()
1407 // ---------------------------------------------------------------------------
1408
QueryWKText()1409 void GeoRasterWrapper::QueryWKText()
1410 {
1411 char* pszWKText = (char*) VSI_MALLOC2_VERBOSE( sizeof(char), 3 * OWTEXT);
1412 char* pszAuthority = (char*) VSI_MALLOC2_VERBOSE( sizeof(char), OWTEXT);
1413
1414 OWStatement* poStmt = poConnection->CreateStatement(
1415 "select wktext, auth_name from mdsys.cs_srs "
1416 "where srid = :1 and wktext is not null" );
1417
1418 poStmt->Bind( &nSRID );
1419 poStmt->Define( pszWKText, 3 * OWTEXT );
1420 poStmt->Define( pszAuthority, OWTEXT );
1421
1422 if( poStmt->Execute() )
1423 {
1424 sWKText = pszWKText;
1425 sAuthority = pszAuthority;
1426 }
1427
1428 CPLFree( pszWKText );
1429 CPLFree( pszAuthority );
1430
1431 delete poStmt;
1432 }
1433
1434 // ---------------------------------------------------------------------------
1435 // GetStatistics()
1436 // ---------------------------------------------------------------------------
1437
GetStatistics(int nBand,char * pszMin,char * pszMax,char * pszMean,char * pszMedian,char * pszMode,char * pszStdDev,char * pszSampling)1438 bool GeoRasterWrapper::GetStatistics( int nBand,
1439 char* pszMin,
1440 char* pszMax,
1441 char* pszMean,
1442 char* pszMedian,
1443 char* pszMode,
1444 char* pszStdDev,
1445 char* pszSampling )
1446 {
1447 int n = 1;
1448
1449 CPLXMLNode *phSubLayer = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
1450
1451 for( n = 1 ; phSubLayer ; phSubLayer = phSubLayer->psNext, n++ )
1452 {
1453 if( n == nBand && CPLGetXMLNode( phSubLayer, "statisticDataset" ) )
1454 {
1455 strncpy( pszSampling, CPLGetXMLValue( phSubLayer,
1456 "statisticDataset.samplingFactor", "0.0" ), MAX_DOUBLE_STR_REP );
1457 strncpy( pszMin, CPLGetXMLValue( phSubLayer,
1458 "statisticDataset.MIN", "0.0" ), MAX_DOUBLE_STR_REP );
1459 strncpy( pszMax, CPLGetXMLValue( phSubLayer,
1460 "statisticDataset.MAX", "0.0" ), MAX_DOUBLE_STR_REP );
1461 strncpy( pszMean, CPLGetXMLValue( phSubLayer,
1462 "statisticDataset.MEAN", "0.0" ), MAX_DOUBLE_STR_REP );
1463 strncpy( pszMedian, CPLGetXMLValue( phSubLayer,
1464 "statisticDataset.MEDIAN", "0.0" ), MAX_DOUBLE_STR_REP );
1465 strncpy( pszMode, CPLGetXMLValue( phSubLayer,
1466 "statisticDataset.MODEVALUE", "0.0" ), MAX_DOUBLE_STR_REP );
1467 strncpy( pszStdDev, CPLGetXMLValue( phSubLayer,
1468 "statisticDataset.STD", "0.0" ), MAX_DOUBLE_STR_REP );
1469 return true;
1470 }
1471 }
1472 return false;
1473 }
1474
1475 // ---------------------------------------------------------------------------
1476 // SetStatistics()
1477 // ---------------------------------------------------------------------------
1478
SetStatistics(int nBand,const char * pszMin,const char * pszMax,const char * pszMean,const char * pszMedian,const char * pszMode,const char * pszStdDev,const char * pszSampling)1479 bool GeoRasterWrapper::SetStatistics( int nBand,
1480 const char* pszMin,
1481 const char* pszMax,
1482 const char* pszMean,
1483 const char* pszMedian,
1484 const char* pszMode,
1485 const char* pszStdDev,
1486 const char* pszSampling )
1487 {
1488 InitializeLayersNode();
1489
1490 bFlushMetadata = true;
1491
1492 int n = 1;
1493
1494 CPLXMLNode* phSubLayer = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
1495
1496 for( n = 1 ; phSubLayer ; phSubLayer = phSubLayer->psNext, n++ )
1497 {
1498 if( n != nBand )
1499 {
1500 continue;
1501 }
1502
1503 CPLXMLNode* psSDaset = CPLGetXMLNode( phSubLayer, "statisticDataset" );
1504
1505 if( psSDaset != nullptr )
1506 {
1507 CPLRemoveXMLChild( phSubLayer, psSDaset );
1508 CPLDestroyXMLNode( psSDaset );
1509 }
1510
1511 psSDaset = CPLCreateXMLNode(phSubLayer,CXT_Element,"statisticDataset");
1512
1513 CPLCreateXMLElementAndValue(psSDaset,"samplingFactor", pszSampling );
1514 CPLCreateXMLElementAndValue(psSDaset,"MIN", pszMin );
1515 CPLCreateXMLElementAndValue(psSDaset,"MAX", pszMax );
1516 CPLCreateXMLElementAndValue(psSDaset,"MEAN", pszMean );
1517 CPLCreateXMLElementAndValue(psSDaset,"MEDIAN", pszMedian );
1518 CPLCreateXMLElementAndValue(psSDaset,"MODEVALUE", pszMode );
1519 CPLCreateXMLElementAndValue(psSDaset,"STD", pszStdDev );
1520
1521 return true;
1522 }
1523 return false;
1524 }
1525
1526 // ---------------------------------------------------------------------------
1527 // HasColorTable()
1528 // ---------------------------------------------------------------------------
1529
HasColorMap(int nBand)1530 bool GeoRasterWrapper::HasColorMap( int nBand )
1531 {
1532 int n = 1;
1533
1534 CPLXMLNode *psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
1535
1536 for( ; psLayers; psLayers = psLayers->psNext, n++ )
1537 {
1538 if( n == nBand )
1539 {
1540 if( CPLGetXMLNode( psLayers, "colorMap.colors" ) )
1541 {
1542 return true;
1543 }
1544 }
1545 }
1546
1547 return false;
1548 }
1549
1550 // ---------------------------------------------------------------------------
1551 // InitializeLayersNode()
1552 // ---------------------------------------------------------------------------
1553
InitializeLayersNode()1554 void GeoRasterWrapper::InitializeLayersNode()
1555 {
1556 CPLXMLNode *pslInfo = CPLGetXMLNode( phMetadata, "layerInfo" );
1557
1558 int n = 1;
1559
1560 for( n = 0 ; n < nRasterBands; n++ )
1561 {
1562 CPLXMLNode *psSLayer = CPLGetXMLNode( pslInfo, "subLayer" );
1563
1564 if( psSLayer == nullptr )
1565 {
1566 psSLayer = CPLCreateXMLNode( pslInfo, CXT_Element, "subLayer" );
1567
1568 CPLCreateXMLElementAndValue( psSLayer, "layerNumber",
1569 CPLSPrintf( "%d", n + 1 ) );
1570
1571 CPLCreateXMLElementAndValue( psSLayer, "layerDimensionOrdinate",
1572 CPLSPrintf( "%d", n ) );
1573
1574 CPLCreateXMLElementAndValue( psSLayer, "layerID", "" );
1575 }
1576 }
1577 }
1578
1579 // ---------------------------------------------------------------------------
1580 // GetColorTable()
1581 // ---------------------------------------------------------------------------
1582
GetColorMap(int nBand,GDALColorTable * poCT)1583 void GeoRasterWrapper::GetColorMap( int nBand, GDALColorTable* poCT )
1584 {
1585 GDALColorEntry oEntry;
1586
1587 int n = 1;
1588
1589 CPLXMLNode* psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
1590
1591 for( ; psLayers; psLayers = psLayers->psNext, n++ )
1592 {
1593 if( n != nBand )
1594 {
1595 continue;
1596 }
1597
1598 CPLXMLNode* psColors = CPLGetXMLNode( psLayers, "colorMap.colors.cell" );
1599
1600 for( ; psColors; psColors = psColors->psNext )
1601 {
1602 const int iColor = (short) atoi( CPLGetXMLValue( psColors, "value","0"));
1603 oEntry.c1 = (short) atoi( CPLGetXMLValue( psColors, "red", "0"));
1604 oEntry.c2 = (short) atoi( CPLGetXMLValue( psColors, "green","0"));
1605 oEntry.c3 = (short) atoi( CPLGetXMLValue( psColors, "blue", "0"));
1606 oEntry.c4 = (short) atoi( CPLGetXMLValue( psColors, "alpha","0"));
1607 poCT->SetColorEntry( iColor, &oEntry );
1608 }
1609 break;
1610 }
1611 }
1612
1613 // ---------------------------------------------------------------------------
1614 // SetColorTable()
1615 // ---------------------------------------------------------------------------
1616
SetColorMap(int nBand,GDALColorTable * poCT)1617 void GeoRasterWrapper::SetColorMap( int nBand, GDALColorTable* poCT )
1618 {
1619 InitializeLayersNode();
1620
1621 bFlushMetadata = true;
1622
1623 GDALColorEntry oEntry;
1624
1625 int n = 1;
1626
1627 CPLXMLNode* phSubLayer = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
1628
1629 for( n = 1 ; phSubLayer ; phSubLayer = phSubLayer->psNext, n++ )
1630 {
1631 if( n != nBand )
1632 {
1633 continue;
1634 }
1635
1636 CPLXMLNode* psCMap = CPLGetXMLNode( phSubLayer, "colorMap" );
1637
1638 if( psCMap != nullptr )
1639 {
1640 CPLRemoveXMLChild( phSubLayer, psCMap );
1641 CPLDestroyXMLNode( psCMap );
1642 }
1643
1644 psCMap = CPLCreateXMLNode( phSubLayer, CXT_Element, "colorMap" );
1645
1646 CPLXMLNode* psColor = CPLCreateXMLNode( psCMap, CXT_Element, "colors" );
1647
1648 // ------------------------------------------------
1649 // Clean existing colors entry (RGB color table)
1650 // ------------------------------------------------
1651
1652 if( psColor != nullptr )
1653 {
1654 CPLRemoveXMLChild( psCMap, psColor );
1655 CPLDestroyXMLNode( psColor );
1656 }
1657
1658 psColor = CPLCreateXMLNode( psCMap, CXT_Element, "colors" );
1659
1660 int iColor = 0;
1661
1662 int nCount = 0;
1663
1664 switch( nCellSizeBits )
1665 {
1666 case 1 :
1667 nCount = 2;
1668 break;
1669 case 2 :
1670 nCount = 4;
1671 break;
1672 case 4:
1673 nCount = 16;
1674 break;
1675 default:
1676 nCount = poCT->GetColorEntryCount();
1677 }
1678
1679 for( iColor = 0; iColor < nCount; iColor++ )
1680 {
1681 poCT->GetColorEntryAsRGB( iColor, &oEntry );
1682
1683 CPLXMLNode* psCell = CPLCreateXMLNode( psColor, CXT_Element, "cell" );
1684
1685 CPLSetXMLValue( psCell, "#value", CPLSPrintf("%d", iColor) );
1686 CPLSetXMLValue( psCell, "#blue", CPLSPrintf("%d", oEntry.c3) );
1687 CPLSetXMLValue( psCell, "#red", CPLSPrintf("%d", oEntry.c1) );
1688 CPLSetXMLValue( psCell, "#green", CPLSPrintf("%d", oEntry.c2) );
1689 CPLSetXMLValue( psCell, "#alpha", CPLSPrintf("%d", oEntry.c4) );
1690 }
1691 }
1692 }
1693
1694 // ---------------------------------------------------------------------------
1695 // InitializeIO()
1696 // ---------------------------------------------------------------------------
1697
InitializeIO(void)1698 bool GeoRasterWrapper::InitializeIO( void )
1699 {
1700 bInitializeIO = true;
1701
1702 // --------------------------------------------------------------------
1703 // Initialize Pyramid level details
1704 // --------------------------------------------------------------------
1705
1706 pahLevels = (hLevelDetails*) CPLCalloc( sizeof(hLevelDetails),
1707 nPyramidMaxLevel + 1 );
1708
1709 // --------------------------------------------------------------------
1710 // Calculate number and size of the blocks in level zero
1711 // --------------------------------------------------------------------
1712
1713 nBlockCount = (unsigned long) ( nTotalColumnBlocks * nTotalRowBlocks * nTotalBandBlocks );
1714 nBlockBytes = (unsigned long) ( nColumnBlockSize * nRowBlockSize * nBandBlockSize *
1715 nCellSizeBits / 8L );
1716 nGDALBlockBytes = (unsigned long) ( nColumnBlockSize * nRowBlockSize * nGDALCellBytes );
1717
1718 pahLevels[0].nColumnBlockSize = nColumnBlockSize;
1719 pahLevels[0].nRowBlockSize = nRowBlockSize;
1720 pahLevels[0].nTotalColumnBlocks = nTotalColumnBlocks;
1721 pahLevels[0].nTotalRowBlocks = nTotalRowBlocks;
1722 pahLevels[0].nBlockCount = nBlockCount;
1723 pahLevels[0].nBlockBytes = nBlockBytes;
1724 pahLevels[0].nGDALBlockBytes = nGDALBlockBytes;
1725 pahLevels[0].nOffset = 0L;
1726
1727 // --------------------------------------------------------------------
1728 // Calculate number and size of the blocks in Pyramid levels
1729 // --------------------------------------------------------------------
1730
1731 int iLevel = 1;
1732
1733 for( iLevel = 1; iLevel <= nPyramidMaxLevel; iLevel++ )
1734 {
1735 int nRBS = nRowBlockSize;
1736 int nCBS = nColumnBlockSize;
1737 int nTCB;
1738 int nTRB;
1739
1740 // --------------------------------------------------------------------
1741 // Calculate the actual size of a lower resolution block
1742 // --------------------------------------------------------------------
1743
1744 double dfScale = pow( (double) 2.0, (double) iLevel );
1745
1746 int nXSize = (int) floor( (double) nRasterColumns / dfScale );
1747 int nYSize = (int) floor( (double) nRasterRows / dfScale );
1748 int nXBlock = (int) floor( (double) nCBS / 2.0 );
1749 int nYBlock = (int) floor( (double) nRBS / 2.0 );
1750
1751 if( nXSize <= nXBlock && nYSize <= nYBlock )
1752 {
1753 // ------------------------------------------------------------
1754 // Calculate the size of the single small blocks
1755 // ------------------------------------------------------------
1756
1757 nCBS = nXSize;
1758 nRBS = nYSize;
1759 nTCB = 1;
1760 nTRB = 1;
1761 }
1762 else
1763 {
1764 // ------------------------------------------------------------
1765 // Recalculate blocks quantity
1766 // ------------------------------------------------------------
1767
1768 nTCB = (int) ceil( (double) nXSize / nCBS );
1769 nTRB = (int) ceil( (double) nYSize / nRBS );
1770 }
1771
1772 // --------------------------------------------------------------------
1773 // Save level datails
1774 // --------------------------------------------------------------------
1775
1776 pahLevels[iLevel].nColumnBlockSize = nCBS;
1777 pahLevels[iLevel].nRowBlockSize = nRBS;
1778 pahLevels[iLevel].nTotalColumnBlocks = nTCB;
1779 pahLevels[iLevel].nTotalRowBlocks = nTRB;
1780 pahLevels[iLevel].nBlockCount = (unsigned long ) ( nTCB * nTRB * nTotalBandBlocks );
1781 pahLevels[iLevel].nBlockBytes = (unsigned long ) ( nCBS * nRBS * nBandBlockSize *
1782 nCellSizeBits / 8L );
1783 pahLevels[iLevel].nGDALBlockBytes = (unsigned long ) ( nCBS * nRBS * nGDALCellBytes );
1784 pahLevels[iLevel].nOffset = 0L;
1785 }
1786
1787 // --------------------------------------------------------------------
1788 // Calculate total row count and level's offsets
1789 // --------------------------------------------------------------------
1790
1791 nBlockCount = 0L;
1792
1793 for( iLevel = 0; iLevel <= nPyramidMaxLevel; iLevel++ )
1794 {
1795 pahLevels[iLevel].nOffset = nBlockCount;
1796 nBlockCount += pahLevels[iLevel].nBlockCount;
1797 }
1798
1799 // --------------------------------------------------------------------
1800 // Allocate buffer for one raster block
1801 // --------------------------------------------------------------------
1802
1803 long nMaxBufferSize = MAX( nBlockBytes, nGDALBlockBytes );
1804
1805 pabyBlockBuf = (GByte*) VSI_MALLOC_VERBOSE( nMaxBufferSize );
1806
1807 if ( pabyBlockBuf == nullptr )
1808 {
1809 return false;
1810 }
1811
1812 // --------------------------------------------------------------------
1813 // Allocate buffer for one compressed raster block
1814 // --------------------------------------------------------------------
1815
1816 if( bUpdate && ! EQUAL( sCompressionType.c_str(), "NONE") )
1817 {
1818 pabyCompressBuf = (GByte*) VSI_MALLOC_VERBOSE( nMaxBufferSize );
1819
1820 if ( pabyCompressBuf == nullptr )
1821 {
1822 return false;
1823 }
1824 }
1825
1826 // --------------------------------------------------------------------
1827 // Allocate array of LOB Locators
1828 // --------------------------------------------------------------------
1829
1830 pahLocator = (OCILobLocator**) VSI_MALLOC_VERBOSE( sizeof(void*) * nBlockCount );
1831
1832 if ( pahLocator == nullptr )
1833 {
1834 return false;
1835 }
1836
1837 // --------------------------------------------------------------------
1838 // Issue a statement to load the locators
1839 // --------------------------------------------------------------------
1840
1841 const char* pszUpdate = bUpdate ? "\nFOR UPDATE" : "";
1842
1843 delete poBlockStmt;
1844 poBlockStmt = poConnection->CreateStatement( CPLSPrintf(
1845 "SELECT RASTERBLOCK\n"
1846 "FROM %s%s\n"
1847 "WHERE RASTERID = :1\n"
1848 "ORDER BY\n"
1849 " PYRAMIDLEVEL ASC,\n"
1850 " BANDBLOCKNUMBER ASC,\n"
1851 " ROWBLOCKNUMBER ASC,\n"
1852 " COLUMNBLOCKNUMBER ASC%s",
1853 sSchema.c_str(),
1854 sDataTable.c_str(),
1855 pszUpdate ) );
1856
1857 poBlockStmt->Bind( &nRasterId );
1858 poBlockStmt->Define( pahLocator, nBlockCount );
1859
1860 if( ! poBlockStmt->Execute( static_cast<int>(nBlockCount) ) )
1861 {
1862 return false;
1863 }
1864
1865 return true;
1866 }
1867
1868 // ---------------------------------------------------------------------------
1869 // InitializeLevel()
1870 // ---------------------------------------------------------------------------
1871
InitializeLevel(int nLevel)1872 void GeoRasterWrapper::InitializeLevel( int nLevel )
1873 {
1874 nCurrentLevel = nLevel;
1875 nColumnBlockSize = pahLevels[nLevel].nColumnBlockSize;
1876 nRowBlockSize = pahLevels[nLevel].nRowBlockSize;
1877 nTotalColumnBlocks = pahLevels[nLevel].nTotalColumnBlocks;
1878 nTotalRowBlocks = pahLevels[nLevel].nTotalRowBlocks;
1879 nBlockBytes = pahLevels[nLevel].nBlockBytes;
1880 nGDALBlockBytes = pahLevels[nLevel].nGDALBlockBytes;
1881 nLevelOffset = pahLevels[nLevel].nOffset;
1882 }
1883
1884 // ---------------------------------------------------------------------------
1885 // GetDataBlock()
1886 // ---------------------------------------------------------------------------
1887
GetDataBlock(int nBand,int nLevel,int nXOffset,int nYOffset,void * pData)1888 bool GeoRasterWrapper::GetDataBlock( int nBand,
1889 int nLevel,
1890 int nXOffset,
1891 int nYOffset,
1892 void* pData )
1893 {
1894 if( ! bInitializeIO )
1895 {
1896 if( InitializeIO() == false )
1897 {
1898 return false;
1899 }
1900 }
1901
1902 if( nCurrentLevel != nLevel && nLevel != DEFAULT_BMP_MASK )
1903 {
1904 InitializeLevel( nLevel );
1905 }
1906
1907 long nBlock = GetBlockNumber( nBand, nXOffset, nYOffset );
1908
1909 CPLDebug( "Read ",
1910 "Block = %4ld Size = %7ld Band = %d Level = %d X = %d Y = %d",
1911 nBlock, nBlockBytes, nBand, nLevel, nXOffset, nYOffset );
1912
1913 if( nCacheBlockId != nBlock )
1914 {
1915 if ( bFlushBlock )
1916 {
1917 if( ! FlushBlock( nCacheBlockId ) )
1918 {
1919 return false;
1920 }
1921 }
1922
1923 nCacheBlockId = nBlock;
1924
1925 unsigned long nBytesRead = 0;
1926
1927 nBytesRead = poBlockStmt->ReadBlob( pahLocator[nBlock],
1928 pabyBlockBuf,
1929 nBlockBytes );
1930
1931 CPLDebug( "Load ", "Block = %4ld Size = %7ld", nBlock, nBlockBytes );
1932
1933 if( nBytesRead == 0 )
1934 {
1935 memset( pData, 0, nGDALBlockBytes );
1936 return true;
1937 }
1938
1939 if( nBytesRead < nBlockBytes &&
1940 EQUAL( sCompressionType.c_str(), "NONE") )
1941 {
1942 CPLError( CE_Warning, CPLE_AppDefined,
1943 "BLOB size (%ld) is smaller than expected (%ld) !",
1944 nBytesRead, nBlockBytes );
1945 memset( pData, 0, nGDALBlockBytes );
1946 return true;
1947 }
1948
1949 if( nBytesRead > nBlockBytes )
1950 {
1951 CPLError( CE_Warning, CPLE_AppDefined,
1952 "BLOB size (%ld) is bigger than expected (%ld) !",
1953 nBytesRead, nBlockBytes );
1954 memset( pData, 0, nGDALBlockBytes );
1955 return true;
1956 }
1957
1958 // ----------------------------------------------------------------
1959 // GeoRaster BLOB is always Big endian
1960 // ----------------------------------------------------------------
1961
1962 #ifndef CPL_MSB
1963 if( nCellSizeBits > 8 &&
1964 EQUAL( sCompressionType.c_str(), "DEFLATE") == false )
1965 {
1966 int nWordSize = nCellSizeBits / 8;
1967 int nWordCount = nColumnBlockSize * nRowBlockSize * nBandBlockSize;
1968 GDALSwapWords( pabyBlockBuf, nWordSize, nWordCount, nWordSize );
1969 }
1970 #endif
1971
1972 // ----------------------------------------------------------------
1973 // Uncompress
1974 // ----------------------------------------------------------------
1975
1976 if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
1977 {
1978 UncompressJpeg( nBytesRead );
1979 }
1980 else if ( EQUAL( sCompressionType.c_str(), "DEFLATE" ) )
1981 {
1982 UncompressDeflate( nBytesRead );
1983 #ifndef CPL_MSB
1984 if( nCellSizeBits > 8 )
1985 {
1986 int nWordSize = nCellSizeBits / 8;
1987 int nWordCount = nColumnBlockSize * nRowBlockSize * nBandBlockSize;
1988 GDALSwapWords( pabyBlockBuf, nWordSize, nWordCount, nWordSize );
1989 }
1990 #endif
1991 }
1992
1993 // ----------------------------------------------------------------
1994 // Unpack NBits
1995 // ----------------------------------------------------------------
1996
1997 if( nCellSizeBits < 8 || nLevel == DEFAULT_BMP_MASK )
1998 {
1999 UnpackNBits( pabyBlockBuf );
2000 }
2001 }
2002
2003 // --------------------------------------------------------------------
2004 // Uninterleaving, extract band from block buffer
2005 // --------------------------------------------------------------------
2006
2007 int nStart = ( nBand - 1 ) % nBandBlockSize;
2008
2009 if( EQUAL( sInterleaving.c_str(), "BSQ" ) || nBandBlockSize == 1 )
2010 {
2011 nStart *= nGDALBlockBytes;
2012
2013 memcpy( pData, &pabyBlockBuf[nStart], nGDALBlockBytes );
2014 }
2015 else
2016 {
2017 int nIncr = nBandBlockSize * nGDALCellBytes;
2018 int nSize = nGDALCellBytes;
2019
2020 if( EQUAL( sInterleaving.c_str(), "BIL" ) )
2021 {
2022 nStart *= nColumnBlockSize;
2023 nIncr *= nColumnBlockSize;
2024 nSize *= nColumnBlockSize;
2025 }
2026
2027 GByte* pabyData = (GByte*) pData;
2028
2029 unsigned long ii = 0;
2030 unsigned long jj = nStart * nGDALCellBytes;
2031
2032 for( ii = 0; ii < nGDALBlockBytes; ii += nSize, jj += nIncr )
2033 {
2034 memcpy( &pabyData[ii], &pabyBlockBuf[jj], nSize );
2035 }
2036 }
2037
2038 return true;
2039 }
2040
2041 // ---------------------------------------------------------------------------
2042 // SetDataBlock()
2043 // ---------------------------------------------------------------------------
2044
SetDataBlock(int nBand,int nLevel,int nXOffset,int nYOffset,void * pData)2045 bool GeoRasterWrapper::SetDataBlock( int nBand,
2046 int nLevel,
2047 int nXOffset,
2048 int nYOffset,
2049 void* pData )
2050 {
2051 #ifndef CPL_MSB
2052 if( nCellSizeBits > 8 )
2053 {
2054 int nWordSize = nCellSizeBits / 8;
2055 int nWordCount = nColumnBlockSize * nRowBlockSize;
2056 GDALSwapWords( pData, nWordSize, nWordCount, nWordSize );
2057 }
2058 #endif
2059
2060 if( ! bInitializeIO )
2061 {
2062 if( InitializeIO() == false )
2063 {
2064 return false;
2065 }
2066 }
2067
2068 if( nCurrentLevel != nLevel )
2069 {
2070 InitializeLevel( nLevel );
2071 }
2072
2073 long nBlock = GetBlockNumber( nBand, nXOffset, nYOffset );
2074
2075 CPLDebug( "Write ",
2076 "Block = %4ld Size = %7ld Band = %d Level = %d X = %d Y = %d",
2077 nBlock, nBlockBytes, nBand, nLevel, nXOffset, nYOffset );
2078
2079 // --------------------------------------------------------------------
2080 // Flush previous block
2081 // --------------------------------------------------------------------
2082
2083 if( nCacheBlockId != nBlock && bFlushBlock )
2084 {
2085 if( ! FlushBlock( nCacheBlockId ) )
2086 {
2087 return false;
2088 }
2089 }
2090
2091 // --------------------------------------------------------------------
2092 // Re-load interleaved block
2093 // --------------------------------------------------------------------
2094
2095 if( nBandBlockSize > 1 && bWriteOnly == false && nCacheBlockId != nBlock )
2096 {
2097 nCacheBlockId = nBlock;
2098
2099 unsigned long nBytesRead = 0;
2100
2101 nBytesRead = poBlockStmt->ReadBlob( pahLocator[nBlock],
2102 pabyBlockBuf,
2103 static_cast<unsigned long>(nBlockBytes) );
2104
2105 CPLDebug( "Reload", "Block = %4ld Size = %7ld", nBlock, nBlockBytes );
2106
2107 if( nBytesRead == 0 )
2108 {
2109 memset( pabyBlockBuf, 0, nBlockBytes );
2110 }
2111 else
2112 {
2113 // ------------------------------------------------------------
2114 // Uncompress
2115 // ------------------------------------------------------------
2116
2117 if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
2118 {
2119 UncompressJpeg( nBytesRead );
2120 }
2121 else if ( EQUAL( sCompressionType.c_str(), "DEFLATE" ) )
2122 {
2123 UncompressDeflate( nBytesRead );
2124 }
2125
2126 // ------------------------------------------------------------
2127 // Unpack NBits
2128 // ------------------------------------------------------------
2129
2130 if( nCellSizeBits < 8 || nLevel == DEFAULT_BMP_MASK )
2131 {
2132 UnpackNBits( pabyBlockBuf );
2133 }
2134 }
2135 }
2136
2137 GByte *pabyInBuf = (GByte *) pData;
2138
2139 // --------------------------------------------------------------------
2140 // Interleave
2141 // --------------------------------------------------------------------
2142
2143 int nStart = ( nBand - 1 ) % nBandBlockSize;
2144
2145 if( EQUAL( sInterleaving.c_str(), "BSQ" ) || nBandBlockSize == 1 )
2146 {
2147 nStart *= nGDALBlockBytes;
2148
2149 memcpy( &pabyBlockBuf[nStart], pabyInBuf, nGDALBlockBytes );
2150 }
2151 else
2152 {
2153 int nIncr = nBandBlockSize * nGDALCellBytes;
2154 int nSize = nGDALCellBytes;
2155
2156 if( EQUAL( sInterleaving.c_str(), "BIL" ) )
2157 {
2158 nStart *= nColumnBlockSize;
2159 nIncr *= nColumnBlockSize;
2160 nSize *= nColumnBlockSize;
2161 }
2162
2163 unsigned long ii = 0;
2164 unsigned long jj = nStart * nGDALCellBytes;
2165
2166 for( ii = 0; ii < nGDALBlockBytes; ii += nSize, jj += nIncr )
2167 {
2168 memcpy( &pabyBlockBuf[jj], &pabyInBuf[ii], nSize );
2169 }
2170 }
2171
2172 // --------------------------------------------------------------------
2173 // Flag the flush block
2174 // --------------------------------------------------------------------
2175
2176 nCacheBlockId = nBlock;
2177 bFlushBlock = true;
2178 nFlushBlockSize = nBlockBytes;
2179
2180 return true;
2181 }
2182
2183 // ---------------------------------------------------------------------------
2184 // FlushBlock()
2185 // ---------------------------------------------------------------------------
2186
FlushBlock(long nCacheBlock)2187 bool GeoRasterWrapper::FlushBlock( long nCacheBlock )
2188 {
2189 GByte* pabyFlushBuffer = (GByte *) pabyBlockBuf;
2190
2191 // --------------------------------------------------------------------
2192 // Pack bits ( inside pabyOutBuf )
2193 // --------------------------------------------------------------------
2194
2195 if( nCellSizeBits < 8 || nCurrentLevel == DEFAULT_BMP_MASK )
2196 {
2197 PackNBits( pabyFlushBuffer );
2198 }
2199
2200 // --------------------------------------------------------------------
2201 // Compress ( from pabyBlockBuf to pabyBlockBuf2 )
2202 // --------------------------------------------------------------------
2203
2204 if( ! EQUAL( sCompressionType.c_str(), "NONE" ) )
2205 {
2206 if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
2207 {
2208 nFlushBlockSize = CompressJpeg();
2209 }
2210 else if ( EQUAL( sCompressionType.c_str(), "DEFLATE" ) )
2211 {
2212 nFlushBlockSize = CompressDeflate();
2213 }
2214
2215 pabyFlushBuffer = pabyCompressBuf;
2216 }
2217
2218 // --------------------------------------------------------------------
2219 // Write BLOB
2220 // --------------------------------------------------------------------
2221
2222 CPLDebug( "Flush ", "Block = %4ld Size = %7ld", nCacheBlock,
2223 nFlushBlockSize );
2224
2225 if( ! poBlockStmt->WriteBlob( pahLocator[nCacheBlock],
2226 pabyFlushBuffer,
2227 nFlushBlockSize ) )
2228 {
2229 return false;
2230 }
2231
2232 bFlushBlock = false;
2233 bFlushMetadata = true;
2234 nFlushBlockSize = nBlockBytes;
2235
2236 return true;
2237 }
2238
2239 // ---------------------------------------------------------------------------
2240 // LoadNoDataValues()
2241 // ---------------------------------------------------------------------------
2242 static
AddToNoDataList(CPLXMLNode * phNode,int nNumber,CPLList * poList)2243 CPLList* AddToNoDataList( CPLXMLNode* phNode, int nNumber, CPLList* poList )
2244 {
2245 CPLXMLNode* psChild = phNode->psChild;
2246
2247 const char* pszMin = nullptr;
2248 const char* pszMax = nullptr;
2249
2250 for( ; psChild ; psChild = psChild->psNext )
2251 {
2252 if( EQUAL( psChild->pszValue, "value" ) )
2253 {
2254 pszMin = CPLGetXMLValue( psChild, nullptr, "NONE" );
2255 pszMax = pszMin;
2256 }
2257 else if ( EQUAL( psChild->pszValue, "range" ) )
2258 {
2259 pszMin = CPLGetXMLValue( psChild, "min", "NONE" );
2260 pszMax = CPLGetXMLValue( psChild, "max", "NONE" );
2261 }
2262 else
2263 {
2264 continue;
2265 }
2266
2267 hNoDataItem* poItem = (hNoDataItem*) CPLMalloc( sizeof( hNoDataItem ) );
2268
2269 poItem->nBand = nNumber;
2270 poItem->dfLower = CPLAtof( pszMin );
2271 poItem->dfUpper = CPLAtof( pszMax );
2272
2273 poList = CPLListAppend( poList, poItem );
2274 }
2275
2276 return poList;
2277 }
2278
LoadNoDataValues(void)2279 void GeoRasterWrapper::LoadNoDataValues( void )
2280 {
2281 if( psNoDataList )
2282 return;
2283
2284 CPLXMLNode* phLayerInfo = CPLGetXMLNode( phMetadata, "layerInfo" );
2285
2286 if( phLayerInfo == nullptr )
2287 {
2288 return;
2289 }
2290
2291 // -------------------------------------------------------------------
2292 // Load NoData from list of values and list of value ranges
2293 // -------------------------------------------------------------------
2294
2295 CPLXMLNode* phObjNoData = CPLGetXMLNode( phLayerInfo, "objectLayer.NODATA" );
2296
2297 for( ; phObjNoData ; phObjNoData = phObjNoData->psNext )
2298 {
2299 psNoDataList = AddToNoDataList( phObjNoData, 0, psNoDataList );
2300 }
2301
2302 CPLXMLNode* phSubLayer = CPLGetXMLNode( phLayerInfo, "subLayer" );
2303
2304 for( ; phSubLayer ; phSubLayer = phSubLayer->psNext )
2305 {
2306 int nNumber = atoi( CPLGetXMLValue( phSubLayer, "layerNumber", "-1") );
2307
2308 CPLXMLNode* phSubNoData = CPLGetXMLNode( phSubLayer, "NODATA" );
2309
2310 if( phSubNoData )
2311 {
2312 psNoDataList = AddToNoDataList( phSubNoData, nNumber, psNoDataList );
2313 }
2314 }
2315 }
2316
2317 // ---------------------------------------------------------------------------
2318 // GetSpatialReference()
2319 // ---------------------------------------------------------------------------
2320
GetSpatialReference()2321 void GeoRasterWrapper::GetSpatialReference()
2322 {
2323 int i;
2324
2325 CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata, "spatialReferenceInfo" );
2326
2327 if( phSRSInfo == nullptr )
2328 {
2329 return;
2330 }
2331
2332 const char* pszMCL = CPLGetXMLValue( phSRSInfo, "modelCoordinateLocation",
2333 "CENTER" );
2334
2335 if( EQUAL( pszMCL, "CENTER" ) )
2336 {
2337 eModelCoordLocation = MCL_CENTER;
2338 }
2339 else
2340 {
2341 eModelCoordLocation = MCL_UPPERLEFT;
2342 }
2343
2344 const char* pszModelType = CPLGetXMLValue( phSRSInfo, "modelType", "None" );
2345
2346 if( EQUAL( pszModelType, "FunctionalFitting" ) == false )
2347 {
2348 return;
2349 }
2350
2351 CPLXMLNode* phPolyModel = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
2352
2353 if ( phPolyModel == nullptr )
2354 {
2355 return;
2356 }
2357
2358 CPLXMLNode* phPolynomial = CPLGetXMLNode( phPolyModel, "pPolynomial" );
2359
2360 if ( phPolynomial == nullptr )
2361 {
2362 return;
2363 }
2364
2365 int nNumCoeff = atoi( CPLGetXMLValue( phPolynomial, "nCoefficients", "0" ));
2366
2367 if ( nNumCoeff != 3 )
2368 {
2369 return;
2370 }
2371
2372 const char* pszPolyCoeff = CPLGetXMLValue(phPolynomial,
2373 "polynomialCoefficients", "None");
2374
2375 if ( EQUAL( pszPolyCoeff, "None" ) )
2376 {
2377 return;
2378 }
2379
2380 char** papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ",
2381 CSLT_STRIPLEADSPACES );
2382
2383 if( CSLCount( papszCeoff ) < 3 )
2384 {
2385 CSLDestroy(papszCeoff);
2386 return;
2387 }
2388
2389 double adfPCoef[3];
2390
2391 for( i = 0; i < 3; i++ )
2392 {
2393 adfPCoef[i] = CPLAtof( papszCeoff[i] );
2394 }
2395 CSLDestroy(papszCeoff);
2396
2397 phPolynomial = CPLGetXMLNode( phPolyModel, "rPolynomial" );
2398
2399 if ( phPolynomial == nullptr )
2400 {
2401 return;
2402 }
2403
2404 pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
2405
2406 if ( EQUAL( pszPolyCoeff, "None" ) )
2407 {
2408 return;
2409 }
2410
2411 papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
2412
2413 if( CSLCount( papszCeoff ) < 3 )
2414 {
2415 CSLDestroy(papszCeoff);
2416 return;
2417 }
2418
2419 double adfRCoef[3];
2420
2421 for( i = 0; i < 3; i++ )
2422 {
2423 adfRCoef[i] = CPLAtof( papszCeoff[i] );
2424 }
2425 CSLDestroy(papszCeoff);
2426
2427 // -------------------------------------------------------------------
2428 // Inverse the transformation matrix
2429 // -------------------------------------------------------------------
2430
2431 double adfVal[6] = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
2432
2433 double dfDet = adfRCoef[1] * adfPCoef[2] - adfRCoef[2] * adfPCoef[1];
2434
2435 if( CPLIsEqual( dfDet, 0.0 ) )
2436 {
2437 dfDet = 0.0000000001; // to avoid divide by zero
2438 CPLError( CE_Warning, CPLE_AppDefined, "Determinant is ZERO!!!");
2439 }
2440
2441 adfVal[0] = adfPCoef[2] / dfDet;
2442 adfVal[1] = -adfRCoef[2] / dfDet;
2443 adfVal[2] = -(adfRCoef[0] * adfPCoef[2] - adfPCoef[0] * adfRCoef[2]) / dfDet;
2444 adfVal[3] = -adfPCoef[1] / dfDet;
2445 adfVal[4] = adfRCoef[1] / dfDet;
2446 adfVal[5] = (adfRCoef[0] * adfPCoef[1] - adfPCoef[0] * adfRCoef[1]) / dfDet;
2447
2448 // -------------------------------------------------------------------
2449 // Adjust Model Coordinate Location
2450 // -------------------------------------------------------------------
2451
2452 if ( eModelCoordLocation == MCL_CENTER )
2453 {
2454 adfVal[2] -= ( adfVal[0] / 2.0 );
2455 adfVal[5] -= ( adfVal[4] / 2.0 );
2456 }
2457
2458 dfXCoefficient[0] = adfVal[0];
2459 dfXCoefficient[1] = adfVal[1];
2460 dfXCoefficient[2] = adfVal[2];
2461 dfYCoefficient[0] = adfVal[3];
2462 dfYCoefficient[1] = adfVal[4];
2463 dfYCoefficient[2] = adfVal[5];
2464
2465 // -------------------------------------------------------------------
2466 // Apply ULTCoordinate
2467 // -------------------------------------------------------------------
2468
2469 dfXCoefficient[2] += ( anULTCoordinate[0] * dfXCoefficient[0] );
2470
2471 dfYCoefficient[2] += ( anULTCoordinate[1] * dfYCoefficient[1] );
2472 }
2473
2474 // ---------------------------------------------------------------------------
2475 // GetGCP()
2476 // ---------------------------------------------------------------------------
2477
GetGCP()2478 void GeoRasterWrapper::GetGCP()
2479 {
2480 CPLXMLNode* psGCP = CPLGetXMLNode( phMetadata,
2481 "spatialReferenceInfo.gcpGeoreferenceModel.gcp" );
2482
2483 CPLXMLNode* psFirst = psGCP;
2484
2485 if( nGCPCount > 0 && pasGCPList )
2486 {
2487 GDALDeinitGCPs( nGCPCount, pasGCPList );
2488 CPLFree( pasGCPList );
2489 }
2490
2491 pasGCPList = nullptr;
2492 nGCPCount = 0;
2493
2494 for( int i = 1 ; psGCP ; psGCP = psGCP->psNext, i++ )
2495 {
2496 if( ! EQUAL( CPLGetXMLValue( psGCP, "type", "" ), "ControlPoint" ) )
2497 {
2498 continue;
2499 }
2500 nGCPCount++;
2501 }
2502
2503 pasGCPList = static_cast<GDAL_GCP *>(
2504 CPLCalloc(sizeof(GDAL_GCP), nGCPCount) );
2505
2506 psGCP = psFirst;
2507
2508 for( int i = 0 ; psGCP ; psGCP = psGCP->psNext, i++ )
2509 {
2510 if( ! EQUAL( CPLGetXMLValue( psGCP, "type", "" ), "ControlPoint" ) )
2511 {
2512 continue;
2513 }
2514 pasGCPList[i].pszId = CPLStrdup( CPLGetXMLValue( psGCP, "ID", "" ) );
2515 pasGCPList[i].pszInfo = CPLStrdup( "" );
2516 pasGCPList[i].dfGCPLine = CPLAtof( CPLGetXMLValue( psGCP, "row", "0.0" ) );
2517 pasGCPList[i].dfGCPPixel = CPLAtof( CPLGetXMLValue( psGCP, "column", "0.0" ) );
2518 pasGCPList[i].dfGCPX = CPLAtof( CPLGetXMLValue( psGCP, "X", "0.0" ) );
2519 pasGCPList[i].dfGCPY = CPLAtof( CPLGetXMLValue( psGCP, "Y", "0.0" ) );
2520 pasGCPList[i].dfGCPZ = CPLAtof( CPLGetXMLValue( psGCP, "Z", "0.0" ));
2521 }
2522 }
2523
2524 // ---------------------------------------------------------------------------
2525 // SetGCP()
2526 // ---------------------------------------------------------------------------
2527
SetGCP(int nGCPCountIn,const GDAL_GCP * pasGCPListIn)2528 void GeoRasterWrapper::SetGCP( int nGCPCountIn, const GDAL_GCP *pasGCPListIn)
2529 {
2530 if( nGCPCount > 0 )
2531 {
2532 GDALDeinitGCPs( nGCPCount, pasGCPList );
2533 CPLFree( pasGCPList );
2534 }
2535
2536 nGCPCount = nGCPCountIn;
2537 pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPListIn);
2538 bFlushGCP = true;
2539 }
2540
FlushGCP()2541 void GeoRasterWrapper::FlushGCP()
2542 {
2543 const char* pszStatement = CPLSPrintf(
2544 "DECLARE\n"
2545 " gr sdo_georaster;\n"
2546 "BEGIN\n"
2547 " SELECT %s INTO gr FROM %s%s t WHERE %s FOR UPDATE;\n",
2548 sColumn.c_str(),
2549 sSchema.c_str(),
2550 sTable.c_str(),
2551 sWhere.c_str());
2552
2553 int nDimns = 2;
2554
2555 for( int iGCP = 0; iGCP < nGCPCount; ++iGCP )
2556 {
2557 if( pasGCPList[iGCP].dfGCPZ != 0.0 )
2558 {
2559 nDimns = 3;
2560 break;
2561 }
2562 }
2563
2564 if ( nDimns == 3 )
2565 {
2566 pszStatement = CPLSPrintf(
2567 "%s"
2568 " sdo_geor.setControlPoint(gr,\n"
2569 " SDO_GEOR_GCP(TO_CHAR(:1), '', 1,\n"
2570 " 2, sdo_number_array(:2, :3),\n"
2571 " 3, sdo_number_array(:4, :5, :6),\n"
2572 " NULL, NULL));\n",
2573 pszStatement);
2574 }
2575 else
2576 {
2577 pszStatement = CPLSPrintf(
2578 "%s"
2579 " sdo_geor.setControlPoint(gr,\n"
2580 " SDO_GEOR_GCP(TO_CHAR(:1), '', 1,\n"
2581 " 2, sdo_number_array(:2, :3),\n"
2582 " 2, sdo_number_array(:4, :5),\n"
2583 " NULL, NULL));\n",
2584 pszStatement);
2585 }
2586
2587 pszStatement = CPLSPrintf(
2588 "%s"
2589 " UPDATE %s%s t SET %s = gr WHERE %s;\n"
2590 "END;\n",
2591 pszStatement,
2592 sSchema.c_str(),
2593 sTable.c_str(),
2594 sColumn.c_str(),
2595 sWhere.c_str());
2596
2597 OWStatement* poStmt = poConnection->CreateStatement( pszStatement );
2598
2599 long lBindN = 0L;
2600 double dBindL = 0.0;
2601 double dBindP = 0.0;
2602 double dBindX = 0.0;
2603 double dBindY = 0.0;
2604 double dBindZ = 0.0;
2605
2606 poStmt->Bind( &lBindN );
2607 poStmt->Bind( &dBindL );
2608 poStmt->Bind( &dBindP );
2609 poStmt->Bind( &dBindX );
2610 poStmt->Bind( &dBindY );
2611
2612 if ( nDimns == 3 )
2613 {
2614 poStmt->Bind( &dBindZ );
2615 }
2616
2617 for( int iGCP = 0; iGCP < nGCPCount; ++iGCP )
2618 {
2619
2620 // Assign bound variables
2621
2622 lBindN = iGCP + 1;
2623 dBindL = pasGCPList[iGCP].dfGCPLine;
2624 dBindP = pasGCPList[iGCP].dfGCPPixel;
2625 dBindX = pasGCPList[iGCP].dfGCPX;
2626 dBindY = pasGCPList[iGCP].dfGCPY;
2627 dBindZ = nDimns == 3 ? pasGCPList[iGCP].dfGCPZ : 0.0;
2628
2629 // To avoid cppcheck false positive complaints about unreadVariable
2630 CPL_IGNORE_RET_VAL(lBindN);
2631 CPL_IGNORE_RET_VAL(dBindL);
2632 CPL_IGNORE_RET_VAL(dBindP);
2633 CPL_IGNORE_RET_VAL(dBindX);
2634 CPL_IGNORE_RET_VAL(dBindY);
2635 CPL_IGNORE_RET_VAL(dBindZ);
2636
2637 // Consume bound values
2638
2639 if( ! poStmt->Execute() )
2640 {
2641 CPLError( CE_Failure, CPLE_AppDefined, "Error loading GCP.");
2642 }
2643 }
2644
2645 delete poStmt;
2646 }
2647
2648 // ---------------------------------------------------------------------------
2649 // GetRPC()
2650 // ---------------------------------------------------------------------------
2651
2652 /* This is the order for storing 20 coefficients in GeoRaster Metadata */
2653
2654 constexpr int anOrder[] = {
2655 1, 2, 8, 12, 3, 5, 15, 9, 13, 16, 4, 6, 18, 7, 11, 19, 10, 14, 17, 20
2656 };
2657
GetRPC()2658 void GeoRasterWrapper::GetRPC()
2659 {
2660 int i;
2661
2662 CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata,
2663 "spatialReferenceInfo" );
2664
2665 if( phSRSInfo == nullptr )
2666 {
2667 return;
2668 }
2669
2670 CPLXMLNode* phPolyModel = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
2671
2672 if ( phPolyModel == nullptr )
2673 {
2674 return;
2675 }
2676
2677 // pPolynomial refers to LINE_NUM
2678
2679 CPLXMLNode* phPolynomial = CPLGetXMLNode( phPolyModel, "pPolynomial" );
2680
2681 if ( phPolynomial == nullptr )
2682 {
2683 return;
2684 }
2685
2686 int nNumCoeff = atoi( CPLGetXMLValue( phPolynomial, "nCoefficients", "0" ) );
2687
2688 if ( nNumCoeff != 20 )
2689 {
2690 return;
2691 }
2692
2693 const char* pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
2694
2695 if ( EQUAL( pszPolyCoeff, "None" ) )
2696 {
2697 return;
2698 }
2699
2700 char** papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
2701
2702 if( CSLCount( papszCeoff ) != 20 )
2703 {
2704 CSLDestroy(papszCeoff);
2705 return;
2706 }
2707
2708 phRPC = (GDALRPCInfoV2*) VSIMalloc( sizeof(GDALRPCInfoV2) );
2709
2710 phRPC->dfERR_BIAS = -1.0;
2711 phRPC->dfERR_RAND = -1.0;
2712 phRPC->dfLINE_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "rowOff", "0" ) );
2713 phRPC->dfSAMP_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "columnOff", "0" ) );
2714 phRPC->dfLONG_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "xOff", "0" ) );
2715 phRPC->dfLAT_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "yOff", "0" ) );
2716 phRPC->dfHEIGHT_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "zOff", "0" ) );
2717
2718 phRPC->dfLINE_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "rowScale", "0" ) );
2719 phRPC->dfSAMP_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "columnScale", "0" ) );
2720 phRPC->dfLONG_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "xScale", "0" ) );
2721 phRPC->dfLAT_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "yScale", "0" ) );
2722 phRPC->dfHEIGHT_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "zScale", "0" ) );
2723
2724 for( i = 0; i < 20; i++ )
2725 {
2726 phRPC->adfLINE_NUM_COEFF[anOrder[i] - 1] = CPLAtof( papszCeoff[i] );
2727 }
2728 CSLDestroy(papszCeoff);
2729
2730 // qPolynomial refers to LINE_DEN
2731
2732 phPolynomial = CPLGetXMLNode( phPolyModel, "qPolynomial" );
2733
2734 if ( phPolynomial == nullptr )
2735 {
2736 CPLFree( phRPC );
2737 phRPC = nullptr;
2738 return;
2739 }
2740
2741 pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
2742
2743 if ( EQUAL( pszPolyCoeff, "None" ) )
2744 {
2745 CPLFree( phRPC );
2746 phRPC = nullptr;
2747 return;
2748 }
2749
2750 papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
2751
2752 if( CSLCount( papszCeoff ) != 20 )
2753 {
2754 CPLFree( phRPC );
2755 phRPC = nullptr;
2756 CSLDestroy(papszCeoff);
2757 return;
2758 }
2759
2760 for( i = 0; i < 20; i++ )
2761 {
2762 phRPC->adfLINE_DEN_COEFF[anOrder[i] - 1] = CPLAtof( papszCeoff[i] );
2763 }
2764 CSLDestroy(papszCeoff);
2765
2766 // rPolynomial refers to SAMP_NUM
2767
2768 phPolynomial = CPLGetXMLNode( phPolyModel, "rPolynomial" );
2769
2770 if ( phPolynomial == nullptr )
2771 {
2772 CPLFree( phRPC );
2773 phRPC = nullptr;
2774 return;
2775 }
2776
2777 pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
2778
2779 if ( EQUAL( pszPolyCoeff, "None" ) )
2780 {
2781 CPLFree( phRPC );
2782 phRPC = nullptr;
2783 return;
2784 }
2785
2786 papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
2787
2788 if( CSLCount( papszCeoff ) != 20 )
2789 {
2790 CPLFree( phRPC );
2791 phRPC = nullptr;
2792 CSLDestroy(papszCeoff);
2793 return;
2794 }
2795
2796 for( i = 0; i < 20; i++ )
2797 {
2798 phRPC->adfSAMP_NUM_COEFF[anOrder[i] - 1] = CPLAtof( papszCeoff[i] );
2799 }
2800 CSLDestroy(papszCeoff);
2801
2802 // sPolynomial refers to SAMP_DEN
2803
2804 phPolynomial = CPLGetXMLNode( phPolyModel, "sPolynomial" );
2805
2806 if ( phPolynomial == nullptr )
2807 {
2808 CPLFree( phRPC );
2809 phRPC = nullptr;
2810 return;
2811 }
2812
2813 pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
2814
2815 if ( EQUAL( pszPolyCoeff, "None" ) )
2816 {
2817 CPLFree( phRPC );
2818 phRPC = nullptr;
2819 return;
2820 }
2821
2822 papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
2823
2824 if( CSLCount( papszCeoff ) != 20 )
2825 {
2826 CPLFree( phRPC );
2827 phRPC = nullptr;
2828 CSLDestroy(papszCeoff);
2829 return;
2830 }
2831
2832 for( i = 0; i < 20; i++ )
2833 {
2834 phRPC->adfSAMP_DEN_COEFF[anOrder[i] - 1] = CPLAtof( papszCeoff[i] );
2835 }
2836 CSLDestroy(papszCeoff);
2837 }
2838
2839 // ---------------------------------------------------------------------------
2840 // SetRPC()
2841 // ---------------------------------------------------------------------------
2842
SetRPC()2843 void GeoRasterWrapper::SetRPC()
2844 {
2845 // -------------------------------------------------------------------
2846 // Remove "layerInfo" tree
2847 // -------------------------------------------------------------------
2848
2849 CPLXMLNode* phLayerInfo = CPLGetXMLNode( phMetadata, "layerInfo" );
2850 CPLXMLNode* phClone = nullptr;
2851
2852 if( phLayerInfo )
2853 {
2854 phClone = CPLCloneXMLTree( phLayerInfo );
2855 CPLRemoveXMLChild( phMetadata, phLayerInfo );
2856 }
2857
2858 // -------------------------------------------------------------------
2859 // Start loading the RPC to "spatialReferenceInfo" tree
2860 // -------------------------------------------------------------------
2861
2862 int i = 0;
2863 CPLString osField, osMultiField;
2864 CPLXMLNode* phPolynomial = nullptr;
2865
2866 CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata,
2867 "spatialReferenceInfo" );
2868
2869 if( ! phSRSInfo )
2870 {
2871 phSRSInfo = CPLCreateXMLNode( phMetadata, CXT_Element,
2872 "spatialReferenceInfo" );
2873 }
2874 else
2875 {
2876 CPLXMLNode* phNode = CPLGetXMLNode( phSRSInfo, "isReferenced" );
2877 if( phNode )
2878 {
2879 CPLRemoveXMLChild( phSRSInfo, phNode );
2880 }
2881
2882 phNode = CPLGetXMLNode( phSRSInfo, "SRID" );
2883 if( phNode )
2884 {
2885 CPLRemoveXMLChild( phSRSInfo, phNode );
2886 }
2887
2888 phNode = CPLGetXMLNode( phSRSInfo, "modelCoordinateLocation" );
2889 if( phNode )
2890 {
2891 CPLRemoveXMLChild( phSRSInfo, phNode );
2892 }
2893
2894 phNode = CPLGetXMLNode( phSRSInfo, "modelType" );
2895 if( phNode )
2896 {
2897 CPLRemoveXMLChild( phSRSInfo, phNode );
2898 }
2899
2900 phNode = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
2901 if( phNode )
2902 {
2903 CPLRemoveXMLChild( phSRSInfo, phNode );
2904 }
2905 }
2906
2907 CPLCreateXMLElementAndValue( phSRSInfo, "isReferenced", "true" );
2908 CPLCreateXMLElementAndValue( phSRSInfo, "SRID", "4327" );
2909 CPLCreateXMLElementAndValue( phSRSInfo, "modelCoordinateLocation",
2910 "CENTER" );
2911 CPLCreateXMLElementAndValue( phSRSInfo, "modelType", "FunctionalFitting" );
2912 CPLSetXMLValue( phSRSInfo, "polynomialModel.#rowOff",
2913 CPLSPrintf( "%.15g", phRPC->dfLINE_OFF ) );
2914 CPLSetXMLValue( phSRSInfo, "polynomialModel.#columnOff",
2915 CPLSPrintf( "%.15g", phRPC->dfSAMP_OFF ) );
2916 CPLSetXMLValue( phSRSInfo, "polynomialModel.#xOff",
2917 CPLSPrintf( "%.15g", phRPC->dfLONG_OFF ) );
2918 CPLSetXMLValue( phSRSInfo, "polynomialModel.#yOff",
2919 CPLSPrintf( "%.15g", phRPC->dfLAT_OFF ) );
2920 CPLSetXMLValue( phSRSInfo, "polynomialModel.#zOff",
2921 CPLSPrintf( "%.15g", phRPC->dfHEIGHT_OFF ) );
2922 CPLSetXMLValue( phSRSInfo, "polynomialModel.#rowScale",
2923 CPLSPrintf( "%.15g", phRPC->dfLINE_SCALE ) );
2924 CPLSetXMLValue( phSRSInfo, "polynomialModel.#columnScale",
2925 CPLSPrintf( "%.15g", phRPC->dfSAMP_SCALE ) );
2926 CPLSetXMLValue( phSRSInfo, "polynomialModel.#xScale",
2927 CPLSPrintf( "%.15g", phRPC->dfLONG_SCALE ) );
2928 CPLSetXMLValue( phSRSInfo, "polynomialModel.#yScale",
2929 CPLSPrintf( "%.15g", phRPC->dfLAT_SCALE ) );
2930 CPLSetXMLValue( phSRSInfo, "polynomialModel.#zScale",
2931 CPLSPrintf( "%.15g", phRPC->dfHEIGHT_SCALE ) );
2932 CPLXMLNode* phPloyModel = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
2933
2934 // pPolynomial refers to LINE_NUM
2935
2936 CPLSetXMLValue( phPloyModel, "pPolynomial.#pType", "1" );
2937 CPLSetXMLValue( phPloyModel, "pPolynomial.#nVars", "3" );
2938 CPLSetXMLValue( phPloyModel, "pPolynomial.#order", "3" );
2939 CPLSetXMLValue( phPloyModel, "pPolynomial.#nCoefficients", "20" );
2940 for( i = 0; i < 20; i++ )
2941 {
2942 osField.Printf( "%.15g", phRPC->adfLINE_NUM_COEFF[anOrder[i] - 1] );
2943 if( i > 0 )
2944 osMultiField += " ";
2945 else
2946 osMultiField = "";
2947 osMultiField += osField;
2948 }
2949 phPolynomial = CPLGetXMLNode( phPloyModel, "pPolynomial" );
2950 CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
2951 osMultiField );
2952
2953 // qPolynomial refers to LINE_DEN
2954
2955 CPLSetXMLValue( phPloyModel, "qPolynomial.#pType", "1" );
2956 CPLSetXMLValue( phPloyModel, "qPolynomial.#nVars", "3" );
2957 CPLSetXMLValue( phPloyModel, "qPolynomial.#order", "3" );
2958 CPLSetXMLValue( phPloyModel, "qPolynomial.#nCoefficients", "20" );
2959 for( i = 0; i < 20; i++ )
2960 {
2961 osField.Printf( "%.15g", phRPC->adfLINE_DEN_COEFF[anOrder[i] - 1] );
2962 if( i > 0 )
2963 osMultiField += " ";
2964 else
2965 osMultiField = "";
2966 osMultiField += osField;
2967 }
2968 phPolynomial = CPLGetXMLNode( phPloyModel, "qPolynomial" );
2969 CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
2970 osMultiField );
2971
2972 // rPolynomial refers to SAMP_NUM
2973
2974 CPLSetXMLValue( phPloyModel, "rPolynomial.#pType", "1" );
2975 CPLSetXMLValue( phPloyModel, "rPolynomial.#nVars", "3" );
2976 CPLSetXMLValue( phPloyModel, "rPolynomial.#order", "3" );
2977 CPLSetXMLValue( phPloyModel, "rPolynomial.#nCoefficients", "20" );
2978 for( i = 0; i < 20; i++ )
2979 {
2980 osField.Printf( "%.15g", phRPC->adfSAMP_NUM_COEFF[anOrder[i] - 1] );
2981 if( i > 0 )
2982 osMultiField += " ";
2983 else
2984 osMultiField = "";
2985 osMultiField += osField;
2986 }
2987 phPolynomial = CPLGetXMLNode( phPloyModel, "rPolynomial" );
2988 CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
2989 osMultiField );
2990
2991 // sPolynomial refers to SAMP_DEN
2992
2993 CPLSetXMLValue( phPloyModel, "sPolynomial.#pType", "1" );
2994 CPLSetXMLValue( phPloyModel, "sPolynomial.#nVars", "3" );
2995 CPLSetXMLValue( phPloyModel, "sPolynomial.#order", "3" );
2996 CPLSetXMLValue( phPloyModel, "sPolynomial.#nCoefficients", "20" );
2997 for( i = 0; i < 20; i++ )
2998 {
2999 osField.Printf( "%.15g", phRPC->adfSAMP_DEN_COEFF[anOrder[i] - 1] );
3000 if( i > 0 )
3001 osMultiField += " ";
3002 else
3003 osMultiField = "";
3004 osMultiField += osField;
3005 }
3006 phPolynomial = CPLGetXMLNode( phPloyModel, "sPolynomial" );
3007 CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
3008 osMultiField );
3009
3010 // -------------------------------------------------------------------
3011 // Add "layerInfo" tree back
3012 // -------------------------------------------------------------------
3013
3014 if( phClone )
3015 {
3016 CPLAddXMLChild( phMetadata, phClone );
3017 }
3018 }
3019
3020 // ---------------------------------------------------------------------------
3021 // SetMaxLeve()
3022 // ---------------------------------------------------------------------------
3023
SetMaxLevel(int nLevels)3024 void GeoRasterWrapper::SetMaxLevel( int nLevels )
3025 {
3026 CPLXMLNode* psNode = CPLGetXMLNode( phMetadata, "rasterInfo.pyramid" );
3027
3028 if( psNode )
3029 {
3030 CPLSetXMLValue( psNode, "type", "DECREASE" );
3031 CPLSetXMLValue( psNode, "maxLevel", CPLSPrintf( "%d", nLevels ) );
3032 }
3033 }
3034
3035 // ---------------------------------------------------------------------------
3036 // GetNoData()
3037 // ---------------------------------------------------------------------------
3038
GetNoData(int nLayer,double * pdfNoDataValue)3039 bool GeoRasterWrapper::GetNoData( int nLayer, double* pdfNoDataValue )
3040 {
3041 if( psNoDataList == nullptr || CPLListCount( psNoDataList ) == 0 )
3042 {
3043 return false;
3044 }
3045
3046 // -------------------------------------------------------------------
3047 // Get only single value NoData, no list of values or value ranges
3048 // -------------------------------------------------------------------
3049
3050 int nCount = 0;
3051 double dfValue = 0.0;
3052
3053 CPLList* psList = nullptr;
3054
3055 // -------------------------------------------------------------------
3056 // Process Object Layer values
3057 // -------------------------------------------------------------------
3058
3059 for( psList = psNoDataList; psList ; psList = psList->psNext )
3060 {
3061 hNoDataItem* phItem = (hNoDataItem*) psList->pData;
3062
3063 if( phItem->nBand == 0 )
3064 {
3065 if( phItem->dfLower == phItem->dfUpper )
3066 {
3067 dfValue = phItem->dfLower;
3068 nCount++;
3069 }
3070 else
3071 {
3072 return false; // value range
3073 }
3074 }
3075 }
3076
3077 // -------------------------------------------------------------------
3078 // Values from the Object Layer override values from the layers
3079 // -------------------------------------------------------------------
3080
3081 if( nCount == 1 )
3082 {
3083 *pdfNoDataValue = dfValue;
3084 return true;
3085 }
3086
3087 // -------------------------------------------------------------------
3088 // Process SubLayer values
3089 // -------------------------------------------------------------------
3090
3091 for( psList = psNoDataList; psList ; psList = psList->psNext )
3092 {
3093 hNoDataItem* phItem = (hNoDataItem*) psList->pData;
3094
3095 if( phItem->nBand == nLayer )
3096 {
3097 if( phItem->dfLower == phItem->dfUpper )
3098 {
3099 dfValue = phItem->dfLower;
3100 nCount++;
3101 }
3102 else
3103 {
3104 return false; // value range
3105 }
3106 }
3107 }
3108
3109 if( nCount == 1 )
3110 {
3111 *pdfNoDataValue = dfValue;
3112 return true;
3113 }
3114
3115 return false;
3116 }
3117
3118 // ---------------------------------------------------------------------------
3119 // SetNoDataValue()
3120 // ---------------------------------------------------------------------------
3121
SetNoData(int nLayer,const char * pszValue)3122 bool GeoRasterWrapper::SetNoData( int nLayer, const char* pszValue )
3123 {
3124 // ------------------------------------------------------------
3125 // Set one NoData per dataset on "rasterInfo" section (10g)
3126 // ------------------------------------------------------------
3127
3128 if( poConnection->GetVersion() < 11 )
3129 {
3130 CPLXMLNode* psRInfo = CPLGetXMLNode( phMetadata, "rasterInfo" );
3131 CPLXMLNode* psNData = CPLSearchXMLNode( psRInfo, "NODATA" );
3132
3133 if( psNData == nullptr )
3134 {
3135 psNData = CPLCreateXMLNode( nullptr, CXT_Element, "NODATA" );
3136
3137 CPLXMLNode* psCDepth = CPLGetXMLNode( psRInfo, "cellDepth" );
3138
3139 CPLXMLNode* psPointer = psCDepth->psNext;
3140 psCDepth->psNext = psNData;
3141 psNData->psNext = psPointer;
3142 }
3143
3144 CPLSetXMLValue( psRInfo, "NODATA", pszValue );
3145 bFlushMetadata = true;
3146 return true;
3147 }
3148
3149 // ------------------------------------------------------------
3150 // Add NoData for all bands (layer=0) or for a specific band
3151 // ------------------------------------------------------------
3152
3153 char szRDT[OWCODE];
3154 char szNoData[OWTEXT];
3155
3156 snprintf( szRDT, sizeof(szRDT), "%s", sDataTable.c_str() );
3157 snprintf( szNoData, sizeof(szNoData), "%s", pszValue );
3158
3159 long long nRID = nRasterId;
3160
3161 // ------------------------------------------------------------
3162 // Write the in memory XML metadata to avoid losing other changes.
3163 // ------------------------------------------------------------
3164
3165 char* pszMetadata = CPLSerializeXMLTree( phMetadata );
3166
3167 if( pszMetadata == nullptr )
3168 {
3169 return false;
3170 }
3171
3172 OCILobLocator* phLocatorR = nullptr;
3173 OCILobLocator* phLocatorW = nullptr;
3174
3175 OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
3176 "DECLARE\n"
3177 " GR1 sdo_georaster;\n"
3178 "BEGIN\n"
3179 " SELECT %s INTO GR1 FROM %s%s T WHERE %s FOR UPDATE;\n"
3180 "\n"
3181 " GR1.metadata := sys.xmltype.createxml(:1);\n"
3182 "\n"
3183 " SDO_GEOR.addNODATA( GR1, :2, :3 );\n"
3184 "\n"
3185 " UPDATE %s%s T SET %s = GR1 WHERE %s;\n"
3186 "\n"
3187 " EXECUTE IMMEDIATE\n"
3188 " 'SELECT T.%s.METADATA.getClobVal() FROM %s%s T \n"
3189 " WHERE T.%s.RASTERDATATABLE = UPPER(:1)\n"
3190 " AND T.%s.RASTERID = :2'\n"
3191 " INTO :metadata USING :rdt, :rid;\n"
3192 "END;",
3193 sColumn.c_str(), sSchema.c_str(), sTable.c_str(), sWhere.c_str(),
3194 sSchema.c_str(), sTable.c_str(), sColumn.c_str(), sWhere.c_str(),
3195 sColumn.c_str(), sSchema.c_str(), sTable.c_str(),
3196 sColumn.c_str(),
3197 sColumn.c_str() ) );
3198
3199 poStmt->WriteCLob( &phLocatorW, pszMetadata );
3200
3201 poStmt->Bind( &phLocatorW );
3202 poStmt->Bind( &nLayer );
3203 poStmt->Bind( szNoData );
3204 poStmt->BindName( ":metadata", &phLocatorR );
3205 poStmt->BindName( ":rdt", szRDT );
3206 poStmt->BindName( ":rid", &nRID );
3207
3208 CPLFree( pszMetadata );
3209
3210 if( ! poStmt->Execute() )
3211 {
3212 poStmt->FreeLob(phLocatorR);
3213 poStmt->FreeLob(phLocatorW);
3214 delete poStmt;
3215 return false;
3216 }
3217
3218 poStmt->FreeLob(phLocatorW);
3219
3220 // ------------------------------------------------------------
3221 // Read the XML metadata from db to memory with nodata updates
3222 // ------------------------------------------------------------
3223
3224 char* pszXML = poStmt->ReadCLob( phLocatorR );
3225
3226 if( pszXML )
3227 {
3228 CPLDestroyXMLNode( phMetadata );
3229 phMetadata = CPLParseXMLString( pszXML );
3230 CPLFree( pszXML );
3231 }
3232
3233 poStmt->FreeLob(phLocatorR);
3234
3235 bFlushMetadata = true;
3236 delete poStmt;
3237 return false;
3238 }
3239
3240 // ---------------------------------------------------------------------------
3241 // SetVAT()
3242 // ---------------------------------------------------------------------------
3243
SetVAT(int nBand,const char * pszName)3244 bool GeoRasterWrapper::SetVAT( int nBand, const char* pszName )
3245 {
3246 InitializeLayersNode();
3247
3248 bFlushMetadata = true;
3249
3250 int n = 1;
3251
3252 CPLXMLNode* psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
3253
3254 for( ; psLayers; psLayers = psLayers->psNext, n++ )
3255 {
3256 if( n != nBand )
3257 {
3258 continue;
3259 }
3260
3261 CPLXMLNode* psVAT = CPLGetXMLNode( psLayers, "vatTableName" );
3262
3263 if( psVAT != nullptr )
3264 {
3265 CPLRemoveXMLChild( psLayers, psVAT );
3266 CPLDestroyXMLNode( psVAT );
3267 }
3268
3269 CPLCreateXMLElementAndValue(psLayers, "vatTableName", pszName );
3270
3271 // ------------------------------------------------------------
3272 // To be updated at Flush Metadata in SDO_GEOR.setVAT()
3273 // ------------------------------------------------------------
3274
3275 sValueAttributeTab = pszName;
3276
3277 return true;
3278 }
3279
3280 return false;
3281 }
3282
3283 // ---------------------------------------------------------------------------
3284 // GetVAT()
3285 // ---------------------------------------------------------------------------
3286
GetVAT(int nBand)3287 char* GeoRasterWrapper::GetVAT( int nBand )
3288 {
3289 CPLXMLNode* psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
3290
3291 if( psLayers == nullptr )
3292 {
3293 return nullptr;
3294 }
3295
3296 char* pszTablename = nullptr;
3297
3298 int n = 1;
3299
3300 for( ; psLayers; psLayers = psLayers->psNext, n++ )
3301 {
3302 if( n != nBand )
3303 {
3304 continue;
3305 }
3306
3307 CPLXMLNode* psVAT = CPLGetXMLNode( psLayers, "vatTableName" );
3308
3309 if( psVAT != nullptr )
3310 {
3311 pszTablename = CPLStrdup(
3312 CPLGetXMLValue( psLayers, "vatTableName", "" ) );
3313 }
3314
3315 break;
3316 }
3317
3318 return pszTablename;
3319 }
3320
3321 // ---------------------------------------------------------------------------
3322 // FlushMetadata()
3323 // ---------------------------------------------------------------------------
3324
FlushMetadata()3325 bool GeoRasterWrapper::FlushMetadata()
3326 {
3327 if( bFlushBlock )
3328 {
3329 FlushBlock( nCacheBlockId );
3330 }
3331
3332 if( ! bFlushMetadata )
3333 {
3334 return true;
3335 }
3336
3337 bFlushMetadata = false;
3338
3339 // --------------------------------------------------------------------
3340 // Change the isBlank setting left by SDO_GEOR.createBlank() to 'false'
3341 // --------------------------------------------------------------------
3342
3343 CPLXMLNode* psOInfo = CPLGetXMLNode( phMetadata, "objectInfo" );
3344
3345 CPLSetXMLValue( psOInfo, "isBlank", "false" );
3346
3347 CPLXMLNode* psNode = CPLGetXMLNode( psOInfo, "blankCellValue" );
3348
3349 if( psNode != nullptr )
3350 {
3351 CPLRemoveXMLChild( psOInfo, psNode );
3352 CPLDestroyXMLNode( psNode );
3353 }
3354
3355 const char* pszRed = "1";
3356 const char* pszGreen = "1";
3357 const char* pszBlue = "1";
3358
3359 if( ( nRasterBands > 2 ) &&
3360 ( ! HasColorMap( 1 ) ) &&
3361 ( ! HasColorMap( 2 ) ) &&
3362 ( ! HasColorMap( 3 ) ) )
3363 {
3364 pszRed = "1";
3365 pszGreen = "2";
3366 pszBlue = "3";
3367 }
3368
3369 psNode = CPLGetXMLNode( psOInfo, "defaultRed" );
3370 if( psNode )
3371 {
3372 CPLRemoveXMLChild( psOInfo, psNode );
3373 CPLDestroyXMLNode( psNode );
3374 }
3375 CPLCreateXMLElementAndValue( psOInfo, "defaultRed", pszRed );
3376
3377 psNode = CPLGetXMLNode( psOInfo, "defaultGreen" );
3378 if( psNode )
3379 {
3380 CPLRemoveXMLChild( psOInfo, psNode );
3381 CPLDestroyXMLNode( psNode );
3382 }
3383 CPLCreateXMLElementAndValue( psOInfo, "defaultGreen", pszGreen );
3384
3385 psNode = CPLGetXMLNode( psOInfo, "defaultBlue" );
3386 if( psNode )
3387 {
3388 CPLRemoveXMLChild( psOInfo, psNode );
3389 CPLDestroyXMLNode( psNode );
3390 }
3391 CPLCreateXMLElementAndValue( psOInfo, "defaultBlue", pszBlue );
3392
3393 // --------------------------------------------------------------------
3394 // Set compression
3395 // --------------------------------------------------------------------
3396
3397 psNode = CPLGetXMLNode( phMetadata, "rasterInfo.compression" );
3398
3399 if( psNode )
3400 {
3401 CPLSetXMLValue( psNode, "type", sCompressionType.c_str() );
3402
3403 if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
3404 {
3405 CPLSetXMLValue( psNode, "quality",
3406 CPLSPrintf( "%d", nCompressQuality ) );
3407 }
3408 }
3409
3410 // --------------------------------------------------------------------
3411 // Update BitmapMask info
3412 // --------------------------------------------------------------------
3413
3414 if( bHasBitmapMask )
3415 {
3416 CPLXMLNode* psLayers = CPLGetXMLNode( phMetadata, "layerInfo" );
3417
3418 if( psLayers )
3419 {
3420 CPLCreateXMLElementAndValue( psLayers, "bitmapMask", "true" );
3421 }
3422 }
3423
3424 // --------------------------------------------------------------------
3425 // Update the Metadata directly from the XML text
3426 // --------------------------------------------------------------------
3427
3428 double dfXCoef[3];
3429 double dfYCoef[3];
3430 int nMLC;
3431
3432 dfXCoef[0] = dfXCoefficient[0];
3433 dfXCoef[1] = dfXCoefficient[1];
3434 dfXCoef[2] = dfXCoefficient[2];
3435
3436 dfYCoef[0] = dfYCoefficient[0];
3437 dfYCoef[1] = dfYCoefficient[1];
3438 dfYCoef[2] = dfYCoefficient[2];
3439
3440 if ( eModelCoordLocation == MCL_CENTER )
3441 {
3442 dfXCoef[2] += ( dfXCoefficient[0] / 2.0 );
3443 dfYCoef[2] += ( dfYCoefficient[1] / 2.0 );
3444 nMLC = MCL_CENTER;
3445 }
3446 else
3447 {
3448 nMLC = MCL_UPPERLEFT;
3449 }
3450
3451 if( phRPC )
3452 {
3453 SetRPC();
3454 nSRID = NO_CRS;
3455 }
3456
3457 // --------------------------------------------------------------------
3458 // Serialize XML metadata to plain text
3459 // --------------------------------------------------------------------
3460
3461 char* pszMetadata = CPLSerializeXMLTree( phMetadata );
3462
3463 if( pszMetadata == nullptr )
3464 {
3465 return false;
3466 }
3467
3468 // --------------------------------------------------------------------
3469 // Search for existing Spatial Index SRID
3470 // --------------------------------------------------------------------
3471
3472 OWStatement* poStmt = (OWStatement*) nullptr;
3473
3474 if ( nSRID != UNKNOWN_CRS && bGenSpatialExtent )
3475 {
3476 long long nIdxSRID = -1;
3477
3478 poStmt = poConnection->CreateStatement( CPLSPrintf(
3479 "DECLARE\n"
3480 " IDX_SRID NUMBER;\n"
3481 "BEGIN\n"
3482 " BEGIN\n"
3483 " EXECUTE IMMEDIATE \n"
3484 " 'SELECT SRID FROM ALL_SDO_GEOM_METADATA ' || \n"
3485 " 'WHERE OWNER = ''%s'' AND ' || \n"
3486 " 'TABLE_NAME = ''%s'' AND ' || \n"
3487 " 'COLUMN_NAME = ''%s'' || ''.SPATIALEXTENT'' '\n"
3488 " INTO IDX_SRID;\n"
3489 " EXCEPTION\n"
3490 " WHEN NO_DATA_FOUND THEN\n"
3491 " IDX_SRID := -1;\n"
3492 " END;\n"
3493 " :idx_srid := IDX_SRID;\n"
3494 "END;",
3495 sOwner.c_str(),
3496 sTable.c_str(),
3497 sColumn.c_str()));
3498
3499 poStmt->BindName( ":idx_srid", &nIdxSRID );
3500
3501 if( ! poStmt->Execute() )
3502 {
3503 nIdxSRID = -1;
3504 }
3505
3506 if ( nIdxSRID != -1 )
3507 {
3508 if ( nExtentSRID == 0 )
3509 {
3510 nExtentSRID = nIdxSRID;
3511 }
3512 else
3513 {
3514 if ( nExtentSRID != nIdxSRID )
3515 {
3516 CPLError( CE_Warning, CPLE_AppDefined,
3517 "Cannot generate spatialExtent, "
3518 "Spatial Index SRID is (%lld)",
3519 nIdxSRID );
3520
3521 nExtentSRID = 0;
3522 }
3523 }
3524 }
3525 else
3526 {
3527 if (nExtentSRID == 0)
3528 nExtentSRID = nSRID;
3529 }
3530
3531 delete poStmt;
3532
3533 CPLDebug("GEOR","nIdxSRID = %lld",nIdxSRID);
3534 }
3535 else
3536 {
3537 nExtentSRID = 0;
3538 }
3539
3540 if ( nSRID == 0 || nSRID == UNKNOWN_CRS )
3541 {
3542 nExtentSRID = 0;
3543 }
3544
3545 CPLDebug("GEOR","nExtentSRID = %lld",nExtentSRID);
3546 CPLDebug("GEOR","nSRID = %lld",nSRID);
3547
3548 // --------------------------------------------------------------------
3549 // Update GeoRaster Metadata
3550 // --------------------------------------------------------------------
3551
3552 int nException = 0;
3553
3554 OCILobLocator* phLocator = nullptr;
3555
3556 poStmt = poConnection->CreateStatement( CPLSPrintf(
3557 "DECLARE\n"
3558 " GR1 sdo_georaster;\n"
3559 " GM1 sdo_geometry;\n"
3560 " SRID number := :1;\n"
3561 " EXT_SRID number := :2;\n"
3562 " VAT varchar2(128);\n"
3563 "BEGIN\n"
3564 "\n"
3565 " SELECT %s INTO GR1 FROM %s%s T WHERE %s FOR UPDATE;\n"
3566 "\n"
3567 " GR1.metadata := sys.xmltype.createxml(:3);\n"
3568 "\n"
3569 " IF SRID != 0 THEN\n"
3570 " SDO_GEOR.georeference( GR1, SRID, :4, \n"
3571 " SDO_NUMBER_ARRAY(:5, :6, :7), SDO_NUMBER_ARRAY(:8, :9, :10));\n"
3572 " END IF;\n"
3573 "\n"
3574 " IF EXT_SRID = 0 THEN\n"
3575 " GM1 := NULL;\n"
3576 " ELSE\n"
3577 " GM1 := SDO_GEOR.generateSpatialExtent( GR1 );\n"
3578 " IF EXT_SRID != SRID THEN\n"
3579 " GM1 := SDO_CS.transform( GM1, EXT_SRID );\n"
3580 " END IF;\n"
3581 " END IF;\n"
3582 "\n"
3583 " GR1.spatialExtent := GM1;\n"
3584 "\n"
3585 " VAT := '%s';\n"
3586 " IF VAT != '' THEN\n"
3587 " SDO_GEOR.setVAT(GR1, 1, VAT);\n"
3588 " END IF;\n"
3589 "\n"
3590 " BEGIN\n"
3591 " UPDATE %s%s T SET %s = GR1\n"
3592 " WHERE %s;\n"
3593 " EXCEPTION\n"
3594 " WHEN OTHERS THEN\n"
3595 " :except := SQLCODE;\n"
3596 " END;\n"
3597 "\n"
3598 " COMMIT;\n"
3599 "END;",
3600 sColumn.c_str(),
3601 sSchema.c_str(),
3602 sTable.c_str(),
3603 sWhere.c_str(),
3604 sValueAttributeTab.c_str(),
3605 sSchema.c_str(),
3606 sTable.c_str(),
3607 sColumn.c_str(),
3608 sWhere.c_str() ) );
3609
3610 poStmt->WriteCLob( &phLocator, pszMetadata );
3611
3612 poStmt->Bind( &nSRID );
3613 poStmt->Bind( &nExtentSRID );
3614 poStmt->Bind( &phLocator );
3615 poStmt->Bind( &nMLC );
3616 poStmt->Bind( &dfXCoef[0] );
3617 poStmt->Bind( &dfXCoef[1] );
3618 poStmt->Bind( &dfXCoef[2] );
3619 poStmt->Bind( &dfYCoef[0] );
3620 poStmt->Bind( &dfYCoef[1] );
3621 poStmt->Bind( &dfYCoef[2] );
3622 poStmt->BindName( ":except", &nException );
3623
3624 CPLFree( pszMetadata );
3625
3626 if( ! poStmt->Execute() )
3627 {
3628 poStmt->FreeLob(phLocator);
3629 delete poStmt;
3630 return false;
3631 }
3632
3633 poStmt->FreeLob(phLocator);
3634
3635 delete poStmt;
3636
3637 if( nException )
3638 {
3639 CPLError( CE_Warning, CPLE_AppDefined,
3640 "Fail to update GeoRaster Metadata (ORA-%d) ", nException );
3641 }
3642
3643 if (bGenPyramid)
3644 {
3645 if (GeneratePyramid( nPyramidLevels, sPyramidResampling.c_str(), true ))
3646 {
3647 CPLDebug("GEOR", "Generated pyramid successfully.");
3648 }
3649 else
3650 {
3651 CPLError( CE_Warning, CPLE_AppDefined, "Error generating pyramid!");
3652 }
3653 }
3654
3655 return true;
3656 }
3657
3658 // ---------------------------------------------------------------------------
3659 // GeneratePyramid()
3660 // ---------------------------------------------------------------------------
3661
GeneratePyramid(int nLevels,const char * pszResampling,bool bInternal)3662 bool GeoRasterWrapper::GeneratePyramid( int nLevels,
3663 const char* pszResampling,
3664 bool bInternal )
3665 {
3666 nPyramidMaxLevel = nLevels;
3667
3668 if( bInternal )
3669 {
3670 CPLString sLevels = "";
3671
3672 if (nLevels > 0)
3673 {
3674 sLevels = CPLSPrintf("rlevel=%d", nLevels);
3675 }
3676
3677 OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
3678 "DECLARE\n"
3679 " gr sdo_georaster;\n"
3680 "BEGIN\n"
3681 " SELECT %s INTO gr FROM %s t WHERE %s FOR UPDATE;\n"
3682 " sdo_geor.generatePyramid(gr, '%s resampling=%s');\n"
3683 " UPDATE %s t SET %s = gr WHERE %s;\n"
3684 " COMMIT;\n"
3685 "END;\n",
3686 sColumn.c_str(),
3687 sTable.c_str(),
3688 sWhere.c_str(),
3689 sLevels.c_str(),
3690 pszResampling,
3691 sTable.c_str(),
3692 sColumn.c_str(),
3693 sWhere.c_str() ) );
3694
3695 if( poStmt->Execute() )
3696 {
3697 delete poStmt;
3698 return true;
3699 }
3700
3701 delete poStmt;
3702 return false;
3703 }
3704
3705 // -----------------------------------------------------------
3706 // Create rows for pyramid levels
3707 // -----------------------------------------------------------
3708
3709 OWStatement* poStmt = poConnection->CreateStatement(
3710 "DECLARE\n"
3711 " SCL NUMBER := 0;\n"
3712 " RC NUMBER := 0;\n"
3713 " RR NUMBER := 0;\n"
3714 " CBS2 NUMBER := 0;\n"
3715 " RBS2 NUMBER := 0;\n"
3716 " TBB NUMBER := 0;\n"
3717 " TRB NUMBER := 0;\n"
3718 " TCB NUMBER := 0;\n"
3719 " X NUMBER := 0;\n"
3720 " Y NUMBER := 0;\n"
3721 " W NUMBER := 0;\n"
3722 " H NUMBER := 0;\n"
3723 " STM VARCHAR2(1024) := '';\n"
3724 "BEGIN\n"
3725 " EXECUTE IMMEDIATE 'DELETE FROM '||:rdt||' \n"
3726 " WHERE RASTERID = '||:rid||' AND PYRAMIDLEVEL > 0';\n"
3727 " STM := 'INSERT INTO '||:rdt||' VALUES (:1, :2, :3-1, :4-1, :5-1 ,\n"
3728 " SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 3),\n"
3729 " SDO_ORDINATE_ARRAY(:6, :7, :8-1, :9-1)), EMPTY_BLOB() )';\n"
3730 " TBB := :TotalBandBlocks;\n"
3731 " RBS2 := floor(:RowBlockSize / 2);\n"
3732 " CBS2 := floor(:ColumnBlockSize / 2);\n"
3733 " FOR l IN 1..:level LOOP\n"
3734 " SCL := 2 ** l;\n"
3735 " RR := floor(:RasterRows / SCL);\n"
3736 " RC := floor(:RasterColumns / SCL);\n"
3737 " IF (RC <= CBS2) OR (RR <= RBS2) THEN\n"
3738 " H := RR;\n"
3739 " W := RC;\n"
3740 " ELSE\n"
3741 " H := :RowBlockSize;\n"
3742 " W := :ColumnBlockSize;\n"
3743 " END IF;\n"
3744 " TRB := greatest(1, ceil( ceil(:RasterColumns / :ColumnBlockSize) / SCL));\n"
3745 " TCB := greatest(1, ceil( ceil(:RasterRows / :RowBlockSize) / SCL));\n"
3746 " FOR b IN 1..TBB LOOP\n"
3747 " Y := 0;\n"
3748 " FOR r IN 1..TCB LOOP\n"
3749 " X := 0;\n"
3750 " FOR c IN 1..TRB LOOP\n"
3751 " EXECUTE IMMEDIATE STM USING :rid, l, b, r, c, Y, X, (Y+H), (X+W);\n"
3752 " X := X + W;\n"
3753 " END LOOP;\n"
3754 " Y := Y + H;\n"
3755 " END LOOP;\n"
3756 " END LOOP;\n"
3757 " END LOOP;\n"
3758 " COMMIT;\n"
3759 "END;" );
3760
3761 const char* pszDataTable = sDataTable.c_str();
3762
3763 poStmt->BindName( ":rdt", (char*) pszDataTable );
3764 poStmt->BindName( ":rid", &nRasterId );
3765 poStmt->BindName( ":level", &nLevels );
3766 poStmt->BindName( ":TotalBandBlocks", &nTotalBandBlocks );
3767 poStmt->BindName( ":RowBlockSize", &nRowBlockSize );
3768 poStmt->BindName( ":ColumnBlockSize", &nColumnBlockSize );
3769 poStmt->BindName( ":RasterRows", &nRasterRows );
3770 poStmt->BindName( ":RasterColumns", &nRasterColumns );
3771
3772 if( ! poStmt->Execute() )
3773 {
3774 delete poStmt;
3775 return false;
3776 }
3777 delete poStmt;
3778
3779 CPLXMLNode* psNode = CPLGetXMLNode( phMetadata, "rasterInfo.pyramid" );
3780
3781 if( psNode )
3782 {
3783 CPLSetXMLValue( psNode, "type", "DECREASE" );
3784 CPLSetXMLValue( psNode, "resampling", pszResampling );
3785 CPLSetXMLValue( psNode, "maxLevel", CPLSPrintf( "%d", nLevels ) );
3786 }
3787
3788 bFlushMetadata = true;
3789
3790 return true;
3791 }
3792
3793 // ---------------------------------------------------------------------------
3794 // GeneratePyramid()
3795 // ---------------------------------------------------------------------------
3796
DeletePyramid()3797 void GeoRasterWrapper::DeletePyramid()
3798 {
3799 OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
3800 "DECLARE\n"
3801 " gr sdo_georaster;\n"
3802 "BEGIN\n"
3803 " SELECT %s INTO gr FROM %s t WHERE %s FOR UPDATE;\n"
3804 " sdo_geor.deletePyramid(gr);\n"
3805 " UPDATE %s t SET %s = gr WHERE %s;\n"
3806 " COMMIT;\n"
3807 "END;\n",
3808 sColumn.c_str(),
3809 sTable.c_str(),
3810 sWhere.c_str(),
3811 sTable.c_str(),
3812 sColumn.c_str(),
3813 sWhere.c_str() ) );
3814
3815 CPL_IGNORE_RET_VAL(poStmt->Execute());
3816
3817 delete poStmt;
3818 }
3819
3820 // ---------------------------------------------------------------------------
3821 // CreateBitmapMask()
3822 // ---------------------------------------------------------------------------
3823
InitializeMask(int nLevel,int nBlockColumns,int nBlockRows,int nColumnBlocks,int nRowBlocks,int nBandBlocks)3824 bool GeoRasterWrapper::InitializeMask( int nLevel,
3825 int nBlockColumns,
3826 int nBlockRows,
3827 int nColumnBlocks,
3828 int nRowBlocks,
3829 int nBandBlocks )
3830 {
3831 // -----------------------------------------------------------
3832 // Create rows for the bitmap mask
3833 // -----------------------------------------------------------
3834
3835 OWStatement* poStmt = poConnection->CreateStatement(
3836 "DECLARE\n"
3837 " W NUMBER := :1;\n"
3838 " H NUMBER := :2;\n"
3839 " BB NUMBER := :3;\n"
3840 " RB NUMBER := :4;\n"
3841 " CB NUMBER := :5;\n"
3842 " X NUMBER := 0;\n"
3843 " Y NUMBER := 0;\n"
3844 " STM VARCHAR2(1024) := '';\n"
3845 "BEGIN\n"
3846 "\n"
3847 " EXECUTE IMMEDIATE 'DELETE FROM '||:rdt||' \n"
3848 " WHERE RASTERID = '||:rid||' AND PYRAMIDLEVEL = '||:lev||' ';\n"
3849 "\n"
3850 " STM := 'INSERT INTO '||:rdt||' VALUES (:1, :lev, :2-1, :3-1, :4-1 ,\n"
3851 " SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 3),\n"
3852 " SDO_ORDINATE_ARRAY(:5, :6, :7-1, :8-1)), EMPTY_BLOB() )';\n"
3853 "\n"
3854 " FOR b IN 1..BB LOOP\n"
3855 " Y := 0;\n"
3856 " FOR r IN 1..RB LOOP\n"
3857 " X := 0;\n"
3858 " FOR c IN 1..CB LOOP\n"
3859 " EXECUTE IMMEDIATE STM USING :rid, b, r, c, Y, X, (Y+H), (X+W);\n"
3860 " X := X + W;\n"
3861 " END LOOP;\n"
3862 " Y := Y + H;\n"
3863 " END LOOP;\n"
3864 " END LOOP;\n"
3865 "END;" );
3866
3867 char pszDataTable[OWNAME];
3868
3869 poStmt->Bind( &nBlockColumns );
3870 poStmt->Bind( &nBlockRows );
3871 poStmt->Bind( &nBandBlocks );
3872 poStmt->Bind( &nRowBlocks );
3873 poStmt->Bind( &nColumnBlocks );
3874 poStmt->BindName( ":rdt", pszDataTable );
3875 poStmt->BindName( ":rid", &nRasterId );
3876 poStmt->BindName( ":lev", &nLevel );
3877
3878 if( ! poStmt->Execute() )
3879 {
3880 delete poStmt;
3881 return false;
3882 }
3883
3884 delete poStmt;
3885 return true;
3886 }
3887
3888 // ---------------------------------------------------------------------------
3889 // UnpackNBits()
3890 // ---------------------------------------------------------------------------
3891
UnpackNBits(GByte * pabyData)3892 void GeoRasterWrapper::UnpackNBits( GByte* pabyData )
3893 {
3894 int nPixCount = nColumnBlockSize * nRowBlockSize * nBandBlockSize;
3895
3896 if( EQUAL( sCellDepth.c_str(), "4BIT" ) )
3897 {
3898 for( int ii = nPixCount - 2; ii >= 0; ii -= 2 )
3899 {
3900 int k = ii >> 1;
3901 pabyData[ii+1] = (pabyData[k] ) & 0xf;
3902 pabyData[ii] = (pabyData[k] >> 4) & 0xf;
3903 }
3904 }
3905 else if( EQUAL( sCellDepth.c_str(), "2BIT" ) )
3906 {
3907 for( int ii = nPixCount - 4; ii >= 0; ii -= 4 )
3908 {
3909 int k = ii >> 2;
3910 pabyData[ii+3] = (pabyData[k] ) & 0x3;
3911 pabyData[ii+2] = (pabyData[k] >> 2) & 0x3;
3912 pabyData[ii+1] = (pabyData[k] >> 4) & 0x3;
3913 pabyData[ii] = (pabyData[k] >> 6) & 0x3;
3914 }
3915 }
3916 else
3917 {
3918 for( int ii = nPixCount - 1; ii >= 0; ii-- )
3919 {
3920 if( ( pabyData[ii>>3] & ( 128 >> (ii & 0x7) ) ) )
3921 pabyData[ii] = 1;
3922 else
3923 pabyData[ii] = 0;
3924 }
3925 }
3926 }
3927
3928 // ---------------------------------------------------------------------------
3929 // PackNBits()
3930 // ---------------------------------------------------------------------------
3931
PackNBits(GByte * pabyData) const3932 void GeoRasterWrapper::PackNBits( GByte* pabyData ) const
3933 {
3934 int nPixCount = nBandBlockSize * nRowBlockSize * nColumnBlockSize;
3935
3936 GByte* pabyBuffer = (GByte*) VSI_MALLOC_VERBOSE( nPixCount );
3937
3938 if( pabyBuffer == nullptr )
3939 {
3940 return;
3941 }
3942
3943 if( nCellSizeBits == 4 )
3944 {
3945 for( int ii = 0; ii < nPixCount - 1; ii += 2 )
3946 {
3947 int k = ii >> 1;
3948 pabyBuffer[k] =
3949 ((((GByte *) pabyData)[ii+1] & 0xf) )
3950 | ((((GByte *) pabyData)[ii] & 0xf) << 4);
3951 }
3952 }
3953 else if( nCellSizeBits == 2 )
3954 {
3955 for( int ii = 0; ii < nPixCount - 3; ii += 4 )
3956 {
3957 int k = ii >> 2;
3958 pabyBuffer[k] =
3959 ((((GByte *) pabyData)[ii+3] & 0x3) )
3960 | ((((GByte *) pabyData)[ii+2] & 0x3) << 2)
3961 | ((((GByte *) pabyData)[ii+1] & 0x3) << 4)
3962 | ((((GByte *) pabyData)[ii] & 0x3) << 6);
3963 }
3964 }
3965 else
3966 {
3967 for( int ii = 0; ii < nPixCount - 7; ii += 8 )
3968 {
3969 int k = ii >> 3;
3970 pabyBuffer[k] =
3971 ((((GByte *) pabyData)[ii+7] & 0x1) )
3972 | ((((GByte *) pabyData)[ii+6] & 0x1) << 1)
3973 | ((((GByte *) pabyData)[ii+5] & 0x1) << 2)
3974 | ((((GByte *) pabyData)[ii+4] & 0x1) << 3)
3975 | ((((GByte *) pabyData)[ii+3] & 0x1) << 4)
3976 | ((((GByte *) pabyData)[ii+2] & 0x1) << 5)
3977 | ((((GByte *) pabyData)[ii+1] & 0x1) << 6)
3978 | ((((GByte *) pabyData)[ii] & 0x1) << 7);
3979 }
3980 }
3981
3982 memcpy( pabyData, pabyBuffer, nPixCount );
3983
3984 CPLFree( pabyBuffer );
3985 }
3986
3987 // ---------------------------------------------------------------------------
3988 // UncompressJpeg()
3989 // ---------------------------------------------------------------------------
3990
3991 const static int K2Chrominance[64] =
3992 {
3993 17, 18, 24, 47, 99, 99, 99, 99,
3994 18, 21, 26, 66, 99, 99, 99, 99,
3995 24, 26, 56, 99, 99, 99, 99, 99,
3996 47, 66, 99, 99, 99, 99, 99, 99,
3997 99, 99, 99, 99, 99, 99, 99, 99,
3998 99, 99, 99, 99, 99, 99, 99, 99,
3999 99, 99, 99, 99, 99, 99, 99, 99,
4000 99, 99, 99, 99, 99, 99, 99, 99
4001 };
4002
4003 constexpr int AC_BITS[16] =
4004 {
4005 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119
4006 };
4007
4008 constexpr int AC_HUFFVAL[256] =
4009 {
4010 0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18,
4011 65, 81, 7, 97, 113, 19, 34, 50, 129, 8, 20,
4012 66, 145, 161, 177, 193, 9, 35, 51, 82, 240, 21,
4013 98, 114, 209, 10, 22, 36, 52, 225, 37, 241, 23,
4014 24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55,
4015 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74,
4016 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101,
4017 102, 103, 104, 105, 106, 115, 116, 117, 118, 119, 120,
4018 121, 122, 130, 131, 132, 133, 134, 135, 136, 137, 138,
4019 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163,
4020 164, 165, 166, 167, 168, 169, 170, 178, 179, 180, 181,
4021 182, 183, 184, 185, 186, 194, 195, 196, 197, 198, 199,
4022 200, 201, 202, 210, 211, 212, 213, 214, 215, 216, 217,
4023 218, 226, 227, 228, 229, 230, 231, 232, 233, 234, 242,
4024 243, 244, 245, 246, 247, 248, 249, 250
4025 };
4026
4027 constexpr int DC_BITS[16] =
4028 {
4029 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
4030 };
4031
4032 constexpr int DC_HUFFVAL[256] =
4033 {
4034 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
4035 };
4036
4037 /***
4038 *
4039 * Load the tables based on the Java's JAI default values.
4040 *
4041 * JPEGQTable.K2Chrominance.getScaledInstance()
4042 * JPEGHuffmanTable.StdACChrominance
4043 * JPEGHuffmanTable.StdDCChrominance
4044 *
4045 ***/
4046 static
JPEG_LoadTables(JQUANT_TBL * hquant_tbl_ptr,JHUFF_TBL * huff_ac_ptr,JHUFF_TBL * huff_dc_ptr,unsigned int nQuality)4047 void JPEG_LoadTables( JQUANT_TBL* hquant_tbl_ptr,
4048 JHUFF_TBL* huff_ac_ptr,
4049 JHUFF_TBL* huff_dc_ptr,
4050 unsigned int nQuality )
4051 {
4052 int i = 0;
4053 float fscale_factor;
4054
4055 // --------------------------------------------------------------------
4056 // Scale Quantization table based on quality
4057 // --------------------------------------------------------------------
4058
4059 fscale_factor = (float) jpeg_quality_scaling( nQuality ) / (float) 100.0;
4060
4061 for ( i = 0; i < 64; i++ )
4062 {
4063 UINT16 temp = (UINT16) floor( K2Chrominance[i] * fscale_factor + 0.5 );
4064 if ( temp <= 0 )
4065 temp = 1;
4066 if ( temp > 255 )
4067 temp = 255;
4068 hquant_tbl_ptr->quantval[i] = (UINT16) temp;
4069 }
4070
4071 // --------------------------------------------------------------------
4072 // Load AC huffman table
4073 // --------------------------------------------------------------------
4074
4075 for ( i = 1; i <= 16; i++ )
4076 {
4077 /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
4078 huff_ac_ptr->bits[i] = (UINT8) AC_BITS[i-1];
4079 }
4080
4081 for ( i = 0; i < 256; i++ )
4082 {
4083 /* symbols[] is the list of Huffman symbols, in code-length order */
4084 huff_ac_ptr->huffval[i] = (UINT8) AC_HUFFVAL[i];
4085 }
4086
4087 // --------------------------------------------------------------------
4088 // Load DC huffman table
4089 // --------------------------------------------------------------------
4090
4091 for ( i = 1; i <= 16; i++ )
4092 {
4093 /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
4094 huff_dc_ptr->bits[i] = (UINT8) DC_BITS[i-1];
4095 }
4096
4097 for ( i = 0; i < 256; i++ )
4098 {
4099 /* symbols[] is the list of Huffman symbols, in code-length order */
4100 huff_dc_ptr->huffval[i] = (UINT8) DC_HUFFVAL[i];
4101 }
4102 }
4103
UncompressJpeg(unsigned long nInSize)4104 void GeoRasterWrapper::UncompressJpeg( unsigned long nInSize )
4105 {
4106 // --------------------------------------------------------------------
4107 // Load JPEG in a virtual file
4108 // --------------------------------------------------------------------
4109
4110 const char* pszMemFile = CPLSPrintf( "/vsimem/geor_%p.jpg", pabyBlockBuf );
4111
4112 VSILFILE *fpImage = VSIFOpenL( pszMemFile, "wb" );
4113 VSIFWriteL( pabyBlockBuf, nInSize, 1, fpImage );
4114 VSIFCloseL( fpImage );
4115
4116 fpImage = VSIFOpenL( pszMemFile, "rb" );
4117
4118 // --------------------------------------------------------------------
4119 // Initialize decompressor
4120 // --------------------------------------------------------------------
4121
4122 if( ! sDInfo.global_state )
4123 {
4124 sDInfo.err = jpeg_std_error( &sJErr );
4125 jpeg_create_decompress( &sDInfo );
4126
4127 // -----------------------------------------------------------------
4128 // Load table for abbreviated JPEG-B
4129 // -----------------------------------------------------------------
4130
4131 int nComponentsToLoad = -1; /* doesn't load any table */
4132
4133 if( EQUAL( sCompressionType.c_str(), "JPEG-B") )
4134 {
4135 nComponentsToLoad = nBandBlockSize;
4136 }
4137
4138 for( int n = 0; n < nComponentsToLoad; n++ )
4139 {
4140 sDInfo.quant_tbl_ptrs[n] =
4141 jpeg_alloc_quant_table( (j_common_ptr) &sDInfo );
4142 sDInfo.ac_huff_tbl_ptrs[n] =
4143 jpeg_alloc_huff_table( (j_common_ptr) &sDInfo );
4144 sDInfo.dc_huff_tbl_ptrs[n] =
4145 jpeg_alloc_huff_table( (j_common_ptr) &sDInfo );
4146
4147 JPEG_LoadTables( sDInfo.quant_tbl_ptrs[n],
4148 sDInfo.ac_huff_tbl_ptrs[n],
4149 sDInfo.dc_huff_tbl_ptrs[n],
4150 nCompressQuality );
4151 }
4152 }
4153
4154 jpeg_vsiio_src( &sDInfo, fpImage );
4155 jpeg_read_header( &sDInfo, TRUE );
4156
4157 sDInfo.out_color_space = ( nBandBlockSize == 1 ? JCS_GRAYSCALE : JCS_RGB );
4158
4159 jpeg_start_decompress( &sDInfo );
4160
4161 GByte* pabyScanline = pabyBlockBuf;
4162
4163 for( int iLine = 0; iLine < nRowBlockSize; iLine++ )
4164 {
4165 JSAMPLE* ppSamples = (JSAMPLE*) pabyScanline;
4166 jpeg_read_scanlines( &sDInfo, &ppSamples, 1 );
4167 pabyScanline += ( nColumnBlockSize * nBandBlockSize );
4168 }
4169
4170 jpeg_finish_decompress( &sDInfo );
4171
4172 VSIFCloseL( fpImage );
4173
4174 VSIUnlink( pszMemFile );
4175 }
4176
4177 // ---------------------------------------------------------------------------
4178 // CompressJpeg()
4179 // ---------------------------------------------------------------------------
4180
CompressJpeg(void)4181 unsigned long GeoRasterWrapper::CompressJpeg( void )
4182 {
4183 // --------------------------------------------------------------------
4184 // Load JPEG in a virtual file
4185 // --------------------------------------------------------------------
4186
4187 const char* pszMemFile = CPLSPrintf( "/vsimem/geor_%p.jpg", pabyBlockBuf );
4188
4189 VSILFILE *fpImage = VSIFOpenL( pszMemFile, "wb" );
4190
4191 bool write_all_tables = TRUE;
4192
4193 if( EQUAL( sCompressionType.c_str(), "JPEG-B") )
4194 {
4195 write_all_tables = FALSE;
4196 }
4197
4198 // --------------------------------------------------------------------
4199 // Initialize compressor
4200 // --------------------------------------------------------------------
4201
4202 if( ! sCInfo.global_state )
4203 {
4204 sCInfo.err = jpeg_std_error( &sJErr );
4205 jpeg_create_compress( &sCInfo );
4206
4207 jpeg_vsiio_dest( &sCInfo, fpImage );
4208
4209 sCInfo.image_width = nColumnBlockSize;
4210 sCInfo.image_height = nRowBlockSize;
4211 sCInfo.input_components = nBandBlockSize;
4212 sCInfo.in_color_space = (nBandBlockSize == 1 ? JCS_GRAYSCALE : JCS_RGB);
4213 jpeg_set_defaults( &sCInfo );
4214 sCInfo.JFIF_major_version = 1;
4215 sCInfo.JFIF_minor_version = 2;
4216 jpeg_set_quality( &sCInfo, nCompressQuality, TRUE );
4217
4218 // -----------------------------------------------------------------
4219 // Load table for abbreviated JPEG-B
4220 // -----------------------------------------------------------------
4221
4222 int nComponentsToLoad = -1; /* doesn't load any table */
4223
4224 if( EQUAL( sCompressionType.c_str(), "JPEG-B") )
4225 {
4226 nComponentsToLoad = nBandBlockSize;
4227 }
4228
4229 for( int n = 0; n < nComponentsToLoad; n++ )
4230 {
4231 sCInfo.quant_tbl_ptrs[n] =
4232 jpeg_alloc_quant_table( (j_common_ptr) &sCInfo );
4233 sCInfo.ac_huff_tbl_ptrs[n] =
4234 jpeg_alloc_huff_table( (j_common_ptr) &sCInfo );
4235 sCInfo.dc_huff_tbl_ptrs[n] =
4236 jpeg_alloc_huff_table( (j_common_ptr) &sCInfo );
4237
4238 JPEG_LoadTables( sCInfo.quant_tbl_ptrs[n],
4239 sCInfo.ac_huff_tbl_ptrs[n],
4240 sCInfo.dc_huff_tbl_ptrs[n],
4241 nCompressQuality );
4242 }
4243 }
4244 else
4245 {
4246 jpeg_vsiio_dest( &sCInfo, fpImage );
4247 }
4248
4249 jpeg_suppress_tables( &sCInfo, ! write_all_tables );
4250 jpeg_start_compress( &sCInfo, write_all_tables );
4251
4252 GByte* pabyScanline = pabyBlockBuf;
4253
4254 for( int iLine = 0; iLine < nRowBlockSize; iLine++ )
4255 {
4256 JSAMPLE* ppSamples = (JSAMPLE*) pabyScanline;
4257 jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
4258 pabyScanline += ( nColumnBlockSize * nBandBlockSize );
4259 }
4260
4261 jpeg_finish_compress( &sCInfo );
4262
4263 VSIFCloseL( fpImage );
4264
4265 fpImage = VSIFOpenL( pszMemFile, "rb" );
4266 size_t nSize = VSIFReadL( pabyCompressBuf, 1, nBlockBytes, fpImage );
4267 VSIFCloseL( fpImage );
4268
4269 VSIUnlink( pszMemFile );
4270
4271 return (unsigned long) nSize;
4272 }
4273
4274 // ---------------------------------------------------------------------------
4275 // UncompressDeflate()
4276 // ---------------------------------------------------------------------------
4277
UncompressDeflate(unsigned long nBufferSize)4278 bool GeoRasterWrapper::UncompressDeflate( unsigned long nBufferSize )
4279 {
4280 GByte* pabyBuf = (GByte*) VSI_MALLOC_VERBOSE( nBufferSize );
4281
4282 if( pabyBuf == nullptr )
4283 {
4284 return false;
4285 }
4286
4287 memcpy( pabyBuf, pabyBlockBuf, nBufferSize );
4288
4289 // Call ZLib uncompress
4290
4291 unsigned long nDestLen = nBlockBytes;
4292
4293 int nRet = uncompress( pabyBlockBuf, &nDestLen, pabyBuf, nBufferSize );
4294
4295 CPLFree( pabyBuf );
4296
4297 if( nRet != Z_OK )
4298 {
4299 CPLError( CE_Failure, CPLE_AppDefined, "ZLib return code (%d)", nRet );
4300 return false;
4301 }
4302
4303 if( nDestLen != nBlockBytes )
4304 {
4305 CPLError( CE_Failure, CPLE_AppDefined,
4306 "ZLib decompressed buffer size (%ld) expected (%ld)", nDestLen, nBlockBytes );
4307 return false;
4308 }
4309
4310 return true;
4311 }
4312
4313 // ---------------------------------------------------------------------------
4314 // CompressDeflate()
4315 // ---------------------------------------------------------------------------
4316
CompressDeflate(void)4317 unsigned long GeoRasterWrapper::CompressDeflate( void )
4318 {
4319 unsigned long nLen = ((unsigned long)(nBlockBytes * 1.1)) + 12;
4320
4321 GByte* pabyBuf = (GByte*) VSI_MALLOC_VERBOSE( nBlockBytes );
4322
4323 if( pabyBuf == nullptr )
4324 {
4325 return 0;
4326 }
4327
4328 memcpy( pabyBuf, pabyBlockBuf, nBlockBytes );
4329
4330 // Call ZLib compress
4331
4332 int nRet = compress( pabyCompressBuf, &nLen, pabyBuf, nBlockBytes );
4333
4334 CPLFree( pabyBuf );
4335
4336 if( nRet != Z_OK )
4337 {
4338 CPLError( CE_Failure, CPLE_AppDefined, "ZLib return code (%d)", nRet );
4339 return 0;
4340 }
4341
4342 return nLen;
4343 }
4344