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