Leptonica  1.83.1
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. */
131 static 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. */
135 static opj_image_t *pixConvertToOpjImage(PIX *pix);
136 
137 /*---------------------------------------------------------------------*
138  * Callback event handlers *
139  *---------------------------------------------------------------------*/
140 static void error_callback(const char *msg, void *client_data) {
141  (void)client_data;
142  fprintf(stdout, "[ERROR] %s", msg);
143 }
144 
145 static void warning_callback(const char *msg, void *client_data) {
146  (void)client_data;
147  fprintf(stdout, "[WARNING] %s", msg);
148 }
149 
150 static 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  *---------------------------------------------------------------------*/
198 PIX *
199 pixReadJp2k(const char *filename,
200  l_uint32 reduction,
201  BOX *box,
202  l_int32 hint,
203  l_int32 debug)
204 {
205 FILE *fp;
206 PIX *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 
237 PIX *
238 pixReadStreamJp2k(FILE *fp,
239  l_uint32 reduction,
240  BOX *box,
241  l_int32 hint,
242  l_int32 debug)
243 {
244 const char *opjVersion;
245 l_int32 i, j, index, bx, by, bw, bh, val, rval, gval, bval, aval;
246 l_int32 w, h, wpl, bps, spp, xres, yres, reduce, prec, colorspace;
247 l_int32 codec; /* L_J2K_CODEC or L_JP2_CODEC */
248 l_uint32 pixel;
249 l_uint32 *data, *line;
250 opj_dparameters_t parameters; /* decompression parameters */
251 opj_image_t *image = NULL;
252 opj_codec_t *l_codec = NULL; /* handle to decompressor */
253 opj_stream_t *l_stream = NULL; /* opj stream */
254 PIX *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  *---------------------------------------------------------------------*/
477 l_ok
478 pixWriteJp2k(const char *filename,
479  PIX *pix,
480  l_int32 quality,
481  l_int32 nlevels,
482  l_int32 hint,
483  l_int32 debug)
484 {
485 FILE *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 
522 l_ok
523 pixWriteStreamJp2k(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 {
531 l_int32 w, h, d, success;
532 l_float32 snr;
533 const char *opjVersion;
534 PIX *pixs;
535 opj_cparameters_t parameters; /* compression parameters */
536 opj_stream_t *l_stream = NULL;
537 opj_codec_t* l_codec = NULL;;
538 opj_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__);
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 
698 static opj_image_t *
699 pixConvertToOpjImage(PIX *pix)
700 {
701 l_int32 i, j, k, w, h, d, spp, wpl;
702 OPJ_COLOR_SPACE colorspace;
703 l_int32 *ir = NULL;
704 l_int32 *ig = NULL;
705 l_int32 *ib = NULL;
706 l_int32 *ia = NULL;
707 l_uint32 *line, *data;
708 opj_image_t *image;
709 opj_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  *---------------------------------------------------------------------*/
793 PIX *
794 pixReadMemJp2k(const l_uint8 *data,
795  size_t size,
796  l_uint32 reduction,
797  BOX *box,
798  l_int32 hint,
799  l_int32 debug)
800 {
801 FILE *fp;
802 PIX *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 
834 l_ok
835 pixWriteMemJp2k(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 {
843 l_int32 ret;
844 FILE *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  *---------------------------------------------------------------------*/
885 static l_uint64
886 opj_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 
894 static OPJ_SIZE_T
895 opj_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 
900 static OPJ_SIZE_T
901 opj_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 
906 static OPJ_OFF_T
907 opj_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 
914 static l_int32
915 opj_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 */
923 static opj_stream_t *
924 opjCreateStream(FILE *fp,
925  l_int32 is_read_stream)
926 {
927 opj_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)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
l_ok boxGetGeometry(const BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:301
@ 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:113
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
l_ok pixSetResolution(PIX *pix, l_int32 xres, l_int32 yres)
pixSetResolution()
Definition: pix1.c:1297
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1346
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2758
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2728
@ 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
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:384
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3055
PIX * pixConvert24To32(PIX *pixs)
pixConvert24To32()
Definition: pixconv.c:3461
char * getLeptonicaVersion(void)
getLeptonicaVersion()
Definition: utils1.c:960
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1358
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1937
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1905
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:1981
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1864