Unified · Split
| @@ -0,0 +1,3 @@ | ||
| 1 | +*.out | |
| 2 | +*.[o0125678vqki] | |
| 3 | +libjp2.a | |
| @@ -65,10 +65,21 @@ · 64 unmodified lines | ||
| 65 | 65 | * $Id$ |
| 66 | 66 | */ |
| 67 | 67 | |
| 68 | +/******************************************************************************\ | |
| 69 | +* Includes. | |
| 70 | +\******************************************************************************/ | |
| 71 | + | |
| 72 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 73 | + | |
| 68 | 74 | #include "jasper/jas_cm.h" |
| 69 | 75 | #include "jasper/jas_icc.h" |
| 70 | 76 | #include "jasper/jas_malloc.h" |
| 71 | 77 | #include "jasper/jas_math.h" |
| 78 | +#include "jasper/jas_debug.h" | |
| 79 | + | |
| 80 | +/******************************************************************************\ | |
| 81 | +* Function prototypes. | |
| 82 | +\******************************************************************************/ | |
| 72 | 83 | |
| 73 | 84 | static jas_cmprof_t *jas_cmprof_create(void); |
| 74 | 85 | static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *); |
| @@ -89,8 +100,10 @@ static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, · 14 unmodified lines | ||
| 89 | 100 | unsigned, unsigned); |
| 90 | 101 | static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, unsigned n); |
| 91 | 102 | |
| 92 | −static int mono(const jas_iccprof_t *prof, int op, jas_cmpxformseq_t **pxformseq); | |
| 93 | −static int triclr(const jas_iccprof_t *prof, int op, jas_cmpxformseq_t **retpxformseq); | |
| 103 | +static int mono(const jas_iccprof_t *prof, int op, | |
| 104 | + jas_cmpxformseq_t **pxformseq); | |
| 105 | +static int triclr(const jas_iccprof_t *prof, int op, | |
| 106 | + jas_cmpxformseq_t **retpxformseq); | |
| 94 | 107 | |
| 95 | 108 | static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq); |
| 96 | 109 | static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, unsigned i); |
| @@ -100,6 +113,10 @@ static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]); · 3 unmodified lines | ||
| 100 | 113 | static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, |
| 101 | 114 | int i, jas_cmpxform_t *pxform); |
| 102 | 115 | |
| 116 | +/******************************************************************************\ | |
| 117 | +* Function prototypes. | |
| 118 | +\******************************************************************************/ | |
| 119 | + | |
| 103 | 120 | #define SEQFWD(intent) (intent) |
| 104 | 121 | #define SEQREV(intent) (4 + (intent)) |
| 105 | 122 | #define SEQSIM(intent) (8 + (intent)) |
| @@ -122,62 +139,81 @@ static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, · 16 unmodified lines | ||
| 122 | 139 | |
| 123 | 140 | #define gampxformseq(prof) ((prof)->pxformseqs[SEQGAM]) |
| 124 | 141 | |
| 125 | −static jas_clrspc_t icctoclrspc(jas_iccsig_t iccclrspc, int refflag); | |
| 142 | +static int icctoclrspc(jas_iccsig_t iccclrspc, jas_clrspc_t* clrspc, int refflag); | |
| 126 | 143 | static jas_cmpxform_t *jas_cmpxform_create0(void); |
| 127 | 144 | static jas_cmpxform_t *jas_cmpxform_createshapmat(void); |
| 128 | 145 | static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut); |
| 129 | 146 | static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, const jas_icccurv_t *curv); |
| 130 | − | |
| 131 | −static const jas_cmpxformops_t shapmat_ops = {jas_cmshapmat_destroy, jas_cmshapmat_apply}; | |
| 132 | 147 | static jas_cmprof_t *jas_cmprof_createsycc(void); |
| 133 | 148 | |
| 149 | +/******************************************************************************\ | |
| 150 | +* | |
| 151 | +\******************************************************************************/ | |
| 152 | + | |
| 153 | +static const jas_cmpxformops_t shapmat_ops = { | |
| 154 | + jas_cmshapmat_destroy, | |
| 155 | + jas_cmshapmat_apply, | |
| 156 | + 0 | |
| 157 | +}; | |
| 158 | + | |
| 134 | 159 | /******************************************************************************\ |
| 135 | 160 | * Color profile class. |
| 136 | 161 | \******************************************************************************/ |
| 137 | 162 | |
| 138 | 163 | jas_cmprof_t *jas_cmprof_createfromclrspc(jas_clrspc_t clrspc) |
| 139 | 164 | { |
| 165 | + JAS_LOGDEBUGF(1, "jas_cmprof_createfromclrspc(%d)\n", clrspc); | |
| 166 | + | |
| 140 | 167 | jas_iccprof_t *iccprof; |
| 141 | 168 | jas_cmprof_t *prof; |
| 142 | 169 | |
| 143 | 170 | iccprof = 0; |
| 144 | 171 | switch (clrspc) { |
| 145 | 172 | case JAS_CLRSPC_SYCBCR: |
| 146 | − if (!(prof = jas_cmprof_createsycc())) | |
| 173 | + if (!(prof = jas_cmprof_createsycc())) { | |
| 147 | 174 | goto error; |
| 175 | + } | |
| 148 | 176 | break; |
| 149 | 177 | default: |
| 150 | − if (!(iccprof = jas_iccprof_createfromclrspc(clrspc))) | |
| 178 | + if (!(iccprof = jas_iccprof_createfromclrspc(clrspc))) { | |
| 151 | 179 | goto error; |
| 152 | − if (!(prof = jas_cmprof_createfromiccprof(iccprof))) | |
| 180 | + } | |
| 181 | + if (!(prof = jas_cmprof_createfromiccprof(iccprof))) { | |
| 153 | 182 | goto error; |
| 183 | + } | |
| 154 | 184 | jas_iccprof_destroy(iccprof); |
| 155 | − if (!jas_clrspc_isgeneric(clrspc)) | |
| 185 | + if (!jas_clrspc_isgeneric(clrspc)) { | |
| 156 | 186 | prof->clrspc = clrspc; |
| 187 | + } | |
| 157 | 188 | break; |
| 158 | 189 | } |
| 159 | 190 | return prof; |
| 160 | 191 | error: |
| 161 | − if (iccprof) | |
| 192 | + if (iccprof) { | |
| 162 | 193 | jas_iccprof_destroy(iccprof); |
| 194 | + } | |
| 163 | 195 | return 0; |
| 164 | 196 | } |
| 165 | 197 | |
| 166 | 198 | static jas_cmprof_t *jas_cmprof_createsycc() |
| 167 | 199 | { |
| 200 | + JAS_LOGDEBUGF(1, "jas_cmprof_createsycc()\n"); | |
| 201 | + | |
| 168 | 202 | jas_cmprof_t *prof; |
| 169 | − jas_cmpxform_t *fwdpxform = NULL; | |
| 170 | − jas_cmpxform_t *revpxform = NULL; | |
| 203 | + jas_cmpxform_t *fwdpxform = 0; | |
| 204 | + jas_cmpxform_t *revpxform = 0; | |
| 171 | 205 | jas_cmshapmat_t *fwdshapmat; |
| 172 | 206 | jas_cmshapmat_t *revshapmat; |
| 173 | 207 | |
| 174 | − if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) | |
| 208 | + if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) { | |
| 175 | 209 | goto error; |
| 210 | + } | |
| 176 | 211 | prof->clrspc = JAS_CLRSPC_SYCBCR; |
| 177 | 212 | assert(prof->numchans == 3 && prof->numrefchans == 3); |
| 178 | 213 | assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ); |
| 179 | − if (!(fwdpxform = jas_cmpxform_createshapmat())) | |
| 214 | + if (!(fwdpxform = jas_cmpxform_createshapmat())) { | |
| 180 | 215 | goto error; |
| 216 | + } | |
| 181 | 217 | fwdpxform->numinchans = 3; |
| 182 | 218 | fwdpxform->numoutchans = 3; |
| 183 | 219 | fwdshapmat = &fwdpxform->data.shapmat; |
| @@ -197,8 +233,9 @@ static jas_cmprof_t *jas_cmprof_createsycc() · 13 unmodified lines | ||
| 197 | 233 | fwdshapmat->mat[0][3] = -0.5 * (1.402); |
| 198 | 234 | fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414); |
| 199 | 235 | fwdshapmat->mat[2][3] = -0.5 * (1.772); |
| 200 | − if (!(revpxform = jas_cmpxform_createshapmat())) | |
| 236 | + if (!(revpxform = jas_cmpxform_createshapmat())) { | |
| 201 | 237 | goto error; |
| 238 | + } | |
| 202 | 239 | revpxform->numinchans = 3; |
| 203 | 240 | revpxform->numoutchans = 3; |
| 204 | 241 | revshapmat = &revpxform->data.shapmat; |
| @@ -206,20 +243,24 @@ static jas_cmprof_t *jas_cmprof_createsycc() · 1 unmodified line | ||
| 206 | 243 | revshapmat->order = 1; |
| 207 | 244 | revshapmat->useluts = 0; |
| 208 | 245 | revshapmat->usemat = 1; |
| 209 | − jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat); | |
| 246 | + if (jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat)) { | |
| 247 | + goto error; | |
| 248 | + } | |
| 210 | 249 | |
| 211 | 250 | for (unsigned i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) { |
| 212 | 251 | unsigned j = SEQFWD(i); |
| 213 | 252 | if (prof->pxformseqs[j]) { |
| 214 | 253 | if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0, |
| 215 | − fwdpxform)) | |
| 254 | + fwdpxform)) { | |
| 216 | 255 | goto error; |
| 256 | + } | |
| 217 | 257 | } |
| 218 | 258 | j = SEQREV(i); |
| 219 | 259 | if (prof->pxformseqs[j]) { |
| 220 | 260 | if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], |
| 221 | − -1, revpxform)) | |
| 261 | + -1, revpxform)) { | |
| 222 | 262 | goto error; |
| 263 | + } | |
| 223 | 264 | } |
| 224 | 265 | } |
| 225 | 266 | |
| @@ -227,15 +268,22 @@ static jas_cmprof_t *jas_cmprof_createsycc() · 1 unmodified line | ||
| 227 | 268 | jas_cmpxform_destroy(revpxform); |
| 228 | 269 | return prof; |
| 229 | 270 | error: |
| 230 | − if (fwdpxform) | |
| 271 | + if (fwdpxform) { | |
| 231 | 272 | jas_cmpxform_destroy(fwdpxform); |
| 232 | − if (revpxform) | |
| 273 | + } | |
| 274 | + if (revpxform) { | |
| 233 | 275 | jas_cmpxform_destroy(revpxform); |
| 276 | + } | |
| 277 | + if (prof) { | |
| 278 | + jas_cmprof_destroy(prof); | |
| 279 | + } | |
| 234 | 280 | return 0; |
| 235 | 281 | } |
| 236 | 282 | |
| 237 | 283 | jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof) |
| 238 | 284 | { |
| 285 | + JAS_LOGDEBUGF(1, "jas_cmprof_createfromiccprof(%p)\n", iccprof); | |
| 286 | + | |
| 239 | 287 | jas_cmprof_t *prof; |
| 240 | 288 | jas_icchdr_t icchdr; |
| 241 | 289 | jas_cmpxformseq_t *fwdpxformseq; |
| @@ -244,26 +292,44 @@ jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof) · 2 unmodified lines | ||
| 244 | 292 | fwdpxformseq = 0; |
| 245 | 293 | revpxformseq = 0; |
| 246 | 294 | |
| 247 | − if (!(prof = jas_cmprof_create())) | |
| 295 | + if (!(prof = jas_cmprof_create())) { | |
| 296 | + jas_logerrorf("error: cannot create CM profile\n"); | |
| 248 | 297 | goto error; |
| 298 | + } | |
| 249 | 299 | jas_iccprof_gethdr(iccprof, &icchdr); |
| 250 | − if (!(prof->iccprof = jas_iccprof_copy(iccprof))) | |
| 300 | + if (!(prof->iccprof = jas_iccprof_copy(iccprof))) { | |
| 301 | + jas_logerrorf("error: cannot copy ICC profile\n"); | |
| 251 | 302 | goto error; |
| 252 | − prof->clrspc = icctoclrspc(icchdr.colorspc, 0); | |
| 253 | − prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1); | |
| 303 | + } | |
| 304 | + if (icctoclrspc(icchdr.colorspc, &prof->clrspc, 0)) { | |
| 305 | + jas_logerrorf("error: unknown color profile\n"); | |
| 306 | + goto error; | |
| 307 | + } | |
| 308 | + if (icctoclrspc(icchdr.refcolorspc, &prof->refclrspc, 1)) { | |
| 309 | + jas_logerrorf("error: unknown reference color profile\n"); | |
| 310 | + goto error; | |
| 311 | + } | |
| 254 | 312 | prof->numchans = jas_clrspc_numchans(prof->clrspc); |
| 255 | 313 | prof->numrefchans = jas_clrspc_numchans(prof->refclrspc); |
| 256 | 314 | |
| 257 | 315 | if (prof->numchans == 1) { |
| 258 | − if (mono(prof->iccprof, 0, &fwdpxformseq)) | |
| 316 | + if (mono(prof->iccprof, 0, &fwdpxformseq)) { | |
| 317 | + jas_logerrorf("error: mono failed 1\n"); | |
| 259 | 318 | goto error; |
| 260 | − if (mono(prof->iccprof, 1, &revpxformseq)) | |
| 319 | + } | |
| 320 | + if (mono(prof->iccprof, 1, &revpxformseq)) { | |
| 321 | + jas_logerrorf("error: mono failed 2\n"); | |
| 261 | 322 | goto error; |
| 323 | + } | |
| 262 | 324 | } else if (prof->numchans == 3) { |
| 263 | − if (triclr(prof->iccprof, 0, &fwdpxformseq)) | |
| 325 | + if (triclr(prof->iccprof, 0, &fwdpxformseq)) { | |
| 326 | + jas_logerrorf("error: triclr failed 1\n"); | |
| 264 | 327 | goto error; |
| 265 | − if (triclr(prof->iccprof, 1, &revpxformseq)) | |
| 328 | + } | |
| 329 | + if (triclr(prof->iccprof, 1, &revpxformseq)) { | |
| 330 | + jas_logerrorf("error: triclr failed 2\n"); | |
| 266 | 331 | goto error; |
| 332 | + } | |
| 267 | 333 | } |
| 268 | 334 | prof->pxformseqs[SEQFWD(0)] = fwdpxformseq; |
| 269 | 335 | prof->pxformseqs[SEQREV(0)] = revpxformseq; |
| @@ -304,12 +370,14 @@ error: · 34 unmodified lines | ||
| 304 | 370 | static jas_cmprof_t *jas_cmprof_create() |
| 305 | 371 | { |
| 306 | 372 | jas_cmprof_t *prof; |
| 307 | − if (!(prof = jas_malloc(sizeof(jas_cmprof_t)))) | |
| 373 | + if (!(prof = jas_malloc(sizeof(jas_cmprof_t)))) { | |
| 308 | 374 | return 0; |
| 375 | + } | |
| 309 | 376 | memset(prof, 0, sizeof(jas_cmprof_t)); |
| 310 | 377 | prof->iccprof = 0; |
| 311 | − for (unsigned i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) | |
| 378 | + for (unsigned i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) { | |
| 312 | 379 | prof->pxformseqs[i] = 0; |
| 380 | + } | |
| 313 | 381 | return prof; |
| 314 | 382 | } |
| 315 | 383 | |
| @@ -321,8 +389,9 @@ void jas_cmprof_destroy(jas_cmprof_t *prof) · 5 unmodified lines | ||
| 321 | 389 | prof->pxformseqs[i] = 0; |
| 322 | 390 | } |
| 323 | 391 | } |
| 324 | − if (prof->iccprof) | |
| 392 | + if (prof->iccprof) { | |
| 325 | 393 | jas_iccprof_destroy(prof->iccprof); |
| 394 | + } | |
| 326 | 395 | jas_free(prof); |
| 327 | 396 | } |
| 328 | 397 | |
| @@ -330,8 +399,9 @@ jas_cmprof_t *jas_cmprof_copy(const jas_cmprof_t *prof) · 1 unmodified line | ||
| 330 | 399 | { |
| 331 | 400 | jas_cmprof_t *newprof; |
| 332 | 401 | |
| 333 | − if (!(newprof = jas_cmprof_create())) | |
| 402 | + if (!(newprof = jas_cmprof_create())) { | |
| 334 | 403 | goto error; |
| 404 | + } | |
| 335 | 405 | newprof->clrspc = prof->clrspc; |
| 336 | 406 | newprof->numchans = prof->numchans; |
| 337 | 407 | newprof->refclrspc = prof->refclrspc; |
| @@ -345,8 +415,9 @@ jas_cmprof_t *jas_cmprof_copy(const jas_cmprof_t *prof) · 7 unmodified lines | ||
| 345 | 415 | } |
| 346 | 416 | return newprof; |
| 347 | 417 | error: |
| 348 | − if (newprof) | |
| 418 | + if (newprof) { | |
| 349 | 419 | jas_cmprof_destroy(newprof); |
| 420 | + } | |
| 350 | 421 | return 0; |
| 351 | 422 | } |
| 352 | 423 | |
| @@ -363,40 +434,45 @@ jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof, const jas_cmprof_t · 10 unmodified lines | ||
| 363 | 434 | jas_cmpxformseq_t *altoutpxformseq; |
| 364 | 435 | jas_cmpxformseq_t *prfpxformseq; |
| 365 | 436 | |
| 366 | − /* Avoid compiler warnings about unused parameters. */ | |
| 367 | − (void)optimize; | |
| 437 | + JAS_UNUSED(optimize); | |
| 368 | 438 | |
| 369 | 439 | const jas_cmxform_intent_t prfintent = intent; |
| 370 | 440 | |
| 371 | − if (!(xform = jas_malloc(sizeof(jas_cmxform_t)))) | |
| 441 | + if (!(xform = jas_malloc(sizeof(jas_cmxform_t)))) { | |
| 372 | 442 | goto error; |
| 373 | − if (!(xform->pxformseq = jas_cmpxformseq_create())) | |
| 443 | + } | |
| 444 | + if (!(xform->pxformseq = jas_cmpxformseq_create())) { | |
| 374 | 445 | goto error; |
| 446 | + } | |
| 375 | 447 | |
| 376 | 448 | switch (op) { |
| 377 | 449 | case JAS_CMXFORM_OP_FWD: |
| 378 | 450 | inpxformseq = fwdpxformseq(inprof, intent); |
| 379 | 451 | outpxformseq = revpxformseq(outprof, intent); |
| 380 | − if (!inpxformseq || !outpxformseq) | |
| 452 | + if (!inpxformseq || !outpxformseq) { | |
| 381 | 453 | goto error; |
| 454 | + } | |
| 382 | 455 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || |
| 383 | 456 | jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 384 | 457 | inprof->refclrspc, outprof->refclrspc) || |
| 385 | − jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) | |
| 458 | + jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) { | |
| 386 | 459 | goto error; |
| 460 | + } | |
| 387 | 461 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); |
| 388 | 462 | xform->numoutchans = jas_clrspc_numchans(outprof->clrspc); |
| 389 | 463 | break; |
| 390 | 464 | case JAS_CMXFORM_OP_REV: |
| 391 | 465 | outpxformseq = fwdpxformseq(outprof, intent); |
| 392 | 466 | inpxformseq = revpxformseq(inprof, intent); |
| 393 | − if (!outpxformseq || !inpxformseq) | |
| 467 | + if (!outpxformseq || !inpxformseq) { | |
| 394 | 468 | goto error; |
| 469 | + } | |
| 395 | 470 | if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || |
| 396 | 471 | jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 397 | 472 | outprof->refclrspc, inprof->refclrspc) || |
| 398 | − jas_cmpxformseq_append(xform->pxformseq, inpxformseq)) | |
| 473 | + jas_cmpxformseq_append(xform->pxformseq, inpxformseq)) { | |
| 399 | 474 | goto error; |
| 475 | + } | |
| 400 | 476 | xform->numinchans = jas_clrspc_numchans(outprof->clrspc); |
| 401 | 477 | xform->numoutchans = jas_clrspc_numchans(inprof->clrspc); |
| 402 | 478 | break; |
| @@ -404,53 +480,62 @@ jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof, const jas_cmprof_t · 1 unmodified line | ||
| 404 | 480 | assert(prfprof); |
| 405 | 481 | inpxformseq = fwdpxformseq(inprof, intent); |
| 406 | 482 | prfpxformseq = fwdpxformseq(prfprof, prfintent); |
| 407 | − if (!inpxformseq || !prfpxformseq) | |
| 483 | + if (!inpxformseq || !prfpxformseq) { | |
| 408 | 484 | goto error; |
| 485 | + } | |
| 409 | 486 | outpxformseq = simpxformseq(outprof, intent); |
| 410 | 487 | altoutpxformseq = 0; |
| 411 | 488 | if (!outpxformseq) { |
| 412 | 489 | outpxformseq = revpxformseq(outprof, intent); |
| 413 | 490 | altoutpxformseq = fwdpxformseq(outprof, intent); |
| 414 | − if (!outpxformseq || !altoutpxformseq) | |
| 491 | + if (!outpxformseq || !altoutpxformseq) { | |
| 415 | 492 | goto error; |
| 493 | + } | |
| 416 | 494 | } |
| 417 | 495 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || |
| 418 | 496 | jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 419 | − inprof->refclrspc, outprof->refclrspc)) | |
| 497 | + inprof->refclrspc, outprof->refclrspc)) { | |
| 420 | 498 | goto error; |
| 499 | + } | |
| 421 | 500 | if (altoutpxformseq) { |
| 422 | 501 | if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || |
| 423 | − jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq)) | |
| 502 | + jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq)) { | |
| 424 | 503 | goto error; |
| 504 | + } | |
| 425 | 505 | } else { |
| 426 | − if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) | |
| 506 | + if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) { | |
| 427 | 507 | goto error; |
| 508 | + } | |
| 428 | 509 | } |
| 429 | 510 | if (jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 430 | 511 | outprof->refclrspc, inprof->refclrspc) || |
| 431 | − jas_cmpxformseq_append(xform->pxformseq, prfpxformseq)) | |
| 512 | + jas_cmpxformseq_append(xform->pxformseq, prfpxformseq)) { | |
| 432 | 513 | goto error; |
| 514 | + } | |
| 433 | 515 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); |
| 434 | 516 | xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc); |
| 435 | 517 | break; |
| 436 | 518 | case JAS_CMXFORM_OP_GAMUT: |
| 437 | 519 | inpxformseq = fwdpxformseq(inprof, intent); |
| 438 | 520 | outpxformseq = gampxformseq(outprof); |
| 439 | − if (!inpxformseq || !outpxformseq) | |
| 521 | + if (!inpxformseq || !outpxformseq) { | |
| 440 | 522 | goto error; |
| 523 | + } | |
| 441 | 524 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || |
| 442 | 525 | jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 443 | 526 | inprof->refclrspc, outprof->refclrspc) || |
| 444 | − jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) | |
| 527 | + jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) { | |
| 445 | 528 | goto error; |
| 529 | + } | |
| 446 | 530 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); |
| 447 | 531 | xform->numoutchans = 1; |
| 448 | 532 | break; |
| 449 | 533 | } |
| 450 | 534 | return xform; |
| 451 | 535 | error: |
| 452 | − if (xform) | |
| 536 | + if (xform) { | |
| 453 | 537 | jas_cmxform_destroy(xform); |
| 538 | + } | |
| 454 | 539 | return 0; |
| 455 | 540 | } |
| 456 | 541 | |
| @@ -463,8 +548,10 @@ int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, jas_ · 6 unmodified lines | ||
| 463 | 548 | jas_cmreal_t scale; |
| 464 | 549 | long v; |
| 465 | 550 | |
| 466 | − if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts) | |
| 551 | + if (xform->numinchans > in->numcmpts || | |
| 552 | + xform->numoutchans > out->numcmpts) { | |
| 467 | 553 | goto error; |
| 554 | + } | |
| 468 | 555 | |
| 469 | 556 | const jas_cmcmptfmt_t *fmt = &in->cmptfmts[0]; |
| 470 | 557 | const unsigned width = fmt->width; |
| @@ -494,9 +581,10 @@ int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, jas_ · 23 unmodified lines | ||
| 494 | 581 | } |
| 495 | 582 | } |
| 496 | 583 | |
| 497 | − if (maxchans == 0) | |
| 584 | + if (maxchans == 0) { | |
| 498 | 585 | /* avoid division by zero */ |
| 499 | 586 | goto error; |
| 587 | + } | |
| 500 | 588 | |
| 501 | 589 | const unsigned bufmax = APPLYBUFSIZ / maxchans; |
| 502 | 590 | assert(bufmax > 0); |
| @@ -515,8 +603,9 @@ int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, jas_ · 12 unmodified lines | ||
| 515 | 603 | const long *dataptr = &fmt->buf[n]; |
| 516 | 604 | jas_cmreal_t *bufptr = &inbuf[i]; |
| 517 | 605 | for (unsigned j = 0; j < m; ++j) { |
| 518 | − if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v)) | |
| 606 | + if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v)) { | |
| 519 | 607 | goto error; |
| 608 | + } | |
| 520 | 609 | *bufptr = (jas_cmreal_t)(v - bias) / scale; |
| 521 | 610 | bufptr += xform->numinchans; |
| 522 | 611 | } |
| @@ -531,8 +620,9 @@ int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, jas_ · 8 unmodified lines | ||
| 531 | 620 | } else { |
| 532 | 621 | outbuf = inbuf; |
| 533 | 622 | } |
| 534 | − if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m)) | |
| 623 | + if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m)) { | |
| 535 | 624 | goto error; |
| 625 | + } | |
| 536 | 626 | inbuf = outbuf; |
| 537 | 627 | } |
| 538 | 628 | |
| @@ -545,8 +635,9 @@ int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, jas_ · 6 unmodified lines | ||
| 545 | 635 | for (unsigned j = 0; j < m; ++j) { |
| 546 | 636 | v = (long)((*bufptr) * scale + bias); |
| 547 | 637 | bufptr += xform->numoutchans; |
| 548 | − if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v)) | |
| 638 | + if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v)) { | |
| 549 | 639 | goto error; |
| 640 | + } | |
| 550 | 641 | } |
| 551 | 642 | } |
| 552 | 643 | |
| @@ -560,8 +651,9 @@ error: · 7 unmodified lines | ||
| 560 | 651 | |
| 561 | 652 | void jas_cmxform_destroy(jas_cmxform_t *xform) |
| 562 | 653 | { |
| 563 | − if (xform->pxformseq) | |
| 654 | + if (xform->pxformseq) { | |
| 564 | 655 | jas_cmpxformseq_destroy(xform->pxformseq); |
| 656 | + } | |
| 565 | 657 | jas_free(xform); |
| 566 | 658 | } |
| 567 | 659 | |
| @@ -572,17 +664,20 @@ void jas_cmxform_destroy(jas_cmxform_t *xform) · 4 unmodified lines | ||
| 572 | 664 | static jas_cmpxformseq_t *jas_cmpxformseq_create() |
| 573 | 665 | { |
| 574 | 666 | jas_cmpxformseq_t *pxformseq; |
| 575 | − if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t)))) | |
| 667 | + if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t)))) { | |
| 576 | 668 | goto error; |
| 669 | + } | |
| 577 | 670 | pxformseq->pxforms = 0; |
| 578 | 671 | pxformseq->numpxforms = 0; |
| 579 | 672 | pxformseq->maxpxforms = 0; |
| 580 | − if (jas_cmpxformseq_resize(pxformseq, 16)) | |
| 673 | + if (jas_cmpxformseq_resize(pxformseq, 16)) { | |
| 581 | 674 | goto error; |
| 675 | + } | |
| 582 | 676 | return pxformseq; |
| 583 | 677 | error: |
| 584 | − if (pxformseq) | |
| 678 | + if (pxformseq) { | |
| 585 | 679 | jas_cmpxformseq_destroy(pxformseq); |
| 680 | + } | |
| 586 | 681 | return 0; |
| 587 | 682 | } |
| 588 | 683 | |
| @@ -590,23 +685,28 @@ static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq) · 1 unmodified line | ||
| 590 | 685 | { |
| 591 | 686 | jas_cmpxformseq_t *newpxformseq; |
| 592 | 687 | |
| 593 | − if (!(newpxformseq = jas_cmpxformseq_create())) | |
| 688 | + if (!(newpxformseq = jas_cmpxformseq_create())) { | |
| 594 | 689 | goto error; |
| 595 | − if (jas_cmpxformseq_append(newpxformseq, pxformseq)) | |
| 690 | + } | |
| 691 | + if (jas_cmpxformseq_append(newpxformseq, pxformseq)) { | |
| 596 | 692 | goto error; |
| 693 | + } | |
| 597 | 694 | return newpxformseq; |
| 598 | 695 | error: |
| 599 | − if (newpxformseq) | |
| 696 | + if (newpxformseq) { | |
| 600 | 697 | jas_cmpxformseq_destroy(newpxformseq); |
| 698 | + } | |
| 601 | 699 | return 0; |
| 602 | 700 | } |
| 603 | 701 | |
| 604 | 702 | static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq) |
| 605 | 703 | { |
| 606 | − while (pxformseq->numpxforms > 0) | |
| 704 | + while (pxformseq->numpxforms > 0) { | |
| 607 | 705 | jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1); |
| 608 | − if (pxformseq->pxforms) | |
| 706 | + } | |
| 707 | + if (pxformseq->pxforms) { | |
| 609 | 708 | jas_free(pxformseq->pxforms); |
| 709 | + } | |
| 610 | 710 | jas_free(pxformseq); |
| 611 | 711 | } |
| 612 | 712 | |
| @@ -623,11 +723,16 @@ static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, unsigned i) · 10 unmodified lines | ||
| 623 | 723 | static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, |
| 624 | 724 | unsigned dstclrspc, unsigned srcclrspc) |
| 625 | 725 | { |
| 626 | − if (dstclrspc == srcclrspc) | |
| 726 | + JAS_UNUSED(pxformseq); | |
| 727 | + if (dstclrspc == srcclrspc) { | |
| 627 | 728 | return 0; |
| 729 | + } | |
| 730 | + /* | |
| 731 | + I think that this function should not be called if the source and | |
| 732 | + destination color spaces are of different types. | |
| 733 | + That is, it is considered a programmer error, not a run-time error. | |
| 734 | + */ | |
| 628 | 735 | abort(); |
| 629 | − /* Avoid compiler warnings about unused parameters. */ | |
| 630 | − USED(pxformseq); | |
| 631 | 736 | return -1; |
| 632 | 737 | } |
| 633 | 738 | |
| @@ -638,13 +743,14 @@ static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, · 4 unmodified lines | ||
| 638 | 743 | const unsigned i = _i >= 0 ? (unsigned)_i : pxformseq->numpxforms; |
| 639 | 744 | assert(i <= pxformseq->numpxforms); |
| 640 | 745 | if (pxformseq->numpxforms >= pxformseq->maxpxforms) { |
| 641 | − if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms + | |
| 642 | − 16)) | |
| 746 | + if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms + 16)) { | |
| 643 | 747 | goto error; |
| 748 | + } | |
| 644 | 749 | } |
| 645 | 750 | assert(pxformseq->numpxforms < pxformseq->maxpxforms); |
| 646 | − if (!(tmppxform = jas_cmpxform_copy(pxform))) | |
| 751 | + if (!(tmppxform = jas_cmpxform_copy(pxform))) { | |
| 647 | 752 | goto error; |
| 753 | + } | |
| 648 | 754 | const unsigned n = pxformseq->numpxforms - i; |
| 649 | 755 | if (n > 0) { |
| 650 | 756 | memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i], |
| @@ -664,13 +770,15 @@ static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq, · 13 unmodified lines | ||
| 664 | 770 | jas_cmpxform_t *othpxform; |
| 665 | 771 | const unsigned n = pxformseq->numpxforms + othpxformseq->numpxforms; |
| 666 | 772 | if (n > pxformseq->maxpxforms) { |
| 667 | − if (jas_cmpxformseq_resize(pxformseq, n)) | |
| 773 | + if (jas_cmpxformseq_resize(pxformseq, n)) { | |
| 668 | 774 | goto error; |
| 775 | + } | |
| 669 | 776 | } |
| 670 | 777 | for (unsigned i = 0; i < othpxformseq->numpxforms; ++i) { |
| 671 | 778 | othpxform = othpxformseq->pxforms[i]; |
| 672 | − if (!(pxform = jas_cmpxform_copy(othpxform))) | |
| 779 | + if (!(pxform = jas_cmpxform_copy(othpxform))) { | |
| 673 | 780 | goto error; |
| 781 | + } | |
| 674 | 782 | pxformseq->pxforms[pxformseq->numpxforms] = pxform; |
| 675 | 783 | ++pxformseq->numpxforms; |
| 676 | 784 | } |
| @@ -700,8 +808,9 @@ static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, unsigned n) · 23 unmodified lines | ||
| 700 | 808 | static jas_cmpxform_t *jas_cmpxform_create0() |
| 701 | 809 | { |
| 702 | 810 | jas_cmpxform_t *pxform; |
| 703 | − if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t)))) | |
| 811 | + if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t)))) { | |
| 704 | 812 | return 0; |
| 813 | + } | |
| 705 | 814 | memset(pxform, 0, sizeof(jas_cmpxform_t)); |
| 706 | 815 | pxform->refcnt = 0; |
| 707 | 816 | pxform->ops = 0; |
| @@ -730,19 +839,22 @@ static jas_cmpxform_t *jas_cmpxform_createshapmat() · 22 unmodified lines | ||
| 730 | 839 | { |
| 731 | 840 | jas_cmpxform_t *pxform; |
| 732 | 841 | jas_cmshapmat_t *shapmat; |
| 733 | − if (!(pxform = jas_cmpxform_create0())) | |
| 842 | + if (!(pxform = jas_cmpxform_create0())) { | |
| 734 | 843 | return 0; |
| 844 | + } | |
| 735 | 845 | pxform->ops = &shapmat_ops; |
| 736 | 846 | shapmat = &pxform->data.shapmat; |
| 737 | 847 | shapmat->mono = 0; |
| 738 | 848 | shapmat->order = 0; |
| 739 | 849 | shapmat->useluts = 0; |
| 740 | 850 | shapmat->usemat = 0; |
| 741 | − for (unsigned i = 0; i < 3; ++i) | |
| 851 | + for (unsigned i = 0; i < 3; ++i) { | |
| 742 | 852 | jas_cmshapmatlut_init(&shapmat->luts[i]); |
| 853 | + } | |
| 743 | 854 | for (unsigned i = 0; i < 3; ++i) { |
| 744 | − for (unsigned j = 0; j < 4; ++j) | |
| 855 | + for (unsigned j = 0; j < 4; ++j) { | |
| 745 | 856 | shapmat->mat[i][j] = 0.0; |
| 857 | + } | |
| 746 | 858 | } |
| 747 | 859 | ++pxform->refcnt; |
| 748 | 860 | return pxform; |
| @@ -751,8 +863,9 @@ static jas_cmpxform_t *jas_cmpxform_createshapmat() · 2 unmodified lines | ||
| 751 | 863 | static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform) |
| 752 | 864 | { |
| 753 | 865 | jas_cmshapmat_t *shapmat = &pxform->data.shapmat; |
| 754 | − for (unsigned i = 0; i < 3; ++i) | |
| 866 | + for (unsigned i = 0; i < 3; ++i) { | |
| 755 | 867 | jas_cmshapmatlut_cleanup(&shapmat->luts[i]); |
| 868 | + } | |
| 756 | 869 | } |
| 757 | 870 | |
| 758 | 871 | static int jas_cmshapmat_apply(const jas_cmpxform_t *pxform, const jas_cmreal_t *in, |
| @@ -808,8 +921,9 @@ static int jas_cmshapmat_apply(const jas_cmpxform_t *pxform, const jas_cmreal_t · 49 unmodified lines | ||
| 808 | 921 | if (!shapmat->order) { |
| 809 | 922 | while (cnt-- > 0) { |
| 810 | 923 | a0 = *src++; |
| 811 | − if (shapmat->useluts) | |
| 924 | + if (shapmat->useluts) { | |
| 812 | 925 | a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); |
| 926 | + } | |
| 813 | 927 | a2 = a0 * shapmat->mat[2][0]; |
| 814 | 928 | a1 = a0 * shapmat->mat[1][0]; |
| 815 | 929 | a0 = a0 * shapmat->mat[0][0]; |
| @@ -824,8 +938,9 @@ assert(0); · 8 unmodified lines | ||
| 824 | 938 | src++; |
| 825 | 939 | src++; |
| 826 | 940 | a0 = a0 * shapmat->mat[0][0]; |
| 827 | − if (shapmat->useluts) | |
| 941 | + if (shapmat->useluts) { | |
| 828 | 942 | a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); |
| 943 | + } | |
| 829 | 944 | *dst++ = a0; |
| 830 | 945 | } |
| 831 | 946 | } |
| @@ -851,8 +966,9 @@ static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut) · 19 unmodified lines | ||
| 851 | 966 | |
| 852 | 967 | static double gammafn(double x, double gamma) |
| 853 | 968 | { |
| 854 | − if (x == 0.0) | |
| 969 | + if (x == 0.0) { | |
| 855 | 970 | return 0.0; |
| 971 | + } | |
| 856 | 972 | return pow(x, gamma); |
| 857 | 973 | } |
| 858 | 974 | |
| @@ -862,28 +978,32 @@ static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, const jas_icccurv_t *cu · 3 unmodified lines | ||
| 862 | 978 | jas_cmshapmatlut_cleanup(lut); |
| 863 | 979 | if (curv->numents == 0) { |
| 864 | 980 | lut->size = 2; |
| 865 | − if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) | |
| 981 | + if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) { | |
| 866 | 982 | goto error; |
| 983 | + } | |
| 867 | 984 | lut->data[0] = 0.0; |
| 868 | 985 | lut->data[1] = 1.0; |
| 869 | 986 | } else if (curv->numents == 1) { |
| 870 | 987 | lut->size = 256; |
| 871 | − if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) | |
| 988 | + if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) { | |
| 872 | 989 | goto error; |
| 990 | + } | |
| 873 | 991 | gamma = (jas_cmreal_t)curv->ents[0] / 256.0; |
| 874 | 992 | for (unsigned i = 0; i < lut->size; ++i) { |
| 875 | 993 | lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma); |
| 876 | 994 | } |
| 877 | 995 | } else { |
| 878 | 996 | lut->size = curv->numents; |
| 879 | − if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) | |
| 997 | + if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) { | |
| 880 | 998 | goto error; |
| 999 | + } | |
| 881 | 1000 | for (unsigned i = 0; i < lut->size; ++i) { |
| 882 | 1001 | lut->data[i] = (jas_cmreal_t)curv->ents[i] / 65535.0; |
| 883 | 1002 | } |
| 884 | 1003 | } |
| 885 | 1004 | return 0; |
| 886 | 1005 | error: |
| 1006 | + jas_cmshapmatlut_cleanup(lut); | |
| 887 | 1007 | return -1; |
| 888 | 1008 | } |
| 889 | 1009 | |
| @@ -892,11 +1012,13 @@ static jas_cmreal_t jas_cmshapmatlut_lookup(const jas_cmshapmatlut_t *lut, jas_c · 2 unmodified lines | ||
| 892 | 1012 | jas_cmreal_t t; |
| 893 | 1013 | t = x * (lut->size - 1); |
| 894 | 1014 | const int lo = (int)floor(t); |
| 895 | − if (lo < 0) | |
| 1015 | + if (lo < 0) { | |
| 896 | 1016 | return lut->data[0]; |
| 1017 | + } | |
| 897 | 1018 | const unsigned hi = (unsigned)ceil(t); |
| 898 | − if (hi >= lut->size) | |
| 1019 | + if (hi >= lut->size) { | |
| 899 | 1020 | return lut->data[lut->size - 1]; |
| 1021 | + } | |
| 900 | 1022 | return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]); |
| 901 | 1023 | } |
| 902 | 1024 | |
| @@ -921,8 +1043,9 @@ static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut, · 18 unmodified lines | ||
| 921 | 1043 | return -1; |
| 922 | 1044 | } |
| 923 | 1045 | } |
| 924 | − if (!(invlut->data = jas_alloc2(n, sizeof(jas_cmreal_t)))) | |
| 1046 | + if (!(invlut->data = jas_alloc2(n, sizeof(jas_cmreal_t)))) { | |
| 925 | 1047 | return -1; |
| 1048 | + } | |
| 926 | 1049 | invlut->size = n; |
| 927 | 1050 | for (unsigned i = 0; i < invlut->size; ++i) { |
| 928 | 1051 | sy = ((double) i) / (invlut->size - 1); |
| @@ -933,11 +1056,9 @@ static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut, · 4 unmodified lines | ||
| 933 | 1056 | unsigned k; |
| 934 | 1057 | for (k = j + 1; k < lut->size; ++k) { |
| 935 | 1058 | by = lut->data[k]; |
| 936 | − if (by != sy) | |
| 1059 | + if (by != sy) { | |
| 937 | 1060 | break; |
| 938 | −#if 0 | |
| 939 | −assert(0); | |
| 940 | −#endif | |
| 1061 | + } | |
| 941 | 1062 | } |
| 942 | 1063 | if (k < lut->size) { |
| 943 | 1064 | --k; |
| @@ -961,10 +1082,12 @@ assert(0); · 17 unmodified lines | ||
| 961 | 1082 | invlut->data[i] = sx; |
| 962 | 1083 | } |
| 963 | 1084 | #if 0 |
| 964 | −for (i=0;i<lut->size;++i) | |
| 965 | − jas_eprintf("lut[%d]=%f ", i, lut->data[i]); | |
| 966 | −for (i=0;i<invlut->size;++i) | |
| 967 | − jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]); | |
| 1085 | + for (i=0;i<lut->size;++i) { | |
| 1086 | + jas_eprintf("lut[%d]=%f ", i, lut->data[i]); | |
| 1087 | + } | |
| 1088 | + for (i=0;i<invlut->size;++i) { | |
| 1089 | + jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]); | |
| 1090 | + } | |
| 968 | 1091 | #endif |
| 969 | 1092 | return 0; |
| 970 | 1093 | } |
| @@ -975,11 +1098,11 @@ static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]) · 4 unmodified lines | ||
| 975 | 1098 | d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1]) |
| 976 | 1099 | - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0]) |
| 977 | 1100 | + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]); |
| 978 | −#if 0 | |
| 979 | −jas_eprintf("delta=%f\n", d); | |
| 980 | −#endif | |
| 981 | − if (JAS_ABS(d) < 1e-6) | |
| 1101 | + if (JAS_ABS(d) < 1e-6) { | |
| 1102 | + jas_logerrorf("jas_cmshapmat_invmat: matrix is not invertible " | |
| 1103 | + "(determinant %a)\n", d); | |
| 982 | 1104 | return -1; |
| 1105 | + } | |
| 983 | 1106 | out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d; |
| 984 | 1107 | out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d; |
| 985 | 1108 | out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d; |
| @@ -993,14 +1116,14 @@ jas_eprintf("delta=%f\n", d); · 7 unmodified lines | ||
| 993 | 1116 | out[1][3] = -in[1][3]; |
| 994 | 1117 | out[2][3] = -in[2][3]; |
| 995 | 1118 | #if 0 |
| 996 | −jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", | |
| 997 | −in[0][0], in[0][1], in[0][2], in[0][3], | |
| 998 | −in[1][0], in[1][1], in[1][2], in[1][3], | |
| 999 | −in[2][0], in[2][1], in[2][2], in[2][3]); | |
| 1000 | −jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", | |
| 1001 | −out[0][0], out[0][1], out[0][2], out[0][3], | |
| 1002 | −out[1][0], out[1][1], out[1][2], out[1][3], | |
| 1003 | −out[2][0], out[2][1], out[2][2], out[2][3]); | |
| 1119 | + jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", | |
| 1120 | + in[0][0], in[0][1], in[0][2], in[0][3], | |
| 1121 | + in[1][0], in[1][1], in[1][2], in[1][3], | |
| 1122 | + in[2][0], in[2][1], in[2][2], in[2][3]); | |
| 1123 | + jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", | |
| 1124 | + out[0][0], out[0][1], out[0][2], out[0][3], | |
| 1125 | + out[1][0], out[1][1], out[1][2], out[1][3], | |
| 1126 | + out[2][0], out[2][1], out[2][2], out[2][3]); | |
| 1004 | 1127 | #endif |
| 1005 | 1128 | return 0; |
| 1006 | 1129 | } |
| @@ -1009,30 +1132,34 @@ out[2][0], out[2][1], out[2][2], out[2][3]); · 2 unmodified lines | ||
| 1009 | 1132 | * |
| 1010 | 1133 | \******************************************************************************/ |
| 1011 | 1134 | |
| 1012 | −static jas_clrspc_t icctoclrspc(jas_iccsig_t iccclrspc, int refflag) | |
| 1135 | +static int icctoclrspc(jas_iccsig_t iccclrspc, jas_clrspc_t* clrspc, int refflag) | |
| 1013 | 1136 | { |
| 1014 | 1137 | if (refflag) { |
| 1015 | 1138 | switch (iccclrspc) { |
| 1016 | 1139 | case JAS_ICC_COLORSPC_XYZ: |
| 1017 | − return JAS_CLRSPC_CIEXYZ; | |
| 1140 | + *clrspc = JAS_CLRSPC_CIEXYZ; | |
| 1141 | + return 0; | |
| 1018 | 1142 | case JAS_ICC_COLORSPC_LAB: |
| 1019 | − return JAS_CLRSPC_CIELAB; | |
| 1143 | + *clrspc = JAS_CLRSPC_CIELAB; | |
| 1144 | + return 0; | |
| 1020 | 1145 | default: |
| 1021 | − abort(); | |
| 1146 | + return -1; | |
| 1022 | 1147 | } |
| 1023 | 1148 | } else { |
| 1024 | 1149 | switch (iccclrspc) { |
| 1025 | 1150 | case JAS_ICC_COLORSPC_YCBCR: |
| 1026 | − return JAS_CLRSPC_GENYCBCR; | |
| 1151 | + *clrspc = JAS_CLRSPC_GENYCBCR; | |
| 1152 | + return 0; | |
| 1027 | 1153 | case JAS_ICC_COLORSPC_RGB: |
| 1028 | − return JAS_CLRSPC_GENRGB; | |
| 1154 | + *clrspc = JAS_CLRSPC_GENRGB; | |
| 1155 | + return 0; | |
| 1029 | 1156 | case JAS_ICC_COLORSPC_GRAY: |
| 1030 | − return JAS_CLRSPC_GENGRAY; | |
| 1157 | + *clrspc = JAS_CLRSPC_GENGRAY; | |
| 1158 | + return 0; | |
| 1031 | 1159 | default: |
| 1032 | − abort(); | |
| 1160 | + return -1; | |
| 1033 | 1161 | } |
| 1034 | 1162 | } |
| 1035 | − return -1; | |
| 1036 | 1163 | } |
| 1037 | 1164 | |
| 1038 | 1165 | static int mono(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) |
| @@ -1045,15 +1172,19 @@ static int mono(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxf · 6 unmodified lines | ||
| 1045 | 1172 | |
| 1046 | 1173 | jas_cmshapmatlut_init(&lut); |
| 1047 | 1174 | if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) || |
| 1048 | − graytrc->type != JAS_ICC_TYPE_CURV) | |
| 1175 | + graytrc->type != JAS_ICC_TYPE_CURV) { | |
| 1049 | 1176 | goto error; |
| 1050 | − if (!(pxform = jas_cmpxform_createshapmat())) | |
| 1177 | + } | |
| 1178 | + if (!(pxform = jas_cmpxform_createshapmat())) { | |
| 1051 | 1179 | goto error; |
| 1180 | + } | |
| 1052 | 1181 | shapmat = &pxform->data.shapmat; |
| 1053 | − if (!(pxformseq = jas_cmpxformseq_create())) | |
| 1182 | + if (!(pxformseq = jas_cmpxformseq_create())) { | |
| 1054 | 1183 | goto error; |
| 1055 | − if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) | |
| 1184 | + } | |
| 1185 | + if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) { | |
| 1056 | 1186 | goto error; |
| 1187 | + } | |
| 1057 | 1188 | |
| 1058 | 1189 | pxform->numinchans = 1; |
| 1059 | 1190 | pxform->numoutchans = 3; |
| @@ -1066,18 +1197,21 @@ static int mono(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxf · 6 unmodified lines | ||
| 1066 | 1197 | shapmat->mat[0][0] = 0.9642; |
| 1067 | 1198 | shapmat->mat[1][0] = 1.0; |
| 1068 | 1199 | shapmat->mat[2][0] = 0.8249; |
| 1069 | − if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv)) | |
| 1200 | + if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv)) { | |
| 1070 | 1201 | goto error; |
| 1202 | + } | |
| 1071 | 1203 | } else { |
| 1072 | 1204 | shapmat->order = 1; |
| 1073 | 1205 | shapmat->mat[0][0] = 1.0 / 0.9642; |
| 1074 | 1206 | shapmat->mat[1][0] = 1.0; |
| 1075 | 1207 | shapmat->mat[2][0] = 1.0 / 0.8249; |
| 1076 | 1208 | jas_cmshapmatlut_init(&lut); |
| 1077 | − if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv)) | |
| 1209 | + if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv)) { | |
| 1078 | 1210 | goto error; |
| 1079 | − if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size)) | |
| 1211 | + } | |
| 1212 | + if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size)) { | |
| 1080 | 1213 | goto error; |
| 1214 | + } | |
| 1081 | 1215 | jas_cmshapmatlut_cleanup(&lut); |
| 1082 | 1216 | } |
| 1083 | 1217 | jas_iccattrval_destroy(graytrc); |
| @@ -1085,16 +1219,21 @@ static int mono(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxf · 1 unmodified line | ||
| 1085 | 1219 | *retpxformseq = pxformseq; |
| 1086 | 1220 | return 0; |
| 1087 | 1221 | error: |
| 1088 | − if (graytrc) | |
| 1222 | + jas_cmshapmatlut_cleanup(&lut); | |
| 1223 | + if (graytrc) { | |
| 1089 | 1224 | jas_iccattrval_destroy(graytrc); |
| 1090 | − if (pxform) | |
| 1225 | + } | |
| 1226 | + if (pxform) { | |
| 1091 | 1227 | jas_cmpxform_destroy(pxform); |
| 1092 | − if (pxformseq) | |
| 1228 | + } | |
| 1229 | + if (pxformseq) { | |
| 1093 | 1230 | jas_cmpxformseq_destroy(pxformseq); |
| 1231 | + } | |
| 1094 | 1232 | return -1; |
| 1095 | 1233 | } |
| 1096 | 1234 | |
| 1097 | −static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) | |
| 1235 | +static int triclr(const jas_iccprof_t *iccprof, int op, | |
| 1236 | + jas_cmpxformseq_t **retpxformseq) | |
| 1098 | 1237 | { |
| 1099 | 1238 | jas_iccattrval_t *trcs[3]; |
| 1100 | 1239 | jas_iccattrval_t *cols[3]; |
| @@ -1103,6 +1242,7 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 2 unmodified lines | ||
| 1103 | 1242 | jas_cmpxformseq_t *pxformseq; |
| 1104 | 1243 | jas_cmreal_t mat[3][4]; |
| 1105 | 1244 | jas_cmshapmatlut_t lut; |
| 1245 | + jas_cmshapmatlut_init(&lut); | |
| 1106 | 1246 | |
| 1107 | 1247 | pxform = 0; |
| 1108 | 1248 | pxformseq = 0; |
| @@ -1117,22 +1257,32 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 8 unmodified lines | ||
| 1117 | 1257 | !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) || |
| 1118 | 1258 | !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) || |
| 1119 | 1259 | !(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) || |
| 1120 | − !(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL))) | |
| 1260 | + !(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL))) { | |
| 1261 | + jas_logerrorf("error: unexpected attribute value\n"); | |
| 1121 | 1262 | goto error; |
| 1263 | + } | |
| 1122 | 1264 | for (unsigned i = 0; i < 3; ++i) { |
| 1123 | 1265 | if (trcs[i]->type != JAS_ICC_TYPE_CURV || |
| 1124 | − cols[i]->type != JAS_ICC_TYPE_XYZ) | |
| 1266 | + cols[i]->type != JAS_ICC_TYPE_XYZ) { | |
| 1267 | + jas_logerrorf("error: unexpected ICC profile type\n"); | |
| 1125 | 1268 | goto error; |
| 1269 | + } | |
| 1126 | 1270 | } |
| 1127 | − if (!(pxform = jas_cmpxform_createshapmat())) | |
| 1271 | + if (!(pxform = jas_cmpxform_createshapmat())) { | |
| 1272 | + jas_logerrorf("error: jas_cmpxform_createshapmat failed\n"); | |
| 1128 | 1273 | goto error; |
| 1274 | + } | |
| 1129 | 1275 | pxform->numinchans = 3; |
| 1130 | 1276 | pxform->numoutchans = 3; |
| 1131 | 1277 | shapmat = &pxform->data.shapmat; |
| 1132 | − if (!(pxformseq = jas_cmpxformseq_create())) | |
| 1278 | + if (!(pxformseq = jas_cmpxformseq_create())) { | |
| 1279 | + jas_logerrorf("error: jas_cmpxformseq_create failed\n"); | |
| 1133 | 1280 | goto error; |
| 1134 | − if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) | |
| 1281 | + } | |
| 1282 | + if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) { | |
| 1283 | + jas_logerrorf("error: jas_cmpxformseq_insertpxform failed\n"); | |
| 1135 | 1284 | goto error; |
| 1285 | + } | |
| 1136 | 1286 | shapmat->mono = 0; |
| 1137 | 1287 | shapmat->useluts = 1; |
| 1138 | 1288 | shapmat->usemat = 1; |
| @@ -1143,11 +1293,14 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 4 unmodified lines | ||
| 1143 | 1293 | shapmat->mat[1][i] = (jas_cmreal_t)cols[i]->data.xyz.y / 65536.0; |
| 1144 | 1294 | shapmat->mat[2][i] = (jas_cmreal_t)cols[i]->data.xyz.z / 65536.0; |
| 1145 | 1295 | } |
| 1146 | − for (unsigned i = 0; i < 3; ++i) | |
| 1296 | + for (unsigned i = 0; i < 3; ++i) { | |
| 1147 | 1297 | shapmat->mat[i][3] = 0.0; |
| 1298 | + } | |
| 1148 | 1299 | for (unsigned i = 0; i < 3; ++i) { |
| 1149 | − if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv)) | |
| 1300 | + if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv)) { | |
| 1301 | + jas_logerrorf("error: jas_cmshapmatlut_set failed\n"); | |
| 1150 | 1302 | goto error; |
| 1303 | + } | |
| 1151 | 1304 | } |
| 1152 | 1305 | } else { |
| 1153 | 1306 | shapmat->order = 1; |
| @@ -1156,16 +1309,23 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 2 unmodified lines | ||
| 1156 | 1309 | mat[1][i] = (jas_cmreal_t)cols[i]->data.xyz.y / 65536.0; |
| 1157 | 1310 | mat[2][i] = (jas_cmreal_t)cols[i]->data.xyz.z / 65536.0; |
| 1158 | 1311 | } |
| 1159 | − for (unsigned i = 0; i < 3; ++i) | |
| 1312 | + for (unsigned i = 0; i < 3; ++i) { | |
| 1160 | 1313 | mat[i][3] = 0.0; |
| 1161 | − if (jas_cmshapmat_invmat(shapmat->mat, mat)) | |
| 1314 | + } | |
| 1315 | + if (jas_cmshapmat_invmat(shapmat->mat, mat)) { | |
| 1316 | + jas_logerrorf("error: jas_cmshapmat_invmat failed\n"); | |
| 1162 | 1317 | goto error; |
| 1318 | + } | |
| 1163 | 1319 | for (unsigned i = 0; i < 3; ++i) { |
| 1164 | 1320 | jas_cmshapmatlut_init(&lut); |
| 1165 | − if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv)) | |
| 1321 | + if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv)) { | |
| 1322 | + jas_logerrorf("error: jas_cmshapmatlut_set failed\n"); | |
| 1166 | 1323 | goto error; |
| 1167 | − if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size)) | |
| 1324 | + } | |
| 1325 | + if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size)) { | |
| 1326 | + jas_logerrorf("error: jas_cmshapmatlut_invert failed\n"); | |
| 1168 | 1327 | goto error; |
| 1328 | + } | |
| 1169 | 1329 | jas_cmshapmatlut_cleanup(&lut); |
| 1170 | 1330 | } |
| 1171 | 1331 | } |
| @@ -1179,6 +1339,7 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 7 unmodified lines | ||
| 1179 | 1339 | |
| 1180 | 1340 | error: |
| 1181 | 1341 | |
| 1342 | + jas_cmshapmatlut_cleanup(&lut); | |
| 1182 | 1343 | for (unsigned i = 0; i < 3; ++i) { |
| 1183 | 1344 | if (trcs[i]) { |
| 1184 | 1345 | jas_iccattrval_destroy(trcs[i]); |
| @@ -1204,11 +1365,13 @@ static int jas_cmgetint(const long **bufptr, int sgnd, unsigned prec, long *val) · 19 unmodified lines | ||
| 1204 | 1365 | v = **bufptr; |
| 1205 | 1366 | if (sgnd) { |
| 1206 | 1367 | m = (1 << (prec - 1)); |
| 1207 | − if (v < -m || v >= m) | |
| 1368 | + if (v < -m || v >= m) { | |
| 1208 | 1369 | return -1; |
| 1370 | + } | |
| 1209 | 1371 | } else { |
| 1210 | − if (v < 0 || v >= (1 << prec)) | |
| 1372 | + if (v < 0 || v >= (1 << prec)) { | |
| 1211 | 1373 | return -1; |
| 1374 | + } | |
| 1212 | 1375 | } |
| 1213 | 1376 | ++(*bufptr); |
| 1214 | 1377 | *val = v; |
| @@ -1220,11 +1383,13 @@ static int jas_cmputint(long **bufptr, int sgnd, unsigned prec, long val) · 5 unmodified lines | ||
| 1220 | 1383 | int m; |
| 1221 | 1384 | if (sgnd) { |
| 1222 | 1385 | m = (1 << (prec - 1)); |
| 1223 | − if (val < -m || val >= m) | |
| 1386 | + if (val < -m || val >= m) { | |
| 1224 | 1387 | return -1; |
| 1388 | + } | |
| 1225 | 1389 | } else { |
| 1226 | − if (val < 0 || val >= (1 << prec)) | |
| 1390 | + if (val < 0 || val >= (1 << prec)) { | |
| 1227 | 1391 | return -1; |
| 1392 | + } | |
| 1228 | 1393 | } |
| 1229 | 1394 | **bufptr = val; |
| 1230 | 1395 | ++(*bufptr); |
| @@ -1243,8 +1408,8 @@ unsigned jas_clrspc_numchans(jas_clrspc_t clrspc) · 12 unmodified lines | ||
| 1243 | 1408 | return 1; |
| 1244 | 1409 | default: |
| 1245 | 1410 | abort(); |
| 1411 | + return 0; | |
| 1246 | 1412 | } |
| 1247 | − return -1; | |
| 1248 | 1413 | } |
| 1249 | 1414 | |
| 1250 | 1415 | jas_iccprof_t *jas_iccprof_createfromcmprof(const jas_cmprof_t *prof) |
| @@ -63,53 +63,214 @@ · 62 unmodified lines | ||
| 63 | 63 | * Includes. |
| 64 | 64 | \******************************************************************************/ |
| 65 | 65 | |
| 66 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 67 | + | |
| 68 | +#include "jasper/jas_init.h" | |
| 69 | +#include "jasper/jas_compiler.h" | |
| 66 | 70 | #include "jasper/jas_debug.h" |
| 67 | 71 | #include "jasper/jas_types.h" |
| 72 | +#include "jasper/jas_log.h" | |
| 68 | 73 | |
| 69 | 74 | /******************************************************************************\ |
| 70 | −* Local data. | |
| 75 | +* Code for getting/setting the debug level. | |
| 71 | 76 | \******************************************************************************/ |
| 72 | 77 | |
| 73 | −static int jas_dbglevel = 0; | |
| 74 | −/* The debug level. */ | |
| 78 | +/* Set the library debug level. */ | |
| 79 | +JAS_DEPRECATED | |
| 80 | +int jas_setdbglevel(int level) | |
| 81 | +{ | |
| 82 | + jas_deprecated("jas_setdbglevel is deprecated\n"); | |
| 83 | + int old_level = jas_get_debug_level(); | |
| 84 | + jas_set_debug_level(level); | |
| 85 | + return old_level; | |
| 86 | +} | |
| 75 | 87 | |
| 76 | 88 | /******************************************************************************\ |
| 77 | −* Code for getting/setting the debug level. | |
| 89 | +* Code. | |
| 78 | 90 | \******************************************************************************/ |
| 79 | 91 | |
| 80 | −/* Set the library debug level. */ | |
| 81 | −int jas_setdbglevel(int dbglevel) | |
| 92 | +/* Perform formatted output to standard error. */ | |
| 93 | +int jas_eprintf(const char *fmt, ...) | |
| 82 | 94 | { |
| 83 | − int olddbglevel; | |
| 95 | + int ret; | |
| 96 | + va_list ap; | |
| 97 | + va_start(ap, fmt); | |
| 98 | + ret = vfprintf(stderr, fmt, ap); | |
| 99 | + va_end(ap); | |
| 100 | + return ret; | |
| 101 | +} | |
| 84 | 102 | |
| 85 | − /* Save the old debug level. */ | |
| 86 | − olddbglevel = jas_dbglevel; | |
| 103 | +/* Generate formatted error log message. */ | |
| 104 | +int jas_logprintf(const char *fmt, ...) | |
| 105 | +{ | |
| 106 | + int ret; | |
| 107 | + va_list ap; | |
| 108 | + va_start(ap, fmt); | |
| 109 | + ret = jas_vlogmsgf(jas_logtype_init(JAS_LOGTYPE_CLASS_NULL, 0), fmt, | |
| 110 | + ap); | |
| 111 | + va_end(ap); | |
| 112 | + return ret; | |
| 113 | +} | |
| 87 | 114 | |
| 88 | − /* Change the debug level. */ | |
| 89 | − jas_dbglevel = dbglevel; | |
| 115 | +/* Generate formatted error log message. */ | |
| 116 | +int jas_logerrorf(const char *fmt, ...) | |
| 117 | +{ | |
| 118 | + int ret; | |
| 119 | + va_list ap; | |
| 120 | + va_start(ap, fmt); | |
| 121 | + ret = jas_vlogmsgf(jas_logtype_init(JAS_LOGTYPE_CLASS_ERROR, 0), fmt, | |
| 122 | + ap); | |
| 123 | + va_end(ap); | |
| 124 | + return ret; | |
| 125 | +} | |
| 90 | 126 | |
| 91 | − /* Return the old debug level. */ | |
| 92 | − return olddbglevel; | |
| 127 | +/* Generate formatted warning log message. */ | |
| 128 | +int jas_logwarnf(const char *fmt, ...) | |
| 129 | +{ | |
| 130 | + int ret; | |
| 131 | + va_list ap; | |
| 132 | + va_start(ap, fmt); | |
| 133 | + ret = jas_vlogmsgf(jas_logtype_init(JAS_LOGTYPE_CLASS_WARN, 0), fmt, | |
| 134 | + ap); | |
| 135 | + va_end(ap); | |
| 136 | + return ret; | |
| 93 | 137 | } |
| 94 | 138 | |
| 95 | −/* Get the library debug level. */ | |
| 96 | −int jas_getdbglevel() | |
| 139 | +/* Generate formatted informational log message. */ | |
| 140 | +int jas_loginfof(const char *fmt, ...) | |
| 97 | 141 | { |
| 98 | − return jas_dbglevel; | |
| 142 | + int ret; | |
| 143 | + va_list ap; | |
| 144 | + va_start(ap, fmt); | |
| 145 | + ret = jas_vlogmsgf(jas_logtype_init(JAS_LOGTYPE_CLASS_INFO, 0), fmt, | |
| 146 | + ap); | |
| 147 | + va_end(ap); | |
| 148 | + return ret; | |
| 149 | +} | |
| 150 | + | |
| 151 | +/* Generate formatted debugging log message. */ | |
| 152 | +int jas_logdebugf(int priority, const char *fmt, ...) | |
| 153 | +{ | |
| 154 | + int ret; | |
| 155 | + va_list ap; | |
| 156 | + va_start(ap, fmt); | |
| 157 | + ret = jas_vlogmsgf(jas_logtype_init(JAS_LOGTYPE_CLASS_DEBUG, priority), | |
| 158 | + fmt, ap); | |
| 159 | + va_end(ap); | |
| 160 | + return ret; | |
| 161 | +} | |
| 162 | + | |
| 163 | +/*! | |
| 164 | +@brief | |
| 165 | +@details | |
| 166 | +*/ | |
| 167 | +JAS_EXPORT | |
| 168 | +int jas_vlogmsgf(jas_logtype_t type, const char *fmt, va_list ap) | |
| 169 | +{ | |
| 170 | + int ret; | |
| 171 | + jas_vlogmsgf_t *func = jas_get_vlogmsgf(); | |
| 172 | + ret = func(type, fmt, ap); | |
| 173 | + return ret; | |
| 174 | +} | |
| 175 | + | |
| 176 | +/* Perform formatted output to standard error. */ | |
| 177 | +JAS_EXPORT | |
| 178 | +int jas_vlogmsgf_stderr(jas_logtype_t type, const char *fmt, va_list ap) | |
| 179 | +{ | |
| 180 | +#if 1 | |
| 181 | + JAS_UNUSED(type); | |
| 182 | + int result = vfprintf(stderr, fmt, ap); | |
| 183 | + return result; | |
| 184 | +#else | |
| 185 | + const char *s = "INVALID"; | |
| 186 | + switch (jas_logtype_getclass(type)) { | |
| 187 | + case JAS_LOGTYPE_CLASS_NULL: | |
| 188 | + s = "OTHER"; | |
| 189 | + break; | |
| 190 | + case JAS_LOGTYPE_CLASS_ERROR: | |
| 191 | + s = "ERROR"; | |
| 192 | + break; | |
| 193 | + case JAS_LOGTYPE_CLASS_WARN: | |
| 194 | + s = "WARNING"; | |
| 195 | + break; | |
| 196 | + case JAS_LOGTYPE_CLASS_INFO: | |
| 197 | + s = "INFO"; | |
| 198 | + break; | |
| 199 | + case JAS_LOGTYPE_CLASS_DEBUG: | |
| 200 | + s = "DEBUG"; | |
| 201 | + break; | |
| 202 | + } | |
| 203 | + int r1 = fprintf(stderr, "%s: ", s); | |
| 204 | + int r2 = vfprintf(stderr, fmt, ap); | |
| 205 | + int result = -1; | |
| 206 | + if (r1 > 0 && r2 > 0) { | |
| 207 | + result = r1 + r2; | |
| 208 | + } | |
| 209 | + return result; | |
| 210 | +#endif | |
| 211 | +} | |
| 212 | + | |
| 213 | +/* Perform formatted output to standard error. */ | |
| 214 | +JAS_EXPORT | |
| 215 | +int jas_vlogmsgf_discard(jas_logtype_t type, const char *fmt, va_list ap) | |
| 216 | +{ | |
| 217 | + JAS_UNUSED(type); | |
| 218 | + JAS_CAST(void, fmt); | |
| 219 | + JAS_CAST(void, ap); | |
| 220 | + return 0; | |
| 221 | +} | |
| 222 | + | |
| 223 | +/* Dump memory to a stream. */ | |
| 224 | +int jas_memdump(FILE *out, const void *data, size_t len) | |
| 225 | +{ | |
| 226 | + size_t i; | |
| 227 | + size_t j; | |
| 228 | + const jas_uchar *dp = data; | |
| 229 | + for (i = 0; i < len; i += 16) { | |
| 230 | + fprintf(out, "%04zx:", i); | |
| 231 | + for (j = 0; j < 16; ++j) { | |
| 232 | + if (i + j < len) { | |
| 233 | + fprintf(out, " %02x", dp[i + j]); | |
| 234 | + } | |
| 235 | + } | |
| 236 | + fprintf(out, "\n"); | |
| 237 | + } | |
| 238 | + return 0; | |
| 239 | +} | |
| 240 | + | |
| 241 | +/* Dump memory to a stream. */ | |
| 242 | +int jas_logmemdump(const void *data, size_t len) | |
| 243 | +{ | |
| 244 | + size_t i; | |
| 245 | + size_t j; | |
| 246 | + const jas_uchar *dp = data; | |
| 247 | + for (i = 0; i < len; i += 16) { | |
| 248 | + jas_logprintf("%04zx:", i); | |
| 249 | + for (j = 0; j < 16; ++j) { | |
| 250 | + if (i + j < len) { | |
| 251 | + jas_logprintf(" %02x", dp[i + j]); | |
| 252 | + } | |
| 253 | + } | |
| 254 | + jas_logprintf("\n"); | |
| 255 | + } | |
| 256 | + return 0; | |
| 99 | 257 | } |
| 100 | 258 | |
| 101 | 259 | /******************************************************************************\ |
| 102 | 260 | * Code. |
| 103 | 261 | \******************************************************************************/ |
| 104 | 262 | |
| 105 | −/* Perform formatted output to standard error. */ | |
| 106 | −int jas_eprintf(const char *fmt, ...) | |
| 263 | +void jas_deprecated(const char *fmt, ...) | |
| 107 | 264 | { |
| 108 | − int ret; | |
| 265 | + static const char message[] = | |
| 266 | + "WARNING: YOUR CODE IS RELYING ON DEPRECATED FUNCTIONALITY IN THE JASPER\n" | |
| 267 | + "LIBRARY. THIS FUNCTIONALITY WILL BE REMOVED IN THE NEAR FUTURE. PLEASE\n" | |
| 268 | + "FIX THIS PROBLEM BEFORE YOUR CODE STOPS WORKING.\n" | |
| 269 | + ; | |
| 270 | + fprintf(stderr, "%s", message); | |
| 271 | + fprintf(stderr, "deprecation warning: "); | |
| 109 | 272 | va_list ap; |
| 110 | − | |
| 111 | 273 | va_start(ap, fmt); |
| 112 | − ret = vfprint(2, fmt, ap); | |
| 274 | + vfprintf(stderr, fmt, ap); | |
| 113 | 275 | va_end(ap); |
| 114 | − return ret; | |
| 115 | 276 | } |
| @@ -59,12 +59,23 @@ · 58 unmodified lines | ||
| 59 | 59 | * __END_OF_JASPER_LICENSE__ |
| 60 | 60 | */ |
| 61 | 61 | |
| 62 | +/******************************************************************************\ | |
| 63 | +* Includes. | |
| 64 | +\******************************************************************************/ | |
| 65 | + | |
| 66 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 67 | + | |
| 62 | 68 | #include "jasper/jas_icc.h" |
| 63 | 69 | #include "jasper/jas_types.h" |
| 64 | 70 | #include "jasper/jas_malloc.h" |
| 65 | 71 | #include "jasper/jas_debug.h" |
| 66 | 72 | #include "jasper/jas_cm.h" |
| 67 | 73 | #include "jasper/jas_stream.h" |
| 74 | +#include "jasper/jas_string.h" | |
| 75 | + | |
| 76 | +/******************************************************************************\ | |
| 77 | +* | |
| 78 | +\******************************************************************************/ | |
| 68 | 79 | |
| 69 | 80 | #define jas_iccputuint8(out, val) jas_iccputuint(out, 1, val) |
| 70 | 81 | #define jas_iccputuint16(out, val) jas_iccputuint(out, 2, val) |
| @@ -80,15 +91,11 @@ static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val); · 9 unmodified lines | ||
| 80 | 91 | static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val); |
| 81 | 92 | static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val); |
| 82 | 93 | static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val); |
| 83 | −//#ifdef JAS_ENABLE_ENCODER | |
| 84 | 94 | static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val); |
| 85 | 95 | static int jas_iccputsint(jas_stream_t *out, unsigned n, jas_longlong val); |
| 86 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 87 | 96 | static jas_iccprof_t *jas_iccprof_create(void); |
| 88 | 97 | static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr); |
| 89 | −//#ifdef JAS_ENABLE_ENCODER | |
| 90 | 98 | static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr); |
| 91 | −//#endif | |
| 92 | 99 | static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab); |
| 93 | 100 | static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab); |
| 94 | 101 | static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, jas_iccuint32_t name); |
| @@ -104,9 +111,8 @@ static int jas_icccurv_copy(jas_iccattrval_t *attrval, · 9 unmodified lines | ||
| 104 | 111 | static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 105 | 112 | unsigned cnt); |
| 106 | 113 | static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval); |
| 107 | −//#ifdef JAS_ENABLE_ENCODER | |
| 108 | 114 | static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out); |
| 109 | −//#endif | |
| 115 | +static void jas_icccurv_dump(const jas_iccattrval_t *attrval, FILE *out); | |
| 110 | 116 | |
| 111 | 117 | static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval); |
| 112 | 118 | static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval, |
| @@ -114,9 +120,8 @@ static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval, · 1 unmodified line | ||
| 114 | 120 | static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 115 | 121 | unsigned cnt); |
| 116 | 122 | static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval); |
| 117 | −//#ifdef JAS_ENABLE_ENCODER | |
| 118 | 123 | static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out); |
| 119 | −//#endif | |
| 124 | +static void jas_icctxtdesc_dump(const jas_iccattrval_t *attrval, FILE *out); | |
| 120 | 125 | |
| 121 | 126 | static void jas_icctxt_destroy(jas_iccattrval_t *attrval); |
| 122 | 127 | static int jas_icctxt_copy(jas_iccattrval_t *attrval, |
| @@ -124,16 +129,14 @@ static int jas_icctxt_copy(jas_iccattrval_t *attrval, · 1 unmodified line | ||
| 124 | 129 | static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 125 | 130 | unsigned cnt); |
| 126 | 131 | static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval); |
| 127 | −//#ifdef JAS_ENABLE_ENCODER | |
| 128 | 132 | static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out); |
| 129 | −//#endif | |
| 133 | +static void jas_icctxt_dump(const jas_iccattrval_t *attrval, FILE *out); | |
| 130 | 134 | |
| 131 | 135 | static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 132 | 136 | unsigned cnt); |
| 133 | 137 | static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval); |
| 134 | −//#ifdef JAS_ENABLE_ENCODER | |
| 135 | 138 | static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out); |
| 136 | −//#endif | |
| 139 | +static void jas_iccxyz_dump(const jas_iccattrval_t *attrval, FILE *out); | |
| 137 | 140 | |
| 138 | 141 | static jas_iccattrtab_t *jas_iccattrtab_create(void); |
| 139 | 142 | static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab); |
| @@ -143,12 +146,10 @@ static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i, · 3 unmodified lines | ||
| 143 | 146 | static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, unsigned i, |
| 144 | 147 | jas_iccuint32_t name, jas_iccattrval_t *val); |
| 145 | 148 | static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, unsigned i); |
| 146 | −//#ifdef JAS_ENABLE_ENCODER | |
| 147 | 149 | static unsigned jas_iccpadtomult(unsigned x, unsigned y); |
| 148 | 150 | static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i, |
| 149 | 151 | jas_iccattrname_t *name, jas_iccattrval_t **val); |
| 150 | 152 | static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab); |
| 151 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 152 | 153 | |
| 153 | 154 | static void jas_icclut16_destroy(jas_iccattrval_t *attrval); |
| 154 | 155 | static int jas_icclut16_copy(jas_iccattrval_t *attrval, |
| @@ -156,9 +157,8 @@ static int jas_icclut16_copy(jas_iccattrval_t *attrval, · 1 unmodified line | ||
| 156 | 157 | static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 157 | 158 | unsigned cnt); |
| 158 | 159 | static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval); |
| 159 | −//#ifdef JAS_ENABLE_ENCODER | |
| 160 | 160 | static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out); |
| 161 | −//#endif | |
| 161 | +static void jas_icclut16_dump(const jas_iccattrval_t *attrval, FILE *out); | |
| 162 | 162 | |
| 163 | 163 | static void jas_icclut8_destroy(jas_iccattrval_t *attrval); |
| 164 | 164 | static int jas_icclut8_copy(jas_iccattrval_t *attrval, |
| @@ -166,19 +166,19 @@ static int jas_icclut8_copy(jas_iccattrval_t *attrval, · 1 unmodified line | ||
| 166 | 166 | static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 167 | 167 | unsigned cnt); |
| 168 | 168 | static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval); |
| 169 | −//#ifdef JAS_ENABLE_ENCODER | |
| 170 | 169 | static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out); |
| 171 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 170 | +static void jas_icclut8_dump(const jas_iccattrval_t *attrval, FILE *out); | |
| 172 | 171 | |
| 173 | −//#ifdef JAS_ENABLE_ENCODER | |
| 174 | 172 | static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *ctime); |
| 175 | 173 | static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz); |
| 176 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 177 | 174 | |
| 178 | 175 | static unsigned jas_iccpowi(unsigned x, unsigned n); |
| 179 | 176 | |
| 180 | 177 | static char *jas_iccsigtostr(unsigned sig, char *buf); |
| 181 | 178 | |
| 179 | +/******************************************************************************\ | |
| 180 | +* Data. | |
| 181 | +\******************************************************************************/ | |
| 182 | 182 | |
| 183 | 183 | static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { |
| 184 | 184 | { |
| @@ -186,10 +186,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 1 unmodified line | ||
| 186 | 186 | jas_icccurv_destroy, |
| 187 | 187 | jas_icccurv_copy, |
| 188 | 188 | jas_icccurv_input, |
| 189 | −//#ifdef JAS_ENABLE_ENCODER | |
| 190 | 189 | jas_icccurv_output, |
| 191 | −//#endif | |
| 192 | 190 | jas_icccurv_getsize, |
| 191 | + jas_icccurv_dump, | |
| 193 | 192 | }, |
| 194 | 193 | }, |
| 195 | 194 | { |
| @@ -198,10 +197,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines | ||
| 198 | 197 | 0, |
| 199 | 198 | 0, |
| 200 | 199 | jas_iccxyz_input, |
| 201 | −//#ifdef JAS_ENABLE_ENCODER | |
| 202 | 200 | jas_iccxyz_output, |
| 203 | −//#endif | |
| 204 | 201 | jas_iccxyz_getsize, |
| 202 | + jas_iccxyz_dump, | |
| 205 | 203 | }, |
| 206 | 204 | }, |
| 207 | 205 | { |
| @@ -210,10 +208,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines | ||
| 210 | 208 | jas_icctxtdesc_destroy, |
| 211 | 209 | jas_icctxtdesc_copy, |
| 212 | 210 | jas_icctxtdesc_input, |
| 213 | −//#ifdef JAS_ENABLE_ENCODER | |
| 214 | 211 | jas_icctxtdesc_output, |
| 215 | −//#endif | |
| 216 | 212 | jas_icctxtdesc_getsize, |
| 213 | + jas_icctxtdesc_dump, | |
| 217 | 214 | }, |
| 218 | 215 | }, |
| 219 | 216 | { |
| @@ -222,10 +219,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines | ||
| 222 | 219 | jas_icctxt_destroy, |
| 223 | 220 | jas_icctxt_copy, |
| 224 | 221 | jas_icctxt_input, |
| 225 | −//#ifdef JAS_ENABLE_ENCODER | |
| 226 | 222 | jas_icctxt_output, |
| 227 | −//#endif | |
| 228 | 223 | jas_icctxt_getsize, |
| 224 | + jas_icctxt_dump, | |
| 229 | 225 | }, |
| 230 | 226 | }, |
| 231 | 227 | { |
| @@ -234,10 +230,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines | ||
| 234 | 230 | jas_icclut8_destroy, |
| 235 | 231 | jas_icclut8_copy, |
| 236 | 232 | jas_icclut8_input, |
| 237 | −//#ifdef JAS_ENABLE_ENCODER | |
| 238 | 233 | jas_icclut8_output, |
| 239 | −//#endif | |
| 240 | 234 | jas_icclut8_getsize, |
| 235 | + jas_icclut8_dump, | |
| 241 | 236 | }, |
| 242 | 237 | }, |
| 243 | 238 | { |
| @@ -245,10 +240,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 1 unmodified line | ||
| 245 | 240 | jas_icclut16_destroy, |
| 246 | 241 | jas_icclut16_copy, |
| 247 | 242 | jas_icclut16_input, |
| 248 | −//#ifdef JAS_ENABLE_ENCODER | |
| 249 | 243 | jas_icclut16_output, |
| 250 | −//#endif | |
| 251 | 244 | jas_icclut16_getsize, |
| 245 | + jas_icclut16_dump, | |
| 252 | 246 | }, |
| 253 | 247 | }, |
| 254 | 248 | { |
| @@ -257,9 +251,8 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines | ||
| 257 | 251 | 0, |
| 258 | 252 | 0, |
| 259 | 253 | 0, |
| 260 | −//#ifdef JAS_ENABLE_ENCODER | |
| 261 | 254 | 0, |
| 262 | −//#endif | |
| 255 | + 0, | |
| 263 | 256 | 0, |
| 264 | 257 | }, |
| 265 | 258 | } |
| @@ -275,46 +268,58 @@ static jas_iccprof_t *jas_iccprof_create() · 9 unmodified lines | ||
| 275 | 268 | if (!(prof = jas_malloc(sizeof(jas_iccprof_t)))) { |
| 276 | 269 | goto error; |
| 277 | 270 | } |
| 278 | − if (!(prof->attrtab = jas_iccattrtab_create())) | |
| 279 | − goto error; | |
| 280 | − memset(&prof->hdr, 0, sizeof(jas_icchdr_t)); | |
| 281 | 271 | prof->tagtab.numents = 0; |
| 282 | 272 | prof->tagtab.ents = 0; |
| 273 | + if (!(prof->attrtab = jas_iccattrtab_create())) { | |
| 274 | + goto error; | |
| 275 | + } | |
| 276 | + memset(&prof->hdr, 0, sizeof(jas_icchdr_t)); | |
| 283 | 277 | return prof; |
| 284 | 278 | error: |
| 285 | − if (prof) | |
| 279 | + if (prof) { | |
| 286 | 280 | jas_iccprof_destroy(prof); |
| 281 | + } | |
| 287 | 282 | return 0; |
| 288 | 283 | } |
| 289 | 284 | |
| 290 | 285 | jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof) |
| 291 | 286 | { |
| 292 | 287 | jas_iccprof_t *newprof; |
| 293 | − if (!(newprof = jas_iccprof_create())) | |
| 288 | + if (!(newprof = jas_iccprof_create())) { | |
| 294 | 289 | goto error; |
| 290 | + } | |
| 295 | 291 | newprof->hdr = prof->hdr; |
| 296 | 292 | newprof->tagtab.numents = 0; |
| 297 | 293 | newprof->tagtab.ents = 0; |
| 298 | 294 | assert(newprof->attrtab); |
| 299 | 295 | jas_iccattrtab_destroy(newprof->attrtab); |
| 300 | − if (!(newprof->attrtab = jas_iccattrtab_copy(prof->attrtab))) | |
| 296 | + if (!(newprof->attrtab = jas_iccattrtab_copy(prof->attrtab))) { | |
| 301 | 297 | goto error; |
| 298 | + } | |
| 302 | 299 | return newprof; |
| 303 | 300 | error: |
| 304 | − if (newprof) | |
| 301 | + if (newprof) { | |
| 305 | 302 | jas_iccprof_destroy(newprof); |
| 303 | + } | |
| 306 | 304 | return 0; |
| 307 | 305 | } |
| 308 | 306 | |
| 309 | 307 | void jas_iccprof_destroy(jas_iccprof_t *prof) |
| 310 | 308 | { |
| 311 | − if (prof->attrtab) | |
| 309 | + if (prof->attrtab) { | |
| 312 | 310 | jas_iccattrtab_destroy(prof->attrtab); |
| 313 | − if (prof->tagtab.ents) | |
| 311 | + } | |
| 312 | + if (prof->tagtab.ents) { | |
| 314 | 313 | jas_free(prof->tagtab.ents); |
| 314 | + } | |
| 315 | 315 | jas_free(prof); |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | +void jas_iccprof_dump(const jas_iccprof_t *prof, FILE *out) | |
| 319 | +{ | |
| 320 | + jas_iccattrtab_dump(prof->attrtab, out); | |
| 321 | +} | |
| 322 | + | |
| 318 | 323 | jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) |
| 319 | 324 | { |
| 320 | 325 | jas_iccprof_t *prof; |
| @@ -332,11 +337,11 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 11 unmodified lines | ||
| 332 | 337 | } |
| 333 | 338 | |
| 334 | 339 | if (jas_iccprof_readhdr(in, &prof->hdr)) { |
| 335 | − jas_eprintf("cannot get header\n"); | |
| 340 | + jas_logerrorf("cannot get header\n"); | |
| 336 | 341 | goto error; |
| 337 | 342 | } |
| 338 | 343 | if (jas_iccprof_gettagtab(in, &prof->tagtab)) { |
| 339 | − jas_eprintf("cannot get tab table\n"); | |
| 344 | + jas_logerrorf("cannot get tab table\n"); | |
| 340 | 345 | goto error; |
| 341 | 346 | } |
| 342 | 347 | jas_iccprof_sorttagtab(&prof->tagtab); |
| @@ -349,23 +354,24 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 6 unmodified lines | ||
| 349 | 354 | const jas_icctagtabent_t *tagtabent = &prof->tagtab.ents[i]; |
| 350 | 355 | if (tagtabent->off == JAS_CAST(jas_iccuint32_t, prevoff)) { |
| 351 | 356 | if (prevattrval) { |
| 352 | − if (!(attrval = jas_iccattrval_clone(prevattrval))) | |
| 357 | + if (!(attrval = jas_iccattrval_clone(prevattrval))) { | |
| 353 | 358 | goto error; |
| 354 | − if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) | |
| 359 | + } | |
| 360 | + if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) { | |
| 355 | 361 | goto error; |
| 362 | + } | |
| 356 | 363 | jas_iccattrval_destroy(attrval); |
| 357 | 364 | attrval = 0; |
| 358 | 365 | } else { |
| 359 | −#if 0 | |
| 360 | − jas_eprintf("warning: skipping unknown tag type\n"); | |
| 361 | −#endif | |
| 366 | + jas_logwarnf("warning: skipping unknown tag type\n"); | |
| 362 | 367 | } |
| 363 | 368 | continue; |
| 364 | 369 | } |
| 365 | 370 | reloff = tagtabent->off - curoff; |
| 366 | 371 | if (reloff > 0) { |
| 367 | − if (jas_stream_gobble(in, reloff) != reloff) | |
| 372 | + if (jas_stream_gobble(in, reloff) != reloff) { | |
| 368 | 373 | goto error; |
| 374 | + } | |
| 369 | 375 | curoff += reloff; |
| 370 | 376 | } else if (reloff < 0) { |
| 371 | 377 | goto error; |
| @@ -379,9 +385,7 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 7 unmodified lines | ||
| 379 | 385 | } |
| 380 | 386 | curoff += 8; |
| 381 | 387 | if (!jas_iccattrvalinfo_lookup(type)) { |
| 382 | −#if 0 | |
| 383 | − jas_eprintf("warning: skipping unknown tag type\n"); | |
| 384 | −#endif | |
| 388 | + jas_logwarnf("warning: skipping unknown tag type\n"); | |
| 385 | 389 | prevattrval = 0; |
| 386 | 390 | continue; |
| 387 | 391 | } |
| @@ -404,16 +408,17 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 16 unmodified lines | ||
| 404 | 408 | return prof; |
| 405 | 409 | |
| 406 | 410 | error: |
| 407 | − if (prof) | |
| 411 | + if (prof) { | |
| 408 | 412 | jas_iccprof_destroy(prof); |
| 409 | − if (attrval) | |
| 413 | + } | |
| 414 | + if (attrval) { | |
| 410 | 415 | jas_iccattrval_destroy(attrval); |
| 416 | + } | |
| 411 | 417 | return 0; |
| 412 | 418 | } |
| 413 | 419 | |
| 414 | 420 | int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out) |
| 415 | 421 | { |
| 416 | −//#ifdef JAS_ENABLE_ENCODER | |
| 417 | 422 | long curoff; |
| 418 | 423 | long reloff; |
| 419 | 424 | long newoff; |
| @@ -426,14 +431,16 @@ int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out) · 6 unmodified lines | ||
| 426 | 431 | |
| 427 | 432 | tagtab = &prof->tagtab; |
| 428 | 433 | if (!(tagtab->ents = jas_alloc2(prof->attrtab->numattrs, |
| 429 | − sizeof(jas_icctagtabent_t)))) | |
| 434 | + sizeof(jas_icctagtabent_t)))) { | |
| 430 | 435 | goto error; |
| 436 | + } | |
| 431 | 437 | tagtab->numents = prof->attrtab->numattrs; |
| 432 | 438 | curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents; |
| 433 | 439 | for (unsigned i = 0; i < tagtab->numents; ++i) { |
| 434 | 440 | tagtabent = &tagtab->ents[i]; |
| 435 | − if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) | |
| 441 | + if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) { | |
| 436 | 442 | goto error; |
| 443 | + } | |
| 437 | 444 | assert(attrval->ops->output); |
| 438 | 445 | tagtabent->tag = attrname; |
| 439 | 446 | tagtabent->data = &attrval->data; |
| @@ -462,49 +469,49 @@ int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out) · 22 unmodified lines | ||
| 462 | 469 | jas_iccattrval_destroy(attrval); |
| 463 | 470 | } |
| 464 | 471 | prof->hdr.size = curoff; |
| 465 | − if (jas_iccprof_writehdr(out, &prof->hdr)) | |
| 472 | + if (jas_iccprof_writehdr(out, &prof->hdr)) { | |
| 466 | 473 | goto error; |
| 467 | − if (jas_iccprof_puttagtab(out, &prof->tagtab)) | |
| 474 | + } | |
| 475 | + if (jas_iccprof_puttagtab(out, &prof->tagtab)) { | |
| 468 | 476 | goto error; |
| 477 | + } | |
| 469 | 478 | curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents; |
| 470 | 479 | for (unsigned i = 0; i < tagtab->numents;) { |
| 471 | 480 | tagtabent = &tagtab->ents[i]; |
| 472 | 481 | assert(curoff == JAS_CAST(long, tagtabent->off)); |
| 473 | − if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) | |
| 482 | + if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) { | |
| 474 | 483 | goto error; |
| 484 | + } | |
| 475 | 485 | if (jas_iccputuint32(out, attrval->type) || jas_stream_pad(out, |
| 476 | − 4, 0) != 4) | |
| 486 | + 4, 0) != 4) { | |
| 477 | 487 | goto error; |
| 478 | − if ((*attrval->ops->output)(attrval, out)) | |
| 488 | + } | |
| 489 | + if ((*attrval->ops->output)(attrval, out)) { | |
| 479 | 490 | goto error; |
| 491 | + } | |
| 480 | 492 | jas_iccattrval_destroy(attrval); |
| 481 | 493 | curoff += tagtabent->len; |
| 482 | 494 | ++i; |
| 483 | − while (i < tagtab->numents && | |
| 484 | − tagtab->ents[i].first) | |
| 495 | + while (i < tagtab->numents && tagtab->ents[i].first) { | |
| 485 | 496 | ++i; |
| 497 | + } | |
| 486 | 498 | newoff = (i < tagtab->numents) ? |
| 487 | 499 | tagtab->ents[i].off : prof->hdr.size; |
| 488 | 500 | reloff = newoff - curoff; |
| 489 | 501 | assert(reloff >= 0); |
| 490 | 502 | if (reloff > 0) { |
| 491 | − if (jas_stream_pad(out, reloff, 0) != reloff) | |
| 503 | + if (jas_stream_pad(out, reloff, 0) != reloff) { | |
| 492 | 504 | goto error; |
| 505 | + } | |
| 493 | 506 | curoff += reloff; |
| 494 | 507 | } |
| 495 | 508 | } |
| 496 | 509 | return 0; |
| 497 | 510 | error: |
| 498 | 511 | /* XXX - need to free some resources here */ |
| 499 | −//#else | |
| 500 | −// (void)prof; | |
| 501 | −// (void)out; | |
| 502 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 503 | 512 | return -1; |
| 504 | 513 | } |
| 505 | 514 | |
| 506 | −//#ifdef JAS_ENABLE_ENCODER | |
| 507 | − | |
| 508 | 515 | static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr) |
| 509 | 516 | { |
| 510 | 517 | if (jas_iccputuint32(out, hdr->size) || |
| @@ -523,30 +530,31 @@ static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr) · 12 unmodified lines | ||
| 523 | 530 | jas_iccputuint32(out, hdr->intent) || |
| 524 | 531 | jas_iccputxyz(out, &hdr->illum) || |
| 525 | 532 | jas_iccputuint32(out, hdr->creator) || |
| 526 | − jas_stream_pad(out, 44, 0) != 44) | |
| 533 | + jas_stream_pad(out, 44, 0) != 44) { | |
| 527 | 534 | return -1; |
| 535 | + } | |
| 528 | 536 | return 0; |
| 529 | 537 | } |
| 530 | 538 | |
| 531 | 539 | static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab) |
| 532 | 540 | { |
| 533 | 541 | jas_icctagtabent_t *tagtabent; |
| 534 | − if (jas_iccputuint32(out, tagtab->numents)) | |
| 542 | + if (jas_iccputuint32(out, tagtab->numents)) { | |
| 535 | 543 | goto error; |
| 544 | + } | |
| 536 | 545 | for (unsigned i = 0; i < tagtab->numents; ++i) { |
| 537 | 546 | tagtabent = &tagtab->ents[i]; |
| 538 | 547 | if (jas_iccputuint32(out, tagtabent->tag) || |
| 539 | 548 | jas_iccputuint32(out, tagtabent->off) || |
| 540 | − jas_iccputuint32(out, tagtabent->len)) | |
| 549 | + jas_iccputuint32(out, tagtabent->len)) { | |
| 541 | 550 | goto error; |
| 551 | + } | |
| 542 | 552 | } |
| 543 | 553 | return 0; |
| 544 | 554 | error: |
| 545 | 555 | return -1; |
| 546 | 556 | } |
| 547 | 557 | |
| 548 | −//#endif | |
| 549 | − | |
| 550 | 558 | static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr) |
| 551 | 559 | { |
| 552 | 560 | if (jas_iccgetuint32(in, &hdr->size) || |
| @@ -565,8 +573,9 @@ static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr) · 12 unmodified lines | ||
| 565 | 573 | jas_iccgetuint32(in, &hdr->intent) || |
| 566 | 574 | jas_iccgetxyz(in, &hdr->illum) || |
| 567 | 575 | jas_iccgetuint32(in, &hdr->creator) || |
| 568 | − jas_stream_gobble(in, 44) != 44) | |
| 576 | + jas_stream_gobble(in, 44) != 44) { | |
| 569 | 577 | return -1; |
| 578 | + } | |
| 570 | 579 | return 0; |
| 571 | 580 | } |
| 572 | 581 | |
| @@ -578,17 +587,20 @@ static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab) · 5 unmodified lines | ||
| 578 | 587 | jas_free(tagtab->ents); |
| 579 | 588 | tagtab->ents = 0; |
| 580 | 589 | } |
| 581 | − if (jas_iccgetuint32(in, &tagtab->numents)) | |
| 590 | + if (jas_iccgetuint32(in, &tagtab->numents)) { | |
| 582 | 591 | goto error; |
| 592 | + } | |
| 583 | 593 | if (!(tagtab->ents = jas_alloc2(tagtab->numents, |
| 584 | − sizeof(jas_icctagtabent_t)))) | |
| 594 | + sizeof(jas_icctagtabent_t)))) { | |
| 585 | 595 | goto error; |
| 596 | + } | |
| 586 | 597 | tagtabent = tagtab->ents; |
| 587 | 598 | for (unsigned i = 0; i < tagtab->numents; ++i) { |
| 588 | 599 | if (jas_iccgetuint32(in, &tagtabent->tag) || |
| 589 | 600 | jas_iccgetuint32(in, &tagtabent->off) || |
| 590 | − jas_iccgetuint32(in, &tagtabent->len)) | |
| 601 | + jas_iccgetuint32(in, &tagtabent->len)) { | |
| 591 | 602 | goto error; |
| 603 | + } | |
| 592 | 604 | ++tagtabent; |
| 593 | 605 | } |
| 594 | 606 | return 0; |
| @@ -605,10 +617,12 @@ jas_iccattrval_t *jas_iccprof_getattr(const jas_iccprof_t *prof, · 10 unmodified lines | ||
| 605 | 617 | { |
| 606 | 618 | int i; |
| 607 | 619 | jas_iccattrval_t *attrval; |
| 608 | − if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) < 0) | |
| 620 | + if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) < 0) { | |
| 609 | 621 | goto error; |
| 610 | − if (!(attrval = jas_iccattrval_clone(prof->attrtab->attrs[i].val))) | |
| 622 | + } | |
| 623 | + if (!(attrval = jas_iccattrval_clone(prof->attrtab->attrs[i].val))) { | |
| 611 | 624 | goto error; |
| 625 | + } | |
| 612 | 626 | return attrval; |
| 613 | 627 | error: |
| 614 | 628 | return 0; |
| @@ -620,15 +634,17 @@ int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name, · 5 unmodified lines | ||
| 620 | 634 | int i; |
| 621 | 635 | if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) >= 0) { |
| 622 | 636 | if (val) { |
| 623 | − if (jas_iccattrtab_replace(prof->attrtab, i, name, val)) | |
| 637 | + if (jas_iccattrtab_replace(prof->attrtab, i, name, val)) { | |
| 624 | 638 | goto error; |
| 639 | + } | |
| 625 | 640 | } else { |
| 626 | 641 | jas_iccattrtab_delete(prof->attrtab, i); |
| 627 | 642 | } |
| 628 | 643 | } else { |
| 629 | 644 | if (val) { |
| 630 | − if (jas_iccattrtab_add(prof->attrtab, -1, name, val)) | |
| 645 | + if (jas_iccattrtab_add(prof->attrtab, -1, name, val)) { | |
| 631 | 646 | goto error; |
| 647 | + } | |
| 632 | 648 | } else { |
| 633 | 649 | /* NOP */ |
| 634 | 650 | } |
| @@ -658,8 +674,10 @@ static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab) · 23 unmodified lines | ||
| 658 | 674 | |
| 659 | 675 | static int jas_icctagtabent_cmp(const void *src, const void *dst) |
| 660 | 676 | { |
| 661 | − const jas_icctagtabent_t *srctagtabent = JAS_CAST(const jas_icctagtabent_t *, src); | |
| 662 | − const jas_icctagtabent_t *dsttagtabent = JAS_CAST(const jas_icctagtabent_t *, dst); | |
| 677 | + const jas_icctagtabent_t *srctagtabent = | |
| 678 | + JAS_CAST(const jas_icctagtabent_t *, src); | |
| 679 | + const jas_icctagtabent_t *dsttagtabent = | |
| 680 | + JAS_CAST(const jas_icctagtabent_t *, dst); | |
| 663 | 681 | if (srctagtabent->off > dsttagtabent->off) { |
| 664 | 682 | return 1; |
| 665 | 683 | } else if (srctagtabent->off < dsttagtabent->off) { |
| @@ -702,29 +720,29 @@ static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz) · 36 unmodified lines | ||
| 702 | 720 | return 0; |
| 703 | 721 | } |
| 704 | 722 | |
| 705 | −//#ifdef JAS_ENABLE_ENCODER | |
| 706 | − | |
| 707 | 723 | static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *time) |
| 708 | 724 | { |
| 709 | − jas_iccputuint16(out, time->year); | |
| 710 | − jas_iccputuint16(out, time->month); | |
| 711 | − jas_iccputuint16(out, time->day); | |
| 712 | − jas_iccputuint16(out, time->hour); | |
| 713 | − jas_iccputuint16(out, time->min); | |
| 714 | − jas_iccputuint16(out, time->sec); | |
| 725 | + if (jas_iccputuint16(out, time->year) || | |
| 726 | + jas_iccputuint16(out, time->month) || | |
| 727 | + jas_iccputuint16(out, time->day) || | |
| 728 | + jas_iccputuint16(out, time->hour) || | |
| 729 | + jas_iccputuint16(out, time->min) || | |
| 730 | + jas_iccputuint16(out, time->sec)) { | |
| 731 | + return -1; | |
| 732 | + } | |
| 715 | 733 | return 0; |
| 716 | 734 | } |
| 717 | 735 | |
| 718 | 736 | static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz) |
| 719 | 737 | { |
| 720 | − jas_iccputuint32(out, xyz->x); | |
| 721 | − jas_iccputuint32(out, xyz->y); | |
| 722 | − jas_iccputuint32(out, xyz->z); | |
| 738 | + if (jas_iccputuint32(out, xyz->x) || | |
| 739 | + jas_iccputuint32(out, xyz->y) || | |
| 740 | + jas_iccputuint32(out, xyz->z)) { | |
| 741 | + return -1; | |
| 742 | + } | |
| 723 | 743 | return 0; |
| 724 | 744 | } |
| 725 | 745 | |
| 726 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 727 | − | |
| 728 | 746 | /******************************************************************************\ |
| 729 | 747 | * attribute table class |
| 730 | 748 | \******************************************************************************/ |
| @@ -732,29 +750,34 @@ static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz) · 1 unmodified line | ||
| 732 | 750 | static jas_iccattrtab_t *jas_iccattrtab_create() |
| 733 | 751 | { |
| 734 | 752 | jas_iccattrtab_t *tab; |
| 735 | − if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t)))) | |
| 753 | + if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t)))) { | |
| 736 | 754 | goto error; |
| 755 | + } | |
| 737 | 756 | tab->maxattrs = 0; |
| 738 | 757 | tab->numattrs = 0; |
| 739 | 758 | tab->attrs = 0; |
| 740 | − if (jas_iccattrtab_resize(tab, 32)) | |
| 759 | + if (jas_iccattrtab_resize(tab, 32)) { | |
| 741 | 760 | goto error; |
| 761 | + } | |
| 742 | 762 | return tab; |
| 743 | 763 | error: |
| 744 | − if (tab) | |
| 764 | + if (tab) { | |
| 745 | 765 | jas_iccattrtab_destroy(tab); |
| 766 | + } | |
| 746 | 767 | return 0; |
| 747 | 768 | } |
| 748 | 769 | |
| 749 | 770 | static jas_iccattrtab_t *jas_iccattrtab_copy(const jas_iccattrtab_t *attrtab) |
| 750 | 771 | { |
| 751 | 772 | jas_iccattrtab_t *newattrtab; |
| 752 | − if (!(newattrtab = jas_iccattrtab_create())) | |
| 773 | + if (!(newattrtab = jas_iccattrtab_create())) { | |
| 753 | 774 | return NULL; |
| 775 | + } | |
| 754 | 776 | for (unsigned i = 0; i < attrtab->numattrs; ++i) { |
| 755 | 777 | if (jas_iccattrtab_add(newattrtab, i, attrtab->attrs[i].name, |
| 756 | − attrtab->attrs[i].val)) | |
| 778 | + attrtab->attrs[i].val)) { | |
| 757 | 779 | goto error; |
| 780 | + } | |
| 758 | 781 | } |
| 759 | 782 | return newattrtab; |
| 760 | 783 | error: |
| @@ -773,6 +796,29 @@ static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab) · 12 unmodified lines | ||
| 773 | 796 | jas_free(tab); |
| 774 | 797 | } |
| 775 | 798 | |
| 799 | +void jas_iccattrtab_dump(const jas_iccattrtab_t *attrtab, FILE *out) | |
| 800 | +{ | |
| 801 | + char buf[16]; | |
| 802 | + fprintf(out, "numattrs=%d\n", attrtab->numattrs); | |
| 803 | + fprintf(out, "---\n"); | |
| 804 | + for (unsigned i = 0; i < attrtab->numattrs; ++i) { | |
| 805 | + const jas_iccattr_t *attr = &attrtab->attrs[i]; | |
| 806 | + const jas_iccattrval_t *attrval = attr->val; | |
| 807 | + const jas_iccattrvalinfo_t *info = jas_iccattrvalinfo_lookup(attrval->type); | |
| 808 | + assert(info); | |
| 809 | + JAS_UNUSED(info); | |
| 810 | + fprintf(out, "attrno=%d; attrname=\"%s\"(0x%08"PRIxFAST32"); attrtype=\"%s\"(0x%08"PRIxFAST32")\n", | |
| 811 | + i, | |
| 812 | + jas_iccsigtostr(attr->name, &buf[0]), | |
| 813 | + attr->name, | |
| 814 | + jas_iccsigtostr(attrval->type, &buf[8]), | |
| 815 | + attrval->type | |
| 816 | + ); | |
| 817 | + jas_iccattrval_dump(attrval, out); | |
| 818 | + fprintf(out, "---\n"); | |
| 819 | + } | |
| 820 | +} | |
| 821 | + | |
| 776 | 822 | static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, unsigned maxents) |
| 777 | 823 | { |
| 778 | 824 | jas_iccattr_t *newattrs; |
| @@ -801,12 +847,14 @@ static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i, · 22 unmodified lines | ||
| 801 | 847 | return -1; |
| 802 | 848 | } |
| 803 | 849 | } |
| 804 | − if (!(tmpattrval = jas_iccattrval_clone(val))) | |
| 850 | + if (!(tmpattrval = jas_iccattrval_clone(val))) { | |
| 805 | 851 | return -1; |
| 852 | + } | |
| 806 | 853 | const unsigned n = attrtab->numattrs - i; |
| 807 | − if (n > 0) | |
| 854 | + if (n > 0) { | |
| 808 | 855 | memmove(&attrtab->attrs[i + 1], &attrtab->attrs[i], |
| 809 | 856 | n * sizeof(jas_iccattr_t)); |
| 857 | + } | |
| 810 | 858 | attr = &attrtab->attrs[i]; |
| 811 | 859 | attr->name = name; |
| 812 | 860 | attr->val = tmpattrval; |
| @@ -819,8 +867,9 @@ static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, unsigned i, · 6 unmodified lines | ||
| 819 | 867 | { |
| 820 | 868 | jas_iccattrval_t *newval; |
| 821 | 869 | jas_iccattr_t *attr; |
| 822 | − if (!(newval = jas_iccattrval_clone(val))) | |
| 870 | + if (!(newval = jas_iccattrval_clone(val))) { | |
| 823 | 871 | goto error; |
| 872 | + } | |
| 824 | 873 | attr = &attrtab->attrs[i]; |
| 825 | 874 | jas_iccattrval_destroy(attr->val); |
| 826 | 875 | attr->name = name; |
| @@ -834,28 +883,29 @@ static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, unsigned i) · 7 unmodified lines | ||
| 834 | 883 | { |
| 835 | 884 | unsigned n; |
| 836 | 885 | jas_iccattrval_destroy(attrtab->attrs[i].val); |
| 837 | − if ((n = attrtab->numattrs - i - 1) > 0) | |
| 886 | + if ((n = attrtab->numattrs - i - 1) > 0) { | |
| 838 | 887 | memmove(&attrtab->attrs[i], &attrtab->attrs[i + 1], |
| 839 | 888 | n * sizeof(jas_iccattr_t)); |
| 889 | + } | |
| 840 | 890 | --attrtab->numattrs; |
| 841 | 891 | } |
| 842 | 892 | |
| 843 | −//#ifdef JAS_ENABLE_ENCODER | |
| 844 | 893 | static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i, |
| 845 | 894 | jas_iccattrname_t *name, jas_iccattrval_t **val) |
| 846 | 895 | { |
| 847 | 896 | jas_iccattr_t *attr; |
| 848 | − if (i >= attrtab->numattrs) | |
| 897 | + if (i >= attrtab->numattrs) { | |
| 849 | 898 | goto error; |
| 899 | + } | |
| 850 | 900 | attr = &attrtab->attrs[i]; |
| 851 | 901 | *name = attr->name; |
| 852 | − if (!(*val = jas_iccattrval_clone(attr->val))) | |
| 902 | + if (!(*val = jas_iccattrval_clone(attr->val))) { | |
| 853 | 903 | goto error; |
| 904 | + } | |
| 854 | 905 | return 0; |
| 855 | 906 | error: |
| 856 | 907 | return -1; |
| 857 | 908 | } |
| 858 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 859 | 909 | |
| 860 | 910 | static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, |
| 861 | 911 | jas_iccuint32_t name) |
| @@ -863,8 +913,9 @@ static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, · 1 unmodified line | ||
| 863 | 913 | jas_iccattr_t *attr; |
| 864 | 914 | for (unsigned i = 0; i < attrtab->numattrs; ++i) { |
| 865 | 915 | attr = &attrtab->attrs[i]; |
| 866 | − if (attr->name == name) | |
| 916 | + if (attr->name == name) { | |
| 867 | 917 | return i; |
| 918 | + } | |
| 868 | 919 | } |
| 869 | 920 | return -1; |
| 870 | 921 | } |
| @@ -878,10 +929,12 @@ jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type) · 7 unmodified lines | ||
| 878 | 929 | jas_iccattrval_t *attrval; |
| 879 | 930 | const jas_iccattrvalinfo_t *info; |
| 880 | 931 | |
| 881 | − if (!(info = jas_iccattrvalinfo_lookup(type))) | |
| 932 | + if (!(info = jas_iccattrvalinfo_lookup(type))) { | |
| 882 | 933 | goto error; |
| 883 | − if (!(attrval = jas_iccattrval_create0())) | |
| 934 | + } | |
| 935 | + if (!(attrval = jas_iccattrval_create0())) { | |
| 884 | 936 | goto error; |
| 937 | + } | |
| 885 | 938 | attrval->ops = &info->ops; |
| 886 | 939 | attrval->type = type; |
| 887 | 940 | ++attrval->refcnt; |
| @@ -903,25 +956,39 @@ void jas_iccattrval_destroy(jas_iccattrval_t *attrval) · 15 unmodified lines | ||
| 903 | 956 | jas_eprintf("refcnt=%d\n", attrval->refcnt); |
| 904 | 957 | #endif |
| 905 | 958 | if (--attrval->refcnt <= 0) { |
| 906 | − if (attrval->ops->destroy) | |
| 959 | + if (attrval->ops->destroy) { | |
| 907 | 960 | (*attrval->ops->destroy)(attrval); |
| 961 | + } | |
| 908 | 962 | jas_free(attrval); |
| 909 | 963 | } |
| 910 | 964 | } |
| 911 | 965 | |
| 966 | +void jas_iccattrval_dump(const jas_iccattrval_t *attrval, FILE *out) | |
| 967 | +{ | |
| 968 | + char buf[8]; | |
| 969 | + jas_iccsigtostr(attrval->type, buf); | |
| 970 | + fprintf(out, "refcnt = %d; type = 0x%08"PRIxFAST32" %s\n", attrval->refcnt, | |
| 971 | + attrval->type, jas_iccsigtostr(attrval->type, &buf[0])); | |
| 972 | + if (attrval->ops->dump) { | |
| 973 | + (*attrval->ops->dump)(attrval, out); | |
| 974 | + } | |
| 975 | +} | |
| 976 | + | |
| 912 | 977 | int jas_iccattrval_allowmodify(jas_iccattrval_t **attrvalx) |
| 913 | 978 | { |
| 914 | 979 | jas_iccattrval_t *newattrval; |
| 915 | 980 | jas_iccattrval_t *attrval = *attrvalx; |
| 916 | 981 | if (attrval->refcnt > 1) { |
| 917 | − if (!(newattrval = jas_iccattrval_create0())) | |
| 982 | + if (!(newattrval = jas_iccattrval_create0())) { | |
| 918 | 983 | goto error; |
| 984 | + } | |
| 919 | 985 | newattrval->ops = attrval->ops; |
| 920 | 986 | newattrval->type = attrval->type; |
| 921 | 987 | ++newattrval->refcnt; |
| 922 | 988 | if (newattrval->ops->copy) { |
| 923 | − if ((*newattrval->ops->copy)(newattrval, attrval)) | |
| 989 | + if ((*newattrval->ops->copy)(newattrval, attrval)) { | |
| 924 | 990 | goto error; |
| 991 | + } | |
| 925 | 992 | } else { |
| 926 | 993 | memcpy(&newattrval->data, &attrval->data, |
| 927 | 994 | sizeof(newattrval->data)); |
| @@ -939,8 +1006,9 @@ error: · 11 unmodified lines | ||
| 939 | 1006 | static jas_iccattrval_t *jas_iccattrval_create0() |
| 940 | 1007 | { |
| 941 | 1008 | jas_iccattrval_t *attrval; |
| 942 | − if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t)))) | |
| 1009 | + if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t)))) { | |
| 943 | 1010 | return 0; |
| 1011 | + } | |
| 944 | 1012 | memset(attrval, 0, sizeof(jas_iccattrval_t)); |
| 945 | 1013 | attrval->refcnt = 0; |
| 946 | 1014 | attrval->ops = 0; |
| @@ -955,31 +1023,36 @@ static jas_iccattrval_t *jas_iccattrval_create0() · 8 unmodified lines | ||
| 955 | 1023 | static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 956 | 1024 | unsigned len) |
| 957 | 1025 | { |
| 958 | − assert(len == 4 * 3); | |
| 959 | − (void)len; | |
| 1026 | + if (len != 4 * 3) { | |
| 1027 | + return -1; | |
| 1028 | + } | |
| 960 | 1029 | return jas_iccgetxyz(in, &attrval->data.xyz); |
| 961 | 1030 | } |
| 962 | 1031 | |
| 963 | −//#ifdef JAS_ENABLE_ENCODER | |
| 964 | 1032 | static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 965 | 1033 | { |
| 966 | 1034 | const jas_iccxyz_t *xyz = &attrval->data.xyz; |
| 967 | 1035 | if (jas_iccputuint32(out, xyz->x) || |
| 968 | 1036 | jas_iccputuint32(out, xyz->y) || |
| 969 | − jas_iccputuint32(out, xyz->z)) | |
| 1037 | + jas_iccputuint32(out, xyz->z)) { | |
| 970 | 1038 | return -1; |
| 1039 | + } | |
| 971 | 1040 | return 0; |
| 972 | 1041 | } |
| 973 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 974 | 1042 | |
| 975 | 1043 | static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval) |
| 976 | 1044 | { |
| 977 | − /* Avoid compiler warnings about unused parameters. */ | |
| 978 | − USED(attrval); | |
| 979 | − | |
| 1045 | + JAS_UNUSED(attrval); | |
| 980 | 1046 | return 12; |
| 981 | 1047 | } |
| 982 | 1048 | |
| 1049 | +static void jas_iccxyz_dump(const jas_iccattrval_t *attrval, FILE *out) | |
| 1050 | +{ | |
| 1051 | + const jas_iccxyz_t *xyz = &attrval->data.xyz; | |
| 1052 | + fprintf(out, "(%f, %f, %f)\n", xyz->x / 65536.0, xyz->y / 65536.0, | |
| 1053 | + xyz->z / 65536.0); | |
| 1054 | +} | |
| 1055 | + | |
| 983 | 1056 | /******************************************************************************\ |
| 984 | 1057 | * attribute table class |
| 985 | 1058 | \******************************************************************************/ |
| @@ -996,9 +1069,8 @@ static void jas_icccurv_destroy(jas_iccattrval_t *attrval) · 10 unmodified lines | ||
| 996 | 1069 | static int jas_icccurv_copy(jas_iccattrval_t *attrval, |
| 997 | 1070 | const jas_iccattrval_t *othattrval) |
| 998 | 1071 | { |
| 999 | − /* Avoid compiler warnings about unused parameters. */ | |
| 1000 | − USED(attrval); | |
| 1001 | − USED(othattrval); | |
| 1072 | + JAS_UNUSED(attrval); | |
| 1073 | + JAS_UNUSED(othattrval); | |
| 1002 | 1074 | |
| 1003 | 1075 | /* Not yet implemented. */ |
| 1004 | 1076 | abort(); |
| @@ -1013,17 +1085,21 @@ static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 8 unmodified lines | ||
| 1013 | 1085 | curv->numents = 0; |
| 1014 | 1086 | curv->ents = 0; |
| 1015 | 1087 | |
| 1016 | − if (jas_iccgetuint32(in, &curv->numents)) | |
| 1088 | + if (jas_iccgetuint32(in, &curv->numents)) { | |
| 1017 | 1089 | goto error; |
| 1018 | − if (!(curv->ents = jas_alloc2(curv->numents, sizeof(jas_iccuint16_t)))) | |
| 1090 | + } | |
| 1091 | + if (!(curv->ents = jas_alloc2(curv->numents, sizeof(jas_iccuint16_t)))) { | |
| 1019 | 1092 | goto error; |
| 1093 | + } | |
| 1020 | 1094 | for (unsigned i = 0; i < curv->numents; ++i) { |
| 1021 | − if (jas_iccgetuint16(in, &curv->ents[i])) | |
| 1095 | + if (jas_iccgetuint16(in, &curv->ents[i])) { | |
| 1022 | 1096 | goto error; |
| 1097 | + } | |
| 1023 | 1098 | } |
| 1024 | 1099 | |
| 1025 | − if (4 + 2 * curv->numents != cnt) | |
| 1100 | + if (4 + 2 * curv->numents != cnt) { | |
| 1026 | 1101 | goto error; |
| 1102 | + } | |
| 1027 | 1103 | return 0; |
| 1028 | 1104 | |
| 1029 | 1105 | error: |
| @@ -1037,22 +1113,37 @@ static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval) · 7 unmodified lines | ||
| 1037 | 1113 | return 4 + 2 * curv->numents; |
| 1038 | 1114 | } |
| 1039 | 1115 | |
| 1040 | −//#ifdef JAS_ENABLE_ENCODER | |
| 1041 | 1116 | static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1042 | 1117 | { |
| 1043 | 1118 | const jas_icccurv_t *curv = &attrval->data.curv; |
| 1044 | 1119 | |
| 1045 | − if (jas_iccputuint32(out, curv->numents)) | |
| 1120 | + if (jas_iccputuint32(out, curv->numents)) { | |
| 1046 | 1121 | goto error; |
| 1122 | + } | |
| 1047 | 1123 | for (unsigned i = 0; i < curv->numents; ++i) { |
| 1048 | − if (jas_iccputuint16(out, curv->ents[i])) | |
| 1124 | + if (jas_iccputuint16(out, curv->ents[i])) { | |
| 1049 | 1125 | goto error; |
| 1126 | + } | |
| 1050 | 1127 | } |
| 1051 | 1128 | return 0; |
| 1052 | 1129 | error: |
| 1053 | 1130 | return -1; |
| 1054 | 1131 | } |
| 1055 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 1132 | + | |
| 1133 | +static void jas_icccurv_dump(const jas_iccattrval_t *attrval, FILE *out) | |
| 1134 | +{ | |
| 1135 | + const jas_icccurv_t *curv = &attrval->data.curv; | |
| 1136 | + fprintf(out, "number of entries = %"PRIuFAST32"\n", curv->numents); | |
| 1137 | + if (curv->numents == 1) { | |
| 1138 | + fprintf(out, "gamma = %f\n", curv->ents[0] / 256.0); | |
| 1139 | + } else { | |
| 1140 | + for (unsigned i = 0; i < curv->numents; ++i) { | |
| 1141 | + if (i < 3 || i >= curv->numents - 3) { | |
| 1142 | + fprintf(out, "entry[%d] = %f\n", i, curv->ents[i] / 65535.0); | |
| 1143 | + } | |
| 1144 | + } | |
| 1145 | + } | |
| 1146 | +} | |
| 1056 | 1147 | |
| 1057 | 1148 | /******************************************************************************\ |
| 1058 | 1149 | * |
| @@ -1076,10 +1167,9 @@ static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval, · 17 unmodified lines | ||
| 1076 | 1167 | { |
| 1077 | 1168 | jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; |
| 1078 | 1169 | |
| 1079 | − /* Avoid compiler warnings about unused parameters. */ | |
| 1080 | − USED(attrval); | |
| 1081 | − USED(othattrval); | |
| 1082 | − USED(txtdesc); | |
| 1170 | + JAS_UNUSED(attrval); | |
| 1171 | + JAS_UNUSED(othattrval); | |
| 1172 | + JAS_UNUSED(txtdesc); | |
| 1083 | 1173 | |
| 1084 | 1174 | /* Not yet implemented. */ |
| 1085 | 1175 | abort(); |
| @@ -1093,31 +1183,41 @@ static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 7 unmodified lines | ||
| 1093 | 1183 | jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; |
| 1094 | 1184 | txtdesc->ascdata = 0; |
| 1095 | 1185 | txtdesc->ucdata = 0; |
| 1096 | − if (jas_iccgetuint32(in, &txtdesc->asclen)) | |
| 1186 | + if (jas_iccgetuint32(in, &txtdesc->asclen)) { | |
| 1097 | 1187 | goto error; |
| 1098 | − if (txtdesc->asclen < 1) | |
| 1188 | + } | |
| 1189 | + if (txtdesc->asclen < 1) { | |
| 1099 | 1190 | goto error; |
| 1100 | − if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen))) | |
| 1191 | + } | |
| 1192 | + if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen))) { | |
| 1101 | 1193 | goto error; |
| 1194 | + } | |
| 1102 | 1195 | if (jas_stream_read(in, txtdesc->ascdata, txtdesc->asclen) != |
| 1103 | − txtdesc->asclen) | |
| 1196 | + txtdesc->asclen) { | |
| 1104 | 1197 | goto error; |
| 1198 | + } | |
| 1105 | 1199 | txtdesc->ascdata[txtdesc->asclen - 1] = '\0'; |
| 1106 | 1200 | if (jas_iccgetuint32(in, &txtdesc->uclangcode) || |
| 1107 | − jas_iccgetuint32(in, &txtdesc->uclen)) | |
| 1201 | + jas_iccgetuint32(in, &txtdesc->uclen)) { | |
| 1108 | 1202 | goto error; |
| 1109 | − if (!(txtdesc->ucdata = jas_alloc2(txtdesc->uclen, 2))) | |
| 1203 | + } | |
| 1204 | + if (!(txtdesc->ucdata = jas_alloc2(txtdesc->uclen, 2))) { | |
| 1110 | 1205 | goto error; |
| 1206 | + } | |
| 1111 | 1207 | if (jas_stream_read(in, txtdesc->ucdata, txtdesc->uclen * 2) != |
| 1112 | − txtdesc->uclen * 2) | |
| 1208 | + txtdesc->uclen * 2) { | |
| 1113 | 1209 | goto error; |
| 1114 | − if (jas_iccgetuint16(in, &txtdesc->sccode)) | |
| 1210 | + } | |
| 1211 | + if (jas_iccgetuint16(in, &txtdesc->sccode)) { | |
| 1115 | 1212 | goto error; |
| 1116 | − if ((c = jas_stream_getc(in)) == EOF) | |
| 1213 | + } | |
| 1214 | + if ((c = jas_stream_getc(in)) == EOF) { | |
| 1117 | 1215 | goto error; |
| 1216 | + } | |
| 1118 | 1217 | txtdesc->maclen = c; |
| 1119 | − if (jas_stream_read(in, txtdesc->macdata, 67) != 67) | |
| 1218 | + if (jas_stream_read(in, txtdesc->macdata, 67) != 67) { | |
| 1120 | 1219 | goto error; |
| 1220 | + } | |
| 1121 | 1221 | txtdesc->asclen = JAS_CAST(jas_iccuint32_t, strlen(txtdesc->ascdata) + 1); |
| 1122 | 1222 | #define WORKAROUND_BAD_PROFILES |
| 1123 | 1223 | #ifdef WORKAROUND_BAD_PROFILES |
| @@ -1126,12 +1226,14 @@ static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 2 unmodified lines | ||
| 1126 | 1226 | return -1; |
| 1127 | 1227 | } |
| 1128 | 1228 | if (n < cnt) { |
| 1129 | − if (jas_stream_gobble(in, cnt - n) != (int)(cnt - n)) | |
| 1229 | + if (jas_stream_gobble(in, cnt - n) != (int)(cnt - n)) { | |
| 1130 | 1230 | goto error; |
| 1231 | + } | |
| 1131 | 1232 | } |
| 1132 | 1233 | #else |
| 1133 | − if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt) | |
| 1234 | + if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt) { | |
| 1134 | 1235 | return -1; |
| 1236 | + } | |
| 1135 | 1237 | #endif |
| 1136 | 1238 | return 0; |
| 1137 | 1239 | error: |
| @@ -1145,7 +1247,6 @@ static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval) · 7 unmodified lines | ||
| 1145 | 1247 | return strlen(txtdesc->ascdata) + 1 + txtdesc->uclen * 2 + 15 + 67; |
| 1146 | 1248 | } |
| 1147 | 1249 | |
| 1148 | −//#ifdef JAS_ENABLE_ENCODER | |
| 1149 | 1250 | static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1150 | 1251 | { |
| 1151 | 1252 | const jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; |
| @@ -1154,22 +1255,35 @@ static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out) · 2 unmodified lines | ||
| 1154 | 1255 | jas_stream_putc(out, 0) == EOF || |
| 1155 | 1256 | jas_iccputuint32(out, txtdesc->uclangcode) || |
| 1156 | 1257 | jas_iccputuint32(out, txtdesc->uclen) || |
| 1157 | − jas_stream_write(out, txtdesc->ucdata, txtdesc->uclen * 2) != txtdesc->uclen * 2 || | |
| 1258 | + jas_stream_write(out, txtdesc->ucdata, txtdesc->uclen * 2) != | |
| 1259 | + txtdesc->uclen * 2 || | |
| 1158 | 1260 | jas_iccputuint16(out, txtdesc->sccode) || |
| 1159 | − jas_stream_putc(out, txtdesc->maclen) == EOF) | |
| 1261 | + jas_stream_putc(out, txtdesc->maclen) == EOF) { | |
| 1160 | 1262 | goto error; |
| 1263 | + } | |
| 1161 | 1264 | if (txtdesc->maclen > 0) { |
| 1162 | − if (jas_stream_write(out, txtdesc->macdata, 67) != 67) | |
| 1265 | + if (jas_stream_write(out, txtdesc->macdata, 67) != 67) { | |
| 1163 | 1266 | goto error; |
| 1267 | + } | |
| 1164 | 1268 | } else { |
| 1165 | − if (jas_stream_pad(out, 67, 0) != 67) | |
| 1269 | + if (jas_stream_pad(out, 67, 0) != 67) { | |
| 1166 | 1270 | goto error; |
| 1271 | + } | |
| 1167 | 1272 | } |
| 1168 | 1273 | return 0; |
| 1169 | 1274 | error: |
| 1170 | 1275 | return -1; |
| 1171 | 1276 | } |
| 1172 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 1277 | + | |
| 1278 | +static void jas_icctxtdesc_dump(const jas_iccattrval_t *attrval, FILE *out) | |
| 1279 | +{ | |
| 1280 | + const jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; | |
| 1281 | + fprintf(out, "ascii = \"%s\"\n", txtdesc->ascdata); | |
| 1282 | + fprintf(out, "uclangcode = %"PRIuFAST32"; uclen = %"PRIuFAST32"\n", | |
| 1283 | + txtdesc->uclangcode, txtdesc->uclen); | |
| 1284 | + fprintf(out, "sccode = %"PRIuFAST16"\n", txtdesc->sccode); | |
| 1285 | + fprintf(out, "maclen = %d\n", txtdesc->maclen); | |
| 1286 | +} | |
| 1173 | 1287 | |
| 1174 | 1288 | /******************************************************************************\ |
| 1175 | 1289 | * |
| @@ -1189,8 +1303,9 @@ static int jas_icctxt_copy(jas_iccattrval_t *attrval, · 13 unmodified lines | ||
| 1189 | 1303 | { |
| 1190 | 1304 | jas_icctxt_t *txt = &attrval->data.txt; |
| 1191 | 1305 | const jas_icctxt_t *othtxt = &othattrval->data.txt; |
| 1192 | − if (!(txt->string = strdup(othtxt->string))) | |
| 1306 | + if (!(txt->string = jas_strdup(othtxt->string))) { | |
| 1193 | 1307 | return -1; |
| 1308 | + } | |
| 1194 | 1309 | return 0; |
| 1195 | 1310 | } |
| 1196 | 1311 | |
| @@ -1199,13 +1314,16 @@ static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 2 unmodified lines | ||
| 1199 | 1314 | { |
| 1200 | 1315 | jas_icctxt_t *txt = &attrval->data.txt; |
| 1201 | 1316 | txt->string = 0; |
| 1202 | − if (!(txt->string = jas_malloc(cnt))) | |
| 1317 | + if (!(txt->string = jas_malloc(cnt))) { | |
| 1203 | 1318 | goto error; |
| 1204 | − if (jas_stream_read(in, txt->string, cnt) != cnt) | |
| 1319 | + } | |
| 1320 | + if (jas_stream_read(in, txt->string, cnt) != cnt) { | |
| 1205 | 1321 | goto error; |
| 1322 | + } | |
| 1206 | 1323 | txt->string[cnt - 1] = '\0'; |
| 1207 | − if (strlen(txt->string) + 1 != cnt) | |
| 1324 | + if (strlen(txt->string) + 1 != cnt) { | |
| 1208 | 1325 | goto error; |
| 1326 | + } | |
| 1209 | 1327 | return 0; |
| 1210 | 1328 | error: |
| 1211 | 1329 | jas_icctxt_destroy(attrval); |
| @@ -1218,16 +1336,21 @@ static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval) · 6 unmodified lines | ||
| 1218 | 1336 | return strlen(txt->string) + 1; |
| 1219 | 1337 | } |
| 1220 | 1338 | |
| 1221 | −//#ifdef JAS_ENABLE_ENCODER | |
| 1222 | 1339 | static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1223 | 1340 | { |
| 1224 | 1341 | const jas_icctxt_t *txt = &attrval->data.txt; |
| 1225 | 1342 | if (jas_stream_puts(out, txt->string) || |
| 1226 | − jas_stream_putc(out, 0) == EOF) | |
| 1343 | + jas_stream_putc(out, 0) == EOF) { | |
| 1227 | 1344 | return -1; |
| 1345 | + } | |
| 1228 | 1346 | return 0; |
| 1229 | 1347 | } |
| 1230 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 1348 | + | |
| 1349 | +static void jas_icctxt_dump(const jas_iccattrval_t *attrval, FILE *out) | |
| 1350 | +{ | |
| 1351 | + const jas_icctxt_t *txt = &attrval->data.txt; | |
| 1352 | + fprintf(out, "string = \"%s\"\n", txt->string); | |
| 1353 | +} | |
| 1231 | 1354 | |
| 1232 | 1355 | /******************************************************************************\ |
| 1233 | 1356 | * |
| @@ -1261,9 +1384,8 @@ static void jas_icclut8_destroy(jas_iccattrval_t *attrval) · 27 unmodified lines | ||
| 1261 | 1384 | static int jas_icclut8_copy(jas_iccattrval_t *attrval, |
| 1262 | 1385 | const jas_iccattrval_t *othattrval) |
| 1263 | 1386 | { |
| 1264 | − /* Avoid compiler warnings about unused parameters. */ | |
| 1265 | − USED(attrval); | |
| 1266 | − USED(othattrval); | |
| 1387 | + JAS_UNUSED(attrval); | |
| 1388 | + JAS_UNUSED(othattrval); | |
| 1267 | 1389 | abort(); |
| 1268 | 1390 | return -1; |
| 1269 | 1391 | } |
| @@ -1280,54 +1402,64 @@ static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 10 unmodified lines | ||
| 1280 | 1402 | if (jas_iccgetuint8(in, &lut8->numinchans) || |
| 1281 | 1403 | jas_iccgetuint8(in, &lut8->numoutchans) || |
| 1282 | 1404 | jas_iccgetuint8(in, &lut8->clutlen) || |
| 1283 | − jas_stream_getc(in) == EOF) | |
| 1405 | + jas_stream_getc(in) == EOF) { | |
| 1284 | 1406 | goto error; |
| 1407 | + } | |
| 1285 | 1408 | for (unsigned i = 0; i < 3; ++i) { |
| 1286 | 1409 | for (unsigned j = 0; j < 3; ++j) { |
| 1287 | − if (jas_iccgetsint32(in, &lut8->e[i][j])) | |
| 1410 | + if (jas_iccgetsint32(in, &lut8->e[i][j])) { | |
| 1288 | 1411 | goto error; |
| 1412 | + } | |
| 1289 | 1413 | } |
| 1290 | 1414 | } |
| 1291 | 1415 | if (jas_iccgetuint16(in, &lut8->numintabents) || |
| 1292 | − jas_iccgetuint16(in, &lut8->numouttabents)) | |
| 1416 | + jas_iccgetuint16(in, &lut8->numouttabents)) { | |
| 1293 | 1417 | goto error; |
| 1418 | + } | |
| 1294 | 1419 | const unsigned clutsize = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; |
| 1295 | 1420 | if (!(lut8->clut = jas_alloc2(clutsize, sizeof(jas_iccuint8_t))) || |
| 1296 | 1421 | !(lut8->intabsbuf = jas_alloc3(lut8->numinchans, |
| 1297 | 1422 | lut8->numintabents, sizeof(jas_iccuint8_t))) || |
| 1298 | 1423 | !(lut8->intabs = jas_alloc2(lut8->numinchans, |
| 1299 | − sizeof(jas_iccuint8_t *)))) | |
| 1424 | + sizeof(jas_iccuint8_t *)))) { | |
| 1300 | 1425 | goto error; |
| 1426 | + } | |
| 1301 | 1427 | for (unsigned i = 0; i < lut8->numinchans; ++i) |
| 1302 | 1428 | lut8->intabs[i] = &lut8->intabsbuf[i * lut8->numintabents]; |
| 1303 | 1429 | if (!(lut8->outtabsbuf = jas_alloc3(lut8->numoutchans, |
| 1304 | 1430 | lut8->numouttabents, sizeof(jas_iccuint8_t))) || |
| 1305 | 1431 | !(lut8->outtabs = jas_alloc2(lut8->numoutchans, |
| 1306 | − sizeof(jas_iccuint8_t *)))) | |
| 1432 | + sizeof(jas_iccuint8_t *)))) { | |
| 1307 | 1433 | goto error; |
| 1308 | − for (unsigned i = 0; i < lut8->numoutchans; ++i) | |
| 1434 | + } | |
| 1435 | + for (unsigned i = 0; i < lut8->numoutchans; ++i) { | |
| 1309 | 1436 | lut8->outtabs[i] = &lut8->outtabsbuf[i * lut8->numouttabents]; |
| 1437 | + } | |
| 1310 | 1438 | for (unsigned i = 0; i < lut8->numinchans; ++i) { |
| 1311 | 1439 | for (unsigned j = 0; j < lut8->numintabents; ++j) { |
| 1312 | − if (jas_iccgetuint8(in, &lut8->intabs[i][j])) | |
| 1440 | + if (jas_iccgetuint8(in, &lut8->intabs[i][j])) { | |
| 1313 | 1441 | goto error; |
| 1442 | + } | |
| 1314 | 1443 | } |
| 1315 | 1444 | } |
| 1316 | 1445 | for (unsigned i = 0; i < lut8->numoutchans; ++i) { |
| 1317 | 1446 | for (unsigned j = 0; j < lut8->numouttabents; ++j) { |
| 1318 | − if (jas_iccgetuint8(in, &lut8->outtabs[i][j])) | |
| 1447 | + if (jas_iccgetuint8(in, &lut8->outtabs[i][j])) { | |
| 1319 | 1448 | goto error; |
| 1449 | + } | |
| 1320 | 1450 | } |
| 1321 | 1451 | } |
| 1322 | 1452 | for (unsigned i = 0; i < clutsize; ++i) { |
| 1323 | − if (jas_iccgetuint8(in, &lut8->clut[i])) | |
| 1453 | + if (jas_iccgetuint8(in, &lut8->clut[i])) { | |
| 1324 | 1454 | goto error; |
| 1455 | + } | |
| 1325 | 1456 | } |
| 1326 | 1457 | if (44 + lut8->numinchans * lut8->numintabents + |
| 1327 | 1458 | lut8->numoutchans * lut8->numouttabents + |
| 1328 | 1459 | jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans != |
| 1329 | − cnt) | |
| 1460 | + cnt) { | |
| 1330 | 1461 | goto error; |
| 1462 | + } | |
| 1331 | 1463 | return 0; |
| 1332 | 1464 | error: |
| 1333 | 1465 | jas_icclut8_destroy(attrval); |
| @@ -1342,7 +1474,6 @@ static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval) · 8 unmodified lines | ||
| 1342 | 1474 | jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; |
| 1343 | 1475 | } |
| 1344 | 1476 | |
| 1345 | −//#ifdef JAS_ENABLE_ENCODER | |
| 1346 | 1477 | static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1347 | 1478 | { |
| 1348 | 1479 | jas_icclut8_t *lut8 = &attrval->data.lut8; |
| @@ -1354,34 +1485,57 @@ static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out) · 5 unmodified lines | ||
| 1354 | 1485 | if (jas_stream_putc(out, lut8->numinchans) == EOF || |
| 1355 | 1486 | jas_stream_putc(out, lut8->numoutchans) == EOF || |
| 1356 | 1487 | jas_stream_putc(out, lut8->clutlen) == EOF || |
| 1357 | − jas_stream_putc(out, 0) == EOF) | |
| 1488 | + jas_stream_putc(out, 0) == EOF) { | |
| 1358 | 1489 | goto error; |
| 1490 | + } | |
| 1359 | 1491 | for (unsigned i = 0; i < 3; ++i) { |
| 1360 | 1492 | for (unsigned j = 0; j < 3; ++j) { |
| 1361 | − if (jas_iccputsint32(out, lut8->e[i][j])) | |
| 1493 | + if (jas_iccputsint32(out, lut8->e[i][j])) { | |
| 1362 | 1494 | goto error; |
| 1495 | + } | |
| 1363 | 1496 | } |
| 1364 | 1497 | } |
| 1365 | 1498 | if (jas_iccputuint16(out, lut8->numintabents) || |
| 1366 | − jas_iccputuint16(out, lut8->numouttabents)) | |
| 1499 | + jas_iccputuint16(out, lut8->numouttabents)) { | |
| 1367 | 1500 | goto error; |
| 1368 | − for (unsigned i = 0, n = lut8->numinchans * lut8->numintabents; i < n; ++i) { | |
| 1369 | − if (jas_iccputuint8(out, lut8->intabsbuf[i])) | |
| 1501 | + } | |
| 1502 | + for (unsigned i = 0, n = lut8->numinchans * lut8->numintabents; i < n; | |
| 1503 | + ++i) { | |
| 1504 | + if (jas_iccputuint8(out, lut8->intabsbuf[i])) { | |
| 1370 | 1505 | goto error; |
| 1506 | + } | |
| 1371 | 1507 | } |
| 1372 | − for (unsigned i = 0, n = lut8->numoutchans * lut8->numouttabents; i < n; ++i) { | |
| 1373 | − if (jas_iccputuint8(out, lut8->outtabsbuf[i])) | |
| 1508 | + for (unsigned i = 0, n = lut8->numoutchans * lut8->numouttabents; i < n; | |
| 1509 | + ++i) { | |
| 1510 | + if (jas_iccputuint8(out, lut8->outtabsbuf[i])) { | |
| 1374 | 1511 | goto error; |
| 1512 | + } | |
| 1375 | 1513 | } |
| 1376 | − for (unsigned i = 0, n = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; i < n; ++i) { | |
| 1377 | − if (jas_iccputuint8(out, lut8->clut[i])) | |
| 1514 | + for (unsigned i = 0, n = jas_iccpowi(lut8->clutlen, lut8->numinchans) * | |
| 1515 | + lut8->numoutchans; i < n; ++i) { | |
| 1516 | + if (jas_iccputuint8(out, lut8->clut[i])) { | |
| 1378 | 1517 | goto error; |
| 1518 | + } | |
| 1379 | 1519 | } |
| 1380 | 1520 | return 0; |
| 1381 | 1521 | error: |
| 1382 | 1522 | return -1; |
| 1383 | 1523 | } |
| 1384 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 1524 | + | |
| 1525 | +static void jas_icclut8_dump(const jas_iccattrval_t *attrval, FILE *out) | |
| 1526 | +{ | |
| 1527 | + const jas_icclut8_t *lut8 = &attrval->data.lut8; | |
| 1528 | + fprintf(out, "numinchans=%d, numoutchans=%d, clutlen=%d\n", | |
| 1529 | + lut8->numinchans, lut8->numoutchans, lut8->clutlen); | |
| 1530 | + for (unsigned i = 0; i < 3; ++i) { | |
| 1531 | + for (unsigned j = 0; j < 3; ++j) { | |
| 1532 | + fprintf(out, "e[%d][%d]=%f ", i, j, lut8->e[i][j] / 65536.0); | |
| 1533 | + } | |
| 1534 | + fprintf(out, "\n"); | |
| 1535 | + } | |
| 1536 | + fprintf(out, "numintabents=%"PRIuFAST16", numouttabents=%"PRIuFAST16"\n", | |
| 1537 | + lut8->numintabents, lut8->numouttabents); | |
| 1538 | +} | |
| 1385 | 1539 | |
| 1386 | 1540 | /******************************************************************************\ |
| 1387 | 1541 | * |
| @@ -1415,9 +1569,9 @@ static void jas_icclut16_destroy(jas_iccattrval_t *attrval) · 27 unmodified lines | ||
| 1415 | 1569 | static int jas_icclut16_copy(jas_iccattrval_t *attrval, |
| 1416 | 1570 | const jas_iccattrval_t *othattrval) |
| 1417 | 1571 | { |
| 1418 | − /* Avoid compiler warnings about unused parameters. */ | |
| 1419 | − USED(attrval); | |
| 1420 | − USED(othattrval); | |
| 1572 | + JAS_UNUSED(attrval); | |
| 1573 | + JAS_UNUSED(othattrval); | |
| 1574 | + | |
| 1421 | 1575 | /* Not yet implemented. */ |
| 1422 | 1576 | abort(); |
| 1423 | 1577 | return -1; |
| @@ -1435,54 +1589,66 @@ static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 11 unmodified lines | ||
| 1435 | 1589 | if (jas_iccgetuint8(in, &lut16->numinchans) || |
| 1436 | 1590 | jas_iccgetuint8(in, &lut16->numoutchans) || |
| 1437 | 1591 | jas_iccgetuint8(in, &lut16->clutlen) || |
| 1438 | − jas_stream_getc(in) == EOF) | |
| 1592 | + jas_stream_getc(in) == EOF) { | |
| 1439 | 1593 | goto error; |
| 1594 | + } | |
| 1440 | 1595 | for (unsigned i = 0; i < 3; ++i) { |
| 1441 | 1596 | for (unsigned j = 0; j < 3; ++j) { |
| 1442 | − if (jas_iccgetsint32(in, &lut16->e[i][j])) | |
| 1597 | + if (jas_iccgetsint32(in, &lut16->e[i][j])) { | |
| 1443 | 1598 | goto error; |
| 1599 | + } | |
| 1444 | 1600 | } |
| 1445 | 1601 | } |
| 1446 | 1602 | if (jas_iccgetuint16(in, &lut16->numintabents) || |
| 1447 | − jas_iccgetuint16(in, &lut16->numouttabents)) | |
| 1603 | + jas_iccgetuint16(in, &lut16->numouttabents)) { | |
| 1448 | 1604 | goto error; |
| 1449 | − const unsigned clutsize = jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans; | |
| 1605 | + } | |
| 1606 | + const unsigned clutsize = jas_iccpowi(lut16->clutlen, lut16->numinchans) * | |
| 1607 | + lut16->numoutchans; | |
| 1450 | 1608 | if (!(lut16->clut = jas_alloc2(clutsize, sizeof(jas_iccuint16_t))) || |
| 1451 | 1609 | !(lut16->intabsbuf = jas_alloc3(lut16->numinchans, |
| 1452 | 1610 | lut16->numintabents, sizeof(jas_iccuint16_t))) || |
| 1453 | 1611 | !(lut16->intabs = jas_alloc2(lut16->numinchans, |
| 1454 | − sizeof(jas_iccuint16_t *)))) | |
| 1612 | + sizeof(jas_iccuint16_t *)))) { | |
| 1455 | 1613 | goto error; |
| 1456 | − for (unsigned i = 0; i < lut16->numinchans; ++i) | |
| 1614 | + } | |
| 1615 | + for (unsigned i = 0; i < lut16->numinchans; ++i) { | |
| 1457 | 1616 | lut16->intabs[i] = &lut16->intabsbuf[i * lut16->numintabents]; |
| 1617 | + } | |
| 1458 | 1618 | if (!(lut16->outtabsbuf = jas_alloc3(lut16->numoutchans, |
| 1459 | 1619 | lut16->numouttabents, sizeof(jas_iccuint16_t))) || |
| 1460 | 1620 | !(lut16->outtabs = jas_alloc2(lut16->numoutchans, |
| 1461 | − sizeof(jas_iccuint16_t *)))) | |
| 1621 | + sizeof(jas_iccuint16_t *)))) { | |
| 1462 | 1622 | goto error; |
| 1463 | − for (unsigned i = 0; i < lut16->numoutchans; ++i) | |
| 1623 | + } | |
| 1624 | + for (unsigned i = 0; i < lut16->numoutchans; ++i) { | |
| 1464 | 1625 | lut16->outtabs[i] = &lut16->outtabsbuf[i * lut16->numouttabents]; |
| 1626 | + } | |
| 1465 | 1627 | for (unsigned i = 0; i < lut16->numinchans; ++i) { |
| 1466 | 1628 | for (unsigned j = 0; j < lut16->numintabents; ++j) { |
| 1467 | − if (jas_iccgetuint16(in, &lut16->intabs[i][j])) | |
| 1629 | + if (jas_iccgetuint16(in, &lut16->intabs[i][j])) { | |
| 1468 | 1630 | goto error; |
| 1631 | + } | |
| 1469 | 1632 | } |
| 1470 | 1633 | } |
| 1471 | 1634 | for (unsigned i = 0; i < lut16->numoutchans; ++i) { |
| 1472 | 1635 | for (unsigned j = 0; j < lut16->numouttabents; ++j) { |
| 1473 | − if (jas_iccgetuint16(in, &lut16->outtabs[i][j])) | |
| 1636 | + if (jas_iccgetuint16(in, &lut16->outtabs[i][j])) { | |
| 1474 | 1637 | goto error; |
| 1638 | + } | |
| 1475 | 1639 | } |
| 1476 | 1640 | } |
| 1477 | 1641 | for (unsigned i = 0; i < clutsize; ++i) { |
| 1478 | − if (jas_iccgetuint16(in, &lut16->clut[i])) | |
| 1642 | + if (jas_iccgetuint16(in, &lut16->clut[i])) { | |
| 1479 | 1643 | goto error; |
| 1644 | + } | |
| 1480 | 1645 | } |
| 1481 | 1646 | if (44 + 2 * (lut16->numinchans * lut16->numintabents + |
| 1482 | − lut16->numoutchans * lut16->numouttabents + | |
| 1483 | − jas_iccpowi(lut16->clutlen, lut16->numinchans) * | |
| 1484 | − lut16->numoutchans) != cnt) | |
| 1647 | + lut16->numoutchans * lut16->numouttabents + | |
| 1648 | + jas_iccpowi(lut16->clutlen, lut16->numinchans) * | |
| 1649 | + lut16->numoutchans) != cnt) { | |
| 1485 | 1650 | goto error; |
| 1651 | + } | |
| 1486 | 1652 | return 0; |
| 1487 | 1653 | error: |
| 1488 | 1654 | jas_icclut16_destroy(attrval); |
| @@ -1497,41 +1663,63 @@ static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval) · 8 unmodified lines | ||
| 1497 | 1663 | jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans); |
| 1498 | 1664 | } |
| 1499 | 1665 | |
| 1500 | −//#ifdef JAS_ENABLE_ENCODER | |
| 1501 | 1666 | static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1502 | 1667 | { |
| 1503 | 1668 | const jas_icclut16_t *lut16 = &attrval->data.lut16; |
| 1504 | 1669 | if (jas_stream_putc(out, lut16->numinchans) == EOF || |
| 1505 | 1670 | jas_stream_putc(out, lut16->numoutchans) == EOF || |
| 1506 | 1671 | jas_stream_putc(out, lut16->clutlen) == EOF || |
| 1507 | − jas_stream_putc(out, 0) == EOF) | |
| 1672 | + jas_stream_putc(out, 0) == EOF) { | |
| 1508 | 1673 | goto error; |
| 1674 | + } | |
| 1509 | 1675 | for (unsigned i = 0; i < 3; ++i) { |
| 1510 | 1676 | for (unsigned j = 0; j < 3; ++j) { |
| 1511 | − if (jas_iccputsint32(out, lut16->e[i][j])) | |
| 1677 | + if (jas_iccputsint32(out, lut16->e[i][j])) { | |
| 1512 | 1678 | goto error; |
| 1679 | + } | |
| 1513 | 1680 | } |
| 1514 | 1681 | } |
| 1515 | 1682 | if (jas_iccputuint16(out, lut16->numintabents) || |
| 1516 | − jas_iccputuint16(out, lut16->numouttabents)) | |
| 1683 | + jas_iccputuint16(out, lut16->numouttabents)) { | |
| 1517 | 1684 | goto error; |
| 1518 | − for (unsigned i = 0, n = lut16->numinchans * lut16->numintabents; i < n; ++i) { | |
| 1519 | − if (jas_iccputuint16(out, lut16->intabsbuf[i])) | |
| 1685 | + } | |
| 1686 | + for (unsigned i = 0, n = lut16->numinchans * lut16->numintabents; i < n; | |
| 1687 | + ++i) { | |
| 1688 | + if (jas_iccputuint16(out, lut16->intabsbuf[i])) { | |
| 1520 | 1689 | goto error; |
| 1690 | + } | |
| 1521 | 1691 | } |
| 1522 | − for (unsigned i = 0, n = lut16->numoutchans * lut16->numouttabents; i < n; ++i) { | |
| 1523 | − if (jas_iccputuint16(out, lut16->outtabsbuf[i])) | |
| 1692 | + for (unsigned i = 0, n = lut16->numoutchans * lut16->numouttabents; i < n; | |
| 1693 | + ++i) { | |
| 1694 | + if (jas_iccputuint16(out, lut16->outtabsbuf[i])) { | |
| 1524 | 1695 | goto error; |
| 1696 | + } | |
| 1525 | 1697 | } |
| 1526 | − for (unsigned i = 0, n = jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans; i < n; ++i) { | |
| 1527 | − if (jas_iccputuint16(out, lut16->clut[i])) | |
| 1698 | + for (unsigned i = 0, n = jas_iccpowi(lut16->clutlen, lut16->numinchans) * | |
| 1699 | + lut16->numoutchans; i < n; ++i) { | |
| 1700 | + if (jas_iccputuint16(out, lut16->clut[i])) { | |
| 1528 | 1701 | goto error; |
| 1702 | + } | |
| 1529 | 1703 | } |
| 1530 | 1704 | return 0; |
| 1531 | 1705 | error: |
| 1532 | 1706 | return -1; |
| 1533 | 1707 | } |
| 1534 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 1708 | + | |
| 1709 | +static void jas_icclut16_dump(const jas_iccattrval_t *attrval, FILE *out) | |
| 1710 | +{ | |
| 1711 | + const jas_icclut16_t *lut16 = &attrval->data.lut16; | |
| 1712 | + fprintf(out, "numinchans=%d, numoutchans=%d, clutlen=%d\n", | |
| 1713 | + lut16->numinchans, lut16->numoutchans, lut16->clutlen); | |
| 1714 | + for (unsigned i = 0; i < 3; ++i) { | |
| 1715 | + for (unsigned j = 0; j < 3; ++j) { | |
| 1716 | + fprintf(out, "e[%d][%d]=%f ", i, j, lut16->e[i][j] / 65536.0); | |
| 1717 | + } | |
| 1718 | + fprintf(out, "\n"); | |
| 1719 | + } | |
| 1720 | + fprintf(out, "numintabents=%"PRIuFAST16", numouttabents=%"PRIuFAST16"\n", | |
| 1721 | + lut16->numintabents, lut16->numouttabents); | |
| 1722 | +} | |
| 1535 | 1723 | |
| 1536 | 1724 | /******************************************************************************\ |
| 1537 | 1725 | * |
| @@ -1543,8 +1731,9 @@ static int jas_iccgetuint(jas_stream_t *in, unsigned n, jas_ulonglong *val) · 5 unmodified lines | ||
| 1543 | 1731 | jas_ulonglong v; |
| 1544 | 1732 | v = 0; |
| 1545 | 1733 | for (unsigned i = n; i > 0; --i) { |
| 1546 | − if ((c = jas_stream_getc(in)) == EOF) | |
| 1734 | + if ((c = jas_stream_getc(in)) == EOF) { | |
| 1547 | 1735 | return -1; |
| 1736 | + } | |
| 1548 | 1737 | v = (v << 8) | c; |
| 1549 | 1738 | } |
| 1550 | 1739 | *val = v; |
| @@ -1554,8 +1743,9 @@ static int jas_iccgetuint(jas_stream_t *in, unsigned n, jas_ulonglong *val) · 3 unmodified lines | ||
| 1554 | 1743 | static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val) |
| 1555 | 1744 | { |
| 1556 | 1745 | int c; |
| 1557 | − if ((c = jas_stream_getc(in)) == EOF) | |
| 1746 | + if ((c = jas_stream_getc(in)) == EOF) { | |
| 1558 | 1747 | return -1; |
| 1748 | + } | |
| 1559 | 1749 | *val = c; |
| 1560 | 1750 | return 0; |
| 1561 | 1751 | } |
| @@ -1563,8 +1753,9 @@ static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val) · 1 unmodified line | ||
| 1563 | 1753 | static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val) |
| 1564 | 1754 | { |
| 1565 | 1755 | jas_ulonglong tmp; |
| 1566 | − if (jas_iccgetuint(in, 2, &tmp)) | |
| 1756 | + if (jas_iccgetuint(in, 2, &tmp)) { | |
| 1567 | 1757 | return -1; |
| 1758 | + } | |
| 1568 | 1759 | *val = (jas_iccuint16_t)tmp; |
| 1569 | 1760 | return 0; |
| 1570 | 1761 | } |
| @@ -1572,8 +1763,9 @@ static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val) · 1 unmodified line | ||
| 1572 | 1763 | static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val) |
| 1573 | 1764 | { |
| 1574 | 1765 | jas_ulonglong tmp; |
| 1575 | − if (jas_iccgetuint(in, 4, &tmp)) | |
| 1766 | + if (jas_iccgetuint(in, 4, &tmp)) { | |
| 1576 | 1767 | return -1; |
| 1768 | + } | |
| 1577 | 1769 | *val = (tmp & 0x80000000) ? (-JAS_CAST(jas_longlong, (((~tmp) & |
| 1578 | 1770 | 0x7fffffff) + 1))) : JAS_CAST(jas_longlong, tmp); |
| 1579 | 1771 | return 0; |
| @@ -1582,8 +1774,9 @@ static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val) · 2 unmodified lines | ||
| 1582 | 1774 | static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val) |
| 1583 | 1775 | { |
| 1584 | 1776 | jas_ulonglong tmp; |
| 1585 | − if (jas_iccgetuint(in, 4, &tmp)) | |
| 1777 | + if (jas_iccgetuint(in, 4, &tmp)) { | |
| 1586 | 1778 | return -1; |
| 1779 | + } | |
| 1587 | 1780 | *val = (jas_iccuint32_t)tmp; |
| 1588 | 1781 | return 0; |
| 1589 | 1782 | } |
| @@ -1591,21 +1784,21 @@ static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val) · 1 unmodified line | ||
| 1591 | 1784 | static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val) |
| 1592 | 1785 | { |
| 1593 | 1786 | jas_ulonglong tmp; |
| 1594 | − if (jas_iccgetuint(in, 8, &tmp)) | |
| 1787 | + if (jas_iccgetuint(in, 8, &tmp)) { | |
| 1595 | 1788 | return -1; |
| 1789 | + } | |
| 1596 | 1790 | *val = (jas_iccuint64_t)tmp; |
| 1597 | 1791 | return 0; |
| 1598 | 1792 | } |
| 1599 | 1793 | |
| 1600 | −//#ifdef JAS_ENABLE_ENCODER | |
| 1601 | − | |
| 1602 | 1794 | static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val) |
| 1603 | 1795 | { |
| 1604 | 1796 | int c; |
| 1605 | 1797 | for (unsigned i = n; i > 0; --i) { |
| 1606 | 1798 | c = (val >> (8 * (i - 1))) & 0xff; |
| 1607 | − if (jas_stream_putc(out, c) == EOF) | |
| 1799 | + if (jas_stream_putc(out, c) == EOF) { | |
| 1608 | 1800 | return -1; |
| 1801 | + } | |
| 1609 | 1802 | } |
| 1610 | 1803 | return 0; |
| 1611 | 1804 | } |
| @@ -1618,8 +1811,6 @@ static int jas_iccputsint(jas_stream_t *out, unsigned n, jas_longlong val) · 6 unmodified lines | ||
| 1618 | 1811 | return jas_iccputuint(out, n, tmp); |
| 1619 | 1812 | } |
| 1620 | 1813 | |
| 1621 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 1622 | − | |
| 1623 | 1814 | /******************************************************************************\ |
| 1624 | 1815 | * |
| 1625 | 1816 | \******************************************************************************/ |
| @@ -1631,7 +1822,8 @@ static char *jas_iccsigtostr(unsigned sig, char *buf) · 5 unmodified lines | ||
| 1631 | 1822 | bufptr = buf; |
| 1632 | 1823 | for (unsigned n = 4; n > 0; --n) { |
| 1633 | 1824 | c = (sig >> 24) & 0xff; |
| 1634 | − if (isalpha(c) || isdigit(c)) { | |
| 1825 | + if (isalpha(JAS_CAST(unsigned char, c)) || | |
| 1826 | + isdigit(JAS_CAST(unsigned char, c))) { | |
| 1635 | 1827 | *bufptr++ = c; |
| 1636 | 1828 | } |
| 1637 | 1829 | sig <<= 8; |
| @@ -1640,36 +1832,40 @@ static char *jas_iccsigtostr(unsigned sig, char *buf) · 2 unmodified lines | ||
| 1640 | 1832 | return buf; |
| 1641 | 1833 | } |
| 1642 | 1834 | |
| 1643 | −//#ifdef JAS_ENABLE_ENCODER | |
| 1644 | 1835 | static unsigned jas_iccpadtomult(unsigned x, unsigned y) |
| 1645 | 1836 | { |
| 1646 | 1837 | return ((x + y - 1) / y) * y; |
| 1647 | 1838 | } |
| 1648 | −//#endif /* JAS_ENABLE_ENCODER */ | |
| 1649 | 1839 | |
| 1650 | 1840 | static unsigned jas_iccpowi(unsigned x, unsigned n) |
| 1651 | 1841 | { |
| 1652 | 1842 | unsigned y; |
| 1653 | 1843 | y = 1; |
| 1654 | − while (n-- > 0) | |
| 1844 | + while (n-- > 0) { | |
| 1655 | 1845 | y *= x; |
| 1846 | + } | |
| 1656 | 1847 | return y; |
| 1657 | 1848 | } |
| 1658 | 1849 | |
| 1659 | 1850 | |
| 1660 | 1851 | jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len) |
| 1661 | 1852 | { |
| 1853 | + assert(buf); | |
| 1854 | + assert(len > 0); | |
| 1662 | 1855 | jas_stream_t *in; |
| 1663 | 1856 | jas_iccprof_t *prof; |
| 1664 | − if (!(in = jas_stream_memopen(JAS_CAST(char *, buf), len))) | |
| 1857 | + if (!(in = jas_stream_memopen(JAS_CAST(char *, buf), len))) { | |
| 1665 | 1858 | goto error; |
| 1666 | − if (!(prof = jas_iccprof_load(in))) | |
| 1859 | + } | |
| 1860 | + if (!(prof = jas_iccprof_load(in))) { | |
| 1667 | 1861 | goto error; |
| 1862 | + } | |
| 1668 | 1863 | jas_stream_close(in); |
| 1669 | 1864 | return prof; |
| 1670 | 1865 | error: |
| 1671 | − if (in) | |
| 1866 | + if (in) { | |
| 1672 | 1867 | jas_stream_close(in); |
| 1868 | + } | |
| 1673 | 1869 | return 0; |
| 1674 | 1870 | } |
| 1675 | 1871 | |
| @@ -59,9 +59,19 @@ · 58 unmodified lines | ||
| 59 | 59 | * __END_OF_JASPER_LICENSE__ |
| 60 | 60 | */ |
| 61 | 61 | |
| 62 | +/******************************************************************************\ | |
| 63 | +* Includes. | |
| 64 | +\******************************************************************************/ | |
| 65 | + | |
| 66 | +//#define JAS_FOR_INTERNAL_USE_ONLY | |
| 67 | + | |
| 62 | 68 | #include <jasper/jas_config.h> /* IWYU pragma: keep */ |
| 63 | 69 | #include <jasper/jas_types.h> |
| 64 | 70 | |
| 71 | +/******************************************************************************\ | |
| 72 | +* Data. | |
| 73 | +\******************************************************************************/ | |
| 74 | + | |
| 65 | 75 | const jas_uchar jas_iccprofdata_srgb[] = |
| 66 | 76 | { |
| 67 | 77 | 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, |
| @@ -71,9 +71,13 @@ · 70 unmodified lines | ||
| 71 | 71 | * Includes. |
| 72 | 72 | \******************************************************************************/ |
| 73 | 73 | |
| 74 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 75 | + | |
| 76 | +#include "jasper/jas_init.h" | |
| 74 | 77 | #include "jasper/jas_image.h" |
| 75 | 78 | #include "jasper/jas_math.h" |
| 76 | 79 | #include "jasper/jas_malloc.h" |
| 80 | +#include "jasper/jas_string.h" | |
| 77 | 81 | #include "jasper/jas_debug.h" |
| 78 | 82 | |
| 79 | 83 | /******************************************************************************\ |
| @@ -90,7 +94,8 @@ static jas_image_cmpt_t *jas_image_cmpt_create0(void); · 10 unmodified lines | ||
| 90 | 94 | static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt); |
| 91 | 95 | static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, |
| 92 | 96 | int_fast32_t tly, int_fast32_t hstep, int_fast32_t vstep, |
| 93 | − int_fast32_t width, int_fast32_t height, uint_fast16_t depth, bool sgnd); | |
| 97 | + int_fast32_t width, int_fast32_t height, uint_fast16_t depth, bool sgnd, | |
| 98 | + bool inmem); | |
| 94 | 99 | static void jas_image_setbbox(jas_image_t *image); |
| 95 | 100 | static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt); |
| 96 | 101 | static int jas_image_growcmpts(jas_image_t *image, unsigned maxcmpts); |
| @@ -102,30 +107,27 @@ static long uptomult(long x, long y); · 5 unmodified lines | ||
| 102 | 107 | static long downtomult(long x, long y); |
| 103 | 108 | static long convert(long val, bool oldsgnd, unsigned oldprec, bool newsgnd, |
| 104 | 109 | unsigned newprec); |
| 105 | −static void jas_image_calcbbox2(const jas_image_t *image, jas_image_coord_t *tlx, | |
| 106 | − jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry); | |
| 107 | − | |
| 108 | −/******************************************************************************\ | |
| 109 | −* Global data. | |
| 110 | −\******************************************************************************/ | |
| 111 | − | |
| 112 | −static unsigned jas_image_numfmts = 0; | |
| 113 | −static jas_image_fmtinfo_t jas_image_fmtinfos[JAS_IMAGE_MAXFMTS]; | |
| 110 | +static void jas_image_calcbbox2(const jas_image_t *image, | |
| 111 | + jas_image_coord_t *tlx, jas_image_coord_t *tly, jas_image_coord_t *brx, | |
| 112 | + jas_image_coord_t *bry); | |
| 113 | +static void jas_image_fmtinfo_init(jas_image_fmtinfo_t *fmtinfo); | |
| 114 | +static void jas_image_fmtinfo_cleanup(jas_image_fmtinfo_t *fmtinfo); | |
| 114 | 115 | |
| 115 | 116 | /******************************************************************************\ |
| 116 | 117 | * Create and destroy operations. |
| 117 | 118 | \******************************************************************************/ |
| 118 | 119 | |
| 119 | −jas_image_t *jas_image_create(unsigned numcmpts, const jas_image_cmptparm_t *cmptparms, | |
| 120 | − jas_clrspc_t clrspc) | |
| 120 | +jas_image_t *jas_image_create(unsigned numcmpts, | |
| 121 | + const jas_image_cmptparm_t *cmptparms, jas_clrspc_t clrspc) | |
| 121 | 122 | { |
| 122 | 123 | jas_image_t *image; |
| 123 | 124 | size_t rawsize; |
| 124 | 125 | unsigned cmptno; |
| 125 | 126 | const jas_image_cmptparm_t *cmptparm; |
| 126 | 127 | |
| 127 | − JAS_DBGLOG(100, ("jas_image_create(%d, %p, %d)\n", numcmpts, cmptparms, | |
| 128 | − clrspc)); | |
| 128 | + | |
| 129 | + JAS_LOGDEBUGF(100, "jas_image_create(%d, %p, %d)\n", numcmpts, cmptparms, | |
| 130 | + clrspc); | |
| 129 | 131 | |
| 130 | 132 | if (!(image = jas_image_create0())) { |
| 131 | 133 | goto error; |
| @@ -133,6 +135,7 @@ jas_image_t *jas_image_create(unsigned numcmpts, const jas_image_cmptparm_t *cmp · 1 unmodified line | ||
| 133 | 135 | |
| 134 | 136 | image->clrspc_ = clrspc; |
| 135 | 137 | image->maxcmpts_ = numcmpts; |
| 138 | +// image->inmem_ = true; | |
| 136 | 139 | |
| 137 | 140 | /* Allocate memory for the per-component information. */ |
| 138 | 141 | if (!(image->cmpts_ = jas_alloc2(image->maxcmpts_, |
| @@ -144,6 +147,19 @@ jas_image_t *jas_image_create(unsigned numcmpts, const jas_image_cmptparm_t *cmp · 5 unmodified lines | ||
| 144 | 147 | image->cmpts_[cmptno] = 0; |
| 145 | 148 | } |
| 146 | 149 | |
| 150 | +#if 0 | |
| 151 | + /* Compute the approximate raw size of the image. */ | |
| 152 | + rawsize = 0; | |
| 153 | + for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, | |
| 154 | + ++cmptparm) { | |
| 155 | + rawsize += cmptparm->width * cmptparm->height * | |
| 156 | + (cmptparm->prec + 7) / 8; | |
| 157 | + } | |
| 158 | + /* Decide whether to buffer the image data in memory, based on the | |
| 159 | + raw size of the image. */ | |
| 160 | + inmem = (rawsize < JAS_IMAGE_INMEMTHRESH); | |
| 161 | +#endif | |
| 162 | + | |
| 147 | 163 | /* Create the individual image components. */ |
| 148 | 164 | for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, |
| 149 | 165 | ++cmptparm) { |
| @@ -152,10 +168,11 @@ jas_image_t *jas_image_create(unsigned numcmpts, const jas_image_cmptparm_t *cmp · 2 unmodified lines | ||
| 152 | 168 | goto error; |
| 153 | 169 | } |
| 154 | 170 | rawsize /= 8; |
| 171 | + const bool inmem = (rawsize < JAS_IMAGE_INMEMTHRESH); | |
| 155 | 172 | if (!(image->cmpts_[cmptno] = jas_image_cmpt_create(cmptparm->tlx, |
| 156 | 173 | cmptparm->tly, cmptparm->hstep, cmptparm->vstep, |
| 157 | 174 | cmptparm->width, cmptparm->height, cmptparm->prec, |
| 158 | − cmptparm->sgnd))) { | |
| 175 | + cmptparm->sgnd, inmem))) { | |
| 159 | 176 | goto error; |
| 160 | 177 | } |
| 161 | 178 | ++image->numcmpts_; |
| @@ -190,6 +207,7 @@ jas_image_t *jas_image_create0() · 28 unmodified lines | ||
| 190 | 207 | image->numcmpts_ = 0; |
| 191 | 208 | image->maxcmpts_ = 0; |
| 192 | 209 | image->cmpts_ = 0; |
| 210 | +// image->inmem_ = true; | |
| 193 | 211 | image->cmprof_ = 0; |
| 194 | 212 | |
| 195 | 213 | return image; |
| @@ -207,7 +225,8 @@ jas_image_t *jas_image_copy(jas_image_t *image) · 11 unmodified lines | ||
| 207 | 225 | goto error; |
| 208 | 226 | } |
| 209 | 227 | for (unsigned cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { |
| 210 | − if (!(newimage->cmpts_[cmptno] = jas_image_cmpt_copy(image->cmpts_[cmptno]))) { | |
| 228 | + if (!(newimage->cmpts_[cmptno] = jas_image_cmpt_copy( | |
| 229 | + image->cmpts_[cmptno]))) { | |
| 211 | 230 | goto error; |
| 212 | 231 | } |
| 213 | 232 | ++newimage->numcmpts_; |
| @@ -216,8 +235,9 @@ jas_image_t *jas_image_copy(jas_image_t *image) · 2 unmodified lines | ||
| 216 | 235 | jas_image_setbbox(newimage); |
| 217 | 236 | |
| 218 | 237 | if (image->cmprof_) { |
| 219 | − if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_))) | |
| 238 | + if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_))) { | |
| 220 | 239 | goto error; |
| 240 | + } | |
| 221 | 241 | } |
| 222 | 242 | |
| 223 | 243 | return newimage; |
| @@ -259,13 +279,13 @@ static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt) · 35 unmodified lines | ||
| 259 | 279 | if (!(newcmpt->stream_ = jas_stream_memopen(0, 0))) { |
| 260 | 280 | goto error; |
| 261 | 281 | } |
| 262 | − if (jas_stream_seek(cmpt->stream_, 0, 0)) { | |
| 282 | + if (jas_stream_seek(cmpt->stream_, 0, SEEK_SET)) { | |
| 263 | 283 | goto error; |
| 264 | 284 | } |
| 265 | 285 | if (jas_stream_copy(newcmpt->stream_, cmpt->stream_, -1)) { |
| 266 | 286 | goto error; |
| 267 | 287 | } |
| 268 | − if (jas_stream_seek(newcmpt->stream_, 0, 0)) { | |
| 288 | + if (jas_stream_seek(newcmpt->stream_, 0, SEEK_SET)) { | |
| 269 | 289 | goto error; |
| 270 | 290 | } |
| 271 | 291 | return newcmpt; |
| @@ -283,20 +303,22 @@ void jas_image_destroy(jas_image_t *image) · 11 unmodified lines | ||
| 283 | 303 | } |
| 284 | 304 | jas_free(image->cmpts_); |
| 285 | 305 | } |
| 286 | − if (image->cmprof_) | |
| 306 | + if (image->cmprof_) { | |
| 287 | 307 | jas_cmprof_destroy(image->cmprof_); |
| 308 | + } | |
| 288 | 309 | jas_free(image); |
| 289 | 310 | } |
| 290 | 311 | |
| 291 | 312 | static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, |
| 292 | 313 | int_fast32_t tly, int_fast32_t hstep, int_fast32_t vstep, |
| 293 | − int_fast32_t width, int_fast32_t height, uint_fast16_t depth, bool sgnd) | |
| 314 | + int_fast32_t width, int_fast32_t height, uint_fast16_t depth, bool sgnd, | |
| 315 | + bool inmem) | |
| 294 | 316 | { |
| 295 | 317 | jas_image_cmpt_t *cmpt; |
| 296 | 318 | size_t size; |
| 297 | 319 | |
| 298 | − JAS_DBGLOG(100, ( | |
| 299 | − "jas_image_cmpt_create(%ld, %ld, %ld, %ld, %ld, %ld, %d, %d)\n", | |
| 320 | + JAS_LOGDEBUGF(100, | |
| 321 | + "jas_image_cmpt_create(%ld, %ld, %ld, %ld, %ld, %ld, %d, %d, %d)\n", | |
| 300 | 322 | JAS_CAST(long, tlx), |
| 301 | 323 | JAS_CAST(long, tly), |
| 302 | 324 | JAS_CAST(long, hstep), |
| @@ -305,7 +327,8 @@ static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, · 2 unmodified lines | ||
| 305 | 327 | JAS_CAST(long, height), |
| 306 | 328 | JAS_CAST(int, depth), |
| 307 | 329 | sgnd, |
| 308 | − )); | |
| 330 | + inmem | |
| 331 | + ); | |
| 309 | 332 | |
| 310 | 333 | if (depth < 1U + sgnd) { |
| 311 | 334 | /* we need at least 1 bit for unsigned samples and 2 |
| @@ -340,13 +363,16 @@ static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, · 28 unmodified lines | ||
| 340 | 363 | cmpt->stream_ = 0; |
| 341 | 364 | cmpt->cps_ = (depth + 7) / 8; |
| 342 | 365 | |
| 343 | − // Compute the number of samples in the image component, while protecting | |
| 344 | − // against overflow. | |
| 345 | − // size = cmpt->width_ * cmpt->height_ * cmpt->cps_; | |
| 366 | + /* | |
| 367 | + * Compute the number of samples in the image component, while protecting | |
| 368 | + * against overflow. | |
| 369 | + * size = cmpt->width_ * cmpt->height_ * cmpt->cps_; | |
| 370 | + */ | |
| 346 | 371 | if (!jas_safe_size_mul3(cmpt->width_, cmpt->height_, cmpt->cps_, &size)) { |
| 347 | 372 | goto error; |
| 348 | 373 | } |
| 349 | − cmpt->stream_ = jas_stream_memopen2(0, size); | |
| 374 | + cmpt->stream_ = (inmem) ? jas_stream_memopen(0, size) : | |
| 375 | + jas_stream_tmpfile(); | |
| 350 | 376 | if (!cmpt->stream_) { |
| 351 | 377 | goto error; |
| 352 | 378 | } |
| @@ -358,9 +384,9 @@ static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, · 5 unmodified lines | ||
| 358 | 384 | if (size - 1 > LONG_MAX) { |
| 359 | 385 | goto error; |
| 360 | 386 | } |
| 361 | − if (jas_stream_seek(cmpt->stream_, size - 1, 0) < 0 || | |
| 387 | + if (jas_stream_seek(cmpt->stream_, size - 1, SEEK_SET) < 0 || | |
| 362 | 388 | jas_stream_putc(cmpt->stream_, 0) == EOF || |
| 363 | − jas_stream_seek(cmpt->stream_, 0, 0) < 0) { | |
| 389 | + jas_stream_seek(cmpt->stream_, 0, SEEK_SET) < 0) { | |
| 364 | 390 | goto error; |
| 365 | 391 | } |
| 366 | 392 | } |
| @@ -393,25 +419,24 @@ jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr) · 26 unmodified lines | ||
| 393 | 419 | |
| 394 | 420 | /* If possible, try to determine the format of the input data. */ |
| 395 | 421 | if (fmt < 0) { |
| 396 | − if ((fmt = jas_image_getfmt(in)) < 0){ | |
| 397 | − werrstr("unknown format"); | |
| 422 | + if ((fmt = jas_image_getfmt(in)) < 0) { | |
| 423 | + jas_logerrorf("jas_image_decode: cannot determine image format\n"); | |
| 398 | 424 | goto error; |
| 399 | 425 | } |
| 400 | 426 | } |
| 401 | 427 | |
| 402 | 428 | /* Is it possible to decode an image represented in this format? */ |
| 403 | − if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))){ | |
| 404 | − werrstr("unsupported format"); | |
| 429 | + if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) { | |
| 405 | 430 | goto error; |
| 406 | 431 | } |
| 407 | − if (!fmtinfo->ops.decode){ | |
| 408 | − werrstr("no decoder for the format"); | |
| 432 | + if (!fmtinfo->ops.decode) { | |
| 433 | + jas_logerrorf("jas_image_decode: no decode operation available\n"); | |
| 409 | 434 | goto error; |
| 410 | 435 | } |
| 411 | 436 | |
| 412 | 437 | /* Decode the image. */ |
| 413 | − if (!(image = (*fmtinfo->ops.decode)(in, optstr))){ | |
| 414 | − werrstr("failed to decode"); | |
| 438 | + if (!(image = (*fmtinfo->ops.decode)(in, optstr))) { | |
| 439 | + jas_logerrorf("jas_image_decode: decode operation failed\n"); | |
| 415 | 440 | goto error; |
| 416 | 441 | } |
| 417 | 442 | |
| @@ -419,16 +444,18 @@ jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr) · 1 unmodified line | ||
| 419 | 444 | if (!jas_clrspc_isunknown(image->clrspc_) && |
| 420 | 445 | !jas_clrspc_isgeneric(image->clrspc_) && !image->cmprof_) { |
| 421 | 446 | if (!(image->cmprof_ = |
| 422 | − jas_cmprof_createfromclrspc(jas_image_clrspc(image)))){ | |
| 423 | − werrstr("failed to create colorspace"); | |
| 447 | + jas_cmprof_createfromclrspc(jas_image_clrspc(image)))) { | |
| 448 | + jas_logerrorf("jas_image_decode: cannot create CM profile\n"); | |
| 424 | 449 | goto error; |
| 425 | 450 | } |
| 426 | 451 | } |
| 427 | 452 | |
| 428 | 453 | return image; |
| 454 | + | |
| 429 | 455 | error: |
| 430 | − if (image) | |
| 456 | + if (image) { | |
| 431 | 457 | jas_image_destroy(image); |
| 458 | + } | |
| 432 | 459 | return 0; |
| 433 | 460 | } |
| 434 | 461 | |
| @@ -437,7 +464,7 @@ int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, · 2 unmodified lines | ||
| 437 | 464 | { |
| 438 | 465 | const jas_image_fmtinfo_t *fmtinfo; |
| 439 | 466 | if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) { |
| 440 | − jas_eprintf("format lookup failed\n"); | |
| 467 | + jas_logerrorf("format lookup failed\n"); | |
| 441 | 468 | return -1; |
| 442 | 469 | } |
| 443 | 470 | return (fmtinfo->ops.encode) ? (*fmtinfo->ops.encode)(image, out, |
| @@ -460,9 +487,9 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 16 unmodified lines | ||
| 460 | 487 | jas_seqent_t *dr; |
| 461 | 488 | jas_seqent_t *d; |
| 462 | 489 | |
| 463 | − JAS_DBGLOG(100, ("jas_image_readcmpt(%p, %d, %ld, %ld, %ld, %ld, %p)\n", | |
| 490 | + JAS_LOGDEBUGF(100, "jas_image_readcmpt(%p, %d, %ld, %ld, %ld, %ld, %p)\n", | |
| 464 | 491 | image, cmptno, JAS_CAST(long, x), JAS_CAST(long, y), |
| 465 | − JAS_CAST(long, width), JAS_CAST(long, height), data)); | |
| 492 | + JAS_CAST(long, width), JAS_CAST(long, height), data); | |
| 466 | 493 | |
| 467 | 494 | if(data == NULL) { |
| 468 | 495 | return -1; |
| @@ -483,7 +510,8 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 14 unmodified lines | ||
| 483 | 510 | return -1; |
| 484 | 511 | } |
| 485 | 512 | |
| 486 | − if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != width) { | |
| 513 | + if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != | |
| 514 | + width) { | |
| 487 | 515 | if (jas_matrix_resize(data, height, width)) { |
| 488 | 516 | return -1; |
| 489 | 517 | } |
| @@ -497,9 +525,13 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 7 unmodified lines | ||
| 497 | 525 | |
| 498 | 526 | dr = jas_matrix_getref(data, 0, 0); |
| 499 | 527 | const uint_least32_t drs = jas_matrix_rowstep(data); |
| 528 | + | |
| 529 | + jas_uchar stack_buffer[16384]; | |
| 530 | + | |
| 500 | 531 | for (i = 0; i < height; ++i, dr += drs) { |
| 501 | 532 | d = dr; |
| 502 | − if (jas_stream_seek(stream, (cmpt_width * (y + i) + x) * cps, 0) < 0) { | |
| 533 | + if (jas_stream_seek(stream, (cmpt_width * (y + i) + x) | |
| 534 | + * cps, SEEK_SET) < 0) { | |
| 503 | 535 | return -1; |
| 504 | 536 | } |
| 505 | 537 | |
| @@ -507,13 +539,15 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 1 unmodified line | ||
| 507 | 539 | /* fast path for 1 byte per sample and |
| 508 | 540 | unsigned with bulk reads */ |
| 509 | 541 | |
| 510 | − jas_uchar buffer[16384]; | |
| 542 | + jas_uchar *buffer = stack_buffer; | |
| 511 | 543 | |
| 512 | − if (jas_stream_read(stream, buffer, width) != width) | |
| 544 | + if (jas_stream_read(stream, buffer, width) != width) { | |
| 513 | 545 | return -1; |
| 546 | + } | |
| 514 | 547 | |
| 515 | − for (j = 0; j < width; ++j) | |
| 548 | + for (j = 0; j < width; ++j) { | |
| 516 | 549 | d[j] = buffer[j]; |
| 550 | + } | |
| 517 | 551 | |
| 518 | 552 | continue; |
| 519 | 553 | } |
| @@ -533,9 +567,9 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 13 unmodified lines | ||
| 533 | 567 | return 0; |
| 534 | 568 | } |
| 535 | 569 | |
| 536 | −int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, | |
| 537 | − jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, | |
| 538 | − const jas_matrix_t *data) | |
| 570 | +int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, | |
| 571 | + jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, | |
| 572 | + jas_image_coord_t height, const jas_matrix_t *data) | |
| 539 | 573 | { |
| 540 | 574 | jas_image_cmpt_t *cmpt; |
| 541 | 575 | jas_image_coord_t i; |
| @@ -543,9 +577,9 @@ int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x · 1 unmodified line | ||
| 543 | 577 | jas_seqent_t v; |
| 544 | 578 | int c; |
| 545 | 579 | |
| 546 | − JAS_DBGLOG(100, ("jas_image_writecmpt(%p, %d, %ld, %ld, %ld, %ld, %p)\n", | |
| 580 | + JAS_LOGDEBUGF(100, "jas_image_writecmpt(%p, %d, %ld, %ld, %ld, %ld, %p)\n", | |
| 547 | 581 | image, cmptno, JAS_CAST(long, x), JAS_CAST(long, y), |
| 548 | − JAS_CAST(long, width), JAS_CAST(long, height), data)); | |
| 582 | + JAS_CAST(long, width), JAS_CAST(long, height), data); | |
| 549 | 583 | |
| 550 | 584 | if (cmptno >= image->numcmpts_) { |
| 551 | 585 | return -1; |
| @@ -575,9 +609,13 @@ int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x · 23 unmodified lines | ||
| 575 | 609 | |
| 576 | 610 | const jas_seqent_t *dr = jas_matrix_getref(data, 0, 0); |
| 577 | 611 | const uint_least32_t drs = jas_matrix_rowstep(data); |
| 612 | + | |
| 613 | + jas_uchar stack_buffer[16384]; | |
| 614 | + | |
| 578 | 615 | for (i = 0; i < height; ++i, dr += drs) { |
| 579 | 616 | const jas_seqent_t *d = dr; |
| 580 | − if (jas_stream_seek(stream, (cmpt_width * (y + i) + x) * cps, 0) < 0) { | |
| 617 | + if (jas_stream_seek(stream, (cmpt_width * (y + i) + x) | |
| 618 | + * cps, SEEK_SET) < 0) { | |
| 581 | 619 | return -1; |
| 582 | 620 | } |
| 583 | 621 | |
| @@ -585,7 +623,7 @@ int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x · 1 unmodified line | ||
| 585 | 623 | /* fast path for 1 byte per sample and |
| 586 | 624 | unsigned with bulk writes */ |
| 587 | 625 | |
| 588 | − jas_uchar buffer[16384]; | |
| 626 | + jas_uchar *buffer = stack_buffer; | |
| 589 | 627 | |
| 590 | 628 | for (j = 0; j < width; ++j) |
| 591 | 629 | buffer[j] = d[j]; |
| @@ -614,88 +652,139 @@ int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x · 22 unmodified lines | ||
| 614 | 652 | * File format operations. |
| 615 | 653 | \******************************************************************************/ |
| 616 | 654 | |
| 617 | −void jas_image_clearfmts() | |
| 655 | +static void jas_image_fmtinfo_init(jas_image_fmtinfo_t *fmtinfo) | |
| 618 | 656 | { |
| 619 | − jas_image_fmtinfo_t *fmtinfo; | |
| 620 | − for (unsigned i = 0; i < jas_image_numfmts; ++i) { | |
| 621 | − fmtinfo = &jas_image_fmtinfos[i]; | |
| 622 | − if (fmtinfo->name) { | |
| 623 | − jas_free(fmtinfo->name); | |
| 624 | − fmtinfo->name = 0; | |
| 625 | − } | |
| 626 | − if (fmtinfo->ext) { | |
| 627 | − jas_free(fmtinfo->ext); | |
| 628 | − fmtinfo->ext = 0; | |
| 629 | − } | |
| 630 | − if (fmtinfo->desc) { | |
| 631 | − jas_free(fmtinfo->desc); | |
| 632 | − fmtinfo->desc = 0; | |
| 633 | − } | |
| 634 | − } | |
| 635 | − jas_image_numfmts = 0; | |
| 657 | + fmtinfo->id = -1; | |
| 658 | + fmtinfo->name = 0; | |
| 659 | + fmtinfo->ext = 0; | |
| 660 | + fmtinfo->exts = 0; | |
| 661 | + fmtinfo->max_exts = 0; | |
| 662 | + fmtinfo->num_exts = 0; | |
| 663 | + fmtinfo->enabled = 0; | |
| 664 | + fmtinfo->desc = 0; | |
| 665 | + memset(&fmtinfo->ops, 0, sizeof(jas_image_fmtops_t)); | |
| 636 | 666 | } |
| 637 | 667 | |
| 638 | −int jas_image_addfmt(int id, const char *name, const char *ext, | |
| 639 | − const char *desc, const jas_image_fmtops_t *ops) | |
| 668 | +static void jas_image_fmtinfo_cleanup(jas_image_fmtinfo_t *fmtinfo) | |
| 640 | 669 | { |
| 641 | − jas_image_fmtinfo_t *fmtinfo; | |
| 642 | − assert(id >= 0 && name && ext && ops); | |
| 643 | − if (jas_image_numfmts >= JAS_IMAGE_MAXFMTS) { | |
| 644 | − return -1; | |
| 645 | − } | |
| 646 | − fmtinfo = &jas_image_fmtinfos[jas_image_numfmts]; | |
| 647 | − fmtinfo->id = id; | |
| 648 | − if (!(fmtinfo->name = strdup(name))) { | |
| 649 | − return -1; | |
| 650 | − } | |
| 651 | − if (!(fmtinfo->ext = strdup(ext))) { | |
| 670 | + if (fmtinfo->name) { | |
| 652 | 671 | jas_free(fmtinfo->name); |
| 653 | − return -1; | |
| 672 | + fmtinfo->name = 0; | |
| 654 | 673 | } |
| 655 | − if (!(fmtinfo->desc = strdup(desc))) { | |
| 656 | − jas_free(fmtinfo->name); | |
| 674 | + if (fmtinfo->ext) { | |
| 657 | 675 | jas_free(fmtinfo->ext); |
| 658 | − return -1; | |
| 676 | + fmtinfo->ext = 0; | |
| 659 | 677 | } |
| 660 | − fmtinfo->ops = *ops; | |
| 661 | − ++jas_image_numfmts; | |
| 678 | + if (fmtinfo->exts) { | |
| 679 | + assert(fmtinfo->max_exts > 0); | |
| 680 | + for (int i = 0; i < fmtinfo->num_exts; ++i) { | |
| 681 | + jas_free(fmtinfo->exts[i]); | |
| 682 | + } | |
| 683 | + jas_free(fmtinfo->exts); | |
| 684 | + fmtinfo->exts = 0; | |
| 685 | + } | |
| 686 | + if (fmtinfo->desc) { | |
| 687 | + jas_free(fmtinfo->desc); | |
| 688 | + fmtinfo->desc = 0; | |
| 689 | + } | |
| 690 | +} | |
| 691 | + | |
| 692 | +JAS_EXPORT | |
| 693 | +const jas_image_fmtinfo_t *jas_image_getfmtbyind(int index) | |
| 694 | +{ | |
| 695 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 696 | + assert(index >= 0 && index < ctx->image_numfmts); | |
| 697 | + return &ctx->image_fmtinfos[index]; | |
| 698 | +} | |
| 699 | + | |
| 700 | +JAS_EXPORT | |
| 701 | +int jas_image_getnumfmts(void) | |
| 702 | +{ | |
| 703 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 704 | + return ctx->image_numfmts; | |
| 705 | +} | |
| 706 | + | |
| 707 | +JAS_EXPORT | |
| 708 | +int jas_image_setfmtenable(int index, int enabled) | |
| 709 | +{ | |
| 710 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 711 | + ctx->image_fmtinfos[index].enabled = enabled; | |
| 662 | 712 | return 0; |
| 663 | 713 | } |
| 664 | 714 | |
| 665 | −int jas_image_addcmpt(jas_image_t *image, int cmptno, | |
| 666 | − const jas_image_cmptparm_t *cmptparm) | |
| 715 | +void jas_image_clearfmts_internal(jas_image_fmtinfo_t *image_fmtinfos, | |
| 716 | + size_t *image_numfmts) | |
| 667 | 717 | { |
| 668 | − jas_image_cmpt_t *newcmpt; | |
| 669 | − if (cmptno < 0) { | |
| 670 | − cmptno = image->numcmpts_; | |
| 718 | + jas_image_fmtinfo_t *fmtinfo; | |
| 719 | + for (int fmtind = 0; fmtind < *image_numfmts; ++fmtind) { | |
| 720 | + fmtinfo = &image_fmtinfos[fmtind]; | |
| 721 | + jas_image_fmtinfo_cleanup(fmtinfo); | |
| 671 | 722 | } |
| 672 | − assert(cmptno >= 0 && (unsigned)cmptno <= image->numcmpts_); | |
| 673 | − if (image->numcmpts_ >= image->maxcmpts_) { | |
| 674 | − if (jas_image_growcmpts(image, image->maxcmpts_ + 128)) { | |
| 675 | − return -1; | |
| 676 | − } | |
| 723 | + *image_numfmts = 0; | |
| 724 | +} | |
| 725 | + | |
| 726 | +void jas_image_clearfmts() | |
| 727 | +{ | |
| 728 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 729 | + jas_image_clearfmts_internal(ctx->image_fmtinfos, &ctx->image_numfmts); | |
| 730 | +} | |
| 731 | + | |
| 732 | +int jas_image_addfmt_internal(jas_image_fmtinfo_t *image_fmtinfos, | |
| 733 | + size_t *image_numfmts, int id, const char *name, const char *ext, | |
| 734 | + const char *desc, const jas_image_fmtops_t *ops) | |
| 735 | +{ | |
| 736 | + const char delim[] = " \t"; | |
| 737 | + int ret = 0; | |
| 738 | + jas_image_fmtinfo_t *fmtinfo = 0; | |
| 739 | + | |
| 740 | + assert(id >= 0 && name && ext && ops); | |
| 741 | + if (*image_numfmts >= JAS_IMAGE_MAXFMTS) { | |
| 742 | + ret = -1; | |
| 743 | + goto done; | |
| 677 | 744 | } |
| 678 | − if (!(newcmpt = jas_image_cmpt_create(cmptparm->tlx, | |
| 679 | − cmptparm->tly, cmptparm->hstep, cmptparm->vstep, | |
| 680 | − cmptparm->width, cmptparm->height, cmptparm->prec, | |
| 681 | − cmptparm->sgnd))) { | |
| 682 | − return -1; | |
| 745 | + fmtinfo = &image_fmtinfos[*image_numfmts]; | |
| 746 | + jas_image_fmtinfo_init(fmtinfo); | |
| 747 | + fmtinfo->id = id; | |
| 748 | + if (jas_stringtokenize(ext, delim, &fmtinfo->exts, &fmtinfo->max_exts, | |
| 749 | + &fmtinfo->num_exts)) { | |
| 750 | + assert(!fmtinfo->exts && !fmtinfo->max_exts && !fmtinfo->num_exts); | |
| 751 | + ret = -1; | |
| 752 | + goto done; | |
| 753 | + } | |
| 754 | + assert(fmtinfo->num_exts > 0); | |
| 755 | + char *primary_ext = fmtinfo->exts[0]; | |
| 756 | + if (!(fmtinfo->name = jas_strdup(name))) { | |
| 757 | + ret = -1; | |
| 758 | + goto done; | |
| 759 | + } | |
| 760 | + if (!(fmtinfo->ext = jas_strdup(primary_ext))) { | |
| 761 | + ret = -1; | |
| 762 | + goto done; | |
| 763 | + } | |
| 764 | + if (!(fmtinfo->desc = jas_strdup(desc))) { | |
| 765 | + ret = -1; | |
| 766 | + goto done; | |
| 683 | 767 | } |
| 684 | − if ((unsigned)cmptno < image->numcmpts_) { | |
| 685 | − memmove(&image->cmpts_[cmptno + 1], &image->cmpts_[cmptno], | |
| 686 | − (image->numcmpts_ - (unsigned)cmptno) * sizeof(jas_image_cmpt_t *)); | |
| 768 | + fmtinfo->ops = *ops; | |
| 769 | + ++(*image_numfmts); | |
| 770 | +done: | |
| 771 | + if (ret && fmtinfo) { | |
| 772 | + jas_image_fmtinfo_cleanup(fmtinfo); | |
| 687 | 773 | } |
| 688 | − image->cmpts_[cmptno] = newcmpt; | |
| 689 | − ++image->numcmpts_; | |
| 690 | − | |
| 691 | − jas_image_setbbox(image); | |
| 774 | + return ret; | |
| 775 | +} | |
| 692 | 776 | |
| 693 | − return 0; | |
| 777 | +int jas_image_addfmt(int id, const char *name, const char *ext, | |
| 778 | + const char *desc, const jas_image_fmtops_t *ops) | |
| 779 | +{ | |
| 780 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 781 | + return jas_image_addfmt_internal(ctx->image_fmtinfos, &ctx->image_numfmts, | |
| 782 | + id, name, ext, desc, ops); | |
| 694 | 783 | } |
| 695 | 784 | |
| 696 | 785 | /* This is for future consideration for addition to the library API. */ |
| 697 | 786 | #if 0 |
| 698 | −JAS_DLLEXPORT | |
| 787 | +JAS_EXPORT | |
| 699 | 788 | int jas_image_delfmt(int fmtid) |
| 700 | 789 | { |
| 701 | 790 | if (fmtid < 0 || fmtid >= JAS_CAST(int, jas_image_numfmts)) { |
| @@ -734,20 +823,21 @@ const char *jas_image_fmttostr(int fmt) · 32 unmodified lines | ||
| 734 | 823 | |
| 735 | 824 | int jas_image_getfmt(jas_stream_t *in) |
| 736 | 825 | { |
| 826 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 737 | 827 | const jas_image_fmtinfo_t *fmtinfo; |
| 738 | 828 | |
| 739 | 829 | /* Check for data in each of the supported formats. */ |
| 740 | 830 | unsigned i; |
| 741 | − for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, | |
| 831 | + for (i = 0, fmtinfo = ctx->image_fmtinfos; i < ctx->image_numfmts; ++i, | |
| 742 | 832 | ++fmtinfo) { |
| 743 | − if (fmtinfo->ops.validate) { | |
| 833 | + if (fmtinfo->enabled && fmtinfo->ops.validate) { | |
| 744 | 834 | /* Is the input data valid for this format? */ |
| 745 | − JAS_DBGLOG(20, ("testing for format %s ... ", fmtinfo->name)); | |
| 835 | + JAS_LOGDEBUGF(20, "testing for format %s\n", fmtinfo->name); | |
| 746 | 836 | if (!(*fmtinfo->ops.validate)(in)) { |
| 747 | − JAS_DBGLOG(20, ("test succeeded\n")); | |
| 837 | + JAS_LOGDEBUGF(20, "test succeeded\n"); | |
| 748 | 838 | return fmtinfo->id; |
| 749 | 839 | } |
| 750 | − JAS_DBGLOG(20, ("test failed\n")); | |
| 840 | + JAS_LOGDEBUGF(20, "test failed\n"); | |
| 751 | 841 | } |
| 752 | 842 | } |
| 753 | 843 | return -1; |
| @@ -755,6 +845,7 @@ int jas_image_getfmt(jas_stream_t *in) · 1 unmodified line | ||
| 755 | 845 | |
| 756 | 846 | int jas_image_fmtfromname(const char *name) |
| 757 | 847 | { |
| 848 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 758 | 849 | const char *ext; |
| 759 | 850 | const jas_image_fmtinfo_t *fmtinfo; |
| 760 | 851 | /* Get the file name extension. */ |
| @@ -764,10 +855,10 @@ int jas_image_fmtfromname(const char *name) · 3 unmodified lines | ||
| 764 | 855 | ++ext; |
| 765 | 856 | /* Try to find a format that uses this extension. */ |
| 766 | 857 | unsigned i; |
| 767 | − for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, | |
| 858 | + for (i = 0, fmtinfo = ctx->image_fmtinfos; i < ctx->image_numfmts; ++i, | |
| 768 | 859 | ++fmtinfo) { |
| 769 | 860 | /* Do we have a match? */ |
| 770 | − if (!strcmp(ext, fmtinfo->ext)) { | |
| 861 | + if (fmtinfo->enabled && !strcmp(ext, fmtinfo->ext)) { | |
| 771 | 862 | return fmtinfo->id; |
| 772 | 863 | } |
| 773 | 864 | } |
| @@ -824,12 +915,45 @@ void jas_image_delcmpt(jas_image_t *image, unsigned cmptno) · 50 unmodified lines | ||
| 824 | 915 | jas_image_setbbox(image); |
| 825 | 916 | } |
| 826 | 917 | |
| 918 | +int jas_image_addcmpt(jas_image_t *image, int cmptno, | |
| 919 | + const jas_image_cmptparm_t *cmptparm) | |
| 920 | +{ | |
| 921 | + jas_image_cmpt_t *newcmpt; | |
| 922 | + if (cmptno < 0) { | |
| 923 | + cmptno = image->numcmpts_; | |
| 924 | + } | |
| 925 | + assert(cmptno >= 0 && (unsigned)cmptno <= image->numcmpts_); | |
| 926 | + if (image->numcmpts_ >= image->maxcmpts_) { | |
| 927 | + if (jas_image_growcmpts(image, image->maxcmpts_ + 128)) { | |
| 928 | + return -1; | |
| 929 | + } | |
| 930 | + } | |
| 931 | + if (!(newcmpt = jas_image_cmpt_create(cmptparm->tlx, | |
| 932 | + cmptparm->tly, cmptparm->hstep, cmptparm->vstep, | |
| 933 | + cmptparm->width, cmptparm->height, cmptparm->prec, | |
| 934 | + cmptparm->sgnd, true))) { | |
| 935 | + return -1; | |
| 936 | + } | |
| 937 | + if ((unsigned)cmptno < image->numcmpts_) { | |
| 938 | + memmove(&image->cmpts_[cmptno + 1], &image->cmpts_[cmptno], | |
| 939 | + (image->numcmpts_ - (unsigned)cmptno) * sizeof(jas_image_cmpt_t *)); | |
| 940 | + } | |
| 941 | + image->cmpts_[cmptno] = newcmpt; | |
| 942 | + ++image->numcmpts_; | |
| 943 | + | |
| 944 | + jas_image_setbbox(image); | |
| 945 | + | |
| 946 | + return 0; | |
| 947 | +} | |
| 948 | + | |
| 827 | 949 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id) |
| 828 | 950 | { |
| 951 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 829 | 952 | unsigned i; |
| 830 | 953 | const jas_image_fmtinfo_t *fmtinfo; |
| 831 | 954 | |
| 832 | − for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) { | |
| 955 | + for (i = 0, fmtinfo = ctx->image_fmtinfos; i < ctx->image_numfmts; | |
| 956 | + ++i, ++fmtinfo) { | |
| 833 | 957 | if (fmtinfo->id == id) { |
| 834 | 958 | return fmtinfo; |
| 835 | 959 | } |
| @@ -839,10 +963,11 @@ const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id) · 3 unmodified lines | ||
| 839 | 963 | |
| 840 | 964 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name) |
| 841 | 965 | { |
| 966 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 842 | 967 | unsigned i; |
| 843 | 968 | const jas_image_fmtinfo_t *fmtinfo; |
| 844 | − | |
| 845 | − for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) { | |
| 969 | + for (i = 0, fmtinfo = ctx->image_fmtinfos; i < ctx->image_numfmts; | |
| 970 | + ++i, ++fmtinfo) { | |
| 846 | 971 | if (!strcmp(fmtinfo->name, name)) { |
| 847 | 972 | return fmtinfo; |
| 848 | 973 | } |
| @@ -853,7 +978,9 @@ const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name) · 4 unmodified lines | ||
| 853 | 978 | static uint_fast32_t inttobits(jas_seqent_t v, unsigned prec, bool sgnd) |
| 854 | 979 | { |
| 855 | 980 | uint_fast32_t ret; |
| 856 | − ret = ((sgnd && v < 0) ? ((1 << prec) + v) : v) & JAS_ONES(prec); | |
| 981 | + assert(v >= 0 || sgnd); | |
| 982 | + ret = ((sgnd && v < 0) ? (JAS_POW2_X(jas_seqent_t, prec) + v) : v) & | |
| 983 | + JAS_ONES(prec); | |
| 857 | 984 | return ret; |
| 858 | 985 | } |
| 859 | 986 | |
| @@ -945,8 +1072,39 @@ int jas_image_copycmpt(jas_image_t *dstimage, unsigned dstcmptno, · 85 unmodified lines | ||
| 945 | 1072 | return 0; |
| 946 | 1073 | } |
| 947 | 1074 | |
| 948 | −int jas_image_depalettize(jas_image_t *image, unsigned cmptno, unsigned numlutents, | |
| 949 | − const int_fast32_t *lutents, unsigned dtype, unsigned newcmptno) | |
| 1075 | +int jas_image_dump(jas_image_t *image, FILE *out) | |
| 1076 | +{ | |
| 1077 | + long buf[1024]; | |
| 1078 | + jas_image_cmpt_t *cmpt; | |
| 1079 | + for (unsigned cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { | |
| 1080 | + cmpt = image->cmpts_[cmptno]; | |
| 1081 | + fprintf(out, "prec=%d, sgnd=%d, cmpttype=%"PRIiFAST32"\n", cmpt->prec_, | |
| 1082 | + cmpt->sgnd_, cmpt->type_); | |
| 1083 | + const unsigned width = jas_image_cmptwidth(image, cmptno); | |
| 1084 | + const unsigned height = jas_image_cmptheight(image, cmptno); | |
| 1085 | + const unsigned n = JAS_MIN(16, width); | |
| 1086 | + if (jas_image_readcmpt2(image, cmptno, 0, 0, n, 1, buf)) { | |
| 1087 | + return -1; | |
| 1088 | + } | |
| 1089 | + for (unsigned i = 0; i < n; ++i) { | |
| 1090 | + fprintf(out, " f(%d,%d)=%ld", i, 0, buf[i]); | |
| 1091 | + } | |
| 1092 | + fprintf(out, "\n"); | |
| 1093 | + if (jas_image_readcmpt2(image, cmptno, width - n, height - 1, n, 1, | |
| 1094 | + buf)) { | |
| 1095 | + return -1; | |
| 1096 | + } | |
| 1097 | + for (unsigned i = 0; i < n; ++i) { | |
| 1098 | + fprintf(out, " f(%d,%d)=%ld", width - n + i, height - 1, buf[i]); | |
| 1099 | + } | |
| 1100 | + fprintf(out, "\n"); | |
| 1101 | + } | |
| 1102 | + return 0; | |
| 1103 | +} | |
| 1104 | + | |
| 1105 | +int jas_image_depalettize(jas_image_t *image, unsigned cmptno, | |
| 1106 | + unsigned numlutents, const int_fast32_t *lutents, unsigned dtype, | |
| 1107 | + unsigned newcmptno) | |
| 950 | 1108 | { |
| 951 | 1109 | jas_image_cmptparm_t cmptparms; |
| 952 | 1110 | const jas_image_cmpt_t *cmpt = image->cmpts_[cmptno]; |
| @@ -994,7 +1152,8 @@ int jas_image_readcmptsample(jas_image_t *image, unsigned cmptno, unsigned x, un · 41 unmodified lines | ||
| 994 | 1152 | |
| 995 | 1153 | cmpt = image->cmpts_[cmptno]; |
| 996 | 1154 | |
| 997 | − if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_, 0) < 0) { | |
| 1155 | + if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_, | |
| 1156 | + SEEK_SET) < 0) { | |
| 998 | 1157 | return -1; |
| 999 | 1158 | } |
| 1000 | 1159 | v = 0; |
| @@ -1016,7 +1175,8 @@ void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno, unsigned x, · 15 unmodified lines | ||
| 1016 | 1175 | |
| 1017 | 1176 | cmpt = image->cmpts_[cmptno]; |
| 1018 | 1177 | |
| 1019 | − if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_, 0) < 0) { | |
| 1178 | + if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_, | |
| 1179 | + SEEK_SET) < 0) { | |
| 1020 | 1180 | return; |
| 1021 | 1181 | } |
| 1022 | 1182 | t = inttobits(v, cmpt->prec_, cmpt->sgnd_); |
| @@ -1029,7 +1189,8 @@ void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno, unsigned x, · 6 unmodified lines | ||
| 1029 | 1189 | } |
| 1030 | 1190 | } |
| 1031 | 1191 | |
| 1032 | −int jas_image_getcmptbytype(const jas_image_t *image, jas_image_cmpttype_t ctype) | |
| 1192 | +int jas_image_getcmptbytype(const jas_image_t *image, | |
| 1193 | + jas_image_cmpttype_t ctype) | |
| 1033 | 1194 | { |
| 1034 | 1195 | for (unsigned cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { |
| 1035 | 1196 | if (image->cmpts_[cmptno]->type_ == ctype) { |
| @@ -1039,29 +1200,14 @@ int jas_image_getcmptbytype(const jas_image_t *image, jas_image_cmpttype_t ctype · 3 unmodified lines | ||
| 1039 | 1200 | return -1; |
| 1040 | 1201 | } |
| 1041 | 1202 | |
| 1042 | − | |
| 1043 | − | |
| 1044 | − | |
| 1045 | − | |
| 1046 | − | |
| 1047 | − | |
| 1048 | − | |
| 1049 | − | |
| 1050 | − | |
| 1051 | − | |
| 1052 | − | |
| 1053 | − | |
| 1054 | − | |
| 1055 | − | |
| 1056 | − | |
| 1057 | 1203 | /***********************************************/ |
| 1058 | 1204 | /***********************************************/ |
| 1059 | 1205 | /***********************************************/ |
| 1060 | 1206 | /***********************************************/ |
| 1061 | 1207 | |
| 1062 | −int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, | |
| 1063 | − jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, | |
| 1064 | − long *buf) | |
| 1208 | +int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, | |
| 1209 | + jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, | |
| 1210 | + jas_image_coord_t height, long *buf) | |
| 1065 | 1211 | { |
| 1066 | 1212 | jas_image_cmpt_t *cmpt; |
| 1067 | 1213 | jas_image_coord_t i; |
| @@ -1069,21 +1215,26 @@ int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, jas_image_coord_t x · 1 unmodified line | ||
| 1069 | 1215 | long v; |
| 1070 | 1216 | long *bufptr; |
| 1071 | 1217 | |
| 1072 | − if (cmptno >= image->numcmpts_) | |
| 1218 | + if (cmptno >= image->numcmpts_) { | |
| 1073 | 1219 | goto error; |
| 1220 | + } | |
| 1074 | 1221 | cmpt = image->cmpts_[cmptno]; |
| 1075 | 1222 | if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ || |
| 1076 | 1223 | width < 0 || height < 0 || x + width > cmpt->width_ || |
| 1077 | − y + height > cmpt->height_) | |
| 1224 | + y + height > cmpt->height_) { | |
| 1078 | 1225 | goto error; |
| 1226 | + } | |
| 1079 | 1227 | |
| 1080 | 1228 | bufptr = buf; |
| 1081 | 1229 | for (i = 0; i < height; ++i) { |
| 1082 | − if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x) * cmpt->cps_, 0) < 0) | |
| 1230 | + if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x) | |
| 1231 | + * cmpt->cps_, SEEK_SET) < 0) { | |
| 1083 | 1232 | goto error; |
| 1233 | + } | |
| 1084 | 1234 | for (j = 0; j < width; ++j) { |
| 1085 | − if (getint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, &v)) | |
| 1235 | + if (getint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, &v)) { | |
| 1086 | 1236 | goto error; |
| 1237 | + } | |
| 1087 | 1238 | *bufptr++ = v; |
| 1088 | 1239 | } |
| 1089 | 1240 | } |
| @@ -1093,31 +1244,36 @@ error: · 3 unmodified lines | ||
| 1093 | 1244 | return -1; |
| 1094 | 1245 | } |
| 1095 | 1246 | |
| 1096 | −int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, | |
| 1097 | − jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, | |
| 1098 | − const long *buf) | |
| 1247 | +int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, | |
| 1248 | + jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, | |
| 1249 | + jas_image_coord_t height, const long *buf) | |
| 1099 | 1250 | { |
| 1100 | 1251 | jas_image_cmpt_t *cmpt; |
| 1101 | 1252 | jas_image_coord_t i; |
| 1102 | 1253 | jas_image_coord_t j; |
| 1103 | 1254 | long v; |
| 1104 | 1255 | |
| 1105 | − if (cmptno >= image->numcmpts_) | |
| 1256 | + if (cmptno >= image->numcmpts_) { | |
| 1106 | 1257 | goto error; |
| 1258 | + } | |
| 1107 | 1259 | cmpt = image->cmpts_[cmptno]; |
| 1108 | 1260 | if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ || |
| 1109 | 1261 | width < 0 || height < 0 || x + width > cmpt->width_ || |
| 1110 | − y + height > cmpt->height_) | |
| 1262 | + y + height > cmpt->height_) { | |
| 1111 | 1263 | goto error; |
| 1264 | + } | |
| 1112 | 1265 | |
| 1113 | 1266 | const long *bufptr = buf; |
| 1114 | 1267 | for (i = 0; i < height; ++i) { |
| 1115 | − if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x) * cmpt->cps_, 0) < 0) | |
| 1268 | + if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x) | |
| 1269 | + * cmpt->cps_, SEEK_SET) < 0) { | |
| 1116 | 1270 | goto error; |
| 1271 | + } | |
| 1117 | 1272 | for (j = 0; j < width; ++j) { |
| 1118 | 1273 | v = *bufptr++; |
| 1119 | − if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v)) | |
| 1274 | + if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v)) { | |
| 1120 | 1275 | goto error; |
| 1276 | + } | |
| 1121 | 1277 | } |
| 1122 | 1278 | } |
| 1123 | 1279 | |
| @@ -1165,10 +1321,11 @@ int jas_image_sampcmpt(jas_image_t *image, unsigned cmptno, unsigned newcmptno, · 41 unmodified lines | ||
| 1165 | 1321 | cmptparm.height = height; |
| 1166 | 1322 | cmptparm.prec = prec; |
| 1167 | 1323 | cmptparm.sgnd = sgnd; |
| 1168 | − if (jas_image_addcmpt(image, newcmptno, &cmptparm)) | |
| 1324 | + if (jas_image_addcmpt(image, newcmptno, &cmptparm)) { | |
| 1169 | 1325 | goto error; |
| 1170 | −cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_; | |
| 1171 | −cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; | |
| 1326 | + } | |
| 1327 | + cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_; | |
| 1328 | + cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; | |
| 1172 | 1329 | const jas_image_cmpt_t *const newcmpt = image->cmpts_[newcmptno]; |
| 1173 | 1330 | jas_stream_rewind(newcmpt->stream_); |
| 1174 | 1331 | for (unsigned i = 0; i < height; ++i) { |
| @@ -1178,11 +1335,13 @@ cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; · 3 unmodified lines | ||
| 1178 | 1335 | ax = downtomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_; |
| 1179 | 1336 | ay = downtomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_; |
| 1180 | 1337 | bx = uptomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_; |
| 1181 | − if (bx > cmptbrx) | |
| 1338 | + if (bx > cmptbrx) { | |
| 1182 | 1339 | bx = cmptbrx; |
| 1340 | + } | |
| 1183 | 1341 | by = uptomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_; |
| 1184 | − if (by > cmptbry) | |
| 1342 | + if (by > cmptbry) { | |
| 1185 | 1343 | by = cmptbry; |
| 1344 | + } | |
| 1186 | 1345 | d0 = (ax - x) * (ax - x) + (ay - y) * (ay - y); |
| 1187 | 1346 | d1 = (bx - x) * (bx - x) + (ay - y) * (ay - y); |
| 1188 | 1347 | d2 = (bx - x) * (bx - x) + (by - y) * (by - y); |
| @@ -1202,19 +1361,23 @@ cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; · 13 unmodified lines | ||
| 1202 | 1361 | } |
| 1203 | 1362 | assert(oldx >= 0 && oldx < oldcmpt->width_ && |
| 1204 | 1363 | oldy >= 0 && oldy < oldcmpt->height_); |
| 1205 | − if (jas_stream_seek(oldcmpt->stream_, oldcmpt->cps_ * (oldy * oldcmpt->width_ + oldx), 0) < 0) | |
| 1364 | + if (jas_stream_seek(oldcmpt->stream_, oldcmpt->cps_ * | |
| 1365 | + (oldy * oldcmpt->width_ + oldx), SEEK_SET) < 0) { | |
| 1206 | 1366 | goto error; |
| 1367 | + } | |
| 1207 | 1368 | if (getint(oldcmpt->stream_, oldcmpt->sgnd_, |
| 1208 | − oldcmpt->prec_, &v)) | |
| 1369 | + oldcmpt->prec_, &v)) { | |
| 1209 | 1370 | goto error; |
| 1371 | + } | |
| 1210 | 1372 | if (newcmpt->prec_ != oldcmpt->prec_ || |
| 1211 | 1373 | newcmpt->sgnd_ != oldcmpt->sgnd_) { |
| 1212 | 1374 | v = convert(v, oldcmpt->sgnd_, oldcmpt->prec_, |
| 1213 | 1375 | newcmpt->sgnd_, newcmpt->prec_); |
| 1214 | 1376 | } |
| 1215 | 1377 | if (putint(newcmpt->stream_, newcmpt->sgnd_, |
| 1216 | − newcmpt->prec_, v)) | |
| 1378 | + newcmpt->prec_, v)) { | |
| 1217 | 1379 | goto error; |
| 1380 | + } | |
| 1218 | 1381 | } |
| 1219 | 1382 | } |
| 1220 | 1383 | return 0; |
| @@ -1241,8 +1404,9 @@ int jas_image_ishomosamp(const jas_image_t *image) · 20 unmodified lines | ||
| 1241 | 1404 | } |
| 1242 | 1405 | |
| 1243 | 1406 | /* Note: This function defines a bounding box differently. */ |
| 1244 | −static void jas_image_calcbbox2(const jas_image_t *image, jas_image_coord_t *tlx, | |
| 1245 | − jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry) | |
| 1407 | +static void jas_image_calcbbox2(const jas_image_t *image, | |
| 1408 | + jas_image_coord_t *tlx, jas_image_coord_t *tly, jas_image_coord_t *brx, | |
| 1409 | + jas_image_coord_t *bry) | |
| 1246 | 1410 | { |
| 1247 | 1411 | jas_image_coord_t tmptlx; |
| 1248 | 1412 | jas_image_coord_t tmptly; |
| @@ -1257,16 +1421,20 @@ static void jas_image_calcbbox2(const jas_image_t *image, jas_image_coord_t *tlx · 8 unmodified lines | ||
| 1257 | 1421 | tmpbry = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1); |
| 1258 | 1422 | for (unsigned i = 0; i < image->numcmpts_; ++i) { |
| 1259 | 1423 | cmpt = image->cmpts_[i]; |
| 1260 | − if (cmpt->tlx_ < tmptlx) | |
| 1424 | + if (cmpt->tlx_ < tmptlx) { | |
| 1261 | 1425 | tmptlx = cmpt->tlx_; |
| 1262 | − if (cmpt->tly_ < tmptly) | |
| 1426 | + } | |
| 1427 | + if (cmpt->tly_ < tmptly) { | |
| 1263 | 1428 | tmptly = cmpt->tly_; |
| 1429 | + } | |
| 1264 | 1430 | t = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1); |
| 1265 | − if (t > tmpbrx) | |
| 1431 | + if (t > tmpbrx) { | |
| 1266 | 1432 | tmpbrx = t; |
| 1433 | + } | |
| 1267 | 1434 | t = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1); |
| 1268 | − if (t > tmpbry) | |
| 1435 | + if (t > tmpbry) { | |
| 1269 | 1436 | tmpbry = t; |
| 1437 | + } | |
| 1270 | 1438 | } |
| 1271 | 1439 | } else { |
| 1272 | 1440 | tmptlx = 0; |
| @@ -1285,7 +1453,7 @@ static inline long decode_twos_comp(jas_ulong c, unsigned prec) · 12 unmodified lines | ||
| 1285 | 1453 | { |
| 1286 | 1454 | long result; |
| 1287 | 1455 | assert(prec >= 2); |
| 1288 | − jas_eprintf("warning: support for signed data is untested\n"); | |
| 1456 | + jas_logwarnf("warning: support for signed data is untested\n"); | |
| 1289 | 1457 | // NOTE: Is this correct? |
| 1290 | 1458 | result = (c & ((1 << (prec - 1)) - 1)) - (c & (1 << (prec - 1))); |
| 1291 | 1459 | return result; |
| @@ -1296,7 +1464,7 @@ static inline jas_ulong encode_twos_comp(long n, unsigned prec) · 4 unmodified lines | ||
| 1296 | 1464 | { |
| 1297 | 1465 | jas_ulong result; |
| 1298 | 1466 | assert(prec >= 2); |
| 1299 | − jas_eprintf("warning: support for signed data is untested\n"); | |
| 1467 | + jas_logwarnf("warning: support for signed data is untested\n"); | |
| 1300 | 1468 | // NOTE: Is this correct? |
| 1301 | 1469 | if (n < 0) { |
| 1302 | 1470 | result = -n; |
| @@ -1315,8 +1483,9 @@ static int getint(jas_stream_t *in, bool sgnd, unsigned prec, long *val) · 12 unmodified lines | ||
| 1315 | 1483 | assert((!sgnd && prec >= 1) || (sgnd && prec >= 2)); |
| 1316 | 1484 | v = 0; |
| 1317 | 1485 | for (unsigned n = (prec + 7) / 8; n-- > 0;) { |
| 1318 | − if ((c = jas_stream_getc(in)) == EOF) | |
| 1486 | + if ((c = jas_stream_getc(in)) == EOF) { | |
| 1319 | 1487 | return -1; |
| 1488 | + } | |
| 1320 | 1489 | v = (v << 8) | c; |
| 1321 | 1490 | } |
| 1322 | 1491 | v &= ((1 << prec) - 1); |
| @@ -1339,8 +1508,9 @@ static int putint(jas_stream_t *out, bool sgnd, unsigned prec, long val) · 16 unmodified lines | ||
| 1339 | 1508 | val &= (1 << prec) - 1; |
| 1340 | 1509 | for (unsigned n = (prec + 7) / 8; n-- > 0;) { |
| 1341 | 1510 | c = (val >> (n * 8)) & 0xff; |
| 1342 | − if (jas_stream_putc(out, c) != c) | |
| 1511 | + if (jas_stream_putc(out, c) != c) { | |
| 1343 | 1512 | return -1; |
| 1513 | + } | |
| 1344 | 1514 | } |
| 1345 | 1515 | return 0; |
| 1346 | 1516 | } |
| @@ -1348,6 +1518,7 @@ static int putint(jas_stream_t *out, bool sgnd, unsigned prec, long val) · 1 unmodified line | ||
| 1348 | 1518 | static long convert(long val, bool oldsgnd, unsigned oldprec, bool newsgnd, |
| 1349 | 1519 | unsigned newprec) |
| 1350 | 1520 | { |
| 1521 | + /* TODO: The following code looks suspicious (i.e., an empty if body). */ | |
| 1351 | 1522 | if (newsgnd != oldsgnd) { |
| 1352 | 1523 | } |
| 1353 | 1524 | if (newprec != oldprec) { |
| @@ -1372,8 +1543,8 @@ static long uptomult(long x, long y) · 18 unmodified lines | ||
| 1372 | 1543 | return ((x + y - 1) / y) * y; |
| 1373 | 1544 | } |
| 1374 | 1545 | |
| 1375 | −jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, | |
| 1376 | − jas_cmxform_intent_t intent) | |
| 1546 | +jas_image_t *jas_image_chclrspc(jas_image_t *image, | |
| 1547 | + const jas_cmprof_t *outprof, jas_cmxform_intent_t intent) | |
| 1377 | 1548 | { |
| 1378 | 1549 | jas_image_t *inimage; |
| 1379 | 1550 | int k; |
| @@ -1387,16 +1558,25 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 7 unmodified lines | ||
| 1387 | 1558 | jas_cmcmptfmt_t *incmptfmts; |
| 1388 | 1559 | jas_cmcmptfmt_t *outcmptfmts; |
| 1389 | 1560 | |
| 1390 | − if (image->numcmpts_ == 0) | |
| 1391 | − /* can't work with a file with no components; | |
| 1392 | − continuing would crash because we'd attempt to | |
| 1393 | − obtain information about the first component */ | |
| 1394 | − return NULL; | |
| 1561 | +#if 0 | |
| 1562 | + jas_eprintf("IMAGE\n"); | |
| 1563 | + jas_image_dump(image, stderr); | |
| 1564 | +#endif | |
| 1565 | + | |
| 1566 | + if (image->numcmpts_ == 0) { | |
| 1567 | + /* | |
| 1568 | + can't work with a file with no components; | |
| 1569 | + continuing would crash because we'd attempt to | |
| 1570 | + obtain information about the first component | |
| 1571 | + */ | |
| 1572 | + return 0; | |
| 1573 | + } | |
| 1395 | 1574 | |
| 1396 | 1575 | outimage = 0; |
| 1397 | 1576 | xform = 0; |
| 1398 | − if (!(inimage = jas_image_copy(image))) | |
| 1577 | + if (!(inimage = jas_image_copy(image))) { | |
| 1399 | 1578 | goto error; |
| 1579 | + } | |
| 1400 | 1580 | |
| 1401 | 1581 | if (!jas_image_ishomosamp(inimage)) { |
| 1402 | 1582 | unsigned minhstep = jas_image_cmpthstep(inimage, 0); |
| @@ -1414,10 +1594,12 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 11 unmodified lines | ||
| 1414 | 1594 | unsigned n = jas_image_numcmpts(inimage); |
| 1415 | 1595 | for (unsigned i = 0; i < n; ++i) { |
| 1416 | 1596 | if (jas_image_sampcmpt(inimage, i, i + 1, 0, 0, minhstep, minvstep, |
| 1417 | − jas_image_cmptsgnd(inimage, i), jas_image_cmptprec(inimage, i))) { | |
| 1597 | + jas_image_cmptsgnd(inimage, i), jas_image_cmptprec(inimage, | |
| 1598 | + i))) { | |
| 1418 | 1599 | goto error; |
| 1419 | 1600 | } |
| 1420 | − const jas_image_cmpttype_t cmpttype = jas_image_cmpttype(inimage, i); | |
| 1601 | + const jas_image_cmpttype_t cmpttype = jas_image_cmpttype(inimage, | |
| 1602 | + i); | |
| 1421 | 1603 | jas_image_setcmpttype(inimage, i + 1, cmpttype); |
| 1422 | 1604 | jas_image_delcmpt(inimage, i); |
| 1423 | 1605 | } |
| @@ -1429,10 +1611,13 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 5 unmodified lines | ||
| 1429 | 1611 | const unsigned vstep = jas_image_cmptvstep(inimage, 0); |
| 1430 | 1612 | |
| 1431 | 1613 | if (!(inprof = jas_image_cmprof(inimage))) { |
| 1432 | − abort(); | |
| 1614 | + // formerly call to abort() | |
| 1615 | + goto error; | |
| 1433 | 1616 | } |
| 1434 | − const unsigned numinclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(inprof)); | |
| 1435 | − const unsigned numoutclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(outprof)); | |
| 1617 | + const unsigned numinclrchans = | |
| 1618 | + jas_clrspc_numchans(jas_cmprof_clrspc(inprof)); | |
| 1619 | + const unsigned numoutclrchans = | |
| 1620 | + jas_clrspc_numchans(jas_cmprof_clrspc(outprof)); | |
| 1436 | 1621 | const unsigned prec = 8; |
| 1437 | 1622 | |
| 1438 | 1623 | if (!(outimage = jas_image_create0())) { |
| @@ -1449,8 +1634,9 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 10 unmodified lines | ||
| 1449 | 1634 | cmptparm.height = height; |
| 1450 | 1635 | cmptparm.prec = prec; |
| 1451 | 1636 | cmptparm.sgnd = 0; |
| 1452 | − if (jas_image_addcmpt(outimage, -1, &cmptparm)) | |
| 1637 | + if (jas_image_addcmpt(outimage, -1, &cmptparm)) { | |
| 1453 | 1638 | goto error; |
| 1639 | + } | |
| 1454 | 1640 | jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i)); |
| 1455 | 1641 | } |
| 1456 | 1642 | #if 0 |
| @@ -1463,8 +1649,9 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 6 unmodified lines | ||
| 1463 | 1649 | } |
| 1464 | 1650 | #endif |
| 1465 | 1651 | |
| 1466 | − if (!(tmpprof = jas_cmprof_copy(outprof))) | |
| 1652 | + if (!(tmpprof = jas_cmprof_copy(outprof))) { | |
| 1467 | 1653 | goto error; |
| 1654 | + } | |
| 1468 | 1655 | assert(!jas_image_cmprof(outimage)); |
| 1469 | 1656 | jas_image_setcmprof(outimage, tmpprof); |
| 1470 | 1657 | jas_image_setclrspc(outimage, jas_cmprof_clrspc(outprof)); |
| @@ -1476,7 +1663,8 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 5 unmodified lines | ||
| 1476 | 1663 | |
| 1477 | 1664 | inpixmap.numcmpts = numinclrchans; |
| 1478 | 1665 | if (!(incmptfmts = jas_alloc2(numinclrchans, sizeof(jas_cmcmptfmt_t)))) { |
| 1479 | − abort(); | |
| 1666 | + // formerly call to abort() | |
| 1667 | + goto error; | |
| 1480 | 1668 | } |
| 1481 | 1669 | inpixmap.cmptfmts = incmptfmts; |
| 1482 | 1670 | for (unsigned i = 0; i < numinclrchans; ++i) { |
| @@ -1492,14 +1680,16 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 9 unmodified lines | ||
| 1492 | 1680 | |
| 1493 | 1681 | outpixmap.numcmpts = numoutclrchans; |
| 1494 | 1682 | if (!(outcmptfmts = jas_alloc2(numoutclrchans, sizeof(jas_cmcmptfmt_t)))) { |
| 1495 | − abort(); | |
| 1683 | + // formerly call to abort() | |
| 1684 | + goto error; | |
| 1496 | 1685 | } |
| 1497 | 1686 | outpixmap.cmptfmts = outcmptfmts; |
| 1498 | 1687 | |
| 1499 | 1688 | for (unsigned i = 0; i < numoutclrchans; ++i) { |
| 1500 | 1689 | const int j = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(i)); |
| 1501 | − if (!(outcmptfmts[i].buf = jas_alloc2(width, sizeof(long)))) | |
| 1690 | + if (!(outcmptfmts[i].buf = jas_alloc2(width, sizeof(long)))) { | |
| 1502 | 1691 | goto error; |
| 1692 | + } | |
| 1503 | 1693 | outcmptfmts[i].prec = jas_image_cmptprec(outimage, j); |
| 1504 | 1694 | outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j); |
| 1505 | 1695 | outcmptfmts[i].width = width; |
| @@ -1510,15 +1700,17 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 4 unmodified lines | ||
| 1510 | 1700 | for (unsigned j = 0; j < numinclrchans; ++j) { |
| 1511 | 1701 | k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j)); |
| 1512 | 1702 | if (jas_image_readcmpt2(inimage, k, 0, i, width, 1, |
| 1513 | − incmptfmts[j].buf)) | |
| 1703 | + incmptfmts[j].buf)) { | |
| 1514 | 1704 | goto error; |
| 1705 | + } | |
| 1515 | 1706 | } |
| 1516 | 1707 | jas_cmxform_apply(xform, &inpixmap, &outpixmap); |
| 1517 | 1708 | for (unsigned j = 0; j < numoutclrchans; ++j) { |
| 1518 | 1709 | k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j)); |
| 1519 | 1710 | if (jas_image_writecmpt2(outimage, k, 0, i, width, 1, |
| 1520 | − outcmptfmts[j].buf)) | |
| 1711 | + outcmptfmts[j].buf)) { | |
| 1521 | 1712 | goto error; |
| 1713 | + } | |
| 1522 | 1714 | } |
| 1523 | 1715 | } |
| 1524 | 1716 | |
| @@ -1533,13 +1725,22 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 8 unmodified lines | ||
| 1533 | 1725 | jas_cmxform_destroy(xform); |
| 1534 | 1726 | jas_image_destroy(inimage); |
| 1535 | 1727 | |
| 1728 | +#if 0 | |
| 1729 | + jas_eprintf("INIMAGE\n"); | |
| 1730 | + jas_image_dump(inimage, stderr); | |
| 1731 | + jas_eprintf("OUTIMAGE\n"); | |
| 1732 | + jas_image_dump(outimage, stderr); | |
| 1733 | +#endif | |
| 1536 | 1734 | return outimage; |
| 1537 | 1735 | error: |
| 1538 | − if (xform) | |
| 1736 | + if (xform) { | |
| 1539 | 1737 | jas_cmxform_destroy(xform); |
| 1540 | − if (inimage) | |
| 1738 | + } | |
| 1739 | + if (inimage) { | |
| 1541 | 1740 | jas_image_destroy(inimage); |
| 1542 | − if (outimage) | |
| 1741 | + } | |
| 1742 | + if (outimage) { | |
| 1543 | 1743 | jas_image_destroy(outimage); |
| 1744 | + } | |
| 1544 | 1745 | return 0; |
| 1545 | 1746 | } |
| @@ -63,45 +63,971 @@ · 62 unmodified lines | ||
| 63 | 63 | * Includes. |
| 64 | 64 | \******************************************************************************/ |
| 65 | 65 | |
| 66 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 67 | + | |
| 66 | 68 | #include "jasper/jas_init.h" |
| 67 | 69 | #include "jasper/jas_image.h" |
| 70 | +#include "jasper/jas_malloc.h" | |
| 71 | +#include "jasper/jas_debug.h" | |
| 72 | +#include "jasper/jas_string.h" | |
| 73 | +#include "jasper/jas_thread.h" | |
| 74 | + | |
| 75 | +/******************************************************************************\ | |
| 76 | +* Types. | |
| 77 | +\******************************************************************************/ | |
| 78 | + | |
| 79 | +/*! | |
| 80 | +@brief Entry in image format table. | |
| 81 | +*/ | |
| 82 | +typedef struct { | |
| 83 | + | |
| 84 | + /*! | |
| 85 | + A unique name identifying the format. | |
| 86 | + */ | |
| 87 | + const char *name; | |
| 88 | + | |
| 89 | + /*! | |
| 90 | + A short description of the format. | |
| 91 | + */ | |
| 92 | + const char *desc; | |
| 93 | + | |
| 94 | + /*! | |
| 95 | + A whitespace delimited list of file extensions associated with the format. | |
| 96 | + */ | |
| 97 | + const char *exts; | |
| 98 | + | |
| 99 | + /*! | |
| 100 | + The operations for the format (e.g., encode, decode, and validate). | |
| 101 | + */ | |
| 102 | + const jas_image_fmtops_t ops; | |
| 103 | + | |
| 104 | + /*! | |
| 105 | + A boolean flag indicating if the format is enabled. | |
| 106 | + */ | |
| 107 | + int enabled; | |
| 108 | + | |
| 109 | +} jas_image_fmt_t; | |
| 110 | + | |
| 111 | +/* | |
| 112 | +User-configurable settings for library. | |
| 113 | +This is for internal library use only. | |
| 114 | +*/ | |
| 115 | +typedef struct { | |
| 116 | + | |
| 117 | + /* | |
| 118 | + A boolean flag indicating if the library has been configured | |
| 119 | + by invoking the jas_conf_clear function. | |
| 120 | + */ | |
| 121 | + bool initialized; | |
| 122 | + | |
| 123 | + /* | |
| 124 | + A boolean flag indicating if the library is potentially going to be | |
| 125 | + used by more than one thread. | |
| 126 | + */ | |
| 127 | + bool multithread; | |
| 128 | + | |
| 129 | + /* | |
| 130 | + The allocator to be used by the library. | |
| 131 | + */ | |
| 132 | + jas_allocator_t *allocator; | |
| 133 | + | |
| 134 | + /* | |
| 135 | + A boolean flag indicating if the allocator should be accessed through | |
| 136 | + a wrapper that allows memory usage to be tracked and limited. | |
| 137 | + */ | |
| 138 | + bool enable_allocator_wrapper; | |
| 139 | + | |
| 140 | + /* | |
| 141 | + The maximum amount of memory to be used by the library if the | |
| 142 | + allocator wrapper is used. | |
| 143 | + */ | |
| 144 | + size_t max_mem; | |
| 145 | + bool max_mem_valid; | |
| 146 | + | |
| 147 | + /* | |
| 148 | + The image format information to be used to populate the image format | |
| 149 | + table in newly created contexts. | |
| 150 | + */ | |
| 151 | + const jas_image_fmt_t *image_formats; | |
| 152 | + size_t num_image_formats; | |
| 153 | + | |
| 154 | + /* | |
| 155 | + The maximum number of samples allowable in an image to be decoded to be | |
| 156 | + used in newly created contexts. | |
| 157 | + */ | |
| 158 | + size_t dec_default_max_samples; | |
| 159 | + | |
| 160 | + /* | |
| 161 | + The level of debugging checks/output enabled by the library for newly | |
| 162 | + created contexts. | |
| 163 | + A larger value corresponds to a greater level of debugging checks/output. | |
| 164 | + */ | |
| 165 | + int debug_level; | |
| 166 | + | |
| 167 | + /* | |
| 168 | + The function used to output error/warning/informational messages | |
| 169 | + for newly created contexts. | |
| 170 | + */ | |
| 171 | + int (*vlogmsgf)(jas_logtype_t type, const char *format, va_list ap); | |
| 172 | + | |
| 173 | +} jas_conf_t; | |
| 174 | + | |
| 175 | +typedef struct { | |
| 176 | + | |
| 177 | + /* A copy of the run-time library configuration settings. */ | |
| 178 | + jas_conf_t conf; | |
| 179 | + | |
| 180 | + /* A flag indicating if the library is initialized.*/ | |
| 181 | + bool initialized; | |
| 182 | + | |
| 183 | + /* The number of threads currently using the library. */ | |
| 184 | + size_t num_active_threads; | |
| 185 | + | |
| 186 | + /* | |
| 187 | + If JAS_THREADS is not defined, this pointer is used for both the | |
| 188 | + global context and default context. | |
| 189 | + Otherwise, this pointer is only used for the global context. | |
| 190 | + */ | |
| 191 | + jas_ctx_t *ctx; | |
| 192 | + | |
| 193 | + /* | |
| 194 | + The storage for the global context. | |
| 195 | + */ | |
| 196 | + jas_ctx_t ctx_buf; | |
| 197 | + | |
| 198 | +#if defined(JAS_THREADS) | |
| 199 | + | |
| 200 | + /* A mutex to protect this data structure. */ | |
| 201 | + jas_mutex_t lock; | |
| 202 | + | |
| 203 | + /* The TSS for the current context pointer. */ | |
| 204 | + jas_tss_t cur_ctx_tss; | |
| 205 | + | |
| 206 | + /* The TSS for the default context pointer. */ | |
| 207 | + jas_tss_t default_ctx_tss; | |
| 208 | + | |
| 209 | +#endif | |
| 210 | + | |
| 211 | +} jas_global_t; | |
| 212 | + | |
| 213 | +/******************************************************************************\ | |
| 214 | +* Function prototypes. | |
| 215 | +\******************************************************************************/ | |
| 216 | + | |
| 217 | +//static jas_conf_t *jas_get_conf_ptr(void); | |
| 218 | +void jas_ctx_init(jas_ctx_t *ctx); | |
| 219 | +static int jas_init_codecs(jas_ctx_t *ctx); | |
| 220 | +void jas_ctx_cleanup(jas_ctx_t *ctx); | |
| 221 | +void jas_set_ctx(jas_ctx_t *ctx); | |
| 222 | +void jas_set_default_ctx(jas_ctx_t *ctx); | |
| 223 | +jas_ctx_t *jas_ctx_create(void); | |
| 224 | +void jas_ctx_destroy(jas_ctx_t *ctx); | |
| 225 | +jas_ctx_t *jas_get_ctx_internal(void); | |
| 226 | +jas_ctx_t *jas_get_default_ctx(void); | |
| 227 | + | |
| 228 | +/******************************************************************************\ | |
| 229 | +* Codec Table. | |
| 230 | +\******************************************************************************/ | |
| 231 | + | |
| 232 | +static const jas_image_fmt_t jas_image_fmts[] = { | |
| 233 | + | |
| 234 | +#if defined(JAS_INCLUDE_PNM_CODEC) | |
| 235 | + { | |
| 236 | + .name = "pnm", | |
| 237 | + .desc = "Portable Graymap/Pixmap (PNM)", | |
| 238 | + .exts = "pnm pbm pgm ppm", | |
| 239 | + .ops = { | |
| 240 | + .decode = pnm_decode, | |
| 241 | + .encode = pnm_encode, | |
| 242 | + .validate = pnm_validate | |
| 243 | + }, | |
| 244 | + .enabled = JAS_ENABLE_PNM_CODEC, | |
| 245 | + }, | |
| 246 | +#endif | |
| 247 | + | |
| 248 | +#if defined(JAS_INCLUDE_BMP_CODEC) | |
| 249 | + { | |
| 250 | + .name = "bmp", | |
| 251 | + .desc = "Microsoft Bitmap (BMP)", | |
| 252 | + .exts = "bmp", | |
| 253 | + .ops = { | |
| 254 | + .decode = bmp_decode, | |
| 255 | + .encode = bmp_encode, | |
| 256 | + .validate = bmp_validate | |
| 257 | + }, | |
| 258 | + .enabled = JAS_ENABLE_BMP_CODEC, | |
| 259 | + }, | |
| 260 | +#endif | |
| 261 | + | |
| 262 | +#if defined(JAS_INCLUDE_RAS_CODEC) | |
| 263 | + { | |
| 264 | + .name = "ras", | |
| 265 | + .desc = "Sun Rasterfile (RAS)", | |
| 266 | + .exts = "ras", | |
| 267 | + .ops = { | |
| 268 | + .decode = ras_decode, | |
| 269 | + .encode = ras_encode, | |
| 270 | + .validate = ras_validate | |
| 271 | + }, | |
| 272 | + .enabled = JAS_ENABLE_RAS_CODEC, | |
| 273 | + }, | |
| 274 | +#endif | |
| 275 | + | |
| 276 | +#if defined(JAS_INCLUDE_PGX_CODEC) | |
| 277 | + { | |
| 278 | + .name = "pgx", | |
| 279 | + .desc = "JPEG-2000 VM Format (PGX)", | |
| 280 | + .exts = "pgx", | |
| 281 | + .ops = { | |
| 282 | + .decode = pgx_decode, | |
| 283 | + .encode = pgx_encode, | |
| 284 | + .validate = pgx_validate | |
| 285 | + }, | |
| 286 | + .enabled = JAS_ENABLE_PGX_CODEC, | |
| 287 | + }, | |
| 288 | +#endif | |
| 289 | + | |
| 290 | +#if defined(JAS_INCLUDE_JPC_CODEC) || defined(JAS_INCLUDE_JP2_CODEC) | |
| 291 | + { | |
| 292 | + .name = "jpc", | |
| 293 | + .desc = "JPEG-2000 Code Stream Syntax (ISO/IEC 15444-1)", | |
| 294 | + .exts = "jpc", | |
| 295 | + .ops = { | |
| 296 | + .decode = jpc_decode, | |
| 297 | + .encode = jpc_encode, | |
| 298 | + .validate = jpc_validate | |
| 299 | + }, | |
| 300 | + .enabled = JAS_ENABLE_JPC_CODEC, | |
| 301 | + }, | |
| 302 | +#endif | |
| 303 | + | |
| 304 | +#if defined(JAS_INCLUDE_JP2_CODEC) | |
| 305 | + { | |
| 306 | + .name = "jp2", | |
| 307 | + .desc = "JPEG-2000 JP2 File Format Syntax (ISO/IEC 15444-1)", | |
| 308 | + .exts = "jp2", | |
| 309 | + .ops = { | |
| 310 | + .decode = jp2_decode, | |
| 311 | + .encode = jp2_encode, | |
| 312 | + .validate = jp2_validate | |
| 313 | + }, | |
| 314 | + .enabled = JAS_ENABLE_JP2_CODEC, | |
| 315 | + }, | |
| 316 | +#endif | |
| 317 | + | |
| 318 | +#if defined(JAS_INCLUDE_MIF_CODEC) && defined(JAS_ENABLE_MIF_CODEC) | |
| 319 | + { | |
| 320 | + .name = "mif", | |
| 321 | + .desc = "My Image Format (MIF)", | |
| 322 | + .exts = "mif", | |
| 323 | + .ops = { | |
| 324 | + .decode = mif_decode, | |
| 325 | + .encode = mif_encode, | |
| 326 | + .validate = mif_validate | |
| 327 | + }, | |
| 328 | + .enabled = JAS_ENABLE_MIF_CODEC, | |
| 329 | + }, | |
| 330 | +#endif | |
| 331 | + | |
| 332 | +#if defined(JAS_INCLUDE_JPG_CODEC) | |
| 333 | + { | |
| 334 | + .name = "jpg", | |
| 335 | + .desc = "JPEG (ISO/IEC 10918-1)", | |
| 336 | + .exts = "jpg", | |
| 337 | + .ops = { | |
| 338 | + .decode = jpg_decode, | |
| 339 | + .encode = jpg_encode, | |
| 340 | + .validate = jpg_validate | |
| 341 | + }, | |
| 342 | + .enabled = JAS_ENABLE_JPG_CODEC, | |
| 343 | + }, | |
| 344 | +#endif | |
| 345 | + | |
| 346 | +#if defined(JAS_INCLUDE_HEIC_CODEC) | |
| 347 | + { | |
| 348 | + .name = "heic", | |
| 349 | + .desc = "HEIC (ISO/IEC 23008-12)", | |
| 350 | + .exts = "heic heif", | |
| 351 | + .ops = { | |
| 352 | + .decode = jas_heic_decode, | |
| 353 | + .encode = jas_heic_encode, | |
| 354 | + .validate = jas_heic_validate | |
| 355 | + }, | |
| 356 | + .enabled = JAS_ENABLE_HEIC_CODEC, | |
| 357 | + }, | |
| 358 | +#endif | |
| 359 | + | |
| 360 | +}; | |
| 361 | + | |
| 362 | +/******************************************************************************\ | |
| 363 | +* Configuration and Library Data. | |
| 364 | +\******************************************************************************/ | |
| 365 | + | |
| 366 | +/* MUTABLE_SHARED_STATE_TAG: This is mutable shared state. */ | |
| 367 | +/* | |
| 368 | +Various user-configurable settings. | |
| 369 | +*/ | |
| 370 | +jas_conf_t jas_conf = { | |
| 371 | + .initialized = 0, | |
| 372 | +}; | |
| 373 | + | |
| 374 | +/* MUTABLE_SHARED_STATE_TAG: This is mutable shared state. */ | |
| 375 | +jas_global_t jas_global = { | |
| 376 | + .initialized = 0, | |
| 377 | +#if defined(JAS_THREADS) | |
| 378 | + .lock = JAS_MUTEX_INITIALIZER, | |
| 379 | +#endif | |
| 380 | +}; | |
| 381 | + | |
| 382 | +#if defined(JAS_HAVE_THREAD_LOCAL) | |
| 383 | +_Thread_local jas_ctx_t *jas_cur_ctx = 0; | |
| 384 | +_Thread_local jas_ctx_t *jas_default_ctx = 0; | |
| 385 | +#endif | |
| 386 | + | |
| 387 | +/******************************************************************************\ | |
| 388 | +* Library Configuration. | |
| 389 | +\******************************************************************************/ | |
| 390 | + | |
| 391 | +JAS_EXPORT | |
| 392 | +void jas_conf_clear() | |
| 393 | +{ | |
| 394 | + jas_conf.multithread = 0; | |
| 395 | + jas_conf.allocator = 0; | |
| 396 | + jas_conf.enable_allocator_wrapper = 1; | |
| 397 | + jas_conf.max_mem = 0; | |
| 398 | + jas_conf.max_mem_valid = 0; | |
| 399 | + jas_conf.num_image_formats = sizeof(jas_image_fmts) / | |
| 400 | + sizeof(jas_image_fmt_t); | |
| 401 | + jas_conf.image_formats = jas_image_fmts; | |
| 402 | +#if defined(JAS_LEGACY_MODE) | |
| 403 | + jas_conf.dec_default_max_samples = JAS_DEC_DEFAULT_MAX_SAMPLES; | |
| 404 | +#else | |
| 405 | + jas_conf.dec_default_max_samples = 0; | |
| 406 | +#endif | |
| 407 | + jas_conf.debug_level = 0; | |
| 408 | + jas_conf.vlogmsgf = jas_vlogmsgf_stderr; | |
| 409 | + //jas_conf.vlogmsgf = jas_vlogmsgf_discard; | |
| 410 | + jas_conf.initialized = 1; | |
| 411 | +} | |
| 412 | + | |
| 413 | +JAS_EXPORT | |
| 414 | +void jas_conf_set_multithread(int multithread) | |
| 415 | +{ | |
| 416 | + jas_conf.multithread = multithread; | |
| 417 | +} | |
| 418 | + | |
| 419 | +JAS_EXPORT | |
| 420 | +void jas_conf_set_allocator(jas_allocator_t *allocator) | |
| 421 | +{ | |
| 422 | + jas_conf.allocator = allocator; | |
| 423 | +} | |
| 424 | + | |
| 425 | +#ifdef JAS_COMMENT | |
| 426 | +JAS_EXPORT | |
| 427 | +void jas_conf_set_allocator_wrapper(int enabled) | |
| 428 | +{ | |
| 429 | + jas_conf.enable_allocator_wrapper = enabled; | |
| 430 | +} | |
| 431 | +#endif | |
| 432 | + | |
| 433 | +JAS_EXPORT | |
| 434 | +void jas_conf_set_debug_level(int debug_level) | |
| 435 | +{ | |
| 436 | + jas_conf.debug_level = debug_level; | |
| 437 | +} | |
| 438 | + | |
| 439 | +JAS_EXPORT | |
| 440 | +void jas_conf_set_max_mem_usage(size_t max_mem) | |
| 441 | +{ | |
| 442 | + jas_conf.max_mem = max_mem; | |
| 443 | + jas_conf.max_mem_valid = 1; | |
| 444 | +} | |
| 445 | + | |
| 446 | +JAS_EXPORT | |
| 447 | +void jas_conf_set_dec_default_max_samples(size_t n) | |
| 448 | +{ | |
| 449 | + jas_conf.dec_default_max_samples = n; | |
| 450 | +} | |
| 451 | + | |
| 452 | +JAS_EXPORT | |
| 453 | +void jas_conf_set_vlogmsgf(int (*func)(jas_logtype_t type, const char *, | |
| 454 | + va_list)) | |
| 455 | +{ | |
| 456 | + jas_conf.vlogmsgf = func; | |
| 457 | +} | |
| 458 | + | |
| 459 | +/******************************************************************************\ | |
| 460 | +* Library Initialization and Cleanup. | |
| 461 | +\******************************************************************************/ | |
| 462 | + | |
| 463 | +/* | |
| 464 | +Note: I think that it should actually be okay for jas_init_library and | |
| 465 | +jas_cleanup_library to be called from different threads, since: | |
| 466 | +the mutex ensures synchronization and also guarantees that only one | |
| 467 | +thread can use the global context at once. | |
| 468 | +*/ | |
| 469 | +JAS_EXPORT | |
| 470 | +int jas_init_library() | |
| 471 | +{ | |
| 472 | + int ret = 0; | |
| 473 | +#if defined(JAS_THREADS) | |
| 474 | + bool has_lock = false; | |
| 475 | +#endif | |
| 476 | + | |
| 477 | +#if defined(JAS_THREADS) | |
| 478 | + jas_mutex_lock(&jas_global.lock); | |
| 479 | + has_lock = true; | |
| 480 | +#endif | |
| 481 | + | |
| 482 | + /* | |
| 483 | + The following check requires that library configuration be performed on | |
| 484 | + the same thread as library initialization. | |
| 485 | + */ | |
| 486 | + if (!jas_conf.initialized) { | |
| 487 | + jas_eprintf("FATAL ERROR: " | |
| 488 | + "jas_init_library called before JasPer library configured\n"); | |
| 489 | + abort(); | |
| 490 | + } | |
| 491 | + | |
| 492 | + /* | |
| 493 | + The following check requires that library configuration be performed on | |
| 494 | + the same thread as library initialization. | |
| 495 | + */ | |
| 496 | + assert(jas_conf.initialized); | |
| 497 | + assert(!jas_global.initialized); | |
| 498 | + | |
| 499 | + jas_global.conf = jas_conf; | |
| 500 | + assert(jas_global.conf.initialized); | |
| 501 | + | |
| 502 | + size_t max_mem; | |
| 503 | + size_t total_mem_size = jas_get_total_mem_size(); | |
| 504 | + /* | |
| 505 | + NOTE: The values of jas_global.conf.max_mem_valid and max_mem are | |
| 506 | + used later in a deferred warning message. So, their values should be | |
| 507 | + kept for later. | |
| 508 | + */ | |
| 509 | + if (!jas_global.conf.max_mem_valid) { | |
| 510 | + max_mem = total_mem_size / 2; | |
| 511 | + if (!max_mem) { | |
| 512 | + max_mem = JAS_DEFAULT_MAX_MEM_USAGE; | |
| 513 | + } | |
| 514 | + assert(max_mem); | |
| 515 | + jas_global.conf.max_mem = max_mem; | |
| 516 | + } else { | |
| 517 | + max_mem = jas_global.conf.max_mem; | |
| 518 | + } | |
| 519 | + if (max_mem > total_mem_size && total_mem_size > 0) { | |
| 520 | + jas_eprintf("WARNING: JasPer memory limit set to EXCESSIVELY " | |
| 521 | + "LARGE value (i.e., limit exceeds system memory size (%lld > %lld)\n", | |
| 522 | + (long long)max_mem, (long long)total_mem_size); | |
| 523 | + } | |
| 524 | + | |
| 525 | +#if !defined(JAS_THREADS) | |
| 526 | + if (jas_global.conf.multithread) { | |
| 527 | + jas_eprintf("library not built with multithreading support\n"); | |
| 528 | + ret = -1; | |
| 529 | + goto done; | |
| 530 | + } | |
| 531 | +#endif | |
| 532 | + | |
| 533 | +#if defined(JAS_THREADS) && !defined(JAS_HAVE_THREAD_LOCAL) | |
| 534 | + memset(&jas_global.cur_ctx_tss, 0, sizeof(jas_tss_t)); | |
| 535 | + memset(&jas_global.default_ctx_tss, 0, sizeof(jas_tss_t)); | |
| 536 | +#endif | |
| 537 | + | |
| 538 | + /* | |
| 539 | + The initialization of the global context must be performed first. | |
| 540 | + The memory allocator uses information from the context in order to | |
| 541 | + handle log messages. | |
| 542 | + */ | |
| 543 | + jas_ctx_init(&jas_global.ctx_buf); | |
| 544 | + jas_global.ctx = &jas_global.ctx_buf; | |
| 545 | + | |
| 546 | + if (jas_global.conf.enable_allocator_wrapper) { | |
| 547 | + jas_allocator_t *delegate; | |
| 548 | + if (!jas_global.conf.allocator) { | |
| 549 | + jas_std_allocator_init(&jas_std_allocator); | |
| 550 | + delegate = &jas_std_allocator.base; | |
| 551 | + } else { | |
| 552 | + delegate = jas_global.conf.allocator; | |
| 553 | + } | |
| 554 | + jas_basic_allocator_init(&jas_basic_allocator, delegate, | |
| 555 | + jas_global.conf.max_mem); | |
| 556 | + jas_allocator = &jas_basic_allocator.base; | |
| 557 | + } else { | |
| 558 | + if (!jas_global.conf.allocator) { | |
| 559 | + jas_std_allocator_init(&jas_std_allocator); | |
| 560 | + jas_allocator = &jas_std_allocator.base; | |
| 561 | + } else { | |
| 562 | + jas_allocator = jas_global.conf.allocator; | |
| 563 | + } | |
| 564 | + } | |
| 565 | + | |
| 566 | +#if defined(JAS_THREADS) && !defined(JAS_HAVE_THREAD_LOCAL) | |
| 567 | + if ((status = jas_tss_create(&jas_global.cur_ctx_tss, 0))) { | |
| 568 | + jas_eprintf("cannot create thread-specific storage %d\n", status); | |
| 569 | + ret = -1; | |
| 570 | + goto done; | |
| 571 | + } | |
| 572 | + if ((status = jas_tss_create(&jas_global.default_ctx_tss, 0))) { | |
| 573 | + jas_eprintf("cannot create thread-specific storage %d\n", status); | |
| 574 | + ret = -1; | |
| 575 | + goto done; | |
| 576 | + } | |
| 577 | +#endif | |
| 578 | + | |
| 579 | + jas_global.ctx->dec_default_max_samples = | |
| 580 | + jas_global.conf.dec_default_max_samples; | |
| 581 | + jas_global.ctx->debug_level = jas_global.conf.debug_level; | |
| 582 | + jas_global.ctx->image_numfmts = 0; | |
| 583 | + | |
| 584 | + jas_global.initialized = 1; | |
| 585 | + | |
| 586 | +#if defined(JAS_THREADS) | |
| 587 | + jas_mutex_unlock(&jas_global.lock); | |
| 588 | + has_lock = false; | |
| 589 | +#endif | |
| 590 | + | |
| 591 | + JAS_LOGDEBUGF(1, "JasPer library version: %s (%d.%d.%d)\n", JAS_VERSION, | |
| 592 | + JAS_VERSION_MAJOR, JAS_VERSION_MINOR, JAS_VERSION_PATCH); | |
| 593 | + | |
| 594 | + if (!jas_global.conf.max_mem_valid) { | |
| 595 | + jas_eprintf( | |
| 596 | + "warning: The application program did not set the memory limit " | |
| 597 | + "for the JasPer library.\n" | |
| 598 | + ); | |
| 599 | + jas_eprintf( | |
| 600 | + "warning: The JasPer memory limit is being defaulted to a " | |
| 601 | + "value that may be inappropriate for the system. If the default " | |
| 602 | + "is too small, some reasonable encoding/decoding operations will " | |
| 603 | + "fail. If the default is too large, security vulnerabilities " | |
| 604 | + "will result (e.g., decoding a malicious image could exhaust all " | |
| 605 | + "memory and crash the system.\n" | |
| 606 | + ); | |
| 607 | + jas_eprintf("warning: setting JasPer memory limit to %lld bytes\n", | |
| 608 | + (long long)max_mem); | |
| 609 | + } | |
| 610 | + | |
| 611 | + JAS_LOGDEBUGF(1, "JasPer library initialization complete\n"); | |
| 612 | + JAS_LOGDEBUGF(1, "total memory size: %zu\n", jas_get_total_mem_size()); | |
| 613 | + JAS_LOGDEBUGF(1, "JasPer library memory limit: %zu\n", max_mem); | |
| 614 | + | |
| 615 | +#if !defined(JAS_THREADS) || (defined(JAS_THREADS) && !defined(JAS_HAVE_THREAD_LOCAL)) | |
| 616 | +done: | |
| 617 | +#endif | |
| 618 | +#if defined(JAS_THREADS) | |
| 619 | + if (has_lock) { | |
| 620 | + jas_mutex_unlock(&jas_global.lock); | |
| 621 | + } | |
| 622 | +#endif | |
| 623 | + | |
| 624 | + return ret; | |
| 625 | +} | |
| 626 | + | |
| 627 | +JAS_EXPORT | |
| 628 | +int jas_cleanup_library() | |
| 629 | +{ | |
| 630 | + jas_ctx_t *ctx; | |
| 631 | +#if defined(JAS_THREADS) | |
| 632 | + bool has_lock = false; | |
| 633 | +#endif | |
| 634 | + | |
| 635 | +#if defined(JAS_THREADS) | |
| 636 | + jas_mutex_lock(&jas_global.lock); | |
| 637 | + has_lock = true; | |
| 638 | +#endif | |
| 639 | + | |
| 640 | + if (!jas_global.initialized) { | |
| 641 | + jas_eprintf("FATAL ERROR: " | |
| 642 | + "jas_cleanup_library called before JasPer library initialized\n"); | |
| 643 | + abort(); | |
| 644 | + } | |
| 645 | + if (jas_global.num_active_threads) { | |
| 646 | + jas_eprintf("FATAL ERROR: " | |
| 647 | + "jas_cleanup_library called with active JasPer threads\n"); | |
| 648 | + abort(); | |
| 649 | + } | |
| 650 | + | |
| 651 | + assert(jas_global.initialized); | |
| 652 | + assert(!jas_global.num_active_threads); | |
| 653 | + | |
| 654 | + JAS_LOGDEBUGF(10, "jas_cleanup_library invoked\n"); | |
| 655 | + | |
| 656 | + ctx = &jas_global.ctx_buf; | |
| 657 | + jas_ctx_cleanup(ctx); | |
| 658 | + //jas_context_set_debug_level(ctx, 0); | |
| 659 | + | |
| 660 | +#if defined(JAS_THREADS) && !defined(JAS_HAVE_THREAD_LOCAL) | |
| 661 | + jas_tss_delete(jas_global.cur_ctx_tss); | |
| 662 | + jas_tss_delete(jas_global.default_ctx_tss); | |
| 663 | +#endif | |
| 664 | + | |
| 665 | + assert(jas_allocator); | |
| 666 | + jas_allocator_cleanup(jas_allocator); | |
| 667 | + jas_allocator = 0; | |
| 668 | + | |
| 669 | + JAS_LOGDEBUGF(10, "jas_cleanup_library returning\n"); | |
| 670 | + | |
| 671 | + jas_global.initialized = 0; | |
| 672 | + jas_conf.initialized = 0; | |
| 673 | + | |
| 674 | +#if defined(JAS_THREADS) | |
| 675 | + if (has_lock) { | |
| 676 | + jas_mutex_unlock(&jas_global.lock); | |
| 677 | + } | |
| 678 | +#endif | |
| 679 | + | |
| 680 | + return 0; | |
| 681 | +} | |
| 682 | + | |
| 683 | +/******************************************************************************\ | |
| 684 | +* Thread Initialization and Cleanup. | |
| 685 | +\******************************************************************************/ | |
| 686 | + | |
| 687 | +JAS_EXPORT | |
| 688 | +int jas_init_thread() | |
| 689 | +{ | |
| 690 | + int ret = 0; | |
| 691 | + jas_ctx_t *ctx; | |
| 692 | +#if defined(JAS_THREADS) | |
| 693 | + bool has_lock = false; | |
| 694 | +#endif | |
| 695 | + | |
| 696 | + /* | |
| 697 | + The default context must be established as soon as possible. | |
| 698 | + Prior to the default context being initialized the global state in | |
| 699 | + jas_global.conf is used for some settings (e.g., debug level | |
| 700 | + and logging function). | |
| 701 | + Due to the use of this global state, we must hold the lock on | |
| 702 | + this state until the default context is initialized. | |
| 703 | + */ | |
| 704 | +#if defined(JAS_THREADS) | |
| 705 | + jas_mutex_lock(&jas_global.lock); | |
| 706 | + has_lock = true; | |
| 707 | +#endif | |
| 708 | + | |
| 709 | + if (!jas_global.initialized) { | |
| 710 | + jas_eprintf("FATAL ERROR: " | |
| 711 | + "jas_init_thread called before JasPer library initialized\n"); | |
| 712 | + abort(); | |
| 713 | + } | |
| 714 | + assert(jas_global.initialized); | |
| 715 | +#if !defined(JAS_THREADS) | |
| 716 | + assert(jas_global.num_active_threads == 0); | |
| 717 | +#endif | |
| 718 | + assert(jas_get_ctx() == jas_global.ctx); | |
| 719 | + assert(!jas_get_default_ctx() || jas_get_default_ctx() == | |
| 720 | + &jas_global.ctx_buf); | |
| 721 | + | |
| 722 | + if (!(ctx = jas_ctx_create())) { | |
| 723 | + ret = -1; | |
| 724 | + goto done; | |
| 725 | + } | |
| 726 | + jas_set_ctx(ctx); | |
| 727 | + /* As of this point, shared use of jas_global.conf is no longer needed. */ | |
| 728 | + jas_set_default_ctx(ctx); | |
| 729 | + ++jas_global.num_active_threads; | |
| 730 | + | |
| 731 | +#if defined(JAS_THREADS) | |
| 732 | + jas_mutex_unlock(&jas_global.lock); | |
| 733 | + has_lock = false; | |
| 734 | +#endif | |
| 735 | + | |
| 736 | +done: | |
| 737 | +#if defined(JAS_THREADS) | |
| 738 | + if (has_lock) { | |
| 739 | + jas_mutex_unlock(&jas_global.lock); | |
| 740 | + } | |
| 741 | +#endif | |
| 742 | + if (ret && ctx) { | |
| 743 | + jas_ctx_cleanup(ctx); | |
| 744 | + } | |
| 745 | + return ret; | |
| 746 | +} | |
| 747 | + | |
| 748 | +JAS_EXPORT | |
| 749 | +int jas_cleanup_thread() | |
| 750 | +{ | |
| 751 | + jas_ctx_t *ctx; | |
| 752 | +#if defined(JAS_THREADS) | |
| 753 | + bool has_lock = false; | |
| 754 | +#endif | |
| 755 | + | |
| 756 | +#if defined(JAS_THREADS) | |
| 757 | + jas_mutex_lock(&jas_global.lock); | |
| 758 | + has_lock = true; | |
| 759 | +#endif | |
| 760 | + | |
| 761 | + if (!jas_get_default_ctx()) { | |
| 762 | + jas_eprintf("FATAL ERROR: " | |
| 763 | + "jas_cleanup_thread called before JasPer thread initialized\n"); | |
| 764 | + abort(); | |
| 765 | + } | |
| 766 | + | |
| 767 | + assert(jas_get_default_ctx()); | |
| 768 | + assert(jas_get_ctx()); | |
| 769 | + | |
| 770 | + /* Ensure that the library user is not doing something insane. */ | |
| 771 | + assert(jas_get_ctx() == jas_get_default_ctx()); | |
| 772 | + | |
| 773 | + ctx = jas_get_default_ctx(); | |
| 774 | + jas_set_default_ctx(0); | |
| 775 | + jas_set_ctx(0); | |
| 776 | + /* | |
| 777 | + As soon as we clear the current context, the global shared state | |
| 778 | + jas_conf.conf is used for various settings (e.g., debug level and | |
| 779 | + logging function). | |
| 780 | + */ | |
| 781 | + | |
| 782 | + jas_ctx_destroy(ctx); | |
| 783 | + --jas_global.num_active_threads; | |
| 784 | + | |
| 785 | +#if defined(JAS_THREADS) | |
| 786 | + if (has_lock) { | |
| 787 | + jas_mutex_unlock(&jas_global.lock); | |
| 788 | + } | |
| 789 | +#endif | |
| 790 | + | |
| 791 | + return 0; | |
| 792 | +} | |
| 793 | + | |
| 794 | +/******************************************************************************\ | |
| 795 | +* Legacy Library Initialization and Cleanup. | |
| 796 | +\******************************************************************************/ | |
| 797 | + | |
| 798 | +JAS_EXPORT | |
| 799 | +int jas_init() | |
| 800 | +{ | |
| 801 | + jas_deprecated("use of jas_init is deprecated\n"); | |
| 802 | + jas_conf_clear(); | |
| 803 | + if (jas_init_library()) { | |
| 804 | + return -1; | |
| 805 | + } | |
| 806 | + if (jas_init_thread()) { | |
| 807 | + jas_cleanup_library(); | |
| 808 | + return -1; | |
| 809 | + } | |
| 810 | + return 0; | |
| 811 | +} | |
| 812 | + | |
| 813 | +JAS_EXPORT | |
| 814 | +void jas_cleanup() | |
| 815 | +{ | |
| 816 | + jas_deprecated("use of jas_cleanup is deprecated\n"); | |
| 817 | + if (jas_cleanup_thread()) { | |
| 818 | + jas_eprintf("jas_cleanup_thread failed\n"); | |
| 819 | + } | |
| 820 | + if (jas_cleanup_library()) { | |
| 821 | + jas_eprintf("jas_cleanup_library failed\n"); | |
| 822 | + } | |
| 823 | +} | |
| 68 | 824 | |
| 69 | 825 | /******************************************************************************\ |
| 70 | 826 | * Code. |
| 71 | 827 | \******************************************************************************/ |
| 72 | 828 | |
| 73 | 829 | /* Initialize the image format table. */ |
| 74 | −JAS_DLLEXPORT | |
| 75 | −int jas_init(void) | |
| 830 | +static int jas_init_codecs(jas_ctx_t *ctx) | |
| 76 | 831 | { |
| 77 | − jas_image_fmtops_t fmtops; | |
| 78 | − int fmtid = 0; | |
| 832 | + int ret = 0; | |
| 833 | + int i; | |
| 834 | + const jas_image_fmt_t *fmt; | |
| 835 | + for (fmt = jas_global.conf.image_formats, i = 0; | |
| 836 | + i < jas_global.conf.num_image_formats; ++fmt, ++i) { | |
| 837 | + JAS_LOGDEBUGF(10, "adding image format %s %s\n", fmt->name, fmt->exts); | |
| 838 | + if (jas_image_addfmt_internal(ctx->image_fmtinfos, &ctx->image_numfmts, | |
| 839 | + i, fmt->name, fmt->exts, fmt->desc, &fmt->ops)) { | |
| 840 | + ret = -1; | |
| 841 | + break; | |
| 842 | + } | |
| 843 | + assert(ctx->image_fmtinfos[i].id == i); | |
| 844 | + ctx->image_fmtinfos[i].enabled = fmt->enabled; | |
| 845 | + } | |
| 846 | + if (ret) { | |
| 847 | + jas_image_clearfmts_internal(ctx->image_fmtinfos, &ctx->image_numfmts); | |
| 848 | + } | |
| 849 | + return ret; | |
| 850 | +} | |
| 79 | 851 | |
| 80 | −#if defined(JAS_INCLUDE_JP2_CODEC) | |
| 81 | − fmtops.decode = jp2_decode; | |
| 82 | − fmtops.validate = jp2_validate; | |
| 83 | − jas_image_addfmt(fmtid++, "jp2", "jp2", | |
| 84 | − "JPEG-2000 JP2 File Format Syntax (ISO/IEC 15444-1)", &fmtops); | |
| 852 | +/******************************************************************************\ | |
| 853 | +* Context management (e.g., creation and destruction). | |
| 854 | +\******************************************************************************/ | |
| 855 | + | |
| 856 | +void jas_ctx_init(jas_ctx_t *ctx) | |
| 857 | +{ | |
| 858 | + ctx->dec_default_max_samples = jas_conf.dec_default_max_samples; | |
| 859 | + ctx->debug_level = jas_conf.debug_level; | |
| 860 | + ctx->vlogmsgf = jas_conf.vlogmsgf; | |
| 861 | + ctx->image_numfmts = 0; | |
| 862 | + memset(ctx->image_fmtinfos, 0, sizeof(ctx->image_fmtinfos)); | |
| 863 | +} | |
| 864 | + | |
| 865 | +jas_ctx_t *jas_ctx_create() | |
| 866 | +{ | |
| 867 | + jas_ctx_t *ctx; | |
| 868 | + if (!(ctx = jas_malloc(sizeof(jas_ctx_t)))) { | |
| 869 | + return 0; | |
| 870 | + } | |
| 871 | + jas_ctx_init(ctx); | |
| 872 | + jas_init_codecs(ctx); | |
| 873 | + return ctx; | |
| 874 | +} | |
| 875 | + | |
| 876 | +JAS_EXPORT | |
| 877 | +jas_context_t jas_context_create() | |
| 878 | +{ | |
| 879 | + return JAS_CAST(jas_context_t, jas_ctx_create()); | |
| 880 | +} | |
| 881 | + | |
| 882 | +void jas_ctx_cleanup(jas_ctx_t *ctx) | |
| 883 | +{ | |
| 884 | + jas_image_clearfmts_internal(ctx->image_fmtinfos, &ctx->image_numfmts); | |
| 885 | +} | |
| 886 | + | |
| 887 | +void jas_ctx_destroy(jas_ctx_t *ctx) | |
| 888 | +{ | |
| 889 | + jas_ctx_cleanup(ctx); | |
| 890 | + jas_free(ctx); | |
| 891 | +} | |
| 892 | + | |
| 893 | +JAS_EXPORT | |
| 894 | +void jas_context_destroy(jas_context_t context) | |
| 895 | +{ | |
| 896 | + jas_ctx_destroy(JAS_CAST(jas_ctx_t *, context)); | |
| 897 | +} | |
| 898 | + | |
| 899 | +jas_ctx_t *jas_get_ctx_internal() | |
| 900 | +{ | |
| 901 | +#if defined(JAS_THREADS) | |
| 902 | + jas_ctx_t *ctx; | |
| 903 | +#if defined(JAS_HAVE_THREAD_LOCAL) | |
| 904 | + ctx = JAS_CAST(jas_ctx_t *, jas_cur_ctx); | |
| 905 | +#else | |
| 906 | + ctx = JAS_CAST(jas_ctx_t *, jas_tss_get(jas_global.cur_ctx_tss)); | |
| 85 | 907 | #endif |
| 908 | + if (!ctx) { | |
| 909 | + ctx = jas_global.ctx; | |
| 910 | + } | |
| 911 | + assert(ctx); | |
| 912 | + return ctx; | |
| 913 | +#else | |
| 914 | + return (jas_global.ctx) ? jas_global.ctx : &jas_global.ctx_buf; | |
| 915 | +#endif | |
| 916 | +} | |
| 86 | 917 | |
| 87 | −#if defined(JAS_INCLUDE_JPC_CODEC) || defined(JAS_INCLUDE_JP2_CODEC) | |
| 88 | − fmtops.decode = jpc_decode; | |
| 89 | − fmtops.validate = jpc_validate; | |
| 90 | − jas_image_addfmt(fmtid, "jpc", "jpc", | |
| 91 | − "JPEG-2000 Code Stream Syntax (ISO/IEC 15444-1)", &fmtops); | |
| 918 | +JAS_EXPORT | |
| 919 | +jas_context_t jas_get_context() | |
| 920 | +{ | |
| 921 | + return JAS_CAST(jas_context_t, jas_get_ctx()); | |
| 922 | +} | |
| 923 | + | |
| 924 | +JAS_EXPORT | |
| 925 | +jas_context_t jas_get_default_context() | |
| 926 | +{ | |
| 927 | + return JAS_CAST(jas_context_t, jas_get_default_ctx()); | |
| 928 | +} | |
| 929 | + | |
| 930 | +JAS_EXPORT | |
| 931 | +void jas_set_context(jas_context_t context) | |
| 932 | +{ | |
| 933 | + jas_set_ctx(JAS_CAST(jas_ctx_t *, context)); | |
| 934 | +} | |
| 935 | + | |
| 936 | +void jas_set_ctx(jas_ctx_t *ctx) | |
| 937 | +{ | |
| 938 | +#if defined(JAS_THREADS) | |
| 939 | +#if defined(JAS_HAVE_THREAD_LOCAL) | |
| 940 | + jas_cur_ctx = ctx; | |
| 941 | +#else | |
| 942 | + if (jas_tss_set(jas_global.cur_ctx_tss, ctx)) { | |
| 943 | + assert(0); | |
| 944 | + abort(); | |
| 945 | + } | |
| 946 | +#endif | |
| 947 | +#else | |
| 948 | + jas_global.ctx = JAS_CAST(jas_ctx_t *, ctx); | |
| 92 | 949 | #endif |
| 950 | +} | |
| 93 | 951 | |
| 94 | − /* We must not register the JasPer library exit handler until after | |
| 95 | − at least one memory allocation is performed. This is desirable | |
| 96 | − as it ensures that the JasPer exit handler is called before the | |
| 97 | − debug memory allocator exit handler. */ | |
| 98 | − atexit(jas_cleanup); | |
| 952 | +jas_ctx_t *jas_get_default_ctx() | |
| 953 | +{ | |
| 954 | + jas_ctx_t *ctx; | |
| 99 | 955 | |
| 100 | − return 0; | |
| 956 | +#if defined(JAS_THREADS) | |
| 957 | +# if defined(JAS_HAVE_THREAD_LOCAL) | |
| 958 | + ctx = jas_default_ctx; | |
| 959 | +# else | |
| 960 | + ctx = JAS_CAST(jas_ctx_t *, jas_tss_get(jas_global.default_ctx_tss)); | |
| 961 | +# endif | |
| 962 | + if (!ctx) { | |
| 963 | + ctx = jas_global.ctx; | |
| 964 | + } | |
| 965 | +#else | |
| 966 | + ctx = (jas_global.ctx) ? jas_global.ctx : &jas_global.ctx_buf; | |
| 967 | +#endif | |
| 968 | + //JAS_LOGDEBUGF(100, "jas_get_ctx() returning %p", JAS_CAST(void *, ctx)); | |
| 969 | + | |
| 970 | + return ctx; | |
| 971 | +} | |
| 972 | + | |
| 973 | +void jas_set_default_ctx(jas_ctx_t *ctx) | |
| 974 | +{ | |
| 975 | +#if defined(JAS_THREADS) | |
| 976 | +#if defined(JAS_HAVE_THREAD_LOCAL) | |
| 977 | + jas_default_ctx = ctx; | |
| 978 | +#else | |
| 979 | + if (jas_tss_set(jas_global.default_ctx_tss, ctx)) { | |
| 980 | + assert(0); | |
| 981 | + abort(); | |
| 982 | + } | |
| 983 | +#endif | |
| 984 | +#else | |
| 985 | + jas_global.ctx = JAS_CAST(jas_ctx_t *, ctx); | |
| 986 | +#endif | |
| 987 | +} | |
| 988 | + | |
| 989 | +/******************************************************************************\ | |
| 990 | +* Context state management. | |
| 991 | +\******************************************************************************/ | |
| 992 | + | |
| 993 | +JAS_EXPORT | |
| 994 | +void jas_set_debug_level(int debug_level) | |
| 995 | +{ | |
| 996 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 997 | + ctx->debug_level = debug_level; | |
| 998 | +} | |
| 999 | + | |
| 1000 | +JAS_EXPORT | |
| 1001 | +int jas_get_debug_level_internal(void) | |
| 1002 | +{ | |
| 1003 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 1004 | + return ctx->debug_level; | |
| 1005 | +} | |
| 1006 | + | |
| 1007 | +JAS_EXPORT | |
| 1008 | +void jas_set_dec_default_max_samples(size_t max_samples) | |
| 1009 | +{ | |
| 1010 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 1011 | + ctx->dec_default_max_samples = max_samples; | |
| 1012 | +} | |
| 1013 | + | |
| 1014 | +JAS_EXPORT | |
| 1015 | +size_t jas_get_dec_default_max_samples_internal(void) | |
| 1016 | +{ | |
| 1017 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 1018 | + return ctx->dec_default_max_samples; | |
| 1019 | +} | |
| 1020 | + | |
| 1021 | +JAS_EXPORT | |
| 1022 | +void jas_set_vlogmsgf(int (*func)(jas_logtype_t, const char *, va_list)) | |
| 1023 | +{ | |
| 1024 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 1025 | + ctx->vlogmsgf = func; | |
| 101 | 1026 | } |
| 102 | 1027 | |
| 103 | −JAS_DLLEXPORT | |
| 104 | −void jas_cleanup(void) | |
| 1028 | +JAS_EXPORT | |
| 1029 | +jas_vlogmsgf_t *jas_get_vlogmsgf_internal(void) | |
| 105 | 1030 | { |
| 106 | − jas_image_clearfmts(); | |
| 1031 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 1032 | + return ctx->vlogmsgf; | |
| 107 | 1033 | } |
| @@ -0,0 +1,651 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2002 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/* | |
| 65 | + * Memory Allocator | |
| 66 | + * | |
| 67 | + * $Id$ | |
| 68 | + */ | |
| 69 | + | |
| 70 | +/******************************************************************************\ | |
| 71 | +* Includes. | |
| 72 | +\******************************************************************************/ | |
| 73 | + | |
| 74 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 75 | + | |
| 76 | +#include "jasper/jas_types.h" | |
| 77 | +#include "jasper/jas_malloc.h" | |
| 78 | +#include "jasper/jas_debug.h" | |
| 79 | +#include "jasper/jas_math.h" | |
| 80 | + | |
| 81 | +#if defined(__linux__) | |
| 82 | +# include <sys/sysinfo.h> | |
| 83 | +#elif defined(__APPLE__) | |
| 84 | +# include <sys/types.h> | |
| 85 | +# include <sys/sysctl.h> | |
| 86 | +#elif defined(__unix__) && (!defined(__linux__) && !defined(__APPLE__)) | |
| 87 | +# include <unistd.h> | |
| 88 | +#elif defined(_WIN32) | |
| 89 | +# include <windows.h> | |
| 90 | +# include <sysinfoapi.h> | |
| 91 | +#endif | |
| 92 | + | |
| 93 | +/******************************************************************************\ | |
| 94 | +* Data. | |
| 95 | +\******************************************************************************/ | |
| 96 | + | |
| 97 | +/* MUTABLE_SHARED_STATE_TAG: This is mutable shared state. */ | |
| 98 | +/* The memory allocator object to be used for all memory allocation. */ | |
| 99 | +jas_allocator_t *jas_allocator = 0; | |
| 100 | + | |
| 101 | +/* MUTABLE_SHARED_STATE_TAG: This is mutable shared state. */ | |
| 102 | +jas_std_allocator_t jas_std_allocator = { | |
| 103 | + .base = { | |
| 104 | + .cleanup = 0, | |
| 105 | + .alloc = 0, | |
| 106 | + .free = 0, | |
| 107 | + .realloc = 0, | |
| 108 | + }, | |
| 109 | +}; | |
| 110 | + | |
| 111 | +/* MUTABLE_SHARED_STATE_TAG: This is mutable shared state. */ | |
| 112 | +jas_basic_allocator_t jas_basic_allocator = { | |
| 113 | + .base = { | |
| 114 | + .cleanup = 0, | |
| 115 | + .alloc = 0, | |
| 116 | + .free = 0, | |
| 117 | + .realloc = 0, | |
| 118 | + }, | |
| 119 | + .delegate = 0, | |
| 120 | + .mem = 0, | |
| 121 | + .max_mem = 0, | |
| 122 | +}; | |
| 123 | + | |
| 124 | +/******************************************************************************\ | |
| 125 | +* Basic memory allocation and deallocation primitives. | |
| 126 | +\******************************************************************************/ | |
| 127 | + | |
| 128 | +JAS_EXPORT | |
| 129 | +void *jas_malloc(size_t size) | |
| 130 | +{ | |
| 131 | + assert(jas_allocator); | |
| 132 | + void *result; | |
| 133 | + JAS_LOGDEBUGF(101, "jas_malloc(%zu)\n", size); | |
| 134 | +#if defined(JAS_MALLOC_RETURN_NULL_PTR_FOR_ZERO_SIZE) | |
| 135 | + result = size ? (jas_allocator->alloc)(jas_allocator, size) : 0; | |
| 136 | +#else | |
| 137 | + result = (jas_allocator->alloc)(jas_allocator, size ? size : 1); | |
| 138 | +#endif | |
| 139 | + JAS_LOGDEBUGF(100, "jas_malloc(%zu) -> %p\n", size, result); | |
| 140 | + return result; | |
| 141 | +} | |
| 142 | + | |
| 143 | +JAS_EXPORT | |
| 144 | +void *jas_realloc(void *ptr, size_t size) | |
| 145 | +{ | |
| 146 | + assert(jas_allocator); | |
| 147 | + void *result; | |
| 148 | + JAS_LOGDEBUGF(101, "jas_realloc(%p, %zu)\n", ptr, size); | |
| 149 | + if (!size) { | |
| 150 | + jas_logwarnf("warning: zero size reallocations are unwise " | |
| 151 | + "(and have undefined behavior as of C23)\n"); | |
| 152 | + } | |
| 153 | + if (!ptr) { | |
| 154 | + if (size) { | |
| 155 | + /* Handle a new allocation of nonzero size. */ | |
| 156 | + result = (jas_allocator->alloc)(jas_allocator, size); | |
| 157 | + JAS_LOGDEBUGF(101, "jas_realloc: alloc(%p, %zu) -> %p\n", | |
| 158 | + jas_allocator, size, result); | |
| 159 | + } else { | |
| 160 | + /* Handle a new allocation of zero size. */ | |
| 161 | +#if defined(JAS_MALLOC_RETURN_NULL_PTR_FOR_ZERO_SIZE) | |
| 162 | + result = 0; | |
| 163 | + JAS_LOGDEBUGF(101, "jas_realloc: no-op -> %p\n", result); | |
| 164 | +#else | |
| 165 | + result = (jas_allocator->alloc)(jas_allocator, 1); | |
| 166 | + JAS_LOGDEBUGF(101, "jas_realloc: alloc(%p, %p, %zu) -> %p\n", | |
| 167 | + jas_allocator, ptr, size, result); | |
| 168 | +#endif | |
| 169 | + } | |
| 170 | + } else { | |
| 171 | + result = (jas_allocator->realloc)(jas_allocator, ptr, size); | |
| 172 | + JAS_LOGDEBUGF(100, "jas_realloc: realloc(%p, %p, %zu) -> %p\n", | |
| 173 | + jas_allocator, ptr, size, result); | |
| 174 | + } | |
| 175 | + return result; | |
| 176 | +} | |
| 177 | + | |
| 178 | +JAS_EXPORT | |
| 179 | +void jas_free(void *ptr) | |
| 180 | +{ | |
| 181 | + assert(jas_allocator); | |
| 182 | + JAS_LOGDEBUGF(100, "jas_free(%p)\n", ptr); | |
| 183 | + (jas_allocator->free)(jas_allocator, ptr); | |
| 184 | +} | |
| 185 | + | |
| 186 | +/******************************************************************************\ | |
| 187 | +* Additional memory allocation and deallocation primitives | |
| 188 | +* (mainly for overflow checking). | |
| 189 | +\******************************************************************************/ | |
| 190 | + | |
| 191 | +void *jas_calloc(size_t num_elements, size_t element_size) | |
| 192 | +{ | |
| 193 | + void *ptr; | |
| 194 | + size_t size; | |
| 195 | + if (!jas_safe_size_mul(num_elements, element_size, &size)) { | |
| 196 | + return 0; | |
| 197 | + } | |
| 198 | + if (!(ptr = jas_malloc(size))) { | |
| 199 | + return 0; | |
| 200 | + } | |
| 201 | + memset(ptr, 0, size); | |
| 202 | + return ptr; | |
| 203 | +} | |
| 204 | + | |
| 205 | +void *jas_alloc2(size_t num_elements, size_t element_size) | |
| 206 | +{ | |
| 207 | + size_t size; | |
| 208 | + if (!jas_safe_size_mul(num_elements, element_size, &size)) { | |
| 209 | + return 0; | |
| 210 | + } | |
| 211 | + return jas_malloc(size); | |
| 212 | +} | |
| 213 | + | |
| 214 | +void *jas_alloc3(size_t num_arrays, size_t array_size, size_t element_size) | |
| 215 | +{ | |
| 216 | + size_t size; | |
| 217 | + if (!jas_safe_size_mul(array_size, element_size, &size) || | |
| 218 | + !jas_safe_size_mul(size, num_arrays, &size)) { | |
| 219 | + return 0; | |
| 220 | + } | |
| 221 | + return jas_malloc(size); | |
| 222 | +} | |
| 223 | + | |
| 224 | +void *jas_realloc2(void *ptr, size_t num_elements, size_t element_size) | |
| 225 | +{ | |
| 226 | + size_t size; | |
| 227 | + if (!jas_safe_size_mul(num_elements, element_size, &size)) { | |
| 228 | + return 0; | |
| 229 | + } | |
| 230 | + return jas_realloc(ptr, size); | |
| 231 | +} | |
| 232 | + | |
| 233 | +/******************************************************************************\ | |
| 234 | +\******************************************************************************/ | |
| 235 | + | |
| 236 | +JAS_EXPORT | |
| 237 | +void jas_allocator_cleanup(jas_allocator_t *allocator) | |
| 238 | +{ | |
| 239 | + if (allocator->cleanup) { | |
| 240 | + (allocator->cleanup)(allocator); | |
| 241 | + } | |
| 242 | +} | |
| 243 | + | |
| 244 | +/******************************************************************************\ | |
| 245 | +\******************************************************************************/ | |
| 246 | + | |
| 247 | +JAS_EXPORT | |
| 248 | +void *jas_std_alloc(jas_allocator_t *allocator, size_t size); | |
| 249 | +JAS_EXPORT | |
| 250 | +void *jas_std_realloc(jas_allocator_t *allocator, void *ptr, size_t size); | |
| 251 | +JAS_EXPORT | |
| 252 | +void jas_std_free(jas_allocator_t *allocator, void *ptr); | |
| 253 | + | |
| 254 | +JAS_EXPORT | |
| 255 | +void jas_std_allocator_init(jas_std_allocator_t *allocator) | |
| 256 | +{ | |
| 257 | + JAS_CAST(void, allocator); | |
| 258 | + allocator->base.cleanup = 0; | |
| 259 | + allocator->base.alloc = jas_std_alloc; | |
| 260 | + allocator->base.free = jas_std_free; | |
| 261 | + allocator->base.realloc = jas_std_realloc; | |
| 262 | +} | |
| 263 | + | |
| 264 | +JAS_EXPORT | |
| 265 | +void *jas_std_alloc(jas_allocator_t *allocator, size_t size) | |
| 266 | +{ | |
| 267 | + JAS_UNUSED(allocator); | |
| 268 | + JAS_LOGDEBUGF(111, "jas_std_alloc(%zu)\n", size); | |
| 269 | + void* result = malloc(size); | |
| 270 | + JAS_LOGDEBUGF(110, "jas_std_alloc(%zu) -> %p\n", size, result); | |
| 271 | + return result; | |
| 272 | +} | |
| 273 | + | |
| 274 | +JAS_EXPORT | |
| 275 | +void *jas_std_realloc(jas_allocator_t *allocator, void *ptr, size_t size) | |
| 276 | +{ | |
| 277 | + JAS_UNUSED(allocator); | |
| 278 | + JAS_LOGDEBUGF(111, "jas_std_realloc(%p, %zu)\n", allocator, size); | |
| 279 | + void *result = realloc(ptr, size); | |
| 280 | + JAS_LOGDEBUGF(110, "jas_std_realloc(%zu) -> %p\n", size, result); | |
| 281 | + return result; | |
| 282 | +} | |
| 283 | + | |
| 284 | +JAS_EXPORT | |
| 285 | +void jas_std_free(jas_allocator_t *allocator, void *ptr) | |
| 286 | +{ | |
| 287 | + JAS_UNUSED(allocator); | |
| 288 | + JAS_LOGDEBUGF(111, "jas_std_free(%p, %p)\n", allocator, ptr); | |
| 289 | + free(ptr); | |
| 290 | +} | |
| 291 | + | |
| 292 | +/******************************************************************************\ | |
| 293 | +\******************************************************************************/ | |
| 294 | + | |
| 295 | +JAS_EXPORT | |
| 296 | +void *jas_basic_alloc(jas_allocator_t *allocator, size_t size); | |
| 297 | +JAS_EXPORT | |
| 298 | +void *jas_basic_realloc(jas_allocator_t *allocator, void *ptr, size_t size); | |
| 299 | +JAS_EXPORT | |
| 300 | +void jas_basic_free(jas_allocator_t *allocator, void *ptr); | |
| 301 | +JAS_EXPORT | |
| 302 | +void jas_basic_cleanup(jas_allocator_t *allocator); | |
| 303 | + | |
| 304 | +#define JAS_BMA_MAGIC 0xdeadbeefULL | |
| 305 | + | |
| 306 | +typedef struct { | |
| 307 | + unsigned long long magic; | |
| 308 | + size_t size; | |
| 309 | +} jas_mb_t; | |
| 310 | + | |
| 311 | +#define JAS_MB_ADJUST \ | |
| 312 | + ((sizeof(jas_mb_t) + sizeof(max_align_t) - 1) / sizeof(max_align_t)) | |
| 313 | +#define JAS_MB_SIZE (JAS_MB_ADJUST * sizeof(max_align_t)) | |
| 314 | + | |
| 315 | +static void jas_mb_init(jas_mb_t *mb, size_t size) | |
| 316 | +{ | |
| 317 | + mb->magic = JAS_BMA_MAGIC; | |
| 318 | + mb->size = size; | |
| 319 | +} | |
| 320 | + | |
| 321 | +static void jas_mb_destroy(jas_mb_t *mb) | |
| 322 | +{ | |
| 323 | + mb->magic = 0; | |
| 324 | + mb->size = 0; | |
| 325 | +} | |
| 326 | + | |
| 327 | +static void *jas_mb_get_data(jas_mb_t *mb) | |
| 328 | +{ | |
| 329 | + assert(mb->magic == JAS_BMA_MAGIC); | |
| 330 | + return JAS_CAST(void *, JAS_CAST(max_align_t *, mb) + JAS_MB_ADJUST); | |
| 331 | +} | |
| 332 | + | |
| 333 | +static jas_mb_t *jas_get_mb(void *ptr) | |
| 334 | +{ | |
| 335 | + assert(ptr); | |
| 336 | + jas_mb_t *mb = JAS_CAST(jas_mb_t *, | |
| 337 | + JAS_CAST(max_align_t *, ptr) - JAS_MB_ADJUST); | |
| 338 | + assert(mb->magic == JAS_BMA_MAGIC); | |
| 339 | + /* This is one check that I do not want disabled with NDEBUG. */ | |
| 340 | + if (mb->magic != JAS_BMA_MAGIC) { | |
| 341 | + /* This line of code should never be reached. */ | |
| 342 | + assert(0); | |
| 343 | + abort(); | |
| 344 | + } | |
| 345 | + return mb; | |
| 346 | +} | |
| 347 | + | |
| 348 | +void jas_set_max_mem_usage(size_t max_mem) | |
| 349 | +{ | |
| 350 | + assert(jas_allocator == JAS_CAST(jas_allocator_t*, &jas_basic_allocator)); | |
| 351 | + jas_basic_allocator_t *allocator = JAS_CAST(jas_basic_allocator_t *, | |
| 352 | + jas_allocator); | |
| 353 | +#if defined(JAS_THREADS) | |
| 354 | + jas_mutex_lock(&allocator->mutex); | |
| 355 | +#endif | |
| 356 | + allocator->max_mem = (!max_mem || allocator->mem <= max_mem) ? max_mem : | |
| 357 | + allocator->mem; | |
| 358 | +#if defined(JAS_THREADS) | |
| 359 | + jas_mutex_unlock(&allocator->mutex); | |
| 360 | +#endif | |
| 361 | +} | |
| 362 | + | |
| 363 | +size_t jas_get_mem_usage() | |
| 364 | +{ | |
| 365 | + assert(jas_allocator == JAS_CAST(jas_allocator_t*, &jas_basic_allocator)); | |
| 366 | + jas_basic_allocator_t *allocator = JAS_CAST(jas_basic_allocator_t *, | |
| 367 | + jas_allocator); | |
| 368 | +#if defined(JAS_THREADS) | |
| 369 | + jas_mutex_lock(&allocator->mutex); | |
| 370 | +#endif | |
| 371 | + size_t result = allocator->mem; | |
| 372 | +#if defined(JAS_THREADS) | |
| 373 | + jas_mutex_unlock(&allocator->mutex); | |
| 374 | +#endif | |
| 375 | + return result; | |
| 376 | +} | |
| 377 | + | |
| 378 | +void jas_basic_allocator_init(jas_basic_allocator_t *allocator, | |
| 379 | + jas_allocator_t *delegate, size_t max_mem) | |
| 380 | +{ | |
| 381 | + allocator->base.cleanup = jas_basic_cleanup; | |
| 382 | + allocator->base.alloc = jas_basic_alloc; | |
| 383 | + allocator->base.free = jas_basic_free; | |
| 384 | + allocator->base.realloc = jas_basic_realloc; | |
| 385 | + allocator->delegate = delegate; | |
| 386 | + assert(allocator->base.cleanup != delegate->cleanup); | |
| 387 | + assert(allocator->base.alloc != delegate->alloc); | |
| 388 | + assert(allocator->base.free != delegate->free); | |
| 389 | + assert(allocator->base.realloc != delegate->realloc); | |
| 390 | + allocator->max_mem = max_mem; | |
| 391 | + allocator->mem = 0; | |
| 392 | +#if defined(JAS_THREADS) | |
| 393 | + if (jas_mutex_init(&allocator->mutex)) { | |
| 394 | + /* This line of code should never be reached. */ | |
| 395 | + assert(0); | |
| 396 | + abort(); | |
| 397 | + } | |
| 398 | +#endif | |
| 399 | +} | |
| 400 | + | |
| 401 | +JAS_EXPORT | |
| 402 | +void jas_basic_cleanup(jas_allocator_t *allocator) | |
| 403 | +{ | |
| 404 | + jas_basic_allocator_t *a = JAS_CAST(jas_basic_allocator_t *, | |
| 405 | + allocator); | |
| 406 | + if (a->delegate->cleanup) { | |
| 407 | + (a->delegate->cleanup)(allocator); | |
| 408 | + } | |
| 409 | +#if defined(JAS_THREADS) | |
| 410 | + jas_mutex_cleanup(&a->mutex); | |
| 411 | +#endif | |
| 412 | +} | |
| 413 | + | |
| 414 | +JAS_EXPORT | |
| 415 | +void *jas_basic_alloc(jas_allocator_t *allocator, size_t size) | |
| 416 | +{ | |
| 417 | + void *result; | |
| 418 | + jas_mb_t *mb; | |
| 419 | + size_t ext_size; | |
| 420 | + size_t mem; | |
| 421 | + jas_basic_allocator_t *a = JAS_CAST(jas_basic_allocator_t *, allocator); | |
| 422 | + | |
| 423 | + JAS_LOGDEBUGF(100, "jas_basic_alloc(%p, %zu)\n", allocator, size); | |
| 424 | + JAS_LOGDEBUGF(102, "max_mem=%zu; mem=%zu\n", a->max_mem, a->mem); | |
| 425 | +#if defined(JAS_MALLOC_RETURN_NULL_PTR_FOR_ZERO_SIZE) | |
| 426 | + if (!size) { | |
| 427 | + result = 0; | |
| 428 | + goto done; | |
| 429 | + } | |
| 430 | +#endif | |
| 431 | + if (!jas_safe_size_add(size, JAS_MB_SIZE, &ext_size)) { | |
| 432 | + jas_logerrorf("requested memory size is too large (%zu)\n", size); | |
| 433 | + result = 0; | |
| 434 | + goto done; | |
| 435 | + } | |
| 436 | + | |
| 437 | +#if defined(JAS_THREADS) | |
| 438 | + jas_mutex_lock(&a->mutex); | |
| 439 | + has_lock = true; | |
| 440 | +#endif | |
| 441 | + | |
| 442 | + /* | |
| 443 | + Calculate the amount of memory that would be allocated after the requested | |
| 444 | + allocation is performed, being careful to ensure that this computation | |
| 445 | + does not cause overflow. Then, ensure that the computed value does not | |
| 446 | + exceed the memory usage limit. | |
| 447 | + */ | |
| 448 | + if (!jas_safe_size_add(a->mem, ext_size, &mem) || mem > a->max_mem) { | |
| 449 | + jas_logerrorf("maximum memory limit (%lld) would be exceeded\n", | |
| 450 | + (long long)a->max_mem); | |
| 451 | + result = 0; | |
| 452 | + goto done; | |
| 453 | + } | |
| 454 | + | |
| 455 | + /* | |
| 456 | + Perform the requested allocation using the delegated-to allocator. | |
| 457 | + */ | |
| 458 | + JAS_LOGDEBUGF(100, "jas_basic_alloc: alloc(%p, %zu)\n", a->delegate, | |
| 459 | + ext_size); | |
| 460 | + if ((mb = (a->delegate->alloc)(a->delegate, ext_size))) { | |
| 461 | + jas_mb_init(mb, ext_size); | |
| 462 | + result = jas_mb_get_data(mb); | |
| 463 | + a->mem = mem; | |
| 464 | + } else { | |
| 465 | + result = 0; | |
| 466 | + } | |
| 467 | + | |
| 468 | +done: | |
| 469 | +#if defined(JAS_THREADS) | |
| 470 | + if (has_lock) { | |
| 471 | + jas_mutex_unlock(&a->mutex); | |
| 472 | + } | |
| 473 | +#endif | |
| 474 | + | |
| 475 | + JAS_LOGDEBUGF(99, "jas_basic_alloc(%p, %zu) -> %p (mb=%p)\n", allocator, | |
| 476 | + size, result, mb); | |
| 477 | + JAS_LOGDEBUGF(102, "max_mem=%zu; mem=%zu\n", a->max_mem, a->mem); | |
| 478 | + | |
| 479 | + return result; | |
| 480 | +} | |
| 481 | + | |
| 482 | +JAS_EXPORT | |
| 483 | +void *jas_basic_realloc(jas_allocator_t *allocator, void *ptr, size_t size) | |
| 484 | +{ | |
| 485 | + void *result; | |
| 486 | + jas_mb_t *old_mb; | |
| 487 | + size_t old_ext_size; | |
| 488 | + jas_mb_t *mb; | |
| 489 | + size_t ext_size; | |
| 490 | + size_t mem; | |
| 491 | + jas_basic_allocator_t *a = JAS_CAST(jas_basic_allocator_t *, allocator); | |
| 492 | + | |
| 493 | + JAS_LOGDEBUGF(100, "jas_basic_realloc(%p, %p, %zu)\n", allocator, ptr, | |
| 494 | + size); | |
| 495 | + /* | |
| 496 | + Check for a realloc operation that is equivalent to an alloc operation. | |
| 497 | + */ | |
| 498 | + if (!ptr) { | |
| 499 | + result = jas_basic_alloc(allocator, size); | |
| 500 | + goto done; | |
| 501 | + } | |
| 502 | + /* | |
| 503 | + Check for a realloc operation that is equivalent to a zero-sized | |
| 504 | + allocation/reallocation. | |
| 505 | + */ | |
| 506 | + if (ptr && !size) { | |
| 507 | +#if defined(JAS_MALLOC_RETURN_NULL_PTR_FOR_ZERO_SIZE) | |
| 508 | + jas_basic_free(allocator, ptr); | |
| 509 | + result = 0; | |
| 510 | +#else | |
| 511 | + if ((result = jas_basic_alloc(allocator, 1))) { | |
| 512 | + jas_basic_free(allocator, ptr); | |
| 513 | + } | |
| 514 | +#endif | |
| 515 | + goto done; | |
| 516 | + } | |
| 517 | + | |
| 518 | + if (!jas_safe_size_add(size, JAS_MB_SIZE, &ext_size)) { | |
| 519 | + jas_logerrorf("requested memory size is too large (%zu)\n", size); | |
| 520 | + result = 0; | |
| 521 | + goto done; | |
| 522 | + } | |
| 523 | + | |
| 524 | +#if defined(JAS_THREADS) | |
| 525 | + jas_mutex_lock(&a->mutex); | |
| 526 | + has_lock = true; | |
| 527 | +#endif | |
| 528 | + | |
| 529 | + old_mb = jas_get_mb(ptr); | |
| 530 | + old_ext_size = old_mb->size; | |
| 531 | + JAS_LOGDEBUGF(101, "jas_basic_realloc: old_mb=%p; old_ext_size=%zu\n", | |
| 532 | + old_mb, old_ext_size); | |
| 533 | + /* | |
| 534 | + Skip performing any allocation if the currently-allocated block is | |
| 535 | + sufficiently large to accommodate the allocation request. | |
| 536 | + */ | |
| 537 | + if (ext_size <= old_ext_size) { | |
| 538 | + result = jas_mb_get_data(old_mb); | |
| 539 | + goto done; | |
| 540 | + } | |
| 541 | + | |
| 542 | + if (!jas_safe_size_add(a->mem, ext_size - old_ext_size, &mem) || | |
| 543 | + mem > a->max_mem) { | |
| 544 | + jas_logerrorf("maximum memory limit (%zu) would be exceeded\n", | |
| 545 | + a->max_mem); | |
| 546 | + result = 0; | |
| 547 | + goto done; | |
| 548 | + } | |
| 549 | + | |
| 550 | + JAS_LOGDEBUGF(100, "jas_basic_realloc: realloc(%p, %p, %zu)\n", | |
| 551 | + a->delegate, old_mb, ext_size); | |
| 552 | + jas_mb_destroy(old_mb); | |
| 553 | + if ((mb = (a->delegate->realloc)(a->delegate, old_mb, ext_size))) { | |
| 554 | + jas_mb_init(mb, ext_size); | |
| 555 | + result = jas_mb_get_data(mb); | |
| 556 | + a->mem = mem; | |
| 557 | + } else { | |
| 558 | + jas_mb_init(old_mb, old_ext_size); | |
| 559 | + result = 0; | |
| 560 | + } | |
| 561 | + | |
| 562 | +done: | |
| 563 | +#if defined(JAS_THREADS) | |
| 564 | + if (has_lock) { | |
| 565 | + jas_mutex_unlock(&a->mutex); | |
| 566 | + } | |
| 567 | +#endif | |
| 568 | + | |
| 569 | + JAS_LOGDEBUGF(100, "jas_basic_realloc(%p, %p, %zu) -> %p (%p)\n", allocator, | |
| 570 | + ptr, size, result, mb); | |
| 571 | + JAS_LOGDEBUGF(102, "max_mem=%zu; mem=%zu\n", a->max_mem, a->mem); | |
| 572 | + | |
| 573 | + return result; | |
| 574 | +} | |
| 575 | + | |
| 576 | +JAS_EXPORT | |
| 577 | +void jas_basic_free(jas_allocator_t *allocator, void *ptr) | |
| 578 | +{ | |
| 579 | + jas_mb_t *mb; | |
| 580 | + size_t ext_size; | |
| 581 | + jas_basic_allocator_t *a = JAS_CAST(jas_basic_allocator_t *, allocator); | |
| 582 | + | |
| 583 | + | |
| 584 | + JAS_LOGDEBUGF(100, "jas_basic_free(%p)\n", ptr); | |
| 585 | + if (ptr) { | |
| 586 | +#if defined(JAS_THREADS) | |
| 587 | + jas_mutex_lock(&a->mutex); | |
| 588 | +#endif | |
| 589 | + mb = jas_get_mb(ptr); | |
| 590 | + ext_size = mb->size; | |
| 591 | + JAS_LOGDEBUGF(101, "jas_basic_free(%p, %p) (mb=%p; ext_size=%zu)\n", | |
| 592 | + allocator, ptr, mb, ext_size); | |
| 593 | + if (!jas_safe_size_sub(a->mem, ext_size, &a->mem)) { | |
| 594 | + jas_logerrorf("heap corruption detected (%zu exceeds %zu)\n", | |
| 595 | + ext_size, a->mem); | |
| 596 | + /* This line of code should never be reached. */ | |
| 597 | + assert(0); | |
| 598 | + abort(); | |
| 599 | + } | |
| 600 | + JAS_LOGDEBUGF(100, "jas_basic_free: free(%p, %p)\n", a->delegate, mb); | |
| 601 | + jas_mb_destroy(mb); | |
| 602 | + (a->delegate->free)(a->delegate, mb); | |
| 603 | +#if defined(JAS_THREADS) | |
| 604 | + jas_mutex_unlock(&a->mutex); | |
| 605 | +#endif | |
| 606 | + } | |
| 607 | + JAS_LOGDEBUGF(102, "max_mem=%zu; mem=%zu\n", a->max_mem, a->mem); | |
| 608 | + | |
| 609 | +} | |
| 610 | + | |
| 611 | +/******************************************************************************\ | |
| 612 | +\******************************************************************************/ | |
| 613 | + | |
| 614 | +size_t jas_get_total_mem_size() | |
| 615 | +{ | |
| 616 | +#if defined(__linux__) | |
| 617 | + struct sysinfo buf; | |
| 618 | + if (sysinfo(&buf)) { | |
| 619 | + return 0; | |
| 620 | + } | |
| 621 | + return buf.totalram * buf.mem_unit; | |
| 622 | +#elif defined(__APPLE__) | |
| 623 | + int mib[] = {CTL_HW, HW_MEMSIZE}; | |
| 624 | + uint64_t value = 0; | |
| 625 | + size_t length = sizeof(value); | |
| 626 | + if (sysctl(mib, 2, &value, &length, 0, 0)) { | |
| 627 | + return 0; | |
| 628 | + } | |
| 629 | + return JAS_CAST(size_t, value); | |
| 630 | +#elif defined(__unix__) && (!defined(__linux__) && !defined(__APPLE__)) | |
| 631 | + /* | |
| 632 | + Reference: | |
| 633 | + https://stackoverflow.com/questions/2513505/how-to-get-available-memory-c-g | |
| 634 | + */ | |
| 635 | + long pages = sysconf(_SC_PHYS_PAGES); | |
| 636 | + long page_size = sysconf(_SC_PAGE_SIZE); | |
| 637 | + return pages * page_size; | |
| 638 | +#elif defined(_WIN32) | |
| 639 | + /* | |
| 640 | + Reference: | |
| 641 | + https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getphysicallyinstalledsystemmemory | |
| 642 | + */ | |
| 643 | + ULONGLONG size; | |
| 644 | + if (!GetPhysicallyInstalledSystemMemory(&size)) { | |
| 645 | + return 0; | |
| 646 | + } | |
| 647 | + return 1024 * size; | |
| 648 | +#else | |
| 649 | + return 0; | |
| 650 | +#endif | |
| 651 | +} | |
| @@ -71,9 +71,12 @@ · 70 unmodified lines | ||
| 71 | 71 | * Includes. |
| 72 | 72 | \******************************************************************************/ |
| 73 | 73 | |
| 74 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 75 | + | |
| 74 | 76 | #include "jasper/jas_seq.h" |
| 75 | 77 | #include "jasper/jas_malloc.h" |
| 76 | 78 | #include "jasper/jas_math.h" |
| 79 | +#include "jasper/jas_debug.h" | |
| 77 | 80 | |
| 78 | 81 | /******************************************************************************\ |
| 79 | 82 | * Constructors and destructors. |
| @@ -100,6 +103,7 @@ jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols) · 20 unmodified lines | ||
| 100 | 103 | jas_matind_t i; |
| 101 | 104 | size_t size; |
| 102 | 105 | |
| 106 | + | |
| 103 | 107 | if (numrows < 0 || numcols < 0) { |
| 104 | 108 | return NULL; |
| 105 | 109 | } |
| @@ -132,9 +136,7 @@ jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols) · 26 unmodified lines | ||
| 132 | 136 | sizeof(jas_seqent_t)))) { |
| 133 | 137 | goto error; |
| 134 | 138 | } |
| 135 | − | |
| 136 | − memset(matrix->data_, 0, | |
| 137 | − matrix->datasize_ * sizeof(jas_seqent_t)); | |
| 139 | + memset(matrix->data_, 0, matrix->datasize_ * sizeof(jas_seqent_t)); | |
| 138 | 140 | } |
| 139 | 141 | |
| 140 | 142 | for (i = 0; i < numrows; ++i) { |
| @@ -201,11 +203,11 @@ int jas_seq2d_bindsub(jas_matrix_t *s, jas_matrix_t *s1, jas_matind_t xstart, · 60 unmodified lines | ||
| 201 | 203 | jas_matind_t ystart, jas_matind_t xend, jas_matind_t yend) |
| 202 | 204 | { |
| 203 | 205 | if (xstart < s1->xstart_ || ystart < s1->ystart_ || |
| 204 | − xend > s1->xend_ || yend > s1->yend_) | |
| 206 | + xend > s1->xend_ || yend > s1->yend_) { | |
| 205 | 207 | return -1; |
| 206 | − | |
| 207 | − return jas_matrix_bindsub(s, s1, ystart - s1->ystart_, xstart - s1->xstart_, | |
| 208 | − yend - s1->ystart_ - 1, xend - s1->xstart_ - 1); | |
| 208 | + } | |
| 209 | + return jas_matrix_bindsub(s, s1, ystart - s1->ystart_, | |
| 210 | + xstart - s1->xstart_, yend - s1->ystart_ - 1, xend - s1->xstart_ - 1); | |
| 209 | 211 | } |
| 210 | 212 | |
| 211 | 213 | int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, |
| @@ -71,12 +71,31 @@ · 70 unmodified lines | ||
| 71 | 71 | * Includes. |
| 72 | 72 | \******************************************************************************/ |
| 73 | 73 | |
| 74 | +#include "jasper/jas_config.h" | |
| 75 | + | |
| 76 | +/* The following must come before any direct/indirect inclusion of stdlib.h. */ | |
| 77 | +#if defined(JAS_HAVE_MKOSTEMP) | |
| 78 | +#define _GNU_SOURCE | |
| 79 | +#endif | |
| 80 | + | |
| 81 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 82 | + | |
| 74 | 83 | #include "jasper/jas_stream.h" |
| 75 | 84 | #include "jasper/jas_debug.h" |
| 76 | 85 | #include "jasper/jas_types.h" |
| 77 | 86 | #include "jasper/jas_malloc.h" |
| 78 | 87 | #include "jasper/jas_math.h" |
| 79 | 88 | |
| 89 | +/* | |
| 90 | +O_CLOEXEC is a Linux-specific flag which helps avoid leaking file descriptors | |
| 91 | +to child processes created by another thread; for simplicity, we always | |
| 92 | +specify it, and this definition is a fallback for systems where this feature | |
| 93 | +is not available | |
| 94 | +*/ | |
| 95 | +#ifndef O_CLOEXEC | |
| 96 | +#define O_CLOEXEC 0 | |
| 97 | +#endif | |
| 98 | + | |
| 80 | 99 | /******************************************************************************\ |
| 81 | 100 | * Local function prototypes. |
| 82 | 101 | \******************************************************************************/ |
| @@ -87,13 +106,21 @@ static jas_stream_t *jas_stream_create(void); · 4 unmodified lines | ||
| 87 | 106 | static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf, |
| 88 | 107 | int bufsize); |
| 89 | 108 | |
| 90 | −static int mem_read(jas_stream_obj_t *obj, char *buf, unsigned cnt); | |
| 91 | −static int mem_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt); | |
| 109 | +static ssize_t mem_read(jas_stream_obj_t *obj, char *buf, size_t cnt); | |
| 110 | +static ssize_t mem_write(jas_stream_obj_t *obj, const char *buf, | |
| 111 | + size_t cnt); | |
| 92 | 112 | static long mem_seek(jas_stream_obj_t *obj, long offset, int origin); |
| 93 | 113 | static int mem_close(jas_stream_obj_t *obj); |
| 94 | 114 | |
| 95 | −static int file_read(jas_stream_obj_t *obj, char *buf, unsigned cnt); | |
| 96 | −static int file_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt); | |
| 115 | +static ssize_t sfile_read(jas_stream_obj_t *obj, char *buf, size_t cnt); | |
| 116 | +static ssize_t sfile_write(jas_stream_obj_t *obj, const char *buf, | |
| 117 | + size_t cnt); | |
| 118 | +static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin); | |
| 119 | +static int sfile_close(jas_stream_obj_t *obj); | |
| 120 | + | |
| 121 | +static ssize_t file_read(jas_stream_obj_t *obj, char *buf, size_t cnt); | |
| 122 | +static ssize_t file_write(jas_stream_obj_t *obj, const char *buf, | |
| 123 | + size_t cnt); | |
| 97 | 124 | static long file_seek(jas_stream_obj_t *obj, long offset, int origin); |
| 98 | 125 | static int file_close(jas_stream_obj_t *obj); |
| 99 | 126 | |
| @@ -108,6 +135,13 @@ static const jas_stream_ops_t jas_stream_fileops = { · 8 unmodified lines | ||
| 108 | 135 | file_close |
| 109 | 136 | }; |
| 110 | 137 | |
| 138 | +static const jas_stream_ops_t jas_stream_sfileops = { | |
| 139 | + sfile_read, | |
| 140 | + sfile_write, | |
| 141 | + sfile_seek, | |
| 142 | + sfile_close | |
| 143 | +}; | |
| 144 | + | |
| 111 | 145 | static const jas_stream_ops_t jas_stream_memops = { |
| 112 | 146 | mem_read, |
| 113 | 147 | mem_write, |
| @@ -142,17 +176,12 @@ static jas_stream_t *jas_stream_create() · 28 unmodified lines | ||
| 142 | 176 | return stream; |
| 143 | 177 | } |
| 144 | 178 | |
| 145 | −/* | |
| 146 | −This function will eventually replace jas_stream_memopen. | |
| 147 | −For documentation of the interface for this function, see jas_stream.h. | |
| 148 | −*/ | |
| 149 | − | |
| 150 | −jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize) | |
| 179 | +jas_stream_t *jas_stream_memopen(char *buf, size_t bufsize) | |
| 151 | 180 | { |
| 152 | 181 | jas_stream_t *stream; |
| 153 | 182 | jas_stream_memobj_t *obj; |
| 154 | 183 | |
| 155 | − JAS_DBGLOG(100, ("jas_stream_memopen2(%p, %zu)\n", buf, bufsize)); | |
| 184 | + JAS_LOGDEBUGF(100, "jas_stream_memopen(%p, %zu)\n", buf, bufsize); | |
| 156 | 185 | |
| 157 | 186 | assert((buf && bufsize > 0) || (!buf)); |
| 158 | 187 | |
| @@ -201,8 +230,8 @@ jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize) · 42 unmodified lines | ||
| 201 | 230 | jas_stream_close(stream); |
| 202 | 231 | return 0; |
| 203 | 232 | } |
| 204 | − JAS_DBGLOG(100, ("jas_stream_memopen2 buffer buf=%p myalloc=%d\n", | |
| 205 | − obj->buf_, obj->myalloc_)); | |
| 233 | + JAS_LOGDEBUGF(100, "jas_stream_memopen buffer buf=%p myalloc=%d\n", | |
| 234 | + obj->buf_, obj->myalloc_); | |
| 206 | 235 | |
| 207 | 236 | if (bufsize > 0 && buf) { |
| 208 | 237 | /* If a buffer was supplied by the caller and its length is positive, |
| @@ -218,40 +247,13 @@ jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize) · 9 unmodified lines | ||
| 218 | 247 | } |
| 219 | 248 | |
| 220 | 249 | /* |
| 221 | −NOTE: | |
| 222 | −The version of the function jas_stream_memopen only exists for backwards | |
| 223 | −compatibility. | |
| 224 | −Eventually, it should be replaced by jas_stream_memopen2. | |
| 225 | −In retrospect, it was a very poor choice to have specified the buffer | |
| 226 | −size parameter (bufsize) to have type int. On some machines, int may only | |
| 227 | −be a 16-bit integer. This precludes larger-sized buffer allocations, which | |
| 228 | −are needed in practice. | |
| 229 | − | |
| 230 | −If bufsize <= 0, the buffer is growable; otherwise, the buffer has a fixed | |
| 231 | −size of bufsize. | |
| 232 | −If buf is 0, the buffer is dynamically allocated with jas_malloc. | |
| 233 | −If buf is not 0 and bufsize <= 0 (which is not permitted in any | |
| 234 | −circumstances), bad things will happen (especially if the buf was not | |
| 235 | −allocated with jas_malloc). | |
| 250 | +This function is deprecated. | |
| 251 | +It will be removed eventually. | |
| 236 | 252 | */ |
| 237 | −jas_stream_t *jas_stream_memopen(char *buf, int bufsize) | |
| 253 | +jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize) | |
| 238 | 254 | { |
| 239 | − char *new_buf; | |
| 240 | − size_t new_bufsize; | |
| 241 | − | |
| 242 | − JAS_DBGLOG(100, ("jas_stream_memopen(%p, %d)\n", buf, bufsize)); | |
| 243 | − if (bufsize < 0 || (buf && bufsize <= 0)) { | |
| 244 | − jas_eprintf("Invalid use of jas_stream_memopen detected.\n"); | |
| 245 | − return nil; | |
| 246 | − } | |
| 247 | − if (bufsize <= 0) { | |
| 248 | − new_bufsize = 0; | |
| 249 | − new_buf = 0; | |
| 250 | − } else { | |
| 251 | − new_bufsize = bufsize; | |
| 252 | − new_buf = buf; | |
| 253 | − } | |
| 254 | − return jas_stream_memopen2(new_buf, new_bufsize); | |
| 255 | + jas_deprecated("jas_stream_memopen2 is deprecated\n"); | |
| 256 | + return jas_stream_memopen(buf, bufsize); | |
| 255 | 257 | } |
| 256 | 258 | |
| 257 | 259 | jas_stream_t *jas_stream_fopen(const char *filename, const char *mode) |
| @@ -260,7 +262,7 @@ jas_stream_t *jas_stream_fopen(const char *filename, const char *mode) · 2 unmodified lines | ||
| 260 | 262 | jas_stream_fileobj_t *obj; |
| 261 | 263 | int openflags; |
| 262 | 264 | |
| 263 | − JAS_DBGLOG(100, ("jas_stream_fopen(\"%s\", \"%s\")\n", filename, mode)); | |
| 265 | + JAS_LOGDEBUGF(100, "jas_stream_fopen(\"%s\", \"%s\")\n", filename, mode); | |
| 264 | 266 | |
| 265 | 267 | /* Allocate a stream object. */ |
| 266 | 268 | if (!(stream = jas_stream_create())) { |
| @@ -273,19 +275,25 @@ jas_stream_t *jas_stream_fopen(const char *filename, const char *mode) · 6 unmodified lines | ||
| 273 | 275 | /* Determine the correct flags to use for opening the file. */ |
| 274 | 276 | if ((stream->openmode_ & JAS_STREAM_READ) && |
| 275 | 277 | (stream->openmode_ & JAS_STREAM_WRITE)) { |
| 276 | − openflags = ORDWR; | |
| 278 | + openflags = O_RDWR; | |
| 277 | 279 | } else if (stream->openmode_ & JAS_STREAM_READ) { |
| 278 | − openflags = OREAD; | |
| 280 | + openflags = O_RDONLY; | |
| 279 | 281 | } else if (stream->openmode_ & JAS_STREAM_WRITE) { |
| 280 | − openflags = OWRITE; | |
| 282 | + openflags = O_WRONLY; | |
| 281 | 283 | } else { |
| 282 | 284 | openflags = 0; |
| 283 | 285 | } |
| 286 | + if (stream->openmode_ & JAS_STREAM_APPEND) { | |
| 287 | + openflags |= O_APPEND; | |
| 288 | + } | |
| 289 | + if (stream->openmode_ & JAS_STREAM_BINARY) { | |
| 290 | + openflags |= O_BINARY; | |
| 291 | + } | |
| 284 | 292 | if (stream->openmode_ & JAS_STREAM_CREATE) { |
| 285 | − openflags |= OTRUNC; | |
| 293 | + openflags |= O_CREAT | O_TRUNC; | |
| 286 | 294 | } |
| 287 | 295 | |
| 288 | − openflags |= OCEXEC; | |
| 296 | + openflags |= O_CLOEXEC; | |
| 289 | 297 | |
| 290 | 298 | /* Allocate space for the underlying file stream object. */ |
| 291 | 299 | if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) { |
| @@ -294,41 +302,177 @@ jas_stream_t *jas_stream_fopen(const char *filename, const char *mode) · 2 unmodified lines | ||
| 294 | 302 | } |
| 295 | 303 | obj->fd = -1; |
| 296 | 304 | obj->flags = 0; |
| 305 | + obj->pathname[0] = '\0'; | |
| 297 | 306 | stream->obj_ = (void *) obj; |
| 298 | 307 | |
| 299 | 308 | /* Select the operations for a file stream object. */ |
| 300 | 309 | stream->ops_ = &jas_stream_fileops; |
| 301 | 310 | |
| 302 | − if (stream->openmode_ & JAS_STREAM_CREATE) { | |
| 303 | − obj->fd = create(filename, openflags, JAS_STREAM_PERMS); | |
| 304 | − } else { | |
| 305 | − obj->fd = open(filename, openflags); | |
| 306 | − } | |
| 307 | − | |
| 308 | 311 | /* Open the underlying file. */ |
| 309 | − if (obj->fd < 0) { | |
| 312 | + if ((obj->fd = open(filename, openflags/*, JAS_STREAM_PERMS*/)) < 0) { | |
| 310 | 313 | // Free the underlying file object, since it will not otherwise |
| 311 | 314 | // be freed. |
| 312 | 315 | jas_free(obj); |
| 313 | 316 | jas_stream_destroy(stream); |
| 314 | 317 | return 0; |
| 315 | 318 | } |
| 316 | − if (stream->openmode_ & JAS_STREAM_APPEND) { | |
| 317 | − seek(obj->fd, 0, 2); | |
| 319 | + | |
| 320 | + /* By default, use full buffering for this type of stream. */ | |
| 321 | + jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); | |
| 322 | + | |
| 323 | + return stream; | |
| 324 | +} | |
| 325 | + | |
| 326 | +jas_stream_t *jas_stream_freopen(const char *path, const char *mode, FILE *fp) | |
| 327 | +{ | |
| 328 | + jas_stream_t *stream; | |
| 329 | + | |
| 330 | + JAS_LOGDEBUGF(100, "jas_stream_freopen(\"%s\", \"%s\", %p)\n", path, mode, fp); | |
| 331 | + | |
| 332 | + JAS_UNUSED(path); | |
| 333 | + | |
| 334 | + /* Allocate a stream object. */ | |
| 335 | + if (!(stream = jas_stream_create())) { | |
| 336 | + return 0; | |
| 318 | 337 | } |
| 319 | 338 | |
| 339 | + /* Parse the mode string. */ | |
| 340 | + stream->openmode_ = jas_strtoopenmode(mode); | |
| 341 | + | |
| 342 | + stream->obj_ = JAS_CAST(void *, fp); | |
| 343 | + | |
| 344 | + /* Select the operations for a file stream object. */ | |
| 345 | + stream->ops_ = &jas_stream_sfileops; | |
| 346 | + | |
| 320 | 347 | /* By default, use full buffering for this type of stream. */ |
| 321 | 348 | jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); |
| 322 | 349 | |
| 323 | 350 | return stream; |
| 324 | 351 | } |
| 325 | 352 | |
| 353 | +#ifndef _WIN32 | |
| 354 | + | |
| 355 | +/** | |
| 356 | + * Copy the absolute path of the directory for temporary files to the | |
| 357 | + * given buffer (without a null terminator), including a trailing path | |
| 358 | + * separator. | |
| 359 | + * | |
| 360 | + * @return the number of characters copied to the buffer or 0 on error | |
| 361 | + */ | |
| 362 | +static size_t get_temp_directory(char *buffer, size_t size) | |
| 363 | +{ | |
| 364 | + const char *tmpdir = getenv("TMPDIR"); | |
| 365 | + if (tmpdir == NULL) { | |
| 366 | + tmpdir = "/tmp"; | |
| 367 | + } | |
| 368 | + | |
| 369 | + size_t length = strlen(tmpdir); | |
| 370 | + if (length + 1 > size) { | |
| 371 | + return 0; | |
| 372 | + } | |
| 373 | + | |
| 374 | + memcpy(buffer, tmpdir, length); | |
| 375 | + buffer[length++] = '/'; | |
| 376 | + return length; | |
| 377 | +} | |
| 378 | + | |
| 379 | +#endif /* !_WIN32 */ | |
| 380 | + | |
| 381 | +/** | |
| 382 | + * Generate a template for mkstemp(). | |
| 383 | + * | |
| 384 | + * @return 0 on success, -1 on error | |
| 385 | + */ | |
| 386 | +static int make_mkstemp_template(char *buffer, size_t size) | |
| 387 | +{ | |
| 388 | +#ifdef _WIN32 | |
| 389 | + char temp_directory[MAX_PATH]; | |
| 390 | + if (GetTempPathA(sizeof(temp_directory), temp_directory) == 0) { | |
| 391 | + return -1; | |
| 392 | + } | |
| 393 | + JAS_UNUSED(size); | |
| 394 | + return GetTempFileNameA(temp_directory, "jasper", 0, buffer) > 0 | |
| 395 | + ? 0 : -1; | |
| 396 | +#else | |
| 397 | + static const char base[] = "jasper.XXXXXX"; | |
| 398 | + size_t length = get_temp_directory(buffer, size); | |
| 399 | + if (length == 0 || length + sizeof(base) >= size) { | |
| 400 | + return -1; | |
| 401 | + } | |
| 402 | + memcpy(buffer + length, base, sizeof(base)); | |
| 403 | + return 0; | |
| 404 | +#endif | |
| 405 | +} | |
| 406 | + | |
| 407 | +/** | |
| 408 | + * A wrapper for mkstemp() which generates a template for mkstemp() | |
| 409 | + * before calling the function. | |
| 410 | + * | |
| 411 | + * @return a non-negative file descriptor on success, -1 on error | |
| 412 | + */ | |
| 413 | +static int easy_mkstemp(char *buffer, size_t size) | |
| 414 | +{ | |
| 415 | + JAS_UNUSED(buffer); | |
| 416 | + JAS_UNUSED(size); | |
| 417 | + return -1; | |
| 418 | +} | |
| 419 | + | |
| 420 | +jas_stream_t *jas_stream_tmpfile() | |
| 421 | +{ | |
| 422 | + jas_stream_t *stream; | |
| 423 | + jas_stream_fileobj_t *obj; | |
| 424 | + | |
| 425 | + JAS_LOGDEBUGF(100, "jas_stream_tmpfile()\n"); | |
| 426 | + | |
| 427 | + if (!(stream = jas_stream_create())) { | |
| 428 | + return 0; | |
| 429 | + } | |
| 430 | + | |
| 431 | + /* A temporary file stream is always opened for both reading and | |
| 432 | + writing in binary mode. */ | |
| 433 | + stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY; | |
| 434 | + | |
| 435 | + /* Allocate memory for the underlying temporary file object. */ | |
| 436 | + if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) { | |
| 437 | + jas_stream_destroy(stream); | |
| 438 | + return 0; | |
| 439 | + } | |
| 440 | + obj->fd = -1; | |
| 441 | + obj->flags = 0; | |
| 442 | + obj->pathname[0] = '\0'; | |
| 443 | + stream->obj_ = obj; | |
| 444 | + | |
| 445 | + /* Create the temporary file. */ | |
| 446 | + if ((obj->fd = easy_mkstemp(obj->pathname, sizeof(obj->pathname))) < 0) { | |
| 447 | + jas_stream_destroy(stream); | |
| 448 | + return 0; | |
| 449 | + } | |
| 450 | + | |
| 451 | + /* Unlink the file so that it will disappear if the program | |
| 452 | + terminates abnormally. */ | |
| 453 | + /* Under UNIX, one can unlink an open file and continue to do I/O | |
| 454 | + on it. Not all operating systems support this functionality, however. | |
| 455 | + For example, under Microsoft Windows the unlink operation will fail, | |
| 456 | + since the file is open. */ | |
| 457 | + if (*obj->pathname != 0 && unlink(obj->pathname) < 0) { | |
| 458 | + /* We will try unlinking the file again after it is closed. */ | |
| 459 | + obj->flags |= JAS_STREAM_FILEOBJ_DELONCLOSE; | |
| 460 | + } | |
| 461 | + | |
| 462 | + /* Use full buffering. */ | |
| 463 | + jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); | |
| 464 | + | |
| 465 | + stream->ops_ = &jas_stream_fileops; | |
| 466 | + | |
| 467 | + return stream; | |
| 468 | +} | |
| 469 | + | |
| 326 | 470 | jas_stream_t *jas_stream_fdopen(int fd, const char *mode) |
| 327 | 471 | { |
| 328 | 472 | jas_stream_t *stream; |
| 329 | 473 | jas_stream_fileobj_t *obj; |
| 330 | 474 | |
| 331 | − JAS_DBGLOG(100, ("jas_stream_fdopen(%d, \"%s\")\n", fd, mode)); | |
| 475 | + JAS_LOGDEBUGF(100, "jas_stream_fdopen(%d, \"%s\")\n", fd, mode); | |
| 332 | 476 | |
| 333 | 477 | /* Allocate a stream object. */ |
| 334 | 478 | if (!(stream = jas_stream_create())) { |
| @@ -338,7 +482,7 @@ jas_stream_t *jas_stream_fdopen(int fd, const char *mode) · 3 unmodified lines | ||
| 338 | 482 | /* Parse the mode string. */ |
| 339 | 483 | stream->openmode_ = jas_strtoopenmode(mode); |
| 340 | 484 | |
| 341 | −#if defined(WIN32) | |
| 485 | +#if defined(_WIN32) || defined(JAS_HAVE_IO_H) | |
| 342 | 486 | /* Argh!!! Someone ought to banish text mode (i.e., O_TEXT) to the |
| 343 | 487 | greatest depths of purgatory! */ |
| 344 | 488 | /* Ensure that the file descriptor is in binary mode, if the caller |
| @@ -362,6 +506,7 @@ jas_stream_t *jas_stream_fdopen(int fd, const char *mode) · 17 unmodified lines | ||
| 362 | 506 | } |
| 363 | 507 | obj->fd = fd; |
| 364 | 508 | obj->flags = 0; |
| 509 | + obj->pathname[0] = '\0'; | |
| 365 | 510 | stream->obj_ = (void *) obj; |
| 366 | 511 | |
| 367 | 512 | /* Do not close the underlying file descriptor when the stream is |
| @@ -379,13 +524,13 @@ jas_stream_t *jas_stream_fdopen(int fd, const char *mode) · 11 unmodified lines | ||
| 379 | 524 | |
| 380 | 525 | static void jas_stream_destroy(jas_stream_t *stream) |
| 381 | 526 | { |
| 382 | − JAS_DBGLOG(100, ("jas_stream_destroy(%p)\n", stream)); | |
| 527 | + JAS_LOGDEBUGF(100, "jas_stream_destroy(%p)\n", stream); | |
| 383 | 528 | |
| 384 | 529 | /* If the memory for the buffer was allocated with malloc, free |
| 385 | 530 | this memory. */ |
| 386 | 531 | if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) { |
| 387 | − JAS_DBGLOG(100, ("jas_stream_destroy freeing buffer %p\n", | |
| 388 | − stream->bufbase_)); | |
| 532 | + JAS_LOGDEBUGF(100, "jas_stream_destroy freeing buffer %p\n", | |
| 533 | + stream->bufbase_); | |
| 389 | 534 | jas_free(stream->bufbase_); |
| 390 | 535 | stream->bufbase_ = 0; |
| 391 | 536 | } |
| @@ -394,7 +539,7 @@ static void jas_stream_destroy(jas_stream_t *stream) · 2 unmodified lines | ||
| 394 | 539 | |
| 395 | 540 | int jas_stream_close(jas_stream_t *stream) |
| 396 | 541 | { |
| 397 | − JAS_DBGLOG(100, ("jas_stream_close(%p)\n", stream)); | |
| 542 | + JAS_LOGDEBUGF(100, "jas_stream_close(%p)\n", stream); | |
| 398 | 543 | |
| 399 | 544 | /* Flush buffer if necessary. */ |
| 400 | 545 | jas_stream_flush(stream); |
| @@ -451,16 +596,16 @@ int jas_stream_ungetc(jas_stream_t *stream, int c) · 50 unmodified lines | ||
| 451 | 596 | return 0; |
| 452 | 597 | } |
| 453 | 598 | |
| 454 | −/* FIXME integral type */ | |
| 455 | −unsigned jas_stream_read(jas_stream_t *stream, void *buf, unsigned cnt) | |
| 599 | +size_t jas_stream_read(jas_stream_t *stream, void *buf, size_t cnt) | |
| 456 | 600 | { |
| 457 | 601 | int c; |
| 458 | 602 | char *bufptr; |
| 459 | 603 | |
| 460 | − JAS_DBGLOG(100, ("jas_stream_read(%p, %p, %u)\n", stream, buf, cnt)); | |
| 604 | + JAS_LOGDEBUGF(100, "jas_stream_read(%p, %p, %zu)\n", stream, buf, cnt); | |
| 461 | 605 | |
| 462 | − if (cnt == 0) | |
| 606 | + if (cnt == 0) { | |
| 463 | 607 | return 0; |
| 608 | + } | |
| 464 | 609 | |
| 465 | 610 | bufptr = buf; |
| 466 | 611 | |
| @@ -468,11 +613,13 @@ unsigned jas_stream_read(jas_stream_t *stream, void *buf, unsigned cnt) · 1 unmodified line | ||
| 468 | 613 | jas_stream_is_input_buffer_empty(stream)) { |
| 469 | 614 | /* fast path for unbuffered streams */ |
| 470 | 615 | |
| 471 | − if ((stream->flags_ & JAS_STREAM_ERRMASK) != 0) | |
| 616 | + if ((stream->flags_ & JAS_STREAM_ERRMASK) != 0) { | |
| 472 | 617 | return 0; |
| 618 | + } | |
| 473 | 619 | |
| 474 | − if ((stream->openmode_ & JAS_STREAM_READ) == 0) | |
| 620 | + if ((stream->openmode_ & JAS_STREAM_READ) == 0) { | |
| 475 | 621 | return 0; |
| 622 | + } | |
| 476 | 623 | |
| 477 | 624 | assert((stream->bufmode_ & JAS_STREAM_WRBUF) == 0); |
| 478 | 625 | |
| @@ -502,29 +649,32 @@ unsigned jas_stream_read(jas_stream_t *stream, void *buf, unsigned cnt) · 23 unmodified lines | ||
| 502 | 649 | return n; |
| 503 | 650 | } |
| 504 | 651 | |
| 652 | +/* TODO: The return type should probably be changed to size_t. */ | |
| 505 | 653 | unsigned jas_stream_peek(jas_stream_t *stream, void *buf, size_t cnt) |
| 506 | 654 | { |
| 507 | 655 | char *bufptr = buf; |
| 508 | 656 | |
| 509 | − const unsigned n = jas_stream_read(stream, bufptr, cnt); | |
| 657 | + const size_t n = jas_stream_read(stream, bufptr, cnt); | |
| 510 | 658 | |
| 511 | 659 | /* Put the characters read back onto the stream. */ |
| 512 | − for (unsigned i = n; i-- > 0;) | |
| 513 | − if (jas_stream_ungetc(stream, bufptr[i]) == EOF) | |
| 660 | + for (size_t i = n; i-- > 0;) { | |
| 661 | + if (jas_stream_ungetc(stream, bufptr[i]) == EOF) { | |
| 514 | 662 | return 0; |
| 663 | + } | |
| 664 | + } | |
| 515 | 665 | |
| 516 | 666 | return n; |
| 517 | 667 | } |
| 518 | 668 | |
| 519 | −/* FIXME integral type */ | |
| 520 | −unsigned jas_stream_write(jas_stream_t *stream, const void *buf, unsigned cnt) | |
| 669 | +size_t jas_stream_write(jas_stream_t *stream, const void *buf, size_t cnt) | |
| 521 | 670 | { |
| 522 | 671 | const char *bufptr; |
| 523 | 672 | |
| 524 | − JAS_DBGLOG(100, ("jas_stream_write(%p, %p, %d)\n", stream, buf, cnt)); | |
| 673 | + JAS_LOGDEBUGF(100, "jas_stream_write(%p, %p, %zu)\n", stream, buf, cnt); | |
| 525 | 674 | |
| 526 | − if (cnt == 0) | |
| 675 | + if (cnt == 0) { | |
| 527 | 676 | return 0; |
| 677 | + } | |
| 528 | 678 | |
| 529 | 679 | bufptr = buf; |
| 530 | 680 | |
| @@ -533,8 +683,9 @@ unsigned jas_stream_write(jas_stream_t *stream, const void *buf, unsigned cnt) · 2 unmodified lines | ||
| 533 | 683 | |
| 534 | 684 | /* need to flush the output buffer before we do a raw |
| 535 | 685 | write */ |
| 536 | − if (jas_stream_flushbuf(stream, EOF)) | |
| 686 | + if (jas_stream_flushbuf(stream, EOF)) { | |
| 537 | 687 | return 0; |
| 688 | + } | |
| 538 | 689 | |
| 539 | 690 | stream->bufmode_ |= JAS_STREAM_WRBUF; |
| 540 | 691 | |
| @@ -570,7 +721,7 @@ int jas_stream_printf(jas_stream_t *stream, const char *fmt, ...) · 29 unmodified lines | ||
| 570 | 721 | int ret; |
| 571 | 722 | |
| 572 | 723 | va_start(ap, fmt); |
| 573 | − ret = vsnprint(buf, sizeof buf, fmt, ap); | |
| 724 | + ret = vsnprintf(buf, sizeof buf, fmt, ap); | |
| 574 | 725 | jas_stream_puts(stream, buf); |
| 575 | 726 | va_end(ap); |
| 576 | 727 | return ret; |
| @@ -595,7 +746,7 @@ char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize) · 18 unmodified lines | ||
| 595 | 746 | char *bufptr; |
| 596 | 747 | assert(bufsize > 0); |
| 597 | 748 | |
| 598 | − JAS_DBGLOG(100, ("jas_stream_gets(%p, %p, %d)\n", stream, buf, bufsize)); | |
| 749 | + JAS_LOGDEBUGF(100, "jas_stream_gets(%p, %p, %d)\n", stream, buf, bufsize); | |
| 599 | 750 | |
| 600 | 751 | bufptr = buf; |
| 601 | 752 | while (bufsize > 1) { |
| @@ -612,17 +763,10 @@ char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize) · 10 unmodified lines | ||
| 612 | 763 | return buf; |
| 613 | 764 | } |
| 614 | 765 | |
| 615 | −/* FIXME integral type */ | |
| 616 | −int jas_stream_gobble(jas_stream_t *stream, int n) | |
| 766 | +ssize_t jas_stream_gobble(jas_stream_t *stream, size_t n) | |
| 617 | 767 | { |
| 618 | − int m; | |
| 619 | − | |
| 620 | − JAS_DBGLOG(100, ("jas_stream_gobble(%p, %d)\n", stream, n)); | |
| 621 | − | |
| 622 | − if (n < 0) { | |
| 623 | − jas_eprintf("negative count for jas_stream_gobble\n"); | |
| 624 | − return 0; | |
| 625 | − } | |
| 768 | + size_t m; | |
| 769 | + JAS_LOGDEBUGF(100, "jas_stream_gobble(%p, %zu)\n", stream, n); | |
| 626 | 770 | for (m = n; m > 0; --m) { |
| 627 | 771 | if (jas_stream_getc(stream) == EOF) { |
| 628 | 772 | return n - m; |
| @@ -631,20 +775,14 @@ int jas_stream_gobble(jas_stream_t *stream, int n) · 2 unmodified lines | ||
| 631 | 775 | return n; |
| 632 | 776 | } |
| 633 | 777 | |
| 634 | −/* FIXME integral type */ | |
| 635 | −int jas_stream_pad(jas_stream_t *stream, int n, int c) | |
| 778 | +ssize_t jas_stream_pad(jas_stream_t *stream, size_t n, int c) | |
| 636 | 779 | { |
| 637 | − int m; | |
| 638 | − | |
| 639 | − JAS_DBGLOG(100, ("jas_stream_pad(%p, %d, %d)\n", stream, n, c)); | |
| 640 | − | |
| 641 | − if (n < 0) { | |
| 642 | − jas_eprintf("negative count for jas_stream_pad\n"); | |
| 643 | − return 0; | |
| 644 | − } | |
| 780 | + size_t m; | |
| 781 | + JAS_LOGDEBUGF(100, "jas_stream_pad(%p, %zu, %d)\n", stream, n, c); | |
| 645 | 782 | for (m = n; m > 0; --m) { |
| 646 | − if (jas_stream_putc(stream, c) == EOF) | |
| 783 | + if (jas_stream_putc(stream, c) == EOF) { | |
| 647 | 784 | return n - m; |
| 785 | + } | |
| 648 | 786 | } |
| 649 | 787 | return n; |
| 650 | 788 | } |
| @@ -658,7 +796,7 @@ int jas_stream_isseekable(jas_stream_t *stream) · 7 unmodified lines | ||
| 658 | 796 | if (stream->ops_ == &jas_stream_memops) { |
| 659 | 797 | return 1; |
| 660 | 798 | } else if (stream->ops_ == &jas_stream_fileops) { |
| 661 | − if ((*stream->ops_->seek_)(stream->obj_, 0, 1) < 0) { | |
| 799 | + if ((*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR) < 0) { | |
| 662 | 800 | return 0; |
| 663 | 801 | } |
| 664 | 802 | return 1; |
| @@ -669,16 +807,15 @@ int jas_stream_isseekable(jas_stream_t *stream) · 4 unmodified lines | ||
| 669 | 807 | |
| 670 | 808 | int jas_stream_rewind(jas_stream_t *stream) |
| 671 | 809 | { |
| 672 | − JAS_DBGLOG(100, ("jas_stream_rewind(%p)\n", stream)); | |
| 673 | − return jas_stream_seek(stream, 0, 0); | |
| 810 | + JAS_LOGDEBUGF(100, "jas_stream_rewind(%p)\n", stream); | |
| 811 | + return jas_stream_seek(stream, 0, SEEK_SET); | |
| 674 | 812 | } |
| 675 | 813 | |
| 676 | 814 | long jas_stream_seek(jas_stream_t *stream, long offset, int origin) |
| 677 | 815 | { |
| 678 | 816 | long newpos; |
| 679 | 817 | |
| 680 | − JAS_DBGLOG(100, ("jas_stream_seek(%p, %ld, %d)\n", stream, offset, | |
| 681 | − origin)); | |
| 818 | + JAS_LOGDEBUGF(100, "jas_stream_seek(%p, %ld, %d)\n", stream, offset, origin); | |
| 682 | 819 | |
| 683 | 820 | /* The buffer cannot be in use for both reading and writing. */ |
| 684 | 821 | assert(!((stream->bufmode_ & JAS_STREAM_RDBUF) && (stream->bufmode_ & |
| @@ -688,7 +825,7 @@ long jas_stream_seek(jas_stream_t *stream, long offset, int origin) · 3 unmodified lines | ||
| 688 | 825 | stream->flags_ &= ~JAS_STREAM_EOF; |
| 689 | 826 | |
| 690 | 827 | if (stream->bufmode_ & JAS_STREAM_RDBUF) { |
| 691 | − if (origin == 1) { | |
| 828 | + if (origin == SEEK_CUR) { | |
| 692 | 829 | offset -= stream->cnt_; |
| 693 | 830 | } |
| 694 | 831 | } else if (stream->bufmode_ & JAS_STREAM_WRBUF) { |
| @@ -713,7 +850,7 @@ long jas_stream_tell(jas_stream_t *stream) · 18 unmodified lines | ||
| 713 | 850 | int adjust; |
| 714 | 851 | int offset; |
| 715 | 852 | |
| 716 | − JAS_DBGLOG(100, ("jas_stream_tell(%p)\n", stream)); | |
| 853 | + JAS_LOGDEBUGF(100, "jas_stream_tell(%p)\n", stream); | |
| 717 | 854 | |
| 718 | 855 | if (stream->bufmode_ & JAS_STREAM_RDBUF) { |
| 719 | 856 | adjust = -stream->cnt_; |
| @@ -723,7 +860,7 @@ long jas_stream_tell(jas_stream_t *stream) · 3 unmodified lines | ||
| 723 | 860 | adjust = 0; |
| 724 | 861 | } |
| 725 | 862 | |
| 726 | − if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, 1)) < 0) { | |
| 863 | + if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR)) < 0) { | |
| 727 | 864 | return -1; |
| 728 | 865 | } |
| 729 | 866 | |
| @@ -910,10 +1047,9 @@ static int jas_strtoopenmode(const char *s) · 180 unmodified lines | ||
| 910 | 1047 | return openmode; |
| 911 | 1048 | } |
| 912 | 1049 | |
| 913 | −/* FIXME integral type */ | |
| 914 | −int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n) | |
| 1050 | +int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, ssize_t n) | |
| 915 | 1051 | { |
| 916 | − int m; | |
| 1052 | + ssize_t m; | |
| 917 | 1053 | |
| 918 | 1054 | const bool all = n < 0; |
| 919 | 1055 | |
| @@ -921,14 +1057,14 @@ int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n) · 1 unmodified line | ||
| 921 | 1057 | |
| 922 | 1058 | m = n; |
| 923 | 1059 | while (all || m > 0) { |
| 924 | − unsigned nbytes = jas_stream_read(in, buffer, | |
| 925 | − JAS_MIN((size_t)m, sizeof(buffer))); | |
| 926 | − if (nbytes == 0) | |
| 1060 | + size_t nbytes = jas_stream_read(in, buffer, | |
| 1061 | + JAS_MIN((size_t)m, sizeof(buffer))); | |
| 1062 | + if (nbytes == 0) { | |
| 927 | 1063 | return !all || jas_stream_error(in) ? -1 : 0; |
| 928 | − | |
| 929 | − if (jas_stream_write(out, buffer, nbytes) != nbytes) | |
| 1064 | + } | |
| 1065 | + if (jas_stream_write(out, buffer, nbytes) != nbytes) { | |
| 930 | 1066 | return -1; |
| 931 | − | |
| 1067 | + } | |
| 932 | 1068 | m -= nbytes; |
| 933 | 1069 | } |
| 934 | 1070 | |
| @@ -945,7 +1081,7 @@ long jas_stream_setrwcount(jas_stream_t *stream, long rwcnt) · 10 unmodified lines | ||
| 945 | 1081 | return old; |
| 946 | 1082 | } |
| 947 | 1083 | |
| 948 | −JAS_DLLEXPORT | |
| 1084 | +JAS_EXPORT | |
| 949 | 1085 | long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit) |
| 950 | 1086 | { |
| 951 | 1087 | long old; |
| @@ -955,6 +1091,57 @@ long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit) · 3 unmodified lines | ||
| 955 | 1091 | return old; |
| 956 | 1092 | } |
| 957 | 1093 | |
| 1094 | +/* FIXME integral type */ | |
| 1095 | +int jas_stream_display(jas_stream_t *stream, FILE *fp, int n) | |
| 1096 | +{ | |
| 1097 | + unsigned char buf[16]; | |
| 1098 | + int i; | |
| 1099 | + int j; | |
| 1100 | + int m; | |
| 1101 | + int c; | |
| 1102 | + int display; | |
| 1103 | + int cnt; | |
| 1104 | + | |
| 1105 | + cnt = n - (n % 16); | |
| 1106 | + display = 1; | |
| 1107 | + | |
| 1108 | + for (i = 0; i < n; i += 16) { | |
| 1109 | + if (n > 16 && i > 0) { | |
| 1110 | + display = (i >= cnt) ? 1 : 0; | |
| 1111 | + } | |
| 1112 | + if (display) { | |
| 1113 | + fprintf(fp, "%08x:", i); | |
| 1114 | + } | |
| 1115 | + m = JAS_MIN(n - i, 16); | |
| 1116 | + for (j = 0; j < m; ++j) { | |
| 1117 | + if ((c = jas_stream_getc(stream)) == EOF) { | |
| 1118 | + return -1; | |
| 1119 | + } | |
| 1120 | + buf[j] = c; | |
| 1121 | + } | |
| 1122 | + if (display) { | |
| 1123 | + for (j = 0; j < m; ++j) { | |
| 1124 | + fprintf(fp, " %02x", buf[j]); | |
| 1125 | + } | |
| 1126 | + fputc(' ', fp); | |
| 1127 | + for (; j < 16; ++j) { | |
| 1128 | + fprintf(fp, " "); | |
| 1129 | + } | |
| 1130 | + for (j = 0; j < m; ++j) { | |
| 1131 | + if (isprint(buf[j])) { | |
| 1132 | + fputc(buf[j], fp); | |
| 1133 | + } else { | |
| 1134 | + fputc(' ', fp); | |
| 1135 | + } | |
| 1136 | + } | |
| 1137 | + fprintf(fp, "\n"); | |
| 1138 | + } | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + } | |
| 1142 | + return 0; | |
| 1143 | +} | |
| 1144 | + | |
| 958 | 1145 | long jas_stream_length(jas_stream_t *stream) |
| 959 | 1146 | { |
| 960 | 1147 | long oldpos; |
| @@ -962,13 +1149,13 @@ long jas_stream_length(jas_stream_t *stream) · 1 unmodified line | ||
| 962 | 1149 | if ((oldpos = jas_stream_tell(stream)) < 0) { |
| 963 | 1150 | return -1; |
| 964 | 1151 | } |
| 965 | − if (jas_stream_seek(stream, 0, 2) < 0) { | |
| 1152 | + if (jas_stream_seek(stream, 0, SEEK_END) < 0) { | |
| 966 | 1153 | return -1; |
| 967 | 1154 | } |
| 968 | 1155 | if ((pos = jas_stream_tell(stream)) < 0) { |
| 969 | 1156 | return -1; |
| 970 | 1157 | } |
| 971 | − if (jas_stream_seek(stream, oldpos, 0) < 0) { | |
| 1158 | + if (jas_stream_seek(stream, oldpos, SEEK_SET) < 0) { | |
| 972 | 1159 | return -1; |
| 973 | 1160 | } |
| 974 | 1161 | return pos; |
| @@ -978,13 +1165,12 @@ long jas_stream_length(jas_stream_t *stream) · 3 unmodified lines | ||
| 978 | 1165 | * Memory stream object. |
| 979 | 1166 | \******************************************************************************/ |
| 980 | 1167 | |
| 981 | −/* FIXME integral type */ | |
| 982 | −static int mem_read(jas_stream_obj_t *obj, char *buf, unsigned cnt) | |
| 1168 | +static ssize_t mem_read(jas_stream_obj_t *obj, char *buf, size_t cnt) | |
| 983 | 1169 | { |
| 984 | 1170 | jas_stream_memobj_t *m; |
| 985 | 1171 | assert(buf); |
| 986 | 1172 | |
| 987 | − JAS_DBGLOG(100, ("mem_read(%p, %p, %u)\n", obj, buf, cnt)); | |
| 1173 | + JAS_LOGDEBUGF(100, "mem_read(%p, %p, %zu)\n", obj, buf, cnt); | |
| 988 | 1174 | m = (jas_stream_memobj_t *)obj; |
| 989 | 1175 | size_t n = m->len_ - m->pos_; |
| 990 | 1176 | cnt = JAS_MIN(n, cnt); |
| @@ -997,11 +1183,9 @@ static int mem_resize(jas_stream_memobj_t *m, size_t bufsize) · 6 unmodified lines | ||
| 997 | 1183 | { |
| 998 | 1184 | unsigned char *buf; |
| 999 | 1185 | |
| 1000 | − //assert(m->buf_); | |
| 1001 | − | |
| 1002 | − JAS_DBGLOG(100, ("mem_resize(%p, %zu)\n", m, bufsize)); | |
| 1186 | + JAS_LOGDEBUGF(100, "mem_resize(%p, %zu)\n", m, bufsize); | |
| 1003 | 1187 | if (!bufsize) { |
| 1004 | − jas_eprintf( | |
| 1188 | + jas_logerrorf( | |
| 1005 | 1189 | "mem_resize was not really designed to handle a buffer of size 0\n" |
| 1006 | 1190 | "This may not work.\n" |
| 1007 | 1191 | ); |
| @@ -1009,17 +1193,17 @@ static int mem_resize(jas_stream_memobj_t *m, size_t bufsize) · 1 unmodified line | ||
| 1009 | 1193 | |
| 1010 | 1194 | if (!(buf = jas_realloc2(m->buf_, bufsize, sizeof(unsigned char))) && |
| 1011 | 1195 | bufsize) { |
| 1012 | − JAS_DBGLOG(100, ("mem_resize realloc failed\n")); | |
| 1196 | + JAS_LOGDEBUGF(100, "mem_resize realloc failed\n"); | |
| 1013 | 1197 | return -1; |
| 1014 | 1198 | } |
| 1015 | − JAS_DBGLOG(100, ("mem_resize realloc succeeded\n")); | |
| 1199 | + JAS_LOGDEBUGF(100, "mem_resize realloc succeeded\n"); | |
| 1016 | 1200 | m->buf_ = buf; |
| 1017 | 1201 | m->bufsize_ = bufsize; |
| 1018 | 1202 | return 0; |
| 1019 | 1203 | } |
| 1020 | 1204 | |
| 1021 | −/* FIXME integral type */ | |
| 1022 | −static int mem_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt) | |
| 1205 | +static ssize_t mem_write(jas_stream_obj_t *obj, const char *buf, | |
| 1206 | + size_t cnt) | |
| 1023 | 1207 | { |
| 1024 | 1208 | size_t n; |
| 1025 | 1209 | jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; |
| @@ -1028,19 +1212,19 @@ static int mem_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt) · 2 unmodified lines | ||
| 1028 | 1212 | |
| 1029 | 1213 | assert(buf); |
| 1030 | 1214 | |
| 1031 | − JAS_DBGLOG(100, ("mem_write(%p, %p, %u)\n", obj, buf, cnt)); | |
| 1215 | + JAS_LOGDEBUGF(100, "mem_write(%p, %p, %zu)\n", obj, buf, cnt); | |
| 1032 | 1216 | newpos = m->pos_ + cnt; |
| 1033 | 1217 | if (newpos > m->bufsize_ && m->growable_) { |
| 1034 | 1218 | newbufsize = m->bufsize_; |
| 1035 | 1219 | while (newbufsize < newpos) { |
| 1036 | − //newbufsize <<= 1; | |
| 1220 | + /* Attempt to double the buffer size. */ | |
| 1037 | 1221 | if (!jas_safe_size_mul(newbufsize, 2, &newbufsize)) { |
| 1038 | − JAS_DBGLOG(100, ("new buffer size would cause overflow\n")); | |
| 1222 | + JAS_LOGDEBUGF(100, "new buffer size would cause overflow\n"); | |
| 1039 | 1223 | return -1; |
| 1040 | 1224 | } |
| 1041 | 1225 | } |
| 1042 | − JAS_DBGLOG(100, ("mem_write resizing from %d to %zu\n", m->bufsize_, | |
| 1043 | − newbufsize)); | |
| 1226 | + JAS_LOGDEBUGF(100, "mem_write resizing from %d to %zu\n", m->bufsize_, | |
| 1227 | + newbufsize); | |
| 1044 | 1228 | assert(newbufsize > 0); |
| 1045 | 1229 | if (mem_resize(m, newbufsize)) { |
| 1046 | 1230 | return -1; |
| @@ -1078,15 +1262,15 @@ static long mem_seek(jas_stream_obj_t *obj, long offset, int origin) · 31 unmodified lines | ||
| 1078 | 1262 | jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; |
| 1079 | 1263 | long newpos; |
| 1080 | 1264 | |
| 1081 | − JAS_DBGLOG(100, ("mem_seek(%p, %ld, %d)\n", obj, offset, origin)); | |
| 1265 | + JAS_LOGDEBUGF(100, "mem_seek(%p, %ld, %d)\n", obj, offset, origin); | |
| 1082 | 1266 | switch (origin) { |
| 1083 | − case 0: | |
| 1267 | + case SEEK_SET: | |
| 1084 | 1268 | newpos = offset; |
| 1085 | 1269 | break; |
| 1086 | − case 2: | |
| 1270 | + case SEEK_END: | |
| 1087 | 1271 | newpos = m->len_ - offset; |
| 1088 | 1272 | break; |
| 1089 | − case 1: | |
| 1273 | + case SEEK_CUR: | |
| 1090 | 1274 | newpos = m->pos_ + offset; |
| 1091 | 1275 | break; |
| 1092 | 1276 | default: |
| @@ -1104,11 +1288,11 @@ static int mem_close(jas_stream_obj_t *obj) · 11 unmodified lines | ||
| 1104 | 1288 | { |
| 1105 | 1289 | jas_stream_memobj_t *m; |
| 1106 | 1290 | |
| 1107 | − JAS_DBGLOG(100, ("mem_close(%p)\n", obj)); | |
| 1291 | + JAS_LOGDEBUGF(100, "mem_close(%p)\n", obj); | |
| 1108 | 1292 | m = (jas_stream_memobj_t *)obj; |
| 1109 | − JAS_DBGLOG(100, ("mem_close myalloc=%d\n", m->myalloc_)); | |
| 1293 | + JAS_LOGDEBUGF(100, "mem_close myalloc=%d\n", m->myalloc_); | |
| 1110 | 1294 | if (m->myalloc_ && m->buf_) { |
| 1111 | − JAS_DBGLOG(100, ("mem_close freeing buffer %p\n", m->buf_)); | |
| 1295 | + JAS_LOGDEBUGF(100, "mem_close freeing buffer %p\n", m->buf_); | |
| 1112 | 1296 | jas_free(m->buf_); |
| 1113 | 1297 | m->buf_ = 0; |
| 1114 | 1298 | } |
| @@ -1120,20 +1304,19 @@ static int mem_close(jas_stream_obj_t *obj) · 5 unmodified lines | ||
| 1120 | 1304 | * File stream object. |
| 1121 | 1305 | \******************************************************************************/ |
| 1122 | 1306 | |
| 1123 | −/* FIXME integral type */ | |
| 1124 | −static int file_read(jas_stream_obj_t *obj, char *buf, unsigned cnt) | |
| 1307 | +static ssize_t file_read(jas_stream_obj_t *obj, char *buf, size_t cnt) | |
| 1125 | 1308 | { |
| 1126 | 1309 | jas_stream_fileobj_t *fileobj; |
| 1127 | − JAS_DBGLOG(100, ("file_read(%p, %p, %u)\n", obj, buf, cnt)); | |
| 1310 | + JAS_LOGDEBUGF(100, "file_read(%p, %p, %zu)\n", obj, buf, cnt); | |
| 1128 | 1311 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); |
| 1129 | 1312 | return read(fileobj->fd, buf, cnt); |
| 1130 | 1313 | } |
| 1131 | 1314 | |
| 1132 | −/* FIXME integral type */ | |
| 1133 | −static int file_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt) | |
| 1315 | +static ssize_t file_write(jas_stream_obj_t *obj, const char *buf, | |
| 1316 | + size_t cnt) | |
| 1134 | 1317 | { |
| 1135 | 1318 | jas_stream_fileobj_t *fileobj; |
| 1136 | − JAS_DBGLOG(100, ("file_write(%p, %p, %u)\n", obj, buf, cnt)); | |
| 1319 | + JAS_LOGDEBUGF(100, "file_write(%p, %p, %zu)\n", obj, buf, cnt); | |
| 1137 | 1320 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); |
| 1138 | 1321 | return write(fileobj->fd, buf, cnt); |
| 1139 | 1322 | } |
| @@ -1142,18 +1325,91 @@ static int file_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt) · 2 unmodified lines | ||
| 1142 | 1325 | static long file_seek(jas_stream_obj_t *obj, long offset, int origin) |
| 1143 | 1326 | { |
| 1144 | 1327 | jas_stream_fileobj_t *fileobj; |
| 1145 | − JAS_DBGLOG(100, ("file_seek(%p, %ld, %d)\n", obj, offset, origin)); | |
| 1328 | + JAS_LOGDEBUGF(100, "file_seek(%p, %ld, %d)\n", obj, offset, origin); | |
| 1146 | 1329 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); |
| 1147 | − return seek(fileobj->fd, offset, origin); | |
| 1330 | + return lseek(fileobj->fd, offset, origin); | |
| 1148 | 1331 | } |
| 1149 | 1332 | |
| 1150 | 1333 | static int file_close(jas_stream_obj_t *obj) |
| 1151 | 1334 | { |
| 1152 | − int ret; | |
| 1335 | + int ret = 0; | |
| 1153 | 1336 | jas_stream_fileobj_t *fileobj; |
| 1154 | − JAS_DBGLOG(100, ("file_close(%p)\n", obj)); | |
| 1337 | + JAS_LOGDEBUGF(100, "file_close(%p)\n", obj); | |
| 1155 | 1338 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); |
| 1156 | − ret = close(fileobj->fd); | |
| 1339 | + if (!(fileobj->flags & JAS_STREAM_FILEOBJ_NOCLOSE)) { | |
| 1340 | + ret = close(fileobj->fd); | |
| 1341 | + if (fileobj->flags & JAS_STREAM_FILEOBJ_DELONCLOSE) { | |
| 1342 | + unlink(fileobj->pathname); | |
| 1343 | + } | |
| 1344 | + } | |
| 1157 | 1345 | jas_free(fileobj); |
| 1158 | 1346 | return ret; |
| 1159 | 1347 | } |
| 1348 | + | |
| 1349 | +/******************************************************************************\ | |
| 1350 | +* Stdio file stream object. | |
| 1351 | +\******************************************************************************/ | |
| 1352 | + | |
| 1353 | +static ssize_t sfile_read(jas_stream_obj_t *obj, char *buf, size_t cnt) | |
| 1354 | +{ | |
| 1355 | + FILE *fp; | |
| 1356 | + size_t n; | |
| 1357 | + int result; | |
| 1358 | + JAS_LOGDEBUGF(100, "sfile_read(%p, %p, %zu)\n", obj, buf, cnt); | |
| 1359 | + fp = JAS_CAST(FILE *, obj); | |
| 1360 | +#if 0 | |
| 1361 | + n = fread(buf, 1, cnt, fp); | |
| 1362 | + if (n != cnt) { | |
| 1363 | + result = (!ferror(fp) && feof(fp)) ? n : -1; | |
| 1364 | + } else { | |
| 1365 | + result = n; | |
| 1366 | + } | |
| 1367 | +#else | |
| 1368 | + if (ferror(fp)) { | |
| 1369 | + result = -1; | |
| 1370 | + } else { | |
| 1371 | + n = fread(buf, 1, cnt, fp); | |
| 1372 | + return n; | |
| 1373 | + } | |
| 1374 | +#endif | |
| 1375 | + return result; | |
| 1376 | +} | |
| 1377 | + | |
| 1378 | +static ssize_t sfile_write(jas_stream_obj_t *obj, const char *buf, | |
| 1379 | + size_t cnt) | |
| 1380 | +{ | |
| 1381 | + FILE *fp; | |
| 1382 | + size_t n; | |
| 1383 | + JAS_LOGDEBUGF(100, "sfile_write(%p, %p, %zu)\n", obj, buf, cnt); | |
| 1384 | + fp = JAS_CAST(FILE *, obj); | |
| 1385 | + ssize_t result; | |
| 1386 | +#if 0 | |
| 1387 | + n = fwrite(buf, 1, cnt, fp); | |
| 1388 | + return (n != cnt) ? (-1) : cnt; | |
| 1389 | +#else | |
| 1390 | + if (ferror(fp)) { | |
| 1391 | + result = -1; | |
| 1392 | + } else { | |
| 1393 | + n = fwrite(buf, 1, cnt, fp); | |
| 1394 | + result = n; | |
| 1395 | + } | |
| 1396 | + return result; | |
| 1397 | +#endif | |
| 1398 | +} | |
| 1399 | + | |
| 1400 | +/* FIXME integral type */ | |
| 1401 | +static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin) | |
| 1402 | +{ | |
| 1403 | + FILE *fp; | |
| 1404 | + JAS_LOGDEBUGF(100, "sfile_seek(%p, %ld, %d)\n", obj, offset, origin); | |
| 1405 | + fp = JAS_CAST(FILE *, obj); | |
| 1406 | + return fseek(fp, offset, origin); | |
| 1407 | +} | |
| 1408 | + | |
| 1409 | +static int sfile_close(jas_stream_obj_t *obj) | |
| 1410 | +{ | |
| 1411 | + FILE *fp; | |
| 1412 | + JAS_LOGDEBUGF(100, "sfile_close(%p)\n", obj); | |
| 1413 | + fp = JAS_CAST(FILE *, obj); | |
| 1414 | + return fclose(fp); | |
| 1415 | +} | |
| @@ -0,0 +1,216 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2002 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/* | |
| 65 | + * String Library | |
| 66 | + * | |
| 67 | + * $Id$ | |
| 68 | + */ | |
| 69 | + | |
| 70 | +/******************************************************************************\ | |
| 71 | +* Includes | |
| 72 | +\******************************************************************************/ | |
| 73 | + | |
| 74 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 75 | + | |
| 76 | +#include "jasper/jas_string.h" | |
| 77 | +#include "jasper/jas_malloc.h" | |
| 78 | +#include "jasper/jas_debug.h" | |
| 79 | + | |
| 80 | +/******************************************************************************\ | |
| 81 | +* Miscellaneous Functions | |
| 82 | +\******************************************************************************/ | |
| 83 | + | |
| 84 | +/* This function is equivalent to the popular but non-standard (and | |
| 85 | + not-always-available) strdup function. */ | |
| 86 | + | |
| 87 | +char *jas_strdup(const char *s) | |
| 88 | +{ | |
| 89 | + size_t n; | |
| 90 | + char *p; | |
| 91 | + n = strlen(s) + 1; | |
| 92 | + if (!(p = jas_malloc(n))) { | |
| 93 | + return 0; | |
| 94 | + } | |
| 95 | + strcpy(p, s); | |
| 96 | + return p; | |
| 97 | +} | |
| 98 | + | |
| 99 | +char *jas_strtok(char *s, const char *delim, char **save_ptr) | |
| 100 | +{ | |
| 101 | +#if 1 | |
| 102 | + char *result; | |
| 103 | + char *end; | |
| 104 | + if (!s) { | |
| 105 | + s = *save_ptr; | |
| 106 | + } | |
| 107 | + if (*s != '\0') { | |
| 108 | + s += strspn(s, delim); | |
| 109 | + if (*s != '\0') { | |
| 110 | + end = s + strcspn(s, delim); | |
| 111 | + if (*end == '\0') { | |
| 112 | + *save_ptr = end; | |
| 113 | + } else { | |
| 114 | + *end = '\0'; | |
| 115 | + *save_ptr = end + 1; | |
| 116 | + } | |
| 117 | + result = s; | |
| 118 | + } else { | |
| 119 | + *save_ptr = s; | |
| 120 | + result = 0; | |
| 121 | + } | |
| 122 | + } else { | |
| 123 | + *save_ptr = s; | |
| 124 | + result = 0; | |
| 125 | + } | |
| 126 | + return result; | |
| 127 | +#else | |
| 128 | + return strtok_r(str, delim, save_ptr); | |
| 129 | +#endif | |
| 130 | +} | |
| 131 | + | |
| 132 | +JAS_EXPORT | |
| 133 | +int jas_stringtokenize(const char *string, const char *delim, | |
| 134 | + char ***tokens_buf, size_t *max_tokens_buf, size_t *num_tokens_buf) | |
| 135 | +{ | |
| 136 | + char **tokens = 0; | |
| 137 | + size_t max_tokens = 0; | |
| 138 | + size_t num_tokens = 0; | |
| 139 | + char **new_tokens; | |
| 140 | + size_t new_max_tokens; | |
| 141 | + char *buffer; | |
| 142 | + int ret = 0; | |
| 143 | + char *token = 0; | |
| 144 | + | |
| 145 | + if (!(buffer = jas_strdup(string))) { | |
| 146 | + ret = -1; | |
| 147 | + goto done; | |
| 148 | + } | |
| 149 | + //new_max_tokens = 1; | |
| 150 | + new_max_tokens = 0; | |
| 151 | + if (new_max_tokens > 0) { | |
| 152 | + if (!(tokens = jas_malloc(new_max_tokens * sizeof(char *)))) { | |
| 153 | + ret = -1; | |
| 154 | + goto done; | |
| 155 | + } | |
| 156 | + max_tokens = new_max_tokens; | |
| 157 | + } | |
| 158 | + | |
| 159 | + bool first = true; | |
| 160 | + char *saveptr = 0; | |
| 161 | + for (;;) { | |
| 162 | + char *cp; | |
| 163 | + if (!(cp = jas_strtok(first ? buffer : 0, delim, &saveptr))) { | |
| 164 | + break; | |
| 165 | + } | |
| 166 | + first = false; | |
| 167 | + if (!(token = jas_strdup(cp))) { | |
| 168 | + ret = -1; | |
| 169 | + goto done; | |
| 170 | + } | |
| 171 | + if (num_tokens == max_tokens) { | |
| 172 | + new_max_tokens = max_tokens ? 2 * max_tokens : 1; | |
| 173 | + if (!(new_tokens = jas_realloc(tokens, new_max_tokens * | |
| 174 | + sizeof(char *)))) { | |
| 175 | + ret = -1; | |
| 176 | + goto done; | |
| 177 | + } | |
| 178 | + tokens = new_tokens; | |
| 179 | + max_tokens = new_max_tokens; | |
| 180 | + } | |
| 181 | + assert(num_tokens < max_tokens); | |
| 182 | + tokens[num_tokens] = token; | |
| 183 | + token = 0; | |
| 184 | + ++num_tokens; | |
| 185 | + } | |
| 186 | + | |
| 187 | +done: | |
| 188 | + if (buffer) { | |
| 189 | + jas_free(buffer); | |
| 190 | + } | |
| 191 | + if (ret && tokens) { | |
| 192 | + for (int i = 0; i < num_tokens; ++i) { | |
| 193 | + jas_free(tokens[i]); | |
| 194 | + } | |
| 195 | + jas_free(tokens); | |
| 196 | + tokens = 0; | |
| 197 | + max_tokens = 0; | |
| 198 | + num_tokens = 0; | |
| 199 | + } | |
| 200 | + if (token) { | |
| 201 | + jas_free(token); | |
| 202 | + } | |
| 203 | + if (!ret) { | |
| 204 | + *tokens_buf = tokens; | |
| 205 | + *max_tokens_buf = max_tokens; | |
| 206 | + *num_tokens_buf = num_tokens; | |
| 207 | + } | |
| 208 | + if (jas_get_debug_level() >= 100) { | |
| 209 | + jas_eprintf("tokens %p; max_tokens %zu; num_tokens %zu\n", | |
| 210 | + JAS_CAST(void *, tokens), max_tokens, num_tokens); | |
| 211 | + for (int i = 0; i < num_tokens; ++i) { | |
| 212 | + jas_eprintf("[%d] = %s\n", i, tokens[i]); | |
| 213 | + } | |
| 214 | + } | |
| 215 | + return ret; | |
| 216 | +} | |
| @@ -0,0 +1,234 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2001-2002 Michael David Adams. | |
| 3 | + * All rights reserved. | |
| 4 | + */ | |
| 5 | + | |
| 6 | +/* __START_OF_JASPER_LICENSE__ | |
| 7 | + * | |
| 8 | + * JasPer License Version 2.0 | |
| 9 | + * | |
| 10 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 11 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 12 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 13 | + * | |
| 14 | + * All rights reserved. | |
| 15 | + * | |
| 16 | + * Permission is hereby granted, free of charge, to any person (the | |
| 17 | + * "User") obtaining a copy of this software and associated documentation | |
| 18 | + * files (the "Software"), to deal in the Software without restriction, | |
| 19 | + * including without limitation the rights to use, copy, modify, merge, | |
| 20 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 21 | + * persons to whom the Software is furnished to do so, subject to the | |
| 22 | + * following conditions: | |
| 23 | + * | |
| 24 | + * 1. The above copyright notices and this permission notice (which | |
| 25 | + * includes the disclaimer below) shall be included in all copies or | |
| 26 | + * substantial portions of the Software. | |
| 27 | + * | |
| 28 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 29 | + * promote products derived from the Software without specific prior | |
| 30 | + * written permission. | |
| 31 | + * | |
| 32 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 33 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 34 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 35 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 36 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 37 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 38 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 39 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 40 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 41 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 42 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 43 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 44 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 45 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 46 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 47 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 48 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 49 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 50 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 51 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 52 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 53 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 54 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 55 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 56 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 57 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 58 | + * | |
| 59 | + * __END_OF_JASPER_LICENSE__ | |
| 60 | + */ | |
| 61 | + | |
| 62 | +/* | |
| 63 | + * Tag-Value Parser Library | |
| 64 | + * | |
| 65 | + * $Id$ | |
| 66 | + */ | |
| 67 | + | |
| 68 | +/******************************************************************************\ | |
| 69 | +* Includes. | |
| 70 | +\******************************************************************************/ | |
| 71 | + | |
| 72 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 73 | + | |
| 74 | +#include "jasper/jas_tvp.h" | |
| 75 | +#include "jasper/jas_malloc.h" | |
| 76 | +#include "jasper/jas_string.h" | |
| 77 | + | |
| 78 | +/******************************************************************************\ | |
| 79 | +* Macros. | |
| 80 | +\******************************************************************************/ | |
| 81 | + | |
| 82 | +/* Is the specified character valid for a tag name? */ | |
| 83 | +#define JAS_TVP_ISTAG(x) \ | |
| 84 | + (isalpha(x) || (x) == '_' || isdigit(x)) | |
| 85 | + | |
| 86 | +/******************************************************************************\ | |
| 87 | +* Code for creating and destroying a tag-value parser. | |
| 88 | +\******************************************************************************/ | |
| 89 | + | |
| 90 | +jas_tvparser_t *jas_tvparser_create(const char *s) | |
| 91 | +{ | |
| 92 | + jas_tvparser_t *tvp; | |
| 93 | + if (!(tvp = jas_malloc(sizeof(jas_tvparser_t)))) { | |
| 94 | + return 0; | |
| 95 | + } | |
| 96 | + if (!(tvp->buf = jas_strdup(s))) { | |
| 97 | + jas_tvparser_destroy(tvp); | |
| 98 | + return 0; | |
| 99 | + } | |
| 100 | + tvp->pos = tvp->buf; | |
| 101 | + tvp->tag = 0; | |
| 102 | + tvp->val = 0; | |
| 103 | + return tvp; | |
| 104 | +} | |
| 105 | + | |
| 106 | +void jas_tvparser_destroy(jas_tvparser_t *tvp) | |
| 107 | +{ | |
| 108 | + if (tvp->buf) { | |
| 109 | + jas_free(tvp->buf); | |
| 110 | + } | |
| 111 | + jas_free(tvp); | |
| 112 | +} | |
| 113 | + | |
| 114 | +/******************************************************************************\ | |
| 115 | +* Main parsing code. | |
| 116 | +\******************************************************************************/ | |
| 117 | + | |
| 118 | +/* Get the next tag-value pair. */ | |
| 119 | +int jas_tvparser_next(jas_tvparser_t *tvp) | |
| 120 | +{ | |
| 121 | + char *p; | |
| 122 | + char *tag; | |
| 123 | + char *val; | |
| 124 | + | |
| 125 | + /* Skip any leading whitespace. */ | |
| 126 | + p = tvp->pos; | |
| 127 | + while (*p != '\0' && isspace(JAS_CAST(unsigned char, *p))) { | |
| 128 | + ++p; | |
| 129 | + } | |
| 130 | + | |
| 131 | + /* Has the end of the input data been reached? */ | |
| 132 | + if (*p == '\0') { | |
| 133 | + /* No more tags are present. */ | |
| 134 | + tvp->pos = p; | |
| 135 | + return 1; | |
| 136 | + } | |
| 137 | + | |
| 138 | + /* Does the tag name begin with a valid character? */ | |
| 139 | + if (!JAS_TVP_ISTAG(JAS_CAST(unsigned char, *p))) { | |
| 140 | + return -1; | |
| 141 | + } | |
| 142 | + | |
| 143 | + /* Remember where the tag name begins. */ | |
| 144 | + tag = p; | |
| 145 | + | |
| 146 | + /* Find the end of the tag name. */ | |
| 147 | + while (*p != '\0' && JAS_TVP_ISTAG(JAS_CAST(unsigned char, *p))) { | |
| 148 | + ++p; | |
| 149 | + } | |
| 150 | + | |
| 151 | + /* Has the end of the input data been reached? */ | |
| 152 | + if (*p == '\0') { | |
| 153 | + /* The value field is empty. */ | |
| 154 | + tvp->tag = tag; | |
| 155 | + tvp->val = ""; | |
| 156 | + tvp->pos = p; | |
| 157 | + return 0; | |
| 158 | + } | |
| 159 | + | |
| 160 | + /* Is a value field not present? */ | |
| 161 | + if (*p != '=') { | |
| 162 | + if (*p != '\0' && !isspace(JAS_CAST(unsigned char, *p))) { | |
| 163 | + return -1; | |
| 164 | + } | |
| 165 | + *p++ = '\0'; | |
| 166 | + tvp->tag = tag; | |
| 167 | + tvp->val = ""; | |
| 168 | + tvp->pos = p; | |
| 169 | + return 0; | |
| 170 | + } | |
| 171 | + | |
| 172 | + *p++ = '\0'; | |
| 173 | + | |
| 174 | + val = p; | |
| 175 | + while (*p != '\0' && !isspace(JAS_CAST(unsigned char, *p))) { | |
| 176 | + ++p; | |
| 177 | + } | |
| 178 | + | |
| 179 | + if (*p != '\0') { | |
| 180 | + *p++ = '\0'; | |
| 181 | + } | |
| 182 | + | |
| 183 | + tvp->pos = p; | |
| 184 | + tvp->tag = tag; | |
| 185 | + tvp->val = val; | |
| 186 | + | |
| 187 | + return 0; | |
| 188 | +} | |
| 189 | + | |
| 190 | +/******************************************************************************\ | |
| 191 | +* Code for querying the current tag/value. | |
| 192 | +\******************************************************************************/ | |
| 193 | + | |
| 194 | +/* Get the current tag. */ | |
| 195 | +const char *jas_tvparser_gettag(const jas_tvparser_t *tvp) | |
| 196 | +{ | |
| 197 | + return tvp->tag; | |
| 198 | +} | |
| 199 | + | |
| 200 | +/* Get the current value. */ | |
| 201 | +const char *jas_tvparser_getval(const jas_tvparser_t *tvp) | |
| 202 | +{ | |
| 203 | + return tvp->val; | |
| 204 | +} | |
| 205 | + | |
| 206 | +/******************************************************************************\ | |
| 207 | +* Miscellaneous code. | |
| 208 | +\******************************************************************************/ | |
| 209 | + | |
| 210 | +/* Lookup a tag by name. */ | |
| 211 | +const jas_taginfo_t *jas_taginfos_lookup(const jas_taginfo_t *taginfos, const char *name) | |
| 212 | +{ | |
| 213 | + const jas_taginfo_t *taginfo; | |
| 214 | + taginfo = taginfos; | |
| 215 | + while (taginfo->id >= 0) { | |
| 216 | + if (!strcmp(taginfo->name, name)) { | |
| 217 | + return taginfo; | |
| 218 | + } | |
| 219 | + ++taginfo; | |
| 220 | + } | |
| 221 | + return 0; | |
| 222 | +} | |
| 223 | + | |
| 224 | +/* This function is simply for convenience. */ | |
| 225 | +/* One can avoid testing for the special case of a null pointer, by | |
| 226 | + using this function. This function never returns a null pointer. */ | |
| 227 | +const jas_taginfo_t *jas_taginfo_nonull(const jas_taginfo_t *taginfo) | |
| 228 | +{ | |
| 229 | + static const jas_taginfo_t invalidtaginfo = { | |
| 230 | + -1, 0 | |
| 231 | + }; | |
| 232 | + | |
| 233 | + return taginfo ? taginfo : &invalidtaginfo; | |
| 234 | +} | |
| @@ -0,0 +1,69 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2001-2002 Michael David Adams. | |
| 3 | + * All rights reserved. | |
| 4 | + */ | |
| 5 | + | |
| 6 | +/* __START_OF_JASPER_LICENSE__ | |
| 7 | + * | |
| 8 | + * JasPer License Version 2.0 | |
| 9 | + * | |
| 10 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 11 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 12 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 13 | + * | |
| 14 | + * All rights reserved. | |
| 15 | + * | |
| 16 | + * Permission is hereby granted, free of charge, to any person (the | |
| 17 | + * "User") obtaining a copy of this software and associated documentation | |
| 18 | + * files (the "Software"), to deal in the Software without restriction, | |
| 19 | + * including without limitation the rights to use, copy, modify, merge, | |
| 20 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 21 | + * persons to whom the Software is furnished to do so, subject to the | |
| 22 | + * following conditions: | |
| 23 | + * | |
| 24 | + * 1. The above copyright notices and this permission notice (which | |
| 25 | + * includes the disclaimer below) shall be included in all copies or | |
| 26 | + * substantial portions of the Software. | |
| 27 | + * | |
| 28 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 29 | + * promote products derived from the Software without specific prior | |
| 30 | + * written permission. | |
| 31 | + * | |
| 32 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 33 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 34 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 35 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 36 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 37 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 38 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 39 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 40 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 41 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 42 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 43 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 44 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 45 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 46 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 47 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 48 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 49 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 50 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 51 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 52 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 53 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 54 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 55 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 56 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 57 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 58 | + * | |
| 59 | + * __END_OF_JASPER_LICENSE__ | |
| 60 | + */ | |
| 61 | + | |
| 62 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 63 | + | |
| 64 | +#include "jasper/jas_version.h" | |
| 65 | + | |
| 66 | +const char *jas_getversion() | |
| 67 | +{ | |
| 68 | + return JAS_VERSION; | |
| 69 | +} | |
| @@ -67,18 +67,39 @@ · 66 unmodified lines | ||
| 67 | 67 | #ifndef JAS_CM_H |
| 68 | 68 | #define JAS_CM_H |
| 69 | 69 | |
| 70 | +/******************************************************************************\ | |
| 71 | +* | |
| 72 | +\******************************************************************************/ | |
| 73 | + | |
| 70 | 74 | /* The configuration header file should be included first. */ |
| 71 | 75 | #include <jasper/jas_config.h> |
| 72 | 76 | |
| 77 | +#include <jasper/jas_types.h> | |
| 73 | 78 | #include <jasper/jas_icc.h> |
| 74 | 79 | |
| 75 | 80 | #ifdef __cplusplus |
| 76 | 81 | extern "C" { |
| 77 | 82 | #endif |
| 78 | 83 | |
| 84 | +/*! | |
| 85 | + * @addtogroup module_cm | |
| 86 | + * @{ | |
| 87 | + */ | |
| 88 | + | |
| 89 | +/******************************************************************************\ | |
| 90 | +* Types and Macros. | |
| 91 | +\******************************************************************************/ | |
| 92 | + | |
| 93 | +/*! | |
| 94 | +@brief | |
| 95 | +Color space. | |
| 96 | +*/ | |
| 79 | 97 | typedef unsigned jas_clrspc_t; |
| 80 | 98 | |
| 81 | −/* transform operations */ | |
| 99 | +/*! | |
| 100 | +@brief | |
| 101 | +Transform operations | |
| 102 | +*/ | |
| 82 | 103 | typedef enum { |
| 83 | 104 | JAS_CMXFORM_OP_FWD = 0, |
| 84 | 105 | JAS_CMXFORM_OP_REV = 1, |
| @@ -86,7 +107,10 @@ typedef enum { · 1 unmodified line | ||
| 86 | 107 | JAS_CMXFORM_OP_GAMUT = 3, |
| 87 | 108 | } jas_cmxform_op_t; |
| 88 | 109 | |
| 89 | −/* rendering intents */ | |
| 110 | +/*! | |
| 111 | +@brief | |
| 112 | +Rendering intents. | |
| 113 | +*/ | |
| 90 | 114 | typedef enum { |
| 91 | 115 | JAS_CMXFORM_INTENT_PER = 0, |
| 92 | 116 | JAS_CMXFORM_INTENT_RELCLR = 1, |
| @@ -94,24 +118,58 @@ typedef enum { · 1 unmodified line | ||
| 94 | 118 | JAS_CMXFORM_INTENT_SAT = 3, |
| 95 | 119 | } jas_cmxform_intent_t; |
| 96 | 120 | |
| 121 | +/*! | |
| 122 | +@brief | |
| 123 | +Number of rendering intents. | |
| 124 | +*/ | |
| 97 | 125 | #define JAS_CMXFORM_NUMINTENTS 4 |
| 98 | 126 | |
| 127 | +/*! | |
| 128 | +@brief | |
| 129 | +Transform optimization. | |
| 130 | +*/ | |
| 99 | 131 | typedef enum { |
| 100 | 132 | JAS_CMXFORM_OPTM_SPEED = 0, |
| 101 | 133 | JAS_CMXFORM_OPTM_SIZE = 1, |
| 102 | 134 | JAS_CMXFORM_OPTM_ACC = 2, |
| 103 | 135 | } jas_cmxform_optm_t; |
| 104 | 136 | |
| 105 | − | |
| 137 | +/*! | |
| 138 | +@brief | |
| 139 | +Create a color space. | |
| 140 | +*/ | |
| 106 | 141 | #define jas_clrspc_create(fam, mbr) (((fam) << 8) | (mbr)) |
| 142 | + | |
| 143 | +/*! | |
| 144 | +@brief | |
| 145 | +Get the family of a color space. | |
| 146 | +*/ | |
| 147 | + | |
| 107 | 148 | #define jas_clrspc_fam(clrspc) ((clrspc) >> 8) |
| 149 | + | |
| 150 | +/*! | |
| 151 | +@brief | |
| 152 | +Get the (family) member of a color space. | |
| 153 | +*/ | |
| 108 | 154 | #define jas_clrspc_mbr(clrspc) ((clrspc) & 0xff) |
| 155 | + | |
| 156 | +/*! | |
| 157 | +@brief | |
| 158 | +Test if a color space is generic. | |
| 159 | +*/ | |
| 109 | 160 | #define jas_clrspc_isgeneric(clrspc) (!jas_clrspc_mbr(clrspc)) |
| 161 | + | |
| 162 | +/*! | |
| 163 | +@brief | |
| 164 | +Test if a color space is unknown. | |
| 165 | +*/ | |
| 110 | 166 | #define jas_clrspc_isunknown(clrspc) ((clrspc) & JAS_CLRSPC_UNKNOWNMASK) |
| 111 | 167 | |
| 112 | 168 | #define JAS_CLRSPC_UNKNOWNMASK 0x4000 |
| 113 | 169 | |
| 114 | −/* color space families */ | |
| 170 | +/*! | |
| 171 | +@brief Color space families. | |
| 172 | +*/ | |
| 115 | 173 | #define JAS_CLRSPC_FAM_UNKNOWN 0 |
| 116 | 174 | #define JAS_CLRSPC_FAM_XYZ 1 |
| 117 | 175 | #define JAS_CLRSPC_FAM_LAB 2 |
| @@ -119,7 +177,9 @@ typedef enum { · 1 unmodified line | ||
| 119 | 177 | #define JAS_CLRSPC_FAM_RGB 4 |
| 120 | 178 | #define JAS_CLRSPC_FAM_YCBCR 5 |
| 121 | 179 | |
| 122 | −/* specific color spaces */ | |
| 180 | +/*! | |
| 181 | +@brief Specific color spaces. | |
| 182 | +*/ | |
| 123 | 183 | #define JAS_CLRSPC_UNKNOWN JAS_CLRSPC_UNKNOWNMASK |
| 124 | 184 | #define JAS_CLRSPC_CIEXYZ jas_clrspc_create(JAS_CLRSPC_FAM_XYZ, 1) |
| 125 | 185 | #define JAS_CLRSPC_CIELAB jas_clrspc_create(JAS_CLRSPC_FAM_LAB, 1) |
| @@ -127,7 +187,9 @@ typedef enum { · 1 unmodified line | ||
| 127 | 187 | #define JAS_CLRSPC_SRGB jas_clrspc_create(JAS_CLRSPC_FAM_RGB, 1) |
| 128 | 188 | #define JAS_CLRSPC_SYCBCR jas_clrspc_create(JAS_CLRSPC_FAM_YCBCR, 1) |
| 129 | 189 | |
| 130 | −/* generic color spaces */ | |
| 190 | +/*! | |
| 191 | +@brief Generic color spaces. | |
| 192 | +*/ | |
| 131 | 193 | #define JAS_CLRSPC_GENRGB jas_clrspc_create(JAS_CLRSPC_FAM_RGB, 0) |
| 132 | 194 | #define JAS_CLRSPC_GENGRAY jas_clrspc_create(JAS_CLRSPC_FAM_GRAY, 0) |
| 133 | 195 | #define JAS_CLRSPC_GENYCBCR jas_clrspc_create(JAS_CLRSPC_FAM_YCBCR, 0) |
| @@ -142,10 +204,17 @@ typedef enum { · 8 unmodified lines | ||
| 142 | 204 | |
| 143 | 205 | #define JAS_CLRSPC_CHANIND_GRAY_Y 0 |
| 144 | 206 | |
| 207 | +/*! | |
| 208 | +Real-number type. | |
| 209 | +*/ | |
| 145 | 210 | typedef double jas_cmreal_t; |
| 146 | 211 | |
| 147 | 212 | struct jas_cmpxform_s; |
| 148 | 213 | |
| 214 | +/*! | |
| 215 | +@brief | |
| 216 | +Component format. | |
| 217 | +*/ | |
| 149 | 218 | typedef struct { |
| 150 | 219 | long *buf; |
| 151 | 220 | unsigned prec; |
| @@ -154,21 +223,38 @@ typedef struct { · 2 unmodified lines | ||
| 154 | 223 | unsigned height; |
| 155 | 224 | } jas_cmcmptfmt_t; |
| 156 | 225 | |
| 226 | +/*! | |
| 227 | +@brief | |
| 228 | +Pixmap (i.e., multicomponent) format. | |
| 229 | +*/ | |
| 157 | 230 | typedef struct { |
| 158 | 231 | unsigned numcmpts; |
| 159 | 232 | jas_cmcmptfmt_t *cmptfmts; |
| 160 | 233 | } jas_cmpixmap_t; |
| 161 | 234 | |
| 235 | +/*! | |
| 236 | +@brief | |
| 237 | +Transform operations. | |
| 238 | +*/ | |
| 162 | 239 | typedef struct { |
| 163 | 240 | void (*destroy)(struct jas_cmpxform_s *pxform); |
| 164 | 241 | int (*apply)(const struct jas_cmpxform_s *pxform, const jas_cmreal_t *in, jas_cmreal_t *out, unsigned cnt); |
| 242 | + void (*dump)(struct jas_cmpxform_s *pxform); | |
| 165 | 243 | } jas_cmpxformops_t; |
| 166 | 244 | |
| 245 | +/*! | |
| 246 | +@brief | |
| 247 | +Shaper matrix look-up table (LUT). | |
| 248 | +*/ | |
| 167 | 249 | typedef struct { |
| 168 | 250 | jas_cmreal_t *data; |
| 169 | 251 | unsigned size; |
| 170 | 252 | } jas_cmshapmatlut_t; |
| 171 | 253 | |
| 254 | +/*! | |
| 255 | +@brief | |
| 256 | +Shaper matrix. | |
| 257 | +*/ | |
| 172 | 258 | typedef struct { |
| 173 | 259 | int mono; |
| 174 | 260 | int order; |
| @@ -178,36 +264,54 @@ typedef struct { · 3 unmodified lines | ||
| 178 | 264 | jas_cmreal_t mat[3][4]; |
| 179 | 265 | } jas_cmshapmat_t; |
| 180 | 266 | |
| 267 | +/*! | |
| 268 | +@brief | |
| 269 | +Shaper look-up table (LUT). | |
| 270 | +*/ | |
| 181 | 271 | typedef struct { |
| 182 | 272 | int order; |
| 183 | 273 | } jas_cmshaplut_t; |
| 184 | 274 | |
| 275 | +/*! | |
| 276 | +@brief | |
| 277 | +Color space conversion. | |
| 278 | +*/ | |
| 185 | 279 | typedef struct { |
| 186 | 280 | unsigned inclrspc; |
| 187 | 281 | unsigned outclrspc; |
| 188 | 282 | } jas_cmclrspcconv_t; |
| 189 | 283 | |
| 190 | −#define jas_align_t double | |
| 191 | − | |
| 284 | +/*! | |
| 285 | +@brief | |
| 286 | +Transform class. | |
| 287 | +*/ | |
| 192 | 288 | typedef struct jas_cmpxform_s { |
| 193 | 289 | unsigned refcnt; |
| 194 | 290 | const jas_cmpxformops_t *ops; |
| 195 | 291 | unsigned numinchans; |
| 196 | 292 | unsigned numoutchans; |
| 197 | 293 | union { |
| 198 | − jas_align_t dummy; | |
| 294 | + max_align_t dummy; | |
| 199 | 295 | jas_cmshapmat_t shapmat; |
| 200 | 296 | jas_cmshaplut_t shaplut; |
| 201 | 297 | jas_cmclrspcconv_t clrspcconv; |
| 202 | 298 | } data; |
| 203 | 299 | } jas_cmpxform_t; |
| 204 | 300 | |
| 301 | +/*! | |
| 302 | +@brief | |
| 303 | +Primitive transform sequence class. | |
| 304 | +*/ | |
| 205 | 305 | typedef struct { |
| 206 | 306 | unsigned numpxforms; |
| 207 | 307 | unsigned maxpxforms; |
| 208 | 308 | jas_cmpxform_t **pxforms; |
| 209 | 309 | } jas_cmpxformseq_t; |
| 210 | 310 | |
| 311 | +/*! | |
| 312 | +@brief | |
| 313 | +Primitive transform class. | |
| 314 | +*/ | |
| 211 | 315 | typedef struct { |
| 212 | 316 | unsigned numinchans; |
| 213 | 317 | unsigned numoutchans; |
| @@ -219,6 +323,9 @@ typedef struct { · 5 unmodified lines | ||
| 219 | 323 | |
| 220 | 324 | #define JAS_CMPROF_NUMPXFORMSEQS 13 |
| 221 | 325 | |
| 326 | +/*! | |
| 327 | +Color-management (CM) profile. | |
| 328 | +*/ | |
| 222 | 329 | typedef struct { |
| 223 | 330 | jas_clrspc_t clrspc; |
| 224 | 331 | unsigned numchans; |
| @@ -228,6 +335,10 @@ typedef struct { · 3 unmodified lines | ||
| 228 | 335 | jas_cmpxformseq_t *pxformseqs[JAS_CMPROF_NUMPXFORMSEQS]; |
| 229 | 336 | } jas_cmprof_t; |
| 230 | 337 | |
| 338 | +/******************************************************************************\ | |
| 339 | +* | |
| 340 | +\******************************************************************************/ | |
| 341 | + | |
| 231 | 342 | #if 0 |
| 232 | 343 | typedef int_fast32_t jas_cmattrname_t; |
| 233 | 344 | typedef int_fast32_t jas_cmattrval_t; |
| @@ -242,27 +353,144 @@ int jas_cm_prof_setattr(jas_cm_prof_t *prof, jas_cm_attrname_t name, void *val); · 8 unmodified lines | ||
| 242 | 353 | void *jas_cm_prof_getattr(jas_cm_prof_t *prof, jas_cm_attrname_t name); |
| 243 | 354 | #endif |
| 244 | 355 | |
| 245 | −JAS_DLLEXPORT jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof, const jas_cmprof_t *outprof, | |
| 246 | − const jas_cmprof_t *proofprof, jas_cmxform_op_t op, jas_cmxform_intent_t intent, jas_cmxform_optm_t optimize); | |
| 356 | +/******************************************************************************\ | |
| 357 | +* Color-management (CM) profile class. | |
| 358 | +\******************************************************************************/ | |
| 247 | 359 | |
| 248 | −JAS_DLLEXPORT void jas_cmxform_destroy(jas_cmxform_t *xform); | |
| 360 | +/*! | |
| 361 | +@brief | |
| 362 | +Create a color-management profile from an ICC profile. | |
| 363 | + | |
| 364 | +@details | |
| 365 | +This function creates a CM profile from an ICC profile. | |
| 366 | + | |
| 367 | +@returns | |
| 368 | +If successful, a pointer to the created CM profile is returned. | |
| 369 | +Otherwise, a null pointer is returned. | |
| 370 | +*/ | |
| 371 | +JAS_EXPORT | |
| 372 | +jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof); | |
| 373 | + | |
| 374 | +/*! | |
| 375 | +@brief | |
| 376 | +Create a color-management profile from a color space. | |
| 377 | + | |
| 378 | +@details | |
| 379 | +The function creates a CM profile from a color space. | |
| 380 | + | |
| 381 | +@returns | |
| 382 | +If successful, a pointer to the created CM profile is returned. | |
| 383 | +Otherwise, a null pointer is returned. | |
| 384 | +*/ | |
| 385 | +JAS_EXPORT | |
| 386 | +jas_cmprof_t *jas_cmprof_createfromclrspc(jas_clrspc_t clrspc); | |
| 387 | + | |
| 388 | +/*! | |
| 389 | +@brief Destroy a color-management profile. | |
| 390 | + | |
| 391 | +@details | |
| 392 | +*/ | |
| 393 | +JAS_EXPORT | |
| 394 | +void jas_cmprof_destroy(jas_cmprof_t *prof); | |
| 395 | + | |
| 396 | +/*! | |
| 397 | +@brief | |
| 398 | +Copy a color-management profile. | |
| 399 | + | |
| 400 | +@details | |
| 401 | +This function creates a clone (i.e., copy) of a CM profile. | |
| 402 | + | |
| 403 | +@returns | |
| 404 | +If successful, a pointer to the newly created CM profile is returned. | |
| 405 | +Otherwise, a null pointer is returned. | |
| 406 | +*/ | |
| 407 | +JAS_EXPORT | |
| 408 | +jas_cmprof_t *jas_cmprof_copy(const jas_cmprof_t *prof); | |
| 409 | + | |
| 410 | +/*! | |
| 411 | +@brief | |
| 412 | +Create a ICC profile from a CM profile. | |
| 413 | + | |
| 414 | +@details | |
| 415 | +This function creates an ICC profile from a CM profile. | |
| 416 | + | |
| 417 | +@returns | |
| 418 | +If successful, a pointer to the created ICC profile is returned. | |
| 419 | +Otherwise, a null pointer is returned. | |
| 420 | +*/ | |
| 421 | +JAS_EXPORT | |
| 422 | +jas_iccprof_t *jas_iccprof_createfromcmprof(const jas_cmprof_t *prof); | |
| 423 | + | |
| 424 | +/******************************************************************************\ | |
| 425 | +* Color-Management (CM) Transform. | |
| 426 | +\******************************************************************************/ | |
| 249 | 427 | |
| 250 | −/* Apply a transform to data. */ | |
| 251 | −JAS_DLLEXPORT int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, | |
| 428 | +/*! | |
| 429 | +@brief | |
| 430 | +Create a transform from a CM profile. | |
| 431 | + | |
| 432 | +@details | |
| 433 | + | |
| 434 | +@returns | |
| 435 | +If successful, a pointer to the created transform is returned. | |
| 436 | +Otherwise, a null pointer is returned. | |
| 437 | +*/ | |
| 438 | +JAS_EXPORT | |
| 439 | +jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof, | |
| 440 | + const jas_cmprof_t *outprof, const jas_cmprof_t *proofprof, | |
| 441 | + jas_cmxform_op_t op, jas_cmxform_intent_t intent, | |
| 442 | + jas_cmxform_optm_t optimize); | |
| 443 | + | |
| 444 | +/*! | |
| 445 | +@brief | |
| 446 | +Destroy a transform. | |
| 447 | + | |
| 448 | +@details | |
| 449 | +*/ | |
| 450 | +JAS_EXPORT | |
| 451 | +void jas_cmxform_destroy(jas_cmxform_t *xform); | |
| 452 | + | |
| 453 | +/*! | |
| 454 | +@brief | |
| 455 | +Apply a transform to data. | |
| 456 | + | |
| 457 | +@details | |
| 458 | + | |
| 459 | +@returns | |
| 460 | +If successful, zero is returned. | |
| 461 | +Otherwise, a nonzero value is returned. | |
| 462 | +*/ | |
| 463 | +JAS_EXPORT | |
| 464 | +int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, | |
| 252 | 465 | jas_cmpixmap_t *out); |
| 253 | 466 | |
| 254 | −/* Create a profile. */ | |
| 255 | −JAS_DLLEXPORT jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof); | |
| 256 | −JAS_DLLEXPORT jas_cmprof_t *jas_cmprof_createfromclrspc(jas_clrspc_t clrspc); | |
| 467 | +/******************************************************************************\ | |
| 468 | +* Miscellany. | |
| 469 | +\******************************************************************************/ | |
| 470 | + | |
| 471 | +/*! | |
| 472 | +@brief | |
| 473 | +Get the number of channels associated with a particular color space. | |
| 257 | 474 | |
| 258 | −/* Destroy a profile. */ | |
| 259 | −JAS_DLLEXPORT void jas_cmprof_destroy(jas_cmprof_t *prof); | |
| 475 | +@details | |
| 260 | 476 | |
| 477 | +@returns | |
| 478 | +*/ | |
| 261 | 479 | unsigned jas_clrspc_numchans(jas_clrspc_t clrspc); |
| 262 | −JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_createfromcmprof(const jas_cmprof_t *prof); | |
| 263 | 480 | |
| 481 | +/*! | |
| 482 | +@brief | |
| 483 | +Get the color space associated with a color-management profile. | |
| 484 | + | |
| 485 | +@details | |
| 486 | + | |
| 487 | +@returns | |
| 488 | +*/ | |
| 264 | 489 | #define jas_cmprof_clrspc(prof) ((prof)->clrspc) |
| 265 | −JAS_DLLEXPORT jas_cmprof_t *jas_cmprof_copy(const jas_cmprof_t *prof); | |
| 490 | + | |
| 491 | +/*! | |
| 492 | + * @} | |
| 493 | + */ | |
| 266 | 494 | |
| 267 | 495 | #ifdef __cplusplus |
| 268 | 496 | } |
| @@ -66,38 +66,82 @@ · 65 unmodified lines | ||
| 66 | 66 | #include <jasper/jas_config.h> |
| 67 | 67 | |
| 68 | 68 | #ifdef _MSC_VER |
| 69 | −#ifndef __cplusplus | |
| 70 | −#undef inline | |
| 71 | −#define inline __inline | |
| 69 | +# ifndef __cplusplus | |
| 70 | +# undef inline | |
| 71 | +# define inline __inline | |
| 72 | +# endif | |
| 72 | 73 | #endif |
| 74 | + | |
| 75 | +#if defined(__GNUC__) | |
| 76 | +# define JAS_DEPRECATED __attribute__((deprecated)) | |
| 77 | +#else | |
| 78 | +# define JAS_DEPRECATED | |
| 79 | +#endif | |
| 80 | + | |
| 81 | +#if defined(__GNUC__) | |
| 82 | +# define JAS_ATTRIBUTE_CONST __attribute__((const)) | |
| 83 | +#else | |
| 84 | +# define JAS_ATTRIBUTE_CONST | |
| 85 | +#endif | |
| 86 | + | |
| 87 | +#if defined(__GNUC__) | |
| 88 | +# define JAS_ATTRIBUTE_PURE __attribute__((pure)) | |
| 89 | +#else | |
| 90 | +# define JAS_ATTRIBUTE_PURE | |
| 91 | +#endif | |
| 92 | + | |
| 93 | +#if defined(__GNUC__) | |
| 94 | +# define JAS_FORCE_INLINE inline __attribute__((always_inline)) | |
| 95 | +#else | |
| 96 | +# define JAS_FORCE_INLINE inline | |
| 73 | 97 | #endif |
| 74 | 98 | |
| 75 | −#ifdef __GNUC__ | |
| 76 | −#define JAS_DEPRECATED __attribute__((deprecated)) | |
| 77 | −#define JAS_ATTRIBUTE_CONST __attribute__((const)) | |
| 78 | −#define JAS_ATTRIBUTE_PURE __attribute__((pure)) | |
| 79 | −#define JAS_FORCE_INLINE inline __attribute__((always_inline)) | |
| 80 | −#define JAS_UNREACHABLE() __builtin_unreachable() | |
| 81 | −#define JAS_LIKELY(x) __builtin_expect (!!(x), 1) | |
| 82 | −#define JAS_UNLIKELY(x) __builtin_expect (!!(x), 0) | |
| 99 | +#if defined(__GNUC__) | |
| 100 | +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) | |
| 101 | +# define JAS_UNREACHABLE() __builtin_unreachable() | |
| 102 | +# else | |
| 103 | +# define JAS_UNREACHABLE() | |
| 104 | +# endif | |
| 105 | +#elif defined(__clang__) | |
| 106 | +# define JAS_UNREACHABLE() __builtin_unreachable() | |
| 107 | +#elif defined(_MSC_VER) | |
| 108 | +# define JAS_UNREACHABLE() __assume(0) | |
| 83 | 109 | #else |
| 84 | −#define JAS_DEPRECATED | |
| 85 | −#define JAS_ATTRIBUTE_CONST | |
| 86 | −#define JAS_ATTRIBUTE_PURE | |
| 87 | −#define JAS_FORCE_INLINE inline | |
| 88 | −#define JAS_UNREACHABLE() | |
| 89 | −#define JAS_LIKELY(x) (x) | |
| 90 | −#define JAS_UNLIKELY(x) (x) | |
| 110 | +# define JAS_UNREACHABLE() | |
| 91 | 111 | #endif |
| 92 | 112 | |
| 93 | −#ifdef __clang__ | |
| 94 | −#define JAS_ATTRIBUTE_DISABLE_USAN \ | |
| 95 | − __attribute__((no_sanitize("undefined"))) | |
| 96 | −#elif defined(__GNUC__) && __GNUC__ >= 6 | |
| 97 | −#define JAS_ATTRIBUTE_DISABLE_USAN \ | |
| 98 | − __attribute__((no_sanitize_undefined)) | |
| 113 | +#if defined(__GNUC__) | |
| 114 | +# define JAS_LIKELY(x) __builtin_expect (!!(x), 1) | |
| 99 | 115 | #else |
| 100 | −#define JAS_ATTRIBUTE_DISABLE_USAN | |
| 116 | +# define JAS_LIKELY(x) (x) | |
| 101 | 117 | #endif |
| 102 | 118 | |
| 119 | +#if defined(__GNUC__) | |
| 120 | +# define JAS_UNLIKELY(x) __builtin_expect (!!(x), 0) | |
| 121 | +#else | |
| 122 | +# define JAS_UNLIKELY(x) (x) | |
| 123 | +#endif | |
| 124 | + | |
| 125 | +#if defined(__GNUC__) && __GNUC__ >= 6 | |
| 126 | +# define JAS_ATTRIBUTE_DISABLE_UBSAN \ | |
| 127 | + __attribute__((no_sanitize_undefined)) | |
| 128 | +#elif defined(__clang__) | |
| 129 | +# define JAS_ATTRIBUTE_DISABLE_UBSAN \ | |
| 130 | + __attribute__((no_sanitize("undefined"))) | |
| 131 | +#else | |
| 132 | +# define JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 133 | +#endif | |
| 134 | + | |
| 135 | +#ifdef __has_builtin | |
| 136 | +#define jas_has_builtin(x) __has_builtin(x) | |
| 137 | +#else | |
| 138 | +#define jas_has_builtin(x) 0 | |
| 139 | +#endif | |
| 140 | + | |
| 141 | +/*! | |
| 142 | +@brief | |
| 143 | +Indicate that a variable may be unused (in order to avoid a compiler warning). | |
| 144 | +*/ | |
| 145 | +#define JAS_UNUSED(x) USED(x) | |
| 146 | + | |
| 103 | 147 | #endif |
| @@ -4,17 +4,87 @@ · 3 unmodified lines | ||
| 4 | 4 | #include <u.h> |
| 5 | 5 | #include <libc.h> |
| 6 | 6 | #include <ctype.h> |
| 7 | +#include <stdio.h> | |
| 8 | + | |
| 9 | +#define bool int | |
| 10 | +#define false 0 | |
| 11 | +#define true 1 | |
| 12 | + | |
| 13 | +#define PRIxFAST32 "x" | |
| 14 | +#define PRIxFAST16 PRIxFAST32 | |
| 15 | +#define PRIuFAST32 "ud" | |
| 16 | +#define PRIuFAST16 PRIuFAST32 | |
| 17 | +#define PRIiFAST32 "d" | |
| 18 | +#define PRIdPTR "p" | |
| 19 | + | |
| 20 | +#define PRIuLEAST32 PRIuFAST32 | |
| 21 | +#define PRIiLEAST32 PRIiFAST32 | |
| 22 | +#define PRIxLEAST32 PRIxFAST32 | |
| 23 | +#define PRIxLEAST16 PRIxFAST16 | |
| 24 | + | |
| 25 | +typedef u8int uint_least8_t; | |
| 26 | +typedef s8int int_least8_t; | |
| 27 | +typedef u16int uint_least16_t; | |
| 28 | +typedef s16int int_least16_t; | |
| 29 | +typedef u32int uint_least32_t; | |
| 30 | +typedef s32int int_least32_t; | |
| 31 | +typedef u64int uint_least64_t; | |
| 32 | + | |
| 33 | +typedef u8int uint_fast8_t; | |
| 34 | +typedef u16int uint_fast16_t; | |
| 35 | +typedef s16int int_fast16_t; | |
| 36 | +typedef u32int uint_fast32_t; | |
| 37 | +typedef s32int int_fast32_t; | |
| 38 | +typedef u64int uint_fast64_t; | |
| 39 | +typedef s64int int_least64_t; | |
| 40 | + | |
| 41 | +// FIXME | |
| 42 | +typedef s64int intmax_t; | |
| 43 | +typedef long ssize_t; | |
| 44 | +typedef ulong size_t; | |
| 45 | + | |
| 46 | +#define SIZE_MAX 0xffffffffU | |
| 47 | +#define LONG_MAX 0x7fffffffL | |
| 48 | +#define INT_FAST32_MAX 0x7fffffff | |
| 49 | +#define INT_FAST32_MIN (-INT_FAST32_MAX-1) | |
| 50 | +#define UINT_FAST32_MAX 0xffffffffU | |
| 51 | +#define INT_LEAST64_MAX 0x7fffffffffffffff | |
| 52 | +#define INT_LEAST64_MIN ((s64int)0x8000000000000000ULL) | |
| 53 | +#define UINT_LEAST64_MAX 0xffffffffffffffffULL | |
| 54 | + | |
| 55 | +#define INT_LEAST32_MIN INT_FAST32_MIN | |
| 56 | +#define INT_LEAST32_MAX INT_FAST32_MAX | |
| 57 | +#define UINT_LEAST32_MAX UINT_FAST32_MAX | |
| 58 | +#define INT_MAX INT_FAST32_MAX | |
| 59 | + | |
| 60 | +#define DBL_MAX 1.7976931348623157E+308 | |
| 61 | + | |
| 62 | +#define O_RDWR ORDWR | |
| 63 | +#define O_RDONLY OREAD | |
| 64 | +#define O_WRONLY OWRITE | |
| 65 | +#define O_BINARY 0 | |
| 66 | +#define O_TRUNC OTRUNC | |
| 67 | +#define O_CLOEXEC OCEXEC | |
| 68 | + | |
| 69 | +// FIXME | |
| 70 | +#define O_APPEND 0 | |
| 71 | +#define O_CREAT 0 | |
| 72 | + | |
| 7 | 73 | #include <jasper/jas_compiler.h> |
| 8 | 74 | #include <jasper/jas_dll.h> |
| 9 | 75 | |
| 10 | 76 | #define JAS_VERSION "plan9" |
| 77 | +#define JAS_DEFAULT_MAX_MEM_USAGE (512*1024*1024) | |
| 11 | 78 | #define JAS_ENABLE_32BIT 1 |
| 12 | −#define JAS_INCLUDE_JP2_CODEC 1 | |
| 79 | +#define JAS_ENABLE_JPC_CODEC 1 | |
| 80 | +#define JAS_ENABLE_JP2_CODEC 1 | |
| 13 | 81 | #define JAS_INCLUDE_JPC_CODEC 1 |
| 82 | +#define JAS_INCLUDE_JP2_CODEC 1 | |
| 14 | 83 | #define JAS_DEC_DEFAULT_MAX_SAMPLES (64 * ((size_t) 1048576)) |
| 15 | 84 | #define NDEBUG |
| 16 | −#define NULL nil | |
| 85 | +#define JAS_EXPORT | |
| 17 | 86 | |
| 18 | −typedef usize size_t; | |
| 87 | +#define unlink remove | |
| 88 | +#define lseek seek | |
| 19 | 89 | |
| 20 | 90 | #endif |
| @@ -74,6 +74,9 @@ · 73 unmodified lines | ||
| 74 | 74 | /* The configuration header file should be included first. */ |
| 75 | 75 | #include <jasper/jas_config.h> |
| 76 | 76 | |
| 77 | +#include "jasper/jas_init.h" | |
| 78 | +#include "jasper/jas_debug.h" | |
| 79 | + | |
| 77 | 80 | #ifdef __cplusplus |
| 78 | 81 | extern "C" { |
| 79 | 82 | #endif |
| @@ -86,25 +89,112 @@ extern "C" { · 6 unmodified lines | ||
| 86 | 89 | level is set sufficiently high. */ |
| 87 | 90 | #if !defined(NDEBUG) |
| 88 | 91 | #define JAS_DBGLOG(n, x) \ |
| 89 | − ((jas_getdbglevel() >= (n)) ? (jas_eprintf x) : 0) | |
| 92 | + ((jas_get_debug_level() >= (n)) ? (jas_eprintf x) : 0) | |
| 90 | 93 | #else |
| 91 | 94 | #define JAS_DBGLOG(n, x) |
| 92 | 95 | #endif |
| 93 | 96 | |
| 94 | −/* Get the library debug level. */ | |
| 95 | −JAS_ATTRIBUTE_CONST | |
| 96 | −JAS_DLLEXPORT int jas_getdbglevel(void); | |
| 97 | +#if !defined(NDEBUG) | |
| 98 | +#define JAS_LOGDEBUGF(n, ...) \ | |
| 99 | + ((jas_get_debug_level() >= (n)) ? jas_logdebugf((n), __VA_ARGS__) : 0) | |
| 100 | +#else | |
| 101 | +#define JAS_LOGDEBUGF(n, ...) | |
| 102 | +#endif | |
| 103 | + | |
| 104 | +/*! | |
| 105 | +@brief | |
| 106 | +Warn about the use of deprecated functionality. | |
| 107 | +*/ | |
| 108 | +JAS_EXPORT | |
| 109 | +void jas_deprecated(const char *fmt, ...); | |
| 110 | + | |
| 111 | +/*! | |
| 112 | +@brief | |
| 113 | +Get the library debug level. | |
| 114 | + | |
| 115 | +@deprecated | |
| 116 | +This function is deprecated. | |
| 117 | +*/ | |
| 118 | +JAS_DEPRECATED | |
| 119 | +static inline | |
| 120 | +int jas_getdbglevel(void) | |
| 121 | +{ | |
| 122 | + jas_deprecated("jas_getdbglevel is deprecated\n"); | |
| 123 | + return jas_get_debug_level(); | |
| 124 | +} | |
| 125 | + | |
| 126 | +/*! | |
| 127 | +@brief | |
| 128 | +Set the library debug level. | |
| 129 | +*/ | |
| 130 | +JAS_EXPORT | |
| 131 | +int jas_setdbglevel(int dbglevel); | |
| 132 | + | |
| 133 | +/*! | |
| 134 | +@brief | |
| 135 | +Print formatted text for the standard error stream (i.e., stderr). | |
| 136 | +*/ | |
| 137 | +JAS_EXPORT | |
| 138 | +int jas_eprintf(const char *fmt, ...); | |
| 139 | + | |
| 140 | +/*! | |
| 141 | +@brief | |
| 142 | +Generate a generic log message. | |
| 143 | +*/ | |
| 144 | +JAS_EXPORT | |
| 145 | +int jas_logprintf(const char *fmt, ...); | |
| 146 | + | |
| 147 | +/*! | |
| 148 | +@brief | |
| 149 | +Generate an error log message. | |
| 150 | +*/ | |
| 151 | +JAS_EXPORT | |
| 152 | +int jas_logerrorf(const char *fmt, ...); | |
| 153 | + | |
| 154 | +/*! | |
| 155 | +@brief | |
| 156 | +Generate a warning log message. | |
| 157 | +*/ | |
| 158 | +JAS_EXPORT | |
| 159 | +int jas_logwarnf(const char *fmt, ...); | |
| 160 | + | |
| 161 | +/*! | |
| 162 | +@brief | |
| 163 | +Generate an informational log message. | |
| 164 | +*/ | |
| 165 | +JAS_EXPORT | |
| 166 | +int jas_loginfof(const char *fmt, ...); | |
| 97 | 167 | |
| 98 | −/* Set the library debug level. */ | |
| 99 | −JAS_DLLEXPORT int jas_setdbglevel(int dbglevel); | |
| 168 | +/*! | |
| 169 | +@brief | |
| 170 | +Generate a debugging log message. | |
| 171 | +*/ | |
| 172 | +JAS_EXPORT | |
| 173 | +int jas_logdebugf(int priority, const char *fmt, ...); | |
| 100 | 174 | |
| 101 | −/* Perform formatted output to standard error. */ | |
| 102 | −JAS_DLLEXPORT int jas_eprintf(const char *fmt, ...); | |
| 175 | +/*! | |
| 176 | +@brief | |
| 177 | +Dump memory. | |
| 178 | +*/ | |
| 179 | +int jas_logmemdump(const void *data, size_t len); | |
| 103 | 180 | |
| 104 | −/* Convert to a string literal */ | |
| 181 | +/*! | |
| 182 | +@brief | |
| 183 | +Dump memory to a stream. | |
| 184 | +*/ | |
| 185 | +JAS_EXPORT | |
| 186 | +int jas_memdump(FILE *out, const void *data, size_t len); | |
| 187 | + | |
| 188 | +/*! | |
| 189 | +@brief | |
| 190 | +Convert to a string literal. | |
| 191 | +*/ | |
| 105 | 192 | #define JAS_STRINGIFY(x) #x |
| 106 | 193 | |
| 107 | −/* Convert to a string literal after macro expansion */ | |
| 194 | +/*! | |
| 195 | +@brief | |
| 196 | +Convert to a string literal after macro expansion. | |
| 197 | +*/ | |
| 108 | 198 | #define JAS_STRINGIFYX(x) JAS_STRINGIFY(x) |
| 109 | 199 | |
| 110 | 200 | #ifdef __cplusplus |
| @@ -65,29 +65,9 @@ · 64 unmodified lines | ||
| 65 | 65 | /* The configuration header file should be included first. */ |
| 66 | 66 | #include <jasper/jas_config.h> |
| 67 | 67 | |
| 68 | −#if defined(JAS_DLL) | |
| 69 | − #if defined(_WIN32) | |
| 70 | − #if defined(JAS_BUILDING_DLL) | |
| 71 | − #define JAS_DLLEXPORT __declspec(dllexport) | |
| 72 | − #else | |
| 73 | − #define JAS_DLLEXPORT __declspec(dllimport) | |
| 74 | − #endif | |
| 75 | − #define JAS_DLLLOCAL | |
| 76 | − #elif defined(JAS_HAVE_VISIBILITY) | |
| 77 | − #if defined(JAS_BUILDING_DLL) | |
| 78 | − #define JAS_DLLEXPORT __attribute__ ((visibility("default"))) | |
| 79 | − #define JAS_DLLLOCAL __attribute__ ((visibility("hidden"))) | |
| 80 | − #else | |
| 81 | − #define JAS_DLLEXPORT | |
| 82 | − #define JAS_DLLLOCAL | |
| 83 | − #endif | |
| 84 | − #else | |
| 85 | − #define JAS_DLLEXPORT | |
| 86 | − #define JAS_DLLLOCAL | |
| 87 | − #endif | |
| 88 | −#else | |
| 89 | − #define JAS_DLLEXPORT | |
| 90 | − #define JAS_DLLLOCAL | |
| 91 | −#endif | |
| 68 | +/* For backward compatibility only. */ | |
| 69 | +#define JAS_DLLEXPORT JAS_EXPORT | |
| 70 | +/* For backward compatibility only. */ | |
| 71 | +#define JAS_DLLLOCAL JAS_LOCAL | |
| 92 | 72 | |
| 93 | 73 | #endif |
| @@ -82,19 +82,52 @@ · 81 unmodified lines | ||
| 82 | 82 | extern "C" { |
| 83 | 83 | #endif |
| 84 | 84 | |
| 85 | +/*! | |
| 86 | + * @addtogroup module_fixed | |
| 87 | + * @{ | |
| 88 | + */ | |
| 89 | + | |
| 90 | +/******************************************************************************\ | |
| 91 | +* Types. | |
| 92 | +\******************************************************************************/ | |
| 93 | + | |
| 94 | +/*! | |
| 95 | +Integral type used for fixed-point representations. | |
| 96 | +*/ | |
| 97 | +#if defined(JAS_ENABLE_32BIT) | |
| 98 | +typedef int_least32_t jas_fix_t; | |
| 99 | +#define PRIjas_fix PRIiLEAST32 | |
| 100 | +#else | |
| 101 | +typedef int_least64_t jas_fix_t; | |
| 102 | +#define PRIjas_fix PRIiLEAST64 | |
| 103 | +#endif | |
| 104 | + | |
| 105 | +/* | |
| 106 | +Integral type used for double-precision fixed-point representations. | |
| 107 | +*/ | |
| 108 | +#if defined(JAS_ENABLE_32BIT) | |
| 109 | +typedef int_least64_t jas_fix_big_t; | |
| 110 | +#else | |
| 111 | +#if defined(JAS_HAVE_INT128_T) | |
| 112 | +typedef __int128_t jas_fix_big_t; | |
| 113 | +#else | |
| 114 | +typedef int_least64_t jas_fix_big_t; | |
| 115 | +#endif | |
| 116 | +#endif | |
| 117 | + | |
| 85 | 118 | /******************************************************************************\ |
| 86 | 119 | * Constants. |
| 87 | 120 | \******************************************************************************/ |
| 88 | 121 | |
| 89 | −/* The representation of the value zero. */ | |
| 122 | +/*! The representation of the value zero. */ | |
| 90 | 123 | #define JAS_FIX_ZERO(fix_t, fracbits) \ |
| 91 | 124 | JAS_INTTOFIX(fix_t, fracbits, 0) |
| 92 | 125 | |
| 93 | −/* The representation of the value one. */ | |
| 126 | +/*! The representation of the value one. */ | |
| 94 | 127 | #define JAS_FIX_ONE(fix_t, fracbits) \ |
| 95 | 128 | JAS_INTTOFIX(fix_t, fracbits, 1) |
| 96 | 129 | |
| 97 | −/* The representation of the value one half. */ | |
| 130 | +/*! The representation of the value one half. */ | |
| 98 | 131 | #define JAS_FIX_HALF(fix_t, fracbits) \ |
| 99 | 132 | (JAS_CAST(fix_t, 1) << ((fracbits) - 1)) |
| 100 | 133 | |
| @@ -102,19 +135,19 @@ extern "C" { · 1 unmodified line | ||
| 102 | 135 | * Conversion operations. |
| 103 | 136 | \******************************************************************************/ |
| 104 | 137 | |
| 105 | −/* Convert an int to a fixed-point number. */ | |
| 138 | +/*! Convert an int to a fixed-point number. */ | |
| 106 | 139 | #define JAS_INTTOFIX(fix_t, fracbits, x) \ |
| 107 | 140 | (JAS_CAST(fix_t, x) << (fracbits)) |
| 108 | 141 | |
| 109 | −/* Convert a fixed-point number to an int. */ | |
| 142 | +/*! Convert a fixed-point number to an int. */ | |
| 110 | 143 | #define JAS_FIXTOINT(fix_t, fracbits, x) \ |
| 111 | 144 | JAS_CAST(int, (x) >> (fracbits)) |
| 112 | 145 | |
| 113 | −/* Convert a fixed-point number to a double. */ | |
| 146 | +/*! Convert a fixed-point number to a double. */ | |
| 114 | 147 | #define JAS_FIXTODBL(fix_t, fracbits, x) \ |
| 115 | 148 | (JAS_CAST(double, x) / JAS_FIX_ONE(fix_t, fracbits)) |
| 116 | 149 | |
| 117 | −/* Convert a double to a fixed-point number. */ | |
| 150 | +/*! Convert a double to a fixed-point number. */ | |
| 118 | 151 | #define JAS_DBLTOFIX(fix_t, fracbits, x) \ |
| 119 | 152 | JAS_CAST(fix_t, ((x) * JAS_CAST(double, JAS_FIX_ONE(fix_t, fracbits)))) |
| 120 | 153 | |
| @@ -128,17 +161,17 @@ extern "C" { · 7 unmodified lines | ||
| 128 | 161 | * Only the generic macros should be invoked directly by application code. |
| 129 | 162 | \******************************************************************************/ |
| 130 | 163 | |
| 131 | −/* Calculate the sum of two fixed-point numbers. */ | |
| 164 | +/*! Calculate the sum of two fixed-point numbers. */ | |
| 132 | 165 | #if !defined(DEBUG_OVERFLOW) |
| 133 | 166 | #define JAS_FIX_ADD JAS_FIX_ADD_FAST |
| 134 | 167 | #else |
| 135 | 168 | #define JAS_FIX_ADD JAS_FIX_ADD_OFLOW |
| 136 | 169 | #endif |
| 137 | 170 | |
| 138 | −/* Calculate the sum of two fixed-point numbers without overflow checking. */ | |
| 171 | +/*! Calculate the sum of two fixed-point numbers without overflow checking. */ | |
| 139 | 172 | #define JAS_FIX_ADD_FAST(fix_t, fracbits, x, y) ((x) + (y)) |
| 140 | 173 | |
| 141 | −/* Calculate the sum of two fixed-point numbers with overflow checking. */ | |
| 174 | +/*! Calculate the sum of two fixed-point numbers with overflow checking. */ | |
| 142 | 175 | #define JAS_FIX_ADD_OFLOW(fix_t, fracbits, x, y) \ |
| 143 | 176 | ((x) >= 0) ? \ |
| 144 | 177 | (((y) >= 0) ? ((x) + (y) >= 0 || JAS_FIX_OFLOW(), (x) + (y)) : \ |
| @@ -146,20 +179,20 @@ extern "C" { · 1 unmodified line | ||
| 146 | 179 | (((y) >= 0) ? ((x) + (y)) : ((x) + (y) < 0 || JAS_FIX_OFLOW(), \ |
| 147 | 180 | (x) + (y))) |
| 148 | 181 | |
| 149 | −/* Calculate the product of two fixed-point numbers. */ | |
| 182 | +/*! Calculate the product of two fixed-point numbers. */ | |
| 150 | 183 | #if !defined(DEBUG_OVERFLOW) |
| 151 | 184 | #define JAS_FIX_MUL JAS_FIX_MUL_FAST |
| 152 | 185 | #else |
| 153 | 186 | #define JAS_FIX_MUL JAS_FIX_MUL_OFLOW |
| 154 | 187 | #endif |
| 155 | 188 | |
| 156 | −/* Calculate the product of two fixed-point numbers without overflow | |
| 189 | +/*! Calculate the product of two fixed-point numbers without overflow | |
| 157 | 190 | checking. */ |
| 158 | 191 | #define JAS_FIX_MUL_FAST(fix_t, fracbits, bigfix_t, x, y) \ |
| 159 | 192 | JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y)) >> \ |
| 160 | 193 | (fracbits)) |
| 161 | 194 | |
| 162 | −/* Calculate the product of two fixed-point numbers with overflow | |
| 195 | +/*! Calculate the product of two fixed-point numbers with overflow | |
| 163 | 196 | checking. */ |
| 164 | 197 | #define JAS_FIX_MUL_OFLOW(fix_t, fracbits, bigfix_t, x, y) \ |
| 165 | 198 | ((JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y) >> (fracbits)) == \ |
| @@ -168,87 +201,87 @@ extern "C" { · 2 unmodified lines | ||
| 168 | 201 | JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y) >> \ |
| 169 | 202 | (fracbits))) : JAS_FIX_OFLOW()) |
| 170 | 203 | |
| 171 | −/* Calculate the product of a fixed-point number and an int. */ | |
| 204 | +/*! Calculate the product of a fixed-point number and an int. */ | |
| 172 | 205 | #if !defined(DEBUG_OVERFLOW) |
| 173 | 206 | #define JAS_FIX_MULBYINT JAS_FIX_MULBYINT_FAST |
| 174 | 207 | #else |
| 175 | 208 | #define JAS_FIX_MULBYINT JAS_FIX_MULBYINT_OFLOW |
| 176 | 209 | #endif |
| 177 | 210 | |
| 178 | −/* Calculate the product of a fixed-point number and an int without overflow | |
| 211 | +/*! Calculate the product of a fixed-point number and an int without overflow | |
| 179 | 212 | checking. */ |
| 180 | 213 | #define JAS_FIX_MULBYINT_FAST(fix_t, fracbits, x, y) \ |
| 181 | 214 | JAS_CAST(fix_t, ((x) * (y))) |
| 182 | 215 | |
| 183 | −/* Calculate the product of a fixed-point number and an int with overflow | |
| 216 | +/*! Calculate the product of a fixed-point number and an int with overflow | |
| 184 | 217 | checking. */ |
| 185 | 218 | #define JAS_FIX_MULBYINT_OFLOW(fix_t, fracbits, x, y) \ |
| 186 | 219 | JAS_FIX_MULBYINT_FAST(fix_t, fracbits, x, y) |
| 187 | 220 | |
| 188 | −/* Calculate the quotient of two fixed-point numbers. */ | |
| 221 | +/*! Calculate the quotient of two fixed-point numbers. */ | |
| 189 | 222 | #if !defined(DEBUG_OVERFLOW) |
| 190 | 223 | #define JAS_FIX_DIV JAS_FIX_DIV_FAST |
| 191 | 224 | #else |
| 192 | 225 | #define JAS_FIX_DIV JAS_FIX_DIV_UFLOW |
| 193 | 226 | #endif |
| 194 | 227 | |
| 195 | −/* Calculate the quotient of two fixed-point numbers without underflow | |
| 228 | +/*! Calculate the quotient of two fixed-point numbers without underflow | |
| 196 | 229 | checking. */ |
| 197 | 230 | #define JAS_FIX_DIV_FAST(fix_t, fracbits, bigfix_t, x, y) \ |
| 198 | 231 | JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) << (fracbits)) / (y)) |
| 199 | 232 | |
| 200 | −/* Calculate the quotient of two fixed-point numbers with underflow | |
| 233 | +/*! Calculate the quotient of two fixed-point numbers with underflow | |
| 201 | 234 | checking. */ |
| 202 | 235 | #define JAS_FIX_DIV_UFLOW(fix_t, fracbits, bigfix_t, x, y) \ |
| 203 | 236 | JAS_FIX_DIV_FAST(fix_t, fracbits, bigfix_t, x, y) |
| 204 | 237 | |
| 205 | −/* Negate a fixed-point number. */ | |
| 238 | +/*! Negate a fixed-point number. */ | |
| 206 | 239 | #if !defined(DEBUG_OVERFLOW) |
| 207 | 240 | #define JAS_FIX_NEG JAS_FIX_NEG_FAST |
| 208 | 241 | #else |
| 209 | 242 | #define JAS_FIX_NEG JAS_FIX_NEG_OFLOW |
| 210 | 243 | #endif |
| 211 | 244 | |
| 212 | −/* Negate a fixed-point number without overflow checking. */ | |
| 245 | +/*! Negate a fixed-point number without overflow checking. */ | |
| 213 | 246 | #define JAS_FIX_NEG_FAST(fix_t, fracbits, x) \ |
| 214 | 247 | (-(x)) |
| 215 | 248 | |
| 216 | −/* Negate a fixed-point number with overflow checking. */ | |
| 249 | +/*! Negate a fixed-point number with overflow checking. */ | |
| 217 | 250 | /* Yes, overflow is actually possible for two's complement representations, |
| 218 | 251 | although highly unlikely to occur. */ |
| 219 | 252 | #define JAS_FIX_NEG_OFLOW(fix_t, fracbits, x) \ |
| 220 | 253 | (((x) < 0) ? (-(x) > 0 || JAS_FIX_OFLOW(), -(x)) : (-(x))) |
| 221 | 254 | |
| 222 | −/* Perform an arithmetic shift left of a fixed-point number. */ | |
| 255 | +/*! Perform an arithmetic shift left of a fixed-point number. */ | |
| 223 | 256 | #if !defined(DEBUG_OVERFLOW) |
| 224 | 257 | #define JAS_FIX_ASL JAS_FIX_ASL_FAST |
| 225 | 258 | #else |
| 226 | 259 | #define JAS_FIX_ASL JAS_FIX_ASL_OFLOW |
| 227 | 260 | #endif |
| 228 | 261 | |
| 229 | −/* Perform an arithmetic shift left of a fixed-point number without overflow | |
| 262 | +/*! Perform an arithmetic shift left of a fixed-point number without overflow | |
| 230 | 263 | checking. */ |
| 231 | 264 | #define JAS_FIX_ASL_FAST(fix_t, fracbits, x, n) \ |
| 232 | 265 | ((x) << (n)) |
| 233 | 266 | |
| 234 | −/* Perform an arithmetic shift left of a fixed-point number with overflow | |
| 267 | +/*! Perform an arithmetic shift left of a fixed-point number with overflow | |
| 235 | 268 | checking. */ |
| 236 | 269 | #define JAS_FIX_ASL_OFLOW(fix_t, fracbits, x, n) \ |
| 237 | 270 | ((((x) << (n)) >> (n)) == (x) || JAS_FIX_OFLOW(), (x) << (n)) |
| 238 | 271 | |
| 239 | −/* Perform an arithmetic shift right of a fixed-point number. */ | |
| 272 | +/*! Perform an arithmetic shift right of a fixed-point number. */ | |
| 240 | 273 | #if !defined(DEBUG_OVERFLOW) |
| 241 | 274 | #define JAS_FIX_ASR JAS_FIX_ASR_FAST |
| 242 | 275 | #else |
| 243 | 276 | #define JAS_FIX_ASR JAS_FIX_ASR_UFLOW |
| 244 | 277 | #endif |
| 245 | 278 | |
| 246 | −/* Perform an arithmetic shift right of a fixed-point number without underflow | |
| 279 | +/*! Perform an arithmetic shift right of a fixed-point number without underflow | |
| 247 | 280 | checking. */ |
| 248 | 281 | #define JAS_FIX_ASR_FAST(fix_t, fracbits, x, n) \ |
| 249 | 282 | ((x) >> (n)) |
| 250 | 283 | |
| 251 | −/* Perform an arithmetic shift right of a fixed-point number with underflow | |
| 284 | +/*! Perform an arithmetic shift right of a fixed-point number with underflow | |
| 252 | 285 | checking. */ |
| 253 | 286 | #define JAS_FIX_ASR_UFLOW(fix_t, fracbits, x, n) \ |
| 254 | 287 | JAS_FIX_ASR_FAST(fix_t, fracbits, x, n) |
| @@ -257,19 +290,19 @@ extern "C" { · 2 unmodified lines | ||
| 257 | 290 | * Other basic arithmetic operations. |
| 258 | 291 | \******************************************************************************/ |
| 259 | 292 | |
| 260 | −/* Calculate the difference between two fixed-point numbers. */ | |
| 293 | +/*! Calculate the difference between two fixed-point numbers. */ | |
| 261 | 294 | #define JAS_FIX_SUB(fix_t, fracbits, x, y) \ |
| 262 | 295 | JAS_FIX_ADD(fix_t, fracbits, x, JAS_FIX_NEG(fix_t, fracbits, y)) |
| 263 | 296 | |
| 264 | −/* Add one fixed-point number to another. */ | |
| 297 | +/*! Add one fixed-point number to another. */ | |
| 265 | 298 | #define JAS_FIX_PLUSEQ(fix_t, fracbits, x, y) \ |
| 266 | 299 | ((x) = JAS_FIX_ADD(fix_t, fracbits, x, y)) |
| 267 | 300 | |
| 268 | −/* Subtract one fixed-point number from another. */ | |
| 301 | +/*! Subtract one fixed-point number from another. */ | |
| 269 | 302 | #define JAS_FIX_MINUSEQ(fix_t, fracbits, x, y) \ |
| 270 | 303 | ((x) = JAS_FIX_SUB(fix_t, fracbits, x, y)) |
| 271 | 304 | |
| 272 | −/* Multiply one fixed-point number by another. */ | |
| 305 | +/*! Multiply one fixed-point number by another. */ | |
| 273 | 306 | #define JAS_FIX_MULEQ(fix_t, fracbits, bigfix_t, x, y) \ |
| 274 | 307 | ((x) = JAS_FIX_MUL(fix_t, fracbits, bigfix_t, x, y)) |
| 275 | 308 | |
| @@ -277,15 +310,15 @@ extern "C" { · 1 unmodified line | ||
| 277 | 310 | * Miscellaneous operations. |
| 278 | 311 | \******************************************************************************/ |
| 279 | 312 | |
| 280 | −/* Calculate the absolute value of a fixed-point number. */ | |
| 313 | +/*! Calculate the absolute value of a fixed-point number. */ | |
| 281 | 314 | #define JAS_FIX_ABS(fix_t, fracbits, x) \ |
| 282 | 315 | (((x) >= 0) ? (x) : (JAS_FIX_NEG(fix_t, fracbits, x))) |
| 283 | 316 | |
| 284 | −/* Is a fixed-point number an integer? */ | |
| 317 | +/*! Is a fixed-point number an integer? */ | |
| 285 | 318 | #define JAS_FIX_ISINT(fix_t, fracbits, x) \ |
| 286 | 319 | (JAS_FIX_FLOOR(fix_t, fracbits, x) == (x)) |
| 287 | 320 | |
| 288 | −/* Get the sign of a fixed-point number. */ | |
| 321 | +/*! Get the sign of a fixed-point number. */ | |
| 289 | 322 | #define JAS_FIX_SGN(fix_t, fracbits, x) \ |
| 290 | 323 | ((x) >= 0 ? 1 : (-1)) |
| 291 | 324 | |
| @@ -293,23 +326,23 @@ extern "C" { · 1 unmodified line | ||
| 293 | 326 | * Relational operations. |
| 294 | 327 | \******************************************************************************/ |
| 295 | 328 | |
| 296 | −/* Compare two fixed-point numbers. */ | |
| 329 | +/*! Compare two fixed-point numbers. */ | |
| 297 | 330 | #define JAS_FIX_CMP(fix_t, fracbits, x, y) \ |
| 298 | 331 | ((x) > (y) ? 1 : (((x) == (y)) ? 0 : (-1))) |
| 299 | 332 | |
| 300 | −/* Less than. */ | |
| 333 | +/*! Less than. */ | |
| 301 | 334 | #define JAS_FIX_LT(fix_t, fracbits, x, y) \ |
| 302 | 335 | ((x) < (y)) |
| 303 | 336 | |
| 304 | −/* Less than or equal. */ | |
| 337 | +/*! Less than or equal. */ | |
| 305 | 338 | #define JAS_FIX_LTE(fix_t, fracbits, x, y) \ |
| 306 | 339 | ((x) <= (y)) |
| 307 | 340 | |
| 308 | −/* Greater than. */ | |
| 341 | +/*! Greater than. */ | |
| 309 | 342 | #define JAS_FIX_GT(fix_t, fracbits, x, y) \ |
| 310 | 343 | ((x) > (y)) |
| 311 | 344 | |
| 312 | −/* Greater than or equal. */ | |
| 345 | +/*! Greater than or equal. */ | |
| 313 | 346 | #define JAS_FIX_GTE(fix_t, fracbits, x, y) \ |
| 314 | 347 | ((x) >= (y)) |
| 315 | 348 | |
| @@ -317,14 +350,14 @@ extern "C" { · 1 unmodified line | ||
| 317 | 350 | * Rounding functions. |
| 318 | 351 | \******************************************************************************/ |
| 319 | 352 | |
| 320 | −/* Round a fixed-point number to the nearest integer. */ | |
| 353 | +/*! Round a fixed-point number to the nearest integer. */ | |
| 321 | 354 | #define JAS_FIX_ROUND(fix_t, fracbits, x) \ |
| 322 | 355 | (((x) < 0) ? JAS_FIX_FLOOR(fix_t, fracbits, JAS_FIX_ADD(fix_t, fracbits, \ |
| 323 | 356 | (x), JAS_FIX_HALF(fix_t, fracbits))) : \ |
| 324 | 357 | JAS_FIX_NEG(fix_t, fracbits, JAS_FIX_FLOOR(fix_t, fracbits, \ |
| 325 | 358 | JAS_FIX_ADD(fix_t, fracbits, (-(x)), JAS_FIX_HALF(fix_t, fracbits))))) |
| 326 | 359 | |
| 327 | −/* Round a fixed-point number to the nearest integer in the direction of | |
| 360 | +/*! Round a fixed-point number to the nearest integer in the direction of | |
| 328 | 361 | negative infinity (i.e., the floor function). */ |
| 329 | 362 | #define JAS_FIX_FLOOR(fix_t, fracbits, x) \ |
| 330 | 363 | ((x) & (~(JAS_FIX_ONE(fix_t, fracbits) - 1))) |
| @@ -336,11 +369,31 @@ extern "C" { · 5 unmodified lines | ||
| 336 | 369 | |
| 337 | 370 | /* Handle overflow. */ |
| 338 | 371 | #define JAS_FIX_OFLOW() \ |
| 339 | − jas_eprintf("overflow error: file %s, line %d\n", __FILE__, __LINE__) | |
| 372 | + jas_logerrorf("overflow error: file %s, line %d\n", __FILE__, __LINE__) | |
| 340 | 373 | |
| 341 | 374 | /* Handle underflow. */ |
| 342 | 375 | #define JAS_FIX_UFLOW() \ |
| 343 | − jas_eprintf("underflow error: file %s, line %d\n", __FILE__, __LINE__) | |
| 376 | + jas_logerrorf("underflow error: file %s, line %d\n", __FILE__, __LINE__) | |
| 377 | + | |
| 378 | +/******************************************************************************\ | |
| 379 | +* | |
| 380 | +\******************************************************************************/ | |
| 381 | + | |
| 382 | +JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 383 | +static inline jas_fix_t jas_fix_asl(jas_fix_t x, unsigned n) | |
| 384 | +{ | |
| 385 | + return JAS_FIX_ASL(jas_fix_t, 0, x, n); | |
| 386 | +} | |
| 387 | + | |
| 388 | +JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 389 | +static inline jas_fix_t jas_fix_asr(jas_fix_t x, unsigned n) | |
| 390 | +{ | |
| 391 | + return JAS_FIX_ASR(jas_fix_t, 0, x, n); | |
| 392 | +} | |
| 393 | + | |
| 394 | +/*! | |
| 395 | + * @} | |
| 396 | + */ | |
| 344 | 397 | |
| 345 | 398 | #ifdef __cplusplus |
| 346 | 399 | } |
| @@ -77,6 +77,11 @@ · 76 unmodified lines | ||
| 77 | 77 | extern "C" { |
| 78 | 78 | #endif |
| 79 | 79 | |
| 80 | +/*! | |
| 81 | + * @addtogroup module_cm | |
| 82 | + * @{ | |
| 83 | + */ | |
| 84 | + | |
| 80 | 85 | /* Profile file signature. */ |
| 81 | 86 | #define JAS_ICC_MAGIC 0x61637370 |
| 82 | 87 | |
| @@ -308,6 +313,7 @@ typedef struct { · 225 unmodified lines | ||
| 308 | 313 | int (*output)(struct jas_iccattrval_s *, jas_stream_t *); |
| 309 | 314 | //#endif |
| 310 | 315 | unsigned (*getsize)(const struct jas_iccattrval_s *); |
| 316 | + void (*dump)(const struct jas_iccattrval_s *, FILE *); | |
| 311 | 317 | } jas_iccattrvalops_t; |
| 312 | 318 | |
| 313 | 319 | /* Attribute value type (type and value information). */ |
| @@ -381,29 +387,145 @@ typedef struct { · 67 unmodified lines | ||
| 381 | 387 | jas_iccattrvalops_t ops; |
| 382 | 388 | } jas_iccattrvalinfo_t; |
| 383 | 389 | |
| 384 | −JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_load(jas_stream_t *in); | |
| 385 | −JAS_DLLEXPORT int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out); | |
| 386 | −JAS_DLLEXPORT void jas_iccprof_destroy(jas_iccprof_t *prof); | |
| 390 | +/*! | |
| 391 | +@brief | |
| 392 | +Read an ICC profile from a stream. | |
| 393 | +*/ | |
| 394 | +JAS_EXPORT | |
| 395 | +jas_iccprof_t *jas_iccprof_load(jas_stream_t *in); | |
| 396 | + | |
| 397 | +/*! | |
| 398 | +@brief | |
| 399 | +Write an ICC profile to a stream. | |
| 400 | +*/ | |
| 401 | +JAS_EXPORT | |
| 402 | +int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out); | |
| 403 | + | |
| 404 | +/*! | |
| 405 | +@brief | |
| 406 | +Destroy an ICC profile. | |
| 407 | +*/ | |
| 408 | +JAS_EXPORT | |
| 409 | +void jas_iccprof_destroy(jas_iccprof_t *prof); | |
| 410 | + | |
| 411 | +/*! | |
| 412 | +@brief | |
| 413 | +Get an attribute of an ICC profile. | |
| 414 | +*/ | |
| 387 | 415 | JAS_ATTRIBUTE_PURE |
| 388 | −JAS_DLLEXPORT jas_iccattrval_t *jas_iccprof_getattr(const jas_iccprof_t *prof, | |
| 416 | +JAS_EXPORT | |
| 417 | +jas_iccattrval_t *jas_iccprof_getattr(const jas_iccprof_t *prof, | |
| 389 | 418 | jas_iccattrname_t name); |
| 390 | −JAS_DLLEXPORT int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name, | |
| 419 | + | |
| 420 | +/*! | |
| 421 | +@brief | |
| 422 | +Set an attribute of an ICC profile. | |
| 423 | +*/ | |
| 424 | +JAS_EXPORT | |
| 425 | +int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name, | |
| 391 | 426 | jas_iccattrval_t *val); |
| 392 | −JAS_DLLEXPORT int jas_iccprof_gethdr(const jas_iccprof_t *prof, jas_icchdr_t *hdr); | |
| 393 | −JAS_DLLEXPORT int jas_iccprof_sethdr(jas_iccprof_t *prof, const jas_icchdr_t *hdr); | |
| 394 | − | |
| 395 | −JAS_DLLEXPORT void jas_iccattrval_destroy(jas_iccattrval_t *attrval); | |
| 396 | −JAS_DLLEXPORT int jas_iccattrval_allowmodify(jas_iccattrval_t **attrval); | |
| 397 | −JAS_DLLEXPORT jas_iccattrval_t *jas_iccattrval_clone(jas_iccattrval_t *attrval); | |
| 398 | −JAS_DLLEXPORT jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type); | |
| 399 | − | |
| 400 | −JAS_DLLEXPORT extern const jas_uchar jas_iccprofdata_srgb[]; | |
| 401 | −JAS_DLLEXPORT extern const unsigned jas_iccprofdata_srgblen; | |
| 402 | −JAS_DLLEXPORT extern const jas_uchar jas_iccprofdata_sgray[]; | |
| 403 | −JAS_DLLEXPORT extern const unsigned jas_iccprofdata_sgraylen; | |
| 404 | −JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len); | |
| 405 | −JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_createfromclrspc(unsigned clrspc); | |
| 406 | −JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof); | |
| 427 | + | |
| 428 | +/*! | |
| 429 | +@brief | |
| 430 | +Dump an ICC profile to a stream in human-readable format | |
| 431 | +for debugging purposes. | |
| 432 | +*/ | |
| 433 | +JAS_EXPORT | |
| 434 | +void jas_iccprof_dump(const jas_iccprof_t *prof, FILE *out); | |
| 435 | + | |
| 436 | +/*! | |
| 437 | +@brief | |
| 438 | +Create a copy of an ICC profile. | |
| 439 | +*/ | |
| 440 | +JAS_EXPORT | |
| 441 | +jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof); | |
| 442 | + | |
| 443 | +/*! | |
| 444 | +@brief | |
| 445 | +Get the header for an ICC profile. | |
| 446 | +*/ | |
| 447 | +JAS_EXPORT | |
| 448 | +int jas_iccprof_gethdr(const jas_iccprof_t *prof, jas_icchdr_t *hdr); | |
| 449 | + | |
| 450 | +/*! | |
| 451 | +@brief | |
| 452 | +Set the header for an ICC profile. | |
| 453 | +*/ | |
| 454 | +JAS_EXPORT | |
| 455 | +int jas_iccprof_sethdr(jas_iccprof_t *prof, const jas_icchdr_t *hdr); | |
| 456 | + | |
| 457 | +/*! | |
| 458 | +@brief | |
| 459 | +Destroy an ICC profile attribute. | |
| 460 | +*/ | |
| 461 | +JAS_EXPORT | |
| 462 | +void jas_iccattrval_destroy(jas_iccattrval_t *attrval); | |
| 463 | + | |
| 464 | +/*! | |
| 465 | +@brief | |
| 466 | +*/ | |
| 467 | +JAS_EXPORT | |
| 468 | +void jas_iccattrval_dump(const jas_iccattrval_t *attrval, FILE *out); | |
| 469 | + | |
| 470 | +/*! | |
| 471 | +@brief | |
| 472 | + | |
| 473 | +TODO/FIXME | |
| 474 | +*/ | |
| 475 | +JAS_EXPORT | |
| 476 | +int jas_iccattrval_allowmodify(jas_iccattrval_t **attrval); | |
| 477 | + | |
| 478 | +/*! | |
| 479 | +@brief | |
| 480 | +Create a copy of an ICC profile attribute. | |
| 481 | +*/ | |
| 482 | +JAS_EXPORT | |
| 483 | +jas_iccattrval_t *jas_iccattrval_clone(jas_iccattrval_t *attrval); | |
| 484 | + | |
| 485 | +/*! | |
| 486 | +@brief | |
| 487 | +Create an ICC profile attribute. | |
| 488 | +*/ | |
| 489 | +JAS_EXPORT | |
| 490 | +jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type); | |
| 491 | + | |
| 492 | +/*! | |
| 493 | +@brief | |
| 494 | +Dump an ICC profile attribute to a stream in human-readable format | |
| 495 | +for debugging purposes. | |
| 496 | +*/ | |
| 497 | +JAS_EXPORT | |
| 498 | +void jas_iccattrtab_dump(const jas_iccattrtab_t *attrtab, FILE *out); | |
| 499 | + | |
| 500 | +/*! | |
| 501 | +@brief | |
| 502 | +Create an ICC profile from a buffer in memory. | |
| 503 | +*/ | |
| 504 | +JAS_EXPORT | |
| 505 | +jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len); | |
| 506 | + | |
| 507 | +/*! | |
| 508 | +@brief | |
| 509 | +Create an ICC profile from a color space. | |
| 510 | +*/ | |
| 511 | +JAS_EXPORT | |
| 512 | +jas_iccprof_t *jas_iccprof_createfromclrspc(unsigned clrspc); | |
| 513 | + | |
| 514 | +JAS_EXPORT | |
| 515 | +extern const jas_uchar jas_iccprofdata_srgb[]; | |
| 516 | + | |
| 517 | +JAS_EXPORT | |
| 518 | +extern const unsigned jas_iccprofdata_srgblen; | |
| 519 | + | |
| 520 | +JAS_EXPORT | |
| 521 | +extern const jas_uchar jas_iccprofdata_sgray[]; | |
| 522 | + | |
| 523 | +JAS_EXPORT | |
| 524 | +extern const unsigned jas_iccprofdata_sgraylen; | |
| 525 | + | |
| 526 | +/*! | |
| 527 | + * @} | |
| 528 | + */ | |
| 407 | 529 | |
| 408 | 530 | #ifdef __cplusplus |
| 409 | 531 | } |
| @@ -86,7 +86,7 @@ extern "C" { · 85 unmodified lines | ||
| 86 | 86 | #endif |
| 87 | 87 | |
| 88 | 88 | /*! |
| 89 | − * @addtogroup image | |
| 89 | + * @addtogroup module_images | |
| 90 | 90 | * @{ |
| 91 | 91 | */ |
| 92 | 92 | |
| @@ -128,7 +128,8 @@ extern "C" { · 35 unmodified lines | ||
| 128 | 128 | \******************************************************************************/ |
| 129 | 129 | |
| 130 | 130 | /*! |
| 131 | −@brief Image coordinate. */ | |
| 131 | +@brief Image coordinate. | |
| 132 | +*/ | |
| 132 | 133 | typedef int_fast32_t jas_image_coord_t; |
| 133 | 134 | #define JAS_IMAGE_COORD_MAX INT_FAST32_MAX |
| 134 | 135 | #define JAS_IMAGE_COORD_MIN INT_FAST32_MIN |
| @@ -154,81 +155,95 @@ typedef int_fast16_t jas_image_smpltype_t; · 19 unmodified lines | ||
| 154 | 155 | \******************************************************************************/ |
| 155 | 156 | |
| 156 | 157 | /*! |
| 157 | −@brief Image component class. | |
| 158 | +@brief | |
| 159 | +Image component class. | |
| 160 | + | |
| 161 | +@warning | |
| 162 | +Library users should never directly access any of the members of this | |
| 163 | +class. | |
| 164 | +The functions/macros provided by the JasPer library API should always | |
| 165 | +be used. | |
| 158 | 166 | */ |
| 159 | 167 | typedef struct { |
| 160 | 168 | |
| 161 | − jas_image_coord_t tlx_; | |
| 162 | 169 | /* The x-coordinate of the top-left corner of the component. */ |
| 170 | + jas_image_coord_t tlx_; | |
| 163 | 171 | |
| 164 | − jas_image_coord_t tly_; | |
| 165 | 172 | /* The y-coordinate of the top-left corner of the component. */ |
| 173 | + jas_image_coord_t tly_; | |
| 166 | 174 | |
| 167 | − jas_image_coord_t hstep_; | |
| 168 | 175 | /* The horizontal sampling period in units of the reference grid. */ |
| 176 | + jas_image_coord_t hstep_; | |
| 169 | 177 | |
| 170 | − jas_image_coord_t vstep_; | |
| 171 | 178 | /* The vertical sampling period in units of the reference grid. */ |
| 179 | + jas_image_coord_t vstep_; | |
| 172 | 180 | |
| 173 | − jas_image_coord_t width_; | |
| 174 | 181 | /* The component width in samples. */ |
| 182 | + jas_image_coord_t width_; | |
| 175 | 183 | |
| 176 | − jas_image_coord_t height_; | |
| 177 | 184 | /* The component height in samples. */ |
| 185 | + jas_image_coord_t height_; | |
| 178 | 186 | |
| 187 | + /* The precision of the sample data (i.e., the number of bits per sample). | |
| 188 | + If the samples are signed values, this quantity includes the sign bit. */ | |
| 179 | 189 | unsigned prec_; |
| 180 | − /* The precision of the sample data (i.e., the number of bits per | |
| 181 | − sample). If the samples are signed values, this quantity | |
| 182 | − includes the sign bit. */ | |
| 183 | 190 | |
| 184 | − int sgnd_; | |
| 185 | 191 | /* The signedness of the sample data. */ |
| 192 | + int sgnd_; | |
| 186 | 193 | |
| 187 | − jas_stream_t *stream_; | |
| 188 | 194 | /* The stream containing the component data. */ |
| 195 | + jas_stream_t *stream_; | |
| 189 | 196 | |
| 190 | − unsigned cps_; | |
| 191 | 197 | /* The number of characters per sample in the stream. */ |
| 198 | + unsigned cps_; | |
| 192 | 199 | |
| 193 | − jas_image_cmpttype_t type_; | |
| 194 | 200 | /* The type of component (e.g., opacity, red, green, blue, luma). */ |
| 201 | + jas_image_cmpttype_t type_; | |
| 195 | 202 | |
| 196 | 203 | } jas_image_cmpt_t; |
| 197 | 204 | |
| 198 | 205 | /*! |
| 199 | 206 | @brief Image class. |
| 207 | + | |
| 208 | +@warning | |
| 209 | +Library users should never directly access any of the members of this | |
| 210 | +class. | |
| 211 | +The functions/macros provided by the JasPer library API should always | |
| 212 | +be used. | |
| 200 | 213 | */ |
| 201 | 214 | typedef struct { |
| 202 | 215 | |
| 203 | − jas_image_coord_t tlx_; | |
| 204 | 216 | /* The x-coordinate of the top-left corner of the image bounding box. */ |
| 217 | + jas_image_coord_t tlx_; | |
| 205 | 218 | |
| 206 | − jas_image_coord_t tly_; | |
| 207 | 219 | /* The y-coordinate of the top-left corner of the image bounding box. */ |
| 220 | + jas_image_coord_t tly_; | |
| 208 | 221 | |
| 209 | − jas_image_coord_t brx_; | |
| 210 | 222 | /* The x-coordinate of the bottom-right corner of the image bounding |
| 211 | 223 | box (plus one). */ |
| 224 | + jas_image_coord_t brx_; | |
| 212 | 225 | |
| 213 | − jas_image_coord_t bry_; | |
| 214 | 226 | /* The y-coordinate of the bottom-right corner of the image bounding |
| 215 | 227 | box (plus one). */ |
| 228 | + jas_image_coord_t bry_; | |
| 216 | 229 | |
| 217 | − unsigned numcmpts_; | |
| 218 | 230 | /* The number of components. */ |
| 231 | + unsigned numcmpts_; | |
| 219 | 232 | |
| 220 | − unsigned maxcmpts_; | |
| 221 | 233 | /* The maximum number of components that this image can have (i.e., the |
| 222 | 234 | allocated size of the components array). */ |
| 235 | + unsigned maxcmpts_; | |
| 223 | 236 | |
| 224 | − jas_image_cmpt_t **cmpts_; | |
| 225 | 237 | /* Per-component information. */ |
| 238 | + jas_image_cmpt_t **cmpts_; | |
| 226 | 239 | |
| 240 | + /* The color space. */ | |
| 227 | 241 | jas_clrspc_t clrspc_; |
| 228 | 242 | |
| 243 | + /* The CM profile. */ | |
| 229 | 244 | jas_cmprof_t *cmprof_; |
| 230 | 245 | |
| 231 | −// bool inmem_; | |
| 246 | + //bool inmem_; | |
| 232 | 247 | |
| 233 | 248 | } jas_image_t; |
| 234 | 249 | |
| @@ -241,29 +256,29 @@ jas_image_create function. · 6 unmodified lines | ||
| 241 | 256 | */ |
| 242 | 257 | typedef struct { |
| 243 | 258 | |
| 244 | − jas_image_coord_t tlx; | |
| 245 | 259 | /* The x-coordinate of the top-left corner of the component. */ |
| 260 | + jas_image_coord_t tlx; | |
| 246 | 261 | |
| 247 | − jas_image_coord_t tly; | |
| 248 | 262 | /* The y-coordinate of the top-left corner of the component. */ |
| 263 | + jas_image_coord_t tly; | |
| 249 | 264 | |
| 250 | − jas_image_coord_t hstep; | |
| 251 | 265 | /* The horizontal sampling period in units of the reference grid. */ |
| 266 | + jas_image_coord_t hstep; | |
| 252 | 267 | |
| 253 | − jas_image_coord_t vstep; | |
| 254 | 268 | /* The vertical sampling period in units of the reference grid. */ |
| 269 | + jas_image_coord_t vstep; | |
| 255 | 270 | |
| 256 | − jas_image_coord_t width; | |
| 257 | 271 | /* The width of the component in samples. */ |
| 272 | + jas_image_coord_t width; | |
| 258 | 273 | |
| 259 | − jas_image_coord_t height; | |
| 260 | 274 | /* The height of the component in samples. */ |
| 275 | + jas_image_coord_t height; | |
| 261 | 276 | |
| 262 | − unsigned prec; | |
| 263 | 277 | /* The precision of the component sample data. */ |
| 278 | + unsigned prec; | |
| 264 | 279 | |
| 265 | − int sgnd; | |
| 266 | 280 | /* The signedness of the component sample data. */ |
| 281 | + int sgnd; | |
| 267 | 282 | |
| 268 | 283 | } jas_image_cmptparm_t; |
| 269 | 284 | |
| @@ -281,14 +296,14 @@ typedef struct { · 11 unmodified lines | ||
| 281 | 296 | */ |
| 282 | 297 | typedef struct { |
| 283 | 298 | |
| 299 | + /*! Decode image data from a stream. */ | |
| 284 | 300 | jas_image_t *(*decode)(jas_stream_t *in, const char *opts); |
| 285 | − /* Decode image data from a stream. */ | |
| 286 | 301 | |
| 302 | + /*! Encode image data to a stream. */ | |
| 287 | 303 | int (*encode)(jas_image_t *image, jas_stream_t *out, const char *opts); |
| 288 | − /* Encode image data to a stream. */ | |
| 289 | 304 | |
| 305 | + /*! Determine if stream data is in a particular format. */ | |
| 290 | 306 | int (*validate)(jas_stream_t *in); |
| 291 | − /* Determine if stream data is in a particular format. */ | |
| 292 | 307 | |
| 293 | 308 | } jas_image_fmtops_t; |
| 294 | 309 | |
| @@ -297,20 +312,29 @@ typedef struct { · 2 unmodified lines | ||
| 297 | 312 | */ |
| 298 | 313 | typedef struct { |
| 299 | 314 | |
| 315 | + /*! The ID for this format. */ | |
| 300 | 316 | int id; |
| 301 | − /* The ID for this format. */ | |
| 302 | 317 | |
| 318 | + /*! The name by which this format is identified. */ | |
| 303 | 319 | char *name; |
| 304 | − /* The name by which this format is identified. */ | |
| 305 | 320 | |
| 321 | + /* The primary file name extension associated with this format. */ | |
| 322 | + /* This member only exists for backward compatibility. */ | |
| 306 | 323 | char *ext; |
| 307 | − /* The file name extension associated with this format. */ | |
| 308 | 324 | |
| 325 | + /*! The table of file name extensions associated with this format. */ | |
| 326 | + char **exts; | |
| 327 | + size_t max_exts; | |
| 328 | + size_t num_exts; | |
| 329 | + | |
| 330 | + /*! A boolean flag indicating if this format is enabled. */ | |
| 331 | + int enabled; | |
| 332 | + | |
| 333 | + /*! A brief description of the format. */ | |
| 309 | 334 | char *desc; |
| 310 | − /* A brief description of the format. */ | |
| 311 | 335 | |
| 336 | + /*! The operations for this format. */ | |
| 312 | 337 | jas_image_fmtops_t ops; |
| 313 | − /* The operations for this format. */ | |
| 314 | 338 | |
| 315 | 339 | } jas_image_fmtinfo_t; |
| 316 | 340 | |
| @@ -321,23 +345,27 @@ typedef struct { · 4 unmodified lines | ||
| 321 | 345 | /*! |
| 322 | 346 | @brief Create an image. |
| 323 | 347 | */ |
| 324 | −JAS_DLLEXPORT jas_image_t *jas_image_create(unsigned numcmpts, | |
| 348 | +JAS_EXPORT | |
| 349 | +jas_image_t *jas_image_create(unsigned numcmpts, | |
| 325 | 350 | const jas_image_cmptparm_t *cmptparms, jas_clrspc_t clrspc); |
| 326 | 351 | |
| 327 | 352 | /*! |
| 328 | 353 | @brief Create an "empty" image. |
| 329 | 354 | */ |
| 330 | −JAS_DLLEXPORT jas_image_t *jas_image_create0(void); | |
| 355 | +JAS_EXPORT | |
| 356 | +jas_image_t *jas_image_create0(void); | |
| 331 | 357 | |
| 332 | 358 | /*! |
| 333 | 359 | @brief Clone an image. |
| 334 | 360 | */ |
| 335 | −JAS_DLLEXPORT jas_image_t *jas_image_copy(jas_image_t *image); | |
| 361 | +JAS_EXPORT | |
| 362 | +jas_image_t *jas_image_copy(jas_image_t *image); | |
| 336 | 363 | |
| 337 | 364 | /*! |
| 338 | 365 | @brief Deallocate any resources associated with an image. |
| 339 | 366 | */ |
| 340 | −JAS_DLLEXPORT void jas_image_destroy(jas_image_t *image); | |
| 367 | +JAS_EXPORT | |
| 368 | +void jas_image_destroy(jas_image_t *image); | |
| 341 | 369 | |
| 342 | 370 | /*! |
| 343 | 371 | @brief Get the width of the image in units of the image reference grid. |
| @@ -470,26 +498,27 @@ box on the reference grid (plus one). · 126 unmodified lines | ||
| 470 | 498 | @brief Test if all components are specified at the same positions in space. |
| 471 | 499 | */ |
| 472 | 500 | JAS_ATTRIBUTE_PURE |
| 473 | −JAS_DLLEXPORT bool jas_image_cmpt_domains_same(const jas_image_t *image); | |
| 501 | +JAS_EXPORT | |
| 502 | +bool jas_image_cmpt_domains_same(const jas_image_t *image); | |
| 474 | 503 | |
| 475 | 504 | /*! |
| 476 | 505 | @brief Get the raw size of an image |
| 477 | 506 | (i.e., the nominal size of the image without any compression. |
| 478 | 507 | */ |
| 479 | 508 | JAS_ATTRIBUTE_PURE |
| 480 | −JAS_DLLEXPORT | |
| 509 | +JAS_EXPORT | |
| 481 | 510 | uint_fast32_t jas_image_rawsize(const jas_image_t *image); |
| 482 | 511 | |
| 483 | 512 | /*! |
| 484 | 513 | @brief Create an image from a stream in some specified format. |
| 485 | 514 | */ |
| 486 | −JAS_DLLEXPORT | |
| 515 | +JAS_EXPORT | |
| 487 | 516 | jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr); |
| 488 | 517 | |
| 489 | 518 | /*! |
| 490 | 519 | @brief Write an image to a stream in a specified format. |
| 491 | 520 | */ |
| 492 | −JAS_DLLEXPORT | |
| 521 | +JAS_EXPORT | |
| 493 | 522 | int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, |
| 494 | 523 | const char *optstr); |
| 495 | 524 | |
| @@ -500,7 +529,7 @@ int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, · 4 unmodified lines | ||
| 500 | 529 | The position and size of the rectangular region to be read is specified |
| 501 | 530 | relative to the component's coordinate system. |
| 502 | 531 | */ |
| 503 | −JAS_DLLEXPORT | |
| 532 | +JAS_EXPORT | |
| 504 | 533 | int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, |
| 505 | 534 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 506 | 535 | jas_image_coord_t height, jas_matrix_t *data); |
| @@ -508,7 +537,7 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, · 1 unmodified line | ||
| 508 | 537 | /*! |
| 509 | 538 | @brief Write a rectangular region of an image component. |
| 510 | 539 | */ |
| 511 | −JAS_DLLEXPORT | |
| 540 | +JAS_EXPORT | |
| 512 | 541 | int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, |
| 513 | 542 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 514 | 543 | jas_image_coord_t height, const jas_matrix_t *data); |
| @@ -516,18 +545,21 @@ int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, · 1 unmodified line | ||
| 516 | 545 | /*! |
| 517 | 546 | @brief Delete a component from an image. |
| 518 | 547 | */ |
| 519 | −JAS_DLLEXPORT void jas_image_delcmpt(jas_image_t *image, unsigned cmptno); | |
| 548 | +JAS_EXPORT | |
| 549 | +void jas_image_delcmpt(jas_image_t *image, unsigned cmptno); | |
| 520 | 550 | |
| 521 | 551 | /*! |
| 522 | 552 | @brief Add a component to an image. |
| 523 | 553 | */ |
| 524 | −JAS_DLLEXPORT int jas_image_addcmpt(jas_image_t *image, int cmptno, | |
| 554 | +JAS_EXPORT | |
| 555 | +int jas_image_addcmpt(jas_image_t *image, int cmptno, | |
| 525 | 556 | const jas_image_cmptparm_t *cmptparm); |
| 526 | 557 | |
| 527 | 558 | /*! |
| 528 | 559 | @brief Copy a component from one image to another. |
| 529 | 560 | */ |
| 530 | −JAS_DLLEXPORT int jas_image_copycmpt(jas_image_t *dstimage, unsigned dstcmptno, | |
| 561 | +JAS_EXPORT | |
| 562 | +int jas_image_copycmpt(jas_image_t *dstimage, unsigned dstcmptno, | |
| 531 | 563 | jas_image_t *srcimage, unsigned srccmptno); |
| 532 | 564 | |
| 533 | 565 | JAS_ATTRIBUTE_CONST |
| @@ -555,7 +587,8 @@ static inline uint_least8_t JAS_IMAGE_CDT_SETPREC(uint_least8_t dtype) · 21 unmodified lines | ||
| 555 | 587 | } |
| 556 | 588 | |
| 557 | 589 | JAS_ATTRIBUTE_PURE |
| 558 | −static inline uint_least8_t jas_image_cmptdtype(const jas_image_t *image, unsigned cmptno) | |
| 590 | +static inline uint_least8_t jas_image_cmptdtype(const jas_image_t *image, | |
| 591 | + unsigned cmptno) | |
| 559 | 592 | { |
| 560 | 593 | return JAS_IMAGE_CDT_SETSGND(image->cmpts_[cmptno]->sgnd_) | |
| 561 | 594 | JAS_IMAGE_CDT_SETPREC(image->cmpts_[cmptno]->prec_); |
| @@ -564,7 +597,7 @@ static inline uint_least8_t jas_image_cmptdtype(const jas_image_t *image, unsign · 2 unmodified lines | ||
| 564 | 597 | /*! |
| 565 | 598 | @brief Depalettize an image |
| 566 | 599 | */ |
| 567 | −JAS_DLLEXPORT | |
| 600 | +JAS_EXPORT | |
| 568 | 601 | int jas_image_depalettize(jas_image_t *image, unsigned cmptno, |
| 569 | 602 | unsigned numlutents, const int_fast32_t *lutents, unsigned dtype, |
| 570 | 603 | unsigned newcmptno); |
| @@ -572,14 +605,14 @@ int jas_image_depalettize(jas_image_t *image, unsigned cmptno, · 1 unmodified line | ||
| 572 | 605 | /*! |
| 573 | 606 | @brief Read a component sample for an image. |
| 574 | 607 | */ |
| 575 | −JAS_DLLEXPORT | |
| 608 | +JAS_EXPORT | |
| 576 | 609 | int jas_image_readcmptsample(jas_image_t *image, unsigned cmptno, unsigned x, |
| 577 | 610 | unsigned y); |
| 578 | 611 | |
| 579 | 612 | /*! |
| 580 | 613 | @brief Write a component sample for an image. |
| 581 | 614 | */ |
| 582 | −JAS_DLLEXPORT | |
| 615 | +JAS_EXPORT | |
| 583 | 616 | void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno, |
| 584 | 617 | unsigned x, unsigned y, int_fast32_t v); |
| 585 | 618 | |
| @@ -587,7 +620,7 @@ void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno, · 1 unmodified line | ||
| 587 | 620 | @brief Get an image component by its type. |
| 588 | 621 | */ |
| 589 | 622 | JAS_ATTRIBUTE_PURE |
| 590 | −JAS_DLLEXPORT | |
| 623 | +JAS_EXPORT | |
| 591 | 624 | int jas_image_getcmptbytype(const jas_image_t *image, jas_image_cmpttype_t ctype); |
| 592 | 625 | |
| 593 | 626 | /******************************************************************************\ |
| @@ -597,75 +630,122 @@ int jas_image_getcmptbytype(const jas_image_t *image, jas_image_cmpttype_t ctype · 3 unmodified lines | ||
| 597 | 630 | /*! |
| 598 | 631 | @brief Clear the table of image formats. |
| 599 | 632 | */ |
| 600 | −JAS_DLLEXPORT | |
| 633 | +JAS_EXPORT | |
| 601 | 634 | void jas_image_clearfmts(void); |
| 602 | 635 | |
| 636 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 637 | +void jas_image_clearfmts_internal(jas_image_fmtinfo_t *image_fmtinfos, | |
| 638 | + size_t *image_numfmts); | |
| 639 | +#endif | |
| 640 | + | |
| 641 | +/*! | |
| 642 | +@brief Get a image format entry by its table index. | |
| 643 | +*/ | |
| 644 | +JAS_EXPORT | |
| 645 | +const jas_image_fmtinfo_t *jas_image_getfmtbyind(int index); | |
| 646 | + | |
| 647 | +/*! | |
| 648 | +@brief Get the number of image format table entries. | |
| 649 | +*/ | |
| 650 | +JAS_EXPORT | |
| 651 | +int jas_image_getnumfmts(void); | |
| 652 | + | |
| 653 | +#if 0 | |
| 654 | +JAS_EXPORT | |
| 655 | +int jas_image_delfmtbyid(int id); | |
| 656 | +#endif | |
| 657 | + | |
| 658 | +/*! | |
| 659 | +@brief Get the number of image format table entries. | |
| 660 | + | |
| 661 | +@warning | |
| 662 | +This function may be removed in future versions of the library. | |
| 663 | +Do not rely on it. | |
| 664 | +*/ | |
| 665 | +JAS_EXPORT | |
| 666 | +int jas_image_setfmtenable(int index, int enabled); | |
| 667 | + | |
| 668 | +#if 0 | |
| 669 | +// TODO: should this be added? | |
| 670 | +JAS_EXPORT | |
| 671 | +int jas_image_getfmtindbyname(const char* name); | |
| 672 | +#endif | |
| 673 | + | |
| 603 | 674 | /*! |
| 604 | 675 | @brief Add entry to table of image formats. |
| 605 | 676 | */ |
| 606 | −JAS_DLLEXPORT | |
| 677 | +JAS_EXPORT | |
| 607 | 678 | int jas_image_addfmt(int id, const char *name, const char *ext, |
| 608 | 679 | const char *desc, const jas_image_fmtops_t *ops); |
| 609 | 680 | |
| 681 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 682 | +int jas_image_addfmt_internal(jas_image_fmtinfo_t *image_fmtinfos, | |
| 683 | + size_t *image_numfmts, int id, const char *name, const char *ext, | |
| 684 | + const char *desc, const jas_image_fmtops_t *ops); | |
| 685 | +#endif | |
| 686 | + | |
| 610 | 687 | /*! |
| 611 | 688 | @brief Get the ID for the image format with the specified name. |
| 612 | 689 | */ |
| 613 | 690 | JAS_ATTRIBUTE_PURE |
| 614 | −JAS_DLLEXPORT | |
| 691 | +JAS_EXPORT | |
| 615 | 692 | int jas_image_strtofmt(const char *s); |
| 616 | 693 | |
| 617 | 694 | /*! |
| 618 | 695 | @brief Get the name of the image format with the specified ID. |
| 619 | 696 | */ |
| 620 | 697 | JAS_ATTRIBUTE_CONST |
| 621 | −JAS_DLLEXPORT | |
| 698 | +JAS_EXPORT | |
| 622 | 699 | const char *jas_image_fmttostr(int fmt); |
| 623 | 700 | |
| 624 | 701 | /*! |
| 625 | 702 | @brief Lookup image format information by the format ID. |
| 626 | 703 | */ |
| 627 | 704 | JAS_ATTRIBUTE_CONST |
| 628 | −JAS_DLLEXPORT | |
| 705 | +JAS_EXPORT | |
| 629 | 706 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id); |
| 630 | 707 | |
| 631 | 708 | /*! |
| 632 | 709 | @brief Lookup image format information by the format name. |
| 633 | 710 | */ |
| 634 | 711 | JAS_ATTRIBUTE_PURE |
| 635 | −JAS_DLLEXPORT | |
| 712 | +JAS_EXPORT | |
| 636 | 713 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name); |
| 637 | 714 | |
| 638 | 715 | /*! |
| 639 | 716 | @brief Guess the format of an image file based on its name. |
| 640 | 717 | */ |
| 641 | 718 | JAS_ATTRIBUTE_PURE |
| 642 | −JAS_DLLEXPORT | |
| 719 | +JAS_EXPORT | |
| 643 | 720 | int jas_image_fmtfromname(const char *filename); |
| 644 | 721 | |
| 645 | 722 | /*! |
| 646 | 723 | @brief Get the format of image data in a stream. |
| 724 | + | |
| 725 | +@details | |
| 726 | +Note that only enabled codecs are used in determining the image format. | |
| 647 | 727 | */ |
| 648 | 728 | JAS_ATTRIBUTE_PURE |
| 649 | −JAS_DLLEXPORT | |
| 729 | +JAS_EXPORT | |
| 650 | 730 | int jas_image_getfmt(jas_stream_t *in); |
| 651 | 731 | |
| 652 | − | |
| 653 | 732 | /*! |
| 654 | 733 | @brief Get the color management profile of an image. |
| 655 | 734 | */ |
| 656 | 735 | #define jas_image_cmprof(image) ((image)->cmprof_) |
| 657 | 736 | |
| 658 | 737 | /*! |
| 659 | −@brief ??? | |
| 738 | +@brief | |
| 739 | +Test if the sampling of the image is homogeneous. | |
| 660 | 740 | */ |
| 661 | 741 | JAS_ATTRIBUTE_PURE |
| 662 | −JAS_DLLEXPORT | |
| 742 | +JAS_EXPORT | |
| 663 | 743 | int jas_image_ishomosamp(const jas_image_t *image); |
| 664 | 744 | |
| 665 | 745 | /*! |
| 666 | 746 | @brief ??? |
| 667 | 747 | */ |
| 668 | −JAS_DLLEXPORT | |
| 748 | +JAS_EXPORT | |
| 669 | 749 | int jas_image_sampcmpt(jas_image_t *image, unsigned cmptno, unsigned newcmptno, |
| 670 | 750 | jas_image_coord_t ho, jas_image_coord_t vo, jas_image_coord_t hs, |
| 671 | 751 | jas_image_coord_t vs, int sgnd, unsigned prec); |
| @@ -673,14 +753,15 @@ int jas_image_sampcmpt(jas_image_t *image, unsigned cmptno, unsigned newcmptno, · 1 unmodified line | ||
| 673 | 753 | /*! |
| 674 | 754 | @brief Write sample data in a component of an image. |
| 675 | 755 | */ |
| 676 | −JAS_DLLEXPORT int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, | |
| 677 | − jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, | |
| 678 | − const long *buf); | |
| 756 | +JAS_EXPORT | |
| 757 | +int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, | |
| 758 | + jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, | |
| 759 | + jas_image_coord_t height, const long *buf); | |
| 679 | 760 | |
| 680 | 761 | /*! |
| 681 | 762 | @brief Read sample data in a component of an image. |
| 682 | 763 | */ |
| 683 | −JAS_DLLEXPORT | |
| 764 | +JAS_EXPORT | |
| 684 | 765 | int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, |
| 685 | 766 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 686 | 767 | jas_image_coord_t height, long *buf); |
| @@ -693,8 +774,15 @@ int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, · 6 unmodified lines | ||
| 693 | 774 | /*! |
| 694 | 775 | @brief Change the color space for an image. |
| 695 | 776 | */ |
| 696 | −JAS_DLLEXPORT jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, | |
| 697 | − jas_cmxform_intent_t intent); | |
| 777 | +JAS_EXPORT | |
| 778 | +jas_image_t *jas_image_chclrspc(jas_image_t *image, | |
| 779 | + const jas_cmprof_t *outprof, jas_cmxform_intent_t intent); | |
| 780 | + | |
| 781 | +/*! | |
| 782 | +@brief Dump the information for an image (for debugging). | |
| 783 | +*/ | |
| 784 | +JAS_EXPORT | |
| 785 | +int jas_image_dump(jas_image_t *image, FILE *out); | |
| 698 | 786 | |
| 699 | 787 | /******************************************************************************\ |
| 700 | 788 | * Image format-dependent operations. |
| @@ -702,58 +790,92 @@ JAS_DLLEXPORT jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmpr · 1 unmodified line | ||
| 702 | 790 | |
| 703 | 791 | #if defined(JAS_INCLUDE_JPG_CODEC) |
| 704 | 792 | /* Format-dependent operations for JPG support. */ |
| 705 | −JAS_DLLEXPORT jas_image_t *jpg_decode(jas_stream_t *in, const char *optstr); | |
| 706 | −JAS_DLLEXPORT int jpg_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 707 | −JAS_DLLEXPORT int jpg_validate(jas_stream_t *in); | |
| 793 | +//JAS_EXPORT | |
| 794 | +jas_image_t *jpg_decode(jas_stream_t *in, const char *optstr); | |
| 795 | +//JAS_EXPORT | |
| 796 | +int jpg_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 797 | +//JAS_EXPORT | |
| 798 | +int jpg_validate(jas_stream_t *in); | |
| 799 | +#endif | |
| 800 | + | |
| 801 | +#if defined(JAS_INCLUDE_HEIC_CODEC) | |
| 802 | +/* Format-dependent operations for HEIC support. */ | |
| 803 | +//JAS_EXPORT | |
| 804 | +jas_image_t *jas_heic_decode(jas_stream_t *in, const char *optstr); | |
| 805 | +//JAS_EXPORT | |
| 806 | +int jas_heic_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 807 | +//JAS_EXPORT | |
| 808 | +int jas_heic_validate(jas_stream_t *in); | |
| 708 | 809 | #endif |
| 709 | 810 | |
| 710 | 811 | #if defined(JAS_INCLUDE_MIF_CODEC) |
| 711 | 812 | /* Format-dependent operations for MIF support. */ |
| 712 | −JAS_DLLEXPORT jas_image_t *mif_decode(jas_stream_t *in, const char *optstr); | |
| 713 | −JAS_DLLEXPORT int mif_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 714 | −JAS_DLLEXPORT int mif_validate(jas_stream_t *in); | |
| 813 | +//JAS_EXPORT | |
| 814 | +jas_image_t *mif_decode(jas_stream_t *in, const char *optstr); | |
| 815 | +//JAS_EXPORT | |
| 816 | +int mif_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 817 | +//JAS_EXPORT | |
| 818 | +int mif_validate(jas_stream_t *in); | |
| 715 | 819 | #endif |
| 716 | 820 | |
| 717 | 821 | #if defined(JAS_INCLUDE_PNM_CODEC) |
| 718 | 822 | /* Format-dependent operations for PNM support. */ |
| 719 | −JAS_DLLEXPORT jas_image_t *pnm_decode(jas_stream_t *in, const char *optstr); | |
| 720 | −JAS_DLLEXPORT int pnm_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 721 | −JAS_DLLEXPORT int pnm_validate(jas_stream_t *in); | |
| 823 | +//JAS_EXPORT | |
| 824 | +jas_image_t *pnm_decode(jas_stream_t *in, const char *optstr); | |
| 825 | +//JAS_EXPORT | |
| 826 | +int pnm_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 827 | +//JAS_EXPORT | |
| 828 | +int pnm_validate(jas_stream_t *in); | |
| 722 | 829 | #endif |
| 723 | 830 | |
| 724 | 831 | #if defined(JAS_INCLUDE_RAS_CODEC) |
| 725 | 832 | /* Format-dependent operations for Sun Rasterfile support. */ |
| 726 | −JAS_DLLEXPORT jas_image_t *ras_decode(jas_stream_t *in, const char *optstr); | |
| 727 | −JAS_DLLEXPORT int ras_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 728 | −JAS_DLLEXPORT int ras_validate(jas_stream_t *in); | |
| 833 | +//JAS_EXPORT | |
| 834 | +jas_image_t *ras_decode(jas_stream_t *in, const char *optstr); | |
| 835 | +//JAS_EXPORT | |
| 836 | +int ras_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 837 | +//JAS_EXPORT | |
| 838 | +int ras_validate(jas_stream_t *in); | |
| 729 | 839 | #endif |
| 730 | 840 | |
| 731 | 841 | #if defined(JAS_INCLUDE_BMP_CODEC) |
| 732 | 842 | /* Format-dependent operations for BMP support. */ |
| 733 | −JAS_DLLEXPORT jas_image_t *bmp_decode(jas_stream_t *in, const char *optstr); | |
| 734 | −JAS_DLLEXPORT int bmp_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 735 | −JAS_DLLEXPORT int bmp_validate(jas_stream_t *in); | |
| 843 | +//JAS_EXPORT | |
| 844 | +jas_image_t *bmp_decode(jas_stream_t *in, const char *optstr); | |
| 845 | +//JAS_EXPORT | |
| 846 | +int bmp_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 847 | +//JAS_EXPORT | |
| 848 | +int bmp_validate(jas_stream_t *in); | |
| 736 | 849 | #endif |
| 737 | 850 | |
| 738 | 851 | #if defined(JAS_INCLUDE_JP2_CODEC) |
| 739 | 852 | /* Format-dependent operations for JP2 support. */ |
| 740 | −JAS_DLLEXPORT jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr); | |
| 741 | −JAS_DLLEXPORT int jp2_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 742 | −JAS_DLLEXPORT int jp2_validate(jas_stream_t *in); | |
| 853 | +//JAS_EXPORT | |
| 854 | +jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr); | |
| 855 | +//JAS_EXPORT | |
| 856 | +int jp2_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 857 | +//JAS_EXPORT | |
| 858 | +int jp2_validate(jas_stream_t *in); | |
| 743 | 859 | #endif |
| 744 | 860 | |
| 745 | 861 | #if defined(JAS_INCLUDE_JPC_CODEC) |
| 746 | 862 | /* Format-dependent operations for JPEG-2000 code stream support. */ |
| 747 | −JAS_DLLEXPORT jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr); | |
| 748 | −JAS_DLLEXPORT int jpc_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 749 | −JAS_DLLEXPORT int jpc_validate(jas_stream_t *in); | |
| 863 | +//JAS_EXPORT | |
| 864 | +jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr); | |
| 865 | +//JAS_EXPORT | |
| 866 | +int jpc_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 867 | +//JAS_EXPORT | |
| 868 | +int jpc_validate(jas_stream_t *in); | |
| 750 | 869 | #endif |
| 751 | 870 | |
| 752 | 871 | #if defined(JAS_INCLUDE_PGX_CODEC) |
| 753 | 872 | /* Format-dependent operations for PGX support. */ |
| 754 | −JAS_DLLEXPORT jas_image_t *pgx_decode(jas_stream_t *in, const char *optstr); | |
| 755 | −JAS_DLLEXPORT int pgx_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 756 | −JAS_DLLEXPORT int pgx_validate(jas_stream_t *in); | |
| 873 | +//JAS_EXPORT | |
| 874 | +jas_image_t *pgx_decode(jas_stream_t *in, const char *optstr); | |
| 875 | +//JAS_EXPORT | |
| 876 | +int pgx_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | |
| 877 | +//JAS_EXPORT | |
| 878 | +int pgx_validate(jas_stream_t *in); | |
| 757 | 879 | #endif |
| 758 | 880 | |
| 759 | 881 | /*! |
| @@ -70,42 +70,423 @@ · 69 unmodified lines | ||
| 70 | 70 | /* The configuration header file should be included first. */ |
| 71 | 71 | #include <jasper/jas_config.h> |
| 72 | 72 | |
| 73 | +#include "jasper/jas_malloc.h" | |
| 74 | +#include "jasper/jas_image.h" | |
| 75 | +#include "jasper/jas_log.h" | |
| 76 | + | |
| 73 | 77 | #ifdef __cplusplus |
| 74 | 78 | extern "C" { |
| 75 | 79 | #endif |
| 76 | 80 | |
| 77 | 81 | /*! |
| 78 | − * @addtogroup init | |
| 82 | + * @addtogroup module_init | |
| 79 | 83 | * @{ |
| 80 | 84 | */ |
| 81 | 85 | |
| 86 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 87 | +/* | |
| 88 | +Per-thread library context. | |
| 89 | +*/ | |
| 90 | +typedef struct { | |
| 91 | + | |
| 92 | + /* | |
| 93 | + The level of debugging checks/output enabled by the library. | |
| 94 | + A larger value corresponds to a greater level of debugging checks/output. | |
| 95 | + */ | |
| 96 | + int debug_level; | |
| 97 | + | |
| 98 | + /* | |
| 99 | + The function used to output error/warning/informational messages. | |
| 100 | + int (*vlogmsgf)(jas_logtype_t type, const char *format, va_list ap); | |
| 101 | + */ | |
| 102 | + jas_vlogmsgf_t *vlogmsgf; | |
| 103 | + | |
| 104 | + /* | |
| 105 | + The image format information to be used to populate the image format | |
| 106 | + table. | |
| 107 | + */ | |
| 108 | + size_t image_numfmts; | |
| 109 | + jas_image_fmtinfo_t image_fmtinfos[JAS_IMAGE_MAXFMTS]; | |
| 110 | + | |
| 111 | + /* The maximum number of samples allowable in an image to be decoded. */ | |
| 112 | + size_t dec_default_max_samples; | |
| 113 | + | |
| 114 | +} jas_ctx_t; | |
| 115 | +#endif | |
| 116 | + | |
| 117 | +/*! | |
| 118 | +@brief | |
| 119 | +An opaque handle type used to represent a JasPer library context. | |
| 120 | +*/ | |
| 121 | +typedef void *jas_context_t; | |
| 122 | + | |
| 123 | +/******************************************************************************\ | |
| 124 | +* Library Run-Time Configuration. | |
| 125 | +\******************************************************************************/ | |
| 126 | + | |
| 127 | +/*! | |
| 128 | +@brief | |
| 129 | +Configure the JasPer library with the default configuration settings. | |
| 130 | + | |
| 131 | +@details | |
| 132 | +This function configures the JasPer library with the default configuration | |
| 133 | +settings. | |
| 134 | +These settings may be change via the @c jas_conf_* family of function | |
| 135 | +prior to invoking jas_init_library(). | |
| 136 | + | |
| 137 | +@warning | |
| 138 | +Configuration, initialization, and cleanup of the library must be performed | |
| 139 | +on the same thread. | |
| 140 | +*/ | |
| 141 | +JAS_EXPORT | |
| 142 | +void jas_conf_clear(void); | |
| 143 | + | |
| 144 | +/*! | |
| 145 | +@brief Set the multithreading flag for the library. | |
| 146 | + | |
| 147 | +@details | |
| 148 | +*/ | |
| 149 | +JAS_EXPORT | |
| 150 | +void jas_conf_set_multithread(int multithread); | |
| 151 | + | |
| 152 | +/*! | |
| 153 | +@brief Set the memory allocator to be used by the library. | |
| 154 | + | |
| 155 | +@details | |
| 156 | +The object referenced by @c allocator must have a live at least | |
| 157 | +until jas_cleanup() is invoked. | |
| 158 | +How the memory in which @c *allocator reside is allocated is the | |
| 159 | +responsibility of the caller. | |
| 160 | +*/ | |
| 161 | +JAS_EXPORT | |
| 162 | +void jas_conf_set_allocator(jas_allocator_t *allocator); | |
| 163 | + | |
| 164 | +/*! | |
| 165 | +@brief Set the initial debug level for the library. | |
| 166 | + | |
| 167 | +@details | |
| 168 | +*/ | |
| 169 | +JAS_EXPORT | |
| 170 | +void jas_conf_set_debug_level(int debug_level); | |
| 171 | + | |
| 172 | +/*! | |
| 173 | +@brief | |
| 174 | +Set the maximum amount of memory that can be used by the library | |
| 175 | +(assuming the allocator wrapper is not disabled). | |
| 176 | + | |
| 177 | +@details | |
| 178 | + | |
| 179 | +@warning | |
| 180 | +It is strongly recommended that the memory usage limit not be set to an | |
| 181 | +excessively large value, as this poses security risks (e.g., decoding a | |
| 182 | +malicious image file could exhaust all virtual memory and effectively | |
| 183 | +crash the system). | |
| 184 | +*/ | |
| 185 | +JAS_EXPORT | |
| 186 | +void jas_conf_set_max_mem_usage(size_t max_mem); | |
| 187 | + | |
| 188 | +/*! | |
| 189 | +@brief | |
| 190 | +Set the default value for the maximum number of samples that is | |
| 191 | +allowed in an image to be decoded. | |
| 192 | + | |
| 193 | +@details | |
| 194 | +*/ | |
| 195 | +JAS_EXPORT | |
| 196 | +void jas_conf_set_dec_default_max_samples(size_t max_samples); | |
| 197 | + | |
| 198 | +/*! | |
| 199 | +@brief | |
| 200 | +Set the function used by the library to output error, warning, and | |
| 201 | +informational messages. | |
| 202 | + | |
| 203 | +@details | |
| 204 | +*/ | |
| 205 | +JAS_EXPORT | |
| 206 | +void jas_conf_set_vlogmsgf(jas_vlogmsgf_t *func); | |
| 207 | + | |
| 82 | 208 | /******************************************************************************\ |
| 83 | −* Functions. | |
| 209 | +* Library Initialization and Cleanup. | |
| 84 | 210 | \******************************************************************************/ |
| 85 | 211 | |
| 86 | 212 | /*! |
| 87 | −@brief Initialize the JasPer library. | |
| 213 | +@brief | |
| 214 | +Initialize the JasPer library with the current configuration settings. | |
| 88 | 215 | |
| 89 | 216 | @details |
| 90 | −This function must be called before any other code in the JasPer library | |
| 91 | −is invoked. | |
| 92 | −This function registers the codecs that are enabled by default. | |
| 217 | +The library must be configured by invoking the jas_conf_clear() function | |
| 218 | +prior to calling jas_init_library(). | |
| 93 | 219 | |
| 94 | 220 | @returns |
| 95 | −If successful, zero is returned; otherwise, a nonzero value is returned. | |
| 221 | +If the initialization of the library is successful, zero is returned; | |
| 222 | +otherwise, a nonzero value is returned. | |
| 223 | + | |
| 224 | +@warning | |
| 225 | +The jas_init_library() function does NOT synchronize with the | |
| 226 | +jas_conf_clear() function. | |
| 227 | +Configuration, initialization, and cleanup of the library must be | |
| 228 | +performed on the same thread. | |
| 229 | +*/ | |
| 230 | +JAS_EXPORT | |
| 231 | +int jas_init_library(void); | |
| 232 | + | |
| 233 | +/*! | |
| 234 | +@brief | |
| 235 | +Perform clean up for the JasPer library. | |
| 236 | + | |
| 237 | +@details | |
| 238 | +At the point when this function is called, all threads that have called | |
| 239 | +jas_init_thread() must have called jas_cleanup_thread(). | |
| 240 | + | |
| 241 | +@returns | |
| 242 | +If the operation is successful, zero is returned. | |
| 243 | +Otherwise, a nonzero value is returned. | |
| 244 | +*/ | |
| 245 | +JAS_EXPORT | |
| 246 | +int jas_cleanup_library(void); | |
| 247 | + | |
| 248 | +/******************************************************************************\ | |
| 249 | +* Thread Initialization and Cleanup. | |
| 250 | +\******************************************************************************/ | |
| 251 | + | |
| 252 | +/*! | |
| 253 | +@brief | |
| 254 | +Perform per-thread initialization for the JasPer library. | |
| 255 | + | |
| 256 | +@details | |
| 257 | +The library must be initialized by invoking the jas_init_library() function | |
| 258 | +prior to calling jas_init_thread(). | |
| 259 | + | |
| 260 | +@warning | |
| 261 | +The jas_init_thread() function can only be invoked in a single thread | |
| 262 | +unless the run-time configuration has enabled multithreading via | |
| 263 | +jas_set_multithread(). | |
| 96 | 264 | */ |
| 97 | −JAS_DLLEXPORT | |
| 265 | +JAS_EXPORT | |
| 266 | +int jas_init_thread(void); | |
| 267 | + | |
| 268 | +/*! | |
| 269 | +@brief | |
| 270 | +Perform per-thread cleanup for the JasPer library. | |
| 271 | + | |
| 272 | +@details | |
| 273 | +*/ | |
| 274 | +JAS_EXPORT | |
| 275 | +int jas_cleanup_thread(void); | |
| 276 | + | |
| 277 | +/******************************************************************************\ | |
| 278 | +* Legacy Initialization and Cleanup Functions. | |
| 279 | +\******************************************************************************/ | |
| 280 | + | |
| 281 | +/*! | |
| 282 | +@brief | |
| 283 | +Configure and initialize the JasPer library using the default | |
| 284 | +configuration settings. | |
| 285 | + | |
| 286 | +@details | |
| 287 | +The jas_init() function initializes the JasPer library. | |
| 288 | +The library must be initialized before most code in the library can be used. | |
| 289 | + | |
| 290 | +The jas_init() function exists only for reasons of backward compatibility | |
| 291 | +with earlier versions of the library. | |
| 292 | +It is recommended that this function not be used. | |
| 293 | +Instead, the jas_conf_clear() and jas_init_library() functions should be used | |
| 294 | +to configure and initialize the library. | |
| 295 | + | |
| 296 | +@returns | |
| 297 | +If the library is successfully initialized, zero is returned; | |
| 298 | +otherwise, a nonzero value is returned. | |
| 299 | + | |
| 300 | +@warning | |
| 301 | +Configuration, initialization, and cleanup of the library must be performed | |
| 302 | +on the same thread. | |
| 303 | + | |
| 304 | +@deprecated | |
| 305 | +This function is deprecated. | |
| 306 | +*/ | |
| 307 | +JAS_EXPORT | |
| 98 | 308 | int jas_init(void); |
| 99 | 309 | |
| 100 | 310 | /*! |
| 101 | −@brief Perform any clean up for the JasPer library. | |
| 311 | +@brief | |
| 312 | +Perform any clean up for the JasPer library. | |
| 102 | 313 | |
| 103 | 314 | @details |
| 104 | 315 | This function performs any clean up for the JasPer library. |
| 316 | + | |
| 317 | +@warning | |
| 318 | +Configuration, initialization, and cleanup of the library must be performed | |
| 319 | +on the same thread. | |
| 320 | + | |
| 321 | +@deprecated | |
| 322 | +This function is deprecated. | |
| 105 | 323 | */ |
| 106 | −JAS_DLLEXPORT | |
| 324 | +JAS_EXPORT | |
| 107 | 325 | void jas_cleanup(void); |
| 108 | 326 | |
| 327 | +/******************************************************************************\ | |
| 328 | +* Context Management | |
| 329 | +\******************************************************************************/ | |
| 330 | + | |
| 331 | +/*! | |
| 332 | +@brief | |
| 333 | +Create a context. | |
| 334 | + | |
| 335 | +@details | |
| 336 | +*/ | |
| 337 | +JAS_EXPORT | |
| 338 | +jas_context_t jas_context_create(void); | |
| 339 | + | |
| 340 | +/*! | |
| 341 | +@brief | |
| 342 | +Destroy a context. | |
| 343 | + | |
| 344 | +@details | |
| 345 | +The context being destroyed must not be the current context. | |
| 346 | +*/ | |
| 347 | +JAS_EXPORT | |
| 348 | +void jas_context_destroy(jas_context_t context); | |
| 349 | + | |
| 350 | +/*! | |
| 351 | +@brief | |
| 352 | +Get the current context for the calling thread. | |
| 353 | + | |
| 354 | +@details | |
| 355 | +*/ | |
| 356 | +JAS_EXPORT | |
| 357 | +jas_context_t jas_get_default_context(void); | |
| 358 | + | |
| 359 | +/*! | |
| 360 | +@brief | |
| 361 | +Get the current context for the calling thread. | |
| 362 | + | |
| 363 | +@details | |
| 364 | +*/ | |
| 365 | +JAS_EXPORT | |
| 366 | +jas_context_t jas_get_context(void); | |
| 367 | + | |
| 368 | +/*! | |
| 369 | +@brief | |
| 370 | +Set the current context for the calling thread. | |
| 371 | + | |
| 372 | +@details | |
| 373 | +*/ | |
| 374 | +JAS_EXPORT | |
| 375 | +void jas_set_context(jas_context_t context); | |
| 376 | + | |
| 377 | +/******************************************************************************\ | |
| 378 | +* Getting/Setting Context Properties | |
| 379 | +\******************************************************************************/ | |
| 380 | + | |
| 381 | +/* This function is only for internal use by the library. */ | |
| 382 | +JAS_EXPORT | |
| 383 | +int jas_get_debug_level_internal(void); | |
| 384 | + | |
| 385 | +/* This function is only for internal use by the library. */ | |
| 386 | +JAS_EXPORT | |
| 387 | +size_t jas_get_dec_default_max_samples_internal(void); | |
| 388 | + | |
| 389 | +/* This function is only for internal use by the library. */ | |
| 390 | +JAS_EXPORT | |
| 391 | +jas_vlogmsgf_t *jas_get_vlogmsgf_internal(void); | |
| 392 | + | |
| 393 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 394 | +#if defined(JAS_HAVE_THREAD_LOCAL) | |
| 395 | +extern _Thread_local jas_ctx_t *jas_cur_ctx; | |
| 396 | +#endif | |
| 397 | + | |
| 398 | +/* This function is only for internal use by the library. */ | |
| 399 | +jas_ctx_t *jas_get_ctx_internal(void); | |
| 400 | + | |
| 401 | +/* This function is only for internal use by the library. */ | |
| 402 | +static inline jas_ctx_t *jas_get_ctx(void) | |
| 403 | +{ | |
| 404 | +#if defined(JAS_HAVE_THREAD_LOCAL) | |
| 405 | + return jas_cur_ctx ? jas_cur_ctx : jas_get_ctx_internal(); | |
| 406 | +#else | |
| 407 | + return JAS_CAST(jas_ctx_t *, jas_get_ctx_internal()); | |
| 408 | +#endif | |
| 409 | +} | |
| 410 | +#endif | |
| 411 | + | |
| 412 | +/*! | |
| 413 | +@brief | |
| 414 | +Set the debug level for a particular context. | |
| 415 | + | |
| 416 | +@details | |
| 417 | +*/ | |
| 418 | +JAS_EXPORT | |
| 419 | +void jas_set_debug_level(int debug_level); | |
| 420 | + | |
| 421 | +/*! | |
| 422 | +@brief | |
| 423 | +Get the debug level for a particular context. | |
| 424 | + | |
| 425 | +@details | |
| 426 | +*/ | |
| 427 | +static inline int jas_get_debug_level(void) | |
| 428 | +{ | |
| 429 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 430 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 431 | + return ctx->debug_level; | |
| 432 | +#else | |
| 433 | + return jas_get_debug_level_internal(); | |
| 434 | +#endif | |
| 435 | +} | |
| 436 | + | |
| 437 | +/*! | |
| 438 | +@brief | |
| 439 | +Set the default maximum number of samples that a decoder is permitted to | |
| 440 | +process. | |
| 441 | + | |
| 442 | +@details | |
| 443 | +*/ | |
| 444 | +JAS_EXPORT | |
| 445 | +void jas_set_dec_default_max_samples(size_t max_samples); | |
| 446 | + | |
| 447 | +/*! | |
| 448 | +@brief | |
| 449 | +Get the default maximum number of samples that a decoder is permitted to | |
| 450 | +process. | |
| 451 | + | |
| 452 | +@details | |
| 453 | +*/ | |
| 454 | +static inline size_t jas_get_dec_default_max_samples(void) | |
| 455 | +{ | |
| 456 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 457 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 458 | + return ctx->dec_default_max_samples; | |
| 459 | +#else | |
| 460 | + return jas_get_dec_default_max_samples_internal(); | |
| 461 | +#endif | |
| 462 | +} | |
| 463 | + | |
| 464 | +/*! | |
| 465 | +@brief | |
| 466 | +Set the function to be used for log messages. | |
| 467 | + | |
| 468 | +@details | |
| 469 | +*/ | |
| 470 | +JAS_EXPORT | |
| 471 | +void jas_set_vlogmsgf(jas_vlogmsgf_t *func); | |
| 472 | + | |
| 473 | +/*! | |
| 474 | +@brief | |
| 475 | +Get the function to be used for log messages. | |
| 476 | + | |
| 477 | +@details | |
| 478 | +*/ | |
| 479 | +static inline | |
| 480 | +jas_vlogmsgf_t *jas_get_vlogmsgf(void) | |
| 481 | +{ | |
| 482 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 483 | + jas_ctx_t *ctx = jas_get_ctx(); | |
| 484 | + return ctx->vlogmsgf; | |
| 485 | +#else | |
| 486 | + return jas_get_vlogmsgf_internal(); | |
| 487 | +#endif | |
| 488 | +} | |
| 489 | + | |
| 109 | 490 | /*! |
| 110 | 491 | * @} |
| 111 | 492 | */ |
| @@ -0,0 +1,168 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2001-2002 Michael David Adams. | |
| 3 | + * All rights reserved. | |
| 4 | + */ | |
| 5 | + | |
| 6 | +/* __START_OF_JASPER_LICENSE__ | |
| 7 | + * | |
| 8 | + * JasPer License Version 2.0 | |
| 9 | + * | |
| 10 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 11 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 12 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 13 | + * | |
| 14 | + * All rights reserved. | |
| 15 | + * | |
| 16 | + * Permission is hereby granted, free of charge, to any person (the | |
| 17 | + * "User") obtaining a copy of this software and associated documentation | |
| 18 | + * files (the "Software"), to deal in the Software without restriction, | |
| 19 | + * including without limitation the rights to use, copy, modify, merge, | |
| 20 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 21 | + * persons to whom the Software is furnished to do so, subject to the | |
| 22 | + * following conditions: | |
| 23 | + * | |
| 24 | + * 1. The above copyright notices and this permission notice (which | |
| 25 | + * includes the disclaimer below) shall be included in all copies or | |
| 26 | + * substantial portions of the Software. | |
| 27 | + * | |
| 28 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 29 | + * promote products derived from the Software without specific prior | |
| 30 | + * written permission. | |
| 31 | + * | |
| 32 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 33 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 34 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 35 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 36 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 37 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 38 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 39 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 40 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 41 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 42 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 43 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 44 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 45 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 46 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 47 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 48 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 49 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 50 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 51 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 52 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 53 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 54 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 55 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 56 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 57 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 58 | + * | |
| 59 | + * __END_OF_JASPER_LICENSE__ | |
| 60 | + */ | |
| 61 | + | |
| 62 | +/*! | |
| 63 | + * @file jas_log.h | |
| 64 | + * @brief JasPer Logging Functionality | |
| 65 | + */ | |
| 66 | + | |
| 67 | +#ifndef JAS_LOG_H | |
| 68 | +#define JAS_LOG_H | |
| 69 | + | |
| 70 | +/******************************************************************************\ | |
| 71 | +* Includes. | |
| 72 | +\******************************************************************************/ | |
| 73 | + | |
| 74 | +/* The configuration header file should be included first. */ | |
| 75 | +#include <jasper/jas_config.h> | |
| 76 | + | |
| 77 | +#ifdef __cplusplus | |
| 78 | +extern "C" { | |
| 79 | +#endif | |
| 80 | + | |
| 81 | +/*! | |
| 82 | + * @addtogroup module_log | |
| 83 | + * @{ | |
| 84 | + */ | |
| 85 | + | |
| 86 | +/******************************************************************************\ | |
| 87 | +* Macros and functions. | |
| 88 | +\******************************************************************************/ | |
| 89 | + | |
| 90 | +/*! Log type class for unclassified messages. */ | |
| 91 | +#define JAS_LOGTYPE_CLASS_NULL 0 | |
| 92 | +/*! Log type class for errors. */ | |
| 93 | +#define JAS_LOGTYPE_CLASS_ERROR 1 | |
| 94 | +/*! Log type class for warnings. */ | |
| 95 | +#define JAS_LOGTYPE_CLASS_WARN 2 | |
| 96 | +/*! Log type class for informational messages. */ | |
| 97 | +#define JAS_LOGTYPE_CLASS_INFO 3 | |
| 98 | +/*! Log type class for debugging messages. */ | |
| 99 | +#define JAS_LOGTYPE_CLASS_DEBUG 4 | |
| 100 | +#define JAS_LOGTYPE_NUM_CLASSES 5 | |
| 101 | + | |
| 102 | +#define JAS_LOGTYPE_MAX_PRIORITY 16384 | |
| 103 | + | |
| 104 | +// NOTE: without the @struct, jas_logtype_t autolinks are not generated | |
| 105 | +/*! | |
| 106 | +@struct jas_logtype_t | |
| 107 | +@brief Type used for the log type. | |
| 108 | +*/ | |
| 109 | +typedef unsigned int jas_logtype_t; | |
| 110 | + | |
| 111 | +/*! | |
| 112 | +@brief Type used for formatted message logging function. | |
| 113 | +*/ | |
| 114 | +typedef int (jas_vlogmsgf_t)(jas_logtype_t, const char *, va_list); | |
| 115 | + | |
| 116 | +/*! | |
| 117 | +@brief Create an instance of a logtype. | |
| 118 | +*/ | |
| 119 | +static inline jas_logtype_t jas_logtype_init(int clas, int priority) | |
| 120 | +{ | |
| 121 | + assert(clas >= 0 && clas < JAS_LOGTYPE_NUM_CLASSES); | |
| 122 | + assert(priority >= 0 && priority <= JAS_LOGTYPE_MAX_PRIORITY); | |
| 123 | + return (clas & 0xf) | (priority << 4); | |
| 124 | +} | |
| 125 | + | |
| 126 | +/*! | |
| 127 | +@brief Get the class of a logtype. | |
| 128 | +*/ | |
| 129 | +static inline int jas_logtype_getclass(jas_logtype_t type) | |
| 130 | +{ | |
| 131 | + return type & 0xf; | |
| 132 | +} | |
| 133 | + | |
| 134 | +/*! | |
| 135 | +@brief Get the priority of a logtype. | |
| 136 | +*/ | |
| 137 | +static inline int jas_logtype_getpriority(jas_logtype_t type) | |
| 138 | +{ | |
| 139 | + return type >> 4; | |
| 140 | +} | |
| 141 | + | |
| 142 | +/*! | |
| 143 | +@brief Print formatted log message. | |
| 144 | +*/ | |
| 145 | +JAS_EXPORT | |
| 146 | +int jas_vlogmsgf(jas_logtype_t type, const char *fmt, va_list ap); | |
| 147 | + | |
| 148 | +/*! | |
| 149 | +@brief Output a log message to standard error. | |
| 150 | +*/ | |
| 151 | +JAS_EXPORT | |
| 152 | +int jas_vlogmsgf_stderr(jas_logtype_t type, const char *fmt, va_list ap); | |
| 153 | + | |
| 154 | +/*! | |
| 155 | +@brief Output a log message to nowhere (i.e., discard the message). | |
| 156 | +*/ | |
| 157 | +JAS_EXPORT | |
| 158 | +int jas_vlogmsgf_discard(jas_logtype_t type, const char *fmt, va_list ap); | |
| 159 | + | |
| 160 | +/*! | |
| 161 | + * @} | |
| 162 | + */ | |
| 163 | + | |
| 164 | +#ifdef __cplusplus | |
| 165 | +} | |
| 166 | +#endif | |
| 167 | + | |
| 168 | +#endif | |
| @@ -77,17 +77,282 @@ · 76 unmodified lines | ||
| 77 | 77 | /* The configuration header file should be included first. */ |
| 78 | 78 | #include <jasper/jas_config.h> |
| 79 | 79 | |
| 80 | +#include <jasper/jas_types.h> | |
| 81 | +#include <jasper/jas_thread.h> | |
| 82 | + | |
| 80 | 83 | #ifdef __cplusplus |
| 81 | 84 | extern "C" { |
| 82 | 85 | #endif |
| 83 | 86 | |
| 84 | −#define jas_malloc malloc | |
| 85 | −#define jas_free free | |
| 86 | −#define jas_realloc realloc | |
| 87 | −#define jas_calloc calloc | |
| 88 | −#define jas_alloc2(ne, esz) malloc(ne*esz) | |
| 89 | −#define jas_alloc3(na, asz, esz) malloc(na*asz*esz) | |
| 90 | −#define jas_realloc2(p, ne, esz) realloc(p, ne*esz) | |
| 87 | +/*! | |
| 88 | + * @addtogroup module_alloc | |
| 89 | + * @{ | |
| 90 | + */ | |
| 91 | + | |
| 92 | +/******************************************************************************\ | |
| 93 | +* Types. | |
| 94 | +\******************************************************************************/ | |
| 95 | + | |
| 96 | +/*! | |
| 97 | +@brief A memory allocator. | |
| 98 | +*/ | |
| 99 | +typedef struct jas_allocator_s { | |
| 100 | + | |
| 101 | + /*! | |
| 102 | + Function to clean up the allocator when no longer needed. | |
| 103 | + The allocator cannot be used after the clean-up operation is performed. | |
| 104 | + This function pointer may be null, in which case the clean-up operation | |
| 105 | + is treated as a no-op. | |
| 106 | + */ | |
| 107 | + void (*cleanup)(struct jas_allocator_s *allocator); | |
| 108 | + | |
| 109 | + /*! | |
| 110 | + Function to allocate memory. | |
| 111 | + This function should have behavior similar to malloc. | |
| 112 | + */ | |
| 113 | + void *(*alloc)(struct jas_allocator_s *allocator, size_t size); | |
| 114 | + | |
| 115 | + /*! | |
| 116 | + Function to deallocate memory. | |
| 117 | + This function should have behavior similar to free. | |
| 118 | + */ | |
| 119 | + void (*free)(struct jas_allocator_s *allocator, void *pointer); | |
| 120 | + | |
| 121 | + /*! | |
| 122 | + Function to reallocate memory. | |
| 123 | + This function should have behavior similar to realloc. | |
| 124 | + */ | |
| 125 | + void *(*realloc)(struct jas_allocator_s *allocator, void *pointer, | |
| 126 | + size_t new_size); | |
| 127 | + | |
| 128 | + /*! For future use. */ | |
| 129 | + void (*(reserved[4]))(void); | |
| 130 | + | |
| 131 | +} jas_allocator_t; | |
| 132 | + | |
| 133 | +/*! | |
| 134 | +@brief The standard library allocator (i.e., a wrapper for malloc and friends). | |
| 135 | + | |
| 136 | +@details | |
| 137 | +Essentially, jas_std_allocator_t can be thought of as having an inheritance | |
| 138 | +relationship with jas_allocator_t. | |
| 139 | +In particular, jas_std_allocator_t is derived from jas_allocator_t. | |
| 140 | +*/ | |
| 141 | +typedef struct { | |
| 142 | + | |
| 143 | + /* The base class. */ | |
| 144 | + jas_allocator_t base; | |
| 145 | + | |
| 146 | +} jas_std_allocator_t; | |
| 147 | + | |
| 148 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 149 | +/* | |
| 150 | +The allocator wrapper type. | |
| 151 | +This type is an allocator that adds memory usage tracking to another | |
| 152 | +allocator. | |
| 153 | +The allocator wrapper does not directly perform memory allocation itself. | |
| 154 | +Instead, it delegate to another allocator. | |
| 155 | +*/ | |
| 156 | +typedef struct { | |
| 157 | + | |
| 158 | + /* The base class. */ | |
| 159 | + jas_allocator_t base; | |
| 160 | + | |
| 161 | + /* The delegated-to allocator. */ | |
| 162 | + jas_allocator_t *delegate; | |
| 163 | + | |
| 164 | + /* The maximum amount of memory that can be used by the allocator. */ | |
| 165 | + size_t max_mem; | |
| 166 | + | |
| 167 | + /* The current amount of memory in use by the allocator. */ | |
| 168 | + size_t mem; | |
| 169 | + | |
| 170 | +#if defined(JAS_THREADS) | |
| 171 | + /* A mutex for synchronized access to the allocator. */ | |
| 172 | + jas_mutex_t mutex; | |
| 173 | +#endif | |
| 174 | + | |
| 175 | +} jas_basic_allocator_t; | |
| 176 | +#endif | |
| 177 | + | |
| 178 | +/******************************************************************************\ | |
| 179 | +* Data. | |
| 180 | +\******************************************************************************/ | |
| 181 | + | |
| 182 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 183 | +extern jas_allocator_t *jas_allocator; | |
| 184 | +extern jas_std_allocator_t jas_std_allocator; | |
| 185 | +extern jas_basic_allocator_t jas_basic_allocator; | |
| 186 | +#endif | |
| 187 | + | |
| 188 | +/******************************************************************************\ | |
| 189 | +* Functions. | |
| 190 | +\******************************************************************************/ | |
| 191 | + | |
| 192 | +/*! | |
| 193 | +@brief | |
| 194 | +Allocate memory. | |
| 195 | + | |
| 196 | +@details | |
| 197 | +This function has an identical behavior as malloc (from the C standard | |
| 198 | +library), except that a zero-sized allocation returns a non-null pointer | |
| 199 | +(assuming no out-of-memory error occurs). | |
| 200 | +*/ | |
| 201 | +JAS_EXPORT | |
| 202 | +void *jas_malloc(size_t size); | |
| 203 | + | |
| 204 | +/*! | |
| 205 | +@brief | |
| 206 | +Free memory. | |
| 207 | + | |
| 208 | +@details | |
| 209 | +This function has an identical behavior as free (from the C standard library). | |
| 210 | +*/ | |
| 211 | +JAS_EXPORT | |
| 212 | +void jas_free(void *ptr); | |
| 213 | + | |
| 214 | +/*! | |
| 215 | +@brief | |
| 216 | +Resize a block of allocated memory. | |
| 217 | + | |
| 218 | +@details | |
| 219 | +This function has an identical behavior as realloc (from the C standard | |
| 220 | +library). | |
| 221 | +*/ | |
| 222 | +JAS_EXPORT | |
| 223 | +void *jas_realloc(void *ptr, size_t size); | |
| 224 | + | |
| 225 | +/*! | |
| 226 | +@brief | |
| 227 | +Allocate a block of memory and initialize the contents to zero. | |
| 228 | + | |
| 229 | +@details | |
| 230 | +This function has an identical behavior as calloc (from the C standard | |
| 231 | +library). | |
| 232 | +*/ | |
| 233 | +JAS_EXPORT | |
| 234 | +void *jas_calloc(size_t num_elements, size_t element_size); | |
| 235 | + | |
| 236 | +/*! | |
| 237 | +@brief | |
| 238 | +Allocate array (with overflow checking). | |
| 239 | +*/ | |
| 240 | +JAS_EXPORT | |
| 241 | +void *jas_alloc2(size_t num_elements, size_t element_size); | |
| 242 | + | |
| 243 | +/*! | |
| 244 | +@brief | |
| 245 | +Allocate array of arrays (with overflow checking). | |
| 246 | +*/ | |
| 247 | +JAS_EXPORT | |
| 248 | +void *jas_alloc3(size_t num_arrays, size_t array_size, size_t element_size); | |
| 249 | + | |
| 250 | +/*! | |
| 251 | +@brief | |
| 252 | +Resize a block of allocated memory (with overflow checking). | |
| 253 | +*/ | |
| 254 | +JAS_EXPORT | |
| 255 | +void *jas_realloc2(void *ptr, size_t num_elements, size_t element_size); | |
| 256 | + | |
| 257 | +/*! | |
| 258 | +@brief | |
| 259 | +Set the maximum memory usage allowed by the allocator wrapper. | |
| 260 | + | |
| 261 | +@param max_mem | |
| 262 | +The maximum amount of memory (in bytes) that the allocator can use. | |
| 263 | + | |
| 264 | + | |
| 265 | +@details | |
| 266 | +This function sets the maximum amount of memory (in bytes) that the | |
| 267 | +allocator wrapper is permitted to use to @c max_mem. | |
| 268 | +If @c max_mem is zero, no limit is imposed on the amount of memory used by | |
| 269 | +allocator. | |
| 270 | +This function can only be called if the use of the allocator wrapper | |
| 271 | +is enabled. | |
| 272 | +Calling this function if the allocator wrapper is not enabled results | |
| 273 | +in undefined behavior. | |
| 274 | +The limit on the amount of memory that the allocator can use should | |
| 275 | +never be set to a value less than the amount of memory currently being | |
| 276 | +used by the allocator (as doing so results in undefined behavior). | |
| 277 | +*/ | |
| 278 | +JAS_EXPORT | |
| 279 | +void jas_set_max_mem_usage(size_t max_mem); | |
| 280 | + | |
| 281 | +/*! | |
| 282 | +@brief | |
| 283 | +Get the current memory usage from the allocator wrapper. | |
| 284 | + | |
| 285 | +@details | |
| 286 | +This function queries the amount of memory currently in use by the allocator | |
| 287 | +wrapper. | |
| 288 | +This function can only be called if the use of the allocator wrapper | |
| 289 | +is enabled. | |
| 290 | +Calling this function if the allocator wrapper is not enabled results | |
| 291 | +in undefined behavior. | |
| 292 | +*/ | |
| 293 | +JAS_EXPORT | |
| 294 | +size_t jas_get_mem_usage(void); | |
| 295 | + | |
| 296 | +/*! | |
| 297 | +@brief | |
| 298 | +Initialize a memory allocator that uses malloc and related functions | |
| 299 | +for managing memory. | |
| 300 | + | |
| 301 | +@param allocator | |
| 302 | +A pointer to the storage in memory that will hold the state associated | |
| 303 | +with the allocator. | |
| 304 | + | |
| 305 | +@details | |
| 306 | +The object referenced by @c allocator must have a lifetime that extends | |
| 307 | +until @c jas_allocator_cleanup is called for the allocator. | |
| 308 | +*/ | |
| 309 | +JAS_EXPORT | |
| 310 | +void jas_std_allocator_init(jas_std_allocator_t *allocator); | |
| 311 | + | |
| 312 | +/*! | |
| 313 | +@brief | |
| 314 | +Clean up an allocator that is no longer needed. | |
| 315 | + | |
| 316 | +@details | |
| 317 | +This function cleans up an allocator, releasing any resources associated | |
| 318 | +with the allocator. | |
| 319 | +After clean up is performed, the allocator can no longer be used. | |
| 320 | +*/ | |
| 321 | +JAS_EXPORT | |
| 322 | +void jas_allocator_cleanup(jas_allocator_t *allocator); | |
| 323 | + | |
| 324 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) | |
| 325 | + | |
| 326 | +/* This function is for internal library use only. */ | |
| 327 | +void jas_set_allocator(jas_allocator_t* allocator); | |
| 328 | + | |
| 329 | +/* This function is for internal library use only. */ | |
| 330 | +void jas_basic_allocator_init(jas_basic_allocator_t *allocator, | |
| 331 | + jas_allocator_t *delegate, size_t max_mem); | |
| 332 | + | |
| 333 | +#endif | |
| 334 | + | |
| 335 | +/*! | |
| 336 | +@brief | |
| 337 | +Get the total amount of memory available on the system. | |
| 338 | + | |
| 339 | +@details | |
| 340 | +This function may be called prior to the library being initialized. | |
| 341 | +In fact, this function may be useful for determining a reasonable value | |
| 342 | +for the memory limit setting to be used during (run-time) library | |
| 343 | +configuration. | |
| 344 | + | |
| 345 | +@returns | |
| 346 | +The total amount of memory available (in bytes) is returned, if this can | |
| 347 | +be determined. | |
| 348 | +Otherwise, zero is returned. | |
| 349 | +*/ | |
| 350 | +JAS_EXPORT | |
| 351 | +size_t jas_get_total_mem_size(void); | |
| 352 | + | |
| 353 | +/*! | |
| 354 | + * @} | |
| 355 | + */ | |
| 91 | 356 | |
| 92 | 357 | #ifdef __cplusplus |
| 93 | 358 | } |
| @@ -75,6 +75,8 @@ · 74 unmodified lines | ||
| 75 | 75 | |
| 76 | 76 | /* The configuration header file should be included first. */ |
| 77 | 77 | #include <jasper/jas_config.h> |
| 78 | + | |
| 79 | +#include <jasper/jas_compiler.h> | |
| 78 | 80 | #include <jasper/jas_types.h> |
| 79 | 81 | |
| 80 | 82 | #ifdef __cplusplus |
| @@ -109,6 +111,12 @@ extern "C" { · 28 unmodified lines | ||
| 109 | 111 | set to one. */ |
| 110 | 112 | #define JAS_ONES(n) \ |
| 111 | 113 | ((1 << (n)) - 1) |
| 114 | +#if 0 | |
| 115 | +#define JAS_ONES_X(type, n) \ | |
| 116 | + ((JAS_CAST(type, 1) << (n)) - 1) | |
| 117 | +#endif | |
| 118 | +#define JAS_POW2_X(type, n) \ | |
| 119 | + (JAS_CAST(type, 1) << (n)) | |
| 112 | 120 | |
| 113 | 121 | /******************************************************************************\ |
| 114 | 122 | * |
| @@ -122,78 +130,78 @@ extern "C" { · 7 unmodified lines | ||
| 122 | 130 | #endif |
| 123 | 131 | |
| 124 | 132 | JAS_ATTRIBUTE_CONST |
| 125 | −JAS_ATTRIBUTE_DISABLE_USAN | |
| 133 | +JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 126 | 134 | inline static int jas_int_asr(int x, unsigned n) |
| 127 | 135 | { |
| 128 | 136 | // Ensure that the shift of a negative value appears to behave as a |
| 129 | 137 | // signed arithmetic shift. |
| 130 | 138 | assert(((-1) >> 1) == -1); |
| 131 | − // The behavior is undefined when x is negative. */ | |
| 139 | + // The behavior is undefined when x is negative. | |
| 132 | 140 | // We tacitly assume the behavior is equivalent to a signed |
| 133 | 141 | // arithmetic right shift. |
| 134 | 142 | return x >> n; |
| 135 | 143 | } |
| 136 | 144 | |
| 137 | 145 | JAS_ATTRIBUTE_CONST |
| 138 | −JAS_ATTRIBUTE_DISABLE_USAN | |
| 146 | +JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 139 | 147 | inline static int jas_int_asl(int x, unsigned n) |
| 140 | 148 | { |
| 141 | 149 | // Ensure that the shift of a negative value appears to behave as a |
| 142 | 150 | // signed arithmetic shift. |
| 143 | 151 | assert(((-1) << 1) == -2); |
| 144 | − // The behavior is undefined when x is negative. */ | |
| 152 | + // The behavior is undefined when x is negative. | |
| 145 | 153 | // We tacitly assume the behavior is equivalent to a signed |
| 146 | 154 | // arithmetic left shift. |
| 147 | 155 | return x << n; |
| 148 | 156 | } |
| 149 | 157 | |
| 150 | 158 | JAS_ATTRIBUTE_CONST |
| 151 | −JAS_ATTRIBUTE_DISABLE_USAN | |
| 159 | +JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 152 | 160 | inline static int_least32_t jas_least32_asr(int_least32_t x, unsigned n) |
| 153 | 161 | { |
| 154 | 162 | // Ensure that the shift of a negative value appears to behave as a |
| 155 | 163 | // signed arithmetic shift. |
| 156 | 164 | assert(((JAS_CAST(int_least32_t, -1)) >> 1) == JAS_CAST(int_least32_t, -1)); |
| 157 | − // The behavior is undefined when x is negative. */ | |
| 165 | + // The behavior is undefined when x is negative. | |
| 158 | 166 | // We tacitly assume the behavior is equivalent to a signed |
| 159 | 167 | // arithmetic right shift. |
| 160 | 168 | return x >> n; |
| 161 | 169 | } |
| 162 | 170 | |
| 163 | 171 | JAS_ATTRIBUTE_CONST |
| 164 | −JAS_ATTRIBUTE_DISABLE_USAN | |
| 172 | +JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 165 | 173 | inline static int_least32_t jas_least32_asl(int_least32_t x, unsigned n) |
| 166 | 174 | { |
| 167 | 175 | // Ensure that the shift of a negative value appears to behave as a |
| 168 | 176 | // signed arithmetic shift. |
| 169 | 177 | assert(((JAS_CAST(int_least32_t, -1)) << 1) == JAS_CAST(int_least32_t, -2)); |
| 170 | − // The behavior is undefined when x is negative. */ | |
| 178 | + // The behavior is undefined when x is negative. | |
| 171 | 179 | // We tacitly assume the behavior is equivalent to a signed |
| 172 | 180 | // arithmetic left shift. |
| 173 | 181 | return x << n; |
| 174 | 182 | } |
| 175 | 183 | |
| 176 | 184 | JAS_ATTRIBUTE_CONST |
| 177 | −JAS_ATTRIBUTE_DISABLE_USAN | |
| 185 | +JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 178 | 186 | inline static int_fast32_t jas_fast32_asr(int_fast32_t x, unsigned n) |
| 179 | 187 | { |
| 180 | 188 | // Ensure that the shift of a negative value appears to behave as a |
| 181 | 189 | // signed arithmetic shift. |
| 182 | 190 | assert(((JAS_CAST(int_fast32_t, -1)) >> 1) == JAS_CAST(int_fast32_t, -1)); |
| 183 | − // The behavior is undefined when x is negative. */ | |
| 191 | + // The behavior is undefined when x is negative. | |
| 184 | 192 | // We tacitly assume the behavior is equivalent to a signed |
| 185 | 193 | // arithmetic right shift. |
| 186 | 194 | return x >> n; |
| 187 | 195 | } |
| 188 | 196 | |
| 189 | 197 | JAS_ATTRIBUTE_CONST |
| 190 | −JAS_ATTRIBUTE_DISABLE_USAN | |
| 198 | +JAS_ATTRIBUTE_DISABLE_UBSAN | |
| 191 | 199 | inline static int_fast32_t jas_fast32_asl(int_fast32_t x, unsigned n) |
| 192 | 200 | { |
| 193 | 201 | // Ensure that the shift of a negative value appears to behave as a |
| 194 | 202 | // signed arithmetic shift. |
| 195 | 203 | assert(((JAS_CAST(int_fast32_t, -1)) << 1) == JAS_CAST(int_fast32_t, -2)); |
| 196 | − // The behavior is undefined when x is negative. */ | |
| 204 | + // The behavior is undefined when x is negative. | |
| 197 | 205 | // We tacitly assume the behavior is equivalent to a signed |
| 198 | 206 | // arithmetic left shift. |
| 199 | 207 | return x << n; |
| @@ -210,11 +218,13 @@ inline static int_fast32_t jas_fast32_asl(int_fast32_t x, unsigned n) · 10 unmodified lines | ||
| 210 | 218 | /* Compute the product of two size_t integers with overflow checking. */ |
| 211 | 219 | inline static bool jas_safe_size_mul(size_t x, size_t y, size_t *result) |
| 212 | 220 | { |
| 213 | −#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 221 | +#if jas_has_builtin(__builtin_mul_overflow) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 214 | 222 | size_t result_buffer; |
| 215 | − if (!result) | |
| 216 | − result = &result_buffer; | |
| 217 | − return !__builtin_mul_overflow(x, y, result); | |
| 223 | + bool valid = !__builtin_mul_overflow(x, y, &result_buffer); | |
| 224 | + if (valid && result) { | |
| 225 | + *result = result_buffer; | |
| 226 | + } | |
| 227 | + return valid; | |
| 218 | 228 | #else |
| 219 | 229 | /* Check if overflow would occur */ |
| 220 | 230 | if (x && y > SIZE_MAX / x) { |
| @@ -246,11 +256,13 @@ inline static bool jas_safe_size_mul3(size_t a, size_t b, size_t c, · 25 unmodified lines | ||
| 246 | 256 | /* Compute the sum of two size_t integers with overflow checking. */ |
| 247 | 257 | inline static bool jas_safe_size_add(size_t x, size_t y, size_t *result) |
| 248 | 258 | { |
| 249 | −#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 259 | +#if jas_has_builtin(__builtin_add_overflow) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 250 | 260 | size_t result_buffer; |
| 251 | − if (!result) | |
| 252 | − result = &result_buffer; | |
| 253 | − return !__builtin_add_overflow(x, y, result); | |
| 261 | + bool valid = !__builtin_add_overflow(x, y, &result_buffer); | |
| 262 | + if (valid && result) { | |
| 263 | + *result = result_buffer; | |
| 264 | + } | |
| 265 | + return valid; | |
| 254 | 266 | #else |
| 255 | 267 | if (y > SIZE_MAX - x) { |
| 256 | 268 | return false; |
| @@ -265,11 +277,13 @@ inline static bool jas_safe_size_add(size_t x, size_t y, size_t *result) · 8 unmodified lines | ||
| 265 | 277 | /* Compute the difference of two size_t integers with overflow checking. */ |
| 266 | 278 | inline static bool jas_safe_size_sub(size_t x, size_t y, size_t *result) |
| 267 | 279 | { |
| 268 | −#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 280 | +#if jas_has_builtin(__builtin_sub_overflow) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 269 | 281 | size_t result_buffer; |
| 270 | − if (!result) | |
| 271 | − result = &result_buffer; | |
| 272 | − return !__builtin_sub_overflow(x, y, result); | |
| 282 | + bool valid = !__builtin_sub_overflow(x, y, &result_buffer); | |
| 283 | + if (valid && result) { | |
| 284 | + *result = result_buffer; | |
| 285 | + } | |
| 286 | + return valid; | |
| 273 | 287 | #else |
| 274 | 288 | if (y > x) { |
| 275 | 289 | return false; |
| @@ -285,11 +299,13 @@ inline static bool jas_safe_size_sub(size_t x, size_t y, size_t *result) · 9 unmodified lines | ||
| 285 | 299 | inline static bool jas_safe_intfast32_mul(int_fast32_t x, int_fast32_t y, |
| 286 | 300 | int_fast32_t *result) |
| 287 | 301 | { |
| 288 | −#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 302 | +#if jas_has_builtin(__builtin_mul_overflow) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 289 | 303 | int_fast32_t result_buffer; |
| 290 | − if (!result) | |
| 291 | − result = &result_buffer; | |
| 292 | − return !__builtin_mul_overflow(x, y, result); | |
| 304 | + bool valid = !__builtin_mul_overflow(x, y, &result_buffer); | |
| 305 | + if (valid && result) { | |
| 306 | + *result = result_buffer; | |
| 307 | + } | |
| 308 | + return valid; | |
| 293 | 309 | #else |
| 294 | 310 | if (x > 0) { |
| 295 | 311 | /* x is positive */ |
| @@ -344,11 +360,13 @@ inline static bool jas_safe_intfast32_mul3(int_fast32_t a, int_fast32_t b, · 48 unmodified lines | ||
| 344 | 360 | inline static bool jas_safe_intfast32_add(int_fast32_t x, int_fast32_t y, |
| 345 | 361 | int_fast32_t *result) |
| 346 | 362 | { |
| 347 | −#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 363 | +#if jas_has_builtin(__builtin_add_overflow) || (defined(__GNUC__) && __GNUC__ > 5) | |
| 348 | 364 | int_fast32_t result_buffer; |
| 349 | − if (!result) | |
| 350 | − result = &result_buffer; | |
| 351 | − return !__builtin_add_overflow(x, y, result); | |
| 365 | + bool valid = !__builtin_add_overflow(x, y, &result_buffer); | |
| 366 | + if (valid && result) { | |
| 367 | + *result = result_buffer; | |
| 368 | + } | |
| 369 | + return valid; | |
| 352 | 370 | #else |
| 353 | 371 | if ((y > 0 && x > INT_FAST32_MAX - y) || |
| 354 | 372 | (y < 0 && x < INT_FAST32_MIN - y)) { |
| @@ -361,6 +379,357 @@ inline static bool jas_safe_intfast32_add(int_fast32_t x, int_fast32_t y, · 6 unmodified lines | ||
| 361 | 379 | #endif |
| 362 | 380 | } |
| 363 | 381 | |
| 382 | +#if 0 | |
| 383 | +/* | |
| 384 | +This function is potentially useful but not currently used. | |
| 385 | +So, it is commented out. | |
| 386 | +*/ | |
| 387 | +inline static bool jas_safe_uint_mul(unsigned x, unsigned y, unsigned *result) | |
| 388 | +{ | |
| 389 | + /* Check if overflow would occur */ | |
| 390 | + if (x && y > UINT_MAX / x) { | |
| 391 | + /* Overflow would occur. */ | |
| 392 | + return false; | |
| 393 | + } | |
| 394 | + if (result) { | |
| 395 | + *result = x * y; | |
| 396 | + } | |
| 397 | + return true; | |
| 398 | +} | |
| 399 | +#endif | |
| 400 | + | |
| 401 | +/******************************************************************************\ | |
| 402 | +* Safe 32-bit unsigned integer arithmetic (i.e., with overflow checking). | |
| 403 | +\******************************************************************************/ | |
| 404 | + | |
| 405 | +#define JAS_SAFEUI32_MAX (0xffffffffU) | |
| 406 | + | |
| 407 | +typedef struct { | |
| 408 | + bool valid; | |
| 409 | + uint_least32_t value; | |
| 410 | +} jas_safeui32_t; | |
| 411 | + | |
| 412 | +JAS_ATTRIBUTE_CONST | |
| 413 | +static inline jas_safeui32_t jas_safeui32_from_ulong(unsigned long x) | |
| 414 | +{ | |
| 415 | + jas_safeui32_t result; | |
| 416 | + result.valid = 1; | |
| 417 | + result.value = JAS_CAST(uint_least32_t, x); | |
| 418 | + return result; | |
| 419 | +} | |
| 420 | + | |
| 421 | +JAS_ATTRIBUTE_PURE | |
| 422 | +static inline bool jas_safeui32_to_intfast32(jas_safeui32_t x, | |
| 423 | + int_fast32_t* y) | |
| 424 | +{ | |
| 425 | + if (x.value <= INT_FAST32_MAX) { | |
| 426 | + *y = x.value; | |
| 427 | + return true; | |
| 428 | + } else { | |
| 429 | + return false; | |
| 430 | + } | |
| 431 | +} | |
| 432 | + | |
| 433 | +JAS_ATTRIBUTE_CONST | |
| 434 | +static inline jas_safeui32_t jas_safeui32_add(jas_safeui32_t x, | |
| 435 | + jas_safeui32_t y) | |
| 436 | +{ | |
| 437 | + jas_safeui32_t result; | |
| 438 | + if (x.valid && y.valid && y.value <= UINT_LEAST32_MAX - x.value) { | |
| 439 | + result.valid = true; | |
| 440 | + result.value = x.value + y.value; | |
| 441 | + } else { | |
| 442 | + result.valid = false; | |
| 443 | + result.value = 0; | |
| 444 | + } | |
| 445 | + return result; | |
| 446 | +} | |
| 447 | + | |
| 448 | +JAS_ATTRIBUTE_CONST | |
| 449 | +static inline | |
| 450 | +jas_safeui32_t jas_safeui32_sub(jas_safeui32_t x, jas_safeui32_t y) | |
| 451 | +{ | |
| 452 | + jas_safeui32_t result; | |
| 453 | + if (x.valid && y.valid && y.value <= x.value) { | |
| 454 | + result.valid = true; | |
| 455 | + result.value = x.value - y.value; | |
| 456 | + } else { | |
| 457 | + result.valid = false; | |
| 458 | + result.value = 0; | |
| 459 | + } | |
| 460 | + return result; | |
| 461 | +} | |
| 462 | + | |
| 463 | +JAS_ATTRIBUTE_CONST | |
| 464 | +static inline jas_safeui32_t jas_safeui32_mul(jas_safeui32_t x, | |
| 465 | + jas_safeui32_t y) | |
| 466 | +{ | |
| 467 | + jas_safeui32_t result; | |
| 468 | + if (!x.valid || !y.valid || (x.value && y.value > UINT_LEAST32_MAX / | |
| 469 | + x.value)) { | |
| 470 | + result.valid = false; | |
| 471 | + result.value = 0; | |
| 472 | + } else { | |
| 473 | + result.valid = true; | |
| 474 | + result.value = x.value * y.value; | |
| 475 | + } | |
| 476 | + return result; | |
| 477 | +} | |
| 478 | + | |
| 479 | +/******************************************************************************\ | |
| 480 | +* Safe 64-bit signed integer arithmetic (i.e., with overflow checking). | |
| 481 | +\******************************************************************************/ | |
| 482 | + | |
| 483 | +typedef struct { | |
| 484 | + bool valid; | |
| 485 | + int_least64_t value; | |
| 486 | +} jas_safei64_t; | |
| 487 | + | |
| 488 | +JAS_ATTRIBUTE_CONST | |
| 489 | +static inline | |
| 490 | +jas_safei64_t jas_safei64_from_intmax(intmax_t x) | |
| 491 | +{ | |
| 492 | + jas_safei64_t result; | |
| 493 | + result.valid = true; | |
| 494 | + result.value = JAS_CAST(int_least64_t, x); | |
| 495 | + return result; | |
| 496 | +} | |
| 497 | + | |
| 498 | +JAS_ATTRIBUTE_CONST | |
| 499 | +static inline | |
| 500 | +jas_safei64_t jas_safei64_add(jas_safei64_t x, jas_safei64_t y) | |
| 501 | +{ | |
| 502 | + jas_safei64_t result; | |
| 503 | + if (((y.value > 0) && (x.value > (INT_LEAST64_MAX - y.value))) || | |
| 504 | + ((y.value < 0) && (x.value < (INT_LEAST64_MIN - y.value)))) { | |
| 505 | + result.value = false; | |
| 506 | + result.value = 0; | |
| 507 | + } else { | |
| 508 | + result.valid = true; | |
| 509 | + result.value = x.value + y.value; | |
| 510 | + } | |
| 511 | + return result; | |
| 512 | +} | |
| 513 | + | |
| 514 | +JAS_ATTRIBUTE_CONST | |
| 515 | +static inline | |
| 516 | +jas_safei64_t jas_safei64_sub(jas_safei64_t x, jas_safei64_t y) | |
| 517 | +{ | |
| 518 | + jas_safei64_t result; | |
| 519 | + if ((y.value > 0 && x.value < INT_LEAST64_MIN + y.value) || | |
| 520 | + (y.value < 0 && x.value > INT_LEAST64_MAX + y.value)) { | |
| 521 | + result.valid = false; | |
| 522 | + result.value = 0; | |
| 523 | + } else { | |
| 524 | + result.valid = true; | |
| 525 | + result.value = x.value - y.value; | |
| 526 | + } | |
| 527 | + return result; | |
| 528 | +} | |
| 529 | + | |
| 530 | +JAS_ATTRIBUTE_CONST | |
| 531 | +static inline | |
| 532 | +jas_safei64_t jas_safei64_mul(jas_safei64_t x, jas_safei64_t y) | |
| 533 | +{ | |
| 534 | + jas_safei64_t result; | |
| 535 | + if (x.value > 0) { /* x.value is positive */ | |
| 536 | + if (y.value > 0) { /* x.value and y.value are positive */ | |
| 537 | + if (x.value > (INT_LEAST64_MAX / y.value)) { | |
| 538 | + goto error; | |
| 539 | + } | |
| 540 | + } else { /* x.value positive, y.value nonpositive */ | |
| 541 | + if (y.value < (INT_LEAST64_MIN / x.value)) { | |
| 542 | + goto error; | |
| 543 | + } | |
| 544 | + } /* x.value positive, y.value nonpositive */ | |
| 545 | + } else { /* x.value is nonpositive */ | |
| 546 | + if (y.value > 0) { /* x.value is nonpositive, y.value is positive */ | |
| 547 | + if (x.value < (INT_LEAST64_MIN / y.value)) { | |
| 548 | + goto error; | |
| 549 | + } | |
| 550 | + } else { /* x.value and y.value are nonpositive */ | |
| 551 | + if ( (x.value != 0) && (y.value < (INT_LEAST64_MAX / x.value))) { | |
| 552 | + goto error; | |
| 553 | + } | |
| 554 | + } /* End if x.value and y.value are nonpositive */ | |
| 555 | + } /* End if x.value is nonpositive */ | |
| 556 | + result.valid = true; | |
| 557 | + result.value = x.value * y.value; | |
| 558 | + return result; | |
| 559 | +error: | |
| 560 | + result.valid = false; | |
| 561 | + result.value = 0; | |
| 562 | + return result; | |
| 563 | +} | |
| 564 | + | |
| 565 | +#if 0 | |
| 566 | +JAS_ATTRIBUTE_CONST | |
| 567 | +static inline | |
| 568 | +jas_safei64_t jas_safei64_div(jas_safei64_t x, jas_safei64_t y) | |
| 569 | +{ | |
| 570 | + // TODO/FIXME: Not yet implemented. | |
| 571 | + jas_safei64_t result; | |
| 572 | + result.valid = false; | |
| 573 | + result.value = 0; | |
| 574 | + return result; | |
| 575 | +} | |
| 576 | +#endif | |
| 577 | + | |
| 578 | +JAS_ATTRIBUTE_CONST | |
| 579 | +static inline | |
| 580 | +jas_i32_t jas_safei64_to_i32(jas_safei64_t x, jas_i32_t invalid_value) | |
| 581 | +{ | |
| 582 | + jas_i32_t result; | |
| 583 | + if (x.valid && x.value >= JAS_I32_MIN && x.value <= JAS_I32_MAX) { | |
| 584 | + result = JAS_CAST(jas_i32_t, x.value); | |
| 585 | + } else { | |
| 586 | + result = invalid_value; | |
| 587 | + } | |
| 588 | + return result; | |
| 589 | +} | |
| 590 | + | |
| 591 | +/******************************************************************************\ | |
| 592 | +* Safe 64-bit unsigned integer arithmetic (i.e., with overflow checking). | |
| 593 | +\******************************************************************************/ | |
| 594 | + | |
| 595 | +typedef struct { | |
| 596 | + bool valid; | |
| 597 | + uint_least64_t value; | |
| 598 | +} jas_safeui64_t; | |
| 599 | + | |
| 600 | +JAS_ATTRIBUTE_CONST | |
| 601 | +static inline | |
| 602 | +jas_safeui64_t jas_safeui64_from_intmax(intmax_t x) | |
| 603 | +{ | |
| 604 | + jas_safeui64_t result; | |
| 605 | + if (x >= 0) { | |
| 606 | + result.valid = true; | |
| 607 | + result.value = JAS_CAST(uint_least64_t, x); | |
| 608 | + } else { | |
| 609 | + result.valid = false; | |
| 610 | + result.value = 0; | |
| 611 | + } | |
| 612 | + return result; | |
| 613 | +} | |
| 614 | + | |
| 615 | +JAS_ATTRIBUTE_CONST | |
| 616 | +static inline | |
| 617 | +jas_safeui64_t jas_safeui64_add(jas_safeui64_t x, jas_safeui64_t y) | |
| 618 | +{ | |
| 619 | + jas_safeui64_t result; | |
| 620 | + if (x.valid && y.valid && y.value <= UINT_LEAST64_MAX - x.value) { | |
| 621 | + result.valid = true; | |
| 622 | + result.value = x.value + y.value; | |
| 623 | + } else { | |
| 624 | + result.valid = false; | |
| 625 | + result.value = 0; | |
| 626 | + } | |
| 627 | + return result; | |
| 628 | +} | |
| 629 | + | |
| 630 | +JAS_ATTRIBUTE_CONST | |
| 631 | +static inline | |
| 632 | +jas_safeui64_t jas_safeui64_sub(jas_safeui64_t x, jas_safeui64_t y) | |
| 633 | +{ | |
| 634 | + jas_safeui64_t result; | |
| 635 | + if (x.valid && y.valid && y.value <= x.value) { | |
| 636 | + result.valid = true; | |
| 637 | + result.value = x.value - y.value; | |
| 638 | + } else { | |
| 639 | + result.valid = false; | |
| 640 | + result.value = 0; | |
| 641 | + } | |
| 642 | + return result; | |
| 643 | +} | |
| 644 | + | |
| 645 | +JAS_ATTRIBUTE_CONST | |
| 646 | +static inline | |
| 647 | +jas_safeui64_t jas_safeui64_mul(jas_safeui64_t x, jas_safeui64_t y) | |
| 648 | +{ | |
| 649 | + jas_safeui64_t result; | |
| 650 | + if (!x.valid || !y.valid || (x.value && y.value > UINT_LEAST64_MAX / | |
| 651 | + x.value)) { | |
| 652 | + result.valid = false; | |
| 653 | + result.value = 0; | |
| 654 | + } else { | |
| 655 | + result.valid = true; | |
| 656 | + result.value = x.value * y.value; | |
| 657 | + } | |
| 658 | + return result; | |
| 659 | +} | |
| 660 | + | |
| 661 | +JAS_ATTRIBUTE_CONST | |
| 662 | +static inline | |
| 663 | +jas_safeui64_t jas_safeui64_div(jas_safeui64_t x, jas_safeui64_t y) | |
| 664 | +{ | |
| 665 | + jas_safeui64_t result; | |
| 666 | + if (x.valid && y.valid && y.value) { | |
| 667 | + result.valid = true; | |
| 668 | + result.value = x.value / y.value; | |
| 669 | + } else { | |
| 670 | + result.valid = false; | |
| 671 | + result.value = 0; | |
| 672 | + } | |
| 673 | + return result; | |
| 674 | +} | |
| 675 | + | |
| 676 | +JAS_ATTRIBUTE_CONST | |
| 677 | +static inline | |
| 678 | +jas_safeui64_t jas_safeui64_pow2_intmax(intmax_t x) | |
| 679 | +{ | |
| 680 | + jas_safeui64_t result; | |
| 681 | + if (x >= 0 && x < 64) { | |
| 682 | + result.valid = true; | |
| 683 | + result.value = JAS_CAST(uint_least64_t, 1) << x; | |
| 684 | + } else { | |
| 685 | + result.valid = false; | |
| 686 | + result.value = 0; | |
| 687 | + } | |
| 688 | + return result; | |
| 689 | +} | |
| 690 | + | |
| 691 | +JAS_ATTRIBUTE_CONST | |
| 692 | +static inline | |
| 693 | +int jas_safeui64_to_int(jas_safeui64_t x, int invalid_value) | |
| 694 | +{ | |
| 695 | + int result; | |
| 696 | + if (x.valid && x.value <= INT_MAX) { | |
| 697 | + result = JAS_CAST(int, x.value); | |
| 698 | + } else { | |
| 699 | + result = invalid_value; | |
| 700 | + } | |
| 701 | + return result; | |
| 702 | +} | |
| 703 | + | |
| 704 | +JAS_ATTRIBUTE_CONST | |
| 705 | +static inline | |
| 706 | +jas_ui32_t jas_safeui64_to_ui32(jas_safeui64_t x, jas_ui32_t invalid_value) | |
| 707 | +{ | |
| 708 | + jas_ui32_t result; | |
| 709 | + if (x.valid && x.value <= JAS_UI32_MAX) { | |
| 710 | + result = JAS_CAST(jas_ui32_t, x.value); | |
| 711 | + } else { | |
| 712 | + result = invalid_value; | |
| 713 | + } | |
| 714 | + return result; | |
| 715 | +} | |
| 716 | + | |
| 717 | +JAS_ATTRIBUTE_CONST | |
| 718 | +static inline | |
| 719 | +jas_i32_t jas_safeui64_to_i32(jas_safeui64_t x, jas_i32_t invalid_value) | |
| 720 | +{ | |
| 721 | + jas_i32_t result; | |
| 722 | + if (x.valid && x.value <= JAS_I32_MAX) { | |
| 723 | + result = JAS_CAST(jas_i32_t, x.value); | |
| 724 | + } else { | |
| 725 | + result = invalid_value; | |
| 726 | + } | |
| 727 | + return result; | |
| 728 | +} | |
| 729 | + | |
| 730 | +/******************************************************************************\ | |
| 731 | +\******************************************************************************/ | |
| 732 | + | |
| 364 | 733 | #ifdef __cplusplus |
| 365 | 734 | } |
| 366 | 735 | #endif |
| @@ -77,12 +77,18 @@ · 76 unmodified lines | ||
| 77 | 77 | #include <jasper/jas_config.h> /* IWYU pragma: keep */ |
| 78 | 78 | |
| 79 | 79 | #include <jasper/jas_types.h> |
| 80 | +#include <jasper/jas_fix.h> | |
| 80 | 81 | #include <jasper/jas_math.h> |
| 81 | 82 | |
| 82 | 83 | #ifdef __cplusplus |
| 83 | 84 | extern "C" { |
| 84 | 85 | #endif |
| 85 | 86 | |
| 87 | +/*! | |
| 88 | + * @addtogroup module_seq | |
| 89 | + * @{ | |
| 90 | + */ | |
| 91 | + | |
| 86 | 92 | /******************************************************************************\ |
| 87 | 93 | * Constants. |
| 88 | 94 | \******************************************************************************/ |
| @@ -95,29 +101,17 @@ extern "C" { · 6 unmodified lines | ||
| 95 | 101 | \******************************************************************************/ |
| 96 | 102 | |
| 97 | 103 | /* An element in a sequence. */ |
| 98 | −#ifdef JAS_ENABLE_32BIT | |
| 99 | −typedef int_least32_t jas_seqent_t; | |
| 100 | −#define PRIjas_seqent PRIiLEAST32 | |
| 101 | −#else | |
| 102 | −typedef int_fast32_t jas_seqent_t; | |
| 103 | −#define PRIjas_seqent PRIiFAST32 | |
| 104 | −#endif | |
| 104 | +typedef jas_fix_t jas_seqent_t; | |
| 105 | +#define PRIjas_seqent PRIjas_fix | |
| 105 | 106 | |
| 106 | 107 | /* An element in a matrix. */ |
| 107 | −#ifdef JAS_ENABLE_32BIT | |
| 108 | −typedef int_least32_t jas_matent_t; | |
| 109 | −#else | |
| 110 | −typedef int_fast32_t jas_matent_t; | |
| 111 | −#endif | |
| 108 | +typedef jas_fix_t jas_matent_t; | |
| 112 | 109 | |
| 113 | −#ifdef JAS_ENABLE_32BIT | |
| 114 | −typedef int_least32_t jas_matind_t; | |
| 115 | −#else | |
| 116 | −typedef int_fast32_t jas_matind_t; | |
| 117 | −#endif | |
| 118 | − | |
| 119 | −/* Matrix. */ | |
| 110 | +typedef jas_fix_t jas_matind_t; | |
| 120 | 111 | |
| 112 | +/*! | |
| 113 | +@brief Matrix type. | |
| 114 | +*/ | |
| 121 | 115 | typedef struct { |
| 122 | 116 | |
| 123 | 117 | /* Additional state information. */ |
| @@ -155,53 +149,86 @@ typedef struct { · 31 unmodified lines | ||
| 155 | 149 | |
| 156 | 150 | } jas_matrix_t; |
| 157 | 151 | |
| 152 | +/*! | |
| 153 | +@struct jas_seq2d_t | |
| 154 | +@brief Two-dimensional sequence type. | |
| 155 | +*/ | |
| 158 | 156 | typedef jas_matrix_t jas_seq2d_t; |
| 157 | + | |
| 158 | +/*! | |
| 159 | +@struct jas_seq_t | |
| 160 | +@brief One-dimensional sequence type. | |
| 161 | +*/ | |
| 159 | 162 | typedef jas_matrix_t jas_seq_t; |
| 160 | 163 | |
| 161 | 164 | /******************************************************************************\ |
| 162 | 165 | * Functions/macros for matrix class. |
| 163 | 166 | \******************************************************************************/ |
| 164 | 167 | |
| 165 | −/* Get the number of rows. */ | |
| 168 | +/*! | |
| 169 | +@brief | |
| 170 | +Get the number of rows in a matrix. | |
| 171 | +*/ | |
| 166 | 172 | JAS_ATTRIBUTE_PURE |
| 167 | 173 | static inline jas_matind_t jas_matrix_numrows(const jas_matrix_t *matrix) |
| 168 | 174 | { |
| 169 | 175 | return matrix->numrows_; |
| 170 | 176 | } |
| 171 | 177 | |
| 172 | −/* Get the number of columns. */ | |
| 178 | +/*! | |
| 179 | +@brief Get the number of columns in a matrix. | |
| 180 | +*/ | |
| 173 | 181 | JAS_ATTRIBUTE_PURE |
| 174 | 182 | static inline jas_matind_t jas_matrix_numcols(const jas_matrix_t *matrix) |
| 175 | 183 | { |
| 176 | 184 | return matrix->numcols_; |
| 177 | 185 | } |
| 178 | 186 | |
| 187 | +/*! | |
| 188 | +@brief | |
| 189 | +Get the number of elements in a matrix. | |
| 190 | +*/ | |
| 179 | 191 | JAS_ATTRIBUTE_PURE |
| 180 | 192 | static inline jas_matind_t jas_matrix_size(const jas_matrix_t *matrix) |
| 181 | 193 | { |
| 182 | 194 | return jas_matrix_numcols(matrix) * jas_matrix_numrows(matrix); |
| 183 | 195 | } |
| 184 | 196 | |
| 197 | +/*! | |
| 198 | +@brief | |
| 199 | +Test if a matrix is empty (i.e., contains no elements). | |
| 200 | +*/ | |
| 185 | 201 | JAS_ATTRIBUTE_PURE |
| 186 | 202 | static inline bool jas_matrix_empty(const jas_matrix_t *matrix) |
| 187 | 203 | { |
| 188 | 204 | return jas_matrix_numcols(matrix) == 0 || jas_matrix_numrows(matrix) == 0; |
| 189 | 205 | } |
| 190 | 206 | |
| 191 | −/* Get a matrix element. */ | |
| 207 | +/*! | |
| 208 | +@brief | |
| 209 | +Get a matrix element. | |
| 210 | +*/ | |
| 192 | 211 | JAS_ATTRIBUTE_PURE |
| 193 | 212 | static inline jas_seqent_t jas_matrix_get(const jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j) |
| 194 | 213 | { |
| 214 | + assert(i >= 0 && i < matrix->numrows_ && j >= 0 && j < matrix->numcols_); | |
| 195 | 215 | return matrix->rows_[i][j]; |
| 196 | 216 | } |
| 197 | 217 | |
| 198 | −/* Set a matrix element. */ | |
| 218 | +/*! | |
| 219 | +@brief | |
| 220 | +Set a matrix element. | |
| 221 | +*/ | |
| 199 | 222 | static inline void jas_matrix_set(jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j, jas_seqent_t v) |
| 200 | 223 | { |
| 224 | + assert(i >= 0 && i < matrix->numrows_ && j >= 0 && j < matrix->numcols_); | |
| 201 | 225 | matrix->rows_[i][j] = v; |
| 202 | 226 | } |
| 203 | 227 | |
| 204 | −/* Get an element from a matrix that is known to be a row or column vector. */ | |
| 228 | +/*! | |
| 229 | +@brief | |
| 230 | +Get an element from a matrix that is known to be a row or column vector. | |
| 231 | +*/ | |
| 205 | 232 | JAS_ATTRIBUTE_PURE |
| 206 | 233 | static inline jas_seqent_t jas_matrix_getv(const jas_matrix_t *matrix, jas_matind_t i) |
| 207 | 234 | { |
| @@ -210,7 +237,10 @@ static inline jas_seqent_t jas_matrix_getv(const jas_matrix_t *matrix, jas_matin · 2 unmodified lines | ||
| 210 | 237 | : matrix->rows_[i][0]; |
| 211 | 238 | } |
| 212 | 239 | |
| 213 | −/* Set an element in a matrix that is known to be a row or column vector. */ | |
| 240 | +/*! | |
| 241 | +@brief | |
| 242 | +Set an element in a matrix that is known to be a row or column vector. | |
| 243 | +*/ | |
| 214 | 244 | static inline void jas_matrix_setv(jas_matrix_t *matrix, jas_matind_t i, jas_seqent_t v) |
| 215 | 245 | { |
| 216 | 246 | if (matrix->numrows_ == 1) |
| @@ -219,13 +249,20 @@ static inline void jas_matrix_setv(jas_matrix_t *matrix, jas_matind_t i, jas_seq · 2 unmodified lines | ||
| 219 | 249 | matrix->rows_[i][0] = v; |
| 220 | 250 | } |
| 221 | 251 | |
| 222 | −/* Get the address of an element in a matrix. */ | |
| 252 | +/*! | |
| 253 | +@brief | |
| 254 | +Get the address of an element in a matrix. | |
| 255 | +*/ | |
| 223 | 256 | JAS_ATTRIBUTE_PURE |
| 224 | 257 | static inline jas_seqent_t *jas_matrix_getref(const jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j) |
| 225 | 258 | { |
| 226 | 259 | return &matrix->rows_[i][j]; |
| 227 | 260 | } |
| 228 | 261 | |
| 262 | +/*! | |
| 263 | +@brief | |
| 264 | +Get a reference to a particular row of a 2-D sequence. | |
| 265 | +*/ | |
| 229 | 266 | JAS_ATTRIBUTE_PURE |
| 230 | 267 | static inline jas_seqent_t *jas_matrix_getvref(const jas_matrix_t *matrix, jas_matind_t i) |
| 231 | 268 | { |
| @@ -234,50 +271,100 @@ static inline jas_seqent_t *jas_matrix_getvref(const jas_matrix_t *matrix, jas_m · 2 unmodified lines | ||
| 234 | 271 | : jas_matrix_getref(matrix, 0, i); |
| 235 | 272 | } |
| 236 | 273 | |
| 237 | −/* Create a matrix with the specified dimensions. */ | |
| 238 | −JAS_DLLEXPORT jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols); | |
| 274 | +/*! | |
| 275 | +@brief | |
| 276 | +Create a matrix with the specified dimensions. | |
| 277 | +*/ | |
| 278 | +JAS_EXPORT | |
| 279 | +jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols); | |
| 239 | 280 | |
| 240 | −/* Destroy a matrix. */ | |
| 241 | −JAS_DLLEXPORT void jas_matrix_destroy(jas_matrix_t *matrix); | |
| 281 | +/*! | |
| 282 | +@brief | |
| 283 | +Destroy a matrix. | |
| 284 | +*/ | |
| 285 | +JAS_EXPORT | |
| 286 | +void jas_matrix_destroy(jas_matrix_t *matrix); | |
| 242 | 287 | |
| 243 | −/* Resize a matrix. The previous contents of the matrix are lost. */ | |
| 244 | −JAS_DLLEXPORT int jas_matrix_resize(jas_matrix_t *matrix, jas_matind_t numrows, jas_matind_t numcols); | |
| 288 | +/*! | |
| 289 | +@brief | |
| 290 | +Resize a matrix. The previous contents of the matrix are lost. | |
| 291 | +*/ | |
| 292 | +JAS_EXPORT | |
| 293 | +int jas_matrix_resize(jas_matrix_t *matrix, jas_matind_t numrows, jas_matind_t numcols); | |
| 245 | 294 | |
| 246 | −JAS_DLLEXPORT int jas_matrix_output(jas_matrix_t *matrix, int fd); | |
| 295 | +/*! | |
| 296 | +@brief | |
| 297 | +Write a matrix to a C standard library stream. | |
| 298 | +*/ | |
| 299 | +JAS_EXPORT | |
| 300 | +int jas_matrix_output(jas_matrix_t *matrix, FILE *out); | |
| 247 | 301 | |
| 248 | −/* Create a matrix that references part of another matrix. */ | |
| 249 | −JAS_DLLEXPORT int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r0, | |
| 302 | +/*! | |
| 303 | +@brief | |
| 304 | +Create a matrix that references part of another matrix. | |
| 305 | +*/ | |
| 306 | +JAS_EXPORT | |
| 307 | +int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r0, | |
| 250 | 308 | jas_matind_t c0, jas_matind_t r1, jas_matind_t c1); |
| 251 | 309 | |
| 252 | −/* Create a matrix that is a reference to a row of another matrix. */ | |
| 310 | +/*! | |
| 311 | +@brief | |
| 312 | +Create a matrix that is a reference to a row of another matrix. | |
| 313 | +*/ | |
| 253 | 314 | static inline int jas_matrix_bindrow(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r) |
| 254 | 315 | { |
| 255 | 316 | return jas_matrix_bindsub(mat0, mat1, r, 0, r, mat1->numcols_ - 1); |
| 256 | 317 | } |
| 257 | 318 | |
| 258 | −/* Create a matrix that is a reference to a column of another matrix. */ | |
| 319 | +/*! | |
| 320 | +@brief | |
| 321 | +Create a matrix that is a reference to a column of another matrix. | |
| 322 | +*/ | |
| 259 | 323 | static inline int jas_matrix_bindcol(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t c) |
| 260 | 324 | { |
| 261 | 325 | return jas_matrix_bindsub(mat0, mat1, 0, c, mat1->numrows_ - 1, c); |
| 262 | 326 | } |
| 263 | 327 | |
| 264 | −/* Clip the values of matrix elements to the specified range. */ | |
| 265 | −JAS_DLLEXPORT void jas_matrix_clip(jas_matrix_t *matrix, jas_seqent_t minval, | |
| 328 | +/*! | |
| 329 | +@brief | |
| 330 | +Clip the values of matrix elements to the specified range. | |
| 331 | +*/ | |
| 332 | +JAS_EXPORT | |
| 333 | +void jas_matrix_clip(jas_matrix_t *matrix, jas_seqent_t minval, | |
| 266 | 334 | jas_seqent_t maxval); |
| 267 | 335 | |
| 268 | −/* Arithmetic shift left of all elements in a matrix. */ | |
| 269 | −JAS_DLLEXPORT void jas_matrix_asl(jas_matrix_t *matrix, unsigned n); | |
| 336 | +/*! | |
| 337 | +@brief | |
| 338 | +Arithmetic shift left of all elements in a matrix. | |
| 339 | +*/ | |
| 340 | +JAS_EXPORT | |
| 341 | +void jas_matrix_asl(jas_matrix_t *matrix, unsigned n); | |
| 270 | 342 | |
| 271 | −/* Arithmetic shift right of all elements in a matrix. */ | |
| 272 | −JAS_DLLEXPORT void jas_matrix_asr(jas_matrix_t *matrix, unsigned n); | |
| 343 | +/*! | |
| 344 | +@brief | |
| 345 | +Arithmetic shift right of all elements in a matrix. | |
| 346 | +*/ | |
| 347 | +JAS_EXPORT | |
| 348 | +void jas_matrix_asr(jas_matrix_t *matrix, unsigned n); | |
| 273 | 349 | |
| 274 | −/* Almost-but-not-quite arithmetic shift right of all elements in a matrix. */ | |
| 275 | −JAS_DLLEXPORT void jas_matrix_divpow2(jas_matrix_t *matrix, unsigned n); | |
| 350 | +/*! | |
| 351 | +@brief | |
| 352 | +Almost-but-not-quite arithmetic shift right of all elements in a matrix. | |
| 353 | +*/ | |
| 354 | +JAS_EXPORT | |
| 355 | +void jas_matrix_divpow2(jas_matrix_t *matrix, unsigned n); | |
| 276 | 356 | |
| 277 | −/* Set all elements of a matrix to the specified value. */ | |
| 278 | −JAS_DLLEXPORT void jas_matrix_setall(jas_matrix_t *matrix, jas_seqent_t val); | |
| 357 | +/*! | |
| 358 | +@brief | |
| 359 | +Set all elements of a matrix to the specified value. | |
| 360 | +*/ | |
| 361 | +JAS_EXPORT | |
| 362 | +void jas_matrix_setall(jas_matrix_t *matrix, jas_seqent_t val); | |
| 279 | 363 | |
| 280 | −/* The spacing between rows of a matrix. */ | |
| 364 | +/*! | |
| 365 | +@brief | |
| 366 | +The spacing between rows of a matrix. | |
| 367 | +*/ | |
| 281 | 368 | JAS_ATTRIBUTE_PURE |
| 282 | 369 | static inline size_t jas_matrix_rowstep(const jas_matrix_t *matrix) |
| 283 | 370 | { |
| @@ -286,7 +373,10 @@ static inline size_t jas_matrix_rowstep(const jas_matrix_t *matrix) · 2 unmodified lines | ||
| 286 | 373 | : 0u; |
| 287 | 374 | } |
| 288 | 375 | |
| 289 | −/* The spacing between columns of a matrix. */ | |
| 376 | +/*! | |
| 377 | +@brief | |
| 378 | +The spacing between columns of a matrix. | |
| 379 | +*/ | |
| 290 | 380 | JAS_ATTRIBUTE_PURE |
| 291 | 381 | static inline size_t jas_matrix_step(const jas_matrix_t *matrix) |
| 292 | 382 | { |
| @@ -295,101 +385,181 @@ static inline size_t jas_matrix_step(const jas_matrix_t *matrix) · 2 unmodified lines | ||
| 295 | 385 | : 1; |
| 296 | 386 | } |
| 297 | 387 | |
| 298 | −/* Compare two matrices for equality. */ | |
| 299 | −JAS_DLLEXPORT int jas_matrix_cmp(jas_matrix_t *mat0, jas_matrix_t *mat1); | |
| 388 | +/*! | |
| 389 | +@brief | |
| 390 | +Compare two matrices for equality. | |
| 391 | +*/ | |
| 392 | +JAS_EXPORT | |
| 393 | +int jas_matrix_cmp(jas_matrix_t *mat0, jas_matrix_t *mat1); | |
| 300 | 394 | |
| 301 | −JAS_DLLEXPORT jas_matrix_t *jas_matrix_copy(jas_matrix_t *x); | |
| 395 | +/*! | |
| 396 | +@brief | |
| 397 | +Copy a matrix. | |
| 398 | +*/ | |
| 399 | +JAS_EXPORT | |
| 400 | +jas_matrix_t *jas_matrix_copy(jas_matrix_t *x); | |
| 302 | 401 | |
| 303 | −JAS_DLLEXPORT jas_matrix_t *jas_matrix_input(int); | |
| 402 | +/*! | |
| 403 | +@brief | |
| 404 | +Read a matrix from a C standard library stream. | |
| 405 | +*/ | |
| 406 | +JAS_EXPORT | |
| 407 | +jas_matrix_t *jas_matrix_input(FILE *); | |
| 304 | 408 | |
| 409 | +/*! | |
| 410 | +@brief | |
| 411 | +*/ | |
| 305 | 412 | JAS_ATTRIBUTE_CONST |
| 306 | 413 | static inline jas_seqent_t jas_seqent_asl(jas_seqent_t x, unsigned n) |
| 307 | 414 | { |
| 415 | +#if 0 | |
| 308 | 416 | #ifdef JAS_ENABLE_32BIT |
| 309 | 417 | return jas_least32_asl(x, n); |
| 310 | 418 | #else |
| 311 | 419 | return jas_fast32_asl(x, n); |
| 312 | 420 | #endif |
| 421 | +#endif | |
| 422 | + return jas_fix_asl(x, n); | |
| 313 | 423 | } |
| 314 | 424 | |
| 425 | +/*! | |
| 426 | +@brief | |
| 427 | +*/ | |
| 315 | 428 | JAS_ATTRIBUTE_CONST |
| 316 | 429 | static inline jas_seqent_t jas_seqent_asr(jas_seqent_t x, unsigned n) |
| 317 | 430 | { |
| 431 | +#if 0 | |
| 318 | 432 | #ifdef JAS_ENABLE_32BIT |
| 319 | 433 | return jas_least32_asr(x, n); |
| 320 | 434 | #else |
| 321 | 435 | return jas_fast32_asr(x, n); |
| 322 | 436 | #endif |
| 437 | +#endif | |
| 438 | + return jas_fix_asr(x, n); | |
| 323 | 439 | } |
| 324 | 440 | |
| 325 | 441 | /******************************************************************************\ |
| 326 | 442 | * Functions/macros for 2-D sequence class. |
| 327 | 443 | \******************************************************************************/ |
| 328 | 444 | |
| 329 | −JAS_DLLEXPORT jas_seq2d_t *jas_seq2d_copy(jas_seq2d_t *x); | |
| 445 | +/*! | |
| 446 | +@brief | |
| 447 | +Copy a 2-D sequence. | |
| 448 | +*/ | |
| 449 | +JAS_EXPORT | |
| 450 | +jas_seq2d_t *jas_seq2d_copy(jas_seq2d_t *x); | |
| 330 | 451 | |
| 331 | −JAS_DLLEXPORT jas_matrix_t *jas_seq2d_create(jas_matind_t xstart, jas_matind_t ystart, | |
| 452 | +/*! | |
| 453 | +@brief | |
| 454 | +Create a 2-D sequence. | |
| 455 | +*/ | |
| 456 | +JAS_EXPORT | |
| 457 | +jas_matrix_t *jas_seq2d_create(jas_matind_t xstart, jas_matind_t ystart, | |
| 332 | 458 | jas_matind_t xend, jas_matind_t yend); |
| 333 | 459 | |
| 460 | +/*! | |
| 461 | +@brief | |
| 462 | +Destroy a 2-D sequence. | |
| 463 | +*/ | |
| 334 | 464 | static inline void jas_seq2d_destroy(jas_seq2d_t *s) |
| 335 | 465 | { |
| 336 | 466 | jas_matrix_destroy(s); |
| 337 | 467 | } |
| 338 | 468 | |
| 469 | +/*! | |
| 470 | +@brief | |
| 471 | +Get the starting x-coordinate of the sequence. | |
| 472 | +*/ | |
| 339 | 473 | JAS_ATTRIBUTE_PURE |
| 340 | 474 | static inline jas_matind_t jas_seq2d_xstart(const jas_seq2d_t *s) |
| 341 | 475 | { |
| 342 | 476 | return s->xstart_; |
| 343 | 477 | } |
| 344 | 478 | |
| 479 | +/*! | |
| 480 | +@brief | |
| 481 | +Get the starting y-coordinate of the sequence. | |
| 482 | +*/ | |
| 345 | 483 | JAS_ATTRIBUTE_PURE |
| 346 | 484 | static inline jas_matind_t jas_seq2d_ystart(const jas_seq2d_t *s) |
| 347 | 485 | { |
| 348 | 486 | return s->ystart_; |
| 349 | 487 | } |
| 350 | 488 | |
| 489 | +/*! | |
| 490 | +@brief | |
| 491 | +Get the ending x-coordinate of the sequence. | |
| 492 | +*/ | |
| 351 | 493 | JAS_ATTRIBUTE_PURE |
| 352 | 494 | static inline jas_matind_t jas_seq2d_xend(const jas_seq2d_t *s) |
| 353 | 495 | { |
| 354 | 496 | return s->xend_; |
| 355 | 497 | } |
| 356 | 498 | |
| 499 | +/*! | |
| 500 | +@brief | |
| 501 | +Get the ending y-coordinate of the sequence. | |
| 502 | +*/ | |
| 357 | 503 | JAS_ATTRIBUTE_PURE |
| 358 | 504 | static inline jas_matind_t jas_seq2d_yend(const jas_seq2d_t *s) |
| 359 | 505 | { |
| 360 | 506 | return s->yend_; |
| 361 | 507 | } |
| 362 | 508 | |
| 509 | +/*! | |
| 510 | +@brief | |
| 511 | +Get a pointer (i.e., reference) to an element of a 2-D sequence. | |
| 512 | +*/ | |
| 363 | 513 | JAS_ATTRIBUTE_PURE |
| 364 | 514 | static inline jas_seqent_t *jas_seq2d_getref(const jas_seq2d_t *s, jas_matind_t x, jas_matind_t y) |
| 365 | 515 | { |
| 366 | 516 | return jas_matrix_getref(s, y - s->ystart_, x - s->xstart_); |
| 367 | 517 | } |
| 368 | 518 | |
| 519 | +/*! | |
| 520 | +@brief | |
| 521 | +Get an element of a 2-D sequence. | |
| 522 | +*/ | |
| 369 | 523 | JAS_ATTRIBUTE_PURE |
| 370 | 524 | static inline jas_seqent_t jas_seq2d_get(const jas_seq2d_t *s, jas_matind_t x, jas_matind_t y) |
| 371 | 525 | { |
| 372 | 526 | return jas_matrix_get(s, y - s->ystart_, x - s->xstart_); |
| 373 | 527 | } |
| 374 | 528 | |
| 529 | +/*! | |
| 530 | +@brief | |
| 531 | +Get the stride between successive rows in the sequence. | |
| 532 | +*/ | |
| 375 | 533 | JAS_ATTRIBUTE_PURE |
| 376 | 534 | static inline size_t jas_seq2d_rowstep(const jas_seq2d_t *s) |
| 377 | 535 | { |
| 378 | 536 | return jas_matrix_rowstep(s); |
| 379 | 537 | } |
| 380 | 538 | |
| 539 | +/*! | |
| 540 | +@brief | |
| 541 | +Get the number of columns in the sequence. | |
| 542 | +*/ | |
| 381 | 543 | JAS_ATTRIBUTE_PURE |
| 382 | 544 | static inline unsigned jas_seq2d_width(const jas_seq2d_t *s) |
| 383 | 545 | { |
| 384 | 546 | return (unsigned)(s->xend_ - s->xstart_); |
| 385 | 547 | } |
| 386 | 548 | |
| 549 | +/*! | |
| 550 | +@brief | |
| 551 | +Get the number of rows in the sequence. | |
| 552 | +*/ | |
| 387 | 553 | JAS_ATTRIBUTE_PURE |
| 388 | 554 | static inline unsigned jas_seq2d_height(const jas_seq2d_t *s) |
| 389 | 555 | { |
| 390 | 556 | return (unsigned)(s->yend_ - s->ystart_); |
| 391 | 557 | } |
| 392 | 558 | |
| 559 | +/*! | |
| 560 | +@brief | |
| 561 | +Set the shift (i.e., starting x- and y-coordinates) of the sequence. | |
| 562 | +*/ | |
| 393 | 563 | static inline void jas_seq2d_setshift(jas_seq2d_t *s, jas_matind_t x, jas_matind_t y) |
| 394 | 564 | { |
| 395 | 565 | s->xstart_ = x; |
| @@ -398,64 +568,109 @@ static inline void jas_seq2d_setshift(jas_seq2d_t *s, jas_matind_t x, jas_matind · 2 unmodified lines | ||
| 398 | 568 | s->yend_ = s->ystart_ + s->numrows_; |
| 399 | 569 | } |
| 400 | 570 | |
| 571 | +/*! | |
| 572 | +@brief | |
| 573 | +Get the number of elements in the sequence. | |
| 574 | +*/ | |
| 401 | 575 | JAS_ATTRIBUTE_PURE |
| 402 | 576 | static inline jas_matind_t jas_seq2d_size(const jas_seq2d_t *s) |
| 403 | 577 | { |
| 404 | 578 | return jas_seq2d_width(s) * jas_seq2d_height(s); |
| 405 | 579 | } |
| 406 | 580 | |
| 581 | +/*! | |
| 582 | +@brief | |
| 583 | +Test if the sequence is empty (i.e., contains no elements). | |
| 584 | +*/ | |
| 407 | 585 | JAS_ATTRIBUTE_PURE |
| 408 | 586 | static inline bool jas_seq2d_empty(const jas_seq2d_t *s) |
| 409 | 587 | { |
| 410 | 588 | return jas_seq2d_width(s) == 0 || jas_seq2d_height(s) == 0; |
| 411 | 589 | } |
| 412 | 590 | |
| 413 | −JAS_DLLEXPORT int jas_seq2d_bindsub(jas_matrix_t *s, jas_matrix_t *s1, jas_matind_t xstart, | |
| 591 | +/*! | |
| 592 | +@brief | |
| 593 | +Initialize a sequence to reference a subsequence of another sequence. | |
| 594 | +*/ | |
| 595 | +JAS_EXPORT | |
| 596 | +int jas_seq2d_bindsub(jas_matrix_t *s, jas_matrix_t *s1, jas_matind_t xstart, | |
| 414 | 597 | jas_matind_t ystart, jas_matind_t xend, jas_matind_t yend); |
| 415 | 598 | |
| 416 | 599 | /******************************************************************************\ |
| 417 | 600 | * Functions/macros for 1-D sequence class. |
| 418 | 601 | \******************************************************************************/ |
| 419 | 602 | |
| 603 | +/*! | |
| 604 | +@brief | |
| 605 | +Create a 1-D sequence. | |
| 606 | +*/ | |
| 420 | 607 | static inline jas_seq_t *jas_seq_create(jas_matind_t start, jas_matind_t end) |
| 421 | 608 | { |
| 422 | 609 | return jas_seq2d_create(start, 0, end, 1); |
| 423 | 610 | } |
| 424 | 611 | |
| 612 | +/*! | |
| 613 | +@brief | |
| 614 | +Destroy a 1-D sequence. | |
| 615 | +*/ | |
| 425 | 616 | static inline void jas_seq_destroy(jas_seq_t *seq) |
| 426 | 617 | { |
| 427 | 618 | jas_seq2d_destroy(seq); |
| 428 | 619 | } |
| 429 | 620 | |
| 621 | +/*! | |
| 622 | +@brief | |
| 623 | +Set an element of a sequence. | |
| 624 | +*/ | |
| 430 | 625 | static inline void jas_seq_set(jas_seq_t *seq, jas_matind_t i, jas_seqent_t v) |
| 431 | 626 | { |
| 432 | 627 | seq->rows_[0][i - seq->xstart_] = v; |
| 433 | 628 | } |
| 434 | 629 | |
| 630 | +/*! | |
| 631 | +@brief | |
| 632 | +Get a pointer (i.e., reference) to an element of a sequence. | |
| 633 | +*/ | |
| 435 | 634 | JAS_ATTRIBUTE_PURE |
| 436 | 635 | static inline jas_seqent_t *jas_seq_getref(const jas_seq_t *seq, jas_matind_t i) |
| 437 | 636 | { |
| 438 | 637 | return &seq->rows_[0][i - seq->xstart_]; |
| 439 | 638 | } |
| 440 | 639 | |
| 640 | +/*! | |
| 641 | +@brief | |
| 642 | +Get an element of a sequence. | |
| 643 | +*/ | |
| 441 | 644 | JAS_ATTRIBUTE_PURE |
| 442 | 645 | static inline jas_seqent_t jas_seq_get(const jas_seq_t *seq, jas_matind_t i) |
| 443 | 646 | { |
| 444 | 647 | return seq->rows_[0][i - seq->xstart_]; |
| 445 | 648 | } |
| 446 | 649 | |
| 650 | +/*! | |
| 651 | +@brief | |
| 652 | +Get the starting index of a sequence. | |
| 653 | +*/ | |
| 447 | 654 | JAS_ATTRIBUTE_PURE |
| 448 | 655 | static inline jas_matind_t jas_seq_start(const jas_seq_t *seq) |
| 449 | 656 | { |
| 450 | 657 | return seq->xstart_; |
| 451 | 658 | } |
| 452 | 659 | |
| 660 | +/*! | |
| 661 | +@brief | |
| 662 | +Get the ending index of a sequence. | |
| 663 | +*/ | |
| 453 | 664 | JAS_ATTRIBUTE_PURE |
| 454 | 665 | static inline jas_matind_t jas_seq_end(const jas_seq_t *seq) |
| 455 | 666 | { |
| 456 | 667 | return seq->xend_; |
| 457 | 668 | } |
| 458 | 669 | |
| 670 | +/*! | |
| 671 | + * @} | |
| 672 | + */ | |
| 673 | + | |
| 459 | 674 | #ifdef __cplusplus |
| 460 | 675 | } |
| 461 | 676 | #endif |
| @@ -75,6 +75,10 @@ · 74 unmodified lines | ||
| 75 | 75 | |
| 76 | 76 | /* The configuration header file should be included first. */ |
| 77 | 77 | #include <jasper/jas_config.h> /* IWYU pragma: export */ |
| 78 | + | |
| 79 | +#if defined(JAS_HAVE_FCNTL_H) | |
| 80 | +#include <fcntl.h> | |
| 81 | +#endif | |
| 78 | 82 | #include <jasper/jas_types.h> |
| 79 | 83 | |
| 80 | 84 | #ifdef __cplusplus |
| @@ -82,7 +86,7 @@ extern "C" { · 1 unmodified line | ||
| 82 | 86 | #endif |
| 83 | 87 | |
| 84 | 88 | /*! |
| 85 | − * @addtogroup iostreams | |
| 89 | + * @addtogroup module_iostreams | |
| 86 | 90 | * @{ |
| 87 | 91 | */ |
| 88 | 92 | |
| @@ -95,8 +99,6 @@ extern "C" { · 6 unmodified lines | ||
| 95 | 99 | #define O_BINARY 0 |
| 96 | 100 | #endif |
| 97 | 101 | |
| 98 | −#define EOF (-1) | |
| 99 | − | |
| 100 | 102 | /* |
| 101 | 103 | * Stream open flags. |
| 102 | 104 | */ |
| @@ -176,10 +178,10 @@ typedef void jas_stream_obj_t; · 73 unmodified lines | ||
| 176 | 178 | typedef struct { |
| 177 | 179 | |
| 178 | 180 | /* Read characters from a file object. */ |
| 179 | − int (*read_)(jas_stream_obj_t *obj, char *buf, unsigned cnt); | |
| 181 | + ssize_t (*read_)(jas_stream_obj_t *obj, char *buf, size_t cnt); | |
| 180 | 182 | |
| 181 | 183 | /* Write characters to a file object. */ |
| 182 | − int (*write_)(jas_stream_obj_t *obj, const char *buf, unsigned cnt); | |
| 184 | + ssize_t (*write_)(jas_stream_obj_t *obj, const char *buf, size_t cnt); | |
| 183 | 185 | |
| 184 | 186 | /* Set the position for a file object. */ |
| 185 | 187 | long (*seek_)(jas_stream_obj_t *obj, long offset, int origin); |
| @@ -189,8 +191,15 @@ typedef struct { · 3 unmodified lines | ||
| 189 | 191 | |
| 190 | 192 | } jas_stream_ops_t; |
| 191 | 193 | |
| 192 | −/* | |
| 193 | − * Stream object. | |
| 194 | +/*! | |
| 195 | +@brief | |
| 196 | +I/O stream object. | |
| 197 | + | |
| 198 | +@warning | |
| 199 | +Library users should never directly access any of the members of this | |
| 200 | +class. | |
| 201 | +The functions/macros provided by the JasPer library API should always | |
| 202 | +be used. | |
| 194 | 203 | */ |
| 195 | 204 | |
| 196 | 205 | typedef struct { |
| @@ -248,6 +257,7 @@ typedef struct { · 51 unmodified lines | ||
| 248 | 257 | typedef struct { |
| 249 | 258 | int fd; |
| 250 | 259 | int flags; |
| 260 | + char pathname[L_tmpnam + 1]; | |
| 251 | 261 | } jas_stream_fileobj_t; |
| 252 | 262 | |
| 253 | 263 | /* Delete underlying file object upon stream close. */ |
| @@ -268,10 +278,10 @@ typedef struct { · 14 unmodified lines | ||
| 268 | 278 | size_t bufsize_; |
| 269 | 279 | |
| 270 | 280 | /* The length of the file. */ |
| 271 | − uint_fast32_t len_; | |
| 281 | + size_t len_; | |
| 272 | 282 | |
| 273 | 283 | /* The seek position. */ |
| 274 | − uint_fast32_t pos_; | |
| 284 | + size_t pos_; | |
| 275 | 285 | |
| 276 | 286 | /* Is the buffer growable? */ |
| 277 | 287 | int growable_; |
| @@ -299,7 +309,7 @@ C standard library. · 21 unmodified lines | ||
| 299 | 309 | Upon success, a pointer to the opened stream is returned. |
| 300 | 310 | Otherwise, a null pointer is returned. |
| 301 | 311 | */ |
| 302 | −JAS_DLLEXPORT | |
| 312 | +JAS_EXPORT | |
| 303 | 313 | jas_stream_t *jas_stream_fopen(const char *filename, const char *mode); |
| 304 | 314 | |
| 305 | 315 | /*! |
| @@ -325,26 +335,20 @@ If buffer is not 0: · 19 unmodified lines | ||
| 325 | 335 | buffer_size (which, in this case, is not currently allowed to be zero) is |
| 326 | 336 | the size of the (nongrowable) buffer pointed to by buffer. |
| 327 | 337 | </ul> |
| 328 | − | |
| 329 | −@warning | |
| 330 | −TODO/FIXME: The type of the buffer_size parameter will be | |
| 331 | −changed to size_t in the future. | |
| 332 | − | |
| 333 | −@warning | |
| 334 | −TODO/FIXME: | |
| 335 | −In a later release, this function will be changed to have the same | |
| 336 | −prototype as jas_stream_memopen2, at which point jas_stream_memopen2 | |
| 337 | −will be removed. | |
| 338 | 338 | */ |
| 339 | −JAS_DLLEXPORT | |
| 340 | −jas_stream_t *jas_stream_memopen(char *buffer, int buffer_size); | |
| 339 | +JAS_EXPORT | |
| 340 | +jas_stream_t *jas_stream_memopen(char *buffer, size_t buffer_size); | |
| 341 | 341 | |
| 342 | 342 | /*! |
| 343 | −@warning | |
| 344 | −This function will be renamed jas_stream_memopen in a future release. | |
| 343 | +@brief | |
| 344 | +Do not use. | |
| 345 | +@deprecated | |
| 345 | 346 | Do not use this function. |
| 347 | +This function is deprecated. | |
| 348 | +Use jas_stream_memopen instead. | |
| 346 | 349 | */ |
| 347 | −JAS_DLLEXPORT | |
| 350 | +JAS_DEPRECATED | |
| 351 | +JAS_EXPORT | |
| 348 | 352 | jas_stream_t *jas_stream_memopen2(char *buffer, size_t buffer_size); |
| 349 | 353 | |
| 350 | 354 | /*! |
| @@ -361,9 +365,51 @@ in the C standard library. · 10 unmodified lines | ||
| 361 | 365 | Upon success, a pointer to the opened stream is returned. |
| 362 | 366 | Otherwise, a null pointer is returned. |
| 363 | 367 | */ |
| 364 | −JAS_DLLEXPORT | |
| 368 | +JAS_EXPORT | |
| 365 | 369 | jas_stream_t *jas_stream_fdopen(int fd, const char *mode); |
| 366 | 370 | |
| 371 | +/*! | |
| 372 | +@brief Open a stdio (i.e., C standard library) stream as a stream. | |
| 373 | + | |
| 374 | +@param path | |
| 375 | +A pointer to a null-terminated string containing the pathname of the file | |
| 376 | +to be reopened. | |
| 377 | +@param mode | |
| 378 | +A pointer to a null-terminated string containing the mode to be used for | |
| 379 | +reopening the file. | |
| 380 | +This string is similar to that used by the fdopen function in the | |
| 381 | +C standard library. | |
| 382 | +@param fp | |
| 383 | +A pointer to the `FILE` (i.e., stdio stream) to be reopened. | |
| 384 | + | |
| 385 | +@details | |
| 386 | +It is unspecified whether the open mode specified by mode can be | |
| 387 | +changed from the open mode used for opening the stdio stream. | |
| 388 | + | |
| 389 | +@return | |
| 390 | +Upon success, a pointer to the opened stream is returned. | |
| 391 | +Otherwise, a null pointer is returned. | |
| 392 | +*/ | |
| 393 | +JAS_EXPORT | |
| 394 | +jas_stream_t *jas_stream_freopen(const char *path, const char *mode, FILE *fp); | |
| 395 | + | |
| 396 | +/*! | |
| 397 | +@brief Open a temporary file as a stream. | |
| 398 | + | |
| 399 | +@details | |
| 400 | +A temporary file is created and opened as a stream. | |
| 401 | +The temporary file is deleted when closed via jas_stream_close(). | |
| 402 | +Some operating systems provide a mechanism for ensuring that a file | |
| 403 | +is removed when closed. | |
| 404 | +Such functionality may be used by the implementation when available. | |
| 405 | + | |
| 406 | +@return | |
| 407 | +Upon success, a pointer to the opened stream is returned. | |
| 408 | +Otherwise, a null pointer is returned. | |
| 409 | +*/ | |
| 410 | +JAS_EXPORT | |
| 411 | +jas_stream_t *jas_stream_tmpfile(void); | |
| 412 | + | |
| 367 | 413 | /*! |
| 368 | 414 | @brief Close a stream. |
| 369 | 415 | |
| @@ -382,7 +428,7 @@ can fail is due to an I/O error when flushing buffered output. · 12 unmodified lines | ||
| 382 | 428 | If no errors are encountered when closing the stream, 0 is returned. |
| 383 | 429 | Otherwise, a nonzero value is returned. |
| 384 | 430 | */ |
| 385 | −JAS_DLLEXPORT | |
| 431 | +JAS_EXPORT | |
| 386 | 432 | int jas_stream_close(jas_stream_t *stream); |
| 387 | 433 | |
| 388 | 434 | /******************************************************************************\ |
| @@ -404,6 +450,7 @@ A nonzero value indicates that the stream has encountered EOF. · 15 unmodified lines | ||
| 404 | 450 | |
| 405 | 451 | /*! |
| 406 | 452 | @brief Get the error indicator for a stream. |
| 453 | + | |
| 407 | 454 | @param stream |
| 408 | 455 | The stream whose error indicator is to be queried. |
| 409 | 456 | @return |
| @@ -417,6 +464,7 @@ Note that EOF is not an error. · 7 unmodified lines | ||
| 417 | 464 | |
| 418 | 465 | /*! |
| 419 | 466 | @brief Clear the error indicator for a stream. |
| 467 | + | |
| 420 | 468 | @param stream |
| 421 | 469 | The stream whose error indicator is to be cleared. |
| 422 | 470 | |
| @@ -441,6 +489,7 @@ effectively infinite). · 18 unmodified lines | ||
| 441 | 489 | |
| 442 | 490 | /*! |
| 443 | 491 | @brief Set the read/write limit for a stream. |
| 492 | + | |
| 444 | 493 | @param stream |
| 445 | 494 | A pointer to the stream whose read/write limit is to be set. |
| 446 | 495 | @param rwlimit |
| @@ -453,7 +502,7 @@ A negative read/write limit is treated as if it were infinity · 6 unmodified lines | ||
| 453 | 502 | @return |
| 454 | 503 | The old read/write limit is returned. |
| 455 | 504 | */ |
| 456 | −JAS_DLLEXPORT long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit); | |
| 505 | +JAS_EXPORT long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit); | |
| 457 | 506 | |
| 458 | 507 | /*! |
| 459 | 508 | @brief Get the read/write count for a stream. |
| @@ -470,6 +519,7 @@ This operation cannot fail. · 10 unmodified lines | ||
| 470 | 519 | |
| 471 | 520 | /*! |
| 472 | 521 | @brief Set the read/write count for a stream. |
| 522 | + | |
| 473 | 523 | @param stream |
| 474 | 524 | A pointer to the stream whose read/write count is to be set. |
| 475 | 525 | @param rw_count |
| @@ -480,7 +530,8 @@ This operation cannot fail. · 4 unmodified lines | ||
| 480 | 530 | @todo |
| 481 | 531 | TODO/FIXME: Should this macro evaluate to void? |
| 482 | 532 | */ |
| 483 | −JAS_DLLEXPORT long jas_stream_setrwcount(jas_stream_t *stream, long rw_count); | |
| 533 | +JAS_EXPORT | |
| 534 | +long jas_stream_setrwcount(jas_stream_t *stream, long rw_count); | |
| 484 | 535 | |
| 485 | 536 | /******************************************************************************\ |
| 486 | 537 | * Macros/functions for I/O. |
| @@ -491,6 +542,13 @@ JAS_DLLEXPORT long jas_stream_setrwcount(jas_stream_t *stream, long rw_count); · 4 unmodified lines | ||
| 491 | 542 | /*! |
| 492 | 543 | @brief jas_stream_getc |
| 493 | 544 | Read a character from a stream. |
| 545 | + | |
| 546 | +@param stream | |
| 547 | +A pointer to the stream from which to read a character. | |
| 548 | + | |
| 549 | +@returns | |
| 550 | +If a character is succesfully read, the character is returned. | |
| 551 | +Otherwise, EOF is returned. | |
| 494 | 552 | */ |
| 495 | 553 | #define jas_stream_getc(stream) jas_stream_getc_func(stream) |
| 496 | 554 | #else |
| @@ -502,6 +560,16 @@ Read a character from a stream. · 5 unmodified lines | ||
| 502 | 560 | /*! |
| 503 | 561 | @brief jas_stream_putc |
| 504 | 562 | Write a character to a stream. |
| 563 | + | |
| 564 | +@param stream | |
| 565 | +A pointer to the stream to which to write the character. | |
| 566 | +@param c | |
| 567 | +The character to be written. | |
| 568 | + | |
| 569 | +@returns | |
| 570 | +If the character is successfully output, the value of the character is | |
| 571 | +returned. | |
| 572 | +Otherwise, EOF is returned. | |
| 505 | 573 | */ |
| 506 | 574 | #define jas_stream_putc(stream, c) jas_stream_putc_func(stream, c) |
| 507 | 575 | #else |
| @@ -525,6 +593,9 @@ stream @c stream into the buffer starting at @c buffer. · 17 unmodified lines | ||
| 525 | 593 | The number of characters read can be less than @c count, due to |
| 526 | 594 | end-of-file (EOF) or an I/O error. |
| 527 | 595 | |
| 596 | +(This function is analogous to fread with the two read-count | |
| 597 | +parameters combined into a single size.) | |
| 598 | + | |
| 528 | 599 | @return |
| 529 | 600 | The number of characters read is returned. |
| 530 | 601 | In the case that the number of characters read is less than @c count, |
| @@ -535,18 +606,16 @@ to distinguish between: · 4 unmodified lines | ||
| 535 | 606 | <li>a failure due to the read/write limit being exceeded |
| 536 | 607 | <li>EOF. |
| 537 | 608 | </ol> |
| 538 | −TODO/CHECK: can items 1 and 2 be distinguished currently? | |
| 609 | +(The functions jas_stream_getrwcount() and jas_stream_getrwlimit() | |
| 610 | +can be used to distinguish between failure due to an I/O error | |
| 611 | +and failure due to the read/write limit being exceeed.) | |
| 539 | 612 | |
| 540 | −@warning | |
| 541 | −TODO/FIXME/CHECK: jas_stream_error should be true if RWLIMIT exceeded? | |
| 542 | −or need a jas_stream_rwlimit predicate? | |
| 543 | − | |
| 544 | −@warning | |
| 545 | −TODO/FIXME: In the future, the type of the count parameter and the | |
| 546 | −return type will be changed to size_t. | |
| 613 | +@todo | |
| 614 | +TODO: should jas_stream_error be true if RWLIMIT exceeded? | |
| 615 | +or maybe introduce a jas_stream_rwlimit predicate? | |
| 547 | 616 | */ |
| 548 | −JAS_DLLEXPORT | |
| 549 | −unsigned jas_stream_read(jas_stream_t *stream, void *buffer, unsigned count); | |
| 617 | +JAS_EXPORT | |
| 618 | +size_t jas_stream_read(jas_stream_t *stream, void *buffer, size_t count); | |
| 550 | 619 | |
| 551 | 620 | /*! |
| 552 | 621 | @brief Attempt to retrieve one or more pending characters of input |
| @@ -569,9 +638,11 @@ Returns the number of bytes copied to the given buffer, or 0 on error · 16 unmodified lines | ||
| 569 | 638 | or EOF. |
| 570 | 639 | |
| 571 | 640 | @warning |
| 572 | −TODO/FIXME: peeking at EOF should be distinguishable from an I/O error | |
| 641 | +TODO/FIXME: peeking at EOF should be distinguishable from an I/O error; | |
| 642 | +also should return type be changed to size_t? | |
| 643 | + | |
| 573 | 644 | */ |
| 574 | −JAS_DLLEXPORT | |
| 645 | +JAS_EXPORT | |
| 575 | 646 | unsigned jas_stream_peek(jas_stream_t *stream, void *buffer, size_t count); |
| 576 | 647 | |
| 577 | 648 | /*! |
| @@ -590,6 +661,9 @@ from the buffer starting at @c buffer to the stream @c stream. · 12 unmodified lines | ||
| 590 | 661 | The number of characters written can be less than @c count due to |
| 591 | 662 | an I/O error or the read/write limit being exceeded. |
| 592 | 663 | |
| 664 | +(This function is analogous to fwrite with the two write-count | |
| 665 | +parameters combined into a single size.) | |
| 666 | + | |
| 593 | 667 | @return |
| 594 | 668 | Upon success, the number of characters successfully written is returned. |
| 595 | 669 | If an error occurs, the value returned will be less than @c count. |
| @@ -599,15 +673,10 @@ of which does not currently exist?) can be used to distinguish between: · 3 unmodified lines | ||
| 599 | 673 | <li>failure due to an I/O error |
| 600 | 674 | <li>failure due to the read/write limit being exceeded |
| 601 | 675 | </ol> |
| 602 | − | |
| 603 | −@warning | |
| 604 | −TODO/FIXME: | |
| 605 | −The type of the count parameter should be size_t. | |
| 606 | −The return type should be size_t. | |
| 607 | 676 | */ |
| 608 | −JAS_DLLEXPORT | |
| 609 | −unsigned jas_stream_write(jas_stream_t *stream, const void *buffer, | |
| 610 | − unsigned count); | |
| 677 | +JAS_EXPORT | |
| 678 | +size_t jas_stream_write(jas_stream_t *stream, const void *buffer, | |
| 679 | + size_t count); | |
| 611 | 680 | |
| 612 | 681 | /*! |
| 613 | 682 | @brief Write formatted output to a stream. |
| @@ -630,7 +699,7 @@ If an error is encountered, a negative value is returned. · 16 unmodified lines | ||
| 630 | 699 | I think that the return type of int is okay here. |
| 631 | 700 | It is consistent with printf and friends. |
| 632 | 701 | */ |
| 633 | −JAS_DLLEXPORT | |
| 702 | +JAS_EXPORT | |
| 634 | 703 | int jas_stream_printf(jas_stream_t *stream, const char *format, ...); |
| 635 | 704 | |
| 636 | 705 | /*! |
| @@ -644,11 +713,14 @@ A pointer to a null-terminated string for output. · 7 unmodified lines | ||
| 644 | 713 | @details |
| 645 | 714 | The null character is not output. |
| 646 | 715 | |
| 716 | +(This function is analogous to fputs for C standard library streams.) | |
| 717 | + | |
| 647 | 718 | @return |
| 648 | 719 | Upon success, a nonnegative value is returned. |
| 649 | 720 | Upon failure, a negative value is returned. |
| 650 | 721 | */ |
| 651 | −JAS_DLLEXPORT int jas_stream_puts(jas_stream_t *stream, const char *s); | |
| 722 | +JAS_EXPORT | |
| 723 | +int jas_stream_puts(jas_stream_t *stream, const char *s); | |
| 652 | 724 | |
| 653 | 725 | /*! |
| 654 | 726 | @brief Read a line of input from a stream. |
| @@ -666,13 +738,15 @@ If a newline character is read, it is placed in the buffer. · 11 unmodified lines | ||
| 666 | 738 | Since the buffer may be too small to hold the input, |
| 667 | 739 | this operation can fail due to attempted buffer overrun. |
| 668 | 740 | |
| 741 | +(This function is analogous to fgets for C standard library streams.) | |
| 742 | + | |
| 669 | 743 | @return |
| 670 | 744 | If the operation fails (e.g., due to an I/O error or attempted buffer overrun), |
| 671 | 745 | a null pointer is returned. |
| 672 | 746 | Otherwise, buffer is returned. |
| 673 | 747 | */ |
| 674 | −JAS_DLLEXPORT char * | |
| 675 | −jas_stream_gets(jas_stream_t *stream, char *buffer, int buffer_size); | |
| 748 | +JAS_EXPORT | |
| 749 | +char *jas_stream_gets(jas_stream_t *stream, char *buffer, int buffer_size); | |
| 676 | 750 | |
| 677 | 751 | /*! |
| 678 | 752 | @brief Look at the next character to be read from a stream without actually |
| @@ -719,8 +793,8 @@ The approximate limit is given by the value of JAS_STREAM_MAXPUTBACK. · 40 unmodified lines | ||
| 719 | 793 | Upon success, zero is returned. |
| 720 | 794 | If the specified character cannot be pushed back, a negative value is returned. |
| 721 | 795 | */ |
| 722 | −JAS_DLLEXPORT int | |
| 723 | −jas_stream_ungetc(jas_stream_t *stream, int c); | |
| 796 | +JAS_EXPORT | |
| 797 | +int jas_stream_ungetc(jas_stream_t *stream, int c); | |
| 724 | 798 | |
| 725 | 799 | /******************************************************************************\ |
| 726 | 800 | * Macros/functions for getting/setting the stream position. |
| @@ -741,7 +815,8 @@ If the underlying file object supports seek operations, a (strictly) · 14 unmodified lines | ||
| 741 | 815 | positive value is returned. |
| 742 | 816 | Otherwise, 0 is returned. |
| 743 | 817 | */ |
| 744 | −JAS_ATTRIBUTE_PURE JAS_DLLEXPORT | |
| 818 | +JAS_EXPORT | |
| 819 | +JAS_ATTRIBUTE_PURE | |
| 745 | 820 | int jas_stream_isseekable(jas_stream_t *stream); |
| 746 | 821 | |
| 747 | 822 | /*! |
| @@ -763,37 +838,46 @@ in a similar fashion as the fseek function in the C standard library · 15 unmodified lines | ||
| 763 | 838 | Upon success, the new stream position is returned. |
| 764 | 839 | Upon failure, a negative value is returned. |
| 765 | 840 | */ |
| 766 | −JAS_DLLEXPORT | |
| 841 | +JAS_EXPORT | |
| 767 | 842 | long jas_stream_seek(jas_stream_t *stream, long offset, int origin); |
| 768 | 843 | |
| 769 | 844 | /*! |
| 770 | 845 | @brief Get the current position within the stream. |
| 846 | + | |
| 771 | 847 | @param stream |
| 772 | 848 | A pointer to the stream whose current position is to be queried. |
| 773 | 849 | |
| 774 | 850 | @details |
| 775 | 851 | The current position of the stream is returned. |
| 776 | 852 | |
| 853 | +(This function is analogous to ftell for C standard library streams.) | |
| 854 | + | |
| 777 | 855 | @return |
| 778 | 856 | Upon success, the current stream position is returned. |
| 779 | 857 | If an error is encountered, a negative value is returned. |
| 780 | 858 | */ |
| 781 | −JAS_ATTRIBUTE_PURE JAS_DLLEXPORT | |
| 859 | +JAS_EXPORT | |
| 782 | 860 | long jas_stream_tell(jas_stream_t *stream); |
| 783 | 861 | |
| 784 | 862 | /*! |
| 785 | 863 | @brief Seek to the beginning of a stream. |
| 864 | + | |
| 786 | 865 | @param stream |
| 787 | 866 | A pointer to the stream whose position is to be set. |
| 867 | + | |
| 788 | 868 | @details |
| 789 | 869 | The stream position is set to the start of the stream. |
| 790 | 870 | This function is equivalent to returning the value |
| 791 | 871 | of jas_stream_seek(stream, 0, SEEK_SET). |
| 872 | + | |
| 873 | +(This function is analogous to frewind for C standard library streams.) | |
| 874 | + | |
| 792 | 875 | @return |
| 793 | 876 | Upon success, the new stream position is returned. |
| 794 | 877 | Otherwise, a negative value is returned. |
| 795 | 878 | */ |
| 796 | −JAS_DLLEXPORT int jas_stream_rewind(jas_stream_t *stream); | |
| 879 | +JAS_EXPORT | |
| 880 | +int jas_stream_rewind(jas_stream_t *stream); | |
| 797 | 881 | |
| 798 | 882 | /******************************************************************************\ |
| 799 | 883 | * Macros/functions for flushing. |
| @@ -801,15 +885,21 @@ JAS_DLLEXPORT int jas_stream_rewind(jas_stream_t *stream); · 1 unmodified line | ||
| 801 | 885 | |
| 802 | 886 | /*! |
| 803 | 887 | @brief Flush any pending output to a stream. |
| 888 | + | |
| 804 | 889 | @param stream |
| 805 | 890 | A pointer to the stream for which output should be flushed. |
| 891 | + | |
| 806 | 892 | @details |
| 807 | 893 | The function flushes any buffered output to the underlying file object. |
| 894 | + | |
| 895 | +(This function is analogous to fflush for C standard library streams.) | |
| 896 | + | |
| 808 | 897 | @return |
| 809 | 898 | Upon success, zero is returned. |
| 810 | 899 | Otherwise, a negative value is returned. |
| 811 | 900 | */ |
| 812 | −JAS_DLLEXPORT int jas_stream_flush(jas_stream_t *stream); | |
| 901 | +JAS_EXPORT | |
| 902 | +int jas_stream_flush(jas_stream_t *stream); | |
| 813 | 903 | |
| 814 | 904 | /******************************************************************************\ |
| 815 | 905 | * Miscellaneous macros/functions. |
| @@ -828,14 +918,50 @@ The number of characters to copy. · 12 unmodified lines | ||
| 828 | 918 | @details |
| 829 | 919 | The function copies the specified number of characters from the |
| 830 | 920 | source stream to the destination stream. |
| 921 | +In particular, if @c count is nonnegative, @c count characters are | |
| 922 | +copied from the source stream @c source to the destination stream | |
| 923 | +@c destination. | |
| 924 | +Otherwise (i.e., if @c count is negative), the entire source | |
| 925 | +stream @c source (i.e., until EOF is reached) is copied to the | |
| 926 | +destination stream @c destination. | |
| 831 | 927 | |
| 832 | 928 | @return |
| 833 | 929 | Upon success, 0 is returned; otherwise, -1 is returned. |
| 834 | 930 | |
| 835 | 931 | @todo |
| 836 | −TODO/FIXME: count should probably be a size_t; return type ssize_t? | |
| 932 | +TODO/FIXME: should return type be ssize_t and the return value be | |
| 933 | +the count of the characters copied? | |
| 934 | +Perhaps, it might be safer to introduce a new function with differing | |
| 935 | +semantics and deprecate this one? | |
| 837 | 936 | */ |
| 838 | −JAS_DLLEXPORT int jas_stream_copy(jas_stream_t *destination, jas_stream_t *source, int count); | |
| 937 | +JAS_EXPORT | |
| 938 | +int jas_stream_copy(jas_stream_t *destination, jas_stream_t *source, | |
| 939 | + ssize_t count); | |
| 940 | + | |
| 941 | +/*! | |
| 942 | +@brief Print a hex dump of data read from a stream. | |
| 943 | + | |
| 944 | +@param stream | |
| 945 | +A pointer to the stream from which to read data. | |
| 946 | +@param fp | |
| 947 | +A pointer to a stdio stream (i.e., FILE) to which to print the hex dump. | |
| 948 | +@param count | |
| 949 | +The number of characters to include in the hex dump. | |
| 950 | + | |
| 951 | +@details | |
| 952 | +This function prints a hex dump of data read from a stream to a | |
| 953 | +stdio stream. | |
| 954 | +This function is most likely to be useful for debugging. | |
| 955 | + | |
| 956 | +@return | |
| 957 | +Upon success, 0 is returned. | |
| 958 | +Otherwise, a negative value is returned. | |
| 959 | + | |
| 960 | +@todo | |
| 961 | +TODO/FIXME: should count be unsigned int or size_t instead of int? | |
| 962 | +*/ | |
| 963 | +JAS_EXPORT | |
| 964 | +int jas_stream_display(jas_stream_t *stream, FILE *fp, int count); | |
| 839 | 965 | |
| 840 | 966 | /*! |
| 841 | 967 | @brief Consume (i.e., discard) characters from stream. |
| @@ -855,11 +981,9 @@ If an error or EOF is encountered, the number of characters read · 13 unmodified lines | ||
| 855 | 981 | will be less than count. |
| 856 | 982 | To distinguish EOF from an I/O error, jas_stream_eof() and jas_stream_error() |
| 857 | 983 | can be used. |
| 858 | − | |
| 859 | −@warning | |
| 860 | −TODO/FIXME: count be size_t and return type should be ssize_t | |
| 861 | 984 | */ |
| 862 | −JAS_DLLEXPORT int jas_stream_gobble(jas_stream_t *stream, int count); | |
| 985 | +JAS_EXPORT | |
| 986 | +ssize_t jas_stream_gobble(jas_stream_t *stream, size_t count); | |
| 863 | 987 | |
| 864 | 988 | /*! |
| 865 | 989 | @brief Write a fill character multiple times to a stream. |
| @@ -881,16 +1005,15 @@ The number of times the fill character was written to the stream is · 15 unmodified lines | ||
| 881 | 1005 | returned. |
| 882 | 1006 | If this value is less than the specified count, an error must have |
| 883 | 1007 | occurred. |
| 884 | − | |
| 885 | −@todo | |
| 886 | −TODO: should the count be size_t; return type maybe size_t? | |
| 887 | 1008 | */ |
| 888 | −JAS_DLLEXPORT int jas_stream_pad(jas_stream_t *stream, int count, int value); | |
| 1009 | +JAS_EXPORT | |
| 1010 | +ssize_t jas_stream_pad(jas_stream_t *stream, size_t count, int value); | |
| 889 | 1011 | |
| 890 | 1012 | /*! |
| 891 | 1013 | @brief Get the size of the file associated with the specified stream. |
| 892 | 1014 | |
| 893 | 1015 | @param stream |
| 1016 | +A pointer to the stream. | |
| 894 | 1017 | |
| 895 | 1018 | @details |
| 896 | 1019 | This function queries the size (i.e., length) of the underlying file object |
| @@ -901,10 +1024,11 @@ The specified stream must be seekable. · 4 unmodified lines | ||
| 901 | 1024 | Upon success, the size of the stream is returned. |
| 902 | 1025 | If an error occurs, a negative value is returned. |
| 903 | 1026 | |
| 904 | −@warning | |
| 905 | −TODO/FIXME: the return type should be ssize_t? | |
| 1027 | +@todo | |
| 1028 | +Should the return type be long or ssize_t? long is consistent with the | |
| 1029 | +type used for seek offsets. | |
| 906 | 1030 | */ |
| 907 | −JAS_ATTRIBUTE_PURE JAS_DLLEXPORT | |
| 1031 | +JAS_EXPORT | |
| 908 | 1032 | long jas_stream_length(jas_stream_t *stream); |
| 909 | 1033 | |
| 910 | 1034 | /******************************************************************************\ |
| @@ -917,10 +1041,10 @@ directly, you will die a horrible, miserable, and painful death! */ · 6 unmodified lines | ||
| 917 | 1041 | /* These prototypes need to be here for the sake of the stream_getc and |
| 918 | 1042 | stream_putc macros. */ |
| 919 | 1043 | /* Library users must not invoke these functions directly. */ |
| 920 | −JAS_DLLEXPORT int jas_stream_fillbuf(jas_stream_t *stream, int getflag); | |
| 921 | −JAS_DLLEXPORT int jas_stream_flushbuf(jas_stream_t *stream, int c); | |
| 922 | −JAS_DLLEXPORT int jas_stream_getc_func(jas_stream_t *stream); | |
| 923 | −JAS_DLLEXPORT int jas_stream_putc_func(jas_stream_t *stream, int c); | |
| 1044 | +JAS_EXPORT int jas_stream_fillbuf(jas_stream_t *stream, int getflag); | |
| 1045 | +JAS_EXPORT int jas_stream_flushbuf(jas_stream_t *stream, int c); | |
| 1046 | +JAS_EXPORT int jas_stream_getc_func(jas_stream_t *stream); | |
| 1047 | +JAS_EXPORT int jas_stream_putc_func(jas_stream_t *stream, int c); | |
| 924 | 1048 | |
| 925 | 1049 | /* Read a character from a stream. */ |
| 926 | 1050 | static inline int jas_stream_getc2(jas_stream_t *stream) |
| @@ -0,0 +1,150 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2002 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/*! | |
| 65 | + * @file jas_string.h | |
| 66 | + * @brief String Library | |
| 67 | + */ | |
| 68 | + | |
| 69 | +#ifndef JAS_STRING_H | |
| 70 | +#define JAS_STRING_H | |
| 71 | + | |
| 72 | +/******************************************************************************\ | |
| 73 | +* Includes. | |
| 74 | +\******************************************************************************/ | |
| 75 | + | |
| 76 | +/* The configuration header file should be included first. */ | |
| 77 | +#include <jasper/jas_config.h> | |
| 78 | + | |
| 79 | +#include <jasper/jas_types.h> | |
| 80 | + | |
| 81 | +#ifdef __cplusplus | |
| 82 | +extern "C" { | |
| 83 | +#endif | |
| 84 | + | |
| 85 | +/*! | |
| 86 | + * @addtogroup module_string | |
| 87 | + * @{ | |
| 88 | + */ | |
| 89 | + | |
| 90 | +/******************************************************************************\ | |
| 91 | +* Functions. | |
| 92 | +\******************************************************************************/ | |
| 93 | + | |
| 94 | +/*! | |
| 95 | +@brief | |
| 96 | +Create a copy of a null-terminated string. | |
| 97 | + | |
| 98 | +@details | |
| 99 | +This function has a behavior similar to the well-known strdup function. | |
| 100 | +*/ | |
| 101 | +JAS_EXPORT | |
| 102 | +char *jas_strdup(const char *); | |
| 103 | + | |
| 104 | +/*! | |
| 105 | +@brief | |
| 106 | +Extract tokens from a string. | |
| 107 | + | |
| 108 | +@details | |
| 109 | +This function has a similar behavior as @c strtok_r in the POSIX standard. | |
| 110 | +*/ | |
| 111 | +JAS_EXPORT | |
| 112 | +char *jas_strtok(char *str, const char *delim, char **saveptr); | |
| 113 | + | |
| 114 | +/*! | |
| 115 | +@brief | |
| 116 | +Split a string into tokens based on specified delimiters. | |
| 117 | + | |
| 118 | +@param string | |
| 119 | +A pointer to a null-terminated string to be split into tokens. | |
| 120 | +@param delim | |
| 121 | +A pointer to a null-terminated string contained characters used to delimit | |
| 122 | +tokens. | |
| 123 | +@param tokens_buf | |
| 124 | +A pointer to the output token array. | |
| 125 | +@param max_tokens_buf | |
| 126 | +A pointer to the allocated size of the token array. | |
| 127 | +@param num_tokens_buf | |
| 128 | +A pointer to the number of elements in the token array. | |
| 129 | + | |
| 130 | +@details | |
| 131 | +The memory to hold token information is allocated via jas_malloc() | |
| 132 | +and friends. | |
| 133 | + | |
| 134 | +@returns | |
| 135 | +If successful, zero is returned. | |
| 136 | +Otherwise, a nonzero value is returned. | |
| 137 | +*/ | |
| 138 | +JAS_EXPORT | |
| 139 | +int jas_stringtokenize(const char *string, const char *delim, | |
| 140 | + char ***tokens_buf, size_t *max_tokens_buf, size_t *num_tokens_buf); | |
| 141 | + | |
| 142 | +/*! | |
| 143 | + * @} | |
| 144 | + */ | |
| 145 | + | |
| 146 | +#ifdef __cplusplus | |
| 147 | +} | |
| 148 | +#endif | |
| 149 | + | |
| 150 | +#endif | |
| @@ -0,0 +1,795 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2003 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/*! | |
| 65 | + * @file jas_thread.h | |
| 66 | + * @brief Threads | |
| 67 | + */ | |
| 68 | + | |
| 69 | +#ifndef JAS_THREAD_H | |
| 70 | +#define JAS_THREAD_H | |
| 71 | + | |
| 72 | +/******************************************************************************\ | |
| 73 | +* Includes | |
| 74 | +\******************************************************************************/ | |
| 75 | + | |
| 76 | +/* The configuration header file should be included first. */ | |
| 77 | +#include <jasper/jas_config.h> | |
| 78 | + | |
| 79 | +#include "jasper/jas_compiler.h" | |
| 80 | +#include "jasper/jas_types.h" | |
| 81 | + | |
| 82 | +#if defined(JAS_THREADS) | |
| 83 | + | |
| 84 | +#include <stdlib.h> | |
| 85 | +#include <assert.h> | |
| 86 | + | |
| 87 | +#if defined(JAS_THREADS_C11) | |
| 88 | +#include <threads.h> | |
| 89 | +#include <stdatomic.h> | |
| 90 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 91 | +#include <pthread.h> | |
| 92 | +#include <sched.h> | |
| 93 | +#elif defined(JAS_THREADS_WIN32) | |
| 94 | +#include <process.h> | |
| 95 | +#include <windows.h> | |
| 96 | +#include <processthreadsapi.h> | |
| 97 | +#endif | |
| 98 | + | |
| 99 | +#endif | |
| 100 | + | |
| 101 | +/******************************************************************************\ | |
| 102 | +\******************************************************************************/ | |
| 103 | + | |
| 104 | +#ifdef __cplusplus | |
| 105 | +extern "C" { | |
| 106 | +#endif | |
| 107 | + | |
| 108 | +/*! | |
| 109 | + * @cond DOXYGEN_EXCLUDE | |
| 110 | + * @addtogroup module_threads | |
| 111 | + * @{ | |
| 112 | + */ | |
| 113 | + | |
| 114 | +#if defined(JAS_THREADS) | |
| 115 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY) | |
| 116 | + | |
| 117 | +/******************************************************************************\ | |
| 118 | +* Types | |
| 119 | +\******************************************************************************/ | |
| 120 | + | |
| 121 | +#if defined(JAS_THREADS_C11) | |
| 122 | +# define JAS_THREADS_IMPL "C11" | |
| 123 | +# define JAS_USE_SPINLOCK | |
| 124 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 125 | +# define JAS_THREADS_IMPL "PTHREAD" | |
| 126 | +# undef JAS_USE_SPINLOCK | |
| 127 | +#elif defined(JAS_THREADS_WIN32) | |
| 128 | +# define JAS_THREADS_IMPL "WIN32" | |
| 129 | +# define JAS_USE_SPINLOCK | |
| 130 | +#endif | |
| 131 | + | |
| 132 | +/**************************************\ | |
| 133 | +* Spinlock | |
| 134 | +\**************************************/ | |
| 135 | + | |
| 136 | +/*! Spinlock type. */ | |
| 137 | +#if defined(JAS_THREADS_C11) | |
| 138 | +# define JAS_USE_SPINLOCK | |
| 139 | +typedef struct { | |
| 140 | + atomic_flag flag; | |
| 141 | +} jas_spinlock_t; | |
| 142 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 143 | +/* There is no pthread_spinlock_t type on MacOS. */ | |
| 144 | +# undef JAS_USE_SPINLOCK | |
| 145 | +#elif defined(JAS_THREADS_WIN32) | |
| 146 | +# define JAS_USE_SPINLOCK | |
| 147 | +typedef struct { | |
| 148 | + LONG flag; | |
| 149 | +} jas_spinlock_t; | |
| 150 | +#endif | |
| 151 | + | |
| 152 | +/*! Spinlock initializer. */ | |
| 153 | +#if defined(JAS_THREADS_C11) | |
| 154 | +#define JAS_SPINLOCK_INITIALIZER {ATOMIC_FLAG_INIT} | |
| 155 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 156 | +/* There is no pthread_spinlock_t type on MacOS. */ | |
| 157 | +#elif defined(JAS_THREADS_WIN32) | |
| 158 | +#define JAS_SPINLOCK_INITIALIZER {0} | |
| 159 | +#endif | |
| 160 | + | |
| 161 | +/**************************************\ | |
| 162 | +* Basic Mutex | |
| 163 | +\**************************************/ | |
| 164 | + | |
| 165 | +/*! Mutex type. */ | |
| 166 | +#if defined(JAS_THREADS_C11) | |
| 167 | +typedef mtx_t jas_basicmutex_t; | |
| 168 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 169 | +typedef pthread_mutex_t jas_basicmutex_t; | |
| 170 | +#elif defined(JAS_THREADS_WIN32) | |
| 171 | +typedef CRITICAL_SECTION jas_basicmutex_t; | |
| 172 | +#endif | |
| 173 | + | |
| 174 | +/*! Mutex initializer. */ | |
| 175 | +#if defined(JAS_THREADS_C11) | |
| 176 | +#undef JAS_BASICMUTEX_INITIALIZER | |
| 177 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 178 | +#define JAS_BASICMUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER | |
| 179 | +#elif defined(JAS_THREADS_WIN32) | |
| 180 | +#define JAS_BASICMUTEX_INITIALIZER | |
| 181 | +#endif | |
| 182 | + | |
| 183 | +/**************************************\ | |
| 184 | +* Mutex (Allowing Static Initialization) | |
| 185 | +\**************************************/ | |
| 186 | + | |
| 187 | +#if defined(JAS_USE_SPINLOCK) | |
| 188 | +# define jas_mutex_t jas_spinlock_t | |
| 189 | +# define JAS_MUTEX_INITIALIZER JAS_SPINLOCK_INITIALIZER | |
| 190 | +# define jas_mutex_init jas_spinlock_init | |
| 191 | +# define jas_mutex_cleanup jas_spinlock_cleanup | |
| 192 | +# define jas_mutex_lock jas_spinlock_lock | |
| 193 | +# define jas_mutex_unlock jas_spinlock_unlock | |
| 194 | +#else | |
| 195 | +# define jas_mutex_t jas_basicmutex_t | |
| 196 | +# define JAS_MUTEX_INITIALIZER JAS_BASICMUTEX_INITIALIZER | |
| 197 | +# define jas_mutex_init jas_basicmutex_init | |
| 198 | +# define jas_mutex_cleanup jas_basicmutex_cleanup | |
| 199 | +# define jas_mutex_lock jas_basicmutex_lock | |
| 200 | +# define jas_mutex_unlock jas_basicmutex_unlock | |
| 201 | +#endif | |
| 202 | + | |
| 203 | +/**************************************\ | |
| 204 | +* Once Flag | |
| 205 | +\**************************************/ | |
| 206 | + | |
| 207 | +/*! Once-flag type. */ | |
| 208 | +#if defined(JAS_THREADS_C11) | |
| 209 | +typedef once_flag jas_once_flag_t; | |
| 210 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 211 | +typedef pthread_once_t jas_once_flag_t; | |
| 212 | +#elif defined(JAS_THREADS_WIN32) | |
| 213 | +typedef struct { | |
| 214 | + volatile LONG status; | |
| 215 | +} jas_once_flag_t; | |
| 216 | +#endif | |
| 217 | + | |
| 218 | +/*! Once-flag initializer. */ | |
| 219 | +#if defined(JAS_THREADS_C11) | |
| 220 | +# define JAS_ONCE_FLAG_INIT ONCE_FLAG_INIT | |
| 221 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 222 | +# define JAS_ONCE_FLAG_INIT PTHREAD_ONCE_INIT | |
| 223 | +#elif defined(JAS_THREADS_WIN32) | |
| 224 | +# define JAS_ONCE_FLAG_INIT {0} | |
| 225 | +#endif | |
| 226 | + | |
| 227 | +/**************************************\ | |
| 228 | +* Threads | |
| 229 | +\**************************************/ | |
| 230 | + | |
| 231 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY) | |
| 232 | + | |
| 233 | +/*! Thread ID type. */ | |
| 234 | +#if defined(JAS_THREADS_C11) | |
| 235 | +typedef thrd_t jas_thread_id_t; | |
| 236 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 237 | +typedef pthread_t jas_thread_id_t; | |
| 238 | +#elif defined(JAS_THREADS_WIN32) | |
| 239 | +typedef HANDLE jas_thread_id_t; | |
| 240 | +#endif | |
| 241 | + | |
| 242 | +/*! Thread type. */ | |
| 243 | +#if defined(JAS_THREADS_C11) | |
| 244 | +typedef thrd_t jas_thread_t; | |
| 245 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 246 | +typedef struct { | |
| 247 | + pthread_t id; | |
| 248 | + int (*func)(void *); | |
| 249 | + void *arg; | |
| 250 | + int result; | |
| 251 | +} jas_thread_t; | |
| 252 | +#elif defined(JAS_THREADS_WIN32) | |
| 253 | +typedef struct { | |
| 254 | + jas_thread_id_t id; | |
| 255 | + int (*func)(void *); | |
| 256 | + void *arg; | |
| 257 | +} jas_thread_t; | |
| 258 | +#endif | |
| 259 | + | |
| 260 | +static inline void jas_thread_yield(void); | |
| 261 | + | |
| 262 | +#endif | |
| 263 | + | |
| 264 | +/**************************************\ | |
| 265 | +* Thread-Specific Storage (TSS) | |
| 266 | +\**************************************/ | |
| 267 | + | |
| 268 | +/*! Thread-specific storage type. */ | |
| 269 | +#if defined(JAS_THREADS_C11) | |
| 270 | +typedef tss_t jas_tss_t; | |
| 271 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 272 | +typedef pthread_key_t jas_tss_t; | |
| 273 | +#elif defined(JAS_THREADS_WIN32) | |
| 274 | +typedef DWORD jas_tss_t; | |
| 275 | +#endif | |
| 276 | + | |
| 277 | + | |
| 278 | +/******************************************************************************\ | |
| 279 | +* Spinlock | |
| 280 | +\******************************************************************************/ | |
| 281 | + | |
| 282 | +#if defined(JAS_USE_SPINLOCK) | |
| 283 | + | |
| 284 | +/*! | |
| 285 | +@brief | |
| 286 | +Initialize a spinlock. | |
| 287 | + | |
| 288 | +@param mtx | |
| 289 | +A pointer to the spinlock to be initialized. | |
| 290 | + | |
| 291 | +@returns | |
| 292 | +If the spinlock is successfully initialized, zero is returned. | |
| 293 | +Otherwise, a nonzero value is returned. | |
| 294 | +*/ | |
| 295 | +static inline int jas_spinlock_init(jas_spinlock_t *mtx) | |
| 296 | +{ | |
| 297 | + assert(mtx); | |
| 298 | +#if defined(JAS_THREADS_C11) | |
| 299 | + atomic_flag_clear(&mtx->flag); | |
| 300 | + return 0; | |
| 301 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 302 | + JAS_UNUSED(mtx); | |
| 303 | + abort(); | |
| 304 | + return -1; | |
| 305 | +#elif defined(JAS_THREADS_WIN32) | |
| 306 | + InterlockedExchange(&mtx->flag, 0); | |
| 307 | + return 0; | |
| 308 | +#endif | |
| 309 | +} | |
| 310 | + | |
| 311 | +/*! | |
| 312 | +@brief | |
| 313 | +Clean up a spinlock mutex. | |
| 314 | + | |
| 315 | +@param mtx | |
| 316 | +A pointer to the spinlock to be cleaned up. | |
| 317 | + | |
| 318 | +@returns | |
| 319 | +If the spinlock is successfully cleaned up, zero is returned. | |
| 320 | +Otherwise, a nonzero value is returned. | |
| 321 | +*/ | |
| 322 | +static inline int jas_spinlock_cleanup(jas_spinlock_t *mtx) | |
| 323 | +{ | |
| 324 | + assert(mtx); | |
| 325 | +#if defined(JAS_THREADS_C11) | |
| 326 | + JAS_UNUSED(mtx); | |
| 327 | + return 0; | |
| 328 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 329 | + JAS_UNUSED(mtx); | |
| 330 | + abort(); | |
| 331 | + return -1; | |
| 332 | +#elif defined(JAS_THREADS_WIN32) | |
| 333 | + JAS_UNUSED(mtx); | |
| 334 | + return 0; | |
| 335 | +#endif | |
| 336 | +} | |
| 337 | + | |
| 338 | +/*! | |
| 339 | +@brief | |
| 340 | +Acquire a spinlock. | |
| 341 | + | |
| 342 | +@param mtx | |
| 343 | +A pointer to the spinlock to be acquired. | |
| 344 | + | |
| 345 | +@returns | |
| 346 | +If successful, zero is returned. | |
| 347 | +Otherwise, a nonzero value is returned. | |
| 348 | +*/ | |
| 349 | +static inline int jas_spinlock_lock(jas_spinlock_t *mtx) | |
| 350 | +{ | |
| 351 | + assert(mtx); | |
| 352 | +#if defined(JAS_THREADS_C11) | |
| 353 | + while (atomic_flag_test_and_set(&mtx->flag)) {} | |
| 354 | + return 0; | |
| 355 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 356 | + JAS_UNUSED(mtx); | |
| 357 | + abort(); | |
| 358 | + return -1; | |
| 359 | +#elif defined(JAS_THREADS_WIN32) | |
| 360 | + while (InterlockedCompareExchange(&mtx->flag, 1, 0)) {} | |
| 361 | + return 0; | |
| 362 | +#endif | |
| 363 | +} | |
| 364 | + | |
| 365 | +/*! | |
| 366 | +@brief | |
| 367 | +Release a spinlock. | |
| 368 | + | |
| 369 | +@param mtx | |
| 370 | +A pointer to the spinlock to be released. | |
| 371 | + | |
| 372 | +@returns | |
| 373 | +If the operation is successful, zero is returned. | |
| 374 | +Otherwise, a nonzero value is returned. | |
| 375 | +*/ | |
| 376 | +static inline int jas_spinlock_unlock(jas_spinlock_t *mtx) | |
| 377 | +{ | |
| 378 | + assert(mtx); | |
| 379 | +#if defined(JAS_THREADS_C11) | |
| 380 | + atomic_flag_clear(&mtx->flag); | |
| 381 | + return 0; | |
| 382 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 383 | + JAS_UNUSED(mtx); | |
| 384 | + abort(); | |
| 385 | + return -1; | |
| 386 | +#elif defined(JAS_THREADS_WIN32) | |
| 387 | + InterlockedExchange(&mtx->flag, 0); | |
| 388 | + return 0; | |
| 389 | +#endif | |
| 390 | +} | |
| 391 | + | |
| 392 | +#endif | |
| 393 | + | |
| 394 | +/******************************************************************************\ | |
| 395 | +* Basic Mutex | |
| 396 | +\******************************************************************************/ | |
| 397 | + | |
| 398 | +/* For internal use only. */ | |
| 399 | +static inline int jas_basicmutex_init(jas_basicmutex_t *mtx) | |
| 400 | +{ | |
| 401 | + assert(mtx); | |
| 402 | +#if defined(JAS_THREADS_C11) | |
| 403 | + return mtx_init(mtx, mtx_plain) == thrd_success ? 0 : -1; | |
| 404 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 405 | + return pthread_mutex_init(mtx, 0); | |
| 406 | +#elif defined(JAS_THREADS_WIN32) | |
| 407 | + InitializeCriticalSection(mtx); | |
| 408 | + return 0; | |
| 409 | +#endif | |
| 410 | +} | |
| 411 | + | |
| 412 | +/* For internal use only. */ | |
| 413 | +static inline int jas_basicmutex_cleanup(jas_basicmutex_t *mtx) | |
| 414 | +{ | |
| 415 | + assert(mtx); | |
| 416 | +#if defined(JAS_THREADS_C11) | |
| 417 | + mtx_destroy(mtx); | |
| 418 | + return 0; | |
| 419 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 420 | + return pthread_mutex_destroy(mtx); | |
| 421 | +#elif defined(JAS_THREADS_WIN32) | |
| 422 | + DeleteCriticalSection(mtx); | |
| 423 | + return 0; | |
| 424 | +#endif | |
| 425 | +} | |
| 426 | + | |
| 427 | +/* For internal use only. */ | |
| 428 | +static inline int jas_basicmutex_lock(jas_basicmutex_t *mtx) | |
| 429 | +{ | |
| 430 | + assert(mtx); | |
| 431 | +#if defined(JAS_THREADS_C11) | |
| 432 | + return mtx_lock(mtx); | |
| 433 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 434 | + return pthread_mutex_lock(mtx); | |
| 435 | +#elif defined(JAS_THREADS_WIN32) | |
| 436 | + EnterCriticalSection(mtx); | |
| 437 | + return 0; | |
| 438 | +#endif | |
| 439 | +} | |
| 440 | + | |
| 441 | +/* For internal use only. */ | |
| 442 | +static inline int jas_basicmutex_unlock(jas_basicmutex_t *mtx) | |
| 443 | +{ | |
| 444 | + assert(mtx); | |
| 445 | +#if defined(JAS_THREADS_C11) | |
| 446 | + return mtx_unlock(mtx); | |
| 447 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 448 | + return pthread_mutex_unlock(mtx); | |
| 449 | +#elif defined(JAS_THREADS_WIN32) | |
| 450 | + LeaveCriticalSection(mtx); | |
| 451 | + return 0; | |
| 452 | +#endif | |
| 453 | +} | |
| 454 | + | |
| 455 | +/******************************************************************************\ | |
| 456 | +* Thread-Specific Storage (TSS) | |
| 457 | +\******************************************************************************/ | |
| 458 | + | |
| 459 | +/*! | |
| 460 | +@brief | |
| 461 | +Create thread-specific storage. | |
| 462 | + | |
| 463 | +@param tss | |
| 464 | +A pointer to the TSS object to be initialized. | |
| 465 | +@param destructor | |
| 466 | +A function to be called when the TSS is deallocated when the thread exits. | |
| 467 | + | |
| 468 | +@returns | |
| 469 | +If the operation is successful, zero is returned. | |
| 470 | +Otherwise, a nonzero value is returned. | |
| 471 | +*/ | |
| 472 | +static inline | |
| 473 | +int jas_tss_create(jas_tss_t *tss, void (*destructor)(void *)) | |
| 474 | +{ | |
| 475 | + assert(tss); | |
| 476 | +#if defined(JAS_THREADS_C11) | |
| 477 | + return tss_create(tss, destructor) == thrd_success ? 0 : -1; | |
| 478 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 479 | + return pthread_key_create(tss, destructor); | |
| 480 | +#elif defined(JAS_THREADS_WIN32) | |
| 481 | + if (destructor) { | |
| 482 | + return -1; | |
| 483 | + } | |
| 484 | + DWORD id; | |
| 485 | + if ((id = TlsAlloc()) == TLS_OUT_OF_INDEXES) { | |
| 486 | + return -2; | |
| 487 | + } | |
| 488 | + *tss = id; | |
| 489 | + return 0; | |
| 490 | +#endif | |
| 491 | +} | |
| 492 | + | |
| 493 | +/*! | |
| 494 | +@brief Delete thread-specific storage. | |
| 495 | + | |
| 496 | +@param tss | |
| 497 | +The TSS to be destroyed. | |
| 498 | + | |
| 499 | +@returns | |
| 500 | +If the operation is successful, zero is returned. | |
| 501 | +Otherwise, a nonzero value is returned. | |
| 502 | +*/ | |
| 503 | +static inline | |
| 504 | +void jas_tss_delete(jas_tss_t tss) | |
| 505 | +{ | |
| 506 | +#if defined(JAS_THREADS_C11) | |
| 507 | + tss_delete(tss); | |
| 508 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 509 | + pthread_key_delete(tss); | |
| 510 | +#elif defined(JAS_THREADS_WIN32) | |
| 511 | + TlsFree(tss); | |
| 512 | +#endif | |
| 513 | +} | |
| 514 | + | |
| 515 | +/*! | |
| 516 | +@brief Get the thread-specific storage instance for the calling thread. | |
| 517 | + | |
| 518 | +@param tss | |
| 519 | +The TSS to be queried. | |
| 520 | + | |
| 521 | +@returns | |
| 522 | +A pointer to the TSS is returned. | |
| 523 | +*/ | |
| 524 | +static inline | |
| 525 | +void *jas_tss_get(jas_tss_t tss) | |
| 526 | +{ | |
| 527 | +#if defined(JAS_THREADS_C11) | |
| 528 | + return tss_get(tss); | |
| 529 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 530 | + return pthread_getspecific(tss); | |
| 531 | +#elif defined(JAS_THREADS_WIN32) | |
| 532 | + return TlsGetValue(tss); | |
| 533 | +#endif | |
| 534 | +} | |
| 535 | + | |
| 536 | +/*! | |
| 537 | +@brief Set the thread-specific storage instance for the calling thread. | |
| 538 | + | |
| 539 | +@param tss | |
| 540 | +The TSS object. | |
| 541 | + | |
| 542 | +@returns | |
| 543 | +If the operation is successful, zero is returned. | |
| 544 | +Otherwise, a nonzero value is returned. | |
| 545 | +*/ | |
| 546 | +static inline | |
| 547 | +int jas_tss_set(jas_tss_t tss, void *value) | |
| 548 | +{ | |
| 549 | +#if defined(JAS_THREADS_C11) | |
| 550 | + return tss_set(tss, value) == thrd_success ? 0 : -1; | |
| 551 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 552 | + return pthread_setspecific(tss, value); | |
| 553 | +#elif defined(JAS_THREADS_WIN32) | |
| 554 | + return TlsSetValue(tss, value) ? 0 : -1; | |
| 555 | +#endif | |
| 556 | +} | |
| 557 | + | |
| 558 | +/******************************************************************************\ | |
| 559 | +* Once Flag | |
| 560 | +\******************************************************************************/ | |
| 561 | + | |
| 562 | +/*! | |
| 563 | +@brief Register to call a function once. | |
| 564 | + | |
| 565 | +@param flag | |
| 566 | +A pointer to a flag to track whether the function has been called yet. | |
| 567 | +@param func | |
| 568 | +A pointer to the function to be called. | |
| 569 | + | |
| 570 | +@returns | |
| 571 | +*/ | |
| 572 | +static inline int jas_call_once(jas_once_flag_t *flag, void (*func)(void)) | |
| 573 | +{ | |
| 574 | + assert(flag); | |
| 575 | + assert(func); | |
| 576 | +#if defined(JAS_THREADS_C11) | |
| 577 | + call_once(flag, func); | |
| 578 | + return 0; | |
| 579 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 580 | + return pthread_once(flag, func); | |
| 581 | +#elif defined(JAS_THREADS_WIN32) | |
| 582 | + if (InterlockedCompareExchange(&flag->status, 1, 0) == 0) { | |
| 583 | + (func)(); | |
| 584 | + InterlockedExchange(&flag->status, 2); | |
| 585 | + } else { | |
| 586 | + while (flag->status == 1) { | |
| 587 | + /* Perform a busy wait. This is ugly. */ | |
| 588 | + /* Yield processor. */ | |
| 589 | + SwitchToThread(); | |
| 590 | + } | |
| 591 | + } | |
| 592 | + return 0; | |
| 593 | +#endif | |
| 594 | +} | |
| 595 | + | |
| 596 | +/******************************************************************************\ | |
| 597 | +* Threads | |
| 598 | +\******************************************************************************/ | |
| 599 | + | |
| 600 | +#if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY) | |
| 601 | + | |
| 602 | +#if defined(JAS_THREADS_PTHREAD) | |
| 603 | +static void *thread_func_wrapper(void *thread_ptr) | |
| 604 | +{ | |
| 605 | + jas_thread_t *thread = JAS_CAST(jas_thread_t *, thread_ptr); | |
| 606 | + int result = (thread->func)(thread->arg); | |
| 607 | + thread->result = result; | |
| 608 | + return thread; | |
| 609 | +} | |
| 610 | +#elif defined(JAS_THREADS_WIN32) | |
| 611 | +static unsigned __stdcall thread_func_wrapper(void *thread_ptr) | |
| 612 | +{ | |
| 613 | + jas_thread_t *thread = JAS_CAST(jas_thread_t *, thread_ptr); | |
| 614 | + int result = (thread->func)(thread->arg); | |
| 615 | + return JAS_CAST(unsigned, result); | |
| 616 | +} | |
| 617 | +#endif | |
| 618 | + | |
| 619 | +/*! | |
| 620 | +@brief Compare two thread IDs. | |
| 621 | + | |
| 622 | +@warning | |
| 623 | +This function is only for internal use by the JasPer software. | |
| 624 | +This function may be changed/removed without any notice in future versions | |
| 625 | +of JasPer. | |
| 626 | +*/ | |
| 627 | +static inline | |
| 628 | +int jas_thread_compare(jas_thread_id_t x, jas_thread_id_t y) | |
| 629 | +{ | |
| 630 | +#if defined(JAS_THREADS_C11) | |
| 631 | + return thrd_equal(x, y); | |
| 632 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 633 | + return pthread_equal(x, y); | |
| 634 | +#elif defined(JAS_THREADS_WIN32) | |
| 635 | + return GetThreadId(x) == GetThreadId(y); | |
| 636 | +#endif | |
| 637 | +} | |
| 638 | + | |
| 639 | +/*! | |
| 640 | +@brief Create a thread. | |
| 641 | + | |
| 642 | +@warning | |
| 643 | +This function is only for internal use by the JasPer software. | |
| 644 | +This function may be changed/removed without any notice in future versions | |
| 645 | +of JasPer. | |
| 646 | +*/ | |
| 647 | +static inline | |
| 648 | +int jas_thread_create(jas_thread_t *thread, int (*func)(void *), void *arg) | |
| 649 | +{ | |
| 650 | + assert(thread); | |
| 651 | + assert(func); | |
| 652 | +#if defined(JAS_THREADS_C11) | |
| 653 | + return thrd_create(thread, func, arg) == thrd_success ? 0 : -1; | |
| 654 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 655 | + thread->func = func; | |
| 656 | + thread->arg = arg; | |
| 657 | + thread->result = 0; | |
| 658 | + return pthread_create(&thread->id, 0, thread_func_wrapper, thread); | |
| 659 | +#elif defined(JAS_THREADS_WIN32) | |
| 660 | + uintptr_t handle; | |
| 661 | + thread->func = func; | |
| 662 | + thread->arg = arg; | |
| 663 | + if (!(handle = _beginthreadex(0, 0, thread_func_wrapper, thread, 0, 0))) { | |
| 664 | + return -1; | |
| 665 | + } | |
| 666 | + thread->id = JAS_CAST(jas_thread_id_t, handle); | |
| 667 | + return 0; | |
| 668 | +#endif | |
| 669 | +} | |
| 670 | + | |
| 671 | +/*! | |
| 672 | +@brief Join a thread. | |
| 673 | + | |
| 674 | +@warning | |
| 675 | +This function is only for internal use by the JasPer software. | |
| 676 | +This function may be changed/removed without any notice in future versions | |
| 677 | +of JasPer. | |
| 678 | +*/ | |
| 679 | +static inline | |
| 680 | +int jas_thread_join(jas_thread_t *thread, int *result) | |
| 681 | +{ | |
| 682 | + assert(thread); | |
| 683 | +#if defined(JAS_THREADS_C11) | |
| 684 | + return thrd_join(*thread, result) == thrd_success ? 0 : -1; | |
| 685 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 686 | + void *result_buf; | |
| 687 | + int ret = pthread_join(thread->id, &result_buf); | |
| 688 | + if (!ret) { | |
| 689 | + jas_thread_t *other_thread = JAS_CAST(jas_thread_t *, result_buf); | |
| 690 | + if (result) { | |
| 691 | + /* A null pointer is probably a bug. */ | |
| 692 | + assert(other_thread); | |
| 693 | + *result = other_thread ? other_thread->result : 0; | |
| 694 | + } | |
| 695 | + } | |
| 696 | + return ret; | |
| 697 | +#elif defined(JAS_THREADS_WIN32) | |
| 698 | + DWORD w; | |
| 699 | + DWORD code; | |
| 700 | + if ((w = WaitForSingleObject(thread->id, INFINITE)) != WAIT_OBJECT_0) { | |
| 701 | + return -1; | |
| 702 | + } | |
| 703 | + if (result) { | |
| 704 | + if (!GetExitCodeThread(thread->id, &code)) { | |
| 705 | + CloseHandle(thread->id); | |
| 706 | + return -1; | |
| 707 | + } | |
| 708 | + *result = JAS_CAST(int, code); | |
| 709 | + } | |
| 710 | + CloseHandle(thread->id); | |
| 711 | + return 0; | |
| 712 | +#endif | |
| 713 | +} | |
| 714 | + | |
| 715 | +/*! | |
| 716 | +@brief | |
| 717 | +Yield the processor. | |
| 718 | + | |
| 719 | +@warning | |
| 720 | +This function is only for internal use by the JasPer software. | |
| 721 | +This function may be changed/removed without any notice in future versions | |
| 722 | +of JasPer. | |
| 723 | +*/ | |
| 724 | + | |
| 725 | +static inline void jas_thread_yield(void) | |
| 726 | +{ | |
| 727 | +#if defined(JAS_THREADS_C11) | |
| 728 | + thrd_yield(); | |
| 729 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 730 | + sched_yield(); | |
| 731 | +#elif defined(JAS_THREADS_WIN32) | |
| 732 | + SwitchToThread(); | |
| 733 | +#endif | |
| 734 | +} | |
| 735 | + | |
| 736 | +#if 0 | |
| 737 | +/* This functionality is not available for all threading support libraries. */ | |
| 738 | +static inline | |
| 739 | +void jas_thread_exit(int result) | |
| 740 | +{ | |
| 741 | +#if defined(JAS_THREADS_C11) | |
| 742 | + thrd_exit(result); | |
| 743 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 744 | + /* This does not have a trivial implementation, as far as I can see. */ | |
| 745 | + /* There is no jas_thread_find function. */ | |
| 746 | + jas_thread_t *thread = jas_thread_find(pthread_self()); | |
| 747 | + thread->result = result; | |
| 748 | + pthread_exit(JAS_CAST(void *, thread)); | |
| 749 | +#endif | |
| 750 | +} | |
| 751 | +#endif | |
| 752 | + | |
| 753 | +#if 0 | |
| 754 | +/*! | |
| 755 | +@brief Get the ID of the calling thread. | |
| 756 | +*/ | |
| 757 | +static inline | |
| 758 | +jas_thread_id_t jas_thread_current(void) | |
| 759 | +{ | |
| 760 | +#if defined(JAS_THREADS_C11) | |
| 761 | + return thrd_current(); | |
| 762 | +#elif defined(JAS_THREADS_PTHREAD) | |
| 763 | + return pthread_self(); | |
| 764 | +#elif defined(JAS_THREADS_WIN32) | |
| 765 | + /* FIXME - NOT YET IMPLEMENTED. */ | |
| 766 | + abort(); | |
| 767 | +#endif | |
| 768 | +} | |
| 769 | +#endif | |
| 770 | + | |
| 771 | +#endif | |
| 772 | + | |
| 773 | +/******************************************************************************\ | |
| 774 | +* | |
| 775 | +\******************************************************************************/ | |
| 776 | + | |
| 777 | +#endif | |
| 778 | +#else | |
| 779 | + | |
| 780 | +/******************************************************************************\ | |
| 781 | +* No Threading Support. | |
| 782 | +\******************************************************************************/ | |
| 783 | + | |
| 784 | +#endif | |
| 785 | + | |
| 786 | +/*! | |
| 787 | + * @} | |
| 788 | + * @endcond | |
| 789 | + */ | |
| 790 | + | |
| 791 | +#ifdef __cplusplus | |
| 792 | +} | |
| 793 | +#endif | |
| 794 | + | |
| 795 | +#endif | |
| @@ -0,0 +1,200 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2001-2002 Michael David Adams. | |
| 3 | + * All rights reserved. | |
| 4 | + */ | |
| 5 | + | |
| 6 | +/* __START_OF_JASPER_LICENSE__ | |
| 7 | + * | |
| 8 | + * JasPer License Version 2.0 | |
| 9 | + * | |
| 10 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 11 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 12 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 13 | + * | |
| 14 | + * All rights reserved. | |
| 15 | + * | |
| 16 | + * Permission is hereby granted, free of charge, to any person (the | |
| 17 | + * "User") obtaining a copy of this software and associated documentation | |
| 18 | + * files (the "Software"), to deal in the Software without restriction, | |
| 19 | + * including without limitation the rights to use, copy, modify, merge, | |
| 20 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 21 | + * persons to whom the Software is furnished to do so, subject to the | |
| 22 | + * following conditions: | |
| 23 | + * | |
| 24 | + * 1. The above copyright notices and this permission notice (which | |
| 25 | + * includes the disclaimer below) shall be included in all copies or | |
| 26 | + * substantial portions of the Software. | |
| 27 | + * | |
| 28 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 29 | + * promote products derived from the Software without specific prior | |
| 30 | + * written permission. | |
| 31 | + * | |
| 32 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 33 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 34 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 35 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 36 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 37 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 38 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 39 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 40 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 41 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 42 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 43 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 44 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 45 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 46 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 47 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 48 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 49 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 50 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 51 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 52 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 53 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 54 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 55 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 56 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 57 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 58 | + * | |
| 59 | + * __END_OF_JASPER_LICENSE__ | |
| 60 | + */ | |
| 61 | + | |
| 62 | +/*! | |
| 63 | + * @file jas_tvp.h | |
| 64 | + * @brief Tag/Value Pair Parser | |
| 65 | + */ | |
| 66 | + | |
| 67 | +#ifndef JAS_TVP_H | |
| 68 | +#define JAS_TVP_H | |
| 69 | + | |
| 70 | +/******************************************************************************\ | |
| 71 | +* Includes. | |
| 72 | +\******************************************************************************/ | |
| 73 | + | |
| 74 | +/* The configuration header file should be included first. */ | |
| 75 | +#include <jasper/jas_config.h> | |
| 76 | + | |
| 77 | +#ifdef __cplusplus | |
| 78 | +extern "C" { | |
| 79 | +#endif | |
| 80 | + | |
| 81 | +/*! | |
| 82 | + * @addtogroup module_tvp | |
| 83 | + * @{ | |
| 84 | + */ | |
| 85 | + | |
| 86 | +/******************************************************************************\ | |
| 87 | +* Types. | |
| 88 | +\******************************************************************************/ | |
| 89 | + | |
| 90 | +/*! | |
| 91 | +@brief | |
| 92 | +Tag information type. | |
| 93 | +*/ | |
| 94 | +typedef struct { | |
| 95 | + | |
| 96 | + int id; | |
| 97 | + /* The ID for the tag. */ | |
| 98 | + | |
| 99 | + const char *name; | |
| 100 | + /* The name of the tag. */ | |
| 101 | + | |
| 102 | +} jas_taginfo_t; | |
| 103 | + | |
| 104 | +/*! | |
| 105 | +@brief | |
| 106 | +Tag-value parser type. | |
| 107 | +*/ | |
| 108 | +typedef struct { | |
| 109 | + | |
| 110 | + char *buf; | |
| 111 | + /* The parsing buffer. */ | |
| 112 | + | |
| 113 | + char *tag; | |
| 114 | + /* The current tag name. */ | |
| 115 | + | |
| 116 | + const char *val; | |
| 117 | + /* The current value. */ | |
| 118 | + | |
| 119 | + char *pos; | |
| 120 | + /* The current position in the parsing buffer. */ | |
| 121 | + | |
| 122 | +} jas_tvparser_t; | |
| 123 | + | |
| 124 | +/******************************************************************************\ | |
| 125 | +* Tag information functions. | |
| 126 | +\******************************************************************************/ | |
| 127 | + | |
| 128 | +/*! | |
| 129 | +@brief | |
| 130 | +Lookup a tag by name. | |
| 131 | +*/ | |
| 132 | +JAS_ATTRIBUTE_PURE | |
| 133 | +JAS_EXPORT | |
| 134 | +const jas_taginfo_t *jas_taginfos_lookup(const jas_taginfo_t *taginfos, | |
| 135 | + const char *name); | |
| 136 | + | |
| 137 | +/*! | |
| 138 | +@brief | |
| 139 | +Ensure a nonnull taginfo pointer. | |
| 140 | + | |
| 141 | +@details | |
| 142 | +This function returns a pointer to the specified taginfo object if it | |
| 143 | + exists (i.e., the pointer is nonnull); otherwise, a pointer to a dummy | |
| 144 | + object is returned. This is useful in some situations to avoid checking | |
| 145 | + for a null pointer. | |
| 146 | +*/ | |
| 147 | +JAS_ATTRIBUTE_PURE | |
| 148 | +JAS_EXPORT | |
| 149 | +const jas_taginfo_t *jas_taginfo_nonull(const jas_taginfo_t *taginfo); | |
| 150 | + | |
| 151 | +/******************************************************************************\ | |
| 152 | +* Tag-value parser functions. | |
| 153 | +\******************************************************************************/ | |
| 154 | + | |
| 155 | +/*! | |
| 156 | +@brief | |
| 157 | +Create a tag-value parser for the specified string. | |
| 158 | +*/ | |
| 159 | +JAS_EXPORT | |
| 160 | +jas_tvparser_t *jas_tvparser_create(const char *s); | |
| 161 | + | |
| 162 | +/*! | |
| 163 | +@brief | |
| 164 | +Destroy a tag-value parser. | |
| 165 | +*/ | |
| 166 | +JAS_EXPORT | |
| 167 | +void jas_tvparser_destroy(jas_tvparser_t *tvparser); | |
| 168 | + | |
| 169 | +/*! | |
| 170 | +@brief | |
| 171 | +Get the next tag-value pair. | |
| 172 | +*/ | |
| 173 | +JAS_EXPORT | |
| 174 | +int jas_tvparser_next(jas_tvparser_t *tvparser); | |
| 175 | + | |
| 176 | +/*! | |
| 177 | +@brief | |
| 178 | +Get the tag name for the current tag-value pair. | |
| 179 | +*/ | |
| 180 | +JAS_ATTRIBUTE_PURE | |
| 181 | +JAS_EXPORT | |
| 182 | +const char *jas_tvparser_gettag(const jas_tvparser_t *tvparser); | |
| 183 | + | |
| 184 | +/*! | |
| 185 | +@brief | |
| 186 | +Get the value for the current tag-value pair. | |
| 187 | +*/ | |
| 188 | +JAS_ATTRIBUTE_PURE | |
| 189 | +JAS_EXPORT | |
| 190 | +const char *jas_tvparser_getval(const jas_tvparser_t *tvparser); | |
| 191 | + | |
| 192 | +/*! | |
| 193 | + * @} | |
| 194 | + */ | |
| 195 | + | |
| 196 | +#ifdef __cplusplus | |
| 197 | +} | |
| 198 | +#endif | |
| 199 | + | |
| 200 | +#endif | |
| @@ -72,47 +72,71 @@ · 71 unmodified lines | ||
| 72 | 72 | /* The configuration header file should be included first. */ |
| 73 | 73 | #include <jasper/jas_config.h> |
| 74 | 74 | |
| 75 | −#define INT_MAX 0x7fffffff | |
| 76 | −#define UINT_FAST32_MAX 0xffffffff | |
| 77 | −#define SIZE_MAX UINT_FAST32_MAX | |
| 78 | −#define INT_FAST32_MIN ((s32int)0x80000000) | |
| 79 | −#define INT_FAST32_MAX INT_MAX | |
| 80 | −#define LONG_MAX INT_MAX | |
| 81 | − | |
| 82 | −typedef s8int int_least8_t; | |
| 83 | −typedef s16int int_fast16_t; | |
| 84 | −typedef s32int int_fast32_t; | |
| 85 | −typedef s32int int_least32_t; | |
| 86 | −typedef s64int int_fast64_t; | |
| 87 | − | |
| 88 | −typedef u8int uint_least8_t; | |
| 89 | −typedef u8int uint_fast8_t; | |
| 90 | −typedef u16int uint_fast16_t; | |
| 91 | −typedef u16int uint_least16_t; | |
| 92 | −typedef u32int uint_fast32_t; | |
| 93 | −typedef u32int uint_least32_t; | |
| 94 | −typedef u64int uint_least64_t; | |
| 95 | −typedef u64int uint_fast64_t; | |
| 96 | − | |
| 97 | −typedef unsigned char jas_uchar; | |
| 98 | −typedef unsigned int jas_uint; | |
| 99 | −typedef unsigned long jas_ulong; | |
| 100 | −typedef long long jas_longlong; | |
| 101 | −typedef unsigned long long jas_ulonglong; | |
| 102 | − | |
| 103 | −typedef enum { false, true } bool; | |
| 75 | +#if defined(JAS_HAVE_SYS_TYPES_H) | |
| 76 | +#include <sys/types.h> /* IWYU pragma: export */ | |
| 77 | +#endif | |
| 78 | + | |
| 79 | +#ifdef __cplusplus | |
| 80 | +extern "C" { | |
| 81 | +#endif | |
| 82 | + | |
| 83 | +#define jas_uchar unsigned char | |
| 84 | +#define jas_uint unsigned int | |
| 85 | +#define jas_ulong unsigned long | |
| 86 | +#define jas_longlong long long | |
| 87 | +#define jas_ulonglong unsigned long long | |
| 88 | + | |
| 89 | +#if !defined(JAS_NO_SET_SSIZE_T) | |
| 90 | +# if !defined(SSIZE_MAX) | |
| 91 | +# if (JAS_SIZEOF_INT == JAS_SIZEOF_SIZE_T) | |
| 92 | +# define ssize_t int | |
| 93 | +# define SSIZE_MAX INT_MAX | |
| 94 | +# elif (JAS_SIZEOF_LONG == JAS_SIZEOF_SIZE_T) | |
| 95 | +# define ssize_t long | |
| 96 | +# define SSIZE_MAX LONG_MAX | |
| 97 | +# else | |
| 98 | +# define ssize_t jas_longlong | |
| 99 | +# define SSIZE_MAX LLONG_MAX | |
| 100 | +# endif | |
| 101 | +# endif | |
| 102 | +#endif | |
| 103 | + | |
| 104 | +#if 0 | |
| 105 | +#if defined(JAS_HAVE_SSIZE_T) | |
| 106 | +#define jas_ssize_t ssize_t | |
| 107 | +#define JAS_SSIZE_MAX SSIZE_MAX | |
| 108 | +#else | |
| 109 | +#define jas_ssize_t jas_longlong | |
| 110 | +#define JAS_SSIZE_MAX LLONG_MAX | |
| 111 | +#endif | |
| 112 | +#endif | |
| 113 | + | |
| 114 | +#if defined(_MSC_VER) && (_MSC_VER < 1800) | |
| 115 | +#define bool int | |
| 116 | +#define false 0 | |
| 117 | +#define true 1 | |
| 104 | 118 | |
| 105 | 119 | #define PRIxFAST32 "x" |
| 106 | 120 | #define PRIxFAST16 PRIxFAST32 |
| 107 | 121 | #define PRIuFAST32 "u" |
| 108 | 122 | #define PRIuFAST16 PRIuFAST32 |
| 109 | 123 | #define PRIiFAST32 "i" |
| 110 | −#define PRIiLEAST32 PRIiFAST32 | |
| 111 | −#define PRIxLEAST16 "x" | |
| 112 | −#define PRIdPTR "lld" | |
| 113 | −#define _HUGE_ENUF 1e+300 | |
| 124 | +#ifdef _WIN64 | |
| 125 | + #define PRIdPTR "lld" | |
| 126 | +#else | |
| 127 | + #define PRIdPTR "d" | |
| 128 | +#endif | |
| 129 | + | |
| 130 | +#ifndef _HUGE_ENUF | |
| 131 | + #define _HUGE_ENUF 1e+300 | |
| 132 | +#endif | |
| 133 | + | |
| 114 | 134 | #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) |
| 115 | 135 | |
| 136 | +#define strtoull _strtoui64 | |
| 137 | + | |
| 138 | +#endif | |
| 139 | + | |
| 116 | 140 | /* The below macro is intended to be used for type casts. By using this |
| 117 | 141 | macro, type casts can be easily located in the source code with |
| 118 | 142 | tools like "grep". */ |
| @@ -123,10 +147,60 @@ typedef enum { false, true } bool; · 4 unmodified lines | ||
| 123 | 147 | /* NOTE: This could underestimate the size on some exotic architectures. */ |
| 124 | 148 | #define JAS_UINTFAST32_NUMBITS (8 * sizeof(uint_fast32_t)) |
| 125 | 149 | |
| 126 | −#ifdef __cplusplus | |
| 127 | −extern "C" { | |
| 150 | +#if 0 | |
| 151 | +#if defined(JAS_HAVE_MAX_ALIGN_T) | |
| 152 | +#define jas_max_align_t max_align_t | |
| 153 | +#else | |
| 154 | +#define jas_max_align_t long double | |
| 155 | +#endif | |
| 156 | +#endif | |
| 157 | + | |
| 158 | +/* | |
| 159 | +Assume that a compiler claiming to be compliant with C11 or a later version | |
| 160 | +of the C standard provides a suitable definition of max_align_t. | |
| 161 | +The JAS_NO_SET_MAX_ALIGN_T preprocessor symbol can be used to override | |
| 162 | +this behavior. | |
| 163 | +*/ | |
| 164 | +#if defined(JAS_NO_SET_MAX_ALIGN_T) | |
| 165 | + /* | |
| 166 | + The user of this header is assuming responsibility for providing a | |
| 167 | + suitable definition for max_align_t. | |
| 168 | + */ | |
| 169 | +#elif defined(_MSC_VER) | |
| 170 | + /* | |
| 171 | + Define max_align_t as a preprocessor symbol since using typedef will | |
| 172 | + cause problems. | |
| 173 | + */ | |
| 174 | +# define max_align_t long double | |
| 175 | +#elif !(defined(__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 201112L)) | |
| 176 | +# define max_align_t long double | |
| 128 | 177 | #endif |
| 129 | 178 | |
| 179 | +#if 0 | |
| 180 | +#if defined(JAS_HAVE_UINTMAX_T) | |
| 181 | +#define jas_uintmax_t uintmax_t | |
| 182 | +#else | |
| 183 | +#define jas_uintmax_t uint_fast64_t | |
| 184 | +#endif | |
| 185 | +#endif | |
| 186 | + | |
| 187 | +#if 0 | |
| 188 | +#if defined(JAS_HAVE_INTMAX_T) | |
| 189 | +#define jas_intmax_t intmax_t | |
| 190 | +#else | |
| 191 | +#define jas_intmax_t int_fast64_t | |
| 192 | +#endif | |
| 193 | +#endif | |
| 194 | + | |
| 195 | +/* 32-bit unsigned integer type */ | |
| 196 | +typedef uint_least32_t jas_ui32_t; | |
| 197 | +#define JAS_UI32_MAX UINT_LEAST32_MAX | |
| 198 | + | |
| 199 | +/* 32-bit signed integer type */ | |
| 200 | +typedef int_least32_t jas_i32_t; | |
| 201 | +#define JAS_I32_MIN INT_LEAST32_MIN | |
| 202 | +#define JAS_I32_MAX INT_LEAST32_MAX | |
| 203 | + | |
| 130 | 204 | #ifdef __cplusplus |
| 131 | 205 | } |
| 132 | 206 | #endif |
| @@ -0,0 +1,113 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2003 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/*! | |
| 65 | + * @file jas_version.h | |
| 66 | + * @brief JasPer Version | |
| 67 | + */ | |
| 68 | + | |
| 69 | +#ifndef JAS_VERSION_H | |
| 70 | +#define JAS_VERSION_H | |
| 71 | + | |
| 72 | +/* The configuration header file should be included first. */ | |
| 73 | +#include <jasper/jas_config.h> | |
| 74 | + | |
| 75 | +#ifdef __cplusplus | |
| 76 | +extern "C" { | |
| 77 | +#endif | |
| 78 | + | |
| 79 | +/******************************************************************************\ | |
| 80 | +* Constants and types. | |
| 81 | +\******************************************************************************/ | |
| 82 | + | |
| 83 | +#define JAS_COPYRIGHT \ | |
| 84 | + "Copyright (c) 2001-2022 Michael David Adams.\n" \ | |
| 85 | + "Copyright (c) 1999-2000 Image Power, Inc. and the University of\n" \ | |
| 86 | + " British Columbia.\n" \ | |
| 87 | + "All rights reserved.\n" | |
| 88 | + | |
| 89 | +#define JAS_NOTES \ | |
| 90 | + "For information about the JasPer project, see:\n" \ | |
| 91 | + " https://jasper-software.github.io/jasper\n" \ | |
| 92 | + " https://www.ece.uvic.ca/~mdadams/jasper\n" \ | |
| 93 | + "For online documentation on the JasPer software, see:\n" \ | |
| 94 | + " https://jasper-software.github.io/jasper-manual\n" \ | |
| 95 | + "Please submit bug reports using the bug-tracker at:\n" \ | |
| 96 | + " https://github.com/jasper-software/jasper/issues\n" | |
| 97 | + | |
| 98 | +/******************************************************************************\ | |
| 99 | +* Functions. | |
| 100 | +\******************************************************************************/ | |
| 101 | + | |
| 102 | +JAS_ATTRIBUTE_CONST | |
| 103 | +JAS_EXPORT | |
| 104 | +const char *jas_getversion(void); | |
| 105 | +/* Get the version information for the JasPer library. */ | |
| 106 | +/* Note: Since libjasper can be built as a shared library, the version | |
| 107 | + returned by this function may not necessarily correspond to JAS_VERSION. */ | |
| 108 | + | |
| 109 | +#ifdef __cplusplus | |
| 110 | +} | |
| 111 | +#endif | |
| 112 | + | |
| 113 | +#endif | |
| @@ -73,6 +73,7 @@ · 72 unmodified lines | ||
| 73 | 73 | #include <jasper/jas_config.h> |
| 74 | 74 | |
| 75 | 75 | #include <jasper/jas_types.h> |
| 76 | +#include <jasper/jas_version.h> | |
| 76 | 77 | |
| 77 | 78 | #include <jasper/jas_init.h> |
| 78 | 79 | #include <jasper/jas_cm.h> |
| @@ -84,6 +85,11 @@ · 5 unmodified lines | ||
| 84 | 85 | #include <jasper/jas_malloc.h> |
| 85 | 86 | #include <jasper/jas_seq.h> |
| 86 | 87 | #include <jasper/jas_stream.h> |
| 88 | +#include <jasper/jas_string.h> | |
| 89 | +#include <jasper/jas_tvp.h> | |
| 90 | +#include <jasper/jas_thread.h> | |
| 91 | +#include <jasper/jas_init.h> | |
| 92 | +#include <jasper/jas_log.h> | |
| 87 | 93 | |
| 88 | 94 | #pragma lib "./libjp2.a" |
| 89 | 95 | |
| @@ -34,7 +34,10 @@ main(int argc, char **argv) · 33 unmodified lines | ||
| 34 | 34 | usage(); |
| 35 | 35 | |
| 36 | 36 | memimageinit(); |
| 37 | − jas_init(); | |
| 37 | + jas_conf_clear(); | |
| 38 | + jas_conf_set_max_mem_usage(512*1024*1024); | |
| 39 | + jas_init_library(); | |
| 40 | + jas_init_thread(); | |
| 38 | 41 | |
| 39 | 42 | if((cp = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)) == nil){ |
| 40 | 43 | werrstr("failed to create color space"); |
| @@ -75,13 +75,12 @@ · 74 unmodified lines | ||
| 75 | 75 | |
| 76 | 76 | #include "jasper/jas_malloc.h" |
| 77 | 77 | #include "jasper/jas_debug.h" |
| 78 | +#include "jasper/jas_types.h" | |
| 78 | 79 | |
| 79 | 80 | /******************************************************************************\ |
| 80 | 81 | * Function prototypes. |
| 81 | 82 | \******************************************************************************/ |
| 82 | 83 | |
| 83 | −#define ONES(n) ((1 << (n)) - 1) | |
| 84 | − | |
| 85 | 84 | static const jp2_boxinfo_t *jp2_boxinfolookup(int type); |
| 86 | 85 | |
| 87 | 86 | static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val); |
| @@ -95,6 +94,8 @@ static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val); · 7 unmodified lines | ||
| 95 | 94 | |
| 96 | 95 | static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val); |
| 97 | 96 | |
| 97 | +static void jp2_box_dump(const jp2_box_t *box); | |
| 98 | + | |
| 98 | 99 | static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in); |
| 99 | 100 | static int jp2_jp_putdata(const jp2_box_t *box, jas_stream_t *out); |
| 100 | 101 | static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in); |
| @@ -106,46 +107,78 @@ static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in); · 5 unmodified lines | ||
| 106 | 107 | static int jp2_bpcc_putdata(const jp2_box_t *box, jas_stream_t *out); |
| 107 | 108 | static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in); |
| 108 | 109 | static int jp2_colr_putdata(const jp2_box_t *box, jas_stream_t *out); |
| 110 | +static void jp2_colr_dumpdata(const jp2_box_t *box); | |
| 109 | 111 | static void jp2_colr_destroy(jp2_box_t *box); |
| 110 | 112 | static void jp2_cdef_destroy(jp2_box_t *box); |
| 111 | 113 | static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in); |
| 112 | 114 | static int jp2_cdef_putdata(const jp2_box_t *box, jas_stream_t *out); |
| 115 | +static void jp2_cdef_dumpdata(const jp2_box_t *box); | |
| 113 | 116 | static void jp2_cmap_destroy(jp2_box_t *box); |
| 114 | 117 | static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in); |
| 115 | 118 | static int jp2_cmap_putdata(const jp2_box_t *box, jas_stream_t *out); |
| 119 | +static void jp2_cmap_dumpdata(const jp2_box_t *box); | |
| 116 | 120 | static void jp2_pclr_destroy(jp2_box_t *box); |
| 117 | 121 | static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in); |
| 118 | 122 | static int jp2_pclr_putdata(const jp2_box_t *box, jas_stream_t *out); |
| 123 | +static void jp2_pclr_dumpdata(const jp2_box_t *box); | |
| 124 | + | |
| 125 | +/******************************************************************************\ | |
| 126 | +\******************************************************************************/ | |
| 127 | + | |
| 128 | +static inline uint_fast32_t ones(int n) | |
| 129 | +{ | |
| 130 | + assert(n >= 0); | |
| 131 | + return (JAS_CAST(uint_fast32_t, 1) << n) - 1; | |
| 132 | +} | |
| 119 | 133 | |
| 120 | 134 | /******************************************************************************\ |
| 121 | 135 | * Local data. |
| 122 | 136 | \******************************************************************************/ |
| 123 | 137 | |
| 124 | 138 | static const jp2_boxinfo_t jp2_boxinfos[] = { |
| 125 | − {JP2_BOX_JP, 0, "JP", {0, 0, jp2_jp_getdata, jp2_jp_putdata}}, | |
| 126 | − {JP2_BOX_FTYP, 0, "FTYP", {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata}}, | |
| 127 | − {JP2_BOX_JP2H, JP2_BOX_SUPER, "JP2H", {0, 0, 0, 0}}, | |
| 128 | − {JP2_BOX_IHDR, 0, "IHDR", {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata}}, | |
| 129 | − {JP2_BOX_BPCC, 0, "BPCC", {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata}}, | |
| 130 | − {JP2_BOX_COLR, 0, "COLR", {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata}}, | |
| 131 | − {JP2_BOX_PCLR, 0, "PCLR", {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata}}, | |
| 132 | − {JP2_BOX_CMAP, 0, "CMAP", {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata}}, | |
| 133 | − {JP2_BOX_CDEF, 0, "CDEF", {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata}}, | |
| 134 | − {JP2_BOX_RES, JP2_BOX_SUPER, "RES", {0, 0, 0, 0}}, | |
| 135 | − {JP2_BOX_RESC, 0, "RESC", {0, 0, 0, 0}}, | |
| 136 | − {JP2_BOX_RESD, 0, "RESD", {0, 0, 0, 0}}, | |
| 137 | − {JP2_BOX_JP2C, JP2_BOX_NODATA, "JP2C", {0, 0, 0, 0}}, | |
| 138 | − {JP2_BOX_JP2I, 0, "JP2I", {0, 0, 0, 0}}, | |
| 139 | − {JP2_BOX_XML, 0, "XML", {0, 0, 0, 0}}, | |
| 140 | − {JP2_BOX_UUID, 0, "UUID", {0, 0, 0, 0}}, | |
| 141 | − {JP2_BOX_UINF, JP2_BOX_SUPER, "UINF", {0, 0, 0, 0}}, | |
| 142 | − {JP2_BOX_ULST, 0, "ULST", {0, 0, 0, 0}}, | |
| 143 | − {JP2_BOX_URL, 0, "URL", {0, 0, 0, 0}}, | |
| 144 | − {0, 0, 0, {0, 0, 0, 0}}, | |
| 139 | + {JP2_BOX_JP, 0, "JP", | |
| 140 | + {0, 0, jp2_jp_getdata, jp2_jp_putdata, 0}}, | |
| 141 | + {JP2_BOX_FTYP, 0, "FTYP", | |
| 142 | + {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata, 0}}, | |
| 143 | + {JP2_BOX_JP2H, JP2_BOX_SUPER, "JP2H", | |
| 144 | + {0, 0, 0, 0, 0}}, | |
| 145 | + {JP2_BOX_IHDR, 0, "IHDR", | |
| 146 | + {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata, 0}}, | |
| 147 | + {JP2_BOX_BPCC, 0, "BPCC", | |
| 148 | + {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata, 0}}, | |
| 149 | + {JP2_BOX_COLR, 0, "COLR", | |
| 150 | + {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata, jp2_colr_dumpdata}}, | |
| 151 | + {JP2_BOX_PCLR, 0, "PCLR", | |
| 152 | + {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata, jp2_pclr_dumpdata}}, | |
| 153 | + {JP2_BOX_CMAP, 0, "CMAP", | |
| 154 | + {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata, jp2_cmap_dumpdata}}, | |
| 155 | + {JP2_BOX_CDEF, 0, "CDEF", | |
| 156 | + {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata, jp2_cdef_dumpdata}}, | |
| 157 | + {JP2_BOX_RES, JP2_BOX_SUPER, "RES", | |
| 158 | + {0, 0, 0, 0, 0}}, | |
| 159 | + {JP2_BOX_RESC, 0, "RESC", | |
| 160 | + {0, 0, 0, 0, 0}}, | |
| 161 | + {JP2_BOX_RESD, 0, "RESD", | |
| 162 | + {0, 0, 0, 0, 0}}, | |
| 163 | + {JP2_BOX_JP2C, JP2_BOX_NODATA, "JP2C", | |
| 164 | + {0, 0, 0, 0, 0}}, | |
| 165 | + {JP2_BOX_JP2I, 0, "JP2I", | |
| 166 | + {0, 0, 0, 0, 0}}, | |
| 167 | + {JP2_BOX_XML, 0, "XML", | |
| 168 | + {0, 0, 0, 0, 0}}, | |
| 169 | + {JP2_BOX_UUID, 0, "UUID", | |
| 170 | + {0, 0, 0, 0, 0}}, | |
| 171 | + {JP2_BOX_UINF, JP2_BOX_SUPER, "UINF", | |
| 172 | + {0, 0, 0, 0, 0}}, | |
| 173 | + {JP2_BOX_ULST, 0, "ULST", | |
| 174 | + {0, 0, 0, 0, 0}}, | |
| 175 | + {JP2_BOX_URL, 0, "URL", | |
| 176 | + {0, 0, 0, 0, 0}}, | |
| 177 | + {0, 0, 0, {0, 0, 0, 0, 0}}, | |
| 145 | 178 | }; |
| 146 | 179 | |
| 147 | 180 | static const jp2_boxinfo_t jp2_boxinfo_unk = { |
| 148 | − 0, 0, "Unknown", {0, 0, 0, 0} | |
| 181 | + 0, 0, "Unknown", {0, 0, 0, 0, 0} | |
| 149 | 182 | }; |
| 150 | 183 | |
| 151 | 184 | /******************************************************************************\ |
| @@ -239,19 +272,19 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 87 unmodified lines | ||
| 239 | 272 | boxinfo = jp2_boxinfolookup(box->type); |
| 240 | 273 | box->info = boxinfo; |
| 241 | 274 | box->len = len; |
| 242 | − JAS_DBGLOG(10, ( | |
| 275 | + JAS_LOGDEBUGF(10, | |
| 243 | 276 | "preliminary processing of JP2 box: " |
| 244 | 277 | "type=%c%s%c (0x%08x); length=%"PRIuFAST32"\n", |
| 245 | 278 | '"', boxinfo->name, '"', box->type, box->len |
| 246 | − )); | |
| 279 | + ); | |
| 247 | 280 | size_t hdrlen; |
| 248 | 281 | if (box->len == 1) { |
| 249 | − JAS_DBGLOG(10, ("big length\n")); | |
| 282 | + JAS_LOGDEBUGF(10, "big length\n"); | |
| 250 | 283 | if (jp2_getuint64(in, &extlen)) { |
| 251 | 284 | goto error; |
| 252 | 285 | } |
| 253 | 286 | if (extlen > 0xffffffffUL) { |
| 254 | − jas_eprintf("warning: cannot handle large 64-bit box length\n"); | |
| 287 | + jas_logerrorf("cannot handle large 64-bit box length\n"); | |
| 255 | 288 | goto error; |
| 256 | 289 | } |
| 257 | 290 | box->len = extlen; |
| @@ -262,10 +295,9 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 4 unmodified lines | ||
| 262 | 295 | if (box->len != 0 && box->len < 8) { |
| 263 | 296 | goto error; |
| 264 | 297 | } |
| 265 | − if (box->len > 0x7fffffffUL) { | |
| 266 | − /* this limit is the largest value which can | |
| 267 | − be passed to jas_stream_copy() without | |
| 268 | − overflowing */ | |
| 298 | + if (box->len > SSIZE_MAX) { | |
| 299 | + /* This limit is the largest value which can be passed to | |
| 300 | + jas_stream_copy() without overflowing. */ | |
| 269 | 301 | goto error; |
| 270 | 302 | } |
| 271 | 303 | |
| @@ -280,7 +312,7 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 8 unmodified lines | ||
| 280 | 312 | goto error; |
| 281 | 313 | } |
| 282 | 314 | if (jas_stream_copy(tmpstream, in, box->datalen)) { |
| 283 | − jas_eprintf("cannot copy box data\n"); | |
| 315 | + jas_logerrorf("cannot copy box data\n"); | |
| 284 | 316 | goto error; |
| 285 | 317 | } |
| 286 | 318 | jas_stream_rewind(tmpstream); |
| @@ -291,13 +323,17 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 4 unmodified lines | ||
| 291 | 323 | |
| 292 | 324 | if (box->ops->getdata) { |
| 293 | 325 | if ((*box->ops->getdata)(box, tmpstream)) { |
| 294 | − jas_eprintf("cannot parse box data\n"); | |
| 326 | + jas_logerrorf("cannot parse box data\n"); | |
| 295 | 327 | goto error; |
| 296 | 328 | } |
| 297 | 329 | } |
| 298 | 330 | jas_stream_close(tmpstream); |
| 299 | 331 | } |
| 300 | 332 | |
| 333 | + if (jas_get_debug_level() >= 1) { | |
| 334 | + jp2_box_dump(box); | |
| 335 | + } | |
| 336 | + | |
| 301 | 337 | return box; |
| 302 | 338 | |
| 303 | 339 | error: |
| @@ -310,6 +346,19 @@ error: · 6 unmodified lines | ||
| 310 | 346 | return 0; |
| 311 | 347 | } |
| 312 | 348 | |
| 349 | +static void jp2_box_dump(const jp2_box_t *box) | |
| 350 | +{ | |
| 351 | + const jp2_boxinfo_t *boxinfo = box->info; | |
| 352 | + assert(boxinfo); | |
| 353 | + | |
| 354 | + jas_logprintf( | |
| 355 | + "JP2 box: type=%c%s%c (0x%08"PRIxFAST32"); length=%"PRIuFAST32"\n", '"', | |
| 356 | + boxinfo->name, '"', box->type, box->len); | |
| 357 | + if (box->ops->dumpdata) { | |
| 358 | + (*box->ops->dumpdata)(box); | |
| 359 | + } | |
| 360 | +} | |
| 361 | + | |
| 313 | 362 | static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in) |
| 314 | 363 | { |
| 315 | 364 | jp2_jp_t *jp = &box->data.jp; |
| @@ -376,6 +425,20 @@ static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in) · 60 unmodified lines | ||
| 376 | 425 | return 0; |
| 377 | 426 | } |
| 378 | 427 | |
| 428 | +static void jp2_colr_dumpdata(const jp2_box_t *box) | |
| 429 | +{ | |
| 430 | + const jp2_colr_t *colr = &box->data.colr; | |
| 431 | + jas_logprintf("method=%d; pri=%d; approx=%d\n", (int)colr->method, (int)colr->pri, (int)colr->approx); | |
| 432 | + switch (colr->method) { | |
| 433 | + case JP2_COLR_ENUM: | |
| 434 | + jas_logprintf("csid=%d\n", (int)colr->csid); | |
| 435 | + break; | |
| 436 | + case JP2_COLR_ICC: | |
| 437 | + jas_logmemdump(colr->iccp, colr->iccplen); | |
| 438 | + break; | |
| 439 | + } | |
| 440 | +} | |
| 441 | + | |
| 379 | 442 | static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) |
| 380 | 443 | { |
| 381 | 444 | if (box->datalen < 3) |
| @@ -388,23 +451,33 @@ static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) · 6 unmodified lines | ||
| 388 | 451 | |
| 389 | 452 | if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) || |
| 390 | 453 | jp2_getuint8(in, &colr->approx)) { |
| 454 | + jas_logerrorf("cannot get COLR box data\n"); | |
| 391 | 455 | return -1; |
| 392 | 456 | } |
| 393 | 457 | switch (colr->method) { |
| 394 | 458 | case JP2_COLR_ENUM: |
| 395 | 459 | if (jp2_getuint32(in, &colr->csid)) { |
| 460 | + jas_logerrorf("cannot get CSID\n"); | |
| 396 | 461 | return -1; |
| 397 | 462 | } |
| 398 | 463 | break; |
| 399 | 464 | case JP2_COLR_ICC: |
| 465 | + if (box->datalen <= 3) { | |
| 466 | + jas_logerrorf("empty ICC profile data\n"); | |
| 467 | + return -1; | |
| 468 | + } | |
| 469 | + assert(box->datalen >= 3); | |
| 400 | 470 | colr->iccplen = box->datalen - 3; |
| 401 | − if (colr->iccplen > 1024 * 1024) | |
| 471 | +#if 0 | |
| 472 | + if (colr->iccplen > 1024 * 1024) { | |
| 402 | 473 | /* refuse to read ICC profiles larger than 1 |
| 403 | 474 | MB (I have no idea how large ICC profiles |
| 404 | 475 | can get, but I believe this limit might be |
| 405 | 476 | very pessimistic and should be lowered |
| 406 | 477 | further) */ |
| 407 | 478 | return -1; |
| 479 | + } | |
| 480 | +#endif | |
| 408 | 481 | if (!(colr->iccp = jas_alloc2(colr->iccplen, sizeof(uint_fast8_t)))) { |
| 409 | 482 | return -1; |
| 410 | 483 | } |
| @@ -416,6 +489,17 @@ static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) · 5 unmodified lines | ||
| 416 | 489 | return 0; |
| 417 | 490 | } |
| 418 | 491 | |
| 492 | +static void jp2_cdef_dumpdata(const jp2_box_t *box) | |
| 493 | +{ | |
| 494 | + const jp2_cdef_t *cdef = &box->data.cdef; | |
| 495 | + unsigned int i; | |
| 496 | + for (i = 0; i < cdef->numchans; ++i) { | |
| 497 | + jas_logprintf( | |
| 498 | + "channo=%"PRIuFAST16"; type=%"PRIuFAST16"; assoc=%"PRIuFAST16"\n", | |
| 499 | + cdef->ents[i].channo, cdef->ents[i].type, cdef->ents[i].assoc); | |
| 500 | + } | |
| 501 | +} | |
| 502 | + | |
| 419 | 503 | static void jp2_colr_destroy(jp2_box_t *box) |
| 420 | 504 | { |
| 421 | 505 | jp2_colr_t *colr = &box->data.colr; |
| @@ -472,7 +556,7 @@ int jp2_box_put(jp2_box_t *box, jas_stream_t *out) · 50 unmodified lines | ||
| 472 | 556 | box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN(false); |
| 473 | 557 | jas_stream_rewind(tmpstream); |
| 474 | 558 | } |
| 475 | − extlen = (box->len >= (((uint_fast64_t)1) << 32)) != 0; | |
| 559 | + extlen = 0; | |
| 476 | 560 | if (jp2_putuint32(out, extlen ? 1 : box->len)) { |
| 477 | 561 | goto error; |
| 478 | 562 | } |
| @@ -488,7 +572,7 @@ int jp2_box_put(jp2_box_t *box, jas_stream_t *out) · 9 unmodified lines | ||
| 488 | 572 | if (dataflag) { |
| 489 | 573 | if (jas_stream_copy(out, tmpstream, box->len - |
| 490 | 574 | JP2_BOX_HDRLEN(false))) { |
| 491 | − jas_eprintf("cannot copy box data\n"); | |
| 575 | + jas_logerrorf("cannot copy box data\n"); | |
| 492 | 576 | goto error; |
| 493 | 577 | } |
| 494 | 578 | jas_stream_close(tmpstream); |
| @@ -703,10 +787,6 @@ static const jp2_boxinfo_t *jp2_boxinfolookup(int type) · 208 unmodified lines | ||
| 703 | 787 | return &jp2_boxinfo_unk; |
| 704 | 788 | } |
| 705 | 789 | |
| 706 | − | |
| 707 | − | |
| 708 | − | |
| 709 | − | |
| 710 | 790 | static void jp2_cmap_destroy(jp2_box_t *box) |
| 711 | 791 | { |
| 712 | 792 | jp2_cmap_t *cmap = &box->data.cmap; |
| @@ -746,13 +826,23 @@ static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in) · 33 unmodified lines | ||
| 746 | 826 | |
| 747 | 827 | static int jp2_cmap_putdata(const jp2_box_t *box, jas_stream_t *out) |
| 748 | 828 | { |
| 749 | − /* Eliminate compiler warning about unused variables. */ | |
| 750 | − USED(box); | |
| 751 | − USED(out); | |
| 752 | − | |
| 829 | + JAS_UNUSED(box); | |
| 830 | + JAS_UNUSED(out); | |
| 753 | 831 | return -1; |
| 754 | 832 | } |
| 755 | 833 | |
| 834 | +static void jp2_cmap_dumpdata(const jp2_box_t *box) | |
| 835 | +{ | |
| 836 | + const jp2_cmap_t *cmap = &box->data.cmap; | |
| 837 | + unsigned int i; | |
| 838 | + jas_logprintf("numchans = %d\n", (int) cmap->numchans); | |
| 839 | + for (i = 0; i < cmap->numchans; ++i) { | |
| 840 | + const jp2_cmapent_t *ent = &cmap->ents[i]; | |
| 841 | + jas_logprintf("cmptno=%d; map=%d; pcol=%d\n", | |
| 842 | + (int) ent->cmptno, (int) ent->map, (int) ent->pcol); | |
| 843 | + } | |
| 844 | +} | |
| 845 | + | |
| 756 | 846 | static void jp2_pclr_destroy(jp2_box_t *box) |
| 757 | 847 | { |
| 758 | 848 | jp2_pclr_t *pclr = &box->data.pclr; |
| @@ -813,12 +903,26 @@ static int jp2_pclr_putdata(const jp2_box_t *box, jas_stream_t *out) · 54 unmodified lines | ||
| 813 | 903 | #if 0 |
| 814 | 904 | const jp2_pclr_t *pclr = &box->data.pclr; |
| 815 | 905 | #endif |
| 816 | − /* Eliminate warning about unused variable. */ | |
| 817 | − USED(box); | |
| 818 | − USED(out); | |
| 906 | + JAS_UNUSED(box); | |
| 907 | + JAS_UNUSED(out); | |
| 819 | 908 | return -1; |
| 820 | 909 | } |
| 821 | 910 | |
| 911 | +static void jp2_pclr_dumpdata(const jp2_box_t *box) | |
| 912 | +{ | |
| 913 | + const jp2_pclr_t *pclr = &box->data.pclr; | |
| 914 | + unsigned int i; | |
| 915 | + int j; | |
| 916 | + jas_logprintf("numents=%d; numchans=%d\n", (int) pclr->numlutents, | |
| 917 | + (int) pclr->numchans); | |
| 918 | + for (i = 0; i < pclr->numlutents; ++i) { | |
| 919 | + for (j = 0; j < pclr->numchans; ++j) { | |
| 920 | + jas_logprintf("LUT[%d][%d]=%"PRIiFAST32"\n", i, j, | |
| 921 | + pclr->lutdata[i * pclr->numchans + j]); | |
| 922 | + } | |
| 923 | + } | |
| 924 | +} | |
| 925 | + | |
| 822 | 926 | static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val) |
| 823 | 927 | { |
| 824 | 928 | int c; |
| @@ -828,6 +932,12 @@ static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val) · 3 unmodified lines | ||
| 828 | 932 | |
| 829 | 933 | m = (n + 7) / 8; |
| 830 | 934 | |
| 935 | + // Ensure that the integer to be read has a valid size. | |
| 936 | + if (n < 0 || n > 32) { | |
| 937 | + jas_logerrorf("jp2_getint: invalid integer size (%d bits)\n", n); | |
| 938 | + return -1; | |
| 939 | + } | |
| 940 | + | |
| 831 | 941 | v = 0; |
| 832 | 942 | for (i = 0; i < m; ++i) { |
| 833 | 943 | if ((c = jas_stream_getc(in)) == EOF) { |
| @@ -835,11 +945,11 @@ static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val) · 1 unmodified line | ||
| 835 | 945 | } |
| 836 | 946 | v = (v << 8) | c; |
| 837 | 947 | } |
| 838 | − v &= ONES(n); | |
| 948 | + v &= ones(n); | |
| 839 | 949 | if (s) { |
| 840 | 950 | int sb; |
| 841 | − sb = v & (1 << (8 * m - 1)); | |
| 842 | − *val = ((~v) + 1) & ONES(8 * m); | |
| 951 | + sb = v & (JAS_CAST(uint_fast32_t, 1) << (8 * m - 1)); | |
| 952 | + *val = ((~v) + 1) & ones(8 * m); | |
| 843 | 953 | if (sb) { |
| 844 | 954 | *val = -*val; |
| 845 | 955 | } |
| @@ -245,7 +245,7 @@ typedef struct { · 244 unmodified lines | ||
| 245 | 245 | uint_fast32_t type; |
| 246 | 246 | |
| 247 | 247 | /* The length of the box including the (variable-length) header. */ |
| 248 | − uint_fast64_t len; | |
| 248 | + uint_fast32_t len; | |
| 249 | 249 | |
| 250 | 250 | /* The length of the box data. */ |
| 251 | 251 | uint_fast32_t datalen; |
| @@ -268,6 +268,7 @@ typedef struct jp2_boxops_s { · 16 unmodified lines | ||
| 268 | 268 | void (*destroy)(jp2_box_t *box); |
| 269 | 269 | int (*getdata)(jp2_box_t *box, jas_stream_t *in); |
| 270 | 270 | int (*putdata)(const jp2_box_t *box, jas_stream_t *out); |
| 271 | + void (*dumpdata)(const jp2_box_t *box); | |
| 271 | 272 | } jp2_boxops_t; |
| 272 | 273 | |
| 273 | 274 | /******************************************************************************\ |
| @@ -308,5 +309,4 @@ static inline uint_least8_t JP2_BPCTODTYPE(uint_least8_t bpc) · 34 unmodified lines | ||
| 308 | 309 | |
| 309 | 310 | const jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo); |
| 310 | 311 | |
| 311 | − | |
| 312 | 312 | #endif |
| @@ -81,7 +81,9 @@ · 80 unmodified lines | ||
| 81 | 81 | #include "jasper/jas_malloc.h" |
| 82 | 82 | #include "jasper/jas_types.h" |
| 83 | 83 | |
| 84 | −#define JP2_VALIDATELEN (JAS_MIN(JP2_JP_LEN + 16, JAS_STREAM_MAXPUTBACK)) | |
| 84 | +/******************************************************************************\ | |
| 85 | +* Function prototypes. | |
| 86 | +\******************************************************************************/ | |
| 85 | 87 | |
| 86 | 88 | static jp2_dec_t *jp2_dec_create(void); |
| 87 | 89 | static void jp2_dec_destroy(jp2_dec_t *dec); |
| @@ -104,7 +106,10 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 16 unmodified lines | ||
| 104 | 106 | unsigned int i; |
| 105 | 107 | jp2_cmap_t *cmapd; |
| 106 | 108 | jp2_pclr_t *pclrd; |
| 109 | +#if 0 | |
| 110 | + /* The following code appears to no longer be needed. */ | |
| 107 | 111 | jp2_cdef_t *cdefd; |
| 112 | +#endif | |
| 108 | 113 | unsigned int channo; |
| 109 | 114 | int newcmptno; |
| 110 | 115 | int_fast32_t *lutents; |
| @@ -117,8 +122,9 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 6 unmodified lines | ||
| 117 | 122 | jas_iccprof_t *iccprof; |
| 118 | 123 | |
| 119 | 124 | box = 0; |
| 125 | + image = 0; | |
| 120 | 126 | |
| 121 | − JAS_DBGLOG(100, ("jp2_decode(%p, \"%s\")\n", in, optstr)); | |
| 127 | + JAS_LOGDEBUGF(100, "jp2_decode(%p, \"%s\")\n", in, optstr); | |
| 122 | 128 | |
| 123 | 129 | if (!(dec = jp2_dec_create())) { |
| 124 | 130 | goto error; |
| @@ -126,25 +132,28 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line | ||
| 126 | 132 | |
| 127 | 133 | /* Get the first box. This should be a JP box. */ |
| 128 | 134 | if (!(box = jp2_box_get(in))) { |
| 129 | − jas_eprintf("error: cannot get box\n"); | |
| 135 | + jas_logerrorf("error: cannot get box\n"); | |
| 130 | 136 | goto error; |
| 131 | 137 | } |
| 132 | 138 | if (box->type != JP2_BOX_JP) { |
| 133 | − jas_eprintf("error: expecting signature box\n"); | |
| 139 | + jas_logerrorf("error: expecting signature box\n"); | |
| 134 | 140 | goto error; |
| 135 | 141 | } |
| 136 | 142 | if (box->data.jp.magic != JP2_JP_MAGIC) { |
| 137 | − jas_eprintf("incorrect magic number\n"); | |
| 143 | + jas_logerrorf("incorrect magic number (0x%lx != 0x%lx)\n", | |
| 144 | + JAS_CAST(unsigned long, box->data.jp.magic), | |
| 145 | + JAS_CAST(unsigned long, JP2_JP_MAGIC)); | |
| 138 | 146 | goto error; |
| 139 | 147 | } |
| 140 | 148 | jp2_box_destroy(box); |
| 141 | 149 | |
| 142 | 150 | /* Get the second box. This should be a FTYP box. */ |
| 143 | 151 | if (!(box = jp2_box_get(in))) { |
| 152 | + jas_logerrorf("error: cannot get box\n"); | |
| 144 | 153 | goto error; |
| 145 | 154 | } |
| 146 | 155 | if (box->type != JP2_BOX_FTYP) { |
| 147 | − jas_eprintf("expecting file type box\n"); | |
| 156 | + jas_logerrorf("expecting file type box\n"); | |
| 148 | 157 | goto error; |
| 149 | 158 | } |
| 150 | 159 | jp2_box_destroy(box); |
| @@ -152,8 +161,8 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line | ||
| 152 | 161 | /* Get more boxes... */ |
| 153 | 162 | found = 0; |
| 154 | 163 | while ((box = jp2_box_get(in))) { |
| 155 | − if (jas_getdbglevel() >= 1) { | |
| 156 | − jas_eprintf("got box type %s\n", box->info->name); | |
| 164 | + if (jas_get_debug_level() >= 1) { | |
| 165 | + jas_logdebugf(1, "got box type %s\n", box->info->name); | |
| 157 | 166 | } |
| 158 | 167 | switch (box->type) { |
| 159 | 168 | case JP2_BOX_JP2C: |
| @@ -206,18 +215,18 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 46 unmodified lines | ||
| 206 | 215 | } |
| 207 | 216 | |
| 208 | 217 | if (!found) { |
| 209 | − jas_eprintf("error: no code stream found\n"); | |
| 218 | + jas_logerrorf("error: no code stream found\n"); | |
| 210 | 219 | goto error; |
| 211 | 220 | } |
| 212 | 221 | |
| 213 | 222 | if (!(dec->image = jpc_decode(in, optstr))) { |
| 214 | − jas_eprintf("error: cannot decode code stream\n"); | |
| 223 | + jas_logerrorf("error: cannot decode code stream\n"); | |
| 215 | 224 | goto error; |
| 216 | 225 | } |
| 217 | 226 | |
| 218 | 227 | /* An IHDR box must be present. */ |
| 219 | 228 | if (!dec->ihdr) { |
| 220 | − jas_eprintf("error: missing IHDR box\n"); | |
| 229 | + jas_logerrorf("error: missing IHDR box\n"); | |
| 221 | 230 | goto error; |
| 222 | 231 | } |
| 223 | 232 | |
| @@ -225,12 +234,13 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line | ||
| 225 | 234 | the value specified in the code stream? */ |
| 226 | 235 | if (dec->ihdr->data.ihdr.numcmpts != JAS_CAST(jas_uint, |
| 227 | 236 | jas_image_numcmpts(dec->image))) { |
| 228 | − jas_eprintf("warning: number of components mismatch\n"); | |
| 237 | + jas_logerrorf("error: number of components mismatch (IHDR)\n"); | |
| 238 | + goto error; | |
| 229 | 239 | } |
| 230 | 240 | |
| 231 | 241 | /* At least one component must be present. */ |
| 232 | 242 | if (!jas_image_numcmpts(dec->image)) { |
| 233 | − jas_eprintf("error: no components\n"); | |
| 243 | + jas_logerrorf("error: no components\n"); | |
| 234 | 244 | goto error; |
| 235 | 245 | } |
| 236 | 246 | |
| @@ -248,21 +258,23 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 11 unmodified lines | ||
| 248 | 258 | with the data in the code stream? */ |
| 249 | 259 | if ((samedtype && dec->ihdr->data.ihdr.bpc != JP2_DTYPETOBPC(dtype)) || |
| 250 | 260 | (!samedtype && dec->ihdr->data.ihdr.bpc != JP2_IHDR_BPCNULL)) { |
| 251 | − jas_eprintf("warning: component data type mismatch\n"); | |
| 261 | + jas_logerrorf("error: component data type mismatch (IHDR)\n"); | |
| 262 | + goto error; | |
| 252 | 263 | } |
| 253 | 264 | |
| 254 | 265 | /* Is the compression type supported? */ |
| 255 | 266 | if (dec->ihdr->data.ihdr.comptype != JP2_IHDR_COMPTYPE) { |
| 256 | − jas_eprintf("error: unsupported compression type\n"); | |
| 267 | + jas_logerrorf("error: unsupported compression type\n"); | |
| 257 | 268 | goto error; |
| 258 | 269 | } |
| 259 | 270 | |
| 260 | 271 | if (dec->bpcc) { |
| 261 | 272 | /* Is the number of components indicated in the BPCC box |
| 262 | 273 | consistent with the code stream data? */ |
| 263 | − if (dec->bpcc->data.bpcc.numcmpts != JAS_CAST(jas_uint, jas_image_numcmpts( | |
| 264 | − dec->image))) { | |
| 265 | − jas_eprintf("warning: number of components mismatch\n"); | |
| 274 | + if (dec->bpcc->data.bpcc.numcmpts != | |
| 275 | + JAS_CAST(jas_uint, jas_image_numcmpts(dec->image))) { | |
| 276 | + jas_logerrorf("error: number of components mismatch (BPCC)\n"); | |
| 277 | + goto error; | |
| 266 | 278 | } |
| 267 | 279 | /* Is the component data type information indicated in the BPCC |
| 268 | 280 | box consistent with the code stream data? */ |
| @@ -271,17 +283,18 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 2 unmodified lines | ||
| 271 | 283 | ++i) { |
| 272 | 284 | if (jas_image_cmptdtype(dec->image, i) != |
| 273 | 285 | JP2_BPCTODTYPE(dec->bpcc->data.bpcc.bpcs[i])) { |
| 274 | − jas_eprintf("warning: component data type mismatch\n"); | |
| 286 | + jas_logerrorf("error: component data type mismatch (BPCC)\n"); | |
| 287 | + goto error; | |
| 275 | 288 | } |
| 276 | 289 | } |
| 277 | 290 | } else { |
| 278 | − jas_eprintf("warning: superfluous BPCC box\n"); | |
| 291 | + jas_logwarnf("warning: superfluous BPCC box\n"); | |
| 279 | 292 | } |
| 280 | 293 | } |
| 281 | 294 | |
| 282 | 295 | /* A COLR box must be present. */ |
| 283 | 296 | if (!dec->colr) { |
| 284 | − jas_eprintf("error: no COLR box\n"); | |
| 297 | + jas_logerrorf("error: no COLR box\n"); | |
| 285 | 298 | goto error; |
| 286 | 299 | } |
| 287 | 300 | |
| @@ -293,16 +306,17 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 5 unmodified lines | ||
| 293 | 306 | iccprof = jas_iccprof_createfrombuf(dec->colr->data.colr.iccp, |
| 294 | 307 | dec->colr->data.colr.iccplen); |
| 295 | 308 | if (!iccprof) { |
| 296 | − jas_eprintf("error: failed to parse ICC profile\n"); | |
| 309 | + jas_logerrorf("error: failed to parse ICC profile\n"); | |
| 297 | 310 | goto error; |
| 298 | 311 | } |
| 299 | 312 | jas_iccprof_gethdr(iccprof, &icchdr); |
| 300 | − //jas_eprintf("ICC Profile CS %08x\n", icchdr.colorspc); | |
| 301 | − jas_image_setclrspc(dec->image, fromiccpcs(icchdr.colorspc)); | |
| 313 | + JAS_LOGDEBUGF(2, "ICC Profile CS %08x\n", icchdr.colorspc); | |
| 302 | 314 | dec->image->cmprof_ = jas_cmprof_createfromiccprof(iccprof); |
| 303 | 315 | if (!dec->image->cmprof_) { |
| 304 | − jas_iccprof_destroy(iccprof); | |
| 305 | − goto error; | |
| 316 | + jas_image_setclrspc(dec->image, JAS_CLRSPC_UNKNOWN); | |
| 317 | + jas_logwarnf("warning: cannot create CM profile from ICC profile\n"); | |
| 318 | + } else { | |
| 319 | + jas_image_setclrspc(dec->image, fromiccpcs(icchdr.colorspc)); | |
| 306 | 320 | } |
| 307 | 321 | jas_iccprof_destroy(iccprof); |
| 308 | 322 | break; |
| @@ -310,14 +324,14 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line | ||
| 310 | 324 | |
| 311 | 325 | /* If a CMAP box is present, a PCLR box must also be present. */ |
| 312 | 326 | if (dec->cmap && !dec->pclr) { |
| 313 | − jas_eprintf("warning: missing PCLR box or superfluous CMAP box\n"); | |
| 327 | + jas_logwarnf("warning: missing PCLR box or superfluous CMAP box\n"); | |
| 314 | 328 | jp2_box_destroy(dec->cmap); |
| 315 | 329 | dec->cmap = 0; |
| 316 | 330 | } |
| 317 | 331 | |
| 318 | 332 | /* If a CMAP box is not present, a PCLR box must not be present. */ |
| 319 | 333 | if (!dec->cmap && dec->pclr) { |
| 320 | − jas_eprintf("warning: missing CMAP box or superfluous PCLR box\n"); | |
| 334 | + jas_logwarnf("warning: missing CMAP box or superfluous PCLR box\n"); | |
| 321 | 335 | jp2_box_destroy(dec->pclr); |
| 322 | 336 | dec->pclr = 0; |
| 323 | 337 | } |
| @@ -333,13 +347,13 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 9 unmodified lines | ||
| 333 | 347 | /* Is the component number reasonable? */ |
| 334 | 348 | if (dec->cmap->data.cmap.ents[i].cmptno >= JAS_CAST(jas_uint, |
| 335 | 349 | jas_image_numcmpts(dec->image))) { |
| 336 | − jas_eprintf("error: invalid component number in CMAP box\n"); | |
| 350 | + jas_logerrorf("error: invalid component number in CMAP box\n"); | |
| 337 | 351 | goto error; |
| 338 | 352 | } |
| 339 | 353 | /* Is the LUT index reasonable? */ |
| 340 | 354 | if (dec->cmap->data.cmap.ents[i].pcol >= |
| 341 | 355 | dec->pclr->data.pclr.numchans) { |
| 342 | − jas_eprintf("error: invalid CMAP LUT index\n"); | |
| 356 | + jas_logerrorf("error: invalid CMAP LUT index\n"); | |
| 343 | 357 | goto error; |
| 344 | 358 | } |
| 345 | 359 | } |
| @@ -348,7 +362,7 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 2 unmodified lines | ||
| 348 | 362 | /* Allocate space for the channel-number to component-number LUT. */ |
| 349 | 363 | if (!(dec->chantocmptlut = jas_alloc2(dec->numchans, |
| 350 | 364 | sizeof(uint_fast16_t)))) { |
| 351 | − jas_eprintf("error: no memory\n"); | |
| 365 | + jas_logerrorf("error: no memory\n"); | |
| 352 | 366 | goto error; |
| 353 | 367 | } |
| 354 | 368 | |
| @@ -357,30 +371,48 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 2 unmodified lines | ||
| 357 | 371 | dec->chantocmptlut[i] = i; |
| 358 | 372 | } |
| 359 | 373 | } else { |
| 374 | + /* Check to ensure that CMAP/PCLR were initialized. */ | |
| 375 | + if (!dec->cmap || !dec->pclr) { | |
| 376 | + jas_logerrorf("missing CMAP/PCLR box\n"); | |
| 377 | + goto error; | |
| 378 | + } | |
| 379 | + | |
| 360 | 380 | cmapd = &dec->cmap->data.cmap; |
| 361 | 381 | pclrd = &dec->pclr->data.pclr; |
| 382 | +#if 0 | |
| 383 | + /* The following code appears to no longer be needed. */ | |
| 384 | + cdefd = &dec->cdef->data.cdef; | |
| 385 | +#endif | |
| 362 | 386 | for (channo = 0; channo < cmapd->numchans; ++channo) { |
| 363 | 387 | cmapent = &cmapd->ents[channo]; |
| 364 | 388 | if (cmapent->map == JP2_CMAP_DIRECT) { |
| 365 | 389 | dec->chantocmptlut[channo] = channo; |
| 366 | 390 | } else if (cmapent->map == JP2_CMAP_PALETTE) { |
| 367 | 391 | if (!pclrd->numlutents) { |
| 392 | + jas_logerrorf("error: empty LUT\n"); | |
| 368 | 393 | goto error; |
| 369 | 394 | } |
| 370 | − lutents = jas_alloc2(pclrd->numlutents, sizeof(int_fast32_t)); | |
| 371 | − if (!lutents) { | |
| 395 | + if (!(lutents = jas_alloc2(pclrd->numlutents, | |
| 396 | + sizeof(int_fast32_t)))) { | |
| 397 | + jas_logerrorf("error: cannot allocate LUT\n"); | |
| 372 | 398 | goto error; |
| 373 | 399 | } |
| 374 | 400 | for (i = 0; i < pclrd->numlutents; ++i) { |
| 375 | 401 | lutents[i] = pclrd->lutdata[cmapent->pcol + i * pclrd->numchans]; |
| 376 | 402 | } |
| 377 | 403 | newcmptno = jas_image_numcmpts(dec->image); |
| 378 | − jas_image_depalettize(dec->image, cmapent->cmptno, | |
| 404 | + if (jas_image_depalettize(dec->image, cmapent->cmptno, | |
| 379 | 405 | pclrd->numlutents, lutents, |
| 380 | − JP2_BPCTODTYPE(pclrd->bpc[cmapent->pcol]), newcmptno); | |
| 406 | + JP2_BPCTODTYPE(pclrd->bpc[cmapent->pcol]), newcmptno)) { | |
| 407 | + jas_logerrorf("jas_image_depalettize failed\n"); | |
| 408 | + jas_free(lutents); | |
| 409 | + jas_logerrorf("error: depalettize failed\n"); | |
| 410 | + goto error; | |
| 411 | + } | |
| 381 | 412 | dec->chantocmptlut[channo] = newcmptno; |
| 382 | 413 | jas_free(lutents); |
| 383 | 414 | #if 0 |
| 415 | + /* The following code appears to no longer be needed. */ | |
| 384 | 416 | if (dec->cdef) { |
| 385 | 417 | cdefent = jp2_cdef_lookup(cdefd, channo); |
| 386 | 418 | if (!cdefent) { |
| @@ -390,17 +422,25 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 3 unmodified lines | ||
| 390 | 422 | } else { |
| 391 | 423 | jas_image_setcmpttype(dec->image, newcmptno, jp2_getct(jas_image_clrspc(dec->image), 0, channo + 1)); |
| 392 | 424 | } |
| 393 | −#else | |
| 394 | − /* suppress -Wunused-but-set-variable */ | |
| 395 | − (void)cdefd; | |
| 396 | 425 | #endif |
| 397 | 426 | } else { |
| 398 | − jas_eprintf("error: invalid MTYP in CMAP box\n"); | |
| 427 | + jas_logerrorf("error: invalid MTYP in CMAP box\n"); | |
| 399 | 428 | goto error; |
| 400 | 429 | } |
| 401 | 430 | } |
| 402 | 431 | } |
| 403 | 432 | |
| 433 | +#if 0 | |
| 434 | + /* The following code appears to no longer be needed. */ | |
| 435 | + /* Ensure that the number of channels being used by the decoder | |
| 436 | + matches the number of image components. */ | |
| 437 | + if (dec->numchans != jas_image_numcmpts(dec->image)) { | |
| 438 | + jas_logerrorf("error: mismatch in number of components (%d != %d)\n", | |
| 439 | + dec->numchans, jas_image_numcmpts(dec->image)); | |
| 440 | + goto error; | |
| 441 | + } | |
| 442 | +#endif | |
| 443 | + | |
| 404 | 444 | /* Mark all components as being of unknown type. */ |
| 405 | 445 | |
| 406 | 446 | for (i = 0; i < JAS_CAST(jas_uint, jas_image_numcmpts(dec->image)); ++i) { |
| @@ -410,20 +450,34 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 3 unmodified lines | ||
| 410 | 450 | /* Determine the type of each component. */ |
| 411 | 451 | if (dec->cdef) { |
| 412 | 452 | for (i = 0; i < dec->cdef->data.cdef.numchans; ++i) { |
| 453 | + uint_fast16_t channo = dec->cdef->data.cdef.ents[i].channo; | |
| 413 | 454 | /* Is the channel number reasonable? */ |
| 414 | − if (dec->cdef->data.cdef.ents[i].channo >= dec->numchans) { | |
| 415 | − jas_eprintf("error: invalid channel number in CDEF box\n"); | |
| 455 | + if (channo >= dec->numchans) { | |
| 456 | + jas_logerrorf("error: invalid channel number in CDEF box (%d)\n", | |
| 457 | + channo); | |
| 416 | 458 | goto error; |
| 417 | 459 | } |
| 418 | − jas_image_setcmpttype(dec->image, | |
| 419 | − dec->chantocmptlut[dec->cdef->data.cdef.ents[i].channo], | |
| 460 | + unsigned compno = dec->chantocmptlut[channo]; | |
| 461 | + if (compno >= jas_image_numcmpts(dec->image)) { | |
| 462 | + jas_logerrorf( | |
| 463 | + "error: invalid component reference in CDEF box (%d)\n", | |
| 464 | + compno); | |
| 465 | + goto error; | |
| 466 | + } | |
| 467 | + jas_image_setcmpttype(dec->image, compno, | |
| 420 | 468 | jp2_getct(jas_image_clrspc(dec->image), |
| 421 | 469 | dec->cdef->data.cdef.ents[i].type, |
| 422 | 470 | dec->cdef->data.cdef.ents[i].assoc)); |
| 423 | 471 | } |
| 424 | 472 | } else { |
| 425 | 473 | for (i = 0; i < dec->numchans; ++i) { |
| 426 | − jas_image_setcmpttype(dec->image, dec->chantocmptlut[i], | |
| 474 | + unsigned compno = dec->chantocmptlut[i]; | |
| 475 | + if (compno >= jas_image_numcmpts(dec->image)) { | |
| 476 | + jas_logerrorf( | |
| 477 | + "error: invalid component reference (%d)\n", compno); | |
| 478 | + goto error; | |
| 479 | + } | |
| 480 | + jas_image_setcmpttype(dec->image, compno, | |
| 427 | 481 | jp2_getct(jas_image_clrspc(dec->image), 0, i + 1)); |
| 428 | 482 | } |
| 429 | 483 | } |
| @@ -437,12 +491,9 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 7 unmodified lines | ||
| 437 | 491 | |
| 438 | 492 | /* Ensure that some components survived. */ |
| 439 | 493 | if (!jas_image_numcmpts(dec->image)) { |
| 440 | − jas_eprintf("error: no components\n"); | |
| 494 | + jas_logerrorf("error: no components\n"); | |
| 441 | 495 | goto error; |
| 442 | 496 | } |
| 443 | −#if 0 | |
| 444 | −jas_eprintf("no of components is %d\n", jas_image_numcmpts(dec->image)); | |
| 445 | −#endif | |
| 446 | 497 | |
| 447 | 498 | /* Prevent the image from being destroyed later. */ |
| 448 | 499 | image = dec->image; |
| @@ -453,6 +504,9 @@ jas_eprintf("no of components is %d\n", jas_image_numcmpts(dec->image)); · 4 unmodified lines | ||
| 453 | 504 | return image; |
| 454 | 505 | |
| 455 | 506 | error: |
| 507 | + if (image) { | |
| 508 | + jas_image_destroy(image); | |
| 509 | + } | |
| 456 | 510 | if (box) { |
| 457 | 511 | jp2_box_destroy(box); |
| 458 | 512 | } |
| @@ -462,25 +516,25 @@ error: · 3 unmodified lines | ||
| 462 | 516 | return 0; |
| 463 | 517 | } |
| 464 | 518 | |
| 519 | +#define JP2_VALIDATE_LEN JAS_MIN(JP2_JP_LEN + 4, JAS_STREAM_MAXPUTBACK) | |
| 465 | 520 | int jp2_validate(jas_stream_t *in) |
| 466 | 521 | { |
| 467 | − unsigned char buf[JP2_VALIDATELEN]; | |
| 468 | −#if 0 | |
| 469 | − jas_stream_t *tmpstream; | |
| 470 | − jp2_box_t *box; | |
| 471 | −#endif | |
| 472 | − | |
| 473 | − assert(JAS_STREAM_MAXPUTBACK >= JP2_VALIDATELEN); | |
| 522 | + unsigned char buf[JP2_VALIDATE_LEN]; | |
| 474 | 523 | |
| 475 | 524 | /* Read the validation data (i.e., the data used for detecting |
| 476 | 525 | the format). */ |
| 477 | − if (jas_stream_peek(in, buf, sizeof(buf)) != sizeof(buf)) | |
| 526 | + assert(sizeof(buf) <= JAS_STREAM_MAXPUTBACK); | |
| 527 | + if (jas_stream_peek(in, buf, sizeof(buf)) != sizeof(buf)) { | |
| 478 | 528 | return -1; |
| 529 | + } | |
| 479 | 530 | |
| 480 | 531 | /* Is the box type correct? */ |
| 481 | − if ((((uint_least32_t)buf[4] << 24) | ((uint_least32_t)buf[5] << 16) | ((uint_least32_t)buf[6] << 8) | (uint_least32_t)buf[7]) != | |
| 482 | − JP2_BOX_JP) | |
| 483 | − { | |
| 532 | + assert(JP2_VALIDATE_LEN >= 8); | |
| 533 | + if (((JAS_CAST(uint_least32_t, buf[4]) << 24) | | |
| 534 | + (JAS_CAST(uint_least32_t, buf[5]) << 16) | | |
| 535 | + (JAS_CAST(uint_least32_t, buf[6] << 8)) | | |
| 536 | + (JAS_CAST(uint_least32_t, buf[7]))) != | |
| 537 | + JP2_BOX_JP) { | |
| 484 | 538 | return -1; |
| 485 | 539 | } |
| 486 | 540 | |
| @@ -0,0 +1,494 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2003 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/* | |
| 65 | + * JP2 Library | |
| 66 | + * | |
| 67 | + * $Id$ | |
| 68 | + */ | |
| 69 | + | |
| 70 | +/******************************************************************************\ | |
| 71 | +* Includes. | |
| 72 | +\******************************************************************************/ | |
| 73 | + | |
| 74 | +#include "jasper/jas_image.h" | |
| 75 | +#include "jasper/jas_malloc.h" | |
| 76 | +#include "jasper/jas_stream.h" | |
| 77 | +#include "jasper/jas_cm.h" | |
| 78 | +#include "jasper/jas_icc.h" | |
| 79 | +#include "jasper/jas_debug.h" | |
| 80 | + | |
| 81 | +#include "jp2_cod.h" | |
| 82 | + | |
| 83 | +/******************************************************************************\ | |
| 84 | +* Function prototypes. | |
| 85 | +\******************************************************************************/ | |
| 86 | + | |
| 87 | +static uint_fast32_t jp2_gettypeasoc(int colorspace, int ctype); | |
| 88 | +static int clrspctojp2(jas_clrspc_t clrspc); | |
| 89 | + | |
| 90 | +/******************************************************************************\ | |
| 91 | +* Functions. | |
| 92 | +\******************************************************************************/ | |
| 93 | + | |
| 94 | +int jp2_encode(jas_image_t *image, jas_stream_t *out, const char *optstr) | |
| 95 | +{ | |
| 96 | + jp2_box_t *box; | |
| 97 | + jp2_ftyp_t *ftyp; | |
| 98 | + jp2_ihdr_t *ihdr; | |
| 99 | + jas_stream_t *tmpstream; | |
| 100 | + int allcmptssame; | |
| 101 | + jp2_bpcc_t *bpcc; | |
| 102 | + long len; | |
| 103 | + uint_fast16_t cmptno; | |
| 104 | + jp2_colr_t *colr; | |
| 105 | + char buf[4096]; | |
| 106 | + uint_fast32_t overhead; | |
| 107 | + jp2_cdefchan_t *cdefchanent; | |
| 108 | + jp2_cdef_t *cdef; | |
| 109 | + uint_fast32_t typeasoc; | |
| 110 | + jas_iccprof_t *iccprof; | |
| 111 | + jas_stream_t *iccstream; | |
| 112 | + int pos; | |
| 113 | + int needcdef; | |
| 114 | + | |
| 115 | + box = 0; | |
| 116 | + tmpstream = 0; | |
| 117 | + iccstream = 0; | |
| 118 | + iccprof = 0; | |
| 119 | + | |
| 120 | + if (jas_image_numcmpts(image) < 1) { | |
| 121 | + jas_logerrorf("image must have at least one component\n"); | |
| 122 | + goto error; | |
| 123 | + } | |
| 124 | + | |
| 125 | + allcmptssame = 1; | |
| 126 | + const bool sgnd = jas_image_cmptsgnd(image, 0); | |
| 127 | + const unsigned prec = jas_image_cmptprec(image, 0); | |
| 128 | + for (unsigned i = 1; i < jas_image_numcmpts(image); ++i) { | |
| 129 | + if (jas_image_cmptsgnd(image, i) != sgnd || | |
| 130 | + jas_image_cmptprec(image, i) != prec) { | |
| 131 | + allcmptssame = 0; | |
| 132 | + break; | |
| 133 | + } | |
| 134 | + } | |
| 135 | + | |
| 136 | + /* Output the signature box. */ | |
| 137 | + | |
| 138 | + if (!(box = jp2_box_create(JP2_BOX_JP))) { | |
| 139 | + jas_logerrorf("cannot create JP box\n"); | |
| 140 | + goto error; | |
| 141 | + } | |
| 142 | + box->data.jp.magic = JP2_JP_MAGIC; | |
| 143 | + if (jp2_box_put(box, out)) { | |
| 144 | + jas_logerrorf("cannot write JP box\n"); | |
| 145 | + goto error; | |
| 146 | + } | |
| 147 | + jp2_box_destroy(box); | |
| 148 | + | |
| 149 | + /* Output the file type box. */ | |
| 150 | + | |
| 151 | + if (!(box = jp2_box_create(JP2_BOX_FTYP))) { | |
| 152 | + jas_logerrorf("cannot create FTYP box\n"); | |
| 153 | + goto error; | |
| 154 | + } | |
| 155 | + ftyp = &box->data.ftyp; | |
| 156 | + ftyp->majver = JP2_FTYP_MAJVER; | |
| 157 | + ftyp->minver = JP2_FTYP_MINVER; | |
| 158 | + ftyp->numcompatcodes = 1; | |
| 159 | + ftyp->compatcodes[0] = JP2_FTYP_COMPATCODE; | |
| 160 | + if (jp2_box_put(box, out)) { | |
| 161 | + jas_logerrorf("cannot write FTYP box\n"); | |
| 162 | + goto error; | |
| 163 | + } | |
| 164 | + jp2_box_destroy(box); | |
| 165 | + box = 0; | |
| 166 | + | |
| 167 | + /* | |
| 168 | + * Generate the data portion of the JP2 header box. | |
| 169 | + * We cannot simply output the header for this box | |
| 170 | + * since we do not yet know the correct value for the length | |
| 171 | + * field. | |
| 172 | + */ | |
| 173 | + | |
| 174 | + if (!(tmpstream = jas_stream_memopen(0, 0))) { | |
| 175 | + jas_logerrorf("cannot create temporary stream\n"); | |
| 176 | + goto error; | |
| 177 | + } | |
| 178 | + | |
| 179 | + /* Generate image header box. */ | |
| 180 | + | |
| 181 | + if (!(box = jp2_box_create(JP2_BOX_IHDR))) { | |
| 182 | + jas_logerrorf("cannot create IHDR box\n"); | |
| 183 | + goto error; | |
| 184 | + } | |
| 185 | + ihdr = &box->data.ihdr; | |
| 186 | + ihdr->width = jas_image_width(image); | |
| 187 | + ihdr->height = jas_image_height(image); | |
| 188 | + ihdr->numcmpts = jas_image_numcmpts(image); | |
| 189 | + ihdr->bpc = allcmptssame ? JP2_SPTOBPC(jas_image_cmptsgnd(image, 0), | |
| 190 | + jas_image_cmptprec(image, 0)) : JP2_IHDR_BPCNULL; | |
| 191 | + ihdr->comptype = JP2_IHDR_COMPTYPE; | |
| 192 | + ihdr->csunk = 0; | |
| 193 | + ihdr->ipr = 0; | |
| 194 | + if (jp2_box_put(box, tmpstream)) { | |
| 195 | + jas_logerrorf("cannot write IHDR box\n"); | |
| 196 | + goto error; | |
| 197 | + } | |
| 198 | + jp2_box_destroy(box); | |
| 199 | + | |
| 200 | + /* Generate bits per component box. */ | |
| 201 | + | |
| 202 | + if (!allcmptssame) { | |
| 203 | + if (!(box = jp2_box_create(JP2_BOX_BPCC))) { | |
| 204 | + jas_logerrorf("cannot create BPCC box\n"); | |
| 205 | + goto error; | |
| 206 | + } | |
| 207 | + bpcc = &box->data.bpcc; | |
| 208 | + bpcc->numcmpts = jas_image_numcmpts(image); | |
| 209 | + if (!(bpcc->bpcs = jas_alloc2(bpcc->numcmpts, | |
| 210 | + sizeof(uint_fast8_t)))) { | |
| 211 | + jas_logerrorf("memory allocation failed\n"); | |
| 212 | + goto error; | |
| 213 | + } | |
| 214 | + for (cmptno = 0; cmptno < bpcc->numcmpts; ++cmptno) { | |
| 215 | + bpcc->bpcs[cmptno] = JP2_SPTOBPC(jas_image_cmptsgnd(image, | |
| 216 | + cmptno), jas_image_cmptprec(image, cmptno)); | |
| 217 | + } | |
| 218 | + if (jp2_box_put(box, tmpstream)) { | |
| 219 | + jas_logerrorf("cannot write BPCC box\n"); | |
| 220 | + goto error; | |
| 221 | + } | |
| 222 | + jp2_box_destroy(box); | |
| 223 | + } | |
| 224 | + | |
| 225 | + /* Generate color specification box. */ | |
| 226 | + | |
| 227 | + if (!(box = jp2_box_create(JP2_BOX_COLR))) { | |
| 228 | + jas_logerrorf("cannot create COLR box\n"); | |
| 229 | + goto error; | |
| 230 | + } | |
| 231 | + colr = &box->data.colr; | |
| 232 | + switch (jas_image_clrspc(image)) { | |
| 233 | + case JAS_CLRSPC_SRGB: | |
| 234 | + case JAS_CLRSPC_SYCBCR: | |
| 235 | + case JAS_CLRSPC_SGRAY: | |
| 236 | + colr->method = JP2_COLR_ENUM; | |
| 237 | + colr->csid = clrspctojp2(jas_image_clrspc(image)); | |
| 238 | + colr->pri = JP2_COLR_PRI; | |
| 239 | + colr->approx = 0; | |
| 240 | + break; | |
| 241 | + default: | |
| 242 | + colr->method = JP2_COLR_ICC; | |
| 243 | + colr->pri = JP2_COLR_PRI; | |
| 244 | + colr->approx = 0; | |
| 245 | + /* Ensure that cmprof_ is not null. */ | |
| 246 | + if (!jas_image_cmprof(image)) { | |
| 247 | + jas_logerrorf("CM profile is null\n"); | |
| 248 | + goto error; | |
| 249 | + } | |
| 250 | + if (!(iccprof = jas_iccprof_createfromcmprof( | |
| 251 | + jas_image_cmprof(image)))) { | |
| 252 | + jas_logerrorf("cannot create ICC profile\n"); | |
| 253 | + goto error; | |
| 254 | + } | |
| 255 | + if (!(iccstream = jas_stream_memopen(0, 0))) { | |
| 256 | + jas_logerrorf("cannot create temporary stream\n"); | |
| 257 | + goto error; | |
| 258 | + } | |
| 259 | + if (jas_iccprof_save(iccprof, iccstream)) { | |
| 260 | + jas_logerrorf("cannot write ICC profile\n"); | |
| 261 | + goto error; | |
| 262 | + } | |
| 263 | + if ((pos = jas_stream_tell(iccstream)) < 0) { | |
| 264 | + jas_logerrorf("cannot get stream position\n"); | |
| 265 | + goto error; | |
| 266 | + } | |
| 267 | + colr->iccplen = pos; | |
| 268 | + if (!(colr->iccp = jas_malloc(pos))) { | |
| 269 | + jas_logerrorf("memory allocation failed\n"); | |
| 270 | + goto error; | |
| 271 | + } | |
| 272 | + jas_stream_rewind(iccstream); | |
| 273 | + if (jas_stream_read(iccstream, colr->iccp, colr->iccplen) != | |
| 274 | + colr->iccplen) { | |
| 275 | + jas_logerrorf("cannot read temporary stream\n"); | |
| 276 | + goto error; | |
| 277 | + } | |
| 278 | + jas_stream_close(iccstream); | |
| 279 | + iccstream = 0; | |
| 280 | + jas_iccprof_destroy(iccprof); | |
| 281 | + iccprof = 0; | |
| 282 | + break; | |
| 283 | + } | |
| 284 | + if (jp2_box_put(box, tmpstream)) { | |
| 285 | + jas_logerrorf("cannot write box\n"); | |
| 286 | + goto error; | |
| 287 | + } | |
| 288 | + jp2_box_destroy(box); | |
| 289 | + | |
| 290 | + needcdef = 1; | |
| 291 | + switch (jas_clrspc_fam(jas_image_clrspc(image))) { | |
| 292 | + case JAS_CLRSPC_FAM_RGB: | |
| 293 | + if (jas_image_numcmpts(image) >= 3 && | |
| 294 | + jas_image_cmpttype(image, 0) == | |
| 295 | + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R) && | |
| 296 | + jas_image_cmpttype(image, 1) == | |
| 297 | + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G) && | |
| 298 | + jas_image_cmpttype(image, 2) == | |
| 299 | + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)) | |
| 300 | + needcdef = 0; | |
| 301 | + break; | |
| 302 | + case JAS_CLRSPC_FAM_YCBCR: | |
| 303 | + if (jas_image_numcmpts(image) >= 3 && | |
| 304 | + jas_image_cmpttype(image, 0) == | |
| 305 | + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_Y) && | |
| 306 | + jas_image_cmpttype(image, 1) == | |
| 307 | + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CB) && | |
| 308 | + jas_image_cmpttype(image, 2) == | |
| 309 | + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CR)) | |
| 310 | + needcdef = 0; | |
| 311 | + break; | |
| 312 | + case JAS_CLRSPC_FAM_GRAY: | |
| 313 | + if (jas_image_numcmpts(image) >= 1 && | |
| 314 | + jas_image_cmpttype(image, 0) == | |
| 315 | + JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y)) | |
| 316 | + needcdef = 0; | |
| 317 | + break; | |
| 318 | + default: | |
| 319 | + assert(false); | |
| 320 | + JAS_UNREACHABLE(); | |
| 321 | + } | |
| 322 | + | |
| 323 | + if (needcdef) { | |
| 324 | + if (!(box = jp2_box_create(JP2_BOX_CDEF))) { | |
| 325 | + jas_logerrorf("cannot create CDEF box\n"); | |
| 326 | + goto error; | |
| 327 | + } | |
| 328 | + cdef = &box->data.cdef; | |
| 329 | + cdef->numchans = jas_image_numcmpts(image); | |
| 330 | + cdef->ents = jas_alloc2(cdef->numchans, sizeof(jp2_cdefchan_t)); | |
| 331 | + if (!cdef->ents) { | |
| 332 | + goto error; | |
| 333 | + } | |
| 334 | + for (unsigned i = 0; i < jas_image_numcmpts(image); ++i) { | |
| 335 | + cdefchanent = &cdef->ents[i]; | |
| 336 | + cdefchanent->channo = i; | |
| 337 | + typeasoc = jp2_gettypeasoc(jas_image_clrspc(image), jas_image_cmpttype(image, i)); | |
| 338 | + cdefchanent->type = typeasoc >> 16; | |
| 339 | + cdefchanent->assoc = typeasoc & 0x7fff; | |
| 340 | + } | |
| 341 | + if (jp2_box_put(box, tmpstream)) { | |
| 342 | + jas_logerrorf("cannot write CDEF box\n"); | |
| 343 | + goto error; | |
| 344 | + } | |
| 345 | + jp2_box_destroy(box); | |
| 346 | + } | |
| 347 | + | |
| 348 | + /* Determine the total length of the JP2 header box. */ | |
| 349 | + | |
| 350 | + len = jas_stream_tell(tmpstream); | |
| 351 | + jas_stream_rewind(tmpstream); | |
| 352 | + | |
| 353 | + /* | |
| 354 | + * Output the JP2 header box and all of the boxes which it contains. | |
| 355 | + */ | |
| 356 | + | |
| 357 | + if (!(box = jp2_box_create(JP2_BOX_JP2H))) { | |
| 358 | + jas_logerrorf("cannot create JP2H box\n"); | |
| 359 | + goto error; | |
| 360 | + } | |
| 361 | + box->len = len + JP2_BOX_HDRLEN(false); | |
| 362 | + if (jp2_box_put(box, out)) { | |
| 363 | + jas_logerrorf("cannot write JP2H box\n"); | |
| 364 | + goto error; | |
| 365 | + } | |
| 366 | + jp2_box_destroy(box); | |
| 367 | + box = 0; | |
| 368 | + | |
| 369 | + if (jas_stream_copy(out, tmpstream, len)) { | |
| 370 | + jas_logerrorf("cannot copy stream\n"); | |
| 371 | + goto error; | |
| 372 | + } | |
| 373 | + | |
| 374 | + jas_stream_close(tmpstream); | |
| 375 | + tmpstream = 0; | |
| 376 | + | |
| 377 | + /* | |
| 378 | + * Output the contiguous code stream box. | |
| 379 | + */ | |
| 380 | + | |
| 381 | + if (!(box = jp2_box_create(JP2_BOX_JP2C))) { | |
| 382 | + jas_logerrorf("cannot create JP2C box\n"); | |
| 383 | + goto error; | |
| 384 | + } | |
| 385 | + box->len = 0; | |
| 386 | + if (jp2_box_put(box, out)) { | |
| 387 | + jas_logerrorf("cannot write JP2C box\n"); | |
| 388 | + goto error; | |
| 389 | + } | |
| 390 | + jp2_box_destroy(box); | |
| 391 | + box = 0; | |
| 392 | + | |
| 393 | + /* Output the JPEG-2000 code stream. */ | |
| 394 | + | |
| 395 | + overhead = jas_stream_getrwcount(out); | |
| 396 | + sprintf(buf, "%s\n_jp2overhead=%lu\n", (optstr ? optstr : ""), | |
| 397 | + (unsigned long) overhead); | |
| 398 | + | |
| 399 | + if (jpc_encode(image, out, buf)) { | |
| 400 | + jas_logerrorf("jpc_encode failed\n"); | |
| 401 | + goto error; | |
| 402 | + } | |
| 403 | + | |
| 404 | + return 0; | |
| 405 | + | |
| 406 | +error: | |
| 407 | + | |
| 408 | + if (iccprof) { | |
| 409 | + jas_iccprof_destroy(iccprof); | |
| 410 | + } | |
| 411 | + if (iccstream) { | |
| 412 | + jas_stream_close(iccstream); | |
| 413 | + } | |
| 414 | + if (box) { | |
| 415 | + jp2_box_destroy(box); | |
| 416 | + } | |
| 417 | + if (tmpstream) { | |
| 418 | + jas_stream_close(tmpstream); | |
| 419 | + } | |
| 420 | + return -1; | |
| 421 | +} | |
| 422 | + | |
| 423 | +static uint_fast32_t jp2_gettypeasoc(int colorspace, int ctype) | |
| 424 | +{ | |
| 425 | + int type; | |
| 426 | + int asoc; | |
| 427 | + | |
| 428 | + if (ctype & JAS_IMAGE_CT_OPACITY) { | |
| 429 | + type = JP2_CDEF_TYPE_OPACITY; | |
| 430 | + asoc = JP2_CDEF_ASOC_ALL; | |
| 431 | + goto done; | |
| 432 | + } | |
| 433 | + | |
| 434 | + type = JP2_CDEF_TYPE_UNSPEC; | |
| 435 | + asoc = JP2_CDEF_ASOC_NONE; | |
| 436 | + switch (jas_clrspc_fam(colorspace)) { | |
| 437 | + case JAS_CLRSPC_FAM_RGB: | |
| 438 | + switch (JAS_IMAGE_CT_COLOR(ctype)) { | |
| 439 | + case JAS_IMAGE_CT_RGB_R: | |
| 440 | + type = JP2_CDEF_TYPE_COLOR; | |
| 441 | + asoc = JP2_CDEF_RGB_R; | |
| 442 | + break; | |
| 443 | + case JAS_IMAGE_CT_RGB_G: | |
| 444 | + type = JP2_CDEF_TYPE_COLOR; | |
| 445 | + asoc = JP2_CDEF_RGB_G; | |
| 446 | + break; | |
| 447 | + case JAS_IMAGE_CT_RGB_B: | |
| 448 | + type = JP2_CDEF_TYPE_COLOR; | |
| 449 | + asoc = JP2_CDEF_RGB_B; | |
| 450 | + break; | |
| 451 | + } | |
| 452 | + break; | |
| 453 | + case JAS_CLRSPC_FAM_YCBCR: | |
| 454 | + switch (JAS_IMAGE_CT_COLOR(ctype)) { | |
| 455 | + case JAS_IMAGE_CT_YCBCR_Y: | |
| 456 | + type = JP2_CDEF_TYPE_COLOR; | |
| 457 | + asoc = JP2_CDEF_YCBCR_Y; | |
| 458 | + break; | |
| 459 | + case JAS_IMAGE_CT_YCBCR_CB: | |
| 460 | + type = JP2_CDEF_TYPE_COLOR; | |
| 461 | + asoc = JP2_CDEF_YCBCR_CB; | |
| 462 | + break; | |
| 463 | + case JAS_IMAGE_CT_YCBCR_CR: | |
| 464 | + type = JP2_CDEF_TYPE_COLOR; | |
| 465 | + asoc = JP2_CDEF_YCBCR_CR; | |
| 466 | + break; | |
| 467 | + } | |
| 468 | + break; | |
| 469 | + case JAS_CLRSPC_FAM_GRAY: | |
| 470 | + type = JP2_CDEF_TYPE_COLOR; | |
| 471 | + asoc = JP2_CDEF_GRAY_Y; | |
| 472 | + break; | |
| 473 | + } | |
| 474 | + | |
| 475 | +done: | |
| 476 | + return (type << 16) | asoc; | |
| 477 | +} | |
| 478 | + | |
| 479 | +static int clrspctojp2(jas_clrspc_t clrspc) | |
| 480 | +{ | |
| 481 | + switch (clrspc) { | |
| 482 | + case JAS_CLRSPC_SRGB: | |
| 483 | + return JP2_COLR_SRGB; | |
| 484 | + case JAS_CLRSPC_SYCBCR: | |
| 485 | + return JP2_COLR_SYCC; | |
| 486 | + case JAS_CLRSPC_SGRAY: | |
| 487 | + return JP2_COLR_SGRAY; | |
| 488 | + default: | |
| 489 | + assert(false); | |
| 490 | + JAS_UNREACHABLE(); | |
| 491 | + } | |
| 492 | + JAS_UNREACHABLE(); | |
| 493 | + return -1; | |
| 494 | +} | |
| @@ -166,9 +166,9 @@ static jpc_bitstream_t *jpc_bitstream_alloc() · 165 unmodified lines | ||
| 166 | 166 | int jpc_bitstream_getbit_func(jpc_bitstream_t *bitstream) |
| 167 | 167 | { |
| 168 | 168 | int ret; |
| 169 | − JAS_DBGLOG(1000, ("jpc_bitstream_getbit_func(%p)\n", bitstream)); | |
| 169 | + JAS_LOGDEBUGF(1000, "jpc_bitstream_getbit_func(%p)\n", bitstream); | |
| 170 | 170 | ret = jpc_bitstream_getbit_macro(bitstream); |
| 171 | − JAS_DBGLOG(1000, ("jpc_bitstream_getbit_func -> %d\n", ret)); | |
| 171 | + JAS_LOGDEBUGF(1000, "jpc_bitstream_getbit_func -> %d\n", ret); | |
| 172 | 172 | return ret; |
| 173 | 173 | } |
| 174 | 174 | |
| @@ -176,9 +176,9 @@ int jpc_bitstream_getbit_func(jpc_bitstream_t *bitstream) · 1 unmodified line | ||
| 176 | 176 | int jpc_bitstream_putbit_func(jpc_bitstream_t *bitstream, int b) |
| 177 | 177 | { |
| 178 | 178 | int ret; |
| 179 | − JAS_DBGLOG(1000, ("jpc_bitstream_putbit_func(%p, %d)\n", bitstream, b)); | |
| 179 | + JAS_LOGDEBUGF(1000, "jpc_bitstream_putbit_func(%p, %d)\n", bitstream, b); | |
| 180 | 180 | ret = jpc_bitstream_putbit_macro(bitstream, b); |
| 181 | − JAS_DBGLOG(1000, ("jpc_bitstream_putbit_func() -> %d\n", ret)); | |
| 181 | + JAS_LOGDEBUGF(1000, "jpc_bitstream_putbit_func() -> %d\n", ret); | |
| 182 | 182 | return ret; |
| 183 | 183 | } |
| 184 | 184 | |
| @@ -362,6 +362,7 @@ int jpc_bitstream_inalign(jpc_bitstream_t *bitstream, int fillmask, · 177 unmodified lines | ||
| 362 | 362 | } |
| 363 | 363 | if (n > 0) { |
| 364 | 364 | if ((u = jpc_bitstream_getbits(bitstream, n)) < 0) { |
| 365 | + JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed\n"); | |
| 365 | 366 | return -1; |
| 366 | 367 | } |
| 367 | 368 | m += n; |
| @@ -369,6 +370,7 @@ int jpc_bitstream_inalign(jpc_bitstream_t *bitstream, int fillmask, · 1 unmodified line | ||
| 369 | 370 | } |
| 370 | 371 | if ((bitstream->buf_ & 0xff) == 0xff) { |
| 371 | 372 | if ((u = jpc_bitstream_getbits(bitstream, 7)) < 0) { |
| 373 | + JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed\n"); | |
| 372 | 374 | return -1; |
| 373 | 375 | } |
| 374 | 376 | v = (v << 7) | u; |
| @@ -382,6 +384,7 @@ int jpc_bitstream_inalign(jpc_bitstream_t *bitstream, int fillmask, · 7 unmodified lines | ||
| 382 | 384 | } |
| 383 | 385 | if (((~(v ^ filldata)) & fillmask) != fillmask) { |
| 384 | 386 | /* The actual fill pattern does not match the expected one. */ |
| 387 | + JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed (mismatch)\n"); | |
| 385 | 388 | return 1; |
| 386 | 389 | } |
| 387 | 390 | |
| @@ -212,12 +212,12 @@ int jpc_bitstream_putbit_func(jpc_bitstream_t *bitstream, int v); · 211 unmodified lines | ||
| 212 | 212 | int jpc_bitstream_fillbuf(jpc_bitstream_t *bitstream); |
| 213 | 213 | |
| 214 | 214 | #define jpc_bitstream_getbit_macro(bitstream) \ |
| 215 | − ((--(bitstream)->cnt_ >= 0) ? \ | |
| 215 | + ( (--(bitstream)->cnt_ >= 0) ? \ | |
| 216 | 216 | ((int)(((bitstream)->buf_ >> (bitstream)->cnt_) & 1)) : \ |
| 217 | 217 | jpc_bitstream_fillbuf(bitstream)) |
| 218 | 218 | |
| 219 | 219 | #define jpc_bitstream_putbit_macro(bitstream, bit) \ |
| 220 | − ((--(bitstream)->cnt_ < 0) ? \ | |
| 220 | + ( (--(bitstream)->cnt_ < 0) ? \ | |
| 221 | 221 | ((bitstream)->buf_ = ((bitstream)->buf_ << 8) & 0xffff, \ |
| 222 | 222 | (bitstream)->cnt_ = ((bitstream)->buf_ == 0xff00) ? 6 : 7, \ |
| 223 | 223 | (bitstream)->buf_ |= ((bit) & 1) << (bitstream)->cnt_, \ |
| @@ -0,0 +1,109 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2003 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/******************************************************************************\ | |
| 65 | +* Includes. | |
| 66 | +\******************************************************************************/ | |
| 67 | + | |
| 68 | +#define JAS_FOR_INTERNAL_USE_ONLY | |
| 69 | + | |
| 70 | +#include <jasper/jas_config.h> | |
| 71 | +#include "jasper/jas_thread.h" | |
| 72 | +#include "jasper/jas_debug.h" | |
| 73 | + | |
| 74 | +#include "jpc_cod.h" | |
| 75 | + | |
| 76 | +/******************************************************************************\ | |
| 77 | +* | |
| 78 | +\******************************************************************************/ | |
| 79 | + | |
| 80 | +static void jpc_init_helper(void); | |
| 81 | + | |
| 82 | +#if defined(JAS_THREADS) | |
| 83 | +jas_once_flag_t jpc_init_once = JAS_ONCE_FLAG_INIT; | |
| 84 | +#else | |
| 85 | +int jpc_init_once = 0; | |
| 86 | +#endif | |
| 87 | + | |
| 88 | +/******************************************************************************\ | |
| 89 | +* | |
| 90 | +\******************************************************************************/ | |
| 91 | + | |
| 92 | +void jpc_init(void) | |
| 93 | +{ | |
| 94 | +#if defined(JAS_THREADS) | |
| 95 | + jas_call_once(&jpc_init_once, jpc_init_helper); | |
| 96 | +#else | |
| 97 | + if (!jpc_init_once) { | |
| 98 | + jpc_init_helper(); | |
| 99 | + jpc_init_once = 1; | |
| 100 | + } | |
| 101 | +#endif | |
| 102 | +} | |
| 103 | + | |
| 104 | +static void jpc_init_helper(void) | |
| 105 | +{ | |
| 106 | + JAS_LOGDEBUGF(10, "jpc_init_helper called\n"); | |
| 107 | + jpc_initmqctxs(); | |
| 108 | + jpc_initluts(); | |
| 109 | +} | |
| @@ -68,6 +68,8 @@ · 67 unmodified lines | ||
| 68 | 68 | #ifndef JPC_COD_H |
| 69 | 69 | #define JPC_COD_H |
| 70 | 70 | |
| 71 | +#include "jpc_t1cod.h" | |
| 72 | + | |
| 71 | 73 | /******************************************************************************\ |
| 72 | 74 | * Constants. |
| 73 | 75 | \******************************************************************************/ |
| @@ -75,4 +77,6 @@ · 1 unmodified line | ||
| 75 | 77 | /* The nominal word size used by this implementation. */ |
| 76 | 78 | #define JPC_PREC 32 |
| 77 | 79 | |
| 80 | +void jpc_init(void); | |
| 81 | + | |
| 78 | 82 | #endif |
| @@ -94,6 +94,7 @@ typedef struct { · 93 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | static const jpc_mstabent_t *jpc_mstab_lookup(int id); |
| 96 | 96 | |
| 97 | +static int jpc_poc_dumpparms(jpc_ms_t *ms); | |
| 97 | 98 | static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); |
| 98 | 99 | static int jpc_poc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in); |
| 99 | 100 | static void jpc_poc_destroyparms(jpc_ms_t *ms); |
| @@ -126,6 +127,20 @@ static int jpc_ppt_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 26 unmodified lines | ||
| 126 | 127 | static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); |
| 127 | 128 | static int jpc_com_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); |
| 128 | 129 | |
| 130 | +static int jpc_sot_dumpparms(jpc_ms_t *ms); | |
| 131 | +static int jpc_siz_dumpparms(jpc_ms_t *ms); | |
| 132 | +static int jpc_cod_dumpparms(jpc_ms_t *ms); | |
| 133 | +static int jpc_coc_dumpparms(jpc_ms_t *ms); | |
| 134 | +static int jpc_qcd_dumpparms(jpc_ms_t *ms); | |
| 135 | +static int jpc_qcc_dumpparms(jpc_ms_t *ms); | |
| 136 | +static int jpc_rgn_dumpparms(jpc_ms_t *ms); | |
| 137 | +static int jpc_unk_dumpparms(jpc_ms_t *ms); | |
| 138 | +static int jpc_sop_dumpparms(jpc_ms_t *ms); | |
| 139 | +static int jpc_ppm_dumpparms(jpc_ms_t *ms); | |
| 140 | +static int jpc_ppt_dumpparms(jpc_ms_t *ms); | |
| 141 | +static int jpc_crg_dumpparms(jpc_ms_t *ms); | |
| 142 | +static int jpc_com_dumpparms(jpc_ms_t *ms); | |
| 143 | + | |
| 129 | 144 | static void jpc_siz_destroyparms(jpc_ms_t *ms); |
| 130 | 145 | static void jpc_qcd_destroyparms(jpc_ms_t *ms); |
| 131 | 146 | static void jpc_qcc_destroyparms(jpc_ms_t *ms); |
| @@ -153,26 +168,40 @@ static int jpc_cox_putcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 21 unmodified lines | ||
| 153 | 168 | \******************************************************************************/ |
| 154 | 169 | |
| 155 | 170 | static const jpc_mstabent_t jpc_mstab[] = { |
| 156 | − {JPC_MS_SOC, "SOC", {0, 0, 0}}, | |
| 157 | − {JPC_MS_SOT, "SOT", {0, jpc_sot_getparms, jpc_sot_putparms}}, | |
| 158 | − {JPC_MS_SOD, "SOD", {0, 0, 0}}, | |
| 159 | − {JPC_MS_EOC, "EOC", {0, 0, 0}}, | |
| 160 | − {JPC_MS_SIZ, "SIZ", {jpc_siz_destroyparms, jpc_siz_getparms, jpc_siz_putparms}}, | |
| 161 | − {JPC_MS_COD, "COD", {jpc_cod_destroyparms, jpc_cod_getparms, jpc_cod_putparms}}, | |
| 162 | − {JPC_MS_COC, "COC", {jpc_coc_destroyparms, jpc_coc_getparms, jpc_coc_putparms}}, | |
| 163 | − {JPC_MS_RGN, "RGN", {0, jpc_rgn_getparms, jpc_rgn_putparms}}, | |
| 164 | − {JPC_MS_QCD, "QCD", {jpc_qcd_destroyparms, jpc_qcd_getparms, jpc_qcd_putparms}}, | |
| 165 | − {JPC_MS_QCC, "QCC", {jpc_qcc_destroyparms, jpc_qcc_getparms, jpc_qcc_putparms}}, | |
| 166 | − {JPC_MS_POC, "POC", {jpc_poc_destroyparms, jpc_poc_getparms, jpc_poc_putparms}}, | |
| 167 | − {JPC_MS_TLM, "TLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms,}}, | |
| 168 | − {JPC_MS_PLM, "PLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms}}, | |
| 169 | − {JPC_MS_PPM, "PPM", {jpc_ppm_destroyparms, jpc_ppm_getparms, jpc_ppm_putparms}}, | |
| 170 | − {JPC_MS_PPT, "PPT", {jpc_ppt_destroyparms, jpc_ppt_getparms, jpc_ppt_putparms}}, | |
| 171 | − {JPC_MS_SOP, "SOP", {0, jpc_sop_getparms, jpc_sop_putparms}}, | |
| 172 | − {JPC_MS_EPH, "EPH", {0, 0, 0}}, | |
| 173 | − {JPC_MS_CRG, "CRG", {jpc_crg_destroyparms, jpc_crg_getparms, jpc_crg_putparms}}, | |
| 174 | − {JPC_MS_COM, "COM", {jpc_com_destroyparms, jpc_com_getparms, jpc_com_putparms}}, | |
| 175 | − {-1, "UNKNOWN", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms}} | |
| 171 | + {JPC_MS_SOC, "SOC", {0, 0, 0, 0}}, | |
| 172 | + {JPC_MS_SOT, "SOT", {0, jpc_sot_getparms, jpc_sot_putparms, | |
| 173 | + jpc_sot_dumpparms}}, | |
| 174 | + {JPC_MS_SOD, "SOD", {0, 0, 0, 0}}, | |
| 175 | + {JPC_MS_EOC, "EOC", {0, 0, 0, 0}}, | |
| 176 | + {JPC_MS_SIZ, "SIZ", {jpc_siz_destroyparms, jpc_siz_getparms, | |
| 177 | + jpc_siz_putparms, jpc_siz_dumpparms}}, | |
| 178 | + {JPC_MS_COD, "COD", {jpc_cod_destroyparms, jpc_cod_getparms, | |
| 179 | + jpc_cod_putparms, jpc_cod_dumpparms}}, | |
| 180 | + {JPC_MS_COC, "COC", {jpc_coc_destroyparms, jpc_coc_getparms, | |
| 181 | + jpc_coc_putparms, jpc_coc_dumpparms}}, | |
| 182 | + {JPC_MS_RGN, "RGN", {0, jpc_rgn_getparms, jpc_rgn_putparms, | |
| 183 | + jpc_rgn_dumpparms}}, | |
| 184 | + {JPC_MS_QCD, "QCD", {jpc_qcd_destroyparms, jpc_qcd_getparms, | |
| 185 | + jpc_qcd_putparms, jpc_qcd_dumpparms}}, | |
| 186 | + {JPC_MS_QCC, "QCC", {jpc_qcc_destroyparms, jpc_qcc_getparms, | |
| 187 | + jpc_qcc_putparms, jpc_qcc_dumpparms}}, | |
| 188 | + {JPC_MS_POC, "POC", {jpc_poc_destroyparms, jpc_poc_getparms, | |
| 189 | + jpc_poc_putparms, jpc_poc_dumpparms}}, | |
| 190 | + {JPC_MS_TLM, "TLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms, 0}}, | |
| 191 | + {JPC_MS_PLM, "PLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms, 0}}, | |
| 192 | + {JPC_MS_PPM, "PPM", {jpc_ppm_destroyparms, jpc_ppm_getparms, | |
| 193 | + jpc_ppm_putparms, jpc_ppm_dumpparms}}, | |
| 194 | + {JPC_MS_PPT, "PPT", {jpc_ppt_destroyparms, jpc_ppt_getparms, | |
| 195 | + jpc_ppt_putparms, jpc_ppt_dumpparms}}, | |
| 196 | + {JPC_MS_SOP, "SOP", {0, jpc_sop_getparms, jpc_sop_putparms, | |
| 197 | + jpc_sop_dumpparms}}, | |
| 198 | + {JPC_MS_EPH, "EPH", {0, 0, 0, 0}}, | |
| 199 | + {JPC_MS_CRG, "CRG", {jpc_crg_destroyparms, jpc_crg_getparms, | |
| 200 | + jpc_crg_putparms, jpc_crg_dumpparms}}, | |
| 201 | + {JPC_MS_COM, "COM", {jpc_com_destroyparms, jpc_com_getparms, | |
| 202 | + jpc_com_putparms, jpc_com_dumpparms}}, | |
| 203 | + {-1, "UNKNOWN", {jpc_unk_destroyparms, jpc_unk_getparms, | |
| 204 | + jpc_unk_putparms, jpc_unk_dumpparms}} | |
| 176 | 205 | }; |
| 177 | 206 | |
| 178 | 207 | /******************************************************************************\ |
| @@ -238,7 +267,7 @@ jpc_ms_t *jpc_getms(jas_stream_t *in, jpc_cstate_t *cstate) · 59 unmodified lines | ||
| 238 | 267 | return 0; |
| 239 | 268 | } |
| 240 | 269 | if (jas_stream_copy(tmpstream, in, ms->len) || |
| 241 | − jas_stream_seek(tmpstream, 0, 0) < 0) { | |
| 270 | + jas_stream_seek(tmpstream, 0, SEEK_SET) < 0) { | |
| 242 | 271 | jas_stream_close(tmpstream); |
| 243 | 272 | jpc_ms_destroy(ms); |
| 244 | 273 | return 0; |
| @@ -251,8 +280,12 @@ jpc_ms_t *jpc_getms(jas_stream_t *in, jpc_cstate_t *cstate) · 6 unmodified lines | ||
| 251 | 280 | return 0; |
| 252 | 281 | } |
| 253 | 282 | |
| 283 | + if (jas_get_debug_level() > 0) { | |
| 284 | + jpc_ms_dump(ms); | |
| 285 | + } | |
| 286 | + | |
| 254 | 287 | if (JAS_CAST(jas_ulong, jas_stream_tell(tmpstream)) != ms->len) { |
| 255 | − jas_eprintf( | |
| 288 | + jas_logwarnf( | |
| 256 | 289 | "warning: trailing garbage in marker segment (%ld bytes)\n", |
| 257 | 290 | ms->len - jas_stream_tell(tmpstream)); |
| 258 | 291 | } |
| @@ -263,6 +296,10 @@ jpc_ms_t *jpc_getms(jas_stream_t *in, jpc_cstate_t *cstate) · 4 unmodified lines | ||
| 263 | 296 | } else { |
| 264 | 297 | /* There are no marker segment parameters. */ |
| 265 | 298 | ms->len = 0; |
| 299 | + | |
| 300 | + if (jas_get_debug_level() > 0) { | |
| 301 | + jpc_ms_dump(ms); | |
| 302 | + } | |
| 266 | 303 | } |
| 267 | 304 | |
| 268 | 305 | /* Update the code stream state information based on the type of |
| @@ -306,7 +343,7 @@ int jpc_putms(jas_stream_t *out, jpc_cstate_t *cstate, jpc_ms_t *ms) · 37 unmodified lines | ||
| 306 | 343 | ms->len = len; |
| 307 | 344 | /* Write the marker segment length and parameter data to |
| 308 | 345 | the output stream. */ |
| 309 | − if (jas_stream_seek(tmpstream, 0, 0) < 0 || | |
| 346 | + if (jas_stream_seek(tmpstream, 0, SEEK_SET) < 0 || | |
| 310 | 347 | jpc_putuint16(out, ms->len + 2) || |
| 311 | 348 | jas_stream_copy(out, tmpstream, ms->len) < 0) { |
| 312 | 349 | jas_stream_close(tmpstream); |
| @@ -322,6 +359,10 @@ int jpc_putms(jas_stream_t *out, jpc_cstate_t *cstate, jpc_ms_t *ms) · 9 unmodified lines | ||
| 322 | 359 | cstate->numcomps = ms->parms.siz.numcomps; |
| 323 | 360 | } |
| 324 | 361 | |
| 362 | + if (jas_get_debug_level() > 0) { | |
| 363 | + jpc_ms_dump(ms); | |
| 364 | + } | |
| 365 | + | |
| 325 | 366 | return 0; |
| 326 | 367 | } |
| 327 | 368 | |
| @@ -355,6 +396,24 @@ void jpc_ms_destroy(jpc_ms_t *ms) · 27 unmodified lines | ||
| 355 | 396 | jas_free(ms); |
| 356 | 397 | } |
| 357 | 398 | |
| 399 | +/* Dump a marker segment to a stream for debugging. */ | |
| 400 | +void jpc_ms_dump(jpc_ms_t *ms) | |
| 401 | +{ | |
| 402 | + const jpc_mstabent_t *mstabent; | |
| 403 | + mstabent = jpc_mstab_lookup(ms->id); | |
| 404 | + jas_logprintf("type = 0x%04"PRIxFAST16" (%s);", ms->id, mstabent->name); | |
| 405 | + if (JPC_MS_HASPARMS(ms->id)) { | |
| 406 | + jas_logprintf(" len = %"PRIuFAST16";", ms->len + 2); | |
| 407 | + if (ms->ops->dumpparms) { | |
| 408 | + (*ms->ops->dumpparms)(ms); | |
| 409 | + } else { | |
| 410 | + jas_logprintf("\n"); | |
| 411 | + } | |
| 412 | + } else { | |
| 413 | + jas_logprintf("\n"); | |
| 414 | + } | |
| 415 | +} | |
| 416 | + | |
| 358 | 417 | /******************************************************************************\ |
| 359 | 418 | * SOT marker segment operations. |
| 360 | 419 | \******************************************************************************/ |
| @@ -363,8 +422,7 @@ static int jpc_sot_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 2 unmodified lines | ||
| 363 | 422 | { |
| 364 | 423 | jpc_sot_t *sot = &ms->parms.sot; |
| 365 | 424 | |
| 366 | − /* Eliminate compiler warning about unused variables. */ | |
| 367 | − (void)cstate; | |
| 425 | + JAS_UNUSED(cstate); | |
| 368 | 426 | |
| 369 | 427 | if (jpc_getuint16(in, &sot->tileno) || |
| 370 | 428 | jpc_getuint32(in, &sot->len) || |
| @@ -385,8 +443,7 @@ static int jpc_sot_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 14 unmodified lines | ||
| 385 | 443 | { |
| 386 | 444 | jpc_sot_t *sot = &ms->parms.sot; |
| 387 | 445 | |
| 388 | − /* Eliminate compiler warning about unused variables. */ | |
| 389 | − (void)cstate; | |
| 446 | + JAS_UNUSED(cstate); | |
| 390 | 447 | |
| 391 | 448 | if (jpc_putuint16(out, sot->tileno) || |
| 392 | 449 | jpc_putuint32(out, sot->len) || |
| @@ -397,6 +454,15 @@ static int jpc_sot_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 4 unmodified lines | ||
| 397 | 454 | return 0; |
| 398 | 455 | } |
| 399 | 456 | |
| 457 | +static int jpc_sot_dumpparms(jpc_ms_t *ms) | |
| 458 | +{ | |
| 459 | + jpc_sot_t *sot = &ms->parms.sot; | |
| 460 | + jas_logprintf( | |
| 461 | + "tileno = %"PRIuFAST16"; len = %"PRIuFAST32"; partno = %d; numparts = %d\n", | |
| 462 | + sot->tileno, sot->len, sot->partno, sot->numparts); | |
| 463 | + return 0; | |
| 464 | +} | |
| 465 | + | |
| 400 | 466 | /******************************************************************************\ |
| 401 | 467 | * SIZ marker segment operations. |
| 402 | 468 | \******************************************************************************/ |
| @@ -418,8 +484,7 @@ static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 15 unmodified lines | ||
| 418 | 484 | |
| 419 | 485 | siz->comps = 0; |
| 420 | 486 | |
| 421 | − /* Eliminate compiler warning about unused variables. */ | |
| 422 | − (void)cstate; | |
| 487 | + JAS_UNUSED(cstate); | |
| 423 | 488 | |
| 424 | 489 | if (jpc_getuint16(in, &siz->caps) || |
| 425 | 490 | jpc_getuint32(in, &siz->width) || |
| @@ -434,31 +499,31 @@ static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 8 unmodified lines | ||
| 434 | 499 | goto error; |
| 435 | 500 | } |
| 436 | 501 | if (!siz->width || !siz->height) { |
| 437 | − jas_eprintf("reference grid cannot have zero area\n"); | |
| 502 | + jas_logerrorf("reference grid cannot have zero area\n"); | |
| 438 | 503 | goto error; |
| 439 | 504 | } |
| 440 | 505 | if (!siz->tilewidth || !siz->tileheight) { |
| 441 | − jas_eprintf("tile cannot have zero area\n"); | |
| 506 | + jas_logerrorf("tile cannot have zero area\n"); | |
| 442 | 507 | goto error; |
| 443 | 508 | } |
| 444 | 509 | if (!siz->numcomps || siz->numcomps > 16384) { |
| 445 | − jas_eprintf("number of components not in permissible range\n"); | |
| 510 | + jas_logerrorf("number of components not in permissible range\n"); | |
| 446 | 511 | goto error; |
| 447 | 512 | } |
| 448 | 513 | if (siz->xoff >= siz->width) { |
| 449 | − jas_eprintf("XOsiz not in permissible range\n"); | |
| 514 | + jas_logerrorf("XOsiz not in permissible range\n"); | |
| 450 | 515 | goto error; |
| 451 | 516 | } |
| 452 | 517 | if (siz->yoff >= siz->height) { |
| 453 | − jas_eprintf("YOsiz not in permissible range\n"); | |
| 518 | + jas_logerrorf("YOsiz not in permissible range\n"); | |
| 454 | 519 | goto error; |
| 455 | 520 | } |
| 456 | 521 | if (siz->tilexoff > siz->xoff || siz->tilexoff + siz->tilewidth <= siz->xoff) { |
| 457 | − jas_eprintf("XTOsiz not in permissible range\n"); | |
| 522 | + jas_logerrorf("XTOsiz not in permissible range\n"); | |
| 458 | 523 | goto error; |
| 459 | 524 | } |
| 460 | 525 | if (siz->tileyoff > siz->yoff || siz->tileyoff + siz->tileheight <= siz->yoff) { |
| 461 | − jas_eprintf("YTOsiz not in permissible range\n"); | |
| 526 | + jas_logerrorf("YTOsiz not in permissible range\n"); | |
| 462 | 527 | goto error; |
| 463 | 528 | } |
| 464 | 529 | |
| @@ -472,11 +537,11 @@ static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 7 unmodified lines | ||
| 472 | 537 | goto error; |
| 473 | 538 | } |
| 474 | 539 | if (siz->comps[i].hsamp == 0) { |
| 475 | − jas_eprintf("invalid XRsiz value %d\n", siz->comps[i].hsamp); | |
| 540 | + jas_logerrorf("invalid XRsiz value %d\n", siz->comps[i].hsamp); | |
| 476 | 541 | goto error; |
| 477 | 542 | } |
| 478 | 543 | if (siz->comps[i].vsamp == 0) { |
| 479 | − jas_eprintf("invalid YRsiz value %d\n", siz->comps[i].vsamp); | |
| 544 | + jas_logerrorf("invalid YRsiz value %d\n", siz->comps[i].vsamp); | |
| 480 | 545 | goto error; |
| 481 | 546 | } |
| 482 | 547 | siz->comps[i].sgnd = (tmp >> 7) & 1; |
| @@ -485,7 +550,7 @@ static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 2 unmodified lines | ||
| 485 | 550 | samples and 2 bits for signed samples */ |
| 486 | 551 | if (siz->comps[i].prec < 1U + siz->comps[i].sgnd || |
| 487 | 552 | siz->comps[i].prec > 38) { |
| 488 | − jas_eprintf("invalid component bit depth %d\n", siz->comps[i].prec); | |
| 553 | + jas_logerrorf("invalid component bit depth %d\n", siz->comps[i].prec); | |
| 489 | 554 | goto error; |
| 490 | 555 | } |
| 491 | 556 | } |
| @@ -506,8 +571,7 @@ static int jpc_siz_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 14 unmodified lines | ||
| 506 | 571 | jpc_siz_t *siz = &ms->parms.siz; |
| 507 | 572 | unsigned int i; |
| 508 | 573 | |
| 509 | − /* Eliminate compiler warning about unused variables. */ | |
| 510 | − (void)cstate; | |
| 574 | + JAS_UNUSED(cstate); | |
| 511 | 575 | |
| 512 | 576 | assert(siz->width && siz->height && siz->tilewidth && |
| 513 | 577 | siz->tileheight && siz->numcomps); |
| @@ -534,6 +598,26 @@ static int jpc_siz_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 20 unmodified lines | ||
| 534 | 598 | return 0; |
| 535 | 599 | } |
| 536 | 600 | |
| 601 | +static int jpc_siz_dumpparms(jpc_ms_t *ms) | |
| 602 | +{ | |
| 603 | + jpc_siz_t *siz = &ms->parms.siz; | |
| 604 | + unsigned int i; | |
| 605 | + jas_logprintf("caps = 0x%02"PRIxFAST16";\n", siz->caps); | |
| 606 | + jas_logprintf("width = %"PRIuFAST32"; height = %"PRIuFAST32"; xoff = %"PRIuFAST32"; yoff = %" PRIuFAST32 ";\n", | |
| 607 | + siz->width, siz->height, siz->xoff, siz->yoff); | |
| 608 | + jas_logprintf("tilewidth = %"PRIuFAST32"; tileheight = %"PRIuFAST32"; " | |
| 609 | + "tilexoff = %"PRIuFAST32"; tileyoff = %" PRIuFAST32 ";\n", | |
| 610 | + siz->tilewidth, siz->tileheight, siz->tilexoff, siz->tileyoff); | |
| 611 | + jas_logprintf("numcomps = %"PRIuFAST16";\n", siz->numcomps); | |
| 612 | + for (i = 0; i < siz->numcomps; ++i) { | |
| 613 | + jas_logprintf("prec[%d] = %d; sgnd[%d] = %d; hsamp[%d] = %d; " | |
| 614 | + "vsamp[%d] = %d\n", i, siz->comps[i].prec, i, | |
| 615 | + siz->comps[i].sgnd, i, siz->comps[i].hsamp, i, | |
| 616 | + siz->comps[i].vsamp); | |
| 617 | + } | |
| 618 | + return 0; | |
| 619 | +} | |
| 620 | + | |
| 537 | 621 | /******************************************************************************\ |
| 538 | 622 | * COD marker segment operations. |
| 539 | 623 | \******************************************************************************/ |
| @@ -587,6 +671,28 @@ static int jpc_cod_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 47 unmodified lines | ||
| 587 | 671 | return 0; |
| 588 | 672 | } |
| 589 | 673 | |
| 674 | +static int jpc_cod_dumpparms(jpc_ms_t *ms) | |
| 675 | +{ | |
| 676 | + jpc_cod_t *cod = &ms->parms.cod; | |
| 677 | + int i; | |
| 678 | + jas_logprintf("csty = 0x%02x;\n", cod->compparms.csty); | |
| 679 | + jas_logprintf("numdlvls = %d; qmfbid = %d; mctrans = %d\n", | |
| 680 | + cod->compparms.numdlvls, cod->compparms.qmfbid, cod->mctrans); | |
| 681 | + jas_logprintf("prg = %d; numlyrs = %"PRIuFAST16";\n", | |
| 682 | + cod->prg, cod->numlyrs); | |
| 683 | + jas_logprintf("cblkwidthval = %d; cblkheightval = %d; " | |
| 684 | + "cblksty = 0x%02x;\n", cod->compparms.cblkwidthval, cod->compparms.cblkheightval, | |
| 685 | + cod->compparms.cblksty); | |
| 686 | + if (cod->csty & JPC_COX_PRT) { | |
| 687 | + for (i = 0; i < cod->compparms.numrlvls; ++i) { | |
| 688 | + jas_logprintf("prcwidth[%d] = %d, prcheight[%d] = %d\n", | |
| 689 | + i, cod->compparms.rlvls[i].parwidthval, | |
| 690 | + i, cod->compparms.rlvls[i].parheightval); | |
| 691 | + } | |
| 692 | + } | |
| 693 | + return 0; | |
| 694 | +} | |
| 695 | + | |
| 590 | 696 | /******************************************************************************\ |
| 591 | 697 | * COC marker segment operations. |
| 592 | 698 | \******************************************************************************/ |
| @@ -647,14 +753,23 @@ static int jpc_coc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 54 unmodified lines | ||
| 647 | 753 | return 0; |
| 648 | 754 | } |
| 649 | 755 | |
| 756 | +static int jpc_coc_dumpparms(jpc_ms_t *ms) | |
| 757 | +{ | |
| 758 | + jpc_coc_t *coc = &ms->parms.coc; | |
| 759 | + jas_logprintf("compno = %"PRIuFAST16"; csty = 0x%02x; numdlvls = %d;\n", | |
| 760 | + coc->compno, coc->compparms.csty, coc->compparms.numdlvls); | |
| 761 | + jas_logprintf("cblkwidthval = %d; cblkheightval = %d; " | |
| 762 | + "cblksty = 0x%02x; qmfbid = %d;\n", coc->compparms.cblkwidthval, | |
| 763 | + coc->compparms.cblkheightval, coc->compparms.cblksty, coc->compparms.qmfbid); | |
| 764 | + return 0; | |
| 765 | +} | |
| 650 | 766 | /******************************************************************************\ |
| 651 | 767 | * COD/COC marker segment operation helper functions. |
| 652 | 768 | \******************************************************************************/ |
| 653 | 769 | |
| 654 | 770 | static void jpc_cox_destroycompparms(jpc_coxcp_t *compparms) |
| 655 | 771 | { |
| 656 | − /* Eliminate compiler warning about unused variables. */ | |
| 657 | − USED(compparms); | |
| 772 | + JAS_UNUSED(compparms); | |
| 658 | 773 | } |
| 659 | 774 | |
| 660 | 775 | static int jpc_cox_getcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate, |
| @@ -663,9 +778,8 @@ static int jpc_cox_getcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 2 unmodified lines | ||
| 663 | 778 | uint_fast8_t tmp; |
| 664 | 779 | int i; |
| 665 | 780 | |
| 666 | − /* Eliminate compiler warning about unused variables. */ | |
| 667 | − USED(ms); | |
| 668 | − USED(cstate); | |
| 781 | + JAS_UNUSED(ms); | |
| 782 | + JAS_UNUSED(cstate); | |
| 669 | 783 | |
| 670 | 784 | if (jpc_getuint8(in, &compparms->numdlvls) || |
| 671 | 785 | jpc_getuint8(in, &compparms->cblkwidthval) || |
| @@ -711,9 +825,8 @@ static int jpc_cox_putcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 39 unmodified lines | ||
| 711 | 825 | int i; |
| 712 | 826 | assert(compparms->numdlvls <= 32); |
| 713 | 827 | |
| 714 | − /* Eliminate compiler warning about unused variables. */ | |
| 715 | − USED(ms); | |
| 716 | − USED(cstate); | |
| 828 | + JAS_UNUSED(ms); | |
| 829 | + JAS_UNUSED(cstate); | |
| 717 | 830 | |
| 718 | 831 | if (jpc_putuint8(out, compparms->numdlvls) || |
| 719 | 832 | jpc_putuint8(out, compparms->cblkwidthval) || |
| @@ -778,6 +891,14 @@ static int jpc_rgn_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 58 unmodified lines | ||
| 778 | 891 | return 0; |
| 779 | 892 | } |
| 780 | 893 | |
| 894 | +static int jpc_rgn_dumpparms(jpc_ms_t *ms) | |
| 895 | +{ | |
| 896 | + jpc_rgn_t *rgn = &ms->parms.rgn; | |
| 897 | + jas_logprintf("compno = %"PRIuFAST16"; roisty = %d; roishift = %d\n", | |
| 898 | + rgn->compno, rgn->roisty, rgn->roishift); | |
| 899 | + return 0; | |
| 900 | +} | |
| 901 | + | |
| 781 | 902 | /******************************************************************************\ |
| 782 | 903 | * QCD marker segment operations. |
| 783 | 904 | \******************************************************************************/ |
| @@ -800,6 +921,20 @@ static int jpc_qcd_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 16 unmodified lines | ||
| 800 | 921 | return jpc_qcx_putcompparms(compparms, cstate, out); |
| 801 | 922 | } |
| 802 | 923 | |
| 924 | +static int jpc_qcd_dumpparms(jpc_ms_t *ms) | |
| 925 | +{ | |
| 926 | + jpc_qcd_t *qcd = &ms->parms.qcd; | |
| 927 | + int i; | |
| 928 | + jas_logprintf("qntsty = %d; numguard = %d; numstepsizes = %d\n", | |
| 929 | + (int) qcd->compparms.qntsty, qcd->compparms.numguard, qcd->compparms.numstepsizes); | |
| 930 | + for (i = 0; i < qcd->compparms.numstepsizes; ++i) { | |
| 931 | + jas_logprintf("expn[%d] = 0x%04x; mant[%d] = 0x%04x;\n", | |
| 932 | + i, JAS_CAST(unsigned, JPC_QCX_GETEXPN(qcd->compparms.stepsizes[i])), | |
| 933 | + i, JAS_CAST(unsigned, JPC_QCX_GETMANT(qcd->compparms.stepsizes[i]))); | |
| 934 | + } | |
| 935 | + return 0; | |
| 936 | +} | |
| 937 | + | |
| 803 | 938 | /******************************************************************************\ |
| 804 | 939 | * QCC marker segment operations. |
| 805 | 940 | \******************************************************************************/ |
| @@ -856,6 +991,21 @@ static int jpc_qcc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 50 unmodified lines | ||
| 856 | 991 | return 0; |
| 857 | 992 | } |
| 858 | 993 | |
| 994 | +static int jpc_qcc_dumpparms(jpc_ms_t *ms) | |
| 995 | +{ | |
| 996 | + jpc_qcc_t *qcc = &ms->parms.qcc; | |
| 997 | + int i; | |
| 998 | + jas_logprintf("compno = %"PRIuFAST16"; qntsty = %d; numguard = %d; " | |
| 999 | + "numstepsizes = %d\n", qcc->compno, qcc->compparms.qntsty, qcc->compparms.numguard, | |
| 1000 | + qcc->compparms.numstepsizes); | |
| 1001 | + for (i = 0; i < qcc->compparms.numstepsizes; ++i) { | |
| 1002 | + jas_logprintf("expn[%d] = 0x%04x; mant[%d] = 0x%04x;\n", | |
| 1003 | + i, (unsigned) JPC_QCX_GETEXPN(qcc->compparms.stepsizes[i]), | |
| 1004 | + i, (unsigned) JPC_QCX_GETMANT(qcc->compparms.stepsizes[i])); | |
| 1005 | + } | |
| 1006 | + return 0; | |
| 1007 | +} | |
| 1008 | + | |
| 859 | 1009 | /******************************************************************************\ |
| 860 | 1010 | * QCD/QCC marker segment helper functions. |
| 861 | 1011 | \******************************************************************************/ |
| @@ -874,8 +1024,7 @@ static int jpc_qcx_getcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate, · 12 unmodified lines | ||
| 874 | 1024 | int n; |
| 875 | 1025 | int i; |
| 876 | 1026 | |
| 877 | − /* Eliminate compiler warning about unused variables. */ | |
| 878 | − (void)cstate; | |
| 1027 | + JAS_UNUSED(cstate); | |
| 879 | 1028 | |
| 880 | 1029 | n = 0; |
| 881 | 1030 | if (jpc_getuint8(in, &tmp)) { |
| @@ -936,8 +1085,7 @@ static int jpc_qcx_putcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate, · 54 unmodified lines | ||
| 936 | 1085 | { |
| 937 | 1086 | int i; |
| 938 | 1087 | |
| 939 | − /* Eliminate compiler warning about unused variables. */ | |
| 940 | − (void)cstate; | |
| 1088 | + JAS_UNUSED(cstate); | |
| 941 | 1089 | |
| 942 | 1090 | if (jpc_putuint8(out, ((compparms->numguard & 7) << 5) | compparms->qntsty)) { |
| 943 | 1091 | return -1; |
| @@ -965,8 +1113,7 @@ static int jpc_sop_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 21 unmodified lines | ||
| 965 | 1113 | { |
| 966 | 1114 | jpc_sop_t *sop = &ms->parms.sop; |
| 967 | 1115 | |
| 968 | − /* Eliminate compiler warning about unused variable. */ | |
| 969 | − (void)cstate; | |
| 1116 | + JAS_UNUSED(cstate); | |
| 970 | 1117 | |
| 971 | 1118 | if (jpc_getuint16(in, &sop->seqno)) { |
| 972 | 1119 | return -1; |
| @@ -978,8 +1125,7 @@ static int jpc_sop_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 5 unmodified lines | ||
| 978 | 1125 | { |
| 979 | 1126 | jpc_sop_t *sop = &ms->parms.sop; |
| 980 | 1127 | |
| 981 | − /* Eliminate compiler warning about unused variable. */ | |
| 982 | − (void)cstate; | |
| 1128 | + JAS_UNUSED(cstate); | |
| 983 | 1129 | |
| 984 | 1130 | if (jpc_putuint16(out, sop->seqno)) { |
| 985 | 1131 | return -1; |
| @@ -987,6 +1133,13 @@ static int jpc_sop_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 1 unmodified line | ||
| 987 | 1133 | return 0; |
| 988 | 1134 | } |
| 989 | 1135 | |
| 1136 | +static int jpc_sop_dumpparms(jpc_ms_t *ms) | |
| 1137 | +{ | |
| 1138 | + jpc_sop_t *sop = &ms->parms.sop; | |
| 1139 | + jas_logprintf("seqno = %"PRIuFAST16";\n", sop->seqno); | |
| 1140 | + return 0; | |
| 1141 | +} | |
| 1142 | + | |
| 990 | 1143 | /******************************************************************************\ |
| 991 | 1144 | * PPM marker segment operations. |
| 992 | 1145 | \******************************************************************************/ |
| @@ -1003,8 +1156,7 @@ static int jpc_ppm_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 10 unmodified lines | ||
| 1003 | 1156 | { |
| 1004 | 1157 | jpc_ppm_t *ppm = &ms->parms.ppm; |
| 1005 | 1158 | |
| 1006 | − /* Eliminate compiler warning about unused variables. */ | |
| 1007 | − (void)cstate; | |
| 1159 | + JAS_UNUSED(cstate); | |
| 1008 | 1160 | |
| 1009 | 1161 | ppm->data = 0; |
| 1010 | 1162 | |
| @@ -1037,8 +1189,7 @@ static int jpc_ppm_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 26 unmodified lines | ||
| 1037 | 1189 | { |
| 1038 | 1190 | jpc_ppm_t *ppm = &ms->parms.ppm; |
| 1039 | 1191 | |
| 1040 | − /* Eliminate compiler warning about unused variables. */ | |
| 1041 | − (void)cstate; | |
| 1192 | + JAS_UNUSED(cstate); | |
| 1042 | 1193 | |
| 1043 | 1194 | if (JAS_CAST(jas_uint, jas_stream_write(out, (char *) ppm->data, ppm->len)) != ppm->len) { |
| 1044 | 1195 | return -1; |
| @@ -1046,6 +1197,17 @@ static int jpc_ppm_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 1 unmodified line | ||
| 1046 | 1197 | return 0; |
| 1047 | 1198 | } |
| 1048 | 1199 | |
| 1200 | +static int jpc_ppm_dumpparms(jpc_ms_t *ms) | |
| 1201 | +{ | |
| 1202 | + jpc_ppm_t *ppm = &ms->parms.ppm; | |
| 1203 | + jas_logprintf("ind=%d; len = %"PRIuFAST16";\n", ppm->ind, ppm->len); | |
| 1204 | + if (ppm->len > 0) { | |
| 1205 | + jas_logprintf("data =\n"); | |
| 1206 | + jas_logmemdump(ppm->data, ppm->len); | |
| 1207 | + } | |
| 1208 | + return 0; | |
| 1209 | +} | |
| 1210 | + | |
| 1049 | 1211 | /******************************************************************************\ |
| 1050 | 1212 | * PPT marker segment operations. |
| 1051 | 1213 | \******************************************************************************/ |
| @@ -1062,8 +1224,7 @@ static int jpc_ppt_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 10 unmodified lines | ||
| 1062 | 1224 | { |
| 1063 | 1225 | jpc_ppt_t *ppt = &ms->parms.ppt; |
| 1064 | 1226 | |
| 1065 | − /* Eliminate compiler warning about unused variables. */ | |
| 1066 | − (void)cstate; | |
| 1227 | + JAS_UNUSED(cstate); | |
| 1067 | 1228 | |
| 1068 | 1229 | ppt->data = 0; |
| 1069 | 1230 | |
| @@ -1095,8 +1256,7 @@ static int jpc_ppt_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 25 unmodified lines | ||
| 1095 | 1256 | { |
| 1096 | 1257 | jpc_ppt_t *ppt = &ms->parms.ppt; |
| 1097 | 1258 | |
| 1098 | − /* Eliminate compiler warning about unused variable. */ | |
| 1099 | − (void)cstate; | |
| 1259 | + JAS_UNUSED(cstate); | |
| 1100 | 1260 | |
| 1101 | 1261 | if (jpc_putuint8(out, ppt->ind)) { |
| 1102 | 1262 | return -1; |
| @@ -1107,6 +1267,17 @@ static int jpc_ppt_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 4 unmodified lines | ||
| 1107 | 1267 | return 0; |
| 1108 | 1268 | } |
| 1109 | 1269 | |
| 1270 | +static int jpc_ppt_dumpparms(jpc_ms_t *ms) | |
| 1271 | +{ | |
| 1272 | + jpc_ppt_t *ppt = &ms->parms.ppt; | |
| 1273 | + jas_logprintf("ind=%d; len = %"PRIuFAST32";\n", ppt->ind, ppt->len); | |
| 1274 | + if (ppt->len > 0) { | |
| 1275 | + jas_logprintf("data =\n"); | |
| 1276 | + jas_logmemdump(ppt->data, ppt->len); | |
| 1277 | + } | |
| 1278 | + return 0; | |
| 1279 | +} | |
| 1280 | + | |
| 1110 | 1281 | /******************************************************************************\ |
| 1111 | 1282 | * POC marker segment operations. |
| 1112 | 1283 | \******************************************************************************/ |
| @@ -1197,6 +1368,23 @@ static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 84 unmodified lines | ||
| 1197 | 1368 | return 0; |
| 1198 | 1369 | } |
| 1199 | 1370 | |
| 1371 | +static int jpc_poc_dumpparms(jpc_ms_t *ms) | |
| 1372 | +{ | |
| 1373 | + jpc_poc_t *poc = &ms->parms.poc; | |
| 1374 | + jpc_pocpchg_t *pchg; | |
| 1375 | + int pchgno; | |
| 1376 | + for (pchgno = 0, pchg = poc->pchgs; pchgno < poc->numpchgs; | |
| 1377 | + ++pchgno, ++pchg) { | |
| 1378 | + jas_logprintf("po[%d] = %d; ", pchgno, pchg->prgord); | |
| 1379 | + jas_logprintf("cs[%d] = %"PRIuFAST16"; ce[%d] = %"PRIuFAST16"; ", | |
| 1380 | + pchgno, pchg->compnostart, pchgno, pchg->compnoend); | |
| 1381 | + jas_logprintf("rs[%d] = %d; re[%d] = %d; ", | |
| 1382 | + pchgno, pchg->rlvlnostart, pchgno, pchg->rlvlnoend); | |
| 1383 | + jas_logprintf("le[%d] = %"PRIuFAST16"\n", pchgno, pchg->lyrnoend); | |
| 1384 | + } | |
| 1385 | + return 0; | |
| 1386 | +} | |
| 1387 | + | |
| 1200 | 1388 | /******************************************************************************\ |
| 1201 | 1389 | * CRG marker segment operations. |
| 1202 | 1390 | \******************************************************************************/ |
| @@ -1235,8 +1423,7 @@ static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 32 unmodified lines | ||
| 1235 | 1423 | int compno; |
| 1236 | 1424 | jpc_crgcomp_t *comp; |
| 1237 | 1425 | |
| 1238 | − /* Eliminate compiler warning about unused variables. */ | |
| 1239 | − (void)cstate; | |
| 1426 | + JAS_UNUSED(cstate); | |
| 1240 | 1427 | |
| 1241 | 1428 | for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno, |
| 1242 | 1429 | ++comp) { |
| @@ -1248,6 +1435,19 @@ static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 5 unmodified lines | ||
| 1248 | 1435 | return 0; |
| 1249 | 1436 | } |
| 1250 | 1437 | |
| 1438 | +static int jpc_crg_dumpparms(jpc_ms_t *ms) | |
| 1439 | +{ | |
| 1440 | + jpc_crg_t *crg = &ms->parms.crg; | |
| 1441 | + int compno; | |
| 1442 | + jpc_crgcomp_t *comp; | |
| 1443 | + for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno, | |
| 1444 | + ++comp) { | |
| 1445 | + jas_logprintf("hoff[%d] = %"PRIuFAST16"; voff[%d] = %"PRIuFAST16"\n", | |
| 1446 | + compno, comp->hoff, compno, comp->voff); | |
| 1447 | + } | |
| 1448 | + return 0; | |
| 1449 | +} | |
| 1450 | + | |
| 1251 | 1451 | /******************************************************************************\ |
| 1252 | 1452 | * Operations for COM marker segment. |
| 1253 | 1453 | \******************************************************************************/ |
| @@ -1264,8 +1464,7 @@ static int jpc_com_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 10 unmodified lines | ||
| 1264 | 1464 | { |
| 1265 | 1465 | jpc_com_t *com = &ms->parms.com; |
| 1266 | 1466 | |
| 1267 | − /* Eliminate compiler warning about unused variables. */ | |
| 1268 | − (void)cstate; | |
| 1467 | + JAS_UNUSED(cstate); | |
| 1269 | 1468 | |
| 1270 | 1469 | if (jpc_getuint16(in, &com->regid)) { |
| 1271 | 1470 | return -1; |
| @@ -1288,8 +1487,7 @@ static int jpc_com_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 16 unmodified lines | ||
| 1288 | 1487 | { |
| 1289 | 1488 | jpc_com_t *com = &ms->parms.com; |
| 1290 | 1489 | |
| 1291 | − /* Eliminate compiler warning about unused variables. */ | |
| 1292 | − (void)cstate; | |
| 1490 | + JAS_UNUSED(cstate); | |
| 1293 | 1491 | |
| 1294 | 1492 | if (jpc_putuint16(out, com->regid)) { |
| 1295 | 1493 | return -1; |
| @@ -1300,6 +1498,29 @@ static int jpc_com_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 4 unmodified lines | ||
| 1300 | 1498 | return 0; |
| 1301 | 1499 | } |
| 1302 | 1500 | |
| 1501 | +static int jpc_com_dumpparms(jpc_ms_t *ms) | |
| 1502 | +{ | |
| 1503 | + jpc_com_t *com = &ms->parms.com; | |
| 1504 | + unsigned int i; | |
| 1505 | + int printable; | |
| 1506 | + jas_logprintf("regid = %"PRIuFAST16";\n", com->regid); | |
| 1507 | + printable = 1; | |
| 1508 | + for (i = 0; i < com->len; ++i) { | |
| 1509 | + if (!isprint(com->data[i])) { | |
| 1510 | + printable = 0; | |
| 1511 | + break; | |
| 1512 | + } | |
| 1513 | + } | |
| 1514 | + if (printable) { | |
| 1515 | + jas_logprintf("data = %.*s\n", com->len, com->data); | |
| 1516 | +/* FIXME: print the data | |
| 1517 | + fwrite(com->data, sizeof(char), com->len, out); | |
| 1518 | + jas_logprintf("\n"); | |
| 1519 | +*/ | |
| 1520 | + } | |
| 1521 | + return 0; | |
| 1522 | +} | |
| 1523 | + | |
| 1303 | 1524 | /******************************************************************************\ |
| 1304 | 1525 | * Operations for unknown types of marker segments. |
| 1305 | 1526 | \******************************************************************************/ |
| @@ -1318,8 +1539,7 @@ static int jpc_unk_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 12 unmodified lines | ||
| 1318 | 1539 | |
| 1319 | 1540 | unk->data = 0; |
| 1320 | 1541 | |
| 1321 | − /* Eliminate compiler warning about unused variables. */ | |
| 1322 | − (void)cstate; | |
| 1542 | + JAS_UNUSED(cstate); | |
| 1323 | 1543 | |
| 1324 | 1544 | if (ms->len > 0) { |
| 1325 | 1545 | if (!(unk->data = jas_alloc2(ms->len, sizeof(unsigned char)))) { |
| @@ -1339,16 +1559,25 @@ static int jpc_unk_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 13 unmodified lines | ||
| 1339 | 1559 | |
| 1340 | 1560 | static int jpc_unk_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out) |
| 1341 | 1561 | { |
| 1342 | − /* Eliminate compiler warning about unused variables. */ | |
| 1343 | − USED(cstate); | |
| 1344 | − USED(ms); | |
| 1345 | − USED(out); | |
| 1562 | + JAS_UNUSED(cstate); | |
| 1563 | + JAS_UNUSED(ms); | |
| 1564 | + JAS_UNUSED(out); | |
| 1346 | 1565 | |
| 1347 | 1566 | /* If this function is called, we are trying to write an unsupported |
| 1348 | 1567 | type of marker segment. Return with an error indication. */ |
| 1349 | 1568 | return -1; |
| 1350 | 1569 | } |
| 1351 | 1570 | |
| 1571 | +static int jpc_unk_dumpparms(jpc_ms_t *ms) | |
| 1572 | +{ | |
| 1573 | + unsigned int i; | |
| 1574 | + jpc_unk_t *unk = &ms->parms.unk; | |
| 1575 | + for (i = 0; i < unk->len; ++i) { | |
| 1576 | + jas_logprintf("%02x ", unk->data[i]); | |
| 1577 | + } | |
| 1578 | + return 0; | |
| 1579 | +} | |
| 1580 | + | |
| 1352 | 1581 | /******************************************************************************\ |
| 1353 | 1582 | * Primitive I/O operations. |
| 1354 | 1583 | \******************************************************************************/ |
| @@ -1430,6 +1659,12 @@ int jpc_validate(jas_stream_t *in) · 75 unmodified lines | ||
| 1430 | 1659 | { |
| 1431 | 1660 | unsigned char buf[2]; |
| 1432 | 1661 | |
| 1662 | + /* | |
| 1663 | + Note: The validation operation does not require the initialization of the | |
| 1664 | + JPC codec. So, jpc_init is not called here. | |
| 1665 | + jpc_init(); | |
| 1666 | + */ | |
| 1667 | + | |
| 1433 | 1668 | assert(JAS_STREAM_MAXPUTBACK >= 2); |
| 1434 | 1669 | |
| 1435 | 1670 | if (jas_stream_peek(in, buf, sizeof(buf)) != sizeof(buf)) |
| @@ -726,6 +726,9 @@ typedef struct jpc_msops_s { · 725 unmodified lines | ||
| 726 | 726 | /* Put the marker segment parameters to a stream. */ |
| 727 | 727 | int (*putparms)(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); |
| 728 | 728 | |
| 729 | + /* Dump the marker segment parameters (for debugging). */ | |
| 730 | + int (*dumpparms)(jpc_ms_t *ms); | |
| 731 | + | |
| 729 | 732 | } jpc_msops_t; |
| 730 | 733 | |
| 731 | 734 | /******************************************************************************\ |
| @@ -771,6 +774,9 @@ int jpc_getdata(jas_stream_t *in, jas_stream_t *out, long n); · 39 unmodified lines | ||
| 771 | 774 | /* Copy code stream data from one stream to another. */ |
| 772 | 775 | int jpc_putdata(jas_stream_t *out, jas_stream_t *in, long n); |
| 773 | 776 | |
| 777 | +/* Dump a marker segment (for debugging). */ | |
| 778 | +void jpc_ms_dump(jpc_ms_t *ms); | |
| 779 | + | |
| 774 | 780 | /* Read a 8-bit unsigned integer from a stream. */ |
| 775 | 781 | int jpc_getuint8(jas_stream_t *in, uint_fast8_t *val); |
| 776 | 782 | |
| @@ -78,8 +78,10 @@ · 77 unmodified lines | ||
| 78 | 78 | #include "jpc_t1dec.h" |
| 79 | 79 | #include "jpc_math.h" |
| 80 | 80 | |
| 81 | +#include "jasper/jas_init.h" | |
| 81 | 82 | #include "jasper/jas_types.h" |
| 82 | 83 | #include "jasper/jas_math.h" |
| 84 | +#include "jasper/jas_tvp.h" | |
| 83 | 85 | #include "jasper/jas_malloc.h" |
| 84 | 86 | #include "jasper/jas_debug.h" |
| 85 | 87 | |
| @@ -131,6 +133,8 @@ typedef struct { · 45 unmodified lines | ||
| 131 | 133 | * Local function prototypes. |
| 132 | 134 | \******************************************************************************/ |
| 133 | 135 | |
| 136 | +static int jpc_dec_dump(const jpc_dec_t *dec); | |
| 137 | + | |
| 134 | 138 | static jpc_ppxstab_t *jpc_ppxstab_create(void); |
| 135 | 139 | static void jpc_ppxstab_destroy(jpc_ppxstab_t *tab); |
| 136 | 140 | static int jpc_ppxstab_grow(jpc_ppxstab_t *tab, unsigned maxents); |
| @@ -197,6 +201,12 @@ static void jpc_dec_opts_destroy(jpc_dec_importopts_t *opts); · 60 unmodified lines | ||
| 197 | 201 | |
| 198 | 202 | static const jpc_dec_mstabent_t *jpc_dec_mstab_lookup(uint_fast16_t id); |
| 199 | 203 | |
| 204 | +static void jpc_rlvl_init(jpc_dec_rlvl_t *rlvl); | |
| 205 | +static void jpc_band_init(jpc_dec_band_t *band); | |
| 206 | +static void jpc_prc_init(jpc_dec_prc_t *prc); | |
| 207 | +static void jpc_cblk_init(jpc_dec_cblk_t *cblk); | |
| 208 | +static void jpc_seglist_init(jpc_dec_seglist_t *seglist); | |
| 209 | + | |
| 200 | 210 | /******************************************************************************\ |
| 201 | 211 | * Global data. |
| 202 | 212 | \******************************************************************************/ |
| @@ -236,13 +246,14 @@ jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr) · 33 unmodified lines | ||
| 236 | 246 | |
| 237 | 247 | dec = 0; |
| 238 | 248 | |
| 239 | − JAS_DBGLOG(100, ("jpc_decode(%p, \"%s\")\n", in, optstr)); | |
| 249 | + JAS_LOGDEBUGF(100, "jpc_decode(%p, \"%s\")\n", in, optstr); | |
| 240 | 250 | |
| 241 | 251 | if (!(opts = jpc_dec_opts_create(optstr))) { |
| 242 | 252 | goto error; |
| 243 | 253 | } |
| 244 | 254 | |
| 245 | − jpc_initluts(); | |
| 255 | + jpc_init(); | |
| 256 | + //jpc_initluts(); | |
| 246 | 257 | |
| 247 | 258 | if (!(dec = jpc_dec_create(opts, in))) { |
| 248 | 259 | goto error; |
| @@ -290,11 +301,27 @@ error: · 41 unmodified lines | ||
| 290 | 301 | return 0; |
| 291 | 302 | } |
| 292 | 303 | |
| 304 | +typedef enum { | |
| 305 | + OPT_MAXLYRS, | |
| 306 | + OPT_MAXPKTS, | |
| 307 | + OPT_MAXSAMPLES, | |
| 308 | + OPT_DEBUG | |
| 309 | +} optid_t; | |
| 310 | + | |
| 311 | +static const jas_taginfo_t decopts[] = { | |
| 312 | + {OPT_MAXLYRS, "maxlyrs"}, | |
| 313 | + {OPT_MAXPKTS, "maxpkts"}, | |
| 314 | + {OPT_MAXSAMPLES, "max_samples"}, | |
| 315 | + {OPT_DEBUG, "debug"}, | |
| 316 | + {-1, 0} | |
| 317 | +}; | |
| 318 | + | |
| 293 | 319 | static jpc_dec_importopts_t *jpc_dec_opts_create(const char *optstr) |
| 294 | 320 | { |
| 295 | 321 | jpc_dec_importopts_t *opts; |
| 322 | + jas_tvparser_t *tvp; | |
| 323 | + | |
| 296 | 324 | |
| 297 | − USED(optstr); | |
| 298 | 325 | if (!(opts = jas_malloc(sizeof(jpc_dec_importopts_t)))) { |
| 299 | 326 | goto error; |
| 300 | 327 | } |
| @@ -302,7 +329,35 @@ static jpc_dec_importopts_t *jpc_dec_opts_create(const char *optstr) · 1 unmodified line | ||
| 302 | 329 | opts->debug = 0; |
| 303 | 330 | opts->maxlyrs = JPC_MAXLYRS; |
| 304 | 331 | opts->maxpkts = -1; |
| 305 | − opts->max_samples = JAS_DEC_DEFAULT_MAX_SAMPLES; | |
| 332 | + opts->max_samples = jas_get_dec_default_max_samples(); | |
| 333 | + | |
| 334 | + if (!(tvp = jas_tvparser_create(optstr ? optstr : ""))) { | |
| 335 | + goto error; | |
| 336 | + } | |
| 337 | + | |
| 338 | + while (!jas_tvparser_next(tvp)) { | |
| 339 | + switch (jas_taginfo_nonull(jas_taginfos_lookup(decopts, | |
| 340 | + jas_tvparser_gettag(tvp)))->id) { | |
| 341 | + case OPT_MAXLYRS: | |
| 342 | + opts->maxlyrs = atoi(jas_tvparser_getval(tvp)); | |
| 343 | + break; | |
| 344 | + case OPT_DEBUG: | |
| 345 | + opts->debug = atoi(jas_tvparser_getval(tvp)); | |
| 346 | + break; | |
| 347 | + case OPT_MAXPKTS: | |
| 348 | + opts->maxpkts = atoi(jas_tvparser_getval(tvp)); | |
| 349 | + break; | |
| 350 | + case OPT_MAXSAMPLES: | |
| 351 | + opts->max_samples = strtoull(jas_tvparser_getval(tvp), 0, 10); | |
| 352 | + break; | |
| 353 | + default: | |
| 354 | + jas_logwarnf("warning: ignoring invalid option %s\n", | |
| 355 | + jas_tvparser_gettag(tvp)); | |
| 356 | + break; | |
| 357 | + } | |
| 358 | + } | |
| 359 | + | |
| 360 | + jas_tvparser_destroy(tvp); | |
| 306 | 361 | |
| 307 | 362 | return opts; |
| 308 | 363 | |
| @@ -353,7 +408,7 @@ static int jpc_dec_decode(jpc_dec_t *dec) · 44 unmodified lines | ||
| 353 | 408 | |
| 354 | 409 | /* Get the next marker segment in the code stream. */ |
| 355 | 410 | if (!(ms = jpc_getms(dec->in, cstate))) { |
| 356 | − jas_eprintf("cannot get marker segment\n"); | |
| 411 | + jas_logerrorf("cannot get marker segment\n"); | |
| 357 | 412 | return -1; |
| 358 | 413 | } |
| 359 | 414 | |
| @@ -363,7 +418,7 @@ static int jpc_dec_decode(jpc_dec_t *dec) · 3 unmodified lines | ||
| 363 | 418 | /* Ensure that this type of marker segment is permitted |
| 364 | 419 | at this point in the code stream. */ |
| 365 | 420 | if (!(dec->state & mstabent->validstates)) { |
| 366 | − jas_eprintf("unexpected marker segment type\n"); | |
| 421 | + jas_logerrorf("unexpected marker segment type\n"); | |
| 367 | 422 | jpc_ms_destroy(ms); |
| 368 | 423 | return -1; |
| 369 | 424 | } |
| @@ -407,15 +462,14 @@ static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms) · 37 unmodified lines | ||
| 407 | 462 | cmpt->vsubstep = crg->comps[cmptno].voff; |
| 408 | 463 | */ |
| 409 | 464 | /* suppress -Wunused-but-set-variable */ |
| 410 | − USED(crg); | |
| 465 | + JAS_UNUSED(crg); | |
| 411 | 466 | } |
| 412 | 467 | return 0; |
| 413 | 468 | } |
| 414 | 469 | |
| 415 | 470 | static int jpc_dec_process_soc(jpc_dec_t *dec, jpc_ms_t *ms) |
| 416 | 471 | { |
| 417 | − /* Eliminate warnings about unused variables. */ | |
| 418 | − (void)ms; | |
| 472 | + JAS_UNUSED(ms); | |
| 419 | 473 | |
| 420 | 474 | /* We should expect to encounter a SIZ marker segment next. */ |
| 421 | 475 | dec->state = JPC_MHSIZ; |
| @@ -478,7 +532,7 @@ static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms) · 56 unmodified lines | ||
| 478 | 532 | } |
| 479 | 533 | |
| 480 | 534 | if (sot->tileno >= dec->numtiles) { |
| 481 | − jas_eprintf("invalid tile number in SOT marker segment\n"); | |
| 535 | + jas_logerrorf("invalid tile number in SOT marker segment\n"); | |
| 482 | 536 | return -1; |
| 483 | 537 | } |
| 484 | 538 | /* Set the current tile. */ |
| @@ -529,8 +583,7 @@ static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms) · 44 unmodified lines | ||
| 529 | 583 | jpc_dec_tile_t *tile; |
| 530 | 584 | int pos; |
| 531 | 585 | |
| 532 | − /* Eliminate compiler warnings about unused variables. */ | |
| 533 | − (void)ms; | |
| 586 | + JAS_UNUSED(ms); | |
| 534 | 587 | |
| 535 | 588 | if (!(tile = dec->curtile)) { |
| 536 | 589 | return -1; |
| @@ -564,18 +617,22 @@ static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms) · 27 unmodified lines | ||
| 564 | 617 | } |
| 565 | 618 | } |
| 566 | 619 | pos = jas_stream_tell(tile->pkthdrstream); |
| 567 | − jas_stream_seek(tile->pkthdrstream, 0, 2); | |
| 620 | + jas_stream_seek(tile->pkthdrstream, 0, SEEK_END); | |
| 568 | 621 | if (jpc_pptstabwrite(tile->pkthdrstream, tile->pptstab)) { |
| 569 | 622 | return -1; |
| 570 | 623 | } |
| 571 | − jas_stream_seek(tile->pkthdrstream, pos, 0); | |
| 624 | + jas_stream_seek(tile->pkthdrstream, pos, SEEK_SET); | |
| 572 | 625 | jpc_ppxstab_destroy(tile->pptstab); |
| 573 | 626 | tile->pptstab = 0; |
| 574 | 627 | } |
| 575 | 628 | |
| 629 | + if (jas_get_debug_level() >= 10) { | |
| 630 | + jpc_dec_dump(dec); | |
| 631 | + } | |
| 632 | + | |
| 576 | 633 | if (jpc_dec_decodepkts(dec, (tile->pkthdrstream) ? tile->pkthdrstream : |
| 577 | 634 | dec->in, dec->in)) { |
| 578 | − jas_eprintf("jpc_dec_decodepkts failed\n"); | |
| 635 | + jas_logerrorf("jpc_dec_decodepkts failed\n"); | |
| 579 | 636 | return -1; |
| 580 | 637 | } |
| 581 | 638 | |
| @@ -586,17 +643,17 @@ static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms) · 4 unmodified lines | ||
| 586 | 643 | curoff = jas_stream_getrwcount(dec->in); |
| 587 | 644 | if (curoff < dec->curtileendoff) { |
| 588 | 645 | n = dec->curtileendoff - curoff; |
| 589 | − jas_eprintf("warning: ignoring trailing garbage (%lu bytes)\n", | |
| 646 | + jas_logwarnf("warning: ignoring trailing garbage (%lu bytes)\n", | |
| 590 | 647 | (unsigned long) n); |
| 591 | 648 | |
| 592 | 649 | while (n-- > 0) { |
| 593 | 650 | if (jas_stream_getc(dec->in) == EOF) { |
| 594 | − jas_eprintf("read error\n"); | |
| 651 | + jas_logerrorf("read error\n"); | |
| 595 | 652 | return -1; |
| 596 | 653 | } |
| 597 | 654 | } |
| 598 | 655 | } else if (curoff > dec->curtileendoff) { |
| 599 | − jas_eprintf("warning: not enough tile data (%lu bytes)\n", | |
| 656 | + jas_logwarnf("warning: not enough tile data (%lu bytes)\n", | |
| 600 | 657 | (unsigned long) curoff - dec->curtileendoff); |
| 601 | 658 | } |
| 602 | 659 | |
| @@ -653,6 +710,11 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 50 unmodified lines | ||
| 653 | 710 | uint_fast32_t tmpyend; |
| 654 | 711 | jpc_tsfb_band_t bnds[JPC_MAXBANDS]; |
| 655 | 712 | jpc_pchg_t *pchg; |
| 713 | + int retval = 0; | |
| 714 | + | |
| 715 | + if (jas_get_debug_level() >= 1) { | |
| 716 | + jas_logerrorf("jpc_dec_tileinit called\n"); | |
| 717 | + } | |
| 656 | 718 | |
| 657 | 719 | const jpc_dec_cp_t *cp = tile->cp; |
| 658 | 720 | tile->realmode = 0; |
| @@ -665,27 +727,37 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 6 unmodified lines | ||
| 665 | 727 | for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno < |
| 666 | 728 | dec->numcomps; ++compno, ++tcomp, ++cmpt) { |
| 667 | 729 | const jpc_dec_ccp_t *ccp = &tile->cp->ccps[compno]; |
| 730 | + if (jas_get_debug_level() >= 10) { | |
| 731 | + jas_logdebugf(10, "[compno %d]\n", compno); | |
| 732 | + } | |
| 668 | 733 | if (ccp->qmfbid == JPC_COX_INS) { |
| 669 | 734 | tile->realmode = 1; |
| 670 | 735 | } |
| 671 | 736 | tcomp->numrlvls = ccp->numrlvls; |
| 672 | 737 | if (!(tcomp->rlvls = jas_alloc2(tcomp->numrlvls, |
| 673 | 738 | sizeof(jpc_dec_rlvl_t)))) { |
| 674 | − return -1; | |
| 739 | + retval = -1; | |
| 740 | + goto done; | |
| 675 | 741 | } |
| 676 | 742 | for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls; |
| 677 | 743 | ++rlvlno, ++rlvl) { |
| 744 | +#if 0 | |
| 678 | 745 | rlvl->bands = NULL; |
| 746 | +#else | |
| 747 | + jpc_rlvl_init(rlvl); | |
| 748 | +#endif | |
| 679 | 749 | } |
| 680 | 750 | if (!(tcomp->data = jas_seq2d_create(JPC_CEILDIV(tile->xstart, |
| 681 | 751 | cmpt->hstep), JPC_CEILDIV(tile->ystart, cmpt->vstep), |
| 682 | 752 | JPC_CEILDIV(tile->xend, cmpt->hstep), JPC_CEILDIV(tile->yend, |
| 683 | 753 | cmpt->vstep)))) { |
| 684 | − return -1; | |
| 754 | + retval = -1; | |
| 755 | + goto done; | |
| 685 | 756 | } |
| 686 | 757 | if (!(tcomp->tsfb = jpc_cod_gettsfb(ccp->qmfbid, |
| 687 | 758 | tcomp->numrlvls - 1))) { |
| 688 | − return -1; | |
| 759 | + retval = -1; | |
| 760 | + goto done; | |
| 689 | 761 | } |
| 690 | 762 | { |
| 691 | 763 | jpc_tsfb_getbands(tcomp->tsfb, jas_seq2d_xstart(tcomp->data), |
| @@ -719,6 +791,16 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 27 unmodified lines | ||
| 719 | 791 | rlvl->prcheightexpn; |
| 720 | 792 | rlvl->numprcs = rlvl->numhprcs * rlvl->numvprcs; |
| 721 | 793 | |
| 794 | + if (jas_get_debug_level() >= 10) { | |
| 795 | + jas_logdebugf(10, | |
| 796 | + "[compno %d rlvlno %d]: xstart %d ystart %d " | |
| 797 | + "xend %d yend %d prcwidthexpn %d prcheightexpn %d " | |
| 798 | + "numhprcs %d numvprcs %d numprcs %d\n", | |
| 799 | + compno, rlvlno, rlvl->xstart, rlvl->ystart, rlvl->xend, | |
| 800 | + rlvl->yend, rlvl->prcwidthexpn, rlvl->prcheightexpn, | |
| 801 | + rlvl->numhprcs, rlvl->numvprcs, rlvl->numprcs); | |
| 802 | + } | |
| 803 | + | |
| 722 | 804 | if (rlvl->numprcs >= 64 * 1024) { |
| 723 | 805 | /* avoid out-of-memory due to |
| 724 | 806 | malicious file; this limit is |
| @@ -747,7 +829,8 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 22 unmodified lines | ||
| 747 | 829 | if (rlvl->prcwidthexpn < 1 || rlvl->prcheightexpn < 1) { |
| 748 | 830 | /* the control block width/height offset |
| 749 | 831 | exponent must not be negative */ |
| 750 | − return -1; | |
| 832 | + retval = -1; | |
| 833 | + goto done; | |
| 751 | 834 | } |
| 752 | 835 | rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1; |
| 753 | 836 | rlvl->cbgheightexpn = rlvl->prcheightexpn - 1; |
| @@ -760,15 +843,26 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 6 unmodified lines | ||
| 760 | 843 | rlvl->numbands = (!rlvlno) ? 1 : 3; |
| 761 | 844 | if (!(rlvl->bands = jas_alloc2(rlvl->numbands, |
| 762 | 845 | sizeof(jpc_dec_band_t)))) { |
| 763 | − return -1; | |
| 846 | + retval = -1; | |
| 847 | + goto done; | |
| 764 | 848 | } |
| 765 | 849 | unsigned bandno; |
| 850 | +#if 1 | |
| 851 | + for (bandno = 0, band = rlvl->bands; | |
| 852 | + bandno < rlvl->numbands; ++bandno, ++band) { | |
| 853 | + jpc_band_init(band); | |
| 854 | + } | |
| 855 | +#endif | |
| 766 | 856 | for (bandno = 0, band = rlvl->bands; |
| 767 | 857 | bandno < rlvl->numbands; ++bandno, ++band) { |
| 768 | 858 | unsigned bndno = (!rlvlno) ? 0 : (3 * (rlvlno - 1) + |
| 769 | 859 | bandno + 1); |
| 770 | 860 | const jpc_tsfb_band_t *bnd = &bnds[bndno]; |
| 771 | 861 | |
| 862 | + if (jas_get_debug_level() >= 10) { | |
| 863 | + jas_logdebugf(10, "[compno %d rlvlno %d bandno %d]\n", compno, rlvlno, bandno); | |
| 864 | + } | |
| 865 | + | |
| 772 | 866 | band->orient = bnd->orient; |
| 773 | 867 | band->stepsize = ccp->stepsizes[bndno]; |
| 774 | 868 | band->analgain = JPC_NOMINALGAIN(ccp->qmfbid, |
| @@ -785,11 +879,13 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 10 unmodified lines | ||
| 785 | 879 | continue; |
| 786 | 880 | } |
| 787 | 881 | if (!(band->data = jas_seq2d_create(0, 0, 0, 0))) { |
| 788 | − return -1; | |
| 882 | + retval = -1; | |
| 883 | + goto done; | |
| 789 | 884 | } |
| 790 | 885 | if (jas_seq2d_bindsub(band->data, tcomp->data, bnd->locxstart, |
| 791 | 886 | bnd->locystart, bnd->locxend, bnd->locyend)) { |
| 792 | − return -1; | |
| 887 | + retval = -1; | |
| 888 | + goto done; | |
| 793 | 889 | } |
| 794 | 890 | jas_seq2d_setshift(band->data, bnd->xstart, bnd->ystart); |
| 795 | 891 | |
| @@ -797,14 +893,25 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 1 unmodified line | ||
| 797 | 893 | |
| 798 | 894 | if (!(band->prcs = jas_alloc2(rlvl->numprcs, |
| 799 | 895 | sizeof(jpc_dec_prc_t)))) { |
| 800 | − return -1; | |
| 896 | + retval = -1; | |
| 897 | + goto done; | |
| 801 | 898 | } |
| 802 | 899 | |
| 803 | 900 | /************************************************/ |
| 804 | 901 | cbgxstart = tlcbgxstart; |
| 805 | 902 | cbgystart = tlcbgystart; |
| 806 | − unsigned prccnt; for (prccnt = rlvl->numprcs, prc = band->prcs; | |
| 903 | + unsigned prccnt; | |
| 904 | +#if 1 | |
| 905 | + for (prccnt = rlvl->numprcs, prc = band->prcs; | |
| 807 | 906 | prccnt > 0; --prccnt, ++prc) { |
| 907 | + jpc_prc_init(prc); | |
| 908 | + } | |
| 909 | +#endif | |
| 910 | + for (prccnt = rlvl->numprcs, prc = band->prcs; | |
| 911 | + prccnt > 0; --prccnt, ++prc) { | |
| 912 | + if (jas_get_debug_level() >= 10) { | |
| 913 | + jas_logdebugf(10, "[compno %d rlvlno %d bandno %d prccnt %d]\n", compno, rlvlno, bandno, prccnt); | |
| 914 | + } | |
| 808 | 915 | cbgxend = cbgxstart + (1 << rlvl->cbgwidthexpn); |
| 809 | 916 | cbgyend = cbgystart + (1 << rlvl->cbgheightexpn); |
| 810 | 917 | prc->xstart = JAS_MAX(cbgxstart, JAS_CAST(uint_fast32_t, |
| @@ -831,24 +938,43 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 20 unmodified lines | ||
| 831 | 938 | prc->numcblks = prc->numhcblks * prc->numvcblks; |
| 832 | 939 | assert(prc->numcblks > 0); |
| 833 | 940 | |
| 941 | + if (jas_get_debug_level() >= 10) { | |
| 942 | + jas_logdebugf(10, "[compno %d rlvlno %d bandno %d prccnt %d]: " | |
| 943 | + "numhcblks %d numvcblks %d numcblks %d\n", | |
| 944 | + compno, rlvlno, bandno, prccnt, prc->numhcblks, prc->numvcblks, | |
| 945 | + prc->numcblks); | |
| 946 | + } | |
| 947 | + | |
| 834 | 948 | if (!(prc->incltagtree = jpc_tagtree_create( |
| 835 | 949 | prc->numhcblks, prc->numvcblks))) { |
| 836 | − return -1; | |
| 950 | + retval = -1; | |
| 951 | + goto done; | |
| 837 | 952 | } |
| 838 | 953 | if (!(prc->numimsbstagtree = jpc_tagtree_create( |
| 839 | 954 | prc->numhcblks, prc->numvcblks))) { |
| 840 | − return -1; | |
| 955 | + retval = -1; | |
| 956 | + goto done; | |
| 841 | 957 | } |
| 842 | 958 | if (!(prc->cblks = jas_alloc2(prc->numcblks, |
| 843 | 959 | sizeof(jpc_dec_cblk_t)))) { |
| 844 | − return -1; | |
| 960 | + retval = -1; | |
| 961 | + goto done; | |
| 845 | 962 | } |
| 846 | 963 | |
| 847 | 964 | cblkxstart = cbgxstart; |
| 848 | 965 | cblkystart = cbgystart; |
| 849 | 966 | unsigned cblkcnt; |
| 967 | +#if 1 | |
| 968 | + for (cblkcnt = prc->numcblks, cblk = prc->cblks; | |
| 969 | + cblkcnt > 0; ++cblk, --cblkcnt) { | |
| 970 | + jpc_cblk_init(cblk); | |
| 971 | + } | |
| 972 | +#endif | |
| 850 | 973 | for (cblkcnt = prc->numcblks, cblk = prc->cblks; |
| 851 | 974 | cblkcnt > 0;) { |
| 975 | + if (jas_get_debug_level() >= 10000) { | |
| 976 | + jas_logdebugf(10000, "[compno %d rlvlno %d bandno %d prcno %d cblkcnt %d]\n", compno, rlvlno, bandno, prccnt, cblkcnt); | |
| 977 | + } | |
| 852 | 978 | cblkxend = cblkxstart + (1 << rlvl->cblkwidthexpn); |
| 853 | 979 | cblkyend = cblkystart + (1 << rlvl->cblkheightexpn); |
| 854 | 980 | tmpxstart = JAS_MAX(cblkxstart, prc->xstart); |
| @@ -865,11 +991,13 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 10 unmodified lines | ||
| 865 | 991 | cblk->numlenbits = 3; |
| 866 | 992 | if (!(cblk->data = jas_seq2d_create(0, 0, 0, |
| 867 | 993 | 0))) { |
| 868 | − return -1; | |
| 994 | + retval = -1; | |
| 995 | + goto done; | |
| 869 | 996 | } |
| 870 | 997 | if (jas_seq2d_bindsub(cblk->data, band->data, |
| 871 | 998 | tmpxstart, tmpystart, tmpxend, tmpyend)) { |
| 872 | − return -1; | |
| 999 | + retval = -1; | |
| 1000 | + goto done; | |
| 873 | 1001 | } |
| 874 | 1002 | ++cblk; |
| 875 | 1003 | --cblkcnt; |
| @@ -899,7 +1027,8 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 23 unmodified lines | ||
| 899 | 1027 | } |
| 900 | 1028 | |
| 901 | 1029 | if (!(tile->pi = jpc_dec_pi_create(dec, tile))) { |
| 902 | − return -1; | |
| 1030 | + retval = -1; | |
| 1031 | + goto done; | |
| 903 | 1032 | } |
| 904 | 1033 | |
| 905 | 1034 | for (unsigned pchgno = 0; pchgno < jpc_pchglist_numpchgs(tile->cp->pchglist); |
| @@ -910,7 +1039,13 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 4 unmodified lines | ||
| 910 | 1039 | } |
| 911 | 1040 | jpc_pi_init(tile->pi); |
| 912 | 1041 | |
| 913 | − return 0; | |
| 1042 | +done: | |
| 1043 | + | |
| 1044 | + if (jas_get_debug_level() >= 1) { | |
| 1045 | + jas_logdebugf(1, "jpc_dec_tileinit returning %d\n", retval); | |
| 1046 | + } | |
| 1047 | + | |
| 1048 | + return retval; | |
| 914 | 1049 | } |
| 915 | 1050 | |
| 916 | 1051 | static int jpc_dec_tilefini(jpc_dec_t *dec, jpc_dec_tile_t *tile) |
| @@ -920,61 +1055,64 @@ static int jpc_dec_tilefini(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 3 unmodified lines | ||
| 920 | 1055 | jpc_dec_seg_t *seg; |
| 921 | 1056 | jpc_dec_cblk_t *cblk; |
| 922 | 1057 | |
| 923 | − if (tile->tcomps) { | |
| 1058 | + if (jas_get_debug_level() >= 1) { | |
| 1059 | + jas_logdebugf(1, "jpc_dec_tilefini called\n"); | |
| 1060 | + } | |
| 924 | 1061 | |
| 1062 | + if (tile->tcomps) { | |
| 925 | 1063 | unsigned compno; |
| 926 | 1064 | for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps; |
| 927 | 1065 | ++compno, ++tcomp) { |
| 928 | − const jpc_dec_rlvl_t *rlvl; | |
| 929 | − for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls; | |
| 930 | − ++rlvlno, ++rlvl) { | |
| 931 | − if (!rlvl->bands) { | |
| 932 | − continue; | |
| 933 | − } | |
| 934 | − unsigned bandno; | |
| 935 | − const jpc_dec_band_t *band; | |
| 936 | − for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; | |
| 937 | − ++bandno, ++band) { | |
| 938 | − if (band->prcs) { | |
| 939 | − unsigned prcno; | |
| 940 | − const jpc_dec_prc_t *prc; | |
| 941 | − for (prcno = 0, prc = band->prcs; prcno < | |
| 942 | − rlvl->numprcs; ++prcno, ++prc) { | |
| 943 | − if (!prc->cblks) { | |
| 944 | − continue; | |
| 945 | − } | |
| 946 | − unsigned cblkno; | |
| 947 | − for (cblkno = 0, cblk = prc->cblks; cblkno < | |
| 948 | − prc->numcblks; ++cblkno, ++cblk) { | |
| 949 | − | |
| 950 | − while (cblk->segs.head) { | |
| 951 | − seg = cblk->segs.head; | |
| 952 | − jpc_seglist_remove(&cblk->segs, seg); | |
| 953 | − jpc_seg_destroy(seg); | |
| 1066 | + if (tcomp->rlvls) { | |
| 1067 | + const jpc_dec_rlvl_t *rlvl; | |
| 1068 | + for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls; | |
| 1069 | + ++rlvlno, ++rlvl) { | |
| 1070 | + if (!rlvl->bands) { | |
| 1071 | + continue; | |
| 1072 | + } | |
| 1073 | + unsigned bandno; | |
| 1074 | + const jpc_dec_band_t *band; | |
| 1075 | + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; | |
| 1076 | + ++bandno, ++band) { | |
| 1077 | + if (band->prcs) { | |
| 1078 | + unsigned prcno; | |
| 1079 | + const jpc_dec_prc_t *prc; | |
| 1080 | + for (prcno = 0, prc = band->prcs; prcno < | |
| 1081 | + rlvl->numprcs; ++prcno, ++prc) { | |
| 1082 | + if (prc->cblks) { | |
| 1083 | + unsigned cblkno; | |
| 1084 | + for (cblkno = 0, cblk = prc->cblks; cblkno < | |
| 1085 | + prc->numcblks; ++cblkno, ++cblk) { | |
| 1086 | + while (cblk->segs.head) { | |
| 1087 | + seg = cblk->segs.head; | |
| 1088 | + jpc_seglist_remove(&cblk->segs, seg); | |
| 1089 | + jpc_seg_destroy(seg); | |
| 1090 | + } | |
| 1091 | + if (cblk->data) { | |
| 1092 | + jas_matrix_destroy(cblk->data); | |
| 1093 | + } | |
| 1094 | + } | |
| 1095 | + jas_free(prc->cblks); | |
| 1096 | + } | |
| 1097 | + if (prc->incltagtree) { | |
| 1098 | + jpc_tagtree_destroy(prc->incltagtree); | |
| 1099 | + } | |
| 1100 | + if (prc->numimsbstagtree) { | |
| 1101 | + jpc_tagtree_destroy(prc->numimsbstagtree); | |
| 954 | 1102 | } |
| 955 | − jas_matrix_destroy(cblk->data); | |
| 956 | − } | |
| 957 | − if (prc->incltagtree) { | |
| 958 | − jpc_tagtree_destroy(prc->incltagtree); | |
| 959 | − } | |
| 960 | − if (prc->numimsbstagtree) { | |
| 961 | − jpc_tagtree_destroy(prc->numimsbstagtree); | |
| 962 | − } | |
| 963 | − if (prc->cblks) { | |
| 964 | − jas_free(prc->cblks); | |
| 965 | 1103 | } |
| 966 | 1104 | } |
| 1105 | + if (band->data) { | |
| 1106 | + jas_matrix_destroy(band->data); | |
| 1107 | + } | |
| 1108 | + if (band->prcs) { | |
| 1109 | + jas_free(band->prcs); | |
| 1110 | + } | |
| 967 | 1111 | } |
| 968 | − if (band->data) { | |
| 969 | − jas_matrix_destroy(band->data); | |
| 970 | − } | |
| 971 | − if (band->prcs) { | |
| 972 | − jas_free(band->prcs); | |
| 1112 | + if (rlvl->bands) { | |
| 1113 | + jas_free(rlvl->bands); | |
| 973 | 1114 | } |
| 974 | 1115 | } |
| 975 | − if (rlvl->bands) { | |
| 976 | − jas_free(rlvl->bands); | |
| 977 | − } | |
| 978 | 1116 | } |
| 979 | 1117 | if (tcomp->rlvls) { |
| 980 | 1118 | jas_free(tcomp->rlvls); |
| @@ -1020,7 +1158,7 @@ static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 39 unmodified lines | ||
| 1020 | 1158 | int v; |
| 1021 | 1159 | |
| 1022 | 1160 | if (jpc_dec_decodecblks(dec, tile)) { |
| 1023 | − jas_eprintf("jpc_dec_decodecblks failed\n"); | |
| 1161 | + jas_logerrorf("jpc_dec_decodecblks failed\n"); | |
| 1024 | 1162 | return -1; |
| 1025 | 1163 | } |
| 1026 | 1164 | |
| @@ -1065,11 +1203,11 @@ static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 38 unmodified lines | ||
| 1065 | 1203 | switch (tile->cp->mctid) { |
| 1066 | 1204 | case JPC_MCT_RCT: |
| 1067 | 1205 | if (dec->numcomps < 3) { |
| 1068 | − jas_eprintf("RCT requires at least three components\n"); | |
| 1206 | + jas_logerrorf("RCT requires at least three components\n"); | |
| 1069 | 1207 | return -1; |
| 1070 | 1208 | } |
| 1071 | 1209 | if (!jas_image_cmpt_domains_same(dec->image)) { |
| 1072 | − jas_eprintf("RCT requires all components have the same domain\n"); | |
| 1210 | + jas_logerrorf("RCT requires all components have the same domain\n"); | |
| 1073 | 1211 | return -1; |
| 1074 | 1212 | } |
| 1075 | 1213 | jpc_irct(tile->tcomps[0].data, tile->tcomps[1].data, |
| @@ -1077,11 +1215,11 @@ static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 1 unmodified line | ||
| 1077 | 1215 | break; |
| 1078 | 1216 | case JPC_MCT_ICT: |
| 1079 | 1217 | if (dec->numcomps < 3) { |
| 1080 | − jas_eprintf("ICT requires at least three components\n"); | |
| 1218 | + jas_logerrorf("ICT requires at least three components\n"); | |
| 1081 | 1219 | return -1; |
| 1082 | 1220 | } |
| 1083 | 1221 | if (!jas_image_cmpt_domains_same(dec->image)) { |
| 1084 | − jas_eprintf("RCT requires all components have the same domain\n"); | |
| 1222 | + jas_logerrorf("RCT requires all components have the same domain\n"); | |
| 1085 | 1223 | return -1; |
| 1086 | 1224 | } |
| 1087 | 1225 | jpc_iict(tile->tcomps[0].data, tile->tcomps[1].data, |
| @@ -1154,7 +1292,7 @@ static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 66 unmodified lines | ||
| 1154 | 1292 | JPC_CEILDIV(dec->xstart, cmpt->hstep), tcomp->ystart - |
| 1155 | 1293 | JPC_CEILDIV(dec->ystart, cmpt->vstep), jas_matrix_numcols( |
| 1156 | 1294 | tcomp->data), jas_matrix_numrows(tcomp->data), tcomp->data)) { |
| 1157 | − jas_eprintf("write component failed\n"); | |
| 1295 | + jas_logerrorf("write component failed\n"); | |
| 1158 | 1296 | return -1; |
| 1159 | 1297 | } |
| 1160 | 1298 | } |
| @@ -1166,8 +1304,7 @@ static int jpc_dec_process_eoc(jpc_dec_t *dec, jpc_ms_t *ms) · 5 unmodified lines | ||
| 1166 | 1304 | { |
| 1167 | 1305 | jpc_dec_tile_t *tile; |
| 1168 | 1306 | |
| 1169 | − /* Eliminate compiler warnings about unused variables. */ | |
| 1170 | − (void)ms; | |
| 1307 | + JAS_UNUSED(ms); | |
| 1171 | 1308 | |
| 1172 | 1309 | unsigned tileno; |
| 1173 | 1310 | for (tileno = 0, tile = dec->tiles; tileno < dec->numtiles; ++tileno, |
| @@ -1204,14 +1341,14 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms) · 30 unmodified lines | ||
| 1204 | 1341 | size_t total_samples; |
| 1205 | 1342 | if (!jas_safe_size_mul(siz->width, siz->height, &total_samples) || |
| 1206 | 1343 | (dec->max_samples > 0 && total_samples > dec->max_samples)) { |
| 1207 | − jas_eprintf("image too large\n"); | |
| 1344 | + jas_logerrorf("image too large\n"); | |
| 1208 | 1345 | return -1; |
| 1209 | 1346 | } |
| 1210 | 1347 | |
| 1211 | 1348 | size_t tile_samples; |
| 1212 | 1349 | if (!jas_safe_size_mul(siz->tilewidth, siz->tileheight, &tile_samples) || |
| 1213 | 1350 | (dec->max_samples > 0 && tile_samples > dec->max_samples)) { |
| 1214 | − jas_eprintf("tile too large\n"); | |
| 1351 | + jas_logerrorf("tile too large\n"); | |
| 1215 | 1352 | return -1; |
| 1216 | 1353 | } |
| 1217 | 1354 | |
| @@ -1248,18 +1385,22 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms) · 30 unmodified lines | ||
| 1248 | 1385 | cmpt->hsubstep = 0; |
| 1249 | 1386 | cmpt->vsubstep = 0; |
| 1250 | 1387 | |
| 1388 | + if (!cmpt->width || !cmpt->height) { | |
| 1389 | + jas_logerrorf("image component has no samples\n"); | |
| 1390 | + return -1; | |
| 1391 | + } | |
| 1251 | 1392 | if (!jas_safe_size_mul(cmpt->width, cmpt->height, &num_samples_delta)) { |
| 1252 | − jas_eprintf("image too large\n"); | |
| 1393 | + jas_logerrorf("image too large\n"); | |
| 1253 | 1394 | return -1; |
| 1254 | 1395 | } |
| 1255 | 1396 | if (!jas_safe_size_add(num_samples, num_samples_delta, &num_samples)) { |
| 1256 | − jas_eprintf("image too large\n"); | |
| 1397 | + jas_logerrorf("image too large\n"); | |
| 1257 | 1398 | return -1; |
| 1258 | 1399 | } |
| 1259 | 1400 | } |
| 1260 | 1401 | |
| 1261 | 1402 | if (dec->max_samples > 0 && num_samples > dec->max_samples) { |
| 1262 | − jas_eprintf("maximum number of samples exceeded (%zu > %zu)\n", | |
| 1403 | + jas_logerrorf("maximum number of samples exceeded (%zu > %zu)\n", | |
| 1263 | 1404 | num_samples, dec->max_samples); |
| 1264 | 1405 | return -1; |
| 1265 | 1406 | } |
| @@ -1287,8 +1428,8 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms) · 21 unmodified lines | ||
| 1287 | 1428 | return -1; |
| 1288 | 1429 | } |
| 1289 | 1430 | dec->numtiles = size; |
| 1290 | − JAS_DBGLOG(10, ("numtiles = %d; numhtiles = %d; numvtiles = %d;\n", | |
| 1291 | − dec->numtiles, dec->numhtiles, dec->numvtiles)); | |
| 1431 | + JAS_LOGDEBUGF(10, "numtiles = %d; numhtiles = %d; numvtiles = %d;\n", | |
| 1432 | + dec->numtiles, dec->numhtiles, dec->numvtiles); | |
| 1292 | 1433 | if (!(dec->tiles = jas_alloc2(dec->numtiles, sizeof(jpc_dec_tile_t)))) { |
| 1293 | 1434 | return -1; |
| 1294 | 1435 | } |
| @@ -1377,7 +1518,7 @@ static int jpc_dec_process_coc(jpc_dec_t *dec, jpc_ms_t *ms) · 82 unmodified lines | ||
| 1377 | 1518 | jpc_dec_tile_t *tile; |
| 1378 | 1519 | |
| 1379 | 1520 | if (coc->compno >= dec->numcomps) { |
| 1380 | − jas_eprintf("invalid component number in COC marker segment\n"); | |
| 1521 | + jas_logerrorf("invalid component number in COC marker segment\n"); | |
| 1381 | 1522 | return -1; |
| 1382 | 1523 | } |
| 1383 | 1524 | switch (dec->state) { |
| @@ -1403,7 +1544,7 @@ static int jpc_dec_process_rgn(jpc_dec_t *dec, jpc_ms_t *ms) · 19 unmodified lines | ||
| 1403 | 1544 | jpc_dec_tile_t *tile; |
| 1404 | 1545 | |
| 1405 | 1546 | if (rgn->compno >= dec->numcomps) { |
| 1406 | − jas_eprintf("invalid component number in RGN marker segment\n"); | |
| 1547 | + jas_logerrorf("invalid component number in RGN marker segment\n"); | |
| 1407 | 1548 | return -1; |
| 1408 | 1549 | } |
| 1409 | 1550 | switch (dec->state) { |
| @@ -1452,7 +1593,7 @@ static int jpc_dec_process_qcc(jpc_dec_t *dec, jpc_ms_t *ms) · 42 unmodified lines | ||
| 1452 | 1593 | jpc_dec_tile_t *tile; |
| 1453 | 1594 | |
| 1454 | 1595 | if (qcc->compno >= dec->numcomps) { |
| 1455 | − jas_eprintf("invalid component number in QCC marker segment\n"); | |
| 1596 | + jas_logerrorf("invalid component number in QCC marker segment\n"); | |
| 1456 | 1597 | return -1; |
| 1457 | 1598 | } |
| 1458 | 1599 | switch (dec->state) { |
| @@ -1551,19 +1692,17 @@ static int jpc_dec_process_ppt(jpc_dec_t *dec, jpc_ms_t *ms) · 92 unmodified lines | ||
| 1551 | 1692 | |
| 1552 | 1693 | static int jpc_dec_process_com(jpc_dec_t *dec, jpc_ms_t *ms) |
| 1553 | 1694 | { |
| 1554 | − /* Eliminate compiler warnings about unused variables. */ | |
| 1555 | − USED(dec); | |
| 1556 | − USED(ms); | |
| 1695 | + JAS_UNUSED(dec); | |
| 1696 | + JAS_UNUSED(ms); | |
| 1557 | 1697 | |
| 1558 | 1698 | return 0; |
| 1559 | 1699 | } |
| 1560 | 1700 | |
| 1561 | 1701 | static int jpc_dec_process_unk(jpc_dec_t *dec, jpc_ms_t *ms) |
| 1562 | 1702 | { |
| 1563 | − /* Eliminate compiler warnings about unused variables. */ | |
| 1564 | − USED(dec); | |
| 1703 | + JAS_UNUSED(dec); | |
| 1565 | 1704 | |
| 1566 | − jas_eprintf("warning: ignoring unknown marker segment (0x%x)\n", | |
| 1705 | + jas_logwarnf("warning: ignoring unknown marker segment (0x%x)\n", | |
| 1567 | 1706 | ms->id); |
| 1568 | 1707 | return 0; |
| 1569 | 1708 | } |
| @@ -1586,6 +1725,7 @@ static jpc_dec_cp_t *jpc_dec_cp_create(uint_fast16_t numcomps) · 16 unmodified lines | ||
| 1586 | 1725 | cp->numlyrs = 0; |
| 1587 | 1726 | cp->mctid = 0; |
| 1588 | 1727 | cp->csty = 0; |
| 1728 | + cp->pchglist = 0; | |
| 1589 | 1729 | if (!(cp->ccps = jas_alloc2(cp->numcomps, sizeof(jpc_dec_ccp_t)))) { |
| 1590 | 1730 | goto error; |
| 1591 | 1731 | } |
| @@ -1694,7 +1834,11 @@ static int calcstepsizes(uint_fast16_t refstepsize, unsigned numrlvls, · 102 unmodified lines | ||
| 1694 | 1834 | mant = JPC_QCX_GETMANT(refstepsize); |
| 1695 | 1835 | const unsigned numbands = 3 * numrlvls - 2; |
| 1696 | 1836 | for (unsigned bandno = 0; bandno < numbands; ++bandno) { |
| 1697 | −//jas_eprintf("DEBUG %d %d %d %d %d\n", bandno, expn, numrlvls, bandno, ((numrlvls - 1) - (numrlvls - 1 - ((bandno > 0) ? ((bandno + 2) / 3) : (0))))); | |
| 1837 | +#if 0 | |
| 1838 | + jas_eprintf("DEBUG %d %d %d %d %d\n", bandno, expn, numrlvls, bandno, | |
| 1839 | + ((numrlvls - 1) - (numrlvls - 1 - ((bandno > 0) ? ((bandno + 2) / 3) | |
| 1840 | + : (0))))); | |
| 1841 | +#endif | |
| 1698 | 1842 | const unsigned r = (bandno + 2) / 3; |
| 1699 | 1843 | const unsigned nb = (r == 0) ? (numrlvls - 1) - r : (numrlvls - 1) - r + 1; |
| 1700 | 1844 | uint_fast16_t e = expn - (numrlvls - 1) + nb; |
| @@ -1758,8 +1902,7 @@ static int jpc_dec_cp_setfromcox(jpc_dec_cp_t *cp, jpc_dec_ccp_t *ccp, · 57 unmodified lines | ||
| 1758 | 1902 | { |
| 1759 | 1903 | int rlvlno; |
| 1760 | 1904 | |
| 1761 | − /* Eliminate compiler warnings about unused variables. */ | |
| 1762 | − USED(cp); | |
| 1905 | + JAS_UNUSED(cp); | |
| 1763 | 1906 | |
| 1764 | 1907 | if ((flags & JPC_COC) || !(ccp->flags & JPC_COC)) { |
| 1765 | 1908 | ccp->numrlvls = compparms->numdlvls + 1; |
| @@ -1803,8 +1946,7 @@ static int jpc_dec_cp_setfromqcx(jpc_dec_cp_t *cp, jpc_dec_ccp_t *ccp, · 37 unmodified lines | ||
| 1803 | 1946 | { |
| 1804 | 1947 | int bandno; |
| 1805 | 1948 | |
| 1806 | − /* Eliminate compiler warnings about unused variables. */ | |
| 1807 | − USED(cp); | |
| 1949 | + JAS_UNUSED(cp); | |
| 1808 | 1950 | |
| 1809 | 1951 | /* Sanity check to prevent buffer overflow */ |
| 1810 | 1952 | if (compparms->numstepsizes > (3 * JPC_MAXRLVLS + 1)) { |
| @@ -1886,7 +2028,15 @@ static void jpc_dequantize(jas_matrix_t *x, jpc_fix_t absstepsize) · 75 unmodified lines | ||
| 1886 | 2028 | // a reconstruction parameter defined in E 1.1.2 of the ISO/IEC 15444-1 |
| 1887 | 2029 | jpc_fix_t recparam = JPC_FIX_HALF; |
| 1888 | 2030 | |
| 1889 | − assert(absstepsize >= 0); | |
| 2031 | + // Note: | |
| 2032 | + // Should anything special be done to handle the error case of | |
| 2033 | + // absstepsize < 0 (which can arise due to numerical overflow). | |
| 2034 | + // Using an assert is not appropriate, since this results in program | |
| 2035 | + // termination when this type of error occurs. | |
| 2036 | + // Simply allowing a decoded image with very high distortion would appear | |
| 2037 | + // to be consistent with the policy adopted elsewhere in the codec. | |
| 2038 | + // assert(absstepsize >= 0); | |
| 2039 | + | |
| 1890 | 2040 | if (absstepsize == jpc_inttofix(1)) { |
| 1891 | 2041 | return; |
| 1892 | 2042 | } |
| @@ -1920,7 +2070,7 @@ static void jpc_undo_roi(jas_matrix_t *x, int roishift, int bgshift, unsigned nu · 27 unmodified lines | ||
| 1920 | 2070 | if (roishift < 0) { |
| 1921 | 2071 | /* We could instead return an error here. */ |
| 1922 | 2072 | /* I do not think it matters much. */ |
| 1923 | − jas_eprintf("warning: forcing negative ROI shift to zero " | |
| 2073 | + jas_logwarnf("warning: forcing negative ROI shift to zero " | |
| 1924 | 2074 | "(bitstream is probably corrupt)\n"); |
| 1925 | 2075 | roishift = 0; |
| 1926 | 2076 | } |
| @@ -1953,7 +2103,7 @@ static void jpc_undo_roi(jas_matrix_t *x, int roishift, int bgshift, unsigned nu · 26 unmodified lines | ||
| 1953 | 2103 | Here we ensure that any such bits are masked off. */ |
| 1954 | 2104 | if (mag & (~mask)) { |
| 1955 | 2105 | if (!warn) { |
| 1956 | − jas_eprintf("warning: possibly corrupt code stream\n"); | |
| 2106 | + jas_logwarnf("warning: possibly corrupt code stream\n"); | |
| 1957 | 2107 | warn = true; |
| 1958 | 2108 | } |
| 1959 | 2109 | mag &= mask; |
| @@ -1992,7 +2142,7 @@ static jpc_dec_t *jpc_dec_create(jpc_dec_importopts_t *impopts, jas_stream_t *in · 32 unmodified lines | ||
| 1992 | 2142 | dec->cp = 0; |
| 1993 | 2143 | dec->maxlyrs = impopts->maxlyrs; |
| 1994 | 2144 | dec->maxpkts = impopts->maxpkts; |
| 1995 | −dec->numpkts = 0; | |
| 2145 | + dec->numpkts = 0; | |
| 1996 | 2146 | dec->ppmseqno = 0; |
| 1997 | 2147 | dec->state = 0; |
| 1998 | 2148 | dec->cmpts = 0; |
| @@ -2001,6 +2151,10 @@ dec->numpkts = 0; · 2 unmodified lines | ||
| 2001 | 2151 | dec->curtileendoff = 0; |
| 2002 | 2152 | dec->max_samples = impopts->max_samples; |
| 2003 | 2153 | |
| 2154 | + if (jas_get_debug_level() >= 1) { | |
| 2155 | + jas_logdebugf(1, "debug %d\n", jas_get_debug_level()); | |
| 2156 | + } | |
| 2157 | + | |
| 2004 | 2158 | return dec; |
| 2005 | 2159 | } |
| 2006 | 2160 | |
| @@ -2119,6 +2273,83 @@ void jpc_seg_destroy(jpc_dec_seg_t *seg) · 112 unmodified lines | ||
| 2119 | 2273 | jas_free(seg); |
| 2120 | 2274 | } |
| 2121 | 2275 | |
| 2276 | +static int jpc_dec_dump(const jpc_dec_t *dec) | |
| 2277 | +{ | |
| 2278 | + assert(!dec->numtiles || dec->tiles); | |
| 2279 | + unsigned tileno; | |
| 2280 | + const jpc_dec_tile_t *tile; | |
| 2281 | + for (tileno = 0, tile = dec->tiles; tileno < dec->numtiles; | |
| 2282 | + ++tileno, ++tile) { | |
| 2283 | + assert(!dec->numcomps || tile->tcomps); | |
| 2284 | + unsigned compno; | |
| 2285 | + const jpc_dec_tcomp_t *tcomp; | |
| 2286 | + for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps; | |
| 2287 | + ++compno, ++tcomp) { | |
| 2288 | + unsigned rlvlno; | |
| 2289 | + const jpc_dec_rlvl_t *rlvl; | |
| 2290 | + for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < | |
| 2291 | + tcomp->numrlvls; ++rlvlno, ++rlvl) { | |
| 2292 | + jas_logprintf("RESOLUTION LEVEL %d\n", rlvlno); | |
| 2293 | + jas_logprintf("xs = %"PRIuFAST32", ys = %"PRIuFAST32", xe = %"PRIuFAST32", ye = %"PRIuFAST32", w = %"PRIuFAST32", h = %"PRIuFAST32"\n", | |
| 2294 | + rlvl->xstart, rlvl->ystart, rlvl->xend, rlvl->yend, | |
| 2295 | + rlvl->xend - rlvl->xstart, rlvl->yend - rlvl->ystart); | |
| 2296 | + assert(!rlvl->numbands || rlvl->bands); | |
| 2297 | + unsigned bandno; | |
| 2298 | + const jpc_dec_band_t *band; | |
| 2299 | + for (bandno = 0, band = rlvl->bands; | |
| 2300 | + bandno < rlvl->numbands; ++bandno, ++band) { | |
| 2301 | + jas_logprintf("BAND %d\n", bandno); | |
| 2302 | + if (!band->data) { | |
| 2303 | + jas_logprintf("band has no data (null pointer)\n"); | |
| 2304 | + assert(!band->prcs); | |
| 2305 | + continue; | |
| 2306 | + } | |
| 2307 | + jas_logprintf("xs = %"PRIjas_seqent", ys = %"PRIjas_seqent", xe = %"PRIjas_seqent", ye = %"PRIjas_seqent", w = %"PRIjas_seqent", h = %"PRIjas_seqent"\n", | |
| 2308 | + jas_seq2d_xstart(band->data), | |
| 2309 | + jas_seq2d_ystart(band->data), | |
| 2310 | + jas_seq2d_xend(band->data), | |
| 2311 | + jas_seq2d_yend(band->data), | |
| 2312 | + jas_seq2d_xend(band->data) - | |
| 2313 | + jas_seq2d_xstart(band->data), | |
| 2314 | + jas_seq2d_yend(band->data) - | |
| 2315 | + jas_seq2d_ystart(band->data)); | |
| 2316 | + assert(!rlvl->numprcs || band->prcs); | |
| 2317 | + unsigned prcno; | |
| 2318 | + const jpc_dec_prc_t *prc; | |
| 2319 | + for (prcno = 0, prc = band->prcs; | |
| 2320 | + prcno < rlvl->numprcs; ++prcno, | |
| 2321 | + ++prc) { | |
| 2322 | + jas_logprintf("CODE BLOCK GROUP %d\n", prcno); | |
| 2323 | + jas_logprintf("xs = %"PRIuFAST32", ys = %"PRIuFAST32", xe = %"PRIuFAST32", ye = %"PRIuFAST32", w = %"PRIuFAST32", h = %"PRIuFAST32"\n", | |
| 2324 | + prc->xstart, prc->ystart, prc->xend, prc->yend, | |
| 2325 | + prc->xend - prc->xstart, prc->yend - prc->ystart); | |
| 2326 | + assert(!prc->numcblks || prc->cblks); | |
| 2327 | + unsigned cblkno; | |
| 2328 | + const jpc_dec_cblk_t *cblk; | |
| 2329 | + for (cblkno = 0, cblk = | |
| 2330 | + prc->cblks; cblkno < | |
| 2331 | + prc->numcblks; ++cblkno, | |
| 2332 | + ++cblk) { | |
| 2333 | + jas_logprintf("CODE BLOCK %d\n", cblkno); | |
| 2334 | + jas_logprintf("xs = %"PRIjas_seqent", ys = %"PRIjas_seqent", xe = %"PRIjas_seqent", ye = %"PRIjas_seqent", w = %"PRIjas_seqent", h = %"PRIjas_seqent"\n", | |
| 2335 | + jas_seq2d_xstart(cblk->data), | |
| 2336 | + jas_seq2d_ystart(cblk->data), | |
| 2337 | + jas_seq2d_xend(cblk->data), | |
| 2338 | + jas_seq2d_yend(cblk->data), | |
| 2339 | + jas_seq2d_xend(cblk->data) - | |
| 2340 | + jas_seq2d_xstart(cblk->data), | |
| 2341 | + jas_seq2d_yend(cblk->data) - | |
| 2342 | + jas_seq2d_ystart(cblk->data)); | |
| 2343 | + } | |
| 2344 | + } | |
| 2345 | + } | |
| 2346 | + } | |
| 2347 | + } | |
| 2348 | + } | |
| 2349 | + | |
| 2350 | + return 0; | |
| 2351 | +} | |
| 2352 | + | |
| 2122 | 2353 | static jpc_streamlist_t *jpc_streamlist_create() |
| 2123 | 2354 | { |
| 2124 | 2355 | jpc_streamlist_t *streamlist; |
| @@ -2366,3 +2597,75 @@ static void jpc_ppxstabent_destroy(jpc_ppxstabent_t *ent) · 241 unmodified lines | ||
| 2366 | 2597 | } |
| 2367 | 2598 | jas_free(ent); |
| 2368 | 2599 | } |
| 2600 | + | |
| 2601 | +static void jpc_cblk_init(jpc_dec_cblk_t *cblk) | |
| 2602 | +{ | |
| 2603 | +#if 1 | |
| 2604 | + memset(cblk, 0, sizeof(jpc_dec_cblk_t)); | |
| 2605 | + cblk->numpasses = 0; | |
| 2606 | + jpc_seglist_init(&cblk->segs); | |
| 2607 | + cblk->curseg = 0; | |
| 2608 | + cblk->numimsbs = 0; | |
| 2609 | + cblk->numlenbits = 0; | |
| 2610 | + cblk->firstpassno = 0; | |
| 2611 | + cblk->data = 0; | |
| 2612 | +#endif | |
| 2613 | +} | |
| 2614 | + | |
| 2615 | +static void jpc_prc_init(jpc_dec_prc_t *prc) | |
| 2616 | +{ | |
| 2617 | +#if 1 | |
| 2618 | + memset(prc, 0, sizeof(jpc_dec_prc_t)); | |
| 2619 | + prc->xstart = 0; | |
| 2620 | + prc->ystart = 0; | |
| 2621 | + prc->xend = 0; | |
| 2622 | + prc->yend = 0; | |
| 2623 | + prc->numhcblks = 0; | |
| 2624 | + prc->numvcblks = 0; | |
| 2625 | + prc->cblks = 0; | |
| 2626 | + prc->incltagtree = 0; | |
| 2627 | + prc->numimsbstagtree = 0; | |
| 2628 | +#endif | |
| 2629 | +} | |
| 2630 | + | |
| 2631 | +static void jpc_band_init(jpc_dec_band_t *band) | |
| 2632 | +{ | |
| 2633 | +#if 1 | |
| 2634 | + memset(band, 0, sizeof(jpc_dec_band_t)); | |
| 2635 | + band->prcs = 0; | |
| 2636 | + band->data = 0; | |
| 2637 | + band->orient = 0; | |
| 2638 | + band->stepsize = 0; | |
| 2639 | + band->absstepsize = 0; | |
| 2640 | + band->numbps = 0; | |
| 2641 | + band->analgain = 0; | |
| 2642 | + band->roishift = 0; | |
| 2643 | +#endif | |
| 2644 | +} | |
| 2645 | + | |
| 2646 | +static void jpc_rlvl_init(jpc_dec_rlvl_t *rlvl) | |
| 2647 | +{ | |
| 2648 | +#if 1 | |
| 2649 | + memset(rlvl, 0, sizeof(jpc_dec_rlvl_t)); | |
| 2650 | + rlvl->numbands = 0; | |
| 2651 | + rlvl->bands = 0; | |
| 2652 | + rlvl->xstart = 0; | |
| 2653 | + rlvl->ystart = 0; | |
| 2654 | + rlvl->xend = 0; | |
| 2655 | + rlvl->yend = 0; | |
| 2656 | + rlvl->prcwidthexpn = 0; | |
| 2657 | + rlvl->prcheightexpn = 0; | |
| 2658 | + rlvl->numhprcs = 0; | |
| 2659 | + rlvl->numvprcs = 0; | |
| 2660 | + rlvl->numprcs = 0; | |
| 2661 | + rlvl->cbgwidthexpn = 0; | |
| 2662 | + rlvl->cblkheightexpn = 0; | |
| 2663 | +#endif | |
| 2664 | +} | |
| 2665 | + | |
| 2666 | +static void jpc_seglist_init(jpc_dec_seglist_t *seglist) | |
| 2667 | +{ | |
| 2668 | + memset(seglist, 0, sizeof(jpc_dec_seglist_t)); | |
| 2669 | + seglist->head = 0; | |
| 2670 | + seglist->tail = 0; | |
| 2671 | +} | |
| @@ -77,6 +77,7 @@ · 76 unmodified lines | ||
| 77 | 77 | #include "jasper/jas_stream.h" |
| 78 | 78 | #include "jasper/jas_image.h" |
| 79 | 79 | |
| 80 | +#include "jpc_cod.h" | |
| 80 | 81 | #include "jpc_tsfb.h" |
| 81 | 82 | #include "jpc_tagtree.h" |
| 82 | 83 | #include "jpc_cs.h" |
| @@ -0,0 +1,2665 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2003 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/* | |
| 65 | + * $Id$ | |
| 66 | + */ | |
| 67 | + | |
| 68 | +/******************************************************************************\ | |
| 69 | +* Includes. | |
| 70 | +\******************************************************************************/ | |
| 71 | + | |
| 72 | +#include "jpc_enc.h" | |
| 73 | +#include "jpc_flt.h" | |
| 74 | +#include "jpc_fix.h" | |
| 75 | +#include "jpc_tagtree.h" | |
| 76 | +#include "jpc_cs.h" | |
| 77 | +#include "jpc_mct.h" | |
| 78 | +#include "jpc_tsfb.h" | |
| 79 | +#include "jpc_t1cod.h" | |
| 80 | +#include "jpc_t1enc.h" | |
| 81 | +#include "jpc_t2enc.h" | |
| 82 | +#include "jpc_math.h" | |
| 83 | +#include "jpc_util.h" | |
| 84 | + | |
| 85 | +#include "jasper/jas_types.h" | |
| 86 | +#include "jasper/jas_string.h" | |
| 87 | +#include "jasper/jas_malloc.h" | |
| 88 | +#include "jasper/jas_image.h" | |
| 89 | +#include "jasper/jas_tvp.h" | |
| 90 | +#include "jasper/jas_version.h" | |
| 91 | +#include "jasper/jas_math.h" | |
| 92 | +#include "jasper/jas_debug.h" | |
| 93 | + | |
| 94 | +/******************************************************************************\ | |
| 95 | +* | |
| 96 | +\******************************************************************************/ | |
| 97 | + | |
| 98 | +#define JPC_POW2(n) \ | |
| 99 | + (1 << (n)) | |
| 100 | + | |
| 101 | +#define JPC_FLOORTOMULTPOW2(x, n) \ | |
| 102 | + (((n) > 0) ? ((x) & (~((1 << n) - 1))) : (x)) | |
| 103 | +/* Round to the nearest multiple of the specified power of two in the | |
| 104 | + direction of negative infinity. */ | |
| 105 | + | |
| 106 | +#define JPC_CEILTOMULTPOW2(x, n) \ | |
| 107 | + (((n) > 0) ? JPC_FLOORTOMULTPOW2(((x) + (1 << (n)) - 1), n) : (x)) | |
| 108 | +/* Round to the nearest multiple of the specified power of two in the | |
| 109 | + direction of positive infinity. */ | |
| 110 | + | |
| 111 | +#define JPC_POW2(n) \ | |
| 112 | + (1 << (n)) | |
| 113 | + | |
| 114 | +/******************************************************************************\ | |
| 115 | +* Local prototypes. | |
| 116 | +\******************************************************************************/ | |
| 117 | + | |
| 118 | +static jpc_enc_tile_t *jpc_enc_tile_create(jpc_enc_cp_t *cp, jas_image_t *image, int tileno); | |
| 119 | +static void jpc_enc_tile_destroy(jpc_enc_tile_t *tile); | |
| 120 | + | |
| 121 | +static jpc_enc_tcmpt_t *tcmpt_create(jpc_enc_tcmpt_t *tcmpt, jpc_enc_cp_t *cp, | |
| 122 | + jas_image_t *image, jpc_enc_tile_t *tile); | |
| 123 | +static void tcmpt_destroy(jpc_enc_tcmpt_t *tcmpt); | |
| 124 | +static jpc_enc_rlvl_t *rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, | |
| 125 | + jpc_enc_tcmpt_t *tcmpt, jpc_tsfb_band_t *bandinfos); | |
| 126 | +static void rlvl_destroy(jpc_enc_rlvl_t *rlvl); | |
| 127 | +static jpc_enc_band_t *band_create(jpc_enc_band_t *band, jpc_enc_cp_t *cp, | |
| 128 | + jpc_enc_rlvl_t *rlvl, jpc_tsfb_band_t *bandinfos); | |
| 129 | +static void band_destroy(jpc_enc_band_t *bands); | |
| 130 | +static jpc_enc_prc_t *prc_create(jpc_enc_prc_t *prc, | |
| 131 | + jpc_enc_band_t *band); | |
| 132 | +static void prc_destroy(jpc_enc_prc_t *prcs); | |
| 133 | +static jpc_enc_cblk_t *cblk_create(jpc_enc_cblk_t *cblk, | |
| 134 | + jpc_enc_prc_t *prc); | |
| 135 | +static void cblk_destroy(jpc_enc_cblk_t *cblks); | |
| 136 | +int ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size); | |
| 137 | +static void pass_destroy(jpc_enc_pass_t *pass); | |
| 138 | +void jpc_enc_dump(jpc_enc_t *enc); | |
| 139 | + | |
| 140 | +void calcrdslopes(jpc_enc_cblk_t *cblk); | |
| 141 | +void dump_layeringinfo(jpc_enc_t *enc); | |
| 142 | +void jpc_quantize(jas_matrix_t *data, jpc_fix_t stepsize); | |
| 143 | +jpc_enc_t *jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image); | |
| 144 | +void jpc_enc_destroy(jpc_enc_t *enc); | |
| 145 | +static int jpc_enc_encodemainhdr(jpc_enc_t *enc); | |
| 146 | +static int jpc_enc_encodemainbody(jpc_enc_t *enc); | |
| 147 | +int jpc_enc_encodetiledata(jpc_enc_t *enc); | |
| 148 | +int rateallocate(jpc_enc_t *enc, unsigned numlyrs, uint_fast32_t *cumlens); | |
| 149 | +static jpc_enc_cp_t *cp_create(const char *optstr, jas_image_t *image); | |
| 150 | +void jpc_enc_cp_destroy(jpc_enc_cp_t *cp); | |
| 151 | +static uint_fast32_t jpc_abstorelstepsize(jpc_fix_t absdelta, int scaleexpn); | |
| 152 | + | |
| 153 | +/******************************************************************************\ | |
| 154 | +* Types. | |
| 155 | +\******************************************************************************/ | |
| 156 | + | |
| 157 | +typedef enum { | |
| 158 | + OPT_DEBUG, | |
| 159 | + OPT_IMGAREAOFFX, | |
| 160 | + OPT_IMGAREAOFFY, | |
| 161 | + OPT_TILEGRDOFFX, | |
| 162 | + OPT_TILEGRDOFFY, | |
| 163 | + OPT_TILEWIDTH, | |
| 164 | + OPT_TILEHEIGHT, | |
| 165 | + OPT_PRCWIDTH, | |
| 166 | + OPT_PRCHEIGHT, | |
| 167 | + OPT_CBLKWIDTH, | |
| 168 | + OPT_CBLKHEIGHT, | |
| 169 | + OPT_MODE, | |
| 170 | + OPT_PRG, | |
| 171 | + OPT_NOMCT, | |
| 172 | + OPT_MAXRLVLS, | |
| 173 | + OPT_SOP, | |
| 174 | + OPT_EPH, | |
| 175 | + OPT_LAZY, | |
| 176 | + OPT_TERMALL, | |
| 177 | + OPT_SEGSYM, | |
| 178 | + OPT_VCAUSAL, | |
| 179 | + OPT_RESET, | |
| 180 | + OPT_PTERM, | |
| 181 | + OPT_NUMGBITS, | |
| 182 | + OPT_RATE, | |
| 183 | + OPT_ILYRRATES, | |
| 184 | + OPT_JP2OVERHEAD | |
| 185 | +} optid_t; | |
| 186 | + | |
| 187 | +typedef enum { | |
| 188 | + PO_L = 0, | |
| 189 | + PO_R | |
| 190 | +} poid_t; | |
| 191 | + | |
| 192 | +typedef enum { | |
| 193 | + MODE_INT, | |
| 194 | + MODE_REAL | |
| 195 | +} modeid_t; | |
| 196 | + | |
| 197 | +/******************************************************************************\ | |
| 198 | +* Data. | |
| 199 | +\******************************************************************************/ | |
| 200 | + | |
| 201 | +static const jas_taginfo_t encopts[] = { | |
| 202 | + {OPT_DEBUG, "debug"}, | |
| 203 | + {OPT_IMGAREAOFFX, "imgareatlx"}, | |
| 204 | + {OPT_IMGAREAOFFY, "imgareatly"}, | |
| 205 | + {OPT_TILEGRDOFFX, "tilegrdtlx"}, | |
| 206 | + {OPT_TILEGRDOFFY, "tilegrdtly"}, | |
| 207 | + {OPT_TILEWIDTH, "tilewidth"}, | |
| 208 | + {OPT_TILEHEIGHT, "tileheight"}, | |
| 209 | + {OPT_PRCWIDTH, "prcwidth"}, | |
| 210 | + {OPT_PRCHEIGHT, "prcheight"}, | |
| 211 | + {OPT_CBLKWIDTH, "cblkwidth"}, | |
| 212 | + {OPT_CBLKHEIGHT, "cblkheight"}, | |
| 213 | + {OPT_MODE, "mode"}, | |
| 214 | + {OPT_PRG, "prg"}, | |
| 215 | + {OPT_NOMCT, "nomct"}, | |
| 216 | + {OPT_MAXRLVLS, "numrlvls"}, | |
| 217 | + {OPT_SOP, "sop"}, | |
| 218 | + {OPT_EPH, "eph"}, | |
| 219 | + {OPT_LAZY, "lazy"}, | |
| 220 | + {OPT_TERMALL, "termall"}, | |
| 221 | + {OPT_SEGSYM, "segsym"}, | |
| 222 | + {OPT_VCAUSAL, "vcausal"}, | |
| 223 | + {OPT_PTERM, "pterm"}, | |
| 224 | + {OPT_RESET, "resetprob"}, | |
| 225 | + {OPT_NUMGBITS, "numgbits"}, | |
| 226 | + {OPT_RATE, "rate"}, | |
| 227 | + {OPT_ILYRRATES, "ilyrrates"}, | |
| 228 | + {OPT_JP2OVERHEAD, "_jp2overhead"}, | |
| 229 | + {-1, 0} | |
| 230 | +}; | |
| 231 | + | |
| 232 | +static const jas_taginfo_t prgordtab[] = { | |
| 233 | + {JPC_COD_LRCPPRG, "lrcp"}, | |
| 234 | + {JPC_COD_RLCPPRG, "rlcp"}, | |
| 235 | + {JPC_COD_RPCLPRG, "rpcl"}, | |
| 236 | + {JPC_COD_PCRLPRG, "pcrl"}, | |
| 237 | + {JPC_COD_CPRLPRG, "cprl"}, | |
| 238 | + {-1, 0} | |
| 239 | +}; | |
| 240 | + | |
| 241 | +static const jas_taginfo_t modetab[] = { | |
| 242 | + {MODE_INT, "int"}, | |
| 243 | + {MODE_REAL, "real"}, | |
| 244 | + {-1, 0} | |
| 245 | +}; | |
| 246 | + | |
| 247 | +/******************************************************************************\ | |
| 248 | +\******************************************************************************/ | |
| 249 | + | |
| 250 | +/** | |
| 251 | + * @return UINT_FAST32_MAX on error | |
| 252 | + */ | |
| 253 | +static uint_fast32_t jpc_abstorelstepsize(jpc_fix_t absdelta, int scaleexpn) | |
| 254 | +{ | |
| 255 | + int p; | |
| 256 | + uint_fast32_t mant; | |
| 257 | + uint_fast32_t expn; | |
| 258 | + int n; | |
| 259 | + | |
| 260 | + if (absdelta < 0) { | |
| 261 | + return UINT_FAST32_MAX; | |
| 262 | + } | |
| 263 | + | |
| 264 | + p = jpc_fix_firstone(absdelta) - JPC_FIX_FRACBITS; | |
| 265 | + n = 11 - jpc_fix_firstone(absdelta); | |
| 266 | + mant = ((n < 0) ? (absdelta >> (-n)) : (absdelta << n)) & 0x7ff; | |
| 267 | + expn = scaleexpn - p; | |
| 268 | + if (scaleexpn < p) { | |
| 269 | + return UINT_FAST32_MAX; | |
| 270 | + } | |
| 271 | + if (expn >= 0x1f) | |
| 272 | + return UINT_FAST32_MAX; | |
| 273 | + return JPC_QCX_EXPN(expn) | JPC_QCX_MANT(mant); | |
| 274 | +} | |
| 275 | + | |
| 276 | +/******************************************************************************\ | |
| 277 | +* The main encoder entry point. | |
| 278 | +\******************************************************************************/ | |
| 279 | + | |
| 280 | +int jpc_encode(jas_image_t *image, jas_stream_t *out, const char *optstr) | |
| 281 | +{ | |
| 282 | + jpc_enc_t *enc; | |
| 283 | + jpc_enc_cp_t *cp; | |
| 284 | + | |
| 285 | + enc = 0; | |
| 286 | + | |
| 287 | + jpc_init(); | |
| 288 | + | |
| 289 | + if (!(cp = cp_create(optstr, image))) { | |
| 290 | + jas_logerrorf("invalid JP encoder options\n"); | |
| 291 | + goto error; | |
| 292 | + } | |
| 293 | + | |
| 294 | + if (!(enc = jpc_enc_create(cp, out, image))) { | |
| 295 | + jas_logerrorf("jpc_enc_create failed\n"); | |
| 296 | + goto error; | |
| 297 | + } | |
| 298 | + cp = 0; | |
| 299 | + | |
| 300 | + /* Encode the main header. */ | |
| 301 | + if (jpc_enc_encodemainhdr(enc)) { | |
| 302 | + jas_logerrorf("cannot encode main header\n"); | |
| 303 | + goto error; | |
| 304 | + } | |
| 305 | + | |
| 306 | + /* Encode the main body. This constitutes most of the encoding work. */ | |
| 307 | + if (jpc_enc_encodemainbody(enc)) { | |
| 308 | + jas_logerrorf("cannot encode main body\n"); | |
| 309 | + goto error; | |
| 310 | + } | |
| 311 | + | |
| 312 | + /* Write EOC marker segment. */ | |
| 313 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_EOC))) { | |
| 314 | + jas_logerrorf("cannot create EOC marker\n"); | |
| 315 | + goto error; | |
| 316 | + } | |
| 317 | + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { | |
| 318 | + jas_logerrorf("cannot write EOC marker\n"); | |
| 319 | + goto error; | |
| 320 | + } | |
| 321 | + jpc_ms_destroy(enc->mrk); | |
| 322 | + enc->mrk = 0; | |
| 323 | + | |
| 324 | + if (jas_stream_flush(enc->out)) { | |
| 325 | + jas_logerrorf("stream flush failed\n"); | |
| 326 | + goto error; | |
| 327 | + } | |
| 328 | + | |
| 329 | + jpc_enc_destroy(enc); | |
| 330 | + | |
| 331 | + return 0; | |
| 332 | + | |
| 333 | +error: | |
| 334 | + if (cp) { | |
| 335 | + jpc_enc_cp_destroy(cp); | |
| 336 | + } | |
| 337 | + if (enc) { | |
| 338 | + jpc_enc_destroy(enc); | |
| 339 | + } | |
| 340 | + jas_logerrorf("jpc_encode failed\n"); | |
| 341 | + return -1; | |
| 342 | +} | |
| 343 | + | |
| 344 | +/******************************************************************************\ | |
| 345 | +* Option parsing code. | |
| 346 | +\******************************************************************************/ | |
| 347 | + | |
| 348 | +static jpc_enc_cp_t *cp_create(const char *optstr, jas_image_t *image) | |
| 349 | +{ | |
| 350 | + jpc_enc_cp_t *cp; | |
| 351 | + jas_tvparser_t *tvp; | |
| 352 | + int numilyrrates; | |
| 353 | + double *ilyrrates; | |
| 354 | + int i; | |
| 355 | + int tagid; | |
| 356 | + jpc_enc_tcp_t *tcp; | |
| 357 | + jpc_enc_tccp_t *tccp; | |
| 358 | + jpc_enc_ccp_t *ccp; | |
| 359 | + uint_fast16_t rlvlno; | |
| 360 | + uint_fast16_t prcwidthexpn; | |
| 361 | + uint_fast16_t prcheightexpn; | |
| 362 | + bool enablemct; | |
| 363 | + uint_fast32_t jp2overhead; | |
| 364 | + uint_fast16_t lyrno; | |
| 365 | + uint_fast32_t hsteplcm; | |
| 366 | + uint_fast32_t vsteplcm; | |
| 367 | + bool mctvalid; | |
| 368 | + | |
| 369 | + tvp = 0; | |
| 370 | + ilyrrates = 0; | |
| 371 | + numilyrrates = 0; | |
| 372 | + | |
| 373 | + if (!(cp = jas_malloc(sizeof(jpc_enc_cp_t)))) { | |
| 374 | + goto error; | |
| 375 | + } | |
| 376 | + | |
| 377 | + prcwidthexpn = 15; | |
| 378 | + prcheightexpn = 15; | |
| 379 | + enablemct = true; | |
| 380 | + jp2overhead = 0; | |
| 381 | + | |
| 382 | + cp->ccps = 0; | |
| 383 | + cp->debug = 0; | |
| 384 | + cp->imgareatlx = UINT_FAST32_MAX; | |
| 385 | + cp->imgareatly = UINT_FAST32_MAX; | |
| 386 | + cp->refgrdwidth = 0; | |
| 387 | + cp->refgrdheight = 0; | |
| 388 | + cp->tilegrdoffx = UINT_FAST32_MAX; | |
| 389 | + cp->tilegrdoffy = UINT_FAST32_MAX; | |
| 390 | + cp->tilewidth = 0; | |
| 391 | + cp->tileheight = 0; | |
| 392 | + cp->numcmpts = jas_image_numcmpts(image); | |
| 393 | + cp->tcp.ilyrrates = NULL; | |
| 394 | + | |
| 395 | + hsteplcm = 1; | |
| 396 | + vsteplcm = 1; | |
| 397 | + for (unsigned cmptno = 0; cmptno < jas_image_numcmpts(image); ++cmptno) { | |
| 398 | + if (jas_image_cmptbrx(image, cmptno) + jas_image_cmpthstep(image, cmptno) <= | |
| 399 | + jas_image_brx(image) || jas_image_cmptbry(image, cmptno) + | |
| 400 | + jas_image_cmptvstep(image, cmptno) <= jas_image_bry(image)) { | |
| 401 | + jas_logerrorf("unsupported image type\n"); | |
| 402 | + goto error; | |
| 403 | + } | |
| 404 | + /* Note: We ought to be calculating the LCMs here. Fix some day. */ | |
| 405 | + hsteplcm *= jas_image_cmpthstep(image, cmptno); | |
| 406 | + vsteplcm *= jas_image_cmptvstep(image, cmptno); | |
| 407 | + } | |
| 408 | + | |
| 409 | + if (!(cp->ccps = jas_alloc2(cp->numcmpts, sizeof(jpc_enc_ccp_t)))) { | |
| 410 | + goto error; | |
| 411 | + } | |
| 412 | + unsigned cmptno; | |
| 413 | + for (cmptno = 0, ccp = cp->ccps; cmptno < cp->numcmpts; ++cmptno, | |
| 414 | + ++ccp) { | |
| 415 | + ccp->sampgrdstepx = jas_image_cmpthstep(image, cmptno); | |
| 416 | + ccp->sampgrdstepy = jas_image_cmptvstep(image, cmptno); | |
| 417 | + /* XXX - this isn't quite correct for more general image */ | |
| 418 | + ccp->sampgrdsubstepx = 0; | |
| 419 | + ccp->sampgrdsubstepx = 0; | |
| 420 | + ccp->prec = jas_image_cmptprec(image, cmptno); | |
| 421 | + ccp->sgnd = jas_image_cmptsgnd(image, cmptno); | |
| 422 | + ccp->numstepsizes = 0; | |
| 423 | + memset(ccp->stepsizes, 0, sizeof(ccp->stepsizes)); | |
| 424 | + } | |
| 425 | + | |
| 426 | + cp->rawsize = jas_image_rawsize(image); | |
| 427 | + if (cp->rawsize == 0) { | |
| 428 | + /* prevent division by zero in cp_create() */ | |
| 429 | + goto error; | |
| 430 | + } | |
| 431 | + cp->totalsize = UINT_FAST32_MAX; | |
| 432 | + | |
| 433 | + tcp = &cp->tcp; | |
| 434 | + tcp->csty = 0; | |
| 435 | + tcp->intmode = true; | |
| 436 | + tcp->prg = JPC_COD_LRCPPRG; | |
| 437 | + tcp->numlyrs = 1; | |
| 438 | + tcp->ilyrrates = 0; | |
| 439 | + | |
| 440 | + tccp = &cp->tccp; | |
| 441 | + tccp->csty = 0; | |
| 442 | + tccp->maxrlvls = 6; | |
| 443 | + tccp->cblkwidthexpn = 6; | |
| 444 | + tccp->cblkheightexpn = 6; | |
| 445 | + tccp->cblksty = 0; | |
| 446 | + tccp->numgbits = 2; | |
| 447 | + | |
| 448 | + if (!(tvp = jas_tvparser_create(optstr ? optstr : ""))) { | |
| 449 | + goto error; | |
| 450 | + } | |
| 451 | + | |
| 452 | + while (!jas_tvparser_next(tvp)) { | |
| 453 | + switch (jas_taginfo_nonull(jas_taginfos_lookup(encopts, | |
| 454 | + jas_tvparser_gettag(tvp)))->id) { | |
| 455 | + case OPT_DEBUG: | |
| 456 | + cp->debug = atoi(jas_tvparser_getval(tvp)); | |
| 457 | + break; | |
| 458 | + case OPT_IMGAREAOFFX: | |
| 459 | + cp->imgareatlx = atoi(jas_tvparser_getval(tvp)); | |
| 460 | + break; | |
| 461 | + case OPT_IMGAREAOFFY: | |
| 462 | + cp->imgareatly = atoi(jas_tvparser_getval(tvp)); | |
| 463 | + break; | |
| 464 | + case OPT_TILEGRDOFFX: | |
| 465 | + cp->tilegrdoffx = atoi(jas_tvparser_getval(tvp)); | |
| 466 | + break; | |
| 467 | + case OPT_TILEGRDOFFY: | |
| 468 | + cp->tilegrdoffy = atoi(jas_tvparser_getval(tvp)); | |
| 469 | + break; | |
| 470 | + case OPT_TILEWIDTH: | |
| 471 | + cp->tilewidth = atoi(jas_tvparser_getval(tvp)); | |
| 472 | + break; | |
| 473 | + case OPT_TILEHEIGHT: | |
| 474 | + cp->tileheight = atoi(jas_tvparser_getval(tvp)); | |
| 475 | + break; | |
| 476 | + case OPT_PRCWIDTH: | |
| 477 | + prcwidthexpn = jpc_floorlog2(atoi(jas_tvparser_getval(tvp))); | |
| 478 | + break; | |
| 479 | + case OPT_PRCHEIGHT: | |
| 480 | + prcheightexpn = jpc_floorlog2(atoi(jas_tvparser_getval(tvp))); | |
| 481 | + break; | |
| 482 | + case OPT_CBLKWIDTH: | |
| 483 | + tccp->cblkwidthexpn = | |
| 484 | + jpc_floorlog2(atoi(jas_tvparser_getval(tvp))); | |
| 485 | + break; | |
| 486 | + case OPT_CBLKHEIGHT: | |
| 487 | + tccp->cblkheightexpn = | |
| 488 | + jpc_floorlog2(atoi(jas_tvparser_getval(tvp))); | |
| 489 | + break; | |
| 490 | + case OPT_MODE: | |
| 491 | + if ((tagid = jas_taginfo_nonull(jas_taginfos_lookup(modetab, | |
| 492 | + jas_tvparser_getval(tvp)))->id) < 0) { | |
| 493 | + jas_logwarnf("ignoring invalid mode %s\n", | |
| 494 | + jas_tvparser_getval(tvp)); | |
| 495 | + } else { | |
| 496 | + tcp->intmode = (tagid == MODE_INT); | |
| 497 | + } | |
| 498 | + break; | |
| 499 | + case OPT_PRG: | |
| 500 | + if ((tagid = jas_taginfo_nonull(jas_taginfos_lookup(prgordtab, | |
| 501 | + jas_tvparser_getval(tvp)))->id) < 0) { | |
| 502 | + jas_logwarnf("ignoring invalid progression order %s\n", | |
| 503 | + jas_tvparser_getval(tvp)); | |
| 504 | + } else { | |
| 505 | + tcp->prg = tagid; | |
| 506 | + } | |
| 507 | + break; | |
| 508 | + case OPT_NOMCT: | |
| 509 | + enablemct = false; | |
| 510 | + break; | |
| 511 | + case OPT_MAXRLVLS: | |
| 512 | + tccp->maxrlvls = atoi(jas_tvparser_getval(tvp)); | |
| 513 | + if (tccp->maxrlvls > JPC_MAXRLVLS) { | |
| 514 | + jas_logerrorf("number of resolution levels exceeds maximum %d\n", | |
| 515 | + JPC_MAXRLVLS); | |
| 516 | + goto error; | |
| 517 | + } | |
| 518 | + break; | |
| 519 | + case OPT_SOP: | |
| 520 | + cp->tcp.csty |= JPC_COD_SOP; | |
| 521 | + break; | |
| 522 | + case OPT_EPH: | |
| 523 | + cp->tcp.csty |= JPC_COD_EPH; | |
| 524 | + break; | |
| 525 | + case OPT_LAZY: | |
| 526 | + tccp->cblksty |= JPC_COX_LAZY; | |
| 527 | + break; | |
| 528 | + case OPT_TERMALL: | |
| 529 | + tccp->cblksty |= JPC_COX_TERMALL; | |
| 530 | + break; | |
| 531 | + case OPT_SEGSYM: | |
| 532 | + tccp->cblksty |= JPC_COX_SEGSYM; | |
| 533 | + break; | |
| 534 | + case OPT_VCAUSAL: | |
| 535 | + tccp->cblksty |= JPC_COX_VSC; | |
| 536 | + break; | |
| 537 | + case OPT_RESET: | |
| 538 | + tccp->cblksty |= JPC_COX_RESET; | |
| 539 | + break; | |
| 540 | + case OPT_PTERM: | |
| 541 | + tccp->cblksty |= JPC_COX_PTERM; | |
| 542 | + break; | |
| 543 | + case OPT_NUMGBITS: | |
| 544 | + cp->tccp.numgbits = atoi(jas_tvparser_getval(tvp)); | |
| 545 | + break; | |
| 546 | + case OPT_RATE: | |
| 547 | + if (ratestrtosize(jas_tvparser_getval(tvp), cp->rawsize, | |
| 548 | + &cp->totalsize)) { | |
| 549 | + jas_logwarnf("ignoring bad rate specifier %s\n", | |
| 550 | + jas_tvparser_getval(tvp)); | |
| 551 | + } | |
| 552 | + break; | |
| 553 | + case OPT_ILYRRATES: | |
| 554 | + if (jpc_atoaf(jas_tvparser_getval(tvp), &numilyrrates, | |
| 555 | + &ilyrrates)) { | |
| 556 | + jas_logwarnf("warning: invalid intermediate layer rates specifier ignored (%s)\n", | |
| 557 | + jas_tvparser_getval(tvp)); | |
| 558 | + } | |
| 559 | + break; | |
| 560 | + | |
| 561 | + case OPT_JP2OVERHEAD: | |
| 562 | + jp2overhead = atoi(jas_tvparser_getval(tvp)); | |
| 563 | + break; | |
| 564 | + default: | |
| 565 | + jas_logwarnf("warning: ignoring invalid option %s\n", | |
| 566 | + jas_tvparser_gettag(tvp)); | |
| 567 | + break; | |
| 568 | + } | |
| 569 | + } | |
| 570 | + | |
| 571 | + jas_tvparser_destroy(tvp); | |
| 572 | + tvp = 0; | |
| 573 | + | |
| 574 | + if (cp->totalsize != UINT_FAST32_MAX) { | |
| 575 | + cp->totalsize = (cp->totalsize > jp2overhead) ? | |
| 576 | + (cp->totalsize - jp2overhead) : 0; | |
| 577 | + } | |
| 578 | + | |
| 579 | + if (cp->imgareatlx == UINT_FAST32_MAX) { | |
| 580 | + cp->imgareatlx = 0; | |
| 581 | + } else { | |
| 582 | + if (hsteplcm != 1) { | |
| 583 | + jas_logwarnf("warning: overriding imgareatlx value\n"); | |
| 584 | + } | |
| 585 | + cp->imgareatlx *= hsteplcm; | |
| 586 | + } | |
| 587 | + if (cp->imgareatly == UINT_FAST32_MAX) { | |
| 588 | + cp->imgareatly = 0; | |
| 589 | + } else { | |
| 590 | + if (vsteplcm != 1) { | |
| 591 | + jas_logwarnf("warning: overriding imgareatly value\n"); | |
| 592 | + } | |
| 593 | + cp->imgareatly *= vsteplcm; | |
| 594 | + } | |
| 595 | + cp->refgrdwidth = cp->imgareatlx + jas_image_width(image); | |
| 596 | + cp->refgrdheight = cp->imgareatly + jas_image_height(image); | |
| 597 | + if (cp->tilegrdoffx == UINT_FAST32_MAX) { | |
| 598 | + cp->tilegrdoffx = cp->imgareatlx; | |
| 599 | + } | |
| 600 | + if (cp->tilegrdoffy == UINT_FAST32_MAX) { | |
| 601 | + cp->tilegrdoffy = cp->imgareatly; | |
| 602 | + } | |
| 603 | + if (!cp->tilewidth) { | |
| 604 | + cp->tilewidth = cp->refgrdwidth - cp->tilegrdoffx; | |
| 605 | + } | |
| 606 | + if (!cp->tileheight) { | |
| 607 | + cp->tileheight = cp->refgrdheight - cp->tilegrdoffy; | |
| 608 | + } | |
| 609 | + | |
| 610 | + if (cp->numcmpts == 3) { | |
| 611 | + mctvalid = true; | |
| 612 | + for (cmptno = 0; cmptno < jas_image_numcmpts(image); ++cmptno) { | |
| 613 | + if (jas_image_cmptprec(image, cmptno) != jas_image_cmptprec(image, 0) || | |
| 614 | + jas_image_cmptsgnd(image, cmptno) != jas_image_cmptsgnd(image, 0) || | |
| 615 | + jas_image_cmptwidth(image, cmptno) != jas_image_cmptwidth(image, 0) || | |
| 616 | + jas_image_cmptheight(image, cmptno) != jas_image_cmptheight(image, 0)) { | |
| 617 | + mctvalid = false; | |
| 618 | + } | |
| 619 | + } | |
| 620 | + } else { | |
| 621 | + mctvalid = false; | |
| 622 | + } | |
| 623 | + if (mctvalid && enablemct && jas_clrspc_fam(jas_image_clrspc(image)) != JAS_CLRSPC_FAM_RGB) { | |
| 624 | + jas_logwarnf("warning: color space apparently not RGB\n"); | |
| 625 | + } | |
| 626 | + if (mctvalid && enablemct && jas_clrspc_fam(jas_image_clrspc(image)) == JAS_CLRSPC_FAM_RGB) { | |
| 627 | + tcp->mctid = (tcp->intmode) ? (JPC_MCT_RCT) : (JPC_MCT_ICT); | |
| 628 | + } else { | |
| 629 | + tcp->mctid = JPC_MCT_NONE; | |
| 630 | + } | |
| 631 | + tccp->qmfbid = (tcp->intmode) ? (JPC_COX_RFT) : (JPC_COX_INS); | |
| 632 | + | |
| 633 | + for (rlvlno = 0; rlvlno < tccp->maxrlvls; ++rlvlno) { | |
| 634 | + tccp->prcwidthexpns[rlvlno] = prcwidthexpn; | |
| 635 | + tccp->prcheightexpns[rlvlno] = prcheightexpn; | |
| 636 | + } | |
| 637 | + if (prcwidthexpn != 15 || prcheightexpn != 15) { | |
| 638 | + tccp->csty |= JPC_COX_PRT; | |
| 639 | + } | |
| 640 | + | |
| 641 | + /* Ensure that the tile width and height is valid. */ | |
| 642 | + if (!cp->tilewidth) { | |
| 643 | + jas_logerrorf("invalid tile width %lu\n", (unsigned long) | |
| 644 | + cp->tilewidth); | |
| 645 | + goto error; | |
| 646 | + } | |
| 647 | + if (!cp->tileheight) { | |
| 648 | + jas_logerrorf("invalid tile height %lu\n", (unsigned long) | |
| 649 | + cp->tileheight); | |
| 650 | + goto error; | |
| 651 | + } | |
| 652 | + | |
| 653 | + /* Ensure that the tile grid offset is valid. */ | |
| 654 | + if (cp->tilegrdoffx > cp->imgareatlx || | |
| 655 | + cp->tilegrdoffy > cp->imgareatly || | |
| 656 | + cp->tilegrdoffx + cp->tilewidth < cp->imgareatlx || | |
| 657 | + cp->tilegrdoffy + cp->tileheight < cp->imgareatly) { | |
| 658 | + jas_logerrorf("invalid tile grid offset (%lu, %lu)\n", | |
| 659 | + (unsigned long) cp->tilegrdoffx, (unsigned long) | |
| 660 | + cp->tilegrdoffy); | |
| 661 | + goto error; | |
| 662 | + } | |
| 663 | + | |
| 664 | + cp->numhtiles = JPC_CEILDIV(cp->refgrdwidth - cp->tilegrdoffx, | |
| 665 | + cp->tilewidth); | |
| 666 | + cp->numvtiles = JPC_CEILDIV(cp->refgrdheight - cp->tilegrdoffy, | |
| 667 | + cp->tileheight); | |
| 668 | + cp->numtiles = cp->numhtiles * cp->numvtiles; | |
| 669 | + | |
| 670 | + if (ilyrrates && numilyrrates > 0) { | |
| 671 | + tcp->numlyrs = numilyrrates + 1; | |
| 672 | + if (!(tcp->ilyrrates = jas_alloc2((tcp->numlyrs - 1), | |
| 673 | + sizeof(jpc_fix_t)))) { | |
| 674 | + goto error; | |
| 675 | + } | |
| 676 | + for (i = 0; i < JAS_CAST(int, tcp->numlyrs - 1); ++i) { | |
| 677 | + tcp->ilyrrates[i] = jpc_dbltofix(ilyrrates[i]); | |
| 678 | + } | |
| 679 | + } | |
| 680 | + | |
| 681 | + /* Ensure that the integer mode is used in the case of lossless | |
| 682 | + coding. */ | |
| 683 | + if (cp->totalsize == UINT_FAST32_MAX && (!cp->tcp.intmode)) { | |
| 684 | + jas_logerrorf("cannot use real mode for lossless coding\n"); | |
| 685 | + goto error; | |
| 686 | + } | |
| 687 | + | |
| 688 | + /* Ensure that the precinct width is valid. */ | |
| 689 | + if (prcwidthexpn > 15) { | |
| 690 | + jas_logerrorf("invalid precinct width\n"); | |
| 691 | + goto error; | |
| 692 | + } | |
| 693 | + | |
| 694 | + /* Ensure that the precinct height is valid. */ | |
| 695 | + if (prcheightexpn > 15) { | |
| 696 | + jas_logerrorf("invalid precinct height\n"); | |
| 697 | + goto error; | |
| 698 | + } | |
| 699 | + | |
| 700 | + /* Ensure that the code block width is valid. */ | |
| 701 | + if (cp->tccp.cblkwidthexpn < 2 || cp->tccp.cblkwidthexpn > 12) { | |
| 702 | + jas_logerrorf("invalid code block width %d\n", | |
| 703 | + JPC_POW2(cp->tccp.cblkwidthexpn)); | |
| 704 | + goto error; | |
| 705 | + } | |
| 706 | + | |
| 707 | + /* Ensure that the code block height is valid. */ | |
| 708 | + if (cp->tccp.cblkheightexpn < 2 || cp->tccp.cblkheightexpn > 12) { | |
| 709 | + jas_logerrorf("invalid code block height %d\n", | |
| 710 | + JPC_POW2(cp->tccp.cblkheightexpn)); | |
| 711 | + goto error; | |
| 712 | + } | |
| 713 | + | |
| 714 | + /* Ensure that the code block size is not too large. */ | |
| 715 | + if (cp->tccp.cblkwidthexpn + cp->tccp.cblkheightexpn > 12) { | |
| 716 | + jas_logerrorf("code block size too large\n"); | |
| 717 | + goto error; | |
| 718 | + } | |
| 719 | + | |
| 720 | + /* Ensure that the number of layers is valid. */ | |
| 721 | + if (cp->tcp.numlyrs > 16384) { | |
| 722 | + jas_logerrorf("too many layers\n"); | |
| 723 | + goto error; | |
| 724 | + } | |
| 725 | + | |
| 726 | + /* There must be at least one resolution level. */ | |
| 727 | + if (cp->tccp.maxrlvls < 1) { | |
| 728 | + jas_logerrorf("must be at least one resolution level\n"); | |
| 729 | + goto error; | |
| 730 | + } | |
| 731 | + | |
| 732 | + /* Ensure that the number of guard bits is valid. */ | |
| 733 | + if (cp->tccp.numgbits > 8) { | |
| 734 | + jas_logerrorf("invalid number of guard bits\n"); | |
| 735 | + goto error; | |
| 736 | + } | |
| 737 | + | |
| 738 | + /* Ensure that the rate is within the legal range. */ | |
| 739 | + if (cp->totalsize != UINT_FAST32_MAX && cp->totalsize > cp->rawsize) { | |
| 740 | + jas_logwarnf("warning: specified rate is unreasonably large (%lu > %lu)\n", (unsigned long) cp->totalsize, (unsigned long) cp->rawsize); | |
| 741 | + } | |
| 742 | + | |
| 743 | + /* Ensure that the intermediate layer rates are valid. */ | |
| 744 | + if (tcp->numlyrs > 1) { | |
| 745 | + /* The intermediate layers rates must increase monotonically. */ | |
| 746 | + for (lyrno = 0; lyrno + 2 < tcp->numlyrs; ++lyrno) { | |
| 747 | + if (tcp->ilyrrates[lyrno] >= tcp->ilyrrates[lyrno + 1]) { | |
| 748 | + jas_logerrorf("intermediate layer rates must increase monotonically\n"); | |
| 749 | + goto error; | |
| 750 | + } | |
| 751 | + } | |
| 752 | + /* The intermediate layer rates must be less than the overall rate. */ | |
| 753 | + if (cp->totalsize != UINT_FAST32_MAX) { | |
| 754 | + for (lyrno = 0; lyrno < tcp->numlyrs - 1; ++lyrno) { | |
| 755 | + if (jpc_fixtodbl(tcp->ilyrrates[lyrno]) > ((double) cp->totalsize) | |
| 756 | + / cp->rawsize) { | |
| 757 | + jas_logerrorf("warning: intermediate layer rates must be less than overall rate\n"); | |
| 758 | + goto error; | |
| 759 | + } | |
| 760 | + } | |
| 761 | + } | |
| 762 | + } | |
| 763 | + | |
| 764 | + if (ilyrrates) { | |
| 765 | + jas_free(ilyrrates); | |
| 766 | + } | |
| 767 | + | |
| 768 | + return cp; | |
| 769 | + | |
| 770 | +error: | |
| 771 | + | |
| 772 | + if (ilyrrates) { | |
| 773 | + jas_free(ilyrrates); | |
| 774 | + } | |
| 775 | + if (tvp) { | |
| 776 | + jas_tvparser_destroy(tvp); | |
| 777 | + } | |
| 778 | + if (cp) { | |
| 779 | + jpc_enc_cp_destroy(cp); | |
| 780 | + } | |
| 781 | + return 0; | |
| 782 | +} | |
| 783 | + | |
| 784 | +void jpc_enc_cp_destroy(jpc_enc_cp_t *cp) | |
| 785 | +{ | |
| 786 | + if (cp->ccps) { | |
| 787 | + if (cp->tcp.ilyrrates) { | |
| 788 | + jas_free(cp->tcp.ilyrrates); | |
| 789 | + } | |
| 790 | + jas_free(cp->ccps); | |
| 791 | + } | |
| 792 | + jas_free(cp); | |
| 793 | +} | |
| 794 | + | |
| 795 | +int ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size) | |
| 796 | +{ | |
| 797 | + jpc_flt_t f; | |
| 798 | + | |
| 799 | + /* Note: This function must not modify output size on failure. */ | |
| 800 | + if (strchr(s, 'B')) { | |
| 801 | + *size = atoi(s); | |
| 802 | + } else { | |
| 803 | + f = atof(s); | |
| 804 | + if (f < 0) { | |
| 805 | + *size = 0; | |
| 806 | + } else if (f > 1.0) { | |
| 807 | + *size = rawsize + 1; | |
| 808 | + } else { | |
| 809 | + *size = f * rawsize; | |
| 810 | + } | |
| 811 | + } | |
| 812 | + return 0; | |
| 813 | +} | |
| 814 | + | |
| 815 | +/******************************************************************************\ | |
| 816 | +* Encoder constructor and destructor. | |
| 817 | +\******************************************************************************/ | |
| 818 | + | |
| 819 | +jpc_enc_t *jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image) | |
| 820 | +{ | |
| 821 | + jpc_enc_t *enc; | |
| 822 | + | |
| 823 | + if (!(enc = jas_malloc(sizeof(jpc_enc_t)))) { | |
| 824 | + goto error; | |
| 825 | + } | |
| 826 | + | |
| 827 | + enc->image = image; | |
| 828 | + enc->out = out; | |
| 829 | + enc->cp = cp; | |
| 830 | + enc->cstate = 0; | |
| 831 | + enc->tmpstream = 0; | |
| 832 | + enc->mrk = 0; | |
| 833 | + enc->curtile = 0; | |
| 834 | + | |
| 835 | + if (!(enc->cstate = jpc_cstate_create())) { | |
| 836 | + goto error; | |
| 837 | + } | |
| 838 | + enc->len = 0; | |
| 839 | + enc->mainbodysize = 0; | |
| 840 | + | |
| 841 | + return enc; | |
| 842 | + | |
| 843 | +error: | |
| 844 | + | |
| 845 | + if (enc) { | |
| 846 | + jpc_enc_destroy(enc); | |
| 847 | + } | |
| 848 | + return 0; | |
| 849 | +} | |
| 850 | + | |
| 851 | +void jpc_enc_destroy(jpc_enc_t *enc) | |
| 852 | +{ | |
| 853 | + /* The image object (i.e., enc->image) and output stream object | |
| 854 | + (i.e., enc->out) are created outside of the encoder. | |
| 855 | + Therefore, they must not be destroyed here. */ | |
| 856 | + | |
| 857 | + if (enc->curtile) { | |
| 858 | + jpc_enc_tile_destroy(enc->curtile); | |
| 859 | + } | |
| 860 | + if (enc->cp) { | |
| 861 | + jpc_enc_cp_destroy(enc->cp); | |
| 862 | + } | |
| 863 | + if (enc->cstate) { | |
| 864 | + jpc_cstate_destroy(enc->cstate); | |
| 865 | + } | |
| 866 | + if (enc->tmpstream) { | |
| 867 | + jas_stream_close(enc->tmpstream); | |
| 868 | + } | |
| 869 | + if (enc->mrk) { | |
| 870 | + jpc_ms_destroy(enc->mrk); | |
| 871 | + } | |
| 872 | + | |
| 873 | + jas_free(enc); | |
| 874 | +} | |
| 875 | + | |
| 876 | +/******************************************************************************\ | |
| 877 | +* Code. | |
| 878 | +\******************************************************************************/ | |
| 879 | + | |
| 880 | +static int jpc_enc_encodemainhdr(jpc_enc_t *enc) | |
| 881 | +{ | |
| 882 | + jpc_siz_t *siz; | |
| 883 | + jpc_cod_t *cod; | |
| 884 | + jpc_qcd_t *qcd; | |
| 885 | + int i; | |
| 886 | + long startoff; | |
| 887 | + long mainhdrlen; | |
| 888 | + jpc_enc_cp_t *cp; | |
| 889 | + jpc_qcc_t *qcc; | |
| 890 | + jpc_enc_tccp_t *tccp; | |
| 891 | + uint_fast16_t cmptno; | |
| 892 | + jpc_tsfb_band_t bandinfos[JPC_MAXBANDS]; | |
| 893 | + jpc_enc_tcp_t *tcp; | |
| 894 | + jpc_tsfb_t *tsfb; | |
| 895 | + jpc_tsfb_band_t *bandinfo; | |
| 896 | + uint_fast16_t numbands; | |
| 897 | + uint_fast16_t bandno; | |
| 898 | + uint_fast16_t rlvlno; | |
| 899 | + uint_fast16_t analgain; | |
| 900 | + jpc_fix_t absstepsize; | |
| 901 | + char buf[1024]; | |
| 902 | + jpc_com_t *com; | |
| 903 | + | |
| 904 | + cp = enc->cp; | |
| 905 | + | |
| 906 | + startoff = jas_stream_getrwcount(enc->out); | |
| 907 | + | |
| 908 | + /* Write SOC marker segment. */ | |
| 909 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_SOC))) { | |
| 910 | + jas_logerrorf("cannot create SOC marker\n"); | |
| 911 | + return -1; | |
| 912 | + } | |
| 913 | + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { | |
| 914 | + jas_logerrorf("cannot write SOC marker\n"); | |
| 915 | + return -1; | |
| 916 | + } | |
| 917 | + jpc_ms_destroy(enc->mrk); | |
| 918 | + enc->mrk = 0; | |
| 919 | + | |
| 920 | + /* Write SIZ marker segment. */ | |
| 921 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_SIZ))) { | |
| 922 | + jas_logerrorf("cannot create SIZ marker\n"); | |
| 923 | + return -1; | |
| 924 | + } | |
| 925 | + siz = &enc->mrk->parms.siz; | |
| 926 | + siz->caps = 0; | |
| 927 | + siz->xoff = cp->imgareatlx; | |
| 928 | + siz->yoff = cp->imgareatly; | |
| 929 | + siz->width = cp->refgrdwidth; | |
| 930 | + siz->height = cp->refgrdheight; | |
| 931 | + siz->tilexoff = cp->tilegrdoffx; | |
| 932 | + siz->tileyoff = cp->tilegrdoffy; | |
| 933 | + siz->tilewidth = cp->tilewidth; | |
| 934 | + siz->tileheight = cp->tileheight; | |
| 935 | + siz->numcomps = cp->numcmpts; | |
| 936 | + siz->comps = jas_alloc2(siz->numcomps, sizeof(jpc_sizcomp_t)); | |
| 937 | + assert(siz->comps); | |
| 938 | + for (i = 0; i < JAS_CAST(int, cp->numcmpts); ++i) { | |
| 939 | + siz->comps[i].prec = cp->ccps[i].prec; | |
| 940 | + siz->comps[i].sgnd = cp->ccps[i].sgnd; | |
| 941 | + siz->comps[i].hsamp = cp->ccps[i].sampgrdstepx; | |
| 942 | + siz->comps[i].vsamp = cp->ccps[i].sampgrdstepy; | |
| 943 | + } | |
| 944 | + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { | |
| 945 | + jas_logerrorf("cannot write SIZ marker\n"); | |
| 946 | + return -1; | |
| 947 | + } | |
| 948 | + jpc_ms_destroy(enc->mrk); | |
| 949 | + enc->mrk = 0; | |
| 950 | + | |
| 951 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_COM))) { | |
| 952 | + jas_logerrorf("cannot create COM marker\n"); | |
| 953 | + return -1; | |
| 954 | + } | |
| 955 | + sprintf(buf, "Creator: JasPer Version %s", jas_getversion()); | |
| 956 | + com = &enc->mrk->parms.com; | |
| 957 | + com->len = JAS_CAST(uint_fast16_t, strlen(buf)); | |
| 958 | + com->regid = JPC_COM_LATIN; | |
| 959 | + if (!(com->data = JAS_CAST(jas_uchar *, jas_strdup(buf)))) { | |
| 960 | + return -1; | |
| 961 | + } | |
| 962 | + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { | |
| 963 | + jas_logerrorf("cannot write COM marker\n"); | |
| 964 | + return -1; | |
| 965 | + } | |
| 966 | + jpc_ms_destroy(enc->mrk); | |
| 967 | + enc->mrk = 0; | |
| 968 | + | |
| 969 | +#if 0 | |
| 970 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_CRG))) { | |
| 971 | + return -1; | |
| 972 | + } | |
| 973 | + crg = &enc->mrk->parms.crg; | |
| 974 | + crg->comps = jas_alloc2(crg->numcomps, sizeof(jpc_crgcomp_t)); | |
| 975 | + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { | |
| 976 | + jas_logerrorf("cannot write CRG marker\n"); | |
| 977 | + return -1; | |
| 978 | + } | |
| 979 | + jpc_ms_destroy(enc->mrk); | |
| 980 | + enc->mrk = 0; | |
| 981 | +#endif | |
| 982 | + | |
| 983 | + tcp = &cp->tcp; | |
| 984 | + tccp = &cp->tccp; | |
| 985 | + for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) { | |
| 986 | + tsfb = jpc_cod_gettsfb(tccp->qmfbid, tccp->maxrlvls - 1); | |
| 987 | + jpc_tsfb_getbands(tsfb, 0, 0, 1 << tccp->maxrlvls, 1 << tccp->maxrlvls, | |
| 988 | + bandinfos); | |
| 989 | + jpc_tsfb_destroy(tsfb); | |
| 990 | + numbands = 3 * tccp->maxrlvls - 2; | |
| 991 | + for (bandno = 0, bandinfo = bandinfos; bandno < numbands; | |
| 992 | + ++bandno, ++bandinfo) { | |
| 993 | + rlvlno = (bandno) ? ((bandno - 1) / 3 + 1) : 0; | |
| 994 | + analgain = JPC_NOMINALGAIN(tccp->qmfbid, tccp->maxrlvls, | |
| 995 | + rlvlno, bandinfo->orient); | |
| 996 | + if (!tcp->intmode) { | |
| 997 | + absstepsize = jpc_fix_div(jpc_inttofix(1 << | |
| 998 | + (analgain + 1)), bandinfo->synenergywt); | |
| 999 | + } else { | |
| 1000 | + absstepsize = jpc_inttofix(1); | |
| 1001 | + } | |
| 1002 | + const uint_fast32_t stepsize = | |
| 1003 | + jpc_abstorelstepsize(absstepsize, | |
| 1004 | + cp->ccps[cmptno].prec + analgain); | |
| 1005 | + if (stepsize == UINT_FAST32_MAX) | |
| 1006 | + return -1; | |
| 1007 | + cp->ccps[cmptno].stepsizes[bandno] = stepsize; | |
| 1008 | + } | |
| 1009 | + cp->ccps[cmptno].numstepsizes = numbands; | |
| 1010 | + } | |
| 1011 | + | |
| 1012 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_COD))) { | |
| 1013 | + jas_logerrorf("cannot create COD marker\n"); | |
| 1014 | + return -1; | |
| 1015 | + } | |
| 1016 | + cod = &enc->mrk->parms.cod; | |
| 1017 | + cod->csty = cp->tccp.csty | cp->tcp.csty; | |
| 1018 | + cod->compparms.csty = cp->tccp.csty | cp->tcp.csty; | |
| 1019 | + cod->compparms.numdlvls = cp->tccp.maxrlvls - 1; | |
| 1020 | + cod->compparms.numrlvls = cp->tccp.maxrlvls; | |
| 1021 | + cod->prg = cp->tcp.prg; | |
| 1022 | + cod->numlyrs = cp->tcp.numlyrs; | |
| 1023 | + cod->compparms.cblkwidthval = JPC_COX_CBLKSIZEEXPN(cp->tccp.cblkwidthexpn); | |
| 1024 | + cod->compparms.cblkheightval = JPC_COX_CBLKSIZEEXPN(cp->tccp.cblkheightexpn); | |
| 1025 | + cod->compparms.cblksty = cp->tccp.cblksty; | |
| 1026 | + cod->compparms.qmfbid = cp->tccp.qmfbid; | |
| 1027 | + cod->mctrans = (cp->tcp.mctid != JPC_MCT_NONE); | |
| 1028 | + if (tccp->csty & JPC_COX_PRT) { | |
| 1029 | + for (rlvlno = 0; rlvlno < tccp->maxrlvls; ++rlvlno) { | |
| 1030 | + cod->compparms.rlvls[rlvlno].parwidthval = tccp->prcwidthexpns[rlvlno]; | |
| 1031 | + cod->compparms.rlvls[rlvlno].parheightval = tccp->prcheightexpns[rlvlno]; | |
| 1032 | + } | |
| 1033 | + } | |
| 1034 | + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { | |
| 1035 | + jas_logerrorf("cannot write COD marker\n"); | |
| 1036 | + return -1; | |
| 1037 | + } | |
| 1038 | + jpc_ms_destroy(enc->mrk); | |
| 1039 | + enc->mrk = 0; | |
| 1040 | + | |
| 1041 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_QCD))) { | |
| 1042 | + jas_logerrorf("cannot create QCD marker\n"); | |
| 1043 | + return -1; | |
| 1044 | + } | |
| 1045 | + qcd = &enc->mrk->parms.qcd; | |
| 1046 | + qcd->compparms.qntsty = (tccp->qmfbid == JPC_COX_INS) ? | |
| 1047 | + JPC_QCX_SEQNT : JPC_QCX_NOQNT; | |
| 1048 | + qcd->compparms.numstepsizes = cp->ccps[0].numstepsizes; | |
| 1049 | + qcd->compparms.numguard = cp->tccp.numgbits; | |
| 1050 | + qcd->compparms.stepsizes = cp->ccps[0].stepsizes; | |
| 1051 | + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { | |
| 1052 | + jas_logerrorf("cannot write marker\n"); | |
| 1053 | + return -1; | |
| 1054 | + } | |
| 1055 | + /* We do not want the step size array to be freed! */ | |
| 1056 | + qcd->compparms.stepsizes = 0; | |
| 1057 | + jpc_ms_destroy(enc->mrk); | |
| 1058 | + enc->mrk = 0; | |
| 1059 | + | |
| 1060 | + tccp = &cp->tccp; | |
| 1061 | + for (cmptno = 1; cmptno < cp->numcmpts; ++cmptno) { | |
| 1062 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_QCC))) { | |
| 1063 | + jas_logerrorf("cannot create QCC marker\n"); | |
| 1064 | + return -1; | |
| 1065 | + } | |
| 1066 | + qcc = &enc->mrk->parms.qcc; | |
| 1067 | + qcc->compno = cmptno; | |
| 1068 | + qcc->compparms.qntsty = (tccp->qmfbid == JPC_COX_INS) ? | |
| 1069 | + JPC_QCX_SEQNT : JPC_QCX_NOQNT; | |
| 1070 | + qcc->compparms.numstepsizes = cp->ccps[cmptno].numstepsizes; | |
| 1071 | + qcc->compparms.numguard = cp->tccp.numgbits; | |
| 1072 | + qcc->compparms.stepsizes = cp->ccps[cmptno].stepsizes; | |
| 1073 | + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { | |
| 1074 | + jas_logerrorf("cannot write marker\n"); | |
| 1075 | + return -1; | |
| 1076 | + } | |
| 1077 | + /* We do not want the step size array to be freed! */ | |
| 1078 | + qcc->compparms.stepsizes = 0; | |
| 1079 | + jpc_ms_destroy(enc->mrk); | |
| 1080 | + enc->mrk = 0; | |
| 1081 | + } | |
| 1082 | + | |
| 1083 | +#define MAINTLRLEN 2 | |
| 1084 | + mainhdrlen = jas_stream_getrwcount(enc->out) - startoff; | |
| 1085 | + enc->len += mainhdrlen; | |
| 1086 | + if (enc->cp->totalsize != UINT_FAST32_MAX) { | |
| 1087 | + uint_fast32_t overhead; | |
| 1088 | + overhead = mainhdrlen + MAINTLRLEN; | |
| 1089 | + enc->mainbodysize = (enc->cp->totalsize >= overhead) ? | |
| 1090 | + (enc->cp->totalsize - overhead) : 0; | |
| 1091 | + } else { | |
| 1092 | + enc->mainbodysize = UINT_FAST32_MAX; | |
| 1093 | + } | |
| 1094 | + | |
| 1095 | + return 0; | |
| 1096 | +} | |
| 1097 | + | |
| 1098 | +static int jpc_enc_encodemainbody(jpc_enc_t *enc) | |
| 1099 | +{ | |
| 1100 | + int tileno; | |
| 1101 | + jpc_sot_t *sot; | |
| 1102 | + jpc_enc_tcmpt_t *comp; | |
| 1103 | + jpc_enc_tcmpt_t *endcomps; | |
| 1104 | + jpc_enc_band_t *band; | |
| 1105 | + jpc_enc_band_t *endbands; | |
| 1106 | + jpc_enc_rlvl_t *lvl; | |
| 1107 | + unsigned rlvlno; | |
| 1108 | + jpc_qcc_t *qcc; | |
| 1109 | + jpc_cod_t *cod; | |
| 1110 | + int adjust; | |
| 1111 | + int absbandno; | |
| 1112 | + long tilehdrlen; | |
| 1113 | + long tilelen; | |
| 1114 | + jpc_enc_tile_t *tile; | |
| 1115 | + jpc_enc_cp_t *cp; | |
| 1116 | + double rho; | |
| 1117 | + unsigned cmptno; | |
| 1118 | + int samestepsizes; | |
| 1119 | + jpc_enc_ccp_t *ccps; | |
| 1120 | + jpc_enc_tccp_t *tccp; | |
| 1121 | + int bandno; | |
| 1122 | + int mingbits; | |
| 1123 | + int actualnumbps; | |
| 1124 | + jpc_fix_t mxmag; | |
| 1125 | + jpc_fix_t mag; | |
| 1126 | + int numgbits; | |
| 1127 | + | |
| 1128 | + cp = enc->cp; | |
| 1129 | + | |
| 1130 | + for (tileno = 0; tileno < JAS_CAST(int, cp->numtiles); ++tileno) { | |
| 1131 | + if (!(enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, | |
| 1132 | + tileno))) { | |
| 1133 | + jas_logerrorf("cannot create tile\n"); | |
| 1134 | + return -1; | |
| 1135 | + } | |
| 1136 | + | |
| 1137 | + tile = enc->curtile; | |
| 1138 | + | |
| 1139 | + if (jas_get_debug_level() >= 10) { | |
| 1140 | + jpc_enc_dump(enc); | |
| 1141 | + } | |
| 1142 | + | |
| 1143 | + for (cmptno = 0, comp = tile->tcmpts; cmptno < tile->numtcmpts; ++cmptno, ++comp) { | |
| 1144 | + if (!cp->ccps[cmptno].sgnd) { | |
| 1145 | + adjust = 1 << (cp->ccps[cmptno].prec - 1); | |
| 1146 | + for (jas_matind_t i = 0; i < jas_matrix_numrows(comp->data); ++i) { | |
| 1147 | + for (jas_matind_t j = 0; j < jas_matrix_numcols(comp->data); ++j) { | |
| 1148 | + *jas_matrix_getref(comp->data, i, j) -= adjust; | |
| 1149 | + } | |
| 1150 | + } | |
| 1151 | + } | |
| 1152 | + } | |
| 1153 | + | |
| 1154 | + if (!tile->intmode) { | |
| 1155 | + endcomps = &tile->tcmpts[tile->numtcmpts]; | |
| 1156 | + for (comp = tile->tcmpts; comp != endcomps; ++comp) { | |
| 1157 | + jas_matrix_asl(comp->data, JPC_FIX_FRACBITS); | |
| 1158 | + } | |
| 1159 | + } | |
| 1160 | + | |
| 1161 | + switch (tile->mctid) { | |
| 1162 | + case JPC_MCT_RCT: | |
| 1163 | +assert(jas_image_numcmpts(enc->image) == 3); | |
| 1164 | + jpc_rct(tile->tcmpts[0].data, tile->tcmpts[1].data, | |
| 1165 | + tile->tcmpts[2].data); | |
| 1166 | + break; | |
| 1167 | + case JPC_MCT_ICT: | |
| 1168 | +assert(jas_image_numcmpts(enc->image) == 3); | |
| 1169 | + jpc_ict(tile->tcmpts[0].data, tile->tcmpts[1].data, | |
| 1170 | + tile->tcmpts[2].data); | |
| 1171 | + break; | |
| 1172 | + default: | |
| 1173 | + break; | |
| 1174 | + } | |
| 1175 | + | |
| 1176 | + for (unsigned i = 0; i < jas_image_numcmpts(enc->image); ++i) { | |
| 1177 | + comp = &tile->tcmpts[i]; | |
| 1178 | + jpc_tsfb_analyze(comp->tsfb, comp->data); | |
| 1179 | + | |
| 1180 | + } | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + endcomps = &tile->tcmpts[tile->numtcmpts]; | |
| 1184 | + for (cmptno = 0, comp = tile->tcmpts; comp != endcomps; ++cmptno, ++comp) { | |
| 1185 | + mingbits = 0; | |
| 1186 | + absbandno = 0; | |
| 1187 | + /* All bands must have a corresponding quantizer step size, | |
| 1188 | + even if they contain no samples and are never coded. */ | |
| 1189 | + /* Some bands may not be hit by the loop below, so we must | |
| 1190 | + initialize all of the step sizes to a sane value. */ | |
| 1191 | + memset(comp->stepsizes, 0, sizeof(comp->stepsizes)); | |
| 1192 | + for (rlvlno = 0, lvl = comp->rlvls; rlvlno < comp->numrlvls; ++rlvlno, ++lvl) { | |
| 1193 | + if (!lvl->bands) { | |
| 1194 | + absbandno += rlvlno ? 3 : 1; | |
| 1195 | + continue; | |
| 1196 | + } | |
| 1197 | + endbands = &lvl->bands[lvl->numbands]; | |
| 1198 | + for (band = lvl->bands; band != endbands; ++band) { | |
| 1199 | + if (!band->data) { | |
| 1200 | + ++absbandno; | |
| 1201 | + continue; | |
| 1202 | + } | |
| 1203 | + mxmag = 0; | |
| 1204 | + for (jas_matind_t y = 0; y < jas_matrix_numrows(band->data); ++y) { | |
| 1205 | + for (jas_matind_t x = 0; x < jas_matrix_numcols(band->data); ++x) { | |
| 1206 | + mag = JAS_ABS(jas_matrix_get(band->data, y, x)); | |
| 1207 | + if (mag > mxmag) { | |
| 1208 | + mxmag = mag; | |
| 1209 | + } | |
| 1210 | + } | |
| 1211 | + } | |
| 1212 | + if (tile->intmode) { | |
| 1213 | + actualnumbps = jpc_fix_firstone(mxmag) + 1; | |
| 1214 | + } else { | |
| 1215 | + actualnumbps = jpc_fix_firstone(mxmag) + 1 - JPC_FIX_FRACBITS; | |
| 1216 | + } | |
| 1217 | + numgbits = actualnumbps - (cp->ccps[cmptno].prec - 1 + | |
| 1218 | + band->analgain); | |
| 1219 | +#if 0 | |
| 1220 | + jas_eprintf("%d %d mag=%d actual=%d numgbits=%d\n", | |
| 1221 | + cp->ccps[cmptno].prec, band->analgain, mxmag, | |
| 1222 | + actualnumbps, numgbits); | |
| 1223 | +#endif | |
| 1224 | + if (numgbits > mingbits) { | |
| 1225 | + mingbits = numgbits; | |
| 1226 | + } | |
| 1227 | + if (!tile->intmode) { | |
| 1228 | + band->absstepsize = jpc_fix_div(jpc_inttofix(1 | |
| 1229 | + << (band->analgain + 1)), | |
| 1230 | + band->synweight); | |
| 1231 | + } else { | |
| 1232 | + band->absstepsize = jpc_inttofix(1); | |
| 1233 | + } | |
| 1234 | + const uint_fast32_t stepsize = jpc_abstorelstepsize( | |
| 1235 | + band->absstepsize, cp->ccps[cmptno].prec + | |
| 1236 | + band->analgain); | |
| 1237 | + if (stepsize == UINT_FAST32_MAX) | |
| 1238 | + return -1; | |
| 1239 | + band->stepsize = stepsize; | |
| 1240 | + band->numbps = cp->tccp.numgbits + | |
| 1241 | + JPC_QCX_GETEXPN(band->stepsize) - 1; | |
| 1242 | + | |
| 1243 | + if ((!tile->intmode) && band->data) { | |
| 1244 | + jpc_quantize(band->data, band->absstepsize); | |
| 1245 | + } | |
| 1246 | + | |
| 1247 | + comp->stepsizes[absbandno] = band->stepsize; | |
| 1248 | + ++absbandno; | |
| 1249 | + } | |
| 1250 | + } | |
| 1251 | + | |
| 1252 | + assert(JPC_FIX_FRACBITS >= JPC_NUMEXTRABITS); | |
| 1253 | + if (!tile->intmode) { | |
| 1254 | + jas_matrix_divpow2(comp->data, JPC_FIX_FRACBITS - JPC_NUMEXTRABITS); | |
| 1255 | + } else { | |
| 1256 | + jas_matrix_asl(comp->data, JPC_NUMEXTRABITS); | |
| 1257 | + } | |
| 1258 | + | |
| 1259 | +#if 0 | |
| 1260 | + jas_eprintf("numgbits %d mingbits %d\n", cp->tccp.numgbits, | |
| 1261 | + mingbits); | |
| 1262 | +#endif | |
| 1263 | + if (mingbits > cp->tccp.numgbits) { | |
| 1264 | + jas_logerrorf("error: too few guard bits (%d < %d)\n", | |
| 1265 | + cp->tccp.numgbits, mingbits); | |
| 1266 | + return -1; | |
| 1267 | + } | |
| 1268 | + } | |
| 1269 | + | |
| 1270 | + if (!(enc->tmpstream = jas_stream_memopen(0, 0))) { | |
| 1271 | + jas_logerrorf("cannot open tmp file\n"); | |
| 1272 | + return -1; | |
| 1273 | + } | |
| 1274 | + | |
| 1275 | + /* Write the tile header. */ | |
| 1276 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_SOT))) { | |
| 1277 | + return -1; | |
| 1278 | + } | |
| 1279 | + sot = &enc->mrk->parms.sot; | |
| 1280 | + sot->len = 0; | |
| 1281 | + sot->tileno = tileno; | |
| 1282 | + sot->partno = 0; | |
| 1283 | + sot->numparts = 1; | |
| 1284 | + if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { | |
| 1285 | + jas_logerrorf("cannot write SOT marker\n"); | |
| 1286 | + return -1; | |
| 1287 | + } | |
| 1288 | + jpc_ms_destroy(enc->mrk); | |
| 1289 | + enc->mrk = 0; | |
| 1290 | + | |
| 1291 | +/************************************************************************/ | |
| 1292 | +/************************************************************************/ | |
| 1293 | +/************************************************************************/ | |
| 1294 | + | |
| 1295 | + tccp = &cp->tccp; | |
| 1296 | + for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) { | |
| 1297 | + comp = &tile->tcmpts[cmptno]; | |
| 1298 | + if (comp->numrlvls != tccp->maxrlvls) { | |
| 1299 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_COD))) { | |
| 1300 | + return -1; | |
| 1301 | + } | |
| 1302 | +/* XXX = this is not really correct. we are using comp #0's precint sizes | |
| 1303 | +and other characteristics */ | |
| 1304 | + comp = &tile->tcmpts[0]; | |
| 1305 | + cod = &enc->mrk->parms.cod; | |
| 1306 | + cod->compparms.csty = 0; | |
| 1307 | + cod->compparms.numdlvls = comp->numrlvls - 1; | |
| 1308 | + cod->prg = tile->prg; | |
| 1309 | + cod->numlyrs = tile->numlyrs; | |
| 1310 | + cod->compparms.cblkwidthval = JPC_COX_CBLKSIZEEXPN(comp->cblkwidthexpn); | |
| 1311 | + cod->compparms.cblkheightval = JPC_COX_CBLKSIZEEXPN(comp->cblkheightexpn); | |
| 1312 | + cod->compparms.cblksty = comp->cblksty; | |
| 1313 | + cod->compparms.qmfbid = comp->qmfbid; | |
| 1314 | + cod->mctrans = (tile->mctid != JPC_MCT_NONE); | |
| 1315 | + for (unsigned i = 0; i < comp->numrlvls; ++i) { | |
| 1316 | + cod->compparms.rlvls[i].parwidthval = comp->rlvls[i].prcwidthexpn; | |
| 1317 | + cod->compparms.rlvls[i].parheightval = comp->rlvls[i].prcheightexpn; | |
| 1318 | + } | |
| 1319 | + if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { | |
| 1320 | + return -1; | |
| 1321 | + } | |
| 1322 | + jpc_ms_destroy(enc->mrk); | |
| 1323 | + enc->mrk = 0; | |
| 1324 | + } | |
| 1325 | + } | |
| 1326 | + | |
| 1327 | + for (cmptno = 0, comp = tile->tcmpts; cmptno < cp->numcmpts; ++cmptno, ++comp) { | |
| 1328 | + ccps = &cp->ccps[cmptno]; | |
| 1329 | + if (JAS_CAST(int, ccps->numstepsizes) == comp->numstepsizes) { | |
| 1330 | + samestepsizes = 1; | |
| 1331 | + for (bandno = 0; bandno < JAS_CAST(int, ccps->numstepsizes); | |
| 1332 | + ++bandno) { | |
| 1333 | + if (ccps->stepsizes[bandno] != comp->stepsizes[bandno]) { | |
| 1334 | + samestepsizes = 0; | |
| 1335 | + break; | |
| 1336 | + } | |
| 1337 | + } | |
| 1338 | + } else { | |
| 1339 | + samestepsizes = 0; | |
| 1340 | + } | |
| 1341 | + if (!samestepsizes) { | |
| 1342 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_QCC))) { | |
| 1343 | + return -1; | |
| 1344 | + } | |
| 1345 | + qcc = &enc->mrk->parms.qcc; | |
| 1346 | + qcc->compno = cmptno; | |
| 1347 | + qcc->compparms.numguard = cp->tccp.numgbits; | |
| 1348 | + qcc->compparms.qntsty = (comp->qmfbid == JPC_COX_INS) ? | |
| 1349 | + JPC_QCX_SEQNT : JPC_QCX_NOQNT; | |
| 1350 | + qcc->compparms.numstepsizes = comp->numstepsizes; | |
| 1351 | + qcc->compparms.stepsizes = comp->stepsizes; | |
| 1352 | + if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { | |
| 1353 | + return -1; | |
| 1354 | + } | |
| 1355 | + qcc->compparms.stepsizes = 0; | |
| 1356 | + jpc_ms_destroy(enc->mrk); | |
| 1357 | + enc->mrk = 0; | |
| 1358 | + } | |
| 1359 | + } | |
| 1360 | + | |
| 1361 | + /* Write a SOD marker to indicate the end of the tile header. */ | |
| 1362 | + if (!(enc->mrk = jpc_ms_create(JPC_MS_SOD))) { | |
| 1363 | + return -1; | |
| 1364 | + } | |
| 1365 | + if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { | |
| 1366 | + jas_logerrorf("cannot write SOD marker\n"); | |
| 1367 | + return -1; | |
| 1368 | + } | |
| 1369 | + jpc_ms_destroy(enc->mrk); | |
| 1370 | + enc->mrk = 0; | |
| 1371 | + tilehdrlen = jas_stream_getrwcount(enc->tmpstream); | |
| 1372 | + assert(tilehdrlen >= 0); | |
| 1373 | + | |
| 1374 | +/************************************************************************/ | |
| 1375 | +/************************************************************************/ | |
| 1376 | +/************************************************************************/ | |
| 1377 | + | |
| 1378 | + if (jpc_enc_enccblks(enc)) { | |
| 1379 | + return -1; | |
| 1380 | + } | |
| 1381 | + | |
| 1382 | + cp = enc->cp; | |
| 1383 | + rho = (double) (tile->brx - tile->tlx) * (tile->bry - tile->tly) / | |
| 1384 | + ((cp->refgrdwidth - cp->imgareatlx) * (cp->refgrdheight - | |
| 1385 | + cp->imgareatly)); | |
| 1386 | + tile->rawsize = cp->rawsize * rho; | |
| 1387 | + | |
| 1388 | + for (unsigned lyrno = 0; lyrno < tile->numlyrs - 1; ++lyrno) { | |
| 1389 | + tile->lyrsizes[lyrno] = tile->rawsize * jpc_fixtodbl( | |
| 1390 | + cp->tcp.ilyrrates[lyrno]); | |
| 1391 | + } | |
| 1392 | + | |
| 1393 | + if (cp->totalsize != UINT_FAST32_MAX) { | |
| 1394 | + tile->lyrsizes[tile->numlyrs - 1] = (rho * enc->mainbodysize); | |
| 1395 | + } else { | |
| 1396 | + tile->lyrsizes[tile->numlyrs - 1] = UINT_FAST32_MAX; | |
| 1397 | + } | |
| 1398 | + | |
| 1399 | +#if 0 | |
| 1400 | + jas_eprintf("TESTING %ld %ld\n", cp->totalsize != UINT_FAST32_MAX, | |
| 1401 | + tile->lyrsizes[0]); | |
| 1402 | +#endif | |
| 1403 | + for (unsigned lyrno = 0; lyrno < tile->numlyrs; ++lyrno) { | |
| 1404 | + if (tile->lyrsizes[lyrno] != UINT_FAST32_MAX) { | |
| 1405 | + if (JAS_CAST(uint_fast32_t, tilehdrlen) <= tile->lyrsizes[lyrno]) { | |
| 1406 | + tile->lyrsizes[lyrno] -= tilehdrlen; | |
| 1407 | + } else { | |
| 1408 | + tile->lyrsizes[lyrno] = 0; | |
| 1409 | + } | |
| 1410 | + } | |
| 1411 | + } | |
| 1412 | + | |
| 1413 | + if (rateallocate(enc, tile->numlyrs, tile->lyrsizes)) { | |
| 1414 | + return -1; | |
| 1415 | + } | |
| 1416 | + | |
| 1417 | +#if 0 | |
| 1418 | + jas_eprintf("ENCODE TILE DATA\n"); | |
| 1419 | +#endif | |
| 1420 | + if (jpc_enc_encodetiledata(enc)) { | |
| 1421 | + jas_logerrorf("dotile failed\n"); | |
| 1422 | + return -1; | |
| 1423 | + } | |
| 1424 | + | |
| 1425 | +/************************************************************************/ | |
| 1426 | +/************************************************************************/ | |
| 1427 | +/************************************************************************/ | |
| 1428 | + | |
| 1429 | +/************************************************************************/ | |
| 1430 | +/************************************************************************/ | |
| 1431 | +/************************************************************************/ | |
| 1432 | + | |
| 1433 | + tilelen = jas_stream_tell(enc->tmpstream); | |
| 1434 | + | |
| 1435 | + if (jas_stream_seek(enc->tmpstream, 6, SEEK_SET) < 0) { | |
| 1436 | + return -1; | |
| 1437 | + } | |
| 1438 | + jpc_putuint32(enc->tmpstream, tilelen); | |
| 1439 | + | |
| 1440 | + if (jas_stream_seek(enc->tmpstream, 0, SEEK_SET) < 0) { | |
| 1441 | + return -1; | |
| 1442 | + } | |
| 1443 | + if (jpc_putdata(enc->out, enc->tmpstream, -1)) { | |
| 1444 | + return -1; | |
| 1445 | + } | |
| 1446 | + enc->len += tilelen; | |
| 1447 | + | |
| 1448 | + jas_stream_close(enc->tmpstream); | |
| 1449 | + enc->tmpstream = 0; | |
| 1450 | + | |
| 1451 | + jpc_enc_tile_destroy(enc->curtile); | |
| 1452 | + enc->curtile = 0; | |
| 1453 | + | |
| 1454 | + } | |
| 1455 | + | |
| 1456 | + return 0; | |
| 1457 | +} | |
| 1458 | + | |
| 1459 | +int jpc_enc_encodetiledata(jpc_enc_t *enc) | |
| 1460 | +{ | |
| 1461 | +assert(enc->tmpstream); | |
| 1462 | + if (jpc_enc_encpkts(enc, enc->tmpstream)) { | |
| 1463 | + return -1; | |
| 1464 | + } | |
| 1465 | + return 0; | |
| 1466 | +} | |
| 1467 | + | |
| 1468 | +void jpc_quantize(jas_matrix_t *data, jpc_fix_t stepsize) | |
| 1469 | +{ | |
| 1470 | + jpc_fix_t t; | |
| 1471 | + | |
| 1472 | + if (stepsize == jpc_inttofix(1)) { | |
| 1473 | + return; | |
| 1474 | + } | |
| 1475 | + | |
| 1476 | + for (jas_matind_t i = 0; i < jas_matrix_numrows(data); ++i) { | |
| 1477 | + for (jas_matind_t j = 0; j < jas_matrix_numcols(data); ++j) { | |
| 1478 | + t = jas_matrix_get(data, i, j); | |
| 1479 | + | |
| 1480 | +{ | |
| 1481 | + if (t < 0) { | |
| 1482 | + t = jpc_fix_neg(jpc_fix_div(jpc_fix_neg(t), stepsize)); | |
| 1483 | + } else { | |
| 1484 | + t = jpc_fix_div(t, stepsize); | |
| 1485 | + } | |
| 1486 | +} | |
| 1487 | + | |
| 1488 | + jas_matrix_set(data, i, j, t); | |
| 1489 | + } | |
| 1490 | + } | |
| 1491 | +} | |
| 1492 | + | |
| 1493 | +void calcrdslopes(jpc_enc_cblk_t *cblk) | |
| 1494 | +{ | |
| 1495 | + jpc_enc_pass_t *endpasses; | |
| 1496 | + jpc_enc_pass_t *pass0; | |
| 1497 | + jpc_enc_pass_t *pass1; | |
| 1498 | + jpc_enc_pass_t *pass2; | |
| 1499 | + jpc_flt_t slope0; | |
| 1500 | + jpc_flt_t slope; | |
| 1501 | + jpc_flt_t dd; | |
| 1502 | + long dr; | |
| 1503 | + | |
| 1504 | + endpasses = &cblk->passes[cblk->numpasses]; | |
| 1505 | + pass2 = cblk->passes; | |
| 1506 | + slope0 = 0; | |
| 1507 | + while (pass2 != endpasses) { | |
| 1508 | + pass0 = 0; | |
| 1509 | + for (pass1 = cblk->passes; pass1 != endpasses; ++pass1) { | |
| 1510 | + dd = pass1->cumwmsedec; | |
| 1511 | + dr = pass1->end; | |
| 1512 | + if (pass0) { | |
| 1513 | + dd -= pass0->cumwmsedec; | |
| 1514 | + dr -= pass0->end; | |
| 1515 | + } | |
| 1516 | + if (dd <= 0) { | |
| 1517 | + pass1->rdslope = JPC_BADRDSLOPE; | |
| 1518 | + if (pass1 >= pass2) { | |
| 1519 | + pass2 = &pass1[1]; | |
| 1520 | + } | |
| 1521 | + continue; | |
| 1522 | + } | |
| 1523 | + if (pass1 < pass2 && pass1->rdslope <= 0) { | |
| 1524 | + continue; | |
| 1525 | + } | |
| 1526 | + if (!dr) { | |
| 1527 | + assert(pass0); | |
| 1528 | + pass0->rdslope = 0; | |
| 1529 | + break; | |
| 1530 | + } | |
| 1531 | + slope = dd / dr; | |
| 1532 | + if (pass0 && slope >= slope0) { | |
| 1533 | + pass0->rdslope = 0; | |
| 1534 | + break; | |
| 1535 | + } | |
| 1536 | + pass1->rdslope = slope; | |
| 1537 | + if (pass1 >= pass2) { | |
| 1538 | + pass2 = &pass1[1]; | |
| 1539 | + } | |
| 1540 | + pass0 = pass1; | |
| 1541 | + slope0 = slope; | |
| 1542 | + } | |
| 1543 | + } | |
| 1544 | + | |
| 1545 | +#if 0 | |
| 1546 | + for (pass0 = cblk->passes; pass0 != endpasses; ++pass0) { | |
| 1547 | +if (pass0->rdslope > 0.0) { | |
| 1548 | + jas_eprintf("pass %02d nmsedec=%lf dec=%lf end=%d %lf\n", pass0 - cblk->passes, | |
| 1549 | + fixtodbl(pass0->nmsedec), pass0->wmsedec, pass0->end, pass0->rdslope); | |
| 1550 | +} | |
| 1551 | + } | |
| 1552 | +#endif | |
| 1553 | +} | |
| 1554 | + | |
| 1555 | +void dump_layeringinfo(jpc_enc_t *enc) | |
| 1556 | +{ | |
| 1557 | + | |
| 1558 | + jpc_enc_tcmpt_t *tcmpt; | |
| 1559 | + unsigned tcmptno; | |
| 1560 | + jpc_enc_rlvl_t *rlvl; | |
| 1561 | + unsigned rlvlno; | |
| 1562 | + jpc_enc_band_t *band; | |
| 1563 | + unsigned bandno; | |
| 1564 | + jpc_enc_prc_t *prc; | |
| 1565 | + unsigned prcno; | |
| 1566 | + jpc_enc_cblk_t *cblk; | |
| 1567 | + unsigned cblkno; | |
| 1568 | + jpc_enc_pass_t *pass; | |
| 1569 | + unsigned passno; | |
| 1570 | + jpc_enc_tile_t *tile; | |
| 1571 | + | |
| 1572 | + tile = enc->curtile; | |
| 1573 | + | |
| 1574 | + for (unsigned lyrno = 0; lyrno < tile->numlyrs; ++lyrno) { | |
| 1575 | + jas_loginfof("lyrno = %02u\n", lyrno); | |
| 1576 | + for (tcmptno = 0, tcmpt = tile->tcmpts; tcmptno < tile->numtcmpts; | |
| 1577 | + ++tcmptno, ++tcmpt) { | |
| 1578 | + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; | |
| 1579 | + ++rlvlno, ++rlvl) { | |
| 1580 | + if (!rlvl->bands) { | |
| 1581 | + continue; | |
| 1582 | + } | |
| 1583 | + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; | |
| 1584 | + ++bandno, ++band) { | |
| 1585 | + if (!band->data) { | |
| 1586 | + continue; | |
| 1587 | + } | |
| 1588 | + for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; | |
| 1589 | + ++prcno, ++prc) { | |
| 1590 | + if (!prc->cblks) { | |
| 1591 | + continue; | |
| 1592 | + } | |
| 1593 | + for (cblkno = 0, cblk = prc->cblks; cblkno < | |
| 1594 | + prc->numcblks; ++cblkno, ++cblk) { | |
| 1595 | + for (passno = 0, pass = cblk->passes; passno < | |
| 1596 | + cblk->numpasses && pass->lyrno == lyrno; | |
| 1597 | + ++passno, ++pass) { | |
| 1598 | + jas_loginfof("lyrno=%02d cmptno=%02d rlvlno=%02d bandno=%02d prcno=%02d cblkno=%03d passno=%03d\n", | |
| 1599 | + lyrno, tcmptno, rlvlno, bandno, prcno, | |
| 1600 | + cblkno, passno); | |
| 1601 | + } | |
| 1602 | + } | |
| 1603 | + } | |
| 1604 | + } | |
| 1605 | + } | |
| 1606 | + } | |
| 1607 | + } | |
| 1608 | +} | |
| 1609 | + | |
| 1610 | +int rateallocate(jpc_enc_t *enc, unsigned numlyrs, uint_fast32_t *cumlens) | |
| 1611 | +{ | |
| 1612 | + int ret = 0; | |
| 1613 | + jpc_flt_t lo; | |
| 1614 | + jpc_flt_t hi; | |
| 1615 | + jas_stream_t *out; | |
| 1616 | + uint_fast32_t cumlen; | |
| 1617 | + jpc_flt_t thresh; | |
| 1618 | + jpc_flt_t goodthresh; | |
| 1619 | + int success; | |
| 1620 | + long pos; | |
| 1621 | + long oldpos; | |
| 1622 | + int numiters; | |
| 1623 | + | |
| 1624 | + jpc_enc_tcmpt_t *comp; | |
| 1625 | + jpc_enc_tcmpt_t *endcomps; | |
| 1626 | + jpc_enc_rlvl_t *lvl; | |
| 1627 | + jpc_enc_rlvl_t *endlvls; | |
| 1628 | + jpc_enc_band_t *band; | |
| 1629 | + jpc_enc_band_t *endbands; | |
| 1630 | + jpc_enc_cblk_t *cblk; | |
| 1631 | + jpc_enc_cblk_t *endcblks; | |
| 1632 | + jpc_enc_pass_t *pass; | |
| 1633 | + jpc_enc_pass_t *endpasses; | |
| 1634 | + jpc_enc_pass_t *pass1; | |
| 1635 | + jpc_flt_t mxrdslope; | |
| 1636 | + jpc_flt_t mnrdslope; | |
| 1637 | + jpc_enc_tile_t *tile; | |
| 1638 | + jpc_enc_prc_t *prc; | |
| 1639 | + unsigned prcno; | |
| 1640 | + | |
| 1641 | + JAS_LOGDEBUGF(10, "starting rate allocation\n"); | |
| 1642 | + | |
| 1643 | + tile = enc->curtile; | |
| 1644 | + | |
| 1645 | + for (unsigned lyrno = 1; lyrno < numlyrs - 1; ++lyrno) { | |
| 1646 | + assert(cumlens[lyrno - 1] <= cumlens[lyrno]); | |
| 1647 | + } | |
| 1648 | + | |
| 1649 | + if (!(out = jas_stream_memopen(0, 0))) { | |
| 1650 | + ret = -1; | |
| 1651 | + goto done; | |
| 1652 | + } | |
| 1653 | + | |
| 1654 | + /* Find minimum and maximum R-D slope values. */ | |
| 1655 | + mnrdslope = DBL_MAX; | |
| 1656 | + mxrdslope = 0; | |
| 1657 | + endcomps = &tile->tcmpts[tile->numtcmpts]; | |
| 1658 | + for (comp = tile->tcmpts; comp != endcomps; ++comp) { | |
| 1659 | + endlvls = &comp->rlvls[comp->numrlvls]; | |
| 1660 | + for (lvl = comp->rlvls; lvl != endlvls; ++lvl) { | |
| 1661 | + if (!lvl->bands) { | |
| 1662 | + continue; | |
| 1663 | + } | |
| 1664 | + endbands = &lvl->bands[lvl->numbands]; | |
| 1665 | + for (band = lvl->bands; band != endbands; ++band) { | |
| 1666 | + if (!band->data) { | |
| 1667 | + continue; | |
| 1668 | + } | |
| 1669 | + for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; | |
| 1670 | + ++prcno, ++prc) { | |
| 1671 | + if (!prc->cblks) { | |
| 1672 | + continue; | |
| 1673 | + } | |
| 1674 | + endcblks = &prc->cblks[prc->numcblks]; | |
| 1675 | + for (cblk = prc->cblks; cblk != endcblks; ++cblk) { | |
| 1676 | + calcrdslopes(cblk); | |
| 1677 | + endpasses = &cblk->passes[cblk->numpasses]; | |
| 1678 | + for (pass = cblk->passes; pass != endpasses; ++pass) { | |
| 1679 | + if (pass->rdslope > 0) { | |
| 1680 | + if (pass->rdslope < mnrdslope) { | |
| 1681 | + mnrdslope = pass->rdslope; | |
| 1682 | + } | |
| 1683 | + if (pass->rdslope > mxrdslope) { | |
| 1684 | + mxrdslope = pass->rdslope; | |
| 1685 | + } | |
| 1686 | + } | |
| 1687 | + } | |
| 1688 | + } | |
| 1689 | + } | |
| 1690 | + } | |
| 1691 | + } | |
| 1692 | + } | |
| 1693 | + JAS_LOGDEBUGF(10, "min rdslope = %f max rdslope = %f\n", mnrdslope, | |
| 1694 | + mxrdslope); | |
| 1695 | + | |
| 1696 | + jpc_init_t2state(enc, true); | |
| 1697 | + | |
| 1698 | + for (unsigned lyrno = 0; lyrno < numlyrs; ++lyrno) { | |
| 1699 | + | |
| 1700 | + lo = mnrdslope; | |
| 1701 | + hi = mxrdslope; | |
| 1702 | + | |
| 1703 | + success = 0; | |
| 1704 | + goodthresh = 0; | |
| 1705 | + numiters = 0; | |
| 1706 | + | |
| 1707 | + do { | |
| 1708 | + | |
| 1709 | + cumlen = cumlens[lyrno]; | |
| 1710 | + if (cumlen == UINT_FAST32_MAX) { | |
| 1711 | + /* Only the last layer can be free of a rate | |
| 1712 | + constraint (e.g., for lossless coding). */ | |
| 1713 | + assert(lyrno == numlyrs - 1); | |
| 1714 | + goodthresh = -1; | |
| 1715 | + success = 1; | |
| 1716 | + break; | |
| 1717 | + } | |
| 1718 | + | |
| 1719 | + thresh = (lo + hi) / 2; | |
| 1720 | + | |
| 1721 | + /* Save the tier 2 coding state. */ | |
| 1722 | + jpc_save_t2state(enc); | |
| 1723 | + oldpos = jas_stream_tell(out); | |
| 1724 | + assert(oldpos >= 0); | |
| 1725 | + | |
| 1726 | + /* Assign all passes with R-D slopes greater than or | |
| 1727 | + equal to the current threshold to this layer. */ | |
| 1728 | + endcomps = &tile->tcmpts[tile->numtcmpts]; | |
| 1729 | + for (comp = tile->tcmpts; comp != endcomps; ++comp) { | |
| 1730 | + endlvls = &comp->rlvls[comp->numrlvls]; | |
| 1731 | + for (lvl = comp->rlvls; lvl != endlvls; ++lvl) { | |
| 1732 | + if (!lvl->bands) { | |
| 1733 | + continue; | |
| 1734 | + } | |
| 1735 | + endbands = &lvl->bands[lvl->numbands]; | |
| 1736 | + for (band = lvl->bands; band != endbands; ++band) { | |
| 1737 | + if (!band->data) { | |
| 1738 | + continue; | |
| 1739 | + } | |
| 1740 | + for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; | |
| 1741 | + ++prcno, ++prc) { | |
| 1742 | + if (!prc->cblks) { | |
| 1743 | + continue; | |
| 1744 | + } | |
| 1745 | + endcblks = &prc->cblks[prc->numcblks]; | |
| 1746 | + for (cblk = prc->cblks; cblk != endcblks; ++cblk) { | |
| 1747 | + if (cblk->curpass) { | |
| 1748 | + endpasses = &cblk->passes[cblk->numpasses]; | |
| 1749 | + pass1 = cblk->curpass; | |
| 1750 | + for (pass = cblk->curpass; pass != | |
| 1751 | + endpasses; ++pass) { | |
| 1752 | + if (pass->rdslope >= thresh) { | |
| 1753 | + pass1 = &pass[1]; | |
| 1754 | + } | |
| 1755 | + } | |
| 1756 | + for (pass = cblk->curpass; pass != pass1; | |
| 1757 | + ++pass) { | |
| 1758 | + pass->lyrno = lyrno; | |
| 1759 | + } | |
| 1760 | + for (; pass != endpasses; ++pass) { | |
| 1761 | + pass->lyrno = -1; | |
| 1762 | + } | |
| 1763 | + } | |
| 1764 | + } | |
| 1765 | + } | |
| 1766 | + } | |
| 1767 | + } | |
| 1768 | + } | |
| 1769 | + | |
| 1770 | + /* Perform tier 2 coding. */ | |
| 1771 | + endcomps = &tile->tcmpts[tile->numtcmpts]; | |
| 1772 | + for (comp = tile->tcmpts; comp != endcomps; ++comp) { | |
| 1773 | + endlvls = &comp->rlvls[comp->numrlvls]; | |
| 1774 | + for (lvl = comp->rlvls; lvl != endlvls; ++lvl) { | |
| 1775 | + if (!lvl->bands) { | |
| 1776 | + continue; | |
| 1777 | + } | |
| 1778 | + for (prcno = 0; prcno < lvl->numprcs; ++prcno) { | |
| 1779 | + if (jpc_enc_encpkt(enc, out, comp - tile->tcmpts, | |
| 1780 | + lvl - comp->rlvls, prcno, lyrno)) { | |
| 1781 | + ret = -1; | |
| 1782 | + goto done; | |
| 1783 | + } | |
| 1784 | + } | |
| 1785 | + } | |
| 1786 | + } | |
| 1787 | + | |
| 1788 | + pos = jas_stream_tell(out); | |
| 1789 | + | |
| 1790 | + /* Check the rate constraint. */ | |
| 1791 | + assert(pos >= 0); | |
| 1792 | + if ((uint_fast32_t)pos > cumlen) { | |
| 1793 | + /* The rate is too high. */ | |
| 1794 | + lo = thresh; | |
| 1795 | + } else if ((uint_fast32_t)pos <= cumlen) { | |
| 1796 | + /* The rate is low enough, so try higher. */ | |
| 1797 | + hi = thresh; | |
| 1798 | + if (!success || thresh < goodthresh) { | |
| 1799 | + goodthresh = thresh; | |
| 1800 | + success = 1; | |
| 1801 | + } | |
| 1802 | + } | |
| 1803 | + | |
| 1804 | + /* Save the tier 2 coding state. */ | |
| 1805 | + jpc_restore_t2state(enc); | |
| 1806 | + if (jas_stream_seek(out, oldpos, SEEK_SET) < 0) { | |
| 1807 | + ret = -1; | |
| 1808 | + goto done; | |
| 1809 | + } | |
| 1810 | + | |
| 1811 | + JAS_LOGDEBUGF(10, "maxlen=%08ld actuallen=%08ld thresh=%f\n", | |
| 1812 | + cumlen, pos, thresh); | |
| 1813 | + | |
| 1814 | + ++numiters; | |
| 1815 | + } while (lo < hi - 1e-3 && numiters < 32); | |
| 1816 | + | |
| 1817 | + if (!success) { | |
| 1818 | + jas_logwarnf("warning: empty layer generated\n"); | |
| 1819 | + } | |
| 1820 | + | |
| 1821 | + JAS_LOGDEBUGF(10, "success %d goodthresh %f\n", success, goodthresh); | |
| 1822 | + | |
| 1823 | + /* Assign all passes with R-D slopes greater than or | |
| 1824 | + equal to the selected threshold to this layer. */ | |
| 1825 | + endcomps = &tile->tcmpts[tile->numtcmpts]; | |
| 1826 | + for (comp = tile->tcmpts; comp != endcomps; ++comp) { | |
| 1827 | + endlvls = &comp->rlvls[comp->numrlvls]; | |
| 1828 | + for (lvl = comp->rlvls; lvl != endlvls; ++lvl) { | |
| 1829 | + if (!lvl->bands) { | |
| 1830 | + continue; | |
| 1831 | + } | |
| 1832 | + endbands = &lvl->bands[lvl->numbands]; | |
| 1833 | + for (band = lvl->bands; band != endbands; ++band) { | |
| 1834 | + if (!band->data) { | |
| 1835 | + continue; | |
| 1836 | + } | |
| 1837 | + for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; | |
| 1838 | + ++prcno, ++prc) { | |
| 1839 | + if (!prc->cblks) { | |
| 1840 | + continue; | |
| 1841 | + } | |
| 1842 | + endcblks = &prc->cblks[prc->numcblks]; | |
| 1843 | + for (cblk = prc->cblks; cblk != endcblks; ++cblk) { | |
| 1844 | + if (cblk->curpass) { | |
| 1845 | + endpasses = &cblk->passes[cblk->numpasses]; | |
| 1846 | + pass1 = cblk->curpass; | |
| 1847 | + if (success) { | |
| 1848 | + for (pass = cblk->curpass; pass != | |
| 1849 | + endpasses; ++pass) { | |
| 1850 | + if (pass->rdslope >= goodthresh) { | |
| 1851 | + pass1 = &pass[1]; | |
| 1852 | + } | |
| 1853 | + } | |
| 1854 | + } | |
| 1855 | + for (pass = cblk->curpass; pass != pass1; | |
| 1856 | + ++pass) { | |
| 1857 | + pass->lyrno = lyrno; | |
| 1858 | + } | |
| 1859 | + for (; pass != endpasses; ++pass) { | |
| 1860 | + pass->lyrno = -1; | |
| 1861 | + } | |
| 1862 | + } | |
| 1863 | + } | |
| 1864 | + } | |
| 1865 | + } | |
| 1866 | + } | |
| 1867 | + } | |
| 1868 | + | |
| 1869 | + /* Perform tier 2 coding. */ | |
| 1870 | + endcomps = &tile->tcmpts[tile->numtcmpts]; | |
| 1871 | + for (comp = tile->tcmpts; comp != endcomps; ++comp) { | |
| 1872 | + endlvls = &comp->rlvls[comp->numrlvls]; | |
| 1873 | + for (lvl = comp->rlvls; lvl != endlvls; ++lvl) { | |
| 1874 | + if (!lvl->bands) { | |
| 1875 | + continue; | |
| 1876 | + } | |
| 1877 | + for (prcno = 0; prcno < lvl->numprcs; ++prcno) { | |
| 1878 | + if (jpc_enc_encpkt(enc, out, comp - tile->tcmpts, | |
| 1879 | + lvl - comp->rlvls, prcno, lyrno)) { | |
| 1880 | + ret = -1; | |
| 1881 | + goto done; | |
| 1882 | + } | |
| 1883 | + } | |
| 1884 | + } | |
| 1885 | + } | |
| 1886 | + } | |
| 1887 | + | |
| 1888 | + if (jas_get_debug_level() >= 5) { | |
| 1889 | + dump_layeringinfo(enc); | |
| 1890 | + } | |
| 1891 | + | |
| 1892 | + jas_stream_close(out); | |
| 1893 | + out = 0; | |
| 1894 | + | |
| 1895 | +done: | |
| 1896 | + | |
| 1897 | + if (out) { | |
| 1898 | + jas_stream_close(out); | |
| 1899 | + } | |
| 1900 | + | |
| 1901 | + JAS_LOGDEBUGF(10, "finished rate allocation\n"); | |
| 1902 | + | |
| 1903 | + return ret; | |
| 1904 | +} | |
| 1905 | + | |
| 1906 | +/******************************************************************************\ | |
| 1907 | +* Tile constructors and destructors. | |
| 1908 | +\******************************************************************************/ | |
| 1909 | + | |
| 1910 | +static jpc_enc_tile_t *jpc_enc_tile_create(jpc_enc_cp_t *cp, jas_image_t *image, int tileno) | |
| 1911 | +{ | |
| 1912 | + jpc_enc_tile_t *tile; | |
| 1913 | + uint_fast32_t htileno; | |
| 1914 | + uint_fast32_t vtileno; | |
| 1915 | + uint_fast16_t lyrno; | |
| 1916 | + uint_fast16_t cmptno; | |
| 1917 | + jpc_enc_tcmpt_t *tcmpt; | |
| 1918 | + | |
| 1919 | + if (!(tile = jas_malloc(sizeof(jpc_enc_tile_t)))) { | |
| 1920 | + goto error; | |
| 1921 | + } | |
| 1922 | + | |
| 1923 | + /* Initialize a few members used in error recovery. */ | |
| 1924 | + tile->tcmpts = 0; | |
| 1925 | + tile->lyrsizes = 0; | |
| 1926 | + tile->numtcmpts = cp->numcmpts; | |
| 1927 | + tile->pi = 0; | |
| 1928 | + | |
| 1929 | + tile->tileno = tileno; | |
| 1930 | + htileno = tileno % cp->numhtiles; | |
| 1931 | + vtileno = tileno / cp->numhtiles; | |
| 1932 | + | |
| 1933 | + /* Calculate the coordinates of the top-left and bottom-right | |
| 1934 | + corners of the tile. */ | |
| 1935 | + tile->tlx = JAS_MAX(cp->tilegrdoffx + htileno * cp->tilewidth, | |
| 1936 | + cp->imgareatlx); | |
| 1937 | + tile->tly = JAS_MAX(cp->tilegrdoffy + vtileno * cp->tileheight, | |
| 1938 | + cp->imgareatly); | |
| 1939 | + tile->brx = JAS_MIN(cp->tilegrdoffx + (htileno + 1) * cp->tilewidth, | |
| 1940 | + cp->refgrdwidth); | |
| 1941 | + tile->bry = JAS_MIN(cp->tilegrdoffy + (vtileno + 1) * cp->tileheight, | |
| 1942 | + cp->refgrdheight); | |
| 1943 | + | |
| 1944 | + /* Initialize some tile coding parameters. */ | |
| 1945 | + tile->intmode = cp->tcp.intmode; | |
| 1946 | + tile->csty = cp->tcp.csty; | |
| 1947 | + tile->prg = cp->tcp.prg; | |
| 1948 | + tile->mctid = cp->tcp.mctid; | |
| 1949 | + | |
| 1950 | + tile->numlyrs = cp->tcp.numlyrs; | |
| 1951 | + if (!(tile->lyrsizes = jas_alloc2(tile->numlyrs, | |
| 1952 | + sizeof(uint_fast32_t)))) { | |
| 1953 | + goto error; | |
| 1954 | + } | |
| 1955 | + for (lyrno = 0; lyrno < tile->numlyrs; ++lyrno) { | |
| 1956 | + tile->lyrsizes[lyrno] = 0; | |
| 1957 | + } | |
| 1958 | + | |
| 1959 | + /* Allocate an array for the per-tile-component information. */ | |
| 1960 | + if (!(tile->tcmpts = jas_alloc2(cp->numcmpts, sizeof(jpc_enc_tcmpt_t)))) { | |
| 1961 | + goto error; | |
| 1962 | + } | |
| 1963 | + /* Initialize a few members critical for error recovery. */ | |
| 1964 | + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; | |
| 1965 | + ++cmptno, ++tcmpt) { | |
| 1966 | + tcmpt->rlvls = 0; | |
| 1967 | + tcmpt->tsfb = 0; | |
| 1968 | + tcmpt->data = 0; | |
| 1969 | + } | |
| 1970 | + /* Initialize the per-tile-component information. */ | |
| 1971 | + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; | |
| 1972 | + ++cmptno, ++tcmpt) { | |
| 1973 | + if (!tcmpt_create(tcmpt, cp, image, tile)) { | |
| 1974 | + goto error; | |
| 1975 | + } | |
| 1976 | + } | |
| 1977 | + | |
| 1978 | + /* Initialize the synthesis weights for the MCT. */ | |
| 1979 | + switch (tile->mctid) { | |
| 1980 | + case JPC_MCT_RCT: | |
| 1981 | + tile->tcmpts[0].synweight = jpc_dbltofix(sqrt(3.0)); | |
| 1982 | + tile->tcmpts[1].synweight = jpc_dbltofix(sqrt(0.6875)); | |
| 1983 | + tile->tcmpts[2].synweight = jpc_dbltofix(sqrt(0.6875)); | |
| 1984 | + break; | |
| 1985 | + case JPC_MCT_ICT: | |
| 1986 | + tile->tcmpts[0].synweight = jpc_dbltofix(sqrt(3.0000)); | |
| 1987 | + tile->tcmpts[1].synweight = jpc_dbltofix(sqrt(3.2584)); | |
| 1988 | + tile->tcmpts[2].synweight = jpc_dbltofix(sqrt(2.4755)); | |
| 1989 | + break; | |
| 1990 | + default: | |
| 1991 | + case JPC_MCT_NONE: | |
| 1992 | + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; | |
| 1993 | + ++cmptno, ++tcmpt) { | |
| 1994 | + tcmpt->synweight = JPC_FIX_ONE; | |
| 1995 | + } | |
| 1996 | + break; | |
| 1997 | + } | |
| 1998 | + | |
| 1999 | + if (!(tile->pi = jpc_enc_pi_create(cp, tile))) { | |
| 2000 | + goto error; | |
| 2001 | + } | |
| 2002 | + | |
| 2003 | + return tile; | |
| 2004 | + | |
| 2005 | +error: | |
| 2006 | + | |
| 2007 | + if (tile) { | |
| 2008 | + jpc_enc_tile_destroy(tile); | |
| 2009 | + } | |
| 2010 | + return 0; | |
| 2011 | +} | |
| 2012 | + | |
| 2013 | +/* Note: I don't think that it is necessary to marked destroyed subobjects | |
| 2014 | +as such in this function. */ | |
| 2015 | +static void jpc_enc_tile_destroy(jpc_enc_tile_t *tile) | |
| 2016 | +{ | |
| 2017 | + jpc_enc_tcmpt_t *tcmpt; | |
| 2018 | + uint_fast16_t cmptno; | |
| 2019 | + | |
| 2020 | + if (tile->tcmpts) { | |
| 2021 | + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < | |
| 2022 | + tile->numtcmpts; ++cmptno, ++tcmpt) { | |
| 2023 | + tcmpt_destroy(tcmpt); | |
| 2024 | + } | |
| 2025 | + jas_free(tile->tcmpts); | |
| 2026 | + /* tile->tcmpts = NULL; */ | |
| 2027 | + } | |
| 2028 | + if (tile->lyrsizes) { | |
| 2029 | + jas_free(tile->lyrsizes); | |
| 2030 | + /* tile->lyrsizes = NULL; */ | |
| 2031 | + } | |
| 2032 | + if (tile->pi) { | |
| 2033 | + jpc_pi_destroy(tile->pi); | |
| 2034 | + /* tile->pi = NULL; */ | |
| 2035 | + } | |
| 2036 | + jas_free(tile); | |
| 2037 | + /* tile = NULL; */ | |
| 2038 | +} | |
| 2039 | + | |
| 2040 | +/* Note: This constructor creates the object in place. */ | |
| 2041 | +static jpc_enc_tcmpt_t *tcmpt_create(jpc_enc_tcmpt_t *tcmpt, jpc_enc_cp_t *cp, | |
| 2042 | + jas_image_t *image, jpc_enc_tile_t *tile) | |
| 2043 | +{ | |
| 2044 | + uint_fast16_t cmptno; | |
| 2045 | + uint_fast16_t rlvlno; | |
| 2046 | + jpc_enc_rlvl_t *rlvl; | |
| 2047 | + uint_fast32_t tlx; | |
| 2048 | + uint_fast32_t tly; | |
| 2049 | + uint_fast32_t brx; | |
| 2050 | + uint_fast32_t bry; | |
| 2051 | + uint_fast32_t cmpttlx; | |
| 2052 | + uint_fast32_t cmpttly; | |
| 2053 | + jpc_enc_ccp_t *ccp; | |
| 2054 | + jpc_tsfb_band_t bandinfos[JPC_MAXBANDS]; | |
| 2055 | + | |
| 2056 | + tcmpt->tile = tile; | |
| 2057 | + tcmpt->tsfb = 0; | |
| 2058 | + tcmpt->data = 0; | |
| 2059 | + tcmpt->rlvls = 0; | |
| 2060 | + | |
| 2061 | + /* Deduce the component number. */ | |
| 2062 | + cmptno = tcmpt - tile->tcmpts; | |
| 2063 | + | |
| 2064 | + ccp = &cp->ccps[cmptno]; | |
| 2065 | + | |
| 2066 | + /* Compute the coordinates of the top-left and bottom-right | |
| 2067 | + corners of this tile-component. */ | |
| 2068 | + tlx = JPC_CEILDIV(tile->tlx, ccp->sampgrdstepx); | |
| 2069 | + tly = JPC_CEILDIV(tile->tly, ccp->sampgrdstepy); | |
| 2070 | + brx = JPC_CEILDIV(tile->brx, ccp->sampgrdstepx); | |
| 2071 | + bry = JPC_CEILDIV(tile->bry, ccp->sampgrdstepy); | |
| 2072 | + | |
| 2073 | + /* Create a sequence to hold the tile-component sample data. */ | |
| 2074 | + if (!(tcmpt->data = jas_seq2d_create(tlx, tly, brx, bry))) { | |
| 2075 | + goto error; | |
| 2076 | + } | |
| 2077 | + | |
| 2078 | + /* Get the image data associated with this tile-component. */ | |
| 2079 | + cmpttlx = JPC_CEILDIV(cp->imgareatlx, ccp->sampgrdstepx); | |
| 2080 | + cmpttly = JPC_CEILDIV(cp->imgareatly, ccp->sampgrdstepy); | |
| 2081 | + if (jas_image_readcmpt(image, cmptno, tlx - cmpttlx, tly - cmpttly, | |
| 2082 | + brx - tlx, bry - tly, tcmpt->data)) { | |
| 2083 | + goto error; | |
| 2084 | + } | |
| 2085 | + | |
| 2086 | + tcmpt->synweight = 0; | |
| 2087 | + tcmpt->qmfbid = cp->tccp.qmfbid; | |
| 2088 | + tcmpt->numrlvls = cp->tccp.maxrlvls; | |
| 2089 | + tcmpt->numbands = 3 * tcmpt->numrlvls - 2; | |
| 2090 | + if (!(tcmpt->tsfb = jpc_cod_gettsfb(tcmpt->qmfbid, tcmpt->numrlvls - 1))) { | |
| 2091 | + goto error; | |
| 2092 | + } | |
| 2093 | + | |
| 2094 | + for (rlvlno = 0; rlvlno < tcmpt->numrlvls; ++rlvlno) { | |
| 2095 | + tcmpt->prcwidthexpns[rlvlno] = cp->tccp.prcwidthexpns[rlvlno]; | |
| 2096 | + tcmpt->prcheightexpns[rlvlno] = cp->tccp.prcheightexpns[rlvlno]; | |
| 2097 | + } | |
| 2098 | + tcmpt->cblkwidthexpn = cp->tccp.cblkwidthexpn; | |
| 2099 | + tcmpt->cblkheightexpn = cp->tccp.cblkheightexpn; | |
| 2100 | + tcmpt->cblksty = cp->tccp.cblksty; | |
| 2101 | + tcmpt->csty = cp->tccp.csty; | |
| 2102 | + | |
| 2103 | + tcmpt->numstepsizes = tcmpt->numbands; | |
| 2104 | + assert(tcmpt->numstepsizes <= JPC_MAXBANDS); | |
| 2105 | + memset(tcmpt->stepsizes, 0, tcmpt->numstepsizes * sizeof(uint_fast16_t)); | |
| 2106 | + | |
| 2107 | + /* Retrieve information about the various bands. */ | |
| 2108 | + jpc_tsfb_getbands(tcmpt->tsfb, jas_seq2d_xstart(tcmpt->data), | |
| 2109 | + jas_seq2d_ystart(tcmpt->data), jas_seq2d_xend(tcmpt->data), | |
| 2110 | + jas_seq2d_yend(tcmpt->data), bandinfos); | |
| 2111 | + | |
| 2112 | + if (!(tcmpt->rlvls = jas_alloc2(tcmpt->numrlvls, sizeof(jpc_enc_rlvl_t)))) { | |
| 2113 | + goto error; | |
| 2114 | + } | |
| 2115 | + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; | |
| 2116 | + ++rlvlno, ++rlvl) { | |
| 2117 | + rlvl->bands = 0; | |
| 2118 | + rlvl->tcmpt = tcmpt; | |
| 2119 | + } | |
| 2120 | + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; | |
| 2121 | + ++rlvlno, ++rlvl) { | |
| 2122 | + if (!rlvl_create(rlvl, cp, tcmpt, bandinfos)) { | |
| 2123 | + goto error; | |
| 2124 | + } | |
| 2125 | + } | |
| 2126 | + | |
| 2127 | + return tcmpt; | |
| 2128 | + | |
| 2129 | +error: | |
| 2130 | + | |
| 2131 | + tcmpt_destroy(tcmpt); | |
| 2132 | + return 0; | |
| 2133 | + | |
| 2134 | +} | |
| 2135 | + | |
| 2136 | +/* Note: Since jpc_enc_tcmpt_t objects are created in-place, they might | |
| 2137 | +potentially be destroyed multiple times at different levels in the call | |
| 2138 | +chain. So, destroyed subobjects must be marked as destroyed to prevent | |
| 2139 | +problems such as double frees. */ | |
| 2140 | +static void tcmpt_destroy(jpc_enc_tcmpt_t *tcmpt) | |
| 2141 | +{ | |
| 2142 | + jpc_enc_rlvl_t *rlvl; | |
| 2143 | + uint_fast16_t rlvlno; | |
| 2144 | + | |
| 2145 | + if (tcmpt->rlvls) { | |
| 2146 | + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; | |
| 2147 | + ++rlvlno, ++rlvl) { | |
| 2148 | + rlvl_destroy(rlvl); | |
| 2149 | + } | |
| 2150 | + jas_free(tcmpt->rlvls); | |
| 2151 | + tcmpt->rlvls = NULL; | |
| 2152 | + } | |
| 2153 | + | |
| 2154 | + if (tcmpt->data) { | |
| 2155 | + jas_seq2d_destroy(tcmpt->data); | |
| 2156 | + tcmpt->data = NULL; | |
| 2157 | + } | |
| 2158 | + if (tcmpt->tsfb) { | |
| 2159 | + jpc_tsfb_destroy(tcmpt->tsfb); | |
| 2160 | + tcmpt->tsfb = NULL; | |
| 2161 | + } | |
| 2162 | +} | |
| 2163 | + | |
| 2164 | +/* Note: This constructor creates the object in place. */ | |
| 2165 | +static jpc_enc_rlvl_t *rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, | |
| 2166 | + jpc_enc_tcmpt_t *tcmpt, jpc_tsfb_band_t *bandinfos) | |
| 2167 | +{ | |
| 2168 | + uint_fast16_t rlvlno; | |
| 2169 | + uint_fast32_t tlprctlx; | |
| 2170 | + uint_fast32_t tlprctly; | |
| 2171 | + uint_fast32_t brprcbrx; | |
| 2172 | + uint_fast32_t brprcbry; | |
| 2173 | + uint_fast16_t bandno; | |
| 2174 | + jpc_enc_band_t *band; | |
| 2175 | + | |
| 2176 | + /* Deduce the resolution level. */ | |
| 2177 | + rlvlno = rlvl - tcmpt->rlvls; | |
| 2178 | + | |
| 2179 | + /* Initialize members required for error recovery. */ | |
| 2180 | + rlvl->bands = 0; | |
| 2181 | + rlvl->tcmpt = tcmpt; | |
| 2182 | + | |
| 2183 | + /* Compute the coordinates of the top-left and bottom-right | |
| 2184 | + corners of the tile-component at this resolution. */ | |
| 2185 | + rlvl->tlx = JPC_CEILDIVPOW2(JAS_CAST(uint_fast32_t, | |
| 2186 | + jas_seq2d_xstart(tcmpt->data)), tcmpt->numrlvls - 1 - rlvlno); | |
| 2187 | + rlvl->tly = JPC_CEILDIVPOW2(JAS_CAST(uint_fast32_t, | |
| 2188 | + jas_seq2d_ystart(tcmpt->data)), tcmpt->numrlvls - 1 - rlvlno); | |
| 2189 | + rlvl->brx = JPC_CEILDIVPOW2(JAS_CAST(uint_fast32_t, | |
| 2190 | + jas_seq2d_xend(tcmpt->data)), tcmpt->numrlvls - 1 - rlvlno); | |
| 2191 | + rlvl->bry = JPC_CEILDIVPOW2(JAS_CAST(uint_fast32_t, | |
| 2192 | + jas_seq2d_yend(tcmpt->data)), tcmpt->numrlvls - 1 - rlvlno); | |
| 2193 | + | |
| 2194 | + if (rlvl->tlx >= rlvl->brx || rlvl->tly >= rlvl->bry) { | |
| 2195 | + rlvl->numhprcs = 0; | |
| 2196 | + rlvl->numvprcs = 0; | |
| 2197 | + rlvl->numprcs = 0; | |
| 2198 | + return rlvl; | |
| 2199 | + } | |
| 2200 | + | |
| 2201 | + rlvl->numbands = (!rlvlno) ? 1 : 3; | |
| 2202 | + rlvl->prcwidthexpn = cp->tccp.prcwidthexpns[rlvlno]; | |
| 2203 | + rlvl->prcheightexpn = cp->tccp.prcheightexpns[rlvlno]; | |
| 2204 | + if (!rlvlno) { | |
| 2205 | + rlvl->cbgwidthexpn = rlvl->prcwidthexpn; | |
| 2206 | + rlvl->cbgheightexpn = rlvl->prcheightexpn; | |
| 2207 | + } else { | |
| 2208 | + rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1; | |
| 2209 | + rlvl->cbgheightexpn = rlvl->prcheightexpn - 1; | |
| 2210 | + } | |
| 2211 | + rlvl->cblkwidthexpn = JAS_MIN(cp->tccp.cblkwidthexpn, rlvl->cbgwidthexpn); | |
| 2212 | + rlvl->cblkheightexpn = JAS_MIN(cp->tccp.cblkheightexpn, rlvl->cbgheightexpn); | |
| 2213 | + | |
| 2214 | + /* Compute the number of precincts. */ | |
| 2215 | + tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); | |
| 2216 | + tlprctly = JPC_FLOORTOMULTPOW2(rlvl->tly, rlvl->prcheightexpn); | |
| 2217 | + brprcbrx = JPC_CEILTOMULTPOW2(rlvl->brx, rlvl->prcwidthexpn); | |
| 2218 | + brprcbry = JPC_CEILTOMULTPOW2(rlvl->bry, rlvl->prcheightexpn); | |
| 2219 | + rlvl->numhprcs = JPC_FLOORDIVPOW2(brprcbrx - tlprctlx, rlvl->prcwidthexpn); | |
| 2220 | + rlvl->numvprcs = JPC_FLOORDIVPOW2(brprcbry - tlprctly, rlvl->prcheightexpn); | |
| 2221 | + rlvl->numprcs = rlvl->numhprcs * rlvl->numvprcs; | |
| 2222 | + | |
| 2223 | + if (!(rlvl->bands = jas_alloc2(rlvl->numbands, sizeof(jpc_enc_band_t)))) { | |
| 2224 | + goto error; | |
| 2225 | + } | |
| 2226 | + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; | |
| 2227 | + ++bandno, ++band) { | |
| 2228 | + band->prcs = 0; | |
| 2229 | + band->data = 0; | |
| 2230 | + band->rlvl = rlvl; | |
| 2231 | + } | |
| 2232 | + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; | |
| 2233 | + ++bandno, ++band) { | |
| 2234 | + if (!band_create(band, cp, rlvl, bandinfos)) { | |
| 2235 | + goto error; | |
| 2236 | + } | |
| 2237 | + } | |
| 2238 | + | |
| 2239 | + return rlvl; | |
| 2240 | +error: | |
| 2241 | + | |
| 2242 | + rlvl_destroy(rlvl); | |
| 2243 | + return 0; | |
| 2244 | +} | |
| 2245 | + | |
| 2246 | +/* Note: Since jpc_enc_rlvl_t objects are created in-place, they might | |
| 2247 | +potentially be destroyed multiple times at different levels in the call | |
| 2248 | +chain. So, destroyed subobjects must be marked as destroyed to prevent | |
| 2249 | +problems such as double frees. */ | |
| 2250 | +static void rlvl_destroy(jpc_enc_rlvl_t *rlvl) | |
| 2251 | +{ | |
| 2252 | + jpc_enc_band_t *band; | |
| 2253 | + uint_fast16_t bandno; | |
| 2254 | + | |
| 2255 | + if (rlvl->bands) { | |
| 2256 | + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; | |
| 2257 | + ++bandno, ++band) { | |
| 2258 | + band_destroy(band); | |
| 2259 | + } | |
| 2260 | + jas_free(rlvl->bands); | |
| 2261 | + rlvl->bands = NULL; | |
| 2262 | + } | |
| 2263 | +} | |
| 2264 | + | |
| 2265 | +/* Note: This constructor creates the object in place. */ | |
| 2266 | +static jpc_enc_band_t *band_create(jpc_enc_band_t *band, jpc_enc_cp_t *cp, | |
| 2267 | + jpc_enc_rlvl_t *rlvl, jpc_tsfb_band_t *bandinfos) | |
| 2268 | +{ | |
| 2269 | + uint_fast16_t bandno; | |
| 2270 | + uint_fast16_t gblbandno; | |
| 2271 | + uint_fast16_t rlvlno; | |
| 2272 | + jpc_tsfb_band_t *bandinfo; | |
| 2273 | + jpc_enc_tcmpt_t *tcmpt; | |
| 2274 | + uint_fast32_t prcno; | |
| 2275 | + jpc_enc_prc_t *prc; | |
| 2276 | + | |
| 2277 | + tcmpt = rlvl->tcmpt; | |
| 2278 | + band->data = 0; | |
| 2279 | + band->prcs = 0; | |
| 2280 | + band->rlvl = rlvl; | |
| 2281 | + | |
| 2282 | + /* Deduce the resolution level and band number. */ | |
| 2283 | + rlvlno = rlvl - rlvl->tcmpt->rlvls; | |
| 2284 | + bandno = band - rlvl->bands; | |
| 2285 | + gblbandno = (!rlvlno) ? 0 : (3 * (rlvlno - 1) + bandno + 1); | |
| 2286 | + | |
| 2287 | + bandinfo = &bandinfos[gblbandno]; | |
| 2288 | + | |
| 2289 | +if (bandinfo->xstart != bandinfo->xend && bandinfo->ystart != bandinfo->yend) { | |
| 2290 | + if (!(band->data = jas_seq2d_create(0, 0, 0, 0))) { | |
| 2291 | + goto error; | |
| 2292 | + } | |
| 2293 | + if (jas_seq2d_bindsub(band->data, tcmpt->data, bandinfo->locxstart, | |
| 2294 | + bandinfo->locystart, bandinfo->locxend, bandinfo->locyend)) { | |
| 2295 | + goto error; | |
| 2296 | + } | |
| 2297 | + jas_seq2d_setshift(band->data, bandinfo->xstart, bandinfo->ystart); | |
| 2298 | +} | |
| 2299 | + band->orient = bandinfo->orient; | |
| 2300 | + band->analgain = JPC_NOMINALGAIN(cp->tccp.qmfbid, tcmpt->numrlvls, rlvlno, | |
| 2301 | + band->orient); | |
| 2302 | + band->numbps = 0; | |
| 2303 | + band->absstepsize = 0; | |
| 2304 | + band->stepsize = 0; | |
| 2305 | + band->synweight = bandinfo->synenergywt; | |
| 2306 | + | |
| 2307 | +if (band->data) { | |
| 2308 | + if (!(band->prcs = jas_alloc2(rlvl->numprcs, sizeof(jpc_enc_prc_t)))) { | |
| 2309 | + goto error; | |
| 2310 | + } | |
| 2311 | + for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; ++prcno, | |
| 2312 | + ++prc) { | |
| 2313 | + prc->cblks = 0; | |
| 2314 | + prc->incltree = 0; | |
| 2315 | + prc->nlibtree = 0; | |
| 2316 | + prc->savincltree = 0; | |
| 2317 | + prc->savnlibtree = 0; | |
| 2318 | + prc->band = band; | |
| 2319 | + } | |
| 2320 | + for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; ++prcno, | |
| 2321 | + ++prc) { | |
| 2322 | + if (!prc_create(prc, band)) { | |
| 2323 | + goto error; | |
| 2324 | + } | |
| 2325 | + } | |
| 2326 | +} | |
| 2327 | + | |
| 2328 | + return band; | |
| 2329 | + | |
| 2330 | +error: | |
| 2331 | + band_destroy(band); | |
| 2332 | + return 0; | |
| 2333 | +} | |
| 2334 | + | |
| 2335 | +/* Note: Since jpc_enc_band_t objects are created in-place, they might | |
| 2336 | +potentially be destroyed multiple times at different levels in the call | |
| 2337 | +chain. So, destroyed subobjects must be marked as destroyed to prevent | |
| 2338 | +problems such as double frees. */ | |
| 2339 | +static void band_destroy(jpc_enc_band_t *band) | |
| 2340 | +{ | |
| 2341 | + jpc_enc_prc_t *prc; | |
| 2342 | + jpc_enc_rlvl_t *rlvl; | |
| 2343 | + uint_fast32_t prcno; | |
| 2344 | + | |
| 2345 | + if (band->prcs) { | |
| 2346 | + rlvl = band->rlvl; | |
| 2347 | + for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; | |
| 2348 | + ++prcno, ++prc) { | |
| 2349 | + prc_destroy(prc); | |
| 2350 | + } | |
| 2351 | + jas_free(band->prcs); | |
| 2352 | + band->prcs = NULL; | |
| 2353 | + } | |
| 2354 | + if (band->data) { | |
| 2355 | + jas_seq2d_destroy(band->data); | |
| 2356 | + band->data = NULL; | |
| 2357 | + } | |
| 2358 | +} | |
| 2359 | + | |
| 2360 | +/* Note: This constructor creates the object in place. */ | |
| 2361 | +static jpc_enc_prc_t *prc_create(jpc_enc_prc_t *prc, jpc_enc_band_t *band) | |
| 2362 | +{ | |
| 2363 | + uint_fast32_t prcno; | |
| 2364 | + uint_fast32_t prcxind; | |
| 2365 | + uint_fast32_t prcyind; | |
| 2366 | + uint_fast32_t cbgtlx; | |
| 2367 | + uint_fast32_t cbgtly; | |
| 2368 | + uint_fast32_t tlprctlx; | |
| 2369 | + uint_fast32_t tlprctly; | |
| 2370 | + uint_fast32_t tlcbgtlx; | |
| 2371 | + uint_fast32_t tlcbgtly; | |
| 2372 | + uint_fast16_t rlvlno; | |
| 2373 | + jpc_enc_rlvl_t *rlvl; | |
| 2374 | + uint_fast32_t tlcblktlx; | |
| 2375 | + uint_fast32_t tlcblktly; | |
| 2376 | + uint_fast32_t brcblkbrx; | |
| 2377 | + uint_fast32_t brcblkbry; | |
| 2378 | + uint_fast32_t cblkno; | |
| 2379 | + jpc_enc_cblk_t *cblk; | |
| 2380 | + jpc_enc_tcmpt_t *tcmpt; | |
| 2381 | + | |
| 2382 | + prc->cblks = 0; | |
| 2383 | + prc->incltree = 0; | |
| 2384 | + prc->savincltree = 0; | |
| 2385 | + prc->nlibtree = 0; | |
| 2386 | + prc->savnlibtree = 0; | |
| 2387 | + | |
| 2388 | + rlvl = band->rlvl; | |
| 2389 | + tcmpt = rlvl->tcmpt; | |
| 2390 | + rlvlno = rlvl - tcmpt->rlvls; | |
| 2391 | + prcno = prc - band->prcs; | |
| 2392 | + prcxind = prcno % rlvl->numhprcs; | |
| 2393 | + prcyind = prcno / rlvl->numhprcs; | |
| 2394 | + prc->band = band; | |
| 2395 | + | |
| 2396 | + tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); | |
| 2397 | + tlprctly = JPC_FLOORTOMULTPOW2(rlvl->tly, rlvl->prcheightexpn); | |
| 2398 | + if (!rlvlno) { | |
| 2399 | + tlcbgtlx = tlprctlx; | |
| 2400 | + tlcbgtly = tlprctly; | |
| 2401 | + } else { | |
| 2402 | + tlcbgtlx = JPC_CEILDIVPOW2(tlprctlx, 1); | |
| 2403 | + tlcbgtly = JPC_CEILDIVPOW2(tlprctly, 1); | |
| 2404 | + } | |
| 2405 | + | |
| 2406 | + /* Compute the coordinates of the top-left and bottom-right | |
| 2407 | + corners of the precinct. */ | |
| 2408 | + cbgtlx = tlcbgtlx + (prcxind << rlvl->cbgwidthexpn); | |
| 2409 | + cbgtly = tlcbgtly + (prcyind << rlvl->cbgheightexpn); | |
| 2410 | + prc->tlx = JAS_MAX(jas_seq2d_xstart(band->data), (jas_matind_t)cbgtlx); | |
| 2411 | + prc->tly = JAS_MAX(jas_seq2d_ystart(band->data), (jas_matind_t)cbgtly); | |
| 2412 | + prc->brx = JAS_MIN(jas_seq2d_xend(band->data), (jas_matind_t)(cbgtlx + | |
| 2413 | + (1 << rlvl->cbgwidthexpn))); | |
| 2414 | + prc->bry = JAS_MIN(jas_seq2d_yend(band->data), (jas_matind_t)(cbgtly + | |
| 2415 | + (1 << rlvl->cbgheightexpn))); | |
| 2416 | + | |
| 2417 | + if (prc->tlx < prc->brx && prc->tly < prc->bry) { | |
| 2418 | + /* The precinct contains at least one code block. */ | |
| 2419 | + | |
| 2420 | + tlcblktlx = JPC_FLOORTOMULTPOW2(prc->tlx, rlvl->cblkwidthexpn); | |
| 2421 | + tlcblktly = JPC_FLOORTOMULTPOW2(prc->tly, rlvl->cblkheightexpn); | |
| 2422 | + brcblkbrx = JPC_CEILTOMULTPOW2(prc->brx, rlvl->cblkwidthexpn); | |
| 2423 | + brcblkbry = JPC_CEILTOMULTPOW2(prc->bry, rlvl->cblkheightexpn); | |
| 2424 | + prc->numhcblks = JPC_FLOORDIVPOW2(brcblkbrx - tlcblktlx, | |
| 2425 | + rlvl->cblkwidthexpn); | |
| 2426 | + prc->numvcblks = JPC_FLOORDIVPOW2(brcblkbry - tlcblktly, | |
| 2427 | + rlvl->cblkheightexpn); | |
| 2428 | + prc->numcblks = prc->numhcblks * prc->numvcblks; | |
| 2429 | + | |
| 2430 | + if (!(prc->incltree = jpc_tagtree_create(prc->numhcblks, | |
| 2431 | + prc->numvcblks))) { | |
| 2432 | + goto error; | |
| 2433 | + } | |
| 2434 | + if (!(prc->nlibtree = jpc_tagtree_create(prc->numhcblks, | |
| 2435 | + prc->numvcblks))) { | |
| 2436 | + goto error; | |
| 2437 | + } | |
| 2438 | + if (!(prc->savincltree = jpc_tagtree_create(prc->numhcblks, | |
| 2439 | + prc->numvcblks))) { | |
| 2440 | + goto error; | |
| 2441 | + } | |
| 2442 | + if (!(prc->savnlibtree = jpc_tagtree_create(prc->numhcblks, | |
| 2443 | + prc->numvcblks))) { | |
| 2444 | + goto error; | |
| 2445 | + } | |
| 2446 | + | |
| 2447 | + if (!(prc->cblks = jas_alloc2(prc->numcblks, sizeof(jpc_enc_cblk_t)))) { | |
| 2448 | + goto error; | |
| 2449 | + } | |
| 2450 | + for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; | |
| 2451 | + ++cblkno, ++cblk) { | |
| 2452 | + cblk->passes = 0; | |
| 2453 | + cblk->stream = 0; | |
| 2454 | + cblk->mqenc = 0; | |
| 2455 | + cblk->data = 0; | |
| 2456 | + cblk->flags = 0; | |
| 2457 | + cblk->prc = prc; | |
| 2458 | + } | |
| 2459 | + for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; | |
| 2460 | + ++cblkno, ++cblk) { | |
| 2461 | + if (!cblk_create(cblk, prc)) { | |
| 2462 | + goto error; | |
| 2463 | + } | |
| 2464 | + } | |
| 2465 | + } else { | |
| 2466 | + /* The precinct does not contain any code blocks. */ | |
| 2467 | + prc->tlx = prc->brx; | |
| 2468 | + prc->tly = prc->bry; | |
| 2469 | + prc->numcblks = 0; | |
| 2470 | + prc->numhcblks = 0; | |
| 2471 | + prc->numvcblks = 0; | |
| 2472 | + prc->cblks = 0; | |
| 2473 | + prc->incltree = 0; | |
| 2474 | + prc->nlibtree = 0; | |
| 2475 | + prc->savincltree = 0; | |
| 2476 | + prc->savnlibtree = 0; | |
| 2477 | + } | |
| 2478 | + | |
| 2479 | + return prc; | |
| 2480 | + | |
| 2481 | +error: | |
| 2482 | + prc_destroy(prc); | |
| 2483 | + return 0; | |
| 2484 | +} | |
| 2485 | + | |
| 2486 | +/* Note: Since jpc_enc_prc_t objects are created in-place, they might | |
| 2487 | +potentially be destroyed multiple times at different levels in the call | |
| 2488 | +chain. So, destroyed subobjects must be marked as destroyed to prevent | |
| 2489 | +problems such as double frees. */ | |
| 2490 | +static void prc_destroy(jpc_enc_prc_t *prc) | |
| 2491 | +{ | |
| 2492 | + jpc_enc_cblk_t *cblk; | |
| 2493 | + uint_fast32_t cblkno; | |
| 2494 | + | |
| 2495 | + if (prc->cblks) { | |
| 2496 | + for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; | |
| 2497 | + ++cblkno, ++cblk) { | |
| 2498 | + cblk_destroy(cblk); | |
| 2499 | + } | |
| 2500 | + jas_free(prc->cblks); | |
| 2501 | + prc->cblks = NULL; | |
| 2502 | + } | |
| 2503 | + if (prc->incltree) { | |
| 2504 | + jpc_tagtree_destroy(prc->incltree); | |
| 2505 | + prc->incltree = NULL; | |
| 2506 | + } | |
| 2507 | + if (prc->nlibtree) { | |
| 2508 | + jpc_tagtree_destroy(prc->nlibtree); | |
| 2509 | + prc->nlibtree = NULL; | |
| 2510 | + } | |
| 2511 | + if (prc->savincltree) { | |
| 2512 | + jpc_tagtree_destroy(prc->savincltree); | |
| 2513 | + prc->savincltree = NULL; | |
| 2514 | + } | |
| 2515 | + if (prc->savnlibtree) { | |
| 2516 | + jpc_tagtree_destroy(prc->savnlibtree); | |
| 2517 | + prc->savnlibtree = NULL; | |
| 2518 | + } | |
| 2519 | +} | |
| 2520 | + | |
| 2521 | +/* Note: This constructor creates the object in place. */ | |
| 2522 | +static jpc_enc_cblk_t *cblk_create(jpc_enc_cblk_t *cblk, | |
| 2523 | + jpc_enc_prc_t *prc) | |
| 2524 | +{ | |
| 2525 | + jpc_enc_band_t *band; | |
| 2526 | + uint_fast32_t cblktlx; | |
| 2527 | + uint_fast32_t cblktly; | |
| 2528 | + uint_fast32_t cblkbrx; | |
| 2529 | + uint_fast32_t cblkbry; | |
| 2530 | + jpc_enc_rlvl_t *rlvl; | |
| 2531 | + uint_fast32_t cblkxind; | |
| 2532 | + uint_fast32_t cblkyind; | |
| 2533 | + uint_fast32_t cblkno; | |
| 2534 | + uint_fast32_t tlcblktlx; | |
| 2535 | + uint_fast32_t tlcblktly; | |
| 2536 | + | |
| 2537 | + cblkno = cblk - prc->cblks; | |
| 2538 | + cblkxind = cblkno % prc->numhcblks; | |
| 2539 | + cblkyind = cblkno / prc->numhcblks; | |
| 2540 | + rlvl = prc->band->rlvl; | |
| 2541 | + cblk->prc = prc; | |
| 2542 | + | |
| 2543 | + cblk->numpasses = 0; | |
| 2544 | + cblk->passes = 0; | |
| 2545 | + cblk->numencpasses = 0; | |
| 2546 | + cblk->numimsbs = 0; | |
| 2547 | + cblk->numlenbits = 0; | |
| 2548 | + cblk->stream = 0; | |
| 2549 | + cblk->mqenc = 0; | |
| 2550 | + cblk->flags = 0; | |
| 2551 | + cblk->numbps = 0; | |
| 2552 | + cblk->curpass = 0; | |
| 2553 | + cblk->data = 0; | |
| 2554 | + cblk->savedcurpass = 0; | |
| 2555 | + cblk->savednumlenbits = 0; | |
| 2556 | + cblk->savednumencpasses = 0; | |
| 2557 | + | |
| 2558 | + band = prc->band; | |
| 2559 | + tlcblktlx = JPC_FLOORTOMULTPOW2(prc->tlx, rlvl->cblkwidthexpn); | |
| 2560 | + tlcblktly = JPC_FLOORTOMULTPOW2(prc->tly, rlvl->cblkheightexpn); | |
| 2561 | + cblktlx = JAS_MAX(tlcblktlx + (cblkxind << rlvl->cblkwidthexpn), prc->tlx); | |
| 2562 | + cblktly = JAS_MAX(tlcblktly + (cblkyind << rlvl->cblkheightexpn), prc->tly); | |
| 2563 | + cblkbrx = JAS_MIN(tlcblktlx + ((cblkxind + 1) << rlvl->cblkwidthexpn), | |
| 2564 | + prc->brx); | |
| 2565 | + cblkbry = JAS_MIN(tlcblktly + ((cblkyind + 1) << rlvl->cblkheightexpn), | |
| 2566 | + prc->bry); | |
| 2567 | + | |
| 2568 | + assert(cblktlx < cblkbrx && cblktly < cblkbry); | |
| 2569 | + if (!(cblk->data = jas_seq2d_create(0, 0, 0, 0))) { | |
| 2570 | + goto error; | |
| 2571 | + } | |
| 2572 | + if (jas_seq2d_bindsub(cblk->data, band->data, cblktlx, cblktly, cblkbrx, cblkbry)) { | |
| 2573 | + goto error; | |
| 2574 | + } | |
| 2575 | + | |
| 2576 | + return cblk; | |
| 2577 | + | |
| 2578 | +error: | |
| 2579 | + cblk_destroy(cblk); | |
| 2580 | + return 0; | |
| 2581 | +} | |
| 2582 | + | |
| 2583 | +/* Note: Since jpc_enc_cblk_t objects are created in-place, they might | |
| 2584 | +potentially be destroyed multiple times at different levels in the call | |
| 2585 | +chain. So, destroyed subobjects must be marked as destroyed to prevent | |
| 2586 | +problems such as double frees. */ | |
| 2587 | +static void cblk_destroy(jpc_enc_cblk_t *cblk) | |
| 2588 | +{ | |
| 2589 | + uint_fast16_t passno; | |
| 2590 | + jpc_enc_pass_t *pass; | |
| 2591 | + if (cblk->passes) { | |
| 2592 | + for (passno = 0, pass = cblk->passes; passno < cblk->numpasses; | |
| 2593 | + ++passno, ++pass) { | |
| 2594 | + pass_destroy(pass); | |
| 2595 | + } | |
| 2596 | + jas_free(cblk->passes); | |
| 2597 | + cblk->passes = NULL; | |
| 2598 | + } | |
| 2599 | + if (cblk->stream) { | |
| 2600 | + jas_stream_close(cblk->stream); | |
| 2601 | + cblk->stream = NULL; | |
| 2602 | + } | |
| 2603 | + if (cblk->mqenc) { | |
| 2604 | + jpc_mqenc_destroy(cblk->mqenc); | |
| 2605 | + cblk->mqenc = NULL; | |
| 2606 | + } | |
| 2607 | + if (cblk->data) { | |
| 2608 | + jas_seq2d_destroy(cblk->data); | |
| 2609 | + cblk->data = NULL; | |
| 2610 | + } | |
| 2611 | + if (cblk->flags) { | |
| 2612 | + jas_seq2d_destroy(cblk->flags); | |
| 2613 | + cblk->flags = NULL; | |
| 2614 | + } | |
| 2615 | +} | |
| 2616 | + | |
| 2617 | +static void pass_destroy(jpc_enc_pass_t *pass) | |
| 2618 | +{ | |
| 2619 | + /* XXX - need to free resources here */ | |
| 2620 | + JAS_UNUSED(pass); | |
| 2621 | +} | |
| 2622 | + | |
| 2623 | +void jpc_enc_dump(jpc_enc_t *enc) | |
| 2624 | +{ | |
| 2625 | + jpc_enc_tile_t *tile; | |
| 2626 | + jpc_enc_tcmpt_t *tcmpt; | |
| 2627 | + jpc_enc_rlvl_t *rlvl; | |
| 2628 | + jpc_enc_band_t *band; | |
| 2629 | + jpc_enc_prc_t *prc; | |
| 2630 | + jpc_enc_cblk_t *cblk; | |
| 2631 | + uint_fast16_t cmptno; | |
| 2632 | + uint_fast16_t rlvlno; | |
| 2633 | + uint_fast16_t bandno; | |
| 2634 | + uint_fast32_t prcno; | |
| 2635 | + uint_fast32_t cblkno; | |
| 2636 | + | |
| 2637 | + tile = enc->curtile; | |
| 2638 | + | |
| 2639 | + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < tile->numtcmpts; ++cmptno, | |
| 2640 | + ++tcmpt) { | |
| 2641 | + jas_loginfof(" tcmpt %5d %5d %5d %5d\n", jas_seq2d_xstart(tcmpt->data), jas_seq2d_ystart(tcmpt->data), jas_seq2d_xend(tcmpt->data), jas_seq2d_yend(tcmpt->data)); | |
| 2642 | + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; | |
| 2643 | + ++rlvlno, ++rlvl) { | |
| 2644 | + jas_loginfof(" rlvl %5d %5d %5d %5d\n", rlvl->tlx, rlvl->tly, rlvl->brx, rlvl->bry); | |
| 2645 | + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; | |
| 2646 | + ++bandno, ++band) { | |
| 2647 | + if (!band->data) { | |
| 2648 | + continue; | |
| 2649 | + } | |
| 2650 | + jas_loginfof(" band %5d %5d %5d %5d\n", jas_seq2d_xstart(band->data), jas_seq2d_ystart(band->data), jas_seq2d_xend(band->data), jas_seq2d_yend(band->data)); | |
| 2651 | + for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; | |
| 2652 | + ++prcno, ++prc) { | |
| 2653 | + jas_loginfof(" prc %5d %5d %5d %5d (%5d %5d)\n", prc->tlx, prc->tly, prc->brx, prc->bry, prc->brx - prc->tlx, prc->bry - prc->tly); | |
| 2654 | + if (!prc->cblks) { | |
| 2655 | + continue; | |
| 2656 | + } | |
| 2657 | + for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; | |
| 2658 | + ++cblkno, ++cblk) { | |
| 2659 | + jas_loginfof(" cblk %5d %5d %5d %5d\n", jas_seq2d_xstart(cblk->data), jas_seq2d_ystart(cblk->data), jas_seq2d_xend(cblk->data), jas_seq2d_yend(cblk->data)); | |
| 2660 | + } | |
| 2661 | + } | |
| 2662 | + } | |
| 2663 | + } | |
| 2664 | + } | |
| 2665 | +} | |
| @@ -0,0 +1,650 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999-2000 Image Power, Inc. and the University of | |
| 3 | + * British Columbia. | |
| 4 | + * Copyright (c) 2001-2002 Michael David Adams. | |
| 5 | + * All rights reserved. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* __START_OF_JASPER_LICENSE__ | |
| 9 | + * | |
| 10 | + * JasPer License Version 2.0 | |
| 11 | + * | |
| 12 | + * Copyright (c) 2001-2006 Michael David Adams | |
| 13 | + * Copyright (c) 1999-2000 Image Power, Inc. | |
| 14 | + * Copyright (c) 1999-2000 The University of British Columbia | |
| 15 | + * | |
| 16 | + * All rights reserved. | |
| 17 | + * | |
| 18 | + * Permission is hereby granted, free of charge, to any person (the | |
| 19 | + * "User") obtaining a copy of this software and associated documentation | |
| 20 | + * files (the "Software"), to deal in the Software without restriction, | |
| 21 | + * including without limitation the rights to use, copy, modify, merge, | |
| 22 | + * publish, distribute, and/or sell copies of the Software, and to permit | |
| 23 | + * persons to whom the Software is furnished to do so, subject to the | |
| 24 | + * following conditions: | |
| 25 | + * | |
| 26 | + * 1. The above copyright notices and this permission notice (which | |
| 27 | + * includes the disclaimer below) shall be included in all copies or | |
| 28 | + * substantial portions of the Software. | |
| 29 | + * | |
| 30 | + * 2. The name of a copyright holder shall not be used to endorse or | |
| 31 | + * promote products derived from the Software without specific prior | |
| 32 | + * written permission. | |
| 33 | + * | |
| 34 | + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS | |
| 35 | + * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER | |
| 36 | + * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS | |
| 37 | + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 38 | + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| 39 | + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO | |
| 40 | + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL | |
| 41 | + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING | |
| 42 | + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | |
| 43 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
| 44 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE | |
| 45 | + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE | |
| 46 | + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. | |
| 47 | + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS | |
| 48 | + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL | |
| 49 | + * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS | |
| 50 | + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE | |
| 51 | + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE | |
| 52 | + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL | |
| 53 | + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, | |
| 54 | + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL | |
| 55 | + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH | |
| 56 | + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, | |
| 57 | + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH | |
| 58 | + * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY | |
| 59 | + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. | |
| 60 | + * | |
| 61 | + * __END_OF_JASPER_LICENSE__ | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/* | |
| 65 | + * $Id$ | |
| 66 | + */ | |
| 67 | + | |
| 68 | +#ifndef JPC_ENC_H | |
| 69 | +#define JPC_ENC_H | |
| 70 | + | |
| 71 | +/******************************************************************************\ | |
| 72 | +* Includes. | |
| 73 | +\******************************************************************************/ | |
| 74 | + | |
| 75 | +#include "jasper/jas_image.h" | |
| 76 | +#include "jasper/jas_seq.h" | |
| 77 | +#include "jasper/jas_stream.h" | |
| 78 | + | |
| 79 | +#include "jpc_cod.h" | |
| 80 | +#include "jpc_t1cod.h" | |
| 81 | +#include "jpc_t2cod.h" | |
| 82 | +#include "jpc_mqenc.h" | |
| 83 | +#include "jpc_tagtree.h" | |
| 84 | +#include "jpc_cs.h" | |
| 85 | +#include "jpc_fix.h" | |
| 86 | +#include "jpc_flt.h" | |
| 87 | +#include "jpc_tsfb.h" | |
| 88 | + | |
| 89 | +/******************************************************************************\ | |
| 90 | +* Constants. | |
| 91 | +\******************************************************************************/ | |
| 92 | + | |
| 93 | +/* The number of bits used in various lookup tables. */ | |
| 94 | +#define JPC_NUMEXTRABITS JPC_NMSEDEC_FRACBITS | |
| 95 | + | |
| 96 | +/* An invalid R-D slope value. */ | |
| 97 | +#define JPC_BADRDSLOPE (-1) | |
| 98 | + | |
| 99 | +/******************************************************************************\ | |
| 100 | +* Coding parameters types. | |
| 101 | +\******************************************************************************/ | |
| 102 | + | |
| 103 | +/* Per-component coding paramters. */ | |
| 104 | + | |
| 105 | +typedef struct { | |
| 106 | + | |
| 107 | + /* The horizontal sampling period. */ | |
| 108 | + uint_fast8_t sampgrdstepx; | |
| 109 | + | |
| 110 | + /* The vertical sampling period. */ | |
| 111 | + uint_fast8_t sampgrdstepy; | |
| 112 | + | |
| 113 | + /* The sample alignment horizontal offset. */ | |
| 114 | + uint_fast8_t sampgrdsubstepx; | |
| 115 | + | |
| 116 | + /* The sample alignment vertical offset. */ | |
| 117 | + uint_fast8_t sampgrdsubstepy; | |
| 118 | + | |
| 119 | + /* The precision of the samples. */ | |
| 120 | + uint_fast8_t prec; | |
| 121 | + | |
| 122 | + /* The signedness of the samples. */ | |
| 123 | + bool sgnd; | |
| 124 | + | |
| 125 | + /* The number of step sizes. */ | |
| 126 | + uint_fast16_t numstepsizes; | |
| 127 | + | |
| 128 | + /* The quantizer step sizes. */ | |
| 129 | + uint_fast16_t stepsizes[JPC_MAXBANDS]; | |
| 130 | + | |
| 131 | +} jpc_enc_ccp_t; | |
| 132 | + | |
| 133 | +/* Per-tile coding parameters. */ | |
| 134 | + | |
| 135 | +typedef struct { | |
| 136 | + | |
| 137 | + /* The coding mode. */ | |
| 138 | + bool intmode; | |
| 139 | + | |
| 140 | + /* The coding style (i.e., SOP, EPH). */ | |
| 141 | + uint_fast8_t csty; | |
| 142 | + | |
| 143 | + /* The progression order. */ | |
| 144 | + uint_fast8_t prg; | |
| 145 | + | |
| 146 | + /* The multicomponent transform. */ | |
| 147 | + uint_fast8_t mctid; | |
| 148 | + | |
| 149 | + /* The number of layers. */ | |
| 150 | + uint_fast16_t numlyrs; | |
| 151 | + | |
| 152 | + /* The normalized bit rates associated with the various | |
| 153 | + intermediate layers. */ | |
| 154 | + jpc_fix_t *ilyrrates; | |
| 155 | + | |
| 156 | +} jpc_enc_tcp_t; | |
| 157 | + | |
| 158 | +/* Per tile-component coding parameters. */ | |
| 159 | + | |
| 160 | +typedef struct { | |
| 161 | + | |
| 162 | + /* The coding style (i.e., explicit precinct sizes). */ | |
| 163 | + uint_fast8_t csty; | |
| 164 | + | |
| 165 | + /* The maximum number of resolution levels allowed. */ | |
| 166 | + uint_fast8_t maxrlvls; | |
| 167 | + | |
| 168 | + /* The exponent for the nominal code block width. */ | |
| 169 | + uint_fast16_t cblkwidthexpn; | |
| 170 | + | |
| 171 | + /* The exponent for the nominal code block height. */ | |
| 172 | + uint_fast16_t cblkheightexpn; | |
| 173 | + | |
| 174 | + /* The code block style parameters (e.g., lazy, terminate all, | |
| 175 | + segmentation symbols, causal, reset probability models). */ | |
| 176 | + uint_fast8_t cblksty; | |
| 177 | + | |
| 178 | + /* The QMFB. */ | |
| 179 | + uint_fast8_t qmfbid; | |
| 180 | + | |
| 181 | + /* The precinct width values. */ | |
| 182 | + uint_fast16_t prcwidthexpns[JPC_MAXRLVLS]; | |
| 183 | + | |
| 184 | + /* The precinct height values. */ | |
| 185 | + uint_fast16_t prcheightexpns[JPC_MAXRLVLS]; | |
| 186 | + | |
| 187 | + /* The number of guard bits. */ | |
| 188 | + uint_fast8_t numgbits; | |
| 189 | + | |
| 190 | +} jpc_enc_tccp_t; | |
| 191 | + | |
| 192 | +/* Coding parameters. */ | |
| 193 | + | |
| 194 | +typedef struct { | |
| 195 | + | |
| 196 | + /* The debug level. */ | |
| 197 | + int debug; | |
| 198 | + | |
| 199 | + /* The horizontal offset from the origin of the reference grid to the | |
| 200 | + left edge of the image area. */ | |
| 201 | + uint_fast32_t imgareatlx; | |
| 202 | + | |
| 203 | + /* The vertical offset from the origin of the reference grid to the | |
| 204 | + top edge of the image area. */ | |
| 205 | + uint_fast32_t imgareatly; | |
| 206 | + | |
| 207 | + /* The horizontal offset from the origin of the reference grid to the | |
| 208 | + right edge of the image area (plus one). */ | |
| 209 | + uint_fast32_t refgrdwidth; | |
| 210 | + | |
| 211 | + /* The vertical offset from the origin of the reference grid to the | |
| 212 | + bottom edge of the image area (plus one). */ | |
| 213 | + uint_fast32_t refgrdheight; | |
| 214 | + | |
| 215 | + /* The horizontal offset from the origin of the tile grid to the | |
| 216 | + origin of the reference grid. */ | |
| 217 | + uint_fast32_t tilegrdoffx; | |
| 218 | + | |
| 219 | + /* The vertical offset from the origin of the tile grid to the | |
| 220 | + origin of the reference grid. */ | |
| 221 | + uint_fast32_t tilegrdoffy; | |
| 222 | + | |
| 223 | + /* The nominal tile width in units of the image reference grid. */ | |
| 224 | + uint_fast32_t tilewidth; | |
| 225 | + | |
| 226 | + /* The nominal tile height in units of the image reference grid. */ | |
| 227 | + uint_fast32_t tileheight; | |
| 228 | + | |
| 229 | + /* The number of tiles spanning the image area in the horizontal | |
| 230 | + direction. */ | |
| 231 | + uint_fast32_t numhtiles; | |
| 232 | + | |
| 233 | + /* The number of tiles spanning the image area in the vertical | |
| 234 | + direction. */ | |
| 235 | + uint_fast32_t numvtiles; | |
| 236 | + | |
| 237 | + /* The number of tiles. */ | |
| 238 | + uint_fast32_t numtiles; | |
| 239 | + | |
| 240 | + /* The number of components. */ | |
| 241 | + uint_fast16_t numcmpts; | |
| 242 | + | |
| 243 | + /* The per-component coding parameters. */ | |
| 244 | + jpc_enc_ccp_t *ccps; | |
| 245 | + | |
| 246 | + /* The per-tile coding parameters. */ | |
| 247 | + jpc_enc_tcp_t tcp; | |
| 248 | + | |
| 249 | + /* The per-tile-component coding parameters. */ | |
| 250 | + jpc_enc_tccp_t tccp; | |
| 251 | + | |
| 252 | + /* The target code stream length in bytes. */ | |
| 253 | + uint_fast32_t totalsize; | |
| 254 | + | |
| 255 | + /* The raw (i.e., uncompressed) size of the image in bytes. */ | |
| 256 | + uint_fast32_t rawsize; | |
| 257 | + | |
| 258 | +} jpc_enc_cp_t; | |
| 259 | + | |
| 260 | +/******************************************************************************\ | |
| 261 | +* Encoder class. | |
| 262 | +\******************************************************************************/ | |
| 263 | + | |
| 264 | +/* Encoder per-coding-pass state information. */ | |
| 265 | + | |
| 266 | +typedef struct { | |
| 267 | + | |
| 268 | + /* The starting offset for this pass. */ | |
| 269 | + int start; | |
| 270 | + | |
| 271 | + /* The ending offset for this pass. */ | |
| 272 | + int end; | |
| 273 | + | |
| 274 | + /* The type of data in this pass (i.e., MQ or raw). */ | |
| 275 | + enum jpc_segtype type; | |
| 276 | + | |
| 277 | + /* Flag indicating that this pass is terminated. */ | |
| 278 | + int term; | |
| 279 | + | |
| 280 | + /* The entropy coder state after coding this pass. */ | |
| 281 | + jpc_mqencstate_t mqencstate; | |
| 282 | + | |
| 283 | + /* The layer to which this pass has been assigned. */ | |
| 284 | + unsigned lyrno; | |
| 285 | + | |
| 286 | + /* The R-D slope for this pass. */ | |
| 287 | + jpc_flt_t rdslope; | |
| 288 | + | |
| 289 | + /* The weighted MSE reduction associated with this pass. */ | |
| 290 | + jpc_flt_t wmsedec; | |
| 291 | + | |
| 292 | + /* The cumulative weighted MSE reduction. */ | |
| 293 | + jpc_flt_t cumwmsedec; | |
| 294 | + | |
| 295 | + /* The normalized MSE reduction. */ | |
| 296 | + long nmsedec; | |
| 297 | + | |
| 298 | +} jpc_enc_pass_t; | |
| 299 | + | |
| 300 | +/* Encoder per-code-block state information. */ | |
| 301 | + | |
| 302 | +typedef struct { | |
| 303 | + | |
| 304 | + /* The number of passes. */ | |
| 305 | + unsigned numpasses; | |
| 306 | + | |
| 307 | + /* The per-pass information. */ | |
| 308 | + jpc_enc_pass_t *passes; | |
| 309 | + | |
| 310 | + /* The number of passes encoded so far. */ | |
| 311 | + int numencpasses; | |
| 312 | + | |
| 313 | + /* The number of insignificant MSBs. */ | |
| 314 | + int numimsbs; | |
| 315 | + | |
| 316 | + /* The number of bits used to encode pass data lengths. */ | |
| 317 | + int numlenbits; | |
| 318 | + | |
| 319 | + /* The byte stream for this code block. */ | |
| 320 | + jas_stream_t *stream; | |
| 321 | + | |
| 322 | + /* The entropy encoder. */ | |
| 323 | + jpc_mqenc_t *mqenc; | |
| 324 | + | |
| 325 | + /* The data for this code block. */ | |
| 326 | + jas_matrix_t *data; | |
| 327 | + | |
| 328 | + /* The state for this code block. */ | |
| 329 | + jas_matrix_t *flags; | |
| 330 | + | |
| 331 | + /* The number of bit planes required for this code block. */ | |
| 332 | + int numbps; | |
| 333 | + | |
| 334 | + /* The next pass to be encoded. */ | |
| 335 | + jpc_enc_pass_t *curpass; | |
| 336 | + | |
| 337 | + /* The per-code-block-group state information. */ | |
| 338 | + struct jpc_enc_prc_s *prc; | |
| 339 | + | |
| 340 | + /* The saved current pass. */ | |
| 341 | + /* This is used by the rate control code. */ | |
| 342 | + jpc_enc_pass_t *savedcurpass; | |
| 343 | + | |
| 344 | + /* The saved length indicator size. */ | |
| 345 | + /* This is used by the rate control code. */ | |
| 346 | + int savednumlenbits; | |
| 347 | + | |
| 348 | + /* The saved number of encoded passes. */ | |
| 349 | + /* This is used by the rate control code. */ | |
| 350 | + int savednumencpasses; | |
| 351 | + | |
| 352 | +} jpc_enc_cblk_t; | |
| 353 | + | |
| 354 | +/* Encoder per-code-block-group state information. */ | |
| 355 | + | |
| 356 | +typedef struct jpc_enc_prc_s { | |
| 357 | + | |
| 358 | + /* The x-coordinate of the top-left corner of the precinct. */ | |
| 359 | + uint_fast32_t tlx; | |
| 360 | + | |
| 361 | + /* The y-coordinate of the top-left corner of the precinct. */ | |
| 362 | + uint_fast32_t tly; | |
| 363 | + | |
| 364 | + /* The x-coordinate of the bottom-right corner of the precinct | |
| 365 | + (plus one). */ | |
| 366 | + uint_fast32_t brx; | |
| 367 | + | |
| 368 | + /* The y-coordinate of the bottom-right corner of the precinct | |
| 369 | + (plus one). */ | |
| 370 | + uint_fast32_t bry; | |
| 371 | + | |
| 372 | + /* The number of code blocks spanning the precinct in the horizontal | |
| 373 | + direction. */ | |
| 374 | + int numhcblks; | |
| 375 | + | |
| 376 | + /* The number of code blocks spanning the precinct in the vertical | |
| 377 | + direction. */ | |
| 378 | + int numvcblks; | |
| 379 | + | |
| 380 | + /* The total number of code blocks. */ | |
| 381 | + unsigned numcblks; | |
| 382 | + | |
| 383 | + /* The per-code-block information. */ | |
| 384 | + jpc_enc_cblk_t *cblks; | |
| 385 | + | |
| 386 | + /* The inclusion tag tree. */ | |
| 387 | + jpc_tagtree_t *incltree; | |
| 388 | + | |
| 389 | + /* The insignifcant MSBs tag tree. */ | |
| 390 | + jpc_tagtree_t *nlibtree; | |
| 391 | + | |
| 392 | + /* The per-band information. */ | |
| 393 | + struct jpc_enc_band_s *band; | |
| 394 | + | |
| 395 | + /* The saved inclusion tag tree. */ | |
| 396 | + /* This is used by rate control. */ | |
| 397 | + jpc_tagtree_t *savincltree; | |
| 398 | + | |
| 399 | + /* The saved leading-insignificant-bit-planes tag tree. */ | |
| 400 | + /* This is used by rate control. */ | |
| 401 | + jpc_tagtree_t *savnlibtree; | |
| 402 | + | |
| 403 | +} jpc_enc_prc_t; | |
| 404 | + | |
| 405 | +/* Encoder per-band state information. */ | |
| 406 | + | |
| 407 | +typedef struct jpc_enc_band_s { | |
| 408 | + | |
| 409 | + /* The per precinct information. */ | |
| 410 | + jpc_enc_prc_t *prcs; | |
| 411 | + | |
| 412 | + /* The coefficient data for this band. */ | |
| 413 | + jas_matrix_t *data; | |
| 414 | + | |
| 415 | + /* The orientation of this band (i.e., LL, LH, HL, or HH). */ | |
| 416 | + enum jpc_tsfb_orient orient; | |
| 417 | + | |
| 418 | + /* The number of bit planes associated with this band. */ | |
| 419 | + int numbps; | |
| 420 | + | |
| 421 | + /* The quantizer step size. */ | |
| 422 | + jpc_fix_t absstepsize; | |
| 423 | + | |
| 424 | + /* The encoded quantizer step size. */ | |
| 425 | + int stepsize; | |
| 426 | + | |
| 427 | + /* The L2 norm of the synthesis basis functions associated with | |
| 428 | + this band. (The MCT is not considered in this value.) */ | |
| 429 | + jpc_fix_t synweight; | |
| 430 | + | |
| 431 | + /* The analysis gain for this band. */ | |
| 432 | + int analgain; | |
| 433 | + | |
| 434 | + /* The per-resolution-level information. */ | |
| 435 | + struct jpc_enc_rlvl_s *rlvl; | |
| 436 | + | |
| 437 | +} jpc_enc_band_t; | |
| 438 | + | |
| 439 | +/* Encoder per-resolution-level state information. */ | |
| 440 | + | |
| 441 | +typedef struct jpc_enc_rlvl_s { | |
| 442 | + | |
| 443 | + /* The x-coordinate of the top-left corner of the tile-component | |
| 444 | + at this resolution. */ | |
| 445 | + uint_fast32_t tlx; | |
| 446 | + | |
| 447 | + /* The y-coordinate of the top-left corner of the tile-component | |
| 448 | + at this resolution. */ | |
| 449 | + uint_fast32_t tly; | |
| 450 | + | |
| 451 | + /* The x-coordinate of the bottom-right corner of the tile-component | |
| 452 | + at this resolution (plus one). */ | |
| 453 | + uint_fast32_t brx; | |
| 454 | + | |
| 455 | + /* The y-coordinate of the bottom-right corner of the tile-component | |
| 456 | + at this resolution (plus one). */ | |
| 457 | + uint_fast32_t bry; | |
| 458 | + | |
| 459 | + /* The exponent value for the nominal precinct width measured | |
| 460 | + relative to the associated LL band. */ | |
| 461 | + int prcwidthexpn; | |
| 462 | + | |
| 463 | + /* The exponent value for the nominal precinct height measured | |
| 464 | + relative to the associated LL band. */ | |
| 465 | + int prcheightexpn; | |
| 466 | + | |
| 467 | + /* The number of precincts spanning the resolution level in the | |
| 468 | + horizontal direction. */ | |
| 469 | + int numhprcs; | |
| 470 | + | |
| 471 | + /* The number of precincts spanning the resolution level in the | |
| 472 | + vertical direction. */ | |
| 473 | + int numvprcs; | |
| 474 | + | |
| 475 | + /* The total number of precincts. */ | |
| 476 | + unsigned numprcs; | |
| 477 | + | |
| 478 | + /* The exponent value for the nominal code block group width. | |
| 479 | + This quantity is associated with the next lower resolution level | |
| 480 | + (assuming that there is one). */ | |
| 481 | + unsigned cbgwidthexpn; | |
| 482 | + | |
| 483 | + /* The exponent value for the nominal code block group height. | |
| 484 | + This quantity is associated with the next lower resolution level | |
| 485 | + (assuming that there is one). */ | |
| 486 | + unsigned cbgheightexpn; | |
| 487 | + | |
| 488 | + /* The exponent value for the code block width. */ | |
| 489 | + uint_fast16_t cblkwidthexpn; | |
| 490 | + | |
| 491 | + /* The exponent value for the code block height. */ | |
| 492 | + uint_fast16_t cblkheightexpn; | |
| 493 | + | |
| 494 | + /* The number of bands associated with this resolution level. */ | |
| 495 | + unsigned numbands; | |
| 496 | + | |
| 497 | + /* The per-band information. */ | |
| 498 | + jpc_enc_band_t *bands; | |
| 499 | + | |
| 500 | + /* The parent tile-component. */ | |
| 501 | + struct jpc_enc_tcmpt_s *tcmpt; | |
| 502 | + | |
| 503 | +} jpc_enc_rlvl_t; | |
| 504 | + | |
| 505 | +/* Encoder per-tile-component state information. */ | |
| 506 | + | |
| 507 | +typedef struct jpc_enc_tcmpt_s { | |
| 508 | + | |
| 509 | + /* The number of resolution levels. */ | |
| 510 | + unsigned numrlvls; | |
| 511 | + | |
| 512 | + /* The per-resolution-level information. */ | |
| 513 | + jpc_enc_rlvl_t *rlvls; | |
| 514 | + | |
| 515 | + /* The tile-component data. */ | |
| 516 | + jas_matrix_t *data; | |
| 517 | + | |
| 518 | + /* The QMFB. */ | |
| 519 | + int qmfbid; | |
| 520 | + | |
| 521 | + /* The number of bands. */ | |
| 522 | + int numbands; | |
| 523 | + | |
| 524 | + /* The TSFB. */ | |
| 525 | + jpc_tsfb_t *tsfb; | |
| 526 | + | |
| 527 | + /* The synthesis energy weight (for the MCT). */ | |
| 528 | + jpc_fix_t synweight; | |
| 529 | + | |
| 530 | + /* The precinct width exponents. */ | |
| 531 | + int prcwidthexpns[JPC_MAXRLVLS]; | |
| 532 | + | |
| 533 | + /* The precinct height exponents. */ | |
| 534 | + int prcheightexpns[JPC_MAXRLVLS]; | |
| 535 | + | |
| 536 | + /* The code block width exponent. */ | |
| 537 | + int cblkwidthexpn; | |
| 538 | + | |
| 539 | + /* The code block height exponent. */ | |
| 540 | + int cblkheightexpn; | |
| 541 | + | |
| 542 | + /* Coding style (i.e., explicit precinct sizes). */ | |
| 543 | + int csty; | |
| 544 | + | |
| 545 | + /* Code block style. */ | |
| 546 | + int cblksty; | |
| 547 | + | |
| 548 | + /* The number of quantizer step sizes. */ | |
| 549 | + int numstepsizes; | |
| 550 | + | |
| 551 | + /* The encoded quantizer step sizes. */ | |
| 552 | + uint_fast16_t stepsizes[JPC_MAXBANDS]; | |
| 553 | + | |
| 554 | + /* The parent tile. */ | |
| 555 | + struct jpc_enc_tile_s *tile; | |
| 556 | + | |
| 557 | +} jpc_enc_tcmpt_t; | |
| 558 | + | |
| 559 | +/* Encoder per-tile state information. */ | |
| 560 | + | |
| 561 | +typedef struct jpc_enc_tile_s { | |
89 more lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 387 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 522 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 896 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 340 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 250 lines aren’t shown here.
This diff is large: its 657 lines aren’t shown here.
This diff is large: its 106 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 187 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.