comparison mupdf-source/thirdparty/leptonica/src/jp2kio.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
27 /*!
28 * \file jp2kio.c
29 * <pre>
30 *
31 * Read jp2k from file
32 * PIX *pixReadJp2k() [special top level]
33 * PIX *pixReadStreamJp2k()
34 * static PIX *pixReadMemJp2kCore()
35 *
36 * Write jp2k to file
37 * l_int32 pixWriteJp2k() [special top level]
38 * l_int32 pixWriteStreamJp2k()
39 * static opj_image_t *pixConvertToOpjImage()
40 *
41 * Read/write to memory
42 * PIX *pixReadMemJp2k()
43 * l_int32 pixWriteMemJp2k()
44 *
45 * Static generator of opj_stream from a memory buffer
46 * static opj_stream_t *opjCreateMemoryStream()
47 * [and other static helpers]
48 *
49 * Static generator of opj_stream fom a file stream
50 * static opj_stream_t *opjCreateStream()
51 * [and other static helpers]
52 *
53 * Based on the OpenJPEG distribution:
54 * http://www.openjpeg.org/
55 * The ISO/IEC reference for jpeg2000 is:
56 * http://www.jpeg.org/public/15444-1annexi.pdf
57 *
58 * Compressing to memory and decompressing from memory
59 * ---------------------------------------------------
60 * In previous versions, for systems like Windows that do not have
61 * fmemopen() and open_memstream(), we wrote data to a temp file.
62 * Now thanks to the contribution of Anton Tykhyy, we use the
63 * opj_stream interface directly for operations to and from memory.
64 * The file stream interface for these operations is a wrapper
65 * around the memory interface.
66 *
67 * Pdf can accept jp2k compressed strings directly
68 * -----------------------------------------------
69 * Transcoding (with the uncompress/compress cycle) is not required
70 * to wrap images that have already been compressed with jp2k in pdf,
71 * because the pdf format for jp2k includes the full string of the
72 * jp2k compressed images. This is also true for jpeg compressed
73 * strings.
74 *
75 * N.B.
76 * * Reading and writing jp2k are supported here for releases 2.1 and later.
77 * * The openjpeg.h file is installed in an openjpeg-2.X subdirectory.
78 * * In openjpeg-2.X, reading is slow compared to jpeg or webp,
79 * and writing is very slow compared to jpeg or webp.
80 * * Specifying a quality factor for jpeg2000 requires caution. Unlike
81 * jpeg and webp, which have a sensible scale that goes from 0 (very poor)
82 * to 100 (nearly lossless), kakadu and openjpeg use idiosyncratic and
83 * non-intuitive numbers. kakadu uses "rate/distortion" numbers in
84 * a narrow range around 50,000; openjpeg (and our write interface)
85 * use SNR. The visually apparent artifacts introduced by compression
86 * are strongly content-dependent and vary in a highly non-linear
87 * way with SNR. We take SNR = 34 as default, roughly similar in
88 * quality to jpeg's default standard of 75. For document images,
89 * SNR = 25 is very poor, whereas SNR = 45 is nearly lossless. If you
90 * use the latter, you will pay dearly in the size of the compressed file.
91 * * The openjpeg interface was massively changed from 1.X to 2.0.
92 * There were also changes from 2.0 to 2.1. From 2.0 to 2.1, the
93 * ability to interface to a C file stream was removed permanently.
94 * Leptonica supports both file stream and memory buffer interfaces
95 * for every image I/O library, and it requires the libraries to
96 * support at least one of these. However, because openjpeg-2.1+ provides
97 * neither, we have brought several static functions over from
98 * openjpeg-2.0 in order to retain the file stream interface.
99 * See, for example, our static function opjCreateStream().
100 * </pre>
101 */
102
103 #ifdef HAVE_CONFIG_H
104 #include <config_auto.h>
105 #endif /* HAVE_CONFIG_H */
106
107 #include <string.h>
108 #include "allheaders.h"
109
110 /* --------------------------------------------*/
111 #if HAVE_LIBJP2K /* defined in environ.h */
112 /* --------------------------------------------*/
113
114 /* Leptonica supports versions 2.1 and later */
115 #ifdef LIBJP2K_HEADER
116 #include LIBJP2K_HEADER
117 #else
118 #include <openjpeg.h>
119 #endif
120
121 /*! For in-memory encoding and decoding of JP2K */
122 typedef struct OpjBuffer
123 {
124 l_uint8 *data; /*!< data in the buffer */
125 size_t size; /*!< size of buffer */
126 size_t pos; /*!< position relative to beginning of buffer */
127 size_t len; /*!< length of valid data in the buffer */
128 } OpjBuffer;
129
130 /* Static converter pix --> opj_image. Used for compressing pix,
131 * because the codec works on data stored in their raster format. */
132 static opj_image_t *pixConvertToOpjImage(PIX *pix);
133
134 /* Static generator of opj_stream from a memory buffer. */
135 static opj_stream_t *opjCreateMemoryStream(OpjBuffer *buf, l_int32 is_read);
136
137 /* Static generator of opj_stream from file stream.
138 * In 2.0.1, this functionality is provided by
139 * opj_stream_create_default_file_stream(),
140 * but it was removed in 2.1.0. Because we must have either
141 * a file stream or a memory interface to the compressed data,
142 * it is necessary to recreate the stream interface here. */
143 static opj_stream_t *opjCreateStream(FILE *fp, l_int32 is_read);
144
145
146 /*---------------------------------------------------------------------*
147 * Callback event handlers *
148 *---------------------------------------------------------------------*/
149 static void error_callback(const char *msg, void *client_data) {
150 (void)client_data;
151 fprintf(stdout, "[ERROR] %s", msg);
152 }
153
154 static void warning_callback(const char *msg, void *client_data) {
155 (void)client_data;
156 fprintf(stdout, "[WARNING] %s", msg);
157 }
158
159 static void info_callback(const char *msg, void *client_data) {
160 (void)client_data;
161 fprintf(stdout, "[INFO] %s", msg);
162 }
163
164
165 /*---------------------------------------------------------------------*
166 * Read jp2k from file (special function) *
167 *---------------------------------------------------------------------*/
168 /*!
169 * \brief pixReadJp2k()
170 *
171 * \param[in] filename
172 * \param[in] reduction scaling factor: 1, 2, 4, 8, 16
173 * \param[in] box [optional] for extracting a subregion, can be null
174 * \param[in] hint a bitwise OR of L_JP2K_* values; 0 for default
175 * \param[in] debug output callback messages, etc
176 * \return pix 8 or 32 bpp, or NULL on error
177 *
178 * <pre>
179 * Notes:
180 * (1) This is a special function for reading jp2k files.
181 * The high-level pixReadStream() uses default values:
182 * %reduction = 1
183 * %box = NULL
184 * (2) This decodes at either full resolution or at a reduction by
185 * a power of 2. The default value %reduction == 1 gives a full
186 * resolution image. Use %reduction > 1 to get a reduced image.
187 * The actual values of %reduction that can be used on an image
188 * depend on the number of resolution levels chosen when the
189 * image was compressed. We typically encode using six power-of-2
190 * resolution values: 1, 2, 4, 8, 16 and 32. Attempting to read
191 * with a value representing a reduction level that was not
192 * stored when the file was written will fail with the message:
193 * "failed to read the header".
194 * (3) Use %box to decode only a part of the image. The box is defined
195 * at full resolution. It is reduced internally by %reduction,
196 * and clipping to the right and bottom of the image is automatic.
197 * (4) We presently only handle images with 8 bits/sample (bps).
198 * If the image has 16 bps, the read will fail.
199 * (5) There are 4 possible values of samples/pixel (spp).
200 * The values in brackets give the pixel values in the Pix:
201 * spp = 1 ==> grayscale [8 bpp grayscale]
202 * spp = 2 ==> grayscale + alpha [32 bpp rgba]
203 * spp = 3 ==> rgb [32 bpp rgb]
204 * spp = 4 ==> rgba [32 bpp rgba]
205 * (6) The %hint parameter is reserved for future use.
206 * </pre>
207 */
208 PIX *
209 pixReadJp2k(const char *filename,
210 l_uint32 reduction,
211 BOX *box,
212 l_int32 hint,
213 l_int32 debug)
214 {
215 FILE *fp;
216 PIX *pix;
217
218 if (!filename)
219 return (PIX *)ERROR_PTR("filename not defined", __func__, NULL);
220
221 if ((fp = fopenReadStream(filename)) == NULL)
222 return (PIX *)ERROR_PTR_1("image file not found",
223 filename, __func__, NULL);
224 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
225 fclose(fp);
226
227 if (!pix)
228 return (PIX *)ERROR_PTR_1("image not returned",
229 filename, __func__, NULL);
230 return pix;
231 }
232
233
234 /*!
235 * \brief pixReadStreamJp2k()
236 *
237 * \param[in] fp file stream
238 * \param[in] reduction scaling factor: 1, 2, 4, 8
239 * \param[in] box [optional] for extracting a subregion, can be null
240 * \param[in] hint a bitwise OR of L_JP2K_* values; 0 for default
241 * \param[in] debug output callback messages, etc
242 * \return pix 8 or 32 bpp, or NULL on error
243 *
244 * <pre>
245 * Notes:
246 * (1) See pixReadJp2k() for usage.
247 * </pre>
248 */
249 PIX *
250 pixReadStreamJp2k(FILE *fp,
251 l_uint32 reduction,
252 BOX *box,
253 l_int32 hint,
254 l_int32 debug)
255 {
256 l_uint8 *data;
257 size_t size;
258 PIX *pix;
259
260 if (!fp)
261 return (PIX *)ERROR_PTR("fp not defined", __func__, NULL);
262
263 /* fgetJp2kResolution() would read the whole stream anyway,
264 * so we might as well start off by doing that */
265 rewind(fp);
266 if ((data = l_binaryReadStream(fp, &size)) == NULL)
267 return (PIX *)ERROR_PTR("data not read", __func__, NULL);
268
269 pix = pixReadMemJp2k(data, size, reduction, box, hint, debug);
270
271 LEPT_FREE(data);
272 return pix;
273 }
274
275
276 static PIX *
277 pixReadMemJp2kCore(const l_uint8 *bytes,
278 size_t nbytes,
279 l_uint32 reduction,
280 BOX *box,
281 l_int32 hint,
282 l_int32 debug)
283 {
284 const char *opjVersion;
285 l_int32 i, j, index, bx, by, bw, bh, val, rval, gval, bval, aval;
286 l_int32 w, h, wpl, bps, spp, xres, yres, reduce, prec, colorspace;
287 l_int32 codec; /* L_J2K_CODEC or L_JP2_CODEC */
288 l_uint32 pixel;
289 l_uint32 *data, *line;
290 opj_dparameters_t parameters; /* decompression parameters */
291 opj_image_t *image = NULL;
292 opj_codec_t *l_codec = NULL; /* handle to decompressor */
293 opj_stream_t *l_stream = NULL; /* opj stream */
294 PIX *pix = NULL;
295 OpjBuffer buffer;
296
297 opjVersion = opj_version();
298 if (!opjVersion || opjVersion[0] == '\0')
299 return (PIX *)ERROR_PTR("opj version not defined", __func__, NULL);
300 if (opjVersion[0] - 0x30 < 2 ||
301 (opjVersion[0] == '2' && opjVersion[2] - 0x30 == 0)) {
302 L_ERROR("version is %s; must be 2.1 or higher\n", __func__, opjVersion);
303 return NULL;
304 }
305
306 /* Get the resolution, bits/sample and codec type */
307 readResolutionMemJp2k(bytes, nbytes, &xres, &yres);
308 readHeaderMemJp2k(bytes, nbytes, NULL, NULL, &bps, NULL, &codec);
309 if (codec != L_J2K_CODEC && codec != L_JP2_CODEC) {
310 L_ERROR("valid codec not identified\n", __func__);
311 return NULL;
312 }
313
314 if (bps != 8) {
315 L_ERROR("found %d bps; can only handle 8 bps\n", __func__, bps);
316 return NULL;
317 }
318
319 /* Set decoding parameters to default values */
320 opj_set_default_decoder_parameters(&parameters);
321
322 /* Find and set the reduce parameter, which is log2(reduction).
323 * Valid reductions are powers of 2, and are determined when the
324 * compressed string is made. A request for an invalid reduction
325 * will cause an error in opj_read_header(), and no image will
326 * be returned. */
327 for (reduce = 0; (1L << reduce) < reduction; reduce++) { }
328 if ((1L << reduce) != reduction) {
329 L_ERROR("invalid reduction %d; not power of 2\n", __func__, reduction);
330 return NULL;
331 }
332 parameters.cp_reduce = reduce;
333
334 /* Get a decoder handle */
335 if (codec == L_JP2_CODEC)
336 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
337 else if (codec == L_J2K_CODEC)
338 l_codec = opj_create_decompress(OPJ_CODEC_J2K);
339 if (!l_codec) {
340 L_ERROR("failed to make the codec\n", __func__);
341 return NULL;
342 }
343
344 /* Catch and report events using callbacks */
345 if (debug) {
346 opj_set_info_handler(l_codec, info_callback, NULL);
347 opj_set_warning_handler(l_codec, warning_callback, NULL);
348 opj_set_error_handler(l_codec, error_callback, NULL);
349 }
350
351 /* Setup the decoding parameters using user parameters */
352 if (!opj_setup_decoder(l_codec, &parameters)){
353 L_ERROR("failed to set up decoder\n", __func__);
354 opj_destroy_codec(l_codec);
355 return NULL;
356 }
357
358 /* Open decompression 'stream'. */
359 buffer.data = (l_uint8 *)bytes;
360 buffer.size = nbytes;
361 buffer.len = nbytes;
362 buffer.pos = 0;
363 if ((l_stream = opjCreateMemoryStream(&buffer, 1)) == NULL) {
364 L_ERROR("failed to open the stream\n", __func__);
365 opj_destroy_codec(l_codec);
366 return NULL;
367 }
368
369 /* Read the main header of the codestream and, if necessary,
370 * the JP2 boxes */
371 if(!opj_read_header(l_stream, l_codec, &image)){
372 L_ERROR("failed to read the header\n", __func__);
373 opj_stream_destroy(l_stream);
374 opj_destroy_codec(l_codec);
375 opj_image_destroy(image);
376 return NULL;
377 }
378
379 /* Set up to decode a rectangular region */
380 if (box) {
381 boxGetGeometry(box, &bx, &by, &bw, &bh);
382 if (!opj_set_decode_area(l_codec, image, bx, by,
383 bx + bw, by + bh)) {
384 L_ERROR("failed to set the region for decoding\n", __func__);
385 opj_stream_destroy(l_stream);
386 opj_destroy_codec(l_codec);
387 opj_image_destroy(image);
388 return NULL;
389 }
390 }
391
392 /* Get the decoded image */
393 if (!(opj_decode(l_codec, l_stream, image) &&
394 opj_end_decompress(l_codec, l_stream))) {
395 L_ERROR("failed to decode the image\n", __func__);
396 opj_destroy_codec(l_codec);
397 opj_stream_destroy(l_stream);
398 opj_image_destroy(image);
399 return NULL;
400 }
401
402 /* Finished with the byte stream and the codec */
403 opj_stream_destroy(l_stream);
404 opj_destroy_codec(l_codec);
405
406 /* Get the image parameters */
407 spp = image->numcomps;
408 w = image->comps[0].w;
409 h = image->comps[0].h;
410 prec = image->comps[0].prec;
411 if (prec != bps)
412 L_WARNING("precision %d != bps %d!\n", __func__, prec, bps);
413 if (debug) {
414 L_INFO("w = %d, h = %d, bps = %d, spp = %d\n",
415 __func__, w, h, bps, spp);
416 colorspace = image->color_space;
417 if (colorspace == OPJ_CLRSPC_SRGB)
418 L_INFO("colorspace is sRGB\n", __func__);
419 else if (colorspace == OPJ_CLRSPC_GRAY)
420 L_INFO("colorspace is grayscale\n", __func__);
421 else if (colorspace == OPJ_CLRSPC_SYCC)
422 L_INFO("colorspace is YUV\n", __func__);
423 }
424
425 /* Convert the image to a pix */
426 if (spp == 1)
427 pix = pixCreate(w, h, 8);
428 else
429 pix = pixCreate(w, h, 32);
430 pixSetInputFormat(pix, IFF_JP2);
431 pixSetResolution(pix, xres, yres);
432 data = pixGetData(pix);
433 wpl = pixGetWpl(pix);
434 index = 0;
435 if (spp == 1) {
436 for (i = 0; i < h; i++) {
437 line = data + i * wpl;
438 for (j = 0; j < w; j++) {
439 val = image->comps[0].data[index];
440 SET_DATA_BYTE(line, j, val);
441 index++;
442 }
443 }
444 } else if (spp == 2) { /* convert to RGBA */
445 for (i = 0; i < h; i++) {
446 line = data + i * wpl;
447 for (j = 0; j < w; j++) {
448 val = image->comps[0].data[index];
449 aval = image->comps[1].data[index];
450 composeRGBAPixel(val, val, val, aval, &pixel);
451 line[j] = pixel;
452 index++;
453 }
454 }
455 } else if (spp >= 3) {
456 for (i = 0; i < h; i++) {
457 line = data + i * wpl;
458 for (j = 0; j < w; j++) {
459 rval = image->comps[0].data[index];
460 gval = image->comps[1].data[index];
461 bval = image->comps[2].data[index];
462 if (spp == 3) {
463 composeRGBPixel(rval, gval, bval, &pixel);
464 } else { /* spp == 4 */
465 aval = image->comps[3].data[index];
466 composeRGBAPixel(rval, gval, bval, aval, &pixel);
467 }
468 line[j] = pixel;
469 index++;
470 }
471 }
472 }
473
474 /* Free the opj image data structure */
475 opj_image_destroy(image);
476
477 return pix;
478 }
479
480
481 /*---------------------------------------------------------------------*
482 * Write jp2k to file *
483 *---------------------------------------------------------------------*/
484 /*!
485 * \brief pixWriteJp2k()
486 *
487 * \param[in] filename
488 * \param[in] pix any depth, cmap is OK
489 * \param[in] quality SNR > 0; 0 for default (34); 100 for lossless
490 * \param[in] nlevels resolution levels; 6 or 7; use 0 for default (6)
491 * \param[in] hint a bitwise OR of L_JP2K_* values; 0 for default
492 * \param[in] debug output callback messages, etc
493 * \return 0 if OK; 1 on error
494 *
495 * <pre>
496 * Notes:
497 * (1) The %quality parameter is the SNR. The useful range is narrow:
498 * SNR < 27 (terrible quality)
499 * SNR = 34 (default; approximately equivalent to jpeg quality 75)
500 * SNR = 40 (very high quality)
501 * SNR = 45 (nearly lossless)
502 * Use 0 for default; 100 for lossless.
503 * (2) The %nlevels parameter is the number of resolution levels
504 * to be written. Except for very small images, we allow 6 or 7.
505 * For example, with %nlevels == 6, images with reduction factors
506 * of 1, 2, 4, 8, 16 and 32 are encoded, and retrieval is done at
507 * the level requested when reading. For default, use either 0 or 6.
508 * Small images can constrain %nlevels according to
509 * 2^(%nlevels - 1) <= Min(w, h)
510 * and if necessary %nlevels will be reduced to accommodate.
511 * For example, images with a minimum dimension between 32 and 63
512 * can support %nlevels = 6, with reductions up to 32x. An image
513 * with a minimum dimension smaller than 32 will not support
514 * 6 nlevels (reductions of 1, 2, 4, 8, 16 and 32).
515 * (3) By default, we use the JP2 codec.
516 * (4) The %hint parameter is not yet in use.
517 * (5) For now, we only support 1 "layer" for quality.
518 * </pre>
519 */
520 l_ok
521 pixWriteJp2k(const char *filename,
522 PIX *pix,
523 l_int32 quality,
524 l_int32 nlevels,
525 l_int32 hint,
526 l_int32 debug)
527 {
528 FILE *fp;
529
530 if (!pix)
531 return ERROR_INT("pix not defined", __func__, 1);
532 if (!filename)
533 return ERROR_INT("filename not defined", __func__, 1);
534
535 if ((fp = fopenWriteStream(filename, "wb+")) == NULL)
536 return ERROR_INT_1("stream not opened", filename, __func__, 1);
537
538 if (pixWriteStreamJp2k(fp, pix, quality, nlevels, L_JP2_CODEC,
539 hint, debug)) {
540 fclose(fp);
541 return ERROR_INT_1("pix not written to stream", filename, __func__, 1);
542 }
543
544 fclose(fp);
545 return 0;
546 }
547
548
549 /*!
550 * \brief pixWriteOpjStreamJp2k()
551 *
552 * \param[in] l_stream OPJ stream
553 * \param[in] pix any depth, cmap is OK
554 * \param[in] quality SNR > 0; 0 for default (34); 100 for lossless
555 * \param[in] nlevels resolution levels; 6 or 7; use 0 for default (6)
556 * \param[in] codec L_JP2_CODEC or L_J2K_CODEC
557 * \param[in] hint a bitwise OR of L_JP2K_* values; 0 for default
558 * \param[in] debug output callback messages, etc
559 * \return 0 if OK, 1 on error
560 * <pre>
561 * Notes:
562 * (1) See pixWriteJp2k() for usage.
563 * </pre>
564 */
565 static l_ok
566 pixWriteOpjStreamJp2k(opj_stream_t *l_stream,
567 PIX *pix,
568 l_int32 quality,
569 l_int32 nlevels,
570 l_int32 codec,
571 l_int32 hint,
572 l_int32 debug)
573 {
574 l_int32 i, w, h, d, depth, channels, success;
575 l_float64 snr;
576 const char *opjVersion;
577 PIX *pixs;
578 opj_cparameters_t parameters; /* compression parameters */
579 opj_codec_t* l_codec = NULL;;
580 opj_image_t *image = NULL;
581
582 if (!l_stream)
583 return ERROR_INT("stream not open", __func__, 1);
584 if (!pix)
585 return ERROR_INT("pix not defined", __func__, 1);
586
587 snr = (l_float64)quality;
588 if (snr <= 0.0) snr = 34.0; /* default */
589 if (snr < 27.0)
590 L_WARNING("SNR = %d < 27; very low\n", __func__, (l_int32)snr);
591 if (snr == 100.0) snr = 0.0; /* for lossless */
592 if (snr > 45.0) {
593 L_WARNING("SNR > 45; using lossless encoding\n", __func__);
594 snr = 0.0;
595 }
596
597 if (nlevels == 0) nlevels = 6; /* default */
598 if (nlevels < 6) {
599 L_WARNING("nlevels = %d < 6; setting to 6\n", __func__, nlevels);
600 nlevels = 6;
601 }
602 if (nlevels > 7) {
603 L_WARNING("nlevels = %d > 7; setting to 7\n", __func__, nlevels);
604 nlevels = 7;
605 }
606
607 if (codec != L_JP2_CODEC && codec != L_J2K_CODEC)
608 return ERROR_INT("valid codec not identified\n", __func__, 1);
609
610 opjVersion = opj_version();
611 if (!opjVersion || opjVersion[0] == '\0')
612 return ERROR_INT("opj version not defined", __func__, 1);
613 if (opjVersion[0] - 0x30 < 2 ||
614 (opjVersion[0] == '2' && opjVersion[2] - 0x30 == 0)) {
615 L_ERROR("version is %s; must be 2.1 or higher\n", __func__, opjVersion);
616 return 1;
617 }
618
619 /* Remove colormap if it exists; result is 8 or 32 bpp */
620 pixGetDimensions(pix, &w, &h, &d);
621 if (d == 24) {
622 pixs = pixConvert24To32(pix);
623 } else if (d == 32) {
624 pixs = pixClone(pix);
625 } else if (pixGetColormap(pix) == NULL) {
626 pixs = pixConvertTo8(pix, 0);
627 } else { /* colormap */
628 L_INFO("removing colormap; may be better to compress losslessly\n",
629 __func__);
630 pixs = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC);
631 }
632 depth = pixGetDepth(pixs); /* 8 or 32 */
633
634 /* Reduce nlevels if the image has at least one small dimension */
635 for (i = 1; i < 7; i++) {
636 if ((w < (1 << i)) || (h < (1 << i))) {
637 if (i < nlevels) {
638 L_INFO("small image: w = %d, h = %d; setting nlevels to %d\n",
639 __func__, w, h, i);
640 nlevels = i;
641 }
642 break;
643 }
644 }
645
646 /* Convert to opj image format. */
647 pixSetPadBits(pixs, 0);
648 image = pixConvertToOpjImage(pixs);
649 pixDestroy(&pixs);
650
651 /* Set encoding parameters to default values.
652 * We use one layer with the input SNR. */
653 opj_set_default_encoder_parameters(&parameters);
654 parameters.cp_fixed_quality = 1;
655 parameters.cp_disto_alloc = 0;
656 parameters.tcp_distoratio[0] = snr;
657 parameters.tcp_numlayers = 1;
658 parameters.numresolution = nlevels;
659 channels = (depth == 32) ? 3 : 1;
660 parameters.tcp_mct = (channels == 3) ? 1 : 0;
661
662 /* Create comment for codestream */
663 if (parameters.cp_comment == NULL) {
664 const char comment1[] = "Created by Leptonica, version ";
665 const char comment2[] = "; using OpenJPEG, version ";
666 size_t len1 = strlen(comment1);
667 size_t len2 = strlen(comment2);
668 char *version1 = getLeptonicaVersion();
669 const char *version2 = opj_version();
670 len1 += len2 + strlen(version1) + strlen(version2) + 1;
671 parameters.cp_comment = (char *)LEPT_MALLOC(len1);
672 snprintf(parameters.cp_comment, len1, "%s%s%s%s", comment1, version1,
673 comment2, version2);
674 LEPT_FREE(version1);
675 }
676
677 /* Get the encoder handle */
678 if (codec == L_JP2_CODEC)
679 l_codec = opj_create_compress(OPJ_CODEC_JP2);
680 else /* codec == L_J2K_CODEC */
681 l_codec = opj_create_compress(OPJ_CODEC_J2K);
682 if (!l_codec) {
683 opj_image_destroy(image);
684 LEPT_FREE(parameters.cp_comment);
685 return ERROR_INT("failed to get the encoder handle\n", __func__, 1);
686 }
687
688 /* Catch and report events using callbacks */
689 if (debug) {
690 opj_set_info_handler(l_codec, info_callback, NULL);
691 opj_set_warning_handler(l_codec, warning_callback, NULL);
692 opj_set_error_handler(l_codec, error_callback, NULL);
693 }
694
695 /* Set up the encoder */
696 if (!opj_setup_encoder(l_codec, &parameters, image)) {
697 opj_destroy_codec(l_codec);
698 opj_image_destroy(image);
699 LEPT_FREE(parameters.cp_comment);
700 return ERROR_INT("failed to set up the encoder\n", __func__, 1);
701 }
702
703 /* Set the resolution (TBD) */
704
705 /* Encode the image into the l_stream data interface */
706 if (!opj_start_compress(l_codec, image, l_stream)) {
707 opj_destroy_codec(l_codec);
708 opj_image_destroy(image);
709 LEPT_FREE(parameters.cp_comment);
710 return ERROR_INT("opj_start_compress failed\n", __func__, 1);
711 }
712 if (!opj_encode(l_codec, l_stream)) {
713 opj_destroy_codec(l_codec);
714 opj_image_destroy(image);
715 LEPT_FREE(parameters.cp_comment);
716 return ERROR_INT("opj_encode failed\n", __func__, 1);
717 }
718 success = opj_end_compress(l_codec, l_stream);
719
720 /* Clean up */
721 opj_destroy_codec(l_codec);
722 opj_image_destroy(image);
723 LEPT_FREE(parameters.cp_comment);
724 if (success)
725 return 0;
726 else
727 return ERROR_INT("opj_end_compress failed\n", __func__, 1);
728 }
729
730
731 /*!
732 * \brief pixWriteStreamJp2k()
733 *
734 * \param[in] fp file stream
735 * \param[in] pix any depth, cmap is OK
736 * \param[in] quality SNR > 0; 0 for default (34); 100 for lossless
737 * \param[in] nlevels <= 10
738 * \param[in] codec L_JP2_CODEC or L_J2K_CODEC
739 * \param[in] hint a bitwise OR of L_JP2K_* values; 0 for default
740 * \param[in] debug output callback messages, etc
741 * \return 0 if OK, 1 on error
742 *
743 * <pre>
744 * Notes:
745 * (1) This is a wrapper on the memory stream interface.
746 * (2) See pixWriteJp2k() for usage.
747 * </pre>
748 */
749 l_ok
750 pixWriteStreamJp2k(FILE *fp,
751 PIX *pix,
752 l_int32 quality,
753 l_int32 nlevels,
754 l_int32 codec,
755 l_int32 hint,
756 l_int32 debug)
757 {
758 l_ok ok;
759 opj_stream_t *l_stream;
760
761 if (!fp)
762 return ERROR_INT("stream not open", __func__, 1);
763
764 /* Open a compression stream for writing, borrowed from
765 * the 2.0 implementation because the file stream interface
766 * was removed in 2.1. */
767 rewind(fp);
768 if ((l_stream = opjCreateStream(fp, 0)) == NULL)
769 return ERROR_INT("failed to open l_stream\n", __func__, 1);
770
771 ok = pixWriteOpjStreamJp2k(l_stream, pix, quality, nlevels,
772 codec, hint, debug);
773
774 /* Clean up */
775 opj_stream_destroy(l_stream);
776 return ok;
777 }
778
779
780 /*!
781 * \brief pixConvertToOpjImage()
782 *
783 * \param[in] pix 8 or 32 bpp
784 * \return opj_image, or NULL on error
785 *
786 * <pre>
787 * Notes:
788 * (1) Input pix is 8 bpp grayscale, 32 bpp rgb, or 32 bpp rgba.
789 * (2) Gray + alpha pix are all represented as rgba.
790 * </pre>
791 */
792 static opj_image_t *
793 pixConvertToOpjImage(PIX *pix)
794 {
795 l_int32 i, j, k, w, h, d, spp, wpl;
796 OPJ_COLOR_SPACE colorspace;
797 l_int32 *ir = NULL;
798 l_int32 *ig = NULL;
799 l_int32 *ib = NULL;
800 l_int32 *ia = NULL;
801 l_uint32 *line, *data;
802 opj_image_t *image;
803 opj_image_cmptparm_t cmptparm[4];
804
805 if (!pix)
806 return (opj_image_t *)ERROR_PTR("pix not defined", __func__, NULL);
807 pixGetDimensions(pix, &w, &h, &d);
808 if (d != 8 && d != 32) {
809 L_ERROR("invalid depth: %d\n", __func__, d);
810 return NULL;
811 }
812
813 /* Allocate the opj_image. */
814 spp = pixGetSpp(pix);
815 memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
816 for (i = 0; i < spp; i++) {
817 cmptparm[i].prec = 8;
818 cmptparm[i].sgnd = 0;
819 cmptparm[i].dx = 1;
820 cmptparm[i].dy = 1;
821 cmptparm[i].w = w;
822 cmptparm[i].h = h;
823 }
824 colorspace = (spp == 1) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB;
825 if ((image = opj_image_create(spp, &cmptparm[0], colorspace)) == NULL)
826 return (opj_image_t *)ERROR_PTR("image not made", __func__, NULL);
827 image->x0 = 0;
828 image->y0 = 0;
829 image->x1 = w;
830 image->y1 = h;
831
832 /* Set the component pointers */
833 ir = image->comps[0].data;
834 if (spp > 1) {
835 ig = image->comps[1].data;
836 ib = image->comps[2].data;
837 }
838 if(spp == 4)
839 ia = image->comps[3].data;
840
841 /* Transfer the data from the pix */
842 data = pixGetData(pix);
843 wpl = pixGetWpl(pix);
844 for (i = 0, k = 0; i < h; i++) {
845 line = data + i * wpl;
846 for (j = 0; j < w; j++, k++) {
847 if (spp == 1) {
848 ir[k] = GET_DATA_BYTE(line, j);
849 } else if (spp > 1) {
850 ir[k] = GET_DATA_BYTE(line + j, COLOR_RED);
851 ig[k] = GET_DATA_BYTE(line + j, COLOR_GREEN);
852 ib[k] = GET_DATA_BYTE(line + j, COLOR_BLUE);
853 }
854 if (spp == 4)
855 ia[k] = GET_DATA_BYTE(line + j, L_ALPHA_CHANNEL);
856 }
857 }
858
859 return image;
860 }
861
862
863 /*---------------------------------------------------------------------*
864 * Read/write to memory *
865 *---------------------------------------------------------------------*/
866 /*!
867 * \brief pixReadMemJp2k()
868 *
869 * \param[in] data const; jpeg-encoded
870 * \param[in] size of data
871 * \param[in] reduction scaling factor: 1, 2, 4, 8
872 * \param[in] box [optional] for extracting a subregion, can be null
873 * \param[in] hint a bitwise OR of L_JP2K_* values; 0 for default
874 * \param[in] debug output callback messages, etc
875 * \return pix, or NULL on error
876 *
877 * <pre>
878 * Notes:
879 * (1) See pixReadJp2k() for usage.
880 * </pre>
881 */
882 PIX *
883 pixReadMemJp2k(const l_uint8 *data,
884 size_t size,
885 l_uint32 reduction,
886 BOX *box,
887 l_int32 hint,
888 l_int32 debug)
889 {
890 PIX *pix;
891
892 if (!data)
893 return (PIX *)ERROR_PTR("data not defined", __func__, NULL);
894
895 pix = pixReadMemJp2kCore(data, size, reduction, box, hint, debug);
896 if (!pix) L_ERROR("pix not read\n", __func__);
897 return pix;
898 }
899
900
901 /*!
902 * \brief pixWriteMemJp2k()
903 *
904 * \param[out] pdata data of jpeg compressed image
905 * \param[out] psize size of returned data
906 * \param[in] pix 8 or 32 bpp
907 * \param[in] quality SNR > 0; 0 for default (34); 100 for lossless
908 * \param[in] nlevels 0 for default
909 * \param[in] hint a bitwise OR of L_JP2K_* values; 0 for default
910 * \param[in] debug output callback messages, etc
911 * \return 0 if OK, 1 on error
912 *
913 * <pre>
914 * Notes:
915 * (1) See pixWriteJp2k() for usage. This version writes to
916 * memory instead of to a file stream.
917 * </pre>
918 */
919 l_ok
920 pixWriteMemJp2k(l_uint8 **pdata,
921 size_t *psize,
922 PIX *pix,
923 l_int32 quality,
924 l_int32 nlevels,
925 l_int32 hint,
926 l_int32 debug)
927 {
928 l_ok ok;
929 opj_stream_t *l_stream;
930 OpjBuffer buffer;
931
932 if (pdata) *pdata = NULL;
933 if (psize) *psize = 0;
934 if (!pdata)
935 return ERROR_INT("&data not defined", __func__, 1 );
936 if (!psize)
937 return ERROR_INT("&size not defined", __func__, 1 );
938 if (!pix)
939 return ERROR_INT("&pix not defined", __func__, 1 );
940
941 buffer.pos = 0;
942 buffer.len = 0;
943 buffer.size = OPJ_J2K_STREAM_CHUNK_SIZE;
944 buffer.data = (l_uint8 *)LEPT_MALLOC(buffer.size);
945 if (!buffer.data)
946 return ERROR_INT("failed to allocate buffer", __func__, 1 );
947
948 if ((l_stream = opjCreateMemoryStream(&buffer, 0)) == NULL) {
949 return ERROR_INT("failed to open l_stream\n", __func__, 1);
950 }
951
952 ok = pixWriteOpjStreamJp2k(l_stream, pix, quality, nlevels, L_JP2_CODEC,
953 hint, debug);
954
955 /* Clean up */
956 opj_stream_destroy(l_stream);
957
958 if (!ok) {
959 *pdata = buffer.data;
960 *psize = buffer.len;
961 } else {
962 LEPT_FREE(buffer.data);
963 }
964
965 return ok;
966 }
967
968
969 /*---------------------------------------------------------------------*
970 * Static functions for the memory stream interface *
971 *---------------------------------------------------------------------*/
972 static OPJ_SIZE_T
973 opj_read_from_buffer(void *p_buffer, OPJ_SIZE_T p_nb_bytes, OpjBuffer *pbuf) {
974 if (pbuf->pos > pbuf->len)
975 return (OPJ_SIZE_T) - 1;
976
977 OPJ_SIZE_T l_nb_read = pbuf->len - pbuf->pos;
978 if (l_nb_read > p_nb_bytes)
979 l_nb_read = p_nb_bytes;
980 memcpy(p_buffer, pbuf->data + pbuf->pos, l_nb_read);
981 pbuf->pos += l_nb_read;
982 return l_nb_read ? l_nb_read : (OPJ_SIZE_T) - 1;
983 }
984
985 static OPJ_SIZE_T
986 opj_write_from_buffer(const void *p_buffer, OPJ_SIZE_T p_nb_bytes,
987 OpjBuffer *pbuf) {
988 size_t newpos = pbuf->pos + p_nb_bytes;
989 if (newpos > pbuf->size) {
990 size_t oldsize = pbuf->size;
991 size_t newsize = oldsize * 2;
992 if (newsize < newpos)
993 newsize = newpos;
994 if (newsize <= 0) {
995 L_ERROR("buffer too large\n", __func__);
996 return 0;
997 }
998
999 l_uint8 *newdata = (l_uint8 *)LEPT_REALLOC(pbuf->data, newsize);
1000 if (!newdata) {
1001 L_ERROR("out of memory\n", __func__);
1002 return 0;
1003 }
1004
1005 /* clear out any garbage left by realloc */
1006 memset(newdata + oldsize, 0, newsize - oldsize);
1007 pbuf->data = newdata;
1008 pbuf->size = newsize;
1009 }
1010
1011 memcpy(pbuf->data + pbuf->pos, p_buffer, p_nb_bytes);
1012 pbuf->pos = newpos;
1013 if (pbuf->len < newpos)
1014 pbuf->len = newpos;
1015 return p_nb_bytes;
1016 }
1017
1018 static OPJ_OFF_T
1019 opj_skip_from_buffer(OPJ_OFF_T offset, OpjBuffer *pbuf) {
1020 pbuf->pos += offset;
1021 return offset;
1022 }
1023
1024 static l_int32
1025 opj_seek_from_buffer(OPJ_OFF_T offset, OpjBuffer *pbuf) {
1026 pbuf->pos = offset;
1027 return 1;
1028 }
1029
1030
1031 /*---------------------------------------------------------------------*
1032 * Static generator of opj_stream from memory buffer *
1033 *---------------------------------------------------------------------*/
1034 static opj_stream_t *
1035 opjCreateMemoryStream(OpjBuffer *pbuf,
1036 l_int32 is_read_stream)
1037 {
1038 opj_stream_t *l_stream;
1039
1040 if (!pbuf)
1041 return (opj_stream_t *)ERROR_PTR("pbuf not defined", __func__, NULL);
1042
1043 l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, is_read_stream);
1044 if (!l_stream)
1045 return (opj_stream_t *)ERROR_PTR("stream not made", __func__, NULL);
1046
1047 opj_stream_set_user_data(l_stream, pbuf,
1048 (opj_stream_free_user_data_fn)NULL);
1049 opj_stream_set_user_data_length(l_stream, pbuf->len);
1050 opj_stream_set_read_function(l_stream,
1051 (opj_stream_read_fn)opj_read_from_buffer);
1052 opj_stream_set_skip_function(l_stream,
1053 (opj_stream_skip_fn)opj_skip_from_buffer);
1054 opj_stream_set_seek_function(l_stream,
1055 (opj_stream_seek_fn)opj_seek_from_buffer);
1056
1057 if (is_read_stream)
1058 return l_stream;
1059
1060 opj_stream_set_write_function(l_stream,
1061 (opj_stream_write_fn)opj_write_from_buffer);
1062 return l_stream;
1063 }
1064
1065
1066 /*---------------------------------------------------------------------*
1067 * Static functions from opj 2.0 to retain file stream interface *
1068 *---------------------------------------------------------------------*/
1069 static l_uint64
1070 opj_get_user_data_length(FILE *fp) {
1071 OPJ_OFF_T length = 0;
1072 fseek(fp, 0, SEEK_END);
1073 length = (OPJ_OFF_T)ftell(fp);
1074 fseek(fp, 0, SEEK_SET);
1075 return (l_uint64)length;
1076 }
1077
1078 static OPJ_SIZE_T
1079 opj_read_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp) {
1080 OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, fp);
1081 return l_nb_read ? l_nb_read : (OPJ_SIZE_T) - 1;
1082 }
1083
1084 static OPJ_SIZE_T
1085 opj_write_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp)
1086 {
1087 return fwrite(p_buffer, 1, p_nb_bytes, fp);
1088 }
1089
1090 static OPJ_OFF_T
1091 opj_skip_from_file(OPJ_OFF_T offset, FILE *fp) {
1092 if (fseek(fp, offset, SEEK_CUR)) {
1093 return -1;
1094 }
1095 return offset;
1096 }
1097
1098 static l_int32
1099 opj_seek_from_file(OPJ_OFF_T offset, FILE *fp) {
1100 if (fseek(fp, offset, SEEK_SET)) {
1101 return 0;
1102 }
1103 return 1;
1104 }
1105
1106
1107 /*---------------------------------------------------------------------*
1108 * Static generator of opj_stream from a file stream *
1109 *---------------------------------------------------------------------*/
1110 static opj_stream_t *
1111 opjCreateStream(FILE *fp,
1112 l_int32 is_read_stream)
1113 {
1114 opj_stream_t *l_stream;
1115
1116 if (!fp)
1117 return (opj_stream_t *)ERROR_PTR("fp not defined", __func__, NULL);
1118
1119 l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, is_read_stream);
1120 if (!l_stream)
1121 return (opj_stream_t *)ERROR_PTR("stream not made", __func__, NULL);
1122
1123 opj_stream_set_user_data(l_stream, fp,
1124 (opj_stream_free_user_data_fn)NULL);
1125 opj_stream_set_user_data_length(l_stream, opj_get_user_data_length(fp));
1126 opj_stream_set_read_function(l_stream,
1127 (opj_stream_read_fn)opj_read_from_file);
1128 opj_stream_set_write_function(l_stream,
1129 (opj_stream_write_fn)opj_write_from_file);
1130 opj_stream_set_skip_function(l_stream,
1131 (opj_stream_skip_fn)opj_skip_from_file);
1132 opj_stream_set_seek_function(l_stream,
1133 (opj_stream_seek_fn)opj_seek_from_file);
1134
1135 return l_stream;
1136 }
1137
1138 /* --------------------------------------------*/
1139 #endif /* HAVE_LIBJP2K */
1140 /* --------------------------------------------*/