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