1 /******************************************************************************
2  * $Id: sdedataset.cpp 10804 2007-02-08 23:24:59Z hobu $
3  *
4  * Project:  ESRI ArcSDE Raster reader
5  * Purpose:  Rasterband implementaion for ESRI ArcSDE Rasters
6  * Author:   Howard Butler, hobu@hobu.net
7  *
8  * This work was sponsored by the Geological Survey of Canada, Natural
9  * Resources Canada. http://gsc.nrcan.gc.ca/
10  *
11  ******************************************************************************
12  * Copyright (c) 2007, Howard Butler <hobu@hobu.net>
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included
22  * in all copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30  * DEALINGS IN THE SOFTWARE.
31  ****************************************************************************/
32 
33 
34 #include "sderasterband.h"
35 
36 
37 
38 /************************************************************************/
39 /*  SDERasterBand implements a GDAL RasterBand for ArcSDE.  This class  */
40 /*  carries around a pointer to SDE's internal band representation      */
41 /*  is of type SE_RASBANDINFO*.  SDERasterBand provides the following   */
42 /*  capabilities:                                                       */
43 /*                                                                      */
44 /*      -- Statistics support - uses SDE's internal band statistics     */
45 /*      -- Colortable - translates SDE's internal colortable to GDAL's  */
46 /*      -- Block reading through IReadBlock                             */
47 /*      -- Overview support                                             */
48 /*      -- NODATA support                                               */
49 /*                                                                      */
50 /*  Instantiating a SDERasterBand is rather expensive because of all    */
51 /*  of the round trips to the database the SDE C API must make to       */
52 /*  calculate band information.  This overhead hit is also taken in     */
53 /*  the case of grabbing an overview, because information between       */
54 /*  bands is not shared.  It might be possible in the future to do      */
55 /*  do so, but it would likely make things rather complicated.          */
56 /*  In particular, the stream, constraint, and queryinfo SDE objects    */
57 /*  could be passed around from band to overview band without having    */
58 /*  to be instantiated every time.  Stream creation has an especially   */
59 /*  large overhead.                                                     */
60 /*                                                                      */
61 /*  Once the band or overview band is established, querying raster      */
62 /*  blocks does not carry much more network overhead than that requied  */
63 /*  to actually download the bytes.                                     */
64 /*                                                                      */
65 /*  Overview of internal methods:                                       */
66 /*      -- InitializeBand - does most of the work of construction       */
67 /*                          of the band and communication with SDE.     */
68 /*                          Calls InitializeConstraint and              */
69 /*                          IntializeQuery.                             */
70 /*      -- InitializeQuery -    Initializes a SDE queryinfo object      */
71 /*                              that contains information about which   */
72 /*                              tables we are querying from.            */
73 /*      -- InitializeConstraint -   Specifies block constraints (which  */
74 /*                                  are initially set to none in        */
75 /*                                  InitializeBand) as well as which    */
76 /*                                  band for SDE to query from.         */
77 /*      -- MorphESRIRasterType -    translates SDE's raster type to GDAL*/
78 /*      -- MorphESRIRasterDepth -   calculates the bit depth from SDE   */
79 /*      -- ComputeColorTable -  does the work of getting and            */
80 /*                              translating the SDE colortable to GDAL. */
81 /*      -- ComputeSDEBandNumber -   returns the band # for SDE's        */
82 /*                                  internal representation of the band.*/
83 /*      -- QueryRaster -    Does the work of setting the constraint     */
84 /*                          and preparing for querying tiles from SDE.  */
85 /*                                                                      */
86 /************************************************************************/
87 
88 
89 /************************************************************************/
90 /*                           SDERasterBand()                            */
91 /************************************************************************/
92 
SDERasterBand(SDEDataset * poDS,int nBand,int nOverview,const SE_RASBANDINFO * band)93 SDERasterBand::SDERasterBand(   SDEDataset *poDS,
94                                 int nBand,
95                                 int nOverview,
96                                 const SE_RASBANDINFO* band )
97 
98 {
99     // Carry some of the data we were given at construction.
100     // If we were passed -1 for an overview at construction, reset it
101     // to 0 to ensure we get the zero'th level from SDE.
102     // The SE_RASBANDINFO* we were given is actually owned by the
103     // dataset.  We want it around for convenience.
104     this->poDS = poDS;
105     this->nBand = nBand;
106     this->nOverview = nOverview;
107     this->poBand = band;
108 
109     // Initialize our SDE opaque object pointers to NULL.
110     // The nOverviews private data member will be updated when
111     // GetOverviewCount is called and subsequently returned immediately in
112     // later calls if it has been set to anything other than 0.
113     this->hConstraint = NULL;
114     this->hQuery = NULL;
115     this->poColorTable = NULL;
116 
117     if (this->nOverview == -1 || this->nOverview == 0)
118         this->nOverviews = GetOverviewCount();
119     else
120         this->nOverviews = 0;
121 
122     if (nOverview == -1) {
123         this->papoOverviews = (GDALRasterBand**)  CPLMalloc( nOverviews * sizeof(GDALRasterBand*) );
124     }
125     else {
126         this->papoOverviews = NULL;
127     }
128     this->eDataType = GetRasterDataType();
129 
130     // nSDERasterType is set by GetRasterDataType
131     this->dfDepth = MorphESRIRasterDepth(nSDERasterType);
132     InitializeBand(this->nOverview);
133 
134 
135 }
136 
137 /************************************************************************/
138 /*                          ~SDERasterBand()                            */
139 /************************************************************************/
~SDERasterBand(void)140 SDERasterBand::~SDERasterBand( void )
141 
142 {
143 
144     if (hQuery)
145         SE_queryinfo_free(hQuery);
146 
147     if (hConstraint)
148         SE_rasconstraint_free(hConstraint);
149 
150     if (papoOverviews)
151         for (int i=0; i < nOverviews; i++)
152             delete papoOverviews[i];
153         CPLFree(papoOverviews);
154 
155     if (poColorTable != NULL)
156         delete poColorTable;
157 }
158 
159 
160 /************************************************************************/
161 /*                             GetColorTable()                          */
162 /************************************************************************/
GetColorTable(void)163 GDALColorTable* SDERasterBand::GetColorTable(void)
164 {
165 
166     if (SE_rasbandinfo_has_colormap(*poBand)) {
167         if (poColorTable == NULL)
168             ComputeColorTable();
169         return poColorTable;
170     } else {
171         return NULL;
172     }
173 }
174 
175 
176 /************************************************************************/
177 /*                             GetColorInterpretation()                 */
178 /************************************************************************/
GetColorInterpretation()179 GDALColorInterp SDERasterBand::GetColorInterpretation()
180 {
181     // Only return Paletted images when SDE has a colormap.  Otherwise,
182     // just return gray, even in the instance where we have 3 or 4 band,
183     // imagery.  Let the client be smart instead of trying to do too much.
184     if (SE_rasbandinfo_has_colormap(*poBand))
185         return GCI_PaletteIndex;
186     else
187         return GCI_GrayIndex;
188 }
189 
190 /************************************************************************/
191 /*                           GetOverview()                              */
192 /************************************************************************/
GetOverview(int nOverviewValue)193 GDALRasterBand* SDERasterBand::GetOverview( int nOverviewValue )
194 {
195 
196     if (papoOverviews) {
197         return papoOverviews[nOverviewValue];
198     }
199     else
200         return NULL;
201 
202 
203 }
204 
205 /************************************************************************/
206 /*                           GetOverviewCount()                         */
207 /************************************************************************/
GetOverviewCount(void)208 int SDERasterBand::GetOverviewCount( void )
209 {
210     // grab our existing overview count if we have already gotten it,
211     // otherwise request it from SDE and set our member data with it.
212     long nSDEErr;
213     BOOL bSkipLevel;
214     LONG nOvRet;
215 
216     // return nothing if we were an overview band
217     if (nOverview != -1)
218         return 0;
219 
220     nSDEErr = SE_rasbandinfo_get_max_level(*poBand, &nOvRet, &bSkipLevel);
221     if( nSDEErr != SE_SUCCESS )
222     {
223         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_band_size" );
224     }
225 
226     nOverviews = nOvRet;
227 
228     return nOverviews;
229 }
230 
231 /************************************************************************/
232 /*                             GetRasterDataType()                      */
233 /************************************************************************/
GetRasterDataType(void)234 GDALDataType SDERasterBand::GetRasterDataType(void)
235 {
236     // Always ask SDE what it thinks our type is.
237     LONG nSDEErr;
238 
239     nSDEErr = SE_rasbandinfo_get_pixel_type(*poBand, &nSDERasterType);
240     if( nSDEErr != SE_SUCCESS )
241     {
242         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_pixel_type" );
243         return GDT_Byte;
244     }
245 
246     return MorphESRIRasterType(nSDERasterType);
247 }
248 
249 /************************************************************************/
250 /*                             GetStatistics()                          */
251 /************************************************************************/
252 
GetStatistics(int bApproxOK,int bForce,double * pdfMin,double * pdfMax,double * pdfMean,double * pdfStdDev)253 CPLErr SDERasterBand::GetStatistics( int bApproxOK, int bForce,
254                                       double *pdfMin, double *pdfMax,
255                                       double *pdfMean, double *pdfStdDev )
256 {
257     // if SDE hasn't already cached our statistics, we'll depend on the
258     // GDALRasterBands's method for getting them.
259     bool bHasStats;
260     bHasStats = SE_rasbandinfo_has_stats (*poBand);
261     if (!bHasStats)
262         return GDALRasterBand::GetStatistics(    bApproxOK,
263                                                     bForce,
264                                                     pdfMin,
265                                                     pdfMax,
266                                                     pdfMean,
267                                                     pdfStdDev);
268 
269     // bForce has no effect currently.  We always go to SDE to get our
270     // stats if SDE has them.
271 
272     // bApproxOK has no effect currently.  If we're getting stats from
273     // SDE, we're hoping SDE calculates them in the way we want.
274     long nSDEErr;
275     nSDEErr = SE_rasbandinfo_get_stats_min(*poBand, pdfMin);
276     if( nSDEErr != SE_SUCCESS )
277     {
278         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_min" );
279         return CE_Fatal;
280     }
281 
282     nSDEErr = SE_rasbandinfo_get_stats_max(*poBand, pdfMax);
283     if( nSDEErr != SE_SUCCESS )
284     {
285         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_max" );
286         return CE_Fatal;
287     }
288 
289     nSDEErr = SE_rasbandinfo_get_stats_mean(*poBand, pdfMean);
290     if( nSDEErr != SE_SUCCESS )
291     {
292         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_mean" );
293         return CE_Fatal;
294     }
295 
296     nSDEErr = SE_rasbandinfo_get_stats_stddev(*poBand, pdfStdDev);
297     if( nSDEErr != SE_SUCCESS )
298     {
299         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_stddev" );
300         return CE_Fatal;
301     }
302     return CE_None;
303 }
304 
305 /************************************************************************/
306 /*                             GetMinimum()                             */
307 /************************************************************************/
308 
GetMinimum(int * pbSuccess)309 double SDERasterBand::GetMinimum(int *pbSuccess)
310 {
311     double dfMin, dfMax, dfMean, dfStdDev;
312     CPLErr error = GetStatistics( TRUE, TRUE,
313                                   &dfMin,
314                                   &dfMax,
315                                   &dfMean,
316                                   &dfStdDev );
317     if (error == CE_None) {
318         *pbSuccess = TRUE;
319         return dfMin;
320     }
321     *pbSuccess = FALSE;
322     return 0.0;
323 }
324 
325 /************************************************************************/
326 /*                             GetMaximum()                             */
327 /************************************************************************/
328 
GetMaximum(int * pbSuccess)329 double SDERasterBand::GetMaximum(int *pbSuccess)
330 {
331     double dfMin, dfMax, dfMean, dfStdDev;
332     CPLErr error = GetStatistics( TRUE, TRUE,
333                                   &dfMin,
334                                   &dfMax,
335                                   &dfMean,
336                                   &dfStdDev );
337     if (error == CE_None) {
338         *pbSuccess = TRUE;
339         return dfMax;
340     }
341     *pbSuccess = FALSE;
342     return 0.0;
343 }
344 
345 /************************************************************************/
346 /*                             IReadBlock()                             */
347 /************************************************************************/
348 
IReadBlock(int nBlockXOff,int nBlockYOff,void * pImage)349 CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
350                                   int nBlockYOff,
351                                   void * pImage )
352 
353 {
354     // grab our Dataset to limit the casting we have to do.
355     SDEDataset *poGDS = (SDEDataset *) poDS;
356 
357 
358     // SDE manages the acquisition of raster data in "TileInfo" objects.
359     // The hTile is the only heap-allocated object in this method, and
360     // we should make sure to delete it at the end.  Once we get the
361     // pixel data, we'll memcopy it back on to the pImage pointer.
362 
363     SE_RASTILEINFO hTile;
364     long nSDEErr;
365     nSDEErr = SE_rastileinfo_create(&hTile);
366     if( nSDEErr != SE_SUCCESS )
367     {
368         IssueSDEError( nSDEErr, "SE_rastileinfo_create" );
369         return CE_Fatal;
370     }
371 
372     hConstraint = InitializeConstraint( (long*) &nBlockXOff, (long*) &nBlockYOff );
373     if (!hConstraint)
374         CPLError( CE_Failure, CPLE_AppDefined,
375                   "ConstraintInfo initialization failed");
376 
377     CPLErr error = QueryRaster(hConstraint);
378     if (error != CE_None)
379         return error;
380 
381     LONG level;
382     nSDEErr = SE_rastileinfo_get_level(hTile, &level);
383     if( nSDEErr != SE_SUCCESS )
384     {
385         IssueSDEError( nSDEErr, "SE_rastileinfo_get_level" );
386         return CE_Fatal;
387     }
388 
389     nSDEErr = SE_stream_get_raster_tile(poGDS->hStream, hTile);
390     if( nSDEErr != SE_SUCCESS )
391     {
392         IssueSDEError( nSDEErr, "SE_stream_get_raster_tile" );
393         return CE_Fatal;
394     }
395 
396     LONG row, column;
397     nSDEErr = SE_rastileinfo_get_rowcol(hTile, &row, &column);
398     if( nSDEErr != SE_SUCCESS )
399     {
400         IssueSDEError( nSDEErr, "SE_rastileinfo_get_level" );
401         return CE_Fatal;
402     }
403 
404     LONG length;
405     unsigned char* pixels;
406     nSDEErr = SE_rastileinfo_get_pixel_data(hTile, (void**) &pixels, &length);
407     if( nSDEErr != SE_SUCCESS )
408     {
409         IssueSDEError( nSDEErr, "SE_rastileinfo_get_pixel_data" );
410         return CE_Fatal;
411     }
412 
413     int bits_per_pixel = static_cast<int>(dfDepth * 8 + 0.0001);
414     int block_size = (nBlockXSize * bits_per_pixel + 7) / 8 * nBlockYSize;
415     int bitmap_size = (nBlockXSize * nBlockYSize + 7) / 8;
416 
417 
418     if (length == 0) {
419         // ArcSDE says the block has no data in it.
420         // Write 0's and be done with it
421         memset( pImage, 0,
422                 nBlockXSize*nBlockYSize*GDALGetDataTypeSize(eDataType)/8);
423         return CE_None;
424     }
425     if ((length == block_size) || (length == (block_size + bitmap_size))) {
426     if (bits_per_pixel >= 8) {
427         memcpy(pImage, pixels, block_size);
428     } else {
429         GByte *p = reinterpret_cast<GByte*>(pImage);
430         int bit_mask = (2 << bits_per_pixel) - 1;
431         int i = 0;
432         for (int y = 0; y < nBlockYSize; ++y) {
433         for (int x = 0; x < nBlockXSize; ++x) {
434             *p++ = (pixels[i >> 3] >> (i & 7)) & bit_mask;
435             i += bits_per_pixel;
436         }
437         i = (i + 7) / 8 * 8;
438         }
439     }
440     } else {
441 
442             CPLError( CE_Failure, CPLE_AppDefined,
443                       "Bit size calculation failed... "\
444                       "SDE's length:%d With bitmap length: %d Without bitmap length: %d",
445                       length, block_size + bitmap_size, block_size );
446             return CE_Fatal;
447         }
448 
449     SE_rastileinfo_free (hTile);
450 
451     return CE_None ;
452 }
453 
454 
455 
456 /* ---------------------------------------------------------------------*/
457 /* Private Methods                                                      */
458 
459 /************************************************************************/
460 /*                             ComputeColorTable()                      */
461 /************************************************************************/
ComputeColorTable(void)462 void SDERasterBand::ComputeColorTable(void)
463 {
464 
465     SE_COLORMAP_TYPE eCMap_Type;
466     SE_COLORMAP_DATA_TYPE eCMap_DataType;
467 
468     LONG nCMapEntries;
469     void * phSDEColormapData;
470 
471     unsigned char* puszSDECMapData;
472     unsigned short* pushSDECMapData;
473 
474     long nSDEErr;
475 
476     nSDEErr = SE_rasbandinfo_get_colormap(  *poBand,
477                                             &eCMap_Type,
478                                             &eCMap_DataType,
479                                             &nCMapEntries,
480                                             &phSDEColormapData);
481     if( nSDEErr != SE_SUCCESS )
482     {
483         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_colormap" );
484     }
485 
486     // Assign both the short and char pointers
487     // to the void*, and we'll switch and read based
488     // on the eCMap_DataType
489     puszSDECMapData = (unsigned char*) phSDEColormapData;
490     pushSDECMapData = (unsigned short*) phSDEColormapData;
491 
492     poColorTable = new GDALColorTable(GPI_RGB);
493 
494     int red, green, blue, alpha;
495 
496     CPLDebug("SDERASTER", "%d colormap entries specified", nCMapEntries);
497     switch (eCMap_DataType) {
498         case SE_COLORMAP_DATA_BYTE:
499             switch (eCMap_Type){
500                 case SE_COLORMAP_RGB:
501                     for (int i = 0; i < (nCMapEntries); i++) {
502                         int j = i*3;
503                         red = puszSDECMapData[j];
504                         green = puszSDECMapData[j+1];
505                         blue = puszSDECMapData[j+2];
506                         GDALColorEntry sColor;
507                         sColor.c1 = red;
508                         sColor.c2 = green;
509                         sColor.c3 = blue;
510                         sColor.c4 = 255;
511 
512                         // sColor is copied
513                         poColorTable->SetColorEntry(i,&sColor);
514                         CPLDebug ("SDERASTER", "SE_COLORMAP_DATA_BYTE "\
515                                   "SE_COLORMAP_RGB Colormap Entry: %d %d %d",
516                                   red, blue, green);
517                     }
518                     break;
519                 case SE_COLORMAP_RGBA:
520                     for (int i = 0; i < (nCMapEntries); i++) {
521                         int j = i*4;
522                         red = puszSDECMapData[j];
523                         green = puszSDECMapData[j+1];
524                         blue = puszSDECMapData[j+2];
525                         alpha = puszSDECMapData[j+3];
526                         GDALColorEntry sColor;
527                         sColor.c1 = red;
528                         sColor.c2 = green;
529                         sColor.c3 = blue;
530                         sColor.c4 = alpha;
531 
532                         // sColor is copied
533                         poColorTable->SetColorEntry(i,&sColor);
534                         CPLDebug ("SDERASTER", "SE_COLORMAP_DATA_BYTE "\
535                                   "SE_COLORMAP_RGBA Colormap Entry: %d %d %d %d",
536                                   red, blue, green, alpha);
537                     }
538                     break;
539                 case SE_COLORMAP_NONE:
540                     break;
541             }
542             break;
543         case SE_COLORMAP_DATA_SHORT:
544             switch (eCMap_Type) {
545                 case SE_COLORMAP_RGB:
546                     for (int i = 0; i < (nCMapEntries); i++) {
547                         int j = i*3;
548                         red = pushSDECMapData[j];
549                         green = pushSDECMapData[j+1];
550                         blue = pushSDECMapData[j+2];
551                         GDALColorEntry sColor;
552                         sColor.c1 = red;
553                         sColor.c2 = green;
554                         sColor.c3 = blue;
555                         sColor.c4 = 255;
556 
557                         // sColor is copied
558                         poColorTable->SetColorEntry(i,&sColor);
559                         CPLDebug ("SDERASTER", "SE_COLORMAP_DATA_SHORT "\
560                                   "SE_COLORMAP_RGB Colormap Entry: %d %d %d",
561                                   red, blue, green);
562                     }
563                     break;
564                 case SE_COLORMAP_RGBA:
565                     for (int i = 0; i < (nCMapEntries); i++) {
566                         int j = i*4;
567                         red = pushSDECMapData[j];
568                         green = pushSDECMapData[j+1];
569                         blue = pushSDECMapData[j+2];
570                         alpha = pushSDECMapData[j+3];
571                         GDALColorEntry sColor;
572                         sColor.c1 = red;
573                         sColor.c2 = green;
574                         sColor.c3 = blue;
575                         sColor.c4 = alpha;
576 
577                         // sColor is copied
578                         poColorTable->SetColorEntry(i,&sColor);
579                         CPLDebug ("SDERASTER", "SE_COLORMAP_DATA_SHORT "\
580                                   "SE_COLORMAP_RGBA Colormap Entry: %d %d %d %d",
581                                   red, blue, green, alpha);
582                     }
583                     break;
584                 case SE_COLORMAP_NONE:
585                     break;
586             }
587             break;
588     }
589     SE_rasbandinfo_free_colormap(phSDEColormapData);
590 }
591 
592 
593 /************************************************************************/
594 /*                           InitializeBand()                           */
595 /************************************************************************/
InitializeBand(int nOverview)596 CPLErr SDERasterBand::InitializeBand( int nOverview )
597 
598 {
599 
600     SDEDataset *poGDS = (SDEDataset *) poDS;
601 
602     long nSDEErr;
603 
604 
605     hConstraint = InitializeConstraint( NULL, NULL );
606     if (!hConstraint)
607         CPLError( CE_Failure, CPLE_AppDefined,
608                   "ConstraintInfo initialization failed");
609 
610     if (!hQuery) {
611         hQuery = InitializeQuery();
612         if (!hQuery)
613             CPLError( CE_Failure, CPLE_AppDefined,
614                       "QueryInfo initialization failed");
615     }
616 
617     nSDEErr = SE_stream_close(poGDS->hStream, 1);
618     if( nSDEErr != SE_SUCCESS )
619     {
620         IssueSDEError( nSDEErr, "SE_stream_close" );
621         return CE_Fatal;
622     }
623 
624     nSDEErr = SE_stream_query_with_info(poGDS->hStream, hQuery);
625     if( nSDEErr != SE_SUCCESS )
626     {
627         IssueSDEError( nSDEErr, "SE_stream_query_with_info" );
628         return CE_Fatal;
629     }
630 
631     nSDEErr = SE_stream_execute (poGDS->hStream);
632     if( nSDEErr != SE_SUCCESS )
633     {
634         IssueSDEError( nSDEErr, "SE_stream_execute" );
635         return CE_Fatal;
636     }
637     nSDEErr = SE_stream_fetch (poGDS->hStream);
638     if( nSDEErr != SE_SUCCESS )
639     {
640         IssueSDEError( nSDEErr, "SE_stream_fetch" );
641         return CE_Fatal;
642     }
643 
644 
645     CPLErr error = QueryRaster(hConstraint);
646     if (error != CE_None)
647         return error;
648 
649     LONG nBXRet, nBYRet;
650     nSDEErr = SE_rasterattr_get_tile_size (poGDS->hAttributes,
651                                            &nBXRet, &nBYRet);
652     if( nSDEErr != SE_SUCCESS )
653     {
654         IssueSDEError( nSDEErr, "SE_rasterattr_get_tile_size" );
655         return CE_Fatal;
656     }
657 
658     nBlockXSize = nBXRet;
659     nBlockYSize = nBYRet;
660 
661     LONG offset_x, offset_y, num_bands, nXSRet, nYSRet;
662 
663     nSDEErr = SE_rasterattr_get_image_size_by_level (poGDS->hAttributes,
664                                                      &nXSRet, &nYSRet,
665                                                      &offset_x,
666                                                      &offset_y,
667                                                      &num_bands,
668                                                      (nOverview == -1) ? (0): (nOverview));
669 
670     if( nSDEErr != SE_SUCCESS )
671     {
672         IssueSDEError( nSDEErr, "SE_rasterattr_get_image_size_by_level" );
673         return CE_Fatal;
674     }
675 
676     nRasterXSize = nXSRet;
677     nRasterYSize = nYSRet;
678 
679     nBlockSize = nBlockXSize * nBlockYSize;
680 
681     // We're the base level
682     if (nOverview == -1) {
683         for (int i = 0; i<this->nOverviews; i++) {
684             papoOverviews[i]= new SDERasterBand(poGDS, nBand, i, poBand);
685 
686         }
687     }
688     return CE_None;
689 }
690 
691 /************************************************************************/
692 /*                           InitializeConstraint()                     */
693 /************************************************************************/
InitializeConstraint(long * nBlockXOff,long * nBlockYOff)694 SE_RASCONSTRAINT& SDERasterBand::InitializeConstraint( long* nBlockXOff,
695                                                        long* nBlockYOff)
696 {
697 
698     long nSDEErr;
699 
700     if (!hConstraint) {
701         nSDEErr = SE_rasconstraint_create(&hConstraint);
702         if( nSDEErr != SE_SUCCESS )
703         {
704             IssueSDEError( nSDEErr, "SE_rasconstraint_create" );
705         }
706 
707         nSDEErr = SE_rasconstraint_set_level(hConstraint, (nOverview == -1) ? (0): (nOverview));
708         if( nSDEErr != SE_SUCCESS )
709         {
710             IssueSDEError( nSDEErr, "SE_rasconstraint_create" );
711         }
712 
713         LONG nBandIn = nBand;
714         nSDEErr = SE_rasconstraint_set_bands(hConstraint, 1, &nBandIn);
715         if( nSDEErr != SE_SUCCESS )
716         {
717             IssueSDEError( nSDEErr, "SE_rasconstraint_set_bands" );
718         }
719         nSDEErr = SE_rasconstraint_set_interleave(hConstraint, SE_RASTER_INTERLEAVE_BSQ);
720         if( nSDEErr != SE_SUCCESS )
721         {
722             IssueSDEError( nSDEErr, "SE_rasconstraint_set_interleave" );
723         }
724 
725     }
726 
727     if (nBlockXSize != -1 && nBlockYSize != -1) { // we aren't initialized yet
728         if (nBlockXSize >= 0 && nBlockYSize >= 0) {
729             if (*nBlockXOff >= 0 &&  *nBlockYOff >= 0) {
730                 long nMinX, nMinY, nMaxX, nMaxY;
731 
732                 nMinX = *nBlockXOff;
733                 nMinY = *nBlockYOff;
734                 nMaxX = *nBlockXOff;
735                 nMaxY = *nBlockYOff;
736 
737                 nSDEErr = SE_rasconstraint_set_envelope (hConstraint,
738                                                         nMinX,
739                                                         nMinY,
740                                                         nMaxX,
741                                                         nMaxY);
742                 if( nSDEErr != SE_SUCCESS )
743                 {
744                     IssueSDEError( nSDEErr, "SE_rasconstraint_set_envelope" );
745                 }
746             }
747         }
748     }
749     return hConstraint;
750 }
751 
752 /************************************************************************/
753 /*                           InitializeQuery()                          */
754 /************************************************************************/
InitializeQuery(void)755 SE_QUERYINFO& SDERasterBand::InitializeQuery( void )
756 {
757     SDEDataset *poGDS = (SDEDataset *) poDS;
758     long nSDEErr;
759 
760     nSDEErr = SE_queryinfo_create(&hQuery);
761     if( nSDEErr != SE_SUCCESS )
762     {
763         IssueSDEError( nSDEErr, "SE_queryinfo_create" );
764     }
765 
766     nSDEErr = SE_queryinfo_set_tables(hQuery,
767                                       1,
768                                       (const char**) &(poGDS->pszLayerName),
769                                       NULL);
770     if( nSDEErr != SE_SUCCESS )
771     {
772         IssueSDEError( nSDEErr, "SE_queryinfo_set_tables" );
773     }
774 
775     nSDEErr = SE_queryinfo_set_where_clause(hQuery, (const char*) "");
776     if( nSDEErr != SE_SUCCESS )
777     {
778         IssueSDEError( nSDEErr, "SE_queryinfo_set_where" );
779     }
780 
781     nSDEErr = SE_queryinfo_set_columns(hQuery,
782                                        1,
783                                        (const char**) &(poGDS->pszColumnName));
784     if( nSDEErr != SE_SUCCESS )
785     {
786         IssueSDEError( nSDEErr, "SE_queryinfo_set_where" );
787     }
788     return hQuery;
789 }
790 
791 
792 
793 /************************************************************************/
794 /*                             MorphESRIRasterDepth()                   */
795 /************************************************************************/
MorphESRIRasterDepth(int gtype)796 double SDERasterBand::MorphESRIRasterDepth(int gtype) {
797 
798     switch (gtype) {
799         case SE_PIXEL_TYPE_1BIT:
800             return 0.125;
801         case SE_PIXEL_TYPE_4BIT:
802             return 0.5;
803         case SE_PIXEL_TYPE_8BIT_U:
804             return 1.0;
805         case SE_PIXEL_TYPE_8BIT_S:
806             return 1.0;
807         case SE_PIXEL_TYPE_16BIT_U:
808             return 2.0;
809         case SE_PIXEL_TYPE_16BIT_S:
810             return 2.0;
811         case SE_PIXEL_TYPE_32BIT_U:
812             return 4.0;
813         case SE_PIXEL_TYPE_32BIT_S:
814             return 4.0;
815         case SE_PIXEL_TYPE_32BIT_REAL:
816             return 4.0;
817         case SE_PIXEL_TYPE_64BIT_REAL:
818             return 8.0;
819         default:
820             return 2.0;
821         }
822 }
823 
824 /************************************************************************/
825 /*                             MorphESRIRasterType()                    */
826 /************************************************************************/
MorphESRIRasterType(int gtype)827 GDALDataType SDERasterBand::MorphESRIRasterType(int gtype) {
828 
829     switch (gtype) {
830         case SE_PIXEL_TYPE_1BIT:
831             return GDT_Byte;
832         case SE_PIXEL_TYPE_4BIT:
833             return GDT_Byte;
834         case SE_PIXEL_TYPE_8BIT_U:
835             return GDT_Byte;
836         case SE_PIXEL_TYPE_8BIT_S:
837             return GDT_Byte;
838         case SE_PIXEL_TYPE_16BIT_U:
839             return GDT_UInt16;
840         case SE_PIXEL_TYPE_16BIT_S:
841             return GDT_Int16;
842         case SE_PIXEL_TYPE_32BIT_U:
843             return GDT_UInt32;
844         case SE_PIXEL_TYPE_32BIT_S:
845             return GDT_Int32;
846         case SE_PIXEL_TYPE_32BIT_REAL:
847             return GDT_Float32;
848         case SE_PIXEL_TYPE_64BIT_REAL:
849             return GDT_Float64;
850         default:
851             return GDT_UInt16;
852         }
853 }
854 
855 /************************************************************************/
856 /*                           QueryRaster()                              */
857 /************************************************************************/
QueryRaster(SE_RASCONSTRAINT & constraint)858 CPLErr SDERasterBand::QueryRaster( SE_RASCONSTRAINT& constraint )
859 {
860 
861     SDEDataset *poGDS = (SDEDataset *) poDS;
862 
863     long nSDEErr;
864 
865 
866 
867     nSDEErr = SE_stream_query_raster_tile(poGDS->hStream, constraint);
868     if( nSDEErr != SE_SUCCESS )
869     {
870         IssueSDEError( nSDEErr, "SE_stream_query_raster_tile" );
871         return CE_Fatal;
872     }
873 
874     nSDEErr = SE_stream_get_raster (poGDS->hStream, 1, poGDS->hAttributes);
875     if( nSDEErr != SE_SUCCESS )
876     {
877         IssueSDEError( nSDEErr, "SE_stream_fetch" );
878         return CE_Fatal;
879     }
880 
881     return CE_None;
882 }
883 
884 //T:\>gdal_translate -of GTiff SDE:nakina.gis.iastate.edu,5151,,geoservwrite,EsrI4ever,sde_master.geoservwrite.century foo.tif
885 //T:\>gdalinfo SDE:nakina.gis.iastate.edu,5151,,geoservwrite,EsrI4ever,sde_master.geoservwrite.century
886