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 : CBandInterleavedChannel::CBandInterleavedChannel( PCIDSKBuffer &image_header,
52 : uint64 ih_offset,
53 : PCIDSKBuffer &file_header,
54 : int channelnum,
55 : CPCIDSKFile *file,
56 : uint64 image_offset,
57 239 : eChanType pixel_type )
58 239 : : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)
59 :
60 : {
61 239 : io_handle_p = NULL;
62 239 : io_mutex_p = NULL;
63 :
64 : /* -------------------------------------------------------------------- */
65 : /* Establish the data layout. */
66 : /* -------------------------------------------------------------------- */
67 239 : if( strcmp(file->GetInterleaving().c_str(),"FILE") == 0 )
68 : {
69 0 : start_byte = atouint64(image_header.Get( 168, 16 ));
70 0 : pixel_offset = atouint64(image_header.Get( 184, 8 ));
71 0 : line_offset = atouint64(image_header.Get( 192, 8 ));
72 : }
73 : else
74 : {
75 239 : start_byte = image_offset;
76 239 : pixel_offset = DataTypeSize(pixel_type);
77 239 : line_offset = pixel_offset * width;
78 : }
79 :
80 : /* -------------------------------------------------------------------- */
81 : /* Establish the file we will be accessing. */
82 : /* -------------------------------------------------------------------- */
83 239 : image_header.Get(64,64,filename);
84 :
85 239 : if( filename.length() == 0 )
86 239 : file->GetIODetails( &io_handle_p, &io_mutex_p );
87 239 : }
88 :
89 : /************************************************************************/
90 : /* ~CBandInterleavedChannel() */
91 : /************************************************************************/
92 :
93 239 : CBandInterleavedChannel::~CBandInterleavedChannel()
94 :
95 : {
96 239 : }
97 :
98 : /************************************************************************/
99 : /* ReadBlock() */
100 : /************************************************************************/
101 :
102 : int CBandInterleavedChannel::ReadBlock( int block_index, void *buffer,
103 : int xoff, int yoff,
104 81 : int xsize, int ysize )
105 :
106 : {
107 81 : PCIDSKInterfaces *interfaces = file->GetInterfaces();
108 :
109 : /* -------------------------------------------------------------------- */
110 : /* Default window if needed. */
111 : /* -------------------------------------------------------------------- */
112 81 : if( xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1 )
113 : {
114 81 : xoff = 0;
115 81 : yoff = 0;
116 81 : xsize = GetBlockWidth();
117 81 : ysize = GetBlockHeight();
118 : }
119 :
120 : /* -------------------------------------------------------------------- */
121 : /* Validate Window */
122 : /* -------------------------------------------------------------------- */
123 81 : if( xoff < 0 || xoff + xsize > GetBlockWidth()
124 : || yoff < 0 || yoff + ysize > GetBlockHeight() )
125 : {
126 : ThrowPCIDSKException(
127 : "Invalid window in ReadBloc(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
128 0 : xoff, yoff, xsize, ysize );
129 : }
130 :
131 : /* -------------------------------------------------------------------- */
132 : /* Establish region to read. */
133 : /* -------------------------------------------------------------------- */
134 81 : int pixel_size = DataTypeSize( pixel_type );
135 : uint64 offset = start_byte + line_offset * block_index
136 81 : + pixel_offset * xoff;
137 81 : int window_size = (int) (pixel_offset*(xsize-1) + pixel_size);
138 :
139 : /* -------------------------------------------------------------------- */
140 : /* Get file access handles if we don't already have them. */
141 : /* -------------------------------------------------------------------- */
142 81 : if( io_handle_p == NULL )
143 0 : file->GetIODetails( &io_handle_p, &io_mutex_p, filename.c_str() );
144 :
145 : /* -------------------------------------------------------------------- */
146 : /* If the imagery is packed, we can read directly into the */
147 : /* target buffer. */
148 : /* -------------------------------------------------------------------- */
149 81 : if( pixel_size == (int) pixel_offset )
150 : {
151 81 : MutexHolder holder( *io_mutex_p );
152 :
153 81 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
154 81 : interfaces->io->Read( buffer, 1, window_size, *io_handle_p );
155 : }
156 :
157 : /* -------------------------------------------------------------------- */
158 : /* Otherwise we allocate a working buffer that holds the whole */
159 : /* line, read into that, and pick out our data of interest. */
160 : /* -------------------------------------------------------------------- */
161 : else
162 : {
163 : int i;
164 0 : PCIDSKBuffer line_from_disk( window_size );
165 : char *this_pixel;
166 :
167 0 : MutexHolder holder( *io_mutex_p );
168 :
169 0 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
170 : interfaces->io->Read( buffer, 1, line_from_disk.buffer_size,
171 0 : *io_handle_p );
172 :
173 0 : for( i = 0, this_pixel = line_from_disk.buffer; i < xsize; i++ )
174 : {
175 : memcpy( ((char *) buffer) + pixel_size * i,
176 0 : this_pixel, pixel_size );
177 0 : this_pixel += pixel_size;
178 0 : }
179 : }
180 :
181 : /* -------------------------------------------------------------------- */
182 : /* Do byte swapping if needed. */
183 : /* -------------------------------------------------------------------- */
184 81 : if( needs_swap )
185 60 : SwapPixels( buffer, pixel_type, xsize );
186 :
187 81 : return 1;
188 : }
189 :
190 : /************************************************************************/
191 : /* WriteBlock() */
192 : /************************************************************************/
193 :
194 317 : int CBandInterleavedChannel::WriteBlock( int block_index, void *buffer )
195 :
196 : {
197 317 : PCIDSKInterfaces *interfaces = file->GetInterfaces();
198 :
199 317 : if( !file->GetUpdatable() )
200 0 : throw PCIDSKException( "File not open for update in WriteBlock()" );
201 :
202 317 : InvalidateOverviews();
203 :
204 : /* -------------------------------------------------------------------- */
205 : /* Establish region to read. */
206 : /* -------------------------------------------------------------------- */
207 317 : int pixel_size = DataTypeSize( pixel_type );
208 317 : uint64 offset = start_byte + line_offset * block_index;
209 317 : int window_size = (int) (pixel_offset*(width-1) + pixel_size);
210 :
211 : /* -------------------------------------------------------------------- */
212 : /* Get file access handles if we don't already have them. */
213 : /* -------------------------------------------------------------------- */
214 317 : if( io_handle_p == NULL )
215 0 : file->GetIODetails( &io_handle_p, &io_mutex_p, filename.c_str() );
216 :
217 : /* -------------------------------------------------------------------- */
218 : /* If the imagery is packed, we can read directly into the */
219 : /* target buffer. */
220 : /* -------------------------------------------------------------------- */
221 317 : if( pixel_size == (int) pixel_offset )
222 : {
223 317 : MutexHolder holder( *io_mutex_p );
224 :
225 317 : if( needs_swap ) // swap before write.
226 110 : SwapPixels( buffer, pixel_type, width );
227 :
228 317 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
229 317 : interfaces->io->Write( buffer, 1, window_size, *io_handle_p );
230 :
231 317 : if( needs_swap ) // restore to original order.
232 110 : SwapPixels( buffer, pixel_type, width );
233 : }
234 :
235 : /* -------------------------------------------------------------------- */
236 : /* Otherwise we allocate a working buffer that holds the whole */
237 : /* line, read into that, and pick out our data of interest. */
238 : /* -------------------------------------------------------------------- */
239 : else
240 : {
241 : int i;
242 0 : PCIDSKBuffer line_from_disk( window_size );
243 : char *this_pixel;
244 :
245 0 : MutexHolder holder( *io_mutex_p );
246 :
247 0 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
248 : interfaces->io->Read( buffer, 1, line_from_disk.buffer_size,
249 0 : *io_handle_p );
250 :
251 0 : for( i = 0, this_pixel = line_from_disk.buffer; i < width; i++ )
252 : {
253 : memcpy( this_pixel, ((char *) buffer) + pixel_size * i,
254 0 : pixel_size );
255 :
256 0 : if( needs_swap ) // swap before write.
257 0 : SwapPixels( this_pixel, pixel_type, 1 );
258 :
259 0 : this_pixel += pixel_size;
260 : }
261 :
262 0 : interfaces->io->Seek( *io_handle_p, offset, SEEK_SET );
263 : interfaces->io->Write( buffer, 1, line_from_disk.buffer_size,
264 0 : *io_handle_p );
265 : }
266 :
267 : /* -------------------------------------------------------------------- */
268 : /* Do byte swapping if needed. */
269 : /* -------------------------------------------------------------------- */
270 :
271 317 : return 1;
272 : }
273 :
|