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 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINGS IN THE SOFTWARE.
26 : ****************************************************************************/
27 :
28 : #include "pcidsk_exception.h"
29 : #include "core/pcidsk_utils.h"
30 : #include "core/cpcidskfile.h"
31 : #include "channel/cpixelinterleavedchannel.h"
32 : #include <cassert>
33 : #include <cstring>
34 :
35 : using namespace PCIDSK;
36 :
37 : /************************************************************************/
38 : /* CPixelInterleavedChannel() */
39 : /************************************************************************/
40 :
41 0 : CPixelInterleavedChannel::CPixelInterleavedChannel( PCIDSKBuffer &image_headerIn,
42 : uint64 ih_offsetIn,
43 : CPL_UNUSED PCIDSKBuffer &file_headerIn,
44 : int channelnumIn,
45 : CPCIDSKFile *fileIn,
46 : int image_offsetIn,
47 0 : eChanType pixel_typeIn )
48 0 : : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
49 :
50 : {
51 0 : this->image_offset = image_offsetIn;
52 0 : }
53 :
54 : /************************************************************************/
55 : /* ~CPixelInterleavedChannel() */
56 : /************************************************************************/
57 :
58 0 : CPixelInterleavedChannel::~CPixelInterleavedChannel()
59 :
60 : {
61 0 : }
62 :
63 : /************************************************************************/
64 : /* ReadBlock() */
65 : /************************************************************************/
66 :
67 0 : int CPixelInterleavedChannel::ReadBlock( int block_index, void *buffer,
68 : int win_xoff, int win_yoff,
69 : int win_xsize, int win_ysize )
70 :
71 : {
72 : /* -------------------------------------------------------------------- */
73 : /* Default window if needed. */
74 : /* -------------------------------------------------------------------- */
75 0 : if( win_xoff == -1 && win_yoff == -1 && win_xsize == -1 && win_ysize == -1 )
76 : {
77 0 : win_xoff = 0;
78 0 : win_yoff = 0;
79 0 : win_xsize = GetBlockWidth();
80 0 : win_ysize = GetBlockHeight();
81 : }
82 :
83 : /* -------------------------------------------------------------------- */
84 : /* Validate Window */
85 : /* -------------------------------------------------------------------- */
86 0 : if( win_xoff < 0 || win_xoff + win_xsize > GetBlockWidth()
87 0 : || win_yoff < 0 || win_yoff + win_ysize > GetBlockHeight() )
88 : {
89 0 : return ThrowPCIDSKException(0,
90 : "Invalid window in ReadBloc(): win_xoff=%d,win_yoff=%d,xsize=%d,ysize=%d",
91 0 : win_xoff, win_yoff, win_xsize, win_ysize );
92 : }
93 :
94 : /* -------------------------------------------------------------------- */
95 : /* Work out sizes and offsets. */
96 : /* -------------------------------------------------------------------- */
97 0 : int pixel_group = file->GetPixelGroupSize();
98 0 : int pixel_size = DataTypeSize(GetType());
99 :
100 : /* -------------------------------------------------------------------- */
101 : /* Read and lock the scanline. */
102 : /* -------------------------------------------------------------------- */
103 : uint8 *pixel_buffer = (uint8 *)
104 0 : file->ReadAndLockBlock( block_index, win_xoff, win_xsize);
105 :
106 : /* -------------------------------------------------------------------- */
107 : /* Copy the data into our callers buffer. Try to do this */
108 : /* reasonably efficiently. We might consider adding faster */
109 : /* cases for 16/32bit data that is word aligned. */
110 : /* -------------------------------------------------------------------- */
111 0 : if( pixel_size == pixel_group )
112 0 : memcpy( buffer, pixel_buffer, static_cast<size_t>(pixel_size) * win_xsize );
113 : else
114 : {
115 : int i;
116 0 : uint8 *src = ((uint8 *)pixel_buffer) + image_offset;
117 0 : uint8 *dst = (uint8 *) buffer;
118 :
119 0 : if( pixel_size == 1 )
120 : {
121 0 : for( i = win_xsize; i != 0; i-- )
122 : {
123 0 : *dst = *src;
124 0 : dst++;
125 0 : src += pixel_group;
126 : }
127 : }
128 0 : else if( pixel_size == 2 )
129 : {
130 0 : for( i = win_xsize; i != 0; i-- )
131 : {
132 0 : *(dst++) = *(src++);
133 0 : *(dst++) = *(src++);
134 0 : src += pixel_group-2;
135 : }
136 : }
137 0 : else if( pixel_size == 4 )
138 : {
139 0 : for( i = win_xsize; i != 0; i-- )
140 : {
141 0 : *(dst++) = *(src++);
142 0 : *(dst++) = *(src++);
143 0 : *(dst++) = *(src++);
144 0 : *(dst++) = *(src++);
145 0 : src += pixel_group-4;
146 : }
147 : }
148 0 : else if( pixel_size == 8 )
149 : {
150 0 : for( i = win_xsize; i != 0; i-- )
151 : {
152 0 : *(dst++) = *(src++);
153 0 : *(dst++) = *(src++);
154 0 : *(dst++) = *(src++);
155 0 : *(dst++) = *(src++);
156 0 : *(dst++) = *(src++);
157 0 : *(dst++) = *(src++);
158 0 : *(dst++) = *(src++);
159 0 : *(dst++) = *(src++);
160 0 : src += pixel_group-8;
161 : }
162 : }
163 : else
164 0 : return ThrowPCIDSKException(0, "Unsupported pixel type..." );
165 : }
166 :
167 0 : file->UnlockBlock( false );
168 :
169 : /* -------------------------------------------------------------------- */
170 : /* Do byte swapping if needed. */
171 : /* -------------------------------------------------------------------- */
172 0 : if( needs_swap )
173 0 : SwapPixels( buffer, pixel_type, win_xsize );
174 :
175 0 : return 1;
176 : }
177 :
178 : /************************************************************************/
179 : /* CopyPixels() */
180 : /************************************************************************/
181 :
182 : template <typename T>
183 : void CopyPixels(const T* const src, T* const dst,
184 : std::size_t offset, std::size_t count)
185 : {
186 : for (std::size_t i = 0; i < count; i++)
187 : {
188 : dst[i] = src[(i + 1) * offset];
189 : }
190 : }
191 :
192 : /************************************************************************/
193 : /* WriteBlock() */
194 : /************************************************************************/
195 :
196 0 : int CPixelInterleavedChannel::WriteBlock( int block_index, void *buffer )
197 :
198 : {
199 0 : if( !file->GetUpdatable() )
200 0 : return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
201 :
202 0 : InvalidateOverviews();
203 :
204 : /* -------------------------------------------------------------------- */
205 : /* Work out sizes and offsets. */
206 : /* -------------------------------------------------------------------- */
207 0 : int pixel_group = file->GetPixelGroupSize();
208 0 : int pixel_size = DataTypeSize(GetType());
209 :
210 : /* -------------------------------------------------------------------- */
211 : /* Read and lock the scanline. */
212 : /* -------------------------------------------------------------------- */
213 0 : uint8 *pixel_buffer = (uint8 *) file->ReadAndLockBlock( block_index );
214 :
215 : /* -------------------------------------------------------------------- */
216 : /* Copy the data into our callers buffer. Try to do this */
217 : /* reasonably efficiently. We might consider adding faster */
218 : /* cases for 16/32bit data that is word aligned. */
219 : /* -------------------------------------------------------------------- */
220 0 : if( pixel_size == pixel_group )
221 : {
222 0 : memcpy( pixel_buffer, buffer, static_cast<size_t>(pixel_size) * width );
223 :
224 0 : if( needs_swap )
225 : {
226 0 : bool complex = IsDataTypeComplex( GetType() );
227 :
228 0 : if( complex )
229 0 : SwapData( pixel_buffer, pixel_size/2, width*2 );
230 : else
231 0 : SwapData( pixel_buffer, pixel_size, width );
232 : }
233 : }
234 : else
235 : {
236 : int i;
237 0 : uint8 *dst = ((uint8 *)pixel_buffer) + image_offset;
238 0 : uint8 *src = (uint8 *) buffer;
239 :
240 0 : if( pixel_size == 1 )
241 : {
242 0 : for( i = width; i != 0; i-- )
243 : {
244 0 : *dst = *src;
245 0 : src++;
246 0 : dst += pixel_group;
247 : }
248 : }
249 0 : else if( pixel_size == 2 )
250 : {
251 0 : for( i = width; i != 0; i-- )
252 : {
253 0 : *(dst++) = *(src++);
254 0 : *(dst++) = *(src++);
255 :
256 0 : if( needs_swap )
257 0 : SwapData( dst-2, 2, 1 );
258 :
259 0 : dst += pixel_group-2;
260 : }
261 : }
262 0 : else if( pixel_size == 4 )
263 : {
264 0 : bool complex = IsDataTypeComplex( GetType() );
265 :
266 0 : for( i = width; i != 0; i-- )
267 : {
268 0 : *(dst++) = *(src++);
269 0 : *(dst++) = *(src++);
270 0 : *(dst++) = *(src++);
271 0 : *(dst++) = *(src++);
272 :
273 0 : if( needs_swap )
274 : {
275 0 : if( complex )
276 0 : SwapData( dst-4, 2, 2);
277 : else
278 0 : SwapData( dst-4, 4, 1);
279 : }
280 :
281 0 : dst += pixel_group-4;
282 : }
283 : }
284 0 : else if( pixel_size == 8 )
285 : {
286 0 : bool complex = IsDataTypeComplex( GetType() );
287 :
288 0 : for( i = width; i != 0; i-- )
289 : {
290 0 : *(dst++) = *(src++);
291 0 : *(dst++) = *(src++);
292 0 : *(dst++) = *(src++);
293 0 : *(dst++) = *(src++);
294 0 : *(dst++) = *(src++);
295 0 : *(dst++) = *(src++);
296 0 : *(dst++) = *(src++);
297 0 : *(dst++) = *(src++);
298 :
299 0 : if( needs_swap )
300 : {
301 0 : if( complex )
302 0 : SwapData( dst-8, 4, 2);
303 : else
304 0 : SwapData( dst-8, 8, 1);
305 : }
306 :
307 0 : dst += pixel_group-8;
308 : }
309 : }
310 : else
311 0 : return ThrowPCIDSKException(0, "Unsupported pixel type..." );
312 : }
313 :
314 0 : file->UnlockBlock( true );
315 :
316 0 : return 1;
317 : }
|