Leptonica 1.83.1
Image processing and image analysis suite
Loading...
Searching...
No Matches
jp2kio.c
Go to the documentation of this file.
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
101
102#ifdef HAVE_CONFIG_H
103#include <config_auto.h>
104#endif /* HAVE_CONFIG_H */
105
106#include <string.h>
107#include "allheaders.h"
108
109/* --------------------------------------------*/
110#if HAVE_LIBJP2K /* defined in environ.h */
111/* --------------------------------------------*/
112
113 /* Leptonica supports versions 2.0 and newer */
114#ifdef LIBJP2K_HEADER
115#include LIBJP2K_HEADER
116#else
117#include <openjpeg.h>
118#endif
119
120 /* 2.0 didn't define OPJ_VERSION_MINOR. */
121#ifndef OPJ_VERSION_MINOR
122#define OPJ_VERSION_MINOR 0
123#endif
124
125 /* Static generator of opj_stream from file stream.
126 * In 2.0.1, this functionality is provided by
127 * opj_stream_create_default_file_stream(),
128 * but it was removed in 2.1.0. Because we must have either
129 * a file stream or a memory interface to the compressed data,
130 * it is necessary to recreate the stream interface here. */
131static opj_stream_t *opjCreateStream(FILE *fp, l_int32 is_read);
132
133 /* Static converter pix --> opj_image. Used for compressing pix,
134 * because the codec works on data stored in their raster format. */
135static opj_image_t *pixConvertToOpjImage(PIX *pix);
136
137/*---------------------------------------------------------------------*
138 * Callback event handlers *
139 *---------------------------------------------------------------------*/
140static void error_callback(const char *msg, void *client_data) {
141 (void)client_data;
142 fprintf(stdout, "[ERROR] %s", msg);
143}
144
145static void warning_callback(const char *msg, void *client_data) {
146 (void)client_data;
147 fprintf(stdout, "[WARNING] %s", msg);
148}
149
150static void info_callback(const char *msg, void *client_data) {
151 (void)client_data;
152 fprintf(stdout, "[INFO] %s", msg);
153}
154
155
156/*---------------------------------------------------------------------*
157 * Read jp2k from file (special function) *
158 *---------------------------------------------------------------------*/
198PIX *
199pixReadJp2k(const char *filename,
200 l_uint32 reduction,
201 BOX *box,
202 l_int32 hint,
203 l_int32 debug)
204{
205FILE *fp;
206PIX *pix;
207
208 if (!filename)
209 return (PIX *)ERROR_PTR("filename not defined", __func__, NULL);
210
211 if ((fp = fopenReadStream(filename)) == NULL)
212 return (PIX *)ERROR_PTR("image file not found", __func__, NULL);
213 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
214 fclose(fp);
215
216 if (!pix)
217 return (PIX *)ERROR_PTR("image not returned", __func__, NULL);
218 return pix;
219}
220
221
237PIX *
238pixReadStreamJp2k(FILE *fp,
239 l_uint32 reduction,
240 BOX *box,
241 l_int32 hint,
242 l_int32 debug)
243{
244const char *opjVersion;
245l_int32 i, j, index, bx, by, bw, bh, val, rval, gval, bval, aval;
246l_int32 w, h, wpl, bps, spp, xres, yres, reduce, prec, colorspace;
247l_int32 codec; /* L_J2K_CODEC or L_JP2_CODEC */
248l_uint32 pixel;
249l_uint32 *data, *line;
250opj_dparameters_t parameters; /* decompression parameters */
251opj_image_t *image = NULL;
252opj_codec_t *l_codec = NULL; /* handle to decompressor */
253opj_stream_t *l_stream = NULL; /* opj stream */
254PIX *pix = NULL;
255
256 if (!fp)
257 return (PIX *)ERROR_PTR("fp not defined", __func__, NULL);
258
259 opjVersion = opj_version();
260 if (opjVersion[0] != '2') {
261 L_ERROR("version is %s; must be 2.0 or higher\n", __func__, opjVersion);
262 return NULL;
263 }
264 if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
265 L_ERROR("version %s: differs from minor = %d\n",
266 __func__, opjVersion, OPJ_VERSION_MINOR);
267 return NULL;
268 }
269
270 /* Get the resolution, bits/sample and codec type */
271 rewind(fp);
272 fgetJp2kResolution(fp, &xres, &yres);
273 freadHeaderJp2k(fp, NULL, NULL, &bps, NULL, &codec);
274 rewind(fp);
275 if (codec != L_J2K_CODEC && codec != L_JP2_CODEC) {
276 L_ERROR("valid codec not identified\n", __func__);
277 return NULL;
278 }
279
280 if (bps != 8) {
281 L_ERROR("found %d bps; can only handle 8 bps\n", __func__, bps);
282 return NULL;
283 }
284
285 /* Set decoding parameters to default values */
286 opj_set_default_decoder_parameters(&parameters);
287
288 /* Find and set the reduce parameter, which is log2(reduction).
289 * Valid reductions are powers of 2, and are determined when the
290 * compressed string is made. A request for an invalid reduction
291 * will cause an error in opj_read_header(), and no image will
292 * be returned. */
293 for (reduce = 0; (1L << reduce) < reduction; reduce++) { }
294 if ((1L << reduce) != reduction) {
295 L_ERROR("invalid reduction %d; not power of 2\n", __func__, reduction);
296 return NULL;
297 }
298 parameters.cp_reduce = reduce;
299
300 /* Get a decoder handle */
301 if (codec == L_JP2_CODEC)
302 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
303 else if (codec == L_J2K_CODEC)
304 l_codec = opj_create_decompress(OPJ_CODEC_J2K);
305 if (!l_codec) {
306 L_ERROR("failed to make the codec\n", __func__);
307 return NULL;
308 }
309
310 /* Catch and report events using callbacks */
311 if (debug) {
312 opj_set_info_handler(l_codec, info_callback, NULL);
313 opj_set_warning_handler(l_codec, warning_callback, NULL);
314 opj_set_error_handler(l_codec, error_callback, NULL);
315 }
316
317 /* Setup the decoding parameters using user parameters */
318 if (!opj_setup_decoder(l_codec, &parameters)){
319 L_ERROR("failed to set up decoder\n", __func__);
320 opj_destroy_codec(l_codec);
321 return NULL;
322 }
323
324 /* Open decompression 'stream'. In 2.0, we could call this:
325 * opj_stream_create_default_file_stream(fp, 1)
326 * but the file stream interface was removed in 2.1. */
327 if ((l_stream = opjCreateStream(fp, 1)) == NULL) {
328 L_ERROR("failed to open the stream\n", __func__);
329 opj_destroy_codec(l_codec);
330 return NULL;
331 }
332
333 /* Read the main header of the codestream and, if necessary,
334 * the JP2 boxes */
335 if(!opj_read_header(l_stream, l_codec, &image)){
336 L_ERROR("failed to read the header\n", __func__);
337 opj_stream_destroy(l_stream);
338 opj_destroy_codec(l_codec);
339 opj_image_destroy(image);
340 return NULL;
341 }
342
343 /* Set up to decode a rectangular region */
344 if (box) {
345 boxGetGeometry(box, &bx, &by, &bw, &bh);
346 if (!opj_set_decode_area(l_codec, image, bx, by,
347 bx + bw, by + bh)) {
348 L_ERROR("failed to set the region for decoding\n", __func__);
349 opj_stream_destroy(l_stream);
350 opj_destroy_codec(l_codec);
351 opj_image_destroy(image);
352 return NULL;
353 }
354 }
355
356 /* Get the decoded image */
357 if (!(opj_decode(l_codec, l_stream, image) &&
358 opj_end_decompress(l_codec, l_stream))) {
359 L_ERROR("failed to decode the image\n", __func__);
360 opj_destroy_codec(l_codec);
361 opj_stream_destroy(l_stream);
362 opj_image_destroy(image);
363 return NULL;
364 }
365
366 /* Finished with the byte stream and the codec */
367 opj_stream_destroy(l_stream);
368 opj_destroy_codec(l_codec);
369
370 /* Get the image parameters */
371 spp = image->numcomps;
372 w = image->comps[0].w;
373 h = image->comps[0].h;
374 prec = image->comps[0].prec;
375 if (prec != bps)
376 L_WARNING("precision %d != bps %d!\n", __func__, prec, bps);
377 if (debug) {
378 L_INFO("w = %d, h = %d, bps = %d, spp = %d\n",
379 __func__, w, h, bps, spp);
380 colorspace = image->color_space;
381 if (colorspace == OPJ_CLRSPC_SRGB)
382 L_INFO("colorspace is sRGB\n", __func__);
383 else if (colorspace == OPJ_CLRSPC_GRAY)
384 L_INFO("colorspace is grayscale\n", __func__);
385 else if (colorspace == OPJ_CLRSPC_SYCC)
386 L_INFO("colorspace is YUV\n", __func__);
387 }
388
389 /* Convert the image to a pix */
390 if (spp == 1)
391 pix = pixCreate(w, h, 8);
392 else
393 pix = pixCreate(w, h, 32);
394 pixSetInputFormat(pix, IFF_JP2);
395 pixSetResolution(pix, xres, yres);
396 data = pixGetData(pix);
397 wpl = pixGetWpl(pix);
398 index = 0;
399 if (spp == 1) {
400 for (i = 0; i < h; i++) {
401 line = data + i * wpl;
402 for (j = 0; j < w; j++) {
403 val = image->comps[0].data[index];
404 SET_DATA_BYTE(line, j, val);
405 index++;
406 }
407 }
408 } else if (spp == 2) { /* convert to RGBA */
409 for (i = 0; i < h; i++) {
410 line = data + i * wpl;
411 for (j = 0; j < w; j++) {
412 val = image->comps[0].data[index];
413 aval = image->comps[1].data[index];
414 composeRGBAPixel(val, val, val, aval, &pixel);
415 line[j] = pixel;
416 index++;
417 }
418 }
419 } else if (spp >= 3) {
420 for (i = 0; i < h; i++) {
421 line = data + i * wpl;
422 for (j = 0; j < w; j++) {
423 rval = image->comps[0].data[index];
424 gval = image->comps[1].data[index];
425 bval = image->comps[2].data[index];
426 if (spp == 3) {
427 composeRGBPixel(rval, gval, bval, &pixel);
428 } else { /* spp == 4 */
429 aval = image->comps[3].data[index];
430 composeRGBAPixel(rval, gval, bval, aval, &pixel);
431 }
432 line[j] = pixel;
433 index++;
434 }
435 }
436 }
437
438 /* Free the opj image data structure */
439 opj_image_destroy(image);
440
441 return pix;
442}
443
444
445/*---------------------------------------------------------------------*
446 * Write jp2k to file *
447 *---------------------------------------------------------------------*/
477l_ok
478pixWriteJp2k(const char *filename,
479 PIX *pix,
480 l_int32 quality,
481 l_int32 nlevels,
482 l_int32 hint,
483 l_int32 debug)
484{
485FILE *fp;
486
487 if (!pix)
488 return ERROR_INT("pix not defined", __func__, 1);
489 if (!filename)
490 return ERROR_INT("filename not defined", __func__, 1);
491
492 if ((fp = fopenWriteStream(filename, "wb+")) == NULL)
493 return ERROR_INT("stream not opened", __func__, 1);
494
495 if (pixWriteStreamJp2k(fp, pix, quality, nlevels, L_JP2_CODEC,
496 hint, debug)) {
497 fclose(fp);
498 return ERROR_INT("pix not written to stream", __func__, 1);
499 }
500
501 fclose(fp);
502 return 0;
503}
504
505
522l_ok
523pixWriteStreamJp2k(FILE *fp,
524 PIX *pix,
525 l_int32 quality,
526 l_int32 nlevels,
527 l_int32 codec,
528 l_int32 hint,
529 l_int32 debug)
530{
531l_int32 w, h, d, success;
532l_float32 snr;
533const char *opjVersion;
534PIX *pixs;
535opj_cparameters_t parameters; /* compression parameters */
536opj_stream_t *l_stream = NULL;
537opj_codec_t* l_codec = NULL;;
538opj_image_t *image = NULL;
539
540 if (!fp)
541 return ERROR_INT("stream not open", __func__, 1);
542 if (!pix)
543 return ERROR_INT("pix not defined", __func__, 1);
544
545 snr = (l_float32)quality;
546 if (snr <= 0) snr = 34.0; /* default */
547 if (snr < 27)
548 L_WARNING("SNR = %d < 27; very low\n", __func__, (l_int32)snr);
549 if (snr == 100) snr = 0; /* for lossless */
550 if (snr > 45) {
551 L_WARNING("SNR > 45; using lossless encoding\n", __func__);
552 snr = 0;
553 }
554
555 if (nlevels <= 0) nlevels = 5; /* default */
556 if (nlevels > 10) {
557 L_WARNING("nlevels = %d > 10; setting to 10\n", __func__, nlevels);
558 nlevels = 10;
559 }
560 if (codec != L_JP2_CODEC && codec != L_J2K_CODEC)
561 return ERROR_INT("valid codec not identified\n", __func__, 1);
562
563 opjVersion = opj_version();
564 if (opjVersion[0] != '2') {
565 L_ERROR("version is %s; must be 2.0 or higher\n", __func__, opjVersion);
566 return 1;
567 }
568 if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
569 L_ERROR("version %s: differs from minor = %d\n",
570 __func__, opjVersion, OPJ_VERSION_MINOR);
571 return 1;
572 }
573
574 /* Remove colormap if it exists; result is 8 or 32 bpp */
575 pixGetDimensions(pix, &w, &h, &d);
576 if (d == 24) {
577 pixs = pixConvert24To32(pix);
578 } else if (d == 32) {
579 pixs = pixClone(pix);
580 } else if (pixGetColormap(pix) == NULL) {
581 pixs = pixConvertTo8(pix, 0);
582 } else { /* colormap */
583 L_INFO("removing colormap; may be better to compress losslessly\n",
584 __func__);
585 pixs = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC);
586 }
587
588 /* Convert to opj image format. */
589 pixSetPadBits(pixs, 0);
590 image = pixConvertToOpjImage(pixs);
591 pixDestroy(&pixs);
592
593 /* Set encoding parameters to default values.
594 * We use one layer with the input SNR. */
595 opj_set_default_encoder_parameters(&parameters);
596 parameters.cp_fixed_quality = 1;
597 parameters.cp_disto_alloc = 0;
598 parameters.cp_fixed_alloc = 0;
599 parameters.tcp_distoratio[0] = snr;
600 parameters.tcp_numlayers = 1;
601 parameters.numresolution = nlevels;
602
603 /* Create comment for codestream */
604 if (parameters.cp_comment == NULL) {
605 const char comment1[] = "Created by Leptonica, version ";
606 const char comment2[] = "; using OpenJPEG, version ";
607 size_t len1 = strlen(comment1);
608 size_t len2 = strlen(comment2);
609 char *version1 = getLeptonicaVersion();
610 const char *version2 = opj_version();
611 len1 += len2 + strlen(version1) + strlen(version2) + 1;
612 parameters.cp_comment = (char *)LEPT_MALLOC(len1);
613 snprintf(parameters.cp_comment, len1, "%s%s%s%s", comment1, version1,
614 comment2, version2);
615 LEPT_FREE(version1);
616 }
617
618 /* Get the encoder handle */
619 if (codec == L_JP2_CODEC)
620 l_codec = opj_create_compress(OPJ_CODEC_JP2);
621 else /* codec == L_J2K_CODEC */
622 l_codec = opj_create_compress(OPJ_CODEC_J2K);
623 if (!l_codec) {
624 opj_image_destroy(image);
625 LEPT_FREE(parameters.cp_comment);
626 return ERROR_INT("failed to get the encoder handle\n", __func__, 1);
627 }
628
629 /* Catch and report events using callbacks */
630 if (debug) {
631 opj_set_info_handler(l_codec, info_callback, NULL);
632 opj_set_warning_handler(l_codec, warning_callback, NULL);
633 opj_set_error_handler(l_codec, error_callback, NULL);
634 }
635
636 /* Set up the encoder */
637 if (!opj_setup_encoder(l_codec, &parameters, image)) {
638 opj_destroy_codec(l_codec);
639 opj_image_destroy(image);
640 LEPT_FREE(parameters.cp_comment);
641 return ERROR_INT("failed to set up the encoder\n", __func__, 1);
642 }
643
644 /* Set the resolution (TBD) */
645
646 /* Open a compression stream for writing. In 2.0 we could use this:
647 * opj_stream_create_default_file_stream(fp, 0)
648 * but the file stream interface was removed in 2.1. */
649 rewind(fp);
650 if ((l_stream = opjCreateStream(fp, 0)) == NULL) {
651 opj_destroy_codec(l_codec);
652 opj_image_destroy(image);
653 LEPT_FREE(parameters.cp_comment);
654 return ERROR_INT("failed to open l_stream\n", __func__, 1);
655 }
656
657 /* Encode the image */
658 if (!opj_start_compress(l_codec, image, l_stream)) {
659 opj_stream_destroy(l_stream);
660 opj_destroy_codec(l_codec);
661 opj_image_destroy(image);
662 LEPT_FREE(parameters.cp_comment);
663 return ERROR_INT("opj_start_compress failed\n", __func__, 1);
664 }
665 if (!opj_encode(l_codec, l_stream)) {
666 opj_stream_destroy(l_stream);
667 opj_destroy_codec(l_codec);
668 opj_image_destroy(image);
669 LEPT_FREE(parameters.cp_comment);
670 return ERROR_INT("opj_encode failed\n", __func__, 1);
671 }
672 success = opj_end_compress(l_codec, l_stream);
673
674 /* Clean up */
675 opj_stream_destroy(l_stream);
676 opj_destroy_codec(l_codec);
677 opj_image_destroy(image);
678 LEPT_FREE(parameters.cp_comment);
679 if (success)
680 return 0;
681 else
682 return ERROR_INT("opj_end_compress failed\n", __func__, 1);
683}
684
685
698static opj_image_t *
699pixConvertToOpjImage(PIX *pix)
700{
701l_int32 i, j, k, w, h, d, spp, wpl;
702OPJ_COLOR_SPACE colorspace;
703l_int32 *ir = NULL;
704l_int32 *ig = NULL;
705l_int32 *ib = NULL;
706l_int32 *ia = NULL;
707l_uint32 *line, *data;
708opj_image_t *image;
709opj_image_cmptparm_t cmptparm[4];
710
711 if (!pix)
712 return (opj_image_t *)ERROR_PTR("pix not defined", __func__, NULL);
713 pixGetDimensions(pix, &w, &h, &d);
714 if (d != 8 && d != 32) {
715 L_ERROR("invalid depth: %d\n", __func__, d);
716 return NULL;
717 }
718
719 /* Allocate the opj_image. */
720 spp = pixGetSpp(pix);
721 memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
722 for (i = 0; i < spp; i++) {
723 cmptparm[i].prec = 8;
724 cmptparm[i].bpp = 8;
725 cmptparm[i].sgnd = 0;
726 cmptparm[i].dx = 1;
727 cmptparm[i].dy = 1;
728 cmptparm[i].w = w;
729 cmptparm[i].h = h;
730 }
731 colorspace = (spp == 1) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB;
732 if ((image = opj_image_create(spp, &cmptparm[0], colorspace)) == NULL)
733 return (opj_image_t *)ERROR_PTR("image not made", __func__, NULL);
734 image->x0 = 0;
735 image->y0 = 0;
736 image->x1 = w;
737 image->y1 = h;
738
739 /* Set the component pointers */
740 ir = image->comps[0].data;
741 if (spp > 1) {
742 ig = image->comps[1].data;
743 ib = image->comps[2].data;
744 }
745 if(spp == 4)
746 ia = image->comps[3].data;
747
748 /* Transfer the data from the pix */
749 data = pixGetData(pix);
750 wpl = pixGetWpl(pix);
751 for (i = 0, k = 0; i < h; i++) {
752 line = data + i * wpl;
753 for (j = 0; j < w; j++, k++) {
754 if (spp == 1) {
755 ir[k] = GET_DATA_BYTE(line, j);
756 } else if (spp > 1) {
757 ir[k] = GET_DATA_BYTE(line + j, COLOR_RED);
758 ig[k] = GET_DATA_BYTE(line + j, COLOR_GREEN);
759 ib[k] = GET_DATA_BYTE(line + j, COLOR_BLUE);
760 }
761 if (spp == 4)
762 ia[k] = GET_DATA_BYTE(line + j, L_ALPHA_CHANNEL);
763 }
764 }
765
766 return image;
767}
768
769
770/*---------------------------------------------------------------------*
771 * Read/write to memory *
772 *---------------------------------------------------------------------*/
793PIX *
794pixReadMemJp2k(const l_uint8 *data,
795 size_t size,
796 l_uint32 reduction,
797 BOX *box,
798 l_int32 hint,
799 l_int32 debug)
800{
801FILE *fp;
802PIX *pix;
803
804 if (!data)
805 return (PIX *)ERROR_PTR("data not defined", __func__, NULL);
806
807 if ((fp = fopenReadFromMemory(data, size)) == NULL)
808 return (PIX *)ERROR_PTR("stream not opened", __func__, NULL);
809 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
810 fclose(fp);
811 if (!pix) L_ERROR("pix not read\n", __func__);
812 return pix;
813}
814
815
834l_ok
835pixWriteMemJp2k(l_uint8 **pdata,
836 size_t *psize,
837 PIX *pix,
838 l_int32 quality,
839 l_int32 nlevels,
840 l_int32 hint,
841 l_int32 debug)
842{
843l_int32 ret;
844FILE *fp;
845
846 if (pdata) *pdata = NULL;
847 if (psize) *psize = 0;
848 if (!pdata)
849 return ERROR_INT("&data not defined", __func__, 1 );
850 if (!psize)
851 return ERROR_INT("&size not defined", __func__, 1 );
852 if (!pix)
853 return ERROR_INT("&pix not defined", __func__, 1 );
854
855#if HAVE_FMEMOPEN
856 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
857 return ERROR_INT("stream not opened", __func__, 1);
858 ret = pixWriteStreamJp2k(fp, pix, quality, nlevels, L_JP2_CODEC,
859 hint, debug);
860 fputc('\0', fp);
861 fclose(fp);
862 *psize = *psize - 1;
863#else
864 L_INFO("work-around: writing to a temp file\n", __func__);
865 #ifdef _WIN32
866 if ((fp = fopenWriteWinTempfile()) == NULL)
867 return ERROR_INT("tmpfile stream not opened", __func__, 1);
868 #else
869 if ((fp = tmpfile()) == NULL)
870 return ERROR_INT("tmpfile stream not opened", __func__, 1);
871 #endif /* _WIN32 */
872 ret = pixWriteStreamJp2k(fp, pix, quality, nlevels, L_JP2_CODEC,
873 hint, debug);
874 rewind(fp);
875 *pdata = l_binaryReadStream(fp, psize);
876 fclose(fp);
877#endif /* HAVE_FMEMOPEN */
878 return ret;
879}
880
881
882/*---------------------------------------------------------------------*
883 * Static functions from opj 2.0 to retain file stream interface *
884 *---------------------------------------------------------------------*/
885static l_uint64
886opj_get_user_data_length(FILE *fp) {
887 OPJ_OFF_T length = 0;
888 fseek(fp, 0, SEEK_END);
889 length = (OPJ_OFF_T)ftell(fp);
890 fseek(fp, 0, SEEK_SET);
891 return (l_uint64)length;
892}
893
894static OPJ_SIZE_T
895opj_read_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp) {
896 OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, fp);
897 return l_nb_read ? l_nb_read : (OPJ_SIZE_T) - 1;
898}
899
900static OPJ_SIZE_T
901opj_write_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp)
902{
903 return fwrite(p_buffer, 1, p_nb_bytes, fp);
904}
905
906static OPJ_OFF_T
907opj_skip_from_file(OPJ_OFF_T offset, FILE *fp) {
908 if (fseek(fp, offset, SEEK_CUR)) {
909 return -1;
910 }
911 return offset;
912}
913
914static l_int32
915opj_seek_from_file(OPJ_OFF_T offset, FILE *fp) {
916 if (fseek(fp, offset, SEEK_SET)) {
917 return 0;
918 }
919 return 1;
920}
921
922 /* Static generator of opj_stream from file stream */
923static opj_stream_t *
924opjCreateStream(FILE *fp,
925 l_int32 is_read_stream)
926{
927opj_stream_t *l_stream;
928
929 if (!fp)
930 return (opj_stream_t *)ERROR_PTR("fp not defined", __func__, NULL);
931
932 l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, is_read_stream);
933 if (!l_stream)
934 return (opj_stream_t *)ERROR_PTR("stream not made", __func__, NULL);
935
936#if OPJ_VERSION_MINOR == 0
937 opj_stream_set_user_data(l_stream, fp);
938#else
939 opj_stream_set_user_data(l_stream, fp,
940 (opj_stream_free_user_data_fn)NULL);
941#endif
942 opj_stream_set_user_data_length(l_stream, opj_get_user_data_length(fp));
943 opj_stream_set_read_function(l_stream,
944 (opj_stream_read_fn)opj_read_from_file);
945 opj_stream_set_write_function(l_stream,
946 (opj_stream_write_fn)opj_write_from_file);
947 opj_stream_set_skip_function(l_stream,
948 (opj_stream_skip_fn)opj_skip_from_file);
949 opj_stream_set_seek_function(l_stream,
950 (opj_stream_seek_fn)opj_seek_from_file);
951
952 return l_stream;
953}
954
955/* --------------------------------------------*/
956#endif /* HAVE_LIBJP2K */
957/* --------------------------------------------*/
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
@ L_J2K_CODEC
Definition imageio.h:148
@ L_JP2_CODEC
Definition imageio.h:149
@ REMOVE_CMAP_BASED_ON_SRC
Definition pix.h:384
struct Pix PIX
Definition pix.h:228
struct Box BOX
Definition pix.h:252
@ COLOR_BLUE
Definition pix.h:330
@ COLOR_RED
Definition pix.h:328
@ L_ALPHA_CHANNEL
Definition pix.h:331
@ COLOR_GREEN
Definition pix.h:329