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. */
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  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 
239 PIX *
240 pixReadStreamJp2k(FILE *fp,
241  l_uint32 reduction,
242  BOX *box,
243  l_int32 hint,
244  l_int32 debug)
245 {
246 const char *opjVersion;
247 l_int32 i, j, index, bx, by, bw, bh, val, rval, gval, bval, aval;
248 l_int32 w, h, wpl, bps, spp, xres, yres, reduce, prec, colorspace;
249 l_int32 codec; /* L_J2K_CODEC or L_JP2_CODEC */
250 l_uint32 pixel;
251 l_uint32 *data, *line;
252 opj_dparameters_t parameters; /* decompression parameters */
253 opj_image_t *image = NULL;
254 opj_codec_t *l_codec = NULL; /* handle to decompressor */
255 opj_stream_t *l_stream = NULL; /* opj stream */
256 PIX *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  *---------------------------------------------------------------------*/
481 l_ok
482 pixWriteJp2k(const char *filename,
483  PIX *pix,
484  l_int32 quality,
485  l_int32 nlevels,
486  l_int32 hint,
487  l_int32 debug)
488 {
489 FILE *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 
528 l_ok
529 pixWriteStreamJp2k(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 {
537 l_int32 w, h, d, success;
538 l_float32 snr;
539 const char *opjVersion;
540 PIX *pixs;
541 opj_cparameters_t parameters; /* compression parameters */
542 opj_stream_t *l_stream = NULL;
543 opj_codec_t* l_codec = NULL;;
544 opj_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 
706 static opj_image_t *
707 pixConvertToOpjImage(PIX *pix)
708 {
709 l_int32 i, j, k, w, h, d, spp, wpl;
710 OPJ_COLOR_SPACE colorspace;
711 l_int32 *ir = NULL;
712 l_int32 *ig = NULL;
713 l_int32 *ib = NULL;
714 l_int32 *ia = NULL;
715 l_uint32 *line, *data;
716 opj_image_t *image;
717 opj_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  *---------------------------------------------------------------------*/
803 PIX *
804 pixReadMemJp2k(const l_uint8 *data,
805  size_t size,
806  l_uint32 reduction,
807  BOX *box,
808  l_int32 hint,
809  l_int32 debug)
810 {
811 FILE *fp;
812 PIX *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 
846 l_ok
847 pixWriteMemJp2k(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 {
855 l_int32 ret;
856 FILE *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  *---------------------------------------------------------------------*/
899 static l_uint64
900 opj_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 
908 static OPJ_SIZE_T
909 opj_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 
914 static OPJ_SIZE_T
915 opj_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 
920 static OPJ_OFF_T
921 opj_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 
928 static l_int32
929 opj_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 */
937 static opj_stream_t *
938 opjCreateStream(FILE *fp,
939  l_int32 is_read_stream)
940 {
941 opj_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_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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 * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
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 * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
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
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:2009
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:2055
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932