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