Unified · Split
| @@ -0,0 +1,3 @@ | |||
| 1 | *.out | ||
| 2 | *.[o0125678vqki] | ||
| 3 | libjp2.a | ||
| @@ -65,10 +65,21 @@ · 64 unmodified lines | |||
| 65 | * $Id$ | 65 | * $Id$ |
| 66 | */ | 66 | */ |
| 67 | 67 | ||
| 68 | /******************************************************************************\ | ||
| 69 | * Includes. | ||
| 70 | \******************************************************************************/ | ||
| 71 | |||
| 72 | #define JAS_FOR_INTERNAL_USE_ONLY | ||
| 73 | |||
| 68 | #include "jasper/jas_cm.h" | 74 | #include "jasper/jas_cm.h" |
| 69 | #include "jasper/jas_icc.h" | 75 | #include "jasper/jas_icc.h" |
| 70 | #include "jasper/jas_malloc.h" | 76 | #include "jasper/jas_malloc.h" |
| 71 | #include "jasper/jas_math.h" | 77 | #include "jasper/jas_math.h" |
| 78 | #include "jasper/jas_debug.h" | ||
| 79 | |||
| 80 | /******************************************************************************\ | ||
| 81 | * Function prototypes. | ||
| 82 | \******************************************************************************/ | ||
| 72 | 83 | ||
| 73 | static jas_cmprof_t *jas_cmprof_create(void); | 84 | static jas_cmprof_t *jas_cmprof_create(void); |
| 74 | static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *); | 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 | unsigned, unsigned); | 100 | unsigned, unsigned); |
| 90 | static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, unsigned n); | 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); | 103 | static int mono(const jas_iccprof_t *prof, int op, |
| 93 | static int triclr(const jas_iccprof_t *prof, int op, jas_cmpxformseq_t **retpxformseq); | 104 | jas_cmpxformseq_t **pxformseq); |
| 105 | static int triclr(const jas_iccprof_t *prof, int op, | ||
| 106 | jas_cmpxformseq_t **retpxformseq); | ||
| 94 | 107 | ||
| 95 | static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq); | 108 | static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq); |
| 96 | static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, unsigned i); | 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 | static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, | 113 | static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, |
| 101 | int i, jas_cmpxform_t *pxform); | 114 | int i, jas_cmpxform_t *pxform); |
| 102 | 115 | ||
| 116 | /******************************************************************************\ | ||
| 117 | * Function prototypes. | ||
| 118 | \******************************************************************************/ | ||
| 119 | |||
| 103 | #define SEQFWD(intent) (intent) | 120 | #define SEQFWD(intent) (intent) |
| 104 | #define SEQREV(intent) (4 + (intent)) | 121 | #define SEQREV(intent) (4 + (intent)) |
| 105 | #define SEQSIM(intent) (8 + (intent)) | 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 | #define gampxformseq(prof) ((prof)->pxformseqs[SEQGAM]) | 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 | static jas_cmpxform_t *jas_cmpxform_create0(void); | 143 | static jas_cmpxform_t *jas_cmpxform_create0(void); |
| 127 | static jas_cmpxform_t *jas_cmpxform_createshapmat(void); | 144 | static jas_cmpxform_t *jas_cmpxform_createshapmat(void); |
| 128 | static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut); | 145 | static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut); |
| 129 | static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, const jas_icccurv_t *curv); | 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 | static jas_cmprof_t *jas_cmprof_createsycc(void); | 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 | * Color profile class. | 160 | * Color profile class. |
| 136 | \******************************************************************************/ | 161 | \******************************************************************************/ |
| 137 | 162 | ||
| 138 | jas_cmprof_t *jas_cmprof_createfromclrspc(jas_clrspc_t clrspc) | 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 | jas_iccprof_t *iccprof; | 167 | jas_iccprof_t *iccprof; |
| 141 | jas_cmprof_t *prof; | 168 | jas_cmprof_t *prof; |
| 142 | 169 | ||
| 143 | iccprof = 0; | 170 | iccprof = 0; |
| 144 | switch (clrspc) { | 171 | switch (clrspc) { |
| 145 | case JAS_CLRSPC_SYCBCR: | 172 | case JAS_CLRSPC_SYCBCR: |
| 146 | if (!(prof = jas_cmprof_createsycc())) | 173 | if (!(prof = jas_cmprof_createsycc())) { |
| 147 | goto error; | 174 | goto error; |
| 175 | } | ||
| 148 | break; | 176 | break; |
| 149 | default: | 177 | default: |
| 150 | if (!(iccprof = jas_iccprof_createfromclrspc(clrspc))) | 178 | if (!(iccprof = jas_iccprof_createfromclrspc(clrspc))) { |
| 151 | goto error; | 179 | goto error; |
| 152 | if (!(prof = jas_cmprof_createfromiccprof(iccprof))) | 180 | } |
| 181 | if (!(prof = jas_cmprof_createfromiccprof(iccprof))) { | ||
| 153 | goto error; | 182 | goto error; |
| 183 | } | ||
| 154 | jas_iccprof_destroy(iccprof); | 184 | jas_iccprof_destroy(iccprof); |
| 155 | if (!jas_clrspc_isgeneric(clrspc)) | 185 | if (!jas_clrspc_isgeneric(clrspc)) { |
| 156 | prof->clrspc = clrspc; | 186 | prof->clrspc = clrspc; |
| 187 | } | ||
| 157 | break; | 188 | break; |
| 158 | } | 189 | } |
| 159 | return prof; | 190 | return prof; |
| 160 | error: | 191 | error: |
| 161 | if (iccprof) | 192 | if (iccprof) { |
| 162 | jas_iccprof_destroy(iccprof); | 193 | jas_iccprof_destroy(iccprof); |
| 194 | } | ||
| 163 | return 0; | 195 | return 0; |
| 164 | } | 196 | } |
| 165 | 197 | ||
| 166 | static jas_cmprof_t *jas_cmprof_createsycc() | 198 | static jas_cmprof_t *jas_cmprof_createsycc() |
| 167 | { | 199 | { |
| 200 | JAS_LOGDEBUGF(1, "jas_cmprof_createsycc()\n"); | ||
| 201 | |||
| 168 | jas_cmprof_t *prof; | 202 | jas_cmprof_t *prof; |
| 169 | jas_cmpxform_t *fwdpxform = NULL; | 203 | jas_cmpxform_t *fwdpxform = 0; |
| 170 | jas_cmpxform_t *revpxform = NULL; | 204 | jas_cmpxform_t *revpxform = 0; |
| 171 | jas_cmshapmat_t *fwdshapmat; | 205 | jas_cmshapmat_t *fwdshapmat; |
| 172 | jas_cmshapmat_t *revshapmat; | 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 | goto error; | 209 | goto error; |
| 210 | } | ||
| 176 | prof->clrspc = JAS_CLRSPC_SYCBCR; | 211 | prof->clrspc = JAS_CLRSPC_SYCBCR; |
| 177 | assert(prof->numchans == 3 && prof->numrefchans == 3); | 212 | assert(prof->numchans == 3 && prof->numrefchans == 3); |
| 178 | assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ); | 213 | assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ); |
| 179 | if (!(fwdpxform = jas_cmpxform_createshapmat())) | 214 | if (!(fwdpxform = jas_cmpxform_createshapmat())) { |
| 180 | goto error; | 215 | goto error; |
| 216 | } | ||
| 181 | fwdpxform->numinchans = 3; | 217 | fwdpxform->numinchans = 3; |
| 182 | fwdpxform->numoutchans = 3; | 218 | fwdpxform->numoutchans = 3; |
| 183 | fwdshapmat = &fwdpxform->data.shapmat; | 219 | fwdshapmat = &fwdpxform->data.shapmat; |
| @@ -197,8 +233,9 @@ static jas_cmprof_t *jas_cmprof_createsycc() · 13 unmodified lines | |||
| 197 | fwdshapmat->mat[0][3] = -0.5 * (1.402); | 233 | fwdshapmat->mat[0][3] = -0.5 * (1.402); |
| 198 | fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414); | 234 | fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414); |
| 199 | fwdshapmat->mat[2][3] = -0.5 * (1.772); | 235 | fwdshapmat->mat[2][3] = -0.5 * (1.772); |
| 200 | if (!(revpxform = jas_cmpxform_createshapmat())) | 236 | if (!(revpxform = jas_cmpxform_createshapmat())) { |
| 201 | goto error; | 237 | goto error; |
| 238 | } | ||
| 202 | revpxform->numinchans = 3; | 239 | revpxform->numinchans = 3; |
| 203 | revpxform->numoutchans = 3; | 240 | revpxform->numoutchans = 3; |
| 204 | revshapmat = &revpxform->data.shapmat; | 241 | revshapmat = &revpxform->data.shapmat; |
| @@ -206,20 +243,24 @@ static jas_cmprof_t *jas_cmprof_createsycc() · 1 unmodified line | |||
| 206 | revshapmat->order = 1; | 243 | revshapmat->order = 1; |
| 207 | revshapmat->useluts = 0; | 244 | revshapmat->useluts = 0; |
| 208 | revshapmat->usemat = 1; | 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 | for (unsigned i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) { | 250 | for (unsigned i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) { |
| 212 | unsigned j = SEQFWD(i); | 251 | unsigned j = SEQFWD(i); |
| 213 | if (prof->pxformseqs[j]) { | 252 | if (prof->pxformseqs[j]) { |
| 214 | if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0, | 253 | if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0, |
| 215 | fwdpxform)) | 254 | fwdpxform)) { |
| 216 | goto error; | 255 | goto error; |
| 256 | } | ||
| 217 | } | 257 | } |
| 218 | j = SEQREV(i); | 258 | j = SEQREV(i); |
| 219 | if (prof->pxformseqs[j]) { | 259 | if (prof->pxformseqs[j]) { |
| 220 | if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], | 260 | if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], |
| 221 | -1, revpxform)) | 261 | -1, revpxform)) { |
| 222 | goto error; | 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 | jas_cmpxform_destroy(revpxform); | 268 | jas_cmpxform_destroy(revpxform); |
| 228 | return prof; | 269 | return prof; |
| 229 | error: | 270 | error: |
| 230 | if (fwdpxform) | 271 | if (fwdpxform) { |
| 231 | jas_cmpxform_destroy(fwdpxform); | 272 | jas_cmpxform_destroy(fwdpxform); |
| 232 | if (revpxform) | 273 | } |
| 274 | if (revpxform) { | ||
| 233 | jas_cmpxform_destroy(revpxform); | 275 | jas_cmpxform_destroy(revpxform); |
| 276 | } | ||
| 277 | if (prof) { | ||
| 278 | jas_cmprof_destroy(prof); | ||
| 279 | } | ||
| 234 | return 0; | 280 | return 0; |
| 235 | } | 281 | } |
| 236 | 282 | ||
| 237 | jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof) | 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 | jas_cmprof_t *prof; | 287 | jas_cmprof_t *prof; |
| 240 | jas_icchdr_t icchdr; | 288 | jas_icchdr_t icchdr; |
| 241 | jas_cmpxformseq_t *fwdpxformseq; | 289 | jas_cmpxformseq_t *fwdpxformseq; |
| @@ -244,26 +292,44 @@ jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof) · 2 unmodified lines | |||
| 244 | fwdpxformseq = 0; | 292 | fwdpxformseq = 0; |
| 245 | revpxformseq = 0; | 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 | goto error; | 297 | goto error; |
| 298 | } | ||
| 249 | jas_iccprof_gethdr(iccprof, &icchdr); | 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 | goto error; | 302 | goto error; |
| 252 | prof->clrspc = icctoclrspc(icchdr.colorspc, 0); | 303 | } |
| 253 | prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1); | 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 | prof->numchans = jas_clrspc_numchans(prof->clrspc); | 312 | prof->numchans = jas_clrspc_numchans(prof->clrspc); |
| 255 | prof->numrefchans = jas_clrspc_numchans(prof->refclrspc); | 313 | prof->numrefchans = jas_clrspc_numchans(prof->refclrspc); |
| 256 | 314 | ||
| 257 | if (prof->numchans == 1) { | 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 | goto error; | 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 | goto error; | 322 | goto error; |
| 323 | } | ||
| 262 | } else if (prof->numchans == 3) { | 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 | goto error; | 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 | goto error; | 331 | goto error; |
| 332 | } | ||
| 267 | } | 333 | } |
| 268 | prof->pxformseqs[SEQFWD(0)] = fwdpxformseq; | 334 | prof->pxformseqs[SEQFWD(0)] = fwdpxformseq; |
| 269 | prof->pxformseqs[SEQREV(0)] = revpxformseq; | 335 | prof->pxformseqs[SEQREV(0)] = revpxformseq; |
| @@ -304,12 +370,14 @@ error: · 34 unmodified lines | |||
| 304 | static jas_cmprof_t *jas_cmprof_create() | 370 | static jas_cmprof_t *jas_cmprof_create() |
| 305 | { | 371 | { |
| 306 | jas_cmprof_t *prof; | 372 | jas_cmprof_t *prof; |
| 307 | if (!(prof = jas_malloc(sizeof(jas_cmprof_t)))) | 373 | if (!(prof = jas_malloc(sizeof(jas_cmprof_t)))) { |
| 308 | return 0; | 374 | return 0; |
| 375 | } | ||
| 309 | memset(prof, 0, sizeof(jas_cmprof_t)); | 376 | memset(prof, 0, sizeof(jas_cmprof_t)); |
| 310 | prof->iccprof = 0; | 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 | prof->pxformseqs[i] = 0; | 379 | prof->pxformseqs[i] = 0; |
| 380 | } | ||
| 313 | return prof; | 381 | return prof; |
| 314 | } | 382 | } |
| 315 | 383 | ||
| @@ -321,8 +389,9 @@ void jas_cmprof_destroy(jas_cmprof_t *prof) · 5 unmodified lines | |||
| 321 | prof->pxformseqs[i] = 0; | 389 | prof->pxformseqs[i] = 0; |
| 322 | } | 390 | } |
| 323 | } | 391 | } |
| 324 | if (prof->iccprof) | 392 | if (prof->iccprof) { |
| 325 | jas_iccprof_destroy(prof->iccprof); | 393 | jas_iccprof_destroy(prof->iccprof); |
| 394 | } | ||
| 326 | jas_free(prof); | 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 | jas_cmprof_t *newprof; | 400 | jas_cmprof_t *newprof; |
| 332 | 401 | ||
| 333 | if (!(newprof = jas_cmprof_create())) | 402 | if (!(newprof = jas_cmprof_create())) { |
| 334 | goto error; | 403 | goto error; |
| 404 | } | ||
| 335 | newprof->clrspc = prof->clrspc; | 405 | newprof->clrspc = prof->clrspc; |
| 336 | newprof->numchans = prof->numchans; | 406 | newprof->numchans = prof->numchans; |
| 337 | newprof->refclrspc = prof->refclrspc; | 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 | return newprof; | 416 | return newprof; |
| 347 | error: | 417 | error: |
| 348 | if (newprof) | 418 | if (newprof) { |
| 349 | jas_cmprof_destroy(newprof); | 419 | jas_cmprof_destroy(newprof); |
| 420 | } | ||
| 350 | return 0; | 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 | jas_cmpxformseq_t *altoutpxformseq; | 434 | jas_cmpxformseq_t *altoutpxformseq; |
| 364 | jas_cmpxformseq_t *prfpxformseq; | 435 | jas_cmpxformseq_t *prfpxformseq; |
| 365 | 436 | ||
| 366 | /* Avoid compiler warnings about unused parameters. */ | 437 | JAS_UNUSED(optimize); |
| 367 | (void)optimize; | ||
| 368 | 438 | ||
| 369 | const jas_cmxform_intent_t prfintent = intent; | 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 | goto error; | 442 | goto error; |
| 373 | if (!(xform->pxformseq = jas_cmpxformseq_create())) | 443 | } |
| 444 | if (!(xform->pxformseq = jas_cmpxformseq_create())) { | ||
| 374 | goto error; | 445 | goto error; |
| 446 | } | ||
| 375 | 447 | ||
| 376 | switch (op) { | 448 | switch (op) { |
| 377 | case JAS_CMXFORM_OP_FWD: | 449 | case JAS_CMXFORM_OP_FWD: |
| 378 | inpxformseq = fwdpxformseq(inprof, intent); | 450 | inpxformseq = fwdpxformseq(inprof, intent); |
| 379 | outpxformseq = revpxformseq(outprof, intent); | 451 | outpxformseq = revpxformseq(outprof, intent); |
| 380 | if (!inpxformseq || !outpxformseq) | 452 | if (!inpxformseq || !outpxformseq) { |
| 381 | goto error; | 453 | goto error; |
| 454 | } | ||
| 382 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || | 455 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || |
| 383 | jas_cmpxformseq_appendcnvt(xform->pxformseq, | 456 | jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 384 | inprof->refclrspc, outprof->refclrspc) || | 457 | inprof->refclrspc, outprof->refclrspc) || |
| 385 | jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) | 458 | jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) { |
| 386 | goto error; | 459 | goto error; |
| 460 | } | ||
| 387 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); | 461 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); |
| 388 | xform->numoutchans = jas_clrspc_numchans(outprof->clrspc); | 462 | xform->numoutchans = jas_clrspc_numchans(outprof->clrspc); |
| 389 | break; | 463 | break; |
| 390 | case JAS_CMXFORM_OP_REV: | 464 | case JAS_CMXFORM_OP_REV: |
| 391 | outpxformseq = fwdpxformseq(outprof, intent); | 465 | outpxformseq = fwdpxformseq(outprof, intent); |
| 392 | inpxformseq = revpxformseq(inprof, intent); | 466 | inpxformseq = revpxformseq(inprof, intent); |
| 393 | if (!outpxformseq || !inpxformseq) | 467 | if (!outpxformseq || !inpxformseq) { |
| 394 | goto error; | 468 | goto error; |
| 469 | } | ||
| 395 | if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || | 470 | if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || |
| 396 | jas_cmpxformseq_appendcnvt(xform->pxformseq, | 471 | jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 397 | outprof->refclrspc, inprof->refclrspc) || | 472 | outprof->refclrspc, inprof->refclrspc) || |
| 398 | jas_cmpxformseq_append(xform->pxformseq, inpxformseq)) | 473 | jas_cmpxformseq_append(xform->pxformseq, inpxformseq)) { |
| 399 | goto error; | 474 | goto error; |
| 475 | } | ||
| 400 | xform->numinchans = jas_clrspc_numchans(outprof->clrspc); | 476 | xform->numinchans = jas_clrspc_numchans(outprof->clrspc); |
| 401 | xform->numoutchans = jas_clrspc_numchans(inprof->clrspc); | 477 | xform->numoutchans = jas_clrspc_numchans(inprof->clrspc); |
| 402 | break; | 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 | assert(prfprof); | 480 | assert(prfprof); |
| 405 | inpxformseq = fwdpxformseq(inprof, intent); | 481 | inpxformseq = fwdpxformseq(inprof, intent); |
| 406 | prfpxformseq = fwdpxformseq(prfprof, prfintent); | 482 | prfpxformseq = fwdpxformseq(prfprof, prfintent); |
| 407 | if (!inpxformseq || !prfpxformseq) | 483 | if (!inpxformseq || !prfpxformseq) { |
| 408 | goto error; | 484 | goto error; |
| 485 | } | ||
| 409 | outpxformseq = simpxformseq(outprof, intent); | 486 | outpxformseq = simpxformseq(outprof, intent); |
| 410 | altoutpxformseq = 0; | 487 | altoutpxformseq = 0; |
| 411 | if (!outpxformseq) { | 488 | if (!outpxformseq) { |
| 412 | outpxformseq = revpxformseq(outprof, intent); | 489 | outpxformseq = revpxformseq(outprof, intent); |
| 413 | altoutpxformseq = fwdpxformseq(outprof, intent); | 490 | altoutpxformseq = fwdpxformseq(outprof, intent); |
| 414 | if (!outpxformseq || !altoutpxformseq) | 491 | if (!outpxformseq || !altoutpxformseq) { |
| 415 | goto error; | 492 | goto error; |
| 493 | } | ||
| 416 | } | 494 | } |
| 417 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || | 495 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || |
| 418 | jas_cmpxformseq_appendcnvt(xform->pxformseq, | 496 | jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 419 | inprof->refclrspc, outprof->refclrspc)) | 497 | inprof->refclrspc, outprof->refclrspc)) { |
| 420 | goto error; | 498 | goto error; |
| 499 | } | ||
| 421 | if (altoutpxformseq) { | 500 | if (altoutpxformseq) { |
| 422 | if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || | 501 | if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || |
| 423 | jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq)) | 502 | jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq)) { |
| 424 | goto error; | 503 | goto error; |
| 504 | } | ||
| 425 | } else { | 505 | } else { |
| 426 | if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) | 506 | if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) { |
| 427 | goto error; | 507 | goto error; |
| 508 | } | ||
| 428 | } | 509 | } |
| 429 | if (jas_cmpxformseq_appendcnvt(xform->pxformseq, | 510 | if (jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 430 | outprof->refclrspc, inprof->refclrspc) || | 511 | outprof->refclrspc, inprof->refclrspc) || |
| 431 | jas_cmpxformseq_append(xform->pxformseq, prfpxformseq)) | 512 | jas_cmpxformseq_append(xform->pxformseq, prfpxformseq)) { |
| 432 | goto error; | 513 | goto error; |
| 514 | } | ||
| 433 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); | 515 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); |
| 434 | xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc); | 516 | xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc); |
| 435 | break; | 517 | break; |
| 436 | case JAS_CMXFORM_OP_GAMUT: | 518 | case JAS_CMXFORM_OP_GAMUT: |
| 437 | inpxformseq = fwdpxformseq(inprof, intent); | 519 | inpxformseq = fwdpxformseq(inprof, intent); |
| 438 | outpxformseq = gampxformseq(outprof); | 520 | outpxformseq = gampxformseq(outprof); |
| 439 | if (!inpxformseq || !outpxformseq) | 521 | if (!inpxformseq || !outpxformseq) { |
| 440 | goto error; | 522 | goto error; |
| 523 | } | ||
| 441 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || | 524 | if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || |
| 442 | jas_cmpxformseq_appendcnvt(xform->pxformseq, | 525 | jas_cmpxformseq_appendcnvt(xform->pxformseq, |
| 443 | inprof->refclrspc, outprof->refclrspc) || | 526 | inprof->refclrspc, outprof->refclrspc) || |
| 444 | jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) | 527 | jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) { |
| 445 | goto error; | 528 | goto error; |
| 529 | } | ||
| 446 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); | 530 | xform->numinchans = jas_clrspc_numchans(inprof->clrspc); |
| 447 | xform->numoutchans = 1; | 531 | xform->numoutchans = 1; |
| 448 | break; | 532 | break; |
| 449 | } | 533 | } |
| 450 | return xform; | 534 | return xform; |
| 451 | error: | 535 | error: |
| 452 | if (xform) | 536 | if (xform) { |
| 453 | jas_cmxform_destroy(xform); | 537 | jas_cmxform_destroy(xform); |
| 538 | } | ||
| 454 | return 0; | 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 | jas_cmreal_t scale; | 548 | jas_cmreal_t scale; |
| 464 | long v; | 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 | goto error; | 553 | goto error; |
| 554 | } | ||
| 468 | 555 | ||
| 469 | const jas_cmcmptfmt_t *fmt = &in->cmptfmts[0]; | 556 | const jas_cmcmptfmt_t *fmt = &in->cmptfmts[0]; |
| 470 | const unsigned width = fmt->width; | 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 | /* avoid division by zero */ | 585 | /* avoid division by zero */ |
| 499 | goto error; | 586 | goto error; |
| 587 | } | ||
| 500 | 588 | ||
| 501 | const unsigned bufmax = APPLYBUFSIZ / maxchans; | 589 | const unsigned bufmax = APPLYBUFSIZ / maxchans; |
| 502 | assert(bufmax > 0); | 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 | const long *dataptr = &fmt->buf[n]; | 603 | const long *dataptr = &fmt->buf[n]; |
| 516 | jas_cmreal_t *bufptr = &inbuf[i]; | 604 | jas_cmreal_t *bufptr = &inbuf[i]; |
| 517 | for (unsigned j = 0; j < m; ++j) { | 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 | goto error; | 607 | goto error; |
| 608 | } | ||
| 520 | *bufptr = (jas_cmreal_t)(v - bias) / scale; | 609 | *bufptr = (jas_cmreal_t)(v - bias) / scale; |
| 521 | bufptr += xform->numinchans; | 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 | } else { | 620 | } else { |
| 532 | outbuf = inbuf; | 621 | outbuf = inbuf; |
| 533 | } | 622 | } |
| 534 | if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m)) | 623 | if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m)) { |
| 535 | goto error; | 624 | goto error; |
| 625 | } | ||
| 536 | inbuf = outbuf; | 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 | for (unsigned j = 0; j < m; ++j) { | 635 | for (unsigned j = 0; j < m; ++j) { |
| 546 | v = (long)((*bufptr) * scale + bias); | 636 | v = (long)((*bufptr) * scale + bias); |
| 547 | bufptr += xform->numoutchans; | 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 | goto error; | 639 | goto error; |
| 640 | } | ||
| 550 | } | 641 | } |
| 551 | } | 642 | } |
| 552 | 643 | ||
| @@ -560,8 +651,9 @@ error: · 7 unmodified lines | |||
| 560 | 651 | ||
| 561 | void jas_cmxform_destroy(jas_cmxform_t *xform) | 652 | void jas_cmxform_destroy(jas_cmxform_t *xform) |
| 562 | { | 653 | { |
| 563 | if (xform->pxformseq) | 654 | if (xform->pxformseq) { |
| 564 | jas_cmpxformseq_destroy(xform->pxformseq); | 655 | jas_cmpxformseq_destroy(xform->pxformseq); |
| 656 | } | ||
| 565 | jas_free(xform); | 657 | jas_free(xform); |
| 566 | } | 658 | } |
| 567 | 659 | ||
| @@ -572,17 +664,20 @@ void jas_cmxform_destroy(jas_cmxform_t *xform) · 4 unmodified lines | |||
| 572 | static jas_cmpxformseq_t *jas_cmpxformseq_create() | 664 | static jas_cmpxformseq_t *jas_cmpxformseq_create() |
| 573 | { | 665 | { |
| 574 | jas_cmpxformseq_t *pxformseq; | 666 | jas_cmpxformseq_t *pxformseq; |
| 575 | if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t)))) | 667 | if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t)))) { |
| 576 | goto error; | 668 | goto error; |
| 669 | } | ||
| 577 | pxformseq->pxforms = 0; | 670 | pxformseq->pxforms = 0; |
| 578 | pxformseq->numpxforms = 0; | 671 | pxformseq->numpxforms = 0; |
| 579 | pxformseq->maxpxforms = 0; | 672 | pxformseq->maxpxforms = 0; |
| 580 | if (jas_cmpxformseq_resize(pxformseq, 16)) | 673 | if (jas_cmpxformseq_resize(pxformseq, 16)) { |
| 581 | goto error; | 674 | goto error; |
| 675 | } | ||
| 582 | return pxformseq; | 676 | return pxformseq; |
| 583 | error: | 677 | error: |
| 584 | if (pxformseq) | 678 | if (pxformseq) { |
| 585 | jas_cmpxformseq_destroy(pxformseq); | 679 | jas_cmpxformseq_destroy(pxformseq); |
| 680 | } | ||
| 586 | return 0; | 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 | jas_cmpxformseq_t *newpxformseq; | 686 | jas_cmpxformseq_t *newpxformseq; |
| 592 | 687 | ||
| 593 | if (!(newpxformseq = jas_cmpxformseq_create())) | 688 | if (!(newpxformseq = jas_cmpxformseq_create())) { |
| 594 | goto error; | 689 | goto error; |
| 595 | if (jas_cmpxformseq_append(newpxformseq, pxformseq)) | 690 | } |
| 691 | if (jas_cmpxformseq_append(newpxformseq, pxformseq)) { | ||
| 596 | goto error; | 692 | goto error; |
| 693 | } | ||
| 597 | return newpxformseq; | 694 | return newpxformseq; |
| 598 | error: | 695 | error: |
| 599 | if (newpxformseq) | 696 | if (newpxformseq) { |
| 600 | jas_cmpxformseq_destroy(newpxformseq); | 697 | jas_cmpxformseq_destroy(newpxformseq); |
| 698 | } | ||
| 601 | return 0; | 699 | return 0; |
| 602 | } | 700 | } |
| 603 | 701 | ||
| 604 | static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq) | 702 | static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq) |
| 605 | { | 703 | { |
| 606 | while (pxformseq->numpxforms > 0) | 704 | while (pxformseq->numpxforms > 0) { |
| 607 | jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1); | 705 | jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1); |
| 608 | if (pxformseq->pxforms) | 706 | } |
| 707 | if (pxformseq->pxforms) { | ||
| 609 | jas_free(pxformseq->pxforms); | 708 | jas_free(pxformseq->pxforms); |
| 709 | } | ||
| 610 | jas_free(pxformseq); | 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 | static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, | 723 | static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, |
| 624 | unsigned dstclrspc, unsigned srcclrspc) | 724 | unsigned dstclrspc, unsigned srcclrspc) |
| 625 | { | 725 | { |
| 626 | if (dstclrspc == srcclrspc) | 726 | JAS_UNUSED(pxformseq); |
| 727 | if (dstclrspc == srcclrspc) { | ||
| 627 | return 0; | 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 | abort(); | 735 | abort(); |
| 629 | /* Avoid compiler warnings about unused parameters. */ | ||
| 630 | USED(pxformseq); | ||
| 631 | return -1; | 736 | return -1; |
| 632 | } | 737 | } |
| 633 | 738 | ||
| @@ -638,13 +743,14 @@ static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, · 4 unmodified lines | |||
| 638 | const unsigned i = _i >= 0 ? (unsigned)_i : pxformseq->numpxforms; | 743 | const unsigned i = _i >= 0 ? (unsigned)_i : pxformseq->numpxforms; |
| 639 | assert(i <= pxformseq->numpxforms); | 744 | assert(i <= pxformseq->numpxforms); |
| 640 | if (pxformseq->numpxforms >= pxformseq->maxpxforms) { | 745 | if (pxformseq->numpxforms >= pxformseq->maxpxforms) { |
| 641 | if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms + | 746 | if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms + 16)) { |
| 642 | 16)) | ||
| 643 | goto error; | 747 | goto error; |
| 748 | } | ||
| 644 | } | 749 | } |
| 645 | assert(pxformseq->numpxforms < pxformseq->maxpxforms); | 750 | assert(pxformseq->numpxforms < pxformseq->maxpxforms); |
| 646 | if (!(tmppxform = jas_cmpxform_copy(pxform))) | 751 | if (!(tmppxform = jas_cmpxform_copy(pxform))) { |
| 647 | goto error; | 752 | goto error; |
| 753 | } | ||
| 648 | const unsigned n = pxformseq->numpxforms - i; | 754 | const unsigned n = pxformseq->numpxforms - i; |
| 649 | if (n > 0) { | 755 | if (n > 0) { |
| 650 | memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i], | 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 | jas_cmpxform_t *othpxform; | 770 | jas_cmpxform_t *othpxform; |
| 665 | const unsigned n = pxformseq->numpxforms + othpxformseq->numpxforms; | 771 | const unsigned n = pxformseq->numpxforms + othpxformseq->numpxforms; |
| 666 | if (n > pxformseq->maxpxforms) { | 772 | if (n > pxformseq->maxpxforms) { |
| 667 | if (jas_cmpxformseq_resize(pxformseq, n)) | 773 | if (jas_cmpxformseq_resize(pxformseq, n)) { |
| 668 | goto error; | 774 | goto error; |
| 775 | } | ||
| 669 | } | 776 | } |
| 670 | for (unsigned i = 0; i < othpxformseq->numpxforms; ++i) { | 777 | for (unsigned i = 0; i < othpxformseq->numpxforms; ++i) { |
| 671 | othpxform = othpxformseq->pxforms[i]; | 778 | othpxform = othpxformseq->pxforms[i]; |
| 672 | if (!(pxform = jas_cmpxform_copy(othpxform))) | 779 | if (!(pxform = jas_cmpxform_copy(othpxform))) { |
| 673 | goto error; | 780 | goto error; |
| 781 | } | ||
| 674 | pxformseq->pxforms[pxformseq->numpxforms] = pxform; | 782 | pxformseq->pxforms[pxformseq->numpxforms] = pxform; |
| 675 | ++pxformseq->numpxforms; | 783 | ++pxformseq->numpxforms; |
| 676 | } | 784 | } |
| @@ -700,8 +808,9 @@ static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, unsigned n) · 23 unmodified lines | |||
| 700 | static jas_cmpxform_t *jas_cmpxform_create0() | 808 | static jas_cmpxform_t *jas_cmpxform_create0() |
| 701 | { | 809 | { |
| 702 | jas_cmpxform_t *pxform; | 810 | jas_cmpxform_t *pxform; |
| 703 | if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t)))) | 811 | if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t)))) { |
| 704 | return 0; | 812 | return 0; |
| 813 | } | ||
| 705 | memset(pxform, 0, sizeof(jas_cmpxform_t)); | 814 | memset(pxform, 0, sizeof(jas_cmpxform_t)); |
| 706 | pxform->refcnt = 0; | 815 | pxform->refcnt = 0; |
| 707 | pxform->ops = 0; | 816 | pxform->ops = 0; |
| @@ -730,19 +839,22 @@ static jas_cmpxform_t *jas_cmpxform_createshapmat() · 22 unmodified lines | |||
| 730 | { | 839 | { |
| 731 | jas_cmpxform_t *pxform; | 840 | jas_cmpxform_t *pxform; |
| 732 | jas_cmshapmat_t *shapmat; | 841 | jas_cmshapmat_t *shapmat; |
| 733 | if (!(pxform = jas_cmpxform_create0())) | 842 | if (!(pxform = jas_cmpxform_create0())) { |
| 734 | return 0; | 843 | return 0; |
| 844 | } | ||
| 735 | pxform->ops = &shapmat_ops; | 845 | pxform->ops = &shapmat_ops; |
| 736 | shapmat = &pxform->data.shapmat; | 846 | shapmat = &pxform->data.shapmat; |
| 737 | shapmat->mono = 0; | 847 | shapmat->mono = 0; |
| 738 | shapmat->order = 0; | 848 | shapmat->order = 0; |
| 739 | shapmat->useluts = 0; | 849 | shapmat->useluts = 0; |
| 740 | shapmat->usemat = 0; | 850 | shapmat->usemat = 0; |
| 741 | for (unsigned i = 0; i < 3; ++i) | 851 | for (unsigned i = 0; i < 3; ++i) { |
| 742 | jas_cmshapmatlut_init(&shapmat->luts[i]); | 852 | jas_cmshapmatlut_init(&shapmat->luts[i]); |
| 853 | } | ||
| 743 | for (unsigned i = 0; i < 3; ++i) { | 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 | shapmat->mat[i][j] = 0.0; | 856 | shapmat->mat[i][j] = 0.0; |
| 857 | } | ||
| 746 | } | 858 | } |
| 747 | ++pxform->refcnt; | 859 | ++pxform->refcnt; |
| 748 | return pxform; | 860 | return pxform; |
| @@ -751,8 +863,9 @@ static jas_cmpxform_t *jas_cmpxform_createshapmat() · 2 unmodified lines | |||
| 751 | static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform) | 863 | static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform) |
| 752 | { | 864 | { |
| 753 | jas_cmshapmat_t *shapmat = &pxform->data.shapmat; | 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 | jas_cmshapmatlut_cleanup(&shapmat->luts[i]); | 867 | jas_cmshapmatlut_cleanup(&shapmat->luts[i]); |
| 868 | } | ||
| 756 | } | 869 | } |
| 757 | 870 | ||
| 758 | static int jas_cmshapmat_apply(const jas_cmpxform_t *pxform, const jas_cmreal_t *in, | 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 | if (!shapmat->order) { | 921 | if (!shapmat->order) { |
| 809 | while (cnt-- > 0) { | 922 | while (cnt-- > 0) { |
| 810 | a0 = *src++; | 923 | a0 = *src++; |
| 811 | if (shapmat->useluts) | 924 | if (shapmat->useluts) { |
| 812 | a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); | 925 | a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); |
| 926 | } | ||
| 813 | a2 = a0 * shapmat->mat[2][0]; | 927 | a2 = a0 * shapmat->mat[2][0]; |
| 814 | a1 = a0 * shapmat->mat[1][0]; | 928 | a1 = a0 * shapmat->mat[1][0]; |
| 815 | a0 = a0 * shapmat->mat[0][0]; | 929 | a0 = a0 * shapmat->mat[0][0]; |
| @@ -824,8 +938,9 @@ assert(0); · 8 unmodified lines | |||
| 824 | src++; | 938 | src++; |
| 825 | src++; | 939 | src++; |
| 826 | a0 = a0 * shapmat->mat[0][0]; | 940 | a0 = a0 * shapmat->mat[0][0]; |
| 827 | if (shapmat->useluts) | 941 | if (shapmat->useluts) { |
| 828 | a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); | 942 | a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); |
| 943 | } | ||
| 829 | *dst++ = a0; | 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 | static double gammafn(double x, double gamma) | 967 | static double gammafn(double x, double gamma) |
| 853 | { | 968 | { |
| 854 | if (x == 0.0) | 969 | if (x == 0.0) { |
| 855 | return 0.0; | 970 | return 0.0; |
| 971 | } | ||
| 856 | return pow(x, gamma); | 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 | jas_cmshapmatlut_cleanup(lut); | 978 | jas_cmshapmatlut_cleanup(lut); |
| 863 | if (curv->numents == 0) { | 979 | if (curv->numents == 0) { |
| 864 | lut->size = 2; | 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 | goto error; | 982 | goto error; |
| 983 | } | ||
| 867 | lut->data[0] = 0.0; | 984 | lut->data[0] = 0.0; |
| 868 | lut->data[1] = 1.0; | 985 | lut->data[1] = 1.0; |
| 869 | } else if (curv->numents == 1) { | 986 | } else if (curv->numents == 1) { |
| 870 | lut->size = 256; | 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 | goto error; | 989 | goto error; |
| 990 | } | ||
| 873 | gamma = (jas_cmreal_t)curv->ents[0] / 256.0; | 991 | gamma = (jas_cmreal_t)curv->ents[0] / 256.0; |
| 874 | for (unsigned i = 0; i < lut->size; ++i) { | 992 | for (unsigned i = 0; i < lut->size; ++i) { |
| 875 | lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma); | 993 | lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma); |
| 876 | } | 994 | } |
| 877 | } else { | 995 | } else { |
| 878 | lut->size = curv->numents; | 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 | goto error; | 998 | goto error; |
| 999 | } | ||
| 881 | for (unsigned i = 0; i < lut->size; ++i) { | 1000 | for (unsigned i = 0; i < lut->size; ++i) { |
| 882 | lut->data[i] = (jas_cmreal_t)curv->ents[i] / 65535.0; | 1001 | lut->data[i] = (jas_cmreal_t)curv->ents[i] / 65535.0; |
| 883 | } | 1002 | } |
| 884 | } | 1003 | } |
| 885 | return 0; | 1004 | return 0; |
| 886 | error: | 1005 | error: |
| 1006 | jas_cmshapmatlut_cleanup(lut); | ||
| 887 | return -1; | 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 | jas_cmreal_t t; | 1012 | jas_cmreal_t t; |
| 893 | t = x * (lut->size - 1); | 1013 | t = x * (lut->size - 1); |
| 894 | const int lo = (int)floor(t); | 1014 | const int lo = (int)floor(t); |
| 895 | if (lo < 0) | 1015 | if (lo < 0) { |
| 896 | return lut->data[0]; | 1016 | return lut->data[0]; |
| 1017 | } | ||
| 897 | const unsigned hi = (unsigned)ceil(t); | 1018 | const unsigned hi = (unsigned)ceil(t); |
| 898 | if (hi >= lut->size) | 1019 | if (hi >= lut->size) { |
| 899 | return lut->data[lut->size - 1]; | 1020 | return lut->data[lut->size - 1]; |
| 1021 | } | ||
| 900 | return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]); | 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 | return -1; | 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 | return -1; | 1047 | return -1; |
| 1048 | } | ||
| 926 | invlut->size = n; | 1049 | invlut->size = n; |
| 927 | for (unsigned i = 0; i < invlut->size; ++i) { | 1050 | for (unsigned i = 0; i < invlut->size; ++i) { |
| 928 | sy = ((double) i) / (invlut->size - 1); | 1051 | sy = ((double) i) / (invlut->size - 1); |
| @@ -933,11 +1056,9 @@ static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut, · 4 unmodified lines | |||
| 933 | unsigned k; | 1056 | unsigned k; |
| 934 | for (k = j + 1; k < lut->size; ++k) { | 1057 | for (k = j + 1; k < lut->size; ++k) { |
| 935 | by = lut->data[k]; | 1058 | by = lut->data[k]; |
| 936 | if (by != sy) | 1059 | if (by != sy) { |
| 937 | break; | 1060 | break; |
| 938 | #if 0 | 1061 | } |
| 939 | assert(0); | ||
| 940 | #endif | ||
| 941 | } | 1062 | } |
| 942 | if (k < lut->size) { | 1063 | if (k < lut->size) { |
| 943 | --k; | 1064 | --k; |
| @@ -961,10 +1082,12 @@ assert(0); · 17 unmodified lines | |||
| 961 | invlut->data[i] = sx; | 1082 | invlut->data[i] = sx; |
| 962 | } | 1083 | } |
| 963 | #if 0 | 1084 | #if 0 |
| 964 | for (i=0;i<lut->size;++i) | 1085 | for (i=0;i<lut->size;++i) { |
| 965 | jas_eprintf("lut[%d]=%f ", i, lut->data[i]); | 1086 | jas_eprintf("lut[%d]=%f ", i, lut->data[i]); |
| 966 | for (i=0;i<invlut->size;++i) | 1087 | } |
| 967 | jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]); | 1088 | for (i=0;i<invlut->size;++i) { |
| 1089 | jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]); | ||
| 1090 | } | ||
| 968 | #endif | 1091 | #endif |
| 969 | return 0; | 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 | d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1]) | 1098 | d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1]) |
| 976 | - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0]) | 1099 | - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0]) |
| 977 | + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]); | 1100 | + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]); |
| 978 | #if 0 | 1101 | if (JAS_ABS(d) < 1e-6) { |
| 979 | jas_eprintf("delta=%f\n", d); | 1102 | jas_logerrorf("jas_cmshapmat_invmat: matrix is not invertible " |
| 980 | #endif | 1103 | "(determinant %a)\n", d); |
| 981 | if (JAS_ABS(d) < 1e-6) | ||
| 982 | return -1; | 1104 | return -1; |
| 1105 | } | ||
| 983 | out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d; | 1106 | out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d; |
| 984 | out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d; | 1107 | out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d; |
| 985 | out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d; | 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 | out[1][3] = -in[1][3]; | 1116 | out[1][3] = -in[1][3]; |
| 994 | out[2][3] = -in[2][3]; | 1117 | out[2][3] = -in[2][3]; |
| 995 | #if 0 | 1118 | #if 0 |
| 996 | jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", | 1119 | 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], | 1120 | 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], | 1121 | 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]); | 1122 | 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", | 1123 | 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], | 1124 | 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], | 1125 | 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]); | 1126 | out[2][0], out[2][1], out[2][2], out[2][3]); |
| 1004 | #endif | 1127 | #endif |
| 1005 | return 0; | 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 | if (refflag) { | 1137 | if (refflag) { |
| 1015 | switch (iccclrspc) { | 1138 | switch (iccclrspc) { |
| 1016 | case JAS_ICC_COLORSPC_XYZ: | 1139 | case JAS_ICC_COLORSPC_XYZ: |
| 1017 | return JAS_CLRSPC_CIEXYZ; | 1140 | *clrspc = JAS_CLRSPC_CIEXYZ; |
| 1141 | return 0; | ||
| 1018 | case JAS_ICC_COLORSPC_LAB: | 1142 | case JAS_ICC_COLORSPC_LAB: |
| 1019 | return JAS_CLRSPC_CIELAB; | 1143 | *clrspc = JAS_CLRSPC_CIELAB; |
| 1144 | return 0; | ||
| 1020 | default: | 1145 | default: |
| 1021 | abort(); | 1146 | return -1; |
| 1022 | } | 1147 | } |
| 1023 | } else { | 1148 | } else { |
| 1024 | switch (iccclrspc) { | 1149 | switch (iccclrspc) { |
| 1025 | case JAS_ICC_COLORSPC_YCBCR: | 1150 | case JAS_ICC_COLORSPC_YCBCR: |
| 1026 | return JAS_CLRSPC_GENYCBCR; | 1151 | *clrspc = JAS_CLRSPC_GENYCBCR; |
| 1152 | return 0; | ||
| 1027 | case JAS_ICC_COLORSPC_RGB: | 1153 | case JAS_ICC_COLORSPC_RGB: |
| 1028 | return JAS_CLRSPC_GENRGB; | 1154 | *clrspc = JAS_CLRSPC_GENRGB; |
| 1155 | return 0; | ||
| 1029 | case JAS_ICC_COLORSPC_GRAY: | 1156 | case JAS_ICC_COLORSPC_GRAY: |
| 1030 | return JAS_CLRSPC_GENGRAY; | 1157 | *clrspc = JAS_CLRSPC_GENGRAY; |
| 1158 | return 0; | ||
| 1031 | default: | 1159 | default: |
| 1032 | abort(); | 1160 | return -1; |
| 1033 | } | 1161 | } |
| 1034 | } | 1162 | } |
| 1035 | return -1; | ||
| 1036 | } | 1163 | } |
| 1037 | 1164 | ||
| 1038 | static int mono(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) | 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 | jas_cmshapmatlut_init(&lut); | 1173 | jas_cmshapmatlut_init(&lut); |
| 1047 | if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) || | 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 | goto error; | 1176 | goto error; |
| 1050 | if (!(pxform = jas_cmpxform_createshapmat())) | 1177 | } |
| 1178 | if (!(pxform = jas_cmpxform_createshapmat())) { | ||
| 1051 | goto error; | 1179 | goto error; |
| 1180 | } | ||
| 1052 | shapmat = &pxform->data.shapmat; | 1181 | shapmat = &pxform->data.shapmat; |
| 1053 | if (!(pxformseq = jas_cmpxformseq_create())) | 1182 | if (!(pxformseq = jas_cmpxformseq_create())) { |
| 1054 | goto error; | 1183 | goto error; |
| 1055 | if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) | 1184 | } |
| 1185 | if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) { | ||
| 1056 | goto error; | 1186 | goto error; |
| 1187 | } | ||
| 1057 | 1188 | ||
| 1058 | pxform->numinchans = 1; | 1189 | pxform->numinchans = 1; |
| 1059 | pxform->numoutchans = 3; | 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 | shapmat->mat[0][0] = 0.9642; | 1197 | shapmat->mat[0][0] = 0.9642; |
| 1067 | shapmat->mat[1][0] = 1.0; | 1198 | shapmat->mat[1][0] = 1.0; |
| 1068 | shapmat->mat[2][0] = 0.8249; | 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 | goto error; | 1201 | goto error; |
| 1202 | } | ||
| 1071 | } else { | 1203 | } else { |
| 1072 | shapmat->order = 1; | 1204 | shapmat->order = 1; |
| 1073 | shapmat->mat[0][0] = 1.0 / 0.9642; | 1205 | shapmat->mat[0][0] = 1.0 / 0.9642; |
| 1074 | shapmat->mat[1][0] = 1.0; | 1206 | shapmat->mat[1][0] = 1.0; |
| 1075 | shapmat->mat[2][0] = 1.0 / 0.8249; | 1207 | shapmat->mat[2][0] = 1.0 / 0.8249; |
| 1076 | jas_cmshapmatlut_init(&lut); | 1208 | jas_cmshapmatlut_init(&lut); |
| 1077 | if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv)) | 1209 | if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv)) { |
| 1078 | goto error; | 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 | goto error; | 1213 | goto error; |
| 1214 | } | ||
| 1081 | jas_cmshapmatlut_cleanup(&lut); | 1215 | jas_cmshapmatlut_cleanup(&lut); |
| 1082 | } | 1216 | } |
| 1083 | jas_iccattrval_destroy(graytrc); | 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 | *retpxformseq = pxformseq; | 1219 | *retpxformseq = pxformseq; |
| 1086 | return 0; | 1220 | return 0; |
| 1087 | error: | 1221 | error: |
| 1088 | if (graytrc) | 1222 | jas_cmshapmatlut_cleanup(&lut); |
| 1223 | if (graytrc) { | ||
| 1089 | jas_iccattrval_destroy(graytrc); | 1224 | jas_iccattrval_destroy(graytrc); |
| 1090 | if (pxform) | 1225 | } |
| 1226 | if (pxform) { | ||
| 1091 | jas_cmpxform_destroy(pxform); | 1227 | jas_cmpxform_destroy(pxform); |
| 1092 | if (pxformseq) | 1228 | } |
| 1229 | if (pxformseq) { | ||
| 1093 | jas_cmpxformseq_destroy(pxformseq); | 1230 | jas_cmpxformseq_destroy(pxformseq); |
| 1231 | } | ||
| 1094 | return -1; | 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 | jas_iccattrval_t *trcs[3]; | 1238 | jas_iccattrval_t *trcs[3]; |
| 1100 | jas_iccattrval_t *cols[3]; | 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 | jas_cmpxformseq_t *pxformseq; | 1242 | jas_cmpxformseq_t *pxformseq; |
| 1104 | jas_cmreal_t mat[3][4]; | 1243 | jas_cmreal_t mat[3][4]; |
| 1105 | jas_cmshapmatlut_t lut; | 1244 | jas_cmshapmatlut_t lut; |
| 1245 | jas_cmshapmatlut_init(&lut); | ||
| 1106 | 1246 | ||
| 1107 | pxform = 0; | 1247 | pxform = 0; |
| 1108 | pxformseq = 0; | 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 | !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) || | 1257 | !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) || |
| 1118 | !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) || | 1258 | !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) || |
| 1119 | !(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) || | 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 | goto error; | 1262 | goto error; |
| 1263 | } | ||
| 1122 | for (unsigned i = 0; i < 3; ++i) { | 1264 | for (unsigned i = 0; i < 3; ++i) { |
| 1123 | if (trcs[i]->type != JAS_ICC_TYPE_CURV || | 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 | goto error; | 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 | goto error; | 1273 | goto error; |
| 1274 | } | ||
| 1129 | pxform->numinchans = 3; | 1275 | pxform->numinchans = 3; |
| 1130 | pxform->numoutchans = 3; | 1276 | pxform->numoutchans = 3; |
| 1131 | shapmat = &pxform->data.shapmat; | 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 | goto error; | 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 | goto error; | 1284 | goto error; |
| 1285 | } | ||
| 1136 | shapmat->mono = 0; | 1286 | shapmat->mono = 0; |
| 1137 | shapmat->useluts = 1; | 1287 | shapmat->useluts = 1; |
| 1138 | shapmat->usemat = 1; | 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 | shapmat->mat[1][i] = (jas_cmreal_t)cols[i]->data.xyz.y / 65536.0; | 1293 | shapmat->mat[1][i] = (jas_cmreal_t)cols[i]->data.xyz.y / 65536.0; |
| 1144 | shapmat->mat[2][i] = (jas_cmreal_t)cols[i]->data.xyz.z / 65536.0; | 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 | shapmat->mat[i][3] = 0.0; | 1297 | shapmat->mat[i][3] = 0.0; |
| 1298 | } | ||
| 1148 | for (unsigned i = 0; i < 3; ++i) { | 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 | goto error; | 1302 | goto error; |
| 1303 | } | ||
| 1151 | } | 1304 | } |
| 1152 | } else { | 1305 | } else { |
| 1153 | shapmat->order = 1; | 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 | mat[1][i] = (jas_cmreal_t)cols[i]->data.xyz.y / 65536.0; | 1309 | mat[1][i] = (jas_cmreal_t)cols[i]->data.xyz.y / 65536.0; |
| 1157 | mat[2][i] = (jas_cmreal_t)cols[i]->data.xyz.z / 65536.0; | 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 | mat[i][3] = 0.0; | 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 | goto error; | 1317 | goto error; |
| 1318 | } | ||
| 1163 | for (unsigned i = 0; i < 3; ++i) { | 1319 | for (unsigned i = 0; i < 3; ++i) { |
| 1164 | jas_cmshapmatlut_init(&lut); | 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 | goto error; | 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 | goto error; | 1327 | goto error; |
| 1328 | } | ||
| 1169 | jas_cmshapmatlut_cleanup(&lut); | 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 | error: | 1340 | error: |
| 1181 | 1341 | ||
| 1342 | jas_cmshapmatlut_cleanup(&lut); | ||
| 1182 | for (unsigned i = 0; i < 3; ++i) { | 1343 | for (unsigned i = 0; i < 3; ++i) { |
| 1183 | if (trcs[i]) { | 1344 | if (trcs[i]) { |
| 1184 | jas_iccattrval_destroy(trcs[i]); | 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 | v = **bufptr; | 1365 | v = **bufptr; |
| 1205 | if (sgnd) { | 1366 | if (sgnd) { |
| 1206 | m = (1 << (prec - 1)); | 1367 | m = (1 << (prec - 1)); |
| 1207 | if (v < -m || v >= m) | 1368 | if (v < -m || v >= m) { |
| 1208 | return -1; | 1369 | return -1; |
| 1370 | } | ||
| 1209 | } else { | 1371 | } else { |
| 1210 | if (v < 0 || v >= (1 << prec)) | 1372 | if (v < 0 || v >= (1 << prec)) { |
| 1211 | return -1; | 1373 | return -1; |
| 1374 | } | ||
| 1212 | } | 1375 | } |
| 1213 | ++(*bufptr); | 1376 | ++(*bufptr); |
| 1214 | *val = v; | 1377 | *val = v; |
| @@ -1220,11 +1383,13 @@ static int jas_cmputint(long **bufptr, int sgnd, unsigned prec, long val) · 5 unmodified lines | |||
| 1220 | int m; | 1383 | int m; |
| 1221 | if (sgnd) { | 1384 | if (sgnd) { |
| 1222 | m = (1 << (prec - 1)); | 1385 | m = (1 << (prec - 1)); |
| 1223 | if (val < -m || val >= m) | 1386 | if (val < -m || val >= m) { |
| 1224 | return -1; | 1387 | return -1; |
| 1388 | } | ||
| 1225 | } else { | 1389 | } else { |
| 1226 | if (val < 0 || val >= (1 << prec)) | 1390 | if (val < 0 || val >= (1 << prec)) { |
| 1227 | return -1; | 1391 | return -1; |
| 1392 | } | ||
| 1228 | } | 1393 | } |
| 1229 | **bufptr = val; | 1394 | **bufptr = val; |
| 1230 | ++(*bufptr); | 1395 | ++(*bufptr); |
| @@ -1243,8 +1408,8 @@ unsigned jas_clrspc_numchans(jas_clrspc_t clrspc) · 12 unmodified lines | |||
| 1243 | return 1; | 1408 | return 1; |
| 1244 | default: | 1409 | default: |
| 1245 | abort(); | 1410 | abort(); |
| 1411 | return 0; | ||
| 1246 | } | 1412 | } |
| 1247 | return -1; | ||
| 1248 | } | 1413 | } |
| 1249 | 1414 | ||
| 1250 | jas_iccprof_t *jas_iccprof_createfromcmprof(const jas_cmprof_t *prof) | 1415 | jas_iccprof_t *jas_iccprof_createfromcmprof(const jas_cmprof_t *prof) |
| @@ -63,53 +63,214 @@ · 62 unmodified lines | |||
| 63 | * Includes. | 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 | #include "jasper/jas_debug.h" | 70 | #include "jasper/jas_debug.h" |
| 67 | #include "jasper/jas_types.h" | 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; | 78 | /* Set the library debug level. */ |
| 74 | /* The 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. */ | 92 | /* Perform formatted output to standard error. */ |
| 81 | int jas_setdbglevel(int dbglevel) | 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. */ | 103 | /* Generate formatted error log message. */ |
| 86 | olddbglevel = jas_dbglevel; | 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. */ | 115 | /* Generate formatted error log message. */ |
| 89 | jas_dbglevel = dbglevel; | 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. */ | 127 | /* Generate formatted warning log message. */ |
| 92 | return olddbglevel; | 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. */ | 139 | /* Generate formatted informational log message. */ |
| 96 | int jas_getdbglevel() | 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 | * Code. | 260 | * Code. |
| 103 | \******************************************************************************/ | 261 | \******************************************************************************/ |
| 104 | 262 | ||
| 105 | /* Perform formatted output to standard error. */ | 263 | void jas_deprecated(const char *fmt, ...) |
| 106 | int jas_eprintf(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 | va_list ap; | 272 | va_list ap; |
| 110 | |||
| 111 | va_start(ap, fmt); | 273 | va_start(ap, fmt); |
| 112 | ret = vfprint(2, fmt, ap); | 274 | vfprintf(stderr, fmt, ap); |
| 113 | va_end(ap); | 275 | va_end(ap); |
| 114 | return ret; | ||
| 115 | } | 276 | } |
| @@ -59,12 +59,23 @@ · 58 unmodified lines | |||
| 59 | * __END_OF_JASPER_LICENSE__ | 59 | * __END_OF_JASPER_LICENSE__ |
| 60 | */ | 60 | */ |
| 61 | 61 | ||
| 62 | /******************************************************************************\ | ||
| 63 | * Includes. | ||
| 64 | \******************************************************************************/ | ||
| 65 | |||
| 66 | #define JAS_FOR_INTERNAL_USE_ONLY | ||
| 67 | |||
| 62 | #include "jasper/jas_icc.h" | 68 | #include "jasper/jas_icc.h" |
| 63 | #include "jasper/jas_types.h" | 69 | #include "jasper/jas_types.h" |
| 64 | #include "jasper/jas_malloc.h" | 70 | #include "jasper/jas_malloc.h" |
| 65 | #include "jasper/jas_debug.h" | 71 | #include "jasper/jas_debug.h" |
| 66 | #include "jasper/jas_cm.h" | 72 | #include "jasper/jas_cm.h" |
| 67 | #include "jasper/jas_stream.h" | 73 | #include "jasper/jas_stream.h" |
| 74 | #include "jasper/jas_string.h" | ||
| 75 | |||
| 76 | /******************************************************************************\ | ||
| 77 | * | ||
| 78 | \******************************************************************************/ | ||
| 68 | 79 | ||
| 69 | #define jas_iccputuint8(out, val) jas_iccputuint(out, 1, val) | 80 | #define jas_iccputuint8(out, val) jas_iccputuint(out, 1, val) |
| 70 | #define jas_iccputuint16(out, val) jas_iccputuint(out, 2, val) | 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 | static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val); | 91 | static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val); |
| 81 | static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val); | 92 | static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val); |
| 82 | static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val); | 93 | static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val); |
| 83 | //#ifdef JAS_ENABLE_ENCODER | ||
| 84 | static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val); | 94 | static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val); |
| 85 | static int jas_iccputsint(jas_stream_t *out, unsigned n, jas_longlong val); | 95 | static int jas_iccputsint(jas_stream_t *out, unsigned n, jas_longlong val); |
| 86 | //#endif /* JAS_ENABLE_ENCODER */ | ||
| 87 | static jas_iccprof_t *jas_iccprof_create(void); | 96 | static jas_iccprof_t *jas_iccprof_create(void); |
| 88 | static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr); | 97 | static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr); |
| 89 | //#ifdef JAS_ENABLE_ENCODER | ||
| 90 | static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr); | 98 | static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr); |
| 91 | //#endif | ||
| 92 | static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab); | 99 | static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab); |
| 93 | static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab); | 100 | static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab); |
| 94 | static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, jas_iccuint32_t name); | 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 | static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in, | 111 | static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 105 | unsigned cnt); | 112 | unsigned cnt); |
| 106 | static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval); | 113 | static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval); |
| 107 | //#ifdef JAS_ENABLE_ENCODER | ||
| 108 | static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out); | 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 | static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval); | 117 | static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval); |
| 112 | static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval, | 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 | static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, | 120 | static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 115 | unsigned cnt); | 121 | unsigned cnt); |
| 116 | static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval); | 122 | static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval); |
| 117 | //#ifdef JAS_ENABLE_ENCODER | ||
| 118 | static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out); | 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 | static void jas_icctxt_destroy(jas_iccattrval_t *attrval); | 126 | static void jas_icctxt_destroy(jas_iccattrval_t *attrval); |
| 122 | static int jas_icctxt_copy(jas_iccattrval_t *attrval, | 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 | static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in, | 129 | static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 125 | unsigned cnt); | 130 | unsigned cnt); |
| 126 | static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval); | 131 | static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval); |
| 127 | //#ifdef JAS_ENABLE_ENCODER | ||
| 128 | static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out); | 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 | static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in, | 135 | static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 132 | unsigned cnt); | 136 | unsigned cnt); |
| 133 | static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval); | 137 | static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval); |
| 134 | //#ifdef JAS_ENABLE_ENCODER | ||
| 135 | static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out); | 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 | static jas_iccattrtab_t *jas_iccattrtab_create(void); | 141 | static jas_iccattrtab_t *jas_iccattrtab_create(void); |
| 139 | static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab); | 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 | static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, unsigned i, | 146 | static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, unsigned i, |
| 144 | jas_iccuint32_t name, jas_iccattrval_t *val); | 147 | jas_iccuint32_t name, jas_iccattrval_t *val); |
| 145 | static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, unsigned i); | 148 | static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, unsigned i); |
| 146 | //#ifdef JAS_ENABLE_ENCODER | ||
| 147 | static unsigned jas_iccpadtomult(unsigned x, unsigned y); | 149 | static unsigned jas_iccpadtomult(unsigned x, unsigned y); |
| 148 | static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i, | 150 | static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i, |
| 149 | jas_iccattrname_t *name, jas_iccattrval_t **val); | 151 | jas_iccattrname_t *name, jas_iccattrval_t **val); |
| 150 | static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab); | 152 | static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab); |
| 151 | //#endif /* JAS_ENABLE_ENCODER */ | ||
| 152 | 153 | ||
| 153 | static void jas_icclut16_destroy(jas_iccattrval_t *attrval); | 154 | static void jas_icclut16_destroy(jas_iccattrval_t *attrval); |
| 154 | static int jas_icclut16_copy(jas_iccattrval_t *attrval, | 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 | static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in, | 157 | static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 157 | unsigned cnt); | 158 | unsigned cnt); |
| 158 | static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval); | 159 | static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval); |
| 159 | //#ifdef JAS_ENABLE_ENCODER | ||
| 160 | static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out); | 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 | static void jas_icclut8_destroy(jas_iccattrval_t *attrval); | 163 | static void jas_icclut8_destroy(jas_iccattrval_t *attrval); |
| 164 | static int jas_icclut8_copy(jas_iccattrval_t *attrval, | 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 | static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in, | 166 | static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 167 | unsigned cnt); | 167 | unsigned cnt); |
| 168 | static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval); | 168 | static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval); |
| 169 | //#ifdef JAS_ENABLE_ENCODER | ||
| 170 | static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out); | 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 | static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *ctime); | 172 | static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *ctime); |
| 175 | static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz); | 173 | static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz); |
| 176 | //#endif /* JAS_ENABLE_ENCODER */ | ||
| 177 | 174 | ||
| 178 | static unsigned jas_iccpowi(unsigned x, unsigned n); | 175 | static unsigned jas_iccpowi(unsigned x, unsigned n); |
| 179 | 176 | ||
| 180 | static char *jas_iccsigtostr(unsigned sig, char *buf); | 177 | static char *jas_iccsigtostr(unsigned sig, char *buf); |
| 181 | 178 | ||
| 179 | /******************************************************************************\ | ||
| 180 | * Data. | ||
| 181 | \******************************************************************************/ | ||
| 182 | 182 | ||
| 183 | static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { | 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 | jas_icccurv_destroy, | 186 | jas_icccurv_destroy, |
| 187 | jas_icccurv_copy, | 187 | jas_icccurv_copy, |
| 188 | jas_icccurv_input, | 188 | jas_icccurv_input, |
| 189 | //#ifdef JAS_ENABLE_ENCODER | ||
| 190 | jas_icccurv_output, | 189 | jas_icccurv_output, |
| 191 | //#endif | ||
| 192 | jas_icccurv_getsize, | 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 | 0, | 197 | 0, |
| 199 | 0, | 198 | 0, |
| 200 | jas_iccxyz_input, | 199 | jas_iccxyz_input, |
| 201 | //#ifdef JAS_ENABLE_ENCODER | ||
| 202 | jas_iccxyz_output, | 200 | jas_iccxyz_output, |
| 203 | //#endif | ||
| 204 | jas_iccxyz_getsize, | 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 | jas_icctxtdesc_destroy, | 208 | jas_icctxtdesc_destroy, |
| 211 | jas_icctxtdesc_copy, | 209 | jas_icctxtdesc_copy, |
| 212 | jas_icctxtdesc_input, | 210 | jas_icctxtdesc_input, |
| 213 | //#ifdef JAS_ENABLE_ENCODER | ||
| 214 | jas_icctxtdesc_output, | 211 | jas_icctxtdesc_output, |
| 215 | //#endif | ||
| 216 | jas_icctxtdesc_getsize, | 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 | jas_icctxt_destroy, | 219 | jas_icctxt_destroy, |
| 223 | jas_icctxt_copy, | 220 | jas_icctxt_copy, |
| 224 | jas_icctxt_input, | 221 | jas_icctxt_input, |
| 225 | //#ifdef JAS_ENABLE_ENCODER | ||
| 226 | jas_icctxt_output, | 222 | jas_icctxt_output, |
| 227 | //#endif | ||
| 228 | jas_icctxt_getsize, | 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 | jas_icclut8_destroy, | 230 | jas_icclut8_destroy, |
| 235 | jas_icclut8_copy, | 231 | jas_icclut8_copy, |
| 236 | jas_icclut8_input, | 232 | jas_icclut8_input, |
| 237 | //#ifdef JAS_ENABLE_ENCODER | ||
| 238 | jas_icclut8_output, | 233 | jas_icclut8_output, |
| 239 | //#endif | ||
| 240 | jas_icclut8_getsize, | 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 | jas_icclut16_destroy, | 240 | jas_icclut16_destroy, |
| 246 | jas_icclut16_copy, | 241 | jas_icclut16_copy, |
| 247 | jas_icclut16_input, | 242 | jas_icclut16_input, |
| 248 | //#ifdef JAS_ENABLE_ENCODER | ||
| 249 | jas_icclut16_output, | 243 | jas_icclut16_output, |
| 250 | //#endif | ||
| 251 | jas_icclut16_getsize, | 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 | 0, | 251 | 0, |
| 258 | 0, | 252 | 0, |
| 259 | 0, | 253 | 0, |
| 260 | //#ifdef JAS_ENABLE_ENCODER | ||
| 261 | 0, | 254 | 0, |
| 262 | //#endif | 255 | 0, |
| 263 | 0, | 256 | 0, |
| 264 | }, | 257 | }, |
| 265 | } | 258 | } |
| @@ -275,46 +268,58 @@ static jas_iccprof_t *jas_iccprof_create() · 9 unmodified lines | |||
| 275 | if (!(prof = jas_malloc(sizeof(jas_iccprof_t)))) { | 268 | if (!(prof = jas_malloc(sizeof(jas_iccprof_t)))) { |
| 276 | goto error; | 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 | prof->tagtab.numents = 0; | 271 | prof->tagtab.numents = 0; |
| 282 | prof->tagtab.ents = 0; | 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 | return prof; | 277 | return prof; |
| 284 | error: | 278 | error: |
| 285 | if (prof) | 279 | if (prof) { |
| 286 | jas_iccprof_destroy(prof); | 280 | jas_iccprof_destroy(prof); |
| 281 | } | ||
| 287 | return 0; | 282 | return 0; |
| 288 | } | 283 | } |
| 289 | 284 | ||
| 290 | jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof) | 285 | jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof) |
| 291 | { | 286 | { |
| 292 | jas_iccprof_t *newprof; | 287 | jas_iccprof_t *newprof; |
| 293 | if (!(newprof = jas_iccprof_create())) | 288 | if (!(newprof = jas_iccprof_create())) { |
| 294 | goto error; | 289 | goto error; |
| 290 | } | ||
| 295 | newprof->hdr = prof->hdr; | 291 | newprof->hdr = prof->hdr; |
| 296 | newprof->tagtab.numents = 0; | 292 | newprof->tagtab.numents = 0; |
| 297 | newprof->tagtab.ents = 0; | 293 | newprof->tagtab.ents = 0; |
| 298 | assert(newprof->attrtab); | 294 | assert(newprof->attrtab); |
| 299 | jas_iccattrtab_destroy(newprof->attrtab); | 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 | goto error; | 297 | goto error; |
| 298 | } | ||
| 302 | return newprof; | 299 | return newprof; |
| 303 | error: | 300 | error: |
| 304 | if (newprof) | 301 | if (newprof) { |
| 305 | jas_iccprof_destroy(newprof); | 302 | jas_iccprof_destroy(newprof); |
| 303 | } | ||
| 306 | return 0; | 304 | return 0; |
| 307 | } | 305 | } |
| 308 | 306 | ||
| 309 | void jas_iccprof_destroy(jas_iccprof_t *prof) | 307 | void jas_iccprof_destroy(jas_iccprof_t *prof) |
| 310 | { | 308 | { |
| 311 | if (prof->attrtab) | 309 | if (prof->attrtab) { |
| 312 | jas_iccattrtab_destroy(prof->attrtab); | 310 | jas_iccattrtab_destroy(prof->attrtab); |
| 313 | if (prof->tagtab.ents) | 311 | } |
| 312 | if (prof->tagtab.ents) { | ||
| 314 | jas_free(prof->tagtab.ents); | 313 | jas_free(prof->tagtab.ents); |
| 314 | } | ||
| 315 | jas_free(prof); | 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 | jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) | 323 | jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) |
| 319 | { | 324 | { |
| 320 | jas_iccprof_t *prof; | 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 | if (jas_iccprof_readhdr(in, &prof->hdr)) { | 339 | if (jas_iccprof_readhdr(in, &prof->hdr)) { |
| 335 | jas_eprintf("cannot get header\n"); | 340 | jas_logerrorf("cannot get header\n"); |
| 336 | goto error; | 341 | goto error; |
| 337 | } | 342 | } |
| 338 | if (jas_iccprof_gettagtab(in, &prof->tagtab)) { | 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 | goto error; | 345 | goto error; |
| 341 | } | 346 | } |
| 342 | jas_iccprof_sorttagtab(&prof->tagtab); | 347 | jas_iccprof_sorttagtab(&prof->tagtab); |
| @@ -349,23 +354,24 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 6 unmodified lines | |||
| 349 | const jas_icctagtabent_t *tagtabent = &prof->tagtab.ents[i]; | 354 | const jas_icctagtabent_t *tagtabent = &prof->tagtab.ents[i]; |
| 350 | if (tagtabent->off == JAS_CAST(jas_iccuint32_t, prevoff)) { | 355 | if (tagtabent->off == JAS_CAST(jas_iccuint32_t, prevoff)) { |
| 351 | if (prevattrval) { | 356 | if (prevattrval) { |
| 352 | if (!(attrval = jas_iccattrval_clone(prevattrval))) | 357 | if (!(attrval = jas_iccattrval_clone(prevattrval))) { |
| 353 | goto error; | 358 | goto error; |
| 354 | if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) | 359 | } |
| 360 | if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) { | ||
| 355 | goto error; | 361 | goto error; |
| 362 | } | ||
| 356 | jas_iccattrval_destroy(attrval); | 363 | jas_iccattrval_destroy(attrval); |
| 357 | attrval = 0; | 364 | attrval = 0; |
| 358 | } else { | 365 | } else { |
| 359 | #if 0 | 366 | jas_logwarnf("warning: skipping unknown tag type\n"); |
| 360 | jas_eprintf("warning: skipping unknown tag type\n"); | ||
| 361 | #endif | ||
| 362 | } | 367 | } |
| 363 | continue; | 368 | continue; |
| 364 | } | 369 | } |
| 365 | reloff = tagtabent->off - curoff; | 370 | reloff = tagtabent->off - curoff; |
| 366 | if (reloff > 0) { | 371 | if (reloff > 0) { |
| 367 | if (jas_stream_gobble(in, reloff) != reloff) | 372 | if (jas_stream_gobble(in, reloff) != reloff) { |
| 368 | goto error; | 373 | goto error; |
| 374 | } | ||
| 369 | curoff += reloff; | 375 | curoff += reloff; |
| 370 | } else if (reloff < 0) { | 376 | } else if (reloff < 0) { |
| 371 | goto error; | 377 | goto error; |
| @@ -379,9 +385,7 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 7 unmodified lines | |||
| 379 | } | 385 | } |
| 380 | curoff += 8; | 386 | curoff += 8; |
| 381 | if (!jas_iccattrvalinfo_lookup(type)) { | 387 | if (!jas_iccattrvalinfo_lookup(type)) { |
| 382 | #if 0 | 388 | jas_logwarnf("warning: skipping unknown tag type\n"); |
| 383 | jas_eprintf("warning: skipping unknown tag type\n"); | ||
| 384 | #endif | ||
| 385 | prevattrval = 0; | 389 | prevattrval = 0; |
| 386 | continue; | 390 | continue; |
| 387 | } | 391 | } |
| @@ -404,16 +408,17 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 16 unmodified lines | |||
| 404 | return prof; | 408 | return prof; |
| 405 | 409 | ||
| 406 | error: | 410 | error: |
| 407 | if (prof) | 411 | if (prof) { |
| 408 | jas_iccprof_destroy(prof); | 412 | jas_iccprof_destroy(prof); |
| 409 | if (attrval) | 413 | } |
| 414 | if (attrval) { | ||
| 410 | jas_iccattrval_destroy(attrval); | 415 | jas_iccattrval_destroy(attrval); |
| 416 | } | ||
| 411 | return 0; | 417 | return 0; |
| 412 | } | 418 | } |
| 413 | 419 | ||
| 414 | int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out) | 420 | int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out) |
| 415 | { | 421 | { |
| 416 | //#ifdef JAS_ENABLE_ENCODER | ||
| 417 | long curoff; | 422 | long curoff; |
| 418 | long reloff; | 423 | long reloff; |
| 419 | long newoff; | 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 | tagtab = &prof->tagtab; | 432 | tagtab = &prof->tagtab; |
| 428 | if (!(tagtab->ents = jas_alloc2(prof->attrtab->numattrs, | 433 | if (!(tagtab->ents = jas_alloc2(prof->attrtab->numattrs, |
| 429 | sizeof(jas_icctagtabent_t)))) | 434 | sizeof(jas_icctagtabent_t)))) { |
| 430 | goto error; | 435 | goto error; |
| 436 | } | ||
| 431 | tagtab->numents = prof->attrtab->numattrs; | 437 | tagtab->numents = prof->attrtab->numattrs; |
| 432 | curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents; | 438 | curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents; |
| 433 | for (unsigned i = 0; i < tagtab->numents; ++i) { | 439 | for (unsigned i = 0; i < tagtab->numents; ++i) { |
| 434 | tagtabent = &tagtab->ents[i]; | 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 | goto error; | 442 | goto error; |
| 443 | } | ||
| 437 | assert(attrval->ops->output); | 444 | assert(attrval->ops->output); |
| 438 | tagtabent->tag = attrname; | 445 | tagtabent->tag = attrname; |
| 439 | tagtabent->data = &attrval->data; | 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 | jas_iccattrval_destroy(attrval); | 469 | jas_iccattrval_destroy(attrval); |
| 463 | } | 470 | } |
| 464 | prof->hdr.size = curoff; | 471 | prof->hdr.size = curoff; |
| 465 | if (jas_iccprof_writehdr(out, &prof->hdr)) | 472 | if (jas_iccprof_writehdr(out, &prof->hdr)) { |
| 466 | goto error; | 473 | goto error; |
| 467 | if (jas_iccprof_puttagtab(out, &prof->tagtab)) | 474 | } |
| 475 | if (jas_iccprof_puttagtab(out, &prof->tagtab)) { | ||
| 468 | goto error; | 476 | goto error; |
| 477 | } | ||
| 469 | curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents; | 478 | curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents; |
| 470 | for (unsigned i = 0; i < tagtab->numents;) { | 479 | for (unsigned i = 0; i < tagtab->numents;) { |
| 471 | tagtabent = &tagtab->ents[i]; | 480 | tagtabent = &tagtab->ents[i]; |
| 472 | assert(curoff == JAS_CAST(long, tagtabent->off)); | 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 | goto error; | 483 | goto error; |
| 484 | } | ||
| 475 | if (jas_iccputuint32(out, attrval->type) || jas_stream_pad(out, | 485 | if (jas_iccputuint32(out, attrval->type) || jas_stream_pad(out, |
| 476 | 4, 0) != 4) | 486 | 4, 0) != 4) { |
| 477 | goto error; | 487 | goto error; |
| 478 | if ((*attrval->ops->output)(attrval, out)) | 488 | } |
| 489 | if ((*attrval->ops->output)(attrval, out)) { | ||
| 479 | goto error; | 490 | goto error; |
| 491 | } | ||
| 480 | jas_iccattrval_destroy(attrval); | 492 | jas_iccattrval_destroy(attrval); |
| 481 | curoff += tagtabent->len; | 493 | curoff += tagtabent->len; |
| 482 | ++i; | 494 | ++i; |
| 483 | while (i < tagtab->numents && | 495 | while (i < tagtab->numents && tagtab->ents[i].first) { |
| 484 | tagtab->ents[i].first) | ||
| 485 | ++i; | 496 | ++i; |
| 497 | } | ||
| 486 | newoff = (i < tagtab->numents) ? | 498 | newoff = (i < tagtab->numents) ? |
| 487 | tagtab->ents[i].off : prof->hdr.size; | 499 | tagtab->ents[i].off : prof->hdr.size; |
| 488 | reloff = newoff - curoff; | 500 | reloff = newoff - curoff; |
| 489 | assert(reloff >= 0); | 501 | assert(reloff >= 0); |
| 490 | if (reloff > 0) { | 502 | if (reloff > 0) { |
| 491 | if (jas_stream_pad(out, reloff, 0) != reloff) | 503 | if (jas_stream_pad(out, reloff, 0) != reloff) { |
| 492 | goto error; | 504 | goto error; |
| 505 | } | ||
| 493 | curoff += reloff; | 506 | curoff += reloff; |
| 494 | } | 507 | } |
| 495 | } | 508 | } |
| 496 | return 0; | 509 | return 0; |
| 497 | error: | 510 | error: |
| 498 | /* XXX - need to free some resources here */ | 511 | /* XXX - need to free some resources here */ |
| 499 | //#else | ||
| 500 | // (void)prof; | ||
| 501 | // (void)out; | ||
| 502 | //#endif /* JAS_ENABLE_ENCODER */ | ||
| 503 | return -1; | 512 | return -1; |
| 504 | } | 513 | } |
| 505 | 514 | ||
| 506 | //#ifdef JAS_ENABLE_ENCODER | ||
| 507 | |||
| 508 | static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr) | 515 | static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr) |
| 509 | { | 516 | { |
| 510 | if (jas_iccputuint32(out, hdr->size) || | 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 | jas_iccputuint32(out, hdr->intent) || | 530 | jas_iccputuint32(out, hdr->intent) || |
| 524 | jas_iccputxyz(out, &hdr->illum) || | 531 | jas_iccputxyz(out, &hdr->illum) || |
| 525 | jas_iccputuint32(out, hdr->creator) || | 532 | jas_iccputuint32(out, hdr->creator) || |
| 526 | jas_stream_pad(out, 44, 0) != 44) | 533 | jas_stream_pad(out, 44, 0) != 44) { |
| 527 | return -1; | 534 | return -1; |
| 535 | } | ||
| 528 | return 0; | 536 | return 0; |
| 529 | } | 537 | } |
| 530 | 538 | ||
| 531 | static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab) | 539 | static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab) |
| 532 | { | 540 | { |
| 533 | jas_icctagtabent_t *tagtabent; | 541 | jas_icctagtabent_t *tagtabent; |
| 534 | if (jas_iccputuint32(out, tagtab->numents)) | 542 | if (jas_iccputuint32(out, tagtab->numents)) { |
| 535 | goto error; | 543 | goto error; |
| 544 | } | ||
| 536 | for (unsigned i = 0; i < tagtab->numents; ++i) { | 545 | for (unsigned i = 0; i < tagtab->numents; ++i) { |
| 537 | tagtabent = &tagtab->ents[i]; | 546 | tagtabent = &tagtab->ents[i]; |
| 538 | if (jas_iccputuint32(out, tagtabent->tag) || | 547 | if (jas_iccputuint32(out, tagtabent->tag) || |
| 539 | jas_iccputuint32(out, tagtabent->off) || | 548 | jas_iccputuint32(out, tagtabent->off) || |
| 540 | jas_iccputuint32(out, tagtabent->len)) | 549 | jas_iccputuint32(out, tagtabent->len)) { |
| 541 | goto error; | 550 | goto error; |
| 551 | } | ||
| 542 | } | 552 | } |
| 543 | return 0; | 553 | return 0; |
| 544 | error: | 554 | error: |
| 545 | return -1; | 555 | return -1; |
| 546 | } | 556 | } |
| 547 | 557 | ||
| 548 | //#endif | ||
| 549 | |||
| 550 | static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr) | 558 | static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr) |
| 551 | { | 559 | { |
| 552 | if (jas_iccgetuint32(in, &hdr->size) || | 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 | jas_iccgetuint32(in, &hdr->intent) || | 573 | jas_iccgetuint32(in, &hdr->intent) || |
| 566 | jas_iccgetxyz(in, &hdr->illum) || | 574 | jas_iccgetxyz(in, &hdr->illum) || |
| 567 | jas_iccgetuint32(in, &hdr->creator) || | 575 | jas_iccgetuint32(in, &hdr->creator) || |
| 568 | jas_stream_gobble(in, 44) != 44) | 576 | jas_stream_gobble(in, 44) != 44) { |
| 569 | return -1; | 577 | return -1; |
| 578 | } | ||
| 570 | return 0; | 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 | jas_free(tagtab->ents); | 587 | jas_free(tagtab->ents); |
| 579 | tagtab->ents = 0; | 588 | tagtab->ents = 0; |
| 580 | } | 589 | } |
| 581 | if (jas_iccgetuint32(in, &tagtab->numents)) | 590 | if (jas_iccgetuint32(in, &tagtab->numents)) { |
| 582 | goto error; | 591 | goto error; |
| 592 | } | ||
| 583 | if (!(tagtab->ents = jas_alloc2(tagtab->numents, | 593 | if (!(tagtab->ents = jas_alloc2(tagtab->numents, |
| 584 | sizeof(jas_icctagtabent_t)))) | 594 | sizeof(jas_icctagtabent_t)))) { |
| 585 | goto error; | 595 | goto error; |
| 596 | } | ||
| 586 | tagtabent = tagtab->ents; | 597 | tagtabent = tagtab->ents; |
| 587 | for (unsigned i = 0; i < tagtab->numents; ++i) { | 598 | for (unsigned i = 0; i < tagtab->numents; ++i) { |
| 588 | if (jas_iccgetuint32(in, &tagtabent->tag) || | 599 | if (jas_iccgetuint32(in, &tagtabent->tag) || |
| 589 | jas_iccgetuint32(in, &tagtabent->off) || | 600 | jas_iccgetuint32(in, &tagtabent->off) || |
| 590 | jas_iccgetuint32(in, &tagtabent->len)) | 601 | jas_iccgetuint32(in, &tagtabent->len)) { |
| 591 | goto error; | 602 | goto error; |
| 603 | } | ||
| 592 | ++tagtabent; | 604 | ++tagtabent; |
| 593 | } | 605 | } |
| 594 | return 0; | 606 | return 0; |
| @@ -605,10 +617,12 @@ jas_iccattrval_t *jas_iccprof_getattr(const jas_iccprof_t *prof, · 10 unmodified lines | |||
| 605 | { | 617 | { |
| 606 | int i; | 618 | int i; |
| 607 | jas_iccattrval_t *attrval; | 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 | goto error; | 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 | goto error; | 624 | goto error; |
| 625 | } | ||
| 612 | return attrval; | 626 | return attrval; |
| 613 | error: | 627 | error: |
| 614 | return 0; | 628 | return 0; |
| @@ -620,15 +634,17 @@ int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name, · 5 unmodified lines | |||
| 620 | int i; | 634 | int i; |
| 621 | if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) >= 0) { | 635 | if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) >= 0) { |
| 622 | if (val) { | 636 | if (val) { |
| 623 | if (jas_iccattrtab_replace(prof->attrtab, i, name, val)) | 637 | if (jas_iccattrtab_replace(prof->attrtab, i, name, val)) { |
| 624 | goto error; | 638 | goto error; |
| 639 | } | ||
| 625 | } else { | 640 | } else { |
| 626 | jas_iccattrtab_delete(prof->attrtab, i); | 641 | jas_iccattrtab_delete(prof->attrtab, i); |
| 627 | } | 642 | } |
| 628 | } else { | 643 | } else { |
| 629 | if (val) { | 644 | if (val) { |
| 630 | if (jas_iccattrtab_add(prof->attrtab, -1, name, val)) | 645 | if (jas_iccattrtab_add(prof->attrtab, -1, name, val)) { |
| 631 | goto error; | 646 | goto error; |
| 647 | } | ||
| 632 | } else { | 648 | } else { |
| 633 | /* NOP */ | 649 | /* NOP */ |
| 634 | } | 650 | } |
| @@ -658,8 +674,10 @@ static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab) · 23 unmodified lines | |||
| 658 | 674 | ||
| 659 | static int jas_icctagtabent_cmp(const void *src, const void *dst) | 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); | 677 | const jas_icctagtabent_t *srctagtabent = |
| 662 | const jas_icctagtabent_t *dsttagtabent = JAS_CAST(const jas_icctagtabent_t *, dst); | 678 | JAS_CAST(const jas_icctagtabent_t *, src); |
| 679 | const jas_icctagtabent_t *dsttagtabent = | ||
| 680 | JAS_CAST(const jas_icctagtabent_t *, dst); | ||
| 663 | if (srctagtabent->off > dsttagtabent->off) { | 681 | if (srctagtabent->off > dsttagtabent->off) { |
| 664 | return 1; | 682 | return 1; |
| 665 | } else if (srctagtabent->off < dsttagtabent->off) { | 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 | return 0; | 720 | return 0; |
| 703 | } | 721 | } |
| 704 | 722 | ||
| 705 | //#ifdef JAS_ENABLE_ENCODER | ||
| 706 | |||
| 707 | static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *time) | 723 | static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *time) |
| 708 | { | 724 | { |
| 709 | jas_iccputuint16(out, time->year); | 725 | if (jas_iccputuint16(out, time->year) || |
| 710 | jas_iccputuint16(out, time->month); | 726 | jas_iccputuint16(out, time->month) || |
| 711 | jas_iccputuint16(out, time->day); | 727 | jas_iccputuint16(out, time->day) || |
| 712 | jas_iccputuint16(out, time->hour); | 728 | jas_iccputuint16(out, time->hour) || |
| 713 | jas_iccputuint16(out, time->min); | 729 | jas_iccputuint16(out, time->min) || |
| 714 | jas_iccputuint16(out, time->sec); | 730 | jas_iccputuint16(out, time->sec)) { |
| 731 | return -1; | ||
| 732 | } | ||
| 715 | return 0; | 733 | return 0; |
| 716 | } | 734 | } |
| 717 | 735 | ||
| 718 | static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz) | 736 | static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz) |
| 719 | { | 737 | { |
| 720 | jas_iccputuint32(out, xyz->x); | 738 | if (jas_iccputuint32(out, xyz->x) || |
| 721 | jas_iccputuint32(out, xyz->y); | 739 | jas_iccputuint32(out, xyz->y) || |
| 722 | jas_iccputuint32(out, xyz->z); | 740 | jas_iccputuint32(out, xyz->z)) { |
| 741 | return -1; | ||
| 742 | } | ||
| 723 | return 0; | 743 | return 0; |
| 724 | } | 744 | } |
| 725 | 745 | ||
| 726 | //#endif /* JAS_ENABLE_ENCODER */ | ||
| 727 | |||
| 728 | /******************************************************************************\ | 746 | /******************************************************************************\ |
| 729 | * attribute table class | 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 | static jas_iccattrtab_t *jas_iccattrtab_create() | 750 | static jas_iccattrtab_t *jas_iccattrtab_create() |
| 733 | { | 751 | { |
| 734 | jas_iccattrtab_t *tab; | 752 | jas_iccattrtab_t *tab; |
| 735 | if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t)))) | 753 | if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t)))) { |
| 736 | goto error; | 754 | goto error; |
| 755 | } | ||
| 737 | tab->maxattrs = 0; | 756 | tab->maxattrs = 0; |
| 738 | tab->numattrs = 0; | 757 | tab->numattrs = 0; |
| 739 | tab->attrs = 0; | 758 | tab->attrs = 0; |
| 740 | if (jas_iccattrtab_resize(tab, 32)) | 759 | if (jas_iccattrtab_resize(tab, 32)) { |
| 741 | goto error; | 760 | goto error; |
| 761 | } | ||
| 742 | return tab; | 762 | return tab; |
| 743 | error: | 763 | error: |
| 744 | if (tab) | 764 | if (tab) { |
| 745 | jas_iccattrtab_destroy(tab); | 765 | jas_iccattrtab_destroy(tab); |
| 766 | } | ||
| 746 | return 0; | 767 | return 0; |
| 747 | } | 768 | } |
| 748 | 769 | ||
| 749 | static jas_iccattrtab_t *jas_iccattrtab_copy(const jas_iccattrtab_t *attrtab) | 770 | static jas_iccattrtab_t *jas_iccattrtab_copy(const jas_iccattrtab_t *attrtab) |
| 750 | { | 771 | { |
| 751 | jas_iccattrtab_t *newattrtab; | 772 | jas_iccattrtab_t *newattrtab; |
| 752 | if (!(newattrtab = jas_iccattrtab_create())) | 773 | if (!(newattrtab = jas_iccattrtab_create())) { |
| 753 | return NULL; | 774 | return NULL; |
| 775 | } | ||
| 754 | for (unsigned i = 0; i < attrtab->numattrs; ++i) { | 776 | for (unsigned i = 0; i < attrtab->numattrs; ++i) { |
| 755 | if (jas_iccattrtab_add(newattrtab, i, attrtab->attrs[i].name, | 777 | if (jas_iccattrtab_add(newattrtab, i, attrtab->attrs[i].name, |
| 756 | attrtab->attrs[i].val)) | 778 | attrtab->attrs[i].val)) { |
| 757 | goto error; | 779 | goto error; |
| 780 | } | ||
| 758 | } | 781 | } |
| 759 | return newattrtab; | 782 | return newattrtab; |
| 760 | error: | 783 | error: |
| @@ -773,6 +796,29 @@ static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab) · 12 unmodified lines | |||
| 773 | jas_free(tab); | 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 | static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, unsigned maxents) | 822 | static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, unsigned maxents) |
| 777 | { | 823 | { |
| 778 | jas_iccattr_t *newattrs; | 824 | jas_iccattr_t *newattrs; |
| @@ -801,12 +847,14 @@ static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i, · 22 unmodified lines | |||
| 801 | return -1; | 847 | return -1; |
| 802 | } | 848 | } |
| 803 | } | 849 | } |
| 804 | if (!(tmpattrval = jas_iccattrval_clone(val))) | 850 | if (!(tmpattrval = jas_iccattrval_clone(val))) { |
| 805 | return -1; | 851 | return -1; |
| 852 | } | ||
| 806 | const unsigned n = attrtab->numattrs - i; | 853 | const unsigned n = attrtab->numattrs - i; |
| 807 | if (n > 0) | 854 | if (n > 0) { |
| 808 | memmove(&attrtab->attrs[i + 1], &attrtab->attrs[i], | 855 | memmove(&attrtab->attrs[i + 1], &attrtab->attrs[i], |
| 809 | n * sizeof(jas_iccattr_t)); | 856 | n * sizeof(jas_iccattr_t)); |
| 857 | } | ||
| 810 | attr = &attrtab->attrs[i]; | 858 | attr = &attrtab->attrs[i]; |
| 811 | attr->name = name; | 859 | attr->name = name; |
| 812 | attr->val = tmpattrval; | 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 | jas_iccattrval_t *newval; | 868 | jas_iccattrval_t *newval; |
| 821 | jas_iccattr_t *attr; | 869 | jas_iccattr_t *attr; |
| 822 | if (!(newval = jas_iccattrval_clone(val))) | 870 | if (!(newval = jas_iccattrval_clone(val))) { |
| 823 | goto error; | 871 | goto error; |
| 872 | } | ||
| 824 | attr = &attrtab->attrs[i]; | 873 | attr = &attrtab->attrs[i]; |
| 825 | jas_iccattrval_destroy(attr->val); | 874 | jas_iccattrval_destroy(attr->val); |
| 826 | attr->name = name; | 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 | unsigned n; | 884 | unsigned n; |
| 836 | jas_iccattrval_destroy(attrtab->attrs[i].val); | 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 | memmove(&attrtab->attrs[i], &attrtab->attrs[i + 1], | 887 | memmove(&attrtab->attrs[i], &attrtab->attrs[i + 1], |
| 839 | n * sizeof(jas_iccattr_t)); | 888 | n * sizeof(jas_iccattr_t)); |
| 889 | } | ||
| 840 | --attrtab->numattrs; | 890 | --attrtab->numattrs; |
| 841 | } | 891 | } |
| 842 | 892 | ||
| 843 | //#ifdef JAS_ENABLE_ENCODER | ||
| 844 | static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i, | 893 | static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i, |
| 845 | jas_iccattrname_t *name, jas_iccattrval_t **val) | 894 | jas_iccattrname_t *name, jas_iccattrval_t **val) |
| 846 | { | 895 | { |
| 847 | jas_iccattr_t *attr; | 896 | jas_iccattr_t *attr; |
| 848 | if (i >= attrtab->numattrs) | 897 | if (i >= attrtab->numattrs) { |
| 849 | goto error; | 898 | goto error; |
| 899 | } | ||
| 850 | attr = &attrtab->attrs[i]; | 900 | attr = &attrtab->attrs[i]; |
| 851 | *name = attr->name; | 901 | *name = attr->name; |
| 852 | if (!(*val = jas_iccattrval_clone(attr->val))) | 902 | if (!(*val = jas_iccattrval_clone(attr->val))) { |
| 853 | goto error; | 903 | goto error; |
| 904 | } | ||
| 854 | return 0; | 905 | return 0; |
| 855 | error: | 906 | error: |
| 856 | return -1; | 907 | return -1; |
| 857 | } | 908 | } |
| 858 | //#endif /* JAS_ENABLE_ENCODER */ | ||
| 859 | 909 | ||
| 860 | static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, | 910 | static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, |
| 861 | jas_iccuint32_t name) | 911 | jas_iccuint32_t name) |
| @@ -863,8 +913,9 @@ static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, · 1 unmodified line | |||
| 863 | jas_iccattr_t *attr; | 913 | jas_iccattr_t *attr; |
| 864 | for (unsigned i = 0; i < attrtab->numattrs; ++i) { | 914 | for (unsigned i = 0; i < attrtab->numattrs; ++i) { |
| 865 | attr = &attrtab->attrs[i]; | 915 | attr = &attrtab->attrs[i]; |
| 866 | if (attr->name == name) | 916 | if (attr->name == name) { |
| 867 | return i; | 917 | return i; |
| 918 | } | ||
| 868 | } | 919 | } |
| 869 | return -1; | 920 | return -1; |
| 870 | } | 921 | } |
| @@ -878,10 +929,12 @@ jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type) · 7 unmodified lines | |||
| 878 | jas_iccattrval_t *attrval; | 929 | jas_iccattrval_t *attrval; |
| 879 | const jas_iccattrvalinfo_t *info; | 930 | const jas_iccattrvalinfo_t *info; |
| 880 | 931 | ||
| 881 | if (!(info = jas_iccattrvalinfo_lookup(type))) | 932 | if (!(info = jas_iccattrvalinfo_lookup(type))) { |
| 882 | goto error; | 933 | goto error; |
| 883 | if (!(attrval = jas_iccattrval_create0())) | 934 | } |
| 935 | if (!(attrval = jas_iccattrval_create0())) { | ||
| 884 | goto error; | 936 | goto error; |
| 937 | } | ||
| 885 | attrval->ops = &info->ops; | 938 | attrval->ops = &info->ops; |
| 886 | attrval->type = type; | 939 | attrval->type = type; |
| 887 | ++attrval->refcnt; | 940 | ++attrval->refcnt; |
| @@ -903,25 +956,39 @@ void jas_iccattrval_destroy(jas_iccattrval_t *attrval) · 15 unmodified lines | |||
| 903 | jas_eprintf("refcnt=%d\n", attrval->refcnt); | 956 | jas_eprintf("refcnt=%d\n", attrval->refcnt); |
| 904 | #endif | 957 | #endif |
| 905 | if (--attrval->refcnt <= 0) { | 958 | if (--attrval->refcnt <= 0) { |
| 906 | if (attrval->ops->destroy) | 959 | if (attrval->ops->destroy) { |
| 907 | (*attrval->ops->destroy)(attrval); | 960 | (*attrval->ops->destroy)(attrval); |
| 961 | } | ||
| 908 | jas_free(attrval); | 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 | int jas_iccattrval_allowmodify(jas_iccattrval_t **attrvalx) | 977 | int jas_iccattrval_allowmodify(jas_iccattrval_t **attrvalx) |
| 913 | { | 978 | { |
| 914 | jas_iccattrval_t *newattrval; | 979 | jas_iccattrval_t *newattrval; |
| 915 | jas_iccattrval_t *attrval = *attrvalx; | 980 | jas_iccattrval_t *attrval = *attrvalx; |
| 916 | if (attrval->refcnt > 1) { | 981 | if (attrval->refcnt > 1) { |
| 917 | if (!(newattrval = jas_iccattrval_create0())) | 982 | if (!(newattrval = jas_iccattrval_create0())) { |
| 918 | goto error; | 983 | goto error; |
| 984 | } | ||
| 919 | newattrval->ops = attrval->ops; | 985 | newattrval->ops = attrval->ops; |
| 920 | newattrval->type = attrval->type; | 986 | newattrval->type = attrval->type; |
| 921 | ++newattrval->refcnt; | 987 | ++newattrval->refcnt; |
| 922 | if (newattrval->ops->copy) { | 988 | if (newattrval->ops->copy) { |
| 923 | if ((*newattrval->ops->copy)(newattrval, attrval)) | 989 | if ((*newattrval->ops->copy)(newattrval, attrval)) { |
| 924 | goto error; | 990 | goto error; |
| 991 | } | ||
| 925 | } else { | 992 | } else { |
| 926 | memcpy(&newattrval->data, &attrval->data, | 993 | memcpy(&newattrval->data, &attrval->data, |
| 927 | sizeof(newattrval->data)); | 994 | sizeof(newattrval->data)); |
| @@ -939,8 +1006,9 @@ error: · 11 unmodified lines | |||
| 939 | static jas_iccattrval_t *jas_iccattrval_create0() | 1006 | static jas_iccattrval_t *jas_iccattrval_create0() |
| 940 | { | 1007 | { |
| 941 | jas_iccattrval_t *attrval; | 1008 | jas_iccattrval_t *attrval; |
| 942 | if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t)))) | 1009 | if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t)))) { |
| 943 | return 0; | 1010 | return 0; |
| 1011 | } | ||
| 944 | memset(attrval, 0, sizeof(jas_iccattrval_t)); | 1012 | memset(attrval, 0, sizeof(jas_iccattrval_t)); |
| 945 | attrval->refcnt = 0; | 1013 | attrval->refcnt = 0; |
| 946 | attrval->ops = 0; | 1014 | attrval->ops = 0; |
| @@ -955,31 +1023,36 @@ static jas_iccattrval_t *jas_iccattrval_create0() · 8 unmodified lines | |||
| 955 | static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in, | 1023 | static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in, |
| 956 | unsigned len) | 1024 | unsigned len) |
| 957 | { | 1025 | { |
| 958 | assert(len == 4 * 3); | 1026 | if (len != 4 * 3) { |
| 959 | (void)len; | 1027 | return -1; |
| 1028 | } | ||
| 960 | return jas_iccgetxyz(in, &attrval->data.xyz); | 1029 | return jas_iccgetxyz(in, &attrval->data.xyz); |
| 961 | } | 1030 | } |
| 962 | 1031 | ||
| 963 | //#ifdef JAS_ENABLE_ENCODER | ||
| 964 | static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out) | 1032 | static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 965 | { | 1033 | { |
| 966 | const jas_iccxyz_t *xyz = &attrval->data.xyz; | 1034 | const jas_iccxyz_t *xyz = &attrval->data.xyz; |
| 967 | if (jas_iccputuint32(out, xyz->x) || | 1035 | if (jas_iccputuint32(out, xyz->x) || |
| 968 | jas_iccputuint32(out, xyz->y) || | 1036 | jas_iccputuint32(out, xyz->y) || |
| 969 | jas_iccputuint32(out, xyz->z)) | 1037 | jas_iccputuint32(out, xyz->z)) { |
| 970 | return -1; | 1038 | return -1; |
| 1039 | } | ||
| 971 | return 0; | 1040 | return 0; |
| 972 | } | 1041 | } |
| 973 | //#endif /* JAS_ENABLE_ENCODER */ | ||
| 974 | 1042 | ||
| 975 | static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval) | 1043 | static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval) |
| 976 | { | 1044 | { |
| 977 | /* Avoid compiler warnings about unused parameters. */ | 1045 | JAS_UNUSED(attrval); |
| 978 | USED(attrval); | ||
| 979 | |||
| 980 | return 12; | 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 | * attribute table class | 1057 | * attribute table class |
| 985 | \******************************************************************************/ | 1058 | \******************************************************************************/ |
| @@ -996,9 +1069,8 @@ static void jas_icccurv_destroy(jas_iccattrval_t *attrval) · 10 unmodified lines | |||
| 996 | static int jas_icccurv_copy(jas_iccattrval_t *attrval, | 1069 | static int jas_icccurv_copy(jas_iccattrval_t *attrval, |
| 997 | const jas_iccattrval_t *othattrval) | 1070 | const jas_iccattrval_t *othattrval) |
| 998 | { | 1071 | { |
| 999 | /* Avoid compiler warnings about unused parameters. */ | 1072 | JAS_UNUSED(attrval); |
| 1000 | USED(attrval); | 1073 | JAS_UNUSED(othattrval); |
| 1001 | USED(othattrval); | ||
| 1002 | 1074 | ||
| 1003 | /* Not yet implemented. */ | 1075 | /* Not yet implemented. */ |
| 1004 | abort(); | 1076 | abort(); |
| @@ -1013,17 +1085,21 @@ static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 8 unmodified lines | |||
| 1013 | curv->numents = 0; | 1085 | curv->numents = 0; |
| 1014 | curv->ents = 0; | 1086 | curv->ents = 0; |
| 1015 | 1087 | ||
| 1016 | if (jas_iccgetuint32(in, &curv->numents)) | 1088 | if (jas_iccgetuint32(in, &curv->numents)) { |
| 1017 | goto error; | 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 | goto error; | 1092 | goto error; |
| 1093 | } | ||
| 1020 | for (unsigned i = 0; i < curv->numents; ++i) { | 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 | goto error; | 1096 | goto error; |
| 1097 | } | ||
| 1023 | } | 1098 | } |
| 1024 | 1099 | ||
| 1025 | if (4 + 2 * curv->numents != cnt) | 1100 | if (4 + 2 * curv->numents != cnt) { |
| 1026 | goto error; | 1101 | goto error; |
| 1102 | } | ||
| 1027 | return 0; | 1103 | return 0; |
| 1028 | 1104 | ||
| 1029 | error: | 1105 | error: |
| @@ -1037,22 +1113,37 @@ static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval) · 7 unmodified lines | |||
| 1037 | return 4 + 2 * curv->numents; | 1113 | return 4 + 2 * curv->numents; |
| 1038 | } | 1114 | } |
| 1039 | 1115 | ||
| 1040 | //#ifdef JAS_ENABLE_ENCODER | ||
| 1041 | static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out) | 1116 | static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1042 | { | 1117 | { |
| 1043 | const jas_icccurv_t *curv = &attrval->data.curv; | 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 | goto error; | 1121 | goto error; |
| 1122 | } | ||
| 1047 | for (unsigned i = 0; i < curv->numents; ++i) { | 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 | goto error; | 1125 | goto error; |
| 1126 | } | ||
| 1050 | } | 1127 | } |
| 1051 | return 0; | 1128 | return 0; |
| 1052 | error: | 1129 | error: |
| 1053 | return -1; | 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 | jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; | 1168 | jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; |
| 1078 | 1169 | ||
| 1079 | /* Avoid compiler warnings about unused parameters. */ | 1170 | JAS_UNUSED(attrval); |
| 1080 | USED(attrval); | 1171 | JAS_UNUSED(othattrval); |
| 1081 | USED(othattrval); | 1172 | JAS_UNUSED(txtdesc); |
| 1082 | USED(txtdesc); | ||
| 1083 | 1173 | ||
| 1084 | /* Not yet implemented. */ | 1174 | /* Not yet implemented. */ |
| 1085 | abort(); | 1175 | abort(); |
| @@ -1093,31 +1183,41 @@ static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 7 unmodified lines | |||
| 1093 | jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; | 1183 | jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; |
| 1094 | txtdesc->ascdata = 0; | 1184 | txtdesc->ascdata = 0; |
| 1095 | txtdesc->ucdata = 0; | 1185 | txtdesc->ucdata = 0; |
| 1096 | if (jas_iccgetuint32(in, &txtdesc->asclen)) | 1186 | if (jas_iccgetuint32(in, &txtdesc->asclen)) { |
| 1097 | goto error; | 1187 | goto error; |
| 1098 | if (txtdesc->asclen < 1) | 1188 | } |
| 1189 | if (txtdesc->asclen < 1) { | ||
| 1099 | goto error; | 1190 | goto error; |
| 1100 | if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen))) | 1191 | } |
| 1192 | if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen))) { | ||
| 1101 | goto error; | 1193 | goto error; |
| 1194 | } | ||
| 1102 | if (jas_stream_read(in, txtdesc->ascdata, txtdesc->asclen) != | 1195 | if (jas_stream_read(in, txtdesc->ascdata, txtdesc->asclen) != |
| 1103 | txtdesc->asclen) | 1196 | txtdesc->asclen) { |
| 1104 | goto error; | 1197 | goto error; |
| 1198 | } | ||
| 1105 | txtdesc->ascdata[txtdesc->asclen - 1] = '\0'; | 1199 | txtdesc->ascdata[txtdesc->asclen - 1] = '\0'; |
| 1106 | if (jas_iccgetuint32(in, &txtdesc->uclangcode) || | 1200 | if (jas_iccgetuint32(in, &txtdesc->uclangcode) || |
| 1107 | jas_iccgetuint32(in, &txtdesc->uclen)) | 1201 | jas_iccgetuint32(in, &txtdesc->uclen)) { |
| 1108 | goto error; | 1202 | goto error; |
| 1109 | if (!(txtdesc->ucdata = jas_alloc2(txtdesc->uclen, 2))) | 1203 | } |
| 1204 | if (!(txtdesc->ucdata = jas_alloc2(txtdesc->uclen, 2))) { | ||
| 1110 | goto error; | 1205 | goto error; |
| 1206 | } | ||
| 1111 | if (jas_stream_read(in, txtdesc->ucdata, txtdesc->uclen * 2) != | 1207 | if (jas_stream_read(in, txtdesc->ucdata, txtdesc->uclen * 2) != |
| 1112 | txtdesc->uclen * 2) | 1208 | txtdesc->uclen * 2) { |
| 1113 | goto error; | 1209 | goto error; |
| 1114 | if (jas_iccgetuint16(in, &txtdesc->sccode)) | 1210 | } |
| 1211 | if (jas_iccgetuint16(in, &txtdesc->sccode)) { | ||
| 1115 | goto error; | 1212 | goto error; |
| 1116 | if ((c = jas_stream_getc(in)) == EOF) | 1213 | } |
| 1214 | if ((c = jas_stream_getc(in)) == EOF) { | ||
| 1117 | goto error; | 1215 | goto error; |
| 1216 | } | ||
| 1118 | txtdesc->maclen = c; | 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 | goto error; | 1219 | goto error; |
| 1220 | } | ||
| 1121 | txtdesc->asclen = JAS_CAST(jas_iccuint32_t, strlen(txtdesc->ascdata) + 1); | 1221 | txtdesc->asclen = JAS_CAST(jas_iccuint32_t, strlen(txtdesc->ascdata) + 1); |
| 1122 | #define WORKAROUND_BAD_PROFILES | 1222 | #define WORKAROUND_BAD_PROFILES |
| 1123 | #ifdef WORKAROUND_BAD_PROFILES | 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 | return -1; | 1226 | return -1; |
| 1127 | } | 1227 | } |
| 1128 | if (n < cnt) { | 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 | goto error; | 1230 | goto error; |
| 1231 | } | ||
| 1131 | } | 1232 | } |
| 1132 | #else | 1233 | #else |
| 1133 | if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt) | 1234 | if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt) { |
| 1134 | return -1; | 1235 | return -1; |
| 1236 | } | ||
| 1135 | #endif | 1237 | #endif |
| 1136 | return 0; | 1238 | return 0; |
| 1137 | error: | 1239 | error: |
| @@ -1145,7 +1247,6 @@ static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval) · 7 unmodified lines | |||
| 1145 | return strlen(txtdesc->ascdata) + 1 + txtdesc->uclen * 2 + 15 + 67; | 1247 | return strlen(txtdesc->ascdata) + 1 + txtdesc->uclen * 2 + 15 + 67; |
| 1146 | } | 1248 | } |
| 1147 | 1249 | ||
| 1148 | //#ifdef JAS_ENABLE_ENCODER | ||
| 1149 | static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out) | 1250 | static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1150 | { | 1251 | { |
| 1151 | const jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; | 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 | jas_stream_putc(out, 0) == EOF || | 1255 | jas_stream_putc(out, 0) == EOF || |
| 1155 | jas_iccputuint32(out, txtdesc->uclangcode) || | 1256 | jas_iccputuint32(out, txtdesc->uclangcode) || |
| 1156 | jas_iccputuint32(out, txtdesc->uclen) || | 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 | jas_iccputuint16(out, txtdesc->sccode) || | 1260 | jas_iccputuint16(out, txtdesc->sccode) || |
| 1159 | jas_stream_putc(out, txtdesc->maclen) == EOF) | 1261 | jas_stream_putc(out, txtdesc->maclen) == EOF) { |
| 1160 | goto error; | 1262 | goto error; |
| 1263 | } | ||
| 1161 | if (txtdesc->maclen > 0) { | 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 | goto error; | 1266 | goto error; |
| 1267 | } | ||
| 1164 | } else { | 1268 | } else { |
| 1165 | if (jas_stream_pad(out, 67, 0) != 67) | 1269 | if (jas_stream_pad(out, 67, 0) != 67) { |
| 1166 | goto error; | 1270 | goto error; |
| 1271 | } | ||
| 1167 | } | 1272 | } |
| 1168 | return 0; | 1273 | return 0; |
| 1169 | error: | 1274 | error: |
| 1170 | return -1; | 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 | jas_icctxt_t *txt = &attrval->data.txt; | 1304 | jas_icctxt_t *txt = &attrval->data.txt; |
| 1191 | const jas_icctxt_t *othtxt = &othattrval->data.txt; | 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 | return -1; | 1307 | return -1; |
| 1308 | } | ||
| 1194 | return 0; | 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 | jas_icctxt_t *txt = &attrval->data.txt; | 1315 | jas_icctxt_t *txt = &attrval->data.txt; |
| 1201 | txt->string = 0; | 1316 | txt->string = 0; |
| 1202 | if (!(txt->string = jas_malloc(cnt))) | 1317 | if (!(txt->string = jas_malloc(cnt))) { |
| 1203 | goto error; | 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 | goto error; | 1321 | goto error; |
| 1322 | } | ||
| 1206 | txt->string[cnt - 1] = '\0'; | 1323 | txt->string[cnt - 1] = '\0'; |
| 1207 | if (strlen(txt->string) + 1 != cnt) | 1324 | if (strlen(txt->string) + 1 != cnt) { |
| 1208 | goto error; | 1325 | goto error; |
| 1326 | } | ||
| 1209 | return 0; | 1327 | return 0; |
| 1210 | error: | 1328 | error: |
| 1211 | jas_icctxt_destroy(attrval); | 1329 | jas_icctxt_destroy(attrval); |
| @@ -1218,16 +1336,21 @@ static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval) · 6 unmodified lines | |||
| 1218 | return strlen(txt->string) + 1; | 1336 | return strlen(txt->string) + 1; |
| 1219 | } | 1337 | } |
| 1220 | 1338 | ||
| 1221 | //#ifdef JAS_ENABLE_ENCODER | ||
| 1222 | static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out) | 1339 | static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1223 | { | 1340 | { |
| 1224 | const jas_icctxt_t *txt = &attrval->data.txt; | 1341 | const jas_icctxt_t *txt = &attrval->data.txt; |
| 1225 | if (jas_stream_puts(out, txt->string) || | 1342 | if (jas_stream_puts(out, txt->string) || |
| 1226 | jas_stream_putc(out, 0) == EOF) | 1343 | jas_stream_putc(out, 0) == EOF) { |
| 1227 | return -1; | 1344 | return -1; |
| 1345 | } | ||
| 1228 | return 0; | 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 | static int jas_icclut8_copy(jas_iccattrval_t *attrval, | 1384 | static int jas_icclut8_copy(jas_iccattrval_t *attrval, |
| 1262 | const jas_iccattrval_t *othattrval) | 1385 | const jas_iccattrval_t *othattrval) |
| 1263 | { | 1386 | { |
| 1264 | /* Avoid compiler warnings about unused parameters. */ | 1387 | JAS_UNUSED(attrval); |
| 1265 | USED(attrval); | 1388 | JAS_UNUSED(othattrval); |
| 1266 | USED(othattrval); | ||
| 1267 | abort(); | 1389 | abort(); |
| 1268 | return -1; | 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 | if (jas_iccgetuint8(in, &lut8->numinchans) || | 1402 | if (jas_iccgetuint8(in, &lut8->numinchans) || |
| 1281 | jas_iccgetuint8(in, &lut8->numoutchans) || | 1403 | jas_iccgetuint8(in, &lut8->numoutchans) || |
| 1282 | jas_iccgetuint8(in, &lut8->clutlen) || | 1404 | jas_iccgetuint8(in, &lut8->clutlen) || |
| 1283 | jas_stream_getc(in) == EOF) | 1405 | jas_stream_getc(in) == EOF) { |
| 1284 | goto error; | 1406 | goto error; |
| 1407 | } | ||
| 1285 | for (unsigned i = 0; i < 3; ++i) { | 1408 | for (unsigned i = 0; i < 3; ++i) { |
| 1286 | for (unsigned j = 0; j < 3; ++j) { | 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 | goto error; | 1411 | goto error; |
| 1412 | } | ||
| 1289 | } | 1413 | } |
| 1290 | } | 1414 | } |
| 1291 | if (jas_iccgetuint16(in, &lut8->numintabents) || | 1415 | if (jas_iccgetuint16(in, &lut8->numintabents) || |
| 1292 | jas_iccgetuint16(in, &lut8->numouttabents)) | 1416 | jas_iccgetuint16(in, &lut8->numouttabents)) { |
| 1293 | goto error; | 1417 | goto error; |
| 1418 | } | ||
| 1294 | const unsigned clutsize = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; | 1419 | const unsigned clutsize = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; |
| 1295 | if (!(lut8->clut = jas_alloc2(clutsize, sizeof(jas_iccuint8_t))) || | 1420 | if (!(lut8->clut = jas_alloc2(clutsize, sizeof(jas_iccuint8_t))) || |
| 1296 | !(lut8->intabsbuf = jas_alloc3(lut8->numinchans, | 1421 | !(lut8->intabsbuf = jas_alloc3(lut8->numinchans, |
| 1297 | lut8->numintabents, sizeof(jas_iccuint8_t))) || | 1422 | lut8->numintabents, sizeof(jas_iccuint8_t))) || |
| 1298 | !(lut8->intabs = jas_alloc2(lut8->numinchans, | 1423 | !(lut8->intabs = jas_alloc2(lut8->numinchans, |
| 1299 | sizeof(jas_iccuint8_t *)))) | 1424 | sizeof(jas_iccuint8_t *)))) { |
| 1300 | goto error; | 1425 | goto error; |
| 1426 | } | ||
| 1301 | for (unsigned i = 0; i < lut8->numinchans; ++i) | 1427 | for (unsigned i = 0; i < lut8->numinchans; ++i) |
| 1302 | lut8->intabs[i] = &lut8->intabsbuf[i * lut8->numintabents]; | 1428 | lut8->intabs[i] = &lut8->intabsbuf[i * lut8->numintabents]; |
| 1303 | if (!(lut8->outtabsbuf = jas_alloc3(lut8->numoutchans, | 1429 | if (!(lut8->outtabsbuf = jas_alloc3(lut8->numoutchans, |
| 1304 | lut8->numouttabents, sizeof(jas_iccuint8_t))) || | 1430 | lut8->numouttabents, sizeof(jas_iccuint8_t))) || |
| 1305 | !(lut8->outtabs = jas_alloc2(lut8->numoutchans, | 1431 | !(lut8->outtabs = jas_alloc2(lut8->numoutchans, |
| 1306 | sizeof(jas_iccuint8_t *)))) | 1432 | sizeof(jas_iccuint8_t *)))) { |
| 1307 | goto error; | 1433 | goto error; |
| 1308 | for (unsigned i = 0; i < lut8->numoutchans; ++i) | 1434 | } |
| 1435 | for (unsigned i = 0; i < lut8->numoutchans; ++i) { | ||
| 1309 | lut8->outtabs[i] = &lut8->outtabsbuf[i * lut8->numouttabents]; | 1436 | lut8->outtabs[i] = &lut8->outtabsbuf[i * lut8->numouttabents]; |
| 1437 | } | ||
| 1310 | for (unsigned i = 0; i < lut8->numinchans; ++i) { | 1438 | for (unsigned i = 0; i < lut8->numinchans; ++i) { |
| 1311 | for (unsigned j = 0; j < lut8->numintabents; ++j) { | 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 | goto error; | 1441 | goto error; |
| 1442 | } | ||
| 1314 | } | 1443 | } |
| 1315 | } | 1444 | } |
| 1316 | for (unsigned i = 0; i < lut8->numoutchans; ++i) { | 1445 | for (unsigned i = 0; i < lut8->numoutchans; ++i) { |
| 1317 | for (unsigned j = 0; j < lut8->numouttabents; ++j) { | 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 | goto error; | 1448 | goto error; |
| 1449 | } | ||
| 1320 | } | 1450 | } |
| 1321 | } | 1451 | } |
| 1322 | for (unsigned i = 0; i < clutsize; ++i) { | 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 | goto error; | 1454 | goto error; |
| 1455 | } | ||
| 1325 | } | 1456 | } |
| 1326 | if (44 + lut8->numinchans * lut8->numintabents + | 1457 | if (44 + lut8->numinchans * lut8->numintabents + |
| 1327 | lut8->numoutchans * lut8->numouttabents + | 1458 | lut8->numoutchans * lut8->numouttabents + |
| 1328 | jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans != | 1459 | jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans != |
| 1329 | cnt) | 1460 | cnt) { |
| 1330 | goto error; | 1461 | goto error; |
| 1462 | } | ||
| 1331 | return 0; | 1463 | return 0; |
| 1332 | error: | 1464 | error: |
| 1333 | jas_icclut8_destroy(attrval); | 1465 | jas_icclut8_destroy(attrval); |
| @@ -1342,7 +1474,6 @@ static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval) · 8 unmodified lines | |||
| 1342 | jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; | 1474 | jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; |
| 1343 | } | 1475 | } |
| 1344 | 1476 | ||
| 1345 | //#ifdef JAS_ENABLE_ENCODER | ||
| 1346 | static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out) | 1477 | static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1347 | { | 1478 | { |
| 1348 | jas_icclut8_t *lut8 = &attrval->data.lut8; | 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 | if (jas_stream_putc(out, lut8->numinchans) == EOF || | 1485 | if (jas_stream_putc(out, lut8->numinchans) == EOF || |
| 1355 | jas_stream_putc(out, lut8->numoutchans) == EOF || | 1486 | jas_stream_putc(out, lut8->numoutchans) == EOF || |
| 1356 | jas_stream_putc(out, lut8->clutlen) == EOF || | 1487 | jas_stream_putc(out, lut8->clutlen) == EOF || |
| 1357 | jas_stream_putc(out, 0) == EOF) | 1488 | jas_stream_putc(out, 0) == EOF) { |
| 1358 | goto error; | 1489 | goto error; |
| 1490 | } | ||
| 1359 | for (unsigned i = 0; i < 3; ++i) { | 1491 | for (unsigned i = 0; i < 3; ++i) { |
| 1360 | for (unsigned j = 0; j < 3; ++j) { | 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 | goto error; | 1494 | goto error; |
| 1495 | } | ||
| 1363 | } | 1496 | } |
| 1364 | } | 1497 | } |
| 1365 | if (jas_iccputuint16(out, lut8->numintabents) || | 1498 | if (jas_iccputuint16(out, lut8->numintabents) || |
| 1366 | jas_iccputuint16(out, lut8->numouttabents)) | 1499 | jas_iccputuint16(out, lut8->numouttabents)) { |
| 1367 | goto error; | 1500 | goto error; |
| 1368 | for (unsigned i = 0, n = lut8->numinchans * lut8->numintabents; i < n; ++i) { | 1501 | } |
| 1369 | if (jas_iccputuint8(out, lut8->intabsbuf[i])) | 1502 | for (unsigned i = 0, n = lut8->numinchans * lut8->numintabents; i < n; |
| 1503 | ++i) { | ||
| 1504 | if (jas_iccputuint8(out, lut8->intabsbuf[i])) { | ||
| 1370 | goto error; | 1505 | goto error; |
| 1506 | } | ||
| 1371 | } | 1507 | } |
| 1372 | for (unsigned i = 0, n = lut8->numoutchans * lut8->numouttabents; i < n; ++i) { | 1508 | for (unsigned i = 0, n = lut8->numoutchans * lut8->numouttabents; i < n; |
| 1373 | if (jas_iccputuint8(out, lut8->outtabsbuf[i])) | 1509 | ++i) { |
| 1510 | if (jas_iccputuint8(out, lut8->outtabsbuf[i])) { | ||
| 1374 | goto error; | 1511 | goto error; |
| 1512 | } | ||
| 1375 | } | 1513 | } |
| 1376 | for (unsigned i = 0, n = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; i < n; ++i) { | 1514 | for (unsigned i = 0, n = jas_iccpowi(lut8->clutlen, lut8->numinchans) * |
| 1377 | if (jas_iccputuint8(out, lut8->clut[i])) | 1515 | lut8->numoutchans; i < n; ++i) { |
| 1516 | if (jas_iccputuint8(out, lut8->clut[i])) { | ||
| 1378 | goto error; | 1517 | goto error; |
| 1518 | } | ||
| 1379 | } | 1519 | } |
| 1380 | return 0; | 1520 | return 0; |
| 1381 | error: | 1521 | error: |
| 1382 | return -1; | 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 | static int jas_icclut16_copy(jas_iccattrval_t *attrval, | 1569 | static int jas_icclut16_copy(jas_iccattrval_t *attrval, |
| 1416 | const jas_iccattrval_t *othattrval) | 1570 | const jas_iccattrval_t *othattrval) |
| 1417 | { | 1571 | { |
| 1418 | /* Avoid compiler warnings about unused parameters. */ | 1572 | JAS_UNUSED(attrval); |
| 1419 | USED(attrval); | 1573 | JAS_UNUSED(othattrval); |
| 1420 | USED(othattrval); | 1574 | |
| 1421 | /* Not yet implemented. */ | 1575 | /* Not yet implemented. */ |
| 1422 | abort(); | 1576 | abort(); |
| 1423 | return -1; | 1577 | return -1; |
| @@ -1435,54 +1589,66 @@ static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 11 unmodified lines | |||
| 1435 | if (jas_iccgetuint8(in, &lut16->numinchans) || | 1589 | if (jas_iccgetuint8(in, &lut16->numinchans) || |
| 1436 | jas_iccgetuint8(in, &lut16->numoutchans) || | 1590 | jas_iccgetuint8(in, &lut16->numoutchans) || |
| 1437 | jas_iccgetuint8(in, &lut16->clutlen) || | 1591 | jas_iccgetuint8(in, &lut16->clutlen) || |
| 1438 | jas_stream_getc(in) == EOF) | 1592 | jas_stream_getc(in) == EOF) { |
| 1439 | goto error; | 1593 | goto error; |
| 1594 | } | ||
| 1440 | for (unsigned i = 0; i < 3; ++i) { | 1595 | for (unsigned i = 0; i < 3; ++i) { |
| 1441 | for (unsigned j = 0; j < 3; ++j) { | 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 | goto error; | 1598 | goto error; |
| 1599 | } | ||
| 1444 | } | 1600 | } |
| 1445 | } | 1601 | } |
| 1446 | if (jas_iccgetuint16(in, &lut16->numintabents) || | 1602 | if (jas_iccgetuint16(in, &lut16->numintabents) || |
| 1447 | jas_iccgetuint16(in, &lut16->numouttabents)) | 1603 | jas_iccgetuint16(in, &lut16->numouttabents)) { |
| 1448 | goto error; | 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 | if (!(lut16->clut = jas_alloc2(clutsize, sizeof(jas_iccuint16_t))) || | 1608 | if (!(lut16->clut = jas_alloc2(clutsize, sizeof(jas_iccuint16_t))) || |
| 1451 | !(lut16->intabsbuf = jas_alloc3(lut16->numinchans, | 1609 | !(lut16->intabsbuf = jas_alloc3(lut16->numinchans, |
| 1452 | lut16->numintabents, sizeof(jas_iccuint16_t))) || | 1610 | lut16->numintabents, sizeof(jas_iccuint16_t))) || |
| 1453 | !(lut16->intabs = jas_alloc2(lut16->numinchans, | 1611 | !(lut16->intabs = jas_alloc2(lut16->numinchans, |
| 1454 | sizeof(jas_iccuint16_t *)))) | 1612 | sizeof(jas_iccuint16_t *)))) { |
| 1455 | goto error; | 1613 | goto error; |
| 1456 | for (unsigned i = 0; i < lut16->numinchans; ++i) | 1614 | } |
| 1615 | for (unsigned i = 0; i < lut16->numinchans; ++i) { | ||
| 1457 | lut16->intabs[i] = &lut16->intabsbuf[i * lut16->numintabents]; | 1616 | lut16->intabs[i] = &lut16->intabsbuf[i * lut16->numintabents]; |
| 1617 | } | ||
| 1458 | if (!(lut16->outtabsbuf = jas_alloc3(lut16->numoutchans, | 1618 | if (!(lut16->outtabsbuf = jas_alloc3(lut16->numoutchans, |
| 1459 | lut16->numouttabents, sizeof(jas_iccuint16_t))) || | 1619 | lut16->numouttabents, sizeof(jas_iccuint16_t))) || |
| 1460 | !(lut16->outtabs = jas_alloc2(lut16->numoutchans, | 1620 | !(lut16->outtabs = jas_alloc2(lut16->numoutchans, |
| 1461 | sizeof(jas_iccuint16_t *)))) | 1621 | sizeof(jas_iccuint16_t *)))) { |
| 1462 | goto error; | 1622 | goto error; |
| 1463 | for (unsigned i = 0; i < lut16->numoutchans; ++i) | 1623 | } |
| 1624 | for (unsigned i = 0; i < lut16->numoutchans; ++i) { | ||
| 1464 | lut16->outtabs[i] = &lut16->outtabsbuf[i * lut16->numouttabents]; | 1625 | lut16->outtabs[i] = &lut16->outtabsbuf[i * lut16->numouttabents]; |
| 1626 | } | ||
| 1465 | for (unsigned i = 0; i < lut16->numinchans; ++i) { | 1627 | for (unsigned i = 0; i < lut16->numinchans; ++i) { |
| 1466 | for (unsigned j = 0; j < lut16->numintabents; ++j) { | 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 | goto error; | 1630 | goto error; |
| 1631 | } | ||
| 1469 | } | 1632 | } |
| 1470 | } | 1633 | } |
| 1471 | for (unsigned i = 0; i < lut16->numoutchans; ++i) { | 1634 | for (unsigned i = 0; i < lut16->numoutchans; ++i) { |
| 1472 | for (unsigned j = 0; j < lut16->numouttabents; ++j) { | 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 | goto error; | 1637 | goto error; |
| 1638 | } | ||
| 1475 | } | 1639 | } |
| 1476 | } | 1640 | } |
| 1477 | for (unsigned i = 0; i < clutsize; ++i) { | 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 | goto error; | 1643 | goto error; |
| 1644 | } | ||
| 1480 | } | 1645 | } |
| 1481 | if (44 + 2 * (lut16->numinchans * lut16->numintabents + | 1646 | if (44 + 2 * (lut16->numinchans * lut16->numintabents + |
| 1482 | lut16->numoutchans * lut16->numouttabents + | 1647 | lut16->numoutchans * lut16->numouttabents + |
| 1483 | jas_iccpowi(lut16->clutlen, lut16->numinchans) * | 1648 | jas_iccpowi(lut16->clutlen, lut16->numinchans) * |
| 1484 | lut16->numoutchans) != cnt) | 1649 | lut16->numoutchans) != cnt) { |
| 1485 | goto error; | 1650 | goto error; |
| 1651 | } | ||
| 1486 | return 0; | 1652 | return 0; |
| 1487 | error: | 1653 | error: |
| 1488 | jas_icclut16_destroy(attrval); | 1654 | jas_icclut16_destroy(attrval); |
| @@ -1497,41 +1663,63 @@ static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval) · 8 unmodified lines | |||
| 1497 | jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans); | 1663 | jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans); |
| 1498 | } | 1664 | } |
| 1499 | 1665 | ||
| 1500 | //#ifdef JAS_ENABLE_ENCODER | ||
| 1501 | static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out) | 1666 | static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out) |
| 1502 | { | 1667 | { |
| 1503 | const jas_icclut16_t *lut16 = &attrval->data.lut16; | 1668 | const jas_icclut16_t *lut16 = &attrval->data.lut16; |
| 1504 | if (jas_stream_putc(out, lut16->numinchans) == EOF || | 1669 | if (jas_stream_putc(out, lut16->numinchans) == EOF || |
| 1505 | jas_stream_putc(out, lut16->numoutchans) == EOF || | 1670 | jas_stream_putc(out, lut16->numoutchans) == EOF || |
| 1506 | jas_stream_putc(out, lut16->clutlen) == EOF || | 1671 | jas_stream_putc(out, lut16->clutlen) == EOF || |
| 1507 | jas_stream_putc(out, 0) == EOF) | 1672 | jas_stream_putc(out, 0) == EOF) { |
| 1508 | goto error; | 1673 | goto error; |
| 1674 | } | ||
| 1509 | for (unsigned i = 0; i < 3; ++i) { | 1675 | for (unsigned i = 0; i < 3; ++i) { |
| 1510 | for (unsigned j = 0; j < 3; ++j) { | 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 | goto error; | 1678 | goto error; |
| 1679 | } | ||
| 1513 | } | 1680 | } |
| 1514 | } | 1681 | } |
| 1515 | if (jas_iccputuint16(out, lut16->numintabents) || | 1682 | if (jas_iccputuint16(out, lut16->numintabents) || |
| 1516 | jas_iccputuint16(out, lut16->numouttabents)) | 1683 | jas_iccputuint16(out, lut16->numouttabents)) { |
| 1517 | goto error; | 1684 | goto error; |
| 1518 | for (unsigned i = 0, n = lut16->numinchans * lut16->numintabents; i < n; ++i) { | 1685 | } |
| 1519 | if (jas_iccputuint16(out, lut16->intabsbuf[i])) | 1686 | for (unsigned i = 0, n = lut16->numinchans * lut16->numintabents; i < n; |
| 1687 | ++i) { | ||
| 1688 | if (jas_iccputuint16(out, lut16->intabsbuf[i])) { | ||
| 1520 | goto error; | 1689 | goto error; |
| 1690 | } | ||
| 1521 | } | 1691 | } |
| 1522 | for (unsigned i = 0, n = lut16->numoutchans * lut16->numouttabents; i < n; ++i) { | 1692 | for (unsigned i = 0, n = lut16->numoutchans * lut16->numouttabents; i < n; |
| 1523 | if (jas_iccputuint16(out, lut16->outtabsbuf[i])) | 1693 | ++i) { |
| 1694 | if (jas_iccputuint16(out, lut16->outtabsbuf[i])) { | ||
| 1524 | goto error; | 1695 | goto error; |
| 1696 | } | ||
| 1525 | } | 1697 | } |
| 1526 | for (unsigned i = 0, n = jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans; i < n; ++i) { | 1698 | for (unsigned i = 0, n = jas_iccpowi(lut16->clutlen, lut16->numinchans) * |
| 1527 | if (jas_iccputuint16(out, lut16->clut[i])) | 1699 | lut16->numoutchans; i < n; ++i) { |
| 1700 | if (jas_iccputuint16(out, lut16->clut[i])) { | ||
| 1528 | goto error; | 1701 | goto error; |
| 1702 | } | ||
| 1529 | } | 1703 | } |
| 1530 | return 0; | 1704 | return 0; |
| 1531 | error: | 1705 | error: |
| 1532 | return -1; | 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 | jas_ulonglong v; | 1731 | jas_ulonglong v; |
| 1544 | v = 0; | 1732 | v = 0; |
| 1545 | for (unsigned i = n; i > 0; --i) { | 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 | return -1; | 1735 | return -1; |
| 1736 | } | ||
| 1548 | v = (v << 8) | c; | 1737 | v = (v << 8) | c; |
| 1549 | } | 1738 | } |
| 1550 | *val = v; | 1739 | *val = v; |
| @@ -1554,8 +1743,9 @@ static int jas_iccgetuint(jas_stream_t *in, unsigned n, jas_ulonglong *val) · 3 unmodified lines | |||
| 1554 | static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val) | 1743 | static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val) |
| 1555 | { | 1744 | { |
| 1556 | int c; | 1745 | int c; |
| 1557 | if ((c = jas_stream_getc(in)) == EOF) | 1746 | if ((c = jas_stream_getc(in)) == EOF) { |
| 1558 | return -1; | 1747 | return -1; |
| 1748 | } | ||
| 1559 | *val = c; | 1749 | *val = c; |
| 1560 | return 0; | 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 | static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val) | 1753 | static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val) |
| 1564 | { | 1754 | { |
| 1565 | jas_ulonglong tmp; | 1755 | jas_ulonglong tmp; |
| 1566 | if (jas_iccgetuint(in, 2, &tmp)) | 1756 | if (jas_iccgetuint(in, 2, &tmp)) { |
| 1567 | return -1; | 1757 | return -1; |
| 1758 | } | ||
| 1568 | *val = (jas_iccuint16_t)tmp; | 1759 | *val = (jas_iccuint16_t)tmp; |
| 1569 | return 0; | 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 | static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val) | 1763 | static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val) |
| 1573 | { | 1764 | { |
| 1574 | jas_ulonglong tmp; | 1765 | jas_ulonglong tmp; |
| 1575 | if (jas_iccgetuint(in, 4, &tmp)) | 1766 | if (jas_iccgetuint(in, 4, &tmp)) { |
| 1576 | return -1; | 1767 | return -1; |
| 1768 | } | ||
| 1577 | *val = (tmp & 0x80000000) ? (-JAS_CAST(jas_longlong, (((~tmp) & | 1769 | *val = (tmp & 0x80000000) ? (-JAS_CAST(jas_longlong, (((~tmp) & |
| 1578 | 0x7fffffff) + 1))) : JAS_CAST(jas_longlong, tmp); | 1770 | 0x7fffffff) + 1))) : JAS_CAST(jas_longlong, tmp); |
| 1579 | return 0; | 1771 | return 0; |
| @@ -1582,8 +1774,9 @@ static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val) · 2 unmodified lines | |||
| 1582 | static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val) | 1774 | static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val) |
| 1583 | { | 1775 | { |
| 1584 | jas_ulonglong tmp; | 1776 | jas_ulonglong tmp; |
| 1585 | if (jas_iccgetuint(in, 4, &tmp)) | 1777 | if (jas_iccgetuint(in, 4, &tmp)) { |
| 1586 | return -1; | 1778 | return -1; |
| 1779 | } | ||
| 1587 | *val = (jas_iccuint32_t)tmp; | 1780 | *val = (jas_iccuint32_t)tmp; |
| 1588 | return 0; | 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 | static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val) | 1784 | static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val) |
| 1592 | { | 1785 | { |
| 1593 | jas_ulonglong tmp; | 1786 | jas_ulonglong tmp; |
| 1594 | if (jas_iccgetuint(in, 8, &tmp)) | 1787 | if (jas_iccgetuint(in, 8, &tmp)) { |
| 1595 | return -1; | 1788 | return -1; |
| 1789 | } | ||
| 1596 | *val = (jas_iccuint64_t)tmp; | 1790 | *val = (jas_iccuint64_t)tmp; |
| 1597 | return 0; | 1791 | return 0; |
| 1598 | } | 1792 | } |
| 1599 | 1793 | ||
| 1600 | //#ifdef JAS_ENABLE_ENCODER | ||
| 1601 | |||
| 1602 | static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val) | 1794 | static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val) |
| 1603 | { | 1795 | { |
| 1604 | int c; | 1796 | int c; |
| 1605 | for (unsigned i = n; i > 0; --i) { | 1797 | for (unsigned i = n; i > 0; --i) { |
| 1606 | c = (val >> (8 * (i - 1))) & 0xff; | 1798 | c = (val >> (8 * (i - 1))) & 0xff; |
| 1607 | if (jas_stream_putc(out, c) == EOF) | 1799 | if (jas_stream_putc(out, c) == EOF) { |
| 1608 | return -1; | 1800 | return -1; |
| 1801 | } | ||
| 1609 | } | 1802 | } |
| 1610 | return 0; | 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 | return jas_iccputuint(out, n, tmp); | 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 | bufptr = buf; | 1822 | bufptr = buf; |
| 1632 | for (unsigned n = 4; n > 0; --n) { | 1823 | for (unsigned n = 4; n > 0; --n) { |
| 1633 | c = (sig >> 24) & 0xff; | 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 | *bufptr++ = c; | 1827 | *bufptr++ = c; |
| 1636 | } | 1828 | } |
| 1637 | sig <<= 8; | 1829 | sig <<= 8; |
| @@ -1640,36 +1832,40 @@ static char *jas_iccsigtostr(unsigned sig, char *buf) · 2 unmodified lines | |||
| 1640 | return buf; | 1832 | return buf; |
| 1641 | } | 1833 | } |
| 1642 | 1834 | ||
| 1643 | //#ifdef JAS_ENABLE_ENCODER | ||
| 1644 | static unsigned jas_iccpadtomult(unsigned x, unsigned y) | 1835 | static unsigned jas_iccpadtomult(unsigned x, unsigned y) |
| 1645 | { | 1836 | { |
| 1646 | return ((x + y - 1) / y) * y; | 1837 | return ((x + y - 1) / y) * y; |
| 1647 | } | 1838 | } |
| 1648 | //#endif /* JAS_ENABLE_ENCODER */ | ||
| 1649 | 1839 | ||
| 1650 | static unsigned jas_iccpowi(unsigned x, unsigned n) | 1840 | static unsigned jas_iccpowi(unsigned x, unsigned n) |
| 1651 | { | 1841 | { |
| 1652 | unsigned y; | 1842 | unsigned y; |
| 1653 | y = 1; | 1843 | y = 1; |
| 1654 | while (n-- > 0) | 1844 | while (n-- > 0) { |
| 1655 | y *= x; | 1845 | y *= x; |
| 1846 | } | ||
| 1656 | return y; | 1847 | return y; |
| 1657 | } | 1848 | } |
| 1658 | 1849 | ||
| 1659 | 1850 | ||
| 1660 | jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len) | 1851 | jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len) |
| 1661 | { | 1852 | { |
| 1853 | assert(buf); | ||
| 1854 | assert(len > 0); | ||
| 1662 | jas_stream_t *in; | 1855 | jas_stream_t *in; |
| 1663 | jas_iccprof_t *prof; | 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 | goto error; | 1858 | goto error; |
| 1666 | if (!(prof = jas_iccprof_load(in))) | 1859 | } |
| 1860 | if (!(prof = jas_iccprof_load(in))) { | ||
| 1667 | goto error; | 1861 | goto error; |
| 1862 | } | ||
| 1668 | jas_stream_close(in); | 1863 | jas_stream_close(in); |
| 1669 | return prof; | 1864 | return prof; |
| 1670 | error: | 1865 | error: |
| 1671 | if (in) | 1866 | if (in) { |
| 1672 | jas_stream_close(in); | 1867 | jas_stream_close(in); |
| 1868 | } | ||
| 1673 | return 0; | 1869 | return 0; |
| 1674 | } | 1870 | } |
| 1675 | 1871 | ||
| @@ -59,9 +59,19 @@ · 58 unmodified lines | |||
| 59 | * __END_OF_JASPER_LICENSE__ | 59 | * __END_OF_JASPER_LICENSE__ |
| 60 | */ | 60 | */ |
| 61 | 61 | ||
| 62 | /******************************************************************************\ | ||
| 63 | * Includes. | ||
| 64 | \******************************************************************************/ | ||
| 65 | |||
| 66 | //#define JAS_FOR_INTERNAL_USE_ONLY | ||
| 67 | |||
| 62 | #include <jasper/jas_config.h> /* IWYU pragma: keep */ | 68 | #include <jasper/jas_config.h> /* IWYU pragma: keep */ |
| 63 | #include <jasper/jas_types.h> | 69 | #include <jasper/jas_types.h> |
| 64 | 70 | ||
| 71 | /******************************************************************************\ | ||
| 72 | * Data. | ||
| 73 | \******************************************************************************/ | ||
| 74 | |||
| 65 | const jas_uchar jas_iccprofdata_srgb[] = | 75 | const jas_uchar jas_iccprofdata_srgb[] = |
| 66 | { | 76 | { |
| 67 | 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, | 77 | 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, |
| @@ -71,9 +71,13 @@ · 70 unmodified lines | |||
| 71 | * Includes. | 71 | * Includes. |
| 72 | \******************************************************************************/ | 72 | \******************************************************************************/ |
| 73 | 73 | ||
| 74 | #define JAS_FOR_INTERNAL_USE_ONLY | ||
| 75 | |||
| 76 | #include "jasper/jas_init.h" | ||
| 74 | #include "jasper/jas_image.h" | 77 | #include "jasper/jas_image.h" |
| 75 | #include "jasper/jas_math.h" | 78 | #include "jasper/jas_math.h" |
| 76 | #include "jasper/jas_malloc.h" | 79 | #include "jasper/jas_malloc.h" |
| 80 | #include "jasper/jas_string.h" | ||
| 77 | #include "jasper/jas_debug.h" | 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 | static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt); | 94 | static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt); |
| 91 | static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, | 95 | static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, |
| 92 | int_fast32_t tly, int_fast32_t hstep, int_fast32_t vstep, | 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 | static void jas_image_setbbox(jas_image_t *image); | 99 | static void jas_image_setbbox(jas_image_t *image); |
| 95 | static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt); | 100 | static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt); |
| 96 | static int jas_image_growcmpts(jas_image_t *image, unsigned maxcmpts); | 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 | static long downtomult(long x, long y); | 107 | static long downtomult(long x, long y); |
| 103 | static long convert(long val, bool oldsgnd, unsigned oldprec, bool newsgnd, | 108 | static long convert(long val, bool oldsgnd, unsigned oldprec, bool newsgnd, |
| 104 | unsigned newprec); | 109 | unsigned newprec); |
| 105 | static void jas_image_calcbbox2(const jas_image_t *image, jas_image_coord_t *tlx, | 110 | static void jas_image_calcbbox2(const jas_image_t *image, |
| 106 | jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry); | 111 | jas_image_coord_t *tlx, jas_image_coord_t *tly, jas_image_coord_t *brx, |
| 107 | 112 | jas_image_coord_t *bry); | |
| 108 | /******************************************************************************\ | 113 | static void jas_image_fmtinfo_init(jas_image_fmtinfo_t *fmtinfo); |
| 109 | * Global data. | 114 | static void jas_image_fmtinfo_cleanup(jas_image_fmtinfo_t *fmtinfo); |
| 110 | \******************************************************************************/ | ||
| 111 | |||
| 112 | static unsigned jas_image_numfmts = 0; | ||
| 113 | static jas_image_fmtinfo_t jas_image_fmtinfos[JAS_IMAGE_MAXFMTS]; | ||
| 114 | 115 | ||
| 115 | /******************************************************************************\ | 116 | /******************************************************************************\ |
| 116 | * Create and destroy operations. | 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_image_t *jas_image_create(unsigned numcmpts, |
| 120 | jas_clrspc_t clrspc) | 121 | const jas_image_cmptparm_t *cmptparms, jas_clrspc_t clrspc) |
| 121 | { | 122 | { |
| 122 | jas_image_t *image; | 123 | jas_image_t *image; |
| 123 | size_t rawsize; | 124 | size_t rawsize; |
| 124 | unsigned cmptno; | 125 | unsigned cmptno; |
| 125 | const jas_image_cmptparm_t *cmptparm; | 126 | const jas_image_cmptparm_t *cmptparm; |
| 126 | 127 | ||
| 127 | JAS_DBGLOG(100, ("jas_image_create(%d, %p, %d)\n", numcmpts, cmptparms, | 128 | |
| 128 | clrspc)); | 129 | JAS_LOGDEBUGF(100, "jas_image_create(%d, %p, %d)\n", numcmpts, cmptparms, |
| 130 | clrspc); | ||
| 129 | 131 | ||
| 130 | if (!(image = jas_image_create0())) { | 132 | if (!(image = jas_image_create0())) { |
| 131 | goto error; | 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 | image->clrspc_ = clrspc; | 136 | image->clrspc_ = clrspc; |
| 135 | image->maxcmpts_ = numcmpts; | 137 | image->maxcmpts_ = numcmpts; |
| 138 | // image->inmem_ = true; | ||
| 136 | 139 | ||
| 137 | /* Allocate memory for the per-component information. */ | 140 | /* Allocate memory for the per-component information. */ |
| 138 | if (!(image->cmpts_ = jas_alloc2(image->maxcmpts_, | 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 | image->cmpts_[cmptno] = 0; | 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 | /* Create the individual image components. */ | 163 | /* Create the individual image components. */ |
| 148 | for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, | 164 | for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, |
| 149 | ++cmptparm) { | 165 | ++cmptparm) { |
| @@ -152,10 +168,11 @@ jas_image_t *jas_image_create(unsigned numcmpts, const jas_image_cmptparm_t *cmp · 2 unmodified lines | |||
| 152 | goto error; | 168 | goto error; |
| 153 | } | 169 | } |
| 154 | rawsize /= 8; | 170 | rawsize /= 8; |
| 171 | const bool inmem = (rawsize < JAS_IMAGE_INMEMTHRESH); | ||
| 155 | if (!(image->cmpts_[cmptno] = jas_image_cmpt_create(cmptparm->tlx, | 172 | if (!(image->cmpts_[cmptno] = jas_image_cmpt_create(cmptparm->tlx, |
| 156 | cmptparm->tly, cmptparm->hstep, cmptparm->vstep, | 173 | cmptparm->tly, cmptparm->hstep, cmptparm->vstep, |
| 157 | cmptparm->width, cmptparm->height, cmptparm->prec, | 174 | cmptparm->width, cmptparm->height, cmptparm->prec, |
| 158 | cmptparm->sgnd))) { | 175 | cmptparm->sgnd, inmem))) { |
| 159 | goto error; | 176 | goto error; |
| 160 | } | 177 | } |
| 161 | ++image->numcmpts_; | 178 | ++image->numcmpts_; |
| @@ -190,6 +207,7 @@ jas_image_t *jas_image_create0() · 28 unmodified lines | |||
| 190 | image->numcmpts_ = 0; | 207 | image->numcmpts_ = 0; |
| 191 | image->maxcmpts_ = 0; | 208 | image->maxcmpts_ = 0; |
| 192 | image->cmpts_ = 0; | 209 | image->cmpts_ = 0; |
| 210 | // image->inmem_ = true; | ||
| 193 | image->cmprof_ = 0; | 211 | image->cmprof_ = 0; |
| 194 | 212 | ||
| 195 | return image; | 213 | return image; |
| @@ -207,7 +225,8 @@ jas_image_t *jas_image_copy(jas_image_t *image) · 11 unmodified lines | |||
| 207 | goto error; | 225 | goto error; |
| 208 | } | 226 | } |
| 209 | for (unsigned cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { | 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 | goto error; | 230 | goto error; |
| 212 | } | 231 | } |
| 213 | ++newimage->numcmpts_; | 232 | ++newimage->numcmpts_; |
| @@ -216,8 +235,9 @@ jas_image_t *jas_image_copy(jas_image_t *image) · 2 unmodified lines | |||
| 216 | jas_image_setbbox(newimage); | 235 | jas_image_setbbox(newimage); |
| 217 | 236 | ||
| 218 | if (image->cmprof_) { | 237 | if (image->cmprof_) { |
| 219 | if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_))) | 238 | if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_))) { |
| 220 | goto error; | 239 | goto error; |
| 240 | } | ||
| 221 | } | 241 | } |
| 222 | 242 | ||
| 223 | return newimage; | 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 | if (!(newcmpt->stream_ = jas_stream_memopen(0, 0))) { | 279 | if (!(newcmpt->stream_ = jas_stream_memopen(0, 0))) { |
| 260 | goto error; | 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 | goto error; | 283 | goto error; |
| 264 | } | 284 | } |
| 265 | if (jas_stream_copy(newcmpt->stream_, cmpt->stream_, -1)) { | 285 | if (jas_stream_copy(newcmpt->stream_, cmpt->stream_, -1)) { |
| 266 | goto error; | 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 | goto error; | 289 | goto error; |
| 270 | } | 290 | } |
| 271 | return newcmpt; | 291 | return newcmpt; |
| @@ -283,20 +303,22 @@ void jas_image_destroy(jas_image_t *image) · 11 unmodified lines | |||
| 283 | } | 303 | } |
| 284 | jas_free(image->cmpts_); | 304 | jas_free(image->cmpts_); |
| 285 | } | 305 | } |
| 286 | if (image->cmprof_) | 306 | if (image->cmprof_) { |
| 287 | jas_cmprof_destroy(image->cmprof_); | 307 | jas_cmprof_destroy(image->cmprof_); |
| 308 | } | ||
| 288 | jas_free(image); | 309 | jas_free(image); |
| 289 | } | 310 | } |
| 290 | 311 | ||
| 291 | static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, | 312 | static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, |
| 292 | int_fast32_t tly, int_fast32_t hstep, int_fast32_t vstep, | 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 | jas_image_cmpt_t *cmpt; | 317 | jas_image_cmpt_t *cmpt; |
| 296 | size_t size; | 318 | size_t size; |
| 297 | 319 | ||
| 298 | JAS_DBGLOG(100, ( | 320 | JAS_LOGDEBUGF(100, |
| 299 | "jas_image_cmpt_create(%ld, %ld, %ld, %ld, %ld, %ld, %d, %d)\n", | 321 | "jas_image_cmpt_create(%ld, %ld, %ld, %ld, %ld, %ld, %d, %d, %d)\n", |
| 300 | JAS_CAST(long, tlx), | 322 | JAS_CAST(long, tlx), |
| 301 | JAS_CAST(long, tly), | 323 | JAS_CAST(long, tly), |
| 302 | JAS_CAST(long, hstep), | 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 | JAS_CAST(long, height), | 327 | JAS_CAST(long, height), |
| 306 | JAS_CAST(int, depth), | 328 | JAS_CAST(int, depth), |
| 307 | sgnd, | 329 | sgnd, |
| 308 | )); | 330 | inmem |
| 331 | ); | ||
| 309 | 332 | ||
| 310 | if (depth < 1U + sgnd) { | 333 | if (depth < 1U + sgnd) { |
| 311 | /* we need at least 1 bit for unsigned samples and 2 | 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 | cmpt->stream_ = 0; | 363 | cmpt->stream_ = 0; |
| 341 | cmpt->cps_ = (depth + 7) / 8; | 364 | cmpt->cps_ = (depth + 7) / 8; |
| 342 | 365 | ||
| 343 | // Compute the number of samples in the image component, while protecting | 366 | /* |
| 344 | // against overflow. | 367 | * Compute the number of samples in the image component, while protecting |
| 345 | // size = cmpt->width_ * cmpt->height_ * cmpt->cps_; | 368 | * against overflow. |
| 369 | * size = cmpt->width_ * cmpt->height_ * cmpt->cps_; | ||
| 370 | */ | ||
| 346 | if (!jas_safe_size_mul3(cmpt->width_, cmpt->height_, cmpt->cps_, &size)) { | 371 | if (!jas_safe_size_mul3(cmpt->width_, cmpt->height_, cmpt->cps_, &size)) { |
| 347 | goto error; | 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 | if (!cmpt->stream_) { | 376 | if (!cmpt->stream_) { |
| 351 | goto error; | 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 | if (size - 1 > LONG_MAX) { | 384 | if (size - 1 > LONG_MAX) { |
| 359 | goto error; | 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 | jas_stream_putc(cmpt->stream_, 0) == EOF || | 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 | goto error; | 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 | /* If possible, try to determine the format of the input data. */ | 420 | /* If possible, try to determine the format of the input data. */ |
| 395 | if (fmt < 0) { | 421 | if (fmt < 0) { |
| 396 | if ((fmt = jas_image_getfmt(in)) < 0){ | 422 | if ((fmt = jas_image_getfmt(in)) < 0) { |
| 397 | werrstr("unknown format"); | 423 | jas_logerrorf("jas_image_decode: cannot determine image format\n"); |
| 398 | goto error; | 424 | goto error; |
| 399 | } | 425 | } |
| 400 | } | 426 | } |
| 401 | 427 | ||
| 402 | /* Is it possible to decode an image represented in this format? */ | 428 | /* Is it possible to decode an image represented in this format? */ |
| 403 | if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))){ | 429 | if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) { |
| 404 | werrstr("unsupported format"); | ||
| 405 | goto error; | 430 | goto error; |
| 406 | } | 431 | } |
| 407 | if (!fmtinfo->ops.decode){ | 432 | if (!fmtinfo->ops.decode) { |
| 408 | werrstr("no decoder for the format"); | 433 | jas_logerrorf("jas_image_decode: no decode operation available\n"); |
| 409 | goto error; | 434 | goto error; |
| 410 | } | 435 | } |
| 411 | 436 | ||
| 412 | /* Decode the image. */ | 437 | /* Decode the image. */ |
| 413 | if (!(image = (*fmtinfo->ops.decode)(in, optstr))){ | 438 | if (!(image = (*fmtinfo->ops.decode)(in, optstr))) { |
| 414 | werrstr("failed to decode"); | 439 | jas_logerrorf("jas_image_decode: decode operation failed\n"); |
| 415 | goto error; | 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 | if (!jas_clrspc_isunknown(image->clrspc_) && | 444 | if (!jas_clrspc_isunknown(image->clrspc_) && |
| 420 | !jas_clrspc_isgeneric(image->clrspc_) && !image->cmprof_) { | 445 | !jas_clrspc_isgeneric(image->clrspc_) && !image->cmprof_) { |
| 421 | if (!(image->cmprof_ = | 446 | if (!(image->cmprof_ = |
| 422 | jas_cmprof_createfromclrspc(jas_image_clrspc(image)))){ | 447 | jas_cmprof_createfromclrspc(jas_image_clrspc(image)))) { |
| 423 | werrstr("failed to create colorspace"); | 448 | jas_logerrorf("jas_image_decode: cannot create CM profile\n"); |
| 424 | goto error; | 449 | goto error; |
| 425 | } | 450 | } |
| 426 | } | 451 | } |
| 427 | 452 | ||
| 428 | return image; | 453 | return image; |
| 454 | |||
| 429 | error: | 455 | error: |
| 430 | if (image) | 456 | if (image) { |
| 431 | jas_image_destroy(image); | 457 | jas_image_destroy(image); |
| 458 | } | ||
| 432 | return 0; | 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 | const jas_image_fmtinfo_t *fmtinfo; | 465 | const jas_image_fmtinfo_t *fmtinfo; |
| 439 | if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) { | 466 | if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) { |
| 440 | jas_eprintf("format lookup failed\n"); | 467 | jas_logerrorf("format lookup failed\n"); |
| 441 | return -1; | 468 | return -1; |
| 442 | } | 469 | } |
| 443 | return (fmtinfo->ops.encode) ? (*fmtinfo->ops.encode)(image, out, | 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 | jas_seqent_t *dr; | 487 | jas_seqent_t *dr; |
| 461 | jas_seqent_t *d; | 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 | image, cmptno, JAS_CAST(long, x), JAS_CAST(long, y), | 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 | if(data == NULL) { | 494 | if(data == NULL) { |
| 468 | return -1; | 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 | return -1; | 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 | if (jas_matrix_resize(data, height, width)) { | 515 | if (jas_matrix_resize(data, height, width)) { |
| 488 | return -1; | 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 | dr = jas_matrix_getref(data, 0, 0); | 526 | dr = jas_matrix_getref(data, 0, 0); |
| 499 | const uint_least32_t drs = jas_matrix_rowstep(data); | 527 | const uint_least32_t drs = jas_matrix_rowstep(data); |
| 528 | |||
| 529 | jas_uchar stack_buffer[16384]; | ||
| 530 | |||
| 500 | for (i = 0; i < height; ++i, dr += drs) { | 531 | for (i = 0; i < height; ++i, dr += drs) { |
| 501 | d = dr; | 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 | return -1; | 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 | /* fast path for 1 byte per sample and | 539 | /* fast path for 1 byte per sample and |
| 508 | unsigned with bulk reads */ | 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 | return -1; | 545 | return -1; |
| 546 | } | ||
| 514 | 547 | ||
| 515 | for (j = 0; j < width; ++j) | 548 | for (j = 0; j < width; ++j) { |
| 516 | d[j] = buffer[j]; | 549 | d[j] = buffer[j]; |
| 550 | } | ||
| 517 | 551 | ||
| 518 | continue; | 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 | return 0; | 567 | return 0; |
| 534 | } | 568 | } |
| 535 | 569 | ||
| 536 | int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, | 570 | int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, |
| 537 | jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, | 571 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 538 | const jas_matrix_t *data) | 572 | jas_image_coord_t height, const jas_matrix_t *data) |
| 539 | { | 573 | { |
| 540 | jas_image_cmpt_t *cmpt; | 574 | jas_image_cmpt_t *cmpt; |
| 541 | jas_image_coord_t i; | 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 | jas_seqent_t v; | 577 | jas_seqent_t v; |
| 544 | int c; | 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 | image, cmptno, JAS_CAST(long, x), JAS_CAST(long, y), | 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 | if (cmptno >= image->numcmpts_) { | 584 | if (cmptno >= image->numcmpts_) { |
| 551 | return -1; | 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 | const jas_seqent_t *dr = jas_matrix_getref(data, 0, 0); | 610 | const jas_seqent_t *dr = jas_matrix_getref(data, 0, 0); |
| 577 | const uint_least32_t drs = jas_matrix_rowstep(data); | 611 | const uint_least32_t drs = jas_matrix_rowstep(data); |
| 612 | |||
| 613 | jas_uchar stack_buffer[16384]; | ||
| 614 | |||
| 578 | for (i = 0; i < height; ++i, dr += drs) { | 615 | for (i = 0; i < height; ++i, dr += drs) { |
| 579 | const jas_seqent_t *d = dr; | 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 | return -1; | 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 | /* fast path for 1 byte per sample and | 623 | /* fast path for 1 byte per sample and |
| 586 | unsigned with bulk writes */ | 624 | unsigned with bulk writes */ |
| 587 | 625 | ||
| 588 | jas_uchar buffer[16384]; | 626 | jas_uchar *buffer = stack_buffer; |
| 589 | 627 | ||
| 590 | for (j = 0; j < width; ++j) | 628 | for (j = 0; j < width; ++j) |
| 591 | buffer[j] = d[j]; | 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 | * File format operations. | 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; | 657 | fmtinfo->id = -1; |
| 620 | for (unsigned i = 0; i < jas_image_numfmts; ++i) { | 658 | fmtinfo->name = 0; |
| 621 | fmtinfo = &jas_image_fmtinfos[i]; | 659 | fmtinfo->ext = 0; |
| 622 | if (fmtinfo->name) { | 660 | fmtinfo->exts = 0; |
| 623 | jas_free(fmtinfo->name); | 661 | fmtinfo->max_exts = 0; |
| 624 | fmtinfo->name = 0; | 662 | fmtinfo->num_exts = 0; |
| 625 | } | 663 | fmtinfo->enabled = 0; |
| 626 | if (fmtinfo->ext) { | 664 | fmtinfo->desc = 0; |
| 627 | jas_free(fmtinfo->ext); | 665 | memset(&fmtinfo->ops, 0, sizeof(jas_image_fmtops_t)); |
| 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; | ||
| 636 | } | 666 | } |
| 637 | 667 | ||
| 638 | int jas_image_addfmt(int id, const char *name, const char *ext, | 668 | static void jas_image_fmtinfo_cleanup(jas_image_fmtinfo_t *fmtinfo) |
| 639 | const char *desc, const jas_image_fmtops_t *ops) | ||
| 640 | { | 669 | { |
| 641 | jas_image_fmtinfo_t *fmtinfo; | 670 | if (fmtinfo->name) { |
| 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))) { | ||
| 652 | jas_free(fmtinfo->name); | 671 | jas_free(fmtinfo->name); |
| 653 | return -1; | 672 | fmtinfo->name = 0; |
| 654 | } | 673 | } |
| 655 | if (!(fmtinfo->desc = strdup(desc))) { | 674 | if (fmtinfo->ext) { |
| 656 | jas_free(fmtinfo->name); | ||
| 657 | jas_free(fmtinfo->ext); | 675 | jas_free(fmtinfo->ext); |
| 658 | return -1; | 676 | fmtinfo->ext = 0; |
| 659 | } | 677 | } |
| 660 | fmtinfo->ops = *ops; | 678 | if (fmtinfo->exts) { |
| 661 | ++jas_image_numfmts; | 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 | return 0; | 712 | return 0; |
| 663 | } | 713 | } |
| 664 | 714 | ||
| 665 | int jas_image_addcmpt(jas_image_t *image, int cmptno, | 715 | void jas_image_clearfmts_internal(jas_image_fmtinfo_t *image_fmtinfos, |
| 666 | const jas_image_cmptparm_t *cmptparm) | 716 | size_t *image_numfmts) |
| 667 | { | 717 | { |
| 668 | jas_image_cmpt_t *newcmpt; | 718 | jas_image_fmtinfo_t *fmtinfo; |
| 669 | if (cmptno < 0) { | 719 | for (int fmtind = 0; fmtind < *image_numfmts; ++fmtind) { |
| 670 | cmptno = image->numcmpts_; | 720 | fmtinfo = &image_fmtinfos[fmtind]; |
| 721 | jas_image_fmtinfo_cleanup(fmtinfo); | ||
| 671 | } | 722 | } |
| 672 | assert(cmptno >= 0 && (unsigned)cmptno <= image->numcmpts_); | 723 | *image_numfmts = 0; |
| 673 | if (image->numcmpts_ >= image->maxcmpts_) { | 724 | } |
| 674 | if (jas_image_growcmpts(image, image->maxcmpts_ + 128)) { | 725 | |
| 675 | return -1; | 726 | void jas_image_clearfmts() |
| 676 | } | 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, | 745 | fmtinfo = &image_fmtinfos[*image_numfmts]; |
| 679 | cmptparm->tly, cmptparm->hstep, cmptparm->vstep, | 746 | jas_image_fmtinfo_init(fmtinfo); |
| 680 | cmptparm->width, cmptparm->height, cmptparm->prec, | 747 | fmtinfo->id = id; |
| 681 | cmptparm->sgnd))) { | 748 | if (jas_stringtokenize(ext, delim, &fmtinfo->exts, &fmtinfo->max_exts, |
| 682 | return -1; | 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_) { | 768 | fmtinfo->ops = *ops; |
| 685 | memmove(&image->cmpts_[cmptno + 1], &image->cmpts_[cmptno], | 769 | ++(*image_numfmts); |
| 686 | (image->numcmpts_ - (unsigned)cmptno) * sizeof(jas_image_cmpt_t *)); | 770 | done: |
| 771 | if (ret && fmtinfo) { | ||
| 772 | jas_image_fmtinfo_cleanup(fmtinfo); | ||
| 687 | } | 773 | } |
| 688 | image->cmpts_[cmptno] = newcmpt; | 774 | return ret; |
| 689 | ++image->numcmpts_; | 775 | } |
| 690 | |||
| 691 | jas_image_setbbox(image); | ||
| 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 | /* This is for future consideration for addition to the library API. */ | 785 | /* This is for future consideration for addition to the library API. */ |
| 697 | #if 0 | 786 | #if 0 |
| 698 | JAS_DLLEXPORT | 787 | JAS_EXPORT |
| 699 | int jas_image_delfmt(int fmtid) | 788 | int jas_image_delfmt(int fmtid) |
| 700 | { | 789 | { |
| 701 | if (fmtid < 0 || fmtid >= JAS_CAST(int, jas_image_numfmts)) { | 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 | int jas_image_getfmt(jas_stream_t *in) | 824 | int jas_image_getfmt(jas_stream_t *in) |
| 736 | { | 825 | { |
| 826 | jas_ctx_t *ctx = jas_get_ctx(); | ||
| 737 | const jas_image_fmtinfo_t *fmtinfo; | 827 | const jas_image_fmtinfo_t *fmtinfo; |
| 738 | 828 | ||
| 739 | /* Check for data in each of the supported formats. */ | 829 | /* Check for data in each of the supported formats. */ |
| 740 | unsigned i; | 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 | ++fmtinfo) { | 832 | ++fmtinfo) { |
| 743 | if (fmtinfo->ops.validate) { | 833 | if (fmtinfo->enabled && fmtinfo->ops.validate) { |
| 744 | /* Is the input data valid for this format? */ | 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 | if (!(*fmtinfo->ops.validate)(in)) { | 836 | if (!(*fmtinfo->ops.validate)(in)) { |
| 747 | JAS_DBGLOG(20, ("test succeeded\n")); | 837 | JAS_LOGDEBUGF(20, "test succeeded\n"); |
| 748 | return fmtinfo->id; | 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 | return -1; | 843 | return -1; |
| @@ -755,6 +845,7 @@ int jas_image_getfmt(jas_stream_t *in) · 1 unmodified line | |||
| 755 | 845 | ||
| 756 | int jas_image_fmtfromname(const char *name) | 846 | int jas_image_fmtfromname(const char *name) |
| 757 | { | 847 | { |
| 848 | jas_ctx_t *ctx = jas_get_ctx(); | ||
| 758 | const char *ext; | 849 | const char *ext; |
| 759 | const jas_image_fmtinfo_t *fmtinfo; | 850 | const jas_image_fmtinfo_t *fmtinfo; |
| 760 | /* Get the file name extension. */ | 851 | /* Get the file name extension. */ |
| @@ -764,10 +855,10 @@ int jas_image_fmtfromname(const char *name) · 3 unmodified lines | |||
| 764 | ++ext; | 855 | ++ext; |
| 765 | /* Try to find a format that uses this extension. */ | 856 | /* Try to find a format that uses this extension. */ |
| 766 | unsigned i; | 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 | ++fmtinfo) { | 859 | ++fmtinfo) { |
| 769 | /* Do we have a match? */ | 860 | /* Do we have a match? */ |
| 770 | if (!strcmp(ext, fmtinfo->ext)) { | 861 | if (fmtinfo->enabled && !strcmp(ext, fmtinfo->ext)) { |
| 771 | return fmtinfo->id; | 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 | jas_image_setbbox(image); | 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 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id) | 949 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id) |
| 828 | { | 950 | { |
| 951 | jas_ctx_t *ctx = jas_get_ctx(); | ||
| 829 | unsigned i; | 952 | unsigned i; |
| 830 | const jas_image_fmtinfo_t *fmtinfo; | 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 | if (fmtinfo->id == id) { | 957 | if (fmtinfo->id == id) { |
| 834 | return fmtinfo; | 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 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name) | 964 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name) |
| 841 | { | 965 | { |
| 966 | jas_ctx_t *ctx = jas_get_ctx(); | ||
| 842 | unsigned i; | 967 | unsigned i; |
| 843 | const jas_image_fmtinfo_t *fmtinfo; | 968 | const jas_image_fmtinfo_t *fmtinfo; |
| 844 | 969 | for (i = 0, fmtinfo = ctx->image_fmtinfos; i < ctx->image_numfmts; | |
| 845 | for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) { | 970 | ++i, ++fmtinfo) { |
| 846 | if (!strcmp(fmtinfo->name, name)) { | 971 | if (!strcmp(fmtinfo->name, name)) { |
| 847 | return fmtinfo; | 972 | return fmtinfo; |
| 848 | } | 973 | } |
| @@ -853,7 +978,9 @@ const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name) · 4 unmodified lines | |||
| 853 | static uint_fast32_t inttobits(jas_seqent_t v, unsigned prec, bool sgnd) | 978 | static uint_fast32_t inttobits(jas_seqent_t v, unsigned prec, bool sgnd) |
| 854 | { | 979 | { |
| 855 | uint_fast32_t ret; | 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 | return ret; | 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 | return 0; | 1072 | return 0; |
| 946 | } | 1073 | } |
| 947 | 1074 | ||
| 948 | int jas_image_depalettize(jas_image_t *image, unsigned cmptno, unsigned numlutents, | 1075 | int jas_image_dump(jas_image_t *image, FILE *out) |
| 949 | const int_fast32_t *lutents, unsigned dtype, unsigned newcmptno) | 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 | jas_image_cmptparm_t cmptparms; | 1109 | jas_image_cmptparm_t cmptparms; |
| 952 | const jas_image_cmpt_t *cmpt = image->cmpts_[cmptno]; | 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 | cmpt = image->cmpts_[cmptno]; | 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 | return -1; | 1157 | return -1; |
| 999 | } | 1158 | } |
| 1000 | v = 0; | 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 | cmpt = image->cmpts_[cmptno]; | 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 | return; | 1180 | return; |
| 1021 | } | 1181 | } |
| 1022 | t = inttobits(v, cmpt->prec_, cmpt->sgnd_); | 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 | for (unsigned cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { | 1195 | for (unsigned cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { |
| 1035 | if (image->cmpts_[cmptno]->type_ == ctype) { | 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 | return -1; | 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, | 1208 | int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, |
| 1063 | jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, | 1209 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 1064 | long *buf) | 1210 | jas_image_coord_t height, long *buf) |
| 1065 | { | 1211 | { |
| 1066 | jas_image_cmpt_t *cmpt; | 1212 | jas_image_cmpt_t *cmpt; |
| 1067 | jas_image_coord_t i; | 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 | long v; | 1215 | long v; |
| 1070 | long *bufptr; | 1216 | long *bufptr; |
| 1071 | 1217 | ||
| 1072 | if (cmptno >= image->numcmpts_) | 1218 | if (cmptno >= image->numcmpts_) { |
| 1073 | goto error; | 1219 | goto error; |
| 1220 | } | ||
| 1074 | cmpt = image->cmpts_[cmptno]; | 1221 | cmpt = image->cmpts_[cmptno]; |
| 1075 | if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ || | 1222 | if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ || |
| 1076 | width < 0 || height < 0 || x + width > cmpt->width_ || | 1223 | width < 0 || height < 0 || x + width > cmpt->width_ || |
| 1077 | y + height > cmpt->height_) | 1224 | y + height > cmpt->height_) { |
| 1078 | goto error; | 1225 | goto error; |
| 1226 | } | ||
| 1079 | 1227 | ||
| 1080 | bufptr = buf; | 1228 | bufptr = buf; |
| 1081 | for (i = 0; i < height; ++i) { | 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 | goto error; | 1232 | goto error; |
| 1233 | } | ||
| 1084 | for (j = 0; j < width; ++j) { | 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 | goto error; | 1236 | goto error; |
| 1237 | } | ||
| 1087 | *bufptr++ = v; | 1238 | *bufptr++ = v; |
| 1088 | } | 1239 | } |
| 1089 | } | 1240 | } |
| @@ -1093,31 +1244,36 @@ error: · 3 unmodified lines | |||
| 1093 | return -1; | 1244 | return -1; |
| 1094 | } | 1245 | } |
| 1095 | 1246 | ||
| 1096 | int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, | 1247 | int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, |
| 1097 | jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, | 1248 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 1098 | const long *buf) | 1249 | jas_image_coord_t height, const long *buf) |
| 1099 | { | 1250 | { |
| 1100 | jas_image_cmpt_t *cmpt; | 1251 | jas_image_cmpt_t *cmpt; |
| 1101 | jas_image_coord_t i; | 1252 | jas_image_coord_t i; |
| 1102 | jas_image_coord_t j; | 1253 | jas_image_coord_t j; |
| 1103 | long v; | 1254 | long v; |
| 1104 | 1255 | ||
| 1105 | if (cmptno >= image->numcmpts_) | 1256 | if (cmptno >= image->numcmpts_) { |
| 1106 | goto error; | 1257 | goto error; |
| 1258 | } | ||
| 1107 | cmpt = image->cmpts_[cmptno]; | 1259 | cmpt = image->cmpts_[cmptno]; |
| 1108 | if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ || | 1260 | if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ || |
| 1109 | width < 0 || height < 0 || x + width > cmpt->width_ || | 1261 | width < 0 || height < 0 || x + width > cmpt->width_ || |
| 1110 | y + height > cmpt->height_) | 1262 | y + height > cmpt->height_) { |
| 1111 | goto error; | 1263 | goto error; |
| 1264 | } | ||
| 1112 | 1265 | ||
| 1113 | const long *bufptr = buf; | 1266 | const long *bufptr = buf; |
| 1114 | for (i = 0; i < height; ++i) { | 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 | goto error; | 1270 | goto error; |
| 1271 | } | ||
| 1117 | for (j = 0; j < width; ++j) { | 1272 | for (j = 0; j < width; ++j) { |
| 1118 | v = *bufptr++; | 1273 | v = *bufptr++; |
| 1119 | if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v)) | 1274 | if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v)) { |
| 1120 | goto error; | 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 | cmptparm.height = height; | 1321 | cmptparm.height = height; |
| 1166 | cmptparm.prec = prec; | 1322 | cmptparm.prec = prec; |
| 1167 | cmptparm.sgnd = sgnd; | 1323 | cmptparm.sgnd = sgnd; |
| 1168 | if (jas_image_addcmpt(image, newcmptno, &cmptparm)) | 1324 | if (jas_image_addcmpt(image, newcmptno, &cmptparm)) { |
| 1169 | goto error; | 1325 | goto error; |
| 1170 | cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_; | 1326 | } |
| 1171 | cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; | 1327 | cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_; |
| 1328 | cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; | ||
| 1172 | const jas_image_cmpt_t *const newcmpt = image->cmpts_[newcmptno]; | 1329 | const jas_image_cmpt_t *const newcmpt = image->cmpts_[newcmptno]; |
| 1173 | jas_stream_rewind(newcmpt->stream_); | 1330 | jas_stream_rewind(newcmpt->stream_); |
| 1174 | for (unsigned i = 0; i < height; ++i) { | 1331 | for (unsigned i = 0; i < height; ++i) { |
| @@ -1178,11 +1335,13 @@ cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; · 3 unmodified lines | |||
| 1178 | ax = downtomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_; | 1335 | ax = downtomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_; |
| 1179 | ay = downtomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_; | 1336 | ay = downtomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_; |
| 1180 | bx = uptomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_; | 1337 | bx = uptomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_; |
| 1181 | if (bx > cmptbrx) | 1338 | if (bx > cmptbrx) { |
| 1182 | bx = cmptbrx; | 1339 | bx = cmptbrx; |
| 1340 | } | ||
| 1183 | by = uptomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_; | 1341 | by = uptomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_; |
| 1184 | if (by > cmptbry) | 1342 | if (by > cmptbry) { |
| 1185 | by = cmptbry; | 1343 | by = cmptbry; |
| 1344 | } | ||
| 1186 | d0 = (ax - x) * (ax - x) + (ay - y) * (ay - y); | 1345 | d0 = (ax - x) * (ax - x) + (ay - y) * (ay - y); |
| 1187 | d1 = (bx - x) * (bx - x) + (ay - y) * (ay - y); | 1346 | d1 = (bx - x) * (bx - x) + (ay - y) * (ay - y); |
| 1188 | d2 = (bx - x) * (bx - x) + (by - y) * (by - y); | 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 | assert(oldx >= 0 && oldx < oldcmpt->width_ && | 1362 | assert(oldx >= 0 && oldx < oldcmpt->width_ && |
| 1204 | oldy >= 0 && oldy < oldcmpt->height_); | 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 | goto error; | 1366 | goto error; |
| 1367 | } | ||
| 1207 | if (getint(oldcmpt->stream_, oldcmpt->sgnd_, | 1368 | if (getint(oldcmpt->stream_, oldcmpt->sgnd_, |
| 1208 | oldcmpt->prec_, &v)) | 1369 | oldcmpt->prec_, &v)) { |
| 1209 | goto error; | 1370 | goto error; |
| 1371 | } | ||
| 1210 | if (newcmpt->prec_ != oldcmpt->prec_ || | 1372 | if (newcmpt->prec_ != oldcmpt->prec_ || |
| 1211 | newcmpt->sgnd_ != oldcmpt->sgnd_) { | 1373 | newcmpt->sgnd_ != oldcmpt->sgnd_) { |
| 1212 | v = convert(v, oldcmpt->sgnd_, oldcmpt->prec_, | 1374 | v = convert(v, oldcmpt->sgnd_, oldcmpt->prec_, |
| 1213 | newcmpt->sgnd_, newcmpt->prec_); | 1375 | newcmpt->sgnd_, newcmpt->prec_); |
| 1214 | } | 1376 | } |
| 1215 | if (putint(newcmpt->stream_, newcmpt->sgnd_, | 1377 | if (putint(newcmpt->stream_, newcmpt->sgnd_, |
| 1216 | newcmpt->prec_, v)) | 1378 | newcmpt->prec_, v)) { |
| 1217 | goto error; | 1379 | goto error; |
| 1380 | } | ||
| 1218 | } | 1381 | } |
| 1219 | } | 1382 | } |
| 1220 | return 0; | 1383 | return 0; |
| @@ -1241,8 +1404,9 @@ int jas_image_ishomosamp(const jas_image_t *image) · 20 unmodified lines | |||
| 1241 | } | 1404 | } |
| 1242 | 1405 | ||
| 1243 | /* Note: This function defines a bounding box differently. */ | 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, | 1407 | static void jas_image_calcbbox2(const jas_image_t *image, |
| 1245 | jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry) | 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 | jas_image_coord_t tmptlx; | 1411 | jas_image_coord_t tmptlx; |
| 1248 | jas_image_coord_t tmptly; | 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 | tmpbry = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1); | 1421 | tmpbry = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1); |
| 1258 | for (unsigned i = 0; i < image->numcmpts_; ++i) { | 1422 | for (unsigned i = 0; i < image->numcmpts_; ++i) { |
| 1259 | cmpt = image->cmpts_[i]; | 1423 | cmpt = image->cmpts_[i]; |
| 1260 | if (cmpt->tlx_ < tmptlx) | 1424 | if (cmpt->tlx_ < tmptlx) { |
| 1261 | tmptlx = cmpt->tlx_; | 1425 | tmptlx = cmpt->tlx_; |
| 1262 | if (cmpt->tly_ < tmptly) | 1426 | } |
| 1427 | if (cmpt->tly_ < tmptly) { | ||
| 1263 | tmptly = cmpt->tly_; | 1428 | tmptly = cmpt->tly_; |
| 1429 | } | ||
| 1264 | t = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1); | 1430 | t = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1); |
| 1265 | if (t > tmpbrx) | 1431 | if (t > tmpbrx) { |
| 1266 | tmpbrx = t; | 1432 | tmpbrx = t; |
| 1433 | } | ||
| 1267 | t = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1); | 1434 | t = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1); |
| 1268 | if (t > tmpbry) | 1435 | if (t > tmpbry) { |
| 1269 | tmpbry = t; | 1436 | tmpbry = t; |
| 1437 | } | ||
| 1270 | } | 1438 | } |
| 1271 | } else { | 1439 | } else { |
| 1272 | tmptlx = 0; | 1440 | tmptlx = 0; |
| @@ -1285,7 +1453,7 @@ static inline long decode_twos_comp(jas_ulong c, unsigned prec) · 12 unmodified lines | |||
| 1285 | { | 1453 | { |
| 1286 | long result; | 1454 | long result; |
| 1287 | assert(prec >= 2); | 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 | // NOTE: Is this correct? | 1457 | // NOTE: Is this correct? |
| 1290 | result = (c & ((1 << (prec - 1)) - 1)) - (c & (1 << (prec - 1))); | 1458 | result = (c & ((1 << (prec - 1)) - 1)) - (c & (1 << (prec - 1))); |
| 1291 | return result; | 1459 | return result; |
| @@ -1296,7 +1464,7 @@ static inline jas_ulong encode_twos_comp(long n, unsigned prec) · 4 unmodified lines | |||
| 1296 | { | 1464 | { |
| 1297 | jas_ulong result; | 1465 | jas_ulong result; |
| 1298 | assert(prec >= 2); | 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 | // NOTE: Is this correct? | 1468 | // NOTE: Is this correct? |
| 1301 | if (n < 0) { | 1469 | if (n < 0) { |
| 1302 | result = -n; | 1470 | result = -n; |
| @@ -1315,8 +1483,9 @@ static int getint(jas_stream_t *in, bool sgnd, unsigned prec, long *val) · 12 unmodified lines | |||
| 1315 | assert((!sgnd && prec >= 1) || (sgnd && prec >= 2)); | 1483 | assert((!sgnd && prec >= 1) || (sgnd && prec >= 2)); |
| 1316 | v = 0; | 1484 | v = 0; |
| 1317 | for (unsigned n = (prec + 7) / 8; n-- > 0;) { | 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 | return -1; | 1487 | return -1; |
| 1488 | } | ||
| 1320 | v = (v << 8) | c; | 1489 | v = (v << 8) | c; |
| 1321 | } | 1490 | } |
| 1322 | v &= ((1 << prec) - 1); | 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 | val &= (1 << prec) - 1; | 1508 | val &= (1 << prec) - 1; |
| 1340 | for (unsigned n = (prec + 7) / 8; n-- > 0;) { | 1509 | for (unsigned n = (prec + 7) / 8; n-- > 0;) { |
| 1341 | c = (val >> (n * 8)) & 0xff; | 1510 | c = (val >> (n * 8)) & 0xff; |
| 1342 | if (jas_stream_putc(out, c) != c) | 1511 | if (jas_stream_putc(out, c) != c) { |
| 1343 | return -1; | 1512 | return -1; |
| 1513 | } | ||
| 1344 | } | 1514 | } |
| 1345 | return 0; | 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 | static long convert(long val, bool oldsgnd, unsigned oldprec, bool newsgnd, | 1518 | static long convert(long val, bool oldsgnd, unsigned oldprec, bool newsgnd, |
| 1349 | unsigned newprec) | 1519 | unsigned newprec) |
| 1350 | { | 1520 | { |
| 1521 | /* TODO: The following code looks suspicious (i.e., an empty if body). */ | ||
| 1351 | if (newsgnd != oldsgnd) { | 1522 | if (newsgnd != oldsgnd) { |
| 1352 | } | 1523 | } |
| 1353 | if (newprec != oldprec) { | 1524 | if (newprec != oldprec) { |
| @@ -1372,8 +1543,8 @@ static long uptomult(long x, long y) · 18 unmodified lines | |||
| 1372 | return ((x + y - 1) / y) * y; | 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, | 1546 | jas_image_t *jas_image_chclrspc(jas_image_t *image, |
| 1376 | jas_cmxform_intent_t intent) | 1547 | const jas_cmprof_t *outprof, jas_cmxform_intent_t intent) |
| 1377 | { | 1548 | { |
| 1378 | jas_image_t *inimage; | 1549 | jas_image_t *inimage; |
| 1379 | int k; | 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 | jas_cmcmptfmt_t *incmptfmts; | 1558 | jas_cmcmptfmt_t *incmptfmts; |
| 1388 | jas_cmcmptfmt_t *outcmptfmts; | 1559 | jas_cmcmptfmt_t *outcmptfmts; |
| 1389 | 1560 | ||
| 1390 | if (image->numcmpts_ == 0) | 1561 | #if 0 |
| 1391 | /* can't work with a file with no components; | 1562 | jas_eprintf("IMAGE\n"); |
| 1392 | continuing would crash because we'd attempt to | 1563 | jas_image_dump(image, stderr); |
| 1393 | obtain information about the first component */ | 1564 | #endif |
| 1394 | return NULL; | 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 | outimage = 0; | 1575 | outimage = 0; |
| 1397 | xform = 0; | 1576 | xform = 0; |
| 1398 | if (!(inimage = jas_image_copy(image))) | 1577 | if (!(inimage = jas_image_copy(image))) { |
| 1399 | goto error; | 1578 | goto error; |
| 1579 | } | ||
| 1400 | 1580 | ||
| 1401 | if (!jas_image_ishomosamp(inimage)) { | 1581 | if (!jas_image_ishomosamp(inimage)) { |
| 1402 | unsigned minhstep = jas_image_cmpthstep(inimage, 0); | 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 | unsigned n = jas_image_numcmpts(inimage); | 1594 | unsigned n = jas_image_numcmpts(inimage); |
| 1415 | for (unsigned i = 0; i < n; ++i) { | 1595 | for (unsigned i = 0; i < n; ++i) { |
| 1416 | if (jas_image_sampcmpt(inimage, i, i + 1, 0, 0, minhstep, minvstep, | 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 | goto error; | 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 | jas_image_setcmpttype(inimage, i + 1, cmpttype); | 1603 | jas_image_setcmpttype(inimage, i + 1, cmpttype); |
| 1422 | jas_image_delcmpt(inimage, i); | 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 | const unsigned vstep = jas_image_cmptvstep(inimage, 0); | 1611 | const unsigned vstep = jas_image_cmptvstep(inimage, 0); |
| 1430 | 1612 | ||
| 1431 | if (!(inprof = jas_image_cmprof(inimage))) { | 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)); | 1617 | const unsigned numinclrchans = |
| 1435 | const unsigned numoutclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(outprof)); | 1618 | jas_clrspc_numchans(jas_cmprof_clrspc(inprof)); |
| 1619 | const unsigned numoutclrchans = | ||
| 1620 | jas_clrspc_numchans(jas_cmprof_clrspc(outprof)); | ||
| 1436 | const unsigned prec = 8; | 1621 | const unsigned prec = 8; |
| 1437 | 1622 | ||
| 1438 | if (!(outimage = jas_image_create0())) { | 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 | cmptparm.height = height; | 1634 | cmptparm.height = height; |
| 1450 | cmptparm.prec = prec; | 1635 | cmptparm.prec = prec; |
| 1451 | cmptparm.sgnd = 0; | 1636 | cmptparm.sgnd = 0; |
| 1452 | if (jas_image_addcmpt(outimage, -1, &cmptparm)) | 1637 | if (jas_image_addcmpt(outimage, -1, &cmptparm)) { |
| 1453 | goto error; | 1638 | goto error; |
| 1639 | } | ||
| 1454 | jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i)); | 1640 | jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i)); |
| 1455 | } | 1641 | } |
| 1456 | #if 0 | 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 | #endif | 1650 | #endif |
| 1465 | 1651 | ||
| 1466 | if (!(tmpprof = jas_cmprof_copy(outprof))) | 1652 | if (!(tmpprof = jas_cmprof_copy(outprof))) { |
| 1467 | goto error; | 1653 | goto error; |
| 1654 | } | ||
| 1468 | assert(!jas_image_cmprof(outimage)); | 1655 | assert(!jas_image_cmprof(outimage)); |
| 1469 | jas_image_setcmprof(outimage, tmpprof); | 1656 | jas_image_setcmprof(outimage, tmpprof); |
| 1470 | jas_image_setclrspc(outimage, jas_cmprof_clrspc(outprof)); | 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 | inpixmap.numcmpts = numinclrchans; | 1664 | inpixmap.numcmpts = numinclrchans; |
| 1478 | if (!(incmptfmts = jas_alloc2(numinclrchans, sizeof(jas_cmcmptfmt_t)))) { | 1665 | if (!(incmptfmts = jas_alloc2(numinclrchans, sizeof(jas_cmcmptfmt_t)))) { |
| 1479 | abort(); | 1666 | // formerly call to abort() |
| 1667 | goto error; | ||
| 1480 | } | 1668 | } |
| 1481 | inpixmap.cmptfmts = incmptfmts; | 1669 | inpixmap.cmptfmts = incmptfmts; |
| 1482 | for (unsigned i = 0; i < numinclrchans; ++i) { | 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 | outpixmap.numcmpts = numoutclrchans; | 1681 | outpixmap.numcmpts = numoutclrchans; |
| 1494 | if (!(outcmptfmts = jas_alloc2(numoutclrchans, sizeof(jas_cmcmptfmt_t)))) { | 1682 | if (!(outcmptfmts = jas_alloc2(numoutclrchans, sizeof(jas_cmcmptfmt_t)))) { |
| 1495 | abort(); | 1683 | // formerly call to abort() |
| 1684 | goto error; | ||
| 1496 | } | 1685 | } |
| 1497 | outpixmap.cmptfmts = outcmptfmts; | 1686 | outpixmap.cmptfmts = outcmptfmts; |
| 1498 | 1687 | ||
| 1499 | for (unsigned i = 0; i < numoutclrchans; ++i) { | 1688 | for (unsigned i = 0; i < numoutclrchans; ++i) { |
| 1500 | const int j = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(i)); | 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 | goto error; | 1691 | goto error; |
| 1692 | } | ||
| 1503 | outcmptfmts[i].prec = jas_image_cmptprec(outimage, j); | 1693 | outcmptfmts[i].prec = jas_image_cmptprec(outimage, j); |
| 1504 | outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j); | 1694 | outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j); |
| 1505 | outcmptfmts[i].width = width; | 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 | for (unsigned j = 0; j < numinclrchans; ++j) { | 1700 | for (unsigned j = 0; j < numinclrchans; ++j) { |
| 1511 | k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j)); | 1701 | k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j)); |
| 1512 | if (jas_image_readcmpt2(inimage, k, 0, i, width, 1, | 1702 | if (jas_image_readcmpt2(inimage, k, 0, i, width, 1, |
| 1513 | incmptfmts[j].buf)) | 1703 | incmptfmts[j].buf)) { |
| 1514 | goto error; | 1704 | goto error; |
| 1705 | } | ||
| 1515 | } | 1706 | } |
| 1516 | jas_cmxform_apply(xform, &inpixmap, &outpixmap); | 1707 | jas_cmxform_apply(xform, &inpixmap, &outpixmap); |
| 1517 | for (unsigned j = 0; j < numoutclrchans; ++j) { | 1708 | for (unsigned j = 0; j < numoutclrchans; ++j) { |
| 1518 | k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j)); | 1709 | k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j)); |
| 1519 | if (jas_image_writecmpt2(outimage, k, 0, i, width, 1, | 1710 | if (jas_image_writecmpt2(outimage, k, 0, i, width, 1, |
| 1520 | outcmptfmts[j].buf)) | 1711 | outcmptfmts[j].buf)) { |
| 1521 | goto error; | 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 | jas_cmxform_destroy(xform); | 1725 | jas_cmxform_destroy(xform); |
| 1534 | jas_image_destroy(inimage); | 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 | return outimage; | 1734 | return outimage; |
| 1537 | error: | 1735 | error: |
| 1538 | if (xform) | 1736 | if (xform) { |
| 1539 | jas_cmxform_destroy(xform); | 1737 | jas_cmxform_destroy(xform); |
| 1540 | if (inimage) | 1738 | } |
| 1739 | if (inimage) { | ||
| 1541 | jas_image_destroy(inimage); | 1740 | jas_image_destroy(inimage); |
| 1542 | if (outimage) | 1741 | } |
| 1742 | if (outimage) { | ||
| 1543 | jas_image_destroy(outimage); | 1743 | jas_image_destroy(outimage); |
| 1744 | } | ||
| 1544 | return 0; | 1745 | return 0; |
| 1545 | } | 1746 | } |
| @@ -63,45 +63,971 @@ · 62 unmodified lines | |||
| 63 | * Includes. | 63 | * Includes. |
| 64 | \******************************************************************************/ | 64 | \******************************************************************************/ |
| 65 | 65 | ||
| 66 | #define JAS_FOR_INTERNAL_USE_ONLY | ||
| 67 | |||
| 66 | #include "jasper/jas_init.h" | 68 | #include "jasper/jas_init.h" |
| 67 | #include "jasper/jas_image.h" | 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 | * Code. | 826 | * Code. |
| 71 | \******************************************************************************/ | 827 | \******************************************************************************/ |
| 72 | 828 | ||
| 73 | /* Initialize the image format table. */ | 829 | /* Initialize the image format table. */ |
| 74 | JAS_DLLEXPORT | 830 | static int jas_init_codecs(jas_ctx_t *ctx) |
| 75 | int jas_init(void) | ||
| 76 | { | 831 | { |
| 77 | jas_image_fmtops_t fmtops; | 832 | int ret = 0; |
| 78 | int fmtid = 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) | 852 | /******************************************************************************\ |
| 81 | fmtops.decode = jp2_decode; | 853 | * Context management (e.g., creation and destruction). |
| 82 | fmtops.validate = jp2_validate; | 854 | \******************************************************************************/ |
| 83 | jas_image_addfmt(fmtid++, "jp2", "jp2", | 855 | |
| 84 | "JPEG-2000 JP2 File Format Syntax (ISO/IEC 15444-1)", &fmtops); | 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 | #endif | 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) | 918 | JAS_EXPORT |
| 88 | fmtops.decode = jpc_decode; | 919 | jas_context_t jas_get_context() |
| 89 | fmtops.validate = jpc_validate; | 920 | { |
| 90 | jas_image_addfmt(fmtid, "jpc", "jpc", | 921 | return JAS_CAST(jas_context_t, jas_get_ctx()); |
| 91 | "JPEG-2000 Code Stream Syntax (ISO/IEC 15444-1)", &fmtops); | 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 | #endif | 949 | #endif |
| 950 | } | ||
| 93 | 951 | ||
| 94 | /* We must not register the JasPer library exit handler until after | 952 | jas_ctx_t *jas_get_default_ctx() |
| 95 | at least one memory allocation is performed. This is desirable | 953 | { |
| 96 | as it ensures that the JasPer exit handler is called before the | 954 | jas_ctx_t *ctx; |
| 97 | debug memory allocator exit handler. */ | ||
| 98 | atexit(jas_cleanup); | ||
| 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 | 1028 | JAS_EXPORT |
| 104 | void jas_cleanup(void) | 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 | * Includes. | 71 | * Includes. |
| 72 | \******************************************************************************/ | 72 | \******************************************************************************/ |
| 73 | 73 | ||
| 74 | #define JAS_FOR_INTERNAL_USE_ONLY | ||
| 75 | |||
| 74 | #include "jasper/jas_seq.h" | 76 | #include "jasper/jas_seq.h" |
| 75 | #include "jasper/jas_malloc.h" | 77 | #include "jasper/jas_malloc.h" |
| 76 | #include "jasper/jas_math.h" | 78 | #include "jasper/jas_math.h" |
| 79 | #include "jasper/jas_debug.h" | ||
| 77 | 80 | ||
| 78 | /******************************************************************************\ | 81 | /******************************************************************************\ |
| 79 | * Constructors and destructors. | 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 | jas_matind_t i; | 103 | jas_matind_t i; |
| 101 | size_t size; | 104 | size_t size; |
| 102 | 105 | ||
| 106 | |||
| 103 | if (numrows < 0 || numcols < 0) { | 107 | if (numrows < 0 || numcols < 0) { |
| 104 | return NULL; | 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 | sizeof(jas_seqent_t)))) { | 136 | sizeof(jas_seqent_t)))) { |
| 133 | goto error; | 137 | goto error; |
| 134 | } | 138 | } |
| 135 | 139 | memset(matrix->data_, 0, matrix->datasize_ * sizeof(jas_seqent_t)); | |
| 136 | memset(matrix->data_, 0, | ||
| 137 | matrix->datasize_ * sizeof(jas_seqent_t)); | ||
| 138 | } | 140 | } |
| 139 | 141 | ||
| 140 | for (i = 0; i < numrows; ++i) { | 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 | jas_matind_t ystart, jas_matind_t xend, jas_matind_t yend) | 203 | jas_matind_t ystart, jas_matind_t xend, jas_matind_t yend) |
| 202 | { | 204 | { |
| 203 | if (xstart < s1->xstart_ || ystart < s1->ystart_ || | 205 | if (xstart < s1->xstart_ || ystart < s1->ystart_ || |
| 204 | xend > s1->xend_ || yend > s1->yend_) | 206 | xend > s1->xend_ || yend > s1->yend_) { |
| 205 | return -1; | 207 | return -1; |
| 206 | 208 | } | |
| 207 | return jas_matrix_bindsub(s, s1, ystart - s1->ystart_, xstart - s1->xstart_, | 209 | return jas_matrix_bindsub(s, s1, ystart - s1->ystart_, |
| 208 | yend - s1->ystart_ - 1, xend - s1->xstart_ - 1); | 210 | xstart - s1->xstart_, yend - s1->ystart_ - 1, xend - s1->xstart_ - 1); |
| 209 | } | 211 | } |
| 210 | 212 | ||
| 211 | int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, | 213 | int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, |
| @@ -71,12 +71,31 @@ · 70 unmodified lines | |||
| 71 | * Includes. | 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 | #include "jasper/jas_stream.h" | 83 | #include "jasper/jas_stream.h" |
| 75 | #include "jasper/jas_debug.h" | 84 | #include "jasper/jas_debug.h" |
| 76 | #include "jasper/jas_types.h" | 85 | #include "jasper/jas_types.h" |
| 77 | #include "jasper/jas_malloc.h" | 86 | #include "jasper/jas_malloc.h" |
| 78 | #include "jasper/jas_math.h" | 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 | * Local function prototypes. | 100 | * Local function prototypes. |
| 82 | \******************************************************************************/ | 101 | \******************************************************************************/ |
| @@ -87,13 +106,21 @@ static jas_stream_t *jas_stream_create(void); · 4 unmodified lines | |||
| 87 | static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf, | 106 | static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf, |
| 88 | int bufsize); | 107 | int bufsize); |
| 89 | 108 | ||
| 90 | static int mem_read(jas_stream_obj_t *obj, char *buf, unsigned cnt); | 109 | static ssize_t mem_read(jas_stream_obj_t *obj, char *buf, size_t cnt); |
| 91 | static int mem_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt); | 110 | static ssize_t mem_write(jas_stream_obj_t *obj, const char *buf, |
| 111 | size_t cnt); | ||
| 92 | static long mem_seek(jas_stream_obj_t *obj, long offset, int origin); | 112 | static long mem_seek(jas_stream_obj_t *obj, long offset, int origin); |
| 93 | static int mem_close(jas_stream_obj_t *obj); | 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); | 115 | static ssize_t sfile_read(jas_stream_obj_t *obj, char *buf, size_t cnt); |
| 96 | static int file_write(jas_stream_obj_t *obj, const char *buf, unsigned 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 | static long file_seek(jas_stream_obj_t *obj, long offset, int origin); | 124 | static long file_seek(jas_stream_obj_t *obj, long offset, int origin); |
| 98 | static int file_close(jas_stream_obj_t *obj); | 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 | file_close | 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 | static const jas_stream_ops_t jas_stream_memops = { | 145 | static const jas_stream_ops_t jas_stream_memops = { |
| 112 | mem_read, | 146 | mem_read, |
| 113 | mem_write, | 147 | mem_write, |
| @@ -142,17 +176,12 @@ static jas_stream_t *jas_stream_create() · 28 unmodified lines | |||
| 142 | return stream; | 176 | return stream; |
| 143 | } | 177 | } |
| 144 | 178 | ||
| 145 | /* | 179 | jas_stream_t *jas_stream_memopen(char *buf, size_t bufsize) |
| 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) | ||
| 151 | { | 180 | { |
| 152 | jas_stream_t *stream; | 181 | jas_stream_t *stream; |
| 153 | jas_stream_memobj_t *obj; | 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 | assert((buf && bufsize > 0) || (!buf)); | 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 | jas_stream_close(stream); | 230 | jas_stream_close(stream); |
| 202 | return 0; | 231 | return 0; |
| 203 | } | 232 | } |
| 204 | JAS_DBGLOG(100, ("jas_stream_memopen2 buffer buf=%p myalloc=%d\n", | 233 | JAS_LOGDEBUGF(100, "jas_stream_memopen buffer buf=%p myalloc=%d\n", |
| 205 | obj->buf_, obj->myalloc_)); | 234 | obj->buf_, obj->myalloc_); |
| 206 | 235 | ||
| 207 | if (bufsize > 0 && buf) { | 236 | if (bufsize > 0 && buf) { |
| 208 | /* If a buffer was supplied by the caller and its length is positive, | 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: | 250 | This function is deprecated. |
| 222 | The version of the function jas_stream_memopen only exists for backwards | 251 | It will be removed eventually. |
| 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). | ||
| 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; | 255 | jas_deprecated("jas_stream_memopen2 is deprecated\n"); |
| 240 | size_t new_bufsize; | 256 | return jas_stream_memopen(buf, 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 | } | 257 | } |
| 256 | 258 | ||
| 257 | jas_stream_t *jas_stream_fopen(const char *filename, const char *mode) | 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 | jas_stream_fileobj_t *obj; | 262 | jas_stream_fileobj_t *obj; |
| 261 | int openflags; | 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 | /* Allocate a stream object. */ | 267 | /* Allocate a stream object. */ |
| 266 | if (!(stream = jas_stream_create())) { | 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 | /* Determine the correct flags to use for opening the file. */ | 275 | /* Determine the correct flags to use for opening the file. */ |
| 274 | if ((stream->openmode_ & JAS_STREAM_READ) && | 276 | if ((stream->openmode_ & JAS_STREAM_READ) && |
| 275 | (stream->openmode_ & JAS_STREAM_WRITE)) { | 277 | (stream->openmode_ & JAS_STREAM_WRITE)) { |
| 276 | openflags = ORDWR; | 278 | openflags = O_RDWR; |
| 277 | } else if (stream->openmode_ & JAS_STREAM_READ) { | 279 | } else if (stream->openmode_ & JAS_STREAM_READ) { |
| 278 | openflags = OREAD; | 280 | openflags = O_RDONLY; |
| 279 | } else if (stream->openmode_ & JAS_STREAM_WRITE) { | 281 | } else if (stream->openmode_ & JAS_STREAM_WRITE) { |
| 280 | openflags = OWRITE; | 282 | openflags = O_WRONLY; |
| 281 | } else { | 283 | } else { |
| 282 | openflags = 0; | 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 | if (stream->openmode_ & JAS_STREAM_CREATE) { | 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 | /* Allocate space for the underlying file stream object. */ | 298 | /* Allocate space for the underlying file stream object. */ |
| 291 | if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) { | 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 | obj->fd = -1; | 303 | obj->fd = -1; |
| 296 | obj->flags = 0; | 304 | obj->flags = 0; |
| 305 | obj->pathname[0] = '\0'; | ||
| 297 | stream->obj_ = (void *) obj; | 306 | stream->obj_ = (void *) obj; |
| 298 | 307 | ||
| 299 | /* Select the operations for a file stream object. */ | 308 | /* Select the operations for a file stream object. */ |
| 300 | stream->ops_ = &jas_stream_fileops; | 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 | /* Open the underlying file. */ | 311 | /* Open the underlying file. */ |
| 309 | if (obj->fd < 0) { | 312 | if ((obj->fd = open(filename, openflags/*, JAS_STREAM_PERMS*/)) < 0) { |
| 310 | // Free the underlying file object, since it will not otherwise | 313 | // Free the underlying file object, since it will not otherwise |
| 311 | // be freed. | 314 | // be freed. |
| 312 | jas_free(obj); | 315 | jas_free(obj); |
| 313 | jas_stream_destroy(stream); | 316 | jas_stream_destroy(stream); |
| 314 | return 0; | 317 | return 0; |
| 315 | } | 318 | } |
| 316 | if (stream->openmode_ & JAS_STREAM_APPEND) { | 319 | |
| 317 | seek(obj->fd, 0, 2); | 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 | /* By default, use full buffering for this type of stream. */ | 347 | /* By default, use full buffering for this type of stream. */ |
| 321 | jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); | 348 | jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); |
| 322 | 349 | ||
| 323 | return stream; | 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 | jas_stream_t *jas_stream_fdopen(int fd, const char *mode) | 470 | jas_stream_t *jas_stream_fdopen(int fd, const char *mode) |
| 327 | { | 471 | { |
| 328 | jas_stream_t *stream; | 472 | jas_stream_t *stream; |
| 329 | jas_stream_fileobj_t *obj; | 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 | /* Allocate a stream object. */ | 477 | /* Allocate a stream object. */ |
| 334 | if (!(stream = jas_stream_create())) { | 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 | /* Parse the mode string. */ | 482 | /* Parse the mode string. */ |
| 339 | stream->openmode_ = jas_strtoopenmode(mode); | 483 | stream->openmode_ = jas_strtoopenmode(mode); |
| 340 | 484 | ||
| 341 | #if defined(WIN32) | 485 | #if defined(_WIN32) || defined(JAS_HAVE_IO_H) |
| 342 | /* Argh!!! Someone ought to banish text mode (i.e., O_TEXT) to the | 486 | /* Argh!!! Someone ought to banish text mode (i.e., O_TEXT) to the |
| 343 | greatest depths of purgatory! */ | 487 | greatest depths of purgatory! */ |
| 344 | /* Ensure that the file descriptor is in binary mode, if the caller | 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 | obj->fd = fd; | 507 | obj->fd = fd; |
| 364 | obj->flags = 0; | 508 | obj->flags = 0; |
| 509 | obj->pathname[0] = '\0'; | ||
| 365 | stream->obj_ = (void *) obj; | 510 | stream->obj_ = (void *) obj; |
| 366 | 511 | ||
| 367 | /* Do not close the underlying file descriptor when the stream is | 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 | static void jas_stream_destroy(jas_stream_t *stream) | 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 | /* If the memory for the buffer was allocated with malloc, free | 529 | /* If the memory for the buffer was allocated with malloc, free |
| 385 | this memory. */ | 530 | this memory. */ |
| 386 | if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) { | 531 | if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) { |
| 387 | JAS_DBGLOG(100, ("jas_stream_destroy freeing buffer %p\n", | 532 | JAS_LOGDEBUGF(100, "jas_stream_destroy freeing buffer %p\n", |
| 388 | stream->bufbase_)); | 533 | stream->bufbase_); |
| 389 | jas_free(stream->bufbase_); | 534 | jas_free(stream->bufbase_); |
| 390 | stream->bufbase_ = 0; | 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 | int jas_stream_close(jas_stream_t *stream) | 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 | /* Flush buffer if necessary. */ | 544 | /* Flush buffer if necessary. */ |
| 400 | jas_stream_flush(stream); | 545 | jas_stream_flush(stream); |
| @@ -451,16 +596,16 @@ int jas_stream_ungetc(jas_stream_t *stream, int c) · 50 unmodified lines | |||
| 451 | return 0; | 596 | return 0; |
| 452 | } | 597 | } |
| 453 | 598 | ||
| 454 | /* FIXME integral type */ | 599 | size_t jas_stream_read(jas_stream_t *stream, void *buf, size_t cnt) |
| 455 | unsigned jas_stream_read(jas_stream_t *stream, void *buf, unsigned cnt) | ||
| 456 | { | 600 | { |
| 457 | int c; | 601 | int c; |
| 458 | char *bufptr; | 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 | return 0; | 607 | return 0; |
| 608 | } | ||
| 464 | 609 | ||
| 465 | bufptr = buf; | 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 | jas_stream_is_input_buffer_empty(stream)) { | 613 | jas_stream_is_input_buffer_empty(stream)) { |
| 469 | /* fast path for unbuffered streams */ | 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 | return 0; | 617 | return 0; |
| 618 | } | ||
| 473 | 619 | ||
| 474 | if ((stream->openmode_ & JAS_STREAM_READ) == 0) | 620 | if ((stream->openmode_ & JAS_STREAM_READ) == 0) { |
| 475 | return 0; | 621 | return 0; |
| 622 | } | ||
| 476 | 623 | ||
| 477 | assert((stream->bufmode_ & JAS_STREAM_WRBUF) == 0); | 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 | return n; | 649 | return n; |
| 503 | } | 650 | } |
| 504 | 651 | ||
| 652 | /* TODO: The return type should probably be changed to size_t. */ | ||
| 505 | unsigned jas_stream_peek(jas_stream_t *stream, void *buf, size_t cnt) | 653 | unsigned jas_stream_peek(jas_stream_t *stream, void *buf, size_t cnt) |
| 506 | { | 654 | { |
| 507 | char *bufptr = buf; | 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 | /* Put the characters read back onto the stream. */ | 659 | /* Put the characters read back onto the stream. */ |
| 512 | for (unsigned i = n; i-- > 0;) | 660 | for (size_t i = n; i-- > 0;) { |
| 513 | if (jas_stream_ungetc(stream, bufptr[i]) == EOF) | 661 | if (jas_stream_ungetc(stream, bufptr[i]) == EOF) { |
| 514 | return 0; | 662 | return 0; |
| 663 | } | ||
| 664 | } | ||
| 515 | 665 | ||
| 516 | return n; | 666 | return n; |
| 517 | } | 667 | } |
| 518 | 668 | ||
| 519 | /* FIXME integral type */ | 669 | size_t jas_stream_write(jas_stream_t *stream, const void *buf, size_t cnt) |
| 520 | unsigned jas_stream_write(jas_stream_t *stream, const void *buf, unsigned cnt) | ||
| 521 | { | 670 | { |
| 522 | const char *bufptr; | 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 | return 0; | 676 | return 0; |
| 677 | } | ||
| 528 | 678 | ||
| 529 | bufptr = buf; | 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 | /* need to flush the output buffer before we do a raw | 684 | /* need to flush the output buffer before we do a raw |
| 535 | write */ | 685 | write */ |
| 536 | if (jas_stream_flushbuf(stream, EOF)) | 686 | if (jas_stream_flushbuf(stream, EOF)) { |
| 537 | return 0; | 687 | return 0; |
| 688 | } | ||
| 538 | 689 | ||
| 539 | stream->bufmode_ |= JAS_STREAM_WRBUF; | 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 | int ret; | 721 | int ret; |
| 571 | 722 | ||
| 572 | va_start(ap, fmt); | 723 | va_start(ap, fmt); |
| 573 | ret = vsnprint(buf, sizeof buf, fmt, ap); | 724 | ret = vsnprintf(buf, sizeof buf, fmt, ap); |
| 574 | jas_stream_puts(stream, buf); | 725 | jas_stream_puts(stream, buf); |
| 575 | va_end(ap); | 726 | va_end(ap); |
| 576 | return ret; | 727 | return ret; |
| @@ -595,7 +746,7 @@ char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize) · 18 unmodified lines | |||
| 595 | char *bufptr; | 746 | char *bufptr; |
| 596 | assert(bufsize > 0); | 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 | bufptr = buf; | 751 | bufptr = buf; |
| 601 | while (bufsize > 1) { | 752 | while (bufsize > 1) { |
| @@ -612,17 +763,10 @@ char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize) · 10 unmodified lines | |||
| 612 | return buf; | 763 | return buf; |
| 613 | } | 764 | } |
| 614 | 765 | ||
| 615 | /* FIXME integral type */ | 766 | ssize_t jas_stream_gobble(jas_stream_t *stream, size_t n) |
| 616 | int jas_stream_gobble(jas_stream_t *stream, int n) | ||
| 617 | { | 767 | { |
| 618 | int m; | 768 | size_t m; |
| 619 | 769 | JAS_LOGDEBUGF(100, "jas_stream_gobble(%p, %zu)\n", stream, n); | |
| 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 | } | ||
| 626 | for (m = n; m > 0; --m) { | 770 | for (m = n; m > 0; --m) { |
| 627 | if (jas_stream_getc(stream) == EOF) { | 771 | if (jas_stream_getc(stream) == EOF) { |
| 628 | return n - m; | 772 | return n - m; |
| @@ -631,20 +775,14 @@ int jas_stream_gobble(jas_stream_t *stream, int n) · 2 unmodified lines | |||
| 631 | return n; | 775 | return n; |
| 632 | } | 776 | } |
| 633 | 777 | ||
| 634 | /* FIXME integral type */ | 778 | ssize_t jas_stream_pad(jas_stream_t *stream, size_t n, int c) |
| 635 | int jas_stream_pad(jas_stream_t *stream, int n, int c) | ||
| 636 | { | 779 | { |
| 637 | int m; | 780 | size_t m; |
| 638 | 781 | JAS_LOGDEBUGF(100, "jas_stream_pad(%p, %zu, %d)\n", stream, n, c); | |
| 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 | } | ||
| 645 | for (m = n; m > 0; --m) { | 782 | for (m = n; m > 0; --m) { |
| 646 | if (jas_stream_putc(stream, c) == EOF) | 783 | if (jas_stream_putc(stream, c) == EOF) { |
| 647 | return n - m; | 784 | return n - m; |
| 785 | } | ||
| 648 | } | 786 | } |
| 649 | return n; | 787 | return n; |
| 650 | } | 788 | } |
| @@ -658,7 +796,7 @@ int jas_stream_isseekable(jas_stream_t *stream) · 7 unmodified lines | |||
| 658 | if (stream->ops_ == &jas_stream_memops) { | 796 | if (stream->ops_ == &jas_stream_memops) { |
| 659 | return 1; | 797 | return 1; |
| 660 | } else if (stream->ops_ == &jas_stream_fileops) { | 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 | return 0; | 800 | return 0; |
| 663 | } | 801 | } |
| 664 | return 1; | 802 | return 1; |
| @@ -669,16 +807,15 @@ int jas_stream_isseekable(jas_stream_t *stream) · 4 unmodified lines | |||
| 669 | 807 | ||
| 670 | int jas_stream_rewind(jas_stream_t *stream) | 808 | int jas_stream_rewind(jas_stream_t *stream) |
| 671 | { | 809 | { |
| 672 | JAS_DBGLOG(100, ("jas_stream_rewind(%p)\n", stream)); | 810 | JAS_LOGDEBUGF(100, "jas_stream_rewind(%p)\n", stream); |
| 673 | return jas_stream_seek(stream, 0, 0); | 811 | return jas_stream_seek(stream, 0, SEEK_SET); |
| 674 | } | 812 | } |
| 675 | 813 | ||
| 676 | long jas_stream_seek(jas_stream_t *stream, long offset, int origin) | 814 | long jas_stream_seek(jas_stream_t *stream, long offset, int origin) |
| 677 | { | 815 | { |
| 678 | long newpos; | 816 | long newpos; |
| 679 | 817 | ||
| 680 | JAS_DBGLOG(100, ("jas_stream_seek(%p, %ld, %d)\n", stream, offset, | 818 | JAS_LOGDEBUGF(100, "jas_stream_seek(%p, %ld, %d)\n", stream, offset, origin); |
| 681 | origin)); | ||
| 682 | 819 | ||
| 683 | /* The buffer cannot be in use for both reading and writing. */ | 820 | /* The buffer cannot be in use for both reading and writing. */ |
| 684 | assert(!((stream->bufmode_ & JAS_STREAM_RDBUF) && (stream->bufmode_ & | 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 | stream->flags_ &= ~JAS_STREAM_EOF; | 825 | stream->flags_ &= ~JAS_STREAM_EOF; |
| 689 | 826 | ||
| 690 | if (stream->bufmode_ & JAS_STREAM_RDBUF) { | 827 | if (stream->bufmode_ & JAS_STREAM_RDBUF) { |
| 691 | if (origin == 1) { | 828 | if (origin == SEEK_CUR) { |
| 692 | offset -= stream->cnt_; | 829 | offset -= stream->cnt_; |
| 693 | } | 830 | } |
| 694 | } else if (stream->bufmode_ & JAS_STREAM_WRBUF) { | 831 | } else if (stream->bufmode_ & JAS_STREAM_WRBUF) { |
| @@ -713,7 +850,7 @@ long jas_stream_tell(jas_stream_t *stream) · 18 unmodified lines | |||
| 713 | int adjust; | 850 | int adjust; |
| 714 | int offset; | 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 | if (stream->bufmode_ & JAS_STREAM_RDBUF) { | 855 | if (stream->bufmode_ & JAS_STREAM_RDBUF) { |
| 719 | adjust = -stream->cnt_; | 856 | adjust = -stream->cnt_; |
| @@ -723,7 +860,7 @@ long jas_stream_tell(jas_stream_t *stream) · 3 unmodified lines | |||
| 723 | adjust = 0; | 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 | return -1; | 864 | return -1; |
| 728 | } | 865 | } |
| 729 | 866 | ||
| @@ -910,10 +1047,9 @@ static int jas_strtoopenmode(const char *s) · 180 unmodified lines | |||
| 910 | return openmode; | 1047 | return openmode; |
| 911 | } | 1048 | } |
| 912 | 1049 | ||
| 913 | /* FIXME integral type */ | 1050 | int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, ssize_t n) |
| 914 | int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n) | ||
| 915 | { | 1051 | { |
| 916 | int m; | 1052 | ssize_t m; |
| 917 | 1053 | ||
| 918 | const bool all = n < 0; | 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 | m = n; | 1058 | m = n; |
| 923 | while (all || m > 0) { | 1059 | while (all || m > 0) { |
| 924 | unsigned nbytes = jas_stream_read(in, buffer, | 1060 | size_t nbytes = jas_stream_read(in, buffer, |
| 925 | JAS_MIN((size_t)m, sizeof(buffer))); | 1061 | JAS_MIN((size_t)m, sizeof(buffer))); |
| 926 | if (nbytes == 0) | 1062 | if (nbytes == 0) { |
| 927 | return !all || jas_stream_error(in) ? -1 : 0; | 1063 | return !all || jas_stream_error(in) ? -1 : 0; |
| 928 | 1064 | } | |
| 929 | if (jas_stream_write(out, buffer, nbytes) != nbytes) | 1065 | if (jas_stream_write(out, buffer, nbytes) != nbytes) { |
| 930 | return -1; | 1066 | return -1; |
| 931 | 1067 | } | |
| 932 | m -= nbytes; | 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 | return old; | 1081 | return old; |
| 946 | } | 1082 | } |
| 947 | 1083 | ||
| 948 | JAS_DLLEXPORT | 1084 | JAS_EXPORT |
| 949 | long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit) | 1085 | long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit) |
| 950 | { | 1086 | { |
| 951 | long old; | 1087 | long old; |
| @@ -955,6 +1091,57 @@ long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit) · 3 unmodified lines | |||
| 955 | return old; | 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 | long jas_stream_length(jas_stream_t *stream) | 1145 | long jas_stream_length(jas_stream_t *stream) |
| 959 | { | 1146 | { |
| 960 | long oldpos; | 1147 | long oldpos; |
| @@ -962,13 +1149,13 @@ long jas_stream_length(jas_stream_t *stream) · 1 unmodified line | |||
| 962 | if ((oldpos = jas_stream_tell(stream)) < 0) { | 1149 | if ((oldpos = jas_stream_tell(stream)) < 0) { |
| 963 | return -1; | 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 | return -1; | 1153 | return -1; |
| 967 | } | 1154 | } |
| 968 | if ((pos = jas_stream_tell(stream)) < 0) { | 1155 | if ((pos = jas_stream_tell(stream)) < 0) { |
| 969 | return -1; | 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 | return -1; | 1159 | return -1; |
| 973 | } | 1160 | } |
| 974 | return pos; | 1161 | return pos; |
| @@ -978,13 +1165,12 @@ long jas_stream_length(jas_stream_t *stream) · 3 unmodified lines | |||
| 978 | * Memory stream object. | 1165 | * Memory stream object. |
| 979 | \******************************************************************************/ | 1166 | \******************************************************************************/ |
| 980 | 1167 | ||
| 981 | /* FIXME integral type */ | 1168 | static ssize_t mem_read(jas_stream_obj_t *obj, char *buf, size_t cnt) |
| 982 | static int mem_read(jas_stream_obj_t *obj, char *buf, unsigned cnt) | ||
| 983 | { | 1169 | { |
| 984 | jas_stream_memobj_t *m; | 1170 | jas_stream_memobj_t *m; |
| 985 | assert(buf); | 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 | m = (jas_stream_memobj_t *)obj; | 1174 | m = (jas_stream_memobj_t *)obj; |
| 989 | size_t n = m->len_ - m->pos_; | 1175 | size_t n = m->len_ - m->pos_; |
| 990 | cnt = JAS_MIN(n, cnt); | 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 | unsigned char *buf; | 1184 | unsigned char *buf; |
| 999 | 1185 | ||
| 1000 | //assert(m->buf_); | 1186 | JAS_LOGDEBUGF(100, "mem_resize(%p, %zu)\n", m, bufsize); |
| 1001 | |||
| 1002 | JAS_DBGLOG(100, ("mem_resize(%p, %zu)\n", m, bufsize)); | ||
| 1003 | if (!bufsize) { | 1187 | if (!bufsize) { |
| 1004 | jas_eprintf( | 1188 | jas_logerrorf( |
| 1005 | "mem_resize was not really designed to handle a buffer of size 0\n" | 1189 | "mem_resize was not really designed to handle a buffer of size 0\n" |
| 1006 | "This may not work.\n" | 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 | if (!(buf = jas_realloc2(m->buf_, bufsize, sizeof(unsigned char))) && | 1194 | if (!(buf = jas_realloc2(m->buf_, bufsize, sizeof(unsigned char))) && |
| 1011 | bufsize) { | 1195 | bufsize) { |
| 1012 | JAS_DBGLOG(100, ("mem_resize realloc failed\n")); | 1196 | JAS_LOGDEBUGF(100, "mem_resize realloc failed\n"); |
| 1013 | return -1; | 1197 | return -1; |
| 1014 | } | 1198 | } |
| 1015 | JAS_DBGLOG(100, ("mem_resize realloc succeeded\n")); | 1199 | JAS_LOGDEBUGF(100, "mem_resize realloc succeeded\n"); |
| 1016 | m->buf_ = buf; | 1200 | m->buf_ = buf; |
| 1017 | m->bufsize_ = bufsize; | 1201 | m->bufsize_ = bufsize; |
| 1018 | return 0; | 1202 | return 0; |
| 1019 | } | 1203 | } |
| 1020 | 1204 | ||
| 1021 | /* FIXME integral type */ | 1205 | static ssize_t mem_write(jas_stream_obj_t *obj, const char *buf, |
| 1022 | static int mem_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt) | 1206 | size_t cnt) |
| 1023 | { | 1207 | { |
| 1024 | size_t n; | 1208 | size_t n; |
| 1025 | jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; | 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 | assert(buf); | 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 | newpos = m->pos_ + cnt; | 1216 | newpos = m->pos_ + cnt; |
| 1033 | if (newpos > m->bufsize_ && m->growable_) { | 1217 | if (newpos > m->bufsize_ && m->growable_) { |
| 1034 | newbufsize = m->bufsize_; | 1218 | newbufsize = m->bufsize_; |
| 1035 | while (newbufsize < newpos) { | 1219 | while (newbufsize < newpos) { |
| 1036 | //newbufsize <<= 1; | 1220 | /* Attempt to double the buffer size. */ |
| 1037 | if (!jas_safe_size_mul(newbufsize, 2, &newbufsize)) { | 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 | return -1; | 1223 | return -1; |
| 1040 | } | 1224 | } |
| 1041 | } | 1225 | } |
| 1042 | JAS_DBGLOG(100, ("mem_write resizing from %d to %zu\n", m->bufsize_, | 1226 | JAS_LOGDEBUGF(100, "mem_write resizing from %d to %zu\n", m->bufsize_, |
| 1043 | newbufsize)); | 1227 | newbufsize); |
| 1044 | assert(newbufsize > 0); | 1228 | assert(newbufsize > 0); |
| 1045 | if (mem_resize(m, newbufsize)) { | 1229 | if (mem_resize(m, newbufsize)) { |
| 1046 | return -1; | 1230 | return -1; |
| @@ -1078,15 +1262,15 @@ static long mem_seek(jas_stream_obj_t *obj, long offset, int origin) · 31 unmodified lines | |||
| 1078 | jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; | 1262 | jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; |
| 1079 | long newpos; | 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 | switch (origin) { | 1266 | switch (origin) { |
| 1083 | case 0: | 1267 | case SEEK_SET: |
| 1084 | newpos = offset; | 1268 | newpos = offset; |
| 1085 | break; | 1269 | break; |
| 1086 | case 2: | 1270 | case SEEK_END: |
| 1087 | newpos = m->len_ - offset; | 1271 | newpos = m->len_ - offset; |
| 1088 | break; | 1272 | break; |
| 1089 | case 1: | 1273 | case SEEK_CUR: |
| 1090 | newpos = m->pos_ + offset; | 1274 | newpos = m->pos_ + offset; |
| 1091 | break; | 1275 | break; |
| 1092 | default: | 1276 | default: |
| @@ -1104,11 +1288,11 @@ static int mem_close(jas_stream_obj_t *obj) · 11 unmodified lines | |||
| 1104 | { | 1288 | { |
| 1105 | jas_stream_memobj_t *m; | 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 | m = (jas_stream_memobj_t *)obj; | 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 | if (m->myalloc_ && m->buf_) { | 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 | jas_free(m->buf_); | 1296 | jas_free(m->buf_); |
| 1113 | m->buf_ = 0; | 1297 | m->buf_ = 0; |
| 1114 | } | 1298 | } |
| @@ -1120,20 +1304,19 @@ static int mem_close(jas_stream_obj_t *obj) · 5 unmodified lines | |||
| 1120 | * File stream object. | 1304 | * File stream object. |
| 1121 | \******************************************************************************/ | 1305 | \******************************************************************************/ |
| 1122 | 1306 | ||
| 1123 | /* FIXME integral type */ | 1307 | static ssize_t file_read(jas_stream_obj_t *obj, char *buf, size_t cnt) |
| 1124 | static int file_read(jas_stream_obj_t *obj, char *buf, unsigned cnt) | ||
| 1125 | { | 1308 | { |
| 1126 | jas_stream_fileobj_t *fileobj; | 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 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); | 1311 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); |
| 1129 | return read(fileobj->fd, buf, cnt); | 1312 | return read(fileobj->fd, buf, cnt); |
| 1130 | } | 1313 | } |
| 1131 | 1314 | ||
| 1132 | /* FIXME integral type */ | 1315 | static ssize_t file_write(jas_stream_obj_t *obj, const char *buf, |
| 1133 | static int file_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt) | 1316 | size_t cnt) |
| 1134 | { | 1317 | { |
| 1135 | jas_stream_fileobj_t *fileobj; | 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 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); | 1320 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); |
| 1138 | return write(fileobj->fd, buf, cnt); | 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 | static long file_seek(jas_stream_obj_t *obj, long offset, int origin) | 1325 | static long file_seek(jas_stream_obj_t *obj, long offset, int origin) |
| 1143 | { | 1326 | { |
| 1144 | jas_stream_fileobj_t *fileobj; | 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 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); | 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 | static int file_close(jas_stream_obj_t *obj) | 1333 | static int file_close(jas_stream_obj_t *obj) |
| 1151 | { | 1334 | { |
| 1152 | int ret; | 1335 | int ret = 0; |
| 1153 | jas_stream_fileobj_t *fileobj; | 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 | fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); | 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 | jas_free(fileobj); | 1345 | jas_free(fileobj); |
| 1158 | return ret; | 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 | #ifndef JAS_CM_H | 67 | #ifndef JAS_CM_H |
| 68 | #define JAS_CM_H | 68 | #define JAS_CM_H |
| 69 | 69 | ||
| 70 | /******************************************************************************\ | ||
| 71 | * | ||
| 72 | \******************************************************************************/ | ||
| 73 | |||
| 70 | /* The configuration header file should be included first. */ | 74 | /* The configuration header file should be included first. */ |
| 71 | #include <jasper/jas_config.h> | 75 | #include <jasper/jas_config.h> |
| 72 | 76 | ||
| 77 | #include <jasper/jas_types.h> | ||
| 73 | #include <jasper/jas_icc.h> | 78 | #include <jasper/jas_icc.h> |
| 74 | 79 | ||
| 75 | #ifdef __cplusplus | 80 | #ifdef __cplusplus |
| 76 | extern "C" { | 81 | extern "C" { |
| 77 | #endif | 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 | typedef unsigned jas_clrspc_t; | 97 | typedef unsigned jas_clrspc_t; |
| 80 | 98 | ||
| 81 | /* transform operations */ | 99 | /*! |
| 100 | @brief | ||
| 101 | Transform operations | ||
| 102 | */ | ||
| 82 | typedef enum { | 103 | typedef enum { |
| 83 | JAS_CMXFORM_OP_FWD = 0, | 104 | JAS_CMXFORM_OP_FWD = 0, |
| 84 | JAS_CMXFORM_OP_REV = 1, | 105 | JAS_CMXFORM_OP_REV = 1, |
| @@ -86,7 +107,10 @@ typedef enum { · 1 unmodified line | |||
| 86 | JAS_CMXFORM_OP_GAMUT = 3, | 107 | JAS_CMXFORM_OP_GAMUT = 3, |
| 87 | } jas_cmxform_op_t; | 108 | } jas_cmxform_op_t; |
| 88 | 109 | ||
| 89 | /* rendering intents */ | 110 | /*! |
| 111 | @brief | ||
| 112 | Rendering intents. | ||
| 113 | */ | ||
| 90 | typedef enum { | 114 | typedef enum { |
| 91 | JAS_CMXFORM_INTENT_PER = 0, | 115 | JAS_CMXFORM_INTENT_PER = 0, |
| 92 | JAS_CMXFORM_INTENT_RELCLR = 1, | 116 | JAS_CMXFORM_INTENT_RELCLR = 1, |
| @@ -94,24 +118,58 @@ typedef enum { · 1 unmodified line | |||
| 94 | JAS_CMXFORM_INTENT_SAT = 3, | 118 | JAS_CMXFORM_INTENT_SAT = 3, |
| 95 | } jas_cmxform_intent_t; | 119 | } jas_cmxform_intent_t; |
| 96 | 120 | ||
| 121 | /*! | ||
| 122 | @brief | ||
| 123 | Number of rendering intents. | ||
| 124 | */ | ||
| 97 | #define JAS_CMXFORM_NUMINTENTS 4 | 125 | #define JAS_CMXFORM_NUMINTENTS 4 |
| 98 | 126 | ||
| 127 | /*! | ||
| 128 | @brief | ||
| 129 | Transform optimization. | ||
| 130 | */ | ||
| 99 | typedef enum { | 131 | typedef enum { |
| 100 | JAS_CMXFORM_OPTM_SPEED = 0, | 132 | JAS_CMXFORM_OPTM_SPEED = 0, |
| 101 | JAS_CMXFORM_OPTM_SIZE = 1, | 133 | JAS_CMXFORM_OPTM_SIZE = 1, |
| 102 | JAS_CMXFORM_OPTM_ACC = 2, | 134 | JAS_CMXFORM_OPTM_ACC = 2, |
| 103 | } jas_cmxform_optm_t; | 135 | } jas_cmxform_optm_t; |
| 104 | 136 | ||
| 105 | 137 | /*! | |
| 138 | @brief | ||
| 139 | Create a color space. | ||
| 140 | */ | ||
| 106 | #define jas_clrspc_create(fam, mbr) (((fam) << 8) | (mbr)) | 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 | #define jas_clrspc_fam(clrspc) ((clrspc) >> 8) | 148 | #define jas_clrspc_fam(clrspc) ((clrspc) >> 8) |
| 149 | |||
| 150 | /*! | ||
| 151 | @brief | ||
| 152 | Get the (family) member of a color space. | ||
| 153 | */ | ||
| 108 | #define jas_clrspc_mbr(clrspc) ((clrspc) & 0xff) | 154 | #define jas_clrspc_mbr(clrspc) ((clrspc) & 0xff) |
| 155 | |||
| 156 | /*! | ||
| 157 | @brief | ||
| 158 | Test if a color space is generic. | ||
| 159 | */ | ||
| 109 | #define jas_clrspc_isgeneric(clrspc) (!jas_clrspc_mbr(clrspc)) | 160 | #define jas_clrspc_isgeneric(clrspc) (!jas_clrspc_mbr(clrspc)) |
| 161 | |||
| 162 | /*! | ||
| 163 | @brief | ||
| 164 | Test if a color space is unknown. | ||
| 165 | */ | ||
| 110 | #define jas_clrspc_isunknown(clrspc) ((clrspc) & JAS_CLRSPC_UNKNOWNMASK) | 166 | #define jas_clrspc_isunknown(clrspc) ((clrspc) & JAS_CLRSPC_UNKNOWNMASK) |
| 111 | 167 | ||
| 112 | #define JAS_CLRSPC_UNKNOWNMASK 0x4000 | 168 | #define JAS_CLRSPC_UNKNOWNMASK 0x4000 |
| 113 | 169 | ||
| 114 | /* color space families */ | 170 | /*! |
| 171 | @brief Color space families. | ||
| 172 | */ | ||
| 115 | #define JAS_CLRSPC_FAM_UNKNOWN 0 | 173 | #define JAS_CLRSPC_FAM_UNKNOWN 0 |
| 116 | #define JAS_CLRSPC_FAM_XYZ 1 | 174 | #define JAS_CLRSPC_FAM_XYZ 1 |
| 117 | #define JAS_CLRSPC_FAM_LAB 2 | 175 | #define JAS_CLRSPC_FAM_LAB 2 |
| @@ -119,7 +177,9 @@ typedef enum { · 1 unmodified line | |||
| 119 | #define JAS_CLRSPC_FAM_RGB 4 | 177 | #define JAS_CLRSPC_FAM_RGB 4 |
| 120 | #define JAS_CLRSPC_FAM_YCBCR 5 | 178 | #define JAS_CLRSPC_FAM_YCBCR 5 |
| 121 | 179 | ||
| 122 | /* specific color spaces */ | 180 | /*! |
| 181 | @brief Specific color spaces. | ||
| 182 | */ | ||
| 123 | #define JAS_CLRSPC_UNKNOWN JAS_CLRSPC_UNKNOWNMASK | 183 | #define JAS_CLRSPC_UNKNOWN JAS_CLRSPC_UNKNOWNMASK |
| 124 | #define JAS_CLRSPC_CIEXYZ jas_clrspc_create(JAS_CLRSPC_FAM_XYZ, 1) | 184 | #define JAS_CLRSPC_CIEXYZ jas_clrspc_create(JAS_CLRSPC_FAM_XYZ, 1) |
| 125 | #define JAS_CLRSPC_CIELAB jas_clrspc_create(JAS_CLRSPC_FAM_LAB, 1) | 185 | #define JAS_CLRSPC_CIELAB jas_clrspc_create(JAS_CLRSPC_FAM_LAB, 1) |
| @@ -127,7 +187,9 @@ typedef enum { · 1 unmodified line | |||
| 127 | #define JAS_CLRSPC_SRGB jas_clrspc_create(JAS_CLRSPC_FAM_RGB, 1) | 187 | #define JAS_CLRSPC_SRGB jas_clrspc_create(JAS_CLRSPC_FAM_RGB, 1) |
| 128 | #define JAS_CLRSPC_SYCBCR jas_clrspc_create(JAS_CLRSPC_FAM_YCBCR, 1) | 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 | #define JAS_CLRSPC_GENRGB jas_clrspc_create(JAS_CLRSPC_FAM_RGB, 0) | 193 | #define JAS_CLRSPC_GENRGB jas_clrspc_create(JAS_CLRSPC_FAM_RGB, 0) |
| 132 | #define JAS_CLRSPC_GENGRAY jas_clrspc_create(JAS_CLRSPC_FAM_GRAY, 0) | 194 | #define JAS_CLRSPC_GENGRAY jas_clrspc_create(JAS_CLRSPC_FAM_GRAY, 0) |
| 133 | #define JAS_CLRSPC_GENYCBCR jas_clrspc_create(JAS_CLRSPC_FAM_YCBCR, 0) | 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 | #define JAS_CLRSPC_CHANIND_GRAY_Y 0 | 205 | #define JAS_CLRSPC_CHANIND_GRAY_Y 0 |
| 144 | 206 | ||
| 207 | /*! | ||
| 208 | Real-number type. | ||
| 209 | */ | ||
| 145 | typedef double jas_cmreal_t; | 210 | typedef double jas_cmreal_t; |
| 146 | 211 | ||
| 147 | struct jas_cmpxform_s; | 212 | struct jas_cmpxform_s; |
| 148 | 213 | ||
| 214 | /*! | ||
| 215 | @brief | ||
| 216 | Component format. | ||
| 217 | */ | ||
| 149 | typedef struct { | 218 | typedef struct { |
| 150 | long *buf; | 219 | long *buf; |
| 151 | unsigned prec; | 220 | unsigned prec; |
| @@ -154,21 +223,38 @@ typedef struct { · 2 unmodified lines | |||
| 154 | unsigned height; | 223 | unsigned height; |
| 155 | } jas_cmcmptfmt_t; | 224 | } jas_cmcmptfmt_t; |
| 156 | 225 | ||
| 226 | /*! | ||
| 227 | @brief | ||
| 228 | Pixmap (i.e., multicomponent) format. | ||
| 229 | */ | ||
| 157 | typedef struct { | 230 | typedef struct { |
| 158 | unsigned numcmpts; | 231 | unsigned numcmpts; |
| 159 | jas_cmcmptfmt_t *cmptfmts; | 232 | jas_cmcmptfmt_t *cmptfmts; |
| 160 | } jas_cmpixmap_t; | 233 | } jas_cmpixmap_t; |
| 161 | 234 | ||
| 235 | /*! | ||
| 236 | @brief | ||
| 237 | Transform operations. | ||
| 238 | */ | ||
| 162 | typedef struct { | 239 | typedef struct { |
| 163 | void (*destroy)(struct jas_cmpxform_s *pxform); | 240 | void (*destroy)(struct jas_cmpxform_s *pxform); |
| 164 | int (*apply)(const struct jas_cmpxform_s *pxform, const jas_cmreal_t *in, jas_cmreal_t *out, unsigned cnt); | 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 | } jas_cmpxformops_t; | 243 | } jas_cmpxformops_t; |
| 166 | 244 | ||
| 245 | /*! | ||
| 246 | @brief | ||
| 247 | Shaper matrix look-up table (LUT). | ||
| 248 | */ | ||
| 167 | typedef struct { | 249 | typedef struct { |
| 168 | jas_cmreal_t *data; | 250 | jas_cmreal_t *data; |
| 169 | unsigned size; | 251 | unsigned size; |
| 170 | } jas_cmshapmatlut_t; | 252 | } jas_cmshapmatlut_t; |
| 171 | 253 | ||
| 254 | /*! | ||
| 255 | @brief | ||
| 256 | Shaper matrix. | ||
| 257 | */ | ||
| 172 | typedef struct { | 258 | typedef struct { |
| 173 | int mono; | 259 | int mono; |
| 174 | int order; | 260 | int order; |
| @@ -178,36 +264,54 @@ typedef struct { · 3 unmodified lines | |||
| 178 | jas_cmreal_t mat[3][4]; | 264 | jas_cmreal_t mat[3][4]; |
| 179 | } jas_cmshapmat_t; | 265 | } jas_cmshapmat_t; |
| 180 | 266 | ||
| 267 | /*! | ||
| 268 | @brief | ||
| 269 | Shaper look-up table (LUT). | ||
| 270 | */ | ||
| 181 | typedef struct { | 271 | typedef struct { |
| 182 | int order; | 272 | int order; |
| 183 | } jas_cmshaplut_t; | 273 | } jas_cmshaplut_t; |
| 184 | 274 | ||
| 275 | /*! | ||
| 276 | @brief | ||
| 277 | Color space conversion. | ||
| 278 | */ | ||
| 185 | typedef struct { | 279 | typedef struct { |
| 186 | unsigned inclrspc; | 280 | unsigned inclrspc; |
| 187 | unsigned outclrspc; | 281 | unsigned outclrspc; |
| 188 | } jas_cmclrspcconv_t; | 282 | } jas_cmclrspcconv_t; |
| 189 | 283 | ||
| 190 | #define jas_align_t double | 284 | /*! |
| 191 | 285 | @brief | |
| 286 | Transform class. | ||
| 287 | */ | ||
| 192 | typedef struct jas_cmpxform_s { | 288 | typedef struct jas_cmpxform_s { |
| 193 | unsigned refcnt; | 289 | unsigned refcnt; |
| 194 | const jas_cmpxformops_t *ops; | 290 | const jas_cmpxformops_t *ops; |
| 195 | unsigned numinchans; | 291 | unsigned numinchans; |
| 196 | unsigned numoutchans; | 292 | unsigned numoutchans; |
| 197 | union { | 293 | union { |
| 198 | jas_align_t dummy; | 294 | max_align_t dummy; |
| 199 | jas_cmshapmat_t shapmat; | 295 | jas_cmshapmat_t shapmat; |
| 200 | jas_cmshaplut_t shaplut; | 296 | jas_cmshaplut_t shaplut; |
| 201 | jas_cmclrspcconv_t clrspcconv; | 297 | jas_cmclrspcconv_t clrspcconv; |
| 202 | } data; | 298 | } data; |
| 203 | } jas_cmpxform_t; | 299 | } jas_cmpxform_t; |
| 204 | 300 | ||
| 301 | /*! | ||
| 302 | @brief | ||
| 303 | Primitive transform sequence class. | ||
| 304 | */ | ||
| 205 | typedef struct { | 305 | typedef struct { |
| 206 | unsigned numpxforms; | 306 | unsigned numpxforms; |
| 207 | unsigned maxpxforms; | 307 | unsigned maxpxforms; |
| 208 | jas_cmpxform_t **pxforms; | 308 | jas_cmpxform_t **pxforms; |
| 209 | } jas_cmpxformseq_t; | 309 | } jas_cmpxformseq_t; |
| 210 | 310 | ||
| 311 | /*! | ||
| 312 | @brief | ||
| 313 | Primitive transform class. | ||
| 314 | */ | ||
| 211 | typedef struct { | 315 | typedef struct { |
| 212 | unsigned numinchans; | 316 | unsigned numinchans; |
| 213 | unsigned numoutchans; | 317 | unsigned numoutchans; |
| @@ -219,6 +323,9 @@ typedef struct { · 5 unmodified lines | |||
| 219 | 323 | ||
| 220 | #define JAS_CMPROF_NUMPXFORMSEQS 13 | 324 | #define JAS_CMPROF_NUMPXFORMSEQS 13 |
| 221 | 325 | ||
| 326 | /*! | ||
| 327 | Color-management (CM) profile. | ||
| 328 | */ | ||
| 222 | typedef struct { | 329 | typedef struct { |
| 223 | jas_clrspc_t clrspc; | 330 | jas_clrspc_t clrspc; |
| 224 | unsigned numchans; | 331 | unsigned numchans; |
| @@ -228,6 +335,10 @@ typedef struct { · 3 unmodified lines | |||
| 228 | jas_cmpxformseq_t *pxformseqs[JAS_CMPROF_NUMPXFORMSEQS]; | 335 | jas_cmpxformseq_t *pxformseqs[JAS_CMPROF_NUMPXFORMSEQS]; |
| 229 | } jas_cmprof_t; | 336 | } jas_cmprof_t; |
| 230 | 337 | ||
| 338 | /******************************************************************************\ | ||
| 339 | * | ||
| 340 | \******************************************************************************/ | ||
| 341 | |||
| 231 | #if 0 | 342 | #if 0 |
| 232 | typedef int_fast32_t jas_cmattrname_t; | 343 | typedef int_fast32_t jas_cmattrname_t; |
| 233 | typedef int_fast32_t jas_cmattrval_t; | 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 | void *jas_cm_prof_getattr(jas_cm_prof_t *prof, jas_cm_attrname_t name); | 353 | void *jas_cm_prof_getattr(jas_cm_prof_t *prof, jas_cm_attrname_t name); |
| 243 | #endif | 354 | #endif |
| 244 | 355 | ||
| 245 | JAS_DLLEXPORT jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof, const jas_cmprof_t *outprof, | 356 | /******************************************************************************\ |
| 246 | const jas_cmprof_t *proofprof, jas_cmxform_op_t op, jas_cmxform_intent_t intent, jas_cmxform_optm_t optimize); | 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. */ | 428 | /*! |
| 251 | JAS_DLLEXPORT int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, | 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 | jas_cmpixmap_t *out); | 465 | jas_cmpixmap_t *out); |
| 253 | 466 | ||
| 254 | /* Create a profile. */ | 467 | /******************************************************************************\ |
| 255 | JAS_DLLEXPORT jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof); | 468 | * Miscellany. |
| 256 | JAS_DLLEXPORT jas_cmprof_t *jas_cmprof_createfromclrspc(jas_clrspc_t clrspc); | 469 | \******************************************************************************/ |
| 470 | |||
| 471 | /*! | ||
| 472 | @brief | ||
| 473 | Get the number of channels associated with a particular color space. | ||
| 257 | 474 | ||
| 258 | /* Destroy a profile. */ | 475 | @details |
| 259 | JAS_DLLEXPORT void jas_cmprof_destroy(jas_cmprof_t *prof); | ||
| 260 | 476 | ||
| 477 | @returns | ||
| 478 | */ | ||
| 261 | unsigned jas_clrspc_numchans(jas_clrspc_t clrspc); | 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 | #define jas_cmprof_clrspc(prof) ((prof)->clrspc) | 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 | #ifdef __cplusplus | 495 | #ifdef __cplusplus |
| 268 | } | 496 | } |
| @@ -66,38 +66,82 @@ · 65 unmodified lines | |||
| 66 | #include <jasper/jas_config.h> | 66 | #include <jasper/jas_config.h> |
| 67 | 67 | ||
| 68 | #ifdef _MSC_VER | 68 | #ifdef _MSC_VER |
| 69 | #ifndef __cplusplus | 69 | # ifndef __cplusplus |
| 70 | #undef inline | 70 | # undef inline |
| 71 | #define inline __inline | 71 | # define inline __inline |
| 72 | # endif | ||
| 72 | #endif | 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 | #endif | 97 | #endif |
| 74 | 98 | ||
| 75 | #ifdef __GNUC__ | 99 | #if defined(__GNUC__) |
| 76 | #define JAS_DEPRECATED __attribute__((deprecated)) | 100 | # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) |
| 77 | #define JAS_ATTRIBUTE_CONST __attribute__((const)) | 101 | # define JAS_UNREACHABLE() __builtin_unreachable() |
| 78 | #define JAS_ATTRIBUTE_PURE __attribute__((pure)) | 102 | # else |
| 79 | #define JAS_FORCE_INLINE inline __attribute__((always_inline)) | 103 | # define JAS_UNREACHABLE() |
| 80 | #define JAS_UNREACHABLE() __builtin_unreachable() | 104 | # endif |
| 81 | #define JAS_LIKELY(x) __builtin_expect (!!(x), 1) | 105 | #elif defined(__clang__) |
| 82 | #define JAS_UNLIKELY(x) __builtin_expect (!!(x), 0) | 106 | # define JAS_UNREACHABLE() __builtin_unreachable() |
| 107 | #elif defined(_MSC_VER) | ||
| 108 | # define JAS_UNREACHABLE() __assume(0) | ||
| 83 | #else | 109 | #else |
| 84 | #define JAS_DEPRECATED | 110 | # define JAS_UNREACHABLE() |
| 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) | ||
| 91 | #endif | 111 | #endif |
| 92 | 112 | ||
| 93 | #ifdef __clang__ | 113 | #if defined(__GNUC__) |
| 94 | #define JAS_ATTRIBUTE_DISABLE_USAN \ | 114 | # define JAS_LIKELY(x) __builtin_expect (!!(x), 1) |
| 95 | __attribute__((no_sanitize("undefined"))) | ||
| 96 | #elif defined(__GNUC__) && __GNUC__ >= 6 | ||
| 97 | #define JAS_ATTRIBUTE_DISABLE_USAN \ | ||
| 98 | __attribute__((no_sanitize_undefined)) | ||
| 99 | #else | 115 | #else |
| 100 | #define JAS_ATTRIBUTE_DISABLE_USAN | 116 | # define JAS_LIKELY(x) (x) |
| 101 | #endif | 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 | #endif | 147 | #endif |
| @@ -4,17 +4,87 @@ · 3 unmodified lines | |||
| 4 | #include <u.h> | 4 | #include <u.h> |
| 5 | #include <libc.h> | 5 | #include <libc.h> |
| 6 | #include <ctype.h> | 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 | #include <jasper/jas_compiler.h> | 73 | #include <jasper/jas_compiler.h> |
| 8 | #include <jasper/jas_dll.h> | 74 | #include <jasper/jas_dll.h> |
| 9 | 75 | ||
| 10 | #define JAS_VERSION "plan9" | 76 | #define JAS_VERSION "plan9" |
| 77 | #define JAS_DEFAULT_MAX_MEM_USAGE (512*1024*1024) | ||
| 11 | #define JAS_ENABLE_32BIT 1 | 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 | #define JAS_INCLUDE_JPC_CODEC 1 | 81 | #define JAS_INCLUDE_JPC_CODEC 1 |
| 82 | #define JAS_INCLUDE_JP2_CODEC 1 | ||
| 14 | #define JAS_DEC_DEFAULT_MAX_SAMPLES (64 * ((size_t) 1048576)) | 83 | #define JAS_DEC_DEFAULT_MAX_SAMPLES (64 * ((size_t) 1048576)) |
| 15 | #define NDEBUG | 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 | #endif | 90 | #endif |
| @@ -74,6 +74,9 @@ · 73 unmodified lines | |||
| 74 | /* The configuration header file should be included first. */ | 74 | /* The configuration header file should be included first. */ |
| 75 | #include <jasper/jas_config.h> | 75 | #include <jasper/jas_config.h> |
| 76 | 76 | ||
| 77 | #include "jasper/jas_init.h" | ||
| 78 | #include "jasper/jas_debug.h" | ||
| 79 | |||
| 77 | #ifdef __cplusplus | 80 | #ifdef __cplusplus |
| 78 | extern "C" { | 81 | extern "C" { |
| 79 | #endif | 82 | #endif |
| @@ -86,25 +89,112 @@ extern "C" { · 6 unmodified lines | |||
| 86 | level is set sufficiently high. */ | 89 | level is set sufficiently high. */ |
| 87 | #if !defined(NDEBUG) | 90 | #if !defined(NDEBUG) |
| 88 | #define JAS_DBGLOG(n, x) \ | 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 | #else | 93 | #else |
| 91 | #define JAS_DBGLOG(n, x) | 94 | #define JAS_DBGLOG(n, x) |
| 92 | #endif | 95 | #endif |
| 93 | 96 | ||
| 94 | /* Get the library debug level. */ | 97 | #if !defined(NDEBUG) |
| 95 | JAS_ATTRIBUTE_CONST | 98 | #define JAS_LOGDEBUGF(n, ...) \ |
| 96 | JAS_DLLEXPORT int jas_getdbglevel(void); | 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. */ | 168 | /*! |
| 99 | JAS_DLLEXPORT int jas_setdbglevel(int dbglevel); | 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. */ | 175 | /*! |
| 102 | JAS_DLLEXPORT int jas_eprintf(const char *fmt, ...); | 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 | #define JAS_STRINGIFY(x) #x | 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 | #define JAS_STRINGIFYX(x) JAS_STRINGIFY(x) | 198 | #define JAS_STRINGIFYX(x) JAS_STRINGIFY(x) |
| 109 | 199 | ||
| 110 | #ifdef __cplusplus | 200 | #ifdef __cplusplus |
| @@ -65,29 +65,9 @@ · 64 unmodified lines | |||
| 65 | /* The configuration header file should be included first. */ | 65 | /* The configuration header file should be included first. */ |
| 66 | #include <jasper/jas_config.h> | 66 | #include <jasper/jas_config.h> |
| 67 | 67 | ||
| 68 | #if defined(JAS_DLL) | 68 | /* For backward compatibility only. */ |
| 69 | #if defined(_WIN32) | 69 | #define JAS_DLLEXPORT JAS_EXPORT |
| 70 | #if defined(JAS_BUILDING_DLL) | 70 | /* For backward compatibility only. */ |
| 71 | #define JAS_DLLEXPORT __declspec(dllexport) | 71 | #define JAS_DLLLOCAL JAS_LOCAL |
| 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 | ||
| 92 | 72 | ||
| 93 | #endif | 73 | #endif |
| @@ -82,19 +82,52 @@ · 81 unmodified lines | |||
| 82 | extern "C" { | 82 | extern "C" { |
| 83 | #endif | 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 | * Constants. | 119 | * Constants. |
| 87 | \******************************************************************************/ | 120 | \******************************************************************************/ |
| 88 | 121 | ||
| 89 | /* The representation of the value zero. */ | 122 | /*! The representation of the value zero. */ |
| 90 | #define JAS_FIX_ZERO(fix_t, fracbits) \ | 123 | #define JAS_FIX_ZERO(fix_t, fracbits) \ |
| 91 | JAS_INTTOFIX(fix_t, fracbits, 0) | 124 | JAS_INTTOFIX(fix_t, fracbits, 0) |
| 92 | 125 | ||
| 93 | /* The representation of the value one. */ | 126 | /*! The representation of the value one. */ |
| 94 | #define JAS_FIX_ONE(fix_t, fracbits) \ | 127 | #define JAS_FIX_ONE(fix_t, fracbits) \ |
| 95 | JAS_INTTOFIX(fix_t, fracbits, 1) | 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 | #define JAS_FIX_HALF(fix_t, fracbits) \ | 131 | #define JAS_FIX_HALF(fix_t, fracbits) \ |
| 99 | (JAS_CAST(fix_t, 1) << ((fracbits) - 1)) | 132 | (JAS_CAST(fix_t, 1) << ((fracbits) - 1)) |
| 100 | 133 | ||
| @@ -102,19 +135,19 @@ extern "C" { · 1 unmodified line | |||
| 102 | * Conversion operations. | 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 | #define JAS_INTTOFIX(fix_t, fracbits, x) \ | 139 | #define JAS_INTTOFIX(fix_t, fracbits, x) \ |
| 107 | (JAS_CAST(fix_t, x) << (fracbits)) | 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 | #define JAS_FIXTOINT(fix_t, fracbits, x) \ | 143 | #define JAS_FIXTOINT(fix_t, fracbits, x) \ |
| 111 | JAS_CAST(int, (x) >> (fracbits)) | 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 | #define JAS_FIXTODBL(fix_t, fracbits, x) \ | 147 | #define JAS_FIXTODBL(fix_t, fracbits, x) \ |
| 115 | (JAS_CAST(double, x) / JAS_FIX_ONE(fix_t, fracbits)) | 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 | #define JAS_DBLTOFIX(fix_t, fracbits, x) \ | 151 | #define JAS_DBLTOFIX(fix_t, fracbits, x) \ |
| 119 | JAS_CAST(fix_t, ((x) * JAS_CAST(double, JAS_FIX_ONE(fix_t, fracbits)))) | 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 | * Only the generic macros should be invoked directly by application code. | 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 | #if !defined(DEBUG_OVERFLOW) | 165 | #if !defined(DEBUG_OVERFLOW) |
| 133 | #define JAS_FIX_ADD JAS_FIX_ADD_FAST | 166 | #define JAS_FIX_ADD JAS_FIX_ADD_FAST |
| 134 | #else | 167 | #else |
| 135 | #define JAS_FIX_ADD JAS_FIX_ADD_OFLOW | 168 | #define JAS_FIX_ADD JAS_FIX_ADD_OFLOW |
| 136 | #endif | 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 | #define JAS_FIX_ADD_FAST(fix_t, fracbits, x, y) ((x) + (y)) | 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 | #define JAS_FIX_ADD_OFLOW(fix_t, fracbits, x, y) \ | 175 | #define JAS_FIX_ADD_OFLOW(fix_t, fracbits, x, y) \ |
| 143 | ((x) >= 0) ? \ | 176 | ((x) >= 0) ? \ |
| 144 | (((y) >= 0) ? ((x) + (y) >= 0 || JAS_FIX_OFLOW(), (x) + (y)) : \ | 177 | (((y) >= 0) ? ((x) + (y) >= 0 || JAS_FIX_OFLOW(), (x) + (y)) : \ |
| @@ -146,20 +179,20 @@ extern "C" { · 1 unmodified line | |||
| 146 | (((y) >= 0) ? ((x) + (y)) : ((x) + (y) < 0 || JAS_FIX_OFLOW(), \ | 179 | (((y) >= 0) ? ((x) + (y)) : ((x) + (y) < 0 || JAS_FIX_OFLOW(), \ |
| 147 | (x) + (y))) | 180 | (x) + (y))) |
| 148 | 181 | ||
| 149 | /* Calculate the product of two fixed-point numbers. */ | 182 | /*! Calculate the product of two fixed-point numbers. */ |
| 150 | #if !defined(DEBUG_OVERFLOW) | 183 | #if !defined(DEBUG_OVERFLOW) |
| 151 | #define JAS_FIX_MUL JAS_FIX_MUL_FAST | 184 | #define JAS_FIX_MUL JAS_FIX_MUL_FAST |
| 152 | #else | 185 | #else |
| 153 | #define JAS_FIX_MUL JAS_FIX_MUL_OFLOW | 186 | #define JAS_FIX_MUL JAS_FIX_MUL_OFLOW |
| 154 | #endif | 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 | checking. */ | 190 | checking. */ |
| 158 | #define JAS_FIX_MUL_FAST(fix_t, fracbits, bigfix_t, x, y) \ | 191 | #define JAS_FIX_MUL_FAST(fix_t, fracbits, bigfix_t, x, y) \ |
| 159 | JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y)) >> \ | 192 | JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y)) >> \ |
| 160 | (fracbits)) | 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 | checking. */ | 196 | checking. */ |
| 164 | #define JAS_FIX_MUL_OFLOW(fix_t, fracbits, bigfix_t, x, y) \ | 197 | #define JAS_FIX_MUL_OFLOW(fix_t, fracbits, bigfix_t, x, y) \ |
| 165 | ((JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y) >> (fracbits)) == \ | 198 | ((JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y) >> (fracbits)) == \ |
| @@ -168,87 +201,87 @@ extern "C" { · 2 unmodified lines | |||
| 168 | JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y) >> \ | 201 | JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y) >> \ |
| 169 | (fracbits))) : JAS_FIX_OFLOW()) | 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 | #if !defined(DEBUG_OVERFLOW) | 205 | #if !defined(DEBUG_OVERFLOW) |
| 173 | #define JAS_FIX_MULBYINT JAS_FIX_MULBYINT_FAST | 206 | #define JAS_FIX_MULBYINT JAS_FIX_MULBYINT_FAST |
| 174 | #else | 207 | #else |
| 175 | #define JAS_FIX_MULBYINT JAS_FIX_MULBYINT_OFLOW | 208 | #define JAS_FIX_MULBYINT JAS_FIX_MULBYINT_OFLOW |
| 176 | #endif | 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 | checking. */ | 212 | checking. */ |
| 180 | #define JAS_FIX_MULBYINT_FAST(fix_t, fracbits, x, y) \ | 213 | #define JAS_FIX_MULBYINT_FAST(fix_t, fracbits, x, y) \ |
| 181 | JAS_CAST(fix_t, ((x) * (y))) | 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 | checking. */ | 217 | checking. */ |
| 185 | #define JAS_FIX_MULBYINT_OFLOW(fix_t, fracbits, x, y) \ | 218 | #define JAS_FIX_MULBYINT_OFLOW(fix_t, fracbits, x, y) \ |
| 186 | JAS_FIX_MULBYINT_FAST(fix_t, fracbits, x, y) | 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 | #if !defined(DEBUG_OVERFLOW) | 222 | #if !defined(DEBUG_OVERFLOW) |
| 190 | #define JAS_FIX_DIV JAS_FIX_DIV_FAST | 223 | #define JAS_FIX_DIV JAS_FIX_DIV_FAST |
| 191 | #else | 224 | #else |
| 192 | #define JAS_FIX_DIV JAS_FIX_DIV_UFLOW | 225 | #define JAS_FIX_DIV JAS_FIX_DIV_UFLOW |
| 193 | #endif | 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 | checking. */ | 229 | checking. */ |
| 197 | #define JAS_FIX_DIV_FAST(fix_t, fracbits, bigfix_t, x, y) \ | 230 | #define JAS_FIX_DIV_FAST(fix_t, fracbits, bigfix_t, x, y) \ |
| 198 | JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) << (fracbits)) / (y)) | 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 | checking. */ | 234 | checking. */ |
| 202 | #define JAS_FIX_DIV_UFLOW(fix_t, fracbits, bigfix_t, x, y) \ | 235 | #define JAS_FIX_DIV_UFLOW(fix_t, fracbits, bigfix_t, x, y) \ |
| 203 | JAS_FIX_DIV_FAST(fix_t, fracbits, bigfix_t, x, y) | 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 | #if !defined(DEBUG_OVERFLOW) | 239 | #if !defined(DEBUG_OVERFLOW) |
| 207 | #define JAS_FIX_NEG JAS_FIX_NEG_FAST | 240 | #define JAS_FIX_NEG JAS_FIX_NEG_FAST |
| 208 | #else | 241 | #else |
| 209 | #define JAS_FIX_NEG JAS_FIX_NEG_OFLOW | 242 | #define JAS_FIX_NEG JAS_FIX_NEG_OFLOW |
| 210 | #endif | 243 | #endif |
| 211 | 244 | ||
| 212 | /* Negate a fixed-point number without overflow checking. */ | 245 | /*! Negate a fixed-point number without overflow checking. */ |
| 213 | #define JAS_FIX_NEG_FAST(fix_t, fracbits, x) \ | 246 | #define JAS_FIX_NEG_FAST(fix_t, fracbits, x) \ |
| 214 | (-(x)) | 247 | (-(x)) |
| 215 | 248 | ||
| 216 | /* Negate a fixed-point number with overflow checking. */ | 249 | /*! Negate a fixed-point number with overflow checking. */ |
| 217 | /* Yes, overflow is actually possible for two's complement representations, | 250 | /* Yes, overflow is actually possible for two's complement representations, |
| 218 | although highly unlikely to occur. */ | 251 | although highly unlikely to occur. */ |
| 219 | #define JAS_FIX_NEG_OFLOW(fix_t, fracbits, x) \ | 252 | #define JAS_FIX_NEG_OFLOW(fix_t, fracbits, x) \ |
| 220 | (((x) < 0) ? (-(x) > 0 || JAS_FIX_OFLOW(), -(x)) : (-(x))) | 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 | #if !defined(DEBUG_OVERFLOW) | 256 | #if !defined(DEBUG_OVERFLOW) |
| 224 | #define JAS_FIX_ASL JAS_FIX_ASL_FAST | 257 | #define JAS_FIX_ASL JAS_FIX_ASL_FAST |
| 225 | #else | 258 | #else |
| 226 | #define JAS_FIX_ASL JAS_FIX_ASL_OFLOW | 259 | #define JAS_FIX_ASL JAS_FIX_ASL_OFLOW |
| 227 | #endif | 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 | checking. */ | 263 | checking. */ |
| 231 | #define JAS_FIX_ASL_FAST(fix_t, fracbits, x, n) \ | 264 | #define JAS_FIX_ASL_FAST(fix_t, fracbits, x, n) \ |
| 232 | ((x) << (n)) | 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 | checking. */ | 268 | checking. */ |
| 236 | #define JAS_FIX_ASL_OFLOW(fix_t, fracbits, x, n) \ | 269 | #define JAS_FIX_ASL_OFLOW(fix_t, fracbits, x, n) \ |
| 237 | ((((x) << (n)) >> (n)) == (x) || JAS_FIX_OFLOW(), (x) << (n)) | 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 | #if !defined(DEBUG_OVERFLOW) | 273 | #if !defined(DEBUG_OVERFLOW) |
| 241 | #define JAS_FIX_ASR JAS_FIX_ASR_FAST | 274 | #define JAS_FIX_ASR JAS_FIX_ASR_FAST |
| 242 | #else | 275 | #else |
| 243 | #define JAS_FIX_ASR JAS_FIX_ASR_UFLOW | 276 | #define JAS_FIX_ASR JAS_FIX_ASR_UFLOW |
| 244 | #endif | 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 | checking. */ | 280 | checking. */ |
| 248 | #define JAS_FIX_ASR_FAST(fix_t, fracbits, x, n) \ | 281 | #define JAS_FIX_ASR_FAST(fix_t, fracbits, x, n) \ |
| 249 | ((x) >> (n)) | 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 | checking. */ | 285 | checking. */ |
| 253 | #define JAS_FIX_ASR_UFLOW(fix_t, fracbits, x, n) \ | 286 | #define JAS_FIX_ASR_UFLOW(fix_t, fracbits, x, n) \ |
| 254 | JAS_FIX_ASR_FAST(fix_t, fracbits, x, n) | 287 | JAS_FIX_ASR_FAST(fix_t, fracbits, x, n) |
| @@ -257,19 +290,19 @@ extern "C" { · 2 unmodified lines | |||
| 257 | * Other basic arithmetic operations. | 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 | #define JAS_FIX_SUB(fix_t, fracbits, x, y) \ | 294 | #define JAS_FIX_SUB(fix_t, fracbits, x, y) \ |
| 262 | JAS_FIX_ADD(fix_t, fracbits, x, JAS_FIX_NEG(fix_t, fracbits, y)) | 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 | #define JAS_FIX_PLUSEQ(fix_t, fracbits, x, y) \ | 298 | #define JAS_FIX_PLUSEQ(fix_t, fracbits, x, y) \ |
| 266 | ((x) = JAS_FIX_ADD(fix_t, fracbits, x, y)) | 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 | #define JAS_FIX_MINUSEQ(fix_t, fracbits, x, y) \ | 302 | #define JAS_FIX_MINUSEQ(fix_t, fracbits, x, y) \ |
| 270 | ((x) = JAS_FIX_SUB(fix_t, fracbits, x, y)) | 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 | #define JAS_FIX_MULEQ(fix_t, fracbits, bigfix_t, x, y) \ | 306 | #define JAS_FIX_MULEQ(fix_t, fracbits, bigfix_t, x, y) \ |
| 274 | ((x) = JAS_FIX_MUL(fix_t, fracbits, bigfix_t, x, y)) | 307 | ((x) = JAS_FIX_MUL(fix_t, fracbits, bigfix_t, x, y)) |
| 275 | 308 | ||
| @@ -277,15 +310,15 @@ extern "C" { · 1 unmodified line | |||
| 277 | * Miscellaneous operations. | 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 | #define JAS_FIX_ABS(fix_t, fracbits, x) \ | 314 | #define JAS_FIX_ABS(fix_t, fracbits, x) \ |
| 282 | (((x) >= 0) ? (x) : (JAS_FIX_NEG(fix_t, fracbits, x))) | 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 | #define JAS_FIX_ISINT(fix_t, fracbits, x) \ | 318 | #define JAS_FIX_ISINT(fix_t, fracbits, x) \ |
| 286 | (JAS_FIX_FLOOR(fix_t, fracbits, x) == (x)) | 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 | #define JAS_FIX_SGN(fix_t, fracbits, x) \ | 322 | #define JAS_FIX_SGN(fix_t, fracbits, x) \ |
| 290 | ((x) >= 0 ? 1 : (-1)) | 323 | ((x) >= 0 ? 1 : (-1)) |
| 291 | 324 | ||
| @@ -293,23 +326,23 @@ extern "C" { · 1 unmodified line | |||
| 293 | * Relational operations. | 326 | * Relational operations. |
| 294 | \******************************************************************************/ | 327 | \******************************************************************************/ |
| 295 | 328 | ||
| 296 | /* Compare two fixed-point numbers. */ | 329 | /*! Compare two fixed-point numbers. */ |
| 297 | #define JAS_FIX_CMP(fix_t, fracbits, x, y) \ | 330 | #define JAS_FIX_CMP(fix_t, fracbits, x, y) \ |
| 298 | ((x) > (y) ? 1 : (((x) == (y)) ? 0 : (-1))) | 331 | ((x) > (y) ? 1 : (((x) == (y)) ? 0 : (-1))) |
| 299 | 332 | ||
| 300 | /* Less than. */ | 333 | /*! Less than. */ |
| 301 | #define JAS_FIX_LT(fix_t, fracbits, x, y) \ | 334 | #define JAS_FIX_LT(fix_t, fracbits, x, y) \ |
| 302 | ((x) < (y)) | 335 | ((x) < (y)) |
| 303 | 336 | ||
| 304 | /* Less than or equal. */ | 337 | /*! Less than or equal. */ |
| 305 | #define JAS_FIX_LTE(fix_t, fracbits, x, y) \ | 338 | #define JAS_FIX_LTE(fix_t, fracbits, x, y) \ |
| 306 | ((x) <= (y)) | 339 | ((x) <= (y)) |
| 307 | 340 | ||
| 308 | /* Greater than. */ | 341 | /*! Greater than. */ |
| 309 | #define JAS_FIX_GT(fix_t, fracbits, x, y) \ | 342 | #define JAS_FIX_GT(fix_t, fracbits, x, y) \ |
| 310 | ((x) > (y)) | 343 | ((x) > (y)) |
| 311 | 344 | ||
| 312 | /* Greater than or equal. */ | 345 | /*! Greater than or equal. */ |
| 313 | #define JAS_FIX_GTE(fix_t, fracbits, x, y) \ | 346 | #define JAS_FIX_GTE(fix_t, fracbits, x, y) \ |
| 314 | ((x) >= (y)) | 347 | ((x) >= (y)) |
| 315 | 348 | ||
| @@ -317,14 +350,14 @@ extern "C" { · 1 unmodified line | |||
| 317 | * Rounding functions. | 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 | #define JAS_FIX_ROUND(fix_t, fracbits, x) \ | 354 | #define JAS_FIX_ROUND(fix_t, fracbits, x) \ |
| 322 | (((x) < 0) ? JAS_FIX_FLOOR(fix_t, fracbits, JAS_FIX_ADD(fix_t, fracbits, \ | 355 | (((x) < 0) ? JAS_FIX_FLOOR(fix_t, fracbits, JAS_FIX_ADD(fix_t, fracbits, \ |
| 323 | (x), JAS_FIX_HALF(fix_t, fracbits))) : \ | 356 | (x), JAS_FIX_HALF(fix_t, fracbits))) : \ |
| 324 | JAS_FIX_NEG(fix_t, fracbits, JAS_FIX_FLOOR(fix_t, fracbits, \ | 357 | JAS_FIX_NEG(fix_t, fracbits, JAS_FIX_FLOOR(fix_t, fracbits, \ |
| 325 | JAS_FIX_ADD(fix_t, fracbits, (-(x)), JAS_FIX_HALF(fix_t, fracbits))))) | 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 | negative infinity (i.e., the floor function). */ | 361 | negative infinity (i.e., the floor function). */ |
| 329 | #define JAS_FIX_FLOOR(fix_t, fracbits, x) \ | 362 | #define JAS_FIX_FLOOR(fix_t, fracbits, x) \ |
| 330 | ((x) & (~(JAS_FIX_ONE(fix_t, fracbits) - 1))) | 363 | ((x) & (~(JAS_FIX_ONE(fix_t, fracbits) - 1))) |
| @@ -336,11 +369,31 @@ extern "C" { · 5 unmodified lines | |||
| 336 | 369 | ||
| 337 | /* Handle overflow. */ | 370 | /* Handle overflow. */ |
| 338 | #define JAS_FIX_OFLOW() \ | 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 | /* Handle underflow. */ | 374 | /* Handle underflow. */ |
| 342 | #define JAS_FIX_UFLOW() \ | 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 | #ifdef __cplusplus | 398 | #ifdef __cplusplus |
| 346 | } | 399 | } |
| @@ -77,6 +77,11 @@ · 76 unmodified lines | |||
| 77 | extern "C" { | 77 | extern "C" { |
| 78 | #endif | 78 | #endif |
| 79 | 79 | ||
| 80 | /*! | ||
| 81 | * @addtogroup module_cm | ||
| 82 | * @{ | ||
| 83 | */ | ||
| 84 | |||
| 80 | /* Profile file signature. */ | 85 | /* Profile file signature. */ |
| 81 | #define JAS_ICC_MAGIC 0x61637370 | 86 | #define JAS_ICC_MAGIC 0x61637370 |
| 82 | 87 | ||
| @@ -308,6 +313,7 @@ typedef struct { · 225 unmodified lines | |||
| 308 | int (*output)(struct jas_iccattrval_s *, jas_stream_t *); | 313 | int (*output)(struct jas_iccattrval_s *, jas_stream_t *); |
| 309 | //#endif | 314 | //#endif |
| 310 | unsigned (*getsize)(const struct jas_iccattrval_s *); | 315 | unsigned (*getsize)(const struct jas_iccattrval_s *); |
| 316 | void (*dump)(const struct jas_iccattrval_s *, FILE *); | ||
| 311 | } jas_iccattrvalops_t; | 317 | } jas_iccattrvalops_t; |
| 312 | 318 | ||
| 313 | /* Attribute value type (type and value information). */ | 319 | /* Attribute value type (type and value information). */ |
| @@ -381,29 +387,145 @@ typedef struct { · 67 unmodified lines | |||
| 381 | jas_iccattrvalops_t ops; | 387 | jas_iccattrvalops_t ops; |
| 382 | } jas_iccattrvalinfo_t; | 388 | } jas_iccattrvalinfo_t; |
| 383 | 389 | ||
| 384 | JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_load(jas_stream_t *in); | 390 | /*! |
| 385 | JAS_DLLEXPORT int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out); | 391 | @brief |
| 386 | JAS_DLLEXPORT void jas_iccprof_destroy(jas_iccprof_t *prof); | 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 | JAS_ATTRIBUTE_PURE | 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 | jas_iccattrname_t name); | 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 | jas_iccattrval_t *val); | 426 | jas_iccattrval_t *val); |
| 392 | JAS_DLLEXPORT int jas_iccprof_gethdr(const jas_iccprof_t *prof, jas_icchdr_t *hdr); | 427 | |
| 393 | JAS_DLLEXPORT int jas_iccprof_sethdr(jas_iccprof_t *prof, const jas_icchdr_t *hdr); | 428 | /*! |
| 394 | 429 | @brief | |
| 395 | JAS_DLLEXPORT void jas_iccattrval_destroy(jas_iccattrval_t *attrval); | 430 | Dump an ICC profile to a stream in human-readable format |
| 396 | JAS_DLLEXPORT int jas_iccattrval_allowmodify(jas_iccattrval_t **attrval); | 431 | for debugging purposes. |
| 397 | JAS_DLLEXPORT jas_iccattrval_t *jas_iccattrval_clone(jas_iccattrval_t *attrval); | 432 | */ |
| 398 | JAS_DLLEXPORT jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type); | 433 | JAS_EXPORT |
| 399 | 434 | void jas_iccprof_dump(const jas_iccprof_t *prof, FILE *out); | |
| 400 | JAS_DLLEXPORT extern const jas_uchar jas_iccprofdata_srgb[]; | 435 | |
| 401 | JAS_DLLEXPORT extern const unsigned jas_iccprofdata_srgblen; | 436 | /*! |
| 402 | JAS_DLLEXPORT extern const jas_uchar jas_iccprofdata_sgray[]; | 437 | @brief |
| 403 | JAS_DLLEXPORT extern const unsigned jas_iccprofdata_sgraylen; | 438 | Create a copy of an ICC profile. |
| 404 | JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len); | 439 | */ |
| 405 | JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_createfromclrspc(unsigned clrspc); | 440 | JAS_EXPORT |
| 406 | JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof); | 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 | #ifdef __cplusplus | 530 | #ifdef __cplusplus |
| 409 | } | 531 | } |
| @@ -86,7 +86,7 @@ extern "C" { · 85 unmodified lines | |||
| 86 | #endif | 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 | typedef int_fast32_t jas_image_coord_t; | 133 | typedef int_fast32_t jas_image_coord_t; |
| 133 | #define JAS_IMAGE_COORD_MAX INT_FAST32_MAX | 134 | #define JAS_IMAGE_COORD_MAX INT_FAST32_MAX |
| 134 | #define JAS_IMAGE_COORD_MIN INT_FAST32_MIN | 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 | typedef struct { | 167 | typedef struct { |
| 160 | 168 | ||
| 161 | jas_image_coord_t tlx_; | ||
| 162 | /* The x-coordinate of the top-left corner of the component. */ | 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 | /* The y-coordinate of the top-left corner of the component. */ | 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 | /* The horizontal sampling period in units of the reference grid. */ | 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 | /* The vertical sampling period in units of the reference grid. */ | 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 | /* The component width in samples. */ | 181 | /* The component width in samples. */ |
| 182 | jas_image_coord_t width_; | ||
| 175 | 183 | ||
| 176 | jas_image_coord_t height_; | ||
| 177 | /* The component height in samples. */ | 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 | unsigned prec_; | 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 | /* The signedness of the sample data. */ | 191 | /* The signedness of the sample data. */ |
| 192 | int sgnd_; | ||
| 186 | 193 | ||
| 187 | jas_stream_t *stream_; | ||
| 188 | /* The stream containing the component data. */ | 194 | /* The stream containing the component data. */ |
| 195 | jas_stream_t *stream_; | ||
| 189 | 196 | ||
| 190 | unsigned cps_; | ||
| 191 | /* The number of characters per sample in the stream. */ | 197 | /* The number of characters per sample in the stream. */ |
| 198 | unsigned cps_; | ||
| 192 | 199 | ||
| 193 | jas_image_cmpttype_t type_; | ||
| 194 | /* The type of component (e.g., opacity, red, green, blue, luma). */ | 200 | /* The type of component (e.g., opacity, red, green, blue, luma). */ |
| 201 | jas_image_cmpttype_t type_; | ||
| 195 | 202 | ||
| 196 | } jas_image_cmpt_t; | 203 | } jas_image_cmpt_t; |
| 197 | 204 | ||
| 198 | /*! | 205 | /*! |
| 199 | @brief Image class. | 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 | typedef struct { | 214 | typedef struct { |
| 202 | 215 | ||
| 203 | jas_image_coord_t tlx_; | ||
| 204 | /* The x-coordinate of the top-left corner of the image bounding box. */ | 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 | /* The y-coordinate of the top-left corner of the image bounding box. */ | 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 | /* The x-coordinate of the bottom-right corner of the image bounding | 222 | /* The x-coordinate of the bottom-right corner of the image bounding |
| 211 | box (plus one). */ | 223 | box (plus one). */ |
| 224 | jas_image_coord_t brx_; | ||
| 212 | 225 | ||
| 213 | jas_image_coord_t bry_; | ||
| 214 | /* The y-coordinate of the bottom-right corner of the image bounding | 226 | /* The y-coordinate of the bottom-right corner of the image bounding |
| 215 | box (plus one). */ | 227 | box (plus one). */ |
| 228 | jas_image_coord_t bry_; | ||
| 216 | 229 | ||
| 217 | unsigned numcmpts_; | ||
| 218 | /* The number of components. */ | 230 | /* The number of components. */ |
| 231 | unsigned numcmpts_; | ||
| 219 | 232 | ||
| 220 | unsigned maxcmpts_; | ||
| 221 | /* The maximum number of components that this image can have (i.e., the | 233 | /* The maximum number of components that this image can have (i.e., the |
| 222 | allocated size of the components array). */ | 234 | allocated size of the components array). */ |
| 235 | unsigned maxcmpts_; | ||
| 223 | 236 | ||
| 224 | jas_image_cmpt_t **cmpts_; | ||
| 225 | /* Per-component information. */ | 237 | /* Per-component information. */ |
| 238 | jas_image_cmpt_t **cmpts_; | ||
| 226 | 239 | ||
| 240 | /* The color space. */ | ||
| 227 | jas_clrspc_t clrspc_; | 241 | jas_clrspc_t clrspc_; |
| 228 | 242 | ||
| 243 | /* The CM profile. */ | ||
| 229 | jas_cmprof_t *cmprof_; | 244 | jas_cmprof_t *cmprof_; |
| 230 | 245 | ||
| 231 | // bool inmem_; | 246 | //bool inmem_; |
| 232 | 247 | ||
| 233 | } jas_image_t; | 248 | } jas_image_t; |
| 234 | 249 | ||
| @@ -241,29 +256,29 @@ jas_image_create function. · 6 unmodified lines | |||
| 241 | */ | 256 | */ |
| 242 | typedef struct { | 257 | typedef struct { |
| 243 | 258 | ||
| 244 | jas_image_coord_t tlx; | ||
| 245 | /* The x-coordinate of the top-left corner of the component. */ | 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 | /* The y-coordinate of the top-left corner of the component. */ | 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 | /* The horizontal sampling period in units of the reference grid. */ | 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 | /* The vertical sampling period in units of the reference grid. */ | 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 | /* The width of the component in samples. */ | 271 | /* The width of the component in samples. */ |
| 272 | jas_image_coord_t width; | ||
| 258 | 273 | ||
| 259 | jas_image_coord_t height; | ||
| 260 | /* The height of the component in samples. */ | 274 | /* The height of the component in samples. */ |
| 275 | jas_image_coord_t height; | ||
| 261 | 276 | ||
| 262 | unsigned prec; | ||
| 263 | /* The precision of the component sample data. */ | 277 | /* The precision of the component sample data. */ |
| 278 | unsigned prec; | ||
| 264 | 279 | ||
| 265 | int sgnd; | ||
| 266 | /* The signedness of the component sample data. */ | 280 | /* The signedness of the component sample data. */ |
| 281 | int sgnd; | ||
| 267 | 282 | ||
| 268 | } jas_image_cmptparm_t; | 283 | } jas_image_cmptparm_t; |
| 269 | 284 | ||
| @@ -281,14 +296,14 @@ typedef struct { · 11 unmodified lines | |||
| 281 | */ | 296 | */ |
| 282 | typedef struct { | 297 | typedef struct { |
| 283 | 298 | ||
| 299 | /*! Decode image data from a stream. */ | ||
| 284 | jas_image_t *(*decode)(jas_stream_t *in, const char *opts); | 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 | int (*encode)(jas_image_t *image, jas_stream_t *out, const char *opts); | 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 | int (*validate)(jas_stream_t *in); | 306 | int (*validate)(jas_stream_t *in); |
| 291 | /* Determine if stream data is in a particular format. */ | ||
| 292 | 307 | ||
| 293 | } jas_image_fmtops_t; | 308 | } jas_image_fmtops_t; |
| 294 | 309 | ||
| @@ -297,20 +312,29 @@ typedef struct { · 2 unmodified lines | |||
| 297 | */ | 312 | */ |
| 298 | typedef struct { | 313 | typedef struct { |
| 299 | 314 | ||
| 315 | /*! The ID for this format. */ | ||
| 300 | int id; | 316 | int id; |
| 301 | /* The ID for this format. */ | ||
| 302 | 317 | ||
| 318 | /*! The name by which this format is identified. */ | ||
| 303 | char *name; | 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 | char *ext; | 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 | char *desc; | 334 | char *desc; |
| 310 | /* A brief description of the format. */ | ||
| 311 | 335 | ||
| 336 | /*! The operations for this format. */ | ||
| 312 | jas_image_fmtops_t ops; | 337 | jas_image_fmtops_t ops; |
| 313 | /* The operations for this format. */ | ||
| 314 | 338 | ||
| 315 | } jas_image_fmtinfo_t; | 339 | } jas_image_fmtinfo_t; |
| 316 | 340 | ||
| @@ -321,23 +345,27 @@ typedef struct { · 4 unmodified lines | |||
| 321 | /*! | 345 | /*! |
| 322 | @brief Create an image. | 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 | const jas_image_cmptparm_t *cmptparms, jas_clrspc_t clrspc); | 350 | const jas_image_cmptparm_t *cmptparms, jas_clrspc_t clrspc); |
| 326 | 351 | ||
| 327 | /*! | 352 | /*! |
| 328 | @brief Create an "empty" image. | 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 | @brief Clone an image. | 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 | @brief Deallocate any resources associated with an image. | 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 | @brief Get the width of the image in units of the image reference grid. | 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 | @brief Test if all components are specified at the same positions in space. | 498 | @brief Test if all components are specified at the same positions in space. |
| 471 | */ | 499 | */ |
| 472 | JAS_ATTRIBUTE_PURE | 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 | @brief Get the raw size of an image | 505 | @brief Get the raw size of an image |
| 477 | (i.e., the nominal size of the image without any compression. | 506 | (i.e., the nominal size of the image without any compression. |
| 478 | */ | 507 | */ |
| 479 | JAS_ATTRIBUTE_PURE | 508 | JAS_ATTRIBUTE_PURE |
| 480 | JAS_DLLEXPORT | 509 | JAS_EXPORT |
| 481 | uint_fast32_t jas_image_rawsize(const jas_image_t *image); | 510 | uint_fast32_t jas_image_rawsize(const jas_image_t *image); |
| 482 | 511 | ||
| 483 | /*! | 512 | /*! |
| 484 | @brief Create an image from a stream in some specified format. | 513 | @brief Create an image from a stream in some specified format. |
| 485 | */ | 514 | */ |
| 486 | JAS_DLLEXPORT | 515 | JAS_EXPORT |
| 487 | jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr); | 516 | jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr); |
| 488 | 517 | ||
| 489 | /*! | 518 | /*! |
| 490 | @brief Write an image to a stream in a specified format. | 519 | @brief Write an image to a stream in a specified format. |
| 491 | */ | 520 | */ |
| 492 | JAS_DLLEXPORT | 521 | JAS_EXPORT |
| 493 | int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, | 522 | int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, |
| 494 | const char *optstr); | 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 | The position and size of the rectangular region to be read is specified | 529 | The position and size of the rectangular region to be read is specified |
| 501 | relative to the component's coordinate system. | 530 | relative to the component's coordinate system. |
| 502 | */ | 531 | */ |
| 503 | JAS_DLLEXPORT | 532 | JAS_EXPORT |
| 504 | int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, | 533 | int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, |
| 505 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, | 534 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 506 | jas_image_coord_t height, jas_matrix_t *data); | 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 | @brief Write a rectangular region of an image component. | 538 | @brief Write a rectangular region of an image component. |
| 510 | */ | 539 | */ |
| 511 | JAS_DLLEXPORT | 540 | JAS_EXPORT |
| 512 | int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, | 541 | int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, |
| 513 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, | 542 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 514 | jas_image_coord_t height, const jas_matrix_t *data); | 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 | @brief Delete a component from an image. | 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 | @brief Add a component to an image. | 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 | const jas_image_cmptparm_t *cmptparm); | 556 | const jas_image_cmptparm_t *cmptparm); |
| 526 | 557 | ||
| 527 | /*! | 558 | /*! |
| 528 | @brief Copy a component from one image to another. | 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 | jas_image_t *srcimage, unsigned srccmptno); | 563 | jas_image_t *srcimage, unsigned srccmptno); |
| 532 | 564 | ||
| 533 | JAS_ATTRIBUTE_CONST | 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 | JAS_ATTRIBUTE_PURE | 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 | return JAS_IMAGE_CDT_SETSGND(image->cmpts_[cmptno]->sgnd_) | | 593 | return JAS_IMAGE_CDT_SETSGND(image->cmpts_[cmptno]->sgnd_) | |
| 561 | JAS_IMAGE_CDT_SETPREC(image->cmpts_[cmptno]->prec_); | 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 | @brief Depalettize an image | 598 | @brief Depalettize an image |
| 566 | */ | 599 | */ |
| 567 | JAS_DLLEXPORT | 600 | JAS_EXPORT |
| 568 | int jas_image_depalettize(jas_image_t *image, unsigned cmptno, | 601 | int jas_image_depalettize(jas_image_t *image, unsigned cmptno, |
| 569 | unsigned numlutents, const int_fast32_t *lutents, unsigned dtype, | 602 | unsigned numlutents, const int_fast32_t *lutents, unsigned dtype, |
| 570 | unsigned newcmptno); | 603 | unsigned newcmptno); |
| @@ -572,14 +605,14 @@ int jas_image_depalettize(jas_image_t *image, unsigned cmptno, · 1 unmodified line | |||
| 572 | /*! | 605 | /*! |
| 573 | @brief Read a component sample for an image. | 606 | @brief Read a component sample for an image. |
| 574 | */ | 607 | */ |
| 575 | JAS_DLLEXPORT | 608 | JAS_EXPORT |
| 576 | int jas_image_readcmptsample(jas_image_t *image, unsigned cmptno, unsigned x, | 609 | int jas_image_readcmptsample(jas_image_t *image, unsigned cmptno, unsigned x, |
| 577 | unsigned y); | 610 | unsigned y); |
| 578 | 611 | ||
| 579 | /*! | 612 | /*! |
| 580 | @brief Write a component sample for an image. | 613 | @brief Write a component sample for an image. |
| 581 | */ | 614 | */ |
| 582 | JAS_DLLEXPORT | 615 | JAS_EXPORT |
| 583 | void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno, | 616 | void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno, |
| 584 | unsigned x, unsigned y, int_fast32_t v); | 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 | @brief Get an image component by its type. | 620 | @brief Get an image component by its type. |
| 588 | */ | 621 | */ |
| 589 | JAS_ATTRIBUTE_PURE | 622 | JAS_ATTRIBUTE_PURE |
| 590 | JAS_DLLEXPORT | 623 | JAS_EXPORT |
| 591 | int jas_image_getcmptbytype(const jas_image_t *image, jas_image_cmpttype_t ctype); | 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 | @brief Clear the table of image formats. | 631 | @brief Clear the table of image formats. |
| 599 | */ | 632 | */ |
| 600 | JAS_DLLEXPORT | 633 | JAS_EXPORT |
| 601 | void jas_image_clearfmts(void); | 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 | @brief Add entry to table of image formats. | 675 | @brief Add entry to table of image formats. |
| 605 | */ | 676 | */ |
| 606 | JAS_DLLEXPORT | 677 | JAS_EXPORT |
| 607 | int jas_image_addfmt(int id, const char *name, const char *ext, | 678 | int jas_image_addfmt(int id, const char *name, const char *ext, |
| 608 | const char *desc, const jas_image_fmtops_t *ops); | 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 | @brief Get the ID for the image format with the specified name. | 688 | @brief Get the ID for the image format with the specified name. |
| 612 | */ | 689 | */ |
| 613 | JAS_ATTRIBUTE_PURE | 690 | JAS_ATTRIBUTE_PURE |
| 614 | JAS_DLLEXPORT | 691 | JAS_EXPORT |
| 615 | int jas_image_strtofmt(const char *s); | 692 | int jas_image_strtofmt(const char *s); |
| 616 | 693 | ||
| 617 | /*! | 694 | /*! |
| 618 | @brief Get the name of the image format with the specified ID. | 695 | @brief Get the name of the image format with the specified ID. |
| 619 | */ | 696 | */ |
| 620 | JAS_ATTRIBUTE_CONST | 697 | JAS_ATTRIBUTE_CONST |
| 621 | JAS_DLLEXPORT | 698 | JAS_EXPORT |
| 622 | const char *jas_image_fmttostr(int fmt); | 699 | const char *jas_image_fmttostr(int fmt); |
| 623 | 700 | ||
| 624 | /*! | 701 | /*! |
| 625 | @brief Lookup image format information by the format ID. | 702 | @brief Lookup image format information by the format ID. |
| 626 | */ | 703 | */ |
| 627 | JAS_ATTRIBUTE_CONST | 704 | JAS_ATTRIBUTE_CONST |
| 628 | JAS_DLLEXPORT | 705 | JAS_EXPORT |
| 629 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id); | 706 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id); |
| 630 | 707 | ||
| 631 | /*! | 708 | /*! |
| 632 | @brief Lookup image format information by the format name. | 709 | @brief Lookup image format information by the format name. |
| 633 | */ | 710 | */ |
| 634 | JAS_ATTRIBUTE_PURE | 711 | JAS_ATTRIBUTE_PURE |
| 635 | JAS_DLLEXPORT | 712 | JAS_EXPORT |
| 636 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name); | 713 | const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name); |
| 637 | 714 | ||
| 638 | /*! | 715 | /*! |
| 639 | @brief Guess the format of an image file based on its name. | 716 | @brief Guess the format of an image file based on its name. |
| 640 | */ | 717 | */ |
| 641 | JAS_ATTRIBUTE_PURE | 718 | JAS_ATTRIBUTE_PURE |
| 642 | JAS_DLLEXPORT | 719 | JAS_EXPORT |
| 643 | int jas_image_fmtfromname(const char *filename); | 720 | int jas_image_fmtfromname(const char *filename); |
| 644 | 721 | ||
| 645 | /*! | 722 | /*! |
| 646 | @brief Get the format of image data in a stream. | 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 | JAS_ATTRIBUTE_PURE | 728 | JAS_ATTRIBUTE_PURE |
| 649 | JAS_DLLEXPORT | 729 | JAS_EXPORT |
| 650 | int jas_image_getfmt(jas_stream_t *in); | 730 | int jas_image_getfmt(jas_stream_t *in); |
| 651 | 731 | ||
| 652 | |||
| 653 | /*! | 732 | /*! |
| 654 | @brief Get the color management profile of an image. | 733 | @brief Get the color management profile of an image. |
| 655 | */ | 734 | */ |
| 656 | #define jas_image_cmprof(image) ((image)->cmprof_) | 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 | JAS_ATTRIBUTE_PURE | 741 | JAS_ATTRIBUTE_PURE |
| 662 | JAS_DLLEXPORT | 742 | JAS_EXPORT |
| 663 | int jas_image_ishomosamp(const jas_image_t *image); | 743 | int jas_image_ishomosamp(const jas_image_t *image); |
| 664 | 744 | ||
| 665 | /*! | 745 | /*! |
| 666 | @brief ??? | 746 | @brief ??? |
| 667 | */ | 747 | */ |
| 668 | JAS_DLLEXPORT | 748 | JAS_EXPORT |
| 669 | int jas_image_sampcmpt(jas_image_t *image, unsigned cmptno, unsigned newcmptno, | 749 | int jas_image_sampcmpt(jas_image_t *image, unsigned cmptno, unsigned newcmptno, |
| 670 | jas_image_coord_t ho, jas_image_coord_t vo, jas_image_coord_t hs, | 750 | jas_image_coord_t ho, jas_image_coord_t vo, jas_image_coord_t hs, |
| 671 | jas_image_coord_t vs, int sgnd, unsigned prec); | 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 | @brief Write sample data in a component of an image. | 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, | 756 | JAS_EXPORT |
| 677 | jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, | 757 | int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, |
| 678 | const long *buf); | 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 | @brief Read sample data in a component of an image. | 762 | @brief Read sample data in a component of an image. |
| 682 | */ | 763 | */ |
| 683 | JAS_DLLEXPORT | 764 | JAS_EXPORT |
| 684 | int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, | 765 | int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, |
| 685 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, | 766 | jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, |
| 686 | jas_image_coord_t height, long *buf); | 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 | @brief Change the color space for an image. | 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, | 777 | JAS_EXPORT |
| 697 | jas_cmxform_intent_t intent); | 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 | * Image format-dependent operations. | 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 | #if defined(JAS_INCLUDE_JPG_CODEC) | 791 | #if defined(JAS_INCLUDE_JPG_CODEC) |
| 704 | /* Format-dependent operations for JPG support. */ | 792 | /* Format-dependent operations for JPG support. */ |
| 705 | JAS_DLLEXPORT jas_image_t *jpg_decode(jas_stream_t *in, const char *optstr); | 793 | //JAS_EXPORT |
| 706 | JAS_DLLEXPORT int jpg_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | 794 | jas_image_t *jpg_decode(jas_stream_t *in, const char *optstr); |
| 707 | JAS_DLLEXPORT int jpg_validate(jas_stream_t *in); | 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 | #endif | 809 | #endif |
| 709 | 810 | ||
| 710 | #if defined(JAS_INCLUDE_MIF_CODEC) | 811 | #if defined(JAS_INCLUDE_MIF_CODEC) |
| 711 | /* Format-dependent operations for MIF support. */ | 812 | /* Format-dependent operations for MIF support. */ |
| 712 | JAS_DLLEXPORT jas_image_t *mif_decode(jas_stream_t *in, const char *optstr); | 813 | //JAS_EXPORT |
| 713 | JAS_DLLEXPORT int mif_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | 814 | jas_image_t *mif_decode(jas_stream_t *in, const char *optstr); |
| 714 | JAS_DLLEXPORT int mif_validate(jas_stream_t *in); | 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 | #endif | 819 | #endif |
| 716 | 820 | ||
| 717 | #if defined(JAS_INCLUDE_PNM_CODEC) | 821 | #if defined(JAS_INCLUDE_PNM_CODEC) |
| 718 | /* Format-dependent operations for PNM support. */ | 822 | /* Format-dependent operations for PNM support. */ |
| 719 | JAS_DLLEXPORT jas_image_t *pnm_decode(jas_stream_t *in, const char *optstr); | 823 | //JAS_EXPORT |
| 720 | JAS_DLLEXPORT int pnm_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | 824 | jas_image_t *pnm_decode(jas_stream_t *in, const char *optstr); |
| 721 | JAS_DLLEXPORT int pnm_validate(jas_stream_t *in); | 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 | #endif | 829 | #endif |
| 723 | 830 | ||
| 724 | #if defined(JAS_INCLUDE_RAS_CODEC) | 831 | #if defined(JAS_INCLUDE_RAS_CODEC) |
| 725 | /* Format-dependent operations for Sun Rasterfile support. */ | 832 | /* Format-dependent operations for Sun Rasterfile support. */ |
| 726 | JAS_DLLEXPORT jas_image_t *ras_decode(jas_stream_t *in, const char *optstr); | 833 | //JAS_EXPORT |
| 727 | JAS_DLLEXPORT int ras_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | 834 | jas_image_t *ras_decode(jas_stream_t *in, const char *optstr); |
| 728 | JAS_DLLEXPORT int ras_validate(jas_stream_t *in); | 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 | #endif | 839 | #endif |
| 730 | 840 | ||
| 731 | #if defined(JAS_INCLUDE_BMP_CODEC) | 841 | #if defined(JAS_INCLUDE_BMP_CODEC) |
| 732 | /* Format-dependent operations for BMP support. */ | 842 | /* Format-dependent operations for BMP support. */ |
| 733 | JAS_DLLEXPORT jas_image_t *bmp_decode(jas_stream_t *in, const char *optstr); | 843 | //JAS_EXPORT |
| 734 | JAS_DLLEXPORT int bmp_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | 844 | jas_image_t *bmp_decode(jas_stream_t *in, const char *optstr); |
| 735 | JAS_DLLEXPORT int bmp_validate(jas_stream_t *in); | 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 | #endif | 849 | #endif |
| 737 | 850 | ||
| 738 | #if defined(JAS_INCLUDE_JP2_CODEC) | 851 | #if defined(JAS_INCLUDE_JP2_CODEC) |
| 739 | /* Format-dependent operations for JP2 support. */ | 852 | /* Format-dependent operations for JP2 support. */ |
| 740 | JAS_DLLEXPORT jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr); | 853 | //JAS_EXPORT |
| 741 | JAS_DLLEXPORT int jp2_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | 854 | jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr); |
| 742 | JAS_DLLEXPORT int jp2_validate(jas_stream_t *in); | 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 | #endif | 859 | #endif |
| 744 | 860 | ||
| 745 | #if defined(JAS_INCLUDE_JPC_CODEC) | 861 | #if defined(JAS_INCLUDE_JPC_CODEC) |
| 746 | /* Format-dependent operations for JPEG-2000 code stream support. */ | 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); | 863 | //JAS_EXPORT |
| 748 | JAS_DLLEXPORT int jpc_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | 864 | jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr); |
| 749 | JAS_DLLEXPORT int jpc_validate(jas_stream_t *in); | 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 | #endif | 869 | #endif |
| 751 | 870 | ||
| 752 | #if defined(JAS_INCLUDE_PGX_CODEC) | 871 | #if defined(JAS_INCLUDE_PGX_CODEC) |
| 753 | /* Format-dependent operations for PGX support. */ | 872 | /* Format-dependent operations for PGX support. */ |
| 754 | JAS_DLLEXPORT jas_image_t *pgx_decode(jas_stream_t *in, const char *optstr); | 873 | //JAS_EXPORT |
| 755 | JAS_DLLEXPORT int pgx_encode(jas_image_t *image, jas_stream_t *out, const char *optstr); | 874 | jas_image_t *pgx_decode(jas_stream_t *in, const char *optstr); |
| 756 | JAS_DLLEXPORT int pgx_validate(jas_stream_t *in); | 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 | #endif | 879 | #endif |
| 758 | 880 | ||
| 759 | /*! | 881 | /*! |
| @@ -70,42 +70,423 @@ · 69 unmodified lines | |||
| 70 | /* The configuration header file should be included first. */ | 70 | /* The configuration header file should be included first. */ |
| 71 | #include <jasper/jas_config.h> | 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 | #ifdef __cplusplus | 77 | #ifdef __cplusplus |
| 74 | extern "C" { | 78 | extern "C" { |
| 75 | #endif | 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 | @details | 216 | @details |
| 90 | This function must be called before any other code in the JasPer library | 217 | The library must be configured by invoking the jas_conf_clear() function |
| 91 | is invoked. | 218 | prior to calling jas_init_library(). |
| 92 | This function registers the codecs that are enabled by default. | ||
| 93 | 219 | ||
| 94 | @returns | 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 | int jas_init(void); | 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 | @details | 314 | @details |
| 104 | This function performs any clean up for the JasPer library. | 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 | void jas_cleanup(void); | 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 | /* The configuration header file should be included first. */ | 77 | /* The configuration header file should be included first. */ |
| 78 | #include <jasper/jas_config.h> | 78 | #include <jasper/jas_config.h> |
| 79 | 79 | ||
| 80 | #include <jasper/jas_types.h> | ||
| 81 | #include <jasper/jas_thread.h> | ||
| 82 | |||
| 80 | #ifdef __cplusplus | 83 | #ifdef __cplusplus |
| 81 | extern "C" { | 84 | extern "C" { |
| 82 | #endif | 85 | #endif |
| 83 | 86 | ||
| 84 | #define jas_malloc malloc | 87 | /*! |
| 85 | #define jas_free free | 88 | * @addtogroup module_alloc |
| 86 | #define jas_realloc realloc | 89 | * @{ |
| 87 | #define jas_calloc calloc | 90 | */ |
| 88 | #define jas_alloc2(ne, esz) malloc(ne*esz) | 91 | |
| 89 | #define jas_alloc3(na, asz, esz) malloc(na*asz*esz) | 92 | /******************************************************************************\ |
| 90 | #define jas_realloc2(p, ne, esz) realloc(p, ne*esz) | 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 | #ifdef __cplusplus | 357 | #ifdef __cplusplus |
| 93 | } | 358 | } |
| @@ -75,6 +75,8 @@ · 74 unmodified lines | |||
| 75 | 75 | ||
| 76 | /* The configuration header file should be included first. */ | 76 | /* The configuration header file should be included first. */ |
| 77 | #include <jasper/jas_config.h> | 77 | #include <jasper/jas_config.h> |
| 78 | |||
| 79 | #include <jasper/jas_compiler.h> | ||
| 78 | #include <jasper/jas_types.h> | 80 | #include <jasper/jas_types.h> |
| 79 | 81 | ||
| 80 | #ifdef __cplusplus | 82 | #ifdef __cplusplus |
| @@ -109,6 +111,12 @@ extern "C" { · 28 unmodified lines | |||
| 109 | set to one. */ | 111 | set to one. */ |
| 110 | #define JAS_ONES(n) \ | 112 | #define JAS_ONES(n) \ |
| 111 | ((1 << (n)) - 1) | 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 | #endif | 130 | #endif |
| 123 | 131 | ||
| 124 | JAS_ATTRIBUTE_CONST | 132 | JAS_ATTRIBUTE_CONST |
| 125 | JAS_ATTRIBUTE_DISABLE_USAN | 133 | JAS_ATTRIBUTE_DISABLE_UBSAN |
| 126 | inline static int jas_int_asr(int x, unsigned n) | 134 | inline static int jas_int_asr(int x, unsigned n) |
| 127 | { | 135 | { |
| 128 | // Ensure that the shift of a negative value appears to behave as a | 136 | // Ensure that the shift of a negative value appears to behave as a |
| 129 | // signed arithmetic shift. | 137 | // signed arithmetic shift. |
| 130 | assert(((-1) >> 1) == -1); | 138 | assert(((-1) >> 1) == -1); |
| 131 | // The behavior is undefined when x is negative. */ | 139 | // The behavior is undefined when x is negative. |
| 132 | // We tacitly assume the behavior is equivalent to a signed | 140 | // We tacitly assume the behavior is equivalent to a signed |
| 133 | // arithmetic right shift. | 141 | // arithmetic right shift. |
| 134 | return x >> n; | 142 | return x >> n; |
| 135 | } | 143 | } |
| 136 | 144 | ||
| 137 | JAS_ATTRIBUTE_CONST | 145 | JAS_ATTRIBUTE_CONST |
| 138 | JAS_ATTRIBUTE_DISABLE_USAN | 146 | JAS_ATTRIBUTE_DISABLE_UBSAN |
| 139 | inline static int jas_int_asl(int x, unsigned n) | 147 | inline static int jas_int_asl(int x, unsigned n) |
| 140 | { | 148 | { |
| 141 | // Ensure that the shift of a negative value appears to behave as a | 149 | // Ensure that the shift of a negative value appears to behave as a |
| 142 | // signed arithmetic shift. | 150 | // signed arithmetic shift. |
| 143 | assert(((-1) << 1) == -2); | 151 | assert(((-1) << 1) == -2); |
| 144 | // The behavior is undefined when x is negative. */ | 152 | // The behavior is undefined when x is negative. |
| 145 | // We tacitly assume the behavior is equivalent to a signed | 153 | // We tacitly assume the behavior is equivalent to a signed |
| 146 | // arithmetic left shift. | 154 | // arithmetic left shift. |
| 147 | return x << n; | 155 | return x << n; |
| 148 | } | 156 | } |
| 149 | 157 | ||
| 150 | JAS_ATTRIBUTE_CONST | 158 | JAS_ATTRIBUTE_CONST |
| 151 | JAS_ATTRIBUTE_DISABLE_USAN | 159 | JAS_ATTRIBUTE_DISABLE_UBSAN |
| 152 | inline static int_least32_t jas_least32_asr(int_least32_t x, unsigned n) | 160 | inline static int_least32_t jas_least32_asr(int_least32_t x, unsigned n) |
| 153 | { | 161 | { |
| 154 | // Ensure that the shift of a negative value appears to behave as a | 162 | // Ensure that the shift of a negative value appears to behave as a |
| 155 | // signed arithmetic shift. | 163 | // signed arithmetic shift. |
| 156 | assert(((JAS_CAST(int_least32_t, -1)) >> 1) == JAS_CAST(int_least32_t, -1)); | 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 | // We tacitly assume the behavior is equivalent to a signed | 166 | // We tacitly assume the behavior is equivalent to a signed |
| 159 | // arithmetic right shift. | 167 | // arithmetic right shift. |
| 160 | return x >> n; | 168 | return x >> n; |
| 161 | } | 169 | } |
| 162 | 170 | ||
| 163 | JAS_ATTRIBUTE_CONST | 171 | JAS_ATTRIBUTE_CONST |
| 164 | JAS_ATTRIBUTE_DISABLE_USAN | 172 | JAS_ATTRIBUTE_DISABLE_UBSAN |
| 165 | inline static int_least32_t jas_least32_asl(int_least32_t x, unsigned n) | 173 | inline static int_least32_t jas_least32_asl(int_least32_t x, unsigned n) |
| 166 | { | 174 | { |
| 167 | // Ensure that the shift of a negative value appears to behave as a | 175 | // Ensure that the shift of a negative value appears to behave as a |
| 168 | // signed arithmetic shift. | 176 | // signed arithmetic shift. |
| 169 | assert(((JAS_CAST(int_least32_t, -1)) << 1) == JAS_CAST(int_least32_t, -2)); | 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 | // We tacitly assume the behavior is equivalent to a signed | 179 | // We tacitly assume the behavior is equivalent to a signed |
| 172 | // arithmetic left shift. | 180 | // arithmetic left shift. |
| 173 | return x << n; | 181 | return x << n; |
| 174 | } | 182 | } |
| 175 | 183 | ||
| 176 | JAS_ATTRIBUTE_CONST | 184 | JAS_ATTRIBUTE_CONST |
| 177 | JAS_ATTRIBUTE_DISABLE_USAN | 185 | JAS_ATTRIBUTE_DISABLE_UBSAN |
| 178 | inline static int_fast32_t jas_fast32_asr(int_fast32_t x, unsigned n) | 186 | inline static int_fast32_t jas_fast32_asr(int_fast32_t x, unsigned n) |
| 179 | { | 187 | { |
| 180 | // Ensure that the shift of a negative value appears to behave as a | 188 | // Ensure that the shift of a negative value appears to behave as a |
| 181 | // signed arithmetic shift. | 189 | // signed arithmetic shift. |
| 182 | assert(((JAS_CAST(int_fast32_t, -1)) >> 1) == JAS_CAST(int_fast32_t, -1)); | 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 | // We tacitly assume the behavior is equivalent to a signed | 192 | // We tacitly assume the behavior is equivalent to a signed |
| 185 | // arithmetic right shift. | 193 | // arithmetic right shift. |
| 186 | return x >> n; | 194 | return x >> n; |
| 187 | } | 195 | } |
| 188 | 196 | ||
| 189 | JAS_ATTRIBUTE_CONST | 197 | JAS_ATTRIBUTE_CONST |
| 190 | JAS_ATTRIBUTE_DISABLE_USAN | 198 | JAS_ATTRIBUTE_DISABLE_UBSAN |
| 191 | inline static int_fast32_t jas_fast32_asl(int_fast32_t x, unsigned n) | 199 | inline static int_fast32_t jas_fast32_asl(int_fast32_t x, unsigned n) |
| 192 | { | 200 | { |
| 193 | // Ensure that the shift of a negative value appears to behave as a | 201 | // Ensure that the shift of a negative value appears to behave as a |
| 194 | // signed arithmetic shift. | 202 | // signed arithmetic shift. |
| 195 | assert(((JAS_CAST(int_fast32_t, -1)) << 1) == JAS_CAST(int_fast32_t, -2)); | 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 | // We tacitly assume the behavior is equivalent to a signed | 205 | // We tacitly assume the behavior is equivalent to a signed |
| 198 | // arithmetic left shift. | 206 | // arithmetic left shift. |
| 199 | return x << n; | 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 | /* Compute the product of two size_t integers with overflow checking. */ | 218 | /* Compute the product of two size_t integers with overflow checking. */ |
| 211 | inline static bool jas_safe_size_mul(size_t x, size_t y, size_t *result) | 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 | size_t result_buffer; | 222 | size_t result_buffer; |
| 215 | if (!result) | 223 | bool valid = !__builtin_mul_overflow(x, y, &result_buffer); |
| 216 | result = &result_buffer; | 224 | if (valid && result) { |
| 217 | return !__builtin_mul_overflow(x, y, result); | 225 | *result = result_buffer; |
| 226 | } | ||
| 227 | return valid; | ||
| 218 | #else | 228 | #else |
| 219 | /* Check if overflow would occur */ | 229 | /* Check if overflow would occur */ |
| 220 | if (x && y > SIZE_MAX / x) { | 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 | /* Compute the sum of two size_t integers with overflow checking. */ | 256 | /* Compute the sum of two size_t integers with overflow checking. */ |
| 247 | inline static bool jas_safe_size_add(size_t x, size_t y, size_t *result) | 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 | size_t result_buffer; | 260 | size_t result_buffer; |
| 251 | if (!result) | 261 | bool valid = !__builtin_add_overflow(x, y, &result_buffer); |
| 252 | result = &result_buffer; | 262 | if (valid && result) { |
| 253 | return !__builtin_add_overflow(x, y, result); | 263 | *result = result_buffer; |
| 264 | } | ||
| 265 | return valid; | ||
| 254 | #else | 266 | #else |
| 255 | if (y > SIZE_MAX - x) { | 267 | if (y > SIZE_MAX - x) { |
| 256 | return false; | 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 | /* Compute the difference of two size_t integers with overflow checking. */ | 277 | /* Compute the difference of two size_t integers with overflow checking. */ |
| 266 | inline static bool jas_safe_size_sub(size_t x, size_t y, size_t *result) | 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 | size_t result_buffer; | 281 | size_t result_buffer; |
| 270 | if (!result) | 282 | bool valid = !__builtin_sub_overflow(x, y, &result_buffer); |
| 271 | result = &result_buffer; | 283 | if (valid && result) { |
| 272 | return !__builtin_sub_overflow(x, y, result); | 284 | *result = result_buffer; |
| 285 | } | ||
| 286 | return valid; | ||
| 273 | #else | 287 | #else |
| 274 | if (y > x) { | 288 | if (y > x) { |
| 275 | return false; | 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 | inline static bool jas_safe_intfast32_mul(int_fast32_t x, int_fast32_t y, | 299 | inline static bool jas_safe_intfast32_mul(int_fast32_t x, int_fast32_t y, |
| 286 | int_fast32_t *result) | 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 | int_fast32_t result_buffer; | 303 | int_fast32_t result_buffer; |
| 290 | if (!result) | 304 | bool valid = !__builtin_mul_overflow(x, y, &result_buffer); |
| 291 | result = &result_buffer; | 305 | if (valid && result) { |
| 292 | return !__builtin_mul_overflow(x, y, result); | 306 | *result = result_buffer; |
| 307 | } | ||
| 308 | return valid; | ||
| 293 | #else | 309 | #else |
| 294 | if (x > 0) { | 310 | if (x > 0) { |
| 295 | /* x is positive */ | 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 | inline static bool jas_safe_intfast32_add(int_fast32_t x, int_fast32_t y, | 360 | inline static bool jas_safe_intfast32_add(int_fast32_t x, int_fast32_t y, |
| 345 | int_fast32_t *result) | 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 | int_fast32_t result_buffer; | 364 | int_fast32_t result_buffer; |
| 349 | if (!result) | 365 | bool valid = !__builtin_add_overflow(x, y, &result_buffer); |
| 350 | result = &result_buffer; | 366 | if (valid && result) { |
| 351 | return !__builtin_add_overflow(x, y, result); | 367 | *result = result_buffer; |
| 368 | } | ||
| 369 | return valid; | ||
| 352 | #else | 370 | #else |
| 353 | if ((y > 0 && x > INT_FAST32_MAX - y) || | 371 | if ((y > 0 && x > INT_FAST32_MAX - y) || |
| 354 | (y < 0 && x < INT_FAST32_MIN - y)) { | 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 | #endif | 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 | #ifdef __cplusplus | 733 | #ifdef __cplusplus |
| 365 | } | 734 | } |
| 366 | #endif | 735 | #endif |
| @@ -77,12 +77,18 @@ · 76 unmodified lines | |||
| 77 | #include <jasper/jas_config.h> /* IWYU pragma: keep */ | 77 | #include <jasper/jas_config.h> /* IWYU pragma: keep */ |
| 78 | 78 | ||
| 79 | #include <jasper/jas_types.h> | 79 | #include <jasper/jas_types.h> |
| 80 | #include <jasper/jas_fix.h> | ||
| 80 | #include <jasper/jas_math.h> | 81 | #include <jasper/jas_math.h> |
| 81 | 82 | ||
| 82 | #ifdef __cplusplus | 83 | #ifdef __cplusplus |
| 83 | extern "C" { | 84 | extern "C" { |
| 84 | #endif | 85 | #endif |
| 85 | 86 | ||
| 87 | /*! | ||
| 88 | * @addtogroup module_seq | ||
| 89 | * @{ | ||
| 90 | */ | ||
| 91 | |||
| 86 | /******************************************************************************\ | 92 | /******************************************************************************\ |
| 87 | * Constants. | 93 | * Constants. |
| 88 | \******************************************************************************/ | 94 | \******************************************************************************/ |
| @@ -95,29 +101,17 @@ extern "C" { · 6 unmodified lines | |||
| 95 | \******************************************************************************/ | 101 | \******************************************************************************/ |
| 96 | 102 | ||
| 97 | /* An element in a sequence. */ | 103 | /* An element in a sequence. */ |
| 98 | #ifdef JAS_ENABLE_32BIT | 104 | typedef jas_fix_t jas_seqent_t; |
| 99 | typedef int_least32_t jas_seqent_t; | 105 | #define PRIjas_seqent PRIjas_fix |
| 100 | #define PRIjas_seqent PRIiLEAST32 | ||
| 101 | #else | ||
| 102 | typedef int_fast32_t jas_seqent_t; | ||
| 103 | #define PRIjas_seqent PRIiFAST32 | ||
| 104 | #endif | ||
| 105 | 106 | ||
| 106 | /* An element in a matrix. */ | 107 | /* An element in a matrix. */ |
| 107 | #ifdef JAS_ENABLE_32BIT | 108 | typedef jas_fix_t jas_matent_t; |
| 108 | typedef int_least32_t jas_matent_t; | ||
| 109 | #else | ||
| 110 | typedef int_fast32_t jas_matent_t; | ||
| 111 | #endif | ||
| 112 | 109 | ||
| 113 | #ifdef JAS_ENABLE_32BIT | 110 | typedef jas_fix_t jas_matind_t; |
| 114 | typedef int_least32_t jas_matind_t; | ||
| 115 | #else | ||
| 116 | typedef int_fast32_t jas_matind_t; | ||
| 117 | #endif | ||
| 118 | |||
| 119 | /* Matrix. */ | ||
| 120 | 111 | ||
| 112 | /*! | ||
| 113 | @brief Matrix type. | ||
| 114 | */ | ||
| 121 | typedef struct { | 115 | typedef struct { |
| 122 | 116 | ||
| 123 | /* Additional state information. */ | 117 | /* Additional state information. */ |
| @@ -155,53 +149,86 @@ typedef struct { · 31 unmodified lines | |||
| 155 | 149 | ||
| 156 | } jas_matrix_t; | 150 | } jas_matrix_t; |
| 157 | 151 | ||
| 152 | /*! | ||
| 153 | @struct jas_seq2d_t | ||
| 154 | @brief Two-dimensional sequence type. | ||
| 155 | */ | ||
| 158 | typedef jas_matrix_t jas_seq2d_t; | 156 | typedef jas_matrix_t jas_seq2d_t; |
| 157 | |||
| 158 | /*! | ||
| 159 | @struct jas_seq_t | ||
| 160 | @brief One-dimensional sequence type. | ||
| 161 | */ | ||
| 159 | typedef jas_matrix_t jas_seq_t; | 162 | typedef jas_matrix_t jas_seq_t; |
| 160 | 163 | ||
| 161 | /******************************************************************************\ | 164 | /******************************************************************************\ |
| 162 | * Functions/macros for matrix class. | 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 | JAS_ATTRIBUTE_PURE | 172 | JAS_ATTRIBUTE_PURE |
| 167 | static inline jas_matind_t jas_matrix_numrows(const jas_matrix_t *matrix) | 173 | static inline jas_matind_t jas_matrix_numrows(const jas_matrix_t *matrix) |
| 168 | { | 174 | { |
| 169 | return matrix->numrows_; | 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 | JAS_ATTRIBUTE_PURE | 181 | JAS_ATTRIBUTE_PURE |
| 174 | static inline jas_matind_t jas_matrix_numcols(const jas_matrix_t *matrix) | 182 | static inline jas_matind_t jas_matrix_numcols(const jas_matrix_t *matrix) |
| 175 | { | 183 | { |
| 176 | return matrix->numcols_; | 184 | return matrix->numcols_; |
| 177 | } | 185 | } |
| 178 | 186 | ||
| 187 | /*! | ||
| 188 | @brief | ||
| 189 | Get the number of elements in a matrix. | ||
| 190 | */ | ||
| 179 | JAS_ATTRIBUTE_PURE | 191 | JAS_ATTRIBUTE_PURE |
| 180 | static inline jas_matind_t jas_matrix_size(const jas_matrix_t *matrix) | 192 | static inline jas_matind_t jas_matrix_size(const jas_matrix_t *matrix) |
| 181 | { | 193 | { |
| 182 | return jas_matrix_numcols(matrix) * jas_matrix_numrows(matrix); | 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 | JAS_ATTRIBUTE_PURE | 201 | JAS_ATTRIBUTE_PURE |
| 186 | static inline bool jas_matrix_empty(const jas_matrix_t *matrix) | 202 | static inline bool jas_matrix_empty(const jas_matrix_t *matrix) |
| 187 | { | 203 | { |
| 188 | return jas_matrix_numcols(matrix) == 0 || jas_matrix_numrows(matrix) == 0; | 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 | JAS_ATTRIBUTE_PURE | 211 | JAS_ATTRIBUTE_PURE |
| 193 | static inline jas_seqent_t jas_matrix_get(const jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j) | 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 | return matrix->rows_[i][j]; | 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 | static inline void jas_matrix_set(jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j, jas_seqent_t v) | 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 | matrix->rows_[i][j] = v; | 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 | JAS_ATTRIBUTE_PURE | 232 | JAS_ATTRIBUTE_PURE |
| 206 | static inline jas_seqent_t jas_matrix_getv(const jas_matrix_t *matrix, jas_matind_t i) | 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 | : matrix->rows_[i][0]; | 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 | static inline void jas_matrix_setv(jas_matrix_t *matrix, jas_matind_t i, jas_seqent_t v) | 244 | static inline void jas_matrix_setv(jas_matrix_t *matrix, jas_matind_t i, jas_seqent_t v) |
| 215 | { | 245 | { |
| 216 | if (matrix->numrows_ == 1) | 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 | matrix->rows_[i][0] = v; | 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 | JAS_ATTRIBUTE_PURE | 256 | JAS_ATTRIBUTE_PURE |
| 224 | static inline jas_seqent_t *jas_matrix_getref(const jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j) | 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 | return &matrix->rows_[i][j]; | 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 | JAS_ATTRIBUTE_PURE | 266 | JAS_ATTRIBUTE_PURE |
| 230 | static inline jas_seqent_t *jas_matrix_getvref(const jas_matrix_t *matrix, jas_matind_t i) | 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 | : jas_matrix_getref(matrix, 0, i); | 271 | : jas_matrix_getref(matrix, 0, i); |
| 235 | } | 272 | } |
| 236 | 273 | ||
| 237 | /* Create a matrix with the specified dimensions. */ | 274 | /*! |
| 238 | JAS_DLLEXPORT jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols); | 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. */ | 281 | /*! |
| 241 | JAS_DLLEXPORT void jas_matrix_destroy(jas_matrix_t *matrix); | 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. */ | 288 | /*! |
| 244 | JAS_DLLEXPORT int jas_matrix_resize(jas_matrix_t *matrix, jas_matind_t numrows, jas_matind_t numcols); | 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. */ | 302 | /*! |
| 249 | JAS_DLLEXPORT int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r0, | 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 | jas_matind_t c0, jas_matind_t r1, jas_matind_t c1); | 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 | static inline int jas_matrix_bindrow(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r) | 314 | static inline int jas_matrix_bindrow(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r) |
| 254 | { | 315 | { |
| 255 | return jas_matrix_bindsub(mat0, mat1, r, 0, r, mat1->numcols_ - 1); | 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 | static inline int jas_matrix_bindcol(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t c) | 323 | static inline int jas_matrix_bindcol(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t c) |
| 260 | { | 324 | { |
| 261 | return jas_matrix_bindsub(mat0, mat1, 0, c, mat1->numrows_ - 1, c); | 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. */ | 328 | /*! |
| 265 | JAS_DLLEXPORT void jas_matrix_clip(jas_matrix_t *matrix, jas_seqent_t minval, | 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 | jas_seqent_t maxval); | 334 | jas_seqent_t maxval); |
| 267 | 335 | ||
| 268 | /* Arithmetic shift left of all elements in a matrix. */ | 336 | /*! |
| 269 | JAS_DLLEXPORT void jas_matrix_asl(jas_matrix_t *matrix, unsigned n); | 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. */ | 343 | /*! |
| 272 | JAS_DLLEXPORT void jas_matrix_asr(jas_matrix_t *matrix, unsigned n); | 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. */ | 350 | /*! |
| 275 | JAS_DLLEXPORT void jas_matrix_divpow2(jas_matrix_t *matrix, unsigned n); | 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. */ | 357 | /*! |
| 278 | JAS_DLLEXPORT void jas_matrix_setall(jas_matrix_t *matrix, jas_seqent_t val); | 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 | JAS_ATTRIBUTE_PURE | 368 | JAS_ATTRIBUTE_PURE |
| 282 | static inline size_t jas_matrix_rowstep(const jas_matrix_t *matrix) | 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 | : 0u; | 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 | JAS_ATTRIBUTE_PURE | 380 | JAS_ATTRIBUTE_PURE |
| 291 | static inline size_t jas_matrix_step(const jas_matrix_t *matrix) | 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 | : 1; | 385 | : 1; |
| 296 | } | 386 | } |
| 297 | 387 | ||
| 298 | /* Compare two matrices for equality. */ | 388 | /*! |
| 299 | JAS_DLLEXPORT int jas_matrix_cmp(jas_matrix_t *mat0, jas_matrix_t *mat1); | 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 | JAS_ATTRIBUTE_CONST | 412 | JAS_ATTRIBUTE_CONST |
| 306 | static inline jas_seqent_t jas_seqent_asl(jas_seqent_t x, unsigned n) | 413 | static inline jas_seqent_t jas_seqent_asl(jas_seqent_t x, unsigned n) |
| 307 | { | 414 | { |
| 415 | #if 0 | ||
| 308 | #ifdef JAS_ENABLE_32BIT | 416 | #ifdef JAS_ENABLE_32BIT |
| 309 | return jas_least32_asl(x, n); | 417 | return jas_least32_asl(x, n); |
| 310 | #else | 418 | #else |
| 311 | return jas_fast32_asl(x, n); | 419 | return jas_fast32_asl(x, n); |
| 312 | #endif | 420 | #endif |
| 421 | #endif | ||
| 422 | return jas_fix_asl(x, n); | ||
| 313 | } | 423 | } |
| 314 | 424 | ||
| 425 | /*! | ||
| 426 | @brief | ||
| 427 | */ | ||
| 315 | JAS_ATTRIBUTE_CONST | 428 | JAS_ATTRIBUTE_CONST |
| 316 | static inline jas_seqent_t jas_seqent_asr(jas_seqent_t x, unsigned n) | 429 | static inline jas_seqent_t jas_seqent_asr(jas_seqent_t x, unsigned n) |
| 317 | { | 430 | { |
| 431 | #if 0 | ||
| 318 | #ifdef JAS_ENABLE_32BIT | 432 | #ifdef JAS_ENABLE_32BIT |
| 319 | return jas_least32_asr(x, n); | 433 | return jas_least32_asr(x, n); |
| 320 | #else | 434 | #else |
| 321 | return jas_fast32_asr(x, n); | 435 | return jas_fast32_asr(x, n); |
| 322 | #endif | 436 | #endif |
| 437 | #endif | ||
| 438 | return jas_fix_asr(x, n); | ||
| 323 | } | 439 | } |
| 324 | 440 | ||
| 325 | /******************************************************************************\ | 441 | /******************************************************************************\ |
| 326 | * Functions/macros for 2-D sequence class. | 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 | jas_matind_t xend, jas_matind_t yend); | 458 | jas_matind_t xend, jas_matind_t yend); |
| 333 | 459 | ||
| 460 | /*! | ||
| 461 | @brief | ||
| 462 | Destroy a 2-D sequence. | ||
| 463 | */ | ||
| 334 | static inline void jas_seq2d_destroy(jas_seq2d_t *s) | 464 | static inline void jas_seq2d_destroy(jas_seq2d_t *s) |
| 335 | { | 465 | { |
| 336 | jas_matrix_destroy(s); | 466 | jas_matrix_destroy(s); |
| 337 | } | 467 | } |
| 338 | 468 | ||
| 469 | /*! | ||
| 470 | @brief | ||
| 471 | Get the starting x-coordinate of the sequence. | ||
| 472 | */ | ||
| 339 | JAS_ATTRIBUTE_PURE | 473 | JAS_ATTRIBUTE_PURE |
| 340 | static inline jas_matind_t jas_seq2d_xstart(const jas_seq2d_t *s) | 474 | static inline jas_matind_t jas_seq2d_xstart(const jas_seq2d_t *s) |
| 341 | { | 475 | { |
| 342 | return s->xstart_; | 476 | return s->xstart_; |
| 343 | } | 477 | } |
| 344 | 478 | ||
| 479 | /*! | ||
| 480 | @brief | ||
| 481 | Get the starting y-coordinate of the sequence. | ||
| 482 | */ | ||
| 345 | JAS_ATTRIBUTE_PURE | 483 | JAS_ATTRIBUTE_PURE |
| 346 | static inline jas_matind_t jas_seq2d_ystart(const jas_seq2d_t *s) | 484 | static inline jas_matind_t jas_seq2d_ystart(const jas_seq2d_t *s) |
| 347 | { | 485 | { |
| 348 | return s->ystart_; | 486 | return s->ystart_; |
| 349 | } | 487 | } |
| 350 | 488 | ||
| 489 | /*! | ||
| 490 | @brief | ||
| 491 | Get the ending x-coordinate of the sequence. | ||
| 492 | */ | ||
| 351 | JAS_ATTRIBUTE_PURE | 493 | JAS_ATTRIBUTE_PURE |
| 352 | static inline jas_matind_t jas_seq2d_xend(const jas_seq2d_t *s) | 494 | static inline jas_matind_t jas_seq2d_xend(const jas_seq2d_t *s) |
| 353 | { | 495 | { |
| 354 | return s->xend_; | 496 | return s->xend_; |
| 355 | } | 497 | } |
| 356 | 498 | ||
| 499 | /*! | ||
| 500 | @brief | ||
| 501 | Get the ending y-coordinate of the sequence. | ||
| 502 | */ | ||
| 357 | JAS_ATTRIBUTE_PURE | 503 | JAS_ATTRIBUTE_PURE |
| 358 | static inline jas_matind_t jas_seq2d_yend(const jas_seq2d_t *s) | 504 | static inline jas_matind_t jas_seq2d_yend(const jas_seq2d_t *s) |
| 359 | { | 505 | { |
| 360 | return s->yend_; | 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 | JAS_ATTRIBUTE_PURE | 513 | JAS_ATTRIBUTE_PURE |
| 364 | static inline jas_seqent_t *jas_seq2d_getref(const jas_seq2d_t *s, jas_matind_t x, jas_matind_t y) | 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 | return jas_matrix_getref(s, y - s->ystart_, x - s->xstart_); | 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 | JAS_ATTRIBUTE_PURE | 523 | JAS_ATTRIBUTE_PURE |
| 370 | static inline jas_seqent_t jas_seq2d_get(const jas_seq2d_t *s, jas_matind_t x, jas_matind_t y) | 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 | return jas_matrix_get(s, y - s->ystart_, x - s->xstart_); | 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 | JAS_ATTRIBUTE_PURE | 533 | JAS_ATTRIBUTE_PURE |
| 376 | static inline size_t jas_seq2d_rowstep(const jas_seq2d_t *s) | 534 | static inline size_t jas_seq2d_rowstep(const jas_seq2d_t *s) |
| 377 | { | 535 | { |
| 378 | return jas_matrix_rowstep(s); | 536 | return jas_matrix_rowstep(s); |
| 379 | } | 537 | } |
| 380 | 538 | ||
| 539 | /*! | ||
| 540 | @brief | ||
| 541 | Get the number of columns in the sequence. | ||
| 542 | */ | ||
| 381 | JAS_ATTRIBUTE_PURE | 543 | JAS_ATTRIBUTE_PURE |
| 382 | static inline unsigned jas_seq2d_width(const jas_seq2d_t *s) | 544 | static inline unsigned jas_seq2d_width(const jas_seq2d_t *s) |
| 383 | { | 545 | { |
| 384 | return (unsigned)(s->xend_ - s->xstart_); | 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 | JAS_ATTRIBUTE_PURE | 553 | JAS_ATTRIBUTE_PURE |
| 388 | static inline unsigned jas_seq2d_height(const jas_seq2d_t *s) | 554 | static inline unsigned jas_seq2d_height(const jas_seq2d_t *s) |
| 389 | { | 555 | { |
| 390 | return (unsigned)(s->yend_ - s->ystart_); | 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 | static inline void jas_seq2d_setshift(jas_seq2d_t *s, jas_matind_t x, jas_matind_t y) | 563 | static inline void jas_seq2d_setshift(jas_seq2d_t *s, jas_matind_t x, jas_matind_t y) |
| 394 | { | 564 | { |
| 395 | s->xstart_ = x; | 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 | s->yend_ = s->ystart_ + s->numrows_; | 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 | JAS_ATTRIBUTE_PURE | 575 | JAS_ATTRIBUTE_PURE |
| 402 | static inline jas_matind_t jas_seq2d_size(const jas_seq2d_t *s) | 576 | static inline jas_matind_t jas_seq2d_size(const jas_seq2d_t *s) |
| 403 | { | 577 | { |
| 404 | return jas_seq2d_width(s) * jas_seq2d_height(s); | 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 | JAS_ATTRIBUTE_PURE | 585 | JAS_ATTRIBUTE_PURE |
| 408 | static inline bool jas_seq2d_empty(const jas_seq2d_t *s) | 586 | static inline bool jas_seq2d_empty(const jas_seq2d_t *s) |
| 409 | { | 587 | { |
| 410 | return jas_seq2d_width(s) == 0 || jas_seq2d_height(s) == 0; | 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 | jas_matind_t ystart, jas_matind_t xend, jas_matind_t yend); | 597 | jas_matind_t ystart, jas_matind_t xend, jas_matind_t yend); |
| 415 | 598 | ||
| 416 | /******************************************************************************\ | 599 | /******************************************************************************\ |
| 417 | * Functions/macros for 1-D sequence class. | 600 | * Functions/macros for 1-D sequence class. |
| 418 | \******************************************************************************/ | 601 | \******************************************************************************/ |
| 419 | 602 | ||
| 603 | /*! | ||
| 604 | @brief | ||
| 605 | Create a 1-D sequence. | ||
| 606 | */ | ||
| 420 | static inline jas_seq_t *jas_seq_create(jas_matind_t start, jas_matind_t end) | 607 | static inline jas_seq_t *jas_seq_create(jas_matind_t start, jas_matind_t end) |
| 421 | { | 608 | { |
| 422 | return jas_seq2d_create(start, 0, end, 1); | 609 | return jas_seq2d_create(start, 0, end, 1); |
| 423 | } | 610 | } |
| 424 | 611 | ||
| 612 | /*! | ||
| 613 | @brief | ||
| 614 | Destroy a 1-D sequence. | ||
| 615 | */ | ||
| 425 | static inline void jas_seq_destroy(jas_seq_t *seq) | 616 | static inline void jas_seq_destroy(jas_seq_t *seq) |
| 426 | { | 617 | { |
| 427 | jas_seq2d_destroy(seq); | 618 | jas_seq2d_destroy(seq); |
| 428 | } | 619 | } |
| 429 | 620 | ||
| 621 | /*! | ||
| 622 | @brief | ||
| 623 | Set an element of a sequence. | ||
| 624 | */ | ||
| 430 | static inline void jas_seq_set(jas_seq_t *seq, jas_matind_t i, jas_seqent_t v) | 625 | static inline void jas_seq_set(jas_seq_t *seq, jas_matind_t i, jas_seqent_t v) |
| 431 | { | 626 | { |
| 432 | seq->rows_[0][i - seq->xstart_] = v; | 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 | JAS_ATTRIBUTE_PURE | 634 | JAS_ATTRIBUTE_PURE |
| 436 | static inline jas_seqent_t *jas_seq_getref(const jas_seq_t *seq, jas_matind_t i) | 635 | static inline jas_seqent_t *jas_seq_getref(const jas_seq_t *seq, jas_matind_t i) |
| 437 | { | 636 | { |
| 438 | return &seq->rows_[0][i - seq->xstart_]; | 637 | return &seq->rows_[0][i - seq->xstart_]; |
| 439 | } | 638 | } |
| 440 | 639 | ||
| 640 | /*! | ||
| 641 | @brief | ||
| 642 | Get an element of a sequence. | ||
| 643 | */ | ||
| 441 | JAS_ATTRIBUTE_PURE | 644 | JAS_ATTRIBUTE_PURE |
| 442 | static inline jas_seqent_t jas_seq_get(const jas_seq_t *seq, jas_matind_t i) | 645 | static inline jas_seqent_t jas_seq_get(const jas_seq_t *seq, jas_matind_t i) |
| 443 | { | 646 | { |
| 444 | return seq->rows_[0][i - seq->xstart_]; | 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 | JAS_ATTRIBUTE_PURE | 654 | JAS_ATTRIBUTE_PURE |
| 448 | static inline jas_matind_t jas_seq_start(const jas_seq_t *seq) | 655 | static inline jas_matind_t jas_seq_start(const jas_seq_t *seq) |
| 449 | { | 656 | { |
| 450 | return seq->xstart_; | 657 | return seq->xstart_; |
| 451 | } | 658 | } |
| 452 | 659 | ||
| 660 | /*! | ||
| 661 | @brief | ||
| 662 | Get the ending index of a sequence. | ||
| 663 | */ | ||
| 453 | JAS_ATTRIBUTE_PURE | 664 | JAS_ATTRIBUTE_PURE |
| 454 | static inline jas_matind_t jas_seq_end(const jas_seq_t *seq) | 665 | static inline jas_matind_t jas_seq_end(const jas_seq_t *seq) |
| 455 | { | 666 | { |
| 456 | return seq->xend_; | 667 | return seq->xend_; |
| 457 | } | 668 | } |
| 458 | 669 | ||
| 670 | /*! | ||
| 671 | * @} | ||
| 672 | */ | ||
| 673 | |||
| 459 | #ifdef __cplusplus | 674 | #ifdef __cplusplus |
| 460 | } | 675 | } |
| 461 | #endif | 676 | #endif |
| @@ -75,6 +75,10 @@ · 74 unmodified lines | |||
| 75 | 75 | ||
| 76 | /* The configuration header file should be included first. */ | 76 | /* The configuration header file should be included first. */ |
| 77 | #include <jasper/jas_config.h> /* IWYU pragma: export */ | 77 | #include <jasper/jas_config.h> /* IWYU pragma: export */ |
| 78 | |||
| 79 | #if defined(JAS_HAVE_FCNTL_H) | ||
| 80 | #include <fcntl.h> | ||
| 81 | #endif | ||
| 78 | #include <jasper/jas_types.h> | 82 | #include <jasper/jas_types.h> |
| 79 | 83 | ||
| 80 | #ifdef __cplusplus | 84 | #ifdef __cplusplus |
| @@ -82,7 +86,7 @@ extern "C" { · 1 unmodified line | |||
| 82 | #endif | 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 | #define O_BINARY 0 | 99 | #define O_BINARY 0 |
| 96 | #endif | 100 | #endif |
| 97 | 101 | ||
| 98 | #define EOF (-1) | ||
| 99 | |||
| 100 | /* | 102 | /* |
| 101 | * Stream open flags. | 103 | * Stream open flags. |
| 102 | */ | 104 | */ |
| @@ -176,10 +178,10 @@ typedef void jas_stream_obj_t; · 73 unmodified lines | |||
| 176 | typedef struct { | 178 | typedef struct { |
| 177 | 179 | ||
| 178 | /* Read characters from a file object. */ | 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 | /* Write characters to a file object. */ | 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 | /* Set the position for a file object. */ | 186 | /* Set the position for a file object. */ |
| 185 | long (*seek_)(jas_stream_obj_t *obj, long offset, int origin); | 187 | long (*seek_)(jas_stream_obj_t *obj, long offset, int origin); |
| @@ -189,8 +191,15 @@ typedef struct { · 3 unmodified lines | |||
| 189 | 191 | ||
| 190 | } jas_stream_ops_t; | 192 | } jas_stream_ops_t; |
| 191 | 193 | ||
| 192 | /* | 194 | /*! |
| 193 | * Stream object. | 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 | typedef struct { | 205 | typedef struct { |
| @@ -248,6 +257,7 @@ typedef struct { · 51 unmodified lines | |||
| 248 | typedef struct { | 257 | typedef struct { |
| 249 | int fd; | 258 | int fd; |
| 250 | int flags; | 259 | int flags; |
| 260 | char pathname[L_tmpnam + 1]; | ||
| 251 | } jas_stream_fileobj_t; | 261 | } jas_stream_fileobj_t; |
| 252 | 262 | ||
| 253 | /* Delete underlying file object upon stream close. */ | 263 | /* Delete underlying file object upon stream close. */ |
| @@ -268,10 +278,10 @@ typedef struct { · 14 unmodified lines | |||
| 268 | size_t bufsize_; | 278 | size_t bufsize_; |
| 269 | 279 | ||
| 270 | /* The length of the file. */ | 280 | /* The length of the file. */ |
| 271 | uint_fast32_t len_; | 281 | size_t len_; |
| 272 | 282 | ||
| 273 | /* The seek position. */ | 283 | /* The seek position. */ |
| 274 | uint_fast32_t pos_; | 284 | size_t pos_; |
| 275 | 285 | ||
| 276 | /* Is the buffer growable? */ | 286 | /* Is the buffer growable? */ |
| 277 | int growable_; | 287 | int growable_; |
| @@ -299,7 +309,7 @@ C standard library. · 21 unmodified lines | |||
| 299 | Upon success, a pointer to the opened stream is returned. | 309 | Upon success, a pointer to the opened stream is returned. |
| 300 | Otherwise, a null pointer is returned. | 310 | Otherwise, a null pointer is returned. |
| 301 | */ | 311 | */ |
| 302 | JAS_DLLEXPORT | 312 | JAS_EXPORT |
| 303 | jas_stream_t *jas_stream_fopen(const char *filename, const char *mode); | 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 | buffer_size (which, in this case, is not currently allowed to be zero) is | 335 | buffer_size (which, in this case, is not currently allowed to be zero) is |
| 326 | the size of the (nongrowable) buffer pointed to by buffer. | 336 | the size of the (nongrowable) buffer pointed to by buffer. |
| 327 | </ul> | 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 | 339 | JAS_EXPORT |
| 340 | jas_stream_t *jas_stream_memopen(char *buffer, int buffer_size); | 340 | jas_stream_t *jas_stream_memopen(char *buffer, size_t buffer_size); |
| 341 | 341 | ||
| 342 | /*! | 342 | /*! |
| 343 | @warning | 343 | @brief |
| 344 | This function will be renamed jas_stream_memopen in a future release. | 344 | Do not use. |
| 345 | @deprecated | ||
| 345 | Do not use this function. | 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 | jas_stream_t *jas_stream_memopen2(char *buffer, size_t buffer_size); | 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 | Upon success, a pointer to the opened stream is returned. | 365 | Upon success, a pointer to the opened stream is returned. |
| 362 | Otherwise, a null pointer is returned. | 366 | Otherwise, a null pointer is returned. |
| 363 | */ | 367 | */ |
| 364 | JAS_DLLEXPORT | 368 | JAS_EXPORT |
| 365 | jas_stream_t *jas_stream_fdopen(int fd, const char *mode); | 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 | @brief Close a stream. | 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 | If no errors are encountered when closing the stream, 0 is returned. | 428 | If no errors are encountered when closing the stream, 0 is returned. |
| 383 | Otherwise, a nonzero value is returned. | 429 | Otherwise, a nonzero value is returned. |
| 384 | */ | 430 | */ |
| 385 | JAS_DLLEXPORT | 431 | JAS_EXPORT |
| 386 | int jas_stream_close(jas_stream_t *stream); | 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 | @brief Get the error indicator for a stream. | 452 | @brief Get the error indicator for a stream. |
| 453 | |||
| 407 | @param stream | 454 | @param stream |
| 408 | The stream whose error indicator is to be queried. | 455 | The stream whose error indicator is to be queried. |
| 409 | @return | 456 | @return |
| @@ -417,6 +464,7 @@ Note that EOF is not an error. · 7 unmodified lines | |||
| 417 | 464 | ||
| 418 | /*! | 465 | /*! |
| 419 | @brief Clear the error indicator for a stream. | 466 | @brief Clear the error indicator for a stream. |
| 467 | |||
| 420 | @param stream | 468 | @param stream |
| 421 | The stream whose error indicator is to be cleared. | 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 | @brief Set the read/write limit for a stream. | 491 | @brief Set the read/write limit for a stream. |
| 492 | |||
| 444 | @param stream | 493 | @param stream |
| 445 | A pointer to the stream whose read/write limit is to be set. | 494 | A pointer to the stream whose read/write limit is to be set. |
| 446 | @param rwlimit | 495 | @param rwlimit |
| @@ -453,7 +502,7 @@ A negative read/write limit is treated as if it were infinity · 6 unmodified lines | |||
| 453 | @return | 502 | @return |
| 454 | The old read/write limit is returned. | 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 | @brief Get the read/write count for a stream. | 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 | @brief Set the read/write count for a stream. | 521 | @brief Set the read/write count for a stream. |
| 522 | |||
| 473 | @param stream | 523 | @param stream |
| 474 | A pointer to the stream whose read/write count is to be set. | 524 | A pointer to the stream whose read/write count is to be set. |
| 475 | @param rw_count | 525 | @param rw_count |
| @@ -480,7 +530,8 @@ This operation cannot fail. · 4 unmodified lines | |||
| 480 | @todo | 530 | @todo |
| 481 | TODO/FIXME: Should this macro evaluate to void? | 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 | * Macros/functions for I/O. | 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 | @brief jas_stream_getc | 543 | @brief jas_stream_getc |
| 493 | Read a character from a stream. | 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 | #define jas_stream_getc(stream) jas_stream_getc_func(stream) | 553 | #define jas_stream_getc(stream) jas_stream_getc_func(stream) |
| 496 | #else | 554 | #else |
| @@ -502,6 +560,16 @@ Read a character from a stream. · 5 unmodified lines | |||
| 502 | /*! | 560 | /*! |
| 503 | @brief jas_stream_putc | 561 | @brief jas_stream_putc |
| 504 | Write a character to a stream. | 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 | #define jas_stream_putc(stream, c) jas_stream_putc_func(stream, c) | 574 | #define jas_stream_putc(stream, c) jas_stream_putc_func(stream, c) |
| 507 | #else | 575 | #else |
| @@ -525,6 +593,9 @@ stream @c stream into the buffer starting at @c buffer. · 17 unmodified lines | |||
| 525 | The number of characters read can be less than @c count, due to | 593 | The number of characters read can be less than @c count, due to |
| 526 | end-of-file (EOF) or an I/O error. | 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 | @return | 599 | @return |
| 529 | The number of characters read is returned. | 600 | The number of characters read is returned. |
| 530 | In the case that the number of characters read is less than @c count, | 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 | <li>a failure due to the read/write limit being exceeded | 606 | <li>a failure due to the read/write limit being exceeded |
| 536 | <li>EOF. | 607 | <li>EOF. |
| 537 | </ol> | 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 | 613 | @todo |
| 541 | TODO/FIXME/CHECK: jas_stream_error should be true if RWLIMIT exceeded? | 614 | TODO: should jas_stream_error be true if RWLIMIT exceeded? |
| 542 | or need a jas_stream_rwlimit predicate? | 615 | or maybe introduce 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. | ||
| 547 | */ | 616 | */ |
| 548 | JAS_DLLEXPORT | 617 | JAS_EXPORT |
| 549 | unsigned jas_stream_read(jas_stream_t *stream, void *buffer, unsigned count); | 618 | size_t jas_stream_read(jas_stream_t *stream, void *buffer, size_t count); |
| 550 | 619 | ||
| 551 | /*! | 620 | /*! |
| 552 | @brief Attempt to retrieve one or more pending characters of input | 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 | or EOF. | 638 | or EOF. |
| 570 | 639 | ||
| 571 | @warning | 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 | unsigned jas_stream_peek(jas_stream_t *stream, void *buffer, size_t count); | 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 | The number of characters written can be less than @c count due to | 661 | The number of characters written can be less than @c count due to |
| 591 | an I/O error or the read/write limit being exceeded. | 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 | @return | 667 | @return |
| 594 | Upon success, the number of characters successfully written is returned. | 668 | Upon success, the number of characters successfully written is returned. |
| 595 | If an error occurs, the value returned will be less than @c count. | 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 | <li>failure due to an I/O error | 673 | <li>failure due to an I/O error |
| 600 | <li>failure due to the read/write limit being exceeded | 674 | <li>failure due to the read/write limit being exceeded |
| 601 | </ol> | 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 | 677 | JAS_EXPORT |
| 609 | unsigned jas_stream_write(jas_stream_t *stream, const void *buffer, | 678 | size_t jas_stream_write(jas_stream_t *stream, const void *buffer, |
| 610 | unsigned count); | 679 | size_t count); |
| 611 | 680 | ||
| 612 | /*! | 681 | /*! |
| 613 | @brief Write formatted output to a stream. | 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 | I think that the return type of int is okay here. | 699 | I think that the return type of int is okay here. |
| 631 | It is consistent with printf and friends. | 700 | It is consistent with printf and friends. |
| 632 | */ | 701 | */ |
| 633 | JAS_DLLEXPORT | 702 | JAS_EXPORT |
| 634 | int jas_stream_printf(jas_stream_t *stream, const char *format, ...); | 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 | @details | 713 | @details |
| 645 | The null character is not output. | 714 | The null character is not output. |
| 646 | 715 | ||
| 716 | (This function is analogous to fputs for C standard library streams.) | ||
| 717 | |||
| 647 | @return | 718 | @return |
| 648 | Upon success, a nonnegative value is returned. | 719 | Upon success, a nonnegative value is returned. |
| 649 | Upon failure, a negative value is returned. | 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 | @brief Read a line of input from a stream. | 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 | Since the buffer may be too small to hold the input, | 738 | Since the buffer may be too small to hold the input, |
| 667 | this operation can fail due to attempted buffer overrun. | 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 | @return | 743 | @return |
| 670 | If the operation fails (e.g., due to an I/O error or attempted buffer overrun), | 744 | If the operation fails (e.g., due to an I/O error or attempted buffer overrun), |
| 671 | a null pointer is returned. | 745 | a null pointer is returned. |
| 672 | Otherwise, buffer is returned. | 746 | Otherwise, buffer is returned. |
| 673 | */ | 747 | */ |
| 674 | JAS_DLLEXPORT char * | 748 | JAS_EXPORT |
| 675 | jas_stream_gets(jas_stream_t *stream, char *buffer, int buffer_size); | 749 | char *jas_stream_gets(jas_stream_t *stream, char *buffer, int buffer_size); |
| 676 | 750 | ||
| 677 | /*! | 751 | /*! |
| 678 | @brief Look at the next character to be read from a stream without actually | 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 | Upon success, zero is returned. | 793 | Upon success, zero is returned. |
| 720 | If the specified character cannot be pushed back, a negative value is returned. | 794 | If the specified character cannot be pushed back, a negative value is returned. |
| 721 | */ | 795 | */ |
| 722 | JAS_DLLEXPORT int | 796 | JAS_EXPORT |
| 723 | jas_stream_ungetc(jas_stream_t *stream, int c); | 797 | int jas_stream_ungetc(jas_stream_t *stream, int c); |
| 724 | 798 | ||
| 725 | /******************************************************************************\ | 799 | /******************************************************************************\ |
| 726 | * Macros/functions for getting/setting the stream position. | 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 | positive value is returned. | 815 | positive value is returned. |
| 742 | Otherwise, 0 is returned. | 816 | Otherwise, 0 is returned. |
| 743 | */ | 817 | */ |
| 744 | JAS_ATTRIBUTE_PURE JAS_DLLEXPORT | 818 | JAS_EXPORT |
| 819 | JAS_ATTRIBUTE_PURE | ||
| 745 | int jas_stream_isseekable(jas_stream_t *stream); | 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 | Upon success, the new stream position is returned. | 838 | Upon success, the new stream position is returned. |
| 764 | Upon failure, a negative value is returned. | 839 | Upon failure, a negative value is returned. |
| 765 | */ | 840 | */ |
| 766 | JAS_DLLEXPORT | 841 | JAS_EXPORT |
| 767 | long jas_stream_seek(jas_stream_t *stream, long offset, int origin); | 842 | long jas_stream_seek(jas_stream_t *stream, long offset, int origin); |
| 768 | 843 | ||
| 769 | /*! | 844 | /*! |
| 770 | @brief Get the current position within the stream. | 845 | @brief Get the current position within the stream. |
| 846 | |||
| 771 | @param stream | 847 | @param stream |
| 772 | A pointer to the stream whose current position is to be queried. | 848 | A pointer to the stream whose current position is to be queried. |
| 773 | 849 | ||
| 774 | @details | 850 | @details |
| 775 | The current position of the stream is returned. | 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 | @return | 855 | @return |
| 778 | Upon success, the current stream position is returned. | 856 | Upon success, the current stream position is returned. |
| 779 | If an error is encountered, a negative value is returned. | 857 | If an error is encountered, a negative value is returned. |
| 780 | */ | 858 | */ |
| 781 | JAS_ATTRIBUTE_PURE JAS_DLLEXPORT | 859 | JAS_EXPORT |
| 782 | long jas_stream_tell(jas_stream_t *stream); | 860 | long jas_stream_tell(jas_stream_t *stream); |
| 783 | 861 | ||
| 784 | /*! | 862 | /*! |
| 785 | @brief Seek to the beginning of a stream. | 863 | @brief Seek to the beginning of a stream. |
| 864 | |||
| 786 | @param stream | 865 | @param stream |
| 787 | A pointer to the stream whose position is to be set. | 866 | A pointer to the stream whose position is to be set. |
| 867 | |||
| 788 | @details | 868 | @details |
| 789 | The stream position is set to the start of the stream. | 869 | The stream position is set to the start of the stream. |
| 790 | This function is equivalent to returning the value | 870 | This function is equivalent to returning the value |
| 791 | of jas_stream_seek(stream, 0, SEEK_SET). | 871 | of jas_stream_seek(stream, 0, SEEK_SET). |
| 872 | |||
| 873 | (This function is analogous to frewind for C standard library streams.) | ||
| 874 | |||
| 792 | @return | 875 | @return |
| 793 | Upon success, the new stream position is returned. | 876 | Upon success, the new stream position is returned. |
| 794 | Otherwise, a negative value is returned. | 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 | * Macros/functions for flushing. | 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 | @brief Flush any pending output to a stream. | 887 | @brief Flush any pending output to a stream. |
| 888 | |||
| 804 | @param stream | 889 | @param stream |
| 805 | A pointer to the stream for which output should be flushed. | 890 | A pointer to the stream for which output should be flushed. |
| 891 | |||
| 806 | @details | 892 | @details |
| 807 | The function flushes any buffered output to the underlying file object. | 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 | @return | 897 | @return |
| 809 | Upon success, zero is returned. | 898 | Upon success, zero is returned. |
| 810 | Otherwise, a negative value is returned. | 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 | * Miscellaneous macros/functions. | 905 | * Miscellaneous macros/functions. |
| @@ -828,14 +918,50 @@ The number of characters to copy. · 12 unmodified lines | |||
| 828 | @details | 918 | @details |
| 829 | The function copies the specified number of characters from the | 919 | The function copies the specified number of characters from the |
| 830 | source stream to the destination stream. | 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 | @return | 928 | @return |
| 833 | Upon success, 0 is returned; otherwise, -1 is returned. | 929 | Upon success, 0 is returned; otherwise, -1 is returned. |
| 834 | 930 | ||
| 835 | @todo | 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 | @brief Consume (i.e., discard) characters from stream. | 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 | will be less than count. | 981 | will be less than count. |
| 856 | To distinguish EOF from an I/O error, jas_stream_eof() and jas_stream_error() | 982 | To distinguish EOF from an I/O error, jas_stream_eof() and jas_stream_error() |
| 857 | can be used. | 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 | @brief Write a fill character multiple times to a stream. | 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 | returned. | 1005 | returned. |
| 882 | If this value is less than the specified count, an error must have | 1006 | If this value is less than the specified count, an error must have |
| 883 | occurred. | 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 | @brief Get the size of the file associated with the specified stream. | 1013 | @brief Get the size of the file associated with the specified stream. |
| 892 | 1014 | ||
| 893 | @param stream | 1015 | @param stream |
| 1016 | A pointer to the stream. | ||
| 894 | 1017 | ||
| 895 | @details | 1018 | @details |
| 896 | This function queries the size (i.e., length) of the underlying file object | 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 | Upon success, the size of the stream is returned. | 1024 | Upon success, the size of the stream is returned. |
| 902 | If an error occurs, a negative value is returned. | 1025 | If an error occurs, a negative value is returned. |
| 903 | 1026 | ||
| 904 | @warning | 1027 | @todo |
| 905 | TODO/FIXME: the return type should be ssize_t? | 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 | long jas_stream_length(jas_stream_t *stream); | 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 | /* These prototypes need to be here for the sake of the stream_getc and | 1041 | /* These prototypes need to be here for the sake of the stream_getc and |
| 918 | stream_putc macros. */ | 1042 | stream_putc macros. */ |
| 919 | /* Library users must not invoke these functions directly. */ | 1043 | /* Library users must not invoke these functions directly. */ |
| 920 | JAS_DLLEXPORT int jas_stream_fillbuf(jas_stream_t *stream, int getflag); | 1044 | JAS_EXPORT int jas_stream_fillbuf(jas_stream_t *stream, int getflag); |
| 921 | JAS_DLLEXPORT int jas_stream_flushbuf(jas_stream_t *stream, int c); | 1045 | JAS_EXPORT int jas_stream_flushbuf(jas_stream_t *stream, int c); |
| 922 | JAS_DLLEXPORT int jas_stream_getc_func(jas_stream_t *stream); | 1046 | JAS_EXPORT int jas_stream_getc_func(jas_stream_t *stream); |
| 923 | JAS_DLLEXPORT int jas_stream_putc_func(jas_stream_t *stream, int c); | 1047 | JAS_EXPORT int jas_stream_putc_func(jas_stream_t *stream, int c); |
| 924 | 1048 | ||
| 925 | /* Read a character from a stream. */ | 1049 | /* Read a character from a stream. */ |
| 926 | static inline int jas_stream_getc2(jas_stream_t *stream) | 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 | /* The configuration header file should be included first. */ | 72 | /* The configuration header file should be included first. */ |
| 73 | #include <jasper/jas_config.h> | 73 | #include <jasper/jas_config.h> |
| 74 | 74 | ||
| 75 | #define INT_MAX 0x7fffffff | 75 | #if defined(JAS_HAVE_SYS_TYPES_H) |
| 76 | #define UINT_FAST32_MAX 0xffffffff | 76 | #include <sys/types.h> /* IWYU pragma: export */ |
| 77 | #define SIZE_MAX UINT_FAST32_MAX | 77 | #endif |
| 78 | #define INT_FAST32_MIN ((s32int)0x80000000) | 78 | |
| 79 | #define INT_FAST32_MAX INT_MAX | 79 | #ifdef __cplusplus |
| 80 | #define LONG_MAX INT_MAX | 80 | extern "C" { |
| 81 | 81 | #endif | |
| 82 | typedef s8int int_least8_t; | 82 | |
| 83 | typedef s16int int_fast16_t; | 83 | #define jas_uchar unsigned char |
| 84 | typedef s32int int_fast32_t; | 84 | #define jas_uint unsigned int |
| 85 | typedef s32int int_least32_t; | 85 | #define jas_ulong unsigned long |
| 86 | typedef s64int int_fast64_t; | 86 | #define jas_longlong long long |
| 87 | 87 | #define jas_ulonglong unsigned long long | |
| 88 | typedef u8int uint_least8_t; | 88 | |
| 89 | typedef u8int uint_fast8_t; | 89 | #if !defined(JAS_NO_SET_SSIZE_T) |
| 90 | typedef u16int uint_fast16_t; | 90 | # if !defined(SSIZE_MAX) |
| 91 | typedef u16int uint_least16_t; | 91 | # if (JAS_SIZEOF_INT == JAS_SIZEOF_SIZE_T) |
| 92 | typedef u32int uint_fast32_t; | 92 | # define ssize_t int |
| 93 | typedef u32int uint_least32_t; | 93 | # define SSIZE_MAX INT_MAX |
| 94 | typedef u64int uint_least64_t; | 94 | # elif (JAS_SIZEOF_LONG == JAS_SIZEOF_SIZE_T) |
| 95 | typedef u64int uint_fast64_t; | 95 | # define ssize_t long |
| 96 | 96 | # define SSIZE_MAX LONG_MAX | |
| 97 | typedef unsigned char jas_uchar; | 97 | # else |
| 98 | typedef unsigned int jas_uint; | 98 | # define ssize_t jas_longlong |
| 99 | typedef unsigned long jas_ulong; | 99 | # define SSIZE_MAX LLONG_MAX |
| 100 | typedef long long jas_longlong; | 100 | # endif |
| 101 | typedef unsigned long long jas_ulonglong; | 101 | # endif |
| 102 | 102 | #endif | |
| 103 | typedef enum { false, true } bool; | 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 | #define PRIxFAST32 "x" | 119 | #define PRIxFAST32 "x" |
| 106 | #define PRIxFAST16 PRIxFAST32 | 120 | #define PRIxFAST16 PRIxFAST32 |
| 107 | #define PRIuFAST32 "u" | 121 | #define PRIuFAST32 "u" |
| 108 | #define PRIuFAST16 PRIuFAST32 | 122 | #define PRIuFAST16 PRIuFAST32 |
| 109 | #define PRIiFAST32 "i" | 123 | #define PRIiFAST32 "i" |
| 110 | #define PRIiLEAST32 PRIiFAST32 | 124 | #ifdef _WIN64 |
| 111 | #define PRIxLEAST16 "x" | 125 | #define PRIdPTR "lld" |
| 112 | #define PRIdPTR "lld" | 126 | #else |
| 113 | #define _HUGE_ENUF 1e+300 | 127 | #define PRIdPTR "d" |
| 128 | #endif | ||
| 129 | |||
| 130 | #ifndef _HUGE_ENUF | ||
| 131 | #define _HUGE_ENUF 1e+300 | ||
| 132 | #endif | ||
| 133 | |||
| 114 | #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) | 134 | #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) |
| 115 | 135 | ||
| 136 | #define strtoull _strtoui64 | ||
| 137 | |||
| 138 | #endif | ||
| 139 | |||
| 116 | /* The below macro is intended to be used for type casts. By using this | 140 | /* The below macro is intended to be used for type casts. By using this |
| 117 | macro, type casts can be easily located in the source code with | 141 | macro, type casts can be easily located in the source code with |
| 118 | tools like "grep". */ | 142 | tools like "grep". */ |
| @@ -123,10 +147,60 @@ typedef enum { false, true } bool; · 4 unmodified lines | |||
| 123 | /* NOTE: This could underestimate the size on some exotic architectures. */ | 147 | /* NOTE: This could underestimate the size on some exotic architectures. */ |
| 124 | #define JAS_UINTFAST32_NUMBITS (8 * sizeof(uint_fast32_t)) | 148 | #define JAS_UINTFAST32_NUMBITS (8 * sizeof(uint_fast32_t)) |
| 125 | 149 | ||
| 126 | #ifdef __cplusplus | 150 | #if 0 |
| 127 | extern "C" { | 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 | #endif | 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 | #ifdef __cplusplus | 204 | #ifdef __cplusplus |
| 131 | } | 205 | } |
| 132 | #endif | 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 | #include <jasper/jas_config.h> | 73 | #include <jasper/jas_config.h> |
| 74 | 74 | ||
| 75 | #include <jasper/jas_types.h> | 75 | #include <jasper/jas_types.h> |
| 76 | #include <jasper/jas_version.h> | ||
| 76 | 77 | ||
| 77 | #include <jasper/jas_init.h> | 78 | #include <jasper/jas_init.h> |
| 78 | #include <jasper/jas_cm.h> | 79 | #include <jasper/jas_cm.h> |
| @@ -84,6 +85,11 @@ · 5 unmodified lines | |||
| 84 | #include <jasper/jas_malloc.h> | 85 | #include <jasper/jas_malloc.h> |
| 85 | #include <jasper/jas_seq.h> | 86 | #include <jasper/jas_seq.h> |
| 86 | #include <jasper/jas_stream.h> | 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 | #pragma lib "./libjp2.a" | 94 | #pragma lib "./libjp2.a" |
| 89 | 95 | ||
| @@ -34,7 +34,10 @@ main(int argc, char **argv) · 33 unmodified lines | |||
| 34 | usage(); | 34 | usage(); |
| 35 | 35 | ||
| 36 | memimageinit(); | 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 | if((cp = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)) == nil){ | 42 | if((cp = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)) == nil){ |
| 40 | werrstr("failed to create color space"); | 43 | werrstr("failed to create color space"); |
| @@ -75,13 +75,12 @@ · 74 unmodified lines | |||
| 75 | 75 | ||
| 76 | #include "jasper/jas_malloc.h" | 76 | #include "jasper/jas_malloc.h" |
| 77 | #include "jasper/jas_debug.h" | 77 | #include "jasper/jas_debug.h" |
| 78 | #include "jasper/jas_types.h" | ||
| 78 | 79 | ||
| 79 | /******************************************************************************\ | 80 | /******************************************************************************\ |
| 80 | * Function prototypes. | 81 | * Function prototypes. |
| 81 | \******************************************************************************/ | 82 | \******************************************************************************/ |
| 82 | 83 | ||
| 83 | #define ONES(n) ((1 << (n)) - 1) | ||
| 84 | |||
| 85 | static const jp2_boxinfo_t *jp2_boxinfolookup(int type); | 84 | static const jp2_boxinfo_t *jp2_boxinfolookup(int type); |
| 86 | 85 | ||
| 87 | static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val); | 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 | static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val); | 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 | static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in); | 99 | static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in); |
| 99 | static int jp2_jp_putdata(const jp2_box_t *box, jas_stream_t *out); | 100 | static int jp2_jp_putdata(const jp2_box_t *box, jas_stream_t *out); |
| 100 | static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in); | 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 | static int jp2_bpcc_putdata(const jp2_box_t *box, jas_stream_t *out); | 107 | static int jp2_bpcc_putdata(const jp2_box_t *box, jas_stream_t *out); |
| 107 | static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in); | 108 | static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in); |
| 108 | static int jp2_colr_putdata(const jp2_box_t *box, jas_stream_t *out); | 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 | static void jp2_colr_destroy(jp2_box_t *box); | 111 | static void jp2_colr_destroy(jp2_box_t *box); |
| 110 | static void jp2_cdef_destroy(jp2_box_t *box); | 112 | static void jp2_cdef_destroy(jp2_box_t *box); |
| 111 | static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in); | 113 | static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in); |
| 112 | static int jp2_cdef_putdata(const jp2_box_t *box, jas_stream_t *out); | 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 | static void jp2_cmap_destroy(jp2_box_t *box); | 116 | static void jp2_cmap_destroy(jp2_box_t *box); |
| 114 | static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in); | 117 | static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in); |
| 115 | static int jp2_cmap_putdata(const jp2_box_t *box, jas_stream_t *out); | 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 | static void jp2_pclr_destroy(jp2_box_t *box); | 120 | static void jp2_pclr_destroy(jp2_box_t *box); |
| 117 | static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in); | 121 | static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in); |
| 118 | static int jp2_pclr_putdata(const jp2_box_t *box, jas_stream_t *out); | 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 | * Local data. | 135 | * Local data. |
| 122 | \******************************************************************************/ | 136 | \******************************************************************************/ |
| 123 | 137 | ||
| 124 | static const jp2_boxinfo_t jp2_boxinfos[] = { | 138 | static const jp2_boxinfo_t jp2_boxinfos[] = { |
| 125 | {JP2_BOX_JP, 0, "JP", {0, 0, jp2_jp_getdata, jp2_jp_putdata}}, | 139 | {JP2_BOX_JP, 0, "JP", |
| 126 | {JP2_BOX_FTYP, 0, "FTYP", {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata}}, | 140 | {0, 0, jp2_jp_getdata, jp2_jp_putdata, 0}}, |
| 127 | {JP2_BOX_JP2H, JP2_BOX_SUPER, "JP2H", {0, 0, 0, 0}}, | 141 | {JP2_BOX_FTYP, 0, "FTYP", |
| 128 | {JP2_BOX_IHDR, 0, "IHDR", {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata}}, | 142 | {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata, 0}}, |
| 129 | {JP2_BOX_BPCC, 0, "BPCC", {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata}}, | 143 | {JP2_BOX_JP2H, JP2_BOX_SUPER, "JP2H", |
| 130 | {JP2_BOX_COLR, 0, "COLR", {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata}}, | 144 | {0, 0, 0, 0, 0}}, |
| 131 | {JP2_BOX_PCLR, 0, "PCLR", {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata}}, | 145 | {JP2_BOX_IHDR, 0, "IHDR", |
| 132 | {JP2_BOX_CMAP, 0, "CMAP", {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata}}, | 146 | {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata, 0}}, |
| 133 | {JP2_BOX_CDEF, 0, "CDEF", {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata}}, | 147 | {JP2_BOX_BPCC, 0, "BPCC", |
| 134 | {JP2_BOX_RES, JP2_BOX_SUPER, "RES", {0, 0, 0, 0}}, | 148 | {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata, 0}}, |
| 135 | {JP2_BOX_RESC, 0, "RESC", {0, 0, 0, 0}}, | 149 | {JP2_BOX_COLR, 0, "COLR", |
| 136 | {JP2_BOX_RESD, 0, "RESD", {0, 0, 0, 0}}, | 150 | {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata, jp2_colr_dumpdata}}, |
| 137 | {JP2_BOX_JP2C, JP2_BOX_NODATA, "JP2C", {0, 0, 0, 0}}, | 151 | {JP2_BOX_PCLR, 0, "PCLR", |
| 138 | {JP2_BOX_JP2I, 0, "JP2I", {0, 0, 0, 0}}, | 152 | {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata, jp2_pclr_dumpdata}}, |
| 139 | {JP2_BOX_XML, 0, "XML", {0, 0, 0, 0}}, | 153 | {JP2_BOX_CMAP, 0, "CMAP", |
| 140 | {JP2_BOX_UUID, 0, "UUID", {0, 0, 0, 0}}, | 154 | {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata, jp2_cmap_dumpdata}}, |
| 141 | {JP2_BOX_UINF, JP2_BOX_SUPER, "UINF", {0, 0, 0, 0}}, | 155 | {JP2_BOX_CDEF, 0, "CDEF", |
| 142 | {JP2_BOX_ULST, 0, "ULST", {0, 0, 0, 0}}, | 156 | {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata, jp2_cdef_dumpdata}}, |
| 143 | {JP2_BOX_URL, 0, "URL", {0, 0, 0, 0}}, | 157 | {JP2_BOX_RES, JP2_BOX_SUPER, "RES", |
| 144 | {0, 0, 0, {0, 0, 0, 0}}, | 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 | static const jp2_boxinfo_t jp2_boxinfo_unk = { | 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 | boxinfo = jp2_boxinfolookup(box->type); | 272 | boxinfo = jp2_boxinfolookup(box->type); |
| 240 | box->info = boxinfo; | 273 | box->info = boxinfo; |
| 241 | box->len = len; | 274 | box->len = len; |
| 242 | JAS_DBGLOG(10, ( | 275 | JAS_LOGDEBUGF(10, |
| 243 | "preliminary processing of JP2 box: " | 276 | "preliminary processing of JP2 box: " |
| 244 | "type=%c%s%c (0x%08x); length=%"PRIuFAST32"\n", | 277 | "type=%c%s%c (0x%08x); length=%"PRIuFAST32"\n", |
| 245 | '"', boxinfo->name, '"', box->type, box->len | 278 | '"', boxinfo->name, '"', box->type, box->len |
| 246 | )); | 279 | ); |
| 247 | size_t hdrlen; | 280 | size_t hdrlen; |
| 248 | if (box->len == 1) { | 281 | if (box->len == 1) { |
| 249 | JAS_DBGLOG(10, ("big length\n")); | 282 | JAS_LOGDEBUGF(10, "big length\n"); |
| 250 | if (jp2_getuint64(in, &extlen)) { | 283 | if (jp2_getuint64(in, &extlen)) { |
| 251 | goto error; | 284 | goto error; |
| 252 | } | 285 | } |
| 253 | if (extlen > 0xffffffffUL) { | 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 | goto error; | 288 | goto error; |
| 256 | } | 289 | } |
| 257 | box->len = extlen; | 290 | box->len = extlen; |
| @@ -262,10 +295,9 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 4 unmodified lines | |||
| 262 | if (box->len != 0 && box->len < 8) { | 295 | if (box->len != 0 && box->len < 8) { |
| 263 | goto error; | 296 | goto error; |
| 264 | } | 297 | } |
| 265 | if (box->len > 0x7fffffffUL) { | 298 | if (box->len > SSIZE_MAX) { |
| 266 | /* this limit is the largest value which can | 299 | /* This limit is the largest value which can be passed to |
| 267 | be passed to jas_stream_copy() without | 300 | jas_stream_copy() without overflowing. */ |
| 268 | overflowing */ | ||
| 269 | goto error; | 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 | goto error; | 312 | goto error; |
| 281 | } | 313 | } |
| 282 | if (jas_stream_copy(tmpstream, in, box->datalen)) { | 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 | goto error; | 316 | goto error; |
| 285 | } | 317 | } |
| 286 | jas_stream_rewind(tmpstream); | 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 | if (box->ops->getdata) { | 324 | if (box->ops->getdata) { |
| 293 | if ((*box->ops->getdata)(box, tmpstream)) { | 325 | if ((*box->ops->getdata)(box, tmpstream)) { |
| 294 | jas_eprintf("cannot parse box data\n"); | 326 | jas_logerrorf("cannot parse box data\n"); |
| 295 | goto error; | 327 | goto error; |
| 296 | } | 328 | } |
| 297 | } | 329 | } |
| 298 | jas_stream_close(tmpstream); | 330 | jas_stream_close(tmpstream); |
| 299 | } | 331 | } |
| 300 | 332 | ||
| 333 | if (jas_get_debug_level() >= 1) { | ||
| 334 | jp2_box_dump(box); | ||
| 335 | } | ||
| 336 | |||
| 301 | return box; | 337 | return box; |
| 302 | 338 | ||
| 303 | error: | 339 | error: |
| @@ -310,6 +346,19 @@ error: · 6 unmodified lines | |||
| 310 | return 0; | 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 | static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in) | 362 | static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in) |
| 314 | { | 363 | { |
| 315 | jp2_jp_t *jp = &box->data.jp; | 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 | return 0; | 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 | static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) | 442 | static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) |
| 380 | { | 443 | { |
| 381 | if (box->datalen < 3) | 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 | if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) || | 452 | if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) || |
| 390 | jp2_getuint8(in, &colr->approx)) { | 453 | jp2_getuint8(in, &colr->approx)) { |
| 454 | jas_logerrorf("cannot get COLR box data\n"); | ||
| 391 | return -1; | 455 | return -1; |
| 392 | } | 456 | } |
| 393 | switch (colr->method) { | 457 | switch (colr->method) { |
| 394 | case JP2_COLR_ENUM: | 458 | case JP2_COLR_ENUM: |
| 395 | if (jp2_getuint32(in, &colr->csid)) { | 459 | if (jp2_getuint32(in, &colr->csid)) { |
| 460 | jas_logerrorf("cannot get CSID\n"); | ||
| 396 | return -1; | 461 | return -1; |
| 397 | } | 462 | } |
| 398 | break; | 463 | break; |
| 399 | case JP2_COLR_ICC: | 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 | colr->iccplen = box->datalen - 3; | 470 | colr->iccplen = box->datalen - 3; |
| 401 | if (colr->iccplen > 1024 * 1024) | 471 | #if 0 |
| 472 | if (colr->iccplen > 1024 * 1024) { | ||
| 402 | /* refuse to read ICC profiles larger than 1 | 473 | /* refuse to read ICC profiles larger than 1 |
| 403 | MB (I have no idea how large ICC profiles | 474 | MB (I have no idea how large ICC profiles |
| 404 | can get, but I believe this limit might be | 475 | can get, but I believe this limit might be |
| 405 | very pessimistic and should be lowered | 476 | very pessimistic and should be lowered |
| 406 | further) */ | 477 | further) */ |
| 407 | return -1; | 478 | return -1; |
| 479 | } | ||
| 480 | #endif | ||
| 408 | if (!(colr->iccp = jas_alloc2(colr->iccplen, sizeof(uint_fast8_t)))) { | 481 | if (!(colr->iccp = jas_alloc2(colr->iccplen, sizeof(uint_fast8_t)))) { |
| 409 | return -1; | 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 | return 0; | 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 | static void jp2_colr_destroy(jp2_box_t *box) | 503 | static void jp2_colr_destroy(jp2_box_t *box) |
| 420 | { | 504 | { |
| 421 | jp2_colr_t *colr = &box->data.colr; | 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 | box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN(false); | 556 | box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN(false); |
| 473 | jas_stream_rewind(tmpstream); | 557 | jas_stream_rewind(tmpstream); |
| 474 | } | 558 | } |
| 475 | extlen = (box->len >= (((uint_fast64_t)1) << 32)) != 0; | 559 | extlen = 0; |
| 476 | if (jp2_putuint32(out, extlen ? 1 : box->len)) { | 560 | if (jp2_putuint32(out, extlen ? 1 : box->len)) { |
| 477 | goto error; | 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 | if (dataflag) { | 572 | if (dataflag) { |
| 489 | if (jas_stream_copy(out, tmpstream, box->len - | 573 | if (jas_stream_copy(out, tmpstream, box->len - |
| 490 | JP2_BOX_HDRLEN(false))) { | 574 | JP2_BOX_HDRLEN(false))) { |
| 491 | jas_eprintf("cannot copy box data\n"); | 575 | jas_logerrorf("cannot copy box data\n"); |
| 492 | goto error; | 576 | goto error; |
| 493 | } | 577 | } |
| 494 | jas_stream_close(tmpstream); | 578 | jas_stream_close(tmpstream); |
| @@ -703,10 +787,6 @@ static const jp2_boxinfo_t *jp2_boxinfolookup(int type) · 208 unmodified lines | |||
| 703 | return &jp2_boxinfo_unk; | 787 | return &jp2_boxinfo_unk; |
| 704 | } | 788 | } |
| 705 | 789 | ||
| 706 | |||
| 707 | |||
| 708 | |||
| 709 | |||
| 710 | static void jp2_cmap_destroy(jp2_box_t *box) | 790 | static void jp2_cmap_destroy(jp2_box_t *box) |
| 711 | { | 791 | { |
| 712 | jp2_cmap_t *cmap = &box->data.cmap; | 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 | static int jp2_cmap_putdata(const jp2_box_t *box, jas_stream_t *out) | 827 | static int jp2_cmap_putdata(const jp2_box_t *box, jas_stream_t *out) |
| 748 | { | 828 | { |
| 749 | /* Eliminate compiler warning about unused variables. */ | 829 | JAS_UNUSED(box); |
| 750 | USED(box); | 830 | JAS_UNUSED(out); |
| 751 | USED(out); | ||
| 752 | |||
| 753 | return -1; | 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 | static void jp2_pclr_destroy(jp2_box_t *box) | 846 | static void jp2_pclr_destroy(jp2_box_t *box) |
| 757 | { | 847 | { |
| 758 | jp2_pclr_t *pclr = &box->data.pclr; | 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 | #if 0 | 903 | #if 0 |
| 814 | const jp2_pclr_t *pclr = &box->data.pclr; | 904 | const jp2_pclr_t *pclr = &box->data.pclr; |
| 815 | #endif | 905 | #endif |
| 816 | /* Eliminate warning about unused variable. */ | 906 | JAS_UNUSED(box); |
| 817 | USED(box); | 907 | JAS_UNUSED(out); |
| 818 | USED(out); | ||
| 819 | return -1; | 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 | static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val) | 926 | static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val) |
| 823 | { | 927 | { |
| 824 | int c; | 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 | m = (n + 7) / 8; | 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 | v = 0; | 941 | v = 0; |
| 832 | for (i = 0; i < m; ++i) { | 942 | for (i = 0; i < m; ++i) { |
| 833 | if ((c = jas_stream_getc(in)) == EOF) { | 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 | v = (v << 8) | c; | 946 | v = (v << 8) | c; |
| 837 | } | 947 | } |
| 838 | v &= ONES(n); | 948 | v &= ones(n); |
| 839 | if (s) { | 949 | if (s) { |
| 840 | int sb; | 950 | int sb; |
| 841 | sb = v & (1 << (8 * m - 1)); | 951 | sb = v & (JAS_CAST(uint_fast32_t, 1) << (8 * m - 1)); |
| 842 | *val = ((~v) + 1) & ONES(8 * m); | 952 | *val = ((~v) + 1) & ones(8 * m); |
| 843 | if (sb) { | 953 | if (sb) { |
| 844 | *val = -*val; | 954 | *val = -*val; |
| 845 | } | 955 | } |
| @@ -245,7 +245,7 @@ typedef struct { · 244 unmodified lines | |||
| 245 | uint_fast32_t type; | 245 | uint_fast32_t type; |
| 246 | 246 | ||
| 247 | /* The length of the box including the (variable-length) header. */ | 247 | /* The length of the box including the (variable-length) header. */ |
| 248 | uint_fast64_t len; | 248 | uint_fast32_t len; |
| 249 | 249 | ||
| 250 | /* The length of the box data. */ | 250 | /* The length of the box data. */ |
| 251 | uint_fast32_t datalen; | 251 | uint_fast32_t datalen; |
| @@ -268,6 +268,7 @@ typedef struct jp2_boxops_s { · 16 unmodified lines | |||
| 268 | void (*destroy)(jp2_box_t *box); | 268 | void (*destroy)(jp2_box_t *box); |
| 269 | int (*getdata)(jp2_box_t *box, jas_stream_t *in); | 269 | int (*getdata)(jp2_box_t *box, jas_stream_t *in); |
| 270 | int (*putdata)(const jp2_box_t *box, jas_stream_t *out); | 270 | int (*putdata)(const jp2_box_t *box, jas_stream_t *out); |
| 271 | void (*dumpdata)(const jp2_box_t *box); | ||
| 271 | } jp2_boxops_t; | 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 | const jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo); | 310 | const jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo); |
| 310 | 311 | ||
| 311 | |||
| 312 | #endif | 312 | #endif |
| @@ -81,7 +81,9 @@ · 80 unmodified lines | |||
| 81 | #include "jasper/jas_malloc.h" | 81 | #include "jasper/jas_malloc.h" |
| 82 | #include "jasper/jas_types.h" | 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 | static jp2_dec_t *jp2_dec_create(void); | 88 | static jp2_dec_t *jp2_dec_create(void); |
| 87 | static void jp2_dec_destroy(jp2_dec_t *dec); | 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 | unsigned int i; | 106 | unsigned int i; |
| 105 | jp2_cmap_t *cmapd; | 107 | jp2_cmap_t *cmapd; |
| 106 | jp2_pclr_t *pclrd; | 108 | jp2_pclr_t *pclrd; |
| 109 | #if 0 | ||
| 110 | /* The following code appears to no longer be needed. */ | ||
| 107 | jp2_cdef_t *cdefd; | 111 | jp2_cdef_t *cdefd; |
| 112 | #endif | ||
| 108 | unsigned int channo; | 113 | unsigned int channo; |
| 109 | int newcmptno; | 114 | int newcmptno; |
| 110 | int_fast32_t *lutents; | 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 | jas_iccprof_t *iccprof; | 122 | jas_iccprof_t *iccprof; |
| 118 | 123 | ||
| 119 | box = 0; | 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 | if (!(dec = jp2_dec_create())) { | 129 | if (!(dec = jp2_dec_create())) { |
| 124 | goto error; | 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 | /* Get the first box. This should be a JP box. */ | 133 | /* Get the first box. This should be a JP box. */ |
| 128 | if (!(box = jp2_box_get(in))) { | 134 | if (!(box = jp2_box_get(in))) { |
| 129 | jas_eprintf("error: cannot get box\n"); | 135 | jas_logerrorf("error: cannot get box\n"); |
| 130 | goto error; | 136 | goto error; |
| 131 | } | 137 | } |
| 132 | if (box->type != JP2_BOX_JP) { | 138 | if (box->type != JP2_BOX_JP) { |
| 133 | jas_eprintf("error: expecting signature box\n"); | 139 | jas_logerrorf("error: expecting signature box\n"); |
| 134 | goto error; | 140 | goto error; |
| 135 | } | 141 | } |
| 136 | if (box->data.jp.magic != JP2_JP_MAGIC) { | 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 | goto error; | 146 | goto error; |
| 139 | } | 147 | } |
| 140 | jp2_box_destroy(box); | 148 | jp2_box_destroy(box); |
| 141 | 149 | ||
| 142 | /* Get the second box. This should be a FTYP box. */ | 150 | /* Get the second box. This should be a FTYP box. */ |
| 143 | if (!(box = jp2_box_get(in))) { | 151 | if (!(box = jp2_box_get(in))) { |
| 152 | jas_logerrorf("error: cannot get box\n"); | ||
| 144 | goto error; | 153 | goto error; |
| 145 | } | 154 | } |
| 146 | if (box->type != JP2_BOX_FTYP) { | 155 | if (box->type != JP2_BOX_FTYP) { |
| 147 | jas_eprintf("expecting file type box\n"); | 156 | jas_logerrorf("expecting file type box\n"); |
| 148 | goto error; | 157 | goto error; |
| 149 | } | 158 | } |
| 150 | jp2_box_destroy(box); | 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 | /* Get more boxes... */ | 161 | /* Get more boxes... */ |
| 153 | found = 0; | 162 | found = 0; |
| 154 | while ((box = jp2_box_get(in))) { | 163 | while ((box = jp2_box_get(in))) { |
| 155 | if (jas_getdbglevel() >= 1) { | 164 | if (jas_get_debug_level() >= 1) { |
| 156 | jas_eprintf("got box type %s\n", box->info->name); | 165 | jas_logdebugf(1, "got box type %s\n", box->info->name); |
| 157 | } | 166 | } |
| 158 | switch (box->type) { | 167 | switch (box->type) { |
| 159 | case JP2_BOX_JP2C: | 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 | if (!found) { | 217 | if (!found) { |
| 209 | jas_eprintf("error: no code stream found\n"); | 218 | jas_logerrorf("error: no code stream found\n"); |
| 210 | goto error; | 219 | goto error; |
| 211 | } | 220 | } |
| 212 | 221 | ||
| 213 | if (!(dec->image = jpc_decode(in, optstr))) { | 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 | goto error; | 224 | goto error; |
| 216 | } | 225 | } |
| 217 | 226 | ||
| 218 | /* An IHDR box must be present. */ | 227 | /* An IHDR box must be present. */ |
| 219 | if (!dec->ihdr) { | 228 | if (!dec->ihdr) { |
| 220 | jas_eprintf("error: missing IHDR box\n"); | 229 | jas_logerrorf("error: missing IHDR box\n"); |
| 221 | goto error; | 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 | the value specified in the code stream? */ | 234 | the value specified in the code stream? */ |
| 226 | if (dec->ihdr->data.ihdr.numcmpts != JAS_CAST(jas_uint, | 235 | if (dec->ihdr->data.ihdr.numcmpts != JAS_CAST(jas_uint, |
| 227 | jas_image_numcmpts(dec->image))) { | 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 | /* At least one component must be present. */ | 241 | /* At least one component must be present. */ |
| 232 | if (!jas_image_numcmpts(dec->image)) { | 242 | if (!jas_image_numcmpts(dec->image)) { |
| 233 | jas_eprintf("error: no components\n"); | 243 | jas_logerrorf("error: no components\n"); |
| 234 | goto error; | 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 | with the data in the code stream? */ | 258 | with the data in the code stream? */ |
| 249 | if ((samedtype && dec->ihdr->data.ihdr.bpc != JP2_DTYPETOBPC(dtype)) || | 259 | if ((samedtype && dec->ihdr->data.ihdr.bpc != JP2_DTYPETOBPC(dtype)) || |
| 250 | (!samedtype && dec->ihdr->data.ihdr.bpc != JP2_IHDR_BPCNULL)) { | 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 | /* Is the compression type supported? */ | 265 | /* Is the compression type supported? */ |
| 255 | if (dec->ihdr->data.ihdr.comptype != JP2_IHDR_COMPTYPE) { | 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 | goto error; | 268 | goto error; |
| 258 | } | 269 | } |
| 259 | 270 | ||
| 260 | if (dec->bpcc) { | 271 | if (dec->bpcc) { |
| 261 | /* Is the number of components indicated in the BPCC box | 272 | /* Is the number of components indicated in the BPCC box |
| 262 | consistent with the code stream data? */ | 273 | consistent with the code stream data? */ |
| 263 | if (dec->bpcc->data.bpcc.numcmpts != JAS_CAST(jas_uint, jas_image_numcmpts( | 274 | if (dec->bpcc->data.bpcc.numcmpts != |
| 264 | dec->image))) { | 275 | JAS_CAST(jas_uint, jas_image_numcmpts(dec->image))) { |
| 265 | jas_eprintf("warning: number of components mismatch\n"); | 276 | jas_logerrorf("error: number of components mismatch (BPCC)\n"); |
| 277 | goto error; | ||
| 266 | } | 278 | } |
| 267 | /* Is the component data type information indicated in the BPCC | 279 | /* Is the component data type information indicated in the BPCC |
| 268 | box consistent with the code stream data? */ | 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 | ++i) { | 283 | ++i) { |
| 272 | if (jas_image_cmptdtype(dec->image, i) != | 284 | if (jas_image_cmptdtype(dec->image, i) != |
| 273 | JP2_BPCTODTYPE(dec->bpcc->data.bpcc.bpcs[i])) { | 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 | } else { | 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 | /* A COLR box must be present. */ | 295 | /* A COLR box must be present. */ |
| 283 | if (!dec->colr) { | 296 | if (!dec->colr) { |
| 284 | jas_eprintf("error: no COLR box\n"); | 297 | jas_logerrorf("error: no COLR box\n"); |
| 285 | goto error; | 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 | iccprof = jas_iccprof_createfrombuf(dec->colr->data.colr.iccp, | 306 | iccprof = jas_iccprof_createfrombuf(dec->colr->data.colr.iccp, |
| 294 | dec->colr->data.colr.iccplen); | 307 | dec->colr->data.colr.iccplen); |
| 295 | if (!iccprof) { | 308 | if (!iccprof) { |
| 296 | jas_eprintf("error: failed to parse ICC profile\n"); | 309 | jas_logerrorf("error: failed to parse ICC profile\n"); |
| 297 | goto error; | 310 | goto error; |
| 298 | } | 311 | } |
| 299 | jas_iccprof_gethdr(iccprof, &icchdr); | 312 | jas_iccprof_gethdr(iccprof, &icchdr); |
| 300 | //jas_eprintf("ICC Profile CS %08x\n", icchdr.colorspc); | 313 | JAS_LOGDEBUGF(2, "ICC Profile CS %08x\n", icchdr.colorspc); |
| 301 | jas_image_setclrspc(dec->image, fromiccpcs(icchdr.colorspc)); | ||
| 302 | dec->image->cmprof_ = jas_cmprof_createfromiccprof(iccprof); | 314 | dec->image->cmprof_ = jas_cmprof_createfromiccprof(iccprof); |
| 303 | if (!dec->image->cmprof_) { | 315 | if (!dec->image->cmprof_) { |
| 304 | jas_iccprof_destroy(iccprof); | 316 | jas_image_setclrspc(dec->image, JAS_CLRSPC_UNKNOWN); |
| 305 | goto error; | 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 | jas_iccprof_destroy(iccprof); | 321 | jas_iccprof_destroy(iccprof); |
| 308 | break; | 322 | break; |
| @@ -310,14 +324,14 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line | |||
| 310 | 324 | ||
| 311 | /* If a CMAP box is present, a PCLR box must also be present. */ | 325 | /* If a CMAP box is present, a PCLR box must also be present. */ |
| 312 | if (dec->cmap && !dec->pclr) { | 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 | jp2_box_destroy(dec->cmap); | 328 | jp2_box_destroy(dec->cmap); |
| 315 | dec->cmap = 0; | 329 | dec->cmap = 0; |
| 316 | } | 330 | } |
| 317 | 331 | ||
| 318 | /* If a CMAP box is not present, a PCLR box must not be present. */ | 332 | /* If a CMAP box is not present, a PCLR box must not be present. */ |
| 319 | if (!dec->cmap && dec->pclr) { | 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 | jp2_box_destroy(dec->pclr); | 335 | jp2_box_destroy(dec->pclr); |
| 322 | dec->pclr = 0; | 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 | /* Is the component number reasonable? */ | 347 | /* Is the component number reasonable? */ |
| 334 | if (dec->cmap->data.cmap.ents[i].cmptno >= JAS_CAST(jas_uint, | 348 | if (dec->cmap->data.cmap.ents[i].cmptno >= JAS_CAST(jas_uint, |
| 335 | jas_image_numcmpts(dec->image))) { | 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 | goto error; | 351 | goto error; |
| 338 | } | 352 | } |
| 339 | /* Is the LUT index reasonable? */ | 353 | /* Is the LUT index reasonable? */ |
| 340 | if (dec->cmap->data.cmap.ents[i].pcol >= | 354 | if (dec->cmap->data.cmap.ents[i].pcol >= |
| 341 | dec->pclr->data.pclr.numchans) { | 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 | goto error; | 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 | /* Allocate space for the channel-number to component-number LUT. */ | 362 | /* Allocate space for the channel-number to component-number LUT. */ |
| 349 | if (!(dec->chantocmptlut = jas_alloc2(dec->numchans, | 363 | if (!(dec->chantocmptlut = jas_alloc2(dec->numchans, |
| 350 | sizeof(uint_fast16_t)))) { | 364 | sizeof(uint_fast16_t)))) { |
| 351 | jas_eprintf("error: no memory\n"); | 365 | jas_logerrorf("error: no memory\n"); |
| 352 | goto error; | 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 | dec->chantocmptlut[i] = i; | 371 | dec->chantocmptlut[i] = i; |
| 358 | } | 372 | } |
| 359 | } else { | 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 | cmapd = &dec->cmap->data.cmap; | 380 | cmapd = &dec->cmap->data.cmap; |
| 361 | pclrd = &dec->pclr->data.pclr; | 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 | for (channo = 0; channo < cmapd->numchans; ++channo) { | 386 | for (channo = 0; channo < cmapd->numchans; ++channo) { |
| 363 | cmapent = &cmapd->ents[channo]; | 387 | cmapent = &cmapd->ents[channo]; |
| 364 | if (cmapent->map == JP2_CMAP_DIRECT) { | 388 | if (cmapent->map == JP2_CMAP_DIRECT) { |
| 365 | dec->chantocmptlut[channo] = channo; | 389 | dec->chantocmptlut[channo] = channo; |
| 366 | } else if (cmapent->map == JP2_CMAP_PALETTE) { | 390 | } else if (cmapent->map == JP2_CMAP_PALETTE) { |
| 367 | if (!pclrd->numlutents) { | 391 | if (!pclrd->numlutents) { |
| 392 | jas_logerrorf("error: empty LUT\n"); | ||
| 368 | goto error; | 393 | goto error; |
| 369 | } | 394 | } |
| 370 | lutents = jas_alloc2(pclrd->numlutents, sizeof(int_fast32_t)); | 395 | if (!(lutents = jas_alloc2(pclrd->numlutents, |
| 371 | if (!lutents) { | 396 | sizeof(int_fast32_t)))) { |
| 397 | jas_logerrorf("error: cannot allocate LUT\n"); | ||
| 372 | goto error; | 398 | goto error; |
| 373 | } | 399 | } |
| 374 | for (i = 0; i < pclrd->numlutents; ++i) { | 400 | for (i = 0; i < pclrd->numlutents; ++i) { |
| 375 | lutents[i] = pclrd->lutdata[cmapent->pcol + i * pclrd->numchans]; | 401 | lutents[i] = pclrd->lutdata[cmapent->pcol + i * pclrd->numchans]; |
| 376 | } | 402 | } |
| 377 | newcmptno = jas_image_numcmpts(dec->image); | 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 | pclrd->numlutents, lutents, | 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 | dec->chantocmptlut[channo] = newcmptno; | 412 | dec->chantocmptlut[channo] = newcmptno; |
| 382 | jas_free(lutents); | 413 | jas_free(lutents); |
| 383 | #if 0 | 414 | #if 0 |
| 415 | /* The following code appears to no longer be needed. */ | ||
| 384 | if (dec->cdef) { | 416 | if (dec->cdef) { |
| 385 | cdefent = jp2_cdef_lookup(cdefd, channo); | 417 | cdefent = jp2_cdef_lookup(cdefd, channo); |
| 386 | if (!cdefent) { | 418 | if (!cdefent) { |
| @@ -390,17 +422,25 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 3 unmodified lines | |||
| 390 | } else { | 422 | } else { |
| 391 | jas_image_setcmpttype(dec->image, newcmptno, jp2_getct(jas_image_clrspc(dec->image), 0, channo + 1)); | 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 | #endif | 425 | #endif |
| 397 | } else { | 426 | } else { |
| 398 | jas_eprintf("error: invalid MTYP in CMAP box\n"); | 427 | jas_logerrorf("error: invalid MTYP in CMAP box\n"); |
| 399 | goto error; | 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 | /* Mark all components as being of unknown type. */ | 444 | /* Mark all components as being of unknown type. */ |
| 405 | 445 | ||
| 406 | for (i = 0; i < JAS_CAST(jas_uint, jas_image_numcmpts(dec->image)); ++i) { | 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 | /* Determine the type of each component. */ | 450 | /* Determine the type of each component. */ |
| 411 | if (dec->cdef) { | 451 | if (dec->cdef) { |
| 412 | for (i = 0; i < dec->cdef->data.cdef.numchans; ++i) { | 452 | for (i = 0; i < dec->cdef->data.cdef.numchans; ++i) { |
| 453 | uint_fast16_t channo = dec->cdef->data.cdef.ents[i].channo; | ||
| 413 | /* Is the channel number reasonable? */ | 454 | /* Is the channel number reasonable? */ |
| 414 | if (dec->cdef->data.cdef.ents[i].channo >= dec->numchans) { | 455 | if (channo >= dec->numchans) { |
| 415 | jas_eprintf("error: invalid channel number in CDEF box\n"); | 456 | jas_logerrorf("error: invalid channel number in CDEF box (%d)\n", |
| 457 | channo); | ||
| 416 | goto error; | 458 | goto error; |
| 417 | } | 459 | } |
| 418 | jas_image_setcmpttype(dec->image, | 460 | unsigned compno = dec->chantocmptlut[channo]; |
| 419 | dec->chantocmptlut[dec->cdef->data.cdef.ents[i].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 | jp2_getct(jas_image_clrspc(dec->image), | 468 | jp2_getct(jas_image_clrspc(dec->image), |
| 421 | dec->cdef->data.cdef.ents[i].type, | 469 | dec->cdef->data.cdef.ents[i].type, |
| 422 | dec->cdef->data.cdef.ents[i].assoc)); | 470 | dec->cdef->data.cdef.ents[i].assoc)); |
| 423 | } | 471 | } |
| 424 | } else { | 472 | } else { |
| 425 | for (i = 0; i < dec->numchans; ++i) { | 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 | jp2_getct(jas_image_clrspc(dec->image), 0, i + 1)); | 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 | /* Ensure that some components survived. */ | 492 | /* Ensure that some components survived. */ |
| 439 | if (!jas_image_numcmpts(dec->image)) { | 493 | if (!jas_image_numcmpts(dec->image)) { |
| 440 | jas_eprintf("error: no components\n"); | 494 | jas_logerrorf("error: no components\n"); |
| 441 | goto error; | 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 | /* Prevent the image from being destroyed later. */ | 498 | /* Prevent the image from being destroyed later. */ |
| 448 | image = dec->image; | 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 | return image; | 504 | return image; |
| 454 | 505 | ||
| 455 | error: | 506 | error: |
| 507 | if (image) { | ||
| 508 | jas_image_destroy(image); | ||
| 509 | } | ||
| 456 | if (box) { | 510 | if (box) { |
| 457 | jp2_box_destroy(box); | 511 | jp2_box_destroy(box); |
| 458 | } | 512 | } |
| @@ -462,25 +516,25 @@ error: · 3 unmodified lines | |||
| 462 | return 0; | 516 | return 0; |
| 463 | } | 517 | } |
| 464 | 518 | ||
| 519 | #define JP2_VALIDATE_LEN JAS_MIN(JP2_JP_LEN + 4, JAS_STREAM_MAXPUTBACK) | ||
| 465 | int jp2_validate(jas_stream_t *in) | 520 | int jp2_validate(jas_stream_t *in) |
| 466 | { | 521 | { |
| 467 | unsigned char buf[JP2_VALIDATELEN]; | 522 | unsigned char buf[JP2_VALIDATE_LEN]; |
| 468 | #if 0 | ||
| 469 | jas_stream_t *tmpstream; | ||
| 470 | jp2_box_t *box; | ||
| 471 | #endif | ||
| 472 | |||
| 473 | assert(JAS_STREAM_MAXPUTBACK >= JP2_VALIDATELEN); | ||
| 474 | 523 | ||
| 475 | /* Read the validation data (i.e., the data used for detecting | 524 | /* Read the validation data (i.e., the data used for detecting |
| 476 | the format). */ | 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 | return -1; | 528 | return -1; |
| 529 | } | ||
| 479 | 530 | ||
| 480 | /* Is the box type correct? */ | 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]) != | 532 | assert(JP2_VALIDATE_LEN >= 8); |
| 482 | JP2_BOX_JP) | 533 | if (((JAS_CAST(uint_least32_t, buf[4]) << 24) | |
| 483 | { | 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 | return -1; | 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 | int jpc_bitstream_getbit_func(jpc_bitstream_t *bitstream) | 166 | int jpc_bitstream_getbit_func(jpc_bitstream_t *bitstream) |
| 167 | { | 167 | { |
| 168 | int ret; | 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 | ret = jpc_bitstream_getbit_macro(bitstream); | 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 | return ret; | 172 | return ret; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| @@ -176,9 +176,9 @@ int jpc_bitstream_getbit_func(jpc_bitstream_t *bitstream) · 1 unmodified line | |||
| 176 | int jpc_bitstream_putbit_func(jpc_bitstream_t *bitstream, int b) | 176 | int jpc_bitstream_putbit_func(jpc_bitstream_t *bitstream, int b) |
| 177 | { | 177 | { |
| 178 | int ret; | 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 | ret = jpc_bitstream_putbit_macro(bitstream, b); | 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 | return ret; | 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 | if (n > 0) { | 363 | if (n > 0) { |
| 364 | if ((u = jpc_bitstream_getbits(bitstream, n)) < 0) { | 364 | if ((u = jpc_bitstream_getbits(bitstream, n)) < 0) { |
| 365 | JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed\n"); | ||
| 365 | return -1; | 366 | return -1; |
| 366 | } | 367 | } |
| 367 | m += n; | 368 | m += n; |
| @@ -369,6 +370,7 @@ int jpc_bitstream_inalign(jpc_bitstream_t *bitstream, int fillmask, · 1 unmodified line | |||
| 369 | } | 370 | } |
| 370 | if ((bitstream->buf_ & 0xff) == 0xff) { | 371 | if ((bitstream->buf_ & 0xff) == 0xff) { |
| 371 | if ((u = jpc_bitstream_getbits(bitstream, 7)) < 0) { | 372 | if ((u = jpc_bitstream_getbits(bitstream, 7)) < 0) { |
| 373 | JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed\n"); | ||
| 372 | return -1; | 374 | return -1; |
| 373 | } | 375 | } |
| 374 | v = (v << 7) | u; | 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 | if (((~(v ^ filldata)) & fillmask) != fillmask) { | 385 | if (((~(v ^ filldata)) & fillmask) != fillmask) { |
| 384 | /* The actual fill pattern does not match the expected one. */ | 386 | /* The actual fill pattern does not match the expected one. */ |
| 387 | JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed (mismatch)\n"); | ||
| 385 | return 1; | 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 | int jpc_bitstream_fillbuf(jpc_bitstream_t *bitstream); | 212 | int jpc_bitstream_fillbuf(jpc_bitstream_t *bitstream); |
| 213 | 213 | ||
| 214 | #define jpc_bitstream_getbit_macro(bitstream) \ | 214 | #define jpc_bitstream_getbit_macro(bitstream) \ |
| 215 | ((--(bitstream)->cnt_ >= 0) ? \ | 215 | ( (--(bitstream)->cnt_ >= 0) ? \ |
| 216 | ((int)(((bitstream)->buf_ >> (bitstream)->cnt_) & 1)) : \ | 216 | ((int)(((bitstream)->buf_ >> (bitstream)->cnt_) & 1)) : \ |
| 217 | jpc_bitstream_fillbuf(bitstream)) | 217 | jpc_bitstream_fillbuf(bitstream)) |
| 218 | 218 | ||
| 219 | #define jpc_bitstream_putbit_macro(bitstream, bit) \ | 219 | #define jpc_bitstream_putbit_macro(bitstream, bit) \ |
| 220 | ((--(bitstream)->cnt_ < 0) ? \ | 220 | ( (--(bitstream)->cnt_ < 0) ? \ |
| 221 | ((bitstream)->buf_ = ((bitstream)->buf_ << 8) & 0xffff, \ | 221 | ((bitstream)->buf_ = ((bitstream)->buf_ << 8) & 0xffff, \ |
| 222 | (bitstream)->cnt_ = ((bitstream)->buf_ == 0xff00) ? 6 : 7, \ | 222 | (bitstream)->cnt_ = ((bitstream)->buf_ == 0xff00) ? 6 : 7, \ |
| 223 | (bitstream)->buf_ |= ((bit) & 1) << (bitstream)->cnt_, \ | 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 | #ifndef JPC_COD_H | 68 | #ifndef JPC_COD_H |
| 69 | #define JPC_COD_H | 69 | #define JPC_COD_H |
| 70 | 70 | ||
| 71 | #include "jpc_t1cod.h" | ||
| 72 | |||
| 71 | /******************************************************************************\ | 73 | /******************************************************************************\ |
| 72 | * Constants. | 74 | * Constants. |
| 73 | \******************************************************************************/ | 75 | \******************************************************************************/ |
| @@ -75,4 +77,6 @@ · 1 unmodified line | |||
| 75 | /* The nominal word size used by this implementation. */ | 77 | /* The nominal word size used by this implementation. */ |
| 76 | #define JPC_PREC 32 | 78 | #define JPC_PREC 32 |
| 77 | 79 | ||
| 80 | void jpc_init(void); | ||
| 81 | |||
| 78 | #endif | 82 | #endif |
| @@ -94,6 +94,7 @@ typedef struct { · 93 unmodified lines | |||
| 94 | 94 | ||
| 95 | static const jpc_mstabent_t *jpc_mstab_lookup(int id); | 95 | static const jpc_mstabent_t *jpc_mstab_lookup(int id); |
| 96 | 96 | ||
| 97 | static int jpc_poc_dumpparms(jpc_ms_t *ms); | ||
| 97 | static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); | 98 | static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); |
| 98 | static int jpc_poc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in); | 99 | static int jpc_poc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in); |
| 99 | static void jpc_poc_destroyparms(jpc_ms_t *ms); | 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 | static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); | 127 | static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); |
| 127 | static int jpc_com_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); | 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 | static void jpc_siz_destroyparms(jpc_ms_t *ms); | 144 | static void jpc_siz_destroyparms(jpc_ms_t *ms); |
| 130 | static void jpc_qcd_destroyparms(jpc_ms_t *ms); | 145 | static void jpc_qcd_destroyparms(jpc_ms_t *ms); |
| 131 | static void jpc_qcc_destroyparms(jpc_ms_t *ms); | 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 | static const jpc_mstabent_t jpc_mstab[] = { | 170 | static const jpc_mstabent_t jpc_mstab[] = { |
| 156 | {JPC_MS_SOC, "SOC", {0, 0, 0}}, | 171 | {JPC_MS_SOC, "SOC", {0, 0, 0, 0}}, |
| 157 | {JPC_MS_SOT, "SOT", {0, jpc_sot_getparms, jpc_sot_putparms}}, | 172 | {JPC_MS_SOT, "SOT", {0, jpc_sot_getparms, jpc_sot_putparms, |
| 158 | {JPC_MS_SOD, "SOD", {0, 0, 0}}, | 173 | jpc_sot_dumpparms}}, |
| 159 | {JPC_MS_EOC, "EOC", {0, 0, 0}}, | 174 | {JPC_MS_SOD, "SOD", {0, 0, 0, 0}}, |
| 160 | {JPC_MS_SIZ, "SIZ", {jpc_siz_destroyparms, jpc_siz_getparms, jpc_siz_putparms}}, | 175 | {JPC_MS_EOC, "EOC", {0, 0, 0, 0}}, |
| 161 | {JPC_MS_COD, "COD", {jpc_cod_destroyparms, jpc_cod_getparms, jpc_cod_putparms}}, | 176 | {JPC_MS_SIZ, "SIZ", {jpc_siz_destroyparms, jpc_siz_getparms, |
| 162 | {JPC_MS_COC, "COC", {jpc_coc_destroyparms, jpc_coc_getparms, jpc_coc_putparms}}, | 177 | jpc_siz_putparms, jpc_siz_dumpparms}}, |
| 163 | {JPC_MS_RGN, "RGN", {0, jpc_rgn_getparms, jpc_rgn_putparms}}, | 178 | {JPC_MS_COD, "COD", {jpc_cod_destroyparms, jpc_cod_getparms, |
| 164 | {JPC_MS_QCD, "QCD", {jpc_qcd_destroyparms, jpc_qcd_getparms, jpc_qcd_putparms}}, | 179 | jpc_cod_putparms, jpc_cod_dumpparms}}, |
| 165 | {JPC_MS_QCC, "QCC", {jpc_qcc_destroyparms, jpc_qcc_getparms, jpc_qcc_putparms}}, | 180 | {JPC_MS_COC, "COC", {jpc_coc_destroyparms, jpc_coc_getparms, |
| 166 | {JPC_MS_POC, "POC", {jpc_poc_destroyparms, jpc_poc_getparms, jpc_poc_putparms}}, | 181 | jpc_coc_putparms, jpc_coc_dumpparms}}, |
| 167 | {JPC_MS_TLM, "TLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms,}}, | 182 | {JPC_MS_RGN, "RGN", {0, jpc_rgn_getparms, jpc_rgn_putparms, |
| 168 | {JPC_MS_PLM, "PLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms}}, | 183 | jpc_rgn_dumpparms}}, |
| 169 | {JPC_MS_PPM, "PPM", {jpc_ppm_destroyparms, jpc_ppm_getparms, jpc_ppm_putparms}}, | 184 | {JPC_MS_QCD, "QCD", {jpc_qcd_destroyparms, jpc_qcd_getparms, |
| 170 | {JPC_MS_PPT, "PPT", {jpc_ppt_destroyparms, jpc_ppt_getparms, jpc_ppt_putparms}}, | 185 | jpc_qcd_putparms, jpc_qcd_dumpparms}}, |
| 171 | {JPC_MS_SOP, "SOP", {0, jpc_sop_getparms, jpc_sop_putparms}}, | 186 | {JPC_MS_QCC, "QCC", {jpc_qcc_destroyparms, jpc_qcc_getparms, |
| 172 | {JPC_MS_EPH, "EPH", {0, 0, 0}}, | 187 | jpc_qcc_putparms, jpc_qcc_dumpparms}}, |
| 173 | {JPC_MS_CRG, "CRG", {jpc_crg_destroyparms, jpc_crg_getparms, jpc_crg_putparms}}, | 188 | {JPC_MS_POC, "POC", {jpc_poc_destroyparms, jpc_poc_getparms, |
| 174 | {JPC_MS_COM, "COM", {jpc_com_destroyparms, jpc_com_getparms, jpc_com_putparms}}, | 189 | jpc_poc_putparms, jpc_poc_dumpparms}}, |
| 175 | {-1, "UNKNOWN", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms}} | 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 | return 0; | 267 | return 0; |
| 239 | } | 268 | } |
| 240 | if (jas_stream_copy(tmpstream, in, ms->len) || | 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 | jas_stream_close(tmpstream); | 271 | jas_stream_close(tmpstream); |
| 243 | jpc_ms_destroy(ms); | 272 | jpc_ms_destroy(ms); |
| 244 | return 0; | 273 | return 0; |
| @@ -251,8 +280,12 @@ jpc_ms_t *jpc_getms(jas_stream_t *in, jpc_cstate_t *cstate) · 6 unmodified lines | |||
| 251 | return 0; | 280 | return 0; |
| 252 | } | 281 | } |
| 253 | 282 | ||
| 283 | if (jas_get_debug_level() > 0) { | ||
| 284 | jpc_ms_dump(ms); | ||
| 285 | } | ||
| 286 | |||
| 254 | if (JAS_CAST(jas_ulong, jas_stream_tell(tmpstream)) != ms->len) { | 287 | if (JAS_CAST(jas_ulong, jas_stream_tell(tmpstream)) != ms->len) { |
| 255 | jas_eprintf( | 288 | jas_logwarnf( |
| 256 | "warning: trailing garbage in marker segment (%ld bytes)\n", | 289 | "warning: trailing garbage in marker segment (%ld bytes)\n", |
| 257 | ms->len - jas_stream_tell(tmpstream)); | 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 | } else { | 296 | } else { |
| 264 | /* There are no marker segment parameters. */ | 297 | /* There are no marker segment parameters. */ |
| 265 | ms->len = 0; | 298 | ms->len = 0; |
| 299 | |||
| 300 | if (jas_get_debug_level() > 0) { | ||
| 301 | jpc_ms_dump(ms); | ||
| 302 | } | ||
| 266 | } | 303 | } |
| 267 | 304 | ||
| 268 | /* Update the code stream state information based on the type of | 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 | ms->len = len; | 343 | ms->len = len; |
| 307 | /* Write the marker segment length and parameter data to | 344 | /* Write the marker segment length and parameter data to |
| 308 | the output stream. */ | 345 | the output stream. */ |
| 309 | if (jas_stream_seek(tmpstream, 0, 0) < 0 || | 346 | if (jas_stream_seek(tmpstream, 0, SEEK_SET) < 0 || |
| 310 | jpc_putuint16(out, ms->len + 2) || | 347 | jpc_putuint16(out, ms->len + 2) || |
| 311 | jas_stream_copy(out, tmpstream, ms->len) < 0) { | 348 | jas_stream_copy(out, tmpstream, ms->len) < 0) { |
| 312 | jas_stream_close(tmpstream); | 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 | cstate->numcomps = ms->parms.siz.numcomps; | 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 | return 0; | 366 | return 0; |
| 326 | } | 367 | } |
| 327 | 368 | ||
| @@ -355,6 +396,24 @@ void jpc_ms_destroy(jpc_ms_t *ms) · 27 unmodified lines | |||
| 355 | jas_free(ms); | 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 | * SOT marker segment operations. | 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 | jpc_sot_t *sot = &ms->parms.sot; | 423 | jpc_sot_t *sot = &ms->parms.sot; |
| 365 | 424 | ||
| 366 | /* Eliminate compiler warning about unused variables. */ | 425 | JAS_UNUSED(cstate); |
| 367 | (void)cstate; | ||
| 368 | 426 | ||
| 369 | if (jpc_getuint16(in, &sot->tileno) || | 427 | if (jpc_getuint16(in, &sot->tileno) || |
| 370 | jpc_getuint32(in, &sot->len) || | 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 | jpc_sot_t *sot = &ms->parms.sot; | 444 | jpc_sot_t *sot = &ms->parms.sot; |
| 387 | 445 | ||
| 388 | /* Eliminate compiler warning about unused variables. */ | 446 | JAS_UNUSED(cstate); |
| 389 | (void)cstate; | ||
| 390 | 447 | ||
| 391 | if (jpc_putuint16(out, sot->tileno) || | 448 | if (jpc_putuint16(out, sot->tileno) || |
| 392 | jpc_putuint32(out, sot->len) || | 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 | return 0; | 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 | * SIZ marker segment operations. | 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 | siz->comps = 0; | 485 | siz->comps = 0; |
| 420 | 486 | ||
| 421 | /* Eliminate compiler warning about unused variables. */ | 487 | JAS_UNUSED(cstate); |
| 422 | (void)cstate; | ||
| 423 | 488 | ||
| 424 | if (jpc_getuint16(in, &siz->caps) || | 489 | if (jpc_getuint16(in, &siz->caps) || |
| 425 | jpc_getuint32(in, &siz->width) || | 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 | goto error; | 499 | goto error; |
| 435 | } | 500 | } |
| 436 | if (!siz->width || !siz->height) { | 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 | goto error; | 503 | goto error; |
| 439 | } | 504 | } |
| 440 | if (!siz->tilewidth || !siz->tileheight) { | 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 | goto error; | 507 | goto error; |
| 443 | } | 508 | } |
| 444 | if (!siz->numcomps || siz->numcomps > 16384) { | 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 | goto error; | 511 | goto error; |
| 447 | } | 512 | } |
| 448 | if (siz->xoff >= siz->width) { | 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 | goto error; | 515 | goto error; |
| 451 | } | 516 | } |
| 452 | if (siz->yoff >= siz->height) { | 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 | goto error; | 519 | goto error; |
| 455 | } | 520 | } |
| 456 | if (siz->tilexoff > siz->xoff || siz->tilexoff + siz->tilewidth <= siz->xoff) { | 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 | goto error; | 523 | goto error; |
| 459 | } | 524 | } |
| 460 | if (siz->tileyoff > siz->yoff || siz->tileyoff + siz->tileheight <= siz->yoff) { | 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 | goto error; | 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 | goto error; | 537 | goto error; |
| 473 | } | 538 | } |
| 474 | if (siz->comps[i].hsamp == 0) { | 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 | goto error; | 541 | goto error; |
| 477 | } | 542 | } |
| 478 | if (siz->comps[i].vsamp == 0) { | 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 | goto error; | 545 | goto error; |
| 481 | } | 546 | } |
| 482 | siz->comps[i].sgnd = (tmp >> 7) & 1; | 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 | samples and 2 bits for signed samples */ | 550 | samples and 2 bits for signed samples */ |
| 486 | if (siz->comps[i].prec < 1U + siz->comps[i].sgnd || | 551 | if (siz->comps[i].prec < 1U + siz->comps[i].sgnd || |
| 487 | siz->comps[i].prec > 38) { | 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 | goto error; | 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 | jpc_siz_t *siz = &ms->parms.siz; | 571 | jpc_siz_t *siz = &ms->parms.siz; |
| 507 | unsigned int i; | 572 | unsigned int i; |
| 508 | 573 | ||
| 509 | /* Eliminate compiler warning about unused variables. */ | 574 | JAS_UNUSED(cstate); |
| 510 | (void)cstate; | ||
| 511 | 575 | ||
| 512 | assert(siz->width && siz->height && siz->tilewidth && | 576 | assert(siz->width && siz->height && siz->tilewidth && |
| 513 | siz->tileheight && siz->numcomps); | 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 | return 0; | 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 | * COD marker segment operations. | 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 | return 0; | 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 | * COC marker segment operations. | 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 | return 0; | 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 | * COD/COC marker segment operation helper functions. | 767 | * COD/COC marker segment operation helper functions. |
| 652 | \******************************************************************************/ | 768 | \******************************************************************************/ |
| 653 | 769 | ||
| 654 | static void jpc_cox_destroycompparms(jpc_coxcp_t *compparms) | 770 | static void jpc_cox_destroycompparms(jpc_coxcp_t *compparms) |
| 655 | { | 771 | { |
| 656 | /* Eliminate compiler warning about unused variables. */ | 772 | JAS_UNUSED(compparms); |
| 657 | USED(compparms); | ||
| 658 | } | 773 | } |
| 659 | 774 | ||
| 660 | static int jpc_cox_getcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate, | 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 | uint_fast8_t tmp; | 778 | uint_fast8_t tmp; |
| 664 | int i; | 779 | int i; |
| 665 | 780 | ||
| 666 | /* Eliminate compiler warning about unused variables. */ | 781 | JAS_UNUSED(ms); |
| 667 | USED(ms); | 782 | JAS_UNUSED(cstate); |
| 668 | USED(cstate); | ||
| 669 | 783 | ||
| 670 | if (jpc_getuint8(in, &compparms->numdlvls) || | 784 | if (jpc_getuint8(in, &compparms->numdlvls) || |
| 671 | jpc_getuint8(in, &compparms->cblkwidthval) || | 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 | int i; | 825 | int i; |
| 712 | assert(compparms->numdlvls <= 32); | 826 | assert(compparms->numdlvls <= 32); |
| 713 | 827 | ||
| 714 | /* Eliminate compiler warning about unused variables. */ | 828 | JAS_UNUSED(ms); |
| 715 | USED(ms); | 829 | JAS_UNUSED(cstate); |
| 716 | USED(cstate); | ||
| 717 | 830 | ||
| 718 | if (jpc_putuint8(out, compparms->numdlvls) || | 831 | if (jpc_putuint8(out, compparms->numdlvls) || |
| 719 | jpc_putuint8(out, compparms->cblkwidthval) || | 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 | return 0; | 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 | * QCD marker segment operations. | 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 | return jpc_qcx_putcompparms(compparms, cstate, out); | 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 | * QCC marker segment operations. | 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 | return 0; | 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 | * QCD/QCC marker segment helper functions. | 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 | int n; | 1024 | int n; |
| 875 | int i; | 1025 | int i; |
| 876 | 1026 | ||
| 877 | /* Eliminate compiler warning about unused variables. */ | 1027 | JAS_UNUSED(cstate); |
| 878 | (void)cstate; | ||
| 879 | 1028 | ||
| 880 | n = 0; | 1029 | n = 0; |
| 881 | if (jpc_getuint8(in, &tmp)) { | 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 | int i; | 1086 | int i; |
| 938 | 1087 | ||
| 939 | /* Eliminate compiler warning about unused variables. */ | 1088 | JAS_UNUSED(cstate); |
| 940 | (void)cstate; | ||
| 941 | 1089 | ||
| 942 | if (jpc_putuint8(out, ((compparms->numguard & 7) << 5) | compparms->qntsty)) { | 1090 | if (jpc_putuint8(out, ((compparms->numguard & 7) << 5) | compparms->qntsty)) { |
| 943 | return -1; | 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 | jpc_sop_t *sop = &ms->parms.sop; | 1114 | jpc_sop_t *sop = &ms->parms.sop; |
| 967 | 1115 | ||
| 968 | /* Eliminate compiler warning about unused variable. */ | 1116 | JAS_UNUSED(cstate); |
| 969 | (void)cstate; | ||
| 970 | 1117 | ||
| 971 | if (jpc_getuint16(in, &sop->seqno)) { | 1118 | if (jpc_getuint16(in, &sop->seqno)) { |
| 972 | return -1; | 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 | jpc_sop_t *sop = &ms->parms.sop; | 1126 | jpc_sop_t *sop = &ms->parms.sop; |
| 980 | 1127 | ||
| 981 | /* Eliminate compiler warning about unused variable. */ | 1128 | JAS_UNUSED(cstate); |
| 982 | (void)cstate; | ||
| 983 | 1129 | ||
| 984 | if (jpc_putuint16(out, sop->seqno)) { | 1130 | if (jpc_putuint16(out, sop->seqno)) { |
| 985 | return -1; | 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 | return 0; | 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 | * PPM marker segment operations. | 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 | jpc_ppm_t *ppm = &ms->parms.ppm; | 1157 | jpc_ppm_t *ppm = &ms->parms.ppm; |
| 1005 | 1158 | ||
| 1006 | /* Eliminate compiler warning about unused variables. */ | 1159 | JAS_UNUSED(cstate); |
| 1007 | (void)cstate; | ||
| 1008 | 1160 | ||
| 1009 | ppm->data = 0; | 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 | jpc_ppm_t *ppm = &ms->parms.ppm; | 1190 | jpc_ppm_t *ppm = &ms->parms.ppm; |
| 1039 | 1191 | ||
| 1040 | /* Eliminate compiler warning about unused variables. */ | 1192 | JAS_UNUSED(cstate); |
| 1041 | (void)cstate; | ||
| 1042 | 1193 | ||
| 1043 | if (JAS_CAST(jas_uint, jas_stream_write(out, (char *) ppm->data, ppm->len)) != ppm->len) { | 1194 | if (JAS_CAST(jas_uint, jas_stream_write(out, (char *) ppm->data, ppm->len)) != ppm->len) { |
| 1044 | return -1; | 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 | return 0; | 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 | * PPT marker segment operations. | 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 | jpc_ppt_t *ppt = &ms->parms.ppt; | 1225 | jpc_ppt_t *ppt = &ms->parms.ppt; |
| 1064 | 1226 | ||
| 1065 | /* Eliminate compiler warning about unused variables. */ | 1227 | JAS_UNUSED(cstate); |
| 1066 | (void)cstate; | ||
| 1067 | 1228 | ||
| 1068 | ppt->data = 0; | 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 | jpc_ppt_t *ppt = &ms->parms.ppt; | 1257 | jpc_ppt_t *ppt = &ms->parms.ppt; |
| 1097 | 1258 | ||
| 1098 | /* Eliminate compiler warning about unused variable. */ | 1259 | JAS_UNUSED(cstate); |
| 1099 | (void)cstate; | ||
| 1100 | 1260 | ||
| 1101 | if (jpc_putuint8(out, ppt->ind)) { | 1261 | if (jpc_putuint8(out, ppt->ind)) { |
| 1102 | return -1; | 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 | return 0; | 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 | * POC marker segment operations. | 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 | return 0; | 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 | * CRG marker segment operations. | 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 | int compno; | 1423 | int compno; |
| 1236 | jpc_crgcomp_t *comp; | 1424 | jpc_crgcomp_t *comp; |
| 1237 | 1425 | ||
| 1238 | /* Eliminate compiler warning about unused variables. */ | 1426 | JAS_UNUSED(cstate); |
| 1239 | (void)cstate; | ||
| 1240 | 1427 | ||
| 1241 | for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno, | 1428 | for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno, |
| 1242 | ++comp) { | 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 | return 0; | 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 | * Operations for COM marker segment. | 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 | jpc_com_t *com = &ms->parms.com; | 1465 | jpc_com_t *com = &ms->parms.com; |
| 1266 | 1466 | ||
| 1267 | /* Eliminate compiler warning about unused variables. */ | 1467 | JAS_UNUSED(cstate); |
| 1268 | (void)cstate; | ||
| 1269 | 1468 | ||
| 1270 | if (jpc_getuint16(in, &com->regid)) { | 1469 | if (jpc_getuint16(in, &com->regid)) { |
| 1271 | return -1; | 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 | jpc_com_t *com = &ms->parms.com; | 1488 | jpc_com_t *com = &ms->parms.com; |
| 1290 | 1489 | ||
| 1291 | /* Eliminate compiler warning about unused variables. */ | 1490 | JAS_UNUSED(cstate); |
| 1292 | (void)cstate; | ||
| 1293 | 1491 | ||
| 1294 | if (jpc_putuint16(out, com->regid)) { | 1492 | if (jpc_putuint16(out, com->regid)) { |
| 1295 | return -1; | 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 | return 0; | 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 | * Operations for unknown types of marker segments. | 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 | unk->data = 0; | 1540 | unk->data = 0; |
| 1320 | 1541 | ||
| 1321 | /* Eliminate compiler warning about unused variables. */ | 1542 | JAS_UNUSED(cstate); |
| 1322 | (void)cstate; | ||
| 1323 | 1543 | ||
| 1324 | if (ms->len > 0) { | 1544 | if (ms->len > 0) { |
| 1325 | if (!(unk->data = jas_alloc2(ms->len, sizeof(unsigned char)))) { | 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 | static int jpc_unk_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out) | 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. */ | 1562 | JAS_UNUSED(cstate); |
| 1343 | USED(cstate); | 1563 | JAS_UNUSED(ms); |
| 1344 | USED(ms); | 1564 | JAS_UNUSED(out); |
| 1345 | USED(out); | ||
| 1346 | 1565 | ||
| 1347 | /* If this function is called, we are trying to write an unsupported | 1566 | /* If this function is called, we are trying to write an unsupported |
| 1348 | type of marker segment. Return with an error indication. */ | 1567 | type of marker segment. Return with an error indication. */ |
| 1349 | return -1; | 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 | * Primitive I/O operations. | 1582 | * Primitive I/O operations. |
| 1354 | \******************************************************************************/ | 1583 | \******************************************************************************/ |
| @@ -1430,6 +1659,12 @@ int jpc_validate(jas_stream_t *in) · 75 unmodified lines | |||
| 1430 | { | 1659 | { |
| 1431 | unsigned char buf[2]; | 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 | assert(JAS_STREAM_MAXPUTBACK >= 2); | 1668 | assert(JAS_STREAM_MAXPUTBACK >= 2); |
| 1434 | 1669 | ||
| 1435 | if (jas_stream_peek(in, buf, sizeof(buf)) != sizeof(buf)) | 1670 | if (jas_stream_peek(in, buf, sizeof(buf)) != sizeof(buf)) |
| @@ -726,6 +726,9 @@ typedef struct jpc_msops_s { · 725 unmodified lines | |||
| 726 | /* Put the marker segment parameters to a stream. */ | 726 | /* Put the marker segment parameters to a stream. */ |
| 727 | int (*putparms)(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out); | 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 | } jpc_msops_t; | 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 | /* Copy code stream data from one stream to another. */ | 774 | /* Copy code stream data from one stream to another. */ |
| 772 | int jpc_putdata(jas_stream_t *out, jas_stream_t *in, long n); | 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 | /* Read a 8-bit unsigned integer from a stream. */ | 780 | /* Read a 8-bit unsigned integer from a stream. */ |
| 775 | int jpc_getuint8(jas_stream_t *in, uint_fast8_t *val); | 781 | int jpc_getuint8(jas_stream_t *in, uint_fast8_t *val); |
| 776 | 782 | ||
| @@ -78,8 +78,10 @@ · 77 unmodified lines | |||
| 78 | #include "jpc_t1dec.h" | 78 | #include "jpc_t1dec.h" |
| 79 | #include "jpc_math.h" | 79 | #include "jpc_math.h" |
| 80 | 80 | ||
| 81 | #include "jasper/jas_init.h" | ||
| 81 | #include "jasper/jas_types.h" | 82 | #include "jasper/jas_types.h" |
| 82 | #include "jasper/jas_math.h" | 83 | #include "jasper/jas_math.h" |
| 84 | #include "jasper/jas_tvp.h" | ||
| 83 | #include "jasper/jas_malloc.h" | 85 | #include "jasper/jas_malloc.h" |
| 84 | #include "jasper/jas_debug.h" | 86 | #include "jasper/jas_debug.h" |
| 85 | 87 | ||
| @@ -131,6 +133,8 @@ typedef struct { · 45 unmodified lines | |||
| 131 | * Local function prototypes. | 133 | * Local function prototypes. |
| 132 | \******************************************************************************/ | 134 | \******************************************************************************/ |
| 133 | 135 | ||
| 136 | static int jpc_dec_dump(const jpc_dec_t *dec); | ||
| 137 | |||
| 134 | static jpc_ppxstab_t *jpc_ppxstab_create(void); | 138 | static jpc_ppxstab_t *jpc_ppxstab_create(void); |
| 135 | static void jpc_ppxstab_destroy(jpc_ppxstab_t *tab); | 139 | static void jpc_ppxstab_destroy(jpc_ppxstab_t *tab); |
| 136 | static int jpc_ppxstab_grow(jpc_ppxstab_t *tab, unsigned maxents); | 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 | static const jpc_dec_mstabent_t *jpc_dec_mstab_lookup(uint_fast16_t id); | 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 | * Global data. | 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 | dec = 0; | 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 | if (!(opts = jpc_dec_opts_create(optstr))) { | 251 | if (!(opts = jpc_dec_opts_create(optstr))) { |
| 242 | goto error; | 252 | goto error; |
| 243 | } | 253 | } |
| 244 | 254 | ||
| 245 | jpc_initluts(); | 255 | jpc_init(); |
| 256 | //jpc_initluts(); | ||
| 246 | 257 | ||
| 247 | if (!(dec = jpc_dec_create(opts, in))) { | 258 | if (!(dec = jpc_dec_create(opts, in))) { |
| 248 | goto error; | 259 | goto error; |
| @@ -290,11 +301,27 @@ error: · 41 unmodified lines | |||
| 290 | return 0; | 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 | static jpc_dec_importopts_t *jpc_dec_opts_create(const char *optstr) | 319 | static jpc_dec_importopts_t *jpc_dec_opts_create(const char *optstr) |
| 294 | { | 320 | { |
| 295 | jpc_dec_importopts_t *opts; | 321 | jpc_dec_importopts_t *opts; |
| 322 | jas_tvparser_t *tvp; | ||
| 323 | |||
| 296 | 324 | ||
| 297 | USED(optstr); | ||
| 298 | if (!(opts = jas_malloc(sizeof(jpc_dec_importopts_t)))) { | 325 | if (!(opts = jas_malloc(sizeof(jpc_dec_importopts_t)))) { |
| 299 | goto error; | 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 | opts->debug = 0; | 329 | opts->debug = 0; |
| 303 | opts->maxlyrs = JPC_MAXLYRS; | 330 | opts->maxlyrs = JPC_MAXLYRS; |
| 304 | opts->maxpkts = -1; | 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 | return opts; | 362 | return opts; |
| 308 | 363 | ||
| @@ -353,7 +408,7 @@ static int jpc_dec_decode(jpc_dec_t *dec) · 44 unmodified lines | |||
| 353 | 408 | ||
| 354 | /* Get the next marker segment in the code stream. */ | 409 | /* Get the next marker segment in the code stream. */ |
| 355 | if (!(ms = jpc_getms(dec->in, cstate))) { | 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 | return -1; | 412 | return -1; |
| 358 | } | 413 | } |
| 359 | 414 | ||
| @@ -363,7 +418,7 @@ static int jpc_dec_decode(jpc_dec_t *dec) · 3 unmodified lines | |||
| 363 | /* Ensure that this type of marker segment is permitted | 418 | /* Ensure that this type of marker segment is permitted |
| 364 | at this point in the code stream. */ | 419 | at this point in the code stream. */ |
| 365 | if (!(dec->state & mstabent->validstates)) { | 420 | if (!(dec->state & mstabent->validstates)) { |
| 366 | jas_eprintf("unexpected marker segment type\n"); | 421 | jas_logerrorf("unexpected marker segment type\n"); |
| 367 | jpc_ms_destroy(ms); | 422 | jpc_ms_destroy(ms); |
| 368 | return -1; | 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 | cmpt->vsubstep = crg->comps[cmptno].voff; | 462 | cmpt->vsubstep = crg->comps[cmptno].voff; |
| 408 | */ | 463 | */ |
| 409 | /* suppress -Wunused-but-set-variable */ | 464 | /* suppress -Wunused-but-set-variable */ |
| 410 | USED(crg); | 465 | JAS_UNUSED(crg); |
| 411 | } | 466 | } |
| 412 | return 0; | 467 | return 0; |
| 413 | } | 468 | } |
| 414 | 469 | ||
| 415 | static int jpc_dec_process_soc(jpc_dec_t *dec, jpc_ms_t *ms) | 470 | static int jpc_dec_process_soc(jpc_dec_t *dec, jpc_ms_t *ms) |
| 416 | { | 471 | { |
| 417 | /* Eliminate warnings about unused variables. */ | 472 | JAS_UNUSED(ms); |
| 418 | (void)ms; | ||
| 419 | 473 | ||
| 420 | /* We should expect to encounter a SIZ marker segment next. */ | 474 | /* We should expect to encounter a SIZ marker segment next. */ |
| 421 | dec->state = JPC_MHSIZ; | 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 | if (sot->tileno >= dec->numtiles) { | 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 | return -1; | 536 | return -1; |
| 483 | } | 537 | } |
| 484 | /* Set the current tile. */ | 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 | jpc_dec_tile_t *tile; | 583 | jpc_dec_tile_t *tile; |
| 530 | int pos; | 584 | int pos; |
| 531 | 585 | ||
| 532 | /* Eliminate compiler warnings about unused variables. */ | 586 | JAS_UNUSED(ms); |
| 533 | (void)ms; | ||
| 534 | 587 | ||
| 535 | if (!(tile = dec->curtile)) { | 588 | if (!(tile = dec->curtile)) { |
| 536 | return -1; | 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 | pos = jas_stream_tell(tile->pkthdrstream); | 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 | if (jpc_pptstabwrite(tile->pkthdrstream, tile->pptstab)) { | 621 | if (jpc_pptstabwrite(tile->pkthdrstream, tile->pptstab)) { |
| 569 | return -1; | 622 | return -1; |
| 570 | } | 623 | } |
| 571 | jas_stream_seek(tile->pkthdrstream, pos, 0); | 624 | jas_stream_seek(tile->pkthdrstream, pos, SEEK_SET); |
| 572 | jpc_ppxstab_destroy(tile->pptstab); | 625 | jpc_ppxstab_destroy(tile->pptstab); |
| 573 | tile->pptstab = 0; | 626 | tile->pptstab = 0; |
| 574 | } | 627 | } |
| 575 | 628 | ||
| 629 | if (jas_get_debug_level() >= 10) { | ||
| 630 | jpc_dec_dump(dec); | ||
| 631 | } | ||
| 632 | |||
| 576 | if (jpc_dec_decodepkts(dec, (tile->pkthdrstream) ? tile->pkthdrstream : | 633 | if (jpc_dec_decodepkts(dec, (tile->pkthdrstream) ? tile->pkthdrstream : |
| 577 | dec->in, dec->in)) { | 634 | dec->in, dec->in)) { |
| 578 | jas_eprintf("jpc_dec_decodepkts failed\n"); | 635 | jas_logerrorf("jpc_dec_decodepkts failed\n"); |
| 579 | return -1; | 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 | curoff = jas_stream_getrwcount(dec->in); | 643 | curoff = jas_stream_getrwcount(dec->in); |
| 587 | if (curoff < dec->curtileendoff) { | 644 | if (curoff < dec->curtileendoff) { |
| 588 | n = dec->curtileendoff - curoff; | 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 | (unsigned long) n); | 647 | (unsigned long) n); |
| 591 | 648 | ||
| 592 | while (n-- > 0) { | 649 | while (n-- > 0) { |
| 593 | if (jas_stream_getc(dec->in) == EOF) { | 650 | if (jas_stream_getc(dec->in) == EOF) { |
| 594 | jas_eprintf("read error\n"); | 651 | jas_logerrorf("read error\n"); |
| 595 | return -1; | 652 | return -1; |
| 596 | } | 653 | } |
| 597 | } | 654 | } |
| 598 | } else if (curoff > dec->curtileendoff) { | 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 | (unsigned long) curoff - dec->curtileendoff); | 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 | uint_fast32_t tmpyend; | 710 | uint_fast32_t tmpyend; |
| 654 | jpc_tsfb_band_t bnds[JPC_MAXBANDS]; | 711 | jpc_tsfb_band_t bnds[JPC_MAXBANDS]; |
| 655 | jpc_pchg_t *pchg; | 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 | const jpc_dec_cp_t *cp = tile->cp; | 719 | const jpc_dec_cp_t *cp = tile->cp; |
| 658 | tile->realmode = 0; | 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 | for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno < | 727 | for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno < |
| 666 | dec->numcomps; ++compno, ++tcomp, ++cmpt) { | 728 | dec->numcomps; ++compno, ++tcomp, ++cmpt) { |
| 667 | const jpc_dec_ccp_t *ccp = &tile->cp->ccps[compno]; | 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 | if (ccp->qmfbid == JPC_COX_INS) { | 733 | if (ccp->qmfbid == JPC_COX_INS) { |
| 669 | tile->realmode = 1; | 734 | tile->realmode = 1; |
| 670 | } | 735 | } |
| 671 | tcomp->numrlvls = ccp->numrlvls; | 736 | tcomp->numrlvls = ccp->numrlvls; |
| 672 | if (!(tcomp->rlvls = jas_alloc2(tcomp->numrlvls, | 737 | if (!(tcomp->rlvls = jas_alloc2(tcomp->numrlvls, |
| 673 | sizeof(jpc_dec_rlvl_t)))) { | 738 | sizeof(jpc_dec_rlvl_t)))) { |
| 674 | return -1; | 739 | retval = -1; |
| 740 | goto done; | ||
| 675 | } | 741 | } |
| 676 | for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls; | 742 | for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls; |
| 677 | ++rlvlno, ++rlvl) { | 743 | ++rlvlno, ++rlvl) { |
| 744 | #if 0 | ||
| 678 | rlvl->bands = NULL; | 745 | rlvl->bands = NULL; |
| 746 | #else | ||
| 747 | jpc_rlvl_init(rlvl); | ||
| 748 | #endif | ||
| 679 | } | 749 | } |
| 680 | if (!(tcomp->data = jas_seq2d_create(JPC_CEILDIV(tile->xstart, | 750 | if (!(tcomp->data = jas_seq2d_create(JPC_CEILDIV(tile->xstart, |
| 681 | cmpt->hstep), JPC_CEILDIV(tile->ystart, cmpt->vstep), | 751 | cmpt->hstep), JPC_CEILDIV(tile->ystart, cmpt->vstep), |
| 682 | JPC_CEILDIV(tile->xend, cmpt->hstep), JPC_CEILDIV(tile->yend, | 752 | JPC_CEILDIV(tile->xend, cmpt->hstep), JPC_CEILDIV(tile->yend, |
| 683 | cmpt->vstep)))) { | 753 | cmpt->vstep)))) { |
| 684 | return -1; | 754 | retval = -1; |
| 755 | goto done; | ||
| 685 | } | 756 | } |
| 686 | if (!(tcomp->tsfb = jpc_cod_gettsfb(ccp->qmfbid, | 757 | if (!(tcomp->tsfb = jpc_cod_gettsfb(ccp->qmfbid, |
| 687 | tcomp->numrlvls - 1))) { | 758 | tcomp->numrlvls - 1))) { |
| 688 | return -1; | 759 | retval = -1; |
| 760 | goto done; | ||
| 689 | } | 761 | } |
| 690 | { | 762 | { |
| 691 | jpc_tsfb_getbands(tcomp->tsfb, jas_seq2d_xstart(tcomp->data), | 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 | rlvl->prcheightexpn; | 791 | rlvl->prcheightexpn; |
| 720 | rlvl->numprcs = rlvl->numhprcs * rlvl->numvprcs; | 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 | if (rlvl->numprcs >= 64 * 1024) { | 804 | if (rlvl->numprcs >= 64 * 1024) { |
| 723 | /* avoid out-of-memory due to | 805 | /* avoid out-of-memory due to |
| 724 | malicious file; this limit is | 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 | if (rlvl->prcwidthexpn < 1 || rlvl->prcheightexpn < 1) { | 829 | if (rlvl->prcwidthexpn < 1 || rlvl->prcheightexpn < 1) { |
| 748 | /* the control block width/height offset | 830 | /* the control block width/height offset |
| 749 | exponent must not be negative */ | 831 | exponent must not be negative */ |
| 750 | return -1; | 832 | retval = -1; |
| 833 | goto done; | ||
| 751 | } | 834 | } |
| 752 | rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1; | 835 | rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1; |
| 753 | rlvl->cbgheightexpn = rlvl->prcheightexpn - 1; | 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 | rlvl->numbands = (!rlvlno) ? 1 : 3; | 843 | rlvl->numbands = (!rlvlno) ? 1 : 3; |
| 761 | if (!(rlvl->bands = jas_alloc2(rlvl->numbands, | 844 | if (!(rlvl->bands = jas_alloc2(rlvl->numbands, |
| 762 | sizeof(jpc_dec_band_t)))) { | 845 | sizeof(jpc_dec_band_t)))) { |
| 763 | return -1; | 846 | retval = -1; |
| 847 | goto done; | ||
| 764 | } | 848 | } |
| 765 | unsigned bandno; | 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 | for (bandno = 0, band = rlvl->bands; | 856 | for (bandno = 0, band = rlvl->bands; |
| 767 | bandno < rlvl->numbands; ++bandno, ++band) { | 857 | bandno < rlvl->numbands; ++bandno, ++band) { |
| 768 | unsigned bndno = (!rlvlno) ? 0 : (3 * (rlvlno - 1) + | 858 | unsigned bndno = (!rlvlno) ? 0 : (3 * (rlvlno - 1) + |
| 769 | bandno + 1); | 859 | bandno + 1); |
| 770 | const jpc_tsfb_band_t *bnd = &bnds[bndno]; | 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 | band->orient = bnd->orient; | 866 | band->orient = bnd->orient; |
| 773 | band->stepsize = ccp->stepsizes[bndno]; | 867 | band->stepsize = ccp->stepsizes[bndno]; |
| 774 | band->analgain = JPC_NOMINALGAIN(ccp->qmfbid, | 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 | continue; | 879 | continue; |
| 786 | } | 880 | } |
| 787 | if (!(band->data = jas_seq2d_create(0, 0, 0, 0))) { | 881 | if (!(band->data = jas_seq2d_create(0, 0, 0, 0))) { |
| 788 | return -1; | 882 | retval = -1; |
| 883 | goto done; | ||
| 789 | } | 884 | } |
| 790 | if (jas_seq2d_bindsub(band->data, tcomp->data, bnd->locxstart, | 885 | if (jas_seq2d_bindsub(band->data, tcomp->data, bnd->locxstart, |
| 791 | bnd->locystart, bnd->locxend, bnd->locyend)) { | 886 | bnd->locystart, bnd->locxend, bnd->locyend)) { |
| 792 | return -1; | 887 | retval = -1; |
| 888 | goto done; | ||
| 793 | } | 889 | } |
| 794 | jas_seq2d_setshift(band->data, bnd->xstart, bnd->ystart); | 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 | if (!(band->prcs = jas_alloc2(rlvl->numprcs, | 894 | if (!(band->prcs = jas_alloc2(rlvl->numprcs, |
| 799 | sizeof(jpc_dec_prc_t)))) { | 895 | sizeof(jpc_dec_prc_t)))) { |
| 800 | return -1; | 896 | retval = -1; |
| 897 | goto done; | ||
| 801 | } | 898 | } |
| 802 | 899 | ||
| 803 | /************************************************/ | 900 | /************************************************/ |
| 804 | cbgxstart = tlcbgxstart; | 901 | cbgxstart = tlcbgxstart; |
| 805 | cbgystart = tlcbgystart; | 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 | prccnt > 0; --prccnt, ++prc) { | 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 | cbgxend = cbgxstart + (1 << rlvl->cbgwidthexpn); | 915 | cbgxend = cbgxstart + (1 << rlvl->cbgwidthexpn); |
| 809 | cbgyend = cbgystart + (1 << rlvl->cbgheightexpn); | 916 | cbgyend = cbgystart + (1 << rlvl->cbgheightexpn); |
| 810 | prc->xstart = JAS_MAX(cbgxstart, JAS_CAST(uint_fast32_t, | 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 | prc->numcblks = prc->numhcblks * prc->numvcblks; | 938 | prc->numcblks = prc->numhcblks * prc->numvcblks; |
| 832 | assert(prc->numcblks > 0); | 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 | if (!(prc->incltagtree = jpc_tagtree_create( | 948 | if (!(prc->incltagtree = jpc_tagtree_create( |
| 835 | prc->numhcblks, prc->numvcblks))) { | 949 | prc->numhcblks, prc->numvcblks))) { |
| 836 | return -1; | 950 | retval = -1; |
| 951 | goto done; | ||
| 837 | } | 952 | } |
| 838 | if (!(prc->numimsbstagtree = jpc_tagtree_create( | 953 | if (!(prc->numimsbstagtree = jpc_tagtree_create( |
| 839 | prc->numhcblks, prc->numvcblks))) { | 954 | prc->numhcblks, prc->numvcblks))) { |
| 840 | return -1; | 955 | retval = -1; |
| 956 | goto done; | ||
| 841 | } | 957 | } |
| 842 | if (!(prc->cblks = jas_alloc2(prc->numcblks, | 958 | if (!(prc->cblks = jas_alloc2(prc->numcblks, |
| 843 | sizeof(jpc_dec_cblk_t)))) { | 959 | sizeof(jpc_dec_cblk_t)))) { |
| 844 | return -1; | 960 | retval = -1; |
| 961 | goto done; | ||
| 845 | } | 962 | } |
| 846 | 963 | ||
| 847 | cblkxstart = cbgxstart; | 964 | cblkxstart = cbgxstart; |
| 848 | cblkystart = cbgystart; | 965 | cblkystart = cbgystart; |
| 849 | unsigned cblkcnt; | 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 | for (cblkcnt = prc->numcblks, cblk = prc->cblks; | 973 | for (cblkcnt = prc->numcblks, cblk = prc->cblks; |
| 851 | cblkcnt > 0;) { | 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 | cblkxend = cblkxstart + (1 << rlvl->cblkwidthexpn); | 978 | cblkxend = cblkxstart + (1 << rlvl->cblkwidthexpn); |
| 853 | cblkyend = cblkystart + (1 << rlvl->cblkheightexpn); | 979 | cblkyend = cblkystart + (1 << rlvl->cblkheightexpn); |
| 854 | tmpxstart = JAS_MAX(cblkxstart, prc->xstart); | 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 | cblk->numlenbits = 3; | 991 | cblk->numlenbits = 3; |
| 866 | if (!(cblk->data = jas_seq2d_create(0, 0, 0, | 992 | if (!(cblk->data = jas_seq2d_create(0, 0, 0, |
| 867 | 0))) { | 993 | 0))) { |
| 868 | return -1; | 994 | retval = -1; |
| 995 | goto done; | ||
| 869 | } | 996 | } |
| 870 | if (jas_seq2d_bindsub(cblk->data, band->data, | 997 | if (jas_seq2d_bindsub(cblk->data, band->data, |
| 871 | tmpxstart, tmpystart, tmpxend, tmpyend)) { | 998 | tmpxstart, tmpystart, tmpxend, tmpyend)) { |
| 872 | return -1; | 999 | retval = -1; |
| 1000 | goto done; | ||
| 873 | } | 1001 | } |
| 874 | ++cblk; | 1002 | ++cblk; |
| 875 | --cblkcnt; | 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 | if (!(tile->pi = jpc_dec_pi_create(dec, tile))) { | 1029 | if (!(tile->pi = jpc_dec_pi_create(dec, tile))) { |
| 902 | return -1; | 1030 | retval = -1; |
| 1031 | goto done; | ||
| 903 | } | 1032 | } |
| 904 | 1033 | ||
| 905 | for (unsigned pchgno = 0; pchgno < jpc_pchglist_numpchgs(tile->cp->pchglist); | 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 | jpc_pi_init(tile->pi); | 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 | static int jpc_dec_tilefini(jpc_dec_t *dec, jpc_dec_tile_t *tile) | 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 | jpc_dec_seg_t *seg; | 1055 | jpc_dec_seg_t *seg; |
| 921 | jpc_dec_cblk_t *cblk; | 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 | unsigned compno; | 1063 | unsigned compno; |
| 926 | for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps; | 1064 | for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps; |
| 927 | ++compno, ++tcomp) { | 1065 | ++compno, ++tcomp) { |
| 928 | const jpc_dec_rlvl_t *rlvl; | 1066 | if (tcomp->rlvls) { |
| 929 | for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls; | 1067 | const jpc_dec_rlvl_t *rlvl; |
| 930 | ++rlvlno, ++rlvl) { | 1068 | for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls; |
| 931 | if (!rlvl->bands) { | 1069 | ++rlvlno, ++rlvl) { |
| 932 | continue; | 1070 | if (!rlvl->bands) { |
| 933 | } | 1071 | continue; |
| 934 | unsigned bandno; | 1072 | } |
| 935 | const jpc_dec_band_t *band; | 1073 | unsigned bandno; |
| 936 | for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; | 1074 | const jpc_dec_band_t *band; |
| 937 | ++bandno, ++band) { | 1075 | for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; |
| 938 | if (band->prcs) { | 1076 | ++bandno, ++band) { |
| 939 | unsigned prcno; | 1077 | if (band->prcs) { |
| 940 | const jpc_dec_prc_t *prc; | 1078 | unsigned prcno; |
| 941 | for (prcno = 0, prc = band->prcs; prcno < | 1079 | const jpc_dec_prc_t *prc; |
| 942 | rlvl->numprcs; ++prcno, ++prc) { | 1080 | for (prcno = 0, prc = band->prcs; prcno < |
| 943 | if (!prc->cblks) { | 1081 | rlvl->numprcs; ++prcno, ++prc) { |
| 944 | continue; | 1082 | if (prc->cblks) { |
| 945 | } | 1083 | unsigned cblkno; |
| 946 | unsigned cblkno; | 1084 | for (cblkno = 0, cblk = prc->cblks; cblkno < |
| 947 | for (cblkno = 0, cblk = prc->cblks; cblkno < | 1085 | prc->numcblks; ++cblkno, ++cblk) { |
| 948 | prc->numcblks; ++cblkno, ++cblk) { | 1086 | while (cblk->segs.head) { |
| 949 | 1087 | seg = cblk->segs.head; | |
| 950 | while (cblk->segs.head) { | 1088 | jpc_seglist_remove(&cblk->segs, seg); |
| 951 | seg = cblk->segs.head; | 1089 | jpc_seg_destroy(seg); |
| 952 | jpc_seglist_remove(&cblk->segs, seg); | 1090 | } |
| 953 | jpc_seg_destroy(seg); | 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) { | 1112 | if (rlvl->bands) { |
| 969 | jas_matrix_destroy(band->data); | 1113 | jas_free(rlvl->bands); |
| 970 | } | ||
| 971 | if (band->prcs) { | ||
| 972 | jas_free(band->prcs); | ||
| 973 | } | 1114 | } |
| 974 | } | 1115 | } |
| 975 | if (rlvl->bands) { | ||
| 976 | jas_free(rlvl->bands); | ||
| 977 | } | ||
| 978 | } | 1116 | } |
| 979 | if (tcomp->rlvls) { | 1117 | if (tcomp->rlvls) { |
| 980 | jas_free(tcomp->rlvls); | 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 | int v; | 1158 | int v; |
| 1021 | 1159 | ||
| 1022 | if (jpc_dec_decodecblks(dec, tile)) { | 1160 | if (jpc_dec_decodecblks(dec, tile)) { |
| 1023 | jas_eprintf("jpc_dec_decodecblks failed\n"); | 1161 | jas_logerrorf("jpc_dec_decodecblks failed\n"); |
| 1024 | return -1; | 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 | switch (tile->cp->mctid) { | 1203 | switch (tile->cp->mctid) { |
| 1066 | case JPC_MCT_RCT: | 1204 | case JPC_MCT_RCT: |
| 1067 | if (dec->numcomps < 3) { | 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 | return -1; | 1207 | return -1; |
| 1070 | } | 1208 | } |
| 1071 | if (!jas_image_cmpt_domains_same(dec->image)) { | 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 | return -1; | 1211 | return -1; |
| 1074 | } | 1212 | } |
| 1075 | jpc_irct(tile->tcomps[0].data, tile->tcomps[1].data, | 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 | break; | 1215 | break; |
| 1078 | case JPC_MCT_ICT: | 1216 | case JPC_MCT_ICT: |
| 1079 | if (dec->numcomps < 3) { | 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 | return -1; | 1219 | return -1; |
| 1082 | } | 1220 | } |
| 1083 | if (!jas_image_cmpt_domains_same(dec->image)) { | 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 | return -1; | 1223 | return -1; |
| 1086 | } | 1224 | } |
| 1087 | jpc_iict(tile->tcomps[0].data, tile->tcomps[1].data, | 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 | JPC_CEILDIV(dec->xstart, cmpt->hstep), tcomp->ystart - | 1292 | JPC_CEILDIV(dec->xstart, cmpt->hstep), tcomp->ystart - |
| 1155 | JPC_CEILDIV(dec->ystart, cmpt->vstep), jas_matrix_numcols( | 1293 | JPC_CEILDIV(dec->ystart, cmpt->vstep), jas_matrix_numcols( |
| 1156 | tcomp->data), jas_matrix_numrows(tcomp->data), tcomp->data)) { | 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 | return -1; | 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 | jpc_dec_tile_t *tile; | 1305 | jpc_dec_tile_t *tile; |
| 1168 | 1306 | ||
| 1169 | /* Eliminate compiler warnings about unused variables. */ | 1307 | JAS_UNUSED(ms); |
| 1170 | (void)ms; | ||
| 1171 | 1308 | ||
| 1172 | unsigned tileno; | 1309 | unsigned tileno; |
| 1173 | for (tileno = 0, tile = dec->tiles; tileno < dec->numtiles; ++tileno, | 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 | size_t total_samples; | 1341 | size_t total_samples; |
| 1205 | if (!jas_safe_size_mul(siz->width, siz->height, &total_samples) || | 1342 | if (!jas_safe_size_mul(siz->width, siz->height, &total_samples) || |
| 1206 | (dec->max_samples > 0 && total_samples > dec->max_samples)) { | 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 | return -1; | 1345 | return -1; |
| 1209 | } | 1346 | } |
| 1210 | 1347 | ||
| 1211 | size_t tile_samples; | 1348 | size_t tile_samples; |
| 1212 | if (!jas_safe_size_mul(siz->tilewidth, siz->tileheight, &tile_samples) || | 1349 | if (!jas_safe_size_mul(siz->tilewidth, siz->tileheight, &tile_samples) || |
| 1213 | (dec->max_samples > 0 && tile_samples > dec->max_samples)) { | 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 | return -1; | 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 | cmpt->hsubstep = 0; | 1385 | cmpt->hsubstep = 0; |
| 1249 | cmpt->vsubstep = 0; | 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 | if (!jas_safe_size_mul(cmpt->width, cmpt->height, &num_samples_delta)) { | 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 | return -1; | 1394 | return -1; |
| 1254 | } | 1395 | } |
| 1255 | if (!jas_safe_size_add(num_samples, num_samples_delta, &num_samples)) { | 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 | return -1; | 1398 | return -1; |
| 1258 | } | 1399 | } |
| 1259 | } | 1400 | } |
| 1260 | 1401 | ||
| 1261 | if (dec->max_samples > 0 && num_samples > dec->max_samples) { | 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 | num_samples, dec->max_samples); | 1404 | num_samples, dec->max_samples); |
| 1264 | return -1; | 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 | return -1; | 1428 | return -1; |
| 1288 | } | 1429 | } |
| 1289 | dec->numtiles = size; | 1430 | dec->numtiles = size; |
| 1290 | JAS_DBGLOG(10, ("numtiles = %d; numhtiles = %d; numvtiles = %d;\n", | 1431 | JAS_LOGDEBUGF(10, "numtiles = %d; numhtiles = %d; numvtiles = %d;\n", |
| 1291 | dec->numtiles, dec->numhtiles, dec->numvtiles)); | 1432 | dec->numtiles, dec->numhtiles, dec->numvtiles); |
| 1292 | if (!(dec->tiles = jas_alloc2(dec->numtiles, sizeof(jpc_dec_tile_t)))) { | 1433 | if (!(dec->tiles = jas_alloc2(dec->numtiles, sizeof(jpc_dec_tile_t)))) { |
| 1293 | return -1; | 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 | jpc_dec_tile_t *tile; | 1518 | jpc_dec_tile_t *tile; |
| 1378 | 1519 | ||
| 1379 | if (coc->compno >= dec->numcomps) { | 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 | return -1; | 1522 | return -1; |
| 1382 | } | 1523 | } |
| 1383 | switch (dec->state) { | 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 | jpc_dec_tile_t *tile; | 1544 | jpc_dec_tile_t *tile; |
| 1404 | 1545 | ||
| 1405 | if (rgn->compno >= dec->numcomps) { | 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 | return -1; | 1548 | return -1; |
| 1408 | } | 1549 | } |
| 1409 | switch (dec->state) { | 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 | jpc_dec_tile_t *tile; | 1593 | jpc_dec_tile_t *tile; |
| 1453 | 1594 | ||
| 1454 | if (qcc->compno >= dec->numcomps) { | 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 | return -1; | 1597 | return -1; |
| 1457 | } | 1598 | } |
| 1458 | switch (dec->state) { | 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 | static int jpc_dec_process_com(jpc_dec_t *dec, jpc_ms_t *ms) | 1693 | static int jpc_dec_process_com(jpc_dec_t *dec, jpc_ms_t *ms) |
| 1553 | { | 1694 | { |
| 1554 | /* Eliminate compiler warnings about unused variables. */ | 1695 | JAS_UNUSED(dec); |
| 1555 | USED(dec); | 1696 | JAS_UNUSED(ms); |
| 1556 | USED(ms); | ||
| 1557 | 1697 | ||
| 1558 | return 0; | 1698 | return 0; |
| 1559 | } | 1699 | } |
| 1560 | 1700 | ||
| 1561 | static int jpc_dec_process_unk(jpc_dec_t *dec, jpc_ms_t *ms) | 1701 | static int jpc_dec_process_unk(jpc_dec_t *dec, jpc_ms_t *ms) |
| 1562 | { | 1702 | { |
| 1563 | /* Eliminate compiler warnings about unused variables. */ | 1703 | JAS_UNUSED(dec); |
| 1564 | USED(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 | ms->id); | 1706 | ms->id); |
| 1568 | return 0; | 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 | cp->numlyrs = 0; | 1725 | cp->numlyrs = 0; |
| 1587 | cp->mctid = 0; | 1726 | cp->mctid = 0; |
| 1588 | cp->csty = 0; | 1727 | cp->csty = 0; |
| 1728 | cp->pchglist = 0; | ||
| 1589 | if (!(cp->ccps = jas_alloc2(cp->numcomps, sizeof(jpc_dec_ccp_t)))) { | 1729 | if (!(cp->ccps = jas_alloc2(cp->numcomps, sizeof(jpc_dec_ccp_t)))) { |
| 1590 | goto error; | 1730 | goto error; |
| 1591 | } | 1731 | } |
| @@ -1694,7 +1834,11 @@ static int calcstepsizes(uint_fast16_t refstepsize, unsigned numrlvls, · 102 unmodified lines | |||
| 1694 | mant = JPC_QCX_GETMANT(refstepsize); | 1834 | mant = JPC_QCX_GETMANT(refstepsize); |
| 1695 | const unsigned numbands = 3 * numrlvls - 2; | 1835 | const unsigned numbands = 3 * numrlvls - 2; |
| 1696 | for (unsigned bandno = 0; bandno < numbands; ++bandno) { | 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 | const unsigned r = (bandno + 2) / 3; | 1842 | const unsigned r = (bandno + 2) / 3; |
| 1699 | const unsigned nb = (r == 0) ? (numrlvls - 1) - r : (numrlvls - 1) - r + 1; | 1843 | const unsigned nb = (r == 0) ? (numrlvls - 1) - r : (numrlvls - 1) - r + 1; |
| 1700 | uint_fast16_t e = expn - (numrlvls - 1) + nb; | 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 | int rlvlno; | 1903 | int rlvlno; |
| 1760 | 1904 | ||
| 1761 | /* Eliminate compiler warnings about unused variables. */ | 1905 | JAS_UNUSED(cp); |
| 1762 | USED(cp); | ||
| 1763 | 1906 | ||
| 1764 | if ((flags & JPC_COC) || !(ccp->flags & JPC_COC)) { | 1907 | if ((flags & JPC_COC) || !(ccp->flags & JPC_COC)) { |
| 1765 | ccp->numrlvls = compparms->numdlvls + 1; | 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 | int bandno; | 1947 | int bandno; |
| 1805 | 1948 | ||
| 1806 | /* Eliminate compiler warnings about unused variables. */ | 1949 | JAS_UNUSED(cp); |
| 1807 | USED(cp); | ||
| 1808 | 1950 | ||
| 1809 | /* Sanity check to prevent buffer overflow */ | 1951 | /* Sanity check to prevent buffer overflow */ |
| 1810 | if (compparms->numstepsizes > (3 * JPC_MAXRLVLS + 1)) { | 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 | // a reconstruction parameter defined in E 1.1.2 of the ISO/IEC 15444-1 | 2028 | // a reconstruction parameter defined in E 1.1.2 of the ISO/IEC 15444-1 |
| 1887 | jpc_fix_t recparam = JPC_FIX_HALF; | 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 | if (absstepsize == jpc_inttofix(1)) { | 2040 | if (absstepsize == jpc_inttofix(1)) { |
| 1891 | return; | 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 | if (roishift < 0) { | 2070 | if (roishift < 0) { |
| 1921 | /* We could instead return an error here. */ | 2071 | /* We could instead return an error here. */ |
| 1922 | /* I do not think it matters much. */ | 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 | "(bitstream is probably corrupt)\n"); | 2074 | "(bitstream is probably corrupt)\n"); |
| 1925 | roishift = 0; | 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 | Here we ensure that any such bits are masked off. */ | 2103 | Here we ensure that any such bits are masked off. */ |
| 1954 | if (mag & (~mask)) { | 2104 | if (mag & (~mask)) { |
| 1955 | if (!warn) { | 2105 | if (!warn) { |
| 1956 | jas_eprintf("warning: possibly corrupt code stream\n"); | 2106 | jas_logwarnf("warning: possibly corrupt code stream\n"); |
| 1957 | warn = true; | 2107 | warn = true; |
| 1958 | } | 2108 | } |
| 1959 | mag &= mask; | 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 | dec->cp = 0; | 2142 | dec->cp = 0; |
| 1993 | dec->maxlyrs = impopts->maxlyrs; | 2143 | dec->maxlyrs = impopts->maxlyrs; |
| 1994 | dec->maxpkts = impopts->maxpkts; | 2144 | dec->maxpkts = impopts->maxpkts; |
| 1995 | dec->numpkts = 0; | 2145 | dec->numpkts = 0; |
| 1996 | dec->ppmseqno = 0; | 2146 | dec->ppmseqno = 0; |
| 1997 | dec->state = 0; | 2147 | dec->state = 0; |
| 1998 | dec->cmpts = 0; | 2148 | dec->cmpts = 0; |
| @@ -2001,6 +2151,10 @@ dec->numpkts = 0; · 2 unmodified lines | |||
| 2001 | dec->curtileendoff = 0; | 2151 | dec->curtileendoff = 0; |
| 2002 | dec->max_samples = impopts->max_samples; | 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 | return dec; | 2158 | return dec; |
| 2005 | } | 2159 | } |
| 2006 | 2160 | ||
| @@ -2119,6 +2273,83 @@ void jpc_seg_destroy(jpc_dec_seg_t *seg) · 112 unmodified lines | |||
| 2119 | jas_free(seg); | 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 | static jpc_streamlist_t *jpc_streamlist_create() | 2353 | static jpc_streamlist_t *jpc_streamlist_create() |
| 2123 | { | 2354 | { |
| 2124 | jpc_streamlist_t *streamlist; | 2355 | jpc_streamlist_t *streamlist; |
| @@ -2366,3 +2597,75 @@ static void jpc_ppxstabent_destroy(jpc_ppxstabent_t *ent) · 241 unmodified lines | |||
| 2366 | } | 2597 | } |
| 2367 | jas_free(ent); | 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 | #include "jasper/jas_stream.h" | 77 | #include "jasper/jas_stream.h" |
| 78 | #include "jasper/jas_image.h" | 78 | #include "jasper/jas_image.h" |
| 79 | 79 | ||
| 80 | #include "jpc_cod.h" | ||
| 80 | #include "jpc_tsfb.h" | 81 | #include "jpc_tsfb.h" |
| 81 | #include "jpc_tagtree.h" | 82 | #include "jpc_tagtree.h" |
| 82 | #include "jpc_cs.h" | 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.