Coverage Report

Created: 2025-07-23 09:13

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