Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/leptonica/src/jp2kheader.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*====================================================================* | |
| 2 - Copyright (C) 2001 Leptonica. All rights reserved. | |
| 3 - | |
| 4 - Redistribution and use in source and binary forms, with or without | |
| 5 - modification, are permitted provided that the following conditions | |
| 6 - are met: | |
| 7 - 1. Redistributions of source code must retain the above copyright | |
| 8 - notice, this list of conditions and the following disclaimer. | |
| 9 - 2. Redistributions in binary form must reproduce the above | |
| 10 - copyright notice, this list of conditions and the following | |
| 11 - disclaimer in the documentation and/or other materials | |
| 12 - provided with the distribution. | |
| 13 - | |
| 14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY | |
| 18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 25 *====================================================================*/ | |
| 26 | |
| 27 /*! | |
| 28 * \file jp2kheader.c | |
| 29 * <pre> | |
| 30 * | |
| 31 * Read header | |
| 32 * l_int32 readHeaderJp2k() | |
| 33 * l_int32 freadHeaderJp2k() | |
| 34 * l_int32 readHeaderMemJp2k() | |
| 35 * l_int32 fgetJp2kResolution() | |
| 36 * l_int32 readResolutionMemJp2k() | |
| 37 * | |
| 38 * Note: these function read image metadata from a jp2k file, without | |
| 39 * using any jp2k libraries. | |
| 40 * | |
| 41 * To read and write jp2k data, using the OpenJPEG library | |
| 42 * (http://www.openjpeg.org), see jpegio.c. | |
| 43 * </pre> | |
| 44 */ | |
| 45 | |
| 46 #ifdef HAVE_CONFIG_H | |
| 47 #include <config_auto.h> | |
| 48 #endif /* HAVE_CONFIG_H */ | |
| 49 | |
| 50 #include <string.h> | |
| 51 #include <math.h> | |
| 52 #include "allheaders.h" | |
| 53 | |
| 54 #ifndef NO_CONSOLE_IO | |
| 55 #define DEBUG_CODEC 0 | |
| 56 #endif /* ~NO_CONSOLE_IO */ | |
| 57 | |
| 58 /* --------------------------------------------*/ | |
| 59 #if USE_JP2KHEADER /* defined in environ.h */ | |
| 60 /* --------------------------------------------*/ | |
| 61 | |
| 62 /* a sanity check on the size read from file */ | |
| 63 static const l_int32 MAX_JP2K_WIDTH = 100000; | |
| 64 static const l_int32 MAX_JP2K_HEIGHT = 100000; | |
| 65 | |
| 66 /*--------------------------------------------------------------------* | |
| 67 * Stream interface * | |
| 68 *--------------------------------------------------------------------*/ | |
| 69 /*! | |
| 70 * \brief readHeaderJp2k() | |
| 71 * | |
| 72 * \param[in] filename | |
| 73 * \param[out] pw [optional] | |
| 74 * \param[out] ph [optional] | |
| 75 * \param[out] pbps [optional] bits/sample | |
| 76 * \param[out] pspp [optional] samples/pixel | |
| 77 * \param[out] pcodec [optional] L_JP2_CODEC or L_J2K_CODEC | |
| 78 * \return 0 if OK, 1 on error | |
| 79 */ | |
| 80 l_ok | |
| 81 readHeaderJp2k(const char *filename, | |
| 82 l_int32 *pw, | |
| 83 l_int32 *ph, | |
| 84 l_int32 *pbps, | |
| 85 l_int32 *pspp, | |
| 86 l_int32 *pcodec) | |
| 87 { | |
| 88 l_int32 ret; | |
| 89 FILE *fp; | |
| 90 | |
| 91 if (!filename) | |
| 92 return ERROR_INT("filename not defined", __func__, 1); | |
| 93 | |
| 94 if ((fp = fopenReadStream(filename)) == NULL) | |
| 95 return ERROR_INT_1("image file not found", filename, __func__, 1); | |
| 96 ret = freadHeaderJp2k(fp, pw, ph, pbps, pspp, pcodec); | |
| 97 fclose(fp); | |
| 98 return ret; | |
| 99 } | |
| 100 | |
| 101 | |
| 102 /*! | |
| 103 * \brief freadHeaderJp2k() | |
| 104 * | |
| 105 * \param[in] fp file stream opened for read | |
| 106 * \param[out] pw [optional] | |
| 107 * \param[out] ph [optional] | |
| 108 * \param[out] pbps [optional] bits/sample | |
| 109 * \param[out] pspp [optional] samples/pixel | |
| 110 * \param[out] pcodec [optional] L_JP2_CODEC or L_J2K_CODEC | |
| 111 * \return 0 if OK, 1 on error | |
| 112 */ | |
| 113 l_ok | |
| 114 freadHeaderJp2k(FILE *fp, | |
| 115 l_int32 *pw, | |
| 116 l_int32 *ph, | |
| 117 l_int32 *pbps, | |
| 118 l_int32 *pspp, | |
| 119 l_int32 *pcodec) | |
| 120 { | |
| 121 l_uint8 buf[120]; /* usually just need the first 80 bytes */ | |
| 122 l_int32 nread, ret; | |
| 123 | |
| 124 if (!fp) | |
| 125 return ERROR_INT("fp not defined", __func__, 1); | |
| 126 | |
| 127 rewind(fp); | |
| 128 nread = fread(buf, 1, sizeof(buf), fp); | |
| 129 if (nread != sizeof(buf)) | |
| 130 return ERROR_INT("read failure", __func__, 1); | |
| 131 | |
| 132 ret = readHeaderMemJp2k(buf, sizeof(buf), pw, ph, pbps, pspp, pcodec); | |
| 133 rewind(fp); | |
| 134 return ret; | |
| 135 } | |
| 136 | |
| 137 | |
| 138 /*! | |
| 139 * \brief readHeaderMemJp2k() | |
| 140 * | |
| 141 * \param[in] data | |
| 142 * \param[in] size at least 80 | |
| 143 * \param[out] pw [optional] | |
| 144 * \param[out] ph [optional] | |
| 145 * \param[out] pbps [optional] bits/sample | |
| 146 * \param[out] pspp [optional] samples/pixel | |
| 147 * \param[out] pcodec [optional] L_JP2_CODEC or L_J2K_CODEC | |
| 148 * \return 0 if OK, 1 on error | |
| 149 * | |
| 150 * <pre> | |
| 151 * Notes: | |
| 152 * (1) The ISO/IEC reference for jpeg2000 is | |
| 153 * http://www.jpeg.org/public/15444-1annexi.pdf | |
| 154 * and the file format syntax begins at page 127. | |
| 155 * (2) With a image file codec (L_JP2_CODEC), the Image Header Box | |
| 156 * begins with 'ihdr' = 0x69686472 in big-endian order. This | |
| 157 * typically, but not always, starts on byte 44, with the | |
| 158 * big-endian data fields beginning at byte 48: | |
| 159 * h: 4 bytes | |
| 160 * w: 4 bytes | |
| 161 * spp: 2 bytes | |
| 162 * bps: 1 byte (contains bps - 1) | |
| 163 * (3) With a codestream codec (L_J2K_CODEC), the first 4 bytes are | |
| 164 * 0xff4fff51. The fields for w and h appear to start on byte 8, | |
| 165 * and the fields for spp and bps appear to start on byte 40. | |
| 166 * </pre> | |
| 167 */ | |
| 168 l_ok | |
| 169 readHeaderMemJp2k(const l_uint8 *data, | |
| 170 size_t size, | |
| 171 l_int32 *pw, | |
| 172 l_int32 *ph, | |
| 173 l_int32 *pbps, | |
| 174 l_int32 *pspp, | |
| 175 l_int32 *pcodec) | |
| 176 { | |
| 177 l_int32 format, val, w, h, bps, spp, loc, found, index, codec; | |
| 178 l_uint8 ihdr[4] = {0x69, 0x68, 0x64, 0x72}; /* 'ihdr' */ | |
| 179 | |
| 180 if (pw) *pw = 0; | |
| 181 if (ph) *ph = 0; | |
| 182 if (pbps) *pbps = 0; | |
| 183 if (pspp) *pspp = 0; | |
| 184 if (pcodec) *pcodec = 0; | |
| 185 if (!data) | |
| 186 return ERROR_INT("data not defined", __func__, 1); | |
| 187 if (size < 120) | |
| 188 return ERROR_INT("size < 80", __func__, 1); | |
| 189 findFileFormatBuffer(data, &format); | |
| 190 if (format != IFF_JP2) | |
| 191 return ERROR_INT("not jp2 file", __func__, 1); | |
| 192 | |
| 193 /* Find beginning of the image metadata */ | |
| 194 if (!memcmp(data, "\xff\x4f\xff\x51", 4)) { /* codestream */ | |
| 195 index = 8; | |
| 196 codec = L_J2K_CODEC; | |
| 197 } else { /* file data with image header box 'ihdr' */ | |
| 198 arrayFindSequence(data, size, ihdr, 4, &loc, &found); | |
| 199 if (!found) | |
| 200 return ERROR_INT("image parameters not found", __func__, 1); | |
| 201 index = loc + 4; | |
| 202 codec = L_JP2_CODEC; | |
| 203 #if DEBUG_CODEC | |
| 204 if (loc != 44) | |
| 205 L_INFO("Beginning of ihdr is at byte %d\n", __func__, loc); | |
| 206 #endif /* DEBUG_CODEC */ | |
| 207 } | |
| 208 if (pcodec) *pcodec = codec; | |
| 209 | |
| 210 if (codec == L_JP2_CODEC) { | |
| 211 if (size < index + 4 * 3) | |
| 212 return ERROR_INT("header size is too small", __func__, 1); | |
| 213 val = *(l_uint32 *)(data + index); | |
| 214 h = convertOnLittleEnd32(val); | |
| 215 val = *(l_uint32 *)(data + index + 4); | |
| 216 w = convertOnLittleEnd32(val); | |
| 217 val = *(l_uint16 *)(data + index + 8); | |
| 218 spp = convertOnLittleEnd16(val); | |
| 219 bps = *(data + index + 10) + 1; | |
| 220 } else { /* codec == L_J2K_CODEC */ | |
| 221 if (size < index + 4 * 9) | |
| 222 return ERROR_INT("header size is too small", __func__, 1); | |
| 223 val = *(l_uint32 *)(data + index); | |
| 224 w = convertOnLittleEnd32(val); | |
| 225 val = *(l_uint32 *)(data + index + 4); | |
| 226 h = convertOnLittleEnd32(val); | |
| 227 val = *(l_uint16 *)(data + index + 32); | |
| 228 spp = convertOnLittleEnd16(val); | |
| 229 bps = *(data + index + 34) + 1; | |
| 230 } | |
| 231 #if DEBUG_CODEC | |
| 232 lept_stderr("h = %d, w = %d, codec: %s, spp = %d, bps = %d\n", h, w, | |
| 233 (codec == L_JP2_CODEC ? "jp2" : "j2k"), spp, bps); | |
| 234 #endif /* DEBUG_CODEC */ | |
| 235 | |
| 236 if (w < 1 || h < 1) | |
| 237 return ERROR_INT("w and h must both be > 0", __func__, 1); | |
| 238 if (w > MAX_JP2K_WIDTH || h > MAX_JP2K_HEIGHT) | |
| 239 return ERROR_INT("unrealistically large sizes", __func__, 1); | |
| 240 if (spp != 1 && spp != 3 && spp != 4) | |
| 241 return ERROR_INT("spp must be in 1, 3 or 4", __func__, 1); | |
| 242 if (bps != 8 && bps != 16) | |
| 243 return ERROR_INT("bps must be 8 or 16", __func__, 1); | |
| 244 if (pw) *pw = w; | |
| 245 if (ph) *ph = h; | |
| 246 if (pspp) *pspp = spp; | |
| 247 if (pbps) *pbps = bps; | |
| 248 return 0; | |
| 249 } | |
| 250 | |
| 251 | |
| 252 /* | |
| 253 * \brief fgetJp2kResolution() | |
| 254 * | |
| 255 * \param[in] fp file stream opened for read | |
| 256 * \param[oui] pxres in ppi | |
| 257 * \param[oui] pyres in ppi | |
| 258 * \return 0 if found, 1 if not found or on error | |
| 259 * | |
| 260 * <pre> | |
| 261 * Notes: | |
| 262 * (1) If the capture resolution field is not set, this is not an error; | |
| 263 * the returned resolution values are 0 (designating 'unknown'). | |
| 264 * (2) Side-effect: this rewinds the stream. | |
| 265 * (3) The capture resolution box is optional in the jp2 spec, and | |
| 266 * it is usually not written. | |
| 267 * (4) The big-endian data fields that follow the 4 bytes of 'resc' are: | |
| 268 * ynum: 2 bytes | |
| 269 * ydenom: 2 bytes | |
| 270 * xnum: 2 bytes | |
| 271 * xdenom: 2 bytes | |
| 272 * yexp: 1 byte | |
| 273 * xexp: 1 byte | |
| 274 * </pre> | |
| 275 */ | |
| 276 l_int32 | |
| 277 fgetJp2kResolution(FILE *fp, | |
| 278 l_int32 *pxres, | |
| 279 l_int32 *pyres) | |
| 280 { | |
| 281 l_uint8 *data; | |
| 282 size_t nbytes; | |
| 283 l_ok ok; | |
| 284 | |
| 285 if (!fp) | |
| 286 return ERROR_INT("stream not opened", __func__, 1); | |
| 287 | |
| 288 rewind(fp); | |
| 289 data = l_binaryReadStream(fp, &nbytes); | |
| 290 rewind(fp); | |
| 291 | |
| 292 ok = readResolutionMemJp2k(data, nbytes, pxres, pyres); | |
| 293 | |
| 294 LEPT_FREE(data); | |
| 295 return ok; | |
| 296 } | |
| 297 | |
| 298 | |
| 299 /*! | |
| 300 * \brief readResolutionMemJp2k() | |
| 301 * | |
| 302 * \param[in] data const; jp2k-encoded | |
| 303 * \param[in] nbytes of data | |
| 304 * \param[out] pxres [optional] | |
| 305 * \param[out] pyres [optional] | |
| 306 * \return 0 if OK, 1 on error | |
| 307 */ | |
| 308 l_ok | |
| 309 readResolutionMemJp2k(const l_uint8 *data, | |
| 310 size_t nbytes, | |
| 311 l_int32 *pxres, | |
| 312 l_int32 *pyres) | |
| 313 { | |
| 314 l_uint8 xexp, yexp; | |
| 315 l_uint16 xnum, ynum, xdenom, ydenom; /* these jp2k fields are 2-byte */ | |
| 316 l_int32 loc, found; | |
| 317 l_uint8 resc[4] = {0x72, 0x65, 0x73, 0x63}; /* 'resc' */ | |
| 318 l_float64 xres, yres, maxres; | |
| 319 | |
| 320 if (pxres) *pxres = 0; | |
| 321 if (pyres) *pyres = 0; | |
| 322 if (!pxres || !pyres) | |
| 323 return ERROR_INT("&xres and &yres not both defined", __func__, 1); | |
| 324 | |
| 325 /* Search for the start of the first capture resolution box: 'resc' */ | |
| 326 arrayFindSequence(data, nbytes, resc, 4, &loc, &found); | |
| 327 if (!found) { | |
| 328 L_WARNING("image resolution not found\n", __func__); | |
| 329 return 1; | |
| 330 } | |
| 331 if (nbytes < 80 || loc >= nbytes - 13) { | |
| 332 L_WARNING("image resolution found without enough space\n", __func__); | |
| 333 return 1; | |
| 334 } | |
| 335 | |
| 336 /* Extract the fields and calculate the resolution in pixels/meter. | |
| 337 * See section 1.5.3.7.1 of JPEG 2000 ISO/IEC 15444-1 spec. */ | |
| 338 ynum = data[loc + 5] << 8 | data[loc + 4]; | |
| 339 ynum = convertOnLittleEnd16(ynum); | |
| 340 ydenom = data[loc + 7] << 8 | data[loc + 6]; | |
| 341 ydenom = convertOnLittleEnd16(ydenom); | |
| 342 xnum = data[loc + 9] << 8 | data[loc + 8]; | |
| 343 xnum = convertOnLittleEnd16(xnum); | |
| 344 xdenom = data[loc + 11] << 8 | data[loc + 10]; | |
| 345 xdenom = convertOnLittleEnd16(xdenom); | |
| 346 if (ydenom == 0 || xdenom == 0) { | |
| 347 L_WARNING("bad data: ydenom or xdenom is 0\n", __func__); | |
| 348 return 1; | |
| 349 } | |
| 350 yexp = data[loc + 12]; | |
| 351 xexp = data[loc + 13]; | |
| 352 yres = ((l_float64)ynum / (l_float64)ydenom) * pow(10.0, (l_float64)yexp); | |
| 353 xres = ((l_float64)xnum / (l_float64)xdenom) * pow(10.0, (l_float64)xexp); | |
| 354 | |
| 355 /* Convert from pixels/meter to ppi */ | |
| 356 yres *= (300.0 / 11811.0); | |
| 357 xres *= (300.0 / 11811.0); | |
| 358 | |
| 359 /* Sanity check for bad data */ | |
| 360 maxres = 100000.0; /* ppi */ | |
| 361 if (xres > maxres || yres > maxres) { | |
| 362 L_WARNING("ridiculously large resolution\n", __func__); | |
| 363 } else { | |
| 364 *pyres = (l_int32)(yres + 0.5); | |
| 365 *pxres = (l_int32)(xres + 0.5); | |
| 366 } | |
| 367 | |
| 368 return 0; | |
| 369 } | |
| 370 | |
| 371 /* --------------------------------------------*/ | |
| 372 #endif /* USE_JP2KHEADER */ |
