Line data Source code
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 : #define MRF_JSAMPARRAY JSAMPARRAY
121 : #define MRF_JSAMPIMAGE JSAMPIMAGE
122 : #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 20 : MRFJPEGStruct()
148 20 : {
149 20 : memset(&setjmpBuffer, 0, sizeof(setjmpBuffer));
150 20 : mask = nullptr;
151 20 : mask_state = NO_MASK;
152 20 : }
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 157 : static void emitMessage(j_common_ptr cinfo, int msgLevel)
164 : {
165 157 : if (msgLevel > 0)
166 157 : return; // No trace msgs
167 : // There can be many warnings, just print the first one
168 0 : if (cinfo->err->num_warnings++ > 1)
169 0 : return;
170 : char buffer[JMSG_LENGTH_MAX];
171 0 : cinfo->err->format_message(cinfo, buffer);
172 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s", buffer);
173 : }
174 :
175 0 : static void errorExit(j_common_ptr cinfo)
176 : {
177 0 : MRFJPEGStruct *psJPEGStruct = (MRFJPEGStruct *)cinfo->client_data;
178 : // format the warning message
179 : char buffer[JMSG_LENGTH_MAX];
180 :
181 0 : cinfo->err->format_message(cinfo, buffer);
182 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s", buffer);
183 : // return control to the setjmp point
184 0 : longjmp(psJPEGStruct->setjmpBuffer, 1);
185 : }
186 :
187 : /**
188 : *\brief Do nothing stub function for JPEG library, called
189 : */
190 16 : static void stub_source_dec(j_decompress_ptr /*cinfo*/)
191 : {
192 16 : }
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 0 : static boolean fill_input_buffer_dec(j_decompress_ptr cinfo)
200 : {
201 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid JPEG stream");
202 0 : cinfo->err->msg_code = JERR_INPUT_EMPTY;
203 0 : cinfo->err->error_exit((j_common_ptr)(cinfo));
204 0 : return FALSE;
205 : }
206 :
207 : /**
208 : *\brief: Skips unknown chunks
209 : */
210 0 : static void skip_input_data_dec(j_decompress_ptr cinfo, long l)
211 : {
212 0 : struct jpeg_source_mgr *src = cinfo->src;
213 0 : if (l > 0)
214 : {
215 0 : if (static_cast<size_t>(l) > src->bytes_in_buffer)
216 0 : l = static_cast<long>(src->bytes_in_buffer);
217 0 : src->bytes_in_buffer -= l;
218 0 : src->next_input_byte += l;
219 : }
220 0 : }
221 :
222 : // Destination should be already set up
223 24 : static void init_or_terminate_destination(j_compress_ptr /*cinfo*/)
224 : {
225 24 : }
226 :
227 : // Called if the buffer provided is too small
228 0 : static boolean empty_output_buffer(j_compress_ptr /*cinfo*/)
229 : {
230 0 : std::cerr << "JPEG Output buffer empty called\n";
231 0 : return FALSE;
232 : }
233 :
234 : // Returns the number of zero pixels in the page, as well as clearing those bits
235 : // in the mask
236 12 : template <typename T> static int update_mask(BitMask &mask, T *src, int nc)
237 : {
238 12 : int zeros = 0;
239 12 : int h = mask.getHeight();
240 12 : int w = mask.getWidth();
241 6156 : for (int y = 0; y < h; y++)
242 3151876 : for (int x = 0; x < w; x++)
243 : {
244 3145724 : bool is_zero = true;
245 8388608 : for (int c = 0; c < nc; c++)
246 5242884 : if (*src++ != 0)
247 1210910 : is_zero = false;
248 3145724 : if (is_zero)
249 : {
250 2340864 : zeros++;
251 2340864 : mask.clear(x, y);
252 : }
253 : }
254 12 : return zeros;
255 : }
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 1 : CPLErr JPEG_Codec::CompressJPEG12(buf_mgr &dst, buf_mgr &src)
266 : #else
267 11 : CPLErr JPEG_Codec::CompressJPEG(buf_mgr &dst, buf_mgr &src)
268 : #endif
269 :
270 : {
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 : struct jpeg_compress_struct cinfo;
274 12 : MRFJPEGStruct sJPEGStruct;
275 : struct jpeg_error_mgr sJErr;
276 12 : ILSize sz = img.pagesize;
277 :
278 : jpeg_destination_mgr jmgr;
279 12 : jmgr.next_output_byte = (JOCTET *)dst.buffer;
280 12 : jmgr.free_in_buffer = dst.size;
281 12 : jmgr.init_destination = init_or_terminate_destination;
282 12 : jmgr.empty_output_buffer = empty_output_buffer;
283 12 : jmgr.term_destination = init_or_terminate_destination;
284 :
285 12 : memset(&cinfo, 0, sizeof(cinfo));
286 :
287 : // Look at the source of this, some interesting tidbits
288 12 : cinfo.err = jpeg_std_error(&sJErr);
289 12 : sJErr.error_exit = errorExit;
290 12 : sJErr.emit_message = emitMessage;
291 12 : cinfo.client_data = (void *)&(sJPEGStruct);
292 12 : jpeg_create_compress(&cinfo);
293 12 : cinfo.dest = &jmgr;
294 :
295 : // The page specific info, size and color spaces
296 12 : cinfo.image_width = sz.x;
297 12 : cinfo.image_height = sz.y;
298 12 : cinfo.input_components = sz.c;
299 12 : switch (cinfo.input_components)
300 : {
301 8 : case 1:
302 8 : cinfo.in_color_space = JCS_GRAYSCALE;
303 8 : break;
304 4 : case 3:
305 4 : cinfo.in_color_space = JCS_RGB;
306 4 : 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 : }
310 :
311 : #if defined(JPEG12_ON)
312 1 : cinfo.data_precision = 12;
313 : #else
314 11 : cinfo.data_precision = 8;
315 : #endif
316 :
317 : // Set all required fields and overwrite the ones we want to change
318 12 : jpeg_set_defaults(&cinfo);
319 :
320 : // Override certain settings
321 12 : jpeg_set_quality(&cinfo, img.quality, TRUE);
322 12 : cinfo.dct_method = JDCT_FLOAT; // Pretty fast and precise
323 12 : cinfo.optimize_coding =
324 12 : optimize; // Set "OPTIMIZE=TRUE" in OPTIONS, default for 12bit
325 :
326 : // Do we explicitly turn off the YCC color and downsampling?
327 :
328 12 : if (cinfo.in_color_space == JCS_RGB)
329 : {
330 4 : if (rgb)
331 : { // Stored as RGB
332 1 : jpeg_set_colorspace(&cinfo, JCS_RGB); // Huge files
333 : }
334 3 : else if (sameres)
335 : { // YCC, somewhat larger files with improved color spatial detail
336 1 : cinfo.comp_info[0].h_samp_factor = 1;
337 1 : 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 : }
350 : }
351 :
352 24 : int linesize = cinfo.image_width * cinfo.input_components *
353 12 : ((cinfo.data_precision == 8) ? 1 : 2);
354 12 : MRF_JSAMPROW *rowp = (MRF_JSAMPROW *)CPLMalloc(sizeof(MRF_JSAMPROW) * sz.y);
355 12 : if (!rowp)
356 : {
357 0 : CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG compression error");
358 0 : jpeg_destroy_compress(&cinfo);
359 0 : return CE_Failure;
360 : }
361 :
362 6156 : for (int i = 0; i < sz.y; i++)
363 : {
364 6144 : rowp[i] = (MRF_JSAMPROW)(src.buffer + i * linesize);
365 : #if defined(JPEG12_ON)
366 262656 : for (int x = 0; x < sz.x; ++x)
367 : {
368 262144 : if (static_cast<unsigned short>(rowp[i][x]) > 4095)
369 : {
370 0 : rowp[i][x] = (MRF_JSAMPLE)4095;
371 : static bool bClipWarn = false;
372 0 : if (!bClipWarn)
373 : {
374 0 : bClipWarn = true;
375 0 : CPLError(CE_Warning, CPLE_AppDefined,
376 : "One or more pixels clipped to fit 12bit domain "
377 : "for jpeg output.");
378 : }
379 : }
380 : }
381 : #endif
382 : }
383 :
384 12 : if (setjmp(sJPEGStruct.setjmpBuffer))
385 : {
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 : }
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 24 : BitMask mask(sz.x, sz.y);
398 12 : storage_manager mbuffer = {CHUNK_NAME, CHUNK_NAME_SIZE};
399 :
400 : int nzeros =
401 12 : (cinfo.data_precision == 8)
402 12 : ? update_mask(mask, reinterpret_cast<GByte *>(src.buffer), sz.c)
403 1 : : update_mask(mask, reinterpret_cast<GUInt16 *>(src.buffer), sz.c);
404 :
405 : // In case we need to build a Zen chunk
406 12 : char *buffer = nullptr;
407 :
408 12 : if (nzeros != 0)
409 : { // build the Zen chunk
410 12 : mbuffer.size = 2 * mask.size() + CHUNK_NAME_SIZE;
411 12 : buffer = reinterpret_cast<char *>(CPLMalloc(mbuffer.size));
412 12 : if (!buffer)
413 : {
414 0 : jpeg_destroy_compress(&cinfo);
415 0 : CPLFree(rowp);
416 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
417 : "MRF: JPEG Zen mask compression");
418 0 : return CE_Failure;
419 : }
420 :
421 12 : memcpy(buffer, CHUNK_NAME, CHUNK_NAME_SIZE);
422 12 : mbuffer.buffer = buffer + CHUNK_NAME_SIZE;
423 12 : mbuffer.size -= CHUNK_NAME_SIZE;
424 :
425 0 : RLEC3Packer c3;
426 12 : mask.set_packer(&c3);
427 12 : if (!mask.store(&mbuffer))
428 : {
429 0 : CPLError(CE_Failure, CPLE_AppDefined,
430 : "MRF: JPEG Zen mask compression");
431 0 : CPLFree(rowp);
432 0 : CPLFree(buffer);
433 0 : return CE_Failure;
434 : }
435 :
436 : // Change the buffer pointer to include the signature, on output the
437 : // size is the compressed size
438 12 : mbuffer.buffer = buffer;
439 12 : mbuffer.size += CHUNK_NAME_SIZE;
440 :
441 : // Check that the size fits in one JPEG chunk
442 12 : if (mbuffer.size + 2 + CHUNK_NAME_SIZE > 65535)
443 : {
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 : "MRF: JPEG Zen mask too large");
448 0 : mbuffer.size = CHUNK_NAME_SIZE; // Write just the signature
449 : }
450 : }
451 :
452 : // Everything is ready
453 12 : jpeg_start_compress(&cinfo, TRUE);
454 :
455 : // Always write the Zen app chunk, App3
456 12 : jpeg_write_marker(&cinfo, JPEG_APP0 + 3,
457 12 : reinterpret_cast<JOCTET *>(mbuffer.buffer),
458 12 : 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 12 : jpeg_write_scanlines(&cinfo, rowp, sz.y);
464 : #endif
465 12 : jpeg_finish_compress(&cinfo);
466 12 : jpeg_destroy_compress(&cinfo);
467 :
468 12 : CPLFree(rowp);
469 12 : CPLFree(buffer); // Safe to call on null
470 :
471 : // Figure out the size of the JFIF
472 12 : dst.size -= jmgr.free_in_buffer;
473 12 : return CE_None;
474 : }
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 3584 : static void ProgressMonitor(j_common_ptr cinfo)
486 : {
487 3584 : if (cinfo->is_decompressor)
488 : {
489 3584 : const int scan_no =
490 : reinterpret_cast<j_decompress_ptr>(cinfo)->input_scan_number;
491 3584 : const int MAX_SCANS = 100;
492 3584 : if (scan_no >= MAX_SCANS)
493 : {
494 0 : CPLError(CE_Failure, CPLE_AppDefined,
495 : "Scan number %d exceeds maximum scans (%d)", scan_no,
496 : MAX_SCANS);
497 :
498 0 : MRFJPEGStruct *psJPEGStruct = (MRFJPEGStruct *)cinfo->client_data;
499 :
500 : // return control to the setjmp point
501 0 : longjmp(psJPEGStruct->setjmpBuffer, 1);
502 : }
503 : }
504 3584 : }
505 :
506 : // Returns the number of zero pixels, as well as clearing those bits int the
507 : // mask
508 8 : template <typename T> static void apply_mask(MRFJPEGStruct &sJ, T *s, int nc)
509 : {
510 8 : if (NO_MASK == sJ.mask_state)
511 0 : return;
512 :
513 8 : BitMask *mask = sJ.mask;
514 8 : int w = mask->getWidth();
515 8 : int h = mask->getHeight();
516 :
517 8 : if (MASK_LOADED == sJ.mask_state)
518 : { // Partial map
519 4104 : for (int y = 0; y < h; y++)
520 2101246 : for (int x = 0; x < w; x++)
521 : {
522 2097154 : if (mask->isSet(x, y))
523 : { // Non zero pixel
524 1218830 : for (int c = 0; c < nc; c++, s++)
525 : {
526 812929 : if (*s == 0)
527 21654 : *s = 1;
528 : }
529 : }
530 : else
531 : { // Zero pixel
532 5072618 : for (int c = 0; c < nc; c++)
533 3381374 : *s++ = 0;
534 : }
535 : }
536 : }
537 0 : else if (MASK_FULL == sJ.mask_state)
538 : { // All non-zero
539 0 : for (int y = 0; y < h; y++)
540 0 : for (int x = 0; x < w; x++)
541 : {
542 0 : for (int c = 0; c < nc; c++, s++)
543 : {
544 0 : if (*s == 0)
545 0 : *s = 1;
546 : }
547 : }
548 : }
549 : }
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 8 : static boolean MaskProcessor(j_decompress_ptr pcinfo)
554 : {
555 8 : struct jpeg_source_mgr *src = pcinfo->src;
556 8 : if (src->bytes_in_buffer < 2)
557 0 : ERREXIT(pcinfo, JERR_CANT_SUSPEND);
558 : // Big endian length, two bytes
559 8 : int len = (*src->next_input_byte++) << 8;
560 8 : len += *src->next_input_byte++;
561 : // The length includes the two bytes we just read
562 8 : src->bytes_in_buffer -= 2;
563 8 : len -= 2;
564 : // Check that it is safe to read the rest
565 8 : if (src->bytes_in_buffer < static_cast<size_t>(len))
566 0 : ERREXIT(pcinfo, JERR_CANT_SUSPEND);
567 8 : MRFJPEGStruct *psJPEG =
568 : reinterpret_cast<MRFJPEGStruct *>(pcinfo->client_data);
569 8 : BitMask *mask = psJPEG->mask;
570 : // caller doesn't want a mask or wrong chunk, skip the chunk and return
571 8 : if (!mask || static_cast<size_t>(len) < CHUNK_NAME_SIZE ||
572 8 : !EQUALN(reinterpret_cast<const char *>(src->next_input_byte),
573 : CHUNK_NAME, CHUNK_NAME_SIZE))
574 : {
575 0 : src->bytes_in_buffer -= len;
576 0 : src->next_input_byte += len;
577 0 : return true;
578 : }
579 :
580 : // Skip the signature and load the mask
581 8 : src->bytes_in_buffer -= CHUNK_NAME_SIZE;
582 8 : src->next_input_byte += CHUNK_NAME_SIZE;
583 8 : len -= static_cast<int>(CHUNK_NAME_SIZE);
584 8 : if (len == 0)
585 : { // No mask content means mask is all full, just return
586 0 : psJPEG->mask_state = MASK_FULL;
587 0 : return true;
588 : }
589 :
590 : // It is OK to use const cast, the mask doesn't touch the buffer
591 : storage_manager msrc = {const_cast<char *>(reinterpret_cast<const char *>(
592 8 : src->next_input_byte)),
593 8 : static_cast<size_t>(len)};
594 :
595 8 : if (!mask->load(&msrc))
596 : { // Fatal error return, mask is not valid
597 0 : ERREXIT(pcinfo, JERR_CANT_SUSPEND);
598 : }
599 :
600 8 : src->bytes_in_buffer -= len;
601 8 : src->next_input_byte += len;
602 8 : psJPEG->mask_state = MASK_LOADED;
603 8 : return true;
604 : }
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 1 : CPLErr JPEG_Codec::DecompressJPEG12(buf_mgr &dst, const buf_mgr &isrc)
615 : #else
616 7 : CPLErr JPEG_Codec::DecompressJPEG(buf_mgr &dst, const buf_mgr &isrc)
617 : #endif
618 :
619 : {
620 8 : int nbands = img.pagesize.c;
621 : // Locals, clean up after themselves
622 : jpeg_decompress_struct cinfo;
623 8 : MRFJPEGStruct sJPEGStruct;
624 : struct jpeg_error_mgr sJErr;
625 16 : BitMask mask(img.pagesize.x, img.pagesize.y);
626 8 : RLEC3Packer packer;
627 8 : mask.set_packer(&packer);
628 :
629 8 : memset(&cinfo, 0, sizeof(cinfo));
630 : // Pass the mask address to the decompressor
631 8 : sJPEGStruct.mask = &mask;
632 :
633 : struct jpeg_source_mgr src;
634 :
635 8 : cinfo.err = jpeg_std_error(&sJErr);
636 8 : sJErr.error_exit = errorExit;
637 8 : sJErr.emit_message = emitMessage;
638 8 : cinfo.client_data = &sJPEGStruct;
639 :
640 8 : src.next_input_byte = reinterpret_cast<JOCTET *>(isrc.buffer);
641 8 : src.bytes_in_buffer = isrc.size;
642 8 : src.term_source = stub_source_dec;
643 8 : src.init_source = stub_source_dec;
644 8 : src.skip_input_data = skip_input_data_dec;
645 8 : src.fill_input_buffer = fill_input_buffer_dec;
646 8 : src.resync_to_restart = jpeg_resync_to_restart;
647 :
648 8 : jpeg_create_decompress(&cinfo);
649 :
650 8 : if (setjmp(sJPEGStruct.setjmpBuffer))
651 : {
652 0 : CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error reading JPEG page");
653 0 : jpeg_destroy_decompress(&cinfo);
654 0 : return CE_Failure;
655 : }
656 :
657 8 : cinfo.src = &src;
658 8 : jpeg_set_marker_processor(&cinfo, JPEG_APP0 + 3, MaskProcessor);
659 8 : 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 8 : if (jpeg_has_multiple_scans(&(cinfo)))
665 : {
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 0 : vsi_l_offset nRequiredMemory =
671 0 : static_cast<vsi_l_offset>(cinfo.image_width) * cinfo.image_height *
672 0 : 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 0 : if (cinfo.progressive_mode)
676 0 : nRequiredMemory *= 3;
677 :
678 : #ifndef GDAL_LIBJPEG_LARGEST_MEM_ALLOC
679 : #define GDAL_LIBJPEG_LARGEST_MEM_ALLOC (100 * 1024 * 1024)
680 : #endif
681 :
682 0 : if (nRequiredMemory > GDAL_LIBJPEG_LARGEST_MEM_ALLOC &&
683 0 : CPLGetConfigOption("GDAL_ALLOW_LARGE_LIBJPEG_MEM_ALLOC", nullptr) ==
684 : nullptr)
685 : {
686 0 : CPLError(CE_Failure, CPLE_NotSupported,
687 : "Reading this image would require libjpeg to allocate "
688 : "at least " CPL_FRMT_GUIB " bytes. "
689 : "This is disabled since above the " CPL_FRMT_GUIB
690 : " threshold. "
691 : "You may override this restriction by defining the "
692 : "GDAL_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, "
693 : "or recompile GDAL by defining the "
694 : "GDAL_LIBJPEG_LARGEST_MEM_ALLOC macro to a value greater "
695 : "than " CPL_FRMT_GUIB,
696 : static_cast<GUIntBig>(nRequiredMemory),
697 : static_cast<GUIntBig>(GDAL_LIBJPEG_LARGEST_MEM_ALLOC),
698 : static_cast<GUIntBig>(GDAL_LIBJPEG_LARGEST_MEM_ALLOC));
699 0 : jpeg_destroy_decompress(&cinfo);
700 0 : return CE_Failure;
701 : }
702 : }
703 :
704 : // Use float, it is actually faster than the ISLOW method by a tiny bit
705 8 : 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 8 : if (nbands == 3 && cinfo.num_components != nbands)
714 0 : cinfo.out_color_space = JCS_RGB;
715 8 : if (nbands == 1 && cinfo.num_components != nbands)
716 0 : cinfo.out_color_space = JCS_GRAYSCALE;
717 :
718 8 : const int datasize = ((cinfo.data_precision == 8) ? 1 : 2);
719 8 : if (cinfo.image_width >
720 8 : static_cast<unsigned>(INT_MAX / (nbands * datasize)))
721 : {
722 0 : CPLError(CE_Failure, CPLE_AppDefined,
723 : "MRF: JPEG decompress buffer overflow");
724 0 : jpeg_destroy_decompress(&cinfo);
725 0 : return CE_Failure;
726 : }
727 8 : 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 8 : if (linesize > static_cast<int>(INT_MAX / cinfo.image_height))
732 : {
733 0 : CPLError(CE_Failure, CPLE_AppDefined,
734 : "MRF: JPEG decompress buffer overflow");
735 0 : jpeg_destroy_decompress(&cinfo);
736 0 : return CE_Failure;
737 : }
738 8 : if (static_cast<size_t>(linesize) * cinfo.image_height != dst.size)
739 : {
740 0 : CPLError(CE_Warning, CPLE_AppDefined, "MRF: read JPEG size is wrong");
741 0 : if (static_cast<size_t>(linesize) * cinfo.image_height > dst.size)
742 : {
743 0 : CPLError(CE_Failure, CPLE_AppDefined,
744 : "MRF: JPEG decompress buffer overflow");
745 0 : jpeg_destroy_decompress(&cinfo);
746 0 : return CE_Failure;
747 : }
748 : }
749 :
750 : struct jpeg_progress_mgr sJProgress;
751 8 : sJProgress.progress_monitor = ProgressMonitor;
752 8 : cinfo.progress = &sJProgress;
753 :
754 8 : jpeg_start_decompress(&cinfo);
755 :
756 : // Decompress, two lines at a time is what libjpeg does
757 3592 : while (cinfo.output_scanline < cinfo.image_height)
758 : {
759 : char *rp[2];
760 3584 : rp[0] = (char *)dst.buffer + linesize * cinfo.output_scanline;
761 3584 : 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 3584 : if (jpeg_read_scanlines(&cinfo, MRF_JSAMPARRAY(rp), 2) == 0)
768 : #endif
769 : {
770 0 : jpeg_destroy_decompress(&cinfo);
771 0 : return CE_Failure;
772 : }
773 : }
774 8 : jpeg_finish_decompress(&cinfo);
775 8 : jpeg_destroy_decompress(&cinfo);
776 :
777 : // Apply the mask
778 8 : if (datasize == 1)
779 7 : apply_mask(sJPEGStruct, reinterpret_cast<char *>(dst.buffer),
780 7 : img.pagesize.c);
781 : else
782 1 : apply_mask(sJPEGStruct, reinterpret_cast<GUInt16 *>(dst.buffer),
783 1 : img.pagesize.c);
784 :
785 8 : return CE_None;
786 : }
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 7 : static bool isbrunsli(const buf_mgr &src)
799 : {
800 : GUInt32 signature;
801 7 : memcpy(&signature, src.buffer, sizeof(signature));
802 7 : if (BRUN_SIG == CPL_LSBWORD32(signature))
803 0 : return true;
804 7 : return false;
805 : }
806 :
807 0 : bool JPEG_Codec::IsJPEG(const buf_mgr &src)
808 : {
809 0 : if (isbrunsli(src))
810 0 : return true;
811 : 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 : }
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 dispachers
829 8 : CPLErr JPEG_Band::Decompress(buf_mgr &dst, buf_mgr &src)
830 : {
831 : #if defined(JPEG12_SUPPORTED)
832 8 : if (GDT_Byte != img.dt)
833 1 : return codec.DecompressJPEG12(dst, src);
834 : #endif
835 7 : if (!isbrunsli(src))
836 7 : return codec.DecompressJPEG(dst, src);
837 :
838 : // Need conversion to JFIF first
839 : #if !defined(BRUNSLI)
840 0 : CPLError(CE_Failure, CPLE_NotSupported,
841 : "MRF: JPEG-XL content, yet this GDAL was not compiled with "
842 : "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 : }
861 :
862 12 : CPLErr JPEG_Band::Compress(buf_mgr &dst, buf_mgr &src)
863 : {
864 : #if defined(JPEG12_SUPPORTED)
865 12 : if (GDT_Byte != img.dt)
866 1 : return codec.CompressJPEG12(dst, src);
867 : #endif
868 : #if !defined(BRUNSLI)
869 11 : 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 : }
897 :
898 : // PHOTOMETRIC == MULTISPECTRAL turns off YCbCr conversion and downsampling
899 49 : JPEG_Band::JPEG_Band(MRFDataset *pDS, const ILImage &image, int b, int level)
900 49 : : MRFRasterBand(pDS, image, b, int(level)), codec(image)
901 : {
902 49 : const int nbands = image.pagesize.c;
903 : // Check behavior on signed 16bit. Does the libjpeg sign extend?
904 : #if defined(JPEG12_SUPPORTED)
905 49 : if (GDT_Byte != image.dt && GDT_UInt16 != image.dt)
906 : #else
907 : if (GDT_Byte != image.dt)
908 : #endif
909 : {
910 0 : CPLError(CE_Failure, CPLE_NotSupported,
911 : "Data type not supported by MRF JPEG");
912 0 : return;
913 : }
914 :
915 49 : if (nbands == 3)
916 : { // Only the 3 band JPEG has storage flavors
917 30 : CPLString const &pm = pDS->GetPhotometricInterpretation();
918 30 : if (pm == "RGB" || pm == "MULTISPECTRAL")
919 : { // Explicit RGB or MS
920 9 : codec.rgb = TRUE;
921 9 : codec.sameres = TRUE;
922 : }
923 30 : if (pm == "YCC")
924 6 : codec.sameres = TRUE;
925 : }
926 :
927 49 : if (GDT_Byte == image.dt)
928 : {
929 47 : codec.optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE) != FALSE;
930 47 : codec.JFIF = GetOptlist().FetchBoolean("JFIF", FALSE) != FALSE;
931 : }
932 : else
933 : {
934 2 : codec.optimize = true; // Required for 12bit
935 : }
936 : }
937 : #endif
938 :
939 : NAMESPACE_MRF_END
|