Coverage Report

Created: 2025-12-31 08:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/mrf/JPEG_band.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2002-2012, California Institute of Technology.
3
 * All rights reserved.  Based on Government Sponsored Research under contracts
4
 * NAS7-1407 and/or NAS7-03001.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *   1. Redistributions of source code must retain the above copyright notice,
9
 * this list of conditions and the following disclaimer.
10
 *   2. Redistributions in binary form must reproduce the above copyright
11
 * notice, this list of conditions and the following disclaimer in the
12
 * documentation and/or other materials provided with the distribution.
13
 *   3. Neither the name of the California Institute of Technology (Caltech),
14
 * its operating division the Jet Propulsion Laboratory (JPL), the National
15
 * Aeronautics and Space Administration (NASA), nor the names of its
16
 * contributors may be used to endorse or promote products derived from this
17
 * software without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED. IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE
23
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 *
31
 * Copyright 2014-2021 Esri
32
 *
33
 * Licensed under the Apache License, Version 2.0 (the "License");
34
 * you may not use this file except in compliance with the License.
35
 * You may obtain a copy of the License at
36
 *
37
 * http://www.apache.org/licenses/LICENSE-2.0
38
 *
39
 * Unless required by applicable law or agreed to in writing, software
40
 * distributed under the License is distributed on an "AS IS" BASIS,
41
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42
 * See the License for the specific language governing permissions and
43
 * limitations under the License.
44
 *
45
 * Author: Lucian Plesea
46
 *
47
 *
48
 * JPEG band
49
 * JPEG page compression and decompression functions, file gets compiled twice
50
 * once directly and once through inclusion from JPEG12_band.cpp
51
 * JPEG12_SUPPORTED is defined if both 8 and 12 bit JPEG will be supported
52
 * JPEG12_ON    is defined only for the 12 bit versions
53
 *
54
 * The MRF JPEG codec implements the Zen (Zero ENhanced) JPEG extension
55
 * This extension, when supported by the decompressor, preserves the zero or
56
 * non-zero state of all pixels which allows zero pixels to be used as a
57
 * non-data mask Clients which don't support the Zen extension will read it as a
58
 * normal JPEG
59
 *
60
 * On page writes, a mask of all fully zero pixels is built
61
 * If the mask has some zero pixels, it is written in a JPEG APP3 "Zen" marker
62
 * If the mask has no zero pixels, a zero length APP3 marker is inserted
63
 *
64
 * On page reads, after the JPEG decompression, if a mask or a zero length APP3
65
 * marker is detected, the masked pixels with value of zero are set to 1 while
66
 * the non-masked ones are set to zero
67
 *
68
 */
69
70
#include "marfa.h"
71
#include <setjmp.h>
72
#include <vector>
73
74
CPL_C_START
75
#include "jpeglib.h"
76
#include "jerror.h"
77
CPL_C_END
78
79
#define PACKER
80
#include "BitMask2D.h"
81
#include "Packer_RLE.h"
82
83
#if defined(BRUNSLI)
84
#include <brunsli/encode.h>
85
#include <brunsli/decode.h>
86
#endif
87
88
#if defined(EXPECTED_JPEG_LIB_VERSION) && !defined(JPEG12_SUPPORTED)
89
#if EXPECTED_JPEG_LIB_VERSION != JPEG_LIB_VERSION
90
#error EXPECTED_JPEG_LIB_VERSION != JPEG_LIB_VERSION
91
#endif
92
#endif
93
94
/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 2.2 which
95
 * adds a dual-mode 8/12 bit API in the same library.
96
 */
97
98
#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12)
99
/* Start by undefining BITS_IN_JSAMPLE which is always set to 8 in libjpeg-turbo
100
 * >= 2.2 Cf
101
 * https://github.com/libjpeg-turbo/libjpeg-turbo/commit/8b9bc4b9635a2a047fb23ebe70c9acd728d3f99b
102
 */
103
#undef BITS_IN_JSAMPLE
104
/* libjpeg-turbo >= 2.2 adds J12xxxx datatypes for the 12-bit mode. */
105
#if defined(JPEG12_ON)
106
#define BITS_IN_JSAMPLE 12
107
#define MRF_JSAMPLE J12SAMPLE
108
#define MRF_JSAMPARRAY J12SAMPARRAY
109
#define MRF_JSAMPIMAGE J12SAMPIMAGE
110
#define MRF_JSAMPROW J12SAMPROW
111
#else
112
#define BITS_IN_JSAMPLE 8
113
#define MRF_JSAMPLE JSAMPLE
114
#define MRF_JSAMPARRAY JSAMPARRAY
115
#define MRF_JSAMPIMAGE JSAMPIMAGE
116
#define MRF_JSAMPROW JSAMPROW
117
#endif
118
#else
119
#define MRF_JSAMPLE JSAMPLE
120
23.0k
#define MRF_JSAMPARRAY JSAMPARRAY
121
#define MRF_JSAMPIMAGE JSAMPIMAGE
122
0
#define MRF_JSAMPROW JSAMPROW
123
#endif
124
125
NAMESPACE_MRF_START
126
127
typedef BitMap2D<> BitMask;
128
129
// Values for mask_state flag
130
131
enum
132
{
133
    NO_MASK = 0,
134
    MASK_LOADED,
135
    MASK_FULL
136
};
137
138
extern char CHUNK_NAME[];
139
extern size_t CHUNK_NAME_SIZE;
140
141
typedef struct MRFJPEGStruct
142
{
143
    jmp_buf setjmpBuffer;
144
    BitMask *mask;
145
    int mask_state;
146
147
    MRFJPEGStruct()
148
495
    {
149
495
        memset(&setjmpBuffer, 0, sizeof(setjmpBuffer));
150
495
        mask = nullptr;
151
495
        mask_state = NO_MASK;
152
495
    }
153
} MRFJPEGErrorStruct;
154
155
/**
156
 *\brief Called when jpeg wants to report a warning
157
 * msgLevel can be:
158
 * -1 Corrupt data
159
 * 0 always display
160
 * 1... Trace level
161
 */
162
163
static void emitMessage(j_common_ptr cinfo, int msgLevel)
164
259k
{
165
259k
    if (msgLevel > 0)
166
19.1k
        return;  // No trace msgs
167
    // There can be many warnings, just print the first one
168
239k
    if (cinfo->err->num_warnings++ > 1)
169
238k
        return;
170
913
    char buffer[JMSG_LENGTH_MAX];
171
913
    cinfo->err->format_message(cinfo, buffer);
172
913
    CPLError(CE_Failure, CPLE_AppDefined, "%s", buffer);
173
913
}
JPEG_band.cpp:GDAL_MRF::emitMessage(jpeg_common_struct*, int)
Line
Count
Source
164
259k
{
165
259k
    if (msgLevel > 0)
166
19.1k
        return;  // No trace msgs
167
    // There can be many warnings, just print the first one
168
239k
    if (cinfo->err->num_warnings++ > 1)
169
238k
        return;
170
913
    char buffer[JMSG_LENGTH_MAX];
171
913
    cinfo->err->format_message(cinfo, buffer);
172
913
    CPLError(CE_Failure, CPLE_AppDefined, "%s", buffer);
173
913
}
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::emitMessage(jpeg_common_struct12*, int)
174
175
static void errorExit(j_common_ptr cinfo)
176
408
{
177
408
    MRFJPEGStruct *psJPEGStruct = (MRFJPEGStruct *)cinfo->client_data;
178
    // format the warning message
179
408
    char buffer[JMSG_LENGTH_MAX];
180
181
408
    cinfo->err->format_message(cinfo, buffer);
182
408
    CPLError(CE_Failure, CPLE_AppDefined, "%s", buffer);
183
    // return control to the setjmp point
184
408
    longjmp(psJPEGStruct->setjmpBuffer, 1);
185
408
}
JPEG_band.cpp:GDAL_MRF::errorExit(jpeg_common_struct*)
Line
Count
Source
176
408
{
177
408
    MRFJPEGStruct *psJPEGStruct = (MRFJPEGStruct *)cinfo->client_data;
178
    // format the warning message
179
408
    char buffer[JMSG_LENGTH_MAX];
180
181
408
    cinfo->err->format_message(cinfo, buffer);
182
408
    CPLError(CE_Failure, CPLE_AppDefined, "%s", buffer);
183
    // return control to the setjmp point
184
408
    longjmp(psJPEGStruct->setjmpBuffer, 1);
185
408
}
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::errorExit(jpeg_common_struct12*)
186
187
/**
188
 *\brief Do nothing stub function for JPEG library, called
189
 */
