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