1 : /******************************************************************************
2 : * $Id: gdalrasterband.cpp 19815 2010-06-07 22:03:41Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Base class for format specific band class implementation. This
6 : * base class provides default implementation for many methods.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1998, Frank Warmerdam
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "gdal_priv.h"
32 : #include "gdal_rat.h"
33 : #include "cpl_string.h"
34 :
35 : #define SUBBLOCK_SIZE 64
36 : #define TO_SUBBLOCK(x) ((x) >> 6)
37 : #define WITHIN_SUBBLOCK(x) ((x) & 0x3f)
38 :
39 : // Number of data samples that will be used to compute approximate statistics
40 : // (minimum value, maximum value, etc.)
41 : #define GDALSTAT_APPROX_NUMSAMPLES 2500
42 :
43 : CPL_CVSID("$Id: gdalrasterband.cpp 19815 2010-06-07 22:03:41Z rouault $");
44 :
45 : /************************************************************************/
46 : /* GDALRasterBand() */
47 : /************************************************************************/
48 :
49 : /*! Constructor. Applications should never create GDALRasterBands directly. */
50 :
51 620420 : GDALRasterBand::GDALRasterBand()
52 :
53 : {
54 620420 : poDS = NULL;
55 620420 : nBand = 0;
56 620420 : nRasterXSize = nRasterYSize = 0;
57 :
58 620420 : eAccess = GA_ReadOnly;
59 620420 : nBlockXSize = nBlockYSize = -1;
60 620420 : eDataType = GDT_Byte;
61 :
62 620420 : nSubBlocksPerRow = nBlocksPerRow = 0;
63 620420 : nSubBlocksPerColumn = nBlocksPerColumn = 0;
64 :
65 620420 : bSubBlockingActive = FALSE;
66 620420 : papoBlocks = NULL;
67 :
68 620420 : poMask = NULL;
69 620420 : bOwnMask = false;
70 620420 : nMaskFlags = 0;
71 :
72 620420 : nBlockReads = 0;
73 : bForceCachedIO = CSLTestBoolean(
74 620420 : CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") );
75 620420 : }
76 :
77 : /************************************************************************/
78 : /* ~GDALRasterBand() */
79 : /************************************************************************/
80 :
81 : /*! Destructor. Applications should never destroy GDALRasterBands directly,
82 : instead destroy the GDALDataset. */
83 :
84 620420 : GDALRasterBand::~GDALRasterBand()
85 :
86 : {
87 620420 : FlushCache();
88 :
89 620420 : CPLFree( papoBlocks );
90 :
91 620420 : if( nBlockReads > nBlocksPerRow * nBlocksPerColumn
92 : && nBand == 1 && poDS != NULL )
93 : {
94 : CPLDebug( "GDAL", "%d block reads on %d block band 1 of %s.",
95 : nBlockReads, nBlocksPerRow * nBlocksPerColumn,
96 52 : poDS->GetDescription() );
97 : }
98 :
99 620420 : if( bOwnMask )
100 : {
101 557 : delete poMask;
102 557 : poMask = NULL;
103 557 : nMaskFlags = 0;
104 557 : bOwnMask = false;
105 : }
106 620420 : }
107 :
108 : /************************************************************************/
109 : /* RasterIO() */
110 : /************************************************************************/
111 :
112 : /**
113 : * \brief Read/write a region of image data for this band.
114 : *
115 : * This method allows reading a region of a GDALRasterBand into a buffer,
116 : * or writing data from a buffer into a region of a GDALRasterBand. It
117 : * automatically takes care of data type translation if the data type
118 : * (eBufType) of the buffer is different than that of the GDALRasterBand.
119 : * The method also takes care of image decimation / replication if the
120 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
121 : * region being accessed (nXSize x nYSize).
122 : *
123 : * The nPixelSpace and nLineSpace parameters allow reading into or
124 : * writing from unusually organized buffers. This is primarily used
125 : * for buffers containing more than one bands raster data in interleaved
126 : * format.
127 : *
128 : * Some formats may efficiently implement decimation into a buffer by
129 : * reading from lower resolution overview images.
130 : *
131 : * For highest performance full resolution data access, read and write
132 : * on "block boundaries" as returned by GetBlockSize(), or use the
133 : * ReadBlock() and WriteBlock() methods.
134 : *
135 : * This method is the same as the C GDALRasterIO() function.
136 : *
137 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
138 : * write a region of data.
139 : *
140 : * @param nXOff The pixel offset to the top left corner of the region
141 : * of the band to be accessed. This would be zero to start from the left side.
142 : *
143 : * @param nYOff The line offset to the top left corner of the region
144 : * of the band to be accessed. This would be zero to start from the top.
145 : *
146 : * @param nXSize The width of the region of the band to be accessed in pixels.
147 : *
148 : * @param nYSize The height of the region of the band to be accessed in lines.
149 : *
150 : * @param pData The buffer into which the data should be read, or from which
151 : * it should be written. This buffer must contain at least nBufXSize *
152 : * nBufYSize words of type eBufType. It is organized in left to right,
153 : * top to bottom pixel order. Spacing is controlled by the nPixelSpace,
154 : * and nLineSpace parameters.
155 : *
156 : * @param nBufXSize the width of the buffer image into which the desired region is
157 : * to be read, or from which it is to be written.
158 : *
159 : * @param nBufYSize the height of the buffer image into which the desired region is
160 : * to be read, or from which it is to be written.
161 : *
162 : * @param eBufType the type of the pixel values in the pData data buffer. The
163 : * pixel values will automatically be translated to/from the GDALRasterBand
164 : * data type as needed.
165 : *
166 : * @param nPixelSpace The byte offset from the start of one pixel value in
167 : * pData to the start of the next pixel value within a scanline. If defaulted
168 : * (0) the size of the datatype eBufType is used.
169 : *
170 : * @param nLineSpace The byte offset from the start of one scanline in
171 : * pData to the start of the next. If defaulted (0) the size of the datatype
172 : * eBufType * nBufXSize is used.
173 : *
174 : * @return CE_Failure if the access fails, otherwise CE_None.
175 : */
176 :
177 : CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
178 : int nXOff, int nYOff, int nXSize, int nYSize,
179 : void * pData, int nBufXSize, int nBufYSize,
180 : GDALDataType eBufType,
181 : int nPixelSpace,
182 425698 : int nLineSpace )
183 :
184 : {
185 :
186 425698 : if( NULL == pData )
187 : {
188 : CPLError( CE_Failure, CPLE_AppDefined,
189 0 : "The buffer into which the data should be read is null" );
190 0 : return CE_Failure;
191 : }
192 :
193 : /* -------------------------------------------------------------------- */
194 : /* Some size values are "noop". Lets just return to avoid */
195 : /* stressing lower level functions. */
196 : /* -------------------------------------------------------------------- */
197 425698 : if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
198 : {
199 : CPLDebug( "GDAL",
200 : "RasterIO() skipped for odd window or buffer size.\n"
201 : " Window = (%d,%d)x%dx%d\n"
202 : " Buffer = %dx%d\n",
203 : nXOff, nYOff, nXSize, nYSize,
204 1 : nBufXSize, nBufYSize );
205 :
206 1 : return CE_None;
207 : }
208 :
209 : /* -------------------------------------------------------------------- */
210 : /* If pixel and line spaceing are defaulted assign reasonable */
211 : /* value assuming a packed buffer. */
212 : /* -------------------------------------------------------------------- */
213 425697 : if( nPixelSpace == 0 )
214 415121 : nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
215 :
216 425697 : if( nLineSpace == 0 )
217 : {
218 415312 : if (nPixelSpace > INT_MAX / nBufXSize)
219 : {
220 : CPLError( CE_Failure, CPLE_AppDefined,
221 0 : "Int overflow : %d x %d", nPixelSpace, nBufXSize );
222 0 : return CE_Failure;
223 : }
224 415312 : nLineSpace = nPixelSpace * nBufXSize;
225 : }
226 :
227 : /* -------------------------------------------------------------------- */
228 : /* Do some validation of parameters. */
229 : /* -------------------------------------------------------------------- */
230 425697 : if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
231 : || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
232 : {
233 : CPLError( CE_Failure, CPLE_IllegalArg,
234 : "Access window out of range in RasterIO(). Requested\n"
235 : "(%d,%d) of size %dx%d on raster of %dx%d.",
236 13213 : nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
237 13213 : return CE_Failure;
238 : }
239 :
240 412484 : if( eRWFlag != GF_Read && eRWFlag != GF_Write )
241 : {
242 : CPLError( CE_Failure, CPLE_IllegalArg,
243 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
244 0 : eRWFlag );
245 0 : return CE_Failure;
246 : }
247 :
248 : /* -------------------------------------------------------------------- */
249 : /* Call the format specific function. */
250 : /* -------------------------------------------------------------------- */
251 412484 : if( bForceCachedIO )
252 : return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
253 : pData, nBufXSize, nBufYSize, eBufType,
254 22 : nPixelSpace, nLineSpace );
255 : else
256 : return IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
257 : pData, nBufXSize, nBufYSize, eBufType,
258 412462 : nPixelSpace, nLineSpace ) ;
259 : }
260 :
261 : /************************************************************************/
262 : /* GDALRasterIO() */
263 : /************************************************************************/
264 :
265 : /**
266 : * \brief Read/write a region of image data for this band.
267 : *
268 : * @see GDALRasterBand::RasterIO()
269 : */
270 :
271 : CPLErr CPL_STDCALL
272 : GDALRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
273 : int nXOff, int nYOff, int nXSize, int nYSize,
274 : void * pData, int nBufXSize, int nBufYSize,
275 : GDALDataType eBufType,
276 364190 : int nPixelSpace, int nLineSpace )
277 :
278 : {
279 364190 : VALIDATE_POINTER1( hBand, "GDALRasterIO", CE_Failure );
280 :
281 364190 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
282 :
283 : return( poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
284 : pData, nBufXSize, nBufYSize, eBufType,
285 364190 : nPixelSpace, nLineSpace ) );
286 : }
287 :
288 : /************************************************************************/
289 : /* ReadBlock() */
290 : /************************************************************************/
291 :
292 : /**
293 : * \brief Read a block of image data efficiently.
294 : *
295 : * This method accesses a "natural" block from the raster band without
296 : * resampling, or data type conversion. For a more generalized, but
297 : * potentially less efficient access use RasterIO().
298 : *
299 : * This method is the same as the C GDALReadBlock() function.
300 : *
301 : * See the GetLockedBlockRef() method for a way of accessing internally cached
302 : * block oriented data without an extra copy into an application buffer.
303 : *
304 : * @param nXBlockOff the horizontal block offset, with zero indicating
305 : * the left most block, 1 the next block and so forth.
306 : *
307 : * @param nYBlockOff the vertical block offset, with zero indicating
308 : * the left most block, 1 the next block and so forth.
309 : *
310 : * @param pImage the buffer into which the data will be read. The buffer
311 : * must be large enough to hold GetBlockXSize()*GetBlockYSize() words
312 : * of type GetRasterDataType().
313 : *
314 : * @return CE_None on success or CE_Failure on an error.
315 : *
316 : * The following code would efficiently compute a histogram of eight bit
317 : * raster data. Note that the final block may be partial ... data beyond
318 : * the edge of the underlying raster band in these edge blocks is of an
319 : * undermined value.
320 : *
321 : <pre>
322 : CPLErr GetHistogram( GDALRasterBand *poBand, int *panHistogram )
323 :
324 : {
325 : int nXBlocks, nYBlocks, nXBlockSize, nYBlockSize;
326 : int iXBlock, iYBlock;
327 : GByte *pabyData;
328 :
329 : memset( panHistogram, 0, sizeof(int) * 256 );
330 :
331 : CPLAssert( poBand->GetRasterDataType() == GDT_Byte );
332 :
333 : poBand->GetBlockSize( &nXBlockSize, &nYBlockSize );
334 : nXBlocks = (poBand->GetXSize() + nXBlockSize - 1) / nXBlockSize;
335 : nYBlocks = (poBand->GetYSize() + nYBlockSize - 1) / nYBlockSize;
336 :
337 : pabyData = (GByte *) CPLMalloc(nXBlockSize * nYBlockSize);
338 :
339 : for( iYBlock = 0; iYBlock < nYBlocks; iYBlock++ )
340 : {
341 : for( iXBlock = 0; iXBlock < nXBlocks; iXBlock++ )
342 : {
343 : int nXValid, nYValid;
344 :
345 : poBand->ReadBlock( iXBlock, iYBlock, pabyData );
346 :
347 : // Compute the portion of the block that is valid
348 : // for partial edge blocks.
349 : if( (iXBlock+1) * nXBlockSize > poBand->GetXSize() )
350 : nXValid = poBand->GetXSize() - iXBlock * nXBlockSize;
351 : else
352 : nXValid = nXBlockSize;
353 :
354 : if( (iYBlock+1) * nYBlockSize > poBand->GetYSize() )
355 : nYValid = poBand->GetYSize() - iYBlock * nYBlockSize;
356 : else
357 : nYValid = nYBlockSize;
358 :
359 : // Collect the histogram counts.
360 : for( int iY = 0; iY < nYValid; iY++ )
361 : {
362 : for( int iX = 0; iX < nXValid; iX++ )
363 : {
364 : panHistogram[pabyData[iX + iY * nXBlockSize]] += 1;
365 : }
366 : }
367 : }
368 : }
369 : }
370 :
371 : </pre>
372 : */
373 :
374 :
375 : CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
376 180 : void * pImage )
377 :
378 : {
379 : /* -------------------------------------------------------------------- */
380 : /* Validate arguments. */
381 : /* -------------------------------------------------------------------- */
382 180 : CPLAssert( pImage != NULL );
383 :
384 180 : if( !InitBlockInfo() )
385 0 : return CE_Failure;
386 :
387 180 : if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
388 : {
389 : CPLError( CE_Failure, CPLE_IllegalArg,
390 : "Illegal nXBlockOff value (%d) in "
391 : "GDALRasterBand::ReadBlock()\n",
392 0 : nXBlockOff );
393 :
394 0 : return( CE_Failure );
395 : }
396 :
397 180 : if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
398 : {
399 : CPLError( CE_Failure, CPLE_IllegalArg,
400 : "Illegal nYBlockOff value (%d) in "
401 : "GDALRasterBand::ReadBlock()\n",
402 0 : nYBlockOff );
403 :
404 0 : return( CE_Failure );
405 : }
406 :
407 : /* -------------------------------------------------------------------- */
408 : /* Invoke underlying implementation method. */
409 : /* -------------------------------------------------------------------- */
410 180 : return( IReadBlock( nXBlockOff, nYBlockOff, pImage ) );
411 : }
412 :
413 : /************************************************************************/
414 : /* GDALReadBlock() */
415 : /************************************************************************/
416 :
417 : /**
418 : * \brief Read a block of image data efficiently.
419 : *
420 : * @see GDALRasterBand::ReadBlock()
421 : */
422 :
423 : CPLErr CPL_STDCALL GDALReadBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
424 0 : void * pData )
425 :
426 : {
427 0 : VALIDATE_POINTER1( hBand, "GDALReadBlock", CE_Failure );
428 :
429 0 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
430 0 : return( poBand->ReadBlock( nXOff, nYOff, pData ) );
431 : }
432 :
433 : /************************************************************************/
434 : /* IWriteBlock() */
435 : /* */
436 : /* Default internal implementation ... to be overriden by */
437 : /* subclasses that support writing. */
438 : /************************************************************************/
439 :
440 0 : CPLErr GDALRasterBand::IWriteBlock( int, int, void * )
441 :
442 : {
443 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
444 : CPLError( CE_Failure, CPLE_NotSupported,
445 0 : "WriteBlock() not supported for this dataset." );
446 :
447 0 : return( CE_Failure );
448 : }
449 :
450 : /************************************************************************/
451 : /* WriteBlock() */
452 : /************************************************************************/
453 :
454 : /**
455 : * \brief Write a block of image data efficiently.
456 : *
457 : * This method accesses a "natural" block from the raster band without
458 : * resampling, or data type conversion. For a more generalized, but
459 : * potentially less efficient access use RasterIO().
460 : *
461 : * This method is the same as the C GDALWriteBlock() function.
462 : *
463 : * See ReadBlock() for an example of block oriented data access.
464 : *
465 : * @param nXBlockOff the horizontal block offset, with zero indicating
466 : * the left most block, 1 the next block and so forth.
467 : *
468 : * @param nYBlockOff the vertical block offset, with zero indicating
469 : * the left most block, 1 the next block and so forth.
470 : *
471 : * @param pImage the buffer from which the data will be written. The buffer
472 : * must be large enough to hold GetBlockXSize()*GetBlockYSize() words
473 : * of type GetRasterDataType().
474 : *
475 : * @return CE_None on success or CE_Failure on an error.
476 : */
477 :
478 : CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
479 0 : void * pImage )
480 :
481 : {
482 : /* -------------------------------------------------------------------- */
483 : /* Validate arguments. */
484 : /* -------------------------------------------------------------------- */
485 0 : CPLAssert( pImage != NULL );
486 :
487 0 : if( !InitBlockInfo() )
488 0 : return CE_Failure;
489 :
490 0 : if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
491 : {
492 : CPLError( CE_Failure, CPLE_IllegalArg,
493 : "Illegal nXBlockOff value (%d) in "
494 : "GDALRasterBand::WriteBlock()\n",
495 0 : nXBlockOff );
496 :
497 0 : return( CE_Failure );
498 : }
499 :
500 0 : if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
501 : {
502 : CPLError( CE_Failure, CPLE_IllegalArg,
503 : "Illegal nYBlockOff value (%d) in "
504 : "GDALRasterBand::WriteBlock()\n",
505 0 : nYBlockOff );
506 :
507 0 : return( CE_Failure );
508 : }
509 :
510 0 : if( eAccess == GA_ReadOnly )
511 : {
512 : CPLError( CE_Failure, CPLE_NoWriteAccess,
513 : "Attempt to write to read only dataset in"
514 0 : "GDALRasterBand::WriteBlock().\n" );
515 :
516 0 : return( CE_Failure );
517 : }
518 :
519 : /* -------------------------------------------------------------------- */
520 : /* Invoke underlying implementation method. */
521 : /* -------------------------------------------------------------------- */
522 0 : return( IWriteBlock( nXBlockOff, nYBlockOff, pImage ) );
523 : }
524 :
525 : /************************************************************************/
526 : /* GDALWriteBlock() */
527 : /************************************************************************/
528 :
529 : /**
530 : * \brief Write a block of image data efficiently.
531 : *
532 : * @see GDALRasterBand::WriteBlock()
533 : */
534 :
535 : CPLErr CPL_STDCALL GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
536 0 : void * pData )
537 :
538 : {
539 0 : VALIDATE_POINTER1( hBand, "GDALWriteBlock", CE_Failure );
540 :
541 0 : GDALRasterBand *poBand = static_cast<GDALRasterBand *>( hBand );
542 0 : return( poBand->WriteBlock( nXOff, nYOff, pData ) );
543 : }
544 :
545 :
546 : /************************************************************************/
547 : /* GetRasterDataType() */
548 : /************************************************************************/
549 :
550 : /**
551 : * \brief Fetch the pixel data type for this band.
552 : *
553 : * @return the data type of pixels for this band.
554 : */
555 :
556 :
557 614741 : GDALDataType GDALRasterBand::GetRasterDataType()
558 :
559 : {
560 614741 : return eDataType;
561 : }
562 :
563 : /************************************************************************/
564 : /* GDALGetRasterDataType() */
565 : /************************************************************************/
566 :
567 : /**
568 : * \brief Fetch the pixel data type for this band.
569 : *
570 : * @see GDALRasterBand::GetRasterDataType()
571 : */
572 :
573 4961 : GDALDataType CPL_STDCALL GDALGetRasterDataType( GDALRasterBandH hBand )
574 :
575 : {
576 4961 : VALIDATE_POINTER1( hBand, "GDALGetRasterDataType", GDT_Unknown );
577 :
578 4961 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
579 4961 : return poBand->GetRasterDataType();
580 : }
581 :
582 : /************************************************************************/
583 : /* GetBlockSize() */
584 : /************************************************************************/
585 :
586 : /**
587 : * \brief Fetch the "natural" block size of this band.
588 : *
589 : * GDAL contains a concept of the natural block size of rasters so that
590 : * applications can organized data access efficiently for some file formats.
591 : * The natural block size is the block size that is most efficient for
592 : * accessing the format. For many formats this is simple a whole scanline
593 : * in which case *pnXSize is set to GetXSize(), and *pnYSize is set to 1.
594 : *
595 : * However, for tiled images this will typically be the tile size.
596 : *
597 : * Note that the X and Y block sizes don't have to divide the image size
598 : * evenly, meaning that right and bottom edge blocks may be incomplete.
599 : * See ReadBlock() for an example of code dealing with these issues.
600 : *
601 : * @param pnXSize integer to put the X block size into or NULL.
602 : *
603 : * @param pnYSize integer to put the Y block size into or NULL.
604 : */
605 :
606 294052 : void GDALRasterBand::GetBlockSize( int * pnXSize, int *pnYSize )
607 :
608 : {
609 294052 : if( nBlockXSize <= 0 || nBlockYSize <= 0 )
610 : {
611 : CPLError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
612 0 : nBlockXSize, nBlockYSize );
613 0 : if( pnXSize != NULL )
614 0 : *pnXSize = 0;
615 0 : if( pnYSize != NULL )
616 0 : *pnYSize = 0;
617 : }
618 : else
619 : {
620 294052 : if( pnXSize != NULL )
621 294052 : *pnXSize = nBlockXSize;
622 294052 : if( pnYSize != NULL )
623 294052 : *pnYSize = nBlockYSize;
624 : }
625 294052 : }
626 :
627 : /************************************************************************/
628 : /* GDALGetBlockSize() */
629 : /************************************************************************/
630 :
631 : /**
632 : * \brief Fetch the "natural" block size of this band.
633 : *
634 : * @see GDALRasterBand::GetBlockSize()
635 : */
636 :
637 : void CPL_STDCALL
638 759 : GDALGetBlockSize( GDALRasterBandH hBand, int * pnXSize, int * pnYSize )
639 :
640 : {
641 759 : VALIDATE_POINTER0( hBand, "GDALGetBlockSize" );
642 :
643 759 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
644 759 : poBand->GetBlockSize( pnXSize, pnYSize );
645 : }
646 :
647 : /************************************************************************/
648 : /* InitBlockInfo() */
649 : /************************************************************************/
650 :
651 4774917 : int GDALRasterBand::InitBlockInfo()
652 :
653 : {
654 4774917 : if( papoBlocks != NULL )
655 4704101 : return TRUE;
656 :
657 : /* Do some validation of raster and block dimensions in case the driver */
658 : /* would have neglected to do it itself */
659 70816 : if( nBlockXSize <= 0 || nBlockYSize <= 0 )
660 : {
661 : CPLError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
662 0 : nBlockXSize, nBlockYSize );
663 0 : return FALSE;
664 : }
665 :
666 70816 : if( nRasterXSize <= 0 || nRasterYSize <= 0 )
667 : {
668 : CPLError( CE_Failure, CPLE_AppDefined, "Invalid raster dimension : %d * %d",
669 0 : nRasterXSize, nRasterYSize );
670 0 : return FALSE;
671 : }
672 :
673 70816 : if (nBlockXSize >= 10000 || nBlockYSize >= 10000)
674 : {
675 : /* Check that the block size is not overflowing int capacity as it is */
676 : /* (reasonnably) assumed in many places (GDALRasterBlock::Internalize(), */
677 : /* GDALRasterBand::Fill(), many drivers...) */
678 : /* As 10000 * 10000 * 16 < INT_MAX, we don't need to do the multiplication in other cases */
679 :
680 5 : int nSizeInBytes = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
681 :
682 5 : GIntBig nBigSizeInBytes = (GIntBig)nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
683 5 : if ((GIntBig)nSizeInBytes != nBigSizeInBytes)
684 : {
685 : CPLError( CE_Failure, CPLE_NotSupported, "Too big block : %d * %d",
686 0 : nBlockXSize, nBlockYSize );
687 0 : return FALSE;
688 : }
689 : }
690 :
691 : /* Check for overflows in computation of nBlocksPerRow and nBlocksPerColumn */
692 70816 : if (nRasterXSize > INT_MAX - (nBlockXSize-1))
693 : {
694 : CPLError( CE_Failure, CPLE_NotSupported, "Inappropriate raster width (%d) for block width (%d)",
695 0 : nRasterXSize, nBlockXSize );
696 0 : return FALSE;
697 : }
698 :
699 70816 : if (nRasterYSize > INT_MAX - (nBlockYSize-1))
700 : {
701 : CPLError( CE_Failure, CPLE_NotSupported, "Inappropriate raster height (%d) for block height (%d)",
702 0 : nRasterYSize, nBlockYSize );
703 0 : return FALSE;
704 : }
705 :
706 70816 : nBlocksPerRow = (nRasterXSize+nBlockXSize-1) / nBlockXSize;
707 70816 : nBlocksPerColumn = (nRasterYSize+nBlockYSize-1) / nBlockYSize;
708 :
709 70816 : if( nBlocksPerRow < SUBBLOCK_SIZE/2 )
710 : {
711 70768 : bSubBlockingActive = FALSE;
712 :
713 70768 : if (nBlocksPerRow < INT_MAX / nBlocksPerColumn)
714 : {
715 : papoBlocks = (GDALRasterBlock **)
716 70768 : VSICalloc( sizeof(void*), nBlocksPerRow * nBlocksPerColumn );
717 : }
718 : else
719 : {
720 : CPLError( CE_Failure, CPLE_NotSupported, "Too many blocks : %d x %d",
721 0 : nBlocksPerRow, nBlocksPerColumn );
722 0 : return FALSE;
723 : }
724 : }
725 : else
726 : {
727 : /* Check for overflows in computation of nSubBlocksPerRow and nSubBlocksPerColumn */
728 48 : if (nBlocksPerRow > INT_MAX - (SUBBLOCK_SIZE+1))
729 : {
730 : CPLError( CE_Failure, CPLE_NotSupported, "Inappropriate raster width (%d) for block width (%d)",
731 0 : nRasterXSize, nBlockXSize );
732 0 : return FALSE;
733 : }
734 :
735 48 : if (nBlocksPerColumn > INT_MAX - (SUBBLOCK_SIZE+1))
736 : {
737 : CPLError( CE_Failure, CPLE_NotSupported, "Inappropriate raster height (%d) for block height (%d)",
738 0 : nRasterYSize, nBlockYSize );
739 0 : return FALSE;
740 : }
741 :
742 48 : bSubBlockingActive = TRUE;
743 :
744 48 : nSubBlocksPerRow = (nBlocksPerRow + SUBBLOCK_SIZE + 1)/SUBBLOCK_SIZE;
745 48 : nSubBlocksPerColumn = (nBlocksPerColumn + SUBBLOCK_SIZE + 1)/SUBBLOCK_SIZE;
746 :
747 48 : if (nSubBlocksPerRow < INT_MAX / nSubBlocksPerColumn)
748 : {
749 : papoBlocks = (GDALRasterBlock **)
750 48 : VSICalloc( sizeof(void*), nSubBlocksPerRow * nSubBlocksPerColumn );
751 : }
752 : else
753 : {
754 : CPLError( CE_Failure, CPLE_NotSupported, "Too many subblocks : %d x %d",
755 0 : nSubBlocksPerRow, nSubBlocksPerColumn );
756 0 : return FALSE;
757 : }
758 : }
759 :
760 70816 : if( papoBlocks == NULL )
761 : {
762 : CPLError( CE_Failure, CPLE_OutOfMemory,
763 0 : "Out of memory in InitBlockInfo()." );
764 0 : return FALSE;
765 : }
766 :
767 70816 : return TRUE;
768 : }
769 :
770 : /************************************************************************/
771 : /* AdoptBlock() */
772 : /* */
773 : /* Add a block to the raster band's block matrix. If this */
774 : /* exceeds our maximum blocks for this layer, flush the oldest */
775 : /* block out. */
776 : /* */
777 : /* This method is protected. */
778 : /************************************************************************/
779 :
780 : CPLErr GDALRasterBand::AdoptBlock( int nXBlockOff, int nYBlockOff,
781 288957 : GDALRasterBlock * poBlock )
782 :
783 : {
784 : int nBlockIndex;
785 :
786 288957 : if( !InitBlockInfo() )
787 0 : return CE_Failure;
788 :
789 : /* -------------------------------------------------------------------- */
790 : /* Simple case without subblocking. */
791 : /* -------------------------------------------------------------------- */
792 288957 : if( !bSubBlockingActive )
793 : {
794 268203 : nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
795 :
796 268203 : if( papoBlocks[nBlockIndex] == poBlock )
797 0 : return( CE_None );
798 :
799 268203 : if( papoBlocks[nBlockIndex] != NULL )
800 0 : FlushBlock( nXBlockOff, nYBlockOff );
801 :
802 268203 : papoBlocks[nBlockIndex] = poBlock;
803 268203 : poBlock->Touch();
804 :
805 268203 : return( CE_None );
806 : }
807 :
808 : /* -------------------------------------------------------------------- */
809 : /* Identify the subblock in which our target occurs, and create */
810 : /* it if necessary. */
811 : /* -------------------------------------------------------------------- */
812 : int nSubBlock = TO_SUBBLOCK(nXBlockOff)
813 20754 : + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
814 :
815 20754 : if( papoBlocks[nSubBlock] == NULL )
816 : {
817 : int nSubGridSize =
818 92 : sizeof(GDALRasterBlock*) * SUBBLOCK_SIZE * SUBBLOCK_SIZE;
819 :
820 92 : papoBlocks[nSubBlock] = (GDALRasterBlock *) VSIMalloc(nSubGridSize);
821 92 : if( papoBlocks[nSubBlock] == NULL )
822 : {
823 : CPLError( CE_Failure, CPLE_OutOfMemory,
824 0 : "Out of memory in AdoptBlock()." );
825 0 : return CE_Failure;
826 : }
827 :
828 92 : memset( papoBlocks[nSubBlock], 0, nSubGridSize );
829 : }
830 :
831 : /* -------------------------------------------------------------------- */
832 : /* Check within subblock. */
833 : /* -------------------------------------------------------------------- */
834 : GDALRasterBlock **papoSubBlockGrid =
835 20754 : (GDALRasterBlock **) papoBlocks[nSubBlock];
836 :
837 : int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
838 20754 : + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
839 :
840 20754 : if( papoSubBlockGrid[nBlockInSubBlock] == poBlock )
841 0 : return CE_None;
842 :
843 20754 : if( papoSubBlockGrid[nBlockInSubBlock] != NULL )
844 0 : FlushBlock( nXBlockOff, nYBlockOff );
845 :
846 20754 : papoSubBlockGrid[nBlockInSubBlock] = poBlock;
847 20754 : poBlock->Touch();
848 :
849 20754 : return CE_None;
850 : }
851 :
852 : /************************************************************************/
853 : /* FlushCache() */
854 : /************************************************************************/
855 :
856 : /**
857 : * \brief Flush raster data cache.
858 : *
859 : * This call will recover memory used to cache data blocks for this raster
860 : * band, and ensure that new requests are referred to the underlying driver.
861 : *
862 : * This method is the same as the C function GDALFlushRasterCache().
863 : *
864 : * @return CE_None on success.
865 : */
866 :
867 1641360 : CPLErr GDALRasterBand::FlushCache()
868 :
869 : {
870 1641360 : if (papoBlocks == NULL)
871 1429674 : return CE_None;
872 :
873 : /* -------------------------------------------------------------------- */
874 : /* Flush all blocks in memory ... this case is without subblocking.*/
875 : /* -------------------------------------------------------------------- */
876 211686 : if( !bSubBlockingActive )
877 : {
878 1473162 : for( int iY = 0; iY < nBlocksPerColumn; iY++ )
879 : {
880 2541981 : for( int iX = 0; iX < nBlocksPerRow; iX++ )
881 : {
882 1280411 : if( papoBlocks[iX + iY*nBlocksPerRow] != NULL )
883 : {
884 : CPLErr eErr;
885 :
886 267559 : eErr = FlushBlock( iX, iY );
887 :
888 267559 : if( eErr != CE_None )
889 0 : return eErr;
890 : }
891 : }
892 : }
893 211592 : return CE_None;
894 : }
895 :
896 : /* -------------------------------------------------------------------- */
897 : /* With subblocking. We can short circuit missing subblocks. */
898 : /* -------------------------------------------------------------------- */
899 : int iSBX, iSBY;
900 :
901 224 : for( iSBY = 0; iSBY < nSubBlocksPerColumn; iSBY++ )
902 : {
903 543 : for( iSBX = 0; iSBX < nSubBlocksPerRow; iSBX++ )
904 : {
905 413 : int nSubBlock = iSBX + iSBY * nSubBlocksPerRow;
906 :
907 : GDALRasterBlock **papoSubBlockGrid =
908 413 : (GDALRasterBlock **) papoBlocks[nSubBlock];
909 :
910 413 : if( papoSubBlockGrid == NULL )
911 321 : continue;
912 :
913 5980 : for( int iY = 0; iY < SUBBLOCK_SIZE; iY++ )
914 : {
915 382720 : for( int iX = 0; iX < SUBBLOCK_SIZE; iX++ )
916 : {
917 376832 : if( papoSubBlockGrid[iX + iY * SUBBLOCK_SIZE] != NULL )
918 : {
919 : CPLErr eErr;
920 :
921 : eErr = FlushBlock( iX + iSBX * SUBBLOCK_SIZE,
922 20753 : iY + iSBY * SUBBLOCK_SIZE );
923 20753 : if( eErr != CE_None )
924 0 : return eErr;
925 : }
926 : }
927 : }
928 :
929 : // We might as well get rid of this grid chunk since we know
930 : // it is now empty.
931 92 : papoBlocks[nSubBlock] = NULL;
932 92 : CPLFree( papoSubBlockGrid );
933 : }
934 : }
935 :
936 94 : return( CE_None );
937 : }
938 :
939 : /************************************************************************/
940 : /* GDALFlushRasterCache() */
941 : /************************************************************************/
942 :
943 : /**
944 : * \brief Flush raster data cache.
945 : *
946 : * @see GDALRasterBand::FlushCache()
947 : */
948 :
949 8 : CPLErr CPL_STDCALL GDALFlushRasterCache( GDALRasterBandH hBand )
950 :
951 : {
952 8 : VALIDATE_POINTER1( hBand, "GDALFlushRasterCache", CE_Failure );
953 :
954 8 : return ((GDALRasterBand *) hBand)->FlushCache();
955 : }
956 :
957 : /************************************************************************/
958 : /* FlushBlock() */
959 : /* */
960 : /* Flush a block out of the block cache. If it has been */
961 : /* modified write it to disk. If no specific tile is */
962 : /* indicated, write the oldest tile. */
963 : /* */
964 : /* Protected method. */
965 : /************************************************************************/
966 :
967 288957 : CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff )
968 :
969 : {
970 : int nBlockIndex;
971 288957 : GDALRasterBlock *poBlock = NULL;
972 :
973 288957 : if( !papoBlocks )
974 0 : return CE_None;
975 :
976 : /* -------------------------------------------------------------------- */
977 : /* Validate the request */
978 : /* -------------------------------------------------------------------- */
979 288957 : if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
980 : {
981 : CPLError( CE_Failure, CPLE_IllegalArg,
982 : "Illegal nBlockXOff value (%d) in "
983 : "GDALRasterBand::FlushBlock()\n",
984 0 : nXBlockOff );
985 :
986 0 : return( CE_Failure );
987 : }
988 :
989 288957 : if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
990 : {
991 : CPLError( CE_Failure, CPLE_IllegalArg,
992 : "Illegal nBlockYOff value (%d) in "
993 : "GDALRasterBand::FlushBlock()\n",
994 0 : nYBlockOff );
995 :
996 0 : return( CE_Failure );
997 : }
998 :
999 : /* -------------------------------------------------------------------- */
1000 : /* Simple case for single level caches. */
1001 : /* -------------------------------------------------------------------- */
1002 288957 : if( !bSubBlockingActive )
1003 : {
1004 268203 : nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
1005 :
1006 268203 : GDALRasterBlock::SafeLockBlock( papoBlocks + nBlockIndex );
1007 :
1008 268203 : poBlock = papoBlocks[nBlockIndex];
1009 268203 : papoBlocks[nBlockIndex] = NULL;
1010 : }
1011 :
1012 : /* -------------------------------------------------------------------- */
1013 : /* Identify our subblock. */
1014 : /* -------------------------------------------------------------------- */
1015 : else
1016 : {
1017 : int nSubBlock = TO_SUBBLOCK(nXBlockOff)
1018 20754 : + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
1019 :
1020 20754 : if( papoBlocks[nSubBlock] == NULL )
1021 0 : return CE_None;
1022 :
1023 : /* -------------------------------------------------------------------- */
1024 : /* Check within subblock. */
1025 : /* -------------------------------------------------------------------- */
1026 : GDALRasterBlock **papoSubBlockGrid =
1027 20754 : (GDALRasterBlock **) papoBlocks[nSubBlock];
1028 :
1029 : int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
1030 20754 : + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
1031 :
1032 20754 : GDALRasterBlock::SafeLockBlock( papoSubBlockGrid + nBlockInSubBlock );
1033 :
1034 20754 : poBlock = papoSubBlockGrid[nBlockInSubBlock];
1035 20754 : papoSubBlockGrid[nBlockInSubBlock] = NULL;
1036 : }
1037 :
1038 : /* -------------------------------------------------------------------- */
1039 : /* Is the target block dirty? If so we need to write it. */
1040 : /* -------------------------------------------------------------------- */
1041 288957 : CPLErr eErr = CE_None;
1042 :
1043 288957 : if( poBlock == NULL )
1044 0 : return CE_None;
1045 :
1046 288957 : poBlock->Detach();
1047 :
1048 288957 : if( poBlock->GetDirty() )
1049 28892 : eErr = poBlock->Write();
1050 :
1051 : /* -------------------------------------------------------------------- */
1052 : /* Deallocate the block; */
1053 : /* -------------------------------------------------------------------- */
1054 288957 : poBlock->DropLock();
1055 288957 : delete poBlock;
1056 :
1057 288957 : return eErr;
1058 : }
1059 :
1060 : /************************************************************************/
1061 : /* TryGetLockedBlockRef() */
1062 : /************************************************************************/
1063 :
1064 : /**
1065 : * \brief Try fetching block ref.
1066 : *
1067 : * This method will returned the requested block (locked) if it is already
1068 : * in the block cache for the layer. If not, NULL is returned.
1069 : *
1070 : * If a non-NULL value is returned, then a lock for the block will have been
1071 : * acquired on behalf of the caller. It is absolutely imperative that the
1072 : * caller release this lock (with GDALRasterBlock::DropLock()) or else
1073 : * severe problems may result.
1074 : *
1075 : * @param nBlockXOff the horizontal block offset, with zero indicating
1076 : * the left most block, 1 the next block and so forth.
1077 : *
1078 : * @param nYBlockOff the vertical block offset, with zero indicating
1079 : * the top most block, 1 the next block and so forth.
1080 : *
1081 : * @return NULL if block not available, or locked block pointer.
1082 : */
1083 :
1084 : GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
1085 4027979 : int nYBlockOff )
1086 :
1087 : {
1088 4027979 : int nBlockIndex = 0;
1089 :
1090 4027979 : if( !InitBlockInfo() )
1091 0 : return( NULL );
1092 :
1093 : /* -------------------------------------------------------------------- */
1094 : /* Validate the request */
1095 : /* -------------------------------------------------------------------- */
1096 4027979 : if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
1097 : {
1098 : CPLError( CE_Failure, CPLE_IllegalArg,
1099 : "Illegal nBlockXOff value (%d) in "
1100 : "GDALRasterBand::TryGetLockedBlockRef()\n",
1101 0 : nXBlockOff );
1102 :
1103 0 : return( NULL );
1104 : }
1105 :
1106 4027979 : if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
1107 : {
1108 : CPLError( CE_Failure, CPLE_IllegalArg,
1109 : "Illegal nBlockYOff value (%d) in "
1110 : "GDALRasterBand::TryGetLockedBlockRef()\n",
1111 0 : nYBlockOff );
1112 :
1113 0 : return( NULL );
1114 : }
1115 :
1116 : /* -------------------------------------------------------------------- */
1117 : /* Simple case for single level caches. */
1118 : /* -------------------------------------------------------------------- */
1119 4027979 : if( !bSubBlockingActive )
1120 : {
1121 2497209 : nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
1122 :
1123 2497209 : GDALRasterBlock::SafeLockBlock( papoBlocks + nBlockIndex );
1124 :
1125 2497209 : return papoBlocks[nBlockIndex];
1126 : }
1127 :
1128 : /* -------------------------------------------------------------------- */
1129 : /* Identify our subblock. */
1130 : /* -------------------------------------------------------------------- */
1131 : int nSubBlock = TO_SUBBLOCK(nXBlockOff)
1132 1530770 : + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
1133 :
1134 1530770 : if( papoBlocks[nSubBlock] == NULL )
1135 96 : return NULL;
1136 :
1137 : /* -------------------------------------------------------------------- */
1138 : /* Check within subblock. */
1139 : /* -------------------------------------------------------------------- */
1140 : GDALRasterBlock **papoSubBlockGrid =
1141 1530674 : (GDALRasterBlock **) papoBlocks[nSubBlock];
1142 :
1143 : int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
1144 1530674 : + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
1145 :
1146 1530674 : GDALRasterBlock::SafeLockBlock( papoSubBlockGrid + nBlockInSubBlock );
1147 :
1148 1530674 : return papoSubBlockGrid[nBlockInSubBlock];
1149 : }
1150 :
1151 : /************************************************************************/
1152 : /* GetLockedBlockRef() */
1153 : /************************************************************************/
1154 :
1155 : /**
1156 : * \brief Fetch a pointer to an internally cached raster block.
1157 : *
1158 : * This method will returned the requested block (locked) if it is already
1159 : * in the block cache for the layer. If not, the block will be read from
1160 : * the driver, and placed in the layer block cached, then returned. If an
1161 : * error occurs reading the block from the driver, a NULL value will be
1162 : * returned.
1163 : *
1164 : * If a non-NULL value is returned, then a lock for the block will have been
1165 : * acquired on behalf of the caller. It is absolutely imperative that the
1166 : * caller release this lock (with GDALRasterBlock::DropLock()) or else
1167 : * severe problems may result.
1168 : *
1169 : * Note that calling GetLockedBlockRef() on a previously uncached band will
1170 : * enable caching.
1171 : *
1172 : * @param nBlockXOff the horizontal block offset, with zero indicating
1173 : * the left most block, 1 the next block and so forth.
1174 : *
1175 : * @param nYBlockOff the vertical block offset, with zero indicating
1176 : * the top most block, 1 the next block and so forth.
1177 : *
1178 : * @param bJustInitialize If TRUE the block will be allocated and initialized,
1179 : * but not actually read from the source. This is useful when it will just
1180 : * be completely set and written back.
1181 : *
1182 : * @return pointer to the block object, or NULL on failure.
1183 : */
1184 :
1185 : GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
1186 : int nYBlockOff,
1187 4026373 : int bJustInitialize )
1188 :
1189 : {
1190 4026373 : GDALRasterBlock *poBlock = NULL;
1191 :
1192 : /* -------------------------------------------------------------------- */
1193 : /* Try and fetch from cache. */
1194 : /* -------------------------------------------------------------------- */
1195 4026373 : poBlock = TryGetLockedBlockRef( nXBlockOff, nYBlockOff );
1196 :
1197 : /* -------------------------------------------------------------------- */
1198 : /* If we didn't find it in our memory cache, instantiate a */
1199 : /* block (potentially load from disk) and "adopt" it into the */
1200 : /* cache. */
1201 : /* -------------------------------------------------------------------- */
1202 4026373 : if( poBlock == NULL )
1203 : {
1204 288957 : if( !InitBlockInfo() )
1205 0 : return( NULL );
1206 :
1207 : /* -------------------------------------------------------------------- */
1208 : /* Validate the request */
1209 : /* -------------------------------------------------------------------- */
1210 288957 : if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
1211 : {
1212 : CPLError( CE_Failure, CPLE_IllegalArg,
1213 : "Illegal nBlockXOff value (%d) in "
1214 : "GDALRasterBand::GetLockedBlockRef()\n",
1215 0 : nXBlockOff );
1216 :
1217 0 : return( NULL );
1218 : }
1219 :
1220 288957 : if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
1221 : {
1222 : CPLError( CE_Failure, CPLE_IllegalArg,
1223 : "Illegal nBlockYOff value (%d) in "
1224 : "GDALRasterBand::GetLockedBlockRef()\n",
1225 0 : nYBlockOff );
1226 :
1227 0 : return( NULL );
1228 : }
1229 :
1230 288957 : poBlock = new GDALRasterBlock( this, nXBlockOff, nYBlockOff );
1231 :
1232 288957 : poBlock->AddLock();
1233 :
1234 : /* allocate data space */
1235 288957 : if( poBlock->Internalize() != CE_None )
1236 : {
1237 0 : poBlock->DropLock();
1238 0 : delete poBlock;
1239 0 : return( NULL );
1240 : }
1241 :
1242 288957 : if ( AdoptBlock( nXBlockOff, nYBlockOff, poBlock ) != CE_None )
1243 : {
1244 0 : poBlock->DropLock();
1245 0 : delete poBlock;
1246 0 : return( NULL );
1247 : }
1248 :
1249 288957 : if( !bJustInitialize
1250 : && IReadBlock(nXBlockOff,nYBlockOff,poBlock->GetDataRef()) != CE_None)
1251 : {
1252 11 : poBlock->DropLock();
1253 11 : FlushBlock( nXBlockOff, nYBlockOff );
1254 : CPLError( CE_Failure, CPLE_AppDefined,
1255 : "IReadBlock failed at X offset %d, Y offset %d",
1256 11 : nXBlockOff, nYBlockOff );
1257 11 : return( NULL );
1258 : }
1259 :
1260 288946 : if( !bJustInitialize )
1261 : {
1262 264984 : nBlockReads++;
1263 264984 : if( nBlockReads == nBlocksPerRow * nBlocksPerColumn + 1
1264 : && nBand == 1 && poDS != NULL )
1265 : {
1266 : CPLDebug( "GDAL", "Potential thrashing on band %d of %s.",
1267 52 : nBand, poDS->GetDescription() );
1268 : }
1269 : }
1270 : }
1271 :
1272 4026362 : return poBlock;
1273 : }
1274 :
1275 : /************************************************************************/
1276 : /* Fill() */
1277 : /************************************************************************/
1278 :
1279 : /**
1280 : * \brief Fill this band with a constant value.
1281 : *
1282 : * GDAL makes no guarantees
1283 : * about what values pixels in newly created files are set to, so this
1284 : * method can be used to clear a band to a specified "default" value.
1285 : * The fill value is passed in as a double but this will be converted
1286 : * to the underlying type before writing to the file. An optional
1287 : * second argument allows the imaginary component of a complex
1288 : * constant value to be specified.
1289 : *
1290 : * @param dfRealvalue Real component of fill value
1291 : * @param dfImaginaryValue Imaginary component of fill value, defaults to zero
1292 : *
1293 : * @return CE_Failure if the write fails, otherwise CE_None
1294 : */
1295 167996 : CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
1296 :
1297 : // General approach is to construct a source block of the file's
1298 : // native type containing the appropriate value and then copy this
1299 : // to each block in the image via the the RasterBlock cache. Using
1300 : // the cache means we avoid file I/O if it's not necessary, at the
1301 : // expense of some extra memcpy's (since we write to the
1302 : // RasterBlock cache, which is then at some point written to the
1303 : // underlying file, rather than simply directly to the underlying
1304 : // file.)
1305 :
1306 : // Check we can write to the file
1307 167996 : if( eAccess == GA_ReadOnly ) {
1308 : CPLError(CE_Failure, CPLE_NoWriteAccess,
1309 : "Attempt to write to read only dataset in"
1310 0 : "GDALRasterBand::Fill().\n" );
1311 0 : return CE_Failure;
1312 : }
1313 :
1314 : // Make sure block parameters are set
1315 167996 : if( !InitBlockInfo() )
1316 0 : return CE_Failure;
1317 :
1318 : // Allocate the source block
1319 167996 : int blockSize = nBlockXSize * nBlockYSize;
1320 167996 : int elementSize = GDALGetDataTypeSize(eDataType) / 8;
1321 167996 : int blockByteSize = blockSize * elementSize;
1322 167996 : unsigned char* srcBlock = (unsigned char*) VSIMalloc(blockByteSize);
1323 167996 : if (srcBlock == NULL) {
1324 : CPLError(CE_Failure, CPLE_OutOfMemory,
1325 : "GDALRasterBand::Fill(): Out of memory "
1326 0 : "allocating %d bytes.\n", blockByteSize);
1327 0 : return CE_Failure;
1328 : }
1329 :
1330 : // Initialize the first element of the block, doing type conversion
1331 167996 : double complexSrc[2] = { dfRealValue, dfImaginaryValue };
1332 167996 : GDALCopyWords(complexSrc, GDT_CFloat64, 0, srcBlock, eDataType, 0, 1);
1333 :
1334 : // Copy first element to the rest of the block
1335 38837055 : for (unsigned char* blockPtr = srcBlock + elementSize;
1336 : blockPtr < srcBlock + blockByteSize; blockPtr += elementSize) {
1337 38669059 : memcpy(blockPtr, srcBlock, elementSize);
1338 : }
1339 :
1340 : // Write block to block cache
1341 480632 : for (int j = 0; j < nBlocksPerColumn; ++j) {
1342 914272 : for (int i = 0; i < nBlocksPerRow; ++i) {
1343 601636 : GDALRasterBlock* destBlock = GetLockedBlockRef(i, j, TRUE);
1344 601636 : if (destBlock == NULL) {
1345 : CPLError(CE_Failure, CPLE_OutOfMemory,
1346 : "GDALRasterBand::Fill(): Error "
1347 0 : "while retrieving cache block.\n");
1348 0 : VSIFree(srcBlock);
1349 0 : return CE_Failure;
1350 : }
1351 601636 : if (destBlock->GetDataRef() == NULL)
1352 : {
1353 0 : destBlock->DropLock();
1354 0 : VSIFree(srcBlock);
1355 0 : return CE_Failure;
1356 : }
1357 601636 : memcpy(destBlock->GetDataRef(), srcBlock, blockByteSize);
1358 601636 : destBlock->MarkDirty();
1359 601636 : destBlock->DropLock();
1360 : }
1361 : }
1362 :
1363 : // Free up the source block
1364 167996 : VSIFree(srcBlock);
1365 :
1366 167996 : return CE_None;
1367 : }
1368 :
1369 :
1370 : /************************************************************************/
1371 : /* GDALFillRaster() */
1372 : /************************************************************************/
1373 :
1374 : /**
1375 : * \brief Fill this band with a constant value.
1376 : *
1377 : * @see GDALRasterBand::Fill()
1378 : */
1379 : CPLErr CPL_STDCALL GDALFillRaster(GDALRasterBandH hBand, double dfRealValue,
1380 167996 : double dfImaginaryValue)
1381 : {
1382 167996 : VALIDATE_POINTER1( hBand, "GDALFillRaster", CE_Failure );
1383 :
1384 167996 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1385 167996 : return poBand->Fill(dfRealValue, dfImaginaryValue);
1386 : }
1387 :
1388 : /************************************************************************/
1389 : /* GetAccess() */
1390 : /************************************************************************/
1391 :
1392 : /**
1393 : * \brief Find out if we have update permission for this band.
1394 : *
1395 : * This method is the same as the C function GDALGetRasterAccess().
1396 : *
1397 : * @return Either GA_Update or GA_ReadOnly.
1398 : */
1399 :
1400 368 : GDALAccess GDALRasterBand::GetAccess()
1401 :
1402 : {
1403 368 : return eAccess;
1404 : }
1405 :
1406 : /************************************************************************/
1407 : /* GDALGetRasterAccess() */
1408 : /************************************************************************/
1409 :
1410 : /**
1411 : * \brief Find out if we have update permission for this band.
1412 : *
1413 : * @see GDALRasterBand::GetAccess()
1414 : */
1415 :
1416 365 : GDALAccess CPL_STDCALL GDALGetRasterAccess( GDALRasterBandH hBand )
1417 :
1418 : {
1419 365 : VALIDATE_POINTER1( hBand, "GDALGetRasterAccess", GA_ReadOnly );
1420 :
1421 365 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1422 365 : return poBand->GetAccess();
1423 : }
1424 :
1425 : /************************************************************************/
1426 : /* GetCategoryNames() */
1427 : /************************************************************************/
1428 :
1429 : /**
1430 : * \brief Fetch the list of category names for this raster.
1431 : *
1432 : * The return list is a "StringList" in the sense of the CPL functions.
1433 : * That is a NULL terminated array of strings. Raster values without
1434 : * associated names will have an empty string in the returned list. The
1435 : * first entry in the list is for raster values of zero, and so on.
1436 : *
1437 : * The returned stringlist should not be altered or freed by the application.
1438 : * It may change on the next GDAL call, so please copy it if it is needed
1439 : * for any period of time.
1440 : *
1441 : * @return list of names, or NULL if none.
1442 : */
1443 :
1444 17 : char **GDALRasterBand::GetCategoryNames()
1445 :
1446 : {
1447 17 : return NULL;
1448 : }
1449 :
1450 : /************************************************************************/
1451 : /* GDALGetRasterCategoryNames() */
1452 : /************************************************************************/
1453 :
1454 : /**
1455 : * \brief Fetch the list of category names for this raster.
1456 : *
1457 : * @see GDALRasterBand::GetCategoryNames()
1458 : */
1459 :
1460 34 : char ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH hBand )
1461 :
1462 : {
1463 34 : VALIDATE_POINTER1( hBand, "GDALGetRasterCategoryNames", NULL );
1464 :
1465 34 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1466 34 : return poBand->GetCategoryNames();
1467 : }
1468 :
1469 : /************************************************************************/
1470 : /* SetCategoryNames() */
1471 : /************************************************************************/
1472 :
1473 : /**
1474 : * \brief Set the category names for this band.
1475 : *
1476 : * See the GetCategoryNames() method for more on the interpretation of
1477 : * category names.
1478 : *
1479 : * This method is the same as the C function GDALSetRasterCategoryNames().
1480 : *
1481 : * @param papszNames the NULL terminated StringList of category names. May
1482 : * be NULL to just clear the existing list.
1483 : *
1484 : * @return CE_None on success of CE_Failure on failure. If unsupported
1485 : * by the driver CE_Failure is returned, but no error message is reported.
1486 : */
1487 :
1488 0 : CPLErr GDALRasterBand::SetCategoryNames( char ** )
1489 :
1490 : {
1491 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1492 : CPLError( CE_Failure, CPLE_NotSupported,
1493 0 : "SetCategoryNames() not supported for this dataset." );
1494 :
1495 0 : return CE_Failure;
1496 : }
1497 :
1498 : /************************************************************************/
1499 : /* GDALSetCategoryNames() */
1500 : /************************************************************************/
1501 :
1502 : /**
1503 : * \brief Set the category names for this band.
1504 : *
1505 : * @see GDALRasterBand::SetCategoryNames()
1506 : */
1507 :
1508 : CPLErr CPL_STDCALL
1509 0 : GDALSetRasterCategoryNames( GDALRasterBandH hBand, char ** papszNames )
1510 :
1511 : {
1512 0 : VALIDATE_POINTER1( hBand, "GDALSetRasterCategoryNames", CE_Failure );
1513 :
1514 0 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1515 0 : return poBand->SetCategoryNames( papszNames );
1516 : }
1517 :
1518 : /************************************************************************/
1519 : /* GetNoDataValue() */
1520 : /************************************************************************/
1521 :
1522 : /**
1523 : * \brief Fetch the no data value for this band.
1524 : *
1525 : * If there is no out of data value, an out of range value will generally
1526 : * be returned. The no data value for a band is generally a special marker
1527 : * value used to mark pixels that are not valid data. Such pixels should
1528 : * generally not be displayed, nor contribute to analysis operations.
1529 : *
1530 : * This method is the same as the C function GDALGetRasterNoDataValue().
1531 : *
1532 : * @param pbSuccess pointer to a boolean to use to indicate if a value
1533 : * is actually associated with this layer. May be NULL (default).
1534 : *
1535 : * @return the nodata value for this band.
1536 : */
1537 :
1538 1833 : double GDALRasterBand::GetNoDataValue( int *pbSuccess )
1539 :
1540 : {
1541 1833 : if( pbSuccess != NULL )
1542 1833 : *pbSuccess = FALSE;
1543 :
1544 1833 : return -1e10;
1545 : }
1546 :
1547 : /************************************************************************/
1548 : /* GDALGetRasterNoDataValue() */
1549 : /************************************************************************/
1550 :
1551 : /**
1552 : * \brief Fetch the no data value for this band.
1553 : *
1554 : * @see GDALRasterBand::GetNoDataValue()
1555 : */
1556 :
1557 : double CPL_STDCALL
1558 496 : GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
1559 :
1560 : {
1561 496 : VALIDATE_POINTER1( hBand, "GDALGetRasterNoDataValue", 0 );
1562 :
1563 496 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1564 496 : return poBand->GetNoDataValue( pbSuccess );
1565 : }
1566 :
1567 : /************************************************************************/
1568 : /* SetNoDataValue() */
1569 : /************************************************************************/
1570 :
1571 : /**
1572 : * \brief Set the no data value for this band.
1573 : *
1574 : * To clear the nodata value, just set it with an "out of range" value.
1575 : * Complex band no data values must have an imagery component of zero.
1576 : *
1577 : * This method is the same as the C function GDALSetRasterNoDataValue().
1578 : *
1579 : * @param dfNoData the value to set.
1580 : *
1581 : * @return CE_None on success, or CE_Failure on failure. If unsupported
1582 : * by the driver, CE_Failure is returned by no error message will have
1583 : * been emitted.
1584 : */
1585 :
1586 0 : CPLErr GDALRasterBand::SetNoDataValue( double )
1587 :
1588 : {
1589 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1590 : CPLError( CE_Failure, CPLE_NotSupported,
1591 0 : "SetNoDataValue() not supported for this dataset." );
1592 :
1593 0 : return CE_Failure;
1594 : }
1595 :
1596 : /************************************************************************/
1597 : /* GDALSetRasterNoDataValue() */
1598 : /************************************************************************/
1599 :
1600 : /**
1601 : * \brief Set the no data value for this band.
1602 : *
1603 : * @see GDALRasterBand::SetNoDataValue()
1604 : */
1605 :
1606 : CPLErr CPL_STDCALL
1607 57 : GDALSetRasterNoDataValue( GDALRasterBandH hBand, double dfValue )
1608 :
1609 : {
1610 57 : VALIDATE_POINTER1( hBand, "GDALSetRasterNoDataValue", CE_Failure );
1611 :
1612 57 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1613 57 : return poBand->SetNoDataValue( dfValue );
1614 : }
1615 :
1616 : /************************************************************************/
1617 : /* GetMaximum() */
1618 : /************************************************************************/
1619 :
1620 : /**
1621 : * \brief Fetch the maximum value for this band.
1622 : *
1623 : * For file formats that don't know this intrinsically, the maximum supported
1624 : * value for the data type will generally be returned.
1625 : *
1626 : * This method is the same as the C function GDALGetRasterMaximum().
1627 : *
1628 : * @param pbSuccess pointer to a boolean to use to indicate if the
1629 : * returned value is a tight maximum or not. May be NULL (default).
1630 : *
1631 : * @return the maximum raster value (excluding no data pixels)
1632 : */
1633 :
1634 81 : double GDALRasterBand::GetMaximum( int *pbSuccess )
1635 :
1636 : {
1637 81 : const char *pszValue = NULL;
1638 :
1639 81 : if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
1640 : {
1641 0 : if( pbSuccess != NULL )
1642 0 : *pbSuccess = TRUE;
1643 :
1644 0 : return CPLAtofM(pszValue);
1645 : }
1646 :
1647 81 : if( pbSuccess != NULL )
1648 60 : *pbSuccess = FALSE;
1649 :
1650 81 : switch( eDataType )
1651 : {
1652 : case GDT_Byte:
1653 : {
1654 61 : const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
1655 61 : if (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"))
1656 0 : return 127;
1657 : else
1658 61 : return 255;
1659 : }
1660 :
1661 : case GDT_UInt16:
1662 3 : return 65535;
1663 :
1664 : case GDT_Int16:
1665 : case GDT_CInt16:
1666 4 : return 32767;
1667 :
1668 : case GDT_Int32:
1669 : case GDT_CInt32:
1670 3 : return 2147483647.0;
1671 :
1672 : case GDT_UInt32:
1673 3 : return 4294967295.0;
1674 :
1675 : case GDT_Float32:
1676 : case GDT_CFloat32:
1677 4 : return 4294967295.0; /* not actually accurate */
1678 :
1679 : case GDT_Float64:
1680 : case GDT_CFloat64:
1681 3 : return 4294967295.0; /* not actually accurate */
1682 :
1683 : default:
1684 0 : return 4294967295.0; /* not actually accurate */
1685 : }
1686 : }
1687 :
1688 : /************************************************************************/
1689 : /* GDALGetRasterMaximum() */
1690 : /************************************************************************/
1691 :
1692 : /**
1693 : * \brief Fetch the maximum value for this band.
1694 : *
1695 : * @see GDALRasterBand::GetMaximum()
1696 : */
1697 :
1698 : double CPL_STDCALL
1699 36 : GDALGetRasterMaximum( GDALRasterBandH hBand, int *pbSuccess )
1700 :
1701 : {
1702 36 : VALIDATE_POINTER1( hBand, "GDALGetRasterMaximum", 0 );
1703 :
1704 36 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1705 36 : return poBand->GetMaximum( pbSuccess );
1706 : }
1707 :
1708 : /************************************************************************/
1709 : /* GetMinimum() */
1710 : /************************************************************************/
1711 :
1712 : /**
1713 : * \brief Fetch the minimum value for this band.
1714 : *
1715 : * For file formats that don't know this intrinsically, the minimum supported
1716 : * value for the data type will generally be returned.
1717 : *
1718 : * This method is the same as the C function GDALGetRasterMinimum().
1719 : *
1720 : * @param pbSuccess pointer to a boolean to use to indicate if the
1721 : * returned value is a tight minimum or not. May be NULL (default).
1722 : *
1723 : * @return the minimum raster value (excluding no data pixels)
1724 : */
1725 :
1726 81 : double GDALRasterBand::GetMinimum( int *pbSuccess )
1727 :
1728 : {
1729 81 : const char *pszValue = NULL;
1730 :
1731 81 : if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
1732 : {
1733 0 : if( pbSuccess != NULL )
1734 0 : *pbSuccess = TRUE;
1735 :
1736 0 : return CPLAtofM(pszValue);
1737 : }
1738 :
1739 81 : if( pbSuccess != NULL )
1740 60 : *pbSuccess = FALSE;
1741 :
1742 81 : switch( eDataType )
1743 : {
1744 : case GDT_Byte:
1745 : {
1746 61 : const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
1747 61 : if (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"))
1748 0 : return -128;
1749 : else
1750 61 : return 0;
1751 : }
1752 :
1753 : case GDT_UInt16:
1754 3 : return 0;
1755 :
1756 : case GDT_Int16:
1757 4 : return -32768;
1758 :
1759 : case GDT_Int32:
1760 3 : return -2147483648.0;
1761 :
1762 : case GDT_UInt32:
1763 3 : return 0;
1764 :
1765 : case GDT_Float32:
1766 4 : return -4294967295.0; /* not actually accurate */
1767 :
1768 : case GDT_Float64:
1769 3 : return -4294967295.0; /* not actually accurate */
1770 :
1771 : default:
1772 0 : return -4294967295.0; /* not actually accurate */
1773 : }
1774 : }
1775 :
1776 : /************************************************************************/
1777 : /* GDALGetRasterMinimum() */
1778 : /************************************************************************/
1779 :
1780 : /**
1781 : * \brief Fetch the minimum value for this band.
1782 : *
1783 : * @see GDALRasterBand::GetMinimum()
1784 : */
1785 :
1786 : double CPL_STDCALL
1787 36 : GDALGetRasterMinimum( GDALRasterBandH hBand, int *pbSuccess )
1788 :
1789 : {
1790 36 : VALIDATE_POINTER1( hBand, "GDALGetRasterMinimum", 0 );
1791 :
1792 36 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1793 36 : return poBand->GetMinimum( pbSuccess );
1794 : }
1795 :
1796 : /************************************************************************/
1797 : /* GetColorInterpretation() */
1798 : /************************************************************************/
1799 :
1800 : /**
1801 : * \brief How should this band be interpreted as color?
1802 : *
1803 : * GCI_Undefined is returned when the format doesn't know anything
1804 : * about the color interpretation.
1805 : *
1806 : * This method is the same as the C function
1807 : * GDALGetRasterColorInterpretation().
1808 : *
1809 : * @return color interpretation value for band.
1810 : */
1811 :
1812 29 : GDALColorInterp GDALRasterBand::GetColorInterpretation()
1813 :
1814 : {
1815 29 : return GCI_Undefined;
1816 : }
1817 :
1818 : /************************************************************************/
1819 : /* GDALGetRasterColorInterpretation() */
1820 : /************************************************************************/
1821 :
1822 : /**
1823 : * \brief How should this band be interpreted as color?
1824 : *
1825 : * @see GDALRasterBand::GetColorInterpretation()
1826 : */
1827 :
1828 : GDALColorInterp CPL_STDCALL
1829 459 : GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
1830 :
1831 : {
1832 459 : VALIDATE_POINTER1( hBand, "GDALGetRasterColorInterpretation", GCI_Undefined );
1833 :
1834 459 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1835 459 : return poBand->GetColorInterpretation();
1836 : }
1837 :
1838 : /************************************************************************/
1839 : /* SetColorInterpretation() */
1840 : /************************************************************************/
1841 :
1842 : /**
1843 : * \brief Set color interpretation of a band.
1844 : *
1845 : * @param eColorInterp the new color interpretation to apply to this band.
1846 : *
1847 : * @return CE_None on success or CE_Failure if method is unsupported by format.
1848 : */
1849 :
1850 10 : CPLErr GDALRasterBand::SetColorInterpretation( GDALColorInterp eColorInterp)
1851 :
1852 : {
1853 : (void) eColorInterp;
1854 10 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1855 : CPLError( CE_Failure, CPLE_NotSupported,
1856 10 : "SetColorInterpretation() not supported for this dataset." );
1857 10 : return CE_Failure;
1858 : }
1859 :
1860 : /************************************************************************/
1861 : /* GDALSetRasterColorInterpretation() */
1862 : /************************************************************************/
1863 :
1864 : /**
1865 : * \brief Set color interpretation of a band.
1866 : *
1867 : * @see GDALRasterBand::SetColorInterpretation()
1868 : */
1869 :
1870 : CPLErr CPL_STDCALL
1871 : GDALSetRasterColorInterpretation( GDALRasterBandH hBand,
1872 40 : GDALColorInterp eColorInterp )
1873 :
1874 : {
1875 40 : VALIDATE_POINTER1( hBand, "GDALSetRasterColorInterpretation", CE_Failure );
1876 :
1877 40 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1878 40 : return poBand->SetColorInterpretation(eColorInterp);
1879 : }
1880 :
1881 : /************************************************************************/
1882 : /* GetColorTable() */
1883 : /************************************************************************/
1884 :
1885 : /**
1886 : * \brief Fetch the color table associated with band.
1887 : *
1888 : * If there is no associated color table, the return result is NULL. The
1889 : * returned color table remains owned by the GDALRasterBand, and can't
1890 : * be depended on for long, nor should it ever be modified by the caller.
1891 : *
1892 : * This method is the same as the C function GDALGetRasterColorTable().
1893 : *
1894 : * @return internal color table, or NULL.
1895 : */
1896 :
1897 33 : GDALColorTable *GDALRasterBand::GetColorTable()
1898 :
1899 : {
1900 33 : return NULL;
1901 : }
1902 :
1903 : /************************************************************************/
1904 : /* GDALGetRasterColorTable() */
1905 : /************************************************************************/
1906 :
1907 : /**
1908 : * \brief Fetch the color table associated with band.
1909 : *
1910 : * @see GDALRasterBand::GetColorTable()
1911 : */
1912 :
1913 563 : GDALColorTableH CPL_STDCALL GDALGetRasterColorTable( GDALRasterBandH hBand )
1914 :
1915 : {
1916 563 : VALIDATE_POINTER1( hBand, "GDALGetRasterColorTable", NULL );
1917 :
1918 563 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1919 563 : return (GDALColorTableH)poBand->GetColorTable();
1920 : }
1921 :
1922 : /************************************************************************/
1923 : /* SetColorTable() */
1924 : /************************************************************************/
1925 :
1926 : /**
1927 : * \brief Set the raster color table.
1928 : *
1929 : * The driver will make a copy of all desired data in the colortable. It
1930 : * remains owned by the caller after the call.
1931 : *
1932 : * This method is the same as the C function GDALSetRasterColorTable().
1933 : *
1934 : * @param poCT the color table to apply. This may be NULL to clear the color
1935 : * table (where supported).
1936 : *
1937 : * @return CE_None on success, or CE_Failure on failure. If the action is
1938 : * unsupported by the driver, a value of CE_Failure is returned, but no
1939 : * error is issued.
1940 : */
1941 :
1942 0 : CPLErr GDALRasterBand::SetColorTable( GDALColorTable * poCT )
1943 :
1944 : {
1945 : (void) poCT;
1946 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1947 : CPLError( CE_Failure, CPLE_NotSupported,
1948 0 : "SetColorTable() not supported for this dataset." );
1949 0 : return CE_Failure;
1950 : }
1951 :
1952 : /************************************************************************/
1953 : /* GDALSetRasterColorTable() */
1954 : /************************************************************************/
1955 :
1956 : /**
1957 : * \brief Set the raster color table.
1958 : *
1959 : * @see GDALRasterBand::SetColorTable()
1960 : */
1961 :
1962 : CPLErr CPL_STDCALL
1963 21 : GDALSetRasterColorTable( GDALRasterBandH hBand, GDALColorTableH hCT )
1964 :
1965 : {
1966 21 : VALIDATE_POINTER1( hBand, "GDALSetRasterColorTable", CE_Failure );
1967 :
1968 21 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
1969 21 : return poBand->SetColorTable( static_cast<GDALColorTable*>(hCT) );
1970 : }
1971 :
1972 : /************************************************************************/
1973 : /* HasArbitraryOverviews() */
1974 : /************************************************************************/
1975 :
1976 : /**
1977 : * \brief Check for arbitrary overviews.
1978 : *
1979 : * This returns TRUE if the underlying datastore can compute arbitrary
1980 : * overviews efficiently, such as is the case with OGDI over a network.
1981 : * Datastores with arbitrary overviews don't generally have any fixed
1982 : * overviews, but the RasterIO() method can be used in downsampling mode
1983 : * to get overview data efficiently.
1984 : *
1985 : * This method is the same as the C function GDALHasArbitraryOverviews(),
1986 : *
1987 : * @return TRUE if arbitrary overviews available (efficiently), otherwise
1988 : * FALSE.
1989 : */
1990 :
1991 41 : int GDALRasterBand::HasArbitraryOverviews()
1992 :
1993 : {
1994 41 : return FALSE;
1995 : }
1996 :
1997 : /************************************************************************/
1998 : /* GDALHasArbitraryOverviews() */
1999 : /************************************************************************/
2000 :
2001 : /**
2002 : * \brief Check for arbitrary overviews.
2003 : *
2004 : * @see GDALRasterBand::HasArbitraryOverviews()
2005 : */
2006 :
2007 34 : int CPL_STDCALL GDALHasArbitraryOverviews( GDALRasterBandH hBand )
2008 :
2009 : {
2010 34 : VALIDATE_POINTER1( hBand, "GDALHasArbitraryOverviews", 0 );
2011 :
2012 34 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2013 34 : return poBand->HasArbitraryOverviews();
2014 : }
2015 :
2016 : /************************************************************************/
2017 : /* GetOverviewCount() */
2018 : /************************************************************************/
2019 :
2020 : /**
2021 : * \brief Return the number of overview layers available.
2022 : *
2023 : * This method is the same as the C function GDALGetOverviewCount().
2024 : *
2025 : * @return overview count, zero if none.
2026 : */
2027 :
2028 299681 : int GDALRasterBand::GetOverviewCount()
2029 :
2030 : {
2031 299681 : if( poDS != NULL && poDS->oOvManager.IsInitialized() )
2032 299676 : return poDS->oOvManager.GetOverviewCount( nBand );
2033 : else
2034 5 : return 0;
2035 : }
2036 :
2037 : /************************************************************************/
2038 : /* GDALGetOverviewCount() */
2039 : /************************************************************************/
2040 :
2041 : /**
2042 : * \brief Return the number of overview layers available.
2043 : *
2044 : * @see GDALRasterBand::GetOverviewCount()
2045 : */
2046 :
2047 96 : int CPL_STDCALL GDALGetOverviewCount( GDALRasterBandH hBand )
2048 :
2049 : {
2050 96 : VALIDATE_POINTER1( hBand, "GDALGetOverviewCount", 0 );
2051 :
2052 96 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2053 96 : return poBand->GetOverviewCount();
2054 : }
2055 :
2056 :
2057 : /************************************************************************/
2058 : /* GetOverview() */
2059 : /************************************************************************/
2060 :
2061 : /**
2062 : * \brief Fetch overview raster band object.
2063 : *
2064 : * This method is the same as the C function GDALGetOverview().
2065 : *
2066 : * @param i overview index between 0 and GetOverviewCount()-1.
2067 : *
2068 : * @return overview GDALRasterBand.
2069 : */
2070 :
2071 293 : GDALRasterBand * GDALRasterBand::GetOverview( int i )
2072 :
2073 : {
2074 293 : if( poDS != NULL && poDS->oOvManager.IsInitialized() )
2075 293 : return poDS->oOvManager.GetOverview( nBand, i );
2076 : else
2077 0 : return NULL;
2078 : }
2079 :
2080 : /************************************************************************/
2081 : /* GDALGetOverview() */
2082 : /************************************************************************/
2083 :
2084 : /**
2085 : * \brief Fetch overview raster band object.
2086 : *
2087 : * @see GDALRasterBand::GetOverview()
2088 : */
2089 :
2090 218 : GDALRasterBandH CPL_STDCALL GDALGetOverview( GDALRasterBandH hBand, int i )
2091 :
2092 : {
2093 218 : VALIDATE_POINTER1( hBand, "GDALGetOverview", NULL );
2094 :
2095 218 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2096 218 : return (GDALRasterBandH) poBand->GetOverview(i);
2097 : }
2098 :
2099 : /************************************************************************/
2100 : /* GetRasterSampleOverview() */
2101 : /************************************************************************/
2102 :
2103 : /**
2104 : * \brief Fetch best sampling overview.
2105 : *
2106 : * Returns the most reduced overview of the given band that still satisfies
2107 : * the desired number of samples. This function can be used with zero
2108 : * as the number of desired samples to fetch the most reduced overview.
2109 : * The same band as was passed in will be returned if it has not overviews,
2110 : * or if none of the overviews have enough samples.
2111 : *
2112 : * This method is the same as the C function GDALGetRasterSampleOverview().
2113 : *
2114 : * @param nDesiredSamples the returned band will have at least this many
2115 : * pixels.
2116 : *
2117 : * @return optimal overview or the band itself.
2118 : */
2119 :
2120 2 : GDALRasterBand *GDALRasterBand::GetRasterSampleOverview( int nDesiredSamples )
2121 :
2122 : {
2123 2 : double dfBestSamples = 0;
2124 2 : GDALRasterBand *poBestBand = this;
2125 :
2126 2 : dfBestSamples = GetXSize() * (double)GetYSize();
2127 :
2128 12 : for( int iOverview = 0; iOverview < GetOverviewCount(); iOverview++ )
2129 : {
2130 10 : GDALRasterBand *poOBand = GetOverview( iOverview );
2131 10 : double dfOSamples = 0;
2132 :
2133 10 : if (poOBand == NULL)
2134 0 : continue;
2135 :
2136 10 : dfOSamples = poOBand->GetXSize() * (double)poOBand->GetYSize();
2137 :
2138 10 : if( dfOSamples < dfBestSamples && dfOSamples > nDesiredSamples )
2139 : {
2140 6 : dfBestSamples = dfOSamples;
2141 6 : poBestBand = poOBand;
2142 : }
2143 : }
2144 :
2145 2 : return poBestBand;
2146 : }
2147 :
2148 : /************************************************************************/
2149 : /* GDALGetRasterSampleOverview() */
2150 : /************************************************************************/
2151 :
2152 : /**
2153 : * \brief Fetch best sampling overview.
2154 : *
2155 : * @see GDALRasterBand::GetRasterSampleOverview()
2156 : */
2157 :
2158 : GDALRasterBandH CPL_STDCALL
2159 0 : GDALGetRasterSampleOverview( GDALRasterBandH hBand, int nDesiredSamples )
2160 :
2161 : {
2162 0 : VALIDATE_POINTER1( hBand, "GDALGetRasterSampleOverview", NULL );
2163 :
2164 0 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2165 : return (GDALRasterBandH)
2166 0 : poBand->GetRasterSampleOverview( nDesiredSamples );
2167 : }
2168 :
2169 : /************************************************************************/
2170 : /* BuildOverviews() */
2171 : /************************************************************************/
2172 :
2173 : /**
2174 : * \brief Build raster overview(s)
2175 : *
2176 : * If the operation is unsupported for the indicated dataset, then
2177 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2178 : * CPLE_NotSupported.
2179 : *
2180 : * WARNING: It is not possible to build overviews for a single band in
2181 : * TIFF format, and thus this method does not work for TIFF format, or any
2182 : * formats that use the default overview building in TIFF format. Instead
2183 : * it is necessary to build overviews on the dataset as a whole using
2184 : * GDALDataset::BuildOverviews(). That makes this method pretty useless
2185 : * from a practical point of view.
2186 : *
2187 : * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
2188 : * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
2189 : * @param nOverviews number of overviews to build.
2190 : * @param panOverviewList the list of overview decimation factors to build.
2191 : * @param pfnProgress a function to call to report progress, or NULL.
2192 : * @param pProgressData application data to pass to the progress function.
2193 : *
2194 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2195 : */
2196 :
2197 : CPLErr GDALRasterBand::BuildOverviews( const char * pszResampling,
2198 : int nOverviews,
2199 : int * panOverviewList,
2200 : GDALProgressFunc pfnProgress,
2201 0 : void * pProgressData )
2202 :
2203 : {
2204 : (void) pszResampling;
2205 : (void) nOverviews;
2206 : (void) panOverviewList;
2207 : (void) pfnProgress;
2208 : (void) pProgressData;
2209 :
2210 : CPLError( CE_Failure, CPLE_NotSupported,
2211 0 : "BuildOverviews() not supported for this dataset." );
2212 :
2213 0 : return( CE_Failure );
2214 : }
2215 :
2216 : /************************************************************************/
2217 : /* GetOffset() */
2218 : /************************************************************************/
2219 :
2220 : /**
2221 : * \brief Fetch the raster value offset.
2222 : *
2223 : * This value (in combination with the GetScale() value) is used to
2224 : * transform raw pixel values into the units returned by GetUnits().
2225 : * For example this might be used to store elevations in GUInt16 bands
2226 : * with a precision of 0.1, and starting from -100.
2227 : *
2228 : * Units value = (raw value * scale) + offset
2229 : *
2230 : * For file formats that don't know this intrinsically a value of zero
2231 : * is returned.
2232 : *
2233 : * This method is the same as the C function GDALGetRasterOffset().
2234 : *
2235 : * @param pbSuccess pointer to a boolean to use to indicate if the
2236 : * returned value is meaningful or not. May be NULL (default).
2237 : *
2238 : * @return the raster offset.
2239 : */
2240 :
2241 37 : double GDALRasterBand::GetOffset( int *pbSuccess )
2242 :
2243 : {
2244 37 : if( pbSuccess != NULL )
2245 37 : *pbSuccess = FALSE;
2246 :
2247 37 : return 0.0;
2248 : }
2249 :
2250 : /************************************************************************/
2251 : /* GDALGetRasterOffset() */
2252 : /************************************************************************/
2253 :
2254 : /**
2255 : * \brief Fetch the raster value offset.
2256 : *
2257 : * @see GDALRasterBand::GetOffset()
2258 : */
2259 :
2260 41 : double CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH hBand, int *pbSuccess )
2261 :
2262 : {
2263 41 : VALIDATE_POINTER1( hBand, "GDALGetRasterOffset", 0 );
2264 :
2265 41 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2266 41 : return poBand->GetOffset( pbSuccess );
2267 : }
2268 :
2269 : /************************************************************************/
2270 : /* SetOffset() */
2271 : /************************************************************************/
2272 :
2273 : /**
2274 : * \brief Set scaling offset.
2275 : *
2276 : * Very few formats implement this method. When not implemented it will
2277 : * issue a CPLE_NotSupported error and return CE_Failure.
2278 : *
2279 : * @param dfNewOffset the new offset.
2280 : *
2281 : * @return CE_None or success or CE_Failure on failure.
2282 : */
2283 :
2284 0 : CPLErr GDALRasterBand::SetOffset( double dfNewOffset )
2285 :
2286 : {
2287 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
2288 : CPLError( CE_Failure, CPLE_NotSupported,
2289 0 : "SetOffset() not supported on this raster band." );
2290 :
2291 0 : return CE_Failure;
2292 : }
2293 :
2294 : /************************************************************************/
2295 : /* GDALSetRasterOffset() */
2296 : /************************************************************************/
2297 :
2298 : /**
2299 : * \brief Set scaling offset.
2300 : *
2301 : * @see GDALRasterBand::SetOffset()
2302 : */
2303 :
2304 : CPLErr CPL_STDCALL
2305 4 : GDALSetRasterOffset( GDALRasterBandH hBand, double dfNewOffset )
2306 :
2307 : {
2308 4 : VALIDATE_POINTER1( hBand, "GDALSetRasterOffset", CE_Failure );
2309 :
2310 4 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2311 4 : return poBand->SetOffset( dfNewOffset );
2312 : }
2313 :
2314 : /************************************************************************/
2315 : /* GetScale() */
2316 : /************************************************************************/
2317 :
2318 : /**
2319 : * \brief Fetch the raster value scale.
2320 : *
2321 : * This value (in combination with the GetOffset() value) is used to
2322 : * transform raw pixel values into the units returned by GetUnits().
2323 : * For example this might be used to store elevations in GUInt16 bands
2324 : * with a precision of 0.1, and starting from -100.
2325 : *
2326 : * Units value = (raw value * scale) + offset
2327 : *
2328 : * For file formats that don't know this intrinsically a value of one
2329 : * is returned.
2330 : *
2331 : * This method is the same as the C function GDALGetRasterScale().
2332 : *
2333 : * @param pbSuccess pointer to a boolean to use to indicate if the
2334 : * returned value is meaningful or not. May be NULL (default).
2335 : *
2336 : * @return the raster scale.
2337 : */
2338 :
2339 37 : double GDALRasterBand::GetScale( int *pbSuccess )
2340 :
2341 : {
2342 37 : if( pbSuccess != NULL )
2343 37 : *pbSuccess = FALSE;
2344 :
2345 37 : return 1.0;
2346 : }
2347 :
2348 : /************************************************************************/
2349 : /* GDALGetRasterScale() */
2350 : /************************************************************************/
2351 :
2352 : /**
2353 : * \brief Fetch the raster value scale.
2354 : *
2355 : * @see GDALRasterBand::GetScale()
2356 : */
2357 :
2358 41 : double CPL_STDCALL GDALGetRasterScale( GDALRasterBandH hBand, int *pbSuccess )
2359 :
2360 : {
2361 41 : VALIDATE_POINTER1( hBand, "GDALGetRasterScale", 0 );
2362 :
2363 41 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2364 41 : return poBand->GetScale( pbSuccess );
2365 : }
2366 :
2367 : /************************************************************************/
2368 : /* SetScale() */
2369 : /************************************************************************/
2370 :
2371 : /**
2372 : * \brief Set scaling ratio.
2373 : *
2374 : * Very few formats implement this method. When not implemented it will
2375 : * issue a CPLE_NotSupported error and return CE_Failure.
2376 : *
2377 : * @param dfNewScale the new scale.
2378 : *
2379 : * @return CE_None or success or CE_Failure on failure.
2380 : */
2381 :
2382 0 : CPLErr GDALRasterBand::SetScale( double dfNewScale )
2383 :
2384 : {
2385 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
2386 : CPLError( CE_Failure, CPLE_NotSupported,
2387 0 : "SetScale() not supported on this raster band." );
2388 :
2389 0 : return CE_Failure;
2390 : }
2391 :
2392 : /************************************************************************/
2393 : /* GDALSetRasterScale() */
2394 : /************************************************************************/
2395 :
2396 : /**
2397 : * \brief Set scaling ratio.
2398 : *
2399 : * @see GDALRasterBand::SetScale()
2400 : */
2401 :
2402 : CPLErr CPL_STDCALL
2403 4 : GDALSetRasterScale( GDALRasterBandH hBand, double dfNewOffset )
2404 :
2405 : {
2406 4 : VALIDATE_POINTER1( hBand, "GDALSetRasterScale", CE_Failure );
2407 :
2408 4 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2409 4 : return poBand->SetScale( dfNewOffset );
2410 : }
2411 :
2412 : /************************************************************************/
2413 : /* GetUnitType() */
2414 : /************************************************************************/
2415 :
2416 : /**
2417 : * \brief Return raster unit type.
2418 : *
2419 : * Return a name for the units of this raster's values. For instance, it
2420 : * might be "m" for an elevation model in meters, or "ft" for feet. If no
2421 : * units are available, a value of "" will be returned. The returned string
2422 : * should not be modified, nor freed by the calling application.
2423 : *
2424 : * This method is the same as the C function GDALGetRasterUnitType().
2425 : *
2426 : * @return unit name string.
2427 : */
2428 :
2429 15 : const char *GDALRasterBand::GetUnitType()
2430 :
2431 : {
2432 15 : return "";
2433 : }
2434 :
2435 : /************************************************************************/
2436 : /* GDALGetRasterUnitType() */
2437 : /************************************************************************/
2438 :
2439 : /**
2440 : * \brief Return raster unit type.
2441 : *
2442 : * @see GDALRasterBand::GetUnitType()
2443 : */
2444 :
2445 40 : const char * CPL_STDCALL GDALGetRasterUnitType( GDALRasterBandH hBand )
2446 :
2447 : {
2448 40 : VALIDATE_POINTER1( hBand, "GDALGetRasterUnitType", NULL );
2449 :
2450 40 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2451 40 : return poBand->GetUnitType();
2452 : }
2453 :
2454 : /************************************************************************/
2455 : /* SetUnitType() */
2456 : /************************************************************************/
2457 :
2458 : /**
2459 : * \brief Set unit type.
2460 : *
2461 : * Set the unit type for a raster band. Values should be one of
2462 : * "" (the default indicating it is unknown), "m" indicating meters,
2463 : * or "ft" indicating feet, though other nonstandard values are allowed.
2464 : *
2465 : * This method is the same as the C function GDALSetRasterUnitType().
2466 : *
2467 : * @param pszNewValue the new unit type value.
2468 : *
2469 : * @return CE_None on success or CE_Failure if not succuessful, or
2470 : * unsupported.
2471 : */
2472 :
2473 0 : CPLErr GDALRasterBand::SetUnitType( const char *pszNewValue )
2474 :
2475 : {
2476 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
2477 : CPLError( CE_Failure, CPLE_NotSupported,
2478 0 : "SetUnitType() not supported on this raster band." );
2479 0 : return CE_Failure;
2480 : }
2481 :
2482 : /************************************************************************/
2483 : /* GDALSetRasterUnitType() */
2484 : /************************************************************************/
2485 :
2486 : /**
2487 : * \brief Set unit type.
2488 : *
2489 : * @see GDALRasterBand::SetUnitType()
2490 : *
2491 : * @since GDAL 1.8.0
2492 : */
2493 :
2494 4 : CPLErr CPL_STDCALL GDALSetRasterUnitType( GDALRasterBandH hBand, const char *pszNewValue )
2495 :
2496 : {
2497 4 : VALIDATE_POINTER1( hBand, "GDALSetRasterUnitType", CE_Failure );
2498 :
2499 4 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2500 4 : return poBand->SetUnitType(pszNewValue);
2501 : }
2502 :
2503 : /************************************************************************/
2504 : /* GetXSize() */
2505 : /************************************************************************/
2506 :
2507 : /**
2508 : * \brief Fetch XSize of raster.
2509 : *
2510 : * This method is the same as the C function GDALGetRasterBandXSize().
2511 : *
2512 : * @return the width in pixels of this band.
2513 : */
2514 :
2515 563288 : int GDALRasterBand::GetXSize()
2516 :
2517 : {
2518 563288 : return nRasterXSize;
2519 : }
2520 :
2521 : /************************************************************************/
2522 : /* GDALGetRasterBandXSize() */
2523 : /************************************************************************/
2524 :
2525 : /**
2526 : * \brief Fetch XSize of raster.
2527 : *
2528 : * @see GDALRasterBand::GetXSize()
2529 : */
2530 :
2531 2156 : int CPL_STDCALL GDALGetRasterBandXSize( GDALRasterBandH hBand )
2532 :
2533 : {
2534 2156 : VALIDATE_POINTER1( hBand, "GDALGetRasterBandXSize", 0 );
2535 :
2536 2156 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2537 2156 : return poBand->GetXSize();
2538 : }
2539 :
2540 : /************************************************************************/
2541 : /* GetYSize() */
2542 : /************************************************************************/
2543 :
2544 : /**
2545 : * \brief Fetch YSize of raster.
2546 : *
2547 : * This method is the same as the C function GDALGetRasterBandYSize().
2548 : *
2549 : * @return the height in pixels of this band.
2550 : */
2551 :
2552 113754 : int GDALRasterBand::GetYSize()
2553 :
2554 : {
2555 113754 : return nRasterYSize;
2556 : }
2557 :
2558 : /************************************************************************/
2559 : /* GDALGetRasterBandYSize() */
2560 : /************************************************************************/
2561 :
2562 : /**
2563 : * \brief Fetch YSize of raster.
2564 : *
2565 : * @see GDALRasterBand::GetYSize()
2566 : */
2567 :
2568 2107 : int CPL_STDCALL GDALGetRasterBandYSize( GDALRasterBandH hBand )
2569 :
2570 : {
2571 2107 : VALIDATE_POINTER1( hBand, "GDALGetRasterBandYSize", 0 );
2572 :
2573 2107 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2574 2107 : return poBand->GetYSize();
2575 : }
2576 :
2577 : /************************************************************************/
2578 : /* GetBand() */
2579 : /************************************************************************/
2580 :
2581 : /**
2582 : * \brief Fetch the band number.
2583 : *
2584 : * This method returns the band that this GDALRasterBand objects represents
2585 : * within it's dataset. This method may return a value of 0 to indicate
2586 : * GDALRasterBand objects without an apparently relationship to a dataset,
2587 : * such as GDALRasterBands serving as overviews.
2588 : *
2589 : * This method is the same as the C function GDALGetBandNumber().
2590 : *
2591 : * @return band number (1+) or 0 if the band number isn't known.
2592 : */
2593 :
2594 2195 : int GDALRasterBand::GetBand()
2595 :
2596 : {
2597 2195 : return nBand;
2598 : }
2599 :
2600 : /************************************************************************/
2601 : /* GDALGetBandNumber() */
2602 : /************************************************************************/
2603 :
2604 : /**
2605 : * \brief Fetch the band number.
2606 : *
2607 : * @see GDALRasterBand::GetBand()
2608 : */
2609 :
2610 6 : int CPL_STDCALL GDALGetBandNumber( GDALRasterBandH hBand )
2611 :
2612 : {
2613 6 : VALIDATE_POINTER1( hBand, "GDALGetBandNumber", 0 );
2614 :
2615 6 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2616 6 : return poBand->GetBand();
2617 : }
2618 :
2619 : /************************************************************************/
2620 : /* GetDataset() */
2621 : /************************************************************************/
2622 :
2623 : /**
2624 : * \brief Fetch the owning dataset handle.
2625 : *
2626 : * Note that some GDALRasterBands are not considered to be a part of a dataset,
2627 : * such as overviews or other "freestanding" bands.
2628 : *
2629 : * This method is the same as the C function GDALGetBandDataset()
2630 : *
2631 : * @return the pointer to the GDALDataset to which this band belongs, or
2632 : * NULL if this cannot be determined.
2633 : */
2634 :
2635 486349 : GDALDataset *GDALRasterBand::GetDataset()
2636 :
2637 : {
2638 486349 : return poDS;
2639 : }
2640 :
2641 : /************************************************************************/
2642 : /* GDALGetBandDataset() */
2643 : /************************************************************************/
2644 :
2645 : /**
2646 : * \brief Fetch the owning dataset handle.
2647 : *
2648 : * @see GDALRasterBand::GetDataset()
2649 : */
2650 :
2651 14 : GDALDatasetH CPL_STDCALL GDALGetBandDataset( GDALRasterBandH hBand )
2652 :
2653 : {
2654 14 : VALIDATE_POINTER1( hBand, "GDALGetBandDataset", NULL );
2655 :
2656 14 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
2657 14 : return (GDALDatasetH) poBand->GetDataset();
2658 : }
2659 :
2660 : /************************************************************************/
2661 : /* GetHistogram() */
2662 : /************************************************************************/
2663 :
2664 : /**
2665 : * \brief Compute raster histogram.
2666 : *
2667 : * Note that the bucket size is (dfMax-dfMin) / nBuckets.
2668 : *
2669 : * For example to compute a simple 256 entry histogram of eight bit data,
2670 : * the following would be suitable. The unusual bounds are to ensure that
2671 : * bucket boundaries don't fall right on integer values causing possible errors
2672 : * due to rounding after scaling.
2673 : <pre>
2674 : int anHistogram[256];
2675 :
2676 : poBand->GetHistogram( -0.5, 255.5, 256, anHistogram, FALSE, FALSE,
2677 : GDALDummyProgress, NULL );
2678 : </pre>
2679 : *
2680 : * Note that setting bApproxOK will generally result in a subsampling of the
2681 : * file, and will utilize overviews if available. It should generally
2682 : * produce a representative histogram for the data that is suitable for use
2683 : * in generating histogram based luts for instance. Generally bApproxOK is
2684 : * much faster than an exactly computed histogram.
2685 : *
2686 : * @param dfMin the lower bound of the histogram.
2687 : * @param dfMax the upper bound of the histogram.
2688 : * @param nBuckets the number of buckets in panHistogram.
2689 : * @param panHistogram array into which the histogram totals are placed.
2690 : * @param bIncludeOutOfRange if TRUE values below the histogram range will
2691 : * mapped into panHistogram[0], and values above will be mapped into
2692 : * panHistogram[nBuckets-1] otherwise out of range values are discarded.
2693 : * @param bApproxOK TRUE if an approximate, or incomplete histogram OK.
2694 : * @param pfnProgress function to report progress to completion.
2695 : * @param pProgressData application data to pass to pfnProgress.
2696 : *
2697 : * @return CE_None on success, or CE_Failure if something goes wrong.
2698 : */
2699 :
2700 : CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
2701 : int nBuckets, int *panHistogram,
2702 : int bIncludeOutOfRange, int bApproxOK,
2703 : GDALProgressFunc pfnProgress,
2704 6 : void *pProgressData )
2705 :
2706 : {
2707 6 : CPLAssert( NULL != panHistogram );
2708 :
2709 6 : if( pfnProgress == NULL )
2710 4 : pfnProgress = GDALDummyProgress;
2711 :
2712 : /* -------------------------------------------------------------------- */
2713 : /* If we have overviews, use them for the histogram. */
2714 : /* -------------------------------------------------------------------- */
2715 6 : if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
2716 : {
2717 : // FIXME: should we use the most reduced overview here or use some
2718 : // minimum number of samples like GDALRasterBand::ComputeStatistics()
2719 : // does?
2720 0 : GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
2721 :
2722 0 : if( poBestOverview != this )
2723 : {
2724 : return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
2725 : panHistogram,
2726 : bIncludeOutOfRange, bApproxOK,
2727 0 : pfnProgress, pProgressData );
2728 : }
2729 : }
2730 :
2731 : /* -------------------------------------------------------------------- */
2732 : /* Read actual data and build histogram. */
2733 : /* -------------------------------------------------------------------- */
2734 : double dfScale;
2735 :
2736 6 : if( !pfnProgress( 0.0, "Compute Histogram", pProgressData ) )
2737 : {
2738 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2739 0 : return CE_Failure;
2740 : }
2741 :
2742 6 : dfScale = nBuckets / (dfMax - dfMin);
2743 6 : memset( panHistogram, 0, sizeof(int) * nBuckets );
2744 :
2745 6 : const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
2746 6 : int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
2747 :
2748 6 : if ( bApproxOK && HasArbitraryOverviews() )
2749 : {
2750 : /* -------------------------------------------------------------------- */
2751 : /* Figure out how much the image should be reduced to get an */
2752 : /* approximate value. */
2753 : /* -------------------------------------------------------------------- */
2754 : void *pData;
2755 : int nXReduced, nYReduced;
2756 : double dfReduction = sqrt(
2757 0 : (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
2758 :
2759 0 : if ( dfReduction > 1.0 )
2760 : {
2761 0 : nXReduced = (int)( nRasterXSize / dfReduction );
2762 0 : nYReduced = (int)( nRasterYSize / dfReduction );
2763 :
2764 : // Catch the case of huge resizing ratios here
2765 0 : if ( nXReduced == 0 )
2766 0 : nXReduced = 1;
2767 0 : if ( nYReduced == 0 )
2768 0 : nYReduced = 1;
2769 : }
2770 : else
2771 : {
2772 0 : nXReduced = nRasterXSize;
2773 0 : nYReduced = nRasterYSize;
2774 : }
2775 :
2776 : pData =
2777 0 : CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
2778 :
2779 : CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
2780 0 : nXReduced, nYReduced, eDataType, 0, 0 );
2781 0 : if ( eErr != CE_None )
2782 : {
2783 0 : CPLFree(pData);
2784 0 : return eErr;
2785 : }
2786 :
2787 : /* this isn't the fastest way to do this, but is easier for now */
2788 0 : for( int iY = 0; iY < nYReduced; iY++ )
2789 : {
2790 0 : for( int iX = 0; iX < nXReduced; iX++ )
2791 : {
2792 0 : int iOffset = iX + iY * nXReduced;
2793 : int nIndex;
2794 0 : double dfValue = 0.0;
2795 :
2796 0 : switch( eDataType )
2797 : {
2798 : case GDT_Byte:
2799 : {
2800 0 : if (bSignedByte)
2801 0 : dfValue = ((signed char *)pData)[iOffset];
2802 : else
2803 0 : dfValue = ((GByte *)pData)[iOffset];
2804 0 : break;
2805 : }
2806 : case GDT_UInt16:
2807 0 : dfValue = ((GUInt16 *)pData)[iOffset];
2808 0 : break;
2809 : case GDT_Int16:
2810 0 : dfValue = ((GInt16 *)pData)[iOffset];
2811 0 : break;
2812 : case GDT_UInt32:
2813 0 : dfValue = ((GUInt32 *)pData)[iOffset];
2814 0 : break;
2815 : case GDT_Int32:
2816 0 : dfValue = ((GInt32 *)pData)[iOffset];
2817 0 : break;
2818 : case GDT_Float32:
2819 0 : dfValue = ((float *)pData)[iOffset];
2820 0 : if (CPLIsNan(dfValue))
2821 0 : continue;
2822 0 : break;
2823 : case GDT_Float64:
2824 0 : dfValue = ((double *)pData)[iOffset];
2825 0 : if (CPLIsNan(dfValue))
2826 0 : continue;
2827 0 : break;
2828 : case GDT_CInt16:
2829 : {
2830 0 : double dfReal = ((GInt16 *)pData)[iOffset*2];
2831 0 : double dfImag = ((GInt16 *)pData)[iOffset*2+1];
2832 0 : dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
2833 : }
2834 0 : break;
2835 : case GDT_CInt32:
2836 : {
2837 0 : double dfReal = ((GInt32 *)pData)[iOffset*2];
2838 0 : double dfImag = ((GInt32 *)pData)[iOffset*2+1];
2839 0 : dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
2840 : }
2841 0 : break;
2842 : case GDT_CFloat32:
2843 : {
2844 0 : double dfReal = ((float *)pData)[iOffset*2];
2845 0 : double dfImag = ((float *)pData)[iOffset*2+1];
2846 0 : if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
2847 0 : continue;
2848 0 : dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
2849 : }
2850 0 : break;
2851 : case GDT_CFloat64:
2852 : {
2853 0 : double dfReal = ((double *)pData)[iOffset*2];
2854 0 : double dfImag = ((double *)pData)[iOffset*2+1];
2855 0 : if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
2856 0 : continue;
2857 0 : dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
2858 : }
2859 0 : break;
2860 : default:
2861 0 : CPLAssert( FALSE );
2862 : }
2863 :
2864 0 : nIndex = (int) floor((dfValue - dfMin) * dfScale);
2865 :
2866 0 : if( nIndex < 0 )
2867 : {
2868 0 : if( bIncludeOutOfRange )
2869 0 : panHistogram[0]++;
2870 : }
2871 0 : else if( nIndex >= nBuckets )
2872 : {
2873 0 : if( bIncludeOutOfRange )
2874 0 : panHistogram[nBuckets-1]++;
2875 : }
2876 : else
2877 : {
2878 0 : panHistogram[nIndex]++;
2879 : }
2880 : }
2881 : }
2882 :
2883 0 : CPLFree( pData );
2884 : }
2885 :
2886 : else // No arbitrary overviews
2887 : {
2888 : int nSampleRate;
2889 :
2890 6 : if( !InitBlockInfo() )
2891 0 : return CE_Failure;
2892 :
2893 : /* -------------------------------------------------------------------- */
2894 : /* Figure out the ratio of blocks we will read to get an */
2895 : /* approximate value. */
2896 : /* -------------------------------------------------------------------- */
2897 :
2898 6 : if ( bApproxOK )
2899 : {
2900 : nSampleRate =
2901 2 : (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
2902 : }
2903 : else
2904 4 : nSampleRate = 1;
2905 :
2906 : /* -------------------------------------------------------------------- */
2907 : /* Read the blocks, and add to histogram. */
2908 : /* -------------------------------------------------------------------- */
2909 24 : for( int iSampleBlock = 0;
2910 : iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
2911 : iSampleBlock += nSampleRate )
2912 : {
2913 : int iXBlock, iYBlock, nXCheck, nYCheck;
2914 : GDALRasterBlock *poBlock;
2915 : void* pData;
2916 :
2917 18 : if( !pfnProgress( iSampleBlock
2918 : / ((double)nBlocksPerRow * nBlocksPerColumn),
2919 : "Compute Histogram", pProgressData ) )
2920 0 : return CE_Failure;
2921 :
2922 18 : iYBlock = iSampleBlock / nBlocksPerRow;
2923 18 : iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
2924 :
2925 18 : poBlock = GetLockedBlockRef( iXBlock, iYBlock );
2926 18 : if( poBlock == NULL )
2927 0 : return CE_Failure;
2928 18 : if( poBlock->GetDataRef() == NULL )
2929 : {
2930 0 : poBlock->DropLock();
2931 0 : return CE_Failure;
2932 : }
2933 :
2934 18 : pData = poBlock->GetDataRef();
2935 :
2936 18 : if( (iXBlock+1) * nBlockXSize > GetXSize() )
2937 0 : nXCheck = GetXSize() - iXBlock * nBlockXSize;
2938 : else
2939 18 : nXCheck = nBlockXSize;
2940 :
2941 18 : if( (iYBlock+1) * nBlockYSize > GetYSize() )
2942 2 : nYCheck = GetYSize() - iYBlock * nBlockYSize;
2943 : else
2944 16 : nYCheck = nBlockYSize;
2945 :
2946 : /* this is a special case for a common situation */
2947 18 : if( eDataType == GDT_Byte && !bSignedByte
2948 : && dfScale == 1.0 && (dfMin >= -0.5 && dfMin <= 0.5)
2949 : && nYCheck == nBlockYSize && nXCheck == nBlockXSize
2950 : && nBuckets == 256 )
2951 : {
2952 3 : int nPixels = nXCheck * nYCheck;
2953 3 : GByte *pabyData = (GByte *) pData;
2954 :
2955 8903 : for( int i = 0; i < nPixels; i++ )
2956 8900 : panHistogram[pabyData[i]]++;
2957 :
2958 3 : poBlock->DropLock();
2959 3 : continue; /* to next sample block */
2960 : }
2961 :
2962 : /* this isn't the fastest way to do this, but is easier for now */
2963 146 : for( int iY = 0; iY < nYCheck; iY++ )
2964 : {
2965 12091 : for( int iX = 0; iX < nXCheck; iX++ )
2966 : {
2967 11960 : int iOffset = iX + iY * nBlockXSize;
2968 : int nIndex;
2969 11960 : double dfValue = 0.0;
2970 :
2971 11960 : switch( eDataType )
2972 : {
2973 : case GDT_Byte:
2974 : {
2975 11900 : if (bSignedByte)
2976 0 : dfValue = ((signed char *) pData)[iOffset];
2977 : else
2978 11900 : dfValue = ((GByte *) pData)[iOffset];
2979 11900 : break;
2980 : }
2981 : case GDT_UInt16:
2982 0 : dfValue = ((GUInt16 *) pData)[iOffset];
2983 0 : break;
2984 : case GDT_Int16:
2985 0 : dfValue = ((GInt16 *) pData)[iOffset];
2986 0 : break;
2987 : case GDT_UInt32:
2988 0 : dfValue = ((GUInt32 *) pData)[iOffset];
2989 0 : break;
2990 : case GDT_Int32:
2991 60 : dfValue = ((GInt32 *) pData)[iOffset];
2992 60 : break;
2993 : case GDT_Float32:
2994 0 : dfValue = ((float *) pData)[iOffset];
2995 0 : if (CPLIsNan(dfValue))
2996 0 : continue;
2997 0 : break;
2998 : case GDT_Float64:
2999 0 : dfValue = ((double *) pData)[iOffset];
3000 0 : if (CPLIsNan(dfValue))
3001 0 : continue;
3002 0 : break;
3003 : case GDT_CInt16:
3004 : {
3005 : double dfReal =
3006 0 : ((GInt16 *) pData)[iOffset*2];
3007 : double dfImag =
3008 0 : ((GInt16 *) pData)[iOffset*2+1];
3009 0 : dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3010 : }
3011 0 : break;
3012 : case GDT_CInt32:
3013 : {
3014 : double dfReal =
3015 0 : ((GInt32 *) pData)[iOffset*2];
3016 : double dfImag =
3017 0 : ((GInt32 *) pData)[iOffset*2+1];
3018 0 : dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3019 : }
3020 0 : break;
3021 : case GDT_CFloat32:
3022 : {
3023 : double dfReal =
3024 0 : ((float *) pData)[iOffset*2];
3025 : double dfImag =
3026 0 : ((float *) pData)[iOffset*2+1];
3027 0 : if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
3028 0 : continue;
3029 0 : dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3030 : }
3031 0 : break;
3032 : case GDT_CFloat64:
3033 : {
3034 : double dfReal =
3035 0 : ((double *) pData)[iOffset*2];
3036 : double dfImag =
3037 0 : ((double *) pData)[iOffset*2+1];
3038 0 : if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
3039 0 : continue;
3040 0 : dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3041 : }
3042 0 : break;
3043 : default:
3044 0 : CPLAssert( FALSE );
3045 0 : return CE_Failure;
3046 : }
3047 :
3048 11960 : nIndex = (int) floor((dfValue - dfMin) * dfScale);
3049 :
3050 11960 : if( nIndex < 0 )
3051 : {
3052 0 : if( bIncludeOutOfRange )
3053 0 : panHistogram[0]++;
3054 : }
3055 11960 : else if( nIndex >= nBuckets )
3056 : {
3057 6 : if( bIncludeOutOfRange )
3058 3 : panHistogram[nBuckets-1]++;
3059 : }
3060 : else
3061 : {
3062 11954 : panHistogram[nIndex]++;
3063 : }
3064 : }
3065 : }
3066 :
3067 15 : poBlock->DropLock();
3068 : }
3069 : }
3070 :
3071 6 : pfnProgress( 1.0, "Compute Histogram", pProgressData );
3072 :
3073 6 : return CE_None;
3074 : }
3075 :
3076 : /************************************************************************/
3077 : /* GDALGetRasterHistogram() */
3078 : /************************************************************************/
3079 :
3080 : /**
3081 : * \brief Compute raster histogram.
3082 : *
3083 : * @see GDALRasterBand::GetHistogram()
3084 : */
3085 :
3086 : CPLErr CPL_STDCALL
3087 : GDALGetRasterHistogram( GDALRasterBandH hBand,
3088 : double dfMin, double dfMax,
3089 : int nBuckets, int *panHistogram,
3090 : int bIncludeOutOfRange, int bApproxOK,
3091 : GDALProgressFunc pfnProgress,
3092 4 : void *pProgressData )
3093 :
3094 : {
3095 4 : VALIDATE_POINTER1( hBand, "GDALGetRasterHistogram", CE_Failure );
3096 4 : VALIDATE_POINTER1( panHistogram, "GDALGetRasterHistogram", CE_Failure );
3097 :
3098 4 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
3099 :
3100 : return poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogram,
3101 : bIncludeOutOfRange, bApproxOK,
3102 4 : pfnProgress, pProgressData );
3103 : }
3104 :
3105 : /************************************************************************/
3106 : /* GetDefaultHistogram() */
3107 : /************************************************************************/
3108 :
3109 : /**
3110 : * \brief Fetch default raster histogram.
3111 : *
3112 : * The default method in GDALRasterBand will compute a default histogram. This
3113 : * method is overriden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
3114 : * that may be able to fetch efficiently an already stored histogram.
3115 : *
3116 : * @param pdfMin pointer to double value that will contain the lower bound of the histogram.
3117 : * @param pdfMax pointer to double value that will contain the upper bound of the histogram.
3118 : * @param pnBuckets pointer to int value that will contain the number of buckets in *ppanHistogram.
3119 : * @param ppanHistogram pointer to array into which the histogram totals are placed. To be freed with VSIFree
3120 : * @param bForce TRUE to force the computation. If FALSE and no default histogram is available, the method will return CE_Warning
3121 : * @param pfnProgress function to report progress to completion.
3122 : * @param pProgressData application data to pass to pfnProgress.
3123 : *
3124 : * @return CE_None on success, CE_Failure if something goes wrong, or
3125 : * CE_Warning if no default histogram is available.
3126 : */
3127 :
3128 : CPLErr
3129 : GDALRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
3130 : int *pnBuckets, int **ppanHistogram,
3131 : int bForce,
3132 : GDALProgressFunc pfnProgress,
3133 5 : void *pProgressData )
3134 :
3135 : {
3136 5 : CPLAssert( NULL != pnBuckets );
3137 5 : CPLAssert( NULL != ppanHistogram );
3138 5 : CPLAssert( NULL != pdfMin );
3139 5 : CPLAssert( NULL != pdfMax );
3140 :
3141 5 : *pnBuckets = 0;
3142 5 : *ppanHistogram = NULL;
3143 :
3144 5 : if( !bForce )
3145 3 : return CE_Warning;
3146 :
3147 2 : int nBuckets = 256;
3148 :
3149 2 : const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
3150 2 : int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
3151 :
3152 2 : if( GetRasterDataType() == GDT_Byte && !bSignedByte)
3153 : {
3154 2 : *pdfMin = -0.5;
3155 2 : *pdfMax = 255.5;
3156 : }
3157 : else
3158 : {
3159 0 : CPLErr eErr = CE_Failure;
3160 0 : double dfHalfBucket = 0;
3161 :
3162 0 : eErr = GetStatistics( TRUE, TRUE, pdfMin, pdfMax, NULL, NULL );
3163 0 : dfHalfBucket = (*pdfMax - *pdfMin) / (2 * nBuckets);
3164 0 : *pdfMin -= dfHalfBucket;
3165 0 : *pdfMax += dfHalfBucket;
3166 :
3167 0 : if( eErr != CE_None )
3168 0 : return eErr;
3169 : }
3170 :
3171 2 : *ppanHistogram = (int *) VSICalloc(sizeof(int), nBuckets);
3172 2 : if( *ppanHistogram == NULL )
3173 : {
3174 : CPLError( CE_Failure, CPLE_OutOfMemory,
3175 0 : "Out of memory in InitBlockInfo()." );
3176 0 : return CE_Failure;
3177 : }
3178 :
3179 2 : *pnBuckets = nBuckets;
3180 : return GetHistogram( *pdfMin, *pdfMax, *pnBuckets, *ppanHistogram,
3181 2 : TRUE, FALSE, pfnProgress, pProgressData );
3182 : }
3183 :
3184 : /************************************************************************/
3185 : /* GDALGetDefaultHistogram() */
3186 : /************************************************************************/
3187 :
3188 : /**
3189 : * \brief Fetch default raster histogram.
3190 : *
3191 : * @see GDALRasterBand::GetDefaultHistogram()
3192 : */
3193 :
3194 : CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand,
3195 : double *pdfMin, double *pdfMax,
3196 : int *pnBuckets, int **ppanHistogram,
3197 : int bForce,
3198 : GDALProgressFunc pfnProgress,
3199 4 : void *pProgressData )
3200 :
3201 : {
3202 4 : VALIDATE_POINTER1( hBand, "GDALGetDefaultHistogram", CE_Failure );
3203 4 : VALIDATE_POINTER1( pdfMin, "GDALGetDefaultHistogram", CE_Failure );
3204 4 : VALIDATE_POINTER1( pdfMax, "GDALGetDefaultHistogram", CE_Failure );
3205 4 : VALIDATE_POINTER1( pnBuckets, "GDALGetDefaultHistogram", CE_Failure );
3206 4 : VALIDATE_POINTER1( ppanHistogram, "GDALGetDefaultHistogram", CE_Failure );
3207 :
3208 4 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
3209 : return poBand->GetDefaultHistogram( pdfMin, pdfMax,
3210 4 : pnBuckets, ppanHistogram, bForce, pfnProgress, pProgressData );
3211 : }
3212 :
3213 : /************************************************************************/
3214 : /* AdviseRead() */
3215 : /************************************************************************/
3216 :
3217 : /**
3218 : * \brief Advise driver of upcoming read requests.
3219 : *
3220 : * Some GDAL drivers operate more efficiently if they know in advance what
3221 : * set of upcoming read requests will be made. The AdviseRead() method allows
3222 : * an application to notify the driver of the region of interest,
3223 : * and at what resolution the region will be read.
3224 : *
3225 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
3226 : * accelerate access via some drivers.
3227 : *
3228 : * @param nXOff The pixel offset to the top left corner of the region
3229 : * of the band to be accessed. This would be zero to start from the left side.
3230 : *
3231 : * @param nYOff The line offset to the top left corner of the region
3232 : * of the band to be accessed. This would be zero to start from the top.
3233 : *
3234 : * @param nXSize The width of the region of the band to be accessed in pixels.
3235 : *
3236 : * @param nYSize The height of the region of the band to be accessed in lines.
3237 : *
3238 : * @param nBufXSize the width of the buffer image into which the desired region
3239 : * is to be read, or from which it is to be written.
3240 : *
3241 : * @param nBufYSize the height of the buffer image into which the desired
3242 : * region is to be read, or from which it is to be written.
3243 : *
3244 : * @param eBufType the type of the pixel values in the pData data buffer. The
3245 : * pixel values will automatically be translated to/from the GDALRasterBand
3246 : * data type as needed.
3247 : *
3248 : * @param papszOptions a list of name=value strings with special control
3249 : * options. Normally this is NULL.
3250 : *
3251 : * @return CE_Failure if the request is invalid and CE_None if it works or
3252 : * is ignored.
3253 : */
3254 :
3255 : CPLErr GDALRasterBand::AdviseRead(
3256 : int nXOff, int nYOff, int nXSize, int nYSize,
3257 0 : int nBufXSize, int nBufYSize, GDALDataType eDT, char **papszOptions )
3258 :
3259 : {
3260 0 : return CE_None;
3261 : }
3262 :
3263 : /************************************************************************/
3264 : /* GDALRasterAdviseRead() */
3265 : /************************************************************************/
3266 :
3267 :
3268 : /**
3269 : * \brief Advise driver of upcoming read requests.
3270 : *
3271 : * @see GDALRasterBand::AdviseRead()
3272 : */
3273 :
3274 : CPLErr CPL_STDCALL
3275 : GDALRasterAdviseRead( GDALRasterBandH hBand,
3276 : int nXOff, int nYOff, int nXSize, int nYSize,
3277 : int nBufXSize, int nBufYSize,
3278 0 : GDALDataType eDT, char **papszOptions )
3279 :
3280 : {
3281 0 : VALIDATE_POINTER1( hBand, "GDALRasterAdviseRead", CE_Failure );
3282 :
3283 0 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
3284 : return poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize,
3285 0 : nBufXSize, nBufYSize, eDT, papszOptions );
3286 : }
3287 :
3288 : /************************************************************************/
3289 : /* GetStatistics() */
3290 : /************************************************************************/
3291 :
3292 : /**
3293 : * \brief Fetch image statistics.
3294 : *
3295 : * Returns the minimum, maximum, mean and standard deviation of all
3296 : * pixel values in this band. If approximate statistics are sufficient,
3297 : * the bApproxOK flag can be set to true in which case overviews, or a
3298 : * subset of image tiles may be used in computing the statistics.
3299 : *
3300 : * If bForce is FALSE results will only be returned if it can be done
3301 : * quickly (ie. without scanning the data). If bForce is FALSE and
3302 : * results cannot be returned efficiently, the method will return CE_Warning
3303 : * but no warning will have been issued. This is a non-standard use of
3304 : * the CE_Warning return value to indicate "nothing done".
3305 : *
3306 : * Note that file formats using PAM (Persistent Auxilary Metadata) services
3307 : * will generally cache statistics in the .pam file allowing fast fetch
3308 : * after the first request.
3309 : *
3310 : * This method is the same as the C function GDALGetRasterStatistics().
3311 : *
3312 : * @param bApproxOK If TRUE statistics may be computed based on overviews
3313 : * or a subset of all tiles.
3314 : *
3315 : * @param bForce If FALSE statistics will only be returned if it can
3316 : * be done without rescanning the image.
3317 : *
3318 : * @param pdfMin Location into which to load image minimum (may be NULL).
3319 : *
3320 : * @param pdfMax Location into which to load image maximum (may be NULL).-
3321 : *
3322 : * @param pdfMean Location into which to load image mean (may be NULL).
3323 : *
3324 : * @param pdfStdDev Location into which to load image standard deviation
3325 : * (may be NULL).
3326 : *
3327 : * @return CE_None on success, CE_Warning if no values returned,
3328 : * CE_Failure if an error occurs.
3329 : */
3330 :
3331 : CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
3332 : double *pdfMin, double *pdfMax,
3333 86 : double *pdfMean, double *pdfStdDev )
3334 :
3335 : {
3336 86 : double dfMin=0.0, dfMax=0.0;
3337 :
3338 : /* -------------------------------------------------------------------- */
3339 : /* Do we already have metadata items for the requested values? */
3340 : /* -------------------------------------------------------------------- */
3341 86 : if( (pdfMin == NULL || GetMetadataItem("STATISTICS_MINIMUM") != NULL)
3342 : && (pdfMax == NULL || GetMetadataItem("STATISTICS_MAXIMUM") != NULL)
3343 : && (pdfMean == NULL || GetMetadataItem("STATISTICS_MEAN") != NULL)
3344 : && (pdfStdDev == NULL || GetMetadataItem("STATISTICS_STDDEV") != NULL) )
3345 : {
3346 13 : if( pdfMin != NULL )
3347 13 : *pdfMin = atof(GetMetadataItem("STATISTICS_MINIMUM"));
3348 13 : if( pdfMax != NULL )
3349 13 : *pdfMax = atof(GetMetadataItem("STATISTICS_MAXIMUM"));
3350 13 : if( pdfMean != NULL )
3351 13 : *pdfMean = atof(GetMetadataItem("STATISTICS_MEAN"));
3352 13 : if( pdfStdDev != NULL )
3353 13 : *pdfStdDev = atof(GetMetadataItem("STATISTICS_STDDEV"));
3354 :
3355 13 : return CE_None;
3356 : }
3357 :
3358 : /* -------------------------------------------------------------------- */
3359 : /* Does the driver already know the min/max? */
3360 : /* -------------------------------------------------------------------- */
3361 73 : if( bApproxOK && pdfMean == NULL && pdfStdDev == NULL )
3362 : {
3363 : int bSuccessMin, bSuccessMax;
3364 :
3365 0 : dfMin = GetMinimum( &bSuccessMin );
3366 0 : dfMax = GetMaximum( &bSuccessMax );
3367 :
3368 0 : if( bSuccessMin && bSuccessMax )
3369 : {
3370 0 : if( pdfMin != NULL )
3371 0 : *pdfMin = dfMin;
3372 0 : if( pdfMax != NULL )
3373 0 : *pdfMax = dfMax;
3374 0 : return CE_None;
3375 : }
3376 : }
3377 :
3378 : /* -------------------------------------------------------------------- */
3379 : /* Either return without results, or force computation. */
3380 : /* -------------------------------------------------------------------- */
3381 73 : if( !bForce )
3382 36 : return CE_Warning;
3383 : else
3384 : return ComputeStatistics( bApproxOK,
3385 : pdfMin, pdfMax, pdfMean, pdfStdDev,
3386 37 : GDALDummyProgress, NULL );
3387 : }
3388 :
3389 : /************************************************************************/
3390 : /* GDALGetRasterStatistics() */
3391 : /************************************************************************/
3392 :
3393 : /**
3394 : * \brief Fetch image statistics.
3395 : *
3396 : * @see GDALRasterBand::GetStatistics()
3397 : */
3398 :
3399 : CPLErr CPL_STDCALL GDALGetRasterStatistics(
3400 : GDALRasterBandH hBand, int bApproxOK, int bForce,
3401 62 : double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
3402 :
3403 : {
3404 62 : VALIDATE_POINTER1( hBand, "GDALGetRasterStatistics", CE_Failure );
3405 :
3406 62 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
3407 : return poBand->GetStatistics(
3408 62 : bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev );
3409 : }
3410 :
3411 : /************************************************************************/
3412 : /* ComputeStatistics() */
3413 : /************************************************************************/
3414 :
3415 : /**
3416 : * \brief Compute image statistics.
3417 : *
3418 : * Returns the minimum, maximum, mean and standard deviation of all
3419 : * pixel values in this band. If approximate statistics are sufficient,
3420 : * the bApproxOK flag can be set to true in which case overviews, or a
3421 : * subset of image tiles may be used in computing the statistics.
3422 : *
3423 : * Once computed, the statistics will generally be "set" back on the
3424 : * raster band using SetStatistics().
3425 : *
3426 : * This method is the same as the C function GDALComputeRasterStatistics().
3427 : *
3428 : * @param bApproxOK If TRUE statistics may be computed based on overviews
3429 : * or a subset of all tiles.
3430 : *
3431 : * @param pdfMin Location into which to load image minimum (may be NULL).
3432 : *
3433 : * @param pdfMax Location into which to load image maximum (may be NULL).-
3434 : *
3435 : * @param pdfMean Location into which to load image mean (may be NULL).
3436 : *
3437 : * @param pdfStdDev Location into which to load image standard deviation
3438 : * (may be NULL).
3439 : *
3440 : * @param pfnProgress a function to call to report progress, or NULL.
3441 : *
3442 : * @param pProgressData application data to pass to the progress function.
3443 : *
3444 : * @return CE_None on success, or CE_Failure if an error occurs or processing
3445 : * is terminated by the user.
3446 : */
3447 :
3448 : CPLErr
3449 : GDALRasterBand::ComputeStatistics( int bApproxOK,
3450 : double *pdfMin, double *pdfMax,
3451 : double *pdfMean, double *pdfStdDev,
3452 : GDALProgressFunc pfnProgress,
3453 39 : void *pProgressData )
3454 :
3455 : {
3456 39 : if( pfnProgress == NULL )
3457 0 : pfnProgress = GDALDummyProgress;
3458 :
3459 : /* -------------------------------------------------------------------- */
3460 : /* If we have overview bands, use them for statistics. */
3461 : /* -------------------------------------------------------------------- */
3462 39 : if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
3463 : {
3464 : GDALRasterBand *poBand;
3465 :
3466 2 : poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
3467 :
3468 2 : if( poBand != this )
3469 : return poBand->ComputeStatistics( FALSE,
3470 : pdfMin, pdfMax,
3471 : pdfMean, pdfStdDev,
3472 2 : pfnProgress, pProgressData );
3473 : }
3474 :
3475 : /* -------------------------------------------------------------------- */
3476 : /* Read actual data and compute statistics. */
3477 : /* -------------------------------------------------------------------- */
3478 37 : double dfMin = 0.0, dfMax = 0.0;
3479 37 : int bGotNoDataValue, bFirstValue = TRUE;
3480 37 : double dfNoDataValue, dfSum = 0.0, dfSum2 = 0.0;
3481 37 : GIntBig nSampleCount = 0;
3482 :
3483 37 : if( !pfnProgress( 0.0, "Compute Statistics", pProgressData ) )
3484 : {
3485 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3486 0 : return CE_Failure;
3487 : }
3488 :
3489 37 : dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
3490 :
3491 37 : const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
3492 37 : int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
3493 :
3494 37 : if ( bApproxOK && HasArbitraryOverviews() )
3495 : {
3496 : /* -------------------------------------------------------------------- */
3497 : /* Figure out how much the image should be reduced to get an */
3498 : /* approximate value. */
3499 : /* -------------------------------------------------------------------- */
3500 : void *pData;
3501 : int nXReduced, nYReduced;
3502 : double dfReduction = sqrt(
3503 0 : (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
3504 :
3505 0 : if ( dfReduction > 1.0 )
3506 : {
3507 0 : nXReduced = (int)( nRasterXSize / dfReduction );
3508 0 : nYReduced = (int)( nRasterYSize / dfReduction );
3509 :
3510 : // Catch the case of huge resizing ratios here
3511 0 : if ( nXReduced == 0 )
3512 0 : nXReduced = 1;
3513 0 : if ( nYReduced == 0 )
3514 0 : nYReduced = 1;
3515 : }
3516 : else
3517 : {
3518 0 : nXReduced = nRasterXSize;
3519 0 : nYReduced = nRasterYSize;
3520 : }
3521 :
3522 : pData =
3523 0 : CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
3524 :
3525 : CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
3526 0 : nXReduced, nYReduced, eDataType, 0, 0 );
3527 0 : if ( eErr != CE_None )
3528 : {
3529 0 : CPLFree(pData);
3530 0 : return eErr;
3531 : }
3532 :
3533 : /* this isn't the fastest way to do this, but is easier for now */
3534 0 : for( int iY = 0; iY < nYReduced; iY++ )
3535 : {
3536 0 : for( int iX = 0; iX < nXReduced; iX++ )
3537 : {
3538 0 : int iOffset = iX + iY * nXReduced;
3539 0 : double dfValue = 0.0;
3540 :
3541 0 : switch( eDataType )
3542 : {
3543 : case GDT_Byte:
3544 : {
3545 0 : if (bSignedByte)
3546 0 : dfValue = ((signed char *)pData)[iOffset];
3547 : else
3548 0 : dfValue = ((GByte *)pData)[iOffset];
3549 0 : break;
3550 : }
3551 : case GDT_UInt16:
3552 0 : dfValue = ((GUInt16 *)pData)[iOffset];
3553 0 : break;
3554 : case GDT_Int16:
3555 0 : dfValue = ((GInt16 *)pData)[iOffset];
3556 0 : break;
3557 : case GDT_UInt32:
3558 0 : dfValue = ((GUInt32 *)pData)[iOffset];
3559 0 : break;
3560 : case GDT_Int32:
3561 0 : dfValue = ((GInt32 *)pData)[iOffset];
3562 0 : break;
3563 : case GDT_Float32:
3564 0 : dfValue = ((float *)pData)[iOffset];
3565 0 : if (CPLIsNan(dfValue))
3566 0 : continue;
3567 0 : break;
3568 : case GDT_Float64:
3569 0 : dfValue = ((double *)pData)[iOffset];
3570 0 : if (CPLIsNan(dfValue))
3571 0 : continue;
3572 0 : break;
3573 : case GDT_CInt16:
3574 0 : dfValue = ((GInt16 *)pData)[iOffset*2];
3575 0 : break;
3576 : case GDT_CInt32:
3577 0 : dfValue = ((GInt32 *)pData)[iOffset*2];
3578 0 : break;
3579 : case GDT_CFloat32:
3580 0 : dfValue = ((float *)pData)[iOffset*2];
3581 0 : if( CPLIsNan(dfValue) )
3582 0 : continue;
3583 0 : break;
3584 : case GDT_CFloat64:
3585 0 : dfValue = ((double *)pData)[iOffset*2];
3586 0 : if( CPLIsNan(dfValue) )
3587 0 : continue;
3588 0 : break;
3589 : default:
3590 0 : CPLAssert( FALSE );
3591 : }
3592 :
3593 0 : if( bGotNoDataValue && EQUAL_TO_NODATA(dfValue, dfNoDataValue) )
3594 0 : continue;
3595 :
3596 0 : if( bFirstValue )
3597 : {
3598 0 : dfMin = dfMax = dfValue;
3599 0 : bFirstValue = FALSE;
3600 : }
3601 : else
3602 : {
3603 0 : dfMin = MIN(dfMin,dfValue);
3604 0 : dfMax = MAX(dfMax,dfValue);
3605 : }
3606 :
3607 0 : dfSum += dfValue;
3608 0 : dfSum2 += dfValue * dfValue;
3609 :
3610 0 : nSampleCount++;
3611 : }
3612 : }
3613 :
3614 0 : CPLFree( pData );
3615 : }
3616 :
3617 : else // No arbitrary overviews
3618 : {
3619 : int nSampleRate;
3620 :
3621 37 : if( !InitBlockInfo() )
3622 0 : return CE_Failure;
3623 :
3624 : /* -------------------------------------------------------------------- */
3625 : /* Figure out the ratio of blocks we will read to get an */
3626 : /* approximate value. */
3627 : /* -------------------------------------------------------------------- */
3628 37 : if ( bApproxOK )
3629 : {
3630 : nSampleRate =
3631 3 : (int)MAX( 1, sqrt((double)nBlocksPerRow * nBlocksPerColumn) );
3632 : }
3633 : else
3634 34 : nSampleRate = 1;
3635 :
3636 360 : for( int iSampleBlock = 0;
3637 : iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
3638 : iSampleBlock += nSampleRate )
3639 : {
3640 : int iXBlock, iYBlock, nXCheck, nYCheck;
3641 : GDALRasterBlock *poBlock;
3642 : void* pData;
3643 :
3644 323 : iYBlock = iSampleBlock / nBlocksPerRow;
3645 323 : iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
3646 :
3647 323 : poBlock = GetLockedBlockRef( iXBlock, iYBlock );
3648 323 : if( poBlock == NULL )
3649 0 : continue;
3650 323 : if( poBlock->GetDataRef() == NULL )
3651 : {
3652 0 : poBlock->DropLock();
3653 0 : continue;
3654 : }
3655 :
3656 323 : pData = poBlock->GetDataRef();
3657 :
3658 323 : if( (iXBlock+1) * nBlockXSize > GetXSize() )
3659 2 : nXCheck = GetXSize() - iXBlock * nBlockXSize;
3660 : else
3661 321 : nXCheck = nBlockXSize;
3662 :
3663 323 : if( (iYBlock+1) * nBlockYSize > GetYSize() )
3664 3 : nYCheck = GetYSize() - iYBlock * nBlockYSize;
3665 : else
3666 320 : nYCheck = nBlockYSize;
3667 :
3668 : /* this isn't the fastest way to do this, but is easier for now */
3669 7863 : for( int iY = 0; iY < nYCheck; iY++ )
3670 : {
3671 6623811 : for( int iX = 0; iX < nXCheck; iX++ )
3672 : {
3673 6616271 : int iOffset = iX + iY * nBlockXSize;
3674 6616271 : double dfValue = 0.0;
3675 :
3676 6616271 : switch( eDataType )
3677 : {
3678 : case GDT_Byte:
3679 : {
3680 307218 : if (bSignedByte)
3681 5 : dfValue = ((signed char *)pData)[iOffset];
3682 : else
3683 307213 : dfValue = ((GByte *)pData)[iOffset];
3684 307218 : break;
3685 : }
3686 : case GDT_UInt16:
3687 6307940 : dfValue = ((GUInt16 *)pData)[iOffset];
3688 6307940 : break;
3689 : case GDT_Int16:
3690 100 : dfValue = ((GInt16 *)pData)[iOffset];
3691 100 : break;
3692 : case GDT_UInt32:
3693 100 : dfValue = ((GUInt32 *)pData)[iOffset];
3694 100 : break;
3695 : case GDT_Int32:
3696 100 : dfValue = ((GInt32 *)pData)[iOffset];
3697 100 : break;
3698 : case GDT_Float32:
3699 213 : dfValue = ((float *)pData)[iOffset];
3700 213 : if (CPLIsNan(dfValue))
3701 10 : continue;
3702 203 : break;
3703 : case GDT_Float64:
3704 600 : dfValue = ((double *)pData)[iOffset];
3705 600 : if (CPLIsNan(dfValue))
3706 50 : continue;
3707 550 : break;
3708 : case GDT_CInt16:
3709 0 : dfValue = ((GInt16 *)pData)[iOffset*2];
3710 0 : break;
3711 : case GDT_CInt32:
3712 0 : dfValue = ((GInt32 *)pData)[iOffset*2];
3713 0 : break;
3714 : case GDT_CFloat32:
3715 0 : dfValue = ((float *)pData)[iOffset*2];
3716 0 : if( CPLIsNan(dfValue) )
3717 0 : continue;
3718 0 : break;
3719 : case GDT_CFloat64:
3720 0 : dfValue = ((double *)pData)[iOffset*2];
3721 0 : if( CPLIsNan(dfValue) )
3722 0 : continue;
3723 0 : break;
3724 : default:
3725 0 : CPLAssert( FALSE );
3726 : }
3727 :
3728 6616211 : if( bGotNoDataValue && EQUAL_TO_NODATA(dfValue, dfNoDataValue) )
3729 32 : continue;
3730 :
3731 6616179 : if( bFirstValue )
3732 : {
3733 37 : dfMin = dfMax = dfValue;
3734 37 : bFirstValue = FALSE;
3735 : }
3736 : else
3737 : {
3738 6616142 : dfMin = MIN(dfMin,dfValue);
3739 6616142 : dfMax = MAX(dfMax,dfValue);
3740 : }
3741 :
3742 6616179 : dfSum += dfValue;
3743 6616179 : dfSum2 += dfValue * dfValue;
3744 :
3745 6616179 : nSampleCount++;
3746 : }
3747 : }
3748 :
3749 323 : poBlock->DropLock();
3750 :
3751 323 : if ( !pfnProgress(iSampleBlock
3752 : / ((double)(nBlocksPerRow*nBlocksPerColumn)),
3753 : "Compute Statistics", pProgressData) )
3754 : {
3755 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3756 0 : return CE_Failure;
3757 : }
3758 : }
3759 : }
3760 :
3761 37 : if( !pfnProgress( 1.0, "Compute Statistics", pProgressData ) )
3762 : {
3763 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3764 0 : return CE_Failure;
3765 : }
3766 :
3767 : /* -------------------------------------------------------------------- */
3768 : /* Save computed information. */
3769 : /* -------------------------------------------------------------------- */
3770 37 : double dfMean = dfSum / nSampleCount;
3771 37 : double dfStdDev = sqrt((dfSum2 / nSampleCount) - (dfMean * dfMean));
3772 :
3773 37 : if( nSampleCount > 1 )
3774 37 : SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
3775 :
3776 : /* -------------------------------------------------------------------- */
3777 : /* Record results. */
3778 : /* -------------------------------------------------------------------- */
3779 37 : if( pdfMin != NULL )
3780 37 : *pdfMin = dfMin;
3781 37 : if( pdfMax != NULL )
3782 37 : *pdfMax = dfMax;
3783 :
3784 37 : if( pdfMean != NULL )
3785 37 : *pdfMean = dfMean;
3786 :
3787 37 : if( pdfStdDev != NULL )
3788 37 : *pdfStdDev = dfStdDev;
3789 :
3790 37 : if( nSampleCount > 0 )
3791 37 : return CE_None;
3792 : else
3793 : {
3794 : CPLError( CE_Failure, CPLE_AppDefined,
3795 0 : "Failed to compute statistics, no valid pixels found in sampling." );
3796 0 : return CE_Failure;
3797 : }
3798 : }
3799 :
3800 : /************************************************************************/
3801 : /* GDALComputeRasterStatistics() */
3802 : /************************************************************************/
3803 :
3804 : /**
3805 : * \brief Compute image statistics.
3806 : *
3807 : * @see GDALRasterBand::ComputeStatistics()
3808 : */
3809 :
3810 : CPLErr CPL_STDCALL GDALComputeRasterStatistics(
3811 : GDALRasterBandH hBand, int bApproxOK,
3812 : double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev,
3813 0 : GDALProgressFunc pfnProgress, void *pProgressData )
3814 :
3815 : {
3816 0 : VALIDATE_POINTER1( hBand, "GDALComputeRasterStatistics", CE_Failure );
3817 :
3818 0 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
3819 :
3820 : return poBand->ComputeStatistics(
3821 : bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev,
3822 0 : pfnProgress, pProgressData );
3823 : }
3824 :
3825 : /************************************************************************/
3826 : /* SetStatistics() */
3827 : /************************************************************************/
3828 :
3829 : /**
3830 : * \brief Set statistics on band.
3831 : *
3832 : * This method can be used to store min/max/mean/standard deviation
3833 : * statistics on a raster band.
3834 : *
3835 : * The default implementation stores them as metadata, and will only work
3836 : * on formats that can save arbitrary metadata. This method cannot detect
3837 : * whether metadata will be properly saved and so may return CE_None even
3838 : * if the statistics will never be saved.
3839 : *
3840 : * This method is the same as the C function GDALSetRasterStatistics().
3841 : *
3842 : * @param dfMin minimum pixel value.
3843 : *
3844 : * @param dfMax maximum pixel value.
3845 : *
3846 : * @param dfMean mean (average) of all pixel values.
3847 : *
3848 : * @param dfStdDev Standard deviation of all pixel values.
3849 : *
3850 : * @return CE_None on success or CE_Failure on failure.
3851 : */
3852 :
3853 : CPLErr GDALRasterBand::SetStatistics( double dfMin, double dfMax,
3854 69 : double dfMean, double dfStdDev )
3855 :
3856 : {
3857 69 : char szValue[128] = { 0 };
3858 :
3859 69 : sprintf( szValue, "%.14g", dfMin );
3860 69 : SetMetadataItem( "STATISTICS_MINIMUM", szValue );
3861 :
3862 69 : sprintf( szValue, "%.14g", dfMax );
3863 69 : SetMetadataItem( "STATISTICS_MAXIMUM", szValue );
3864 :
3865 69 : sprintf( szValue, "%.14g", dfMean );
3866 69 : SetMetadataItem( "STATISTICS_MEAN", szValue );
3867 :
3868 69 : sprintf( szValue, "%.14g", dfStdDev );
3869 69 : SetMetadataItem( "STATISTICS_STDDEV", szValue );
3870 :
3871 69 : return CE_None;
3872 : }
3873 :
3874 : /************************************************************************/
3875 : /* GDALSetRasterStatistics() */
3876 : /************************************************************************/
3877 :
3878 : /**
3879 : * \brief Set statistics on band.
3880 : *
3881 : * @see GDALRasterBand::SetStatistics()
3882 : */
3883 :
3884 : CPLErr CPL_STDCALL GDALSetRasterStatistics(
3885 : GDALRasterBandH hBand,
3886 0 : double dfMin, double dfMax, double dfMean, double dfStdDev )
3887 :
3888 : {
3889 0 : VALIDATE_POINTER1( hBand, "GDALSetRasterStatistics", CE_Failure );
3890 :
3891 0 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
3892 0 : return poBand->SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
3893 : }
3894 :
3895 : /************************************************************************/
3896 : /* ComputeRasterMinMax() */
3897 : /************************************************************************/
3898 :
3899 : /**
3900 : * \brief Compute the min/max values for a band.
3901 : *
3902 : * If approximate is OK, then the band's GetMinimum()/GetMaximum() will
3903 : * be trusted. If it doesn't work, a subsample of blocks will be read to
3904 : * get an approximate min/max. If the band has a nodata value it will
3905 : * be excluded from the minimum and maximum.
3906 : *
3907 : * If bApprox is FALSE, then all pixels will be read and used to compute
3908 : * an exact range.
3909 : *
3910 : * This method is the same as the C function GDALComputeRasterMinMax().
3911 : *
3912 : * @param bApproxOK TRUE if an approximate (faster) answer is OK, otherwise
3913 : * FALSE.
3914 : * @param adfMinMax the array in which the minimum (adfMinMax[0]) and the
3915 : * maximum (adfMinMax[1]) are returned.
3916 : *
3917 : * @return CE_None on success or CE_Failure on failure.
3918 : */
3919 :
3920 :
3921 : CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
3922 805 : double adfMinMax[2] )
3923 : {
3924 805 : double dfMin = 0.0;
3925 805 : double dfMax = 0.0;
3926 :
3927 : /* -------------------------------------------------------------------- */
3928 : /* Does the driver already know the min/max? */
3929 : /* -------------------------------------------------------------------- */
3930 805 : if( bApproxOK )
3931 : {
3932 : int bSuccessMin, bSuccessMax;
3933 :
3934 0 : dfMin = GetMinimum( &bSuccessMin );
3935 0 : dfMax = GetMaximum( &bSuccessMax );
3936 :
3937 0 : if( bSuccessMin && bSuccessMax )
3938 : {
3939 0 : adfMinMax[0] = dfMin;
3940 0 : adfMinMax[1] = dfMax;
3941 0 : return CE_None;
3942 : }
3943 : }
3944 :
3945 : /* -------------------------------------------------------------------- */
3946 : /* If we have overview bands, use them for min/max. */
3947 : /* -------------------------------------------------------------------- */
3948 805 : if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
3949 : {
3950 : GDALRasterBand *poBand;
3951 :
3952 0 : poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
3953 :
3954 0 : if ( poBand != this )
3955 0 : return poBand->ComputeRasterMinMax( FALSE, adfMinMax );
3956 : }
3957 :
3958 : /* -------------------------------------------------------------------- */
3959 : /* Read actual data and compute minimum and maximum. */
3960 : /* -------------------------------------------------------------------- */
3961 805 : int bGotNoDataValue, bFirstValue = TRUE;
3962 : double dfNoDataValue;
3963 :
3964 805 : dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
3965 :
3966 805 : const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
3967 805 : int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
3968 :
3969 805 : if ( bApproxOK && HasArbitraryOverviews() )
3970 : {
3971 : /* -------------------------------------------------------------------- */
3972 : /* Figure out how much the image should be reduced to get an */
3973 : /* approximate value. */
3974 : /* -------------------------------------------------------------------- */
3975 : void *pData;
3976 : int nXReduced, nYReduced;
3977 : double dfReduction = sqrt(
3978 0 : (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
3979 :
3980 0 : if ( dfReduction > 1.0 )
3981 : {
3982 0 : nXReduced = (int)( nRasterXSize / dfReduction );
3983 0 : nYReduced = (int)( nRasterYSize / dfReduction );
3984 :
3985 : // Catch the case of huge resizing ratios here
3986 0 : if ( nXReduced == 0 )
3987 0 : nXReduced = 1;
3988 0 : if ( nYReduced == 0 )
3989 0 : nYReduced = 1;
3990 : }
3991 : else
3992 : {
3993 0 : nXReduced = nRasterXSize;
3994 0 : nYReduced = nRasterYSize;
3995 : }
3996 :
3997 : pData =
3998 0 : CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
3999 :
4000 : CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
4001 0 : nXReduced, nYReduced, eDataType, 0, 0 );
4002 0 : if ( eErr != CE_None )
4003 : {
4004 0 : CPLFree(pData);
4005 0 : return eErr;
4006 : }
4007 :
4008 : /* this isn't the fastest way to do this, but is easier for now */
4009 0 : for( int iY = 0; iY < nYReduced; iY++ )
4010 : {
4011 0 : for( int iX = 0; iX < nXReduced; iX++ )
4012 : {
4013 0 : int iOffset = iX + iY * nXReduced;
4014 0 : double dfValue = 0.0;
4015 :
4016 0 : switch( eDataType )
4017 : {
4018 : case GDT_Byte:
4019 : {
4020 0 : if (bSignedByte)
4021 0 : dfValue = ((signed char *)pData)[iOffset];
4022 : else
4023 0 : dfValue = ((GByte *)pData)[iOffset];
4024 0 : break;
4025 : }
4026 : case GDT_UInt16:
4027 0 : dfValue = ((GUInt16 *)pData)[iOffset];
4028 0 : break;
4029 : case GDT_Int16:
4030 0 : dfValue = ((GInt16 *)pData)[iOffset];
4031 0 : break;
4032 : case GDT_UInt32:
4033 0 : dfValue = ((GUInt32 *)pData)[iOffset];
4034 0 : break;
4035 : case GDT_Int32:
4036 0 : dfValue = ((GInt32 *)pData)[iOffset];
4037 0 : break;
4038 : case GDT_Float32:
4039 0 : dfValue = ((float *)pData)[iOffset];
4040 0 : if (CPLIsNan(dfValue))
4041 0 : continue;
4042 0 : break;
4043 : case GDT_Float64:
4044 0 : dfValue = ((double *)pData)[iOffset];
4045 0 : if (CPLIsNan(dfValue))
4046 0 : continue;
4047 0 : break;
4048 : case GDT_CInt16:
4049 0 : dfValue = ((GInt16 *)pData)[iOffset*2];
4050 0 : break;
4051 : case GDT_CInt32:
4052 0 : dfValue = ((GInt32 *)pData)[iOffset*2];
4053 0 : break;
4054 : case GDT_CFloat32:
4055 0 : dfValue = ((float *)pData)[iOffset*2];
4056 0 : if( CPLIsNan(dfValue) )
4057 0 : continue;
4058 0 : break;
4059 : case GDT_CFloat64:
4060 0 : dfValue = ((double *)pData)[iOffset*2];
4061 0 : if( CPLIsNan(dfValue) )
4062 0 : continue;
4063 0 : break;
4064 : default:
4065 0 : CPLAssert( FALSE );
4066 : }
4067 :
4068 0 : if( bGotNoDataValue && EQUAL_TO_NODATA(dfValue, dfNoDataValue) )
4069 0 : continue;
4070 :
4071 0 : if( bFirstValue )
4072 : {
4073 0 : dfMin = dfMax = dfValue;
4074 0 : bFirstValue = FALSE;
4075 : }
4076 : else
4077 : {
4078 0 : dfMin = MIN(dfMin,dfValue);
4079 0 : dfMax = MAX(dfMax,dfValue);
4080 : }
4081 : }
4082 : }
4083 :
4084 0 : CPLFree( pData );
4085 : }
4086 :
4087 : else // No arbitrary overviews
4088 : {
4089 : int nSampleRate;
4090 :
4091 805 : if( !InitBlockInfo() )
4092 0 : return CE_Failure;
4093 :
4094 : /* -------------------------------------------------------------------- */
4095 : /* Figure out the ratio of blocks we will read to get an */
4096 : /* approximate value. */
4097 : /* -------------------------------------------------------------------- */
4098 805 : if ( bApproxOK )
4099 : {
4100 : nSampleRate =
4101 0 : (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
4102 : }
4103 : else
4104 805 : nSampleRate = 1;
4105 :
4106 16616 : for( int iSampleBlock = 0;
4107 : iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
4108 : iSampleBlock += nSampleRate )
4109 : {
4110 : int iXBlock, iYBlock, nXCheck, nYCheck;
4111 : GDALRasterBlock *poBlock;
4112 : void* pData;
4113 :
4114 15811 : iYBlock = iSampleBlock / nBlocksPerRow;
4115 15811 : iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
4116 :
4117 15811 : poBlock = GetLockedBlockRef( iXBlock, iYBlock );
4118 15811 : if( poBlock == NULL )
4119 0 : continue;
4120 15811 : if( poBlock->GetDataRef() == NULL )
4121 : {
4122 0 : poBlock->DropLock();
4123 0 : continue;
4124 : }
4125 :
4126 15811 : pData = poBlock->GetDataRef();
4127 :
4128 15811 : if( (iXBlock+1) * nBlockXSize > GetXSize() )
4129 836 : nXCheck = GetXSize() - iXBlock * nBlockXSize;
4130 : else
4131 14975 : nXCheck = nBlockXSize;
4132 :
4133 15811 : if( (iYBlock+1) * nBlockYSize > GetYSize() )
4134 186 : nYCheck = GetYSize() - iYBlock * nBlockYSize;
4135 : else
4136 15625 : nYCheck = nBlockYSize;
4137 :
4138 : /* this isn't the fastest way to do this, but is easier for now */
4139 183524 : for( int iY = 0; iY < nYCheck; iY++ )
4140 : {
4141 5390957 : for( int iX = 0; iX < nXCheck; iX++ )
4142 : {
4143 5223244 : int iOffset = iX + iY * nBlockXSize;
4144 5223244 : double dfValue = 0.0;
4145 :
4146 5223244 : switch( eDataType )
4147 : {
4148 : case GDT_Byte:
4149 : {
4150 2901085 : if (bSignedByte)
4151 0 : dfValue = ((signed char *) pData)[iOffset];
4152 : else
4153 2901085 : dfValue = ((GByte *) pData)[iOffset];
4154 2901085 : break;
4155 : }
4156 : case GDT_UInt16:
4157 34900 : dfValue = ((GUInt16 *) pData)[iOffset];
4158 34900 : break;
4159 : case GDT_Int16:
4160 1742994 : dfValue = ((GInt16 *) pData)[iOffset];
4161 1742994 : break;
4162 : case GDT_UInt32:
4163 16900 : dfValue = ((GUInt32 *) pData)[iOffset];
4164 16900 : break;
4165 : case GDT_Int32:
4166 53770 : dfValue = ((GInt32 *) pData)[iOffset];
4167 53770 : break;
4168 : case GDT_Float32:
4169 422695 : dfValue = ((float *) pData)[iOffset];
4170 422695 : if( CPLIsNan(dfValue) )
4171 0 : continue;
4172 422695 : break;
4173 : case GDT_Float64:
4174 26500 : dfValue = ((double *) pData)[iOffset];
4175 26500 : if( CPLIsNan(dfValue) )
4176 0 : continue;
4177 26500 : break;
4178 : case GDT_CInt16:
4179 4000 : dfValue = ((GInt16 *) pData)[iOffset*2];
4180 4000 : break;
4181 : case GDT_CInt32:
4182 4000 : dfValue = ((GInt32 *) pData)[iOffset*2];
4183 4000 : break;
4184 : case GDT_CFloat32:
4185 8000 : dfValue = ((float *) pData)[iOffset*2];
4186 8000 : if( CPLIsNan(dfValue) )
4187 0 : continue;
4188 8000 : break;
4189 : case GDT_CFloat64:
4190 8400 : dfValue = ((double *) pData)[iOffset*2];
4191 8400 : if( CPLIsNan(dfValue) )
4192 0 : continue;
4193 8400 : break;
4194 : default:
4195 0 : CPLAssert( FALSE );
4196 : }
4197 :
4198 5223244 : if( bGotNoDataValue && EQUAL_TO_NODATA(dfValue, dfNoDataValue) )
4199 333765 : continue;
4200 :
4201 4889479 : if( bFirstValue )
4202 : {
4203 805 : dfMin = dfMax = dfValue;
4204 805 : bFirstValue = FALSE;
4205 : }
4206 : else
4207 : {
4208 4888674 : dfMin = MIN(dfMin,dfValue);
4209 4888674 : dfMax = MAX(dfMax,dfValue);
4210 : }
4211 : }
4212 : }
4213 :
4214 15811 : poBlock->DropLock();
4215 : }
4216 : }
4217 :
4218 805 : adfMinMax[0] = dfMin;
4219 805 : adfMinMax[1] = dfMax;
4220 :
4221 805 : if (bFirstValue)
4222 : {
4223 : CPLError( CE_Failure, CPLE_AppDefined,
4224 0 : "Failed to compute min/max, no valid pixels found in sampling." );
4225 0 : return CE_Failure;
4226 : }
4227 : else
4228 : {
4229 805 : return CE_None;
4230 : }
4231 : }
4232 :
4233 : /************************************************************************/
4234 : /* GDALComputeRasterMinMax() */
4235 : /************************************************************************/
4236 :
4237 : /**
4238 : * \brief Compute the min/max values for a band.
4239 : *
4240 : * @see GDALRasterBand::ComputeRasterMinMax()
4241 : */
4242 :
4243 : void CPL_STDCALL
4244 : GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK,
4245 805 : double adfMinMax[2] )
4246 :
4247 : {
4248 805 : VALIDATE_POINTER0( hBand, "GDALComputeRasterMinMax" );
4249 :
4250 805 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
4251 805 : poBand->ComputeRasterMinMax( bApproxOK, adfMinMax );
4252 : }
4253 :
4254 : /************************************************************************/
4255 : /* SetDefaultHistogram() */
4256 : /************************************************************************/
4257 :
4258 : /* FIXME : add proper documentation */
4259 : /**
4260 : * \brief Set default histogram.
4261 : */
4262 : CPLErr GDALRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
4263 0 : int nBuckets, int *panHistogram )
4264 :
4265 : {
4266 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
4267 : CPLError( CE_Failure, CPLE_NotSupported,
4268 0 : "SetDefaultHistogram() not implemented for this format." );
4269 :
4270 0 : return CE_Failure;
4271 : }
4272 :
4273 : /************************************************************************/
4274 : /* GDALSetDefaultHistogram() */
4275 : /************************************************************************/
4276 :
4277 : /**
4278 : * \brief Set default histogram.
4279 : *
4280 : * @see GDALRasterBand::SetDefaultHistogram()
4281 : */
4282 :
4283 : CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand,
4284 : double dfMin, double dfMax,
4285 0 : int nBuckets, int *panHistogram )
4286 :
4287 : {
4288 0 : VALIDATE_POINTER1( hBand, "GDALSetDefaultHistogram", CE_Failure );
4289 :
4290 0 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
4291 0 : return poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram );
4292 : }
4293 :
4294 : /************************************************************************/
4295 : /* GetDefaultRAT() */
4296 : /************************************************************************/
4297 :
4298 : /**
4299 : * \brief Fetch default Raster Attribute Table.
4300 : *
4301 : * A RAT will be returned if there is a default one associated with the
4302 : * band, otherwise NULL is returned. The returned RAT is owned by the
4303 : * band and should not be deleted, or altered by the application.
4304 : *
4305 : * @return NULL, or a pointer to an internal RAT owned by the band.
4306 : */
4307 :
4308 133 : const GDALRasterAttributeTable *GDALRasterBand::GetDefaultRAT()
4309 :
4310 : {
4311 133 : return NULL;
4312 : }
4313 :
4314 : /************************************************************************/
4315 : /* GDALGetDefaultRAT() */
4316 : /************************************************************************/
4317 :
4318 : /**
4319 : * \brief Fetch default Raster Attribute Table.
4320 : *
4321 : * @see GDALRasterBand::GetDefaultRAT()
4322 : */
4323 :
4324 38 : GDALRasterAttributeTableH CPL_STDCALL GDALGetDefaultRAT( GDALRasterBandH hBand)
4325 :
4326 : {
4327 38 : VALIDATE_POINTER1( hBand, "GDALGetDefaultRAT", NULL );
4328 :
4329 38 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
4330 38 : return (GDALRasterAttributeTableH) poBand->GetDefaultRAT();
4331 : }
4332 :
4333 : /************************************************************************/
4334 : /* SetDefaultRAT() */
4335 : /************************************************************************/
4336 :
4337 : /**
4338 : * \brief Set default Raster Attribute Table.
4339 : *
4340 : * Associates a default RAT with the band. If not implemented for the
4341 : * format a CPLE_NotSupported error will be issued. If successful a copy
4342 : * of the RAT is made, the original remains owned by the caller.
4343 : *
4344 : * @param poRAT the RAT to assign to the band.
4345 : *
4346 : * @return CE_None on success or CE_Failure if unsupported or otherwise
4347 : * failing.
4348 : */
4349 :
4350 0 : CPLErr GDALRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
4351 :
4352 : {
4353 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
4354 : CPLError( CE_Failure, CPLE_NotSupported,
4355 0 : "SetDefaultRAT() not implemented for this format." );
4356 :
4357 0 : return CE_Failure;
4358 : }
4359 :
4360 : /************************************************************************/
4361 : /* GDALSetDefaultRAT() */
4362 : /************************************************************************/
4363 :
4364 : /**
4365 : * \brief Set default Raster Attribute Table.
4366 : *
4367 : * @see GDALRasterBand::GDALSetDefaultRAT()
4368 : */
4369 :
4370 : CPLErr CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH hBand,
4371 1 : GDALRasterAttributeTableH hRAT )
4372 :
4373 : {
4374 1 : VALIDATE_POINTER1( hBand, "GDALSetDefaultRAT", CE_Failure );
4375 1 : VALIDATE_POINTER1( hRAT, "GDALSetDefaultRAT", CE_Failure );
4376 :
4377 1 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
4378 :
4379 : return poBand->SetDefaultRAT(
4380 1 : static_cast<GDALRasterAttributeTable *>(hRAT) );
4381 : }
4382 :
4383 : /************************************************************************/
4384 : /* GetMaskBand() */
4385 : /************************************************************************/
4386 :
4387 : /**
4388 : * \brief Return the mask band associated with the band.
4389 : *
4390 : * The GDALRasterBand class includes a default implementation of GetMaskBand() that
4391 : * returns one of four default implementations :
4392 : * <ul>
4393 : * <li>If a corresponding .msk file exists it will be used for the mask band.</li>
4394 : * <li>If the dataset has a NODATA_VALUES metadata item, an instance of the
4395 : * new GDALNoDataValuesMaskBand class will be returned.
4396 : * GetMaskFlags() will return GMF_NODATA | GMF_PER_DATASET. @since GDAL 1.6.0</li>
4397 : * <li>If the band has a nodata value set, an instance of the new
4398 : * GDALNodataMaskRasterBand class will be returned.
4399 : * GetMaskFlags() will return GMF_NODATA.</li>
4400 : * <li>If there is no nodata value, but the dataset has an alpha band that seems
4401 : * to apply to this band (specific rules yet to be determined) and that is
4402 : * of type GDT_Byte then that alpha band will be returned, and the flags
4403 : * GMF_PER_DATASET and GMF_ALPHA will be returned in the flags.</li>
4404 : * <li>If neither of the above apply, an instance of the new GDALAllValidRasterBand
4405 : * class will be returned that has 255 values for all pixels.
4406 : * The null flags will return GMF_ALL_VALID.</li>
4407 : * </ul>
4408 : *
4409 : * Note that the GetMaskBand() should always return a GDALRasterBand mask, even if it is only
4410 : * an all 255 mask with the flags indicating GMF_ALL_VALID.
4411 : *
4412 : * @return a valid mask band.
4413 : *
4414 : * @since GDAL 1.5.0
4415 : *
4416 : * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
4417 : *
4418 : */
4419 666 : GDALRasterBand *GDALRasterBand::GetMaskBand()
4420 :
4421 : {
4422 666 : if( poMask != NULL )
4423 82 : return poMask;
4424 :
4425 : /* -------------------------------------------------------------------- */
4426 : /* Check for a mask in a .msk file. */
4427 : /* -------------------------------------------------------------------- */
4428 584 : GDALDataset *poDS = GetDataset();
4429 :
4430 584 : if( poDS != NULL && poDS->oOvManager.HaveMaskFile() )
4431 : {
4432 10 : poMask = poDS->oOvManager.GetMaskBand( nBand );
4433 10 : if( poMask != NULL )
4434 : {
4435 10 : nMaskFlags = poDS->oOvManager.GetMaskFlags( nBand );
4436 10 : return poMask;
4437 : }
4438 : }
4439 :
4440 : /* -------------------------------------------------------------------- */
4441 : /* Check for NODATA_VALUES metadata. */
4442 : /* -------------------------------------------------------------------- */
4443 574 : if (poDS != NULL)
4444 : {
4445 573 : const char* pszNoDataValues = poDS->GetMetadataItem("NODATA_VALUES");
4446 573 : if (pszNoDataValues != NULL)
4447 : {
4448 41 : char** papszNoDataValues = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
4449 :
4450 : /* Make sure we have as many values as bands */
4451 41 : if (CSLCount(papszNoDataValues) == poDS->GetRasterCount() && poDS->GetRasterCount() != 0)
4452 : {
4453 41 : CSLDestroy(papszNoDataValues);
4454 :
4455 : /* Make sure that all bands have the same data type */
4456 : /* This is cleraly not a fundamental condition, just a condition to make implementation */
4457 : /* easier. */
4458 : int i;
4459 41 : GDALDataType eDT = GDT_Unknown;
4460 164 : for(i=0;i<poDS->GetRasterCount();i++)
4461 : {
4462 123 : if (i == 0)
4463 41 : eDT = poDS->GetRasterBand(1)->GetRasterDataType();
4464 82 : else if (eDT != poDS->GetRasterBand(i + 1)->GetRasterDataType())
4465 : {
4466 0 : break;
4467 : }
4468 : }
4469 41 : if (i == poDS->GetRasterCount())
4470 : {
4471 41 : nMaskFlags = GMF_NODATA | GMF_PER_DATASET;
4472 41 : poMask = new GDALNoDataValuesMaskBand ( poDS );
4473 41 : bOwnMask = true;
4474 41 : return poMask;
4475 : }
4476 : else
4477 : {
4478 : CPLError(CE_Warning, CPLE_AppDefined,
4479 0 : "All bands should have the same type in order the NODATA_VALUES metadata item to be used as a mask.");
4480 : }
4481 : }
4482 : else
4483 : {
4484 : CPLError(CE_Warning, CPLE_AppDefined,
4485 : "NODATA_VALUES metadata item doesn't have the same number of values as the number of bands.\n"
4486 0 : "Ignoring it for mask.");
4487 : }
4488 :
4489 0 : CSLDestroy(papszNoDataValues);
4490 : }
4491 : }
4492 :
4493 : /* -------------------------------------------------------------------- */
4494 : /* Check for nodata case. */
4495 : /* -------------------------------------------------------------------- */
4496 : int bHaveNoData;
4497 :
4498 533 : GetNoDataValue( &bHaveNoData );
4499 :
4500 533 : if( bHaveNoData )
4501 : {
4502 76 : nMaskFlags = GMF_NODATA;
4503 76 : poMask = new GDALNoDataMaskBand( this );
4504 76 : bOwnMask = true;
4505 76 : return poMask;
4506 : }
4507 :
4508 : /* -------------------------------------------------------------------- */
4509 : /* Check for alpha case. */
4510 : /* -------------------------------------------------------------------- */
4511 457 : if( poDS != NULL
4512 : && poDS->GetRasterCount() == 2
4513 : && this == poDS->GetRasterBand(1)
4514 : && poDS->GetRasterBand(2)->GetColorInterpretation() == GCI_AlphaBand
4515 : && poDS->GetRasterBand(2)->GetRasterDataType() == GDT_Byte )
4516 : {
4517 2 : nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
4518 2 : poMask = poDS->GetRasterBand(2);
4519 2 : return poMask;
4520 : }
4521 :
4522 455 : if( poDS != NULL
4523 : && poDS->GetRasterCount() == 4
4524 : && (this == poDS->GetRasterBand(1)
4525 : || this == poDS->GetRasterBand(2)
4526 : || this == poDS->GetRasterBand(3))
4527 : && poDS->GetRasterBand(4)->GetColorInterpretation() == GCI_AlphaBand
4528 : && poDS->GetRasterBand(4)->GetRasterDataType() == GDT_Byte )
4529 : {
4530 15 : nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
4531 15 : poMask = poDS->GetRasterBand(4);
4532 15 : return poMask;
4533 : }
4534 :
4535 : /* -------------------------------------------------------------------- */
4536 : /* Fallback to all valid case. */
4537 : /* -------------------------------------------------------------------- */
4538 440 : nMaskFlags = GMF_ALL_VALID;
4539 440 : poMask = new GDALAllValidMaskBand( this );
4540 440 : bOwnMask = true;
4541 :
4542 440 : return poMask;
4543 : }
4544 :
4545 : /************************************************************************/
4546 : /* GDALGetMaskBand() */
4547 : /************************************************************************/
4548 :
4549 : /**
4550 : * \brief Return the mask band associated with the band.
4551 : *
4552 : * @see GDALRasterBand::GetMaskBand()
4553 : */
4554 :
4555 83 : GDALRasterBandH CPL_STDCALL GDALGetMaskBand( GDALRasterBandH hBand )
4556 :
4557 : {
4558 83 : VALIDATE_POINTER1( hBand, "GDALGetMaskBand", NULL );
4559 :
4560 83 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
4561 83 : return poBand->GetMaskBand();
4562 : }
4563 :
4564 : /************************************************************************/
4565 : /* GetMaskFlags() */
4566 : /************************************************************************/
4567 :
4568 : /**
4569 : * \brief Return the status flags of the mask band associated with the band.
4570 : *
4571 : * The GetMaskFlags() method returns an bitwise OR-ed set of status flags with
4572 : * the following available definitions that may be extended in the future:
4573 : * <ul>
4574 : * <li>GMF_ALL_VALID(0x01): There are no invalid pixels, all mask values will be 255.
4575 : * When used this will normally be the only flag set.</li>
4576 : * <li>GMF_PER_DATASET(0x02): The mask band is shared between all bands on the dataset.</li>
4577 : * <li>GMF_ALPHA(0x04): The mask band is actually an alpha band and may have values
4578 : * other than 0 and 255.</li>
4579 : * <li>GMF_NODATA(0x08): Indicates the mask is actually being generated from nodata values.
4580 : * (mutually exclusive of GMF_ALPHA)</li>
4581 : * </ul>
4582 : *
4583 : * The GDALRasterBand class includes a default implementation of GetMaskBand() that
4584 : * returns one of four default implementations :
4585 : * <ul>
4586 : * <li>If a corresponding .msk file exists it will be used for the mask band.</li>
4587 : * <li>If the dataset has a NODATA_VALUES metadata item, an instance of the
4588 : * new GDALNoDataValuesMaskBand class will be returned.
4589 : * GetMaskFlags() will return GMF_NODATA | GMF_PER_DATASET. @since GDAL 1.6.0</li>
4590 : * <li>If the band has a nodata value set, an instance of the new
4591 : * GDALNodataMaskRasterBand class will be returned.
4592 : * GetMaskFlags() will return GMF_NODATA.</li>
4593 : * <li>If there is no nodata value, but the dataset has an alpha band that seems
4594 : * to apply to this band (specific rules yet to be determined) and that is
4595 : * of type GDT_Byte then that alpha band will be returned, and the flags
4596 : * GMF_PER_DATASET and GMF_ALPHA will be returned in the flags.</li>
4597 : * <li>If neither of the above apply, an instance of the new GDALAllValidRasterBand
4598 : * class will be returned that has 255 values for all pixels.
4599 : * The null flags will return GMF_ALL_VALID.</li>
4600 : * </ul>
4601 : *
4602 : * @since GDAL 1.5.0
4603 : *
4604 : * @return a valid mask band.
4605 : *
4606 : * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
4607 : *
4608 : */
4609 1567 : int GDALRasterBand::GetMaskFlags()
4610 :
4611 : {
4612 : // If we don't have a band yet, force this now so that the masks value
4613 : // will be initialized.
4614 :
4615 1567 : if( poMask == NULL )
4616 569 : GetMaskBand();
4617 :
4618 1567 : return nMaskFlags;
4619 : }
4620 :
4621 : /************************************************************************/
4622 : /* GDALGetMaskFlags() */
4623 : /************************************************************************/
4624 :
4625 : /**
4626 : * \brief Return the status flags of the mask band associated with the band.
4627 : *
4628 : * @see GDALRasterBand::GetMaskFlags()
4629 : */
4630 :
4631 93 : int CPL_STDCALL GDALGetMaskFlags( GDALRasterBandH hBand )
4632 :
4633 : {
4634 93 : VALIDATE_POINTER1( hBand, "GDALGetMaskFlags", GMF_ALL_VALID );
4635 :
4636 93 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
4637 93 : return poBand->GetMaskFlags();
4638 : }
4639 :
4640 : /************************************************************************/
4641 : /* CreateMaskBand() */
4642 : /************************************************************************/
4643 :
4644 : /**
4645 : * \brief Adds a mask band to the current band
4646 : *
4647 : * The default implementation of the CreateMaskBand() method is implemented
4648 : * based on similar rules to the .ovr handling implemented using the
4649 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
4650 : * be created with the same basename as the original file, and it will have
4651 : * as many bands as the original image (or just one for GMF_PER_DATASET).
4652 : * The mask images will be deflate compressed tiled images with the same
4653 : * block size as the original image if possible.
4654 : *
4655 : * @since GDAL 1.5.0
4656 : *
4657 : * @return CE_None on success or CE_Failure on an error.
4658 : *
4659 : * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
4660 : *
4661 : */
4662 :
4663 0 : CPLErr GDALRasterBand::CreateMaskBand( int nFlags )
4664 :
4665 : {
4666 0 : if( poDS != NULL && poDS->oOvManager.IsInitialized() )
4667 0 : return poDS->oOvManager.CreateMaskBand( nFlags, nBand );
4668 :
4669 : CPLError( CE_Failure, CPLE_NotSupported,
4670 0 : "CreateMaskBand() not supported for this band." );
4671 :
4672 0 : return CE_Failure;
4673 : }
4674 :
4675 : /************************************************************************/
4676 : /* GDALCreateMaskBand() */
4677 : /************************************************************************/
4678 :
4679 : /**
4680 : * \brief Adds a mask band to the current band
4681 : *
4682 : * @see GDALRasterBand::CreateMaskBand()
4683 : */
4684 :
4685 6 : CPLErr CPL_STDCALL GDALCreateMaskBand( GDALRasterBandH hBand, int nFlags )
4686 :
4687 : {
4688 6 : VALIDATE_POINTER1( hBand, "GDALCreateMaskBand", CE_Failure );
4689 :
4690 6 : GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
4691 6 : return poBand->CreateMaskBand( nFlags );
4692 : }
4693 :
4694 : /************************************************************************/
4695 : /* GetIndexColorTranslationTo() */
4696 : /************************************************************************/
4697 :
4698 : /**
4699 : * \brief Compute translation table for color tables.
4700 : *
4701 : * When the raster band has a palette index, it may be usefull to compute
4702 : * the "translation" of this palette to the palette of another band.
4703 : * The translation tries to do exact matching first, and then approximate
4704 : * matching if no exact matching is possible.
4705 : * This method returns a table such that table[i] = j where i is an index
4706 : * of the 'this' rasterband and j the corresponding index for the reference
4707 : * rasterband.
4708 : *
4709 : * This method is thought as internal to GDAL and is used for drivers
4710 : * like RPFTOC.
4711 : *
4712 : * The implementation only supports 1-byte palette rasterbands.
4713 : *
4714 : * @param poReferenceBand the raster band
4715 : * @param pTranslationTable an already allocated translation table (at least 256 bytes),
4716 : * or NULL to let the method allocate it
4717 : * @param poApproximateMatching a pointer to a flag that is set if the matching
4718 : * is approximate. May be NULL.
4719 : *
4720 : * @return a translation table if the two bands are palette index and that they do
4721 : * not match or NULL in other cases.
4722 : * The table must be freed with CPLFree if NULL was passed for pTranslationTable.
4723 : */
4724 :
4725 : unsigned char* GDALRasterBand::GetIndexColorTranslationTo(GDALRasterBand* poReferenceBand,
4726 : unsigned char* pTranslationTable,
4727 3 : int* pApproximateMatching )
4728 : {
4729 3 : if (poReferenceBand == NULL)
4730 0 : return NULL;
4731 :
4732 3 : if (poReferenceBand->GetColorInterpretation() == GCI_PaletteIndex &&
4733 : GetColorInterpretation() == GCI_PaletteIndex &&
4734 : poReferenceBand->GetRasterDataType() == GDT_Byte &&
4735 : GetRasterDataType() == GDT_Byte)
4736 : {
4737 3 : GDALColorTable* srcColorTable = GetColorTable();
4738 3 : GDALColorTable* destColorTable = poReferenceBand->GetColorTable();
4739 3 : if (srcColorTable != NULL && destColorTable != NULL)
4740 : {
4741 3 : int nEntries = srcColorTable->GetColorEntryCount();
4742 3 : int nRefEntries = destColorTable->GetColorEntryCount();
4743 : int bHasNoDataValueSrc;
4744 3 : int noDataValueSrc = (int)GetNoDataValue(&bHasNoDataValueSrc);
4745 : int bHasNoDataValueRef;
4746 3 : int noDataValueRef = (int)poReferenceBand->GetNoDataValue(&bHasNoDataValueRef);
4747 : int samePalette;
4748 : int i, j;
4749 :
4750 3 : if (pApproximateMatching)
4751 2 : *pApproximateMatching = FALSE;
4752 :
4753 6 : if (nEntries == nRefEntries && bHasNoDataValueSrc == bHasNoDataValueRef &&
4754 : (bHasNoDataValueSrc == FALSE || noDataValueSrc == noDataValueRef))
4755 : {
4756 3 : samePalette = TRUE;
4757 693 : for(i=0;i<nEntries;i++)
4758 : {
4759 690 : if (noDataValueSrc == i)
4760 2 : continue;
4761 688 : const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
4762 688 : const GDALColorEntry* entryRef = destColorTable->GetColorEntry(i);
4763 688 : if (entry->c1 != entryRef->c1 ||
4764 : entry->c2 != entryRef->c2 ||
4765 : entry->c3 != entryRef->c3)
4766 : {
4767 0 : samePalette = FALSE;
4768 : }
4769 : }
4770 : }
4771 : else
4772 : {
4773 0 : samePalette = FALSE;
4774 : }
4775 3 : if (samePalette == FALSE)
4776 : {
4777 0 : if (pTranslationTable == NULL)
4778 0 : pTranslationTable = (unsigned char*)CPLMalloc(256);
4779 :
4780 : /* Trying to remap the product palette on the subdataset palette */
4781 0 : for(i=0;i<nEntries;i++)
4782 : {
4783 0 : if (bHasNoDataValueSrc && bHasNoDataValueRef && noDataValueSrc == i)
4784 0 : continue;
4785 0 : const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
4786 0 : for(j=0;j<nRefEntries;j++)
4787 : {
4788 0 : if (bHasNoDataValueRef && noDataValueRef == j)
4789 0 : continue;
4790 0 : const GDALColorEntry* entryRef = destColorTable->GetColorEntry(j);
4791 0 : if (entry->c1 == entryRef->c1 &&
4792 : entry->c2 == entryRef->c2 &&
4793 : entry->c3 == entryRef->c3)
4794 : {
4795 0 : pTranslationTable[i] = j;
4796 0 : break;
4797 : }
4798 : }
4799 0 : if (j == nEntries)
4800 : {
4801 : /* No exact match. Looking for closest color now... */
4802 0 : int best_j = 0;
4803 0 : int best_distance = 0;
4804 0 : if (pApproximateMatching)
4805 0 : *pApproximateMatching = TRUE;
4806 0 : for(j=0;j<nRefEntries;j++)
4807 : {
4808 0 : const GDALColorEntry* entryRef = destColorTable->GetColorEntry(j);
4809 : int distance = (entry->c1 - entryRef->c1) * (entry->c1 - entryRef->c1) +
4810 : (entry->c2 - entryRef->c2) * (entry->c2 - entryRef->c2) +
4811 0 : (entry->c3 - entryRef->c3) * (entry->c3 - entryRef->c3);
4812 0 : if (j == 0 || distance < best_distance)
4813 : {
4814 0 : best_j = j;
4815 0 : best_distance = distance;
4816 : }
4817 : }
4818 0 : pTranslationTable[i] = best_j;
4819 : }
4820 : }
4821 0 : if (bHasNoDataValueRef && bHasNoDataValueSrc)
4822 0 : pTranslationTable[noDataValueSrc] = noDataValueRef;
4823 :
4824 0 : return pTranslationTable;
4825 : }
4826 : }
4827 : }
4828 3 : return NULL;
4829 : }
|