190
static void stub_source_dec(j_decompress_ptr /*cinfo*/)
191
531
{
192
531
}
JPEG_band.cpp:GDAL_MRF::stub_source_dec(jpeg_decompress_struct*)
Line
Count
Source
191
531
{
192
531
}
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::stub_source_dec(jpeg_decompress_struct12*)
193
194
/**
195
 *\brief: This function is supposed to do refilling of the input buffer,
196
 * but as we provided everything at the beginning, if it is called, then
197
 * we have an error.
198
 */
199
static boolean fill_input_buffer_dec(j_decompress_ptr cinfo)
200
117
{
201
117
    CPLError(CE_Failure, CPLE_AppDefined, "Invalid JPEG stream");
202
117
    cinfo->err->msg_code = JERR_INPUT_EMPTY;
203
117
    cinfo->err->error_exit((j_common_ptr)(cinfo));
204
117
    return FALSE;
205
117
}
JPEG_band.cpp:GDAL_MRF::fill_input_buffer_dec(jpeg_decompress_struct*)
Line
Count
Source
200
117
{
201
117
    CPLError(CE_Failure, CPLE_AppDefined, "Invalid JPEG stream");
202
117
    cinfo->err->msg_code = JERR_INPUT_EMPTY;
203
117
    cinfo->err->error_exit((j_common_ptr)(cinfo));
204
117
    return FALSE;
205
117
}
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::fill_input_buffer_dec(jpeg_decompress_struct12*)
206
207
/**
208
 *\brief: Skips unknown chunks
209
 */
210
static void skip_input_data_dec(j_decompress_ptr cinfo, long l)
211
302
{
212
302
    struct jpeg_source_mgr *src = cinfo->src;
213
302
    if (l > 0)
214
302
    {
215
302
        if (static_cast<size_t>(l) > src->bytes_in_buffer)
216
31
            l = static_cast<long>(src->bytes_in_buffer);
217
302
        src->bytes_in_buffer -= l;
218
302
        src->next_input_byte += l;
219
302
    }
220
302
}
JPEG_band.cpp:GDAL_MRF::skip_input_data_dec(jpeg_decompress_struct*, long)
Line
Count
Source
211
302
{
212
302
    struct jpeg_source_mgr *src = cinfo->src;
213
302
    if (l > 0)
214
302
    {
215
302
        if (static_cast<size_t>(l) > src->bytes_in_buffer)
216
31
            l = static_cast<long>(src->bytes_in_buffer);
217
302
        src->bytes_in_buffer -= l;
218
302
        src->next_input_byte += l;
219
302
    }
220
302
}
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::skip_input_data_dec(jpeg_decompress_struct12*, long)
221
222
// Destination should be already set up
223
static void init_or_terminate_destination(j_compress_ptr /*cinfo*/)
224
0
{
225
0
}
Unexecuted instantiation: JPEG_band.cpp:GDAL_MRF::init_or_terminate_destination(jpeg_compress_struct*)
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::init_or_terminate_destination(jpeg_compress_struct12*)
226
227
// Called if the buffer provided is too small
228
static boolean empty_output_buffer(j_compress_ptr /*cinfo*/)
229
0
{
230
0
    std::cerr << "JPEG Output buffer empty called\n";
231
0
    return FALSE;
232
0
}
Unexecuted instantiation: JPEG_band.cpp:GDAL_MRF::empty_output_buffer(jpeg_compress_struct*)
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::empty_output_buffer(jpeg_compress_struct12*)
233
234
// Returns the number of zero pixels in the page, as well as clearing those bits
235
// in the mask
236
template <typename T> static int update_mask(BitMask &mask, T *src, int nc)
237
0
{
238
0
    int zeros = 0;
239
0
    int h = mask.getHeight();
240
0
    int w = mask.getWidth();
241
0
    for (int y = 0; y < h; y++)
242
0
        for (int x = 0; x < w; x++)
243
0
        {
244
0
            bool is_zero = true;
245
0
            for (int c = 0; c < nc; c++)
246
0
                if (*src++ != 0)
247
0
                    is_zero = false;
248
0
            if (is_zero)
249
0
            {
250
0
                zeros++;
251
0
                mask.clear(x, y);
252
0
            }
253
0
        }
254
0
    return zeros;
255
0
}
Unexecuted instantiation: JPEG_band.cpp:int GDAL_MRF::update_mask<unsigned char>(GDAL_MRF::BitMap2D<unsigned long long>&, unsigned char*, int)
Unexecuted instantiation: JPEG_band.cpp:int GDAL_MRF::update_mask<unsigned short>(GDAL_MRF::BitMap2D<unsigned long long>&, unsigned short*, int)
Unexecuted instantiation: JPEG12_band.cpp:int GDAL_MRF::update_mask<unsigned char>(GDAL_MRF::BitMap2D<unsigned long long>&, unsigned char*, int)
Unexecuted instantiation: JPEG12_band.cpp:int GDAL_MRF::update_mask<unsigned short>(GDAL_MRF::BitMap2D<unsigned long long>&, unsigned short*, int)
256
257
/*
258
 *\brief Compress a JPEG page in memory
259
 *
260
 * It handles byte or 12 bit data, grayscale, RGB, YUV, and multispectral
261
 *
262
 * Returns the compressed size in dest.size
263
 */
