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,
208 PROCNAME(
"pixReadJp2k");
211 return (
PIX *)ERROR_PTR(
"filename not defined", procName, NULL);
214 return (
PIX *)ERROR_PTR(
"image file not found", procName, NULL);
215 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
219 return (
PIX *)ERROR_PTR(
"image not returned", procName, NULL);
240 pixReadStreamJp2k(FILE *fp,
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;
251 l_uint32 *data, *line;
252 opj_dparameters_t parameters;
253 opj_image_t *image = NULL;
254 opj_codec_t *l_codec = NULL;
255 opj_stream_t *l_stream = NULL;
258 PROCNAME(
"pixReadStreamJp2k");
261 return (
PIX *)ERROR_PTR(
"fp not defined", procName, NULL);
263 opjVersion = opj_version();
264 if (opjVersion[0] !=
'2') {
265 L_ERROR(
"version is %s; must be 2.0 or higher\n", procName, opjVersion);
268 if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
269 L_ERROR(
"version %s: differs from minor = %d\n",
270 procName, opjVersion, OPJ_VERSION_MINOR);
276 fgetJp2kResolution(fp, &xres, &yres);
280 L_ERROR(
"valid codec not identified\n", procName);
285 L_ERROR(
"found %d bps; can only handle 8 bps\n", procName, bps);
290 opj_set_default_decoder_parameters(¶meters);
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);
302 parameters.cp_reduce = reduce;
306 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
308 l_codec = opj_create_decompress(OPJ_CODEC_J2K);
310 L_ERROR(
"failed to make the codec\n", procName);
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);
322 if (!opj_setup_decoder(l_codec, ¶meters)){
323 L_ERROR(
"failed to set up decoder\n", procName);
324 opj_destroy_codec(l_codec);
331 if ((l_stream = opjCreateStream(fp, 1)) == NULL) {
332 L_ERROR(
"failed to open the stream\n", procName);
333 opj_destroy_codec(l_codec);
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);
350 if (!opj_set_decode_area(l_codec, image, bx, by,
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);
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);
371 opj_stream_destroy(l_stream);
372 opj_destroy_codec(l_codec);
375 spp = image->numcomps;
376 w = image->comps[0].w;
377 h = image->comps[0].h;
378 prec = image->comps[0].prec;
380 L_WARNING(
"precision %d != bps %d!\n", procName, prec, bps);
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);
398 pixSetInputFormat(pix, IFF_JP2);
401 wpl = pixGetWpl(pix);
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];
412 }
else if (spp == 2) {
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];
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];
433 aval = image->comps[3].data[index];
443 opj_image_destroy(image);
482 pixWriteJp2k(
const char *filename,
491 PROCNAME(
"pixWriteJp2k");
494 return ERROR_INT(
"pix not defined", procName, 1);
496 return ERROR_INT(
"filename not defined", procName, 1);
499 return ERROR_INT(
"stream not opened", procName, 1);
501 if (pixWriteStreamJp2k(fp, pix, quality, nlevels,
L_JP2_CODEC,
504 return ERROR_INT(
"pix not written to stream", procName, 1);
529 pixWriteStreamJp2k(FILE *fp,
537 l_int32 w, h, d, success;
539 const char *opjVersion;
541 opj_cparameters_t parameters;
542 opj_stream_t *l_stream = NULL;
543 opj_codec_t* l_codec = NULL;;
544 opj_image_t *image = NULL;
546 PROCNAME(
"pixWriteStreamJp2k");
549 return ERROR_INT(
"stream not open", procName, 1);
551 return ERROR_INT(
"pix not defined", procName, 1);
553 snr = (l_float32)quality;
554 if (snr <= 0) snr = 34.0;
556 L_WARNING(
"SNR = %d < 27; very low\n", procName, (l_int32)snr);
557 if (snr == 100) snr = 0;
559 L_WARNING(
"SNR > 45; using lossless encoding\n", procName);
563 if (nlevels <= 0) nlevels = 5;
565 L_WARNING(
"nlevels = %d > 10; setting to 10\n", procName, nlevels);
569 return ERROR_INT(
"valid codec not identified\n", procName, 1);
571 opjVersion = opj_version();
572 if (opjVersion[0] !=
'2') {
573 L_ERROR(
"version is %s; must be 2.0 or higher\n", procName, opjVersion);
576 if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
577 L_ERROR(
"version %s: differs from minor = %d\n",
578 procName, opjVersion, OPJ_VERSION_MINOR);
586 }
else if (d == 32) {
588 }
else if (pixGetColormap(pix) == NULL) {
591 L_INFO(
"removing colormap; may be better to compress losslessly\n",
598 image = pixConvertToOpjImage(pixs);
603 opj_set_default_encoder_parameters(¶meters);
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;
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);
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,
628 l_codec = opj_create_compress(OPJ_CODEC_JP2);
630 l_codec = opj_create_compress(OPJ_CODEC_J2K);
632 opj_image_destroy(image);
633 LEPT_FREE(parameters.cp_comment);
634 return ERROR_INT(
"failed to get the encoder handle\n", procName, 1);
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);
645 if (!opj_setup_encoder(l_codec, ¶meters, 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);
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);
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);
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);
680 success = opj_end_compress(l_codec, l_stream);
683 opj_stream_destroy(l_stream);
684 opj_destroy_codec(l_codec);
685 opj_image_destroy(image);
686 LEPT_FREE(parameters.cp_comment);
690 return ERROR_INT(
"opj_end_compress failed\n", procName, 1);
707 pixConvertToOpjImage(
PIX *pix)
709 l_int32 i, j, k, w, h, d, spp, wpl;
710 OPJ_COLOR_SPACE colorspace;
715 l_uint32 *line, *data;
717 opj_image_cmptparm_t cmptparm[4];
719 PROCNAME(
"pixConvertToOpjImage");
722 return (opj_image_t *)ERROR_PTR(
"pix not defined", procName, NULL);
724 if (d != 8 && d != 32) {
725 L_ERROR(
"invalid depth: %d\n", procName, d);
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;
735 cmptparm[i].sgnd = 0;
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);
750 ir = image->comps[0].data;
752 ig = image->comps[1].data;
753 ib = image->comps[2].data;
756 ia = image->comps[3].data;
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++) {
766 }
else if (spp > 1) {
804 pixReadMemJp2k(
const l_uint8 *data,
814 PROCNAME(
"pixReadMemJp2k");
817 return (
PIX *)ERROR_PTR(
"data not defined", procName, NULL);
820 return (
PIX *)ERROR_PTR(
"stream not opened", procName, NULL);
821 pix = pixReadStreamJp2k(fp, reduction, box, hint, debug);
823 if (!pix) L_ERROR(
"pix not read\n", procName);
847 pixWriteMemJp2k(l_uint8 **pdata,
858 PROCNAME(
"pixWriteMemJp2k");
860 if (pdata) *pdata = NULL;
861 if (psize) *psize = 0;
863 return ERROR_INT(
"&data not defined", procName, 1 );
865 return ERROR_INT(
"&size not defined", procName, 1 );
867 return ERROR_INT(
"&pix not defined", procName, 1 );
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,
878 L_INFO(
"work-around: writing to a temp file\n", procName);
881 return ERROR_INT(
"tmpfile stream not opened", procName, 1);
883 if ((fp = tmpfile()) == NULL)
884 return ERROR_INT(
"tmpfile stream not opened", procName, 1);
886 ret = pixWriteStreamJp2k(fp, pix, quality, nlevels,
L_JP2_CODEC,
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;
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;
915 opj_write_from_file(
void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *fp)
917 return fwrite(p_buffer, 1, p_nb_bytes, fp);
921 opj_skip_from_file(OPJ_OFF_T offset, FILE *fp) {
922 if (fseek(fp, offset, SEEK_CUR)) {
929 opj_seek_from_file(OPJ_OFF_T offset, FILE *fp) {
930 if (fseek(fp, offset, SEEK_SET)) {
937 static opj_stream_t *
938 opjCreateStream(FILE *fp,
939 l_int32 is_read_stream)
941 opj_stream_t *l_stream;
943 PROCNAME(
"opjCreateStream");
946 return (opj_stream_t *)ERROR_PTR(
"fp not defined", procName, NULL);
948 l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, is_read_stream);
950 return (opj_stream_t *)ERROR_PTR(
"stream not made", procName, NULL);
952 #if OPJ_VERSION_MINOR == 0
953 opj_stream_set_user_data(l_stream, fp);
955 opj_stream_set_user_data(l_stream, fp,
956 (opj_stream_free_user_data_fn)NULL);
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);
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
l_ok boxGetGeometry(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()