Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GeoTIFF Driver 4 : * Purpose: GDAL GeoTIFF support. 5 : * Author: Frank Warmerdam, warmerdam@pobox.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 1998, 2002, Frank Warmerdam <warmerdam@pobox.com> 9 : * Copyright (c) 2007-2015, Even Rouault <even dot rouault at spatialys dot com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************/ 13 : 14 : #include "gtiffsplitband.h" 15 : 16 : #include "gtiffdataset.h" 17 : #include "gdal_priv.h" 18 : 19 : /************************************************************************/ 20 : /* GTiffSplitBand() */ 21 : /************************************************************************/ 22 : 23 131118 : GTiffSplitBand::GTiffSplitBand(GTiffDataset *poDSIn, int nBandIn) 24 131118 : : GTiffRasterBand(poDSIn, nBandIn) 25 : { 26 131118 : nBlockXSize = poDS->GetRasterXSize(); 27 131118 : nBlockYSize = 1; 28 131118 : } 29 : 30 : /************************************************************************/ 31 : /* IGetDataCoverageStatus() */ 32 : /************************************************************************/ 33 : 34 0 : int GTiffSplitBand::IGetDataCoverageStatus(int, int, int, int, int, double *) 35 : { 36 : return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | 37 0 : GDAL_DATA_COVERAGE_STATUS_DATA; 38 : } 39 : 40 : /************************************************************************/ 41 : /* IReadBlock() */ 42 : /************************************************************************/ 43 : 44 78291 : CPLErr GTiffSplitBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff, 45 : void *pImage) 46 : 47 : { 48 78291 : m_poGDS->Crystalize(); 49 : 50 : // Optimization when reading the same line in a contig multi-band TIFF. 51 78291 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG && 52 48291 : m_poGDS->nBands > 1 && m_poGDS->m_nLoadedBlock == nBlockYOff) 53 : { 54 4011 : goto extract_band_data; 55 : } 56 : 57 74280 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG && m_poGDS->nBands > 1) 58 : { 59 40276 : if (m_poGDS->m_pabyBlockBuf == nullptr) 60 : { 61 14 : m_poGDS->m_pabyBlockBuf = static_cast<GByte *>( 62 7 : VSI_MALLOC_VERBOSE(TIFFScanlineSize(m_poGDS->m_hTIFF))); 63 7 : if (m_poGDS->m_pabyBlockBuf == nullptr) 64 : { 65 1 : return CE_Failure; 66 : } 67 : } 68 : } 69 : else 70 : { 71 34004 : CPLAssert(TIFFScanlineSize(m_poGDS->m_hTIFF) == nBlockXSize); 72 : } 73 : 74 : /* -------------------------------------------------------------------- */ 75 : /* Read through to target scanline. */ 76 : /* -------------------------------------------------------------------- */ 77 74279 : if (m_poGDS->m_nLoadedBlock >= nBlockYOff) 78 33 : m_poGDS->m_nLoadedBlock = -1; 79 : 80 74279 : if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE && 81 30000 : m_poGDS->nBands > 1) 82 : { 83 : // If we change of band, we must start reading the 84 : // new strip from its beginning. 85 30000 : if (m_poGDS->m_nLastBandRead != nBand) 86 20 : m_poGDS->m_nLoadedBlock = -1; 87 30000 : m_poGDS->m_nLastBandRead = nBand; 88 : } 89 : 90 203674 : while (m_poGDS->m_nLoadedBlock < nBlockYOff) 91 : { 92 129397 : ++m_poGDS->m_nLoadedBlock; 93 194550 : if (TIFFReadScanline(m_poGDS->m_hTIFF, 94 61149 : m_poGDS->m_pabyBlockBuf ? m_poGDS->m_pabyBlockBuf 95 : : pImage, 96 129397 : m_poGDS->m_nLoadedBlock, 97 129397 : (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) 98 64244 : ? static_cast<uint16_t>(nBand - 1) 99 129399 : : 0) == -1 && 100 2 : !m_poGDS->m_bIgnoreReadErrors) 101 : { 102 2 : ReportError(CE_Failure, CPLE_AppDefined, 103 : "TIFFReadScanline() failed."); 104 2 : m_poGDS->m_nLoadedBlock = -1; 105 2 : return CE_Failure; 106 : } 107 : } 108 : 109 74277 : extract_band_data: 110 : /* -------------------------------------------------------------------- */ 111 : /* Extract band data from contig buffer. */ 112 : /* -------------------------------------------------------------------- */ 113 78288 : if (m_poGDS->m_pabyBlockBuf != nullptr) 114 : { 115 44286 : for (int iPixel = 0, iSrcOffset = nBand - 1, iDstOffset = 0; 116 180732 : iPixel < nBlockXSize; 117 136446 : ++iPixel, iSrcOffset += m_poGDS->nBands, ++iDstOffset) 118 : { 119 136446 : static_cast<GByte *>(pImage)[iDstOffset] = 120 136446 : m_poGDS->m_pabyBlockBuf[iSrcOffset]; 121 : } 122 : } 123 : 124 78288 : return CE_None; 125 : } 126 : 127 : /************************************************************************/ 128 : /* IWriteBlock() */ 129 : /************************************************************************/ 130 : 131 0 : CPLErr GTiffSplitBand::IWriteBlock(int /* nBlockXOff */, int /* nBlockYOff */, 132 : void * /* pImage */) 133 : 134 : { 135 0 : ReportError(CE_Failure, CPLE_AppDefined, "Split bands are read-only."); 136 0 : return CE_Failure; 137 : }