264
#if defined(JPEG12_ON)
265
CPLErr JPEG_Codec::CompressJPEG12(buf_mgr &dst, buf_mgr &src)
266
#else
267
CPLErr JPEG_Codec::CompressJPEG(buf_mgr &dst, buf_mgr &src)
268
#endif
269
270
0
{
271
    // The cinfo should stay open and reside in the DS, since it can be left
272
    // initialized It saves some time because it has the tables initialized
273
0
    struct jpeg_compress_struct cinfo;
274
0
    MRFJPEGStruct sJPEGStruct;
275
0
    struct jpeg_error_mgr sJErr;
276
0
    ILSize sz = img.pagesize;
277
278
0
    jpeg_destination_mgr jmgr;
279
0
    jmgr.next_output_byte = reinterpret_cast<JOCTET *>(dst.buffer);
280
0
    jmgr.free_in_buffer = dst.size;
281
0
    jmgr.init_destination = init_or_terminate_destination;
282
0
    jmgr.empty_output_buffer = empty_output_buffer;
283
0
    jmgr.term_destination = init_or_terminate_destination;
284
285
0
    memset(&cinfo, 0, sizeof(cinfo));
286
287
    // Look at the source of this, some interesting tidbits
288
0
    cinfo.err = jpeg_std_error(&sJErr);
289
0
    sJErr.error_exit = errorExit;
290
0
    sJErr.emit_message = emitMessage;
291
0
    cinfo.client_data = (void *)&(sJPEGStruct);
292
0
    jpeg_create_compress(&cinfo);
293
0
    cinfo.dest = &jmgr;
294
295
    // The page specific info, size and color spaces
296
0
    cinfo.image_width = sz.x;
297
0
    cinfo.image_height = sz.y;
298
0
    cinfo.input_components = sz.c;
299
0
    switch (cinfo.input_components)
300
0
    {
301
0
        case 1:
302
0
            cinfo.in_color_space = JCS_GRAYSCALE;
303
0
            break;
304
0
        case 3:
305
0
            cinfo.in_color_space = JCS_RGB;
306
0
            break;  // Stored as YCbCr 4:2:0 by default
307
0
        default:
308
0
            cinfo.in_color_space = JCS_UNKNOWN;  // 2, 4-10 bands
309
0
    }
310
311
#if defined(JPEG12_ON)
312
0
    cinfo.data_precision = 12;
313
#else
314
0
    cinfo.data_precision = 8;
315
0
#endif
316
317
    // Set all required fields and overwrite the ones we want to change
318
0
    jpeg_set_defaults(&cinfo);
319
320
    // Override certain settings
321
0
    jpeg_set_quality(&cinfo, img.quality, TRUE);
322
0
    cinfo.dct_method = JDCT_FLOAT;  // Pretty fast and precise
323
0
    cinfo.optimize_coding =
324
0
        optimize;  // Set "OPTIMIZE=TRUE" in OPTIONS, default for 12bit
325
326
    // Do we explicitly turn off the YCC color and downsampling?
327
328
0
    if (cinfo.in_color_space == JCS_RGB)
329
0
    {
330
0
        if (rgb)
331
0
        {                                          // Stored as RGB
332
0
            jpeg_set_colorspace(&cinfo, JCS_RGB);  // Huge files
333
0
        }
334
0
        else if (sameres)
335
0
        {  // YCC, somewhat larger files with improved color spatial detail
336
0
            cinfo.comp_info[0].h_samp_factor = 1;
337
0
            cinfo.comp_info[0].v_samp_factor = 1;
338
339
            // Enabling these lines will make the color components use the same
340
            // tables as Y, even larger file with slightly better color depth
341
            // detail cinfo.comp_info[1].quant_tbl_no = 0;
342
            // cinfo.comp_info[2].quant_tbl_no = 0;
343
344
            // cinfo.comp_info[1].dc_tbl_no = 0;
345
            // cinfo.comp_info[2].dc_tbl_no = 0;
346
347
            // cinfo.comp_info[1].ac_tbl_no = 0;
348
            // cinfo.comp_info[2].ac_tbl_no = 0;
349
0
        }
350
0
    }
351
352
0
    int linesize = cinfo.image_width * cinfo.input_components *
353
0
                   ((cinfo.data_precision == 8) ? 1 : 2);
354
0
    MRF_JSAMPROW *rowp = (MRF_JSAMPROW *)CPLMalloc(sizeof(MRF_JSAMPROW) * sz.y);
355
0
    if (!rowp)
356
0
    {
357
0
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG compression error");
358
0
        jpeg_destroy_compress(&cinfo);
359
0
        return CE_Failure;
360
0
    }
361
362
0
    for (int i = 0; i < sz.y; i++)
363
0
    {
364
0
        rowp[i] = (MRF_JSAMPROW)(src.buffer + i * linesize);
365
#if defined(JPEG12_ON)
366
0
        for (int x = 0; x < sz.x; ++x)
367
0
        {
368
0
            if (static_cast<unsigned short>(rowp[i][x]) > 4095)
369
0
            {
370
0
                rowp[i][x] = (MRF_JSAMPLE)4095;
371
0
                static bool bClipWarn = false;
372
0
                if (!bClipWarn)
373
0
                {
374
0
                    bClipWarn = true;
375
0
                    CPLError(CE_Warning, CPLE_AppDefined,
376
0
                             "One or more pixels clipped to fit 12bit domain "
377
0
                             "for jpeg output.");
378
0
                }
379
0
            }
380
0
        }
381
#endif
382
0
    }
383
384
0
    if (setjmp(sJPEGStruct.setjmpBuffer))
385
0
    {
386
0
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG compression error");
387
0
        jpeg_destroy_compress(&cinfo);
388
0
        CPLFree(rowp);
389
0
        return CE_Failure;
390
0
    }
391
392
    // Build a bitmaps of the black pixels
393
    // If there are any black pixels, write a compressed mask in APP3 "Zen"
394
    // chunk
395
396
    // Mask is initialized to all pixels valid
397
0
    BitMask mask(sz.x, sz.y);
398
0
    storage_manager mbuffer = {CHUNK_NAME, CHUNK_NAME_SIZE};
399
400
0
    int nzeros =
401
0
        (cinfo.data_precision == 8)
402
0
            ? update_mask(mask, reinterpret_cast<GByte *>(src.buffer), sz.c)
403
0
            : update_mask(mask, reinterpret_cast<GUInt16 *>(src.buffer), sz.c);
404
405
    // In case we need to build a Zen chunk
406
0
    char *buffer = nullptr;
407
408
0
    if (nzeros != 0)
409
0
    {  // build the Zen chunk
410
0
        mbuffer.size = 2 * mask.size() + CHUNK_NAME_SIZE;
411
0
        buffer = static_cast<char *>(CPLMalloc(mbuffer.size));
412
0
        if (!buffer)
413
0
        {
414
0
            jpeg_destroy_compress(&cinfo);
415
0
            CPLFree(rowp);
416
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
417
0
                     "MRF: JPEG Zen mask compression");
418
0
            return CE_Failure;
419
0
        }
420
421
0
        memcpy(buffer, CHUNK_NAME, CHUNK_NAME_SIZE);
422
0
        mbuffer.buffer = buffer + CHUNK_NAME_SIZE;
423
0
        mbuffer.size -= CHUNK_NAME_SIZE;
424
425
0
        RLEC3Packer c3;
426
0
        mask.set_packer(&c3);
427
0
        if (!mask.store(&mbuffer))
428
0
        {
429
0
            CPLError(CE_Failure, CPLE_AppDefined,
430
0
                     "MRF: JPEG Zen mask compression");
431
0
            CPLFree(rowp);
432
0
            CPLFree(buffer);
433
0
            return CE_Failure;
434
0
        }
435
436
        // Change the buffer pointer to include the signature, on output the
437
        // size is the compressed size
438
0
        mbuffer.buffer = buffer;
439
0
        mbuffer.size += CHUNK_NAME_SIZE;
440
441
        // Check that the size fits in one JPEG chunk
442
0
        if (mbuffer.size + 2 + CHUNK_NAME_SIZE > 65535)
443
0
        {
444
            // Should split it in multiple chunks, for now mark this tile as all
445
            // data and emit a warning
446
0
            CPLError(CE_Warning, CPLE_NotSupported,
447
0
                     "MRF: JPEG Zen mask too large");
448
0
            mbuffer.size = CHUNK_NAME_SIZE;  // Write just the signature
449
0
        }
450
0
    }
451
452
    // Everything is ready
453
0
    jpeg_start_compress(&cinfo, TRUE);
454
455
    // Always write the Zen app chunk, App3
456
0
    jpeg_write_marker(&cinfo, JPEG_APP0 + 3,
457
0
                      reinterpret_cast<JOCTET *>(mbuffer.buffer),
458
0
                      static_cast<unsigned int>(mbuffer.size));
