/src/gdal/frmts/gtiff/gtiffrgbaband.cpp
Line | Count | Source (jump to first uncovered line) |
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 "gtiffrgbaband.h" |
15 | | #include "gtiffdataset.h" |
16 | | |
17 | | #include "tiffio.h" |
18 | | |
19 | | /************************************************************************/ |
20 | | /* GTiffRGBABand() */ |
21 | | /************************************************************************/ |
22 | | |
23 | | GTiffRGBABand::GTiffRGBABand(GTiffDataset *poDSIn, int nBandIn) |
24 | 0 | : GTiffRasterBand(poDSIn, nBandIn) |
25 | 0 | { |
26 | 0 | eDataType = GDT_Byte; |
27 | 0 | } |
28 | | |
29 | | /************************************************************************/ |
30 | | /* IGetDataCoverageStatus() */ |
31 | | /************************************************************************/ |
32 | | |
33 | | int GTiffRGBABand::IGetDataCoverageStatus(int, int, int, int, int, double *) |
34 | 0 | { |
35 | 0 | return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | |
36 | 0 | GDAL_DATA_COVERAGE_STATUS_DATA; |
37 | 0 | } |
38 | | |
39 | | /************************************************************************/ |
40 | | /* IWriteBlock() */ |
41 | | /************************************************************************/ |
42 | | |
43 | | CPLErr GTiffRGBABand::IWriteBlock(int, int, void *) |
44 | | |
45 | 0 | { |
46 | 0 | ReportError(CE_Failure, CPLE_AppDefined, |
47 | 0 | "RGBA interpreted raster bands are read-only."); |
48 | 0 | return CE_Failure; |
49 | 0 | } |
50 | | |
51 | | /************************************************************************/ |
52 | | /* IReadBlock() */ |
53 | | /************************************************************************/ |
54 | | |
55 | | CPLErr GTiffRGBABand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) |
56 | | |
57 | 0 | { |
58 | 0 | m_poGDS->Crystalize(); |
59 | |
|
60 | 0 | const auto nBlockBufSize = |
61 | 0 | 4 * static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize; |
62 | 0 | const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow; |
63 | |
|
64 | 0 | if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) |
65 | 0 | { |
66 | 0 | for (int iBand = 0; iBand < m_poGDS->m_nSamplesPerPixel; iBand++) |
67 | 0 | { |
68 | 0 | int nBlockIdBand = nBlockId + iBand * m_poGDS->m_nBlocksPerBand; |
69 | 0 | if (!m_poGDS->IsBlockAvailable(nBlockIdBand, nullptr, nullptr, |
70 | 0 | nullptr)) |
71 | 0 | return CE_Failure; |
72 | 0 | } |
73 | 0 | } |
74 | 0 | else |
75 | 0 | { |
76 | 0 | if (!m_poGDS->IsBlockAvailable(nBlockId, nullptr, nullptr, nullptr)) |
77 | 0 | return CE_Failure; |
78 | 0 | } |
79 | | |
80 | | /* -------------------------------------------------------------------- */ |
81 | | /* Allocate a temporary buffer for this strip. */ |
82 | | /* -------------------------------------------------------------------- */ |
83 | 0 | if (m_poGDS->m_pabyBlockBuf == nullptr) |
84 | 0 | { |
85 | 0 | m_poGDS->m_pabyBlockBuf = static_cast<GByte *>( |
86 | 0 | VSI_MALLOC3_VERBOSE(4, nBlockXSize, nBlockYSize)); |
87 | 0 | if (m_poGDS->m_pabyBlockBuf == nullptr) |
88 | 0 | return CE_Failure; |
89 | 0 | } |
90 | | |
91 | | /* -------------------------------------------------------------------- */ |
92 | | /* Read the strip */ |
93 | | /* -------------------------------------------------------------------- */ |
94 | 0 | CPLErr eErr = CE_None; |
95 | |
|
96 | 0 | if (m_poGDS->m_nLoadedBlock != nBlockId) |
97 | 0 | { |
98 | 0 | if (TIFFIsTiled(m_poGDS->m_hTIFF)) |
99 | 0 | { |
100 | 0 | if (TIFFReadRGBATileExt( |
101 | 0 | m_poGDS->m_hTIFF, nBlockXOff * nBlockXSize, |
102 | 0 | nBlockYOff * nBlockYSize, |
103 | 0 | reinterpret_cast<uint32_t *>(m_poGDS->m_pabyBlockBuf), |
104 | 0 | !m_poGDS->m_bIgnoreReadErrors) == 0 && |
105 | 0 | !m_poGDS->m_bIgnoreReadErrors) |
106 | 0 | { |
107 | | // Once TIFFError() is properly hooked, this can go away. |
108 | 0 | ReportError(CE_Failure, CPLE_AppDefined, |
109 | 0 | "TIFFReadRGBATile() failed."); |
110 | |
|
111 | 0 | memset(m_poGDS->m_pabyBlockBuf, 0, nBlockBufSize); |
112 | |
|
113 | 0 | eErr = CE_Failure; |
114 | 0 | } |
115 | 0 | } |
116 | 0 | else |
117 | 0 | { |
118 | 0 | if (TIFFReadRGBAStripExt( |
119 | 0 | m_poGDS->m_hTIFF, nBlockId * nBlockYSize, |
120 | 0 | reinterpret_cast<uint32_t *>(m_poGDS->m_pabyBlockBuf), |
121 | 0 | !m_poGDS->m_bIgnoreReadErrors) == 0 && |
122 | 0 | !m_poGDS->m_bIgnoreReadErrors) |
123 | 0 | { |
124 | | // Once TIFFError() is properly hooked, this can go away. |
125 | 0 | ReportError(CE_Failure, CPLE_AppDefined, |
126 | 0 | "TIFFReadRGBAStrip() failed."); |
127 | |
|
128 | 0 | memset(m_poGDS->m_pabyBlockBuf, 0, nBlockBufSize); |
129 | |
|
130 | 0 | eErr = CE_Failure; |
131 | 0 | } |
132 | 0 | } |
133 | 0 | } |
134 | |
|
135 | 0 | m_poGDS->m_nLoadedBlock = eErr == CE_None ? nBlockId : -1; |
136 | | |
137 | | /* -------------------------------------------------------------------- */ |
138 | | /* Handle simple case of eight bit data, and pixel interleaving. */ |
139 | | /* -------------------------------------------------------------------- */ |
140 | 0 | int nThisBlockYSize = nBlockYSize; |
141 | |
|
142 | 0 | if (nBlockYOff * nBlockYSize > GetYSize() - nBlockYSize && |
143 | 0 | !TIFFIsTiled(m_poGDS->m_hTIFF)) |
144 | 0 | nThisBlockYSize = GetYSize() - nBlockYOff * nBlockYSize; |
145 | |
|
146 | 0 | #ifdef CPL_LSB |
147 | 0 | const int nBO = nBand - 1; |
148 | | #else |
149 | | const int nBO = 4 - nBand; |
150 | | #endif |
151 | |
|
152 | 0 | for (int iDestLine = 0; iDestLine < nThisBlockYSize; ++iDestLine) |
153 | 0 | { |
154 | 0 | const auto nSrcOffset = |
155 | 0 | static_cast<GPtrDiff_t>(nThisBlockYSize - iDestLine - 1) * |
156 | 0 | nBlockXSize * 4; |
157 | |
|
158 | 0 | GDALCopyWords(m_poGDS->m_pabyBlockBuf + nBO + nSrcOffset, GDT_Byte, 4, |
159 | 0 | static_cast<GByte *>(pImage) + |
160 | 0 | static_cast<GPtrDiff_t>(iDestLine) * nBlockXSize, |
161 | 0 | GDT_Byte, 1, nBlockXSize); |
162 | 0 | } |
163 | |
|
164 | 0 | if (eErr == CE_None) |
165 | 0 | eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff); |
166 | |
|
167 | 0 | return eErr; |
168 | 0 | } |
169 | | |
170 | | /************************************************************************/ |
171 | | /* GetColorInterpretation() */ |
172 | | /************************************************************************/ |
173 | | |
174 | | GDALColorInterp GTiffRGBABand::GetColorInterpretation() |
175 | | |
176 | 0 | { |
177 | 0 | if (nBand == 1) |
178 | 0 | return GCI_RedBand; |
179 | 0 | if (nBand == 2) |
180 | 0 | return GCI_GreenBand; |
181 | 0 | if (nBand == 3) |
182 | 0 | return GCI_BlueBand; |
183 | | |
184 | 0 | return GCI_AlphaBand; |
185 | 0 | } |