1 /******************************************************************************
2 *
3 * Project: GDAL Core
4 * Purpose: Base class for format specific band class implementation. This
5 * base class provides default implementation for many methods.
6 * Author: Frank Warmerdam, warmerdam@pobox.com
7 *
8 ******************************************************************************
9 * Copyright (c) 1998, Frank Warmerdam
10 * Copyright (c) 2007-2016, Even Rouault <even dot rouault at spatialys dot com>
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 "cpl_port.h"
32 #include "gdal_priv.h"
33
34 #include <climits>
35 #include <cmath>
36 #include <cstdarg>
37 #include <cstddef>
38 #include <cstdio>
39 #include <cstdlib>
40 #include <cstring>
41 #include <algorithm>
AutoLoadPythonDrivers()42 #include <limits>
43 #include <memory>
44 #include <new>
45
46 #include "cpl_conv.h"
47 #include "cpl_error.h"
48 #include "cpl_progress.h"
49 #include "cpl_string.h"
50 #include "cpl_virtualmem.h"
51 #include "cpl_vsi.h"
52 #include "gdal.h"
53 #include "gdal_rat.h"
54 #include "gdal_priv_templates.hpp"
55
56 CPL_CVSID("$Id: gdalrasterband.cpp 0daa4251466091d6d8acbd64a17dec0fe27d6b34 2021-08-04 12:01:30 +0200 Even Rouault $")
57
58 /************************************************************************/
59 /* GDALRasterBand() */
60 /************************************************************************/
61
62 /*! Constructor. Applications should never create GDALRasterBands directly. */
63
64 GDALRasterBand::GDALRasterBand() :
65 GDALRasterBand(CPLTestBool( CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") ) )
66 {
67 }
68
IncRefAndReturn(PyObject * obj)69 /** Constructor. Applications should never create GDALRasterBands directly.
70 * @param bForceCachedIOIn Whether cached IO should be forced.
71 */
72 GDALRasterBand::GDALRasterBand(int bForceCachedIOIn):
73 bForceCachedIO(bForceCachedIOIn)
74
75 {
76 }
77
78 /************************************************************************/
CallPython(PyObject * function)79 /* ~GDALRasterBand() */
80 /************************************************************************/
81
82 /*! Destructor. Applications should never destroy GDALRasterBands directly,
83 instead destroy the GDALDataset. */
84
85 GDALRasterBand::~GDALRasterBand()
86
87 {
88 GDALRasterBand::FlushCache();
89
90 delete poBandBlockCache;
91
92 if( static_cast<GIntBig>(nBlockReads) > static_cast<GIntBig>(nBlocksPerRow) * nBlocksPerColumn
93 && nBand == 1 && poDS != nullptr )
94 {
95 CPLDebug( "GDAL", "%d block reads on %d block band 1 of %s.",
96 nBlockReads, nBlocksPerRow * nBlocksPerColumn,
97 poDS->GetDescription() );
98 }
99
100 InvalidateMaskBand();
101 nBand = -nBand;
102 }
103
InitializePythonAndLoadGDALPythonDriverModule()104 /************************************************************************/
105 /* RasterIO() */
106 /************************************************************************/
107
108 /**
109 * \fn GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
110 * int nXOff, int nYOff, int nXSize, int nYSize,
111 * void * pData, int nBufXSize, int nBufYSize,
112 * GDALDataType eBufType,
113 * GSpacing nPixelSpace,
114 * GSpacing nLineSpace,
115 * GDALRasterIOExtraArg* psExtraArg )
116 * \brief Read/write a region of image data for this band.
117 *
118 * This method allows reading a region of a GDALRasterBand into a buffer,
119 * or writing data from a buffer into a region of a GDALRasterBand. It
120 * automatically takes care of data type translation if the data type
121 * (eBufType) of the buffer is different than that of the GDALRasterBand.
122 * The method also takes care of image decimation / replication if the
123 * buffer size (nBufXSize x nBufYSize) is different than the size of the
124 * region being accessed (nXSize x nYSize).
125 *
126 * The nPixelSpace and nLineSpace parameters allow reading into or
127 * writing from unusually organized buffers. This is primarily used
128 * for buffers containing more than one bands raster data in interleaved
129 * format.
130 *
131 * Some formats may efficiently implement decimation into a buffer by
132 * reading from lower resolution overview images.
133 *
134 * For highest performance full resolution data access, read and write
135 * on "block boundaries" as returned by GetBlockSize(), or use the
136 * ReadBlock() and WriteBlock() methods.
137 *
138 * This method is the same as the C GDALRasterIO() or GDALRasterIOEx() functions.
139 *
140 * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
141 * write a region of data.
142 *
143 * @param nXOff The pixel offset to the top left corner of the region
144 * of the band to be accessed. This would be zero to start from the left side.
145 *
146 * @param nYOff The line offset to the top left corner of the region
147 * of the band to be accessed. This would be zero to start from the top.
148 *
149 * @param nXSize The width of the region of the band to be accessed in pixels.
150 *
151 * @param nYSize The height of the region of the band to be accessed in lines.
152 *
153 * @param pData The buffer into which the data should be read, or from which
154 * it should be written. This buffer must contain at least nBufXSize *
155 * nBufYSize words of type eBufType. It is organized in left to right,
156 * top to bottom pixel order. Spacing is controlled by the nPixelSpace,
157 * and nLineSpace parameters.
158 *
159 * @param nBufXSize the width 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 nBufYSize the height of the buffer image into which the desired region is
163 * to be read, or from which it is to be written.
164 *
165 * @param eBufType the type of the pixel values in the pData data buffer. The
166 * pixel values will automatically be translated to/from the GDALRasterBand
167 * data type as needed.
168 *
169 * @param nPixelSpace The byte offset from the start of one pixel value in
170 * pData to the start of the next pixel value within a scanline. If defaulted
171 * (0) the size of the datatype eBufType is used.
172 *
173 * @param nLineSpace The byte offset from the start of one scanline in
174 * pData to the start of the next. If defaulted (0) the size of the datatype
175 * eBufType * nBufXSize is used.
176 *
177 * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg structure with additional
178 * arguments to specify resampling and progress callback, or NULL for default
179 * behavior. The GDAL_RASTERIO_RESAMPLING configuration option can also be defined
180 * to override the default resampling to one of BILINEAR, CUBIC, CUBICSPLINE,
181 * LANCZOS, AVERAGE or MODE.
182 *
183 * @return CE_Failure if the access fails, otherwise CE_None.
184 */
185
186 /**
187 * \brief Read/write a region of image data for this band.
188 *
189 * This method allows reading a region of a GDALRasterBand into a buffer,
190 * or writing data from a buffer into a region of a GDALRasterBand. It
191 * automatically takes care of data type translation if the data type
192 * (eBufType) of the buffer is different than that of the GDALRasterBand.
193 * The method also takes care of image decimation / replication if the
194 * buffer size (nBufXSize x nBufYSize) is different than the size of the
195 * region being accessed (nXSize x nYSize).
196 *
197 * The nPixelSpace and nLineSpace parameters allow reading into or
198 * writing from unusually organized buffers. This is primarily used
199 * for buffers containing more than one bands raster data in interleaved
200 * format.
201 *
202 * Some formats may efficiently implement decimation into a buffer by
203 * reading from lower resolution overview images.
204 *
205 * For highest performance full resolution data access, read and write
206 * on "block boundaries" as returned by GetBlockSize(), or use the
207 * ReadBlock() and WriteBlock() methods.
208 *
209 * This method is the same as the C GDALRasterIO() or GDALRasterIOEx() functions.
210 *
211 * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
212 * write a region of data.
213 *
214 * @param nXOff The pixel offset to the top left corner of the region
215 * of the band to be accessed. This would be zero to start from the left side.
216 *
217 * @param nYOff The line offset to the top left corner of the region
218 * of the band to be accessed. This would be zero to start from the top.
219 *
220 * @param nXSize The width of the region of the band to be accessed in pixels.
221 *
222 * @param nYSize The height of the region of the band to be accessed in lines.
223 *
224 * @param[in,out] pData The buffer into which the data should be read, or from which
225 * it should be written. This buffer must contain at least nBufXSize *
226 * nBufYSize words of type eBufType. It is organized in left to right,
227 * top to bottom pixel order. Spacing is controlled by the nPixelSpace,
228 * and nLineSpace parameters.
229 *
230 * @param nBufXSize the width of the buffer image into which the desired region is
231 * to be read, or from which it is to be written.
232 *
233 * @param nBufYSize the height of the buffer image into which the desired region is
234 * to be read, or from which it is to be written.
235 *
236 * @param eBufType the type of the pixel values in the pData data buffer. The
237 * pixel values will automatically be translated to/from the GDALRasterBand
238 * data type as needed.
239 *
240 * @param nPixelSpace The byte offset from the start of one pixel value in
241 * pData to the start of the next pixel value within a scanline. If defaulted
242 * (0) the size of the datatype eBufType is used.
243 *
244 * @param nLineSpace The byte offset from the start of one scanline in
245 * pData to the start of the next. If defaulted (0) the size of the datatype
246 * eBufType * nBufXSize is used.
247 *
248 * @param[in] psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg structure with additional
249 * arguments to specify resampling and progress callback, or NULL for default
250 * behavior. The GDAL_RASTERIO_RESAMPLING configuration option can also be defined
251 * to override the default resampling to one of BILINEAR, CUBIC, CUBICSPLINE,
252 * LANCZOS, AVERAGE or MODE.
253 *
254 * @return CE_Failure if the access fails, otherwise CE_None.
255 */
256
257 CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
258 int nXOff, int nYOff, int nXSize, int nYSize,
259 void * pData, int nBufXSize, int nBufYSize,
260 GDALDataType eBufType,
261 GSpacing nPixelSpace,
262 GSpacing nLineSpace,
263 GDALRasterIOExtraArg* psExtraArg )
264
265 {
266 GDALRasterIOExtraArg sExtraArg;
267 if( psExtraArg == nullptr )
268 {
269 INIT_RASTERIO_EXTRA_ARG(sExtraArg);
270 psExtraArg = &sExtraArg;
271 }
272 else if( psExtraArg->nVersion != RASTERIO_EXTRA_ARG_CURRENT_VERSION )
273 {
274 ReportError( CE_Failure, CPLE_AppDefined,
275 "Unhandled version of GDALRasterIOExtraArg" );
276 return CE_Failure;
277 }
278
279 GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize,
280 nBufXSize, nBufYSize);
281
282 if( nullptr == pData )
283 {
284 ReportError( CE_Failure, CPLE_AppDefined,
285 "The buffer into which the data should be read is null" );
286 return CE_Failure;
287 }
288
289 /* -------------------------------------------------------------------- */
290 /* Some size values are "noop". Lets just return to avoid */
291 /* stressing lower level functions. */
292 /* -------------------------------------------------------------------- */
293 if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
294 {
295 CPLDebug( "GDAL",
296 "RasterIO() skipped for odd window or buffer size.\n"
297 " Window = (%d,%d)x%dx%d\n"
298 " Buffer = %dx%d\n",
299 nXOff, nYOff, nXSize, nYSize,
300 nBufXSize, nBufYSize );
301
302 return CE_None;
303 }
304
305 if( eRWFlag == GF_Write )
306 {
307 if( eFlushBlockErr != CE_None )
308 {
309 ReportError(eFlushBlockErr, CPLE_AppDefined,
310 "An error occurred while writing a dirty block "
311 "from GDALRasterBand::RasterIO");
312 CPLErr eErr = eFlushBlockErr;
313 eFlushBlockErr = CE_None;
314 return eErr;
315 }
316 if( eAccess != GA_Update )
317 {
318 ReportError( CE_Failure, CPLE_AppDefined,
319 "Write operation not permitted on dataset opened "
320 "in read-only mode" );
321 return CE_Failure;
322 }
323 }
324
325 /* -------------------------------------------------------------------- */
326 /* If pixel and line spacing are defaulted assign reasonable */
327 /* value assuming a packed buffer. */
328 /* -------------------------------------------------------------------- */
329 if( nPixelSpace == 0 )
330 {
331 nPixelSpace = GDALGetDataTypeSizeBytes( eBufType );
332 }
333
334 if( nLineSpace == 0 )
335 {
336 nLineSpace = nPixelSpace * nBufXSize;
337 }
338
339 /* -------------------------------------------------------------------- */
340 /* Do some validation of parameters. */
341 /* -------------------------------------------------------------------- */
342 if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
343 || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
344 {
345 ReportError( CE_Failure, CPLE_IllegalArg,
346 "Access window out of range in RasterIO(). Requested\n"
347 "(%d,%d) of size %dx%d on raster of %dx%d.",
348 nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
349 return CE_Failure;
350 }
351
352 if( eRWFlag != GF_Read && eRWFlag != GF_Write )
353 {
354 ReportError( CE_Failure, CPLE_IllegalArg,
355 "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
356 eRWFlag );
357 return CE_Failure;
358 }
359
360 /* -------------------------------------------------------------------- */
361 /* Call the format specific function. */
362 /* -------------------------------------------------------------------- */
363
364 const bool bCallLeaveReadWrite = CPL_TO_BOOL(EnterReadWrite(eRWFlag));
365
366 CPLErr eErr;
367 if( bForceCachedIO )
368 eErr = GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
369 pData, nBufXSize, nBufYSize, eBufType,
370 nPixelSpace, nLineSpace, psExtraArg );
371 else
372 eErr = IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
373 pData, nBufXSize, nBufYSize, eBufType,
374 nPixelSpace, nLineSpace, psExtraArg ) ;
375
376 if( bCallLeaveReadWrite) LeaveReadWrite();
377
378 return eErr;
379 }
380
381 /************************************************************************/
382 /* GDALRasterIO() */
383 /************************************************************************/
384
385 /**
386 * \brief Read/write a region of image data for this band.
387 *
388 * Use GDALRasterIOEx() if 64 bit spacings or extra arguments (resampling
389 * resolution, progress callback, etc. are needed)
390 *
391 * @see GDALRasterBand::RasterIO()
392 */
393
394 CPLErr CPL_STDCALL
395 GDALRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
396 int nXOff, int nYOff, int nXSize, int nYSize,
397 void * pData, int nBufXSize, int nBufYSize,
398 GDALDataType eBufType,
399 int nPixelSpace, int nLineSpace )
400
401 {
402 VALIDATE_POINTER1( hBand, "GDALRasterIO", CE_Failure );
403
404 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
405
406 return( poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
407 pData, nBufXSize, nBufYSize, eBufType,
408 nPixelSpace, nLineSpace, nullptr) );
~PythonPluginLayer()409 }
410
411 /************************************************************************/
412 /* GDALRasterIOEx() */
413 /************************************************************************/
414
415 /**
416 * \brief Read/write a region of image data for this band.
417 *
418 * @see GDALRasterBand::RasterIO()
419 * @since GDAL 2.0
420 */
421
422 CPLErr CPL_STDCALL
423 GDALRasterIOEx( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
424 int nXOff, int nYOff, int nXSize, int nYSize,
425 void * pData, int nBufXSize, int nBufYSize,
426 GDALDataType eBufType,
427 GSpacing nPixelSpace, GSpacing nLineSpace,
428 GDALRasterIOExtraArg* psExtraArg )
429
430 {
431 VALIDATE_POINTER1( hBand, "GDALRasterIOEx", CE_Failure );
432
433 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
434
435 return( poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
436 pData, nBufXSize, nBufYSize, eBufType,
437 nPixelSpace, nLineSpace, psExtraArg) );
438 }
439 /************************************************************************/
440 /* ReadBlock() */
441 /************************************************************************/
442
443 /**
444 * \brief Read a block of image data efficiently.
445 *
446 * This method accesses a "natural" block from the raster band without
447 * resampling, or data type conversion. For a more generalized, but
448 * potentially less efficient access use RasterIO().
449 *
450 * This method is the same as the C GDALReadBlock() function.
451 *
452 * See the GetLockedBlockRef() method for a way of accessing internally cached
453 * block oriented data without an extra copy into an application buffer.
454 *
SetAttributeFilter(const char * pszFilter)455 * The following code would efficiently compute a histogram of eight bit
456 * raster data. Note that the final block may be partial ... data beyond
457 * the edge of the underlying raster band in these edge blocks is of an
458 * undetermined value.
459 *
460 \code{.cpp}
461 CPLErr GetHistogram( GDALRasterBand *poBand, GUIntBig *panHistogram )
462
463 {
464 memset( panHistogram, 0, sizeof(GUIntBig) * 256 );
465
466 CPLAssert( poBand->GetRasterDataType() == GDT_Byte );
467
468 int nXBlockSize, nYBlockSize;
469
470 poBand->GetBlockSize( &nXBlockSize, &nYBlockSize );
471 int nXBlocks = (poBand->GetXSize() + nXBlockSize - 1) / nXBlockSize;
472 int nYBlocks = (poBand->GetYSize() + nYBlockSize - 1) / nYBlockSize;
473
474 GByte *pabyData = (GByte *) CPLMalloc(nXBlockSize * nYBlockSize);
475
476 for( int iYBlock = 0; iYBlock < nYBlocks; iYBlock++ )
477 {
478 for( int iXBlock = 0; iXBlock < nXBlocks; iXBlock++ )
479 {
480 int nXValid, nYValid;
481
482 poBand->ReadBlock( iXBlock, iYBlock, pabyData );
483
484 // Compute the portion of the block that is valid
485 // for partial edge blocks.
486 poBand->GetActualBlockSize(iXBlock, iYBlock, &nXValid, &nYValid)
487
488 // Collect the histogram counts.
489 for( int iY = 0; iY < nYValid; iY++ )
490 {
491 for( int iX = 0; iX < nXValid; iX++ )
492 {
493 panHistogram[pabyData[iX + iY * nXBlockSize]] += 1;
494 }
495 }
496 }
497 }
498 }
499 \endcode
500 *
501 * @param nXBlockOff the horizontal block offset, with zero indicating
502 * the left most block, 1 the next block and so forth.
503 *
504 * @param nYBlockOff the vertical block offset, with zero indicating
505 * the top most block, 1 the next block and so forth.
506 *
507 * @param pImage the buffer into which the data will be read. The buffer
508 * must be large enough to hold GetBlockXSize()*GetBlockYSize() words
509 * of type GetRasterDataType().
510 *
511 * @return CE_None on success or CE_Failure on an error.
512 */
513
514 CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
515 void * pImage )
516
517 {
518 /* -------------------------------------------------------------------- */
519 /* Validate arguments. */
520 /* -------------------------------------------------------------------- */
521 CPLAssert( pImage != nullptr );
522
523 if( !InitBlockInfo() )
524 return CE_Failure;
525
526 if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
527 {
528 ReportError( CE_Failure, CPLE_IllegalArg,
529 "Illegal nXBlockOff value (%d) in "
530 "GDALRasterBand::ReadBlock()\n",
531 nXBlockOff );
532
533 return( CE_Failure );
534 }
535
536 if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
537 {
538 ReportError( CE_Failure, CPLE_IllegalArg,
539 "Illegal nYBlockOff value (%d) in "
540 "GDALRasterBand::ReadBlock()\n",
541 nYBlockOff );
542
543 return( CE_Failure );
544 }
545
546 /* -------------------------------------------------------------------- */
547 /* Invoke underlying implementation method. */
548 /* -------------------------------------------------------------------- */
549
550 int bCallLeaveReadWrite = EnterReadWrite(GF_Read);
551 CPLErr eErr = IReadBlock( nXBlockOff, nYBlockOff, pImage );
552 if( bCallLeaveReadWrite) LeaveReadWrite();
553 return eErr;
554 }
555
556 /************************************************************************/
557 /* GDALReadBlock() */
TestCapability(const char * pszCap)558 /************************************************************************/
559
560 /**
561 * \brief Read a block of image data efficiently.
562 *
563 * @see GDALRasterBand::ReadBlock()
564 */
565
566 CPLErr CPL_STDCALL GDALReadBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
567 void * pData )
568
569 {
570 VALIDATE_POINTER1( hBand, "GDALReadBlock", CE_Failure );
571
572 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
573 return( poBand->ReadBlock( nXOff, nYOff, pData ) );
574 }
575
576 /************************************************************************/
577 /* IReadBlock() */
578 /************************************************************************/
579
580 /** \fn GDALRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *pData )
581 * \brief Read a block of data.
582 *
583 * Default internal implementation ... to be overridden by
584 * subclasses that support reading.
585 * @param nBlockXOff Block X Offset
586 * @param nBlockYOff Block Y Offset
587 * @param pData Pixel buffer into which to place read data.
588 * @return CE_None on success or CE_Failure on an error.
589 */
590
GetFIDColumn()591 /************************************************************************/
592 /* IWriteBlock() */
593 /************************************************************************/
594
595 /**
596 * \fn GDALRasterBand::IWriteBlock(int, int, void*)
597 * Write a block of data.
598 *
599 * Default internal implementation ... to be overridden by
600 * subclasses that support writing.
601 * @param nBlockXOff Block X Offset
602 * @param nBlockYOff Block Y Offset
603 * @param pData Pixel buffer to write
604 * @return CE_None on success or CE_Failure on an error.
605 */
606
607 /**/
608 /**/
609
610 CPLErr GDALRasterBand::IWriteBlock( int /*nBlockXOff*/,
611 int /*nBlockYOff*/,
612 void * /*pData*/ )
613
614 {
615 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
616 ReportError( CE_Failure, CPLE_NotSupported,
617 "WriteBlock() not supported for this dataset." );
618
619 return( CE_Failure );
620 }
621
622 /************************************************************************/
623 /* WriteBlock() */
layer_featureCount(PyObject *,PyObject * args,PyObject *)624 /************************************************************************/
625
626 /**
627 * \brief Write a block of image data efficiently.
628 *
629 * This method accesses a "natural" block from the raster band without
630 * resampling, or data type conversion. For a more generalized, but
631 * potentially less efficient access use RasterIO().
632 *
633 * This method is the same as the C GDALWriteBlock() function.
634 *
635 * See ReadBlock() for an example of block oriented data access.
636 *
637 * @param nXBlockOff the horizontal block offset, with zero indicating
638 * the left most block, 1 the next block and so forth.
639 *
640 * @param nYBlockOff the vertical block offset, with zero indicating
641 * the left most block, 1 the next block and so forth.
642 *
643 * @param pImage the buffer from which the data will be written. The buffer
644 * must be large enough to hold GetBlockXSize()*GetBlockYSize() words
645 * of type GetRasterDataType().
646 *
647 * @return CE_None on success or CE_Failure on an error.
648 */
649
650 CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
651 void * pImage )
652
653 {
654 /* -------------------------------------------------------------------- */
655 /* Validate arguments. */
656 /* -------------------------------------------------------------------- */
657 CPLAssert( pImage != nullptr );
658
659 if( !InitBlockInfo() )
660 return CE_Failure;
661
662 if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
663 {
664 ReportError( CE_Failure, CPLE_IllegalArg,
665 "Illegal nXBlockOff value (%d) in "
666 "GDALRasterBand::WriteBlock()\n",
667 nXBlockOff );
668
669 return( CE_Failure );
670 }
671
672 if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
673 {
674 ReportError( CE_Failure, CPLE_IllegalArg,
675 "Illegal nYBlockOff value (%d) in "
676 "GDALRasterBand::WriteBlock()\n",
677 nYBlockOff );
678
679 return( CE_Failure );
680 }
681
682 if( eAccess == GA_ReadOnly )
683 {
684 ReportError( CE_Failure, CPLE_NoWriteAccess,
685 "Attempt to write to read only dataset in"
686 "GDALRasterBand::WriteBlock().\n" );
687
688 return( CE_Failure );
689 }
690
691 if( eFlushBlockErr != CE_None )
692 {
693 ReportError(eFlushBlockErr, CPLE_AppDefined,
694 "An error occurred while writing a dirty block "
695 "from GDALRasterBand::WriteBlock");
696 CPLErr eErr = eFlushBlockErr;
697 eFlushBlockErr = CE_None;
698 return eErr;
699 }
700
701 /* -------------------------------------------------------------------- */
702 /* Invoke underlying implementation method. */
703 /* -------------------------------------------------------------------- */
704
705 const bool bCallLeaveReadWrite = CPL_TO_BOOL(EnterReadWrite(GF_Write));
706 CPLErr eErr = IWriteBlock( nXBlockOff, nYBlockOff, pImage );
707 if( bCallLeaveReadWrite ) LeaveReadWrite();
708
709 return eErr;
710 }
711
712 /************************************************************************/
713 /* GDALWriteBlock() */
714 /************************************************************************/
715
716 /**
717 * \brief Write a block of image data efficiently.
718 *
719 * @see GDALRasterBand::WriteBlock()
720 */
721
722 CPLErr CPL_STDCALL GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
723 void * pData )
724
725 {
726 VALIDATE_POINTER1( hBand, "GDALWriteBlock", CE_Failure );
727
728 GDALRasterBand *poBand = GDALRasterBand::FromHandle( hBand );
729 return( poBand->WriteBlock( nXOff, nYOff, pData ) );
730 }
731
732 /************************************************************************/
733 /* GetActualBlockSize() */
734 /************************************************************************/
735 /**
736 * \brief Fetch the actual block size for a given block offset.
737 *
738 * Handles partial blocks at the edges of the raster and returns the true
739 * number of pixels
740 *
741 * @param nXBlockOff the horizontal block offset for which to calculate the number of
742 * valid pixels, with zero indicating the left most block, 1 the next block and so forth.
TranslateToOGRFeature(PyObject * poObj)743 *
744 * @param nYBlockOff the vertical block offset, with zero indicating
745 * the left most block, 1 the next block and so forth.
746 *
747 * @param pnXValid pointer to an integer in which the number of valid pixels in the x
748 * direction will be stored
749 *
750 * @param pnYValid pointer to an integer in which the number of valid pixels in the y
751 * direction will be stored
752 *
753 * @return CE_None if the input parameter are valid, CE_Failure otherwise
754 *
755 * @since GDAL 2.2
756 */
757 CPLErr GDALRasterBand::GetActualBlockSize(int nXBlockOff, int nYBlockOff,
758 int *pnXValid, int *pnYValid)
759 {
760 if( nXBlockOff < 0 || nBlockXSize == 0 ||
761 nXBlockOff >= nRasterXSize / nBlockXSize + ((nRasterXSize % nBlockXSize) ? 1 : 0) ||
762 nYBlockOff < 0 || nBlockYSize == 0 ||
763 nYBlockOff >= nRasterYSize / nBlockYSize + ((nRasterYSize % nBlockYSize) ? 1 : 0) )
764 {
765 return CE_Failure;
766 }
767
768 int nXPixelOff = nXBlockOff * nBlockXSize;
769 int nYPixelOff = nYBlockOff * nBlockYSize;
770
771 *pnXValid = nBlockXSize;
772 *pnYValid = nBlockYSize;
773
774 if( nXPixelOff + nBlockXSize >= nRasterXSize)
775 {
776 *pnXValid = nRasterXSize - nXPixelOff;
777 }
778
779 if( nYPixelOff + nBlockYSize >= nRasterYSize)
780 {
781 *pnYValid = nRasterYSize - nYPixelOff;
782 }
783
784 return CE_None;
785 }
786
787 /************************************************************************/
788 /* GDALGetActualBlockSize() */
789 /************************************************************************/
790
791 /**
792 * \brief Retrieve the actual block size for a given block offset.
793 *
794 * @see GDALRasterBand::GetActualBlockSize()
795 */
796
797 CPLErr CPL_STDCALL GDALGetActualBlockSize( GDALRasterBandH hBand,
798 int nXBlockOff,
799 int nYBlockOff,
800 int *pnXValid,
801 int *pnYValid )
802
803 {
804 VALIDATE_POINTER1( hBand, "GDALGetActualBlockSize", CE_Failure );
805
806 GDALRasterBand *poBand = GDALRasterBand::FromHandle( hBand );
807 return( poBand->GetActualBlockSize( nXBlockOff, nYBlockOff, pnXValid, pnYValid ) );
808 }
809
810 /************************************************************************/
811 /* GetRasterDataType() */
812 /************************************************************************/
813
814 /**
815 * \brief Fetch the pixel data type for this band.
816 *
817 * This method is the same as the C function GDALGetRasterDataType().
818 *
819 * @return the data type of pixels for this band.
820 */
821
822 GDALDataType GDALRasterBand::GetRasterDataType()
823
824 {
825 return eDataType;
826 }
827
828 /************************************************************************/
829 /* GDALGetRasterDataType() */
830 /************************************************************************/
831
832 /**
833 * \brief Fetch the pixel data type for this band.
834 *
835 * @see GDALRasterBand::GetRasterDataType()
836 */
837
838 GDALDataType CPL_STDCALL GDALGetRasterDataType( GDALRasterBandH hBand )
839
840 {
841 VALIDATE_POINTER1( hBand, "GDALGetRasterDataType", GDT_Unknown );
842
843 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
844 return poBand->GetRasterDataType();
845 }
846
847 /************************************************************************/
848 /* GetBlockSize() */
849 /************************************************************************/
850
851 /**
852 * \brief Fetch the "natural" block size of this band.
853 *
854 * GDAL contains a concept of the natural block size of rasters so that
855 * applications can organized data access efficiently for some file formats.
856 * The natural block size is the block size that is most efficient for
857 * accessing the format. For many formats this is simple a whole scanline
858 * in which case *pnXSize is set to GetXSize(), and *pnYSize is set to 1.
859 *
860 * However, for tiled images this will typically be the tile size.
861 *
862 * Note that the X and Y block sizes don't have to divide the image size
863 * evenly, meaning that right and bottom edge blocks may be incomplete.
864 * See ReadBlock() for an example of code dealing with these issues.
865 *
866 * This method is the same as the C function GDALGetBlockSize().
867 *
868 * @param pnXSize integer to put the X block size into or NULL.
869 *
870 * @param pnYSize integer to put the Y block size into or NULL.
871 */
872
873 void GDALRasterBand::GetBlockSize( int * pnXSize, int *pnYSize )
874
875 {
876 if( nBlockXSize <= 0 || nBlockYSize <= 0 )
877 {
878 ReportError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
879 nBlockXSize, nBlockYSize );
880 if( pnXSize != nullptr )
881 *pnXSize = 0;
882 if( pnYSize != nullptr )
883 *pnYSize = 0;
884 }
885 else
886 {
887 if( pnXSize != nullptr )
888 *pnXSize = nBlockXSize;
889 if( pnYSize != nullptr )
890 *pnYSize = nBlockYSize;
891 }
892 }
893
894 /************************************************************************/
895 /* GDALGetBlockSize() */
896 /************************************************************************/
897
898 /**
899 * \brief Fetch the "natural" block size of this band.
900 *
901 * @see GDALRasterBand::GetBlockSize()
902 */
903
904 void CPL_STDCALL
905 GDALGetBlockSize( GDALRasterBandH hBand, int * pnXSize, int * pnYSize )
906
907 {
908 VALIDATE_POINTER0( hBand, "GDALGetBlockSize" );
GetFeature(GIntBig nFID)909
910 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
911 poBand->GetBlockSize( pnXSize, pnYSize );
912 }
913
914 /************************************************************************/
915 /* InitBlockInfo() */
916 /************************************************************************/
917
918 //! @cond Doxygen_Suppress
919 int GDALRasterBand::InitBlockInfo()
920
921 {
922 if( poBandBlockCache != nullptr )
923 return poBandBlockCache->IsInitOK();
924
925 /* Do some validation of raster and block dimensions in case the driver */
926 /* would have neglected to do it itself */
927 if( nBlockXSize <= 0 || nBlockYSize <= 0 )
928 {
929 ReportError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
930 nBlockXSize, nBlockYSize );
931 return FALSE;
932 }
933
934 if( nRasterXSize <= 0 || nRasterYSize <= 0 )
935 {
936 ReportError( CE_Failure, CPLE_AppDefined, "Invalid raster dimension : %d * %d",
937 nRasterXSize, nRasterYSize );
938 return FALSE;
ResetReading()939 }
940
941 const int nDataTypeSize = GDALGetDataTypeSizeBytes(eDataType);
942 if( nDataTypeSize == 0 )
943 {
944 ReportError( CE_Failure, CPLE_AppDefined, "Invalid data type" );
945 return FALSE;
946 }
947
948 #if SIZEOF_VOIDP == 4
949 if (nBlockXSize >= 10000 || nBlockYSize >= 10000)
950 {
951 /* As 10000 * 10000 * 16 < INT_MAX, we don't need to do the multiplication in other cases */
952 if( nBlockXSize > INT_MAX / nDataTypeSize ||
953 nBlockYSize > INT_MAX / (nDataTypeSize * nBlockXSize) )
GetNextFeature()954 {
955 ReportError( CE_Failure, CPLE_NotSupported, "Too big block : %d * %d for 32-bit build",
956 nBlockXSize, nBlockYSize );
957 return FALSE;
958 }
959 }
960 #endif
961
962 nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
963 nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
964
965 const char* pszBlockStrategy = CPLGetConfigOption("GDAL_BAND_BLOCK_CACHE", nullptr);
966 bool bUseArray = true;
967 if( pszBlockStrategy == nullptr )
968 {
969 if( poDS == nullptr ||
970 (poDS->nOpenFlags & GDAL_OF_BLOCK_ACCESS_MASK) ==
971 GDAL_OF_DEFAULT_BLOCK_ACCESS )
972 {
973 GUIntBig nBlockCount = static_cast<GIntBig>(nBlocksPerRow) * nBlocksPerColumn;
974 if( poDS != nullptr )
975 nBlockCount *= poDS->GetRasterCount();
976 bUseArray = ( nBlockCount < 1024 * 1024 );
977 }
978 else if( (poDS->nOpenFlags & GDAL_OF_BLOCK_ACCESS_MASK) ==
979 GDAL_OF_HASHSET_BLOCK_ACCESS )
980 {
981 bUseArray = false;
982 }
983 }
984 else if( EQUAL(pszBlockStrategy, "HASHSET") )
985 bUseArray = false;
986 if( bUseArray )
987 poBandBlockCache = GDALArrayBandBlockCacheCreate(this);
988 else
989 {
990 if( nBand == 1)
991 CPLDebug("GDAL", "Use hashset band block cache");
992 poBandBlockCache = GDALHashSetBandBlockCacheCreate(this);
993 }
994 if( poBandBlockCache == nullptr )
995 return FALSE;
996 return poBandBlockCache->Init();
997 }
998 //! @endcond
999
1000 /************************************************************************/
1001 /* FlushCache() */
1002 /************************************************************************/
GetLayerDefn()1003
1004 /**
1005 * \brief Flush raster data cache.
1006 *
1007 * This call will recover memory used to cache data blocks for this raster
1008 * band, and ensure that new requests are referred to the underlying driver.
1009 *
1010 * This method is the same as the C function GDALFlushRasterCache().
1011 *
1012 * @return CE_None on success.
1013 */
1014
1015 CPLErr GDALRasterBand::FlushCache()
1016
1017 {
1018 CPLErr eGlobalErr = eFlushBlockErr;
1019
1020 if (eFlushBlockErr != CE_None)
1021 {
1022 ReportError(
1023 eFlushBlockErr, CPLE_AppDefined,
1024 "An error occurred while writing a dirty block from FlushCache");
1025 eFlushBlockErr = CE_None;
1026 }
1027
1028 if (poBandBlockCache == nullptr || !poBandBlockCache->IsInitOK())
1029 return eGlobalErr;
1030
1031 return poBandBlockCache->FlushCache();
1032 }
1033
1034 /************************************************************************/
1035 /* GDALFlushRasterCache() */
1036 /************************************************************************/
1037
1038 /**
1039 * \brief Flush raster data cache.
1040 *
1041 * @see GDALRasterBand::FlushCache()
1042 */
1043
1044 CPLErr CPL_STDCALL GDALFlushRasterCache( GDALRasterBandH hBand )
1045
1046 {
1047 VALIDATE_POINTER1( hBand, "GDALFlushRasterCache", CE_Failure );
1048
1049 return GDALRasterBand::FromHandle(hBand)->FlushCache();
1050 }
1051
1052 /************************************************************************/
1053 /* UnreferenceBlock() */
1054 /* */
1055 /* Unreference the block from our array of blocks */
1056 /* This method should only be called by */
1057 /* GDALRasterBlock::Internalize() and FlushCacheBlock() (and under */
1058 /* the block cache mutex) */
1059 /************************************************************************/
1060
1061 CPLErr GDALRasterBand::UnreferenceBlock( GDALRasterBlock* poBlock )
1062 {
1063 #ifdef notdef
1064 if( poBandBlockCache == nullptr || !poBandBlockCache->IsInitOK() )
1065 {
1066 if( poBandBlockCache == nullptr )
1067 printf("poBandBlockCache == NULL\n");/*ok*/
1068 else
1069 printf("!poBandBlockCache->IsInitOK()\n");/*ok*/
1070 printf("caller = %s\n", pszCaller);/*ok*/
1071 printf("GDALRasterBand: %p\n", this);/*ok*/
1072 printf("GDALRasterBand: nBand=%d\n", nBand);/*ok*/
1073 printf("nRasterXSize = %d\n", nRasterXSize);/*ok*/
1074 printf("nRasterYSize = %d\n", nRasterYSize);/*ok*/
1075 printf("nBlockXSize = %d\n", nBlockXSize);/*ok*/
1076 printf("nBlockYSize = %d\n", nBlockYSize);/*ok*/
1077 poBlock->DumpBlock();
1078 if( GetDataset() != nullptr )
1079 printf("Dataset: %s\n", GetDataset()->GetDescription());/*ok*/
1080 GDALRasterBlock::Verify();
1081 abort();
1082 }
1083 #endif
1084 CPLAssert(poBandBlockCache && poBandBlockCache->IsInitOK());
1085 return poBandBlockCache->UnreferenceBlock( poBlock );
1086 }
1087
1088 /************************************************************************/
1089 /* AddBlockToFreeList() */
1090 /* */
1091 /* When GDALRasterBlock::Internalize() or FlushCacheBlock() are */
1092 /* finished with a block about to be free'd, they pass it to that */
1093 /* method. */
1094 /************************************************************************/
1095
1096 //! @cond Doxygen_Suppress
1097 void GDALRasterBand::AddBlockToFreeList( GDALRasterBlock * poBlock )
1098 {
1099 CPLAssert(poBandBlockCache && poBandBlockCache->IsInitOK());
1100 return poBandBlockCache->AddBlockToFreeList( poBlock );
1101 }
1102 //! @endcond
1103
1104 /************************************************************************/
1105 /* FlushBlock() */
1106 /************************************************************************/
1107
1108 /** Flush a block out of the block cache.
1109 * @param nXBlockOff block x offset
1110 * @param nYBlockOff blocky offset
1111 * @param bWriteDirtyBlock whether the block should be written to disk if dirty.
1112 * @return CE_None in case of success, an error code otherwise.
1113 */
1114 CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff,
1115 int bWriteDirtyBlock )
1116
1117 {
1118 if( poBandBlockCache == nullptr || !poBandBlockCache->IsInitOK() )
1119 return( CE_Failure );
1120
1121 /* -------------------------------------------------------------------- */
1122 /* Validate the request */
1123 /* -------------------------------------------------------------------- */
1124 if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
1125 {
1126 ReportError( CE_Failure, CPLE_IllegalArg,
1127 "Illegal nBlockXOff value (%d) in "
1128 "GDALRasterBand::FlushBlock()\n",
1129 nXBlockOff );
1130
1131 return( CE_Failure );
1132 }
1133
1134 if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
1135 {
1136 ReportError( CE_Failure, CPLE_IllegalArg,
1137 "Illegal nBlockYOff value (%d) in "
1138 "GDALRasterBand::FlushBlock()\n",
1139 nYBlockOff );
1140
1141 return( CE_Failure );
1142 }
1143
1144 return poBandBlockCache->FlushBlock( nXBlockOff, nYBlockOff, bWriteDirtyBlock );
1145 }
1146
1147 /************************************************************************/
1148 /* TryGetLockedBlockRef() */
1149 /************************************************************************/
1150
1151 /**
1152 * \brief Try fetching block ref.
1153 *
1154 * This method will returned the requested block (locked) if it is already
1155 * in the block cache for the layer. If not, nullptr is returned.
1156 *
1157 * If a non-NULL value is returned, then a lock for the block will have been
1158 * acquired on behalf of the caller. It is absolutely imperative that the
1159 * caller release this lock (with GDALRasterBlock::DropLock()) or else
1160 * severe problems may result.
1161 *
1162 * @param nXBlockOff the horizontal block offset, with zero indicating
1163 * the left most block, 1 the next block and so forth.
1164 *
1165 * @param nYBlockOff the vertical block offset, with zero indicating
1166 * the top most block, 1 the next block and so forth.
1167 *
1168 * @return NULL if block not available, or locked block pointer.
1169 */
1170
1171 GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
1172 int nYBlockOff )
1173
1174 {
1175 if( poBandBlockCache == nullptr || !poBandBlockCache->IsInitOK() )
1176 return nullptr;
1177
1178 /* -------------------------------------------------------------------- */
1179 /* Validate the request */
1180 /* -------------------------------------------------------------------- */
1181 if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
1182 {
1183 ReportError( CE_Failure, CPLE_IllegalArg,
1184 "Illegal nBlockXOff value (%d) in "
1185 "GDALRasterBand::TryGetLockedBlockRef()\n",
1186 nXBlockOff );
1187
GetGeomFields()1188 return( nullptr );
1189 }
1190
1191 if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
1192 {
1193 ReportError( CE_Failure, CPLE_IllegalArg,
1194 "Illegal nBlockYOff value (%d) in "
1195 "GDALRasterBand::TryGetLockedBlockRef()\n",
1196 nYBlockOff );
1197
1198 return( nullptr );
1199 }
1200
1201 return poBandBlockCache->TryGetLockedBlockRef(nXBlockOff, nYBlockOff);
1202 }
1203
1204 /************************************************************************/
1205 /* GetLockedBlockRef() */
1206 /************************************************************************/
1207
1208 /**
1209 * \brief Fetch a pointer to an internally cached raster block.
1210 *
1211 * This method will returned the requested block (locked) if it is already
1212 * in the block cache for the layer. If not, the block will be read from
1213 * the driver, and placed in the layer block cached, then returned. If an
1214 * error occurs reading the block from the driver, a NULL value will be
1215 * returned.
1216 *
1217 * If a non-NULL value is returned, then a lock for the block will have been
1218 * acquired on behalf of the caller. It is absolutely imperative that the
1219 * caller release this lock (with GDALRasterBlock::DropLock()) or else
1220 * severe problems may result.
1221 *
1222 * Note that calling GetLockedBlockRef() on a previously uncached band will
1223 * enable caching.
1224 *
1225 * @param nXBlockOff the horizontal block offset, with zero indicating
1226 * the left most block, 1 the next block and so forth.
1227 *
1228 * @param nYBlockOff the vertical block offset, with zero indicating
1229 * the top most block, 1 the next block and so forth.
1230 *
1231 * @param bJustInitialize If TRUE the block will be allocated and initialized,
1232 * but not actually read from the source. This is useful when it will just
1233 * be completely set and written back.
1234 *
1235 * @return pointer to the block object, or NULL on failure.
1236 */
1237
1238 GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
1239 int nYBlockOff,
1240 int bJustInitialize )
1241
1242 {
1243 /* -------------------------------------------------------------------- */
1244 /* Try and fetch from cache. */
1245 /* -------------------------------------------------------------------- */
1246 GDALRasterBlock *poBlock = TryGetLockedBlockRef( nXBlockOff, nYBlockOff );
1247
1248 /* -------------------------------------------------------------------- */
1249 /* If we didn't find it in our memory cache, instantiate a */
1250 /* block (potentially load from disk) and "adopt" it into the */
1251 /* cache. */
1252 /* -------------------------------------------------------------------- */
1253 if( poBlock == nullptr )
1254 {
1255 if( !InitBlockInfo() )
1256 return( nullptr );
1257
1258 /* -------------------------------------------------------------------- */
1259 /* Validate the request */
1260 /* -------------------------------------------------------------------- */
1261 if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
1262 {
1263 ReportError( CE_Failure, CPLE_IllegalArg,
1264 "Illegal nBlockXOff value (%d) in "
1265 "GDALRasterBand::GetLockedBlockRef()\n",
1266 nXBlockOff );
1267
1268 return( nullptr );
1269 }
1270
1271 if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
1272 {
1273 ReportError( CE_Failure, CPLE_IllegalArg,
1274 "Illegal nBlockYOff value (%d) in "
1275 "GDALRasterBand::GetLockedBlockRef()\n",
1276 nYBlockOff );
1277
1278 return( nullptr );
1279 }
1280
1281 poBlock = poBandBlockCache->CreateBlock( nXBlockOff, nYBlockOff );
1282 if( poBlock == nullptr )
1283 return nullptr;
1284
1285 poBlock->AddLock();
1286
1287 /* We need to temporarily drop the read-write lock in the following */
1288 /*scenario. Imagine 2 threads T1 and T2 that respectively write dataset */
1289 /* D1 and D2. T1 will take the mutex on D1 and T2 on D2. Now when the */
1290 /* block cache fills, T1 might need to flush dirty blocks of D2 in the */
1291 /* below Internalize(), which will cause GDALRasterBlock::Write() to be */
1292 /* called and attempt at taking the lock on T2 (already taken). Similarly */
1293 /* for T2 with D1, hence a deadlock situation (#6163) */
1294 /* But this may open the door to other problems... */
1295 if( poDS )
1296 poDS->TemporarilyDropReadWriteLock();
1297 /* allocate data space */
1298 CPLErr eErr = poBlock->Internalize();
1299 if( poDS )
1300 poDS->ReacquireReadWriteLock();
1301 if( eErr != CE_None )
1302 {
1303 poBlock->DropLock();
1304 delete poBlock;
1305 return nullptr;
1306 }
1307
1308 if ( poBandBlockCache->AdoptBlock(poBlock) != CE_None )
1309 {
1310 poBlock->DropLock();
1311 delete poBlock;
1312 return nullptr;
1313 }
1314
1315 if( !bJustInitialize )
1316 {
1317 const GUInt32 nErrorCounter = CPLGetErrorCounter();
1318 int bCallLeaveReadWrite = EnterReadWrite(GF_Read);
1319 eErr = IReadBlock(nXBlockOff,nYBlockOff,poBlock->GetDataRef());
1320 if( bCallLeaveReadWrite) LeaveReadWrite();
1321 if( eErr != CE_None )
1322 {
1323 poBlock->DropLock();
1324 FlushBlock( nXBlockOff, nYBlockOff );
1325 ReportError( CE_Failure, CPLE_AppDefined,
GetMetadata(PyObject * obj,const char * pszDomain)1326 "IReadBlock failed at X offset %d, Y offset %d%s",
1327 nXBlockOff, nYBlockOff,
1328 (nErrorCounter != CPLGetErrorCounter()) ?
1329 CPLSPrintf(": %s", CPLGetLastErrorMsg()) : "");
1330 return nullptr;
1331 }
1332
1333 nBlockReads++;
1334 if( static_cast<GIntBig>(nBlockReads) ==
1335 static_cast<GIntBig>(nBlocksPerRow) * nBlocksPerColumn + 1
1336 && nBand == 1 && poDS != nullptr )
1337 {
1338 CPLDebug( "GDAL", "Potential thrashing on band %d of %s.",
1339 nBand, poDS->GetDescription() );
1340 }
1341 }
1342 }
1343
1344 return poBlock;
1345 }
1346
1347 /************************************************************************/
1348 /* Fill() */
1349 /************************************************************************/
1350
1351 /**
1352 * \brief Fill this band with a constant value.
1353 *
1354 * GDAL makes no guarantees
1355 * about what values pixels in newly created files are set to, so this
1356 * method can be used to clear a band to a specified "default" value.
1357 * The fill value is passed in as a double but this will be converted
1358 * to the underlying type before writing to the file. An optional
1359 * second argument allows the imaginary component of a complex
1360 * constant value to be specified.
1361 *
1362 * This method is the same as the C function GDALFillRaster().
1363 *
1364 * @param dfRealValue Real component of fill value
1365 * @param dfImaginaryValue Imaginary component of fill value, defaults to zero
GetMetadata(const char * pszDomain)1366 *
1367 * @return CE_Failure if the write fails, otherwise CE_None
1368 */
1369 CPLErr GDALRasterBand::Fill( double dfRealValue, double dfImaginaryValue ) {
1370
1371 // General approach is to construct a source block of the file's
1372 // native type containing the appropriate value and then copy this
1373 // to each block in the image via the RasterBlock cache. Using
1374 // the cache means we avoid file I/O if it is not necessary, at the
1375 // expense of some extra memcpy's (since we write to the
1376 // RasterBlock cache, which is then at some point written to the
1377 // underlying file, rather than simply directly to the underlying
1378 // file.)
1379
1380 // Check we can write to the file.
1381 if( eAccess == GA_ReadOnly ) {
1382 ReportError( CE_Failure, CPLE_NoWriteAccess,
1383 "Attempt to write to read only dataset in "
1384 "GDALRasterBand::Fill()." );
1385 return CE_Failure;
1386 }
1387
1388 // Make sure block parameters are set.
1389 if( !InitBlockInfo() )
1390 return CE_Failure;
1391
1392 // Allocate the source block.
1393 auto blockSize = static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize;
1394 int elementSize = GDALGetDataTypeSizeBytes(eDataType);
1395 auto blockByteSize = blockSize * elementSize;
1396 unsigned char* srcBlock =
1397 static_cast<unsigned char*>( VSIMalloc(blockByteSize) );
1398 if (srcBlock == nullptr) {
1399 ReportError( CE_Failure, CPLE_OutOfMemory,
1400 "GDALRasterBand::Fill(): Out of memory "
1401 "allocating " CPL_FRMT_GUIB " bytes.\n",
1402 static_cast<GUIntBig>(blockByteSize) );
1403 return CE_Failure;
1404 }
1405
1406 // Initialize the source block.
1407 double complexSrc[2] = { dfRealValue, dfImaginaryValue };
1408 GDALCopyWords64(complexSrc, GDT_CFloat64, 0,
1409 srcBlock, eDataType, elementSize, blockSize);
1410
1411 const bool bCallLeaveReadWrite = CPL_TO_BOOL(EnterReadWrite(GF_Write));
1412
1413 // Write block to block cache
1414 for (int j = 0; j < nBlocksPerColumn; ++j) {
1415 for (int i = 0; i < nBlocksPerRow; ++i) {
1416 GDALRasterBlock* destBlock = GetLockedBlockRef(i, j, TRUE);
1417 if (destBlock == nullptr)
1418 {
1419 ReportError( CE_Failure, CPLE_OutOfMemory,
1420 "GDALRasterBand::Fill(): Error "
1421 "while retrieving cache block.");
1422 VSIFree(srcBlock);
1423 return CE_Failure;
1424 }
1425 memcpy(destBlock->GetDataRef(), srcBlock, blockByteSize);
1426 destBlock->MarkDirty();
1427 destBlock->DropLock();
1428 }
1429 }
1430
1431 if( bCallLeaveReadWrite ) LeaveReadWrite();
1432
1433 // Free up the source block
1434 VSIFree(srcBlock);
1435
1436 return CE_None;
1437 }
1438
1439 /************************************************************************/
1440 /* GDALFillRaster() */
1441 /************************************************************************/
1442
1443 /**
1444 * \brief Fill this band with a constant value.
1445 *
1446 * @see GDALRasterBand::Fill()
1447 */
1448 CPLErr CPL_STDCALL GDALFillRaster(
1449 GDALRasterBandH hBand, double dfRealValue, double dfImaginaryValue )
1450 {
1451 VALIDATE_POINTER1( hBand, "GDALFillRaster", CE_Failure );
1452
1453 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1454 return poBand->Fill(dfRealValue, dfImaginaryValue);
1455 }
GetLayerCount()1456
1457 /************************************************************************/
1458 /* GetAccess() */
1459 /************************************************************************/
1460
1461 /**
1462 * \brief Find out if we have update permission for this band.
1463 *
1464 * This method is the same as the C function GDALGetRasterAccess().
1465 *
1466 * @return Either GA_Update or GA_ReadOnly.
1467 */
1468
1469 GDALAccess GDALRasterBand::GetAccess()
1470
1471 {
1472 return eAccess;
1473 }
1474
1475 /************************************************************************/
1476 /* GDALGetRasterAccess() */
1477 /************************************************************************/
1478
1479 /**
1480 * \brief Find out if we have update permission for this band.
1481 *
1482 * @see GDALRasterBand::GetAccess()
1483 */
1484
1485 GDALAccess CPL_STDCALL GDALGetRasterAccess( GDALRasterBandH hBand )
1486
1487 {
1488 VALIDATE_POINTER1( hBand, "GDALGetRasterAccess", GA_ReadOnly );
1489
1490 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1491 return poBand->GetAccess();
1492 }
1493
1494 /************************************************************************/
1495 /* GetCategoryNames() */
1496 /************************************************************************/
1497
1498 /**
1499 * \brief Fetch the list of category names for this raster.
1500 *
1501 * The return list is a "StringList" in the sense of the CPL functions.
1502 * That is a NULL terminated array of strings. Raster values without
1503 * associated names will have an empty string in the returned list. The
1504 * first entry in the list is for raster values of zero, and so on.
1505 *
1506 * The returned stringlist should not be altered or freed by the application.
1507 * It may change on the next GDAL call, so please copy it if it is needed
1508 * for any period of time.
1509 *
1510 * This method is the same as the C function GDALGetRasterCategoryNames().
1511 *
1512 * @return list of names, or NULL if none.
1513 */
GetMetadata(const char * pszDomain)1514
1515 char **GDALRasterBand::GetCategoryNames()
1516
1517 {
1518 return nullptr;
1519 }
1520
1521 /************************************************************************/
1522 /* GDALGetRasterCategoryNames() */
1523 /************************************************************************/
1524
1525 /**
1526 * \brief Fetch the list of category names for this raster.
1527 *
1528 * @see GDALRasterBand::GetCategoryNames()
1529 */
1530
1531 char ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH hBand )
1532
1533 {
1534 VALIDATE_POINTER1( hBand, "GDALGetRasterCategoryNames", nullptr );
1535
1536 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1537 return poBand->GetCategoryNames();
1538 }
1539
1540 /************************************************************************/
1541 /* SetCategoryNames() */
1542 /************************************************************************/
1543
1544 /**
1545 * \fn GDALRasterBand::SetCategoryNames(char**)
1546 * \brief Set the category names for this band.
1547 *
1548 * See the GetCategoryNames() method for more on the interpretation of
1549 * category names.
1550 *
1551 * This method is the same as the C function GDALSetRasterCategoryNames().
1552 *
1553 * @param papszNames the NULL terminated StringList of category names. May
LoadPlugin()1554 * be NULL to just clear the existing list.
1555 *
1556 * @return CE_None on success of CE_Failure on failure. If unsupported
1557 * by the driver CE_Failure is returned, but no error message is reported.
1558 */
1559
1560 /**/
1561 /**/
1562
1563 CPLErr GDALRasterBand::SetCategoryNames( char ** /*papszNames*/ )
1564 {
1565 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1566 ReportError( CE_Failure, CPLE_NotSupported,
1567 "SetCategoryNames() not supported for this dataset." );
1568
1569 return CE_Failure;
1570 }
1571
1572 /************************************************************************/
1573 /* GDALSetCategoryNames() */
1574 /************************************************************************/
1575
1576 /**
1577 * \brief Set the category names for this band.
1578 *
1579 * @see GDALRasterBand::SetCategoryNames()
1580 */
1581
1582 CPLErr CPL_STDCALL
1583 GDALSetRasterCategoryNames( GDALRasterBandH hBand, CSLConstList papszNames )
1584
1585 {
1586 VALIDATE_POINTER1( hBand, "GDALSetRasterCategoryNames", CE_Failure );
1587
1588 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1589 return poBand->SetCategoryNames( const_cast<char**>(papszNames) );
1590 }
1591
1592 /************************************************************************/
1593 /* GetNoDataValue() */
1594 /************************************************************************/
1595
1596 /**
1597 * \brief Fetch the no data value for this band.
1598 *
1599 * If there is no out of data value, an out of range value will generally
1600 * be returned. The no data value for a band is generally a special marker
1601 * value used to mark pixels that are not valid data. Such pixels should
1602 * generally not be displayed, nor contribute to analysis operations.
1603 *
1604 * The no data value returned is 'raw', meaning that it has no offset and
1605 * scale applied.
1606 *
1607 * This method is the same as the C function GDALGetRasterNoDataValue().
1608 *
1609 * @param pbSuccess pointer to a boolean to use to indicate if a value
1610 * is actually associated with this layer. May be NULL (default).
1611 *
1612 * @return the nodata value for this band.
1613 */
1614
1615 double GDALRasterBand::GetNoDataValue( int *pbSuccess )
1616
1617 {
1618 if( pbSuccess != nullptr )
1619 *pbSuccess = FALSE;
1620
1621 return -1e10;
1622 }
BuildIdentifyOpenArgs(GDALOpenInfo * poOpenInfo,PyObject * & pyArgs,PyObject * & pyKwargs)1623
1624 /************************************************************************/
1625 /* GDALGetRasterNoDataValue() */
1626 /************************************************************************/
1627
1628 /**
1629 * \brief Fetch the no data value for this band.
1630 *
1631 * @see GDALRasterBand::GetNoDataValue()
1632 */
1633
1634 double CPL_STDCALL
1635 GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
1636
1637 {
1638 VALIDATE_POINTER1( hBand, "GDALGetRasterNoDataValue", 0 );
1639
1640 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1641 return poBand->GetNoDataValue( pbSuccess );
1642 }
1643
1644 /************************************************************************/
1645 /* SetNoDataValue() */
1646 /************************************************************************/
1647
1648 /**
1649 * \fn GDALRasterBand::SetNoDataValue(double)
1650 * \brief Set the no data value for this band.
1651 *
1652 * Depending on drivers, changing the no data value may or may not have an
1653 * effect on the pixel values of a raster that has just been created. It is
1654 * thus advised to explicitly called Fill() if the intent is to initialize
1655 * the raster to the nodata value.
1656 * In ay case, changing an existing no data value, when one already exists and
Identify(GDALOpenInfo * poOpenInfo)1657 * the dataset exists or has been initialized, has no effect on the pixel whose
1658 * value matched the previous nodata value.
1659 *
1660 * To clear the nodata value, use DeleteNoDataValue().
1661 *
1662 * This method is the same as the C function GDALSetRasterNoDataValue().
1663 *
1664 * @param dfNoData the value to set.
1665 *
1666 * @return CE_None on success, or CE_Failure on failure. If unsupported
1667 * by the driver, CE_Failure is returned by no error message will have
1668 * been emitted.
1669 */
1670
1671 /**/
1672 /**/
1673
1674 CPLErr GDALRasterBand::SetNoDataValue( double /*dfNoData*/ )
1675
1676 {
1677 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1678 ReportError( CE_Failure, CPLE_NotSupported,
1679 "SetNoDataValue() not supported for this dataset." );
1680
1681 return CE_Failure;
1682 }
1683
1684 /************************************************************************/
1685 /* GDALSetRasterNoDataValue() */
1686 /************************************************************************/
1687
1688 /**
1689 * \brief Set the no data value for this band.
1690 *
1691 * Depending on drivers, changing the no data value may or may not have an
1692 * effect on the pixel values of a raster that has just been created. It is
1693 * thus advised to explicitly called Fill() if the intent is to initialize
1694 * the raster to the nodata value.
1695 * In ay case, changing an existing no data value, when one already exists and
1696 * the dataset exists or has been initialized, has no effect on the pixel whose
1697 * value matched the previous nodata value.
1698 *
1699 * @see GDALRasterBand::SetNoDataValue()
1700 */
1701
1702 CPLErr CPL_STDCALL
1703 GDALSetRasterNoDataValue( GDALRasterBandH hBand, double dfValue )
IdentifyEx(GDALDriver * poDrv,GDALOpenInfo * poOpenInfo)1704
1705 {
1706 VALIDATE_POINTER1( hBand, "GDALSetRasterNoDataValue", CE_Failure );
1707
1708 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1709 return poBand->SetNoDataValue( dfValue );
1710 }
1711
1712 /************************************************************************/
Open(GDALOpenInfo * poOpenInfo)1713 /* DeleteNoDataValue() */
1714 /************************************************************************/
1715
1716 /**
1717 * \brief Remove the no data value for this band.
1718 *
1719 * This method is the same as the C function GDALDeleteRasterNoDataValue().
1720 *
1721 * @return CE_None on success, or CE_Failure on failure. If unsupported
1722 * by the driver, CE_Failure is returned by no error message will have
1723 * been emitted.
1724 *
1725 * @since GDAL 2.1
1726 */
1727
1728 CPLErr GDALRasterBand::DeleteNoDataValue()
1729
1730 {
1731 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1732 ReportError( CE_Failure, CPLE_NotSupported,
1733 "DeleteNoDataValue() not supported for this dataset." );
1734
1735 return CE_Failure;
1736 }
1737
1738 /************************************************************************/
1739 /* GDALDeleteRasterNoDataValue() */
1740 /************************************************************************/
1741
1742 /**
1743 * \brief Remove the no data value for this band.
1744 *
1745 * @see GDALRasterBand::DeleteNoDataValue()
1746 *
1747 * @since GDAL 2.1
1748 */
1749
1750 CPLErr CPL_STDCALL
1751 GDALDeleteRasterNoDataValue( GDALRasterBandH hBand )
1752
1753 {
1754 VALIDATE_POINTER1( hBand, "GDALDeleteRasterNoDataValue", CE_Failure );
1755
1756 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
OpenEx(GDALDriver * poDrv,GDALOpenInfo * poOpenInfo)1757 return poBand->DeleteNoDataValue();
1758 }
1759
1760 /************************************************************************/
1761 /* GetMaximum() */
1762 /************************************************************************/
1763
1764 /**
1765 * \brief Fetch the maximum value for this band.
1766 *
PythonPluginDriver(const char * pszFilename,const char * pszPluginName,char ** papszMD)1767 * For file formats that don't know this intrinsically, the maximum supported
1768 * value for the data type will generally be returned.
1769 *
1770 * This method is the same as the C function GDALGetRasterMaximum().
1771 *
1772 * @param pbSuccess pointer to a boolean to use to indicate if the
1773 * returned value is a tight maximum or not. May be NULL (default).
1774 *
1775 * @return the maximum raster value (excluding no data pixels)
1776 */
1777
1778 double GDALRasterBand::GetMaximum( int *pbSuccess )
1779
1780 {
1781 const char *pszValue = nullptr;
1782
1783 if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != nullptr )
1784 {
1785 if( pbSuccess != nullptr )
1786 *pbSuccess = TRUE;
1787
1788 return CPLAtofM(pszValue);
1789 }
1790
1791 if( pbSuccess != nullptr )
1792 *pbSuccess = FALSE;
1793
1794 switch( eDataType )
1795 {
1796 case GDT_Byte:
1797 {
1798 const char* pszPixelType =
1799 GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
1800 if (pszPixelType != nullptr && EQUAL(pszPixelType, "SIGNEDBYTE"))
1801 return 127;
1802
1803 return 255;
1804 }
1805
1806 case GDT_UInt16:
1807 return 65535;
1808
1809 case GDT_Int16:
1810 case GDT_CInt16:
1811 return 32767;
1812
1813 case GDT_Int32:
1814 case GDT_CInt32:
1815 return 2147483647.0;
1816
1817 case GDT_UInt32:
1818 return 4294967295.0;
1819
1820 case GDT_Float32:
1821 case GDT_CFloat32:
1822 return 4294967295.0; // Not actually accurate.
1823
1824 case GDT_Float64:
1825 case GDT_CFloat64:
1826 return 4294967295.0; // Not actually accurate.
1827
1828 default:
1829 return 4294967295.0; // Not actually accurate.
1830 }
1831 }
1832
1833 /************************************************************************/
1834 /* GDALGetRasterMaximum() */
1835 /************************************************************************/
1836
1837 /**
1838 * \brief Fetch the maximum value for this band.
1839 *
1840 * @see GDALRasterBand::GetMaximum()
1841 */
1842
1843 double CPL_STDCALL
1844 GDALGetRasterMaximum( GDALRasterBandH hBand, int *pbSuccess )
1845
1846 {
1847 VALIDATE_POINTER1( hBand, "GDALGetRasterMaximum", 0 );
1848
1849 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1850 return poBand->GetMaximum( pbSuccess );
1851 }
1852
1853 /************************************************************************/
1854 /* GetMinimum() */
1855 /************************************************************************/
1856
1857 /**
1858 * \brief Fetch the minimum value for this band.
1859 *
1860 * For file formats that don't know this intrinsically, the minimum supported
1861 * value for the data type will generally be returned.
1862 *
1863 * This method is the same as the C function GDALGetRasterMinimum().
1864 *
1865 * @param pbSuccess pointer to a boolean to use to indicate if the
1866 * returned value is a tight minimum or not. May be NULL (default).
1867 *
1868 * @return the minimum raster value (excluding no data pixels)
1869 */
1870
1871 double GDALRasterBand::GetMinimum( int *pbSuccess )
1872
1873 {
1874 const char *pszValue = nullptr;
1875
1876 if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != nullptr )
1877 {
1878 if( pbSuccess != nullptr )
1879 *pbSuccess = TRUE;
1880
1881 return CPLAtofM(pszValue);
1882 }
1883
1884 if( pbSuccess != nullptr )
1885 *pbSuccess = FALSE;
1886
1887 switch( eDataType )
1888 {
1889 case GDT_Byte:
1890 {
1891 const char* pszPixelType =
1892 GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
1893 if (pszPixelType != nullptr && EQUAL(pszPixelType, "SIGNEDBYTE"))
1894 return -128;
1895
1896 return 0;
1897 }
1898
1899 case GDT_UInt16:
AutoLoadPythonDrivers()1900 return 0;
1901
1902 case GDT_Int16:
1903 return -32768;
1904
1905 case GDT_Int32:
1906 return -2147483648.0;
1907
1908 case GDT_UInt32:
1909 return 0;
1910
1911 case GDT_Float32:
1912 return -4294967295.0; // Not actually accurate.
1913
1914 case GDT_Float64:
1915 return -4294967295.0; // Not actually accurate.
1916
1917 default:
1918 return -4294967295.0; // Not actually accurate.
1919 }
1920 }
1921
1922 /************************************************************************/
1923 /* GDALGetRasterMinimum() */
1924 /************************************************************************/
1925
1926 /**
1927 * \brief Fetch the minimum value for this band.
1928 *
1929 * @see GDALRasterBand::GetMinimum()
1930 */
1931
1932 double CPL_STDCALL
1933 GDALGetRasterMinimum( GDALRasterBandH hBand, int *pbSuccess )
1934
1935 {
1936 VALIDATE_POINTER1( hBand, "GDALGetRasterMinimum", 0 );
1937
1938 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1939 return poBand->GetMinimum( pbSuccess );
1940 }
1941
1942 /************************************************************************/
1943 /* GetColorInterpretation() */
1944 /************************************************************************/
1945
1946 /**
1947 * \brief How should this band be interpreted as color?
1948 *
1949 * GCI_Undefined is returned when the format doesn't know anything
1950 * about the color interpretation.
1951 *
1952 * This method is the same as the C function
1953 * GDALGetRasterColorInterpretation().
1954 *
1955 * @return color interpretation value for band.
1956 */
CleanupPythonDrivers()1957
1958 GDALColorInterp GDALRasterBand::GetColorInterpretation()
1959
1960 {
1961 return GCI_Undefined;
1962 }
1963
1964 /************************************************************************/
1965 /* GDALGetRasterColorInterpretation() */
1966 /************************************************************************/
1967
1968 /**
1969 * \brief How should this band be interpreted as color?
1970 *
1971 * @see GDALRasterBand::GetColorInterpretation()
1972 */
1973
1974 GDALColorInterp CPL_STDCALL
1975 GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
1976
1977 {
1978 VALIDATE_POINTER1( hBand, "GDALGetRasterColorInterpretation",
1979 GCI_Undefined );
1980
1981 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
1982 return poBand->GetColorInterpretation();
1983 }
1984
1985 /************************************************************************/
1986 /* SetColorInterpretation() */
1987 /************************************************************************/
1988
1989 /**
1990 * \fn GDALRasterBand::SetColorInterpretation(GDALColorInterp)
1991 * \brief Set color interpretation of a band.
1992 *
1993 * This method is the same as the C function GDALSetRasterColorInterpretation().
1994 *
1995 * @param eColorInterp the new color interpretation to apply to this band.
1996 *
1997 * @return CE_None on success or CE_Failure if method is unsupported by format.
1998 */
1999
2000 /**/
2001 /**/
2002
2003 CPLErr GDALRasterBand::SetColorInterpretation(
2004 GDALColorInterp /*eColorInterp*/ )
2005
2006 {
2007 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
2008 ReportError( CE_Failure, CPLE_NotSupported,
2009 "SetColorInterpretation() not supported for this dataset." );
2010 return CE_Failure;
2011 }
2012
2013 /************************************************************************/
2014 /* GDALSetRasterColorInterpretation() */
2015 /************************************************************************/
2016
2017 /**
2018 * \brief Set color interpretation of a band.
2019 *
2020 * @see GDALRasterBand::SetColorInterpretation()
2021 */
2022
2023 CPLErr CPL_STDCALL
2024 GDALSetRasterColorInterpretation( GDALRasterBandH hBand,
2025 GDALColorInterp eColorInterp )
2026
2027 {
2028 VALIDATE_POINTER1( hBand, "GDALSetRasterColorInterpretation", CE_Failure );
2029
2030 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2031 return poBand->SetColorInterpretation(eColorInterp);
2032 }
2033
2034 /************************************************************************/
2035 /* GetColorTable() */
2036 /************************************************************************/
2037
2038 /**
2039 * \brief Fetch the color table associated with band.
2040 *
2041 * If there is no associated color table, the return result is NULL. The
2042 * returned color table remains owned by the GDALRasterBand, and can't
2043 * be depended on for long, nor should it ever be modified by the caller.
2044 *
2045 * This method is the same as the C function GDALGetRasterColorTable().
2046 *
2047 * @return internal color table, or NULL.
2048 */
2049
2050 GDALColorTable *GDALRasterBand::GetColorTable()
2051
2052 {
2053 return nullptr;
2054 }
2055
2056 /************************************************************************/
2057 /* GDALGetRasterColorTable() */
2058 /************************************************************************/
2059
2060 /**
2061 * \brief Fetch the color table associated with band.
2062 *
2063 * @see GDALRasterBand::GetColorTable()
2064 */
2065
2066 GDALColorTableH CPL_STDCALL GDALGetRasterColorTable( GDALRasterBandH hBand )
2067
2068 {
2069 VALIDATE_POINTER1( hBand, "GDALGetRasterColorTable", nullptr );
2070
2071 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2072 return GDALColorTable::ToHandle(poBand->GetColorTable());
2073 }
2074
2075 /************************************************************************/
2076 /* SetColorTable() */
2077 /************************************************************************/
2078
2079 /**
2080 * \fn GDALRasterBand::SetColorTable(GDALColorTable*)
2081 * \brief Set the raster color table.
2082 *
2083 * The driver will make a copy of all desired data in the colortable. It
2084 * remains owned by the caller after the call.
2085 *
2086 * This method is the same as the C function GDALSetRasterColorTable().
2087 *
2088 * @param poCT the color table to apply. This may be NULL to clear the color
2089 * table (where supported).
2090 *
2091 * @return CE_None on success, or CE_Failure on failure. If the action is
2092 * unsupported by the driver, a value of CE_Failure is returned, but no
2093 * error is issued.
2094 */
2095
2096 /**/
2097 /**/
2098
2099 CPLErr GDALRasterBand::SetColorTable( GDALColorTable * /*poCT*/ )
2100
2101 {
2102 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
2103 ReportError( CE_Failure, CPLE_NotSupported,
2104 "SetColorTable() not supported for this dataset." );
2105 return CE_Failure;
2106 }
2107
2108 /************************************************************************/
2109 /* GDALSetRasterColorTable() */
2110 /************************************************************************/
2111
2112 /**
2113 * \brief Set the raster color table.
2114 *
2115 * @see GDALRasterBand::SetColorTable()
2116 */
2117
2118 CPLErr CPL_STDCALL
2119 GDALSetRasterColorTable( GDALRasterBandH hBand, GDALColorTableH hCT )
2120
2121 {
2122 VALIDATE_POINTER1( hBand, "GDALSetRasterColorTable", CE_Failure );
2123
2124 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2125 return poBand->SetColorTable( GDALColorTable::FromHandle(hCT) );
2126 }
2127
2128 /************************************************************************/
2129 /* HasArbitraryOverviews() */
2130 /************************************************************************/
2131
2132 /**
2133 * \brief Check for arbitrary overviews.
2134 *
2135 * This returns TRUE if the underlying datastore can compute arbitrary
2136 * overviews efficiently, such as is the case with OGDI over a network.
2137 * Datastores with arbitrary overviews don't generally have any fixed
2138 * overviews, but the RasterIO() method can be used in downsampling mode
2139 * to get overview data efficiently.
2140 *
2141 * This method is the same as the C function GDALHasArbitraryOverviews(),
2142 *
2143 * @return TRUE if arbitrary overviews available (efficiently), otherwise
2144 * FALSE.
2145 */
2146
2147 int GDALRasterBand::HasArbitraryOverviews()
2148
2149 {
2150 return FALSE;
2151 }
2152
2153 /************************************************************************/
2154 /* GDALHasArbitraryOverviews() */
2155 /************************************************************************/
2156
2157 /**
2158 * \brief Check for arbitrary overviews.
2159 *
2160 * @see GDALRasterBand::HasArbitraryOverviews()
2161 */
2162
2163 int CPL_STDCALL GDALHasArbitraryOverviews( GDALRasterBandH hBand )
2164
2165 {
2166 VALIDATE_POINTER1( hBand, "GDALHasArbitraryOverviews", 0 );
2167
2168 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2169 return poBand->HasArbitraryOverviews();
2170 }
2171
2172 /************************************************************************/
2173 /* GetOverviewCount() */
2174 /************************************************************************/
2175
2176 /**
2177 * \brief Return the number of overview layers available.
2178 *
2179 * This method is the same as the C function GDALGetOverviewCount().
2180 *
2181 * @return overview count, zero if none.
2182 */
2183
2184 int GDALRasterBand::GetOverviewCount()
2185
2186 {
2187 if( poDS != nullptr && poDS->oOvManager.IsInitialized() && poDS->AreOverviewsEnabled() )
2188 return poDS->oOvManager.GetOverviewCount( nBand );
2189
2190 return 0;
2191 }
2192
2193 /************************************************************************/
2194 /* GDALGetOverviewCount() */
2195 /************************************************************************/
2196
2197 /**
2198 * \brief Return the number of overview layers available.
2199 *
2200 * @see GDALRasterBand::GetOverviewCount()
2201 */
2202
2203 int CPL_STDCALL GDALGetOverviewCount( GDALRasterBandH hBand )
2204
2205 {
2206 VALIDATE_POINTER1( hBand, "GDALGetOverviewCount", 0 );
2207
2208 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2209 return poBand->GetOverviewCount();
2210 }
2211
2212 /************************************************************************/
2213 /* GetOverview() */
2214 /************************************************************************/
2215
2216 /**
2217 * \brief Fetch overview raster band object.
2218 *
2219 * This method is the same as the C function GDALGetOverview().
2220 *
2221 * @param i overview index between 0 and GetOverviewCount()-1.
2222 *
2223 * @return overview GDALRasterBand.
2224 */
2225
2226 GDALRasterBand * GDALRasterBand::GetOverview( int i )
2227
2228 {
2229 if( poDS != nullptr && poDS->oOvManager.IsInitialized() && poDS->AreOverviewsEnabled() )
2230 return poDS->oOvManager.GetOverview( nBand, i );
2231
2232 return nullptr;
2233 }
2234
2235 /************************************************************************/
2236 /* GDALGetOverview() */
2237 /************************************************************************/
2238
2239 /**
2240 * \brief Fetch overview raster band object.
2241 *
2242 * @see GDALRasterBand::GetOverview()
2243 */
2244
2245 GDALRasterBandH CPL_STDCALL GDALGetOverview( GDALRasterBandH hBand, int i )
2246
2247 {
2248 VALIDATE_POINTER1( hBand, "GDALGetOverview", nullptr );
2249
2250 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2251 return GDALRasterBand::ToHandle(poBand->GetOverview(i));
2252 }
2253
2254 /************************************************************************/
2255 /* GetRasterSampleOverview() */
2256 /************************************************************************/
2257
2258 /**
2259 * \brief Fetch best sampling overview.
2260 *
2261 * Returns the most reduced overview of the given band that still satisfies
2262 * the desired number of samples. This function can be used with zero
2263 * as the number of desired samples to fetch the most reduced overview.
2264 * The same band as was passed in will be returned if it has not overviews,
2265 * or if none of the overviews have enough samples.
2266 *
2267 * This method is the same as the C functions GDALGetRasterSampleOverview()
2268 * and GDALGetRasterSampleOverviewEx().
2269 *
2270 * @param nDesiredSamples the returned band will have at least this many
2271 * pixels.
2272 *
2273 * @return optimal overview or the band itself.
2274 */
2275
2276 GDALRasterBand *GDALRasterBand::GetRasterSampleOverview(
2277 GUIntBig nDesiredSamples )
2278
2279 {
2280 GDALRasterBand *poBestBand = this;
2281
2282 double dfBestSamples = GetXSize() * static_cast<double>(GetYSize());
2283
2284 for( int iOverview = 0; iOverview < GetOverviewCount(); iOverview++ )
2285 {
2286 GDALRasterBand *poOBand = GetOverview( iOverview );
2287
2288 if (poOBand == nullptr)
2289 continue;
2290
2291 const double dfOSamples =
2292 poOBand->GetXSize() * static_cast<double>(poOBand->GetYSize());
2293
2294 if( dfOSamples < dfBestSamples && dfOSamples > nDesiredSamples )
2295 {
2296 dfBestSamples = dfOSamples;
2297 poBestBand = poOBand;
2298 }
2299 }
2300
2301 return poBestBand;
2302 }
2303
2304 /************************************************************************/
2305 /* GDALGetRasterSampleOverview() */
2306 /************************************************************************/
2307
2308 /**
2309 * \brief Fetch best sampling overview.
2310 *
2311 * Use GDALGetRasterSampleOverviewEx() to be able to specify more than 2
2312 * billion samples.
2313 *
2314 * @see GDALRasterBand::GetRasterSampleOverview()
2315 * @see GDALGetRasterSampleOverviewEx()
2316 */
2317
2318 GDALRasterBandH CPL_STDCALL
2319 GDALGetRasterSampleOverview( GDALRasterBandH hBand, int nDesiredSamples )
2320
2321 {
2322 VALIDATE_POINTER1( hBand, "GDALGetRasterSampleOverview", nullptr );
2323
2324 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2325 return GDALRasterBand::ToHandle(
2326 poBand->GetRasterSampleOverview(
2327 nDesiredSamples < 0 ? 0 : static_cast<GUIntBig>(nDesiredSamples) ));
2328 }
2329
2330 /************************************************************************/
2331 /* GDALGetRasterSampleOverviewEx() */
2332 /************************************************************************/
2333
2334 /**
2335 * \brief Fetch best sampling overview.
2336 *
2337 * @see GDALRasterBand::GetRasterSampleOverview()
2338 * @since GDAL 2.0
2339 */
2340
2341 GDALRasterBandH CPL_STDCALL
2342 GDALGetRasterSampleOverviewEx( GDALRasterBandH hBand, GUIntBig nDesiredSamples )
2343
2344 {
2345 VALIDATE_POINTER1( hBand, "GDALGetRasterSampleOverviewEx", nullptr );
2346
2347 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2348 return GDALRasterBand::ToHandle(
2349 poBand->GetRasterSampleOverview( nDesiredSamples ));
2350 }
2351
2352 /************************************************************************/
2353 /* BuildOverviews() */
2354 /************************************************************************/
2355
2356 /**
2357 * \fn GDALRasterBand::BuildOverviews(const char*, int, int*, GDALProgressFunc, void*)
2358 * \brief Build raster overview(s)
2359 *
2360 * If the operation is unsupported for the indicated dataset, then
2361 * CE_Failure is returned, and CPLGetLastErrorNo() will return
2362 * CPLE_NotSupported.
2363 *
2364 * WARNING: It is not possible to build overviews for a single band in
2365 * TIFF format, and thus this method does not work for TIFF format, or any
2366 * formats that use the default overview building in TIFF format. Instead
2367 * it is necessary to build overviews on the dataset as a whole using
2368 * GDALDataset::BuildOverviews(). That makes this method pretty useless
2369 * from a practical point of view.
2370 *
2371 * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
2372 * "AVERAGE_MAGPHASE" "RMS" or "NONE" controlling the downsampling method applied.
2373 * @param nOverviews number of overviews to build.
2374 * @param panOverviewList the list of overview decimation factors to build.
2375 * @param pfnProgress a function to call to report progress, or NULL.
2376 * @param pProgressData application data to pass to the progress function.
2377 *
2378 * @return CE_None on success or CE_Failure if the operation doesn't work.
2379 */
2380
2381 /**/
2382 /**/
2383
2384 CPLErr GDALRasterBand::BuildOverviews( const char* /*pszResampling*/,
2385 int /*nOverviews*/,
2386 int* /*panOverviewList*/,
2387 GDALProgressFunc /*pfnProgress*/,
2388 void * /*pProgressData*/ )
2389
2390 {
2391 ReportError( CE_Failure, CPLE_NotSupported,
2392 "BuildOverviews() not supported for this dataset." );
2393
2394 return( CE_Failure );
2395 }
2396
2397 /************************************************************************/
2398 /* GetOffset() */
2399 /************************************************************************/
2400
2401 /**
2402 * \brief Fetch the raster value offset.
2403 *
2404 * This value (in combination with the GetScale() value) can be used to
2405 * transform raw pixel values into the units returned by GetUnitType().
2406 * For example this might be used to store elevations in GUInt16 bands
2407 * with a precision of 0.1, and starting from -100.
2408 *
2409 * Units value = (raw value * scale) + offset
2410 *
2411 * Note that applying scale and offset is of the responsibility of the user,
2412 * and is not done by methods such as RasterIO() or ReadBlock().
2413 *
2414 * For file formats that don't know this intrinsically a value of zero
2415 * is returned.
2416 *
2417 * This method is the same as the C function GDALGetRasterOffset().
2418 *
2419 * @param pbSuccess pointer to a boolean to use to indicate if the
2420 * returned value is meaningful or not. May be NULL (default).
2421 *
2422 * @return the raster offset.
2423 */
2424
2425 double GDALRasterBand::GetOffset( int *pbSuccess )
2426
2427 {
2428 if( pbSuccess != nullptr )
2429 *pbSuccess = FALSE;
2430
2431 return 0.0;
2432 }
2433
2434 /************************************************************************/
2435 /* GDALGetRasterOffset() */
2436 /************************************************************************/
2437
2438 /**
2439 * \brief Fetch the raster value offset.
2440 *
2441 * @see GDALRasterBand::GetOffset()
2442 */
2443
2444 double CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH hBand, int *pbSuccess )
2445
2446 {
2447 VALIDATE_POINTER1( hBand, "GDALGetRasterOffset", 0 );
2448
2449 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2450 return poBand->GetOffset( pbSuccess );
2451 }
2452
2453 /************************************************************************/
2454 /* SetOffset() */
2455 /************************************************************************/
2456
2457 /**
2458 * \fn GDALRasterBand::SetOffset(double)
2459 * \brief Set scaling offset.
2460 *
2461 * Very few formats implement this method. When not implemented it will
2462 * issue a CPLE_NotSupported error and return CE_Failure.
2463 *
2464 * This method is the same as the C function GDALSetRasterOffset().
2465 *
2466 * @param dfNewOffset the new offset.
2467 *
2468 * @return CE_None or success or CE_Failure on failure.
2469 */
2470
2471 /**/
2472 /**/
2473
2474 CPLErr GDALRasterBand::SetOffset( double /*dfNewOffset*/ )
2475 {
2476 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
2477 ReportError( CE_Failure, CPLE_NotSupported,
2478 "SetOffset() not supported on this raster band." );
2479
2480 return CE_Failure;
2481 }
2482
2483 /************************************************************************/
2484 /* GDALSetRasterOffset() */
2485 /************************************************************************/
2486
2487 /**
2488 * \brief Set scaling offset.
2489 *
2490 * @see GDALRasterBand::SetOffset()
2491 */
2492
2493 CPLErr CPL_STDCALL
2494 GDALSetRasterOffset( GDALRasterBandH hBand, double dfNewOffset )
2495
2496 {
2497 VALIDATE_POINTER1( hBand, "GDALSetRasterOffset", CE_Failure );
2498
2499 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2500 return poBand->SetOffset( dfNewOffset );
2501 }
2502
2503 /************************************************************************/
2504 /* GetScale() */
2505 /************************************************************************/
2506
2507 /**
2508 * \brief Fetch the raster value scale.
2509 *
2510 * This value (in combination with the GetOffset() value) can be used to
2511 * transform raw pixel values into the units returned by GetUnitType().
2512 * For example this might be used to store elevations in GUInt16 bands
2513 * with a precision of 0.1, and starting from -100.
2514 *
2515 * Units value = (raw value * scale) + offset
2516 *
2517 * Note that applying scale and offset is of the responsibility of the user,
2518 * and is not done by methods such as RasterIO() or ReadBlock().
2519 *
2520 * For file formats that don't know this intrinsically a value of one
2521 * is returned.
2522 *
2523 * This method is the same as the C function GDALGetRasterScale().
2524 *
2525 * @param pbSuccess pointer to a boolean to use to indicate if the
2526 * returned value is meaningful or not. May be NULL (default).
2527 *
2528 * @return the raster scale.
2529 */
2530
2531 double GDALRasterBand::GetScale( int *pbSuccess )
2532
2533 {
2534 if( pbSuccess != nullptr )
2535 *pbSuccess = FALSE;
2536
2537 return 1.0;
2538 }
2539
2540 /************************************************************************/
2541 /* GDALGetRasterScale() */
2542 /************************************************************************/
2543
2544 /**
2545 * \brief Fetch the raster value scale.
2546 *
2547 * @see GDALRasterBand::GetScale()
2548 */
2549
2550 double CPL_STDCALL GDALGetRasterScale( GDALRasterBandH hBand, int *pbSuccess )
2551
2552 {
2553 VALIDATE_POINTER1( hBand, "GDALGetRasterScale", 0 );
2554
2555 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2556 return poBand->GetScale( pbSuccess );
2557 }
2558
2559 /************************************************************************/
2560 /* SetScale() */
2561 /************************************************************************/
2562
2563 /**
2564 * \fn GDALRasterBand::SetScale(double)
2565 * \brief Set scaling ratio.
2566 *
2567 * Very few formats implement this method. When not implemented it will
2568 * issue a CPLE_NotSupported error and return CE_Failure.
2569 *
2570 * This method is the same as the C function GDALSetRasterScale().
2571 *
2572 * @param dfNewScale the new scale.
2573 *
2574 * @return CE_None or success or CE_Failure on failure.
2575 */
2576
2577 /**/
2578 /**/
2579
2580 CPLErr GDALRasterBand::SetScale( double /*dfNewScale*/ )
2581
2582 {
2583 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
2584 ReportError( CE_Failure, CPLE_NotSupported,
2585 "SetScale() not supported on this raster band." );
2586
2587 return CE_Failure;
2588 }
2589
2590 /************************************************************************/
2591 /* GDALSetRasterScale() */
2592 /************************************************************************/
2593
2594 /**
2595 * \brief Set scaling ratio.
2596 *
2597 * @see GDALRasterBand::SetScale()
2598 */
2599
2600 CPLErr CPL_STDCALL
2601 GDALSetRasterScale( GDALRasterBandH hBand, double dfNewOffset )
2602
2603 {
2604 VALIDATE_POINTER1( hBand, "GDALSetRasterScale", CE_Failure );
2605
2606 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2607 return poBand->SetScale( dfNewOffset );
2608 }
2609
2610 /************************************************************************/
2611 /* GetUnitType() */
2612 /************************************************************************/
2613
2614 /**
2615 * \brief Return raster unit type.
2616 *
2617 * Return a name for the units of this raster's values. For instance, it
2618 * might be "m" for an elevation model in meters, or "ft" for feet. If no
2619 * units are available, a value of "" will be returned. The returned string
2620 * should not be modified, nor freed by the calling application.
2621 *
2622 * This method is the same as the C function GDALGetRasterUnitType().
2623 *
2624 * @return unit name string.
2625 */
2626
2627 const char *GDALRasterBand::GetUnitType()
2628
2629 {
2630 return "";
2631 }
2632
2633 /************************************************************************/
2634 /* GDALGetRasterUnitType() */
2635 /************************************************************************/
2636
2637 /**
2638 * \brief Return raster unit type.
2639 *
2640 * @see GDALRasterBand::GetUnitType()
2641 */
2642
2643 const char * CPL_STDCALL GDALGetRasterUnitType( GDALRasterBandH hBand )
2644
2645 {
2646 VALIDATE_POINTER1( hBand, "GDALGetRasterUnitType", nullptr );
2647
2648 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2649 return poBand->GetUnitType();
2650 }
2651
2652 /************************************************************************/
2653 /* SetUnitType() */
2654 /************************************************************************/
2655
2656 /**
2657 * \fn GDALRasterBand::SetUnitType(const char*)
2658 * \brief Set unit type.
2659 *
2660 * Set the unit type for a raster band. Values should be one of
2661 * "" (the default indicating it is unknown), "m" indicating meters,
2662 * or "ft" indicating feet, though other nonstandard values are allowed.
2663 *
2664 * This method is the same as the C function GDALSetRasterUnitType().
2665 *
2666 * @param pszNewValue the new unit type value.
2667 *
2668 * @return CE_None on success or CE_Failure if not successful, or
2669 * unsupported.
2670 */
2671
2672 /**/
2673 /**/
2674
2675 CPLErr GDALRasterBand::SetUnitType( const char * /*pszNewValue*/ )
2676
2677 {
2678 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
2679 ReportError( CE_Failure, CPLE_NotSupported,
2680 "SetUnitType() not supported on this raster band." );
2681 return CE_Failure;
2682 }
2683
2684 /************************************************************************/
2685 /* GDALSetRasterUnitType() */
2686 /************************************************************************/
2687
2688 /**
2689 * \brief Set unit type.
2690 *
2691 * @see GDALRasterBand::SetUnitType()
2692 *
2693 * @since GDAL 1.8.0
2694 */
2695
2696 CPLErr CPL_STDCALL GDALSetRasterUnitType( GDALRasterBandH hBand, const char *pszNewValue )
2697
2698 {
2699 VALIDATE_POINTER1( hBand, "GDALSetRasterUnitType", CE_Failure );
2700
2701 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2702 return poBand->SetUnitType(pszNewValue);
2703 }
2704
2705 /************************************************************************/
2706 /* GetXSize() */
2707 /************************************************************************/
2708
2709 /**
2710 * \brief Fetch XSize of raster.
2711 *
2712 * This method is the same as the C function GDALGetRasterBandXSize().
2713 *
2714 * @return the width in pixels of this band.
2715 */
2716
2717 int GDALRasterBand::GetXSize()
2718
2719 {
2720 return nRasterXSize;
2721 }
2722
2723 /************************************************************************/
2724 /* GDALGetRasterBandXSize() */
2725 /************************************************************************/
2726
2727 /**
2728 * \brief Fetch XSize of raster.
2729 *
2730 * @see GDALRasterBand::GetXSize()
2731 */
2732
2733 int CPL_STDCALL GDALGetRasterBandXSize( GDALRasterBandH hBand )
2734
2735 {
2736 VALIDATE_POINTER1( hBand, "GDALGetRasterBandXSize", 0 );
2737
2738 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2739 return poBand->GetXSize();
2740 }
2741
2742 /************************************************************************/
2743 /* GetYSize() */
2744 /************************************************************************/
2745
2746 /**
2747 * \brief Fetch YSize of raster.
2748 *
2749 * This method is the same as the C function GDALGetRasterBandYSize().
2750 *
2751 * @return the height in pixels of this band.
2752 */
2753
2754 int GDALRasterBand::GetYSize()
2755
2756 {
2757 return nRasterYSize;
2758 }
2759
2760 /************************************************************************/
2761 /* GDALGetRasterBandYSize() */
2762 /************************************************************************/
2763
2764 /**
2765 * \brief Fetch YSize of raster.
2766 *
2767 * @see GDALRasterBand::GetYSize()
2768 */
2769
2770 int CPL_STDCALL GDALGetRasterBandYSize( GDALRasterBandH hBand )
2771
2772 {
2773 VALIDATE_POINTER1( hBand, "GDALGetRasterBandYSize", 0 );
2774
2775 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2776 return poBand->GetYSize();
2777 }
2778
2779 /************************************************************************/
2780 /* GetBand() */
2781 /************************************************************************/
2782
2783 /**
2784 * \brief Fetch the band number.
2785 *
2786 * This method returns the band that this GDALRasterBand objects represents
2787 * within its dataset. This method may return a value of 0 to indicate
2788 * GDALRasterBand objects without an apparently relationship to a dataset,
2789 * such as GDALRasterBands serving as overviews.
2790 *
2791 * This method is the same as the C function GDALGetBandNumber().
2792 *
2793 * @return band number (1+) or 0 if the band number isn't known.
2794 */
2795
2796 int GDALRasterBand::GetBand()
2797
2798 {
2799 return nBand;
2800 }
2801
2802 /************************************************************************/
2803 /* GDALGetBandNumber() */
2804 /************************************************************************/
2805
2806 /**
2807 * \brief Fetch the band number.
2808 *
2809 * @see GDALRasterBand::GetBand()
2810 */
2811
2812 int CPL_STDCALL GDALGetBandNumber( GDALRasterBandH hBand )
2813
2814 {
2815 VALIDATE_POINTER1( hBand, "GDALGetBandNumber", 0 );
2816
2817 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2818 return poBand->GetBand();
2819 }
2820
2821 /************************************************************************/
2822 /* GetDataset() */
2823 /************************************************************************/
2824
2825 /**
2826 * \brief Fetch the owning dataset handle.
2827 *
2828 * Note that some GDALRasterBands are not considered to be a part of a dataset,
2829 * such as overviews or other "freestanding" bands.
2830 *
2831 * This method is the same as the C function GDALGetBandDataset().
2832 *
2833 * @return the pointer to the GDALDataset to which this band belongs, or
2834 * NULL if this cannot be determined.
2835 */
2836
2837 GDALDataset *GDALRasterBand::GetDataset()
2838
2839 {
2840 return poDS;
2841 }
2842
2843 /************************************************************************/
2844 /* GDALGetBandDataset() */
2845 /************************************************************************/
2846
2847 /**
2848 * \brief Fetch the owning dataset handle.
2849 *
2850 * @see GDALRasterBand::GetDataset()
2851 */
2852
2853 GDALDatasetH CPL_STDCALL GDALGetBandDataset( GDALRasterBandH hBand )
2854
2855 {
2856 VALIDATE_POINTER1( hBand, "GDALGetBandDataset", nullptr );
2857
2858 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
2859 return GDALDataset::ToHandle(poBand->GetDataset());
2860 }
2861
2862 /************************************************************************/
2863 /* ComputeFloatNoDataValue() */
2864 /************************************************************************/
2865
2866 static inline void ComputeFloatNoDataValue( GDALDataType eDataType,
2867 double dfNoDataValue,
2868 int& bGotNoDataValue,
2869 float& fNoDataValue,
2870 bool& bGotFloatNoDataValue )
2871 {
2872 if( eDataType == GDT_Float32 && bGotNoDataValue )
2873 {
2874 dfNoDataValue = GDALAdjustNoDataCloseToFloatMax(dfNoDataValue);
2875 if (GDALIsValueInRange<float>(dfNoDataValue) )
2876 {
2877 fNoDataValue = static_cast<float>(dfNoDataValue);
2878 bGotFloatNoDataValue = true;
2879 bGotNoDataValue = false;
2880 }
2881 }
2882 }
2883
2884 /************************************************************************/
2885 /* GetHistogram() */
2886 /************************************************************************/
2887
2888 /**
2889 * \brief Compute raster histogram.
2890 *
2891 * Note that the bucket size is (dfMax-dfMin) / nBuckets.
2892 *
2893 * For example to compute a simple 256 entry histogram of eight bit data,
2894 * the following would be suitable. The unusual bounds are to ensure that
2895 * bucket boundaries don't fall right on integer values causing possible errors
2896 * due to rounding after scaling.
2897 \code{.cpp}
2898 GUIntBig anHistogram[256];
2899
2900 poBand->GetHistogram( -0.5, 255.5, 256, anHistogram, FALSE, FALSE,
2901 GDALDummyProgress, nullptr );
2902 \endcode
2903 *
2904 * Note that setting bApproxOK will generally result in a subsampling of the
2905 * file, and will utilize overviews if available. It should generally
2906 * produce a representative histogram for the data that is suitable for use
2907 * in generating histogram based luts for instance. Generally bApproxOK is
2908 * much faster than an exactly computed histogram.
2909 *
2910 * This method is the same as the C functions GDALGetRasterHistogram() and
2911 * GDALGetRasterHistogramEx().
2912 *
2913 * @param dfMin the lower bound of the histogram.
2914 * @param dfMax the upper bound of the histogram.
2915 * @param nBuckets the number of buckets in panHistogram.
2916 * @param panHistogram array into which the histogram totals are placed.
2917 * @param bIncludeOutOfRange if TRUE values below the histogram range will
2918 * mapped into panHistogram[0], and values above will be mapped into
2919 * panHistogram[nBuckets-1] otherwise out of range values are discarded.
2920 * @param bApproxOK TRUE if an approximate, or incomplete histogram OK.
2921 * @param pfnProgress function to report progress to completion.
2922 * @param pProgressData application data to pass to pfnProgress.
2923 *
2924 * @return CE_None on success, or CE_Failure if something goes wrong.
2925 */
2926
2927 CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
2928 int nBuckets, GUIntBig *panHistogram,
2929 int bIncludeOutOfRange, int bApproxOK,
2930 GDALProgressFunc pfnProgress,
2931 void *pProgressData )
2932
2933 {
2934 CPLAssert( nullptr != panHistogram );
2935
2936 if( pfnProgress == nullptr )
2937 pfnProgress = GDALDummyProgress;
2938
2939 /* -------------------------------------------------------------------- */
2940 /* If we have overviews, use them for the histogram. */
2941 /* -------------------------------------------------------------------- */
2942 if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
2943 {
2944 // FIXME: should we use the most reduced overview here or use some
2945 // minimum number of samples like GDALRasterBand::ComputeStatistics()
2946 // does?
2947 GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
2948
2949 if( poBestOverview != this )
2950 {
2951 return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
2952 panHistogram,
2953 bIncludeOutOfRange, bApproxOK,
2954 pfnProgress, pProgressData );
2955 }
2956 }
2957
2958 /* -------------------------------------------------------------------- */
2959 /* Read actual data and build histogram. */
2960 /* -------------------------------------------------------------------- */
2961 if( !pfnProgress( 0.0, "Compute Histogram", pProgressData ) )
2962 {
2963 ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2964 return CE_Failure;
2965 }
2966
2967 GDALRasterIOExtraArg sExtraArg;
2968 INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2969
2970 const double dfScale = (dfMax > dfMin) ? nBuckets / (dfMax - dfMin) : 0.0;
2971 memset( panHistogram, 0, sizeof(GUIntBig) * nBuckets );
2972
2973 int bGotNoDataValue = FALSE;
2974 const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
2975 bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
2976 // Not advertized. May be removed at any time. Just as a provision if the
2977 // old behavior made sense sometimes.
2978 bGotNoDataValue = bGotNoDataValue &&
2979 !CPLTestBool(CPLGetConfigOption("GDAL_NODATA_IN_HISTOGRAM", "NO"));
2980 bool bGotFloatNoDataValue = false;
2981 float fNoDataValue = 0.0f;
2982 ComputeFloatNoDataValue( eDataType, dfNoDataValue, bGotNoDataValue,
2983 fNoDataValue, bGotFloatNoDataValue );
2984
2985 const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
2986 const bool bSignedByte =
2987 pszPixelType != nullptr && EQUAL(pszPixelType, "SIGNEDBYTE");
2988
2989 if ( bApproxOK && HasArbitraryOverviews() )
2990 {
2991 /* -------------------------------------------------------------------- */
2992 /* Figure out how much the image should be reduced to get an */
2993 /* approximate value. */
2994 /* -------------------------------------------------------------------- */
2995 const double dfReduction = sqrt(
2996 static_cast<double>(nRasterXSize) * nRasterYSize /
2997 GDALSTAT_APPROX_NUMSAMPLES );
2998
2999 int nXReduced = nRasterXSize;
3000 int nYReduced = nRasterYSize;
3001 if ( dfReduction > 1.0 )
3002 {
3003 nXReduced = static_cast<int>( nRasterXSize / dfReduction );
3004 nYReduced = static_cast<int>( nRasterYSize / dfReduction );
3005
3006 // Catch the case of huge resizing ratios here
3007 if ( nXReduced == 0 )
3008 nXReduced = 1;
3009 if ( nYReduced == 0 )
3010 nYReduced = 1;
3011 }
3012
3013 void *pData =
3014 CPLMalloc(
3015 GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
3016
3017 const CPLErr eErr =
3018 IRasterIO(
3019 GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
3020 nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
3021 if ( eErr != CE_None )
3022 {
3023 CPLFree(pData);
3024 return eErr;
3025 }
3026
3027 // This isn't the fastest way to do this, but is easier for now.
3028 for( int iY = 0; iY < nYReduced; iY++ )
3029 {
3030 for( int iX = 0; iX < nXReduced; iX++ )
3031 {
3032 const int iOffset = iX + iY * nXReduced;
3033 double dfValue = 0.0;
3034
3035 switch( eDataType )
3036 {
3037 case GDT_Byte:
3038 {
3039 if( bSignedByte )
3040 dfValue = static_cast<signed char *>(pData)[iOffset];
3041 else
3042 dfValue = static_cast<GByte *>(pData)[iOffset];
3043 break;
3044 }
3045 case GDT_UInt16:
3046 dfValue = static_cast<GUInt16 *>(pData)[iOffset];
3047 break;
3048 case GDT_Int16:
3049 dfValue = static_cast<GInt16 *>(pData)[iOffset];
3050 break;
3051 case GDT_UInt32:
3052 dfValue = static_cast<GUInt32 *>(pData)[iOffset];
3053 break;
3054 case GDT_Int32:
3055 dfValue = static_cast<GInt32 *>(pData)[iOffset];
3056 break;
3057 case GDT_Float32:
3058 {
3059 const float fValue = static_cast<float *>(pData)[iOffset];
3060 if( CPLIsNan(fValue) ||
3061 (bGotFloatNoDataValue && ARE_REAL_EQUAL(fValue, fNoDataValue)) )
3062 continue;
3063 dfValue = fValue;
3064 break;
3065 }
3066 case GDT_Float64:
3067 dfValue = static_cast<double *>(pData)[iOffset];
3068 if( CPLIsNan(dfValue) )
3069 continue;
3070 break;
3071 case GDT_CInt16:
3072 {
3073 const double dfReal =
3074 static_cast<GInt16 *>(pData)[iOffset*2];
3075 const double dfImag =
3076 static_cast<GInt16 *>(pData)[iOffset*2+1];
3077 if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
3078 continue;
3079 dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3080 }
3081 break;
3082 case GDT_CInt32:
3083 {
3084 const double dfReal =
3085 static_cast<GInt32 *>(pData)[iOffset*2];
3086 const double dfImag =
3087 static_cast<GInt32 *>(pData)[iOffset*2+1];
3088 if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
3089 continue;
3090 dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3091 }
3092 break;
3093 case GDT_CFloat32:
3094 {
3095 const double dfReal =
3096 static_cast<float *>(pData)[iOffset*2];
3097 const double dfImag =
3098 static_cast<float *>(pData)[iOffset*2+1];
3099 if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
3100 continue;
3101 dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3102 }
3103 break;
3104 case GDT_CFloat64:
3105 {
3106 const double dfReal =
3107 static_cast<double *>(pData)[iOffset*2];
3108 const double dfImag =
3109 static_cast<double *>(pData)[iOffset*2+1];
3110 if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
3111 continue;
3112 dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3113 }
3114 break;
3115 default:
3116 CPLAssert( false );
3117 }
3118
3119 if( eDataType != GDT_Float32 &&
3120 bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
3121 continue;
3122
3123 const int nIndex =
3124 static_cast<int>(floor((dfValue - dfMin) * dfScale));
3125
3126 if( nIndex < 0 )
3127 {
3128 if( bIncludeOutOfRange )
3129 panHistogram[0]++;
3130 }
3131 else if( nIndex >= nBuckets )
3132 {
3133 if( bIncludeOutOfRange )
3134 ++panHistogram[nBuckets-1];
3135 }
3136 else
3137 {
3138 ++panHistogram[nIndex];
3139 }
3140 }
3141 }
3142
3143 CPLFree( pData );
3144 }
3145 else // No arbitrary overviews.
3146 {
3147 if( !InitBlockInfo() )
3148 return CE_Failure;
3149
3150 /* -------------------------------------------------------------------- */
3151 /* Figure out the ratio of blocks we will read to get an */
3152 /* approximate value. */
3153 /* -------------------------------------------------------------------- */
3154
3155 int nSampleRate = 1;
3156 if ( bApproxOK )
3157 {
3158 nSampleRate = static_cast<int>(
3159 std::max(1.0,
3160 sqrt(static_cast<double>(nBlocksPerRow) *
3161 nBlocksPerColumn)));
3162 // We want to avoid probing only the first column of blocks for
3163 // a square shaped raster, because it is not unlikely that it may
3164 // be padding only (#6378).
3165 if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
3166 nSampleRate += 1;
3167 }
3168
3169 /* -------------------------------------------------------------------- */
3170 /* Read the blocks, and add to histogram. */
3171 /* -------------------------------------------------------------------- */
3172 for( int iSampleBlock = 0;
3173 iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
3174 iSampleBlock += nSampleRate )
3175 {
3176 if( !pfnProgress(
3177 iSampleBlock /
3178 (static_cast<double>(nBlocksPerRow) * nBlocksPerColumn),
3179 "Compute Histogram", pProgressData ) )
3180 return CE_Failure;
3181
3182 const int iYBlock = iSampleBlock / nBlocksPerRow;
3183 const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
3184
3185 GDALRasterBlock *poBlock = GetLockedBlockRef( iXBlock, iYBlock );
3186 if( poBlock == nullptr )
3187 return CE_Failure;
3188
3189 void *pData = poBlock->GetDataRef();
3190
3191 int nXCheck = 0, nYCheck = 0;
3192 GetActualBlockSize(iXBlock, iYBlock, &nXCheck, &nYCheck);
3193
3194 // this is a special case for a common situation.
3195 if( eDataType == GDT_Byte && !bSignedByte
3196 && dfScale == 1.0 && (dfMin >= -0.5 && dfMin <= 0.5)
3197 && nYCheck == nBlockYSize && nXCheck == nBlockXSize
3198 && nBuckets == 256 )
3199 {
3200 const GPtrDiff_t nPixels = static_cast<GPtrDiff_t>(nXCheck) * nYCheck;
3201 GByte *pabyData = static_cast<GByte *>(pData);
3202
3203 for( GPtrDiff_t i = 0; i < nPixels; i++ )
3204 if( ! (bGotNoDataValue &&
3205 (pabyData[i] == static_cast<GByte>(dfNoDataValue))))
3206 {
3207 panHistogram[pabyData[i]]++;
3208 }
3209
3210 poBlock->DropLock();
3211 continue; // To next sample block.
3212 }
3213
3214 // This isn't the fastest way to do this, but is easier for now.
3215 for( int iY = 0; iY < nYCheck; iY++ )
3216 {
3217 for( int iX = 0; iX < nXCheck; iX++ )
3218 {
3219 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
3220 double dfValue = 0.0;
3221
3222 switch( eDataType )
3223 {
3224 case GDT_Byte:
3225 {
3226 if( bSignedByte )
3227 dfValue =
3228 static_cast<signed char *>(pData)[iOffset];
3229 else
3230 dfValue = static_cast<GByte *>(pData)[iOffset];
3231 break;
3232 }
3233 case GDT_UInt16:
3234 dfValue = static_cast<GUInt16 *>(pData)[iOffset];
3235 break;
3236 case GDT_Int16:
3237 dfValue = static_cast<GInt16 *>(pData)[iOffset];
3238 break;
3239 case GDT_UInt32:
3240 dfValue = static_cast<GUInt32 *>(pData)[iOffset];
3241 break;
3242 case GDT_Int32:
3243 dfValue = static_cast<GInt32 *>(pData)[iOffset];
3244 break;
3245 case GDT_Float32:
3246 {
3247 const float fValue = static_cast<float *>(pData)[iOffset];
3248 if( CPLIsNan(fValue) ||
3249 (bGotFloatNoDataValue && ARE_REAL_EQUAL(fValue, fNoDataValue)) )
3250 continue;
3251 dfValue = fValue;
3252 break;
3253 }
3254 case GDT_Float64:
3255 dfValue = static_cast<double *>(pData)[iOffset];
3256 if( CPLIsNan(dfValue) )
3257 continue;
3258 break;
3259 case GDT_CInt16:
3260 {
3261 double dfReal =
3262 static_cast<GInt16 *>(pData)[iOffset*2];
3263 double dfImag =
3264 static_cast<GInt16 *>(pData)[iOffset*2+1];
3265 dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3266 }
3267 break;
3268 case GDT_CInt32:
3269 {
3270 double dfReal =
3271 static_cast<GInt32 *>(pData)[iOffset*2];
3272 double dfImag =
3273 static_cast<GInt32 *>(pData)[iOffset*2+1];
3274 dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3275 }
3276 break;
3277 case GDT_CFloat32:
3278 {
3279 double dfReal =
3280 static_cast<float *>(pData)[iOffset*2];
3281 double dfImag =
3282 static_cast<float *>(pData)[iOffset*2+1];
3283 if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
3284 continue;
3285 dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3286 }
3287 break;
3288 case GDT_CFloat64:
3289 {
3290 double dfReal =
3291 static_cast<double *>(pData)[iOffset*2];
3292 double dfImag =
3293 static_cast<double *>(pData)[iOffset*2+1];
3294 if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
3295 continue;
3296 dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
3297 }
3298 break;
3299 default:
3300 CPLAssert( false );
3301 return CE_Failure;
3302 }
3303
3304 if( eDataType != GDT_Float32 && bGotNoDataValue &&
3305 ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
3306 continue;
3307
3308 const int nIndex =
3309 static_cast<int>(floor((dfValue - dfMin) * dfScale));
3310
3311 if( nIndex < 0 )
3312 {
3313 if( bIncludeOutOfRange )
3314 ++panHistogram[0];
3315 }
3316 else if( nIndex >= nBuckets )
3317 {
3318 if( bIncludeOutOfRange )
3319 ++panHistogram[nBuckets-1];
3320 }
3321 else
3322 {
3323 panHistogram[nIndex]++;
3324 }
3325 }
3326 }
3327
3328 poBlock->DropLock();
3329 }
3330 }
3331
3332 pfnProgress( 1.0, "Compute Histogram", pProgressData );
3333
3334 return CE_None;
3335 }
3336
3337 /************************************************************************/
3338 /* GDALGetRasterHistogram() */
3339 /************************************************************************/
3340
3341 /**
3342 * \brief Compute raster histogram.
3343 *
3344 * Use GDALGetRasterHistogramEx() instead to get correct counts for values
3345 * exceeding 2 billion.
3346 *
3347 * @see GDALRasterBand::GetHistogram()
3348 * @see GDALGetRasterHistogramEx()
3349 */
3350
3351 CPLErr CPL_STDCALL
3352 GDALGetRasterHistogram( GDALRasterBandH hBand,
3353 double dfMin, double dfMax,
3354 int nBuckets, int *panHistogram,
3355 int bIncludeOutOfRange, int bApproxOK,
3356 GDALProgressFunc pfnProgress,
3357 void *pProgressData )
3358
3359 {
3360 VALIDATE_POINTER1( hBand, "GDALGetRasterHistogram", CE_Failure );
3361 VALIDATE_POINTER1( panHistogram, "GDALGetRasterHistogram", CE_Failure );
3362
3363 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
3364
3365 GUIntBig* panHistogramTemp = static_cast<GUIntBig *>(
3366 VSIMalloc2(sizeof(GUIntBig), nBuckets) );
3367 if( panHistogramTemp == nullptr )
3368 {
3369 poBand->ReportError(
3370 CE_Failure, CPLE_OutOfMemory,
3371 "Out of memory in GDALGetRasterHistogram()." );
3372 return CE_Failure;
3373 }
3374
3375 CPLErr eErr = poBand->GetHistogram(
3376 dfMin, dfMax, nBuckets, panHistogramTemp,
3377 bIncludeOutOfRange, bApproxOK,
3378 pfnProgress, pProgressData );
3379
3380 if( eErr == CE_None )
3381 {
3382 for(int i=0;i<nBuckets;i++)
3383 {
3384 if( panHistogramTemp[i] > INT_MAX )
3385 {
3386 CPLError(
3387 CE_Warning, CPLE_AppDefined,
3388 "Count for bucket %d, which is " CPL_FRMT_GUIB
3389 " exceeds maximum 32 bit value",
3390 i, panHistogramTemp[i] );
3391 panHistogram[i] = INT_MAX;
3392 }
3393 else
3394 {
3395 panHistogram[i] = static_cast<int>(panHistogramTemp[i]);
3396 }
3397 }
3398 }
3399
3400 CPLFree(panHistogramTemp);
3401
3402 return eErr;
3403 }
3404
3405 /************************************************************************/
3406 /* GDALGetRasterHistogramEx() */
3407 /************************************************************************/
3408
3409 /**
3410 * \brief Compute raster histogram.
3411 *
3412 * @see GDALRasterBand::GetHistogram()
3413 *
3414 * @since GDAL 2.0
3415 */
3416
3417 CPLErr CPL_STDCALL
3418 GDALGetRasterHistogramEx( GDALRasterBandH hBand,
3419 double dfMin, double dfMax,
3420 int nBuckets, GUIntBig *panHistogram,
3421 int bIncludeOutOfRange, int bApproxOK,
3422 GDALProgressFunc pfnProgress,
3423 void *pProgressData )
3424
3425 {
3426 VALIDATE_POINTER1( hBand, "GDALGetRasterHistogramEx", CE_Failure );
3427 VALIDATE_POINTER1( panHistogram, "GDALGetRasterHistogramEx", CE_Failure );
3428
3429 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
3430
3431 return poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogram,
3432 bIncludeOutOfRange, bApproxOK,
3433 pfnProgress, pProgressData );
3434 }
3435
3436 /************************************************************************/
3437 /* GetDefaultHistogram() */
3438 /************************************************************************/
3439
3440 /**
3441 * \brief Fetch default raster histogram.
3442 *
3443 * The default method in GDALRasterBand will compute a default histogram. This
3444 * method is overridden by derived classes (such as GDALPamRasterBand,
3445 * VRTDataset, HFADataset...) that may be able to fetch efficiently an already
3446 * stored histogram.
3447 *
3448 * This method is the same as the C functions GDALGetDefaultHistogram() and
3449 * GDALGetDefaultHistogramEx().
3450 *
3451 * @param pdfMin pointer to double value that will contain the lower bound of
3452 * the histogram.
3453 * @param pdfMax pointer to double value that will contain the upper bound of
3454 * the histogram.
3455 * @param pnBuckets pointer to int value that will contain the number of buckets
3456 * in *ppanHistogram.
3457 * @param ppanHistogram pointer to array into which the histogram totals are
3458 * placed. To be freed with VSIFree
3459 * @param bForce TRUE to force the computation. If FALSE and no default
3460 * histogram is available, the method will return CE_Warning
3461 * @param pfnProgress function to report progress to completion.
3462 * @param pProgressData application data to pass to pfnProgress.
3463 *
3464 * @return CE_None on success, CE_Failure if something goes wrong, or
3465 * CE_Warning if no default histogram is available.
3466 */
3467
3468 CPLErr
3469 GDALRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
3470 int *pnBuckets,
3471 GUIntBig **ppanHistogram,
3472 int bForce,
3473 GDALProgressFunc pfnProgress,
3474 void *pProgressData )
3475
3476 {
3477 CPLAssert( nullptr != pnBuckets );
3478 CPLAssert( nullptr != ppanHistogram );
3479 CPLAssert( nullptr != pdfMin );
3480 CPLAssert( nullptr != pdfMax );
3481
3482 *pnBuckets = 0;
3483 *ppanHistogram = nullptr;
3484
3485 if( !bForce )
3486 return CE_Warning;
3487
3488 const int nBuckets = 256;
3489
3490 const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
3491 const int bSignedByte =
3492 pszPixelType != nullptr && EQUAL(pszPixelType, "SIGNEDBYTE");
3493
3494 if( GetRasterDataType() == GDT_Byte && !bSignedByte)
3495 {
3496 *pdfMin = -0.5;
3497 *pdfMax = 255.5;
3498 }
3499 else
3500 {
3501
3502 const CPLErr eErr =
3503 GetStatistics( TRUE, TRUE, pdfMin, pdfMax, nullptr, nullptr );
3504 const double dfHalfBucket = (*pdfMax - *pdfMin) / (2 * (nBuckets - 1));
3505 *pdfMin -= dfHalfBucket;
3506 *pdfMax += dfHalfBucket;
3507
3508 if( eErr != CE_None )
3509 return eErr;
3510 }
3511
3512 *ppanHistogram = static_cast<GUIntBig *>(
3513 VSICalloc(sizeof(GUIntBig), nBuckets) );
3514 if( *ppanHistogram == nullptr )
3515 {
3516 ReportError( CE_Failure, CPLE_OutOfMemory,
3517 "Out of memory in InitBlockInfo()." );
3518 return CE_Failure;
3519 }
3520
3521 *pnBuckets = nBuckets;
3522 CPLErr eErr = GetHistogram( *pdfMin, *pdfMax, *pnBuckets, *ppanHistogram,
3523 TRUE, FALSE, pfnProgress, pProgressData );
3524 if( eErr != CE_None )
3525 {
3526 *pnBuckets = 0;
3527 }
3528 return eErr;
3529 }
3530
3531 /************************************************************************/
3532 /* GDALGetDefaultHistogram() */
3533 /************************************************************************/
3534
3535 /**
3536 * \brief Fetch default raster histogram.
3537 *
3538 * Use GDALGetRasterHistogramEx() instead to get correct counts for values
3539 * exceeding 2 billion.
3540 *
3541 * @see GDALRasterBand::GDALGetDefaultHistogram()
3542 * @see GDALGetRasterHistogramEx()
3543 */
3544
3545 CPLErr CPL_STDCALL GDALGetDefaultHistogram(
3546 GDALRasterBandH hBand,
3547 double *pdfMin, double *pdfMax,
3548 int *pnBuckets, int **ppanHistogram,
3549 int bForce,
3550 GDALProgressFunc pfnProgress,
3551 void *pProgressData )
3552
3553 {
3554 VALIDATE_POINTER1( hBand, "GDALGetDefaultHistogram", CE_Failure );
3555 VALIDATE_POINTER1( pdfMin, "GDALGetDefaultHistogram", CE_Failure );
3556 VALIDATE_POINTER1( pdfMax, "GDALGetDefaultHistogram", CE_Failure );
3557 VALIDATE_POINTER1( pnBuckets, "GDALGetDefaultHistogram", CE_Failure );
3558 VALIDATE_POINTER1( ppanHistogram, "GDALGetDefaultHistogram", CE_Failure );
3559
3560 GDALRasterBand * const poBand = GDALRasterBand::FromHandle(hBand);
3561 GUIntBig* panHistogramTemp = nullptr;
3562 CPLErr eErr = poBand->GetDefaultHistogram( pdfMin, pdfMax,
3563 pnBuckets, &panHistogramTemp, bForce, pfnProgress, pProgressData );
3564 if( eErr == CE_None )
3565 {
3566 const int nBuckets = *pnBuckets;
3567 *ppanHistogram = static_cast<int *>(VSIMalloc2(sizeof(int), nBuckets));
3568 if( *ppanHistogram == nullptr )
3569 {
3570 poBand->ReportError(
3571 CE_Failure, CPLE_OutOfMemory,
3572 "Out of memory in GDALGetDefaultHistogram()." );
3573 VSIFree(panHistogramTemp);
3574 return CE_Failure;
3575 }
3576
3577 for( int i = 0; i < nBuckets; ++i )
3578 {
3579 if( panHistogramTemp[i] > INT_MAX )
3580 {
3581 CPLError(
3582 CE_Warning, CPLE_AppDefined,
3583 "Count for bucket %d, which is " CPL_FRMT_GUIB
3584 " exceeds maximum 32 bit value",
3585 i, panHistogramTemp[i] );
3586 (*ppanHistogram)[i] = INT_MAX;
3587 }
3588 else
3589 {
3590 (*ppanHistogram)[i] = static_cast<int>(panHistogramTemp[i]);
3591 }
3592 }
3593
3594 CPLFree(panHistogramTemp);
3595 }
3596 else
3597 {
3598 *ppanHistogram = nullptr;
3599 }
3600
3601 return eErr;
3602 }
3603
3604 /************************************************************************/
3605 /* GDALGetDefaultHistogramEx() */
3606 /************************************************************************/
3607
3608 /**
3609 * \brief Fetch default raster histogram.
3610 *
3611 * @see GDALRasterBand::GetDefaultHistogram()
3612 *
3613 * @since GDAL 2.0
3614 */
3615
3616 CPLErr CPL_STDCALL GDALGetDefaultHistogramEx(
3617 GDALRasterBandH hBand,
3618 double *pdfMin, double *pdfMax,
3619 int *pnBuckets, GUIntBig **ppanHistogram,
3620 int bForce,
3621 GDALProgressFunc pfnProgress,
3622 void *pProgressData )
3623
3624 {
3625 VALIDATE_POINTER1( hBand, "GDALGetDefaultHistogram", CE_Failure );
3626 VALIDATE_POINTER1( pdfMin, "GDALGetDefaultHistogram", CE_Failure );
3627 VALIDATE_POINTER1( pdfMax, "GDALGetDefaultHistogram", CE_Failure );
3628 VALIDATE_POINTER1( pnBuckets, "GDALGetDefaultHistogram", CE_Failure );
3629 VALIDATE_POINTER1( ppanHistogram, "GDALGetDefaultHistogram", CE_Failure );
3630
3631 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
3632 return poBand->GetDefaultHistogram( pdfMin, pdfMax,
3633 pnBuckets, ppanHistogram, bForce, pfnProgress, pProgressData );
3634 }
3635 /************************************************************************/
3636 /* AdviseRead() */
3637 /************************************************************************/
3638
3639 /**
3640 * \fn GDALRasterBand::AdviseRead(int,int,int,int,int,int,GDALDataType,char**)
3641 * \brief Advise driver of upcoming read requests.
3642 *
3643 * Some GDAL drivers operate more efficiently if they know in advance what
3644 * set of upcoming read requests will be made. The AdviseRead() method allows
3645 * an application to notify the driver of the region of interest,
3646 * and at what resolution the region will be read.
3647 *
3648 * Many drivers just ignore the AdviseRead() call, but it can dramatically
3649 * accelerate access via some drivers.
3650 *
3651 * Depending on call paths, drivers might receive several calls to
3652 * AdviseRead() with the same parameters.
3653 *
3654 * @param nXOff The pixel offset to the top left corner of the region
3655 * of the band to be accessed. This would be zero to start from the left side.
3656 *
3657 * @param nYOff The line offset to the top left corner of the region
3658 * of the band to be accessed. This would be zero to start from the top.
3659 *
3660 * @param nXSize The width of the region of the band to be accessed in pixels.
3661 *
3662 * @param nYSize The height of the region of the band to be accessed in lines.
3663 *
3664 * @param nBufXSize the width of the buffer image into which the desired region
3665 * is to be read, or from which it is to be written.
3666 *
3667 * @param nBufYSize the height of the buffer image into which the desired
3668 * region is to be read, or from which it is to be written.
3669 *
3670 * @param eBufType the type of the pixel values in the pData data buffer. The
3671 * pixel values will automatically be translated to/from the GDALRasterBand
3672 * data type as needed.
3673 *
3674 * @param papszOptions a list of name=value strings with special control
3675 * options. Normally this is NULL.
3676 *
3677 * @return CE_Failure if the request is invalid and CE_None if it works or
3678 * is ignored.
3679 */
3680
3681 /**/
3682 /**/
3683
3684 CPLErr GDALRasterBand::AdviseRead(
3685 int /*nXOff*/,
3686 int /*nYOff*/,
3687 int /*nXSize*/,
3688 int /*nYSize*/,
3689 int /*nBufXSize*/,
3690 int /*nBufYSize*/,
3691 GDALDataType /*eBufType*/,
3692 char ** /*papszOptions*/ )
3693 {
3694 return CE_None;
3695 }
3696
3697 /************************************************************************/
3698 /* GDALRasterAdviseRead() */
3699 /************************************************************************/
3700
3701 /**
3702 * \brief Advise driver of upcoming read requests.
3703 *
3704 * @see GDALRasterBand::AdviseRead()
3705 */
3706
3707 CPLErr CPL_STDCALL
3708 GDALRasterAdviseRead( GDALRasterBandH hBand,
3709 int nXOff, int nYOff, int nXSize, int nYSize,
3710 int nBufXSize, int nBufYSize,
3711 GDALDataType eDT, CSLConstList papszOptions )
3712
3713 {
3714 VALIDATE_POINTER1( hBand, "GDALRasterAdviseRead", CE_Failure );
3715
3716 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
3717 return poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize,
3718 nBufXSize, nBufYSize, eDT, const_cast<char**>(papszOptions) );
3719 }
3720
3721 /************************************************************************/
3722 /* GetStatistics() */
3723 /************************************************************************/
3724
3725 /**
3726 * \brief Fetch image statistics.
3727 *
3728 * Returns the minimum, maximum, mean and standard deviation of all
3729 * pixel values in this band. If approximate statistics are sufficient,
3730 * the bApproxOK flag can be set to true in which case overviews, or a
3731 * subset of image tiles may be used in computing the statistics.
3732 *
3733 * If bForce is FALSE results will only be returned if it can be done
3734 * quickly (i.e. without scanning the data). If bForce is FALSE and
3735 * results cannot be returned efficiently, the method will return CE_Warning
3736 * but no warning will have been issued. This is a non-standard use of
3737 * the CE_Warning return value to indicate "nothing done".
3738 *
3739 * Note that file formats using PAM (Persistent Auxiliary Metadata) services
3740 * will generally cache statistics in the .pam file allowing fast fetch
3741 * after the first request.
3742 *
3743 * This method is the same as the C function GDALGetRasterStatistics().
3744 *
3745 * @param bApproxOK If TRUE statistics may be computed based on overviews
3746 * or a subset of all tiles.
3747 *
3748 * @param bForce If FALSE statistics will only be returned if it can
3749 * be done without rescanning the image.
3750 *
3751 * @param pdfMin Location into which to load image minimum (may be NULL).
3752 *
3753 * @param pdfMax Location into which to load image maximum (may be NULL).-
3754 *
3755 * @param pdfMean Location into which to load image mean (may be NULL).
3756 *
3757 * @param pdfStdDev Location into which to load image standard deviation
3758 * (may be NULL).
3759 *
3760 * @return CE_None on success, CE_Warning if no values returned,
3761 * CE_Failure if an error occurs.
3762 */
3763
3764 CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
3765 double *pdfMin, double *pdfMax,
3766 double *pdfMean, double *pdfStdDev )
3767
3768 {
3769 /* -------------------------------------------------------------------- */
3770 /* Do we already have metadata items for the requested values? */
3771 /* -------------------------------------------------------------------- */
3772 if( (pdfMin == nullptr || GetMetadataItem("STATISTICS_MINIMUM") != nullptr)
3773 && (pdfMax == nullptr || GetMetadataItem("STATISTICS_MAXIMUM") != nullptr)
3774 && (pdfMean == nullptr || GetMetadataItem("STATISTICS_MEAN") != nullptr)
3775 && (pdfStdDev == nullptr || GetMetadataItem("STATISTICS_STDDEV") != nullptr) )
3776 {
3777 if( !(GetMetadataItem("STATISTICS_APPROXIMATE") && !bApproxOK) )
3778 {
3779 if( pdfMin != nullptr )
3780 *pdfMin = CPLAtofM(GetMetadataItem("STATISTICS_MINIMUM"));
3781 if( pdfMax != nullptr )
3782 *pdfMax = CPLAtofM(GetMetadataItem("STATISTICS_MAXIMUM"));
3783 if( pdfMean != nullptr )
3784 *pdfMean = CPLAtofM(GetMetadataItem("STATISTICS_MEAN"));
3785 if( pdfStdDev != nullptr )
3786 *pdfStdDev = CPLAtofM(GetMetadataItem("STATISTICS_STDDEV"));
3787
3788 return CE_None;
3789 }
3790 }
3791
3792 /* -------------------------------------------------------------------- */
3793 /* Does the driver already know the min/max? */
3794 /* -------------------------------------------------------------------- */
3795 if( bApproxOK && pdfMean == nullptr && pdfStdDev == nullptr )
3796 {
3797 int bSuccessMin = FALSE;
3798 int bSuccessMax = FALSE;
3799
3800 const double dfMin = GetMinimum( &bSuccessMin );
3801 const double dfMax = GetMaximum( &bSuccessMax );
3802
3803 if( bSuccessMin && bSuccessMax )
3804 {
3805 if( pdfMin != nullptr )
3806 *pdfMin = dfMin;
3807 if( pdfMax != nullptr )
3808 *pdfMax = dfMax;
3809 return CE_None;
3810 }
3811 }
3812
3813 /* -------------------------------------------------------------------- */
3814 /* Either return without results, or force computation. */
3815 /* -------------------------------------------------------------------- */
3816 if( !bForce )
3817 return CE_Warning;
3818 else
3819 return ComputeStatistics( bApproxOK,
3820 pdfMin, pdfMax, pdfMean, pdfStdDev,
3821 GDALDummyProgress, nullptr );
3822 }
3823
3824 /************************************************************************/
3825 /* GDALGetRasterStatistics() */
3826 /************************************************************************/
3827
3828 /**
3829 * \brief Fetch image statistics.
3830 *
3831 * @see GDALRasterBand::GetStatistics()
3832 */
3833
3834 CPLErr CPL_STDCALL GDALGetRasterStatistics(
3835 GDALRasterBandH hBand, int bApproxOK, int bForce,
3836 double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
3837
3838 {
3839 VALIDATE_POINTER1( hBand, "GDALGetRasterStatistics", CE_Failure );
3840
3841 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
3842 return poBand->GetStatistics(
3843 bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev );
3844 }
3845
3846 #ifdef CPL_HAS_GINT64
3847
3848 /************************************************************************/
3849 /* GDALUInt128 */
3850 /************************************************************************/
3851
3852 #ifdef HAVE_UINT128_T
3853 class GDALUInt128
3854 {
3855 __uint128_t val;
3856
3857 explicit GDALUInt128(__uint128_t valIn) : val(valIn) {}
3858
3859 public:
3860 static GDALUInt128 Mul(GUIntBig first, GUIntBig second)
3861 {
3862 // Evaluates to just a single mul on x86_64
3863 return GDALUInt128(static_cast<__uint128_t>(first) * second);
3864 }
3865
3866 GDALUInt128 operator- (const GDALUInt128& other) const
3867 {
3868 return GDALUInt128(val - other.val);
3869 }
3870
3871 operator double() const
3872 {
3873 return static_cast<double>(val);
3874 }
3875 };
3876 #else
3877
3878 #if defined(_MSC_VER) && defined(_M_X64)
3879 #include <intrin.h>
3880 #endif
3881
3882 class GDALUInt128
3883 {
3884 GUIntBig low, high;
3885
3886 GDALUInt128(GUIntBig lowIn, GUIntBig highIn):
3887 low(lowIn), high(highIn) {}
3888
3889 public:
3890 static GDALUInt128 Mul(GUIntBig first, GUIntBig second)
3891 {
3892 #if defined(_MSC_VER) && defined(_M_X64)
3893 GUIntBig highRes;
3894 GUIntBig lowRes = _umul128(first, second, &highRes);
3895 return GDALUInt128(lowRes, highRes);
3896 #else
3897 const GUInt32 firstLow = static_cast<GUInt32>(first);
3898 const GUInt32 firstHigh = static_cast<GUInt32>(first >> 32);
3899 const GUInt32 secondLow = static_cast<GUInt32>(second);
3900 const GUInt32 secondHigh = static_cast<GUInt32>(second >> 32);
3901 GUIntBig highRes = 0;
3902 const GUIntBig firstLowSecondHigh =
3903 static_cast<GUIntBig>(firstLow) * secondHigh;
3904 const GUIntBig firstHighSecondLow =
3905 static_cast<GUIntBig>(firstHigh) * secondLow;
3906 const GUIntBig middleTerm = firstLowSecondHigh + firstHighSecondLow;
3907 if( middleTerm < firstLowSecondHigh ) // check for overflow
3908 highRes += static_cast<GUIntBig>(1) << 32;
3909 const GUIntBig firstLowSecondLow =
3910 static_cast<GUIntBig>(firstLow) * secondLow;
3911 GUIntBig lowRes = firstLowSecondLow + (middleTerm << 32);
3912 if( lowRes < firstLowSecondLow ) // check for overflow
3913 highRes ++;
3914 highRes += (middleTerm >> 32) +
3915 static_cast<GUIntBig>(firstHigh) * secondHigh;
3916 return GDALUInt128(lowRes, highRes);
3917 #endif
3918 }
3919
3920 GDALUInt128 operator- (const GDALUInt128& other) const
3921 {
3922 GUIntBig highRes = high - other.high;
3923 GUIntBig lowRes = low - other.low;
3924 if (lowRes > low) // check for underflow
3925 --highRes;
3926 return GDALUInt128(lowRes, highRes);
3927 }
3928
3929 operator double() const
3930 {
3931 const double twoPow64 = 18446744073709551616.0;
3932 return high * twoPow64 + low;
3933 }
3934 };
3935 #endif
3936
3937 /************************************************************************/
3938 /* ComputeStatisticsInternal() */
3939 /************************************************************************/
3940
3941 // The rationale for below optimizations is detailed in statistics.txt
3942
3943 // Use with T = GDT_Byte or GDT_UInt16 only !
3944 template<class T>
3945 static void ComputeStatisticsInternalGeneric( int nXCheck,
3946 int nBlockXSize,
3947 int nYCheck,
3948 const T* pData,
3949 bool bHasNoData,
3950 GUInt32 nNoDataValue,
3951 GUInt32& nMin,
3952 GUInt32& nMax,
3953 GUIntBig& nSum,
3954 GUIntBig& nSumSquare,
3955 GUIntBig& nSampleCount,
3956 GUIntBig& nValidCount )
3957 {
3958 if( bHasNoData )
3959 {
3960 // General case
3961 for( int iY = 0; iY < nYCheck; iY++ )
3962 {
3963 for( int iX = 0; iX < nXCheck; iX++ )
3964 {
3965 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
3966 const GUInt32 nValue = pData[iOffset];
3967 if( nValue == nNoDataValue )
3968 continue;
3969 nValidCount ++;
3970 if( nValue < nMin )
3971 nMin = nValue;
3972 if( nValue > nMax )
3973 nMax = nValue;
3974 nSum += nValue;
3975 nSumSquare += nValue * nValue;
3976 }
3977 }
3978 nSampleCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
3979 }
3980 else if( nMin == std::numeric_limits<T>::min() &&
3981 nMax == std::numeric_limits<T>::max() )
3982 {
3983 // Optimization when there is no nodata and we know we have already
3984 // reached the min and max
3985 for( int iY = 0; iY < nYCheck; iY++ )
3986 {
3987 int iX;
3988 for( iX = 0; iX + 3 < nXCheck; iX+=4 )
3989 {
3990 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
3991 const GUInt32 nValue = pData[iOffset];
3992 const GUInt32 nValue2 = pData[iOffset+1];
3993 const GUInt32 nValue3 = pData[iOffset+2];
3994 const GUInt32 nValue4 = pData[iOffset+3];
3995 nSum += nValue;
3996 nSumSquare += nValue * nValue;
3997 nSum += nValue2;
3998 nSumSquare += nValue2 * nValue2;
3999 nSum += nValue3;
4000 nSumSquare += nValue3 * nValue3;
4001 nSum += nValue4;
4002 nSumSquare += nValue4 * nValue4;
4003 }
4004 for( ; iX < nXCheck; ++iX )
4005 {
4006 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
4007 const GUInt32 nValue = pData[iOffset];
4008 nSum += nValue;
4009 nSumSquare += nValue * nValue;
4010 }
4011 }
4012 nSampleCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4013 nValidCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4014 }
4015 else
4016 {
4017 for( int iY = 0; iY < nYCheck; iY++ )
4018 {
4019 int iX;
4020 for( iX = 0; iX + 1 < nXCheck; iX+=2 )
4021 {
4022 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
4023 const GUInt32 nValue = pData[iOffset];
4024 const GUInt32 nValue2 = pData[iOffset+1];
4025 if( nValue < nValue2 )
4026 {
4027 if( nValue < nMin )
4028 nMin = nValue;
4029 if( nValue2 > nMax )
4030 nMax = nValue2;
4031 }
4032 else
4033 {
4034 if( nValue2 < nMin )
4035 nMin = nValue2;
4036 if( nValue > nMax )
4037 nMax = nValue;
4038 }
4039 nSum += nValue;
4040 nSumSquare += nValue * nValue;
4041 nSum += nValue2;
4042 nSumSquare += nValue2 * nValue2;
4043 }
4044 if( iX < nXCheck )
4045 {
4046 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
4047 const GUInt32 nValue = pData[iOffset];
4048 if( nValue < nMin )
4049 nMin = nValue;
4050 if( nValue > nMax )
4051 nMax = nValue;
4052 nSum += nValue;
4053 nSumSquare += nValue * nValue;
4054 }
4055 }
4056 nSampleCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4057 nValidCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4058 }
4059 }
4060
4061 // Specialization for Byte that is mostly 32 bit friendly as it avoids
4062 // using 64bit accumulators in internal loops. This also slightly helps in
4063 // 64bit mode.
4064 template<>
4065 void ComputeStatisticsInternalGeneric<GByte>( int nXCheck,
4066 int nBlockXSize,
4067 int nYCheck,
4068 const GByte* pData,
4069 bool bHasNoData,
4070 GUInt32 nNoDataValue,
4071 GUInt32& nMin,
4072 GUInt32& nMax,
4073 GUIntBig& nSum,
4074 GUIntBig& nSumSquare,
4075 GUIntBig& nSampleCount,
4076 GUIntBig& nValidCount )
4077 {
4078 int nOuterLoops = nXCheck / 65536;
4079 if( nXCheck % 65536 )
4080 nOuterLoops ++;
4081
4082 if( bHasNoData )
4083 {
4084 // General case
4085 for( int iY = 0; iY < nYCheck; iY++ )
4086 {
4087 int iX = 0;
4088 for( int k=0; k< nOuterLoops; k++ )
4089 {
4090 int iMax = iX + 65536;
4091 if (iMax > nXCheck )
4092 iMax = nXCheck;
4093 GUInt32 nSum32bit = 0;
4094 GUInt32 nSumSquare32bit = 0;
4095 GUInt32 nValidCount32bit = 0;
4096 GUInt32 nSampleCount32bit = 0;
4097 for( ; iX < iMax; iX++)
4098 {
4099 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
4100 const GUInt32 nValue = pData[iOffset];
4101
4102 nSampleCount32bit ++;
4103 if( nValue == nNoDataValue )
4104 continue;
4105 nValidCount32bit ++;
4106 if( nValue < nMin )
4107 nMin = nValue;
4108 if( nValue > nMax )
4109 nMax = nValue;
4110 nSum32bit += nValue;
4111 nSumSquare32bit += nValue * nValue;
4112 }
4113 nSampleCount += nSampleCount32bit;
4114 nValidCount += nValidCount32bit;
4115 nSum += nSum32bit;
4116 nSumSquare += nSumSquare32bit;
4117 }
4118 }
4119 }
4120 else if( nMin == 0 &&
4121 nMax == 255 )
4122 {
4123 // Optimization when there is no nodata and we know we have already
4124 // reached the min and max
4125 for( int iY = 0; iY < nYCheck; iY++ )
4126 {
4127 int iX = 0;
4128 for( int k=0; k< nOuterLoops; k++ )
4129 {
4130 int iMax = iX + 65536;
4131 if (iMax > nXCheck )
4132 iMax = nXCheck;
4133 GUInt32 nSum32bit = 0;
4134 GUInt32 nSumSquare32bit = 0;
4135 for( ; iX + 3 < iMax; iX+=4 )
4136 {
4137 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
4138 const GUInt32 nValue = pData[iOffset];
4139 const GUInt32 nValue2 = pData[iOffset+1];
4140 const GUInt32 nValue3 = pData[iOffset+2];
4141 const GUInt32 nValue4 = pData[iOffset+3];
4142 nSum32bit += nValue;
4143 nSumSquare32bit += nValue * nValue;
4144 nSum32bit += nValue2;
4145 nSumSquare32bit += nValue2 * nValue2;
4146 nSum32bit += nValue3;
4147 nSumSquare32bit += nValue3 * nValue3;
4148 nSum32bit += nValue4;
4149 nSumSquare32bit += nValue4 * nValue4;
4150 }
4151 nSum += nSum32bit;
4152 nSumSquare += nSumSquare32bit;
4153 }
4154 for( ; iX < nXCheck; ++iX )
4155 {
4156 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
4157 const GUInt32 nValue = pData[iOffset];
4158 nSum += nValue;
4159 nSumSquare += nValue * nValue;
4160 }
4161 }
4162 nSampleCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4163 nValidCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4164 }
4165 else
4166 {
4167 for( int iY = 0; iY < nYCheck; iY++ )
4168 {
4169 int iX = 0;
4170 for( int k=0; k< nOuterLoops; k++ )
4171 {
4172 int iMax = iX + 65536;
4173 if (iMax > nXCheck )
4174 iMax = nXCheck;
4175 GUInt32 nSum32bit = 0;
4176 GUInt32 nSumSquare32bit = 0;
4177 for( ; iX + 1 < iMax; iX+=2 )
4178 {
4179 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
4180 const GUInt32 nValue = pData[iOffset];
4181 const GUInt32 nValue2 = pData[iOffset+1];
4182 if( nValue < nValue2 )
4183 {
4184 if( nValue < nMin )
4185 nMin = nValue;
4186 if( nValue2 > nMax )
4187 nMax = nValue2;
4188 }
4189 else
4190 {
4191 if( nValue2 < nMin )
4192 nMin = nValue2;
4193 if( nValue > nMax )
4194 nMax = nValue;
4195 }
4196 nSum32bit += nValue;
4197 nSumSquare32bit += nValue * nValue;
4198 nSum32bit += nValue2;
4199 nSumSquare32bit += nValue2 * nValue2;
4200 }
4201 nSum += nSum32bit;
4202 nSumSquare += nSumSquare32bit;
4203 }
4204 if( iX < nXCheck )
4205 {
4206 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
4207 const GUInt32 nValue = pData[iOffset];
4208 if( nValue < nMin )
4209 nMin = nValue;
4210 if( nValue > nMax )
4211 nMax = nValue;
4212 nSum += nValue;
4213 nSumSquare += nValue * nValue;
4214 }
4215 }
4216 nSampleCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4217 nValidCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4218 }
4219 }
4220
4221 template<class T>
4222 static void ComputeStatisticsInternal( int nXCheck,
4223 int nBlockXSize,
4224 int nYCheck,
4225 const T* pData,
4226 bool bHasNoData,
4227 GUInt32 nNoDataValue,
4228 GUInt32& nMin,
4229 GUInt32& nMax,
4230 GUIntBig& nSum,
4231 GUIntBig& nSumSquare,
4232 GUIntBig& nSampleCount,
4233 GUIntBig& nValidCount )
4234 {
4235 ComputeStatisticsInternalGeneric( nXCheck, nBlockXSize, nYCheck,
4236 pData,
4237 bHasNoData, nNoDataValue,
4238 nMin, nMax, nSum, nSumSquare,
4239 nSampleCount, nValidCount );
4240 }
4241
4242 #if (defined(__x86_64__) || defined(_M_X64)) && (defined(__GNUC__) || defined(_MSC_VER))
4243
4244 #include <emmintrin.h>
4245
4246 #ifdef __SSE4_1__
4247 #include <smmintrin.h>
4248 #endif
4249
4250 #if defined(__GNUC__)
4251 #define ALIGNED_16(x) x __attribute__ ((aligned (16)))
4252 #else
4253 #define ALIGNED_16(x) __declspec(align(16)) x
4254 #endif
4255
4256 // Some convenience macros
4257 #define ZERO128 _mm_setzero_si128()
4258 #ifdef __SSE4_1__
4259 #define EXTEND_UINT16_TO_UINT32(reg) _mm_cvtepu16_epi32(reg)
4260 #else
4261 #define EXTEND_UINT16_TO_UINT32(reg) _mm_unpacklo_epi16(reg, ZERO128)
4262 #endif
4263 #define GET_HIGH_64BIT(reg) _mm_shuffle_epi32(reg, 2 | (3 << 2))
4264
4265 #include "gdal_avx2_emulation.hpp"
4266
4267 #define ZERO256 GDALmm256_setzero_si256()
4268
4269 // SSE2/AVX2 optimization for GByte case
4270 // In pure SSE2, this relies on gdal_avx2_emulation.hpp. There is no
4271 // penaly in using the emulation, because, given the mm256 intrinsics used here,
4272 // there are strictly equivalent to 2 parallel SSE2 streams.
4273 template<>
4274 void ComputeStatisticsInternal<GByte>( int nXCheck,
4275 int nBlockXSize,
4276 int nYCheck,
4277 // assumed to be aligned on 256 bits
4278 const GByte* pData,
4279 bool bHasNoData,
4280 GUInt32 nNoDataValue,
4281 GUInt32& nMin,
4282 GUInt32& nMax,
4283 GUIntBig& nSum,
4284 GUIntBig& nSumSquare,
4285 GUIntBig& nSampleCount,
4286 GUIntBig& nValidCount )
4287 {
4288 const auto nBlockPixels = static_cast<GPtrDiff_t>(nXCheck) * nYCheck;
4289 if( bHasNoData && nXCheck == nBlockXSize && nBlockPixels >= 32 &&
4290 nMin <= nMax )
4291 {
4292 // 32-byte alignment may not be enforced by linker, so do it at hand
4293 GByte aby32ByteUnaligned[32+32+32+32+32];
4294 GByte* paby32ByteAligned = aby32ByteUnaligned +
4295 (32 - (reinterpret_cast<GUIntptr_t>(aby32ByteUnaligned) % 32));
4296 GByte* pabyMin = paby32ByteAligned;
4297 GByte* pabyMax = paby32ByteAligned + 32;
4298 GUInt32* panSum = reinterpret_cast<GUInt32*>(paby32ByteAligned + 32*2);
4299 GUInt32* panSumSquare = reinterpret_cast<GUInt32*>(paby32ByteAligned + 32*3);
4300
4301 GPtrDiff_t i = 0;
4302 // Make sure that sumSquare can fit on uint32
4303 // * 8 since we can hold 8 sums per vector register
4304 const int nMaxIterationsPerInnerLoop = 8 *
4305 ((std::numeric_limits<GUInt32>::max() / (255 * 255)) & ~31);
4306 auto nOuterLoops = nBlockPixels / nMaxIterationsPerInnerLoop;
4307 if( (nBlockPixels % nMaxIterationsPerInnerLoop) != 0 )
4308 nOuterLoops ++;
4309
4310 const GDALm256i ymm_nodata = GDALmm256_set1_epi8(
4311 static_cast<GByte>(nNoDataValue) );
4312 // any non noData value in [min,max] would do.
4313 const GDALm256i ymm_neutral = GDALmm256_set1_epi8(
4314 static_cast<GByte>(nMin) );
4315 GDALm256i ymm_min = ymm_neutral;
4316 GDALm256i ymm_max = ymm_neutral;
4317
4318 const bool bComputeMinMax = nMin > 0 || nMax < 255;
4319
4320 for( GPtrDiff_t k=0; k< nOuterLoops; k++ )
4321 {
4322 const auto iMax = std::min(nBlockPixels, i + nMaxIterationsPerInnerLoop);
4323
4324 // holds 4 uint32 sums in [0], [2], [4] and [6]
4325 GDALm256i ymm_sum = ZERO256;
4326 // holds 8 uint32 sums
4327 GDALm256i ymm_sumsquare = ZERO256;
4328 // holds 4 uint32 sums in [0], [2], [4] and [6]
4329 GDALm256i ymm_count_nodata_mul_255 = ZERO256;
4330 const auto iInit = i;
4331 for( ;i+31<iMax; i+=32 )
4332 {
4333 const GDALm256i ymm = GDALmm256_load_si256(reinterpret_cast<const GDALm256i*>(pData + i));
4334
4335 // Check which values are nodata
4336 const GDALm256i ymm_eq_nodata =
4337 GDALmm256_cmpeq_epi8( ymm, ymm_nodata );
4338 // Count how many values are nodata (due to cmpeq putting 255
4339 // when condition is met, this will actually be 255 times
4340 // the number of nodata value, spread in 4 64 bits words).
4341 // We can use add_epi32 as the counter will not overflow uint32
4342 ymm_count_nodata_mul_255 = GDALmm256_add_epi32 (
4343 ymm_count_nodata_mul_255,
4344 GDALmm256_sad_epu8(ymm_eq_nodata, ZERO256) );
4345 // Replace all nodata values by zero for the purpose of sum
4346 // and sumquare.
4347 const GDALm256i ymm_nodata_by_zero =
4348 GDALmm256_andnot_si256(ymm_eq_nodata, ymm);
4349 if( bComputeMinMax )
4350 {
4351 // Replace all nodata values by a neutral value for the
4352 // purpose of min and max.
4353 const GDALm256i ymm_nodata_by_neutral = GDALmm256_or_si256(
4354 GDALmm256_and_si256(ymm_eq_nodata, ymm_neutral),
4355 ymm_nodata_by_zero);
4356
4357 ymm_min = GDALmm256_min_epu8 (ymm_min,
4358 ymm_nodata_by_neutral);
4359 ymm_max = GDALmm256_max_epu8 (ymm_max,
4360 ymm_nodata_by_neutral);
4361 }
4362
4363 // Extend lower 128 bits of ymm from uint8 to uint16
4364 const GDALm256i ymm_low = GDALmm256_cvtepu8_epi16(
4365 GDALmm256_extracti128_si256(ymm_nodata_by_zero, 0));
4366 // Compute square of those 16 values as 32 bit result
4367 // and add adjacent pairs
4368 const GDALm256i ymm_low_square =
4369 GDALmm256_madd_epi16(ymm_low, ymm_low);
4370 // Add to the sumsquare accumulator
4371 ymm_sumsquare = GDALmm256_add_epi32(ymm_sumsquare, ymm_low_square);
4372
4373 // Same as before with high 128bits of ymm
4374 const GDALm256i ymm_high = GDALmm256_cvtepu8_epi16(
4375 GDALmm256_extracti128_si256(ymm_nodata_by_zero, 1));
4376 const GDALm256i ymm_high_square =
4377 GDALmm256_madd_epi16(ymm_high, ymm_high);
4378 ymm_sumsquare = GDALmm256_add_epi32(ymm_sumsquare, ymm_high_square);
4379
4380 // Now compute the sums
4381 ymm_sum = GDALmm256_add_epi32(ymm_sum,
4382 GDALmm256_sad_epu8(ymm_nodata_by_zero, ZERO256));
4383 }
4384
4385 GUInt32* panCoutNoDataMul255 = panSum;
4386 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(panCoutNoDataMul255),
4387 ymm_count_nodata_mul_255);
4388
4389 nSampleCount += (i - iInit);
4390
4391 nValidCount += (i - iInit) -
4392 (panCoutNoDataMul255[0] + panCoutNoDataMul255[2] +
4393 panCoutNoDataMul255[4] + panCoutNoDataMul255[6]) / 255;
4394
4395 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(panSum), ymm_sum);
4396 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(panSumSquare), ymm_sumsquare);
4397 nSum += panSum[0] + panSum[2] + panSum[4] + panSum[6];
4398 nSumSquare += static_cast<GUIntBig>(panSumSquare[0]) +
4399 panSumSquare[1] + panSumSquare[2] + panSumSquare[3] +
4400 panSumSquare[4] + panSumSquare[5] + panSumSquare[6] +
4401 panSumSquare[7];
4402 }
4403
4404 if( bComputeMinMax )
4405 {
4406 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(pabyMin), ymm_min);
4407 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(pabyMax), ymm_max);
4408 for(int j=0;j<32;j++)
4409 {
4410 if( pabyMin[j] < nMin ) nMin = pabyMin[j];
4411 if( pabyMax[j] > nMax ) nMax = pabyMax[j];
4412 }
4413 }
4414
4415 for( ; i<nBlockPixels; i++)
4416 {
4417 const GUInt32 nValue = pData[i];
4418 nSampleCount ++;
4419 if( nValue == nNoDataValue )
4420 continue;
4421 nValidCount ++;
4422 if( nValue < nMin )
4423 nMin = nValue;
4424 if( nValue > nMax )
4425 nMax = nValue;
4426 nSum += nValue;
4427 nSumSquare += nValue * nValue;
4428 }
4429 }
4430 else if( !bHasNoData && nXCheck == nBlockXSize && nBlockPixels >= 32 )
4431 {
4432 // 32-byte alignment may not be enforced by linker, so do it at hand
4433 GByte aby32ByteUnaligned[32+32+32+32+32];
4434 GByte* paby32ByteAligned = aby32ByteUnaligned +
4435 (32 - (reinterpret_cast<GUIntptr_t>(aby32ByteUnaligned) % 32));
4436 GByte* pabyMin = paby32ByteAligned;
4437 GByte* pabyMax = paby32ByteAligned + 32;
4438 GUInt32* panSum = reinterpret_cast<GUInt32*>(paby32ByteAligned + 32*2);
4439 GUInt32* panSumSquare = reinterpret_cast<GUInt32*>(paby32ByteAligned + 32*3);
4440
4441 GPtrDiff_t i = 0;
4442 // Make sure that sumSquare can fit on uint32
4443 // * 8 since we can hold 8 sums per vector register
4444 const int nMaxIterationsPerInnerLoop = 8 *
4445 ((std::numeric_limits<GUInt32>::max() / (255 * 255)) & ~31);
4446 GPtrDiff_t nOuterLoops = nBlockPixels / nMaxIterationsPerInnerLoop;
4447 if( (nBlockPixels % nMaxIterationsPerInnerLoop) != 0 )
4448 nOuterLoops ++;
4449
4450 GDALm256i ymm_min = GDALmm256_load_si256(reinterpret_cast<const GDALm256i*>(pData + i));
4451 GDALm256i ymm_max = ymm_min;
4452
4453 const bool bComputeMinMax = nMin > 0 || nMax < 255;
4454
4455 for( GPtrDiff_t k=0; k< nOuterLoops; k++ )
4456 {
4457 const auto iMax = std::min(nBlockPixels, i + nMaxIterationsPerInnerLoop);
4458
4459 // holds 4 uint32 sums in [0], [2], [4] and [6]
4460 GDALm256i ymm_sum = ZERO256;
4461 GDALm256i ymm_sumsquare = ZERO256; // holds 8 uint32 sums
4462 for( ;i+31<iMax; i+=32 )
4463 {
4464 const GDALm256i ymm = GDALmm256_load_si256(reinterpret_cast<const GDALm256i*>(pData + i));
4465 if( bComputeMinMax )
4466 {
4467 ymm_min = GDALmm256_min_epu8 (ymm_min, ymm);
4468 ymm_max = GDALmm256_max_epu8 (ymm_max, ymm);
4469 }
4470
4471 // Extend lower 128 bits of ymm from uint8 to uint16
4472 const GDALm256i ymm_low = GDALmm256_cvtepu8_epi16(
4473 GDALmm256_extracti128_si256(ymm, 0));
4474 // Compute square of those 16 values as 32 bit result
4475 // and add adjacent pairs
4476 const GDALm256i ymm_low_square =
4477 GDALmm256_madd_epi16(ymm_low, ymm_low);
4478 // Add to the sumsquare accumulator
4479 ymm_sumsquare = GDALmm256_add_epi32(ymm_sumsquare, ymm_low_square);
4480
4481 // Same as before with high 128bits of ymm
4482 const GDALm256i ymm_high = GDALmm256_cvtepu8_epi16(
4483 GDALmm256_extracti128_si256(ymm, 1));
4484 const GDALm256i ymm_high_square =
4485 GDALmm256_madd_epi16(ymm_high, ymm_high);
4486 ymm_sumsquare = GDALmm256_add_epi32(ymm_sumsquare, ymm_high_square);
4487
4488 // Now compute the sums
4489 ymm_sum = GDALmm256_add_epi32(ymm_sum,
4490 GDALmm256_sad_epu8(ymm, ZERO256));
4491 }
4492
4493 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(panSum), ymm_sum);
4494 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(panSumSquare), ymm_sumsquare);
4495
4496 nSum += panSum[0] + panSum[2] + panSum[4] + panSum[6];
4497 nSumSquare += static_cast<GUIntBig>(panSumSquare[0]) +
4498 panSumSquare[1] + panSumSquare[2] + panSumSquare[3] +
4499 panSumSquare[4] + panSumSquare[5] + panSumSquare[6] +
4500 panSumSquare[7];
4501 }
4502
4503 if( bComputeMinMax )
4504 {
4505 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(pabyMin), ymm_min);
4506 GDALmm256_store_si256(reinterpret_cast<GDALm256i*>(pabyMax), ymm_max);
4507 for(int j=0;j<32;j++)
4508 {
4509 if( pabyMin[j] < nMin ) nMin = pabyMin[j];
4510 if( pabyMax[j] > nMax ) nMax = pabyMax[j];
4511 }
4512 }
4513
4514 for( ; i<nBlockPixels; i++)
4515 {
4516 const GUInt32 nValue = pData[i];
4517 if( nValue < nMin )
4518 nMin = nValue;
4519 if( nValue > nMax )
4520 nMax = nValue;
4521 nSum += nValue;
4522 nSumSquare += nValue * nValue;
4523 }
4524
4525 nSampleCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4526 nValidCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4527 }
4528 else
4529 {
4530 ComputeStatisticsInternalGeneric( nXCheck, nBlockXSize, nYCheck,
4531 pData,
4532 bHasNoData, nNoDataValue,
4533 nMin, nMax, nSum, nSumSquare,
4534 nSampleCount, nValidCount );
4535 }
4536 }
4537
4538 CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
4539 static void UnshiftSumSquare( GUIntBig& nSumSquare,
4540 GUIntBig nSumThis,
4541 GUIntBig i )
4542 {
4543 nSumSquare += 32768 * (2 * nSumThis - i * 32768);
4544 }
4545
4546 // AVX2/SSE2 optimization for GUInt16 case
4547 template<>
4548 void ComputeStatisticsInternal<GUInt16>( int nXCheck,
4549 int nBlockXSize,
4550 int nYCheck,
4551 // assumed to be aligned on 128 bits
4552 const GUInt16* pData,
4553 bool bHasNoData,
4554 GUInt32 nNoDataValue,
4555 GUInt32& nMin,
4556 GUInt32& nMax,
4557 GUIntBig& nSum,
4558 GUIntBig& nSumSquare,
4559 GUIntBig& nSampleCount,
4560 GUIntBig& nValidCount )
4561 {
4562 const auto nBlockPixels = static_cast<GPtrDiff_t>(nXCheck) * nYCheck;
4563 if( !bHasNoData && nXCheck == nBlockXSize && nBlockPixels >= 16 )
4564 {
4565 GPtrDiff_t i = 0;
4566 // In SSE2, min_epu16 and max_epu16 do not exist, so shift from
4567 // UInt16 to SInt16 to be able to use min_epi16 and max_epi16.
4568 // Furthermore the shift is also needed to use madd_epi16
4569 const GDALm256i ymm_m32768 = GDALmm256_set1_epi16(-32768);
4570 GDALm256i ymm_min = GDALmm256_load_si256(reinterpret_cast<const GDALm256i*>(pData + i));
4571 ymm_min = GDALmm256_add_epi16(ymm_min, ymm_m32768);
4572 GDALm256i ymm_max = ymm_min;
4573 GDALm256i ymm_sumsquare = ZERO256; // holds 4 uint64 sums
4574
4575 // Make sure that sum can fit on uint32
4576 // * 8 since we can hold 8 sums per vector register
4577 const int nMaxIterationsPerInnerLoop = 8 *
4578 ((std::numeric_limits<GUInt32>::max() / 65535) & ~15);
4579 GPtrDiff_t nOuterLoops = nBlockPixels / nMaxIterationsPerInnerLoop;
4580 if( (nBlockPixels % nMaxIterationsPerInnerLoop) != 0 )
4581 nOuterLoops ++;
4582
4583 const bool bComputeMinMax = nMin > 0 || nMax < 65535;
4584
4585 GUIntBig nSumThis = 0;
4586 for( int k=0; k< nOuterLoops; k++ )
4587 {
4588 const auto iMax = std::min(nBlockPixels, i + nMaxIterationsPerInnerLoop);
4589
4590 GDALm256i ymm_sum = ZERO256; // holds 8 uint32 sums
4591 for( ;i+15<iMax ; i+=16 )
4592 {
4593 const GDALm256i ymm = GDALmm256_load_si256(reinterpret_cast<const GDALm256i*>(pData + i));
4594 const GDALm256i ymm_shifted = GDALmm256_add_epi16(ymm, ymm_m32768);
4595 if( bComputeMinMax )
4596 {
4597 ymm_min = GDALmm256_min_epi16 (ymm_min, ymm_shifted);
4598 ymm_max = GDALmm256_max_epi16 (ymm_max, ymm_shifted);
4599 }
4600
4601 // Extend the 8 lower uint16 to uint32
4602 const GDALm256i ymm_low = GDALmm256_cvtepu16_epi32(
4603 GDALmm256_extracti128_si256(ymm, 0));
4604 const GDALm256i ymm_high = GDALmm256_cvtepu16_epi32(
4605 GDALmm256_extracti128_si256(ymm, 1));
4606
4607 #ifndef naive_version
4608 // Note: the int32 range can overflow for (0-32768)^2 +
4609 // (0-32768)^2 = 0x80000000, but as we know the result is
4610 // positive, this is OK as we interpret is a uint32.
4611 const GDALm256i ymm_square = GDALmm256_madd_epi16(ymm_shifted,
4612 ymm_shifted);
4613 const GDALm256i ymm_square_low = GDALmm256_cvtepu32_epi64(
4614 GDALmm256_extracti128_si256(ymm_square, 0));
4615 ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare,
4616 ymm_square_low);
4617 const GDALm256i ymm_square_high = GDALmm256_cvtepu32_epi64(
4618 GDALmm256_extracti128_si256(ymm_square, 1));
4619 ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare,
4620 ymm_square_high);
4621 #else
4622 // Compute square of those 8 values
4623 const GDALm256i ymm_low2 = GDALmm256_mullo_epi32(ymm_low, ymm_low);
4624 // Extract 4 low uint32 and extend them to uint64
4625 const GDALm256i ymm_low2_low = GDALmm256_cvtepu32_epi64(
4626 GDALmm256_extracti128_si256(ymm_low2, 0));
4627 // Extract 4 high uint32 and extend them to uint64
4628 const GDALm256i ymm_low2_high = GDALmm256_cvtepu32_epi64(
4629 GDALmm256_extracti128_si256(ymm_low2, 1));
4630 // Add to the sumsquare accumulator
4631 ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare, ymm_low2_low);
4632 ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare, ymm_low2_high);
4633
4634 // Same with the 8 upper uint16
4635 const GDALm256i ymm_high2 = GDALmm256_mullo_epi32(ymm_high, ymm_high);
4636 const GDALm256i ymm_high2_low = GDALmm256_cvtepu32_epi64(
4637 GDALmm256_extracti128_si256(ymm_high2, 0));
4638 const GDALm256i ymm_high2_high = GDALmm256_cvtepu32_epi64(
4639 GDALmm256_extracti128_si256(ymm_high2, 1));
4640 ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare, ymm_high2_low);
4641 ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare, ymm_high2_high);
4642 #endif
4643
4644 // Now compute the sums
4645 ymm_sum = GDALmm256_add_epi32(ymm_sum, ymm_low);
4646 ymm_sum = GDALmm256_add_epi32(ymm_sum, ymm_high);
4647 }
4648
4649 GUInt32 anSum[8];
4650 GDALmm256_storeu_si256(reinterpret_cast<GDALm256i*>(anSum), ymm_sum);
4651 nSumThis += static_cast<GUIntBig>(anSum[0]) + anSum[1] +
4652 anSum[2] + anSum[3] + anSum[4] + anSum[5] +
4653 anSum[6] + anSum[7];
4654 }
4655
4656 if( bComputeMinMax )
4657 {
4658 GUInt16 anMin[16];
4659 GUInt16 anMax[16];
4660
4661 // Unshift the result
4662 ymm_min = GDALmm256_sub_epi16(ymm_min, ymm_m32768);
4663 ymm_max = GDALmm256_sub_epi16(ymm_max, ymm_m32768);
4664 GDALmm256_storeu_si256(reinterpret_cast<GDALm256i*>(anMin), ymm_min);
4665 GDALmm256_storeu_si256(reinterpret_cast<GDALm256i*>(anMax), ymm_max);
4666 for(int j=0;j<16;j++)
4667 {
4668 if( anMin[j] < nMin ) nMin = anMin[j];
4669 if( anMax[j] > nMax ) nMax = anMax[j];
4670 }
4671 }
4672
4673 GUIntBig anSumSquare[4];
4674 GDALmm256_storeu_si256(reinterpret_cast<GDALm256i*>(anSumSquare), ymm_sumsquare);
4675 nSumSquare += anSumSquare[0] +
4676 anSumSquare[1] + anSumSquare[2] + anSumSquare[3];
4677 #ifndef naive_version
4678 // Unshift the sum of squares
4679 UnshiftSumSquare(nSumSquare, nSumThis, static_cast<GUIntBig>(i));
4680 #endif
4681 nSum += nSumThis;
4682
4683 for( ; i<nBlockPixels; i++)
4684 {
4685 const GUInt32 nValue = pData[i];
4686 if( nValue < nMin )
4687 nMin = nValue;
4688 if( nValue > nMax )
4689 nMax = nValue;
4690 nSum += nValue;
4691 nSumSquare += nValue * nValue;
4692 }
4693
4694 nSampleCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4695 nValidCount += static_cast<GUIntBig>(nXCheck) * nYCheck;
4696 }
4697 else
4698 {
4699 ComputeStatisticsInternalGeneric( nXCheck, nBlockXSize, nYCheck,
4700 pData,
4701 bHasNoData, nNoDataValue,
4702 nMin, nMax, nSum, nSumSquare,
4703 nSampleCount, nValidCount );
4704 }
4705 }
4706
4707 #endif // (defined(__x86_64__) || defined(_M_X64)) && (defined(__GNUC__) || defined(_MSC_VER))
4708
4709 #endif // CPL_HAS_GINT64
4710
4711
4712 /************************************************************************/
4713 /* GetPixelValue() */
4714 /************************************************************************/
4715
4716 static
4717 inline double GetPixelValue( GDALDataType eDataType,
4718 bool bSignedByte,
4719 const void* pData,
4720 GPtrDiff_t iOffset,
4721 bool bGotNoDataValue,
4722 double dfNoDataValue,
4723 bool bGotFloatNoDataValue,
4724 float fNoDataValue,
4725 bool& bValid )
4726 {
4727 bValid = true;
4728 double dfValue;
4729 switch( eDataType )
4730 {
4731 case GDT_Byte:
4732 {
4733 if( bSignedByte )
4734 dfValue = static_cast<const signed char *>(pData)[iOffset];
4735 else
4736 dfValue = static_cast<const GByte *>(pData)[iOffset];
4737 break;
4738 }
4739 case GDT_UInt16:
4740 dfValue = static_cast<const GUInt16 *>(pData)[iOffset];
4741 break;
4742 case GDT_Int16:
4743 dfValue = static_cast<const GInt16 *>(pData)[iOffset];
4744 break;
4745 case GDT_UInt32:
4746 dfValue = static_cast<const GUInt32 *>(pData)[iOffset];
4747 break;
4748 case GDT_Int32:
4749 dfValue = static_cast<const GInt32 *>(pData)[iOffset];
4750 break;
4751 case GDT_Float32:
4752 {
4753 const float fValue = static_cast<const float *>(pData)[iOffset];
4754 if( CPLIsNan(fValue) ||
4755 (bGotFloatNoDataValue && ARE_REAL_EQUAL(fValue, fNoDataValue)) )
4756 {
4757 bValid = false;
4758 return 0.0;
4759 }
4760 dfValue = fValue;
4761 return dfValue;
4762 }
4763 case GDT_Float64:
4764 dfValue = static_cast<const double *>(pData)[iOffset];
4765 if( CPLIsNan(dfValue) )
4766 {
4767 bValid = false;
4768 return 0.0;
4769 }
4770 break;
4771 case GDT_CInt16:
4772 dfValue = static_cast<const GInt16 *>(pData)[iOffset*2];
4773 break;
4774 case GDT_CInt32:
4775 dfValue = static_cast<const GInt32 *>(pData)[iOffset*2];
4776 break;
4777 case GDT_CFloat32:
4778 dfValue = static_cast<const float *>(pData)[iOffset*2];
4779 if( CPLIsNan(dfValue) )
4780 {
4781 bValid = false;
4782 return 0.0;
4783 }
4784 break;
4785 case GDT_CFloat64:
4786 dfValue = static_cast<const double *>(pData)[iOffset*2];
4787 if( CPLIsNan(dfValue) )
4788 {
4789 bValid = false;
4790 return 0.0;
4791 }
4792 break;
4793 default:
4794 #ifndef CSA_BUILD
4795 dfValue = 0.0;
4796 #endif
4797 CPLAssert( false );
4798 }
4799
4800 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
4801 {
4802 bValid = false;
4803 return 0.0;
4804 }
4805 return dfValue;
4806 }
4807
4808 /************************************************************************/
4809 /* SetValidPercent() */
4810 /************************************************************************/
4811
4812 /**
4813 * \brief Set percentage of valid (not nodata) pixels.
4814 *
4815 * Stores the percentage of valid pixels in the metadata item
4816 * STATISTICS_VALID_PERCENT
4817 *
4818 * @param nSampleCount Number of sampled pixels.
4819 *
4820 * @param nValidCount Number of valid pixels.
4821 */
4822
4823 void GDALRasterBand::SetValidPercent(GUIntBig nSampleCount, GUIntBig nValidCount)
4824 {
4825 if( nValidCount == 0 )
4826 {
4827 SetMetadataItem( "STATISTICS_VALID_PERCENT", "0" );
4828 }
4829 else if( nValidCount == nSampleCount )
4830 {
4831 SetMetadataItem( "STATISTICS_VALID_PERCENT", "100" );
4832 }
4833 else /* nValidCount < nSampleCount */
4834 {
4835 char szValue[128] = { 0 };
4836
4837 /* percentage is only an indicator: limit precision */
4838 CPLsnprintf( szValue, sizeof(szValue), "%.4g",
4839 100. * static_cast<double>(nValidCount) / nSampleCount );
4840
4841 if (EQUAL(szValue, "100"))
4842 {
4843 /* don't set 100 percent valid
4844 * because some of the sampled pixels were nodata */
4845 SetMetadataItem( "STATISTICS_VALID_PERCENT", "99.999" );
4846 }
4847 else
4848 {
4849 SetMetadataItem( "STATISTICS_VALID_PERCENT", szValue );
4850 }
4851 }
4852 }
4853
4854 /************************************************************************/
4855 /* ComputeStatistics() */
4856 /************************************************************************/
4857
4858 /**
4859 * \brief Compute image statistics.
4860 *
4861 * Returns the minimum, maximum, mean and standard deviation of all
4862 * pixel values in this band. If approximate statistics are sufficient,
4863 * the bApproxOK flag can be set to true in which case overviews, or a
4864 * subset of image tiles may be used in computing the statistics.
4865 *
4866 * Once computed, the statistics will generally be "set" back on the
4867 * raster band using SetStatistics().
4868 *
4869 * Cached statistics can be cleared with GDALDataset::ClearStatistics().
4870 *
4871 * This method is the same as the C function GDALComputeRasterStatistics().
4872 *
4873 * @param bApproxOK If TRUE statistics may be computed based on overviews
4874 * or a subset of all tiles.
4875 *
4876 * @param pdfMin Location into which to load image minimum (may be NULL).
4877 *
4878 * @param pdfMax Location into which to load image maximum (may be NULL).-
4879 *
4880 * @param pdfMean Location into which to load image mean (may be NULL).
4881 *
4882 * @param pdfStdDev Location into which to load image standard deviation
4883 * (may be NULL).
4884 *
4885 * @param pfnProgress a function to call to report progress, or NULL.
4886 *
4887 * @param pProgressData application data to pass to the progress function.
4888 *
4889 * @return CE_None on success, or CE_Failure if an error occurs or processing
4890 * is terminated by the user.
4891 */
4892
4893 CPLErr
4894 GDALRasterBand::ComputeStatistics( int bApproxOK,
4895 double *pdfMin, double *pdfMax,
4896 double *pdfMean, double *pdfStdDev,
4897 GDALProgressFunc pfnProgress,
4898 void *pProgressData )
4899
4900 {
4901 if( pfnProgress == nullptr )
4902 pfnProgress = GDALDummyProgress;
4903
4904 /* -------------------------------------------------------------------- */
4905 /* If we have overview bands, use them for statistics. */
4906 /* -------------------------------------------------------------------- */
4907 if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
4908 {
4909 GDALRasterBand *poBand
4910 = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
4911
4912 if( poBand != this )
4913 {
4914 CPLErr eErr = poBand->ComputeStatistics( FALSE,
4915 pdfMin, pdfMax,
4916 pdfMean, pdfStdDev,
4917 pfnProgress, pProgressData );
4918 if( eErr == CE_None )
4919 {
4920 if( pdfMin && pdfMax && pdfMean && pdfStdDev )
4921 {
4922 SetMetadataItem( "STATISTICS_APPROXIMATE", "YES" );
4923 SetStatistics( *pdfMin,*pdfMax, *pdfMean, *pdfStdDev );
4924 }
4925
4926 /* transfer metadata from overview band to this */
4927 const char *pszPercentValid = poBand->GetMetadataItem("STATISTICS_VALID_PERCENT");
4928
4929 if ( pszPercentValid != nullptr )
4930 {
4931 SetMetadataItem( "STATISTICS_VALID_PERCENT", pszPercentValid );
4932 }
4933 }
4934 return eErr;
4935 }
4936 }
4937
4938 if( !pfnProgress( 0.0, "Compute Statistics", pProgressData ) )
4939 {
4940 ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
4941 return CE_Failure;
4942 }
4943
4944 /* -------------------------------------------------------------------- */
4945 /* Read actual data and compute statistics. */
4946 /* -------------------------------------------------------------------- */
4947 bool bFirstValue = true;
4948 // Using Welford algorithm:
4949 // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
4950 // to compute standard deviation in a more numerically robust way than
4951 // the difference of the sum of square values with the square of the sum.
4952 // dfMean and dfM2 are updated at each sample.
4953 // dfM2 is the sum of square of differences to the current mean.
4954 double dfMin = 0.0;
4955 double dfMax = 0.0;
4956 double dfMean = 0.0;
4957 double dfM2 = 0.0;
4958
4959 GDALRasterIOExtraArg sExtraArg;
4960 INIT_RASTERIO_EXTRA_ARG(sExtraArg);
4961
4962 int bGotNoDataValue = FALSE;
4963 const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
4964 bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
4965 bool bGotFloatNoDataValue = false;
4966 float fNoDataValue = 0.0f;
4967 ComputeFloatNoDataValue( eDataType, dfNoDataValue, bGotNoDataValue,
4968 fNoDataValue, bGotFloatNoDataValue );
4969
4970 const char* pszPixelType =
4971 GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
4972 const bool bSignedByte =
4973 pszPixelType != nullptr && EQUAL(pszPixelType, "SIGNEDBYTE");
4974
4975 GUIntBig nSampleCount = 0;
4976 GUIntBig nValidCount = 0;
4977
4978 if ( bApproxOK && HasArbitraryOverviews() )
4979 {
4980 /* -------------------------------------------------------------------- */
4981 /* Figure out how much the image should be reduced to get an */
4982 /* approximate value. */
4983 /* -------------------------------------------------------------------- */
4984 double dfReduction = sqrt(
4985 static_cast<double>(nRasterXSize) * nRasterYSize /
4986 GDALSTAT_APPROX_NUMSAMPLES );
4987
4988 int nXReduced = nRasterXSize;
4989 int nYReduced = nRasterYSize;
4990 if ( dfReduction > 1.0 )
4991 {
4992 nXReduced = static_cast<int>( nRasterXSize / dfReduction );
4993 nYReduced = static_cast<int>( nRasterYSize / dfReduction );
4994
4995 // Catch the case of huge resizing ratios here
4996 if ( nXReduced == 0 )
4997 nXReduced = 1;
4998 if ( nYReduced == 0 )
4999 nYReduced = 1;
5000 }
5001
5002 void *pData =
5003 CPLMalloc(
5004 GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
5005
5006 const CPLErr eErr = IRasterIO(
5007 GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
5008 nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
5009 if ( eErr != CE_None )
5010 {
5011 CPLFree(pData);
5012 return eErr;
5013 }
5014
5015 /* this isn't the fastest way to do this, but is easier for now */
5016 for( int iY = 0; iY < nYReduced; iY++ )
5017 {
5018 for( int iX = 0; iX < nXReduced; iX++ )
5019 {
5020 const int iOffset = iX + iY * nXReduced;
5021 bool bValid = true;
5022 double dfValue = GetPixelValue( eDataType,
5023 bSignedByte,
5024 pData,
5025 iOffset,
5026 CPL_TO_BOOL(bGotNoDataValue),
5027 dfNoDataValue,
5028 bGotFloatNoDataValue,
5029 fNoDataValue,
5030 bValid );
5031 nSampleCount++;
5032 if( !bValid )
5033 continue;
5034
5035 if( bFirstValue )
5036 {
5037 dfMin = dfValue;
5038 dfMax = dfValue;
5039 bFirstValue = false;
5040 }
5041 else
5042 {
5043 dfMin = std::min(dfMin, dfValue);
5044 dfMax = std::max(dfMax, dfValue);
5045 }
5046
5047 nValidCount++;
5048 const double dfDelta = dfValue - dfMean;
5049 dfMean += dfDelta / nValidCount;
5050 dfM2 += dfDelta * (dfValue - dfMean);
5051 }
5052 }
5053
5054 CPLFree( pData );
5055 }
5056
5057 else // No arbitrary overviews.
5058 {
5059 if( !InitBlockInfo() )
5060 return CE_Failure;
5061
5062 /* -------------------------------------------------------------------- */
5063 /* Figure out the ratio of blocks we will read to get an */
5064 /* approximate value. */
5065 /* -------------------------------------------------------------------- */
5066 int nSampleRate = 1;
5067 if ( bApproxOK )
5068 {
5069 nSampleRate = static_cast<int>(
5070 std::max(1.0,
5071 sqrt(static_cast<double>(nBlocksPerRow) *
5072 nBlocksPerColumn)));
5073 // We want to avoid probing only the first column of blocks for
5074 // a square shaped raster, because it is not unlikely that it may
5075 // be padding only (#6378)
5076 if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
5077 nSampleRate += 1;
5078 }
5079 if( nSampleRate == 1 )
5080 bApproxOK = false;
5081
5082 #ifdef CPL_HAS_GINT64
5083 // Particular case for GDT_Byte that only use integral types for all
5084 // intermediate computations. Only possible if the number of pixels
5085 // explored is lower than GUINTBIG_MAX / (255*255), so that nSumSquare
5086 // can fit on a uint64. Should be 99.99999% of cases.
5087 // For GUInt16, this limits to raster of 4 giga pixels
5088 if( (eDataType == GDT_Byte && !bSignedByte &&
5089 static_cast<GUIntBig>(nBlocksPerRow)*nBlocksPerColumn/nSampleRate <
5090 GUINTBIG_MAX / (255U * 255U) /
5091 (static_cast<GUInt64>(nBlockXSize) * static_cast<GUInt64>(nBlockYSize))) ||
5092 (eDataType == GDT_UInt16 &&
5093 static_cast<GUIntBig>(nBlocksPerRow)*nBlocksPerColumn/nSampleRate <
5094 GUINTBIG_MAX / (65535U * 65535U) /
5095 (static_cast<GUInt64>(nBlockXSize) * static_cast<GUInt64>(nBlockYSize))) )
5096 {
5097 const GUInt32 nMaxValueType = (eDataType == GDT_Byte) ? 255 : 65535;
5098 GUInt32 nMin = nMaxValueType;
5099 GUInt32 nMax = 0;
5100 GUIntBig nSum = 0;
5101 GUIntBig nSumSquare = 0;
5102 // If no valid nodata, map to invalid value (256 for Byte)
5103 const GUInt32 nNoDataValue =
5104 (bGotNoDataValue && dfNoDataValue >= 0 &&
5105 dfNoDataValue <= nMaxValueType &&
5106 fabs(dfNoDataValue -
5107 static_cast<GUInt32>(dfNoDataValue + 1e-10)) < 1e-10 ) ?
5108 static_cast<GUInt32>(dfNoDataValue + 1e-10) :
5109 nMaxValueType+1;
5110
5111 for( int iSampleBlock = 0;
5112 iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
5113 iSampleBlock += nSampleRate )
5114 {
5115 const int iYBlock = iSampleBlock / nBlocksPerRow;
5116 const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
5117
5118 GDALRasterBlock * const poBlock =
5119 GetLockedBlockRef( iXBlock, iYBlock );
5120 if( poBlock == nullptr )
5121 return CE_Failure;
5122
5123 void* const pData = poBlock->GetDataRef();
5124
5125 int nXCheck = 0, nYCheck = 0;
5126 GetActualBlockSize(iXBlock, iYBlock, &nXCheck, &nYCheck);
5127
5128 if( eDataType == GDT_Byte )
5129 {
5130 ComputeStatisticsInternal( nXCheck,
5131 nBlockXSize,
5132 nYCheck,
5133 static_cast<const GByte*>(pData),
5134 nNoDataValue <= nMaxValueType,
5135 nNoDataValue,
5136 nMin, nMax, nSum,
5137 nSumSquare,
5138 nSampleCount,
5139 nValidCount );
5140 }
5141 else
5142 {
5143 ComputeStatisticsInternal( nXCheck,
5144 nBlockXSize,
5145 nYCheck,
5146 static_cast<const GUInt16*>(pData),
5147 nNoDataValue <= nMaxValueType,
5148 nNoDataValue,
5149 nMin, nMax, nSum,
5150 nSumSquare,
5151 nSampleCount,
5152 nValidCount );
5153 }
5154
5155 poBlock->DropLock();
5156
5157 if ( !pfnProgress( iSampleBlock
5158 / static_cast<double>(nBlocksPerRow*nBlocksPerColumn),
5159 "Compute Statistics", pProgressData) )
5160 {
5161 ReportError( CE_Failure, CPLE_UserInterrupt,
5162 "User terminated" );
5163 return CE_Failure;
5164 }
5165 }
5166
5167 if( !pfnProgress( 1.0, "Compute Statistics", pProgressData ) )
5168 {
5169 ReportError( CE_Failure, CPLE_UserInterrupt,
5170 "User terminated" );
5171 return CE_Failure;
5172 }
5173
5174 /* -------------------------------------------------------------------- */
5175 /* Save computed information. */
5176 /* -------------------------------------------------------------------- */
5177 if( nValidCount )
5178 dfMean = static_cast<double>(nSum) / nValidCount;
5179
5180 // To avoid potential precision issues when doing the difference,
5181 // we need to do that computation on 128 bit rather than casting
5182 // to double
5183 const GDALUInt128 nTmpForStdDev(
5184 GDALUInt128::Mul(nSumSquare,nValidCount) -
5185 GDALUInt128::Mul(nSum,nSum));
5186 const double dfStdDev =
5187 nValidCount > 0 ?
5188 sqrt(static_cast<double>(nTmpForStdDev)) / nValidCount :
5189 0.0;
5190
5191 if( nValidCount > 0 )
5192 {
5193 if( bApproxOK )
5194 {
5195 SetMetadataItem( "STATISTICS_APPROXIMATE", "YES" );
5196 }
5197 else if( GetMetadataItem( "STATISTICS_APPROXIMATE" ) )
5198 {
5199 SetMetadataItem( "STATISTICS_APPROXIMATE", nullptr );
5200 }
5201 SetStatistics( nMin, nMax, dfMean, dfStdDev );
5202 }
5203
5204 SetValidPercent( nSampleCount, nValidCount );
5205
5206 /* -------------------------------------------------------------------- */
5207 /* Record results. */
5208 /* -------------------------------------------------------------------- */
5209 if( pdfMin != nullptr )
5210 *pdfMin = nValidCount ? nMin : 0;
5211 if( pdfMax != nullptr )
5212 *pdfMax = nValidCount ? nMax : 0;
5213
5214 if( pdfMean != nullptr )
5215 *pdfMean = dfMean;
5216
5217 if( pdfStdDev != nullptr )
5218 *pdfStdDev = dfStdDev;
5219
5220 if( nValidCount > 0 )
5221 return CE_None;
5222
5223 ReportError(
5224 CE_Failure, CPLE_AppDefined,
5225 "Failed to compute statistics, no valid pixels found in sampling." );
5226 return CE_Failure;
5227 }
5228 #endif
5229
5230 for( int iSampleBlock = 0;
5231 iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
5232 iSampleBlock += nSampleRate )
5233 {
5234 const int iYBlock = iSampleBlock / nBlocksPerRow;
5235 const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
5236
5237 GDALRasterBlock * const poBlock = GetLockedBlockRef( iXBlock, iYBlock );
5238 if( poBlock == nullptr )
5239 return CE_Failure;
5240
5241 void* const pData = poBlock->GetDataRef();
5242
5243 int nXCheck = 0, nYCheck = 0;
5244 GetActualBlockSize(iXBlock, iYBlock, &nXCheck, &nYCheck);
5245
5246 // This isn't the fastest way to do this, but is easier for now.
5247 for( int iY = 0; iY < nYCheck; iY++ )
5248 {
5249 for( int iX = 0; iX < nXCheck; iX++ )
5250 {
5251 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
5252 bool bValid = true;
5253 double dfValue = GetPixelValue( eDataType,
5254 bSignedByte,
5255 pData,
5256 iOffset,
5257 CPL_TO_BOOL(bGotNoDataValue),
5258 dfNoDataValue,
5259 bGotFloatNoDataValue,
5260 fNoDataValue,
5261 bValid );
5262
5263 nSampleCount++;
5264 if( !bValid )
5265 continue;
5266
5267 if( bFirstValue )
5268 {
5269 dfMin = dfValue;
5270 dfMax = dfValue;
5271 bFirstValue = false;
5272 }
5273 else
5274 {
5275 dfMin = std::min(dfMin, dfValue);
5276 dfMax = std::max(dfMax, dfValue);
5277 }
5278
5279 nValidCount++;
5280 const double dfDelta = dfValue - dfMean;
5281 dfMean += dfDelta / nValidCount;
5282 dfM2 += dfDelta * (dfValue - dfMean);
5283 }
5284 }
5285
5286 poBlock->DropLock();
5287
5288 if ( !pfnProgress(
5289 iSampleBlock
5290 / static_cast<double>(nBlocksPerRow*nBlocksPerColumn),
5291 "Compute Statistics", pProgressData) )
5292 {
5293 ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
5294 return CE_Failure;
5295 }
5296 }
5297 }
5298
5299 if( !pfnProgress( 1.0, "Compute Statistics", pProgressData ) )
5300 {
5301 ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
5302 return CE_Failure;
5303 }
5304
5305 /* -------------------------------------------------------------------- */
5306 /* Save computed information. */
5307 /* -------------------------------------------------------------------- */
5308 const double dfStdDev =
5309 nValidCount > 0 ? sqrt(dfM2 / nValidCount) : 0.0;
5310
5311 if( nValidCount > 0 )
5312 {
5313 if( bApproxOK )
5314 {
5315 SetMetadataItem( "STATISTICS_APPROXIMATE", "YES" );
5316 }
5317 else if( GetMetadataItem( "STATISTICS_APPROXIMATE" ) )
5318 {
5319 SetMetadataItem( "STATISTICS_APPROXIMATE", nullptr );
5320 }
5321 SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
5322 }
5323
5324 SetValidPercent( nSampleCount, nValidCount );
5325
5326 /* -------------------------------------------------------------------- */
5327 /* Record results. */
5328 /* -------------------------------------------------------------------- */
5329 if( pdfMin != nullptr )
5330 *pdfMin = dfMin;
5331 if( pdfMax != nullptr )
5332 *pdfMax = dfMax;
5333
5334 if( pdfMean != nullptr )
5335 *pdfMean = dfMean;
5336
5337 if( pdfStdDev != nullptr )
5338 *pdfStdDev = dfStdDev;
5339
5340 if( nValidCount > 0 )
5341 return CE_None;
5342
5343 ReportError(
5344 CE_Failure, CPLE_AppDefined,
5345 "Failed to compute statistics, no valid pixels found in sampling." );
5346 return CE_Failure;
5347 }
5348
5349 /************************************************************************/
5350 /* GDALComputeRasterStatistics() */
5351 /************************************************************************/
5352
5353 /**
5354 * \brief Compute image statistics.
5355 *
5356 * @see GDALRasterBand::ComputeStatistics()
5357 */
5358
5359 CPLErr CPL_STDCALL GDALComputeRasterStatistics(
5360 GDALRasterBandH hBand, int bApproxOK,
5361 double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev,
5362 GDALProgressFunc pfnProgress, void *pProgressData )
5363
5364 {
5365 VALIDATE_POINTER1( hBand, "GDALComputeRasterStatistics", CE_Failure );
5366
5367 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
5368
5369 return poBand->ComputeStatistics(
5370 bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev,
5371 pfnProgress, pProgressData );
5372 }
5373
5374 /************************************************************************/
5375 /* SetStatistics() */
5376 /************************************************************************/
5377
5378 /**
5379 * \brief Set statistics on band.
5380 *
5381 * This method can be used to store min/max/mean/standard deviation
5382 * statistics on a raster band.
5383 *
5384 * The default implementation stores them as metadata, and will only work
5385 * on formats that can save arbitrary metadata. This method cannot detect
5386 * whether metadata will be properly saved and so may return CE_None even
5387 * if the statistics will never be saved.
5388 *
5389 * This method is the same as the C function GDALSetRasterStatistics().
5390 *
5391 * @param dfMin minimum pixel value.
5392 *
5393 * @param dfMax maximum pixel value.
5394 *
5395 * @param dfMean mean (average) of all pixel values.
5396 *
5397 * @param dfStdDev Standard deviation of all pixel values.
5398 *
5399 * @return CE_None on success or CE_Failure on failure.
5400 */
5401
5402 CPLErr GDALRasterBand::SetStatistics( double dfMin, double dfMax,
5403 double dfMean, double dfStdDev )
5404
5405 {
5406 char szValue[128] = { 0 };
5407
5408 CPLsnprintf( szValue, sizeof(szValue), "%.14g", dfMin );
5409 SetMetadataItem( "STATISTICS_MINIMUM", szValue );
5410
5411 CPLsnprintf( szValue, sizeof(szValue), "%.14g", dfMax );
5412 SetMetadataItem( "STATISTICS_MAXIMUM", szValue );
5413
5414 CPLsnprintf( szValue, sizeof(szValue), "%.14g", dfMean );
5415 SetMetadataItem( "STATISTICS_MEAN", szValue );
5416
5417 CPLsnprintf( szValue, sizeof(szValue), "%.14g", dfStdDev );
5418 SetMetadataItem( "STATISTICS_STDDEV", szValue );
5419
5420 return CE_None;
5421 }
5422
5423 /************************************************************************/
5424 /* GDALSetRasterStatistics() */
5425 /************************************************************************/
5426
5427 /**
5428 * \brief Set statistics on band.
5429 *
5430 * @see GDALRasterBand::SetStatistics()
5431 */
5432
5433 CPLErr CPL_STDCALL GDALSetRasterStatistics(
5434 GDALRasterBandH hBand,
5435 double dfMin, double dfMax, double dfMean, double dfStdDev )
5436
5437 {
5438 VALIDATE_POINTER1( hBand, "GDALSetRasterStatistics", CE_Failure );
5439
5440 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
5441 return poBand->SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
5442 }
5443
5444 /************************************************************************/
5445 /* ComputeRasterMinMax() */
5446 /************************************************************************/
5447
5448 /**
5449 * \brief Compute the min/max values for a band.
5450 *
5451 * If approximate is OK, then the band's GetMinimum()/GetMaximum() will
5452 * be trusted. If it doesn't work, a subsample of blocks will be read to
5453 * get an approximate min/max. If the band has a nodata value it will
5454 * be excluded from the minimum and maximum.
5455 *
5456 * If bApprox is FALSE, then all pixels will be read and used to compute
5457 * an exact range.
5458 *
5459 * This method is the same as the C function GDALComputeRasterMinMax().
5460 *
5461 * @param bApproxOK TRUE if an approximate (faster) answer is OK, otherwise
5462 * FALSE.
5463 * @param adfMinMax the array in which the minimum (adfMinMax[0]) and the
5464 * maximum (adfMinMax[1]) are returned.
5465 *
5466 * @return CE_None on success or CE_Failure on failure.
5467 */
5468
5469 CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
5470 double* adfMinMax )
5471 {
5472 double dfMin = 0.0;
5473 double dfMax = 0.0;
5474
5475 /* -------------------------------------------------------------------- */
5476 /* Does the driver already know the min/max? */
5477 /* -------------------------------------------------------------------- */
5478 if( bApproxOK )
5479 {
5480 int bSuccessMin = FALSE;
5481 int bSuccessMax = FALSE;
5482
5483 dfMin = GetMinimum( &bSuccessMin );
5484 dfMax = GetMaximum( &bSuccessMax );
5485
5486 if( bSuccessMin && bSuccessMax )
5487 {
5488 adfMinMax[0] = dfMin;
5489 adfMinMax[1] = dfMax;
5490 return CE_None;
5491 }
5492 }
5493
5494 /* -------------------------------------------------------------------- */
5495 /* If we have overview bands, use them for min/max. */
5496 /* -------------------------------------------------------------------- */
5497 // cppcheck-suppress knownConditionTrueFalse
5498 if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
5499 {
5500 GDALRasterBand *poBand =
5501 GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
5502
5503 if ( poBand != this )
5504 return poBand->ComputeRasterMinMax( FALSE, adfMinMax );
5505 }
5506
5507 /* -------------------------------------------------------------------- */
5508 /* Read actual data and compute minimum and maximum. */
5509 /* -------------------------------------------------------------------- */
5510 int bGotNoDataValue = FALSE;
5511 const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
5512 bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
5513 bool bGotFloatNoDataValue = false;
5514 float fNoDataValue = 0.0f;
5515 ComputeFloatNoDataValue( eDataType, dfNoDataValue, bGotNoDataValue,
5516 fNoDataValue, bGotFloatNoDataValue );
5517
5518 const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
5519 const bool bSignedByte =
5520 pszPixelType != nullptr && EQUAL(pszPixelType, "SIGNEDBYTE");
5521
5522 GDALRasterIOExtraArg sExtraArg;
5523 INIT_RASTERIO_EXTRA_ARG(sExtraArg);
5524
5525 bool bFirstValue = true;
5526 if ( bApproxOK && HasArbitraryOverviews() )
5527 {
5528 /* -------------------------------------------------------------------- */
5529 /* Figure out how much the image should be reduced to get an */
5530 /* approximate value. */
5531 /* -------------------------------------------------------------------- */
5532 double dfReduction = sqrt(
5533 static_cast<double>(nRasterXSize) * nRasterYSize /
5534 GDALSTAT_APPROX_NUMSAMPLES );
5535
5536 int nXReduced = nRasterXSize;
5537 int nYReduced = nRasterYSize;
5538 if ( dfReduction > 1.0 )
5539 {
5540 nXReduced = static_cast<int>( nRasterXSize / dfReduction );
5541 nYReduced = static_cast<int>( nRasterYSize / dfReduction );
5542
5543 // Catch the case of huge resizing ratios here
5544 if ( nXReduced == 0 )
5545 nXReduced = 1;
5546 if ( nYReduced == 0 )
5547 nYReduced = 1;
5548 }
5549
5550 void * const pData =
5551 CPLMalloc(
5552 GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
5553
5554 const CPLErr eErr = IRasterIO(
5555 GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
5556 nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
5557 if ( eErr != CE_None )
5558 {
5559 CPLFree(pData);
5560 return eErr;
5561 }
5562
5563 /* this isn't the fastest way to do this, but is easier for now */
5564 for( int iY = 0; iY < nYReduced; iY++ )
5565 {
5566 for( int iX = 0; iX < nXReduced; iX++ )
5567 {
5568 const int iOffset = iX + iY * nXReduced;
5569 bool bValid = true;
5570 double dfValue = GetPixelValue( eDataType,
5571 bSignedByte,
5572 pData,
5573 iOffset,
5574 CPL_TO_BOOL(bGotNoDataValue),
5575 dfNoDataValue,
5576 bGotFloatNoDataValue,
5577 fNoDataValue,
5578 bValid );
5579 if( !bValid )
5580 continue;
5581
5582 if( bFirstValue )
5583 {
5584 dfMin = dfValue;
5585 dfMax = dfValue;
5586 bFirstValue = false;
5587 }
5588 else
5589 {
5590 dfMin = std::min(dfMin, dfValue);
5591 dfMax = std::max(dfMax, dfValue);
5592 }
5593 }
5594 }
5595
5596 CPLFree( pData );
5597 }
5598
5599 else // No arbitrary overviews
5600 {
5601 if( !InitBlockInfo() )
5602 return CE_Failure;
5603
5604 /* -------------------------------------------------------------------- */
5605 /* Figure out the ratio of blocks we will read to get an */
5606 /* approximate value. */
5607 /* -------------------------------------------------------------------- */
5608 int nSampleRate = 1;
5609
5610 if ( bApproxOK )
5611 {
5612 nSampleRate = static_cast<int>(
5613 std::max(1.0,
5614 sqrt(static_cast<double>(nBlocksPerRow) *
5615 nBlocksPerColumn)));
5616 // We want to avoid probing only the first column of blocks for
5617 // a square shaped raster, because it is not unlikely that it may
5618 // be padding only (#6378).
5619 if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
5620 nSampleRate += 1;
5621 }
5622
5623 for( int iSampleBlock = 0;
5624 iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
5625 iSampleBlock += nSampleRate )
5626 {
5627 const int iYBlock = iSampleBlock / nBlocksPerRow;
5628 const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
5629
5630 GDALRasterBlock *poBlock = GetLockedBlockRef( iXBlock, iYBlock );
5631 if( poBlock == nullptr )
5632 return CE_Failure;
5633
5634 void * const pData = poBlock->GetDataRef();
5635
5636 int nXCheck = 0, nYCheck = 0;
5637 GetActualBlockSize(iXBlock, iYBlock, &nXCheck, &nYCheck);
5638
5639 // This isn't the fastest way to do this, but is easier for now.
5640 for( int iY = 0; iY < nYCheck; iY++ )
5641 {
5642 for( int iX = 0; iX < nXCheck; iX++ )
5643 {
5644 const GPtrDiff_t iOffset = iX + static_cast<GPtrDiff_t>(iY) * nBlockXSize;
5645 bool bValid = true;
5646 double dfValue = GetPixelValue( eDataType,
5647 bSignedByte,
5648 pData,
5649 iOffset,
5650 CPL_TO_BOOL(bGotNoDataValue),
5651 dfNoDataValue,
5652 bGotFloatNoDataValue,
5653 fNoDataValue,
5654 bValid );
5655 if( !bValid )
5656 continue;
5657
5658 if( bFirstValue )
5659 {
5660 dfMin = dfValue;
5661 dfMax = dfValue;
5662 bFirstValue = false;
5663 }
5664 else
5665 {
5666 dfMin = std::min(dfMin, dfValue);
5667 dfMax = std::max(dfMax, dfValue);
5668 }
5669 }
5670 }
5671
5672 poBlock->DropLock();
5673 }
5674 }
5675
5676 adfMinMax[0] = dfMin;
5677 adfMinMax[1] = dfMax;
5678
5679 if (bFirstValue)
5680 {
5681 ReportError(
5682 CE_Failure, CPLE_AppDefined,
5683 "Failed to compute min/max, no valid pixels found in sampling." );
5684 return CE_Failure;
5685 }
5686
5687 return CE_None;
5688 }
5689
5690 /************************************************************************/
5691 /* GDALComputeRasterMinMax() */
5692 /************************************************************************/
5693
5694 /**
5695 * \brief Compute the min/max values for a band.
5696 *
5697 * @see GDALRasterBand::ComputeRasterMinMax()
5698 */
5699
5700 void CPL_STDCALL
5701 GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK,
5702 double adfMinMax[2] )
5703
5704 {
5705 VALIDATE_POINTER0( hBand, "GDALComputeRasterMinMax" );
5706
5707 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
5708 poBand->ComputeRasterMinMax( bApproxOK, adfMinMax );
5709 }
5710
5711 /************************************************************************/
5712 /* SetDefaultHistogram() */
5713 /************************************************************************/
5714
5715 /* FIXME : add proper documentation */
5716 /**
5717 * \brief Set default histogram.
5718 *
5719 * This method is the same as the C function GDALSetDefaultHistogram() and
5720 * GDALSetDefaultHistogramEx()
5721 */
5722 CPLErr GDALRasterBand::SetDefaultHistogram( double /* dfMin */,
5723 double /* dfMax */,
5724 int /* nBuckets */,
5725 GUIntBig * /* panHistogram */)
5726
5727 {
5728 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
5729 ReportError( CE_Failure, CPLE_NotSupported,
5730 "SetDefaultHistogram() not implemented for this format." );
5731
5732 return CE_Failure;
5733 }
5734
5735 /************************************************************************/
5736 /* GDALSetDefaultHistogram() */
5737 /************************************************************************/
5738
5739 /**
5740 * \brief Set default histogram.
5741 *
5742 * Use GDALSetRasterHistogramEx() instead to be able to set counts exceeding
5743 * 2 billion.
5744 *
5745 * @see GDALRasterBand::SetDefaultHistogram()
5746 * @see GDALSetRasterHistogramEx()
5747 */
5748
5749 CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand,
5750 double dfMin, double dfMax,
5751 int nBuckets, int *panHistogram )
5752
5753 {
5754 VALIDATE_POINTER1( hBand, "GDALSetDefaultHistogram", CE_Failure );
5755
5756 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
5757
5758 GUIntBig* panHistogramTemp = static_cast<GUIntBig *>(
5759 VSIMalloc2(sizeof(GUIntBig), nBuckets) );
5760 if( panHistogramTemp == nullptr )
5761 {
5762 poBand->ReportError(
5763 CE_Failure, CPLE_OutOfMemory,
5764 "Out of memory in GDALSetDefaultHistogram()." );
5765 return CE_Failure;
5766 }
5767
5768 for( int i = 0; i < nBuckets; ++i )
5769 {
5770 panHistogramTemp[i] = static_cast<GUIntBig>(panHistogram[i]);
5771 }
5772
5773 const CPLErr eErr =
5774 poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogramTemp );
5775
5776 CPLFree(panHistogramTemp);
5777
5778 return eErr;
5779 }
5780
5781 /************************************************************************/
5782 /* GDALSetDefaultHistogramEx() */
5783 /************************************************************************/
5784
5785 /**
5786 * \brief Set default histogram.
5787 *
5788 * @see GDALRasterBand::SetDefaultHistogram()
5789 *
5790 * @since GDAL 2.0
5791 */
5792
5793 CPLErr CPL_STDCALL GDALSetDefaultHistogramEx( GDALRasterBandH hBand,
5794 double dfMin, double dfMax,
5795 int nBuckets,
5796 GUIntBig *panHistogram )
5797
5798 {
5799 VALIDATE_POINTER1( hBand, "GDALSetDefaultHistogramEx", CE_Failure );
5800
5801 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
5802 return poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram );
5803 }
5804
5805 /************************************************************************/
5806 /* GetDefaultRAT() */
5807 /************************************************************************/
5808
5809 /**
5810 * \brief Fetch default Raster Attribute Table.
5811 *
5812 * A RAT will be returned if there is a default one associated with the
5813 * band, otherwise NULL is returned. The returned RAT is owned by the
5814 * band and should not be deleted by the application.
5815 *
5816 * This method is the same as the C function GDALGetDefaultRAT().
5817 *
5818 * @return NULL, or a pointer to an internal RAT owned by the band.
5819 */
5820
5821 GDALRasterAttributeTable *GDALRasterBand::GetDefaultRAT()
5822
5823 {
5824 return nullptr;
5825 }
5826
5827 /************************************************************************/
5828 /* GDALGetDefaultRAT() */
5829 /************************************************************************/
5830
5831 /**
5832 * \brief Fetch default Raster Attribute Table.
5833 *
5834 * @see GDALRasterBand::GetDefaultRAT()
5835 */
5836
5837 GDALRasterAttributeTableH CPL_STDCALL GDALGetDefaultRAT( GDALRasterBandH hBand)
5838
5839 {
5840 VALIDATE_POINTER1( hBand, "GDALGetDefaultRAT", nullptr );
5841
5842 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
5843 return GDALRasterAttributeTable::ToHandle(poBand->GetDefaultRAT());
5844 }
5845
5846 /************************************************************************/
5847 /* SetDefaultRAT() */
5848 /************************************************************************/
5849
5850 /**
5851 * \fn GDALRasterBand::SetDefaultRAT(const GDALRasterAttributeTable*)
5852 * \brief Set default Raster Attribute Table.
5853 *
5854 * Associates a default RAT with the band. If not implemented for the
5855 * format a CPLE_NotSupported error will be issued. If successful a copy
5856 * of the RAT is made, the original remains owned by the caller.
5857 *
5858 * This method is the same as the C function GDALSetDefaultRAT().
5859 *
5860 * @param poRAT the RAT to assign to the band.
5861 *
5862 * @return CE_None on success or CE_Failure if unsupported or otherwise
5863 * failing.
5864 */
5865
5866 /**/
5867 /**/
5868
5869 CPLErr GDALRasterBand::SetDefaultRAT(
5870 const GDALRasterAttributeTable * /* poRAT */ )
5871 {
5872 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
5873 {
5874 CPLPushErrorHandler(CPLQuietErrorHandler);
5875 ReportError( CE_Failure, CPLE_NotSupported,
5876 "SetDefaultRAT() not implemented for this format." );
5877 CPLPopErrorHandler();
5878 }
5879 return CE_Failure;
5880 }
5881
5882 /************************************************************************/
5883 /* GDALSetDefaultRAT() */
5884 /************************************************************************/
5885
5886 /**
5887 * \brief Set default Raster Attribute Table.
5888 *
5889 * @see GDALRasterBand::GDALSetDefaultRAT()
5890 */
5891
5892 CPLErr CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH hBand,
5893 GDALRasterAttributeTableH hRAT )
5894
5895 {
5896 VALIDATE_POINTER1( hBand, "GDALSetDefaultRAT", CE_Failure );
5897
5898 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
5899
5900 return poBand->SetDefaultRAT(
5901 GDALRasterAttributeTable::FromHandle(hRAT) );
5902 }
5903
5904 /************************************************************************/
5905 /* GetMaskBand() */
5906 /************************************************************************/
5907
5908 /**
5909 * \brief Return the mask band associated with the band.
5910 *
5911 * The GDALRasterBand class includes a default implementation of GetMaskBand() that
5912 * returns one of four default implementations :
5913 * <ul>
5914 * <li>If a corresponding .msk file exists it will be used for the mask band.</li>
5915 * <li>If the dataset has a NODATA_VALUES metadata item, an instance of the
5916 * new GDALNoDataValuesMaskBand class will be returned.
5917 * GetMaskFlags() will return GMF_NODATA | GMF_PER_DATASET. @since GDAL 1.6.0</li>
5918 * <li>If the band has a nodata value set, an instance of the new
5919 * GDALNodataMaskRasterBand class will be returned.
5920 * GetMaskFlags() will return GMF_NODATA.</li>
5921 * <li>If there is no nodata value, but the dataset has an alpha band that seems
5922 * to apply to this band (specific rules yet to be determined) and that is
5923 * of type GDT_Byte then that alpha band will be returned, and the flags
5924 * GMF_PER_DATASET and GMF_ALPHA will be returned in the flags.</li>
5925 * <li>If neither of the above apply, an instance of the new GDALAllValidRasterBand
5926 * class will be returned that has 255 values for all pixels.
5927 * The null flags will return GMF_ALL_VALID.</li>
5928 * </ul>
5929 *
5930 * Note that the GetMaskBand() should always return a GDALRasterBand mask, even
5931 * if it is only an all 255 mask with the flags indicating GMF_ALL_VALID.
5932 *
5933 * For an external .msk file to be recognized by GDAL, it must be a valid GDAL
5934 * dataset, with the same name as the main dataset and suffixed with .msk,
5935 * with either one band (in the GMF_PER_DATASET case), or as many bands as the
5936 * main dataset.
5937 * It must have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
5938 * level, where xx matches the band number of a band of the main dataset. The
5939 * value of those items is a combination of the flags GMF_ALL_VALID,
5940 * GMF_PER_DATASET, GMF_ALPHA and GMF_NODATA. If a metadata item is missing for
5941 * a band, then the other rules explained above will be used to generate a
5942 * on-the-fly mask band.
5943 * \see CreateMaskBand() for the characteristics of .msk files created by GDAL.
5944 *
5945 * This method is the same as the C function GDALGetMaskBand().
5946 *
5947 * @return a valid mask band.
5948 *
5949 * @since GDAL 1.5.0
5950 *
5951 * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
5952 *
5953 */
5954 GDALRasterBand *GDALRasterBand::GetMaskBand()
5955
5956 {
5957 if( poMask != nullptr )
5958 return poMask;
5959
5960 /* -------------------------------------------------------------------- */
5961 /* Check for a mask in a .msk file. */
5962 /* -------------------------------------------------------------------- */
5963 if( poDS != nullptr && poDS->oOvManager.HaveMaskFile() )
5964 {
5965 poMask = poDS->oOvManager.GetMaskBand( nBand );
5966 if( poMask != nullptr )
5967 {
5968 nMaskFlags = poDS->oOvManager.GetMaskFlags( nBand );
5969 return poMask;
5970 }
5971 }
5972
5973 /* -------------------------------------------------------------------- */
5974 /* Check for NODATA_VALUES metadata. */
5975 /* -------------------------------------------------------------------- */
5976 if( poDS != nullptr )
5977 {
5978 const char* pszNoDataValues = poDS->GetMetadataItem("NODATA_VALUES");
5979 if( pszNoDataValues != nullptr )
5980 {
5981 char** papszNoDataValues
5982 = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
5983
5984 // Make sure we have as many values as bands.
5985 if (CSLCount(papszNoDataValues) == poDS->GetRasterCount()
5986 && poDS->GetRasterCount() != 0)
5987 {
5988 // Make sure that all bands have the same data type
5989 // This is clearly not a fundamental condition, just a
5990 // condition to make implementation easier.
5991 GDALDataType eDT = GDT_Unknown;
5992 int i = 0; // Used after for.
5993 for( ; i < poDS->GetRasterCount(); ++i )
5994 {
5995 if( i == 0 )
5996 eDT = poDS->GetRasterBand(1)->GetRasterDataType();
5997 else if (eDT != poDS->GetRasterBand(i + 1)->GetRasterDataType())
5998 {
5999 break;
6000 }
6001 }
6002 if( i == poDS->GetRasterCount() )
6003 {
6004 nMaskFlags = GMF_NODATA | GMF_PER_DATASET;
6005 try
6006 {
6007 poMask = new GDALNoDataValuesMaskBand ( poDS );
6008 }
6009 catch( const std::bad_alloc& )
6010 {
6011 CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
6012 poMask = nullptr;
6013 }
6014 bOwnMask = true;
6015 CSLDestroy(papszNoDataValues);
6016 return poMask;
6017 }
6018 else
6019 {
6020 ReportError( CE_Warning, CPLE_AppDefined,
6021 "All bands should have the same type in "
6022 "order the NODATA_VALUES metadata item "
6023 "to be used as a mask." );
6024 }
6025 }
6026 else
6027 {
6028 ReportError(
6029 CE_Warning, CPLE_AppDefined,
6030 "NODATA_VALUES metadata item doesn't have the same number "
6031 "of values as the number of bands. "
6032 "Ignoring it for mask.");
6033 }
6034
6035 CSLDestroy(papszNoDataValues);
6036 }
6037 }
6038
6039 /* -------------------------------------------------------------------- */
6040 /* Check for nodata case. */
6041 /* -------------------------------------------------------------------- */
6042 int bHaveNoData = FALSE;
6043 const double dfNoDataValue = GetNoDataValue( &bHaveNoData );
6044
6045 if( bHaveNoData &&
6046 GDALNoDataMaskBand::IsNoDataInRange(dfNoDataValue, eDataType) )
6047 {
6048 nMaskFlags = GMF_NODATA;
6049 try
6050 {
6051 poMask = new GDALNoDataMaskBand( this );
6052 }
6053 catch( const std::bad_alloc& )
6054 {
6055 CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
6056 poMask = nullptr;
6057 }
6058 bOwnMask = true;
6059 return poMask;
6060 }
6061
6062 /* -------------------------------------------------------------------- */
6063 /* Check for alpha case. */
6064 /* -------------------------------------------------------------------- */
6065 if( poDS != nullptr
6066 && poDS->GetRasterCount() == 2
6067 && this == poDS->GetRasterBand(1)
6068 && poDS->GetRasterBand(2)->GetColorInterpretation() == GCI_AlphaBand )
6069 {
6070 if( poDS->GetRasterBand(2)->GetRasterDataType() == GDT_Byte )
6071 {
6072 nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
6073 poMask = poDS->GetRasterBand(2);
6074 return poMask;
6075 }
6076 else if( poDS->GetRasterBand(2)->GetRasterDataType() == GDT_UInt16 )
6077 {
6078 nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
6079 try
6080 {
6081 poMask = new GDALRescaledAlphaBand( poDS->GetRasterBand(2) );
6082 }
6083 catch( const std::bad_alloc& )
6084 {
6085 CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
6086 poMask = nullptr;
6087 }
6088 bOwnMask = true;
6089 return poMask;
6090 }
6091 }
6092
6093 if( poDS != nullptr
6094 && poDS->GetRasterCount() == 4
6095 && (this == poDS->GetRasterBand(1)
6096 || this == poDS->GetRasterBand(2)
6097 || this == poDS->GetRasterBand(3))
6098 && poDS->GetRasterBand(4)->GetColorInterpretation() == GCI_AlphaBand )
6099 {
6100 if( poDS->GetRasterBand(4)->GetRasterDataType() == GDT_Byte )
6101 {
6102 nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
6103 poMask = poDS->GetRasterBand(4);
6104 return poMask;
6105 }
6106 else if( poDS->GetRasterBand(4)->GetRasterDataType() == GDT_UInt16 )
6107 {
6108 nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
6109 try
6110 {
6111 poMask = new GDALRescaledAlphaBand( poDS->GetRasterBand(4) );
6112 }
6113 catch( const std::bad_alloc& )
6114 {
6115 CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
6116 poMask = nullptr;
6117 }
6118 bOwnMask = true;
6119 return poMask;
6120 }
6121 }
6122
6123 /* -------------------------------------------------------------------- */
6124 /* Fallback to all valid case. */
6125 /* -------------------------------------------------------------------- */
6126 nMaskFlags = GMF_ALL_VALID;
6127 try
6128 {
6129 poMask = new GDALAllValidMaskBand( this );
6130 }
6131 catch( const std::bad_alloc& )
6132 {
6133 CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
6134 poMask = nullptr;
6135 }
6136 bOwnMask = true;
6137
6138 return poMask;
6139 }
6140
6141 /************************************************************************/
6142 /* GDALGetMaskBand() */
6143 /************************************************************************/
6144
6145 /**
6146 * \brief Return the mask band associated with the band.
6147 *
6148 * @see GDALRasterBand::GetMaskBand()
6149 */
6150
6151 GDALRasterBandH CPL_STDCALL GDALGetMaskBand( GDALRasterBandH hBand )
6152
6153 {
6154 VALIDATE_POINTER1( hBand, "GDALGetMaskBand", nullptr );
6155
6156 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
6157 return poBand->GetMaskBand();
6158 }
6159
6160 /************************************************************************/
6161 /* GetMaskFlags() */
6162 /************************************************************************/
6163
6164 /**
6165 * \brief Return the status flags of the mask band associated with the band.
6166 *
6167 * The GetMaskFlags() method returns an bitwise OR-ed set of status flags with
6168 * the following available definitions that may be extended in the future:
6169 * <ul>
6170 * <li>GMF_ALL_VALID(0x01): There are no invalid pixels, all mask values will be 255.
6171 * When used this will normally be the only flag set.</li>
6172 * <li>GMF_PER_DATASET(0x02): The mask band is shared between all bands on the dataset.</li>
6173 * <li>GMF_ALPHA(0x04): The mask band is actually an alpha band and may have values
6174 * other than 0 and 255.</li>
6175 * <li>GMF_NODATA(0x08): Indicates the mask is actually being generated from nodata values.
6176 * (mutually exclusive of GMF_ALPHA)</li>
6177 * </ul>
6178 *
6179 * The GDALRasterBand class includes a default implementation of GetMaskBand() that
6180 * returns one of four default implementations :
6181 * <ul>
6182 * <li>If a corresponding .msk file exists it will be used for the mask band.</li>
6183 * <li>If the dataset has a NODATA_VALUES metadata item, an instance of the
6184 * new GDALNoDataValuesMaskBand class will be returned.
6185 * GetMaskFlags() will return GMF_NODATA | GMF_PER_DATASET. @since GDAL 1.6.0</li>
6186 * <li>If the band has a nodata value set, an instance of the new
6187 * GDALNodataMaskRasterBand class will be returned.
6188 * GetMaskFlags() will return GMF_NODATA.</li>
6189 * <li>If there is no nodata value, but the dataset has an alpha band that seems
6190 * to apply to this band (specific rules yet to be determined) and that is
6191 * of type GDT_Byte then that alpha band will be returned, and the flags
6192 * GMF_PER_DATASET and GMF_ALPHA will be returned in the flags.</li>
6193 * <li>If neither of the above apply, an instance of the new GDALAllValidRasterBand
6194 * class will be returned that has 255 values for all pixels.
6195 * The null flags will return GMF_ALL_VALID.</li>
6196 * </ul>
6197 *
6198 * For an external .msk file to be recognized by GDAL, it must be a valid GDAL
6199 * dataset, with the same name as the main dataset and suffixed with .msk,
6200 * with either one band (in the GMF_PER_DATASET case), or as many bands as the
6201 * main dataset.
6202 * It must have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
6203 * level, where xx matches the band number of a band of the main dataset. The
6204 * value of those items is a combination of the flags GMF_ALL_VALID,
6205 * GMF_PER_DATASET, GMF_ALPHA and GMF_NODATA. If a metadata item is missing for
6206 * a band, then the other rules explained above will be used to generate a
6207 * on-the-fly mask band.
6208 * \see CreateMaskBand() for the characteristics of .msk files created by GDAL.
6209 *
6210 * This method is the same as the C function GDALGetMaskFlags().
6211 *
6212 * @since GDAL 1.5.0
6213 *
6214 * @return a valid mask band.
6215 *
6216 * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
6217 *
6218 */
6219 int GDALRasterBand::GetMaskFlags()
6220
6221 {
6222 // If we don't have a band yet, force this now so that the masks value
6223 // will be initialized.
6224
6225 if( poMask == nullptr )
6226 GetMaskBand();
6227
6228 return nMaskFlags;
6229 }
6230
6231 /************************************************************************/
6232 /* GDALGetMaskFlags() */
6233 /************************************************************************/
6234
6235 /**
6236 * \brief Return the status flags of the mask band associated with the band.
6237 *
6238 * @see GDALRasterBand::GetMaskFlags()
6239 */
6240
6241 int CPL_STDCALL GDALGetMaskFlags( GDALRasterBandH hBand )
6242
6243 {
6244 VALIDATE_POINTER1( hBand, "GDALGetMaskFlags", GMF_ALL_VALID );
6245
6246 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
6247 return poBand->GetMaskFlags();
6248 }
6249
6250 /************************************************************************/
6251 /* InvalidateMaskBand() */
6252 /************************************************************************/
6253
6254 //! @cond Doxygen_Suppress
6255 void GDALRasterBand::InvalidateMaskBand()
6256 {
6257 if (bOwnMask)
6258 delete poMask;
6259 bOwnMask = false;
6260 nMaskFlags = 0;
6261 poMask = nullptr;
6262 }
6263 //! @endcond
6264
6265 /************************************************************************/
6266 /* CreateMaskBand() */
6267 /************************************************************************/
6268
6269 /**
6270 * \brief Adds a mask band to the current band
6271 *
6272 * The default implementation of the CreateMaskBand() method is implemented
6273 * based on similar rules to the .ovr handling implemented using the
6274 * GDALDefaultOverviews object. A TIFF file with the extension .msk will
6275 * be created with the same basename as the original file, and it will have
6276 * as many bands as the original image (or just one for GMF_PER_DATASET).
6277 * The mask images will be deflate compressed tiled images with the same
6278 * block size as the original image if possible.
6279 * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
6280 * level, where xx matches the band number of a band of the main dataset. The
6281 * value of those items will be the one of the nFlagsIn parameter.
6282 *
6283 * Note that if you got a mask band with a previous call to GetMaskBand(),
6284 * it might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
6285 * again.
6286 *
6287 * This method is the same as the C function GDALCreateMaskBand().
6288 *
6289 * @since GDAL 1.5.0
6290 *
6291 * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
6292 *
6293 * @return CE_None on success or CE_Failure on an error.
6294 *
6295 * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
6296 * @see GDALDataset::CreateMaskBand()
6297 *
6298 */
6299
6300 CPLErr GDALRasterBand::CreateMaskBand( int nFlagsIn )
6301
6302 {
6303 if( poDS != nullptr && poDS->oOvManager.IsInitialized() )
6304 {
6305 const CPLErr eErr = poDS->oOvManager.CreateMaskBand( nFlagsIn, nBand );
6306 if (eErr != CE_None)
6307 return eErr;
6308
6309 InvalidateMaskBand();
6310
6311 return CE_None;
6312 }
6313
6314 ReportError( CE_Failure, CPLE_NotSupported,
6315 "CreateMaskBand() not supported for this band." );
6316
6317 return CE_Failure;
6318 }
6319
6320 /************************************************************************/
6321 /* GDALCreateMaskBand() */
6322 /************************************************************************/
6323
6324 /**
6325 * \brief Adds a mask band to the current band
6326 *
6327 * @see GDALRasterBand::CreateMaskBand()
6328 */
6329
6330 CPLErr CPL_STDCALL GDALCreateMaskBand( GDALRasterBandH hBand, int nFlags )
6331
6332 {
6333 VALIDATE_POINTER1( hBand, "GDALCreateMaskBand", CE_Failure );
6334
6335 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
6336 return poBand->CreateMaskBand( nFlags );
6337 }
6338
6339 /************************************************************************/
6340 /* GetIndexColorTranslationTo() */
6341 /************************************************************************/
6342
6343 /**
6344 * \brief Compute translation table for color tables.
6345 *
6346 * When the raster band has a palette index, it may be useful to compute
6347 * the "translation" of this palette to the palette of another band.
6348 * The translation tries to do exact matching first, and then approximate
6349 * matching if no exact matching is possible.
6350 * This method returns a table such that table[i] = j where i is an index
6351 * of the 'this' rasterband and j the corresponding index for the reference
6352 * rasterband.
6353 *
6354 * This method is thought as internal to GDAL and is used for drivers
6355 * like RPFTOC.
6356 *
6357 * The implementation only supports 1-byte palette rasterbands.
6358 *
6359 * @param poReferenceBand the raster band
6360 * @param pTranslationTable an already allocated translation table (at least 256 bytes),
6361 * or NULL to let the method allocate it
6362 * @param pApproximateMatching a pointer to a flag that is set if the matching
6363 * is approximate. May be NULL.
6364 *
6365 * @return a translation table if the two bands are palette index and that they do
6366 * not match or NULL in other cases.
6367 * The table must be freed with CPLFree if NULL was passed for pTranslationTable.
6368 */
6369
6370 unsigned char* GDALRasterBand::GetIndexColorTranslationTo(
6371 GDALRasterBand* poReferenceBand,
6372 unsigned char* pTranslationTable,
6373 int* pApproximateMatching )
6374 {
6375 if (poReferenceBand == nullptr)
6376 return nullptr;
6377
6378 // cppcheck-suppress knownConditionTrueFalse
6379 if (poReferenceBand->GetColorInterpretation() == GCI_PaletteIndex &&
6380 // cppcheck-suppress knownConditionTrueFalse
6381 GetColorInterpretation() == GCI_PaletteIndex &&
6382 poReferenceBand->GetRasterDataType() == GDT_Byte &&
6383 GetRasterDataType() == GDT_Byte)
6384 {
6385 const GDALColorTable* srcColorTable = GetColorTable();
6386 GDALColorTable* destColorTable = poReferenceBand->GetColorTable();
6387 if (srcColorTable != nullptr && destColorTable != nullptr)
6388 {
6389 const int nEntries = srcColorTable->GetColorEntryCount();
6390 const int nRefEntries = destColorTable->GetColorEntryCount();
6391
6392 int bHasNoDataValueSrc = FALSE;
6393 double dfNoDataValueSrc = GetNoDataValue(&bHasNoDataValueSrc);
6394 if( !(bHasNoDataValueSrc &&
6395 dfNoDataValueSrc >= 0 && dfNoDataValueSrc <= 255 &&
6396 dfNoDataValueSrc == static_cast<int>(dfNoDataValueSrc)) )
6397 bHasNoDataValueSrc = FALSE;
6398 const int noDataValueSrc =
6399 bHasNoDataValueSrc ? static_cast<int>(dfNoDataValueSrc) : 0;
6400
6401 int bHasNoDataValueRef = FALSE;
6402 const double dfNoDataValueRef =
6403 poReferenceBand->GetNoDataValue(&bHasNoDataValueRef);
6404 if( !(bHasNoDataValueRef &&
6405 dfNoDataValueRef >= 0 && dfNoDataValueRef <= 255 &&
6406 dfNoDataValueRef == static_cast<int>(dfNoDataValueRef)) )
6407 bHasNoDataValueRef = FALSE;
6408 const int noDataValueRef =
6409 bHasNoDataValueRef ? static_cast<int>(dfNoDataValueRef) : 0;
6410
6411 bool samePalette = false;
6412
6413 if (pApproximateMatching)
6414 *pApproximateMatching = FALSE;
6415
6416 if (nEntries == nRefEntries && bHasNoDataValueSrc == bHasNoDataValueRef &&
6417 (bHasNoDataValueSrc == FALSE || noDataValueSrc == noDataValueRef))
6418 {
6419 samePalette = true;
6420 for( int i = 0; i < nEntries; ++i )
6421 {
6422 if (noDataValueSrc == i)
6423 continue;
6424 const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
6425 const GDALColorEntry* entryRef = destColorTable->GetColorEntry(i);
6426 if (entry->c1 != entryRef->c1 ||
6427 entry->c2 != entryRef->c2 ||
6428 entry->c3 != entryRef->c3)
6429 {
6430 samePalette = false;
6431 }
6432 }
6433 }
6434
6435 if( !samePalette )
6436 {
6437 if (pTranslationTable == nullptr)
6438 {
6439 pTranslationTable = static_cast<unsigned char *>(
6440 VSI_CALLOC_VERBOSE(1, std::max(256, nEntries)) );
6441 if( pTranslationTable == nullptr )
6442 return nullptr;
6443 }
6444
6445 // Trying to remap the product palette on the subdataset
6446 // palette.
6447 for( int i = 0; i < nEntries; ++i )
6448 {
6449 if( bHasNoDataValueSrc && bHasNoDataValueRef &&
6450 noDataValueSrc == i )
6451 continue;
6452 const GDALColorEntry* entry =
6453 srcColorTable->GetColorEntry(i);
6454 bool bMatchFound = false;
6455 for( int j = 0; j < nRefEntries; ++j )
6456 {
6457 if (bHasNoDataValueRef && noDataValueRef == j)
6458 continue;
6459 const GDALColorEntry* entryRef =
6460 destColorTable->GetColorEntry(j);
6461 if( entry->c1 == entryRef->c1 &&
6462 entry->c2 == entryRef->c2 &&
6463 entry->c3 == entryRef->c3 )
6464 {
6465 pTranslationTable[i] =
6466 static_cast<unsigned char>(j);
6467 bMatchFound = true;
6468 break;
6469 }
6470 }
6471 if( !bMatchFound )
6472 {
6473 // No exact match. Looking for closest color now.
6474 int best_j = 0;
6475 int best_distance = 0;
6476 if( pApproximateMatching )
6477 *pApproximateMatching = TRUE;
6478 for( int j = 0; j < nRefEntries; ++j )
6479 {
6480 const GDALColorEntry* entryRef =
6481 destColorTable->GetColorEntry(j);
6482 int distance =
6483 (entry->c1 - entryRef->c1) *
6484 (entry->c1 - entryRef->c1) +
6485 (entry->c2 - entryRef->c2) *
6486 (entry->c2 - entryRef->c2) +
6487 (entry->c3 - entryRef->c3) *
6488 (entry->c3 - entryRef->c3);
6489 if( j == 0 || distance < best_distance )
6490 {
6491 best_j = j;
6492 best_distance = distance;
6493 }
6494 }
6495 pTranslationTable[i] =
6496 static_cast<unsigned char>(best_j);
6497 }
6498 }
6499 if( bHasNoDataValueRef && bHasNoDataValueSrc )
6500 pTranslationTable[noDataValueSrc] =
6501 static_cast<unsigned char>( noDataValueRef );
6502
6503 return pTranslationTable;
6504 }
6505 }
6506 }
6507 return nullptr;
6508 }
6509
6510 /************************************************************************/
6511 /* SetFlushBlockErr() */
6512 /************************************************************************/
6513
6514 /**
6515 * \brief Store that an error occurred while writing a dirty block.
6516 *
6517 * This function stores the fact that an error occurred while writing a dirty
6518 * block from GDALRasterBlock::FlushCacheBlock(). Indeed when dirty blocks are
6519 * flushed when the block cache get full, it is not convenient/possible to
6520 * report that a dirty block could not be written correctly. This function
6521 * remembers the error and re-issue it from GDALRasterBand::FlushCache(),
6522 * GDALRasterBand::WriteBlock() and GDALRasterBand::RasterIO(), which are
6523 * places where the user can easily match the error with the relevant dataset.
6524 */
6525
6526 void GDALRasterBand::SetFlushBlockErr( CPLErr eErr )
6527 {
6528 eFlushBlockErr = eErr;
6529 }
6530
6531 /************************************************************************/
6532 /* IncDirtyBlocks() */
6533 /************************************************************************/
6534
6535 /**
6536 * \brief Increment/decrement the number of dirty blocks
6537 */
6538
6539 void GDALRasterBand::IncDirtyBlocks( int nInc )
6540 {
6541 if( poBandBlockCache )
6542 poBandBlockCache->IncDirtyBlocks(nInc);
6543 }
6544
6545 /************************************************************************/
6546 /* ReportError() */
6547 /************************************************************************/
6548
6549 #ifndef DOXYGEN_XML
6550 /**
6551 * \brief Emits an error related to a raster band.
6552 *
6553 * This function is a wrapper for regular CPLError(). The only difference
6554 * with CPLError() is that it prepends the error message with the dataset
6555 * name and the band number.
6556 *
6557 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
6558 * @param err_no the error number (CPLE_*) from cpl_error.h.
6559 * @param fmt a printf() style format string. Any additional arguments
6560 * will be treated as arguments to fill in this format in a manner
6561 * similar to printf().
6562 *
6563 * @since GDAL 1.9.0
6564 */
6565
6566 void GDALRasterBand::ReportError( CPLErr eErrClass, CPLErrorNum err_no,
6567 const char *fmt, ... )
6568 {
6569 va_list args;
6570
6571 va_start(args, fmt);
6572
6573 char szNewFmt[256] = { '\0' };
6574 const char* pszDSName = poDS ? poDS->GetDescription() : "";
6575 if( strlen(fmt) + strlen(pszDSName) + 20 >= sizeof(szNewFmt) - 1 )
6576 pszDSName = CPLGetFilename(pszDSName);
6577 if( pszDSName[0] != '\0' && strchr(pszDSName, '%') == nullptr &&
6578 strlen(fmt) + strlen(pszDSName) + 20 < sizeof(szNewFmt) - 1 )
6579 {
6580 snprintf(szNewFmt, sizeof(szNewFmt), "%s, band %d: %s",
6581 pszDSName, GetBand(), fmt);
6582 CPLErrorV( eErrClass, err_no, szNewFmt, args );
6583 }
6584 else
6585 {
6586 CPLErrorV( eErrClass, err_no, fmt, args );
6587 }
6588 va_end(args);
6589 }
6590 #endif
6591
6592 /************************************************************************/
6593 /* GetVirtualMemAuto() */
6594 /************************************************************************/
6595
6596 /** \brief Create a CPLVirtualMem object from a GDAL raster band object.
6597 *
6598 * Only supported on Linux and Unix systems with mmap() for now.
6599 *
6600 * This method allows creating a virtual memory object for a GDALRasterBand,
6601 * that exposes the whole image data as a virtual array.
6602 *
6603 * The default implementation relies on GDALRasterBandGetVirtualMem(), but specialized
6604 * implementation, such as for raw files, may also directly use mechanisms of the
6605 * operating system to create a view of the underlying file into virtual memory
6606 * ( CPLVirtualMemFileMapNew() )
6607 *
6608 * At the time of writing, the GeoTIFF driver and "raw" drivers (EHdr, ...) offer
6609 * a specialized implementation with direct file mapping, provided that some
6610 * requirements are met :
6611 * - for all drivers, the dataset must be backed by a "real" file in the file
6612 * system, and the byte ordering of multi-byte datatypes (Int16, etc.)
6613 * must match the native ordering of the CPU.
6614 * - in addition, for the GeoTIFF driver, the GeoTIFF file must be uncompressed, scanline
6615 * oriented (i.e. not tiled). Strips must be organized in the file in sequential
6616 * order, and be equally spaced (which is generally the case). Only power-of-two
6617 * bit depths are supported (8 for GDT_Bye, 16 for GDT_Int16/GDT_UInt16,
6618 * 32 for GDT_Float32 and 64 for GDT_Float64)
6619 *
6620 * The pointer returned remains valid until CPLVirtualMemFree() is called.
6621 * CPLVirtualMemFree() must be called before the raster band object is destroyed.
6622 *
6623 * If p is such a pointer and base_type the type matching GDALGetRasterDataType(),
6624 * the element of image coordinates (x, y) can be accessed with
6625 * *(base_type*) ((GByte*)p + x * *pnPixelSpace + y * *pnLineSpace)
6626 *
6627 * This method is the same as the C GDALGetVirtualMemAuto() function.
6628 *
6629 * @param eRWFlag Either GF_Read to read the band, or GF_Write to
6630 * read/write the band.
6631 *
6632 * @param pnPixelSpace Output parameter giving the byte offset from the start of one pixel value in
6633 * the buffer to the start of the next pixel value within a scanline.
6634 *
6635 * @param pnLineSpace Output parameter giving the byte offset from the start of one scanline in
6636 * the buffer to the start of the next.
6637 *
6638 * @param papszOptions NULL terminated list of options.
6639 * If a specialized implementation exists, defining USE_DEFAULT_IMPLEMENTATION=YES
6640 * will cause the default implementation to be used.
6641 * On the contrary, starting with GDAL 2.2, defining USE_DEFAULT_IMPLEMENTATION=NO
6642 * will prevent the default implementation from being used (thus only allowing
6643 * efficient implementations to be used).
6644 * When requiring or falling back to the default implementation, the following
6645 * options are available : CACHE_SIZE (in bytes, defaults to 40 MB),
6646 * PAGE_SIZE_HINT (in bytes),
6647 * SINGLE_THREAD ("FALSE" / "TRUE", defaults to FALSE)
6648 *
6649 * @return a virtual memory object that must be unreferenced by CPLVirtualMemFree(),
6650 * or NULL in case of failure.
6651 *
6652 * @since GDAL 1.11
6653 */
6654
6655 CPLVirtualMem *GDALRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
6656 int *pnPixelSpace,
6657 GIntBig *pnLineSpace,
6658 char **papszOptions )
6659 {
6660 const char* pszImpl = CSLFetchNameValueDef(
6661 papszOptions, "USE_DEFAULT_IMPLEMENTATION", "AUTO");
6662 if( EQUAL(pszImpl, "NO") || EQUAL(pszImpl, "OFF") ||
6663 EQUAL(pszImpl, "0") || EQUAL(pszImpl, "FALSE") )
6664 {
6665 return nullptr;
6666 }
6667
6668 const int nPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
6669 const GIntBig nLineSpace = static_cast<GIntBig>(nRasterXSize) * nPixelSpace;
6670 if( pnPixelSpace )
6671 *pnPixelSpace = nPixelSpace;
6672 if( pnLineSpace )
6673 *pnLineSpace = nLineSpace;
6674 const size_t nCacheSize = atoi(
6675 CSLFetchNameValueDef(papszOptions, "CACHE_SIZE", "40000000"));
6676 const size_t nPageSizeHint = atoi(
6677 CSLFetchNameValueDef(papszOptions, "PAGE_SIZE_HINT", "0") );
6678 const bool bSingleThreadUsage =
6679 CPLTestBool( CSLFetchNameValueDef( papszOptions,
6680 "SINGLE_THREAD", "FALSE" ) );
6681 return GDALRasterBandGetVirtualMem( GDALRasterBand::ToHandle(this),
6682 eRWFlag,
6683 0, 0, nRasterXSize, nRasterYSize,
6684 nRasterXSize, nRasterYSize,
6685 eDataType,
6686 nPixelSpace, nLineSpace,
6687 nCacheSize,
6688 nPageSizeHint,
6689 bSingleThreadUsage,
6690 papszOptions );
6691 }
6692
6693 /************************************************************************/
6694 /* GDALGetVirtualMemAuto() */
6695 /************************************************************************/
6696
6697 /**
6698 * \brief Create a CPLVirtualMem object from a GDAL raster band object.
6699 *
6700 * @see GDALRasterBand::GetVirtualMemAuto()
6701 */
6702
6703 CPLVirtualMem * GDALGetVirtualMemAuto( GDALRasterBandH hBand,
6704 GDALRWFlag eRWFlag,
6705 int *pnPixelSpace,
6706 GIntBig *pnLineSpace,
6707 CSLConstList papszOptions )
6708 {
6709 VALIDATE_POINTER1( hBand, "GDALGetVirtualMemAuto", nullptr );
6710
6711 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
6712
6713 return poBand->GetVirtualMemAuto( eRWFlag, pnPixelSpace,
6714 pnLineSpace,
6715 const_cast<char**>(papszOptions) );
6716 }
6717
6718 /************************************************************************/
6719 /* GDALGetDataCoverageStatus() */
6720 /************************************************************************/
6721
6722 /**
6723 * \brief Get the coverage status of a sub-window of the raster.
6724 *
6725 * Returns whether a sub-window of the raster contains only data, only empty
6726 * blocks or a mix of both. This function can be used to determine quickly
6727 * if it is worth issuing RasterIO / ReadBlock requests in datasets that may
6728 * be sparse.
6729 *
6730 * Empty blocks are blocks that are generally not physically present in the
6731 * file, and when read through GDAL, contain only pixels whose value is the
6732 * nodata value when it is set, or whose value is 0 when the nodata value is
6733 * not set.
6734 *
6735 * The query is done in an efficient way without reading the actual pixel
6736 * values. If not possible, or not implemented at all by the driver,
6737 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | GDAL_DATA_COVERAGE_STATUS_DATA will
6738 * be returned.
6739 *
6740 * The values that can be returned by the function are the following,
6741 * potentially combined with the binary or operator :
6742 * <ul>
6743 * <li>GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED : the driver does not implement
6744 * GetDataCoverageStatus(). This flag should be returned together with
6745 * GDAL_DATA_COVERAGE_STATUS_DATA.</li>
6746 * <li>GDAL_DATA_COVERAGE_STATUS_DATA: There is (potentially) data in the queried
6747 * window.</li>
6748 * <li>GDAL_DATA_COVERAGE_STATUS_EMPTY: There is nodata in the queried window.
6749 * This is typically identified by the concept of missing block in formats that
6750 * supports it.
6751 * </li>
6752 * </ul>
6753 *
6754 * Note that GDAL_DATA_COVERAGE_STATUS_DATA might have false positives and
6755 * should be interpreted more as hint of potential presence of data. For example
6756 * if a GeoTIFF file is created with blocks filled with zeroes (or set to the
6757 * nodata value), instead of using the missing block mechanism,
6758 * GDAL_DATA_COVERAGE_STATUS_DATA will be returned. On the contrary,
6759 * GDAL_DATA_COVERAGE_STATUS_EMPTY should have no false positives.
6760 *
6761 * The nMaskFlagStop should be generally set to 0. It can be set to a
6762 * binary-or'ed mask of the above mentioned values to enable a quick exiting of
6763 * the function as soon as the computed mask matches the nMaskFlagStop. For
6764 * example, you can issue a request on the whole raster with nMaskFlagStop =
6765 * GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon as one missing block is encountered,
6766 * the function will exit, so that you can potentially refine the requested area
6767 * to find which particular region(s) have missing blocks.
6768 *
6769 * @see GDALRasterBand::GetDataCoverageStatus()
6770 *
6771 * @param hBand raster band
6772 *
6773 * @param nXOff The pixel offset to the top left corner of the region
6774 * of the band to be queried. This would be zero to start from the left side.
6775 *
6776 * @param nYOff The line offset to the top left corner of the region
6777 * of the band to be queried. This would be zero to start from the top.
6778 *
6779 * @param nXSize The width of the region of the band to be queried in pixels.
6780 *
6781 * @param nYSize The height of the region of the band to be queried in lines.
6782 *
6783 * @param nMaskFlagStop 0, or a binary-or'ed mask of possible values
6784 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
6785 * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon
6786 * as the computation of the coverage matches the mask, the computation will be
6787 * stopped. *pdfDataPct will not be valid in that case.
6788 *
6789 * @param pdfDataPct Optional output parameter whose pointed value will be set
6790 * to the (approximate) percentage in [0,100] of pixels in the queried
6791 * sub-window that have valid values. The implementation might not always be
6792 * able to compute it, in which case it will be set to a negative value.
6793 *
6794 * @return a binary-or'ed combination of possible values
6795 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
6796 * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY
6797 *
6798 * @note Added in GDAL 2.2
6799 */
6800
6801 int CPL_STDCALL GDALGetDataCoverageStatus( GDALRasterBandH hBand,
6802 int nXOff, int nYOff,
6803 int nXSize,
6804 int nYSize,
6805 int nMaskFlagStop,
6806 double* pdfDataPct)
6807 {
6808 VALIDATE_POINTER1( hBand, "GDALGetDataCoverageStatus",
6809 GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED );
6810
6811 GDALRasterBand *poBand = GDALRasterBand::FromHandle(hBand);
6812
6813 return poBand->GetDataCoverageStatus( nXOff, nYOff, nXSize, nYSize,
6814 nMaskFlagStop, pdfDataPct );
6815 }
6816
6817 /************************************************************************/
6818 /* GetDataCoverageStatus() */
6819 /************************************************************************/
6820
6821 /**
6822 * \fn GDALRasterBand::IGetDataCoverageStatus( int nXOff,
6823 * int nYOff,
6824 * int nXSize,
6825 * int nYSize,
6826 * int nMaskFlagStop,
6827 * double* pdfDataPct)
6828 * \brief Get the coverage status of a sub-window of the raster.
6829 *
6830 * Returns whether a sub-window of the raster contains only data, only empty
6831 * blocks or a mix of both. This function can be used to determine quickly
6832 * if it is worth issuing RasterIO / ReadBlock requests in datasets that may
6833 * be sparse.
6834 *
6835 * Empty blocks are blocks that contain only pixels whose value is the nodata
6836 * value when it is set, or whose value is 0 when the nodata value is not set.
6837 *
6838 * The query is done in an efficient way without reading the actual pixel
6839 * values. If not possible, or not implemented at all by the driver,
6840 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | GDAL_DATA_COVERAGE_STATUS_DATA will
6841 * be returned.
6842 *
6843 * The values that can be returned by the function are the following,
6844 * potentially combined with the binary or operator :
6845 * <ul>
6846 * <li>GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED : the driver does not implement
6847 * GetDataCoverageStatus(). This flag should be returned together with
6848 * GDAL_DATA_COVERAGE_STATUS_DATA.</li>
6849 * <li>GDAL_DATA_COVERAGE_STATUS_DATA: There is (potentially) data in the queried
6850 * window.</li>
6851 * <li>GDAL_DATA_COVERAGE_STATUS_EMPTY: There is nodata in the queried window.
6852 * This is typically identified by the concept of missing block in formats that
6853 * supports it.
6854 * </li>
6855 * </ul>
6856 *
6857 * Note that GDAL_DATA_COVERAGE_STATUS_DATA might have false positives and
6858 * should be interpreted more as hint of potential presence of data. For example
6859 * if a GeoTIFF file is created with blocks filled with zeroes (or set to the
6860 * nodata value), instead of using the missing block mechanism,
6861 * GDAL_DATA_COVERAGE_STATUS_DATA will be returned. On the contrary,
6862 * GDAL_DATA_COVERAGE_STATUS_EMPTY should have no false positives.
6863 *
6864 * The nMaskFlagStop should be generally set to 0. It can be set to a
6865 * binary-or'ed mask of the above mentioned values to enable a quick exiting of
6866 * the function as soon as the computed mask matches the nMaskFlagStop. For
6867 * example, you can issue a request on the whole raster with nMaskFlagStop =
6868 * GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon as one missing block is encountered,
6869 * the function will exit, so that you can potentially refine the requested area
6870 * to find which particular region(s) have missing blocks.
6871 *
6872 * @see GDALGetDataCoverageStatus()
6873 *
6874 * @param nXOff The pixel offset to the top left corner of the region
6875 * of the band to be queried. This would be zero to start from the left side.
6876 *
6877 * @param nYOff The line offset to the top left corner of the region
6878 * of the band to be queried. This would be zero to start from the top.
6879 *
6880 * @param nXSize The width of the region of the band to be queried in pixels.
6881 *
6882 * @param nYSize The height of the region of the band to be queried in lines.
6883 *
6884 * @param nMaskFlagStop 0, or a binary-or'ed mask of possible values
6885 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
6886 * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon
6887 * as the computation of the coverage matches the mask, the computation will be
6888 * stopped. *pdfDataPct will not be valid in that case.
6889 *
6890 * @param pdfDataPct Optional output parameter whose pointed value will be set
6891 * to the (approximate) percentage in [0,100] of pixels in the queried
6892 * sub-window that have valid values. The implementation might not always be
6893 * able to compute it, in which case it will be set to a negative value.
6894 *
6895 * @return a binary-or'ed combination of possible values
6896 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
6897 * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY
6898 *
6899 * @note Added in GDAL 2.2
6900 */
6901
6902 /**
6903 * \brief Get the coverage status of a sub-window of the raster.
6904 *
6905 * Returns whether a sub-window of the raster contains only data, only empty
6906 * blocks or a mix of both. This function can be used to determine quickly
6907 * if it is worth issuing RasterIO / ReadBlock requests in datasets that may
6908 * be sparse.
6909 *
6910 * Empty blocks are blocks that contain only pixels whose value is the nodata
6911 * value when it is set, or whose value is 0 when the nodata value is not set.
6912 *
6913 * The query is done in an efficient way without reading the actual pixel
6914 * values. If not possible, or not implemented at all by the driver,
6915 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | GDAL_DATA_COVERAGE_STATUS_DATA will
6916 * be returned.
6917 *
6918 * The values that can be returned by the function are the following,
6919 * potentially combined with the binary or operator :
6920 * <ul>
6921 * <li>GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED : the driver does not implement
6922 * GetDataCoverageStatus(). This flag should be returned together with
6923 * GDAL_DATA_COVERAGE_STATUS_DATA.</li>
6924 * <li>GDAL_DATA_COVERAGE_STATUS_DATA: There is (potentially) data in the queried
6925 * window.</li>
6926 * <li>GDAL_DATA_COVERAGE_STATUS_EMPTY: There is nodata in the queried window.
6927 * This is typically identified by the concept of missing block in formats that
6928 * supports it.
6929 * </li>
6930 * </ul>
6931 *
6932 * Note that GDAL_DATA_COVERAGE_STATUS_DATA might have false positives and
6933 * should be interpreted more as hint of potential presence of data. For example
6934 * if a GeoTIFF file is created with blocks filled with zeroes (or set to the
6935 * nodata value), instead of using the missing block mechanism,
6936 * GDAL_DATA_COVERAGE_STATUS_DATA will be returned. On the contrary,
6937 * GDAL_DATA_COVERAGE_STATUS_EMPTY should have no false positives.
6938 *
6939 * The nMaskFlagStop should be generally set to 0. It can be set to a
6940 * binary-or'ed mask of the above mentioned values to enable a quick exiting of
6941 * the function as soon as the computed mask matches the nMaskFlagStop. For
6942 * example, you can issue a request on the whole raster with nMaskFlagStop =
6943 * GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon as one missing block is encountered,
6944 * the function will exit, so that you can potentially refine the requested area
6945 * to find which particular region(s) have missing blocks.
6946 *
6947 * @see GDALGetDataCoverageStatus()
6948 *
6949 * @param nXOff The pixel offset to the top left corner of the region
6950 * of the band to be queried. This would be zero to start from the left side.
6951 *
6952 * @param nYOff The line offset to the top left corner of the region
6953 * of the band to be queried. This would be zero to start from the top.
6954 *
6955 * @param nXSize The width of the region of the band to be queried in pixels.
6956 *
6957 * @param nYSize The height of the region of the band to be queried in lines.
6958 *
6959 * @param nMaskFlagStop 0, or a binary-or'ed mask of possible values
6960 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
6961 * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon
6962 * as the computation of the coverage matches the mask, the computation will be
6963 * stopped. *pdfDataPct will not be valid in that case.
6964 *
6965 * @param pdfDataPct Optional output parameter whose pointed value will be set
6966 * to the (approximate) percentage in [0,100] of pixels in the queried
6967 * sub-window that have valid values. The implementation might not always be
6968 * able to compute it, in which case it will be set to a negative value.
6969 *
6970 * @return a binary-or'ed combination of possible values
6971 * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
6972 * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY
6973 *
6974 * @note Added in GDAL 2.2
6975 */
6976
6977 int GDALRasterBand::GetDataCoverageStatus( int nXOff,
6978 int nYOff,
6979 int nXSize,
6980 int nYSize,
6981 int nMaskFlagStop,
6982 double* pdfDataPct)
6983 {
6984 if( nXOff < 0 || nYOff < 0 ||
6985 nXSize > INT_MAX - nXOff ||
6986 nYSize > INT_MAX - nYOff ||
6987 nXOff + nXSize > nRasterXSize ||
6988 nYOff + nYSize > nRasterYSize )
6989 {
6990 CPLError(CE_Failure, CPLE_AppDefined, "Bad window");
6991 if( pdfDataPct )
6992 *pdfDataPct = 0.0;
6993 return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED |
6994 GDAL_DATA_COVERAGE_STATUS_EMPTY;
6995 }
6996 return IGetDataCoverageStatus(nXOff, nYOff, nXSize, nYSize,
6997 nMaskFlagStop, pdfDataPct);
6998 }
6999
7000 /************************************************************************/
7001 /* IGetDataCoverageStatus() */
7002 /************************************************************************/
7003
7004 int GDALRasterBand::IGetDataCoverageStatus( int /*nXOff*/,
7005 int /*nYOff*/,
7006 int /*nXSize*/,
7007 int /*nYSize*/,
7008 int /*nMaskFlagStop*/,
7009 double* pdfDataPct)
7010 {
7011 if( pdfDataPct != nullptr )
7012 *pdfDataPct = 100.0;
7013 return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED |
7014 GDAL_DATA_COVERAGE_STATUS_DATA;
7015 }
7016
7017 //! @cond Doxygen_Suppress
7018 /************************************************************************/
7019 /* EnterReadWrite() */
7020 /************************************************************************/
7021
7022 int GDALRasterBand::EnterReadWrite( GDALRWFlag eRWFlag )
7023 {
7024 if( poDS != nullptr )
7025 return poDS->EnterReadWrite(eRWFlag);
7026 return FALSE;
7027 }
7028
7029 /************************************************************************/
7030 /* LeaveReadWrite() */
7031 /************************************************************************/
7032
7033 void GDALRasterBand::LeaveReadWrite()
7034 {
7035 if( poDS != nullptr )
7036 poDS->LeaveReadWrite();
7037 }
7038
7039 /************************************************************************/
7040 /* InitRWLock() */
7041 /************************************************************************/
7042
7043 void GDALRasterBand::InitRWLock()
7044 {
7045 if( poDS != nullptr )
7046 poDS->InitRWLock();
7047 }
7048
7049 //! @endcond
7050
7051 /**
7052 * \fn GDALRasterBand::SetMetadata( char ** papszMetadata, const char * pszDomain)
7053 * \brief Set metadata.
7054 *
7055 * CAUTION: depending on the format, older values of the updated information might
7056 * still be found in the file in a "ghost" state, even if no longer accessible
7057 * through the GDAL API. This is for example the case of the GTiff format (this is
7058 * not a exhaustive list)
7059 *
7060 * The C function GDALSetMetadata() does the same thing as this method.
7061 *
7062 * @param papszMetadata the metadata in name=value string list format to
7063 * apply.
7064 * @param pszDomain the domain of interest. Use "" or NULL for the default
7065 * domain.
7066 * @return CE_None on success, CE_Failure on failure and CE_Warning if the
7067 * metadata has been accepted, but is likely not maintained persistently
7068 * by the underlying object between sessions.
7069 */
7070
7071 /**
7072 * \fn GDALRasterBand::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
7073 * \brief Set single metadata item.
7074 *
7075 * CAUTION: depending on the format, older values of the updated information might
7076 * still be found in the file in a "ghost" state, even if no longer accessible
7077 * through the GDAL API. This is for example the case of the GTiff format (this is
7078 * not a exhaustive list)
7079 *
7080 * The C function GDALSetMetadataItem() does the same thing as this method.
7081 *
7082 * @param pszName the key for the metadata item to fetch.
7083 * @param pszValue the value to assign to the key.
7084 * @param pszDomain the domain to set within, use NULL for the default domain.
7085 *
7086 * @return CE_None on success, or an error code on failure.
7087 */
7088
7089 /************************************************************************/
7090 /* GDALMDArrayFromRasterBand */
7091 /************************************************************************/
7092
7093 class GDALMDArrayFromRasterBand final: public GDALMDArray
7094 {
7095 CPL_DISALLOW_COPY_ASSIGN(GDALMDArrayFromRasterBand)
7096
7097 GDALDataset* m_poDS;
7098 GDALRasterBand* m_poBand;
7099 GDALExtendedDataType m_dt;
7100 std::vector<std::shared_ptr<GDALDimension>> m_dims{};
7101 std::string m_osUnit;
7102 std::vector<GByte> m_pabyNoData{};
7103 std::shared_ptr<GDALMDArray> m_varX{};
7104 std::shared_ptr<GDALMDArray> m_varY{};
7105
7106 bool ReadWrite(GDALRWFlag eRWFlag,
7107 const GUInt64* arrayStartIdx,
7108 const size_t* count,
7109 const GInt64* arrayStep,
7110 const GPtrDiff_t* bufferStride,
7111 const GDALExtendedDataType& bufferDataType,
7112 void* pBuffer) const;
7113
7114 protected:
7115 GDALMDArrayFromRasterBand(GDALDataset* poDS,
7116 GDALRasterBand* poBand):
7117 GDALAbstractMDArray( std::string(),
7118 std::string(poDS->GetDescription()) +
7119 CPLSPrintf(" band %d", poBand->GetBand()) ),
7120 GDALMDArray( std::string(),
7121 std::string(poDS->GetDescription()) +
7122 CPLSPrintf(" band %d", poBand->GetBand()) ),
7123 m_poDS(poDS),
7124 m_poBand(poBand),
7125 m_dt(GDALExtendedDataType::Create(poBand->GetRasterDataType())),
7126 m_osUnit( poBand->GetUnitType() )
7127 {
7128 m_poDS->Reference();
7129
7130 int bHasNoData = false;
7131 double dfNoData = m_poBand->GetNoDataValue(&bHasNoData);
7132 if( bHasNoData )
7133 {
7134 m_pabyNoData.resize(m_dt.GetSize());
7135 GDALCopyWords(&dfNoData, GDT_Float64, 0,
7136 &m_pabyNoData[0], m_dt.GetNumericDataType(), 0,
7137 1);
7138 }
7139
7140 const int nXSize = poBand->GetXSize();
7141 const int nYSize = poBand->GetYSize();
7142
7143 auto poSRS = m_poDS->GetSpatialRef();
7144 std::string osTypeY;
7145 std::string osTypeX;
7146 std::string osDirectionY;
7147 std::string osDirectionX;
7148 if( poSRS && poSRS->GetAxesCount() == 2 )
7149 {
7150 const auto mapping = poSRS->GetDataAxisToSRSAxisMapping();
7151 OGRAxisOrientation eOrientation1 = OAO_Other;
7152 poSRS->GetAxis(nullptr, 0, &eOrientation1 );
7153 OGRAxisOrientation eOrientation2 = OAO_Other;
7154 poSRS->GetAxis(nullptr, 1, &eOrientation2 );
7155 if( eOrientation1 == OAO_East && eOrientation2 == OAO_North )
7156 {
7157 if( mapping == std::vector<int>{1,2} )
7158 {
7159 osTypeY = GDAL_DIM_TYPE_HORIZONTAL_Y;
7160 osDirectionY = "NORTH";
7161 osTypeX = GDAL_DIM_TYPE_HORIZONTAL_X;
7162 osDirectionX = "EAST";
7163 }
7164 }
7165 else if( eOrientation1 == OAO_North && eOrientation2 == OAO_East )
7166 {
7167 if( mapping == std::vector<int>{2,1} )
7168 {
7169 osTypeY = GDAL_DIM_TYPE_HORIZONTAL_Y;
7170 osDirectionY = "NORTH";
7171 osTypeX = GDAL_DIM_TYPE_HORIZONTAL_X;
7172 osDirectionX = "EAST";
7173 }
7174 }
7175 }
7176
7177 m_dims = {
7178 std::make_shared<GDALDimensionWeakIndexingVar>(
7179 "/", "Y", osTypeY, osDirectionY, nYSize),
7180 std::make_shared<GDALDimensionWeakIndexingVar>(
7181 "/", "X", osTypeX, osDirectionX, nXSize)
7182 };
7183
7184 double adfGeoTransform[6];
7185 if( m_poDS->GetGeoTransform(adfGeoTransform) == CE_None &&
7186 adfGeoTransform[2] == 0 && adfGeoTransform[4] == 0 )
7187 {
7188 m_varX = std::make_shared<GDALMDArrayRegularlySpaced>(
7189 "/", "X", m_dims[1],
7190 adfGeoTransform[0],
7191 adfGeoTransform[1], 0.5);
7192 m_dims[1]->SetIndexingVariable(m_varX);
7193
7194 m_varY = std::make_shared<GDALMDArrayRegularlySpaced>(
7195 "/", "Y", m_dims[0],
7196 adfGeoTransform[3],
7197 adfGeoTransform[5], 0.5);
7198 m_dims[0]->SetIndexingVariable(m_varY);
7199 }
7200 }
7201
7202 bool IRead(const GUInt64* arrayStartIdx,
7203 const size_t* count,
7204 const GInt64* arrayStep,
7205 const GPtrDiff_t* bufferStride,
7206 const GDALExtendedDataType& bufferDataType,
7207 void* pDstBuffer) const override
7208 {
7209 return ReadWrite(GF_Read, arrayStartIdx, count, arrayStep, bufferStride,
7210 bufferDataType, pDstBuffer);
7211 }
7212
7213 bool IWrite(const GUInt64* arrayStartIdx,
7214 const size_t* count,
7215 const GInt64* arrayStep,
7216 const GPtrDiff_t* bufferStride,
7217 const GDALExtendedDataType& bufferDataType,
7218 const void* pSrcBuffer) override
7219 {
7220 return ReadWrite(GF_Write, arrayStartIdx, count, arrayStep, bufferStride,
7221 bufferDataType, const_cast<void*>(pSrcBuffer));
7222 }
7223
7224 public:
7225 ~GDALMDArrayFromRasterBand()
7226 {
7227 m_poDS->ReleaseRef();
7228 }
7229
7230 static std::shared_ptr<GDALMDArray> Create(GDALDataset* poDS,
7231 GDALRasterBand* poBand)
7232 {
7233 auto array(std::shared_ptr<GDALMDArrayFromRasterBand>(
7234 new GDALMDArrayFromRasterBand(poDS, poBand)));
7235 array->SetSelf(array);
7236 return array;
7237 }
7238
7239 bool IsWritable() const override { return m_poDS->GetAccess() == GA_Update; }
7240
7241 const std::vector<std::shared_ptr<GDALDimension>>& GetDimensions() const override { return m_dims; }
7242
7243 const GDALExtendedDataType &GetDataType() const override { return m_dt; }
7244
7245 const std::string& GetUnit() const override { return m_osUnit; }
7246
7247 const void* GetRawNoDataValue() const override
7248 { return m_pabyNoData.empty() ? nullptr: m_pabyNoData.data(); }
7249
7250 double GetOffset(bool* pbHasOffset, GDALDataType* peStorageType) const override
7251 {
7252 int bHasOffset = false;
7253 double dfRes = m_poBand->GetOffset(&bHasOffset);
7254 if( pbHasOffset )
7255 *pbHasOffset = CPL_TO_BOOL(bHasOffset);
7256 if( peStorageType )
7257 *peStorageType = GDT_Unknown;
7258 return dfRes;
7259 }
7260
7261 double GetScale(bool* pbHasScale, GDALDataType* peStorageType) const override
7262 {
7263 int bHasScale = false;
7264 double dfRes = m_poBand->GetScale(&bHasScale);
7265 if( pbHasScale )
7266 *pbHasScale = CPL_TO_BOOL(bHasScale);
7267 if( peStorageType )
7268 *peStorageType = GDT_Unknown;
7269 return dfRes;
7270 }
7271
7272 std::shared_ptr<OGRSpatialReference> GetSpatialRef() const override
7273 {
7274 auto poSrcSRS = m_poDS->GetSpatialRef();
7275 if( !poSrcSRS )
7276 return nullptr;
7277 auto poSRS = std::shared_ptr<OGRSpatialReference>(poSrcSRS->Clone());
7278
7279 auto axisMapping = poSRS->GetDataAxisToSRSAxisMapping();
7280 constexpr int iYDim = 0;
7281 constexpr int iXDim = 1;
7282 for( auto& m: axisMapping )
7283 {
7284 if( m == 1 )
7285 m = iXDim + 1;
7286 else if( m == 2 )
7287 m = iYDim + 1;
7288 else
7289 m = 0;
7290 }
7291 poSRS->SetDataAxisToSRSAxisMapping(axisMapping);
7292 return poSRS;
7293 }
7294
7295 std::vector<GUInt64> GetBlockSize() const override
7296 {
7297 int nBlockXSize = 0;
7298 int nBlockYSize = 0;
7299 m_poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
7300 return std::vector<GUInt64>{ static_cast<GUInt64>(nBlockYSize),
7301 static_cast<GUInt64>(nBlockXSize) };
7302 }
7303
7304 class MDIAsAttribute: public GDALAttribute
7305 {
7306 std::vector<std::shared_ptr<GDALDimension>> m_dims{};
7307 const GDALExtendedDataType m_dt = GDALExtendedDataType::CreateString();
7308 std::string m_osValue;
7309
7310 public:
7311 MDIAsAttribute(const std::string& name, const std::string& value):
7312 GDALAbstractMDArray(std::string(), name),
7313 GDALAttribute(std::string(), name),
7314 m_osValue(value)
7315 {
7316 }
7317
7318 const std::vector<std::shared_ptr<GDALDimension>>& GetDimensions() const override { return m_dims; }
7319
7320 const GDALExtendedDataType &GetDataType() const override { return m_dt; }
7321
7322 bool IRead(const GUInt64*, const size_t*,
7323 const GInt64*, const GPtrDiff_t*,
7324 const GDALExtendedDataType& bufferDataType,
7325 void* pDstBuffer) const override
7326 {
7327 const char* pszStr = m_osValue.c_str();
7328 GDALExtendedDataType::CopyValue(&pszStr, m_dt,
7329 pDstBuffer, bufferDataType);
7330 return true;
7331 }
7332 };
7333
7334 std::vector<std::shared_ptr<GDALAttribute>> GetAttributes(CSLConstList) const override
7335 {
7336 std::vector<std::shared_ptr<GDALAttribute>> res;
7337 auto papszMD = m_poBand->GetMetadata();
7338 for( auto iter = papszMD; iter && iter[0]; ++iter )
7339 {
7340 char* pszKey = nullptr;
7341 const char* pszValue = CPLParseNameValue(*iter, &pszKey);
7342 if( pszKey && pszValue )
7343 {
7344 res.emplace_back(std::make_shared<MDIAsAttribute>(pszKey, pszValue));
7345 }
7346 CPLFree(pszKey);
7347 }
7348 return res;
7349 }
7350 };
7351
7352 /************************************************************************/
7353 /* ReadWrite() */
7354 /************************************************************************/
7355
7356 bool GDALMDArrayFromRasterBand::ReadWrite(GDALRWFlag eRWFlag,
7357 const GUInt64* arrayStartIdx,
7358 const size_t* count,
7359 const GInt64* arrayStep,
7360 const GPtrDiff_t* bufferStride,
7361 const GDALExtendedDataType& bufferDataType,
7362 void* pBuffer) const
7363 {
7364 if( bufferDataType.GetClass() != GEDTC_NUMERIC )
7365 return false;
7366 const auto eDT(bufferDataType.GetNumericDataType());
7367 const auto nDTSize(GDALGetDataTypeSizeBytes(eDT));
7368 constexpr int kX = 1;
7369 constexpr int kY = 0;
7370 const int nX = arrayStep[kX] > 0 ?
7371 static_cast<int>(arrayStartIdx[kX]) :
7372 static_cast<int>(arrayStartIdx[kX] - (count[kX]-1) * -arrayStep[kX]);
7373 const int nY = arrayStep[kY] > 0 ?
7374 static_cast<int>(arrayStartIdx[kY]) :
7375 static_cast<int>(arrayStartIdx[kY] - (count[kY]-1) * -arrayStep[kY]);
7376 const int nSizeX = static_cast<int>(count[kX] * ABS(arrayStep[kX]));
7377 const int nSizeY = static_cast<int>(count[kY] * ABS(arrayStep[kY]));
7378 GByte* pabyBuffer = static_cast<GByte*>(pBuffer);
7379 int nStrideXSign = 1;
7380 if( arrayStep[kX] < 0 )
7381 {
7382 pabyBuffer += (count[kX]-1) * bufferStride[kX] * nDTSize;
7383 nStrideXSign = -1;
7384 }
7385 int nStrideYSign = 1;
7386 if( arrayStep[kY] < 0 )
7387 {
7388 pabyBuffer += (count[kY]-1) * bufferStride[kY] * nDTSize;
7389 nStrideYSign = -1;
7390 }
7391
7392 return m_poBand->RasterIO(eRWFlag,
7393 nX, nY, nSizeX, nSizeY,
7394 pabyBuffer,
7395 static_cast<int>(count[kX]),
7396 static_cast<int>(count[kY]),
7397 eDT,
7398 static_cast<GSpacing>(nStrideXSign * bufferStride[kX] * nDTSize),
7399 static_cast<GSpacing>(nStrideYSign * bufferStride[kY] * nDTSize),
7400 nullptr) == CE_None;
7401 }
7402
7403 /************************************************************************/
7404 /* AsMDArray() */
7405 /************************************************************************/
7406
7407 /** Return a view of this raster band as a 2D multidimensional GDALMDArray.
7408 *
7409 * The band must be linked to a GDALDataset. If this dataset is not already
7410 * marked as shared, it will be, so that the returned array holds a reference
7411 * to it.
7412 *
7413 * If the dataset has a geotransform attached, the X and Y dimensions of the
7414 * returned array will have an associated indexing variable.
7415 *
7416 * This is the same as the C function GDALRasterBandAsMDArray().
7417 *
7418 * The "reverse" method is GDALMDArray::AsClassicDataset().
7419 *
7420 * @return a new array, or nullptr.
7421 *
7422 * @since GDAL 3.1
7423 */
7424 std::shared_ptr<GDALMDArray> GDALRasterBand::AsMDArray() const
7425 {
7426 if( !poDS )
7427 {
7428 CPLError(CE_Failure, CPLE_AppDefined, "Band not attached to a dataset");
7429 return nullptr;
7430 }
7431 if( !poDS->GetShared() )
7432 {
7433 poDS->MarkAsShared();
7434 }
7435 return GDALMDArrayFromRasterBand::Create(poDS,
7436 const_cast<GDALRasterBand*>(this));
7437 }
7438