Line data Source code
1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the CTiledChannel 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, 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_exception.h"
19 : #include "channel/ctiledchannel.h"
20 : #include "segment/systiledir.h"
21 : #include "blockdir/blocktilelayer.h"
22 : #include "core/cpcidskfile.h"
23 : #include "core/cpcidskblockfile.h"
24 : #include "core/pcidsk_raster.h"
25 : #include "core/pcidsk_utils.h"
26 : #include <cassert>
27 : #include <cstdlib>
28 : #include <cstring>
29 :
30 : namespace PCIDSK
31 : {
32 :
33 : /************************************************************************/
34 : /* CTiledChannel() */
35 : /************************************************************************/
36 :
37 36 : CTiledChannel::CTiledChannel( PCIDSKBuffer &image_headerIn,
38 : uint64 ih_offsetIn,
39 : CPL_UNUSED PCIDSKBuffer &file_headerIn,
40 : int channelnumIn,
41 : CPCIDSKFile *fileIn,
42 36 : eChanType pixel_typeIn )
43 36 : : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
44 :
45 : {
46 36 : std::string filename;
47 :
48 36 : image_headerIn.Get(64,64,filename);
49 :
50 36 : assert( strstr(filename.c_str(),"SIS=") != nullptr );
51 :
52 36 : image = atoi(strstr(filename.c_str(),"SIS=") + 4);
53 :
54 36 : mpoTileLayer = nullptr;
55 36 : }
56 :
57 : /************************************************************************/
58 : /* ~CTiledChannel() */
59 : /************************************************************************/
60 72 : CTiledChannel::~CTiledChannel()
61 : {
62 : try
63 : {
64 36 : Synchronize();
65 : }
66 0 : catch( const PCIDSKException& e )
67 : {
68 0 : fprintf(stderr, "Exception in ~CTiledChannel(): %s", e.what()); // ok
69 : }
70 72 : }
71 :
72 : /************************************************************************/
73 : /* EstablishAccess() */
74 : /************************************************************************/
75 232 : void CTiledChannel::EstablishAccess() const
76 : {
77 232 : if (mpoTileLayer)
78 196 : return;
79 :
80 36 : CPCIDSKBlockFile oBlockFile(file);
81 :
82 36 : SysTileDir * poTileDir = oBlockFile.GetTileDir();
83 :
84 36 : if (!poTileDir)
85 0 : return ThrowPCIDSKException("Unable to find the tile directory segment.");
86 :
87 36 : mpoTileLayer = poTileDir->GetTileLayer((uint32) image);
88 :
89 36 : if (!mpoTileLayer)
90 0 : return ThrowPCIDSKException("Unable to find the tiled channel: %d", image);
91 :
92 36 : const char * pszDataType = mpoTileLayer->GetDataType();
93 :
94 36 : if (GetDataTypeFromName(pszDataType) == CHN_UNKNOWN)
95 0 : return ThrowPCIDSKException("Unknown channel type: %s", pszDataType);
96 : }
97 :
98 : /************************************************************************/
99 : /* Synchronize() */
100 : /* */
101 : /* Flush updated blockmap to disk if it is dirty. */
102 : /************************************************************************/
103 50 : void CTiledChannel::Synchronize()
104 : {
105 50 : if (mpoTileLayer)
106 50 : mpoTileLayer->Sync();
107 50 : }
108 :
109 : /************************************************************************/
110 : /* ReadTile() */
111 : /************************************************************************/
112 29 : void CTiledChannel::ReadTile(void * buffer, uint32 nCol, uint32 nRow)
113 : {
114 29 : int nTileXSize = (int) mpoTileLayer->GetTileXSize();
115 29 : int nTileYSize = (int) mpoTileLayer->GetTileYSize();
116 :
117 29 : eChanType nDataType = GetType();
118 :
119 : // Check if we can read an sparse tile.
120 29 : if (mpoTileLayer->ReadSparseTile(buffer, nCol, nRow))
121 : {
122 : // Do byte swapping if needed.
123 0 : if( needs_swap )
124 : {
125 0 : SwapPixels( buffer, nDataType, static_cast<size_t>(nTileXSize) * nTileYSize );
126 : }
127 :
128 25 : return;
129 : }
130 :
131 29 : const char * compression = mpoTileLayer->GetCompressType();
132 :
133 29 : if (strcmp(compression, "NONE") == 0)
134 : {
135 25 : mpoTileLayer->ReadTile(buffer, nCol, nRow, mpoTileLayer->GetTileSize());
136 :
137 : // Do byte swapping if needed.
138 25 : if( needs_swap )
139 : {
140 7 : SwapPixels( buffer, nDataType, static_cast<size_t>(nTileXSize) * nTileYSize );
141 : }
142 :
143 25 : return;
144 : }
145 :
146 4 : uint32 nTileDataSize = mpoTileLayer->GetTileDataSize(nCol, nRow);
147 :
148 4 : PCIDSKBuffer oCompressedData(nTileDataSize);
149 4 : PCIDSKBuffer oUncompressedData(mpoTileLayer->GetTileSize());
150 :
151 4 : mpoTileLayer->ReadTile(oCompressedData.buffer, nCol, nRow, nTileDataSize);
152 :
153 4 : if (strcmp(compression, "RLE") == 0)
154 : {
155 3 : RLEDecompressBlock( oCompressedData, oUncompressedData );
156 : }
157 1 : else if (STARTS_WITH(compression, "JPEG"))
158 : {
159 1 : JPEGDecompressBlock( oCompressedData, oUncompressedData );
160 : }
161 : else
162 : {
163 0 : return ThrowPCIDSKException(
164 : "Unable to read tile of unsupported compression type: %s",
165 0 : compression);
166 : }
167 :
168 : /* -------------------------------------------------------------------- */
169 : /* Swap if necessary. TODO: there is some reason to doubt that */
170 : /* the old implementation properly byte swapped compressed */
171 : /* data. Perhaps this should be conditional? */
172 : /* -------------------------------------------------------------------- */
173 4 : if( needs_swap )
174 3 : SwapPixels( oUncompressedData.buffer, nDataType,
175 3 : static_cast<size_t>(nTileXSize) * nTileYSize );
176 :
177 4 : memcpy(buffer, oUncompressedData.buffer, oUncompressedData.buffer_size);
178 : }
179 :
180 : /************************************************************************/
181 : /* ReadBlock() */
182 : /************************************************************************/
183 29 : int CTiledChannel::ReadBlock( int iBlock, void *buffer,
184 : int xoff, int yoff,
185 : int xsize, int ysize )
186 : {
187 29 : EstablishAccess();
188 :
189 : // Validate the block index.
190 29 : int nTileCount = (int) mpoTileLayer->GetTileCount();
191 :
192 29 : if( iBlock < 0 || iBlock >= nTileCount )
193 : {
194 0 : return ThrowPCIDSKException(0, "Requested non-existent block (%d)",
195 0 : iBlock );
196 : }
197 :
198 29 : int nTileXSize = (int) mpoTileLayer->GetTileXSize();
199 29 : int nTileYSize = (int) mpoTileLayer->GetTileYSize();
200 :
201 : // Default window.
202 29 : if (xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1)
203 : {
204 29 : xoff = 0;
205 29 : yoff = 0;
206 29 : xsize = nTileXSize;
207 29 : ysize = nTileYSize;
208 : }
209 :
210 : // Validate the requested window.
211 29 : if (xoff < 0 || xoff + xsize > nTileXSize ||
212 29 : yoff < 0 || yoff + ysize > nTileYSize)
213 : {
214 0 : return ThrowPCIDSKException(0,
215 : "Invalid window in ReadBlock(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
216 0 : xoff, yoff, xsize, ysize );
217 : }
218 :
219 29 : uint32 nTilePerRow = mpoTileLayer->GetTilePerRow();
220 :
221 29 : if (nTilePerRow == 0)
222 0 : return ThrowPCIDSKException(0, "Invalid number of tiles per row.");
223 :
224 29 : uint32 nCol = iBlock % nTilePerRow;
225 29 : uint32 nRow = iBlock / nTilePerRow;
226 :
227 : // Check if the entire tile was requested.
228 29 : if (xoff == 0 && xsize == nTileXSize &&
229 29 : yoff == 0 && ysize == nTileYSize)
230 : {
231 29 : ReadTile(buffer, nCol, nRow);
232 :
233 29 : return 1;
234 : }
235 :
236 0 : eChanType nDataType = GetType();
237 0 : int nPixelSize = DataTypeSize(nDataType);
238 0 : int nPixelCount = xsize * ysize;
239 :
240 : // Check if we can read an sparse tile.
241 0 : if (!mpoTileLayer->IsTileValid(nCol, nRow))
242 : {
243 0 : if (xoff == 0 && xsize == nTileXSize)
244 : {
245 0 : mpoTileLayer->ReadPartialSparseTile
246 0 : (buffer, nCol, nRow,
247 0 : yoff * nTileXSize * nPixelSize,
248 0 : nPixelCount * nPixelSize);
249 : }
250 : else
251 : {
252 0 : for (int iy = 0; iy < ysize; iy++)
253 : {
254 0 : mpoTileLayer->ReadPartialSparseTile
255 0 : ((char*) buffer + iy * xsize * nPixelSize, nCol, nRow,
256 0 : ((iy + yoff) * nTileXSize + xoff) * nPixelSize,
257 0 : xsize * nPixelSize);
258 : }
259 : }
260 :
261 : // Do byte swapping if needed.
262 0 : if( needs_swap )
263 0 : SwapPixels( buffer, nDataType, nPixelCount );
264 :
265 0 : return 1;
266 : }
267 :
268 0 : const char * compression = mpoTileLayer->GetCompressType();
269 :
270 : // Read the requested window.
271 0 : if (strcmp(compression, "NONE") == 0 && xoff == 0 && xsize == nTileXSize)
272 : {
273 0 : mpoTileLayer->ReadPartialTile(buffer, nCol, nRow,
274 0 : yoff * nTileXSize * nPixelSize,
275 0 : nPixelCount * nPixelSize);
276 :
277 : // Do byte swapping if needed.
278 0 : if( needs_swap )
279 0 : SwapPixels( buffer, nDataType, nPixelCount );
280 : }
281 : // Read the requested window line by line.
282 0 : else if (strcmp(compression, "NONE") == 0)
283 : {
284 0 : for (int iy = 0; iy < ysize; iy++)
285 : {
286 0 : mpoTileLayer->ReadPartialTile
287 0 : ((char*) buffer + iy * xsize * nPixelSize, nCol, nRow,
288 0 : ((iy + yoff) * nTileXSize + xoff) * nPixelSize,
289 0 : xsize * nPixelSize);
290 : }
291 :
292 : // Do byte swapping if needed.
293 0 : if( needs_swap )
294 0 : SwapPixels( buffer, nDataType, nPixelCount );
295 : }
296 : // Read the entire tile and copy the requested window.
297 : else
298 : {
299 0 : PCIDSKBuffer oTileData(mpoTileLayer->GetTileSize());
300 :
301 0 : ReadTile(oTileData.buffer, nCol, nRow);
302 :
303 0 : for (int iy = 0; iy < ysize; iy++)
304 : {
305 0 : memcpy((char*) buffer + iy * xsize * nPixelSize,
306 0 : oTileData.buffer + ((iy + yoff) * nTileXSize + xoff) * nPixelSize,
307 0 : static_cast<size_t>(xsize) * nPixelSize);
308 : }
309 : }
310 :
311 0 : return 1;
312 : }
313 :
314 : /************************************************************************/
315 : /* WriteBlock() */
316 : /************************************************************************/
317 8 : int CTiledChannel::WriteBlock( int iBlock, void *buffer )
318 : {
319 8 : if( !file->GetUpdatable() )
320 0 : return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
321 :
322 8 : InvalidateOverviews();
323 :
324 8 : EstablishAccess();
325 :
326 : // Validate the block index.
327 8 : int nTileCount = (int) mpoTileLayer->GetTileCount();
328 :
329 8 : if( iBlock < 0 || iBlock >= nTileCount )
330 : {
331 0 : return ThrowPCIDSKException(0, "Requested non-existent block (%d)",
332 0 : iBlock );
333 : }
334 :
335 8 : int nTileXSize = GetBlockWidth();
336 8 : int nTileYSize = GetBlockHeight();
337 :
338 8 : eChanType nDataType = GetType();
339 8 : int nPixelCount = nTileXSize * nTileYSize;
340 :
341 8 : uint32 nTilePerRow = mpoTileLayer->GetTilePerRow();
342 :
343 8 : if (nTilePerRow == 0)
344 0 : return ThrowPCIDSKException(0, "Invalid number of tiles per row.");
345 :
346 8 : uint32 nCol = iBlock % nTilePerRow;
347 8 : uint32 nRow = iBlock / nTilePerRow;
348 :
349 : // Do byte swapping if needed.
350 8 : if( needs_swap )
351 7 : SwapPixels( buffer, nDataType, nPixelCount );
352 :
353 : // Check if we can write an sparse tile.
354 8 : if (mpoTileLayer->WriteSparseTile(buffer, nCol, nRow))
355 : {
356 0 : if( needs_swap )
357 0 : SwapPixels( buffer, nDataType, nPixelCount );
358 :
359 0 : return 1;
360 : }
361 :
362 8 : const char * compression = mpoTileLayer->GetCompressType();
363 :
364 : /* -------------------------------------------------------------------- */
365 : /* The simplest case it an uncompressed direct and complete */
366 : /* tile read into the destination buffer. */
367 : /* -------------------------------------------------------------------- */
368 8 : if (strcmp(compression, "NONE") == 0)
369 : {
370 4 : mpoTileLayer->WriteTile(buffer, nCol, nRow);
371 :
372 4 : if( needs_swap )
373 4 : SwapPixels( buffer, nDataType, nPixelCount );
374 :
375 4 : return 1;
376 : }
377 :
378 : /* -------------------------------------------------------------------- */
379 : /* Copy the uncompressed data into a PCIDSKBuffer, and byte */
380 : /* swap if needed. */
381 : /* -------------------------------------------------------------------- */
382 8 : PCIDSKBuffer oUncompressedData(mpoTileLayer->GetTileSize());
383 :
384 4 : memcpy(oUncompressedData.buffer, buffer,
385 4 : oUncompressedData.buffer_size);
386 :
387 4 : if( needs_swap )
388 3 : SwapPixels( buffer, nDataType, nPixelCount );
389 :
390 : /* -------------------------------------------------------------------- */
391 : /* Compress the imagery. */
392 : /* -------------------------------------------------------------------- */
393 8 : PCIDSKBuffer oCompressedData;
394 :
395 4 : if (strcmp(compression, "NONE") == 0)
396 : {
397 0 : oCompressedData = oUncompressedData;
398 : }
399 4 : else if (strcmp(compression, "RLE") == 0)
400 : {
401 3 : RLECompressBlock( oUncompressedData, oCompressedData );
402 : }
403 1 : else if (STARTS_WITH(compression, "JPEG"))
404 : {
405 1 : JPEGCompressBlock( oUncompressedData, oCompressedData );
406 : }
407 : else
408 : {
409 0 : return ThrowPCIDSKException(0,
410 : "Unable to write tile of unsupported compression type: %s",
411 0 : compression);
412 : }
413 :
414 4 : mpoTileLayer->WriteTile(oCompressedData.buffer, nCol, nRow,
415 4 : oCompressedData.buffer_size);
416 :
417 4 : return 1;
418 : }
419 :
420 : /************************************************************************/
421 : /* GetBlockWidth() */
422 : /************************************************************************/
423 71 : int CTiledChannel::GetBlockWidth(void) const
424 : {
425 71 : EstablishAccess();
426 :
427 71 : return (int) mpoTileLayer->GetTileXSize();
428 : }
429 :
430 : /************************************************************************/
431 : /* GetBlockHeight() */
432 : /************************************************************************/
433 71 : int CTiledChannel::GetBlockHeight(void) const
434 : {
435 71 : EstablishAccess();
436 :
437 71 : return (int) mpoTileLayer->GetTileYSize();
438 : }
439 :
440 : /************************************************************************/
441 : /* GetWidth() */
442 : /************************************************************************/
443 11 : int CTiledChannel::GetWidth(void) const
444 : {
445 11 : EstablishAccess();
446 :
447 11 : return (int) mpoTileLayer->GetXSize();
448 : }
449 :
450 : /************************************************************************/
451 : /* GetHeight() */
452 : /************************************************************************/
453 11 : int CTiledChannel::GetHeight(void) const
454 : {
455 11 : EstablishAccess();
456 :
457 11 : return (int) mpoTileLayer->GetYSize();
458 : }
459 :
460 : /************************************************************************/
461 : /* GetType() */
462 : /************************************************************************/
463 163 : eChanType CTiledChannel::GetType(void) const
464 : {
465 163 : eChanType nDataType = CPCIDSKChannel::GetType();
466 :
467 163 : if (nDataType != CHN_UNKNOWN)
468 132 : return nDataType;
469 :
470 31 : EstablishAccess();
471 :
472 31 : return GetDataTypeFromName(mpoTileLayer->GetDataType());
473 : }
474 :
475 : /************************************************************************/
476 : /* RLEDecompressBlock() */
477 : /************************************************************************/
478 :
479 3 : void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
480 : PCIDSKBuffer &oDecompressedData )
481 :
482 :
483 : {
484 3 : int src_offset=0, dst_offset=0;
485 3 : uint8 *src = (uint8 *) oCompressedData.buffer;
486 3 : uint8 *dst = (uint8 *) oDecompressedData.buffer;
487 3 : int nPixelSize = DataTypeSize(GetType());
488 :
489 : /* -------------------------------------------------------------------- */
490 : /* Process till we are out of source data, or our destination */
491 : /* buffer is full. These conditions should be satisfied at */
492 : /* the same time! */
493 : /* -------------------------------------------------------------------- */
494 27 : while( src_offset + 1 + nPixelSize <= oCompressedData.buffer_size
495 30 : && dst_offset < oDecompressedData.buffer_size )
496 : {
497 : /* -------------------------------------------------------------------- */
498 : /* Extract a repeat run */
499 : /* -------------------------------------------------------------------- */
500 27 : if( src[src_offset] > 127 )
501 : {
502 15 : int count = src[src_offset++] - 128;
503 : int i;
504 :
505 15 : if( dst_offset + count * nPixelSize > oDecompressedData.buffer_size)
506 : {
507 0 : return ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
508 : }
509 :
510 1563 : while( count-- > 0 )
511 : {
512 4644 : for( i = 0; i < nPixelSize; i++ )
513 3096 : dst[dst_offset++] = src[src_offset+i];
514 : }
515 15 : src_offset += nPixelSize;
516 : }
517 :
518 : /* -------------------------------------------------------------------- */
519 : /* Extract a literal run. */
520 : /* -------------------------------------------------------------------- */
521 : else
522 : {
523 12 : int count = src[src_offset++];
524 :
525 12 : if( dst_offset + count*nPixelSize > oDecompressedData.buffer_size
526 12 : || src_offset + count*nPixelSize > oCompressedData.buffer_size)
527 : {
528 0 : return ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
529 : }
530 :
531 12 : memcpy( dst + dst_offset, src + src_offset,
532 12 : nPixelSize * count );
533 12 : src_offset += nPixelSize * count;
534 12 : dst_offset += nPixelSize * count;
535 : }
536 :
537 : }
538 :
539 : /* -------------------------------------------------------------------- */
540 : /* Final validation. */
541 : /* -------------------------------------------------------------------- */
542 3 : if( src_offset != oCompressedData.buffer_size
543 3 : || dst_offset != oDecompressedData.buffer_size )
544 : {
545 0 : return ThrowPCIDSKException( "RLE compressed tile corrupt, result incomplete." );
546 : }
547 : }
548 :
549 : /************************************************************************/
550 : /* RLECompressBlock() */
551 : /* */
552 : /* TODO: There does not seem to be any byte order logic in here! */
553 : /************************************************************************/
554 :
555 3 : void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
556 : PCIDSKBuffer &oCompressedData )
557 :
558 :
559 : {
560 3 : int src_bytes = oUncompressedData.buffer_size;
561 3 : int nPixelSize = DataTypeSize(GetType());
562 3 : int src_offset = 0, dst_offset = 0;
563 : int i;
564 3 : uint8 *src = (uint8 *) oUncompressedData.buffer;
565 :
566 : /* -------------------------------------------------------------------- */
567 : /* Loop till input exhausted. */
568 : /* -------------------------------------------------------------------- */
569 30 : while( src_offset < src_bytes )
570 : {
571 27 : bool bGotARun = false;
572 :
573 : /* -------------------------------------------------------------------- */
574 : /* Establish the run length, and emit if greater than 3. */
575 : /* -------------------------------------------------------------------- */
576 27 : if( src_offset + 3*nPixelSize < src_bytes )
577 : {
578 27 : int count = 1;
579 :
580 1533 : while( count < 127
581 1560 : && src_offset + count*nPixelSize < src_bytes )
582 : {
583 1548 : bool bWordMatch = true;
584 :
585 4644 : for( i = 0; i < nPixelSize; i++ )
586 : {
587 3096 : if( src[src_offset+i]
588 3096 : != src[src_offset+i+count*nPixelSize] )
589 24 : bWordMatch = false;
590 : }
591 :
592 1548 : if( !bWordMatch )
593 15 : break;
594 :
595 1533 : count++;
596 : }
597 :
598 27 : if( count >= 3 )
599 : {
600 15 : if( oCompressedData.buffer_size < dst_offset + nPixelSize+1 )
601 3 : oCompressedData.SetSize( oCompressedData.buffer_size*2+100);
602 :
603 15 : oCompressedData.buffer[dst_offset++] = (char) (count+128);
604 :
605 45 : for( i = 0; i < nPixelSize; i++ )
606 30 : oCompressedData.buffer[dst_offset++] = src[src_offset+i];
607 :
608 15 : src_offset += count * nPixelSize;
609 :
610 15 : bGotARun = true;
611 : }
612 : else
613 12 : bGotARun = false;
614 : }
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Otherwise emit a literal till we encounter at least a three */
618 : /* word series. */
619 : /* -------------------------------------------------------------------- */
620 27 : if( !bGotARun )
621 : {
622 12 : int count = 1;
623 12 : int match_count = 0;
624 :
625 1512 : while( count < 127
626 1524 : && src_offset + count*nPixelSize < src_bytes )
627 : {
628 1512 : bool bWordMatch = true;
629 :
630 4536 : for( i = 0; i < nPixelSize; i++ )
631 : {
632 3024 : if( src[src_offset+i]
633 3024 : != src[src_offset+i+count*nPixelSize] )
634 2172 : bWordMatch = false;
635 : }
636 :
637 1512 : if( bWordMatch )
638 0 : match_count++;
639 : else
640 1512 : match_count = 0;
641 :
642 1512 : if( match_count > 2 )
643 0 : break;
644 :
645 1512 : count++;
646 : }
647 :
648 12 : assert( src_offset + count*nPixelSize <= src_bytes );
649 :
650 9 : while( oCompressedData.buffer_size
651 21 : < dst_offset + count*nPixelSize+1 )
652 9 : oCompressedData.SetSize( oCompressedData.buffer_size*2+100 );
653 :
654 12 : oCompressedData.buffer[dst_offset++] = (char) count;
655 12 : memcpy( oCompressedData.buffer + dst_offset,
656 12 : src + src_offset,
657 12 : cpl::fits_on<int>(count * nPixelSize) );
658 12 : src_offset += count * nPixelSize;
659 12 : dst_offset += count * nPixelSize;
660 : }
661 : }
662 :
663 3 : oCompressedData.buffer_size = dst_offset;
664 3 : }
665 :
666 : /************************************************************************/
667 : /* JPEGDecompressBlock() */
668 : /************************************************************************/
669 :
670 1 : void CTiledChannel::JPEGDecompressBlock( PCIDSKBuffer &oCompressedData,
671 : PCIDSKBuffer &oDecompressedData )
672 :
673 :
674 : {
675 1 : if( file->GetInterfaces()->JPEGDecompressBlock == nullptr )
676 0 : return ThrowPCIDSKException( "JPEG decompression not enabled in the PCIDSKInterfaces of this build." );
677 :
678 1 : file->GetInterfaces()->JPEGDecompressBlock(
679 1 : (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
680 1 : (uint8 *) oDecompressedData.buffer, oDecompressedData.buffer_size,
681 : GetBlockWidth(), GetBlockHeight(), GetType() );
682 : }
683 :
684 : /************************************************************************/
685 : /* JPEGCompressBlock() */
686 : /************************************************************************/
687 :
688 1 : void CTiledChannel::JPEGCompressBlock( PCIDSKBuffer &oDecompressedData,
689 : PCIDSKBuffer &oCompressedData )
690 :
691 :
692 :
693 : {
694 1 : if( file->GetInterfaces()->JPEGCompressBlock == nullptr )
695 0 : return ThrowPCIDSKException( "JPEG compression not enabled in the PCIDSKInterfaces of this build." );
696 :
697 : /* -------------------------------------------------------------------- */
698 : /* What quality should we be using? */
699 : /* -------------------------------------------------------------------- */
700 1 : int quality = 75;
701 :
702 1 : const char * compression = mpoTileLayer->GetCompressType();
703 :
704 1 : if (strlen(compression) > 4 && isdigit(static_cast<unsigned char>(compression[4])))
705 0 : quality = atoi(compression + 4);
706 :
707 : /* -------------------------------------------------------------------- */
708 : /* Make the output buffer plenty big to hold any conceivable */
709 : /* result. */
710 : /* -------------------------------------------------------------------- */
711 1 : oCompressedData.SetSize( oDecompressedData.buffer_size * 2 + 1000 );
712 :
713 : /* -------------------------------------------------------------------- */
714 : /* invoke. */
715 : /* -------------------------------------------------------------------- */
716 1 : file->GetInterfaces()->JPEGCompressBlock(
717 1 : (uint8 *) oDecompressedData.buffer, oDecompressedData.buffer_size,
718 1 : (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
719 : GetBlockWidth(), GetBlockHeight(), GetType(), quality );
720 : }
721 :
722 : } // namespace PCIDSK;
|