459
460
#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && defined(JPEG12_ON)
461
    jpeg12_write_scanlines(&cinfo, rowp, sz.y);
462
#else
463
0
    jpeg_write_scanlines(&cinfo, rowp, sz.y);
464
0
#endif
465
0
    jpeg_finish_compress(&cinfo);
466
0
    jpeg_destroy_compress(&cinfo);
467
468
0
    CPLFree(rowp);
469
0
    CPLFree(buffer);  // Safe to call on null
470
471
    // Figure out the size of the JFIF
472
0
    dst.size -= jmgr.free_in_buffer;
473
0
    return CE_None;
474
0
}
Unexecuted instantiation: GDAL_MRF::JPEG_Codec::CompressJPEG(GDAL_MRF::buf_mgr&, GDAL_MRF::buf_mgr&)
Unexecuted instantiation: GDAL_MRF::JPEG_Codec::CompressJPEG12(GDAL_MRF::buf_mgr&, GDAL_MRF::buf_mgr&)
475
476
/************************************************************************/
477
/*                          ProgressMonitor()                           */
478
/************************************************************************/
479
480
/* Avoid the risk of denial-of-service on crafted JPEGs with an insane */
481
/* number of scans. */
482
/* See
483
 * http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf
484
 */
485
static void ProgressMonitor(j_common_ptr cinfo)
486
262k
{
487
262k
    if (cinfo->is_decompressor)
488
262k
    {
489
262k
        const int scan_no =
490
262k
            reinterpret_cast<j_decompress_ptr>(cinfo)->input_scan_number;
491
262k
        const int MAX_SCANS = 100;
492
262k
        if (scan_no >= MAX_SCANS)
493
10
        {
494
10
            CPLError(CE_Failure, CPLE_AppDefined,
495
10
                     "Scan number %d exceeds maximum scans (%d)", scan_no,
496
10
                     MAX_SCANS);
497
498
10
            MRFJPEGStruct *psJPEGStruct = (MRFJPEGStruct *)cinfo->client_data;
499
500
            // return control to the setjmp point
501
10
            longjmp(psJPEGStruct->setjmpBuffer, 1);
502
10
        }
503
262k
    }
504
262k
}
JPEG_band.cpp:GDAL_MRF::ProgressMonitor(jpeg_common_struct*)
Line
Count
Source
486
262k
{
487
262k
    if (cinfo->is_decompressor)
488
262k
    {
489
262k
        const int scan_no =
490
262k
            reinterpret_cast<j_decompress_ptr>(cinfo)->input_scan_number;
491
262k
        const int MAX_SCANS = 100;
492
262k
        if (scan_no >= MAX_SCANS)
493
10
        {
494
10
            CPLError(CE_Failure, CPLE_AppDefined,
495
10
                     "Scan number %d exceeds maximum scans (%d)", scan_no,
496
10
                     MAX_SCANS);
497
498
10
            MRFJPEGStruct *psJPEGStruct = (MRFJPEGStruct *)cinfo->client_data;
499
500
            // return control to the setjmp point
501
10
            longjmp(psJPEGStruct->setjmpBuffer, 1);
502
10
        }
503
262k
    }
504
262k
}
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::ProgressMonitor(jpeg_common_struct12*)
505
506
// Returns the number of zero pixels, as well as clearing those bits int the
507
// mask
508
template <typename T> static void apply_mask(MRFJPEGStruct &sJ, T *s, int nc)
509
36
{
510
36
    if (NO_MASK == sJ.mask_state)
511
2
        return;
512
513
34
    BitMask *mask = sJ.mask;
514
34
    int w = mask->getWidth();
515
34
    int h = mask->getHeight();
516
517
34
    if (MASK_LOADED == sJ.mask_state)
518
21
    {  // Partial map
519
10.5k
        for (int y = 0; y < h; y++)
520
3.71M
            for (int x = 0; x < w; x++)
521
3.69M
            {
522
3.69M
                if (mask->isSet(x, y))
523
1.84M
                {  // Non zero pixel
524
55.2M
                    for (int c = 0; c < nc; c++, s++)
525
53.3M
                    {
526
53.3M
                        if (*s == 0)
527
8.58M
                            *s = 1;
528
53.3M
                    }
529
1.84M
                }
530
1.85M
                else
531
1.85M
                {  // Zero pixel
532
55.7M
                    for (int c = 0; c < nc; c++)
533
53.9M
                        *s++ = 0;
534
1.85M
                }
535
3.69M
            }
536
21
    }
537
13
    else if (MASK_FULL == sJ.mask_state)
538
13
    {  // All non-zero
539
6.55k
        for (int y = 0; y < h; y++)
540
2.77M
            for (int x = 0; x < w; x++)
541
2.77M
            {
542
16.6M
                for (int c = 0; c < nc; c++, s++)
543
13.8M
                {
544
13.8M
                    if (*s == 0)
545
6.73M
                        *s = 1;
546
13.8M
                }
547
2.77M
            }
548
13
    }
549
34
}
JPEG_band.cpp:void GDAL_MRF::apply_mask<char>(GDAL_MRF::MRFJPEGStruct&, char*, int)
Line
Count
Source
509
36
{
510
36
    if (NO_MASK == sJ.mask_state)
511
2
        return;
512
513
34
    BitMask *mask = sJ.mask;
514
34
    int w = mask->getWidth();
515
34
    int h = mask->getHeight();
516
517
34
    if (MASK_LOADED == sJ.mask_state)
518
21
    {  // Partial map
519
10.5k
        for (int y = 0; y < h; y++)
520
3.71M
            for (int x = 0; x < w; x++)
521
3.69M
            {
522
3.69M
                if (mask->isSet(x, y))
523
1.84M
                {  // Non zero pixel
524
55.2M
                    for (int c = 0; c < nc; c++, s++)
525
53.3M
                    {
526
53.3M
                        if (*s == 0)
527
8.58M
                            *s = 1;
528
53.3M
                    }
529
1.84M
                }
530
1.85M
                else
531
1.85M
                {  // Zero pixel
532
55.7M
                    for (int c = 0; c < nc; c++)
533
53.9M
                        *s++ = 0;
534
1.85M
                }
535
3.69M
            }
536
21
    }
537
13
    else if (MASK_FULL == sJ.mask_state)
538
13
    {  // All non-zero
539
6.55k
        for (int y = 0; y < h; y++)
540
2.77M
            for (int x = 0; x < w; x++)
541
2.77M
            {
542
16.6M
                for (int c = 0; c < nc; c++, s++)
543
13.8M
                {
544
13.8M
                    if (*s == 0)
545
6.73M
                        *s = 1;
546
13.8M
                }
547
2.77M
            }
548
13
    }
549
34
}
Unexecuted instantiation: JPEG_band.cpp:void GDAL_MRF::apply_mask<unsigned short>(GDAL_MRF::MRFJPEGStruct&, unsigned short*, int)
Unexecuted instantiation: JPEG12_band.cpp:void GDAL_MRF::apply_mask<char>(GDAL_MRF::MRFJPEGStruct&, char*, int)
Unexecuted instantiation: JPEG12_band.cpp:void GDAL_MRF::apply_mask<unsigned short>(GDAL_MRF::MRFJPEGStruct&, unsigned short*, int)
550
551
// JPEG marker processor, for the Zen app3 marker
552
// Can't return error, only works if the JPEG mask is all in the buffer
553
static boolean MaskProcessor(j_decompress_ptr pcinfo)
554
3.95k
{
555
3.95k
    struct jpeg_source_mgr *src = pcinfo->src;
556
3.95k
    if (src->bytes_in_buffer < 2)
557
3.95k
        ERREXIT(pcinfo, JERR_CANT_SUSPEND);
558
    // Big endian length, two bytes
559
3.95k
    int len = (*src->next_input_byte++) << 8;
560
3.95k
    len += *src->next_input_byte++;
561
    // The length includes the two bytes we just read
562
3.95k
    src->bytes_in_buffer -= 2;
563
3.95k
    len -= 2;
564
    // Check that it is safe to read the rest
565
3.95k
    if (src->bytes_in_buffer < static_cast<size_t>(len))
566
3.95k
        ERREXIT(pcinfo, JERR_CANT_SUSPEND);
567
3.95k
    MRFJPEGStruct *psJPEG =
568
3.95k
        reinterpret_cast<MRFJPEGStruct *>(pcinfo->client_data);
569
3.95k
    BitMask *mask = psJPEG->mask;
570
    // caller doesn't want a mask or wrong chunk, skip the chunk and return
571
3.95k
    if (!mask || static_cast<size_t>(len) < CHUNK_NAME_SIZE ||
572
2.41k
        !EQUALN(reinterpret_cast<const char *>(src->next_input_byte),
573
3.95k
                CHUNK_NAME, CHUNK_NAME_SIZE))
574
2.54k
    {
575
2.54k
        src->bytes_in_buffer -= len;
576
2.54k
        src->next_input_byte += len;
577
2.54k
        return true;
578
2.54k
    }
579
580
    // Skip the signature and load the mask
581
1.41k
    src->bytes_in_buffer -= CHUNK_NAME_SIZE;
582
1.41k
    src->next_input_byte += CHUNK_NAME_SIZE;
583
1.41k
    len -= static_cast<int>(CHUNK_NAME_SIZE);
584
1.41k
    if (len == 0)
585
1.11k
    {  // No mask content means mask is all full, just return
586
1.11k
        psJPEG->mask_state = MASK_FULL;
587
1.11k
        return true;
588
1.11k
    }
589
590
    // It is OK to use const cast, the mask doesn't touch the buffer
591
295
    storage_manager msrc = {const_cast<char *>(reinterpret_cast<const char *>(
592
295
                                src->next_input_byte)),
593
295
                            static_cast<size_t>(len)};
594
595
295
    if (!mask->load(&msrc))
596
194
    {  // Fatal error return, mask is not valid
597
194
        ERREXIT(pcinfo, JERR_CANT_SUSPEND);
598
194
    }
599
600
295
    src->bytes_in_buffer -= len;
601
295
    src->next_input_byte += len;
602
295
    psJPEG->mask_state = MASK_LOADED;
603
295
    return true;
604
1.41k
}
JPEG_band.cpp:GDAL_MRF::MaskProcessor(jpeg_decompress_struct*)
Line
Count
Source
554
3.95k
{
555
3.95k
    struct jpeg_source_mgr *src = pcinfo->src;
556
3.95k
    if (src->bytes_in_buffer < 2)
557
3.95k
        ERREXIT(pcinfo, JERR_CANT_SUSPEND);
558
    // Big endian length, two bytes
559
3.95k
    int len = (*src->next_input_byte++) << 8;
560
3.95k
    len += *src->next_input_byte++;
561
    // The length includes the two bytes we just read
562
3.95k
    src->bytes_in_buffer -= 2;
563
3.95k
    len -= 2;
564
    // Check that it is safe to read the rest
565
3.95k
    if (src->bytes_in_buffer < static_cast<size_t>(len))
566
3.95k
        ERREXIT(pcinfo, JERR_CANT_SUSPEND);
567
3.95k
    MRFJPEGStruct *psJPEG =
568
3.95k
        reinterpret_cast<MRFJPEGStruct *>(pcinfo->client_data);
569
3.95k
    BitMask *mask = psJPEG->mask;
570
    // caller doesn't want a mask or wrong chunk, skip the chunk and return
571
3.95k
    if (!mask || static_cast<size_t>(len) < CHUNK_NAME_SIZE ||
572
2.41k
        !EQUALN(reinterpret_cast<const char *>(src->next_input_byte),
573
3.95k
                CHUNK_NAME, CHUNK_NAME_SIZE))
574
2.54k
    {
575
2.54k
        src->bytes_in_buffer -= len;
576
2.54k
        src->next_input_byte += len;
577
2.54k
        return true;
578
2.54k
    }
579
580
    // Skip the signature and load the mask
581
1.41k
    src->bytes_in_buffer -= CHUNK_NAME_SIZE;
582
1.41k
    src->next_input_byte += CHUNK_NAME_SIZE;
583
1.41k
    len -= static_cast<int>(CHUNK_NAME_SIZE);
584
1.41k
    if (len == 0)
585
1.11k
    {  // No mask content means mask is all full, just return
586
1.11k
        psJPEG->mask_state = MASK_FULL;
587
1.11k
        return true;
588
1.11k
    }
589
590
    // It is OK to use const cast, the mask doesn't touch the buffer
591
295
    storage_manager msrc = {const_cast<char *>(reinterpret_cast<const char *>(
592
295
                                src->next_input_byte)),
593
295
                            static_cast<size_t>(len)};
594
595
295
    if (!mask->load(&msrc))
596
194
    {  // Fatal error return, mask is not valid
597
194
        ERREXIT(pcinfo, JERR_CANT_SUSPEND);
598
194
    }
599
600
295
    src->bytes_in_buffer -= len;
601
295
    src->next_input_byte += len;
602
295
    psJPEG->mask_state = MASK_LOADED;
603
295
    return true;
604
1.41k
}
Unexecuted instantiation: JPEG12_band.cpp:GDAL_MRF::MaskProcessor(jpeg_decompress_struct12*)
605
606
/**
607
 *\brief In memory decompression of JPEG file
608
 *
609
 * @param data pointer to output buffer
610
 * @param png pointer to PNG in memory
611
 * @param sz if non-zero, test that uncompressed data fits in the buffer.
612
 */
