Coverage Report

Created: 2025-06-09 08:44

/src/gdal/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Purpose:  Implementation of the CPCIDSKBitmap class.
4
 *
5
 ******************************************************************************
6
 * Copyright (c) 2010
7
 * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 ****************************************************************************/
11
12
#include "pcidsk_exception.h"
13
#include "segment/cpcidskbitmap.h"
14
#include "pcidsk_file.h"
15
#include "core/pcidsk_utils.h"
16
#include <cassert>
17
#include <cstring>
18
#include <cstdlib>
19
#include <cstdio>
20
#include <cctype>
21
22
using namespace PCIDSK;
23
24
/************************************************************************/
25
/*                           CPCIDSKBitmap()                            */
26
/************************************************************************/
27
28
CPCIDSKBitmap::CPCIDSKBitmap( PCIDSKFile *fileIn, int segmentIn,
29
                              const char *segment_pointer )
30
0
        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer )
31
32
0
{
33
0
    loaded = false;
34
0
    width = 0;
35
0
    height = 0;
36
0
    block_width = 0;
37
0
    block_height = 0;
38
0
}
Unexecuted instantiation: PCIDSK::CPCIDSKBitmap::CPCIDSKBitmap(PCIDSK::PCIDSKFile*, int, char const*)
Unexecuted instantiation: PCIDSK::CPCIDSKBitmap::CPCIDSKBitmap(PCIDSK::PCIDSKFile*, int, char const*)
39
40
/************************************************************************/
41
/*                           ~CPCIDSKBitmap()                           */
42
/************************************************************************/
43
44
CPCIDSKBitmap::~CPCIDSKBitmap()
45
46
0
{
47
0
}
48
49
/************************************************************************/
50
/*                             Initialize()                             */
51
/*                                                                      */
52
/*      Set up a newly created bitmap segment.  We just need to         */
53
/*      write some stuff into the segment header.                       */
54
/************************************************************************/
55
56
void CPCIDSKBitmap::Initialize()
57
58
0
{
59
0
    loaded = false;
60
61
0
    CPCIDSKBitmap *pThis = (CPCIDSKBitmap *) this;
62
63
0
    PCIDSKBuffer &bheader = pThis->GetHeader();
64
65
0
    bheader.Put( 0, 160     , 16 );
66
0
    bheader.Put( 0, 160+16*1, 16 );
67
0
    bheader.Put( file->GetWidth(), 160+16*2, 16 );
68
0
    bheader.Put( file->GetHeight(), 160+16*3, 16 );
69
0
    bheader.Put( -1, 160+16*4, 16 );
70
71
0
    file->WriteToFile( bheader.buffer, data_offset, 1024 );
72
0
}
73
74
/************************************************************************/
75
/*                                Load()                                */
76
/************************************************************************/
77
78
void CPCIDSKBitmap::Load() const
79
80
0
{
81
0
    if( loaded )
82
0
        return;
83
84
    // We don't really mean the internals are const, just a lie to
85
    // keep the const interfaces happy.
86
87
0
    CPCIDSKBitmap *pThis = (CPCIDSKBitmap *) this;
88
89
0
    PCIDSKBuffer &bheader = pThis->GetHeader();
90
91
0
    pThis->width  = bheader.GetInt( 192,    16 );
92
0
    pThis->height = bheader.GetInt( 192+16, 16 );
93
94
    // Choosing 8 lines per block ensures that each block
95
    // starts on a byte boundary.
96
0
    pThis->block_width = pThis->width;
97
0
    pThis->block_height = 8;
98
99
0
    pThis->loaded = true;
100
0
}
101
102
/************************************************************************/
103
/*                           GetBlockWidth()                            */
104
/************************************************************************/
105
106
int CPCIDSKBitmap::GetBlockWidth() const
107
108
0
{
109
0
    if( !loaded )
110
0
        Load();
111
112
0
    return block_width;
113
0
}
114
115
/************************************************************************/
116
/*                           GetBlockHeight()                           */
117
/************************************************************************/
118
119
int CPCIDSKBitmap::GetBlockHeight() const
120
121
0
{
122
0
    if( !loaded )
123
0
        Load();
124
125
0
    return block_height;
126
0
}
127
128
/************************************************************************/
129
/*                           GetBlockCount()                            */
130
/************************************************************************/
131
132
int CPCIDSKBitmap::GetBlockCount() const
133
134
0
{
135
0
    if( !loaded )
136
0
        Load();
137
138
0
    return DIV_ROUND_UP(width, block_width) * DIV_ROUND_UP(height, block_height);
139
0
}
140
141
/************************************************************************/
142
/*                              GetWidth()                              */
143
/************************************************************************/
144
145
int CPCIDSKBitmap::GetWidth() const
146
147
0
{
148
0
    if( !loaded )
149
0
        Load();
150
151
0
    return width;
152
0
}
153
154
/************************************************************************/
155
/*                             GetHeight()                              */
156
/************************************************************************/
157
158
int CPCIDSKBitmap::GetHeight() const
159
160
0
{
161
0
    if( !loaded )
162
0
        Load();
163
164
0
    return height;
165
0
}
166
167
/************************************************************************/
168
/*                              GetType()                               */
169
/************************************************************************/
170
171
eChanType CPCIDSKBitmap::GetType() const
172
173
0
{
174
0
    return CHN_BIT;
175
0
}
176
177
/************************************************************************/
178
/*                          PCIDSK_CopyBits()                           */
179
/*                                                                      */
180
/*      Copy bit strings - adapted from GDAL.                           */
181
/************************************************************************/
182
183
static void
184
PCIDSK_CopyBits( const uint8 *pabySrcData, int nSrcOffset, int nSrcStep,
185
                 uint8 *pabyDstData, int nDstOffset, int nDstStep,
186
                 int nBitCount, int nStepCount )
