97#include <config_auto.h>
101#include "allheaders.h"
109#include LIBJP2K_HEADER
120static opj_stream_t *opjCreateStream(FILE *fp, l_int32 is_read);
124static opj_image_t *pixConvertToOpjImage(
PIX *pix);
129static void error_callback(
const char *msg,
void *client_data) {
131 fprintf(stdout,
"[ERROR] %s", msg);
134static void warning_callback(
const char *msg,
void *client_data) {
136 fprintf(stdout,
"[WARNING] %s", msg);
139static void info_callback(
const char *msg,
void *client_data) {
141 fprintf(stdout,
"[INFO] %s", msg);
188pixReadJp2k(
const char *filename,
198 return (
PIX *)ERROR_PTR(
"filename not defined", __func__, NULL);
200 if ((fp = fopenReadStream(filename)) == NULL)
201 return (
PIX *)ERROR_PTR_1(
"image file not found",
202 filename, __func__, NULL);
203 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
207 return (
PIX *)ERROR_PTR_1(
"image not returned",
208 filename, __func__, NULL);
229pixReadStreamJp2k(FILE *fp,
235const char *opjVersion;
236l_int32 i, j, index, bx, by, bw, bh, val, rval, gval, bval, aval;
237l_int32 w, h, wpl, bps, spp, xres, yres, reduce, prec, colorspace;
240l_uint32 *data, *line;
241opj_dparameters_t parameters;
242opj_image_t *image = NULL;
243opj_codec_t *l_codec = NULL;
244opj_stream_t *l_stream = NULL;
248 return (
PIX *)ERROR_PTR(
"fp not defined", __func__, NULL);
250 opjVersion = opj_version();
251 if (!opjVersion || opjVersion[0] ==
'\0')
252 return (
PIX *)ERROR_PTR(
"opj version not defined", __func__, NULL);
253 if (opjVersion[0] - 0x30 < 2 ||
254 (opjVersion[0] ==
'2' && opjVersion[2] - 0x30 == 0)) {
255 L_ERROR(
"version is %s; must be 2.1 or higher\n", __func__, opjVersion);
261 fgetJp2kResolution(fp, &xres, &yres);
262 freadHeaderJp2k(fp, NULL, NULL, &bps, NULL, &codec);
265 L_ERROR(
"valid codec not identified\n", __func__);
270 L_ERROR(
"found %d bps; can only handle 8 bps\n", __func__, bps);
275 opj_set_default_decoder_parameters(¶meters);
282 for (reduce = 0; (1L << reduce) < reduction; reduce++) { }
283 if ((1L << reduce) != reduction) {
284 L_ERROR(
"invalid reduction %d; not power of 2\n", __func__, reduction);
287 parameters.cp_reduce = reduce;
291 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
293 l_codec = opj_create_decompress(OPJ_CODEC_J2K);
295 L_ERROR(
"failed to make the codec\n", __func__);
301 opj_set_info_handler(l_codec, info_callback, NULL);
302 opj_set_warning_handler(l_codec, warning_callback, NULL);
303 opj_set_error_handler(l_codec, error_callback, NULL);
307 if (!opj_setup_decoder(l_codec, ¶meters)){
308 L_ERROR(
"failed to set up decoder\n", __func__);
309 opj_destroy_codec(l_codec);
315 if ((l_stream = opjCreateStream(fp, 1)) == NULL) {
316 L_ERROR(
"failed to open the stream\n", __func__);
317 opj_destroy_codec(l_codec);
323 if(!opj_read_header(l_stream, l_codec, &image)){
324 L_ERROR(
"failed to read the header\n", __func__);
325 opj_stream_destroy(l_stream);
326 opj_destroy_codec(l_codec);
327 opj_image_destroy(image);
333 boxGetGeometry(box, &bx, &by, &bw, &bh);
334 if (!opj_set_decode_area(l_codec, image, bx, by,
336 L_ERROR(
"failed to set the region for decoding\n", __func__);
337 opj_stream_destroy(l_stream);
338 opj_destroy_codec(l_codec);
339 opj_image_destroy(image);
345 if (!(opj_decode(l_codec, l_stream, image) &&
346 opj_end_decompress(l_codec, l_stream))) {
347 L_ERROR(
"failed to decode the image\n", __func__);
348 opj_destroy_codec(l_codec);
349 opj_stream_destroy(l_stream);
350 opj_image_destroy(image);
355 opj_stream_destroy(l_stream);
356 opj_destroy_codec(l_codec);
359 spp = image->numcomps;
360 w = image->comps[0].w;
361 h = image->comps[0].h;
362 prec = image->comps[0].prec;
364 L_WARNING(
"precision %d != bps %d!\n", __func__, prec, bps);
366 L_INFO(
"w = %d, h = %d, bps = %d, spp = %d\n",
367 __func__, w, h, bps, spp);
368 colorspace = image->color_space;
369 if (colorspace == OPJ_CLRSPC_SRGB)
370 L_INFO(
"colorspace is sRGB\n", __func__);
371 else if (colorspace == OPJ_CLRSPC_GRAY)
372 L_INFO(
"colorspace is grayscale\n", __func__);
373 else if (colorspace == OPJ_CLRSPC_SYCC)
374 L_INFO(
"colorspace is YUV\n", __func__);
379 pix = pixCreate(w, h, 8);
381 pix = pixCreate(w, h, 32);
382 pixSetInputFormat(pix, IFF_JP2);
383 pixSetResolution(pix, xres, yres);
384 data = pixGetData(pix);
385 wpl = pixGetWpl(pix);
388 for (i = 0; i < h; i++) {
389 line = data + i * wpl;
390 for (j = 0; j < w; j++) {
391 val = image->comps[0].data[index];
396 }
else if (spp == 2) {
397 for (i = 0; i < h; i++) {
398 line = data + i * wpl;
399 for (j = 0; j < w; j++) {
400 val = image->comps[0].data[index];
401 aval = image->comps[1].data[index];
402 composeRGBAPixel(val, val, val, aval, &pixel);
407 }
else if (spp >= 3) {
408 for (i = 0; i < h; i++) {
409 line = data + i * wpl;
410 for (j = 0; j < w; j++) {
411 rval = image->comps[0].data[index];
412 gval = image->comps[1].data[index];
413 bval = image->comps[2].data[index];
415 composeRGBPixel(rval, gval, bval, &pixel);
417 aval = image->comps[3].data[index];
418 composeRGBAPixel(rval, gval, bval, aval, &pixel);
427 opj_image_destroy(image);
466pixWriteJp2k(
const char *filename,
476 return ERROR_INT(
"pix not defined", __func__, 1);
478 return ERROR_INT(
"filename not defined", __func__, 1);
480 if ((fp = fopenWriteStream(filename,
"wb+")) == NULL)
481 return ERROR_INT_1(
"stream not opened", filename, __func__, 1);
483 if (pixWriteStreamJp2k(fp, pix, quality, nlevels,
L_JP2_CODEC,
486 return ERROR_INT_1(
"pix not written to stream", filename, __func__, 1);
511pixWriteStreamJp2k(FILE *fp,
519l_int32 w, h, d, success;
521const char *opjVersion;
523opj_cparameters_t parameters;
524opj_stream_t *l_stream = NULL;
525opj_codec_t* l_codec = NULL;;
526opj_image_t *image = NULL;
529 return ERROR_INT(
"stream not open", __func__, 1);
531 return ERROR_INT(
"pix not defined", __func__, 1);
533 snr = (l_float32)quality;
534 if (snr <= 0) snr = 34.0;
536 L_WARNING(
"SNR = %d < 27; very low\n", __func__, (l_int32)snr);
537 if (snr == 100) snr = 0;
539 L_WARNING(
"SNR > 45; using lossless encoding\n", __func__);
543 if (nlevels <= 0) nlevels = 5;
545 L_WARNING(
"nlevels = %d > 10; setting to 10\n", __func__, nlevels);
549 return ERROR_INT(
"valid codec not identified\n", __func__, 1);
551 opjVersion = opj_version();
552 if (!opjVersion || opjVersion[0] ==
'\0')
553 return ERROR_INT(
"opj version not defined", __func__, 1);
554 if (opjVersion[0] - 0x30 < 2 ||
555 (opjVersion[0] ==
'2' && opjVersion[2] - 0x30 == 0)) {
556 L_ERROR(
"version is %s; must be 2.1 or higher\n", __func__, opjVersion);
561 pixGetDimensions(pix, &w, &h, &d);
563 pixs = pixConvert24To32(pix);
564 }
else if (d == 32) {
565 pixs = pixClone(pix);
566 }
else if (pixGetColormap(pix) == NULL) {
567 pixs = pixConvertTo8(pix, 0);
569 L_INFO(
"removing colormap; may be better to compress losslessly\n",
575 pixSetPadBits(pixs, 0);
576 image = pixConvertToOpjImage(pixs);
581 opj_set_default_encoder_parameters(¶meters);
582 parameters.cp_fixed_quality = 1;
583 parameters.cp_disto_alloc = 0;
584 parameters.cp_fixed_alloc = 0;
585 parameters.tcp_distoratio[0] = snr;
586 parameters.tcp_numlayers = 1;
587 parameters.numresolution = nlevels;
590 if (parameters.cp_comment == NULL) {
591 const char comment1[] =
"Created by Leptonica, version ";
592 const char comment2[] =
"; using OpenJPEG, version ";
593 size_t len1 = strlen(comment1);
594 size_t len2 = strlen(comment2);
595 char *version1 = getLeptonicaVersion();
596 const char *version2 = opj_version();
597 len1 += len2 + strlen(version1) + strlen(version2) + 1;
598 parameters.cp_comment = (
char *)LEPT_MALLOC(len1);
599 snprintf(parameters.cp_comment, len1,
"%s%s%s%s", comment1, version1,
606 l_codec = opj_create_compress(OPJ_CODEC_JP2);
608 l_codec = opj_create_compress(OPJ_CODEC_J2K);
610 opj_image_destroy(image);
611 LEPT_FREE(parameters.cp_comment);
612 return ERROR_INT(
"failed to get the encoder handle\n", __func__, 1);
617 opj_set_info_handler(l_codec, info_callback, NULL);
618 opj_set_warning_handler(l_codec, warning_callback, NULL);
619 opj_set_error_handler(l_codec, error_callback, NULL);
623 if (!opj_setup_encoder(l_codec, ¶meters, image)) {
624 opj_destroy_codec(l_codec);
625 opj_image_destroy(image);
626 LEPT_FREE(parameters.cp_comment);
627 return ERROR_INT(
"failed to set up the encoder\n", __func__, 1);
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", __func__, 1);
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", __func__, 1);
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", __func__, 1);
657 success = opj_end_compress(l_codec, l_stream);
660 opj_stream_destroy(l_stream);
661 opj_destroy_codec(l_codec);
662 opj_image_destroy(image);
663 LEPT_FREE(parameters.cp_comment);
667 return ERROR_INT(
"opj_end_compress failed\n", __func__, 1);
684pixConvertToOpjImage(
PIX *pix)
686l_int32 i, j, k, w, h, d, spp, wpl;
687OPJ_COLOR_SPACE colorspace;
692l_uint32 *line, *data;
694opj_image_cmptparm_t cmptparm[4];
697 return (opj_image_t *)ERROR_PTR(
"pix not defined", __func__, NULL);
698 pixGetDimensions(pix, &w, &h, &d);
699 if (d != 8 && d != 32) {
700 L_ERROR(
"invalid depth: %d\n", __func__, d);
705 spp = pixGetSpp(pix);
706 memset(&cmptparm[0], 0, 4 *
sizeof(opj_image_cmptparm_t));
707 for (i = 0; i < spp; i++) {
708 cmptparm[i].prec = 8;
709 cmptparm[i].sgnd = 0;
715 colorspace = (spp == 1) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB;
716 if ((image = opj_image_create(spp, &cmptparm[0], colorspace)) == NULL)
717 return (opj_image_t *)ERROR_PTR(
"image not made", __func__, NULL);
724 ir = image->comps[0].data;
726 ig = image->comps[1].data;
727 ib = image->comps[2].data;
730 ia = image->comps[3].data;
733 data = pixGetData(pix);
734 wpl = pixGetWpl(pix);
735 for (i = 0, k = 0; i < h; i++) {
736 line = data + i * wpl;
737 for (j = 0; j < w; j++, k++) {
740 }
else if (spp > 1) {
777pixReadMemJp2k(
const l_uint8 *data,
788 return (
PIX *)ERROR_PTR(
"data not defined", __func__, NULL);
790 if ((fp = fopenReadFromMemory(data, size)) == NULL)
791 return (
PIX *)ERROR_PTR(
"stream not opened", __func__, NULL);
792 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
794 if (!pix) L_ERROR(
"pix not read\n", __func__);
818pixWriteMemJp2k(l_uint8 **pdata,
829 if (pdata) *pdata = NULL;
830 if (psize) *psize = 0;
832 return ERROR_INT(
"&data not defined", __func__, 1 );
834 return ERROR_INT(
"&size not defined", __func__, 1 );
836 return ERROR_INT(
"&pix not defined", __func__, 1 );
839 if ((fp = open_memstream((
char **)pdata, psize)) == NULL)
840 return ERROR_INT(
"stream not opened", __func__, 1);
841 ret = pixWriteStreamJp2k(fp, pix, quality, nlevels,
L_JP2_CODEC,
847 L_INFO(
"no fmemopen API --> work-around: writing to a temp file\n", __func__);
849 if ((fp = fopenWriteWinTempfile()) == NULL)
850 return ERROR_INT(
"tmpfile stream not opened", __func__, 1);
852 if ((fp = tmpfile()) == NULL)
853 return ERROR_INT(
"tmpfile stream not opened", __func__, 1);
855 ret = pixWriteStreamJp2k(fp, pix, quality, nlevels,
L_JP2_CODEC,
858 *pdata = l_binaryReadStream(fp, psize);
869opj_get_user_data_length(FILE *fp) {
870 OPJ_OFF_T length = 0;
871 fseek(fp, 0, SEEK_END);
872 length = (OPJ_OFF_T)ftell(fp);
873 fseek(fp, 0, SEEK_SET);
874 return (l_uint64)length;
878opj_read_from_file(
void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp) {
879 OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, fp);
880 return l_nb_read ? l_nb_read : (OPJ_SIZE_T) - 1;
884opj_write_from_file(
void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp)
886 return fwrite(p_buffer, 1, p_nb_bytes, fp);
890opj_skip_from_file(OPJ_OFF_T offset, FILE *fp) {
891 if (fseek(fp, offset, SEEK_CUR)) {
898opj_seek_from_file(OPJ_OFF_T offset, FILE *fp) {
899 if (fseek(fp, offset, SEEK_SET)) {
907opjCreateStream(FILE *fp,
908 l_int32 is_read_stream)
910opj_stream_t *l_stream;
913 return (opj_stream_t *)ERROR_PTR(
"fp not defined", __func__, NULL);
915 l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, is_read_stream);
917 return (opj_stream_t *)ERROR_PTR(
"stream not made", __func__, NULL);
919 opj_stream_set_user_data(l_stream, fp,
920 (opj_stream_free_user_data_fn)NULL);
921 opj_stream_set_user_data_length(l_stream, opj_get_user_data_length(fp));
922 opj_stream_set_read_function(l_stream,
923 (opj_stream_read_fn)opj_read_from_file);
924 opj_stream_set_write_function(l_stream,
925 (opj_stream_write_fn)opj_write_from_file);
926 opj_stream_set_skip_function(l_stream,
927 (opj_stream_skip_fn)opj_skip_from_file);
928 opj_stream_set_seek_function(l_stream,
929 (opj_stream_seek_fn)opj_seek_from_file);
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
@ REMOVE_CMAP_BASED_ON_SRC