Line data Source code
1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the CExternalChannel class.
4 : *
5 : * This class is used to implement band interleaved channels that are
6 : * references to an external image database that is not just a raw file.
7 : * It uses the application supplied EDB interface to access non-PCIDSK files.
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2010
11 : * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
12 : *
13 : * SPDX-License-Identifier: MIT
14 : ****************************************************************************/
15 :
16 : #include "pcidsk_config.h"
17 : #include "pcidsk_types.h"
18 : #include "pcidsk_channel.h"
19 : #include "pcidsk_buffer.h"
20 : #include "pcidsk_exception.h"
21 : #include "pcidsk_file.h"
22 : #include "core/pcidsk_utils.h"
23 : #include "core/cpcidskfile.h"
24 : #include "channel/cexternalchannel.h"
25 : #include "core/clinksegment.h"
26 : #include <algorithm>
27 : #include <cassert>
28 : #include <cstring>
29 : #include <cstdio>
30 : #include <cstdlib>
31 : #include <climits>
32 :
33 : using namespace PCIDSK;
34 :
35 : /************************************************************************/
36 : /* CExternalChannel() */
37 : /************************************************************************/
38 :
39 0 : CExternalChannel::CExternalChannel( PCIDSKBuffer &image_headerIn,
40 : uint64 ih_offsetIn,
41 : CPL_UNUSED PCIDSKBuffer &file_headerIn,
42 : const std::string& filenameIn,
43 : int channelnumIn,
44 : CPCIDSKFile *fileIn,
45 0 : eChanType pixel_typeIn )
46 0 : : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
47 :
48 : {
49 0 : db = nullptr;
50 0 : mutex = nullptr;
51 0 : writable = false;
52 0 : blocks_per_row = 0;
53 :
54 : /* -------------------------------------------------------------------- */
55 : /* Establish the data window. */
56 : /* -------------------------------------------------------------------- */
57 0 : exoff = atoi(image_headerIn.Get( 250, 8 ));
58 0 : eyoff = atoi(image_headerIn.Get( 258, 8 ));
59 0 : exsize = atoi(image_headerIn.Get( 266, 8 ));
60 0 : eysize = atoi(image_headerIn.Get( 274, 8 ));
61 :
62 0 : echannel = atoi(image_headerIn.Get( 282, 8 ));
63 :
64 0 : if (echannel == 0) {
65 0 : echannel = channelnumIn;
66 : }
67 :
68 0 : if( exoff < 0 || eyoff < 0 || exsize < 0 || eysize < 0 )
69 : {
70 0 : ThrowPCIDSKException("Invalid data window parameters for CExternalChannel");
71 : }
72 :
73 : /* -------------------------------------------------------------------- */
74 : /* Establish the file we will be accessing. */
75 : /* -------------------------------------------------------------------- */
76 0 : if( filenameIn != "" )
77 0 : this->filename = filenameIn;
78 : else
79 0 : image_headerIn.Get(64,64,this->filename);
80 0 : }
81 :
82 : /************************************************************************/
83 : /* ~CExternalChannel() */
84 : /************************************************************************/
85 :
86 0 : CExternalChannel::~CExternalChannel()
87 :
88 : {
89 : // no need to deaccess the EDBFile - the file is responsible for that.
90 0 : }
91 :
92 : /************************************************************************/
93 : /* AccessDB() */
94 : /************************************************************************/
95 :
96 0 : void CExternalChannel::AccessDB() const
97 :
98 : {
99 0 : if( db )
100 0 : return;
101 :
102 : /* -------------------------------------------------------------------- */
103 : /* open, or fetch an already open file handle. */
104 : /* -------------------------------------------------------------------- */
105 0 : writable = file->GetEDBFileDetails( &db, &mutex, filename );
106 :
107 0 : if( !db )
108 : {
109 0 : ThrowPCIDSKException("db == nullptr");
110 : }
111 : else
112 : {
113 0 : if( echannel < 0 || echannel > db->GetChannels() )
114 : {
115 0 : ThrowPCIDSKException( 0,
116 0 : "Invalid channel number: %d", echannel );
117 : }
118 :
119 0 : pixel_type = db->GetType(echannel);
120 :
121 : /* -------------------------------------------------------------------- */
122 : /* Capture the block size. */
123 : /* -------------------------------------------------------------------- */
124 0 : block_width = db->GetBlockWidth( echannel );
125 0 : if( block_width > width )
126 0 : block_width = width;
127 0 : block_height = db->GetBlockHeight( echannel );
128 0 : if( block_height > height )
129 0 : block_height = height;
130 :
131 0 : blocks_per_row = DIV_ROUND_UP(GetWidth(), block_width);
132 : }
133 : }
134 :
135 : /************************************************************************/
136 : /* GetType() */
137 : /************************************************************************/
138 :
139 0 : eChanType CExternalChannel::GetType() const
140 : {
141 0 : AccessDB();
142 :
143 0 : return pixel_type;
144 : }
145 :
146 : /************************************************************************/
147 : /* GetBlockWidth() */
148 : /************************************************************************/
149 :
150 0 : int CExternalChannel::GetBlockWidth() const
151 :
152 : {
153 0 : AccessDB();
154 :
155 0 : return block_width;
156 : }
157 :
158 : /************************************************************************/
159 : /* GetBlockHeight() */
160 : /************************************************************************/
161 :
162 0 : int CExternalChannel::GetBlockHeight() const
163 :
164 : {
165 0 : AccessDB();
166 :
167 0 : return block_height;
168 : }
169 :
170 : /************************************************************************/
171 : /* ReadBlock() */
172 : /************************************************************************/
173 :
174 0 : int CExternalChannel::ReadBlock( int block_index, void *buffer,
175 : int xoff, int yoff,
176 : int xsize, int ysize )
177 :
178 : {
179 0 : AccessDB();
180 :
181 : /* -------------------------------------------------------------------- */
182 : /* Default window if needed. */
183 : /* -------------------------------------------------------------------- */
184 0 : if( xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1 )
185 : {
186 0 : xoff = 0;
187 0 : yoff = 0;
188 0 : xsize = GetBlockWidth();
189 0 : ysize = GetBlockHeight();
190 : }
191 :
192 : /* -------------------------------------------------------------------- */
193 : /* Validate Window */
194 : /* -------------------------------------------------------------------- */
195 0 : if( xoff < 0 || xoff + xsize > GetBlockWidth()
196 0 : || yoff < 0 || yoff + ysize > GetBlockHeight() )
197 : {
198 0 : return ThrowPCIDSKException( 0,
199 : "Invalid window in ReadBlock(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
200 0 : xoff, yoff, xsize, ysize );
201 : }
202 :
203 : /* -------------------------------------------------------------------- */
204 : /* Do a direct call for the simplest case of 1:1 block mapping. */
205 : /* -------------------------------------------------------------------- */
206 0 : if( exoff == 0 && eyoff == 0
207 0 : && exsize == db->GetWidth()
208 0 : && eysize == db->GetHeight() )
209 : {
210 0 : MutexHolder oHolder( mutex );
211 0 : return db->ReadBlock( echannel, block_index, buffer,
212 0 : xoff, yoff, xsize, ysize );
213 : }
214 :
215 : /* ==================================================================== */
216 : /* Otherwise we need to break this down into potentially up to */
217 : /* four requests against the source file. */
218 : /* ==================================================================== */
219 0 : int src_block_width = db->GetBlockWidth( echannel );
220 0 : int src_block_height = db->GetBlockHeight( echannel );
221 0 : int src_blocks_per_row = (db->GetWidth() + src_block_width - 1)
222 0 : / src_block_width;
223 0 : int pixel_size = DataTypeSize(GetType());
224 0 : std::vector<uint8> temp_buffer_vec;
225 : try
226 : {
227 0 : temp_buffer_vec.resize(static_cast<size_t>(src_block_width)*src_block_height*pixel_size);
228 : }
229 0 : catch( const std::exception& )
230 : {
231 0 : return ThrowPCIDSKException(0, "Failed to allocate temporary block buffer." );
232 : }
233 0 : uint8 *temp_buffer = &temp_buffer_vec[0];
234 :
235 0 : const int dst_blockx = block_index % blocks_per_row;
236 0 : const int dst_blocky = block_index / blocks_per_row;
237 :
238 : // what is the region of our desired data on the destination file?
239 :
240 0 : const int txoff = dst_blockx * block_width + exoff + xoff;
241 0 : const int tyoff = dst_blocky * block_height + eyoff + yoff;
242 0 : const int txsize = xsize;
243 0 : const int tysize = ysize;
244 :
245 : /* -------------------------------------------------------------------- */
246 : /* read external block for top left corner of target block. */
247 : /* -------------------------------------------------------------------- */
248 0 : int block1_xsize=0, block1_ysize=0;
249 : {
250 0 : const int ttxoff = txoff;
251 0 : const int ttyoff = tyoff;
252 0 : const int ttxsize = txsize;
253 0 : const int ttysize = tysize;
254 :
255 0 : const int ablock_x = ttxoff / src_block_width;
256 0 : const int ablock_y = ttyoff / src_block_height;
257 :
258 0 : const int axoff = ttxoff - ablock_x * src_block_width;
259 0 : const int ayoff = ttyoff - ablock_y * src_block_height;
260 :
261 0 : const int axsize = std::min(src_block_width - axoff, ttxsize);
262 0 : const int aysize = std::min(src_block_height - ayoff, ttysize);
263 :
264 0 : block1_xsize = std::max(0, axsize);
265 0 : block1_ysize = std::max(0, aysize);
266 :
267 0 : if( axsize > 0 && aysize > 0 )
268 : {
269 0 : MutexHolder oHolder( mutex );
270 0 : if( src_blocks_per_row > 0 &&
271 0 : (ablock_y > INT_MAX / src_blocks_per_row ||
272 0 : ablock_y * src_blocks_per_row > INT_MAX - ablock_x) )
273 : {
274 0 : ThrowPCIDSKException(0, "Integer overflow." );
275 : }
276 0 : db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
277 0 : temp_buffer, axoff, ayoff, axsize, aysize );
278 :
279 0 : for( int i_line = 0; i_line < aysize; i_line++ )
280 : {
281 0 : memcpy( ((uint8*) buffer) + i_line * xsize * pixel_size,
282 0 : temp_buffer + i_line * axsize * pixel_size,
283 0 : static_cast<size_t>(axsize) * pixel_size );
284 : }
285 : }
286 : }
287 :
288 : /* -------------------------------------------------------------------- */
289 : /* read external block for top right corner of target block. */
290 : /* -------------------------------------------------------------------- */
291 : {
292 0 : const int ttxoff = txoff + block1_xsize;
293 0 : const int ttyoff = tyoff;
294 0 : const int ttxsize = txsize - block1_xsize;
295 0 : const int ttysize = tysize;
296 :
297 0 : const int ablock_x = ttxoff / src_block_width;
298 0 : const int ablock_y = ttyoff / src_block_height;
299 :
300 0 : const int axoff = ttxoff - ablock_x * src_block_width;
301 0 : const int ayoff = ttyoff - ablock_y * src_block_height;
302 :
303 0 : const int axsize = std::min(src_block_width - axoff, ttxsize);
304 0 : const int aysize = std::min(src_block_height - ayoff, ttysize);
305 :
306 0 : if( axsize > 0 && aysize > 0 )
307 : {
308 0 : MutexHolder oHolder( mutex );
309 0 : db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
310 0 : temp_buffer, axoff, ayoff, axsize, aysize );
311 :
312 0 : for( int i_line = 0; i_line < aysize; i_line++ )
313 : {
314 0 : memcpy( ((uint8*) buffer)
315 0 : + (block1_xsize + i_line * xsize) * pixel_size,
316 0 : temp_buffer + i_line * axsize * pixel_size,
317 0 : static_cast<size_t>(axsize) * pixel_size );
318 : }
319 : }
320 : }
321 :
322 : /* -------------------------------------------------------------------- */
323 : /* read external block for bottom left corner of target block. */
324 : /* -------------------------------------------------------------------- */
325 : {
326 0 : const int ttxoff = txoff;
327 0 : const int ttyoff = tyoff + block1_ysize;
328 0 : const int ttxsize = txsize;
329 0 : const int ttysize = tysize - block1_ysize;
330 :
331 0 : const int ablock_x = ttxoff / src_block_width;
332 0 : const int ablock_y = ttyoff / src_block_height;
333 :
334 0 : const int axoff = ttxoff - ablock_x * src_block_width;
335 0 : const int ayoff = ttyoff - ablock_y * src_block_height;
336 :
337 0 : const int axsize = std::min(src_block_width - axoff, ttxsize);
338 0 : const int aysize = std::min(src_block_height - ayoff, ttysize);
339 :
340 0 : if( axsize > 0 && aysize > 0 )
341 : {
342 0 : MutexHolder oHolder( mutex );
343 0 : db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
344 0 : temp_buffer, axoff, ayoff, axsize, aysize );
345 :
346 0 : for( int i_line = 0; i_line < aysize; i_line++ )
347 : {
348 0 : memcpy( ((uint8*) buffer)
349 0 : + (i_line + block1_ysize) * xsize * pixel_size,
350 0 : temp_buffer + i_line * axsize * pixel_size,
351 0 : static_cast<size_t>(axsize) * pixel_size );
352 : }
353 : }
354 : }
355 :
356 : /* -------------------------------------------------------------------- */
357 : /* read external block for bottom left corner of target block. */
358 : /* -------------------------------------------------------------------- */
359 : {
360 0 : const int ttxoff = txoff + block1_xsize;
361 0 : const int ttyoff = tyoff + block1_ysize;
362 0 : const int ttxsize = txsize - block1_xsize;
363 0 : const int ttysize = tysize - block1_ysize;
364 :
365 0 : const int ablock_x = ttxoff / src_block_width;
366 0 : const int ablock_y = ttyoff / src_block_height;
367 :
368 0 : const int axoff = ttxoff - ablock_x * src_block_width;
369 0 : const int ayoff = ttyoff - ablock_y * src_block_height;
370 :
371 0 : const int axsize = std::min(src_block_width - axoff, ttxsize);
372 0 : const int aysize = std::min(src_block_height - ayoff, ttysize);
373 :
374 0 : if( axsize > 0 && aysize > 0 )
375 : {
376 0 : MutexHolder oHolder( mutex );
377 0 : db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
378 0 : temp_buffer, axoff, ayoff, axsize, aysize );
379 :
380 0 : for( int i_line = 0; i_line < aysize; i_line++ )
381 : {
382 0 : memcpy( ((uint8*) buffer)
383 0 : + (block1_xsize + (i_line + block1_ysize) * xsize) * pixel_size,
384 0 : temp_buffer + i_line * axsize * pixel_size,
385 0 : static_cast<size_t>(axsize) * pixel_size );
386 : }
387 : }
388 : }
389 :
390 0 : return 1;
391 : }
392 :
393 : /************************************************************************/
394 : /* WriteBlock() */
395 : /************************************************************************/
396 :
397 0 : int CExternalChannel::WriteBlock( int block_index, void *buffer )
398 :
399 : {
400 0 : AccessDB();
401 :
402 0 : if( !file->GetUpdatable() || !writable )
403 0 : return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
404 :
405 : /* -------------------------------------------------------------------- */
406 : /* Pass the request on directly in the simple case. */
407 : /* -------------------------------------------------------------------- */
408 0 : if( exoff == 0 && eyoff == 0
409 0 : && exsize == db->GetWidth()
410 0 : && eysize == db->GetHeight() )
411 : {
412 0 : MutexHolder oHolder( mutex );
413 0 : return db->WriteBlock( echannel, block_index, buffer );
414 : }
415 :
416 : /* ==================================================================== */
417 : /* Otherwise we need to break this down into potentially up to */
418 : /* four requests against the source file. */
419 : /* ==================================================================== */
420 0 : int src_block_width = db->GetBlockWidth( echannel );
421 0 : int src_block_height = db->GetBlockHeight( echannel );
422 0 : int src_blocks_per_row = (db->GetWidth() + src_block_width - 1)
423 0 : / src_block_width;
424 0 : int pixel_size = DataTypeSize(GetType());
425 0 : uint8 *temp_buffer = (uint8 *) calloc(static_cast<size_t>(src_block_width)*src_block_height,
426 : pixel_size);
427 : int txoff, tyoff, txsize, tysize;
428 : int dst_blockx, dst_blocky;
429 :
430 0 : if( temp_buffer == nullptr )
431 0 : return ThrowPCIDSKException(0, "Failed to allocate temporary block buffer." );
432 :
433 0 : dst_blockx = block_index % blocks_per_row;
434 0 : dst_blocky = block_index / blocks_per_row;
435 :
436 : // what is the region of our desired data on the destination file?
437 :
438 0 : txoff = dst_blockx * block_width + exoff;
439 0 : tyoff = dst_blocky * block_height + eyoff;
440 0 : txsize = block_width;
441 0 : tysize = block_height;
442 :
443 : /* -------------------------------------------------------------------- */
444 : /* process external block for top left corner of target block. */
445 : /* -------------------------------------------------------------------- */
446 : int ablock_x, ablock_y, i_line;
447 : int axoff, ayoff, axsize, aysize;
448 0 : int block1_xsize=0, block1_ysize=0;
449 : int ttxoff, ttyoff, ttxsize, ttysize;
450 :
451 0 : ttxoff = txoff;
452 0 : ttyoff = tyoff;
453 0 : ttxsize = txsize;
454 0 : ttysize = tysize;
455 :
456 0 : ablock_x = ttxoff / src_block_width;
457 0 : ablock_y = ttyoff / src_block_height;
458 :
459 0 : axoff = ttxoff - ablock_x * src_block_width;
460 0 : ayoff = ttyoff - ablock_y * src_block_height;
461 :
462 0 : if( axoff + ttxsize > src_block_width )
463 0 : axsize = src_block_width - axoff;
464 : else
465 0 : axsize = ttxsize;
466 :
467 0 : if( ayoff + ttysize > src_block_height )
468 0 : aysize = src_block_height - ayoff;
469 : else
470 0 : aysize = ttysize;
471 :
472 0 : if( axsize > 0 )
473 0 : block1_xsize = axsize;
474 : else
475 0 : block1_xsize = 0;
476 :
477 0 : if( aysize > 0 )
478 0 : block1_ysize = aysize;
479 : else
480 0 : block1_ysize = 0;
481 :
482 0 : if( axsize > 0 && aysize > 0 )
483 : {
484 0 : MutexHolder oHolder( mutex );
485 0 : db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
486 0 : temp_buffer );
487 :
488 0 : for( i_line = 0; i_line < aysize; i_line++ )
489 : {
490 0 : memcpy( temp_buffer
491 0 : + (i_line+ayoff) * src_block_width * pixel_size
492 0 : + axoff * pixel_size,
493 0 : ((uint8*) buffer) + i_line * block_width * pixel_size,
494 0 : static_cast<size_t>(axsize) * pixel_size );
495 : }
496 :
497 0 : db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
498 0 : temp_buffer );
499 : }
500 :
501 : /* -------------------------------------------------------------------- */
502 : /* read external block for top right corner of target block. */
503 : /* -------------------------------------------------------------------- */
504 0 : ttxoff = txoff + block1_xsize;
505 0 : ttyoff = tyoff;
506 0 : ttxsize = txsize - block1_xsize;
507 0 : ttysize = tysize;
508 :
509 0 : ablock_x = ttxoff / src_block_width;
510 0 : ablock_y = ttyoff / src_block_height;
511 :
512 0 : axoff = ttxoff - ablock_x * src_block_width;
513 0 : ayoff = ttyoff - ablock_y * src_block_height;
514 :
515 0 : if( axoff + ttxsize > src_block_width )
516 0 : axsize = src_block_width - axoff;
517 : else
518 0 : axsize = ttxsize;
519 :
520 0 : if( ayoff + ttysize > src_block_height )
521 0 : aysize = src_block_height - ayoff;
522 : else
523 0 : aysize = ttysize;
524 :
525 0 : if( axsize > 0 && aysize > 0 )
526 : {
527 0 : MutexHolder oHolder( mutex );
528 0 : db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
529 0 : temp_buffer );
530 :
531 0 : for( i_line = 0; i_line < aysize; i_line++ )
532 : {
533 0 : memcpy( temp_buffer
534 0 : + (i_line+ayoff) * src_block_width * pixel_size
535 0 : + axoff * pixel_size,
536 0 : ((uint8*) buffer) + i_line * block_width * pixel_size
537 0 : + block1_xsize * pixel_size,
538 0 : static_cast<size_t>(axsize) * pixel_size );
539 : }
540 :
541 0 : db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
542 0 : temp_buffer );
543 : }
544 :
545 : /* -------------------------------------------------------------------- */
546 : /* read external block for bottom left corner of target block. */
547 : /* -------------------------------------------------------------------- */
548 0 : ttxoff = txoff;
549 0 : ttyoff = tyoff + block1_ysize;
550 0 : ttxsize = txsize;
551 0 : ttysize = tysize - block1_ysize;
552 :
553 0 : ablock_x = ttxoff / src_block_width;
554 0 : ablock_y = ttyoff / src_block_height;
555 :
556 0 : axoff = ttxoff - ablock_x * src_block_width;
557 0 : ayoff = ttyoff - ablock_y * src_block_height;
558 :
559 0 : if( axoff + ttxsize > src_block_width )
560 0 : axsize = src_block_width - axoff;
561 : else
562 0 : axsize = ttxsize;
563 :
564 0 : if( ayoff + ttysize > src_block_height )
565 0 : aysize = src_block_height - ayoff;
566 : else
567 0 : aysize = ttysize;
568 :
569 0 : if( axsize > 0 && aysize > 0 )
570 : {
571 0 : MutexHolder oHolder( mutex );
572 0 : db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
573 0 : temp_buffer );
574 :
575 0 : for( i_line = 0; i_line < aysize; i_line++ )
576 : {
577 0 : memcpy( temp_buffer
578 0 : + (i_line+ayoff) * src_block_width * pixel_size
579 0 : + axoff * pixel_size,
580 : ((uint8*) buffer)
581 0 : + (i_line+block1_ysize) * block_width * pixel_size,
582 0 : static_cast<size_t>(axsize) * pixel_size );
583 : }
584 :
585 0 : db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
586 0 : temp_buffer );
587 : }
588 :
589 : /* -------------------------------------------------------------------- */
590 : /* read external block for bottom left corner of target block. */
591 : /* -------------------------------------------------------------------- */
592 0 : ttxoff = txoff + block1_xsize;
593 0 : ttyoff = tyoff + block1_ysize;
594 0 : ttxsize = txsize - block1_xsize;
595 0 : ttysize = tysize - block1_ysize;
596 :
597 0 : ablock_x = ttxoff / src_block_width;
598 0 : ablock_y = ttyoff / src_block_height;
599 :
600 0 : axoff = ttxoff - ablock_x * src_block_width;
601 0 : ayoff = ttyoff - ablock_y * src_block_height;
602 :
603 0 : if( axoff + ttxsize > src_block_width )
604 0 : axsize = src_block_width - axoff;
605 : else
606 0 : axsize = ttxsize;
607 :
608 0 : if( ayoff + ttysize > src_block_height )
609 0 : aysize = src_block_height - ayoff;
610 : else
611 0 : aysize = ttysize;
612 :
613 0 : if( axsize > 0 && aysize > 0 )
614 : {
615 0 : MutexHolder oHolder( mutex );
616 0 : db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
617 0 : temp_buffer );
618 :
619 0 : for( i_line = 0; i_line < aysize; i_line++ )
620 : {
621 0 : memcpy( temp_buffer
622 0 : + (i_line+ayoff) * src_block_width * pixel_size
623 0 : + axoff * pixel_size,
624 : ((uint8*) buffer)
625 0 : + (i_line+block1_ysize) * block_width * pixel_size
626 0 : + block1_xsize * pixel_size,
627 0 : static_cast<size_t>(axsize) * pixel_size );
628 : }
629 :
630 0 : db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
631 0 : temp_buffer );
632 : }
633 :
634 0 : free( temp_buffer );
635 :
636 0 : return 1;
637 : }
638 :
639 : /************************************************************************/
640 : /* GetEChanInfo() */
641 : /************************************************************************/
642 0 : void CExternalChannel::GetEChanInfo( std::string &filenameOut, int &echannelOut,
643 : int &exoffOut, int &eyoffOut,
644 : int &exsizeOut, int &eysizeOut ) const
645 :
646 : {
647 0 : echannelOut = this->echannel;
648 0 : exoffOut = this->exoff;
649 0 : eyoffOut = this->eyoff;
650 0 : exsizeOut = this->exsize;
651 0 : eysizeOut = this->eysize;
652 0 : filenameOut = this->filename;
653 0 : }
654 :
655 : /************************************************************************/
656 : /* SetEChanInfo() */
657 : /************************************************************************/
658 :
659 0 : void CExternalChannel::SetEChanInfo( std::string filenameIn, int echannelIn,
660 : int exoffIn, int eyoffIn,
661 : int exsizeIn, int eysizeIn )
662 :
663 : {
664 0 : if( ih_offset == 0 )
665 0 : return ThrowPCIDSKException( "No Image Header available for this channel." );
666 :
667 : /* -------------------------------------------------------------------- */
668 : /* Fetch the existing image header. */
669 : /* -------------------------------------------------------------------- */
670 0 : PCIDSKBuffer ih(1024);
671 :
672 0 : file->ReadFromFile( ih.buffer, ih_offset, 1024 );
673 :
674 : /* -------------------------------------------------------------------- */
675 : /* If the linked filename is too long to fit in the 64 */
676 : /* character IHi.2 field, then we need to use a link segment to */
677 : /* store the filename. */
678 : /* -------------------------------------------------------------------- */
679 0 : std::string IHi2_filename;
680 :
681 0 : if( filenameIn.size() > 64 )
682 : {
683 : int link_segment;
684 :
685 0 : ih.Get( 64, 64, IHi2_filename );
686 :
687 0 : if( IHi2_filename.substr(0,3) == "LNK" )
688 : {
689 0 : link_segment = std::atoi( IHi2_filename.c_str() + 4 );
690 : }
691 : else
692 : {
693 : char link_filename[64];
694 :
695 : link_segment =
696 0 : file->CreateSegment( "Link ",
697 : "Long external channel filename link.",
698 : SEG_SYS, 1 );
699 :
700 0 : snprintf( link_filename, sizeof(link_filename), "LNK %4d", link_segment );
701 0 : IHi2_filename = link_filename;
702 : }
703 :
704 : CLinkSegment *link =
705 0 : dynamic_cast<CLinkSegment*>( file->GetSegment( link_segment ) );
706 :
707 0 : if( link != nullptr )
708 : {
709 0 : link->SetPath( filenameIn );
710 0 : link->Synchronize();
711 : }
712 : }
713 :
714 : /* -------------------------------------------------------------------- */
715 : /* If we used to have a link segment but no longer need it, we */
716 : /* need to delete the link segment. */
717 : /* -------------------------------------------------------------------- */
718 : else
719 : {
720 0 : ih.Get( 64, 64, IHi2_filename );
721 :
722 0 : if( IHi2_filename.substr(0,3) == "LNK" )
723 : {
724 0 : int link_segment = std::atoi( IHi2_filename.c_str() + 4 );
725 :
726 0 : file->DeleteSegment( link_segment );
727 : }
728 :
729 0 : IHi2_filename = filenameIn;
730 : }
731 :
732 : /* -------------------------------------------------------------------- */
733 : /* Update the image header. */
734 : /* -------------------------------------------------------------------- */
735 : // IHi.2
736 0 : ih.Put( IHi2_filename.c_str(), 64, 64 );
737 :
738 : // IHi.6.1
739 0 : ih.Put( "", 168, 16 );
740 :
741 : // IHi.6.2
742 0 : ih.Put( "", 184, 8 );
743 :
744 : // IHi.6.3
745 0 : ih.Put( "", 192, 8 );
746 :
747 : // IHi.6.5
748 0 : ih.Put( "", 201, 1 );
749 :
750 : // IHi.6.7
751 0 : ih.Put( exoffIn, 250, 8 );
752 :
753 : // IHi.6.8
754 0 : ih.Put( eyoffIn, 258, 8 );
755 :
756 : // IHi.6.9
757 0 : ih.Put( exsizeIn, 266, 8 );
758 :
759 : // IHi.6.10
760 0 : ih.Put( eysizeIn, 274, 8 );
761 :
762 : // IHi.6.11
763 0 : ih.Put( echannelIn, 282, 8 );
764 :
765 0 : file->WriteToFile( ih.buffer, ih_offset, 1024 );
766 :
767 : /* -------------------------------------------------------------------- */
768 : /* Update local configuration. */
769 : /* -------------------------------------------------------------------- */
770 0 : this->filename = file->GetInterfaces()->MergeRelativePath( file->GetInterfaces()->io,
771 0 : file->GetFilename(),
772 0 : filenameIn );
773 :
774 0 : this->exoff = exoffIn;
775 0 : this->eyoff = eyoffIn;
776 0 : this->exsize = exsizeIn;
777 0 : this->eysize = eysizeIn;
778 0 : this->echannel = echannelIn;
779 : }
|