187
188
0
{
189
0
    int iStep;
190
0
    int iBit;
191
192
0
    for( iStep = 0; iStep < nStepCount; iStep++ )
193
0
    {
194
0
        for( iBit = 0; iBit < nBitCount; iBit++ )
195
0
        {
196
0
            if( pabySrcData[nSrcOffset>>3]
197
0
                & (0x80 >>(nSrcOffset & 7)) )
198
0
                pabyDstData[nDstOffset>>3] |= (0x80 >> (nDstOffset & 7));
199
0
            else
200
0
                pabyDstData[nDstOffset>>3] &= ~(0x80 >> (nDstOffset & 7));
201
202
203
0
            nSrcOffset++;
204
0
            nDstOffset++;
205
0
        }
206
207
0
        nSrcOffset += (nSrcStep - nBitCount);
208
0
        nDstOffset += (nDstStep - nBitCount);
209
0
    }
210
0
}
211
212
/************************************************************************/
213
/*                             ReadBlock()                              */
214
/************************************************************************/
215
216
int CPCIDSKBitmap::ReadBlock( int block_index, void *buffer,
217
                              int win_xoff, int win_yoff,
218
                              int win_xsize, int win_ysize )
219
220
0
{
221
0
    uint64 block_size = (static_cast<uint64>(block_width) * block_height + 7) / 8;
222
0
    uint8 *wrk_buffer = (uint8 *) buffer;
223
224
0
    if( block_index < 0 || block_index >= GetBlockCount() )
225
0
    {
226
0
        return ThrowPCIDSKException(0, "Requested non-existent block (%d)",
227
0
                              block_index );
228
0
    }
229
/* -------------------------------------------------------------------- */
230
/*      If we are doing subwindowing, we will need to create a          */
231
/*      temporary bitmap to load into.  If we are concerned about       */
232
/*      high performance access to small windows in big bitmaps we      */
233
/*      will eventually want to reimplement this to avoid reading       */
234
/*      the whole block to subwindow from.                              */
235
/* -------------------------------------------------------------------- */
236
0
    if( win_ysize != -1 )
237
0
    {
238
0
        if( win_xoff < 0 || win_xoff + win_xsize > GetBlockWidth()
239
0
            || win_yoff < 0 || win_yoff + win_ysize > GetBlockHeight() )
240
0
        {
241
0
            return ThrowPCIDSKException( 0,
242
0
                "Invalid window in CPCIDSKBitmap::ReadBlock(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
243
0
                win_xoff, win_yoff, win_xsize, win_ysize );
244
0
        }
245
246
0
        wrk_buffer = (uint8 *) malloc((size_t) block_size);
247
0
        if( wrk_buffer == nullptr )
248
0
            return ThrowPCIDSKException(0, "Out of memory allocating %d bytes in CPCIDSKBitmap::ReadBlock()",
249
0
                                  (int) block_size );
250
0
    }
251
252
/* -------------------------------------------------------------------- */
253
/*      Read the block, taking care in the case of partial blocks at    */
254
/*      the bottom of the image.                                        */
255
/* -------------------------------------------------------------------- */
256
0
    if( (block_index+1) * block_height <= height )
257
0
        ReadFromFile( wrk_buffer, block_size * block_index, block_size );
258
0
    else
259
0
    {
260
0
        uint64 short_block_size;
261
262
0
        memset( buffer, 0, (size_t) block_size );
263
264
0
        short_block_size =
265
0
            (static_cast<uint64>(height - block_index*block_height) * block_width + 7) / 8;
266
267
0
        ReadFromFile( wrk_buffer, block_size * block_index, short_block_size );
268
0
    }
269
270
/* -------------------------------------------------------------------- */
271
/*      Perform subwindowing if needed.                                 */
272
/* -------------------------------------------------------------------- */
273
0
    if( win_ysize != -1 )
274
0
    {
275
0
        int y_out;
276
277
0
        for( y_out = 0; y_out <  win_ysize; y_out++ )
278
0
        {
279
0
            PCIDSK_CopyBits( wrk_buffer,
280
0
                             win_xoff + (y_out+win_yoff)*block_width, 0,
281
0
                             (uint8*) buffer, y_out * win_xsize, 0,
282
0
                             win_xsize, 1 );
283
0
        }
284
285
0
        free( wrk_buffer );
286
0
    }
287
288
0
    return 0;
289
0
}
290
291
/************************************************************************/
292
/*                             WriteBlock()                             */
293
/************************************************************************/
294
295
int CPCIDSKBitmap::WriteBlock( int block_index, void *buffer )
296
297
0
{
298
0
    uint64 block_size = (static_cast<uint64>(block_width) * block_height) / 8;
299
300
0
    if( (block_index+1) * block_height <= height )
301
0
        WriteToFile( buffer, block_size * block_index, block_size );
302
0
    else
303
0
    {
304
0
        uint64 short_block_size;
305
306
0
        short_block_size =
307
0
            (static_cast<uint64>(height - block_index*block_height) * block_width + 7) / 8;
308
309
0
        WriteToFile( buffer, block_size * block_index, short_block_size );
310
0
    }
311
312
0
    return 1;
313
0
}
314
315
/************************************************************************/
316
/*                          GetOverviewCount()                          */
317
/************************************************************************/
318
319
int CPCIDSKBitmap::GetOverviewCount()
320
0
{
321
0
    return 0;
322
0
}
323
324
/************************************************************************/
325
/*                            GetOverview()                             */
326
/************************************************************************/
327
328
PCIDSKChannel *CPCIDSKBitmap::GetOverview( int i )
329
0
{
330
0
    return (PCIDSKChannel*) ThrowPCIDSKExceptionPtr("Non-existent overview %d requested on bitmap segment.", i);
331
0
}
332
333
/************************************************************************/
334
/*                          IsOverviewValid()                           */
335
/************************************************************************/
336
337
bool CPCIDSKBitmap::IsOverviewValid( CPL_UNUSED int i )
338
0
{
339
0
    return false;
340
0
}
341
342
/************************************************************************/
343
/*                       GetOverviewResampling()                        */
344
/************************************************************************/
345
346
std::string CPCIDSKBitmap::GetOverviewResampling( CPL_UNUSED int i )
347
0
{
348
0
    return "";
349
0
}
350
351
/************************************************************************/
352
/*                        SetOverviewValidity()                         */
353
/************************************************************************/
354
355
void CPCIDSKBitmap::SetOverviewValidity( CPL_UNUSED int i, CPL_UNUSED bool validity )
356
0
{
357
0
}
358
359
/************************************************************************/
360
/*                          GetMetadataValue()                          */
361
/************************************************************************/
362
363
std::string CPCIDSKBitmap::GetMetadataValue( const std::string &key ) const
364
365
0
{
366
0
    return CPCIDSKSegment::GetMetadataValue( key );
367
0
}
368
369
/************************************************************************/
370
/*                          SetMetadataValue()                          */
371
/************************************************************************/
372
373
void CPCIDSKBitmap::SetMetadataValue( const std::string &key,
374
                                      const std::string &value )
