Line data Source code
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 0 : 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 0 : eChanType pixel_typeIn )
32 0 : : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
33 :
34 : {
35 0 : this->image_offset = image_offsetIn;
36 0 : }
37 :
38 : /************************************************************************/
39 : /* ~CPixelInterleavedChannel() */
40 : /************************************************************************/
41 :
42 0 : CPixelInterleavedChannel::~CPixelInterleavedChannel()
43 :
44 : {
45 0 : }
46 :
47 : /************************************************************************/
48 : /* ReadBlock() */
49 : /************************************************************************/
50 :
51 0 : int CPixelInterleavedChannel::ReadBlock( int block_index, void *buffer,
52 : int win_xoff, int win_yoff,
53 : int win_xsize, int win_ysize )
54 :
55 : {
56 : /* -------------------------------------------------------------------- */
57 : /* Default window if needed. */
58 : /* -------------------------------------------------------------------- */
59 0 : if( win_xoff == -1 && win_yoff == -1 && win_xsize == -1 && win_ysize == -1 )
60 : {
61 0 : win_xoff = 0;
62 0 : win_yoff = 0;
63 0 : win_xsize = GetBlockWidth();
64 0 : win_ysize = GetBlockHeight();
65 : }
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 : {
73 0 : return ThrowPCIDSKException(0,
74 : "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 : }
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 : 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 : else
98 : {
99 : int i;
100 0 : uint8 *src = ((uint8 *)pixel_buffer) + image_offset;
101 0 : uint8 *dst = (uint8 *) buffer;
102 :
103 0 : if( pixel_size == 1 )
104 : {
105 0 : for( i = win_xsize; i != 0; i-- )
106 : {
107 0 : *dst = *src;
108 0 : dst++;
109 0 : src += pixel_group;
110 : }
111 : }
112 0 : else if( pixel_size == 2 )
113 : {
114 0 : for( i = win_xsize; i != 0; i-- )
115 : {
116 0 : *(dst++) = *(src++);
117 0 : *(dst++) = *(src++);
118 0 : src += pixel_group-2;
119 : }
120 : }
121 0 : else if( pixel_size == 4 )
122 : {
123 0 : for( i = win_xsize; i != 0; i-- )
124 : {
125 0 : *(dst++) = *(src++);
126 0 : *(dst++) = *(src++);
127 0 : *(dst++) = *(src++);
128 0 : *(dst++) = *(src++);
129 0 : src += pixel_group-4;
130 : }
131 : }
132 0 : else if( pixel_size == 8 )
133 : {
134 0 : for( i = win_xsize; i != 0; i-- )
135 : {
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 : }
146 : }
147 : else
148 0 : return ThrowPCIDSKException(0, "Unsupported pixel type..." );
149 : }
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 : }
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 0 : int CPixelInterleavedChannel::WriteBlock( int block_index, void *buffer )
181 :
182 : {
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 : {
206 0 : memcpy( pixel_buffer, buffer, static_cast<size_t>(pixel_size) * width );
207 :
208 0 : if( needs_swap )
209 : {
210 0 : bool complex = IsDataTypeComplex( GetType() );
211 :
212 0 : if( complex )
213 0 : SwapData( pixel_buffer, pixel_size/2, width*2 );
214 : else
215 0 : SwapData( pixel_buffer, pixel_size, width );
216 : }
217 : }
218 : else
219 : {
220 : int i;
221 0 : uint8 *dst = ((uint8 *)pixel_buffer) + image_offset;
222 0 : uint8 *src = (uint8 *) buffer;
223 :
224 0 : if( pixel_size == 1 )
225 : {
226 0 : for( i = width; i != 0; i-- )
227 : {
228 0 : *dst = *src;
229 0 : src++;
230 0 : dst += pixel_group;
231 : }
232 : }
233 0 : else if( pixel_size == 2 )
234 : {
235 0 : for( i = width; i != 0; i-- )
236 : {
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 : }
245 : }
246 0 : else if( pixel_size == 4 )
247 : {
248 0 : bool complex = IsDataTypeComplex( GetType() );
249 :
250 0 : for( i = width; i != 0; i-- )
251 : {
252 0 : *(dst++) = *(src++);
253 0 : *(dst++) = *(src++);
254 0 : *(dst++) = *(src++);
255 0 : *(dst++) = *(src++);
256 :
257 0 : if( needs_swap )
258 : {
259 0 : if( complex )
260 0 : SwapData( dst-4, 2, 2);
261 : else
262 0 : SwapData( dst-4, 4, 1);
263 : }
264 :
265 0 : dst += pixel_group-4;
266 : }
267 : }
268 0 : else if( pixel_size == 8 )
269 : {
270 0 : bool complex = IsDataTypeComplex( GetType() );
271 :
272 0 : for( i = width; i != 0; i-- )
273 : {
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 : {
285 0 : if( complex )
286 0 : SwapData( dst-8, 4, 2);
287 : else
288 0 : SwapData( dst-8, 8, 1);
289 : }
290 :
291 0 : dst += pixel_group-8;
292 : }
293 : }
294 : else
295 0 : return ThrowPCIDSKException(0, "Unsupported pixel type..." );
296 : }
297 :
298 0 : file->UnlockBlock( true );
299 :
300 0 : return 1;
301 : }
|