Skip to content

Commit

Permalink
Make pix{Read,Write}MemJp2k work via direct memory access.
Browse files Browse the repository at this point in the history
* On platforms lacking open_memstream(), pix{Read,Write}MemJp2k()
  worked via a temporary file, but this overhead is unnecessary
  as openjpeg2000's opj_stream allows one to read/write directly
  from a memory buffer by supplying it with appropriate callbacks.
* This commit makes pix{Read,Write}MemJp2k() use this more direct
  mechanism on all platforms.
* In addition, since pixReadStreamJp2k() always read the whole
  stream into memory when it called fgetJp2kResolution(),
  this commit saves a bit of compute resources by in effect making
  pixReadStreamJp2k() into a wrapper for pixReadMemJp2k().
  • Loading branch information
atykhyy committed Feb 5, 2024
1 parent ad52063 commit cfc875a
Show file tree
Hide file tree
Showing 4 changed files with 271 additions and 76 deletions.
1 change: 1 addition & 0 deletions src/allheaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,7 @@ LEPT_DLL extern l_ok readHeaderJp2k ( const char *filename, l_int32 *pw, l_int32
LEPT_DLL extern l_ok freadHeaderJp2k ( FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *pcodec );
LEPT_DLL extern l_ok readHeaderMemJp2k ( const l_uint8 *data, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *pcodec );
LEPT_DLL extern l_int32 fgetJp2kResolution ( FILE *fp, l_int32 *pxres, l_int32 *pyres );
LEPT_DLL extern l_ok readResolutionMemJp2k ( const l_uint8 *data, size_t size, l_int32 *pxres, l_int32 *pyres );
LEPT_DLL extern PIX * pixReadJp2k ( const char *filename, l_uint32 reduction, BOX *box, l_int32 hint, l_int32 debug );
LEPT_DLL extern PIX * pixReadStreamJp2k ( FILE *fp, l_uint32 reduction, BOX *box, l_int32 hint, l_int32 debug );
LEPT_DLL extern l_ok pixWriteJp2k ( const char *filename, PIX *pix, l_int32 quality, l_int32 nlevels, l_int32 hint, l_int32 debug );
Expand Down
44 changes: 32 additions & 12 deletions src/jp2kheader.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,35 +274,57 @@ fgetJp2kResolution(FILE *fp,
l_int32 *pxres,
l_int32 *pyres)
{
l_uint8 xexp, yexp;
l_uint8 *data;
size_t nbytes;
l_ok ok;

if (!fp)
return ERROR_INT("stream not opened", __func__, 1);

rewind(fp);
data = l_binaryReadStream(fp, &nbytes);
rewind(fp);

ok = readResolutionMemJp2k(data, nbytes, pxres, pyres);

LEPT_FREE(data);
return ok;
}

/*!
* \brief readResolutionMemJp2k()
*
* \param[in] data const; jp2k-encoded
* \param[in] size of data
* \param[out] pxres [optional]
* \param[out] pyres [optional]
* \return 0 if OK, 1 on error
*/
l_ok
readResolutionMemJp2k(const l_uint8 *data,
size_t nbytes,
l_int32 *pxres,
l_int32 *pyres)
{
l_uint8 xexp, yexp;
l_uint16 xnum, ynum, xdenom, ydenom; /* these jp2k fields are 2-byte */
l_int32 loc, found;
l_uint8 resc[4] = {0x72, 0x65, 0x73, 0x63}; /* 'resc' */
size_t nbytes;
l_float64 xres, yres, maxres;

if (pxres) *pxres = 0;
if (pyres) *pyres = 0;
if (!pxres || !pyres)
return ERROR_INT("&xres and &yres not both defined", __func__, 1);
if (!fp)
return ERROR_INT("stream not opened", __func__, 1);

rewind(fp);
data = l_binaryReadStream(fp, &nbytes);
rewind(fp);

/* Search for the start of the first capture resolution box: 'resc' */
arrayFindSequence(data, nbytes, resc, 4, &loc, &found);
if (!found) {
L_WARNING("image resolution not found\n", __func__);
LEPT_FREE(data);
return 1;
}
if (nbytes < 80 || loc >= nbytes - 13) {
L_WARNING("image resolution found without enough space\n", __func__);
LEPT_FREE(data);
return 1;
}

Expand All @@ -318,7 +340,6 @@ l_float64 xres, yres, maxres;
xdenom = convertOnLittleEnd16(xdenom);
if (ydenom == 0 || xdenom == 0) {
L_WARNING("bad data: ydenom or xdenom is 0\n", __func__);
LEPT_FREE(data);
return 1;
}
yexp = data[loc + 12];
Expand All @@ -339,7 +360,6 @@ l_float64 xres, yres, maxres;
*pxres = (l_int32)(xres + 0.5);
}

LEPT_FREE(data);
return 0;
}

Expand Down
8 changes: 8 additions & 0 deletions src/jp2kheaderstub.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,13 @@ l_int32 fgetJp2kResolution(FILE *fp, l_int32 *pxres, l_int32 *pyres)
return ERROR_INT("function not present", __func__, 1);
}

/* ----------------------------------------------------------------------*/

l_ok readResolutionMemJp2k(const l_uint8 *data, size_t size,
l_int32 *pxres, l_int32 *pyres)
{
return ERROR_INT("function not present", __func__, 1);
}

/* --------------------------------------------*/
#endif /* !USE_JP2KHEADER */
Loading

0 comments on commit cfc875a

Please sign in to comment.