103 #include <config_auto.h>
107 #include "allheaders.h"
114 #ifdef LIBJP2K_HEADER
115 #include LIBJP2K_HEADER
117 #include <openjpeg.h>
121 #ifndef OPJ_VERSION_MINOR
122 #define OPJ_VERSION_MINOR 0
131 static opj_stream_t *opjCreateStream(FILE *fp, l_int32 is_read);
135 static opj_image_t *pixConvertToOpjImage(
PIX *pix);
140 static void error_callback(
const char *msg,
void *client_data) {
142 fprintf(stdout,
"[ERROR] %s", msg);
145 static void warning_callback(
const char *msg,
void *client_data) {
147 fprintf(stdout,
"[WARNING] %s", msg);
150 static void info_callback(
const char *msg,
void *client_data) {
152 fprintf(stdout,
"[INFO] %s", msg);
199 pixReadJp2k(
const char *filename,
209 return (
PIX *)ERROR_PTR(
"filename not defined", __func__, NULL);
212 return (
PIX *)ERROR_PTR(
"image file not found", __func__, NULL);
213 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
217 return (
PIX *)ERROR_PTR(
"image not returned", __func__, NULL);
238 pixReadStreamJp2k(FILE *fp,
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;
249 l_uint32 *data, *line;
250 opj_dparameters_t parameters;
251 opj_image_t *image = NULL;
252 opj_codec_t *l_codec = NULL;
253 opj_stream_t *l_stream = NULL;
257 return (
PIX *)ERROR_PTR(
"fp not defined", __func__, NULL);
259 opjVersion = opj_version();
260 if (opjVersion[0] !=
'2') {
261 L_ERROR(
"version is %s; must be 2.0 or higher\n", __func__, opjVersion);
264 if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
265 L_ERROR(
"version %s: differs from minor = %d\n",
266 __func__, opjVersion, OPJ_VERSION_MINOR);
272 fgetJp2kResolution(fp, &xres, &yres);
276 L_ERROR(
"valid codec not identified\n", __func__);
281 L_ERROR(
"found %d bps; can only handle 8 bps\n", __func__, bps);
286 opj_set_default_decoder_parameters(¶meters);
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);
298 parameters.cp_reduce = reduce;
302 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
304 l_codec = opj_create_decompress(OPJ_CODEC_J2K);
306 L_ERROR(
"failed to make the codec\n", __func__);
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);
318 if (!opj_setup_decoder(l_codec, ¶meters)){
319 L_ERROR(
"failed to set up decoder\n", __func__);
320 opj_destroy_codec(l_codec);
327 if ((l_stream = opjCreateStream(fp, 1)) == NULL) {
328 L_ERROR(
"failed to open the stream\n", __func__);
329 opj_destroy_codec(l_codec);
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);
346 if (!opj_set_decode_area(l_codec, image, bx, by,
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);
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);
367 opj_stream_destroy(l_stream);
368 opj_destroy_codec(l_codec);
371 spp = image->numcomps;
372 w = image->comps[0].w;
373 h = image->comps[0].h;
374 prec = image->comps[0].prec;
376 L_WARNING(
"precision %d != bps %d!\n", __func__, prec, bps);
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__);
394 pixSetInputFormat(pix, IFF_JP2);
397 wpl = pixGetWpl(pix);
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];
408 }
else if (spp == 2) {
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];
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];
429 aval = image->comps[3].data[index];
439 opj_image_destroy(image);
478 pixWriteJp2k(
const char *filename,
488 return ERROR_INT(
"pix not defined", __func__, 1);
490 return ERROR_INT(
"filename not defined", __func__, 1);
493 return ERROR_INT(
"stream not opened", __func__, 1);
495 if (pixWriteStreamJp2k(fp, pix, quality, nlevels,
L_JP2_CODEC,
498 return ERROR_INT(
"pix not written to stream", __func__, 1);
523 pixWriteStreamJp2k(FILE *fp,
531 l_int32 w, h, d, success;
533 const char *opjVersion;
535 opj_cparameters_t parameters;
536 opj_stream_t *l_stream = NULL;
537 opj_codec_t* l_codec = NULL;;
538 opj_image_t *image = NULL;
541 return ERROR_INT(
"stream not open", __func__, 1);
543 return ERROR_INT(
"pix not defined", __func__, 1);
545 snr = (l_float32)quality;
546 if (snr <= 0) snr = 34.0;
548 L_WARNING(
"SNR = %d < 27; very low\n", __func__, (l_int32)snr);
549 if (snr == 100) snr = 0;
551 L_WARNING(
"SNR > 45; using lossless encoding\n", __func__);
555 if (nlevels <= 0) nlevels = 5;
557 L_WARNING(
"nlevels = %d > 10; setting to 10\n", __func__, nlevels);
561 return ERROR_INT(
"valid codec not identified\n", __func__, 1);
563 opjVersion = opj_version();
564 if (opjVersion[0] !=
'2') {
565 L_ERROR(
"version is %s; must be 2.0 or higher\n", __func__, opjVersion);
568 if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
569 L_ERROR(
"version %s: differs from minor = %d\n",
570 __func__, opjVersion, OPJ_VERSION_MINOR);
578 }
else if (d == 32) {
580 }
else if (pixGetColormap(pix) == NULL) {
583 L_INFO(
"removing colormap; may be better to compress losslessly\n",
590 image = pixConvertToOpjImage(pixs);
595 opj_set_default_encoder_parameters(¶meters);
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;
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);
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,
620 l_codec = opj_create_compress(OPJ_CODEC_JP2);
622 l_codec = opj_create_compress(OPJ_CODEC_J2K);
624 opj_image_destroy(image);
625 LEPT_FREE(parameters.cp_comment);
626 return ERROR_INT(
"failed to get the encoder handle\n", __func__, 1);
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);
637 if (!opj_setup_encoder(l_codec, ¶meters, 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);
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);
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);
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);
672 success = opj_end_compress(l_codec, l_stream);
675 opj_stream_destroy(l_stream);
676 opj_destroy_codec(l_codec);
677 opj_image_destroy(image);
678 LEPT_FREE(parameters.cp_comment);
682 return ERROR_INT(
"opj_end_compress failed\n", __func__, 1);
699 pixConvertToOpjImage(
PIX *pix)
701 l_int32 i, j, k, w, h, d, spp, wpl;
702 OPJ_COLOR_SPACE colorspace;
707 l_uint32 *line, *data;
709 opj_image_cmptparm_t cmptparm[4];
712 return (opj_image_t *)ERROR_PTR(
"pix not defined", __func__, NULL);
714 if (d != 8 && d != 32) {
715 L_ERROR(
"invalid depth: %d\n", __func__, d);
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;
725 cmptparm[i].sgnd = 0;
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);
740 ir = image->comps[0].data;
742 ig = image->comps[1].data;
743 ib = image->comps[2].data;
746 ia = image->comps[3].data;
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++) {
756 }
else if (spp > 1) {
794 pixReadMemJp2k(
const l_uint8 *data,
805 return (
PIX *)ERROR_PTR(
"data not defined", __func__, NULL);
808 return (
PIX *)ERROR_PTR(
"stream not opened", __func__, NULL);
809 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
811 if (!pix) L_ERROR(
"pix not read\n", __func__);
835 pixWriteMemJp2k(l_uint8 **pdata,
846 if (pdata) *pdata = NULL;
847 if (psize) *psize = 0;
849 return ERROR_INT(
"&data not defined", __func__, 1 );
851 return ERROR_INT(
"&size not defined", __func__, 1 );
853 return ERROR_INT(
"&pix not defined", __func__, 1 );
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,
864 L_INFO(
"work-around: writing to a temp file\n", __func__);
867 return ERROR_INT(
"tmpfile stream not opened", __func__, 1);
869 if ((fp = tmpfile()) == NULL)
870 return ERROR_INT(
"tmpfile stream not opened", __func__, 1);
872 ret = pixWriteStreamJp2k(fp, pix, quality, nlevels,
L_JP2_CODEC,
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;
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;
901 opj_write_from_file(
void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp)
903 return fwrite(p_buffer, 1, p_nb_bytes, fp);
907 opj_skip_from_file(OPJ_OFF_T offset, FILE *fp) {
908 if (fseek(fp, offset, SEEK_CUR)) {
915 opj_seek_from_file(OPJ_OFF_T offset, FILE *fp) {
916 if (fseek(fp, offset, SEEK_SET)) {
923 static opj_stream_t *
924 opjCreateStream(FILE *fp,
925 l_int32 is_read_stream)
927 opj_stream_t *l_stream;
930 return (opj_stream_t *)ERROR_PTR(
"fp not defined", __func__, NULL);
932 l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, is_read_stream);
934 return (opj_stream_t *)ERROR_PTR(
"stream not made", __func__, NULL);
936 #if OPJ_VERSION_MINOR == 0
937 opj_stream_set_user_data(l_stream, fp);
939 opj_stream_set_user_data(l_stream, fp,
940 (opj_stream_free_user_data_fn)NULL);
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);
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
l_ok boxGetGeometry(const BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
l_ok pixSetResolution(PIX *pix, l_int32 xres, l_int32 yres)
pixSetResolution()
void pixDestroy(PIX **ppix)
pixDestroy()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
PIX * pixClone(PIX *pixs)
pixClone()
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
@ REMOVE_CMAP_BASED_ON_SRC
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
PIX * pixConvert24To32(PIX *pixs)
pixConvert24To32()
char * getLeptonicaVersion(void)
getLeptonicaVersion()
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
FILE * fopenReadStream(const char *filename)
fopenReadStream()