613
#if defined(JPEG12_ON)
614
CPLErr JPEG_Codec::DecompressJPEG12(buf_mgr &dst, const buf_mgr &isrc)
615
#else
616
CPLErr JPEG_Codec::DecompressJPEG(buf_mgr &dst, const buf_mgr &isrc)
617
#endif
618
619
495
{
620
495
    int nbands = img.pagesize.c;
621
    // Locals, clean up after themselves
622
495
    jpeg_decompress_struct cinfo;
623
495
    MRFJPEGStruct sJPEGStruct;
624
495
    struct jpeg_error_mgr sJErr;
625
495
    BitMask mask(img.pagesize.x, img.pagesize.y);
626
495
    RLEC3Packer packer;
627
495
    mask.set_packer(&packer);
628
629
495
    memset(&cinfo, 0, sizeof(cinfo));
630
    // Pass the mask address to the decompressor
631
495
    sJPEGStruct.mask = &mask;
632
633
495
    struct jpeg_source_mgr src;
634
635
495
    cinfo.err = jpeg_std_error(&sJErr);
636
495
    sJErr.error_exit = errorExit;
637
495
    sJErr.emit_message = emitMessage;
638
495
    cinfo.client_data = &sJPEGStruct;
639
640
495
    src.next_input_byte = reinterpret_cast<JOCTET *>(isrc.buffer);
641
495
    src.bytes_in_buffer = isrc.size;
642
495
    src.term_source = stub_source_dec;
643
495
    src.init_source = stub_source_dec;
644
495
    src.skip_input_data = skip_input_data_dec;
645
495
    src.fill_input_buffer = fill_input_buffer_dec;
646
495
    src.resync_to_restart = jpeg_resync_to_restart;
647
648
495
    jpeg_create_decompress(&cinfo);
649
650
495
    if (setjmp(sJPEGStruct.setjmpBuffer))
651
418
    {
652
418
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error reading JPEG page");
653
418
        jpeg_destroy_decompress(&cinfo);
654
418
        return CE_Failure;
655
418
    }
656
657
77
    cinfo.src = &src;
658
77
    jpeg_set_marker_processor(&cinfo, JPEG_APP0 + 3, MaskProcessor);
659
77
    jpeg_read_header(&cinfo, TRUE);
660
661
    /* In some cases, libjpeg needs to allocate a lot of memory */
662
    /* http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf
663
     */
664
77
    if (jpeg_has_multiple_scans(&(cinfo)))
665
163
    {
666
        /* In this case libjpeg will need to allocate memory or backing */
667
        /* store for all coefficients */
668
        /* See call to jinit_d_coef_controller() from master_selection() */
669
        /* in libjpeg */
670
163
        vsi_l_offset nRequiredMemory =
671
163
            static_cast<vsi_l_offset>(cinfo.image_width) * cinfo.image_height *
672
163
            cinfo.num_components * ((cinfo.data_precision + 7) / 8);
673
        /* BLOCK_SMOOTHING_SUPPORTED is generally defined, so we need */
674
        /* to replicate the logic of jinit_d_coef_controller() */
675
163
        if (cinfo.progressive_mode)
676
163
            nRequiredMemory *= 3;
677
678
163
#ifndef GDAL_LIBJPEG_LARGEST_MEM_ALLOC
679
326
#define GDAL_LIBJPEG_LARGEST_MEM_ALLOC (100 * 1024 * 1024)
680
163
#endif
681
682
163
        if (nRequiredMemory > GDAL_LIBJPEG_LARGEST_MEM_ALLOC &&
683
0
            CPLGetConfigOption("GDAL_ALLOW_LARGE_LIBJPEG_MEM_ALLOC", nullptr) ==
684
0
                nullptr)
685
0
        {
686
0
            CPLError(CE_Failure, CPLE_NotSupported,
687
0
                     "Reading this image would require libjpeg to allocate "
688
0
                     "at least " CPL_FRMT_GUIB " bytes. "
689
0
                     "This is disabled since above the " CPL_FRMT_GUIB
690
0
                     " threshold. "
691
0
                     "You may override this restriction by defining the "
692
0
                     "GDAL_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, "
693
0
                     "or recompile GDAL by defining the "
694
0
                     "GDAL_LIBJPEG_LARGEST_MEM_ALLOC macro to a value greater "
695
0
                     "than " CPL_FRMT_GUIB,
696
0
                     static_cast<GUIntBig>(nRequiredMemory),
697
0
                     static_cast<GUIntBig>(GDAL_LIBJPEG_LARGEST_MEM_ALLOC),
698
0
                     static_cast<GUIntBig>(GDAL_LIBJPEG_LARGEST_MEM_ALLOC));
699
0
            jpeg_destroy_decompress(&cinfo);
700
0
            return CE_Failure;
701
0
        }
702
163
    }
703
704
    // Use float, it is actually faster than the ISLOW method by a tiny bit
705
77
    cinfo.dct_method = JDCT_FLOAT;
706
707
    //
708
    // Tolerate different input if we can do the conversion
709
    // Gray and RGB for example
710
    // This also means that a RGB MRF can be read as grayscale and vice versa
711
    // If libJPEG can't convert it will throw an error
712
    //
713
77
    if (nbands == 3 && cinfo.num_components != nbands)
714
12
        cinfo.out_color_space = JCS_RGB;
715
77
    if (nbands == 1 && cinfo.num_components != nbands)
716
0
        cinfo.out_color_space = JCS_GRAYSCALE;
717
718
18.4E
    const int datasize = ((cinfo.data_precision == 8) ? 1 : 2);
719
77
    if (cinfo.image_width >
720
77
        static_cast<unsigned>(INT_MAX / (nbands * datasize)))
721
0
    {
722
0
        CPLError(CE_Failure, CPLE_AppDefined,
723
0
                 "MRF: JPEG decompress buffer overflow");
724
0
        jpeg_destroy_decompress(&cinfo);
725
0
        return CE_Failure;
726
0
    }
727
77
    int linesize = cinfo.image_width * nbands * datasize;
728
729
    // We have a mismatch between the real and the declared data format
730
    // warn and fail if output buffer is too small
731
77
    if (linesize > static_cast<int>(INT_MAX / cinfo.image_height))
732
0
    {
733
0
        CPLError(CE_Failure, CPLE_AppDefined,
734
0
                 "MRF: JPEG decompress buffer overflow");
735
0
        jpeg_destroy_decompress(&cinfo);
736
0
        return CE_Failure;
737
0
    }
738
77
    if (static_cast<size_t>(linesize) * cinfo.image_height != dst.size)
739
176
    {
740
176
        CPLError(CE_Warning, CPLE_AppDefined, "MRF: read JPEG size is wrong");
741
176
        if (static_cast<size_t>(linesize) * cinfo.image_height > dst.size)
742
41
        {
743
41
            CPLError(CE_Failure, CPLE_AppDefined,
744
41
                     "MRF: JPEG decompress buffer overflow");
745
41
            jpeg_destroy_decompress(&cinfo);
746
41
            return CE_Failure;
747
41
        }
748
176
    }
749
750
36
    struct jpeg_progress_mgr sJProgress;
751
36
    sJProgress.progress_monitor = ProgressMonitor;
752
36
    cinfo.progress = &sJProgress;
753
754
36
    jpeg_start_decompress(&cinfo);
755
756
    // Decompress, two lines at a time is what libjpeg does
757
23.0k
    while (cinfo.output_scanline < cinfo.image_height)
758
23.0k
    {
759
23.0k
        char *rp[2];
760
23.0k
        rp[0] = (char *)dst.buffer + linesize * cinfo.output_scanline;
761
23.0k
        rp[1] = rp[0] + linesize;
762
        // if this fails, it calls the error handler
763
        // which will report an error
764
#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && defined(JPEG12_ON)
765
        if (jpeg12_read_scanlines(&cinfo, MRF_JSAMPARRAY(rp), 2) == 0)
766
#else
767
23.0k
        if (jpeg_read_scanlines(&cinfo, MRF_JSAMPARRAY(rp), 2) == 0)
768
0
#endif
769
0
        {
770
0
            jpeg_destroy_decompress(&cinfo);
771
0
            return CE_Failure;
772
0
        }
773
23.0k
    }
774
36
    jpeg_finish_decompress(&cinfo);
775
0
    jpeg_destroy_decompress(&cinfo);
776
777
    // Apply the mask
778
36
    if (datasize == 1)
779
36
        apply_mask(sJPEGStruct, reinterpret_cast<char *>(dst.buffer),
780
36
                   img.pagesize.c);
781
0
    else
782
0
        apply_mask(sJPEGStruct, reinterpret_cast<GUInt16 *>(dst.buffer),
783
0
                   img.pagesize.c);
784
785
0
    return CE_None;
786
36
}
GDAL_MRF::JPEG_Codec::DecompressJPEG(GDAL_MRF::buf_mgr&, GDAL_MRF::buf_mgr const&)
Line
Count
Source
619
495
{
620
495
    int nbands = img.pagesize.c;
621
    // Locals, clean up after themselves
622
495
    jpeg_decompress_struct cinfo;
623
495
    MRFJPEGStruct sJPEGStruct;
624
495
    struct jpeg_error_mgr sJErr;
625
495
    BitMask mask(img.pagesize.x, img.pagesize.y);
626
495
    RLEC3Packer packer;
627
495
    mask.set_packer(&packer);
628
629
495
    memset(&cinfo, 0, sizeof(cinfo));
630
    // Pass the mask address to the decompressor
631
495
    sJPEGStruct.mask = &mask;
632
633
495
    struct jpeg_source_mgr src;
634
635
495
    cinfo.err = jpeg_std_error(&sJErr);
636
495
    sJErr.error_exit = errorExit;
637
495
    sJErr.emit_message = emitMessage;
638
495
    cinfo.client_data = &sJPEGStruct;
639
640
495
    src.next_input_byte = reinterpret_cast<JOCTET *>(isrc.buffer);
641
495
    src.bytes_in_buffer = isrc.size;
642
495
    src.term_source = stub_source_dec;
643
495
    src.init_source = stub_source_dec;
644
495
    src.skip_input_data = skip_input_data_dec;
645
495
    src.fill_input_buffer = fill_input_buffer_dec;
646
495
    src.resync_to_restart = jpeg_resync_to_restart;
647
648
495
    jpeg_create_decompress(&cinfo);
649
650
495
    if (setjmp(sJPEGStruct.setjmpBuffer))
651
418
    {
652
418
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error reading JPEG page");
653
418
        jpeg_destroy_decompress(&cinfo);
654
418
        return CE_Failure;
655
418
    }
656
657
77
    cinfo.src = &src;
658
77
    jpeg_set_marker_processor(&cinfo, JPEG_APP0 + 3, MaskProcessor);
659
77
    jpeg_read_header(&cinfo, TRUE);
660
661
    /* In some cases, libjpeg needs to allocate a lot of memory */
662
    /* http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf
663
     */
664
77
    if (jpeg_has_multiple_scans(&(cinfo)))
665
163
    {
666
        /* In this case libjpeg will need to allocate memory or backing */
667
        /* store for all coefficients */
668
        /* See call to jinit_d_coef_controller() from master_selection() */
669
        /* in libjpeg */
670
163
        vsi_l_offset nRequiredMemory =
671
163
            static_cast<vsi_l_offset>(cinfo.image_width) * cinfo.image_height *
672
163
            cinfo.num_components * ((cinfo.data_precision + 7) / 8);
673
        /* BLOCK_SMOOTHING_SUPPORTED is generally defined, so we need */
674
        /* to replicate the logic of jinit_d_coef_controller() */
675
163
        if (cinfo.progressive_mode)
676
163
            nRequiredMemory *= 3;
677
678
163
#ifndef GDAL_LIBJPEG_LARGEST_MEM_ALLOC
679
163
#define GDAL_LIBJPEG_LARGEST_MEM_ALLOC (100 * 1024 * 1024)
680
163
#endif
681
682
163
        if (nRequiredMemory > GDAL_LIBJPEG_LARGEST_MEM_ALLOC &&
683
0
            CPLGetConfigOption("GDAL_ALLOW_LARGE_LIBJPEG_MEM_ALLOC", nullptr) ==
684
0
                nullptr)
685
0
        {
686
0
            CPLError(CE_Failure, CPLE_NotSupported,
687
0
                     "Reading this image would require libjpeg to allocate "
688
0
                     "at least " CPL_FRMT_GUIB " bytes. "
689
0
                     "This is disabled since above the " CPL_FRMT_GUIB
690
0
                     " threshold. "
691
0
                     "You may override this restriction by defining the "
692
0
                     "GDAL_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, "
693
0
                     "or recompile GDAL by defining the "
694
0
                     "GDAL_LIBJPEG_LARGEST_MEM_ALLOC macro to a value greater "
695
0
                     "than " CPL_FRMT_GUIB,
696
0
                     static_cast<GUIntBig>(nRequiredMemory),
697
0
                     static_cast<GUIntBig>(GDAL_LIBJPEG_LARGEST_MEM_ALLOC),
698
0
                     static_cast<GUIntBig>(GDAL_LIBJPEG_LARGEST_MEM_ALLOC));
699
0
            jpeg_destroy_decompress(&cinfo);
700
0
            return CE_Failure;
701
0
        }
702
163
    }
703
704
    // Use float, it is actually faster than the ISLOW method by a tiny bit
705
77
    cinfo.dct_method = JDCT_FLOAT;
706
707
    //
708
    // Tolerate different input if we can do the conversion
709
    // Gray and RGB for example
710
    // This also means that a RGB MRF can be read as grayscale and vice versa
711
    // If libJPEG can't convert it will throw an error
712
    //
713
77
    if (nbands == 3 && cinfo.num_components != nbands)
714
12
        cinfo.out_color_space = JCS_RGB;
715
77
    if (nbands == 1 && cinfo.num_components != nbands)
716
0
        cinfo.out_color_space = JCS_GRAYSCALE;
717
718
18.4E
    const int datasize = ((cinfo.data_precision == 8) ? 1 : 2);
719
77
    if (cinfo.image_width >
720
77
        static_cast<unsigned>(INT_MAX / (nbands * datasize)))
721
0
    {
722
0
        CPLError(CE_Failure, CPLE_AppDefined,
723
0
                 "MRF: JPEG decompress buffer overflow");
724
0
        jpeg_destroy_decompress(&cinfo);
725
0
        return CE_Failure;
726
0
    }
727
77
    int linesize = cinfo.image_width * nbands * datasize;
728
729
    // We have a mismatch between the real and the declared data format
730
    // warn and fail if output buffer is too small
731
77
    if (linesize > static_cast<int>(INT_MAX / cinfo.image_height))
732
0
    {
733
0
        CPLError(CE_Failure, CPLE_AppDefined,
734
0
                 "MRF: JPEG decompress buffer overflow");
735
0
        jpeg_destroy_decompress(&cinfo);
736
0
        return CE_Failure;
737
0
    }
738
77
    if (static_cast<size_t>(linesize) * cinfo.image_height != dst.size)
739
176
    {
740
176
        CPLError(CE_Warning, CPLE_AppDefined, "MRF: read JPEG size is wrong");
741
176
        if (static_cast<size_t>(linesize) * cinfo.image_height > dst.size)
742
41
        {
743
41
            CPLError(CE_Failure, CPLE_AppDefined,
744
41
                     "MRF: JPEG decompress buffer overflow");
745
41
            jpeg_destroy_decompress(&cinfo);
746
41
            return CE_Failure;
747
41
        }
748
176
    }
749
750
36
    struct jpeg_progress_mgr sJProgress;
751
36
    sJProgress.progress_monitor = ProgressMonitor;
752
36
    cinfo.progress = &sJProgress;
753
754
36
    jpeg_start_decompress(&cinfo);
755
756
    // Decompress, two lines at a time is what libjpeg does
757
23.0k
    while (cinfo.output_scanline < cinfo.image_height)
758
23.0k
    {
759
23.0k
        char *rp[2];
760
23.0k
        rp[0] = (char *)dst.buffer + linesize * cinfo.output_scanline;
761
23.0k
        rp[1] = rp[0] + linesize;
762
        // if this fails, it calls the error handler
763
        // which will report an error
764
#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && defined(JPEG12_ON)
765
        if (jpeg12_read_scanlines(&cinfo, MRF_JSAMPARRAY(rp), 2) == 0)
766
#else
767
23.0k
        if (jpeg_read_scanlines(&cinfo, MRF_JSAMPARRAY(rp), 2) == 0)
768
0
#endif
769
0
        {
770
0
            jpeg_destroy_decompress(&cinfo);
771
0
            return CE_Failure;
772
0
        }
773
23.0k
    }
774
36
    jpeg_finish_decompress(&cinfo);
775
36
    jpeg_destroy_decompress(&cinfo);
776
777
    // Apply the mask
778
36
    if (datasize == 1)
779
36
        apply_mask(sJPEGStruct, reinterpret_cast<char *>(dst.buffer),
780
36
                   img.pagesize.c);
781
0
    else
782
0
        apply_mask(sJPEGStruct, reinterpret_cast<GUInt16 *>(dst.buffer),
783
0
                   img.pagesize.c);
784
785
36
    return CE_None;
786
36
}
Unexecuted instantiation: GDAL_MRF::JPEG_Codec::DecompressJPEG12(GDAL_MRF::buf_mgr&, GDAL_MRF::buf_mgr const&)
787
788
// From here to end it gets compiled only once
789
#if !defined(JPEG12_ON)
790
791
// The Zen chunk signature
792
char CHUNK_NAME[] = "Zen";
793
size_t CHUNK_NAME_SIZE = strlen(CHUNK_NAME) + 1;
794
795
const static GUInt32 JPEG_SIG = 0xe0ffd8ff;  // JPEG 4CC code
796
const static GUInt32 BRUN_SIG = 0xd242040a;  // Brunsli 4CC code, native
797
798
static bool isbrunsli(const buf_mgr &src)
799
495
{
800
495
    GUInt32 signature;
801
495
    memcpy(&signature, src.buffer, sizeof(signature));
802
495
    if (BRUN_SIG == CPL_LSBWORD32(signature))
803
0
        return true;
804
495
    return false;
805
495
}
806
807
bool JPEG_Codec::IsJPEG(const buf_mgr &src)
808
0
{
809
0
    if (isbrunsli(src))
810
0
        return true;
811
0
    GUInt32 signature;
812
0
    memcpy(&signature, src.buffer, sizeof(signature));
813
0
    if (JPEG_SIG == CPL_LSBWORD32(signature))
814
0
        return true;
815
0
    return false;
816
0
}
817
818
#if defined(BRUNSLI)
819
// Append to end of out vector
820
static size_t brunsli_fun_callback(void *out, const GByte *data, size_t size)
821
{
822
    auto outv = static_cast<std::vector<GByte> *>(out);
823
    outv->insert(outv->end(), data, data + size);
824
    return size;
825
}
826
#endif
827
828
// Type dependent dispatchers
829
CPLErr JPEG_Band::Decompress(buf_mgr &dst, buf_mgr &src)
830
495
{
831
495
#if defined(JPEG12_SUPPORTED)
832
495
    if (GDT_UInt8 != img.dt)
833
0
        return codec.DecompressJPEG12(dst, src);
834
495
#endif
835
495
    if (!isbrunsli(src))
836
495
        return codec.DecompressJPEG(dst, src);
837
838
        // Need conversion to JFIF first
839
0
#if !defined(BRUNSLI)
840
0
    CPLError(CE_Failure, CPLE_NotSupported,
841
0
             "MRF: JPEG-XL content, yet this GDAL was not compiled with "
842
0
             "BRUNSLI support");
843
0
    return CE_Failure;
844
#else
845
    std::vector<GByte> out;
846
    // Returns 0 on failure
847
    if (!DecodeBrunsli(src.size, reinterpret_cast<uint8_t *>(src.buffer), &out,
848
                       brunsli_fun_callback))
849
    {
850
        CPLError(CE_Failure, CPLE_AppDefined,
851
                 "MRF: JPEG-XL (brunsli) tile decode failed");
852
        return CE_Failure;
853
    }
854
855
    buf_mgr jfif_src;
856
    jfif_src.buffer = reinterpret_cast<char *>(out.data());
857
    jfif_src.size = out.size();
858
    return Decompress(dst, jfif_src);  // Call itself with JFIF JPEG source
859
#endif  // BRUNSLI
860
495
}
861
862
CPLErr JPEG_Band::Compress(buf_mgr &dst, buf_mgr &src)
863
0
{
864
0
#if defined(JPEG12_SUPPORTED)
865
0
    if (GDT_UInt8 != img.dt)
866
0
        return codec.CompressJPEG12(dst, src);
867
0
#endif
868
0
#if !defined(BRUNSLI)
869
0
    return codec.CompressJPEG(dst, src);
870
#else
871
    auto dst_size = dst.size;          // Save the original size
872
    auto err_code = codec.CompressJPEG(dst, src);
873
    if (codec.JFIF || err_code != CE_None)
874
        return err_code;
875
876
    // The JFIF is in dst buffer
877
    std::vector<GByte> out;
878
    if (!EncodeBrunsli(dst.size, reinterpret_cast<uint8_t *>(dst.buffer), &out,
879
                       brunsli_fun_callback))
880
    {
881
        CPLError(CE_Failure, CPLE_AppDefined,
882
                 "MRF: JPEG-XL (brunsli) tile encode failed");
883
        return CE_Failure;
884
    }
885
    // Copy the brunsli to the dst buffer
886
    if (out.size() > dst_size)
887
    {
888
        CPLError(CE_Failure, CPLE_AppDefined,
889
                 "MRF: JPEG-XL (brunsli) encoded tile too large");
890
        return CE_Failure;
891
    }
892
    memcpy(dst.buffer, out.data(), out.size());
893
    dst.size = out.size();
894
    return CE_None;
895
#endif  // BRUNSLI
896
0
}
897
898
// PHOTOMETRIC == MULTISPECTRAL turns off YCbCr conversion and downsampling
899
JPEG_Band::JPEG_Band(MRFDataset *pDS, const ILImage &image, int b, int level)
900
7.44k
    : MRFRasterBand(pDS, image, b, int(level)), codec(image)
