Coverage Report

Created: 2025-07-23 09:13

/src/gdal/frmts/gtiff/gtiffsplitbitmapband.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  GeoTIFF Driver
4
 * Purpose:  GDAL GeoTIFF support.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 1998, 2002, Frank Warmerdam <warmerdam@pobox.com>
9
 * Copyright (c) 2007-2015, Even Rouault <even dot rouault at spatialys dot com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "gtiffsplitbitmapband.h"
15
16
#include "gtiffdataset.h"
17
18
#include "cpl_error_internal.h"
19
20
/************************************************************************/
21
/*                       GTiffSplitBitmapBand()                         */
22
/************************************************************************/
23
24
GTiffSplitBitmapBand::GTiffSplitBitmapBand(GTiffDataset *poDSIn, int nBandIn)
25
14.5k
    : GTiffBitmapBand(poDSIn, nBandIn)
26
27
14.5k
{
28
14.5k
    nBlockXSize = poDS->GetRasterXSize();
29
14.5k
    nBlockYSize = 1;
30
14.5k
}
31
32
/************************************************************************/
33
/*                      ~GTiffSplitBitmapBand()                         */
34
/************************************************************************/
35
36
GTiffSplitBitmapBand::~GTiffSplitBitmapBand()
37
14.5k
{
38
14.5k
}
39
40
/************************************************************************/
41
/*                       IGetDataCoverageStatus()                       */
42
/************************************************************************/
43
44
int GTiffSplitBitmapBand::IGetDataCoverageStatus(int, int, int, int, int,
45
                                                 double *)
46
139
{
47
139
    return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED |
48
139
           GDAL_DATA_COVERAGE_STATUS_DATA;
49
139
}
50
51
/************************************************************************/
52
/*                             IReadBlock()                             */
53
/************************************************************************/
54
55
CPLErr GTiffSplitBitmapBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff,
56
                                        void *pImage)
57
58
377k
{
59
377k
    m_poGDS->Crystalize();
60
61
377k
    if (m_nLastLineValid >= 0 && nBlockYOff > m_nLastLineValid)
62
10
        return CE_Failure;
63
64
377k
    if (m_poGDS->m_pabyBlockBuf == nullptr)
65
3.58k
    {
66
3.58k
        m_poGDS->m_pabyBlockBuf = static_cast<GByte *>(
67
3.58k
            VSI_MALLOC_VERBOSE(TIFFScanlineSize(m_poGDS->m_hTIFF)));
68
3.58k
        if (m_poGDS->m_pabyBlockBuf == nullptr)
69
0
        {
70
0
            return CE_Failure;
71
0
        }
72
3.58k
    }
73
74
    /* -------------------------------------------------------------------- */
75
    /*      Read through to target scanline.                                */
76
    /* -------------------------------------------------------------------- */
77
377k
    if (m_poGDS->m_nLoadedBlock >= nBlockYOff)
78
514
        m_poGDS->m_nLoadedBlock = -1;
79
80
    // Set to 1 to allow GTiffErrorHandler to implement limitation on error
81
    // messages
82
377k
    GTIFFGetThreadLocalLibtiffError() = 1;
83
2.52M
    while (m_poGDS->m_nLoadedBlock < nBlockYOff)
84
2.15M
    {
85
2.15M
        ++m_poGDS->m_nLoadedBlock;
86
87
2.15M
        CPLErrorAccumulator oErrorAccumulator;
88
2.15M
        int nRet;
89
2.15M
        {
90
2.15M
            auto oAccumulator = oErrorAccumulator.InstallForCurrentScope();
91
2.15M
            nRet = TIFFReadScanline(m_poGDS->m_hTIFF, m_poGDS->m_pabyBlockBuf,
92
2.15M
                                    m_poGDS->m_nLoadedBlock, 0);
93
2.15M
        }
94
95
2.15M
        for (const auto &oError : oErrorAccumulator.GetErrors())
96
402k
        {
97
402k
            ReportError(oError.type, oError.no, "%s", oError.msg.c_str());
98
            // FAX decoding only handles EOF condition as a warning, so
99
            // catch it so as to turn on error when attempting to read
100
            // following lines, to avoid performance issues.
101
402k
            if (!m_poGDS->m_bIgnoreReadErrors &&
102
402k
                oError.msg.find("Premature EOF") != std::string::npos)
103
633
            {
104
633
                m_nLastLineValid = nBlockYOff;
105
633
                nRet = -1;
106
633
            }
107
402k
        }
108
109
2.15M
        if (nRet == -1 && !m_poGDS->m_bIgnoreReadErrors)
110
6.83k
        {
111
6.83k
            ReportError(CE_Failure, CPLE_AppDefined,
112
6.83k
                        "TIFFReadScanline() failed.");
113
6.83k
            m_poGDS->m_nLoadedBlock = -1;
114
6.83k
            GTIFFGetThreadLocalLibtiffError() = 0;
115
6.83k
            return CE_Failure;
116
6.83k
        }
117
2.15M
    }
118
370k
    GTIFFGetThreadLocalLibtiffError() = 0;
119
120
    /* -------------------------------------------------------------------- */
121
    /*      Translate 1bit data to eight bit.                               */
122
    /* -------------------------------------------------------------------- */
123
370k
    int iSrcOffset = 0;
124
370k
    int iDstOffset = 0;
125
126
773M
    for (int iPixel = 0; iPixel < nBlockXSize; ++iPixel, ++iSrcOffset)
127
772M
    {
128
772M
        if (m_poGDS->m_pabyBlockBuf[iSrcOffset >> 3] &
129
772M
            (0x80 >> (iSrcOffset & 0x7)))
130
72.3M
            static_cast<GByte *>(pImage)[iDstOffset++] = 1;
131
700M
        else
132
700M
            static_cast<GByte *>(pImage)[iDstOffset++] = 0;
133
772M
    }
134
135
370k
    return CE_None;
136
377k
}
137
138
/************************************************************************/
139
/*                            IWriteBlock()                             */
140
/************************************************************************/
141
142
CPLErr GTiffSplitBitmapBand::IWriteBlock(int /* nBlockXOff */,
143
                                         int /* nBlockYOff */,
144
                                         void * /* pImage */)
145
146
0
{
147
0
    ReportError(CE_Failure, CPLE_AppDefined,
148
0
                "Split bitmap bands are read-only.");
149
0
    return CE_Failure;
150
0
}