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