1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the CBandInterleavedChannel class.
4 : *
5 : * This class is used to implement band interleaved channels within a
6 : * PCIDSK file (which are always packed, and FILE interleaved data from
7 : * external raw files which may not be packed.
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2009
11 : * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "pcidsk_config.h"
33 : #include "pcidsk_types.h"
34 : #include "pcidsk_channel.h"
35 : #include "pcidsk_buffer.h"
36 : #include "pcidsk_exception.h"
37 : #include "pcidsk_file.h"
38 : #include "core/pcidsk_utils.h"
39 : #include "core/cpcidskfile.h"
40 : #include "channel/cbandinterleavedchannel.h"
41 : #include <cassert>
42 : #include <cstring>
43 : #include <cstdio>
44 :
45 : using namespace PCIDSK;
46 :
47 : /************************************************************************/
48 : /* CBandInterleavedChannel() */
49 : /************************************************************************/
50 :
51 124 : CBandInterleavedChannel::CBandInterleavedChannel( PCIDSKBuffer &image_header,
52 : PCIDSKBuffer &file_header,
53 : int channelnum,
54 : CPCIDSKFile *file,
55 : uint64 image_offset,
56 : eChanType pixel_type )
57 124 : : CPCIDSKChannel( image_header, file, pixel_type, channelnum )
58 :
59 : {
60 124 : io_handle_p = NULL;
61 124 : io_mutex_p = NULL;
62 :
63 : /* -------------------------------------------------------------------- */
64 : /* Establish the data layout. */
65 : /* -------------------------------------------------------------------- */
66 124 : if( strcmp(file->GetInterleaving().c_str(),"FILE") == 0 )
67 : {
68 0 : start_byte = atouint64(image_header.Get( 168, 16 ));
69 0 : pixel_offset = atouint64(image_header.Get( 184, 8 ));
70 0 : line_offset = atouint64(image_header.Get( 192, 8 ));
71 : }
72 : else
73 : {
74 124 : start_byte = image_offset;
75 124 : pixel_offset = DataTypeSize(pixel_type);
76 124 : line_offset = pixel_offset * width;
77 : }
78 :
79 : /* -------------------------------------------------------------------- */
80 : /* Establish the file we will be accessing. */
81 : /* -------------------------------------------------------------------- */
82 124 : image_header.Get(64,64,filename);
83 :
84 124 : if( filename.length() == 0 )
85 124 : file->GetIODetails( &io_handle_p, &io_mutex_p );
86 124 : }
87 :
88 : /************************************************************************/
89 : /* ~CBandInterleavedChannel() */
90 : /************************************************************************/
91 :
92 248 : CBandInterleavedChannel::~CBandInterleavedChannel()
93 :
94 : {
95 248 : }
96 :
97 : /************************************************************************/
98 : /* ReadBlock() */
99 : /************************************************************************/
100 :
101 81 : int CBandInterleavedChannel::ReadBlock( int block_index, void *buffer,
102 : int xoff, int yoff,
103 : int xsize, int ysize )
104 :
105 : {
106 81 : PCIDSKInterfaces *interfaces = file->GetInterfaces();
107 :
108 : /* -------------------------------------------------------------------- */
109 : /* Default window if needed. */
110 : /* -------------------------------------------------------------------- */
111 81 : if( xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1 )
112 : {
113 81 : xoff = 0;
114 81 : yoff = 0;
115 81 : xsize = GetBlockWidth();
116 81 : ysize = GetBlockHeight();
117 : }
118 :
119 : /* -------------------------------------------------------------------- */
120 : /* Validate Window */
121 : /* -------------------------------------------------------------------- */
122 162 : if( xoff < 0 || xoff + xsize > GetBlockWidth()
123 81 : || yoff < 0 || yoff + ysize > GetBlockHeight() )
124 : {
125 : ThrowPCIDSKException(
126 : "Invalid window in ReadBloc(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
127 0 : xoff, yoff, xsize, ysize );
128 : }
129 :
130 : /* -------------------------------------------------------------------- */
131 : /* Establish region to read. */
132 : /* -------------------------------------------------------------------- */
133 81 : int pixel_size = DataTypeSize( pixel_type );
134 : uint64 offset = start_byte + line_offset * block_index
135 81 : + pixel_offset * xoff;
136 81 : int window_size = (int) (pixel_offset*(xsize-1) + pixel_size);
137 :
138 : /* -------------------------------------------------------------------- */
139 : /* Get file access handles if we don't already have them. */
140 : /* -------------------------------------------------------------------- */
141 81 : if( io_handle_p == NULL )
142 0 : file->GetIODetails( &io_handle_p, &io_mutex_p, filename.c_str() );
143 :
144 : /* -------------------------------------------------------------------- */
145 : /* If the imagery is packed, we can read directly into the */
146 : /* target buffer. */
147 : /* -------------------------------------------------------------------- */
148 81 : if( pixel_size == (int) pixel_offset )
149 : {
150 81 : MutexHolder holder( *io_mutex_p );
151 :
152 81 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
153 81 : interfaces->io->Read( buffer, 1, window_size, *io_handle_p );
154 : }
155 :
156 : /* -------------------------------------------------------------------- */
157 : /* Otherwise we allocate a working buffer that holds the whole */
158 : /* line, read into that, and pick out our data of interest. */
159 : /* -------------------------------------------------------------------- */
160 : else
161 : {
162 : int i;
163 0 : PCIDSKBuffer line_from_disk( window_size );
164 : char *this_pixel;
165 :
166 0 : MutexHolder holder( *io_mutex_p );
167 :
168 0 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
169 : interfaces->io->Read( buffer, 1, line_from_disk.buffer_size,
170 0 : *io_handle_p );
171 :
172 0 : for( i = 0, this_pixel = line_from_disk.buffer; i < xsize; i++ )
173 : {
174 : memcpy( ((char *) buffer) + pixel_size * i,
175 0 : this_pixel, pixel_size );
176 0 : this_pixel += pixel_size;
177 0 : }
178 : }
179 :
180 : /* -------------------------------------------------------------------- */
181 : /* Do byte swapping if needed. */
182 : /* -------------------------------------------------------------------- */
183 81 : if( needs_swap )
184 60 : SwapData( buffer, pixel_size, xsize );
185 :
186 81 : return 1;
187 : }
188 :
189 : /************************************************************************/
190 : /* WriteBlock() */
191 : /************************************************************************/
192 :
193 317 : int CBandInterleavedChannel::WriteBlock( int block_index, void *buffer )
194 :
195 : {
196 317 : PCIDSKInterfaces *interfaces = file->GetInterfaces();
197 :
198 317 : if( !file->GetUpdatable() )
199 0 : throw PCIDSKException( "File not open for update in WriteBlock()" );
200 :
201 : /* -------------------------------------------------------------------- */
202 : /* Establish region to read. */
203 : /* -------------------------------------------------------------------- */
204 317 : int pixel_size = DataTypeSize( pixel_type );
205 317 : uint64 offset = start_byte + line_offset * block_index;
206 317 : int window_size = (int) (pixel_offset*(width-1) + pixel_size);
207 :
208 : /* -------------------------------------------------------------------- */
209 : /* Get file access handles if we don't already have them. */
210 : /* -------------------------------------------------------------------- */
211 317 : if( io_handle_p == NULL )
212 0 : file->GetIODetails( &io_handle_p, &io_mutex_p, filename.c_str() );
213 :
214 : /* -------------------------------------------------------------------- */
215 : /* If the imagery is packed, we can read directly into the */
216 : /* target buffer. */
217 : /* -------------------------------------------------------------------- */
218 317 : if( pixel_size == (int) pixel_offset )
219 : {
220 317 : MutexHolder holder( *io_mutex_p );
221 :
222 317 : if( needs_swap ) // swap before write.
223 90 : SwapData( buffer, pixel_size, width );
224 :
225 317 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
226 317 : interfaces->io->Write( buffer, 1, window_size, *io_handle_p );
227 :
228 317 : if( needs_swap ) // restore to original order.
229 90 : SwapData( buffer, pixel_size, width );
230 : }
231 :
232 : /* -------------------------------------------------------------------- */
233 : /* Otherwise we allocate a working buffer that holds the whole */
234 : /* line, read into that, and pick out our data of interest. */
235 : /* -------------------------------------------------------------------- */
236 : else
237 : {
238 : int i;
239 0 : PCIDSKBuffer line_from_disk( window_size );
240 : char *this_pixel;
241 :
242 0 : MutexHolder holder( *io_mutex_p );
243 :
244 0 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
245 : interfaces->io->Read( buffer, 1, line_from_disk.buffer_size,
246 0 : *io_handle_p );
247 :
248 0 : for( i = 0, this_pixel = line_from_disk.buffer; i < width; i++ )
249 : {
250 : memcpy( this_pixel, ((char *) buffer) + pixel_size * i,
251 0 : pixel_size );
252 :
253 0 : if( needs_swap ) // swap before write.
254 0 : SwapData( this_pixel, pixel_size, 1 );
255 :
256 0 : this_pixel += pixel_size;
257 : }
258 :
259 0 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
260 : interfaces->io->Write( buffer, 1, line_from_disk.buffer_size,
261 0 : *io_handle_p );
262 : }
263 :
264 : /* -------------------------------------------------------------------- */
265 : /* Do byte swapping if needed. */
266 : /* -------------------------------------------------------------------- */
267 :
268 317 : return 1;
269 : }
270 :
|