Skip to content

Commit

Permalink
Remove support for openjpeg 2.0.
Browse files Browse the repository at this point in the history
* This cleans up the jp2kio.c code and fixes a new bug with 2.5.0,
  where for reasons not yet understood the fragile code set up for 2.0
  causes 2.5.0 to select the 2.0 path.
* Improve error handling for stringLength() and stringCat(), and
  add tests to prog/string_reg.
* Fix warnings of uninitialized or unused variables.
* Prepare for release of 1.84.1
  • Loading branch information
DanBloomberg committed Jan 3, 2024
1 parent 9a08040 commit 7e803e7
Show file tree
Hide file tree
Showing 22 changed files with 135 additions and 91 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake Targets")
project(
leptonica
LANGUAGES C
VERSION 1.84.0)
VERSION 1.84.1)
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)

Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = Leptonica
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 1.84.0
PROJECT_NUMBER = 1.84.1

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
AC_PREREQ([2.69])
AC_INIT([leptonica], [1.84.0])
AC_INIT([leptonica], [1.84.1])
AC_CONFIG_AUX_DIR([config])
AC_CONFIG_HEADERS([config_auto.h:config/config.h.in])
AC_CONFIG_SRCDIR([src/adaptmap.c])
Expand Down
2 changes: 1 addition & 1 deletion prog/boxa3_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ TestBoxa(L_REGPARAMS *rp,
l_uint8 *data;
l_int32 w, h, medw, medh, isame;
size_t size;
l_float32 scalefact, devw, ratiowh, fvarp, fvarm;
l_float32 scalefact, ratiowh, fvarp, fvarm;
BOXA *boxa1, *boxa2, *boxa3;
PIX *pix1;

Expand Down
3 changes: 1 addition & 2 deletions prog/deskew_it.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ int main(int argc,
{
char *filein, *fileout;
l_int32 threshold, tryboth, format;
l_float32 deg2rad, sweeprange, angle, conf;
l_float32 sweeprange, angle, conf;
PIX *pixs, *pix1, *pix2, *pixd;

if (argc != 6)
Expand All @@ -80,7 +80,6 @@ PIX *pixs, *pix1, *pix2, *pixd;

setLeptDebugOK(1);
pixd = NULL;
deg2rad = 3.1415926535 / 180.;

if ((pixs = pixRead(filein)) == NULL)
return ERROR_INT("pixs not made", __func__, 1);
Expand Down
56 changes: 54 additions & 2 deletions prog/string_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* * sarray serialization
* * file splitting
* * sarray splitting
* * string length and string cancatenation
*/

#ifdef HAVE_CONFIG_H
Expand All @@ -49,10 +50,10 @@ char substr2[4] = "00";
int main(int argc,
char **argv)
{
l_int32 i, loc, count;
l_int32 i, loc, count, n;
size_t size1, size2;
char *str0, *str1, *str2, *str3, *str4, *str5, *str6;
char fname[128];
char fname[128], smallbuf[8], medbuf[32];
l_uint8 *data1, *data2;
L_DNA *da;
SARRAY *sa1, *sa2, *sa3, *sa4, *sa5;
Expand Down Expand Up @@ -225,5 +226,56 @@ L_REGPARAMS *rp;
lept_free(str3);
lept_free(str4);

/* String length */
lept_stderr("************************************************\n");
lept_stderr("* This error message is intentional *\n");
n = stringLength("", 0);
lept_stderr("************************************************\n");
regTestCompareValues(rp, 0.0, (l_float32)n, 0.0); /* 27 */
n = stringLength("", 4);
regTestCompareValues(rp, 0, (l_float32)n, 0.0); /* 28 */
lept_stderr("************************************************\n");
lept_stderr("* This error message is intentional *\n");
n = stringLength("morethan4", 4);
lept_stderr("************************************************\n");
regTestCompareValues(rp, 4, (l_float32)n, 0.0); /* 29 */

/* String concatenation */
smallbuf[0] = '\0';
n = stringCat(smallbuf, 8, "abc");
regTestCompareValues(rp, 3.0, (l_float32)n, 0.0); /* 30 */
n = stringCat(smallbuf, 8, "def");
regTestCompareValues(rp, 3.0, (l_float32)n, 0.0); /* 31 */
n = stringLength(smallbuf, 8);
regTestCompareValues(rp, 6.0, (l_float32)n, 0.0); /* 32 */
lept_stderr("************************************************\n");
lept_stderr("* This error message is intentional *\n");
n = stringCat(smallbuf, 8, "gh");
lept_stderr("************************************************\n");
regTestCompareValues(rp, -1.0, (l_float32)n, 0.0); /* 33 */
stringCopy(medbuf, smallbuf, 32);
n = stringCat(medbuf, 32, smallbuf);
regTestCompareValues(rp, 6.0, (l_float32)n, 0.0); /* 34 */
n = stringLength(medbuf, 32);
regTestCompareValues(rp, 12.0, (l_float32)n, 0.0); /* 35 */
n = stringCat(medbuf, 32, medbuf);
regTestCompareValues(rp, 12.0, (l_float32)n, 0.0); /* 36 */
medbuf[23] = '\0'; /* shorten by 1 byte */
n = stringLength(medbuf, 32);
regTestCompareValues(rp, 23.0, (l_float32)n, 0.0); /* 37 */
str1 = stringConcatNew(medbuf, "jkl", NULL);
n = stringLength(str1, 32);
lept_free(str1);
regTestCompareValues(rp, 26.0, (l_float32)n, 0.0); /* 38 */
stringCopy(smallbuf, medbuf, 6);
n = stringLength(smallbuf, 8);
regTestCompareValues(rp, 6.0, (l_float32)n, 0.0); /* 39 */
stringCopy(smallbuf, medbuf, 8);
lept_stderr("************************************************\n");
lept_stderr("* This error message is intentional *\n");
n = stringLength(smallbuf, 8);
lept_stderr("************************************************\n");
regTestCompareValues(rp, 8.0, (l_float32)n, 0.0); /* 40 */

return regTestCleanup(rp);
}
3 changes: 1 addition & 2 deletions prog/writetext_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,11 @@ AddTextAndSave(PIXA *pixa,
l_int32 location,
l_uint32 val)
{
l_int32 n, newrow, ovf;
l_int32 n, ovf;
PIX *pix1;

pix1 = pixAddSingleTextblock(pixs, bmf, textstr, val, location, &ovf);
n = pixaGetCount(pixa);
newrow = (n % 4) ? 0 : 1;
pixaAddPix(pixa, pix1, L_INSERT);
if (ovf) lept_stderr("Overflow writing text in image %d\n", n + 1);
}
2 changes: 1 addition & 1 deletion src/allheaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

#define LIBLEPT_MAJOR_VERSION 1
#define LIBLEPT_MINOR_VERSION 84
#define LIBLEPT_PATCH_VERSION 0
#define LIBLEPT_PATCH_VERSION 1

#include "alltypes.h"

Expand Down
2 changes: 1 addition & 1 deletion src/allheaders_top.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

#define LIBLEPT_MAJOR_VERSION 1
#define LIBLEPT_MINOR_VERSION 84
#define LIBLEPT_PATCH_VERSION 0
#define LIBLEPT_PATCH_VERSION 1

#include "alltypes.h"

Expand Down
2 changes: 1 addition & 1 deletion src/blend.c
Original file line number Diff line number Diff line change
Expand Up @@ -2208,7 +2208,7 @@ l_uint32 *data, *line;
range = (l_int32)(distfract * h);
ymin = 0;
slope = maxfade / (l_float32)range;
} else if (dir == L_FROM_BOT) {
} else { /* dir == L_FROM_BOT */
range = (l_int32)(distfract * h);
ymin = h - range;
slope = maxfade / (l_float32)range;
Expand Down
3 changes: 1 addition & 2 deletions src/dnafunc1.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,6 @@ l_hmapCreateFromDna(L_DNA *da)
l_int32 i, n;
l_uint64 key;
l_float64 dval;
L_HASHITEM *hitem;
L_HASHMAP *hmap;

if (!da)
Expand All @@ -521,7 +520,7 @@ L_HASHMAP *hmap;
for (i = 0; i < n; i++) {
l_dnaGetDValue(da, i, &dval);
l_hashFloat64ToUint64(dval, &key);
hitem = l_hmapLookup(hmap, key, i, L_HMAP_CREATE);
l_hmapLookup(hmap, key, i, L_HMAP_CREATE);
}
return hmap;
}
Expand Down
4 changes: 2 additions & 2 deletions src/environ.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ typedef uintptr_t l_uintptr_t;


/*-----------------------------------------------------------------------*
* Leptonica supports OpenJPEG 2.0+. If you have a version of openjpeg *
* (HAVE_LIBJP2K == 1) that is >= 2.0, set the path to the openjpeg.h *
* Leptonica supports OpenJPEG 2.1+. If you have a version of openjpeg *
* (HAVE_LIBJP2K == 1) that is >= 2.1, set the path to the openjpeg.h *
* header in angle brackets here. *
*-----------------------------------------------------------------------*/
#define LIBJP2K_HEADER <openjpeg-2.3/openjpeg.h>
Expand Down
82 changes: 30 additions & 52 deletions src/jp2kio.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,25 +66,10 @@
* strings.
*
* N.B.
* * This is based on the most recent openjpeg release: 2.1.
* * The openjpeg interface was massively changed from 1.X. The debian
* distribution is way back at 1.3. We have inquired but are unable
* to determine if or when a debian distribution will be built for 2.1.
* * For version 2.1, the openjpeg.h file is installed in an
* openjpeg-2.1 subdirectory, which is hard to support.
* * In openjpeg-2.1, reading is slow compared to jpeg or webp,
* and writing is very slow compared to jpeg or webp. This is expected
* to improve significantly in future versions.
* * Reading and writing jp2k are supported here for 2.1.
* The high-level interface to openjpeg continues to change.
* From 2.0 to 2.1, the ability to interface to a C file stream
* was removed permanently. Leptonica supports both file stream
* and memory buffer interfaces for every image I/O library, and
* it requires the libraries to support at least one of these.
* However, openjpeg-2.1 provides neither, so we have brought
* several static functions over from openjpeg-2.0 in order to
* retain the file stream interface. See our static function
* opjCreateStream().
* * Reading and writing jp2k are supported here for releases 2.1 and later.
* * The openjpeg.h file is installed in an openjpeg-2.X subdirectory.
* * In openjpeg-2.X, reading is slow compared to jpeg or webp,
* and writing is very slow compared to jpeg or webp.
* * Specifying a quality factor for jpeg2000 requires caution. Unlike
* jpeg and webp, which have a sensible scale that goes from 0 (very poor)
* to 100 (nearly lossless), kakadu and openjpeg use idiosyncratic and
Expand All @@ -96,6 +81,15 @@
* quality to jpeg's default standard of 75. For document images,
* SNR = 25 is very poor, whereas SNR = 45 is nearly lossless. If you
* use the latter, you will pay dearly in the size of the compressed file.
* * The openjpeg interface was massively changed from 1.X to 2.0.
* There were also changes from 2.0 to 2.1. From 2.0 to 2.1, the
* ability to interface to a C file stream was removed permanently.
* Leptonica supports both file stream and memory buffer interfaces
* for every image I/O library, and it requires the libraries to
* support at least one of these. However, because openjpeg-2.1+ provides
* neither, we have brought several static functions over from
* openjpeg-2.0 in order to retain the file stream interface.
* See, for example, our static function opjCreateStream().
* </pre>
*/

Expand All @@ -110,16 +104,11 @@
#if HAVE_LIBJP2K /* defined in environ.h */
/* --------------------------------------------*/

/* Leptonica supports versions 2.0 and newer */
/* Leptonica supports versions 2.1 and later */
#ifdef LIBJP2K_HEADER
#include LIBJP2K_HEADER
#else
#include <openjpeg.h>
#endif

/* 2.0 didn't define OPJ_VERSION_MINOR. */
#ifndef OPJ_VERSION_MINOR
#define OPJ_VERSION_MINOR 0
#endif

/* Static generator of opj_stream from file stream.
Expand Down Expand Up @@ -259,15 +248,13 @@ PIX *pix = NULL;
return (PIX *)ERROR_PTR("fp not defined", __func__, NULL);

opjVersion = opj_version();
if (opjVersion[0] != '2') {
L_ERROR("version is %s; must be 2.0 or higher\n", __func__, opjVersion);
if (!opjVersion || opjVersion[0] == '\0')
return (PIX *)ERROR_PTR("opj version not defined", __func__, NULL);
if (opjVersion[0] - 0x30 < 2 ||
(opjVersion[0] == '2' && opjVersion[2] - 0x30 == 0)) {
L_ERROR("version is %s; must be 2.1 or higher\n", __func__, opjVersion);
return NULL;
}
if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
L_ERROR("version %s: differs from minor = %d\n",
__func__, opjVersion, OPJ_VERSION_MINOR);
return NULL;
}

/* Get the resolution, bits/sample and codec type */
rewind(fp);
Expand Down Expand Up @@ -323,9 +310,8 @@ PIX *pix = NULL;
return NULL;
}

/* Open decompression 'stream'. In 2.0, we could call this:
* opj_stream_create_default_file_stream(fp, 1)
* but the file stream interface was removed in 2.1. */
/* Open decompression 'stream'. This uses our version of the
* function that was removed in 2.1. */
if ((l_stream = opjCreateStream(fp, 1)) == NULL) {
L_ERROR("failed to open the stream\n", __func__);
opj_destroy_codec(l_codec);
Expand Down Expand Up @@ -563,15 +549,13 @@ opj_image_t *image = NULL;
return ERROR_INT("valid codec not identified\n", __func__, 1);

opjVersion = opj_version();
if (opjVersion[0] != '2') {
L_ERROR("version is %s; must be 2.0 or higher\n", __func__, opjVersion);
if (!opjVersion || opjVersion[0] == '\0')
return ERROR_INT("opj version not defined", __func__, 1);
if (opjVersion[0] - 0x30 < 2 ||
(opjVersion[0] == '2' && opjVersion[2] - 0x30 == 0)) {
L_ERROR("version is %s; must be 2.1 or higher\n", __func__, opjVersion);
return 1;
}
if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
L_ERROR("version %s: differs from minor = %d\n",
__func__, opjVersion, OPJ_VERSION_MINOR);
return 1;
}

/* Remove colormap if it exists; result is 8 or 32 bpp */
pixGetDimensions(pix, &w, &h, &d);
Expand Down Expand Up @@ -645,9 +629,8 @@ opj_image_t *image = NULL;

/* Set the resolution (TBD) */

/* Open a compression stream for writing. In 2.0 we could use this:
* opj_stream_create_default_file_stream(fp, 0)
* but the file stream interface was removed in 2.1. */
/* Open compression stream for writing. This uses our version
* of the function that was removed in 2.1. */
rewind(fp);
if ((l_stream = opjCreateStream(fp, 0)) == NULL) {
opj_destroy_codec(l_codec);
Expand Down Expand Up @@ -785,9 +768,8 @@ opj_image_cmptparm_t cmptparm[4];
* <pre>
* Notes:
* (1) This crashes when reading through the fmemopen cookie.
* Until we can fix this, we use the file-based work-around.
* And fixing this may take some time, because the basic
* stream interface is no longer supported in openjpeg.
* Until this is fixed, which may take a long time, we use
* the file-based work-around.
* (2) See pixReadJp2k() for usage.
* </pre>
*/
Expand Down Expand Up @@ -934,12 +916,8 @@ opj_stream_t *l_stream;
if (!l_stream)
return (opj_stream_t *)ERROR_PTR("stream not made", __func__, NULL);

#if OPJ_VERSION_MINOR == 0
opj_stream_set_user_data(l_stream, fp);
#else
opj_stream_set_user_data(l_stream, fp,
(opj_stream_free_user_data_fn)NULL);
#endif
opj_stream_set_user_data_length(l_stream, opj_get_user_data_length(fp));
opj_stream_set_read_function(l_stream,
(opj_stream_read_fn)opj_read_from_file);
Expand Down
2 changes: 1 addition & 1 deletion src/makefile.static
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ LIBRARIAN_SHARED = gcc -shared
# <libname>.X, and <libname>, where Y is the minor revision number.
MAJOR_REV = 1
MINOR_REV = 84
PATCH_REV = 0
PATCH_REV = 1

#########################################################

Expand Down
4 changes: 2 additions & 2 deletions src/pageseg.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ pixCropImage(PIX *pixs,
BOX **pcropbox)
{
char cmd[64];
l_int32 w, h, d, lrc, tbc, val;
l_int32 w, h, d, val;
l_int32 left, right, top, bot, leftfinal, rightfinal, topfinal, botfinal;
static l_int32 first_time = TRUE;
l_float32 hscale;
Expand Down Expand Up @@ -632,7 +632,7 @@ BOX *box1, *box2;
pixClipToForeground(pix2, NULL, &box1);
} else {
val = edgeclean + 1;
snprintf(cmd, 32, "c%d.%d + o%d.%d", val, val, val, val);
snprintf(cmd, 64, "c%d.%d + o%d.%d", val, val, val, val);
pix3 = pixMorphSequence(pix2, cmd, 0);
pixClipToForeground(pix3, NULL, &box1);
pixDestroy(&pix3);
Expand Down
Loading

0 comments on commit 7e803e7

Please sign in to comment.