375
376
0
{
377
0
    CPCIDSKSegment::SetMetadataValue( key, value );
378
0
}
379
380
/************************************************************************/
381
/*                   GetOverviewLevelMapping()                          */
382
/************************************************************************/
383
std::vector<int> CPCIDSKBitmap::GetOverviewLevelMapping() const
384
0
{
385
0
    std::vector<int> ov;
386
387
0
    return ov;
388
0
}
389
390
/************************************************************************/
391
/*                          GetMetadataKeys()                           */
392
/************************************************************************/
393
394
std::vector<std::string> CPCIDSKBitmap::GetMetadataKeys() const
395
396
0
{
397
0
    return CPCIDSKSegment::GetMetadataKeys();
398
0
}
399
400
/************************************************************************/
401
/*                            Synchronize()                             */
402
/************************************************************************/
403
404
void CPCIDSKBitmap::Synchronize()
405
406
0
{
407
    // TODO
408
409
0
    CPCIDSKSegment::Synchronize();
410
0
}
411
412
/************************************************************************/
413
/*                           GetDescription()                           */
414
/************************************************************************/
415
416
std::string CPCIDSKBitmap::GetDescription()
417
418
0
{
419
0
    return CPCIDSKSegment::GetDescription();
420
0
}
421
422
/************************************************************************/
423
/*                           SetDescription()                           */
424
/************************************************************************/
425
426
void CPCIDSKBitmap::SetDescription( const std::string &description )
427
428
0
{
429
0
    CPCIDSKSegment::SetDescription( description );
430
0
}
431
432
/************************************************************************/
433
/*                         GetHistoryEntries()                          */
434
/************************************************************************/
435
436
std::vector<std::string> CPCIDSKBitmap::GetHistoryEntries() const
437
438
0
{
439
0
    return CPCIDSKSegment::GetHistoryEntries();
440
0
}
441
442
/************************************************************************/
443
/*                         SetHistoryEntries()                          */
444
/************************************************************************/
445
446
void CPCIDSKBitmap::SetHistoryEntries( const std::vector<std::string> &entries )
447
448
0
{
449
0
    CPCIDSKSegment::SetHistoryEntries( entries );
450
0
}
451
452
/************************************************************************/
453
/*                            PushHistory()                             */
454
/************************************************************************/
455
456
void CPCIDSKBitmap::PushHistory( const std::string &app,
457
                                 const std::string &message )