901
7.44k
{
902
7.44k
    const int nbands = image.pagesize.c;
903
    // Check behavior on signed 16bit.  Does the libjpeg sign extend?
904
7.44k
#if defined(JPEG12_SUPPORTED)
905
7.44k
    if (GDT_UInt8 != image.dt && GDT_UInt16 != image.dt)
906
#else
907
    if (GDT_UInt8 != image.dt)
908
#endif
909
0
    {
910
0
        CPLError(CE_Failure, CPLE_NotSupported,
911
0
                 "Data type not supported by MRF JPEG");
912
0
        return;
913
0
    }
914
915
7.44k
    if (nbands == 3)
916
48
    {  // Only the 3 band JPEG has storage flavors
917
48
        CPLString const &pm = pDS->GetPhotometricInterpretation();
918
48
        if (pm == "RGB" || pm == "MULTISPECTRAL")
919
0
        {  // Explicit RGB or MS
920
0
            codec.rgb = TRUE;
921
0
            codec.sameres = TRUE;
922
0
        }
923
48
        if (pm == "YCC")
924
0
            codec.sameres = TRUE;
925
48
    }
926
927
7.44k
    if (GDT_UInt8 == image.dt)
928
7.44k
    {
929
7.44k
        codec.optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE) != FALSE;
930
7.44k
        codec.JFIF = GetOptlist().FetchBoolean("JFIF", FALSE) != FALSE;
931
7.44k
    }
932
0
    else
933
0
    {
934
0
        codec.optimize = true;  // Required for 12bit
935
0
    }
936
    // For high Q, no downsampling and multispectral, output can be larger than the input
937
    // This is just a guess, 20% larger plus some space for the headers and mask
938
    // If too small, the empty_output_buffer() above will be called and an
939
    // error will be generated
940
7.44k
    poMRFDS->SetPBufferSize(int(1.2 * image.pageSizeBytes + 4000));
941
7.44k
}
942
#endif
943
944
NAMESPACE_MRF_END