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 : PCIDSKBuffer &file_header,
43 : int channelnum,
44 : CPCIDSKFile *file,
45 : int image_offset,
46 : eChanType pixel_type )
47 0 : : CPCIDSKChannel( image_header, file, pixel_type, channelnum )
48 :
49 : {
50 0 : this->image_offset = image_offset;
51 0 : }
52 :
53 : /************************************************************************/
54 : /* ~CPixelInterleavedChannel() */
55 : /************************************************************************/
56 :
57 0 : CPixelInterleavedChannel::~CPixelInterleavedChannel()
58 :
59 : {
60 0 : }
61 :
62 : /************************************************************************/
63 : /* ReadBlock() */
64 : /************************************************************************/
65 :
66 0 : int CPixelInterleavedChannel::ReadBlock( int block_index, void *buffer,
67 : int win_xoff, int win_yoff,
68 : int win_xsize, int win_ysize )
69 :
70 : {
71 : /* -------------------------------------------------------------------- */
72 : /* Default window if needed. */
73 : /* -------------------------------------------------------------------- */
74 0 : if( win_xoff == -1 && win_yoff == -1 && win_xsize == -1 && win_ysize == -1 )
75 : {
76 0 : win_xoff = 0;
77 0 : win_yoff = 0;
78 0 : win_xsize = GetBlockWidth();
79 0 : win_ysize = GetBlockHeight();
80 : }
81 :
82 : /* -------------------------------------------------------------------- */
83 : /* Validate Window */
84 : /* -------------------------------------------------------------------- */
85 0 : if( win_xoff < 0 || win_xoff + win_xsize > GetBlockWidth()
86 0 : || win_yoff < 0 || win_yoff + win_ysize > GetBlockHeight() )
87 : {
88 : ThrowPCIDSKException(
89 : "Invalid window in ReadBloc(): win_xoff=%d,win_yoff=%d,xsize=%d,ysize=%d",
90 0 : win_xoff, win_yoff, win_xsize, win_ysize );
91 : }
92 :
93 : /* -------------------------------------------------------------------- */
94 : /* Work out sizes and offsets. */
95 : /* -------------------------------------------------------------------- */
96 0 : int pixel_group = file->GetPixelGroupSize();
97 0 : int pixel_size = DataTypeSize(GetType());
98 :
99 : /* -------------------------------------------------------------------- */
100 : /* Read and lock the scanline. */
101 : /* -------------------------------------------------------------------- */
102 : uint8 *pixel_buffer = (uint8 *)
103 0 : file->ReadAndLockBlock( block_index, win_xoff, win_xsize);
104 :
105 : /* -------------------------------------------------------------------- */
106 : /* Copy the data into our callers buffer. Try to do this */
107 : /* reasonably efficiently. We might consider adding faster */
108 : /* cases for 16/32bit data that is word aligned. */
109 : /* -------------------------------------------------------------------- */
110 0 : if( pixel_size == pixel_group )
111 0 : memcpy( buffer, pixel_buffer, pixel_size * win_xsize );
112 : else
113 : {
114 : int i;
115 0 : uint8 *src = ((uint8 *)pixel_buffer) + image_offset;
116 0 : uint8 *dst = (uint8 *) buffer;
117 :
118 0 : if( pixel_size == 1 )
119 : {
120 0 : for( i = win_xsize; i != 0; i-- )
121 : {
122 0 : *dst = *src;
123 0 : dst++;
124 0 : src += pixel_group;
125 : }
126 : }
127 0 : else if( pixel_size == 2 )
128 : {
129 0 : for( i = win_xsize; i != 0; i-- )
130 : {
131 0 : *(dst++) = *(src++);
132 0 : *(dst++) = *(src++);
133 0 : src += pixel_group-2;
134 : }
135 : }
136 0 : else if( pixel_size == 4 )
137 : {
138 0 : for( i = win_xsize; i != 0; i-- )
139 : {
140 0 : *(dst++) = *(src++);
141 0 : *(dst++) = *(src++);
142 0 : *(dst++) = *(src++);
143 0 : *(dst++) = *(src++);
144 0 : src += pixel_group-4;
145 : }
146 : }
147 : else
148 0 : ThrowPCIDSKException( "Unsupported pixel type..." );
149 : }
150 :
151 0 : file->UnlockBlock( 0 );
152 :
153 : /* -------------------------------------------------------------------- */
154 : /* Do byte swapping if needed. */
155 : /* -------------------------------------------------------------------- */
156 0 : if( needs_swap )
157 0 : SwapData( buffer, pixel_size, win_xsize );
158 :
159 0 : return 1;
160 : }
161 :
162 : /************************************************************************/
163 : /* WriteBlock() */
164 : /************************************************************************/
165 :
166 0 : int CPixelInterleavedChannel::WriteBlock( int block_index, void *buffer )
167 :
168 : {
169 0 : if( !file->GetUpdatable() )
170 0 : throw PCIDSKException( "File not open for update in WriteBlock()" );
171 :
172 : /* -------------------------------------------------------------------- */
173 : /* Work out sizes and offsets. */
174 : /* -------------------------------------------------------------------- */
175 0 : int pixel_group = file->GetPixelGroupSize();
176 0 : int pixel_size = DataTypeSize(GetType());
177 :
178 : /* -------------------------------------------------------------------- */
179 : /* Read and lock the scanline. */
180 : /* -------------------------------------------------------------------- */
181 0 : uint8 *pixel_buffer = (uint8 *) file->ReadAndLockBlock( block_index );
182 :
183 : /* -------------------------------------------------------------------- */
184 : /* Copy the data into our callers buffer. Try to do this */
185 : /* reasonably efficiently. We might consider adding faster */
186 : /* cases for 16/32bit data that is word aligned. */
187 : /* -------------------------------------------------------------------- */
188 0 : if( pixel_size == pixel_group )
189 0 : memcpy( pixel_buffer, buffer, pixel_size * width );
190 : else
191 : {
192 : int i;
193 0 : uint8 *dst = ((uint8 *)pixel_buffer) + image_offset;
194 0 : uint8 *src = (uint8 *) buffer;
195 :
196 0 : if( pixel_size == 1 )
197 : {
198 0 : for( i = width; i != 0; i-- )
199 : {
200 0 : *dst = *src;
201 0 : src++;
202 0 : dst += pixel_group;
203 : }
204 : }
205 0 : else if( pixel_size == 2 )
206 : {
207 0 : for( i = width; i != 0; i-- )
208 : {
209 0 : *(dst++) = *(src++);
210 0 : *(dst++) = *(src++);
211 :
212 0 : if( needs_swap )
213 0 : SwapData( dst-2, 2, 1 );
214 :
215 0 : dst += pixel_group-2;
216 : }
217 : }
218 0 : else if( pixel_size == 4 )
219 : {
220 0 : for( i = width; i != 0; i-- )
221 : {
222 0 : *(dst++) = *(src++);
223 0 : *(dst++) = *(src++);
224 0 : *(dst++) = *(src++);
225 0 : *(dst++) = *(src++);
226 :
227 0 : if( needs_swap )
228 0 : SwapData( dst-4, 4, 1);
229 :
230 0 : dst += pixel_group-4;
231 :
232 : }
233 : }
234 : else
235 0 : ThrowPCIDSKException( "Unsupported pixel type..." );
236 : }
237 :
238 0 : file->UnlockBlock( 1 );
239 :
240 : /* -------------------------------------------------------------------- */
241 : /* Do byte swapping if needed. */
242 : /* -------------------------------------------------------------------- */
243 :
244 0 : return 1;
245 : }
246 :
|