458
459
0
{
460
0
    CPCIDSKSegment::PushHistory( app, message );
461
0
}
462
463
/************************************************************************/
464
/*                            GetChanInfo()                             */
465
/************************************************************************/
466
void CPCIDSKBitmap::GetChanInfo( std::string &filename, uint64 &image_offset,
467
                                 uint64 &pixel_offset, uint64 &line_offset,
468
                                 bool &little_endian ) const
469
470
0
{
471
0
    image_offset = 0;
472
0
    pixel_offset = 0;
473
0
    line_offset = 0;
474
0
    little_endian = true;
475
0
    filename = "";
476
0
}
477
478
/************************************************************************/
479
/*                            SetChanInfo()                             */
480
/************************************************************************/
481
482
void CPCIDSKBitmap::SetChanInfo( CPL_UNUSED std::string filename, CPL_UNUSED uint64 image_offset,
483
                                 CPL_UNUSED uint64 pixel_offset, CPL_UNUSED uint64 line_offset,
484
                                 CPL_UNUSED bool little_endian )
485
0
{
486
0
    return ThrowPCIDSKException( "Attempt to SetChanInfo() on a bitmap." );
487
0
}
488
489
/************************************************************************/
490
/*                            GetEChanInfo()                            */
491
/************************************************************************/
492
void CPCIDSKBitmap::GetEChanInfo( std::string &filename, int &echannel,
493
                                  int &exoff, int &eyoff,
494
                                  int &exsize, int &eysize ) const
495
0
{
496
0
    echannel = 0;
497
0
    exoff = 0;
498
0
    eyoff = 0;
499
0
    exsize = 0;
500
0
    eysize = 0;
501
0
    filename = "";
502
0
}
503
504
/************************************************************************/
505
/*                            SetEChanInfo()                            */
506
/************************************************************************/
507
508
void CPCIDSKBitmap::SetEChanInfo( CPL_UNUSED std::string filename, CPL_UNUSED int echannel,
509
                                  CPL_UNUSED int exoff, CPL_UNUSED int eyoff,
510
                                  CPL_UNUSED int exsize, CPL_UNUSED int eysize )
511
0
{
512
0
    return ThrowPCIDSKException( "Attempt to SetEChanInfo() on a bitmap." );
513
0
}