1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the CPixelInterleavedChannel class.
4 : *
5 : ******************************************************************************
6 : * Copyright (c) 2009
7 : * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, 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_header,
42 : uint64 ih_offset,
43 : PCIDSKBuffer &file_header,
44 : int channelnum,
45 : CPCIDSKFile *file,
46 : int image_offset,
47 : eChanType pixel_type )
48 0 : : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)
49 :
50 : {
51 0 : this->image_offset = image_offset;
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 : ThrowPCIDSKException(
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, 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 : else
149 0 : ThrowPCIDSKException( "Unsupported pixel type..." );
150 : }
151 :
152 0 : file->UnlockBlock( 0 );
153 :
154 : /* -------------------------------------------------------------------- */
155 : /* Do byte swapping if needed. */
156 : /* -------------------------------------------------------------------- */
157 0 : if( needs_swap )
158 0 : SwapPixels( buffer, pixel_type, win_xsize );
159 :
160 0 : return 1;
161 : }
162 :
163 : template <typename T>
164 : void CopyPixels(const T* const src, T* const dst,
165 : std::size_t offset, std::size_t count)
166 : {
167 : for (std::size_t i = 0; i < count; i++)
168 : {
169 : dst[i] = src[(i + 1) * offset];
170 : }
171 : }
172 :
173 : /************************************************************************/
174 : /* WriteBlock() */
175 : /************************************************************************/
176 :
177 0 : int CPixelInterleavedChannel::WriteBlock( int block_index, void *buffer )
178 :
179 : {
180 0 : if( !file->GetUpdatable() )
181 0 : throw PCIDSKException( "File not open for update in WriteBlock()" );
182 :
183 0 : InvalidateOverviews();
184 :
185 : /* -------------------------------------------------------------------- */
186 : /* Work out sizes and offsets. */
187 : /* -------------------------------------------------------------------- */
188 0 : int pixel_group = file->GetPixelGroupSize();
189 0 : int pixel_size = DataTypeSize(GetType());
190 :
191 : /* -------------------------------------------------------------------- */
192 : /* Read and lock the scanline. */
193 : /* -------------------------------------------------------------------- */
194 0 : uint8 *pixel_buffer = (uint8 *) file->ReadAndLockBlock( block_index );
195 :
196 : /* -------------------------------------------------------------------- */
197 : /* Copy the data into our callers buffer. Try to do this */
198 : /* reasonably efficiently. We might consider adding faster */
199 : /* cases for 16/32bit data that is word aligned. */
200 : /* -------------------------------------------------------------------- */
201 : // TODO: fixup for the complex case
202 0 : if( pixel_size == pixel_group )
203 0 : memcpy( pixel_buffer, buffer, pixel_size * width );
204 : else
205 : {
206 : int i;
207 0 : uint8 *dst = ((uint8 *)pixel_buffer) + image_offset;
208 0 : uint8 *src = (uint8 *) buffer;
209 :
210 0 : if( pixel_size == 1 )
211 : {
212 0 : for( i = width; i != 0; i-- )
213 : {
214 0 : *dst = *src;
215 0 : src++;
216 0 : dst += pixel_group;
217 : }
218 : }
219 0 : else if( pixel_size == 2 )
220 : {
221 0 : for( i = width; i != 0; i-- )
222 : {
223 0 : *(dst++) = *(src++);
224 0 : *(dst++) = *(src++);
225 :
226 0 : if( needs_swap )
227 0 : SwapData( dst-2, 2, 1 );
228 :
229 0 : dst += pixel_group-2;
230 : }
231 : }
232 0 : else if( pixel_size == 4 )
233 : {
234 0 : for( i = width; i != 0; i-- )
235 : {
236 0 : *(dst++) = *(src++);
237 0 : *(dst++) = *(src++);
238 0 : *(dst++) = *(src++);
239 0 : *(dst++) = *(src++);
240 :
241 0 : if( needs_swap )
242 0 : SwapData( dst-4, 4, 1);
243 :
244 0 : dst += pixel_group-4;
245 :
246 : }
247 : }
248 : else
249 0 : ThrowPCIDSKException( "Unsupported pixel type..." );
250 : }
251 :
252 0 : file->UnlockBlock( 1 );
253 :
254 : /* -------------------------------------------------------------------- */
255 : /* Do byte swapping if needed. */
256 : /* -------------------------------------------------------------------- */
257 :
258 0 : return 1;
259 : }
260 :
|