Coverage Report

Created: 2025-08-11 09:23

/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
13.8k
    : GTiffBitmapBand(poDSIn, nBandIn)
26
27
13.8k
{
28
13.8k
    nBlockXSize = poDS->GetRasterXSize();
29
13.8k
    nBlockYSize = 1;
30
13.8k
}
31
32
/************************************************************************/
33
/*                      ~GTiffSplitBitmapBand()                         */
34
/************************************************************************/
35
36
GTiffSplitBitmapBand::~GTiffSplitBitmapBand()
37
13.8k
{
38
13.8k
}
39
40
/************************************************************************/
41
/*                       IGetDataCoverageStatus()                       */
42
/************************************************************************/
43
44
int GTiffSplitBitmapBand::IGetDataCoverageStatus(int, int, int, int, int,
45
                                                 double *)
46
122
{
47
122
    return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED |
48
122
           GDAL_DATA_COVERAGE_STATUS_DATA;
49
122
}
50
51
/************************************************************************/
52
/*                             IReadBlock()                             */
53
/************************************************************************/
54
55
CPLErr GTiffSplitBitmapBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff,
56
                                        void *pImage)
57
58
356k
{
59
356k
    m_poGDS->Crystalize();
60
61
356k
    if (m_nLastLineValid >= 0 && nBlockYOff > m_nLastLineValid)
62
10
        return CE_Failure;
63
64
356k
    if (m_poGDS->m_pabyBlockBuf == nullptr)
65
3.45k
    {
66
3.45k
        m_poGDS->m_pabyBlockBuf = static_cast<GByte *>(
67
3.45k
            VSI_MALLOC_VERBOSE(TIFFScanlineSize(m_poGDS->m_hTIFF)));
68
3.45k
        if (m_poGDS->m_pabyBlockBuf == nullptr)
69
0
        {
70
0
            return CE_Failure;
71
0
        }
72
3.45k
    }
73
74
    /* -------------------------------------------------------------------- */
75
    /*      Read through to target scanline.                                */
76
    /* -------------------------------------------------------------------- */
77
356k
    if (m_poGDS->m_nLoadedBlock >= nBlockYOff)
78
771
        m_poGDS->m_nLoadedBlock = -1;
79
80
    // Set to 1 to allow GTiffErrorHandler to implement limitation on error
81
    // messages
82
356k
    GTIFFGetThreadLocalLibtiffError() = 1;
83
3.45M
    while (m_poGDS->m_nLoadedBlock < nBlockYOff)
84
3.11M
    {
85
3.11M
        ++m_poGDS->m_nLoadedBlock;
86
87
3.11M
        CPLErrorAccumulator oErrorAccumulator;
88
3.11M
        int nRet;
89
3.11M
        {
90
3.11M
            auto oAccumulator = oErrorAccumulator.InstallForCurrentScope();
91
3.11M
            nRet = TIFFReadScanline(m_poGDS->m_hTIFF, m_poGDS->m_pabyBlockBuf,
92
3.11M
                                    m_poGDS->m_nLoadedBlock, 0);
93
3.11M
        }
94
95
3.11M
        for (const auto &oError : oErrorAccumulator.GetErrors())
96
369k
        {
97
369k
            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
369k
            if (!m_poGDS->m_bIgnoreReadErrors &&
102
369k
                oError.msg.find("Premature EOF") != std::string::npos)
103
777
            {
104
777
                m_nLastLineValid = nBlockYOff;
105
777
                nRet = -1;
106
777
            }
107
369k
        }
108
109
3.11M
        if (nRet == -1 && !m_poGDS->m_bIgnoreReadErrors)
110
7.77k
        {
111
7.77k
            ReportError(CE_Failure, CPLE_AppDefined,
112
7.77k
                        "TIFFReadScanline() failed.");
113
7.77k
            m_poGDS->m_nLoadedBlock = -1;
114
7.77k
            GTIFFGetThreadLocalLibtiffError() = 0;
115
7.77k
            return CE_Failure;
116
7.77k
        }
117
3.11M
    }
118
348k
    GTIFFGetThreadLocalLibtiffError() = 0;
119
120
    /* -------------------------------------------------------------------- */
121
    /*      Translate 1bit data to eight bit.                               */
122
    /* -------------------------------------------------------------------- */
123
348k
    int iSrcOffset = 0;
124
348k
    int iDstOffset = 0;
125
126
777M
    for (int iPixel = 0; iPixel < nBlockXSize; ++iPixel, ++iSrcOffset)
127
776M
    {
128
776M
        if (m_poGDS->m_pabyBlockBuf[iSrcOffset >> 3] &
129
776M
            (0x80 >> (iSrcOffset & 0x7)))
130
75.0M
            static_cast<GByte *>(pImage)[iDstOffset++] = 1;
131
701M
        else
132
701M
            static_cast<GByte *>(pImage)[iDstOffset++] = 0;
133
776M
    }
134
135
348k
    return CE_None;
136
356k
}
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
}