Leptonica  1.77.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_uint32 pixel;
250 l_uint32 *data, *line;
251 opj_dparameters_t parameters; /* decompression parameters */
252 opj_image_t *image = NULL;
253 opj_codec_t *l_codec = NULL; /* handle to decompressor */
254 opj_stream_t *l_stream = NULL; /* opj stream */
255 PIX *pix = NULL;
256 
257  PROCNAME("pixReadStreamJp2k");
258 
259  if (!fp)
260  return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
261 
262  opjVersion = opj_version();
263  if (opjVersion[0] != '2') {
264  L_ERROR("version is %s; must be 2.0 or higher\n", procName, opjVersion);
265  return NULL;
266  }
267  if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
268  L_ERROR("version %s: differs from minor = %d\n",
269  procName, opjVersion, OPJ_VERSION_MINOR);
270  return NULL;
271  }
272 
273  /* Get the resolution and the bits/sample */
274  rewind(fp);
275  fgetJp2kResolution(fp, &xres, &yres);
276  freadHeaderJp2k(fp, NULL, NULL, &bps, NULL);
277  rewind(fp);
278 
279  if (bps > 8) {
280  L_ERROR("found %d bps; can only handle 8 bps\n", procName, bps);
281  return NULL;
282  }
283 
284  /* Set decoding parameters to default values */
285  opj_set_default_decoder_parameters(&parameters);
286 
287  /* Find and set the reduce parameter, which is log2(reduction).
288  * Valid reductions are powers of 2, and are determined when the
289  * compressed string is made. A request for an invalid reduction
290  * will cause an error in opj_read_header(), and no image will
291  * be returned. */
292  for (reduce = 0; (1L << reduce) < reduction; reduce++) { }
293  if ((1L << reduce) != reduction) {
294  L_ERROR("invalid reduction %d; not power of 2\n", procName, reduction);
295  return NULL;
296  }
297  parameters.cp_reduce = reduce;
298 
299  /* Get a decoder handle */
300  if ((l_codec = opj_create_decompress(OPJ_CODEC_JP2)) == NULL) {
301  L_ERROR("failed to make the codec\n", procName);
302  return NULL;
303  }
304 
305  /* Catch and report events using callbacks */
306  if (debug) {
307  opj_set_info_handler(l_codec, info_callback, NULL);
308  opj_set_warning_handler(l_codec, warning_callback, NULL);
309  opj_set_error_handler(l_codec, error_callback, NULL);
310  }
311 
312  /* Setup the decoding parameters using user parameters */
313  if (!opj_setup_decoder(l_codec, &parameters)){
314  L_ERROR("failed to set up decoder\n", procName);
315  opj_destroy_codec(l_codec);
316  return NULL;
317  }
318 
319  /* Open decompression 'stream'. In 2.0, we could call this:
320  * opj_stream_create_default_file_stream(fp, 1)
321  * but the file stream interface was removed in 2.1. */
322  if ((l_stream = opjCreateStream(fp, 1)) == NULL) {
323  L_ERROR("failed to open the stream\n", procName);
324  opj_destroy_codec(l_codec);
325  return NULL;
326  }
327 
328  /* Read the main header of the codestream and, if necessary,
329  * the JP2 boxes */
330  if(!opj_read_header(l_stream, l_codec, &image)){
331  L_ERROR("failed to read the header\n", procName);
332  opj_stream_destroy(l_stream);
333  opj_destroy_codec(l_codec);
334  opj_image_destroy(image);
335  return NULL;
336  }
337 
338  /* Set up to decode a rectangular region */
339  if (box) {
340  boxGetGeometry(box, &bx, &by, &bw, &bh);
341  if (!opj_set_decode_area(l_codec, image, bx, by,
342  bx + bw, by + bh)) {
343  L_ERROR("failed to set the region for decoding\n", procName);
344  opj_stream_destroy(l_stream);
345  opj_destroy_codec(l_codec);
346  opj_image_destroy(image);
347  return NULL;
348  }
349  }
350 
351  /* Get the decoded image */
352  if (!(opj_decode(l_codec, l_stream, image) &&
353  opj_end_decompress(l_codec, l_stream))) {
354  L_ERROR("failed to decode the image\n", procName);
355  opj_destroy_codec(l_codec);
356  opj_stream_destroy(l_stream);
357  opj_image_destroy(image);
358  return NULL;
359  }
360 
361  /* Finished with the byte stream and the codec */
362  opj_stream_destroy(l_stream);
363  opj_destroy_codec(l_codec);
364 
365  /* Get the image parameters */
366  spp = image->numcomps;
367  w = image->comps[0].w;
368  h = image->comps[0].h;
369  prec = image->comps[0].prec;
370  if (prec != bps)
371  L_WARNING("precision %d != bps %d!\n", procName, prec, bps);
372  if (debug) {
373  L_INFO("w = %d, h = %d, bps = %d, spp = %d\n",
374  procName, w, h, bps, spp);
375  colorspace = image->color_space;
376  if (colorspace == OPJ_CLRSPC_SRGB)
377  L_INFO("colorspace is sRGB\n", procName);
378  else if (colorspace == OPJ_CLRSPC_GRAY)
379  L_INFO("colorspace is grayscale\n", procName);
380  else if (colorspace == OPJ_CLRSPC_SYCC)
381  L_INFO("colorspace is YUV\n", procName);
382  }
383 
384  /* Convert the image to a pix */
385  if (spp == 1)
386  pix = pixCreate(w, h, 8);
387  else
388  pix = pixCreate(w, h, 32);
389  pixSetInputFormat(pix, IFF_JP2);
390  pixSetResolution(pix, xres, yres);
391  data = pixGetData(pix);
392  wpl = pixGetWpl(pix);
393  index = 0;
394  if (spp == 1) {
395  for (i = 0; i < h; i++) {
396  line = data + i * wpl;
397  for (j = 0; j < w; j++) {
398  val = image->comps[0].data[index];
399  SET_DATA_BYTE(line, j, val);
400  index++;
401  }
402  }
403  } else if (spp == 2) { /* convert to RGBA */
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  aval = image->comps[1].data[index];
409  composeRGBAPixel(val, val, val, aval, &pixel);
410  line[j] = pixel;
411  index++;
412  }
413  }
414  } else if (spp >= 3) {
415  for (i = 0; i < h; i++) {
416  line = data + i * wpl;
417  for (j = 0; j < w; j++) {
418  rval = image->comps[0].data[index];
419  gval = image->comps[1].data[index];
420  bval = image->comps[2].data[index];
421  if (spp == 3) {
422  composeRGBPixel(rval, gval, bval, &pixel);
423  } else { /* spp == 4 */
424  aval = image->comps[3].data[index];
425  composeRGBAPixel(rval, gval, bval, aval, &pixel);
426  }
427  line[j] = pixel;
428  index++;
429  }
430  }
431  }
432 
433  /* Free the opj image data structure */
434  opj_image_destroy(image);
435 
436  return pix;
437 }
438 
439 
440 /*---------------------------------------------------------------------*
441  * Write jp2k to file *
442  *---------------------------------------------------------------------*/
471 l_ok
472 pixWriteJp2k(const char *filename,
473  PIX *pix,
474  l_int32 quality,
475  l_int32 nlevels,
476  l_int32 hint,
477  l_int32 debug)
478 {
479 FILE *fp;
480 
481  PROCNAME("pixWriteJp2k");
482 
483  if (!pix)
484  return ERROR_INT("pix not defined", procName, 1);
485  if (!filename)
486  return ERROR_INT("filename not defined", procName, 1);
487 
488  if ((fp = fopenWriteStream(filename, "wb+")) == NULL)
489  return ERROR_INT("stream not opened", procName, 1);
490 
491  if (pixWriteStreamJp2k(fp, pix, quality, nlevels, hint, debug)) {
492  fclose(fp);
493  return ERROR_INT("pix not written to stream", procName, 1);
494  }
495 
496  fclose(fp);
497  return 0;
498 }
499 
500 
518 l_ok
519 pixWriteStreamJp2k(FILE *fp,
520  PIX *pix,
521  l_int32 quality,
522  l_int32 nlevels,
523  l_int32 hint,
524  l_int32 debug)
525 {
526 l_int32 w, h, d, success, snr;
527 const char *opjVersion;
528 PIX *pixs;
529 opj_cparameters_t parameters; /* compression parameters */
530 opj_stream_t *l_stream = NULL;
531 opj_codec_t* l_codec = NULL;;
532 opj_image_t *image = NULL;
533 
534  PROCNAME("pixWriteStreamJp2k");
535 
536  if (!fp)
537  return ERROR_INT("stream not open", procName, 1);
538  if (!pix)
539  return ERROR_INT("pix not defined", procName, 1);
540  if (quality < 0)
541  return ERROR_INT("quality must be >= 0", procName, 1);
542  if (quality > 0 && quality < 27)
543  L_WARNING("SNR = %d < 27; very low\n", procName, quality);
544  if (quality > 45)
545  L_WARNING("SNR = %d > 45; nearly lossless\n", procName, quality);
546  snr = (l_float32)quality;
547 
548  if (nlevels <= 0) nlevels = 5; /* default */
549  if (nlevels > 10) {
550  L_WARNING("nlevels = %d > 10; setting to 10\n", procName, nlevels);
551  nlevels = 10;
552  }
553 
554  opjVersion = opj_version();
555  if (opjVersion[0] != '2') {
556  L_ERROR("version is %s; must be 2.0 or higher\n", procName, opjVersion);
557  return 1;
558  }
559  if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
560  L_ERROR("version %s: differs from minor = %d\n",
561  procName, opjVersion, OPJ_VERSION_MINOR);
562  return 1;
563  }
564 
565  /* Remove colormap if it exists; result is 8 or 32 bpp */
566  pixGetDimensions(pix, &w, &h, &d);
567  if (d == 24) {
568  pixs = pixConvert24To32(pix);
569  } else if (d == 32) {
570  pixs = pixClone(pix);
571  } else if (pixGetColormap(pix) == NULL) {
572  pixs = pixConvertTo8(pix, 0);
573  } else { /* colormap */
574  L_INFO("removing colormap; may be better to compress losslessly\n",
575  procName);
577  }
578 
579  /* Convert to opj image format. */
580  pixSetPadBits(pixs, 0);
581  image = pixConvertToOpjImage(pixs);
582  pixDestroy(&pixs);
583 
584  /* Set encoding parameters to default values.
585  * We use one layer with the input SNR. */
586  opj_set_default_encoder_parameters(&parameters);
587  parameters.cp_fixed_quality = 1;
588  parameters.cp_disto_alloc = 0;
589  parameters.cp_fixed_alloc = 0;
590  parameters.tcp_distoratio[0] = snr;
591  parameters.tcp_numlayers = 1;
592  parameters.numresolution = nlevels + 1;
593 
594  /* Create comment for codestream */
595  if (parameters.cp_comment == NULL) {
596  const char comment1[] = "Created by Leptonica, version ";
597  const char comment2[] = "; using OpenJPEG, version ";
598  size_t len1 = strlen(comment1);
599  size_t len2 = strlen(comment2);
600  char *version1 = getLeptonicaVersion();
601  const char *version2 = opj_version();
602  len1 += len2 + strlen(version1) + strlen(version2) + 1;
603  parameters.cp_comment = (char *)LEPT_MALLOC(len1);
604  snprintf(parameters.cp_comment, len1, "%s%s%s%s", comment1, version1,
605  comment2, version2);
606  LEPT_FREE(version1);
607  }
608 
609  /* Get the encoder handle */
610  if ((l_codec = opj_create_compress(OPJ_CODEC_JP2)) == NULL) {
611  opj_image_destroy(image);
612  LEPT_FREE(parameters.cp_comment);
613  return ERROR_INT("failed to get the encoder handle\n", procName, 1);
614  }
615 
616  /* Catch and report events using callbacks */
617  if (debug) {
618  opj_set_info_handler(l_codec, info_callback, NULL);
619  opj_set_warning_handler(l_codec, warning_callback, NULL);
620  opj_set_error_handler(l_codec, error_callback, NULL);
621  }
622 
623  /* Set up the encoder */
624  if (!opj_setup_encoder(l_codec, &parameters, image)) {
625  opj_destroy_codec(l_codec);
626  opj_image_destroy(image);
627  LEPT_FREE(parameters.cp_comment);
628  return ERROR_INT("failed to set up the encoder\n", procName, 1);
629  }
630 
631  /* Open a compression stream for writing. In 2.0 we could use this:
632  * opj_stream_create_default_file_stream(fp, 0)
633  * but the file stream interface was removed in 2.1. */
634  rewind(fp);
635  if ((l_stream = opjCreateStream(fp, 0)) == NULL) {
636  opj_destroy_codec(l_codec);
637  opj_image_destroy(image);
638  LEPT_FREE(parameters.cp_comment);
639  return ERROR_INT("failed to open l_stream\n", procName, 1);
640  }
641 
642  /* Encode the image */
643  if (!opj_start_compress(l_codec, image, l_stream)) {
644  opj_stream_destroy(l_stream);
645  opj_destroy_codec(l_codec);
646  opj_image_destroy(image);
647  LEPT_FREE(parameters.cp_comment);
648  return ERROR_INT("opj_start_compress failed\n", procName, 1);
649  }
650  if (!opj_encode(l_codec, l_stream)) {
651  opj_stream_destroy(l_stream);
652  opj_destroy_codec(l_codec);
653  opj_image_destroy(image);
654  LEPT_FREE(parameters.cp_comment);
655  return ERROR_INT("opj_encode failed\n", procName, 1);
656  }
657  success = opj_end_compress(l_codec, l_stream);
658 
659  /* Clean up */
660  opj_stream_destroy(l_stream);
661  opj_destroy_codec(l_codec);
662  opj_image_destroy(image);
663  LEPT_FREE(parameters.cp_comment);
664  if (success)
665  return 0;
666  else
667  return ERROR_INT("opj_end_compress failed\n", procName, 1);
668 }
669 
670 
683 static opj_image_t *
684 pixConvertToOpjImage(PIX *pix)
685 {
686 l_int32 i, j, k, w, h, d, spp, wpl;
687 OPJ_COLOR_SPACE colorspace;
688 l_int32 *ir = NULL;
689 l_int32 *ig = NULL;
690 l_int32 *ib = NULL;
691 l_int32 *ia = NULL;
692 l_uint32 *line, *data;
693 opj_image_t *image;
694 opj_image_cmptparm_t cmptparm[4];
695 
696  PROCNAME("pixConvertToOpjImage");
697 
698  if (!pix)
699  return (opj_image_t *)ERROR_PTR("pix not defined", procName, NULL);
700  pixGetDimensions(pix, &w, &h, &d);
701  if (d != 8 && d != 32) {
702  L_ERROR("invalid depth: %d\n", procName, d);
703  return NULL;
704  }
705 
706  /* Allocate the opj_image. */
707  spp = pixGetSpp(pix);
708  memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
709  for (i = 0; i < spp; i++) {
710  cmptparm[i].prec = 8;
711  cmptparm[i].bpp = 8;
712  cmptparm[i].sgnd = 0;
713  cmptparm[i].dx = 1;
714  cmptparm[i].dy = 1;
715  cmptparm[i].w = w;
716  cmptparm[i].h = h;
717  }
718  colorspace = (spp == 1) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB;
719  if ((image = opj_image_create(spp, &cmptparm[0], colorspace)) == NULL)
720  return (opj_image_t *)ERROR_PTR("image not made", procName, NULL);
721  image->x0 = 0;
722  image->y0 = 0;
723  image->x1 = w;
724  image->y1 = h;
725 
726  /* Set the component pointers */
727  ir = image->comps[0].data;
728  if (spp > 1) {
729  ig = image->comps[1].data;
730  ib = image->comps[2].data;
731  }
732  if(spp == 4)
733  ia = image->comps[3].data;
734 
735  /* Transfer the data from the pix */
736  data = pixGetData(pix);
737  wpl = pixGetWpl(pix);
738  for (i = 0, k = 0; i < h; i++) {
739  line = data + i * wpl;
740  for (j = 0; j < w; j++, k++) {
741  if (spp == 1) {
742  ir[k] = GET_DATA_BYTE(line, j);
743  } else if (spp > 1) {
744  ir[k] = GET_DATA_BYTE(line + j, COLOR_RED);
745  ig[k] = GET_DATA_BYTE(line + j, COLOR_GREEN);
746  ib[k] = GET_DATA_BYTE(line + j, COLOR_BLUE);
747  }
748  if (spp == 4)
749  ia[k] = GET_DATA_BYTE(line + j, L_ALPHA_CHANNEL);
750  }
751  }
752 
753  return image;
754 }
755 
756 
757 /*---------------------------------------------------------------------*
758  * Read/write to memory *
759  *---------------------------------------------------------------------*/
760 
781 PIX *
782 pixReadMemJp2k(const l_uint8 *data,
783  size_t size,
784  l_uint32 reduction,
785  BOX *box,
786  l_int32 hint,
787  l_int32 debug)
788 {
789 FILE *fp;
790 PIX *pix;
791 
792  PROCNAME("pixReadMemJp2k");
793 
794  if (!data)
795  return (PIX *)ERROR_PTR("data not defined", procName, NULL);
796 
797  if ((fp = fopenReadFromMemory(data, size)) == NULL)
798  return (PIX *)ERROR_PTR("stream not opened", procName, NULL);
799  pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
800  fclose(fp);
801  if (!pix) L_ERROR("pix not read\n", procName);
802  return pix;
803 }
804 
805 
824 l_ok
825 pixWriteMemJp2k(l_uint8 **pdata,
826  size_t *psize,
827  PIX *pix,
828  l_int32 quality,
829  l_int32 nlevels,
830  l_int32 hint,
831  l_int32 debug)
832 {
833 l_int32 ret;
834 FILE *fp;
835 
836  PROCNAME("pixWriteMemJp2k");
837 
838  if (pdata) *pdata = NULL;
839  if (psize) *psize = 0;
840  if (!pdata)
841  return ERROR_INT("&data not defined", procName, 1 );
842  if (!psize)
843  return ERROR_INT("&size not defined", procName, 1 );
844  if (!pix)
845  return ERROR_INT("&pix not defined", procName, 1 );
846 
847 #if HAVE_FMEMOPEN
848  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
849  return ERROR_INT("stream not opened", procName, 1);
850  ret = pixWriteStreamJp2k(fp, pix, quality, nlevels, hint, debug);
851 #else
852  L_INFO("work-around: writing to a temp file\n", procName);
853  #ifdef _WIN32
854  if ((fp = fopenWriteWinTempfile()) == NULL)
855  return ERROR_INT("tmpfile stream not opened", procName, 1);
856  #else
857  if ((fp = tmpfile()) == NULL)
858  return ERROR_INT("tmpfile stream not opened", procName, 1);
859  #endif /* _WIN32 */
860  ret = pixWriteStreamJp2k(fp, pix, quality, nlevels, hint, debug);
861  rewind(fp);
862  *pdata = l_binaryReadStream(fp, psize);
863 #endif /* HAVE_FMEMOPEN */
864  fclose(fp);
865  return ret;
866 }
867 
868 
869 /*---------------------------------------------------------------------*
870  * Static functions from opj 2.0 to retain file stream interface *
871  *---------------------------------------------------------------------*/
872 static l_uint64
873 opj_get_user_data_length(FILE *fp) {
874  OPJ_OFF_T length = 0;
875  fseek(fp, 0, SEEK_END);
876  length = (OPJ_OFF_T)ftell(fp);
877  fseek(fp, 0, SEEK_SET);
878  return (l_uint64)length;
879 }
880 
881 static OPJ_SIZE_T
882 opj_read_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp) {
883  OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, fp);
884  return l_nb_read ? l_nb_read : (OPJ_SIZE_T) - 1;
885 }
886 
887 static OPJ_SIZE_T
888 opj_write_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp)
889 {
890  return fwrite(p_buffer, 1, p_nb_bytes, fp);
891 }
892 
893 static OPJ_OFF_T
894 opj_skip_from_file(OPJ_OFF_T offset, FILE *fp) {
895  if (fseek(fp, offset, SEEK_CUR)) {
896  return -1;
897  }
898  return offset;
899 }
900 
901 static l_int32
902 opj_seek_from_file(OPJ_OFF_T offset, FILE *fp) {
903  if (fseek(fp, offset, SEEK_SET)) {
904  return 0;
905  }
906  return 1;
907 }
908 
909  /* Static generator of opj_stream from file stream */
910 static opj_stream_t *
911 opjCreateStream(FILE *fp,
912  l_int32 is_read_stream)
913 {
914 opj_stream_t *l_stream;
915 
916  PROCNAME("opjCreateStream");
917 
918  if (!fp)
919  return (opj_stream_t *)ERROR_PTR("fp not defined", procName, NULL);
920 
921  l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, is_read_stream);
922  if (!l_stream)
923  return (opj_stream_t *)ERROR_PTR("stream not made", procName, NULL);
924 
925 #if OPJ_VERSION_MINOR == 0
926  opj_stream_set_user_data(l_stream, fp);
927 #else
928  opj_stream_set_user_data(l_stream, fp,
929  (opj_stream_free_user_data_fn)NULL);
930 #endif
931  opj_stream_set_user_data_length(l_stream, opj_get_user_data_length(fp));
932  opj_stream_set_read_function(l_stream,
933  (opj_stream_read_fn)opj_read_from_file);
934  opj_stream_set_write_function(l_stream,
935  (opj_stream_write_fn)opj_write_from_file);
936  opj_stream_set_skip_function(l_stream,
937  (opj_stream_skip_fn)opj_skip_from_file);
938  opj_stream_set_seek_function(l_stream,
939  (opj_stream_seek_fn)opj_seek_from_file);
940 
941  return l_stream;
942 }
943 
944 /* --------------------------------------------*/
945 #endif /* HAVE_LIBJP2K */
946 /* --------------------------------------------*/
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:322
l_ok freadHeaderJp2k(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp)
freadHeaderJp2k()
Definition: jp2kheader.c:112
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1734
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
PIX * pixConvert24To32(PIX *pixs)
pixConvert24To32()
Definition: pixconv.c:3456
char * getLeptonicaVersion()
getLeptonicaVersion()
Definition: utils1.c:810
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2702
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1307
FILE * fopenWriteWinTempfile()
fopenWriteWinTempfile()
Definition: utils2.c:1780
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
struct Pix * pix
Definition: jbclass.h:106
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
l_int32 w
Definition: jbclass.h:108
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1700
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1657
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1262
l_int32 h
Definition: jbclass.h:109
Definition: pix.h:134
Definition: pix.h:201
l_ok pixSetResolution(PIX *pix, l_int32 xres, l_int32 yres)
pixSetResolution()
Definition: pix1.c:1339
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:310
Definition: pix.h:480