/src/gdal/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.cpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Purpose: Implementation of the CPixelInterleavedChannel class. |
4 | | * |
5 | | ****************************************************************************** |
6 | | * Copyright (c) 2009 |
7 | | * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada. |
8 | | * |
9 | | * SPDX-License-Identifier: MIT |
10 | | ****************************************************************************/ |
11 | | |
12 | | #include "pcidsk_exception.h" |
13 | | #include "core/pcidsk_utils.h" |
14 | | #include "core/cpcidskfile.h" |
15 | | #include "channel/cpixelinterleavedchannel.h" |
16 | | #include <cassert> |
17 | | #include <cstring> |
18 | | |
19 | | using namespace PCIDSK; |
20 | | |
21 | | /************************************************************************/ |
22 | | /* CPixelInterleavedChannel() */ |
23 | | /************************************************************************/ |
24 | | |
25 | | CPixelInterleavedChannel::CPixelInterleavedChannel( PCIDSKBuffer &image_headerIn, |
26 | | uint64 ih_offsetIn, |
27 | | CPL_UNUSED PCIDSKBuffer &file_headerIn, |
28 | | int channelnumIn, |
29 | | CPCIDSKFile *fileIn, |
30 | | int image_offsetIn, |
31 | | eChanType pixel_typeIn ) |
32 | 0 | : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn) |
33 | | |
34 | 0 | { |
35 | 0 | this->image_offset = image_offsetIn; |
36 | 0 | } |
37 | | |
38 | | /************************************************************************/ |
39 | | /* ~CPixelInterleavedChannel() */ |
40 | | /************************************************************************/ |
41 | | |
42 | | CPixelInterleavedChannel::~CPixelInterleavedChannel() |
43 | | |
44 | 0 | { |
45 | 0 | } |
46 | | |
47 | | /************************************************************************/ |
48 | | /* ReadBlock() */ |
49 | | /************************************************************************/ |
50 | | |
51 | | int CPixelInterleavedChannel::ReadBlock( int block_index, void *buffer, |
52 | | int win_xoff, int win_yoff, |
53 | | int win_xsize, int win_ysize ) |
54 | | |
55 | 0 | { |
56 | | /* -------------------------------------------------------------------- */ |
57 | | /* Default window if needed. */ |
58 | | /* -------------------------------------------------------------------- */ |
59 | 0 | if( win_xoff == -1 && win_yoff == -1 && win_xsize == -1 && win_ysize == -1 ) |
60 | 0 | { |
61 | 0 | win_xoff = 0; |
62 | 0 | win_yoff = 0; |
63 | 0 | win_xsize = GetBlockWidth(); |
64 | 0 | win_ysize = GetBlockHeight(); |
65 | 0 | } |
66 | | |
67 | | /* -------------------------------------------------------------------- */ |
68 | | /* Validate Window */ |
69 | | /* -------------------------------------------------------------------- */ |
70 | 0 | if( win_xoff < 0 || win_xoff + win_xsize > GetBlockWidth() |
71 | 0 | || win_yoff < 0 || win_yoff + win_ysize > GetBlockHeight() ) |
72 | 0 | { |
73 | 0 | return ThrowPCIDSKException(0, |
74 | 0 | "Invalid window in ReadBloc(): win_xoff=%d,win_yoff=%d,xsize=%d,ysize=%d", |
75 | 0 | win_xoff, win_yoff, win_xsize, win_ysize ); |
76 | 0 | } |
77 | | |
78 | | /* -------------------------------------------------------------------- */ |
79 | | /* Work out sizes and offsets. */ |
80 | | /* -------------------------------------------------------------------- */ |
81 | 0 | int pixel_group = file->GetPixelGroupSize(); |
82 | 0 | int pixel_size = DataTypeSize(GetType()); |
83 | | |
84 | | /* -------------------------------------------------------------------- */ |
85 | | /* Read and lock the scanline. */ |
86 | | /* -------------------------------------------------------------------- */ |
87 | 0 | uint8 *pixel_buffer = (uint8 *) |
88 | 0 | file->ReadAndLockBlock( block_index, win_xoff, win_xsize); |
89 | | |
90 | | /* -------------------------------------------------------------------- */ |
91 | | /* Copy the data into our callers buffer. Try to do this */ |
92 | | /* reasonably efficiently. We might consider adding faster */ |
93 | | /* cases for 16/32bit data that is word aligned. */ |
94 | | /* -------------------------------------------------------------------- */ |
95 | 0 | if( pixel_size == pixel_group ) |
96 | 0 | memcpy( buffer, pixel_buffer, static_cast<size_t>(pixel_size) * win_xsize ); |
97 | 0 | else |
98 | 0 | { |
99 | 0 | int i; |
100 | 0 | const uint8 *src = pixel_buffer + image_offset; |
101 | 0 | uint8 *dst = static_cast<uint8 *>(buffer); |
102 | |
|
103 | 0 | if( pixel_size == 1 ) |
104 | 0 | { |
105 | 0 | for( i = win_xsize; i != 0; i-- ) |
106 | 0 | { |
107 | 0 | *dst = *src; |
108 | 0 | dst++; |
109 | 0 | src += pixel_group; |
110 | 0 | } |
111 | 0 | } |
112 | 0 | else if( pixel_size == 2 ) |
113 | 0 | { |
114 | 0 | for( i = win_xsize; i != 0; i-- ) |
115 | 0 | { |
116 | 0 | *(dst++) = *(src++); |
117 | 0 | *(dst++) = *(src++); |
118 | 0 | src += pixel_group-2; |
119 | 0 | } |
120 | 0 | } |
121 | 0 | else if( pixel_size == 4 ) |
122 | 0 | { |
123 | 0 | for( i = win_xsize; i != 0; i-- ) |
124 | 0 | { |
125 | 0 | *(dst++) = *(src++); |
126 | 0 | *(dst++) = *(src++); |
127 | 0 | *(dst++) = *(src++); |
128 | 0 | *(dst++) = *(src++); |
129 | 0 | src += pixel_group-4; |
130 | 0 | } |
131 | 0 | } |
132 | 0 | else if( pixel_size == 8 ) |
133 | 0 | { |
134 | 0 | for( i = win_xsize; i != 0; i-- ) |
135 | 0 | { |
136 | 0 | *(dst++) = *(src++); |
137 | 0 | *(dst++) = *(src++); |
138 | 0 | *(dst++) = *(src++); |
139 | 0 | *(dst++) = *(src++); |
140 | 0 | *(dst++) = *(src++); |
141 | 0 | *(dst++) = *(src++); |
142 | 0 | *(dst++) = *(src++); |
143 | 0 | *(dst++) = *(src++); |
144 | 0 | src += pixel_group-8; |
145 | 0 | } |
146 | 0 | } |
147 | 0 | else |
148 | 0 | return ThrowPCIDSKException(0, "Unsupported pixel type..." ); |
149 | 0 | } |
150 | | |
151 | 0 | file->UnlockBlock( false ); |
152 | | |
153 | | /* -------------------------------------------------------------------- */ |
154 | | /* Do byte swapping if needed. */ |
155 | | /* -------------------------------------------------------------------- */ |
156 | 0 | if( needs_swap ) |
157 | 0 | SwapPixels( buffer, pixel_type, win_xsize ); |
158 | |
|
159 | 0 | return 1; |
160 | 0 | } |
161 | | |
162 | | /************************************************************************/ |
163 | | /* CopyPixels() */ |
164 | | /************************************************************************/ |
165 | | |
166 | | template <typename T> |
167 | | void CopyPixels(const T* const src, T* const dst, |
168 | | std::size_t offset, std::size_t count) |
169 | | { |
170 | | for (std::size_t i = 0; i < count; i++) |
171 | | { |
172 | | dst[i] = src[(i + 1) * offset]; |
173 | | } |
174 | | } |
175 | | |
176 | | /************************************************************************/ |
177 | | /* WriteBlock() */ |
178 | | /************************************************************************/ |
179 | | |
180 | | int CPixelInterleavedChannel::WriteBlock( int block_index, void *buffer ) |
181 | | |
182 | 0 | { |
183 | 0 | if( !file->GetUpdatable() ) |
184 | 0 | return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" ); |
185 | | |
186 | 0 | InvalidateOverviews(); |
187 | | |
188 | | /* -------------------------------------------------------------------- */ |
189 | | /* Work out sizes and offsets. */ |
190 | | /* -------------------------------------------------------------------- */ |
191 | 0 | int pixel_group = file->GetPixelGroupSize(); |
192 | 0 | int pixel_size = DataTypeSize(GetType()); |
193 | | |
194 | | /* -------------------------------------------------------------------- */ |
195 | | /* Read and lock the scanline. */ |
196 | | /* -------------------------------------------------------------------- */ |
197 | 0 | uint8 *pixel_buffer = (uint8 *) file->ReadAndLockBlock( block_index ); |
198 | | |
199 | | /* -------------------------------------------------------------------- */ |
200 | | /* Copy the data into our callers buffer. Try to do this */ |
201 | | /* reasonably efficiently. We might consider adding faster */ |
202 | | /* cases for 16/32bit data that is word aligned. */ |
203 | | /* -------------------------------------------------------------------- */ |
204 | 0 | if( pixel_size == pixel_group ) |
205 | 0 | { |
206 | 0 | memcpy( pixel_buffer, buffer, static_cast<size_t>(pixel_size) * width ); |
207 | |
|
208 | 0 | if( needs_swap ) |
209 | 0 | { |
210 | 0 | bool complex = IsDataTypeComplex( GetType() ); |
211 | |
|
212 | 0 | if( complex ) |
213 | 0 | SwapData( pixel_buffer, pixel_size/2, width*2 ); |
214 | 0 | else |
215 | 0 | SwapData( pixel_buffer, pixel_size, width ); |
216 | 0 | } |
217 | 0 | } |
218 | 0 | else |
219 | 0 | { |
220 | 0 | int i; |
221 | 0 | uint8 *dst = pixel_buffer + image_offset; |
222 | 0 | const uint8 *src = static_cast<uint8 *>(buffer); |
223 | |
|
224 | 0 | if( pixel_size == 1 ) |
225 | 0 | { |
226 | 0 | for( i = width; i != 0; i-- ) |
227 | 0 | { |
228 | 0 | *dst = *src; |
229 | 0 | src++; |
230 | 0 | dst += pixel_group; |
231 | 0 | } |
232 | 0 | } |
233 | 0 | else if( pixel_size == 2 ) |
234 | 0 | { |
235 | 0 | for( i = width; i != 0; i-- ) |
236 | 0 | { |
237 | 0 | *(dst++) = *(src++); |
238 | 0 | *(dst++) = *(src++); |
239 | |
|
240 | 0 | if( needs_swap ) |
241 | 0 | SwapData( dst-2, 2, 1 ); |
242 | |
|
243 | 0 | dst += pixel_group-2; |
244 | 0 | } |
245 | 0 | } |
246 | 0 | else if( pixel_size == 4 ) |
247 | 0 | { |
248 | 0 | bool complex = IsDataTypeComplex( GetType() ); |
249 | |
|
250 | 0 | for( i = width; i != 0; i-- ) |
251 | 0 | { |
252 | 0 | *(dst++) = *(src++); |
253 | 0 | *(dst++) = *(src++); |
254 | 0 | *(dst++) = *(src++); |
255 | 0 | *(dst++) = *(src++); |
256 | |
|
257 | 0 | if( needs_swap ) |
258 | 0 | { |
259 | 0 | if( complex ) |
260 | 0 | SwapData( dst-4, 2, 2); |
261 | 0 | else |
262 | 0 | SwapData( dst-4, 4, 1); |
263 | 0 | } |
264 | |
|
265 | 0 | dst += pixel_group-4; |
266 | 0 | } |
267 | 0 | } |
268 | 0 | else if( pixel_size == 8 ) |
269 | 0 | { |
270 | 0 | bool complex = IsDataTypeComplex( GetType() ); |
271 | |
|
272 | 0 | for( i = width; i != 0; i-- ) |
273 | 0 | { |
274 | 0 | *(dst++) = *(src++); |
275 | 0 | *(dst++) = *(src++); |
276 | 0 | *(dst++) = *(src++); |
277 | 0 | *(dst++) = *(src++); |
278 | 0 | *(dst++) = *(src++); |
279 | 0 | *(dst++) = *(src++); |
280 | 0 | *(dst++) = *(src++); |
281 | 0 | *(dst++) = *(src++); |
282 | |
|
283 | 0 | if( needs_swap ) |
284 | 0 | { |
285 | 0 | if( complex ) |
286 | 0 | SwapData( dst-8, 4, 2); |
287 | 0 | else |
288 | 0 | SwapData( dst-8, 8, 1); |
289 | 0 | } |
290 | |
|
291 | 0 | dst += pixel_group-8; |
292 | 0 | } |
293 | 0 | } |
294 | 0 | else |
295 | 0 | return ThrowPCIDSKException(0, "Unsupported pixel type..." ); |
296 | 0 | } |
297 | | |
298 | 0 | file->UnlockBlock( true ); |
299 | |
|
300 | 0 | return 1; |
301 | 0 | } |