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