History

update to current

Sigrid Solveig Haflínudóttir committed 3 years agomaster

Commit f7e5af41 parent 7cdf83972 files · +16016 −1840Browse files

Unified · Split

72 files
  1. .gitignore +3 −0
  2. jas_cm.c +307 −142
  3. jas_debug.c +183 −22
  4. jas_icc.c +435 −239
  5. jas_iccdata.c +10 −0
  6. jas_image.c +404 −203
  7. jas_init.c +949 −23
  8. jas_malloc.c +651 −0
  9. jas_seq.c +9 −7
  10. jas_stream.c +413 −157
  11. jas_string.c +216 −0
  12. jas_tvp.c +234 −0
  13. jas_version.c +69 −0
  14. jasper/jas_cm.h +249 −21
  15. jasper/jas_compiler.h +69 −25
  16. jasper/jas_config.h +73 −3
  17. jasper/jas_debug.h +100 −10
  18. jasper/jas_dll.h +4 −24
  19. jasper/jas_fix.h +97 −44
  20. jasper/jas_icc.h +142 −20
  21. jasper/jas_image.h +222 −100
  22. jasper/jas_init.h +391 −10
  23. jasper/jas_log.h +168 −0
  24. jasper/jas_malloc.h +272 −7
  25. jasper/jas_math.h +401 −32
  26. jasper/jas_seq.h +271 −56
  27. jasper/jas_stream.h +201 −77
  28. jasper/jas_string.h +150 −0
  29. jasper/jas_thread.h +795 −0
  30. jasper/jas_tvp.h +200 −0
  31. jasper/jas_types.h +109 −35
  32. jasper/jas_version.h +113 −0
  33. jasper/jasper.h +6 −0
  34. jp2.c +4 −1
  35. jp2_cod.c +160 −50
  36. jp2_cod.h +2 −2
  37. jp2_dec.c +113 −59
  38. jp2_enc.c +494 −0
  39. jpc_bs.c +7 −4
  40. jpc_bs.h +2 −2
  41. jpc_cod.c +109 −0
  42. jpc_cod.h +4 −0
  43. jpc_cs.c +312 −77
  44. jpc_cs.h +6 −0
  45. jpc_dec.c +415 −112
  46. jpc_dec.h +1 −0
  47. jpc_enc.c +2665 −0
  48. jpc_enc.h +650 −0
  49. jpc_fix.h +28 −15
  50. jpc_math.c +34 −0
  51. jpc_math.h +8 −0
  52. jpc_mqdec.c +22 −4
  53. jpc_mqdec.h +7 −0
  54. jpc_mqenc.c +386 −0
  55. jpc_mqenc.h +217 −0
  56. jpc_qmfb.c +131 −141
  57. jpc_t1cod.c +18 −15
  58. jpc_t1cod.h +2 −0
  59. jpc_t1dec.c +19 −17
  60. jpc_t1enc.c +895 −0
  61. jpc_t1enc.h +86 −0
  62. jpc_t2cod.c +153 −53
  63. jpc_t2cod.h +6 −0
  64. jpc_t2dec.c +47 −21
  65. jpc_t2enc.c +656 −0
  66. jpc_t2enc.h +105 −0
  67. jpc_tagtree.c +21 −6
  68. jpc_tagtree.h +3 −0
  69. jpc_tsfb.c +9 −4
  70. jpc_util.c +186 −0
  71. jpc_util.h +82 −0
  72. mklib +35 −0
.gitignore+3−0
@@ -0,0 +1,3 @@
1+*.out
2+*.[o0125678vqki]
3+libjp2.a
jas_cm.c+307−142
@@ -65,10 +65,21 @@ · 64 unmodified lines
6565 * $Id$
6666 */
6767
68+/******************************************************************************\
69+* Includes.
70+\******************************************************************************/
71+
72+#define JAS_FOR_INTERNAL_USE_ONLY
73+
6874 #include "jasper/jas_cm.h"
6975 #include "jasper/jas_icc.h"
7076 #include "jasper/jas_malloc.h"
7177 #include "jasper/jas_math.h"
78+#include "jasper/jas_debug.h"
79+
80+/******************************************************************************\
81+* Function prototypes.
82+\******************************************************************************/
7283
7384 static jas_cmprof_t *jas_cmprof_create(void);
7485 static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *);
@@ -89,8 +100,10 @@ static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, · 14 unmodified lines
89100 unsigned, unsigned);
90101 static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, unsigned n);
91102
92−static int mono(const jas_iccprof_t *prof, int op, jas_cmpxformseq_t **pxformseq);
93−static int triclr(const jas_iccprof_t *prof, int op, jas_cmpxformseq_t **retpxformseq);
103+static int mono(const jas_iccprof_t *prof, int op,
104+ jas_cmpxformseq_t **pxformseq);
105+static int triclr(const jas_iccprof_t *prof, int op,
106+ jas_cmpxformseq_t **retpxformseq);
94107
95108 static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq);
96109 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
100113 static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq,
101114 int i, jas_cmpxform_t *pxform);
102115
116+/******************************************************************************\
117+* Function prototypes.
118+\******************************************************************************/
119+
103120 #define SEQFWD(intent) (intent)
104121 #define SEQREV(intent) (4 + (intent))
105122 #define SEQSIM(intent) (8 + (intent))
@@ -122,62 +139,81 @@ static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, · 16 unmodified lines
122139
123140 #define gampxformseq(prof) ((prof)->pxformseqs[SEQGAM])
124141
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);
126143 static jas_cmpxform_t *jas_cmpxform_create0(void);
127144 static jas_cmpxform_t *jas_cmpxform_createshapmat(void);
128145 static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut);
129146 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};
132147 static jas_cmprof_t *jas_cmprof_createsycc(void);
133148
149+/******************************************************************************\
150+*
151+\******************************************************************************/
152+
153+static const jas_cmpxformops_t shapmat_ops = {
154+ jas_cmshapmat_destroy,
155+ jas_cmshapmat_apply,
156+ 0
157+};
158+
134159 /******************************************************************************\
135160 * Color profile class.
136161 \******************************************************************************/
137162
138163 jas_cmprof_t *jas_cmprof_createfromclrspc(jas_clrspc_t clrspc)
139164 {
165+ JAS_LOGDEBUGF(1, "jas_cmprof_createfromclrspc(%d)\n", clrspc);
166+
140167 jas_iccprof_t *iccprof;
141168 jas_cmprof_t *prof;
142169
143170 iccprof = 0;
144171 switch (clrspc) {
145172 case JAS_CLRSPC_SYCBCR:
146− if (!(prof = jas_cmprof_createsycc()))
173+ if (!(prof = jas_cmprof_createsycc())) {
147174 goto error;
175+ }
148176 break;
149177 default:
150− if (!(iccprof = jas_iccprof_createfromclrspc(clrspc)))
178+ if (!(iccprof = jas_iccprof_createfromclrspc(clrspc))) {
151179 goto error;
152− if (!(prof = jas_cmprof_createfromiccprof(iccprof)))
180+ }
181+ if (!(prof = jas_cmprof_createfromiccprof(iccprof))) {
153182 goto error;
183+ }
154184 jas_iccprof_destroy(iccprof);
155− if (!jas_clrspc_isgeneric(clrspc))
185+ if (!jas_clrspc_isgeneric(clrspc)) {
156186 prof->clrspc = clrspc;
187+ }
157188 break;
158189 }
159190 return prof;
160191 error:
161− if (iccprof)
192+ if (iccprof) {
162193 jas_iccprof_destroy(iccprof);
194+ }
163195 return 0;
164196 }
165197
166198 static jas_cmprof_t *jas_cmprof_createsycc()
167199 {
200+ JAS_LOGDEBUGF(1, "jas_cmprof_createsycc()\n");
201+
168202 jas_cmprof_t *prof;
169− jas_cmpxform_t *fwdpxform = NULL;
170− jas_cmpxform_t *revpxform = NULL;
203+ jas_cmpxform_t *fwdpxform = 0;
204+ jas_cmpxform_t *revpxform = 0;
171205 jas_cmshapmat_t *fwdshapmat;
172206 jas_cmshapmat_t *revshapmat;
173207
174− if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)))
208+ if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) {
175209 goto error;
210+ }
176211 prof->clrspc = JAS_CLRSPC_SYCBCR;
177212 assert(prof->numchans == 3 && prof->numrefchans == 3);
178213 assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ);
179− if (!(fwdpxform = jas_cmpxform_createshapmat()))
214+ if (!(fwdpxform = jas_cmpxform_createshapmat())) {
180215 goto error;
216+ }
181217 fwdpxform->numinchans = 3;
182218 fwdpxform->numoutchans = 3;
183219 fwdshapmat = &fwdpxform->data.shapmat;
@@ -197,8 +233,9 @@ static jas_cmprof_t *jas_cmprof_createsycc() · 13 unmodified lines
197233 fwdshapmat->mat[0][3] = -0.5 * (1.402);
198234 fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414);
199235 fwdshapmat->mat[2][3] = -0.5 * (1.772);
200− if (!(revpxform = jas_cmpxform_createshapmat()))
236+ if (!(revpxform = jas_cmpxform_createshapmat())) {
201237 goto error;
238+ }
202239 revpxform->numinchans = 3;
203240 revpxform->numoutchans = 3;
204241 revshapmat = &revpxform->data.shapmat;
@@ -206,20 +243,24 @@ static jas_cmprof_t *jas_cmprof_createsycc() · 1 unmodified line
206243 revshapmat->order = 1;
207244 revshapmat->useluts = 0;
208245 revshapmat->usemat = 1;
209− jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat);
246+ if (jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat)) {
247+ goto error;
248+ }
210249
211250 for (unsigned i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) {
212251 unsigned j = SEQFWD(i);
213252 if (prof->pxformseqs[j]) {
214253 if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0,
215− fwdpxform))
254+ fwdpxform)) {
216255 goto error;
256+ }
217257 }
218258 j = SEQREV(i);
219259 if (prof->pxformseqs[j]) {
220260 if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j],
221− -1, revpxform))
261+ -1, revpxform)) {
222262 goto error;
263+ }
223264 }
224265 }
225266
@@ -227,15 +268,22 @@ static jas_cmprof_t *jas_cmprof_createsycc() · 1 unmodified line
227268 jas_cmpxform_destroy(revpxform);
228269 return prof;
229270 error:
230− if (fwdpxform)
271+ if (fwdpxform) {
231272 jas_cmpxform_destroy(fwdpxform);
232− if (revpxform)
273+ }
274+ if (revpxform) {
233275 jas_cmpxform_destroy(revpxform);
276+ }
277+ if (prof) {
278+ jas_cmprof_destroy(prof);
279+ }
234280 return 0;
235281 }
236282
237283 jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof)
238284 {
285+ JAS_LOGDEBUGF(1, "jas_cmprof_createfromiccprof(%p)\n", iccprof);
286+
239287 jas_cmprof_t *prof;
240288 jas_icchdr_t icchdr;
241289 jas_cmpxformseq_t *fwdpxformseq;
@@ -244,26 +292,44 @@ jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof) · 2 unmodified lines
244292 fwdpxformseq = 0;
245293 revpxformseq = 0;
246294
247− if (!(prof = jas_cmprof_create()))
295+ if (!(prof = jas_cmprof_create())) {
296+ jas_logerrorf("error: cannot create CM profile\n");
248297 goto error;
298+ }
249299 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");
251302 goto error;
252− prof->clrspc = icctoclrspc(icchdr.colorspc, 0);
253− prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1);
303+ }
304+ if (icctoclrspc(icchdr.colorspc, &prof->clrspc, 0)) {
305+ jas_logerrorf("error: unknown color profile\n");
306+ goto error;
307+ }
308+ if (icctoclrspc(icchdr.refcolorspc, &prof->refclrspc, 1)) {
309+ jas_logerrorf("error: unknown reference color profile\n");
310+ goto error;
311+ }
254312 prof->numchans = jas_clrspc_numchans(prof->clrspc);
255313 prof->numrefchans = jas_clrspc_numchans(prof->refclrspc);
256314
257315 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");
259318 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");
261322 goto error;
323+ }
262324 } 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");
264327 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");
266331 goto error;
332+ }
267333 }
268334 prof->pxformseqs[SEQFWD(0)] = fwdpxformseq;
269335 prof->pxformseqs[SEQREV(0)] = revpxformseq;
@@ -304,12 +370,14 @@ error: · 34 unmodified lines
304370 static jas_cmprof_t *jas_cmprof_create()
305371 {
306372 jas_cmprof_t *prof;
307− if (!(prof = jas_malloc(sizeof(jas_cmprof_t))))
373+ if (!(prof = jas_malloc(sizeof(jas_cmprof_t)))) {
308374 return 0;
375+ }
309376 memset(prof, 0, sizeof(jas_cmprof_t));
310377 prof->iccprof = 0;
311− for (unsigned i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i)
378+ for (unsigned i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) {
312379 prof->pxformseqs[i] = 0;
380+ }
313381 return prof;
314382 }
315383
@@ -321,8 +389,9 @@ void jas_cmprof_destroy(jas_cmprof_t *prof) · 5 unmodified lines
321389 prof->pxformseqs[i] = 0;
322390 }
323391 }
324− if (prof->iccprof)
392+ if (prof->iccprof) {
325393 jas_iccprof_destroy(prof->iccprof);
394+ }
326395 jas_free(prof);
327396 }
328397
@@ -330,8 +399,9 @@ jas_cmprof_t *jas_cmprof_copy(const jas_cmprof_t *prof) · 1 unmodified line
330399 {
331400 jas_cmprof_t *newprof;
332401
333− if (!(newprof = jas_cmprof_create()))
402+ if (!(newprof = jas_cmprof_create())) {
334403 goto error;
404+ }
335405 newprof->clrspc = prof->clrspc;
336406 newprof->numchans = prof->numchans;
337407 newprof->refclrspc = prof->refclrspc;
@@ -345,8 +415,9 @@ jas_cmprof_t *jas_cmprof_copy(const jas_cmprof_t *prof) · 7 unmodified lines
345415 }
346416 return newprof;
347417 error:
348− if (newprof)
418+ if (newprof) {
349419 jas_cmprof_destroy(newprof);
420+ }
350421 return 0;
351422 }
352423
@@ -363,40 +434,45 @@ jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof, const jas_cmprof_t · 10 unmodified lines
363434 jas_cmpxformseq_t *altoutpxformseq;
364435 jas_cmpxformseq_t *prfpxformseq;
365436
366− /* Avoid compiler warnings about unused parameters. */
367− (void)optimize;
437+ JAS_UNUSED(optimize);
368438
369439 const jas_cmxform_intent_t prfintent = intent;
370440
371− if (!(xform = jas_malloc(sizeof(jas_cmxform_t))))
441+ if (!(xform = jas_malloc(sizeof(jas_cmxform_t)))) {
372442 goto error;
373− if (!(xform->pxformseq = jas_cmpxformseq_create()))
443+ }
444+ if (!(xform->pxformseq = jas_cmpxformseq_create())) {
374445 goto error;
446+ }
375447
376448 switch (op) {
377449 case JAS_CMXFORM_OP_FWD:
378450 inpxformseq = fwdpxformseq(inprof, intent);
379451 outpxformseq = revpxformseq(outprof, intent);
380− if (!inpxformseq || !outpxformseq)
452+ if (!inpxformseq || !outpxformseq) {
381453 goto error;
454+ }
382455 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
383456 jas_cmpxformseq_appendcnvt(xform->pxformseq,
384457 inprof->refclrspc, outprof->refclrspc) ||
385− jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
458+ jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) {
386459 goto error;
460+ }
387461 xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
388462 xform->numoutchans = jas_clrspc_numchans(outprof->clrspc);
389463 break;
390464 case JAS_CMXFORM_OP_REV:
391465 outpxformseq = fwdpxformseq(outprof, intent);
392466 inpxformseq = revpxformseq(inprof, intent);
393− if (!outpxformseq || !inpxformseq)
467+ if (!outpxformseq || !inpxformseq) {
394468 goto error;
469+ }
395470 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
396471 jas_cmpxformseq_appendcnvt(xform->pxformseq,
397472 outprof->refclrspc, inprof->refclrspc) ||
398− jas_cmpxformseq_append(xform->pxformseq, inpxformseq))
473+ jas_cmpxformseq_append(xform->pxformseq, inpxformseq)) {
399474 goto error;
475+ }
400476 xform->numinchans = jas_clrspc_numchans(outprof->clrspc);
401477 xform->numoutchans = jas_clrspc_numchans(inprof->clrspc);
402478 break;
@@ -404,53 +480,62 @@ jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof, const jas_cmprof_t · 1 unmodified line
404480 assert(prfprof);
405481 inpxformseq = fwdpxformseq(inprof, intent);
406482 prfpxformseq = fwdpxformseq(prfprof, prfintent);
407− if (!inpxformseq || !prfpxformseq)
483+ if (!inpxformseq || !prfpxformseq) {
408484 goto error;
485+ }
409486 outpxformseq = simpxformseq(outprof, intent);
410487 altoutpxformseq = 0;
411488 if (!outpxformseq) {
412489 outpxformseq = revpxformseq(outprof, intent);
413490 altoutpxformseq = fwdpxformseq(outprof, intent);
414− if (!outpxformseq || !altoutpxformseq)
491+ if (!outpxformseq || !altoutpxformseq) {
415492 goto error;
493+ }
416494 }
417495 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
418496 jas_cmpxformseq_appendcnvt(xform->pxformseq,
419− inprof->refclrspc, outprof->refclrspc))
497+ inprof->refclrspc, outprof->refclrspc)) {
420498 goto error;
499+ }
421500 if (altoutpxformseq) {
422501 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
423− jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq))
502+ jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq)) {
424503 goto error;
504+ }
425505 } else {
426− if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
506+ if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) {
427507 goto error;
508+ }
428509 }
429510 if (jas_cmpxformseq_appendcnvt(xform->pxformseq,
430511 outprof->refclrspc, inprof->refclrspc) ||
431− jas_cmpxformseq_append(xform->pxformseq, prfpxformseq))
512+ jas_cmpxformseq_append(xform->pxformseq, prfpxformseq)) {
432513 goto error;
514+ }
433515 xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
434516 xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc);
435517 break;
436518 case JAS_CMXFORM_OP_GAMUT:
437519 inpxformseq = fwdpxformseq(inprof, intent);
438520 outpxformseq = gampxformseq(outprof);
439− if (!inpxformseq || !outpxformseq)
521+ if (!inpxformseq || !outpxformseq) {
440522 goto error;
523+ }
441524 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
442525 jas_cmpxformseq_appendcnvt(xform->pxformseq,
443526 inprof->refclrspc, outprof->refclrspc) ||
444− jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
527+ jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) {
445528 goto error;
529+ }
446530 xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
447531 xform->numoutchans = 1;
448532 break;
449533 }
450534 return xform;
451535 error:
452− if (xform)
536+ if (xform) {
453537 jas_cmxform_destroy(xform);
538+ }
454539 return 0;
455540 }
456541
@@ -463,8 +548,10 @@ int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, jas_ · 6 unmodified lines
463548 jas_cmreal_t scale;
464549 long v;
465550
466− if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts)
551+ if (xform->numinchans > in->numcmpts ||
552+ xform->numoutchans > out->numcmpts) {
467553 goto error;
554+ }
468555
469556 const jas_cmcmptfmt_t *fmt = &in->cmptfmts[0];
470557 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
494581 }
495582 }
496583
497− if (maxchans == 0)
584+ if (maxchans == 0) {
498585 /* avoid division by zero */
499586 goto error;
587+ }
500588
501589 const unsigned bufmax = APPLYBUFSIZ / maxchans;
502590 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
515603 const long *dataptr = &fmt->buf[n];
516604 jas_cmreal_t *bufptr = &inbuf[i];
517605 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)) {
519607 goto error;
608+ }
520609 *bufptr = (jas_cmreal_t)(v - bias) / scale;
521610 bufptr += xform->numinchans;
522611 }
@@ -531,8 +620,9 @@ int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, jas_ · 8 unmodified lines
531620 } else {
532621 outbuf = inbuf;
533622 }
534− if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m))
623+ if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m)) {
535624 goto error;
625+ }
536626 inbuf = outbuf;
537627 }
538628
@@ -545,8 +635,9 @@ int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in, jas_ · 6 unmodified lines
545635 for (unsigned j = 0; j < m; ++j) {
546636 v = (long)((*bufptr) * scale + bias);
547637 bufptr += xform->numoutchans;
548− if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v))
638+ if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v)) {
549639 goto error;
640+ }
550641 }
551642 }
552643
@@ -560,8 +651,9 @@ error: · 7 unmodified lines
560651
561652 void jas_cmxform_destroy(jas_cmxform_t *xform)
562653 {
563− if (xform->pxformseq)
654+ if (xform->pxformseq) {
564655 jas_cmpxformseq_destroy(xform->pxformseq);
656+ }
565657 jas_free(xform);
566658 }
567659
@@ -572,17 +664,20 @@ void jas_cmxform_destroy(jas_cmxform_t *xform) · 4 unmodified lines
572664 static jas_cmpxformseq_t *jas_cmpxformseq_create()
573665 {
574666 jas_cmpxformseq_t *pxformseq;
575− if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t))))
667+ if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t)))) {
576668 goto error;
669+ }
577670 pxformseq->pxforms = 0;
578671 pxformseq->numpxforms = 0;
579672 pxformseq->maxpxforms = 0;
580− if (jas_cmpxformseq_resize(pxformseq, 16))
673+ if (jas_cmpxformseq_resize(pxformseq, 16)) {
581674 goto error;
675+ }
582676 return pxformseq;
583677 error:
584− if (pxformseq)
678+ if (pxformseq) {
585679 jas_cmpxformseq_destroy(pxformseq);
680+ }
586681 return 0;
587682 }
588683
@@ -590,23 +685,28 @@ static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq) · 1 unmodified line
590685 {
591686 jas_cmpxformseq_t *newpxformseq;
592687
593− if (!(newpxformseq = jas_cmpxformseq_create()))
688+ if (!(newpxformseq = jas_cmpxformseq_create())) {
594689 goto error;
595− if (jas_cmpxformseq_append(newpxformseq, pxformseq))
690+ }
691+ if (jas_cmpxformseq_append(newpxformseq, pxformseq)) {
596692 goto error;
693+ }
597694 return newpxformseq;
598695 error:
599− if (newpxformseq)
696+ if (newpxformseq) {
600697 jas_cmpxformseq_destroy(newpxformseq);
698+ }
601699 return 0;
602700 }
603701
604702 static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq)
605703 {
606− while (pxformseq->numpxforms > 0)
704+ while (pxformseq->numpxforms > 0) {
607705 jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1);
608− if (pxformseq->pxforms)
706+ }
707+ if (pxformseq->pxforms) {
609708 jas_free(pxformseq->pxforms);
709+ }
610710 jas_free(pxformseq);
611711 }
612712
@@ -623,11 +723,16 @@ static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, unsigned i) · 10 unmodified lines
623723 static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq,
624724 unsigned dstclrspc, unsigned srcclrspc)
625725 {
626− if (dstclrspc == srcclrspc)
726+ JAS_UNUSED(pxformseq);
727+ if (dstclrspc == srcclrspc) {
627728 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+ */
628735 abort();
629− /* Avoid compiler warnings about unused parameters. */
630− USED(pxformseq);
631736 return -1;
632737 }
633738
@@ -638,13 +743,14 @@ static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, · 4 unmodified lines
638743 const unsigned i = _i >= 0 ? (unsigned)_i : pxformseq->numpxforms;
639744 assert(i <= pxformseq->numpxforms);
640745 if (pxformseq->numpxforms >= pxformseq->maxpxforms) {
641− if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms +
642− 16))
746+ if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms + 16)) {
643747 goto error;
748+ }
644749 }
645750 assert(pxformseq->numpxforms < pxformseq->maxpxforms);
646− if (!(tmppxform = jas_cmpxform_copy(pxform)))
751+ if (!(tmppxform = jas_cmpxform_copy(pxform))) {
647752 goto error;
753+ }
648754 const unsigned n = pxformseq->numpxforms - i;
649755 if (n > 0) {
650756 memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i],
@@ -664,13 +770,15 @@ static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq, · 13 unmodified lines
664770 jas_cmpxform_t *othpxform;
665771 const unsigned n = pxformseq->numpxforms + othpxformseq->numpxforms;
666772 if (n > pxformseq->maxpxforms) {
667− if (jas_cmpxformseq_resize(pxformseq, n))
773+ if (jas_cmpxformseq_resize(pxformseq, n)) {
668774 goto error;
775+ }
669776 }
670777 for (unsigned i = 0; i < othpxformseq->numpxforms; ++i) {
671778 othpxform = othpxformseq->pxforms[i];
672− if (!(pxform = jas_cmpxform_copy(othpxform)))
779+ if (!(pxform = jas_cmpxform_copy(othpxform))) {
673780 goto error;
781+ }
674782 pxformseq->pxforms[pxformseq->numpxforms] = pxform;
675783 ++pxformseq->numpxforms;
676784 }
@@ -700,8 +808,9 @@ static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, unsigned n) · 23 unmodified lines
700808 static jas_cmpxform_t *jas_cmpxform_create0()
701809 {
702810 jas_cmpxform_t *pxform;
703− if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t))))
811+ if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t)))) {
704812 return 0;
813+ }
705814 memset(pxform, 0, sizeof(jas_cmpxform_t));
706815 pxform->refcnt = 0;
707816 pxform->ops = 0;
@@ -730,19 +839,22 @@ static jas_cmpxform_t *jas_cmpxform_createshapmat() · 22 unmodified lines
730839 {
731840 jas_cmpxform_t *pxform;
732841 jas_cmshapmat_t *shapmat;
733− if (!(pxform = jas_cmpxform_create0()))
842+ if (!(pxform = jas_cmpxform_create0())) {
734843 return 0;
844+ }
735845 pxform->ops = &shapmat_ops;
736846 shapmat = &pxform->data.shapmat;
737847 shapmat->mono = 0;
738848 shapmat->order = 0;
739849 shapmat->useluts = 0;
740850 shapmat->usemat = 0;
741− for (unsigned i = 0; i < 3; ++i)
851+ for (unsigned i = 0; i < 3; ++i) {
742852 jas_cmshapmatlut_init(&shapmat->luts[i]);
853+ }
743854 for (unsigned i = 0; i < 3; ++i) {
744− for (unsigned j = 0; j < 4; ++j)
855+ for (unsigned j = 0; j < 4; ++j) {
745856 shapmat->mat[i][j] = 0.0;
857+ }
746858 }
747859 ++pxform->refcnt;
748860 return pxform;
@@ -751,8 +863,9 @@ static jas_cmpxform_t *jas_cmpxform_createshapmat() · 2 unmodified lines
751863 static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform)
752864 {
753865 jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
754− for (unsigned i = 0; i < 3; ++i)
866+ for (unsigned i = 0; i < 3; ++i) {
755867 jas_cmshapmatlut_cleanup(&shapmat->luts[i]);
868+ }
756869 }
757870
758871 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
808921 if (!shapmat->order) {
809922 while (cnt-- > 0) {
810923 a0 = *src++;
811− if (shapmat->useluts)
924+ if (shapmat->useluts) {
812925 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
926+ }
813927 a2 = a0 * shapmat->mat[2][0];
814928 a1 = a0 * shapmat->mat[1][0];
815929 a0 = a0 * shapmat->mat[0][0];
@@ -824,8 +938,9 @@ assert(0); · 8 unmodified lines
824938 src++;
825939 src++;
826940 a0 = a0 * shapmat->mat[0][0];
827− if (shapmat->useluts)
941+ if (shapmat->useluts) {
828942 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
943+ }
829944 *dst++ = a0;
830945 }
831946 }
@@ -851,8 +966,9 @@ static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut) · 19 unmodified lines
851966
852967 static double gammafn(double x, double gamma)
853968 {
854− if (x == 0.0)
969+ if (x == 0.0) {
855970 return 0.0;
971+ }
856972 return pow(x, gamma);
857973 }
858974
@@ -862,28 +978,32 @@ static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, const jas_icccurv_t *cu · 3 unmodified lines
862978 jas_cmshapmatlut_cleanup(lut);
863979 if (curv->numents == 0) {
864980 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)))) {
866982 goto error;
983+ }
867984 lut->data[0] = 0.0;
868985 lut->data[1] = 1.0;
869986 } else if (curv->numents == 1) {
870987 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)))) {
872989 goto error;
990+ }
873991 gamma = (jas_cmreal_t)curv->ents[0] / 256.0;
874992 for (unsigned i = 0; i < lut->size; ++i) {
875993 lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma);
876994 }
877995 } else {
878996 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)))) {
880998 goto error;
999+ }
8811000 for (unsigned i = 0; i < lut->size; ++i) {
8821001 lut->data[i] = (jas_cmreal_t)curv->ents[i] / 65535.0;
8831002 }
8841003 }
8851004 return 0;
8861005 error:
1006+ jas_cmshapmatlut_cleanup(lut);
8871007 return -1;
8881008 }
8891009
@@ -892,11 +1012,13 @@ static jas_cmreal_t jas_cmshapmatlut_lookup(const jas_cmshapmatlut_t *lut, jas_c · 2 unmodified lines
8921012 jas_cmreal_t t;
8931013 t = x * (lut->size - 1);
8941014 const int lo = (int)floor(t);
895− if (lo < 0)
1015+ if (lo < 0) {
8961016 return lut->data[0];
1017+ }
8971018 const unsigned hi = (unsigned)ceil(t);
898− if (hi >= lut->size)
1019+ if (hi >= lut->size) {
8991020 return lut->data[lut->size - 1];
1021+ }
9001022 return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]);
9011023 }
9021024
@@ -921,8 +1043,9 @@ static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut, · 18 unmodified lines
9211043 return -1;
9221044 }
9231045 }
924− if (!(invlut->data = jas_alloc2(n, sizeof(jas_cmreal_t))))
1046+ if (!(invlut->data = jas_alloc2(n, sizeof(jas_cmreal_t)))) {
9251047 return -1;
1048+ }
9261049 invlut->size = n;
9271050 for (unsigned i = 0; i < invlut->size; ++i) {
9281051 sy = ((double) i) / (invlut->size - 1);
@@ -933,11 +1056,9 @@ static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut, · 4 unmodified lines
9331056 unsigned k;
9341057 for (k = j + 1; k < lut->size; ++k) {
9351058 by = lut->data[k];
936− if (by != sy)
1059+ if (by != sy) {
9371060 break;
938−#if 0
939−assert(0);
940−#endif
1061+ }
9411062 }
9421063 if (k < lut->size) {
9431064 --k;
@@ -961,10 +1082,12 @@ assert(0); · 17 unmodified lines
9611082 invlut->data[i] = sx;
9621083 }
9631084 #if 0
964−for (i=0;i<lut->size;++i)
965− jas_eprintf("lut[%d]=%f ", i, lut->data[i]);
966−for (i=0;i<invlut->size;++i)
967− jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]);
1085+ for (i=0;i<lut->size;++i) {
1086+ jas_eprintf("lut[%d]=%f ", i, lut->data[i]);
1087+ }
1088+ for (i=0;i<invlut->size;++i) {
1089+ jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]);
1090+ }
9681091 #endif
9691092 return 0;
9701093 }
@@ -975,11 +1098,11 @@ static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]) · 4 unmodified lines
9751098 d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1])
9761099 - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0])
9771100 + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]);
978−#if 0
979−jas_eprintf("delta=%f\n", d);
980−#endif
981− if (JAS_ABS(d) < 1e-6)
1101+ if (JAS_ABS(d) < 1e-6) {
1102+ jas_logerrorf("jas_cmshapmat_invmat: matrix is not invertible "
1103+ "(determinant %a)\n", d);
9821104 return -1;
1105+ }
9831106 out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d;
9841107 out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d;
9851108 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
9931116 out[1][3] = -in[1][3];
9941117 out[2][3] = -in[2][3];
9951118 #if 0
996−jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
997−in[0][0], in[0][1], in[0][2], in[0][3],
998−in[1][0], in[1][1], in[1][2], in[1][3],
999−in[2][0], in[2][1], in[2][2], in[2][3]);
1000−jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
1001−out[0][0], out[0][1], out[0][2], out[0][3],
1002−out[1][0], out[1][1], out[1][2], out[1][3],
1003−out[2][0], out[2][1], out[2][2], out[2][3]);
1119+ jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
1120+ in[0][0], in[0][1], in[0][2], in[0][3],
1121+ in[1][0], in[1][1], in[1][2], in[1][3],
1122+ in[2][0], in[2][1], in[2][2], in[2][3]);
1123+ jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
1124+ out[0][0], out[0][1], out[0][2], out[0][3],
1125+ out[1][0], out[1][1], out[1][2], out[1][3],
1126+ out[2][0], out[2][1], out[2][2], out[2][3]);
10041127 #endif
10051128 return 0;
10061129 }
@@ -1009,30 +1132,34 @@ out[2][0], out[2][1], out[2][2], out[2][3]); · 2 unmodified lines
10091132 *
10101133 \******************************************************************************/
10111134
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)
10131136 {
10141137 if (refflag) {
10151138 switch (iccclrspc) {
10161139 case JAS_ICC_COLORSPC_XYZ:
1017− return JAS_CLRSPC_CIEXYZ;
1140+ *clrspc = JAS_CLRSPC_CIEXYZ;
1141+ return 0;
10181142 case JAS_ICC_COLORSPC_LAB:
1019− return JAS_CLRSPC_CIELAB;
1143+ *clrspc = JAS_CLRSPC_CIELAB;
1144+ return 0;
10201145 default:
1021− abort();
1146+ return -1;
10221147 }
10231148 } else {
10241149 switch (iccclrspc) {
10251150 case JAS_ICC_COLORSPC_YCBCR:
1026− return JAS_CLRSPC_GENYCBCR;
1151+ *clrspc = JAS_CLRSPC_GENYCBCR;
1152+ return 0;
10271153 case JAS_ICC_COLORSPC_RGB:
1028− return JAS_CLRSPC_GENRGB;
1154+ *clrspc = JAS_CLRSPC_GENRGB;
1155+ return 0;
10291156 case JAS_ICC_COLORSPC_GRAY:
1030− return JAS_CLRSPC_GENGRAY;
1157+ *clrspc = JAS_CLRSPC_GENGRAY;
1158+ return 0;
10311159 default:
1032− abort();
1160+ return -1;
10331161 }
10341162 }
1035− return -1;
10361163 }
10371164
10381165 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
10451172
10461173 jas_cmshapmatlut_init(&lut);
10471174 if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) ||
1048− graytrc->type != JAS_ICC_TYPE_CURV)
1175+ graytrc->type != JAS_ICC_TYPE_CURV) {
10491176 goto error;
1050− if (!(pxform = jas_cmpxform_createshapmat()))
1177+ }
1178+ if (!(pxform = jas_cmpxform_createshapmat())) {
10511179 goto error;
1180+ }
10521181 shapmat = &pxform->data.shapmat;
1053− if (!(pxformseq = jas_cmpxformseq_create()))
1182+ if (!(pxformseq = jas_cmpxformseq_create())) {
10541183 goto error;
1055− if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
1184+ }
1185+ if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) {
10561186 goto error;
1187+ }
10571188
10581189 pxform->numinchans = 1;
10591190 pxform->numoutchans = 3;
@@ -1066,18 +1197,21 @@ static int mono(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxf · 6 unmodified lines
10661197 shapmat->mat[0][0] = 0.9642;
10671198 shapmat->mat[1][0] = 1.0;
10681199 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)) {
10701201 goto error;
1202+ }
10711203 } else {
10721204 shapmat->order = 1;
10731205 shapmat->mat[0][0] = 1.0 / 0.9642;
10741206 shapmat->mat[1][0] = 1.0;
10751207 shapmat->mat[2][0] = 1.0 / 0.8249;
10761208 jas_cmshapmatlut_init(&lut);
1077− if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv))
1209+ if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv)) {
10781210 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)) {
10801213 goto error;
1214+ }
10811215 jas_cmshapmatlut_cleanup(&lut);
10821216 }
10831217 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
10851219 *retpxformseq = pxformseq;
10861220 return 0;
10871221 error:
1088− if (graytrc)
1222+ jas_cmshapmatlut_cleanup(&lut);
1223+ if (graytrc) {
10891224 jas_iccattrval_destroy(graytrc);
1090− if (pxform)
1225+ }
1226+ if (pxform) {
10911227 jas_cmpxform_destroy(pxform);
1092− if (pxformseq)
1228+ }
1229+ if (pxformseq) {
10931230 jas_cmpxformseq_destroy(pxformseq);
1231+ }
10941232 return -1;
10951233 }
10961234
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)
10981237 {
10991238 jas_iccattrval_t *trcs[3];
11001239 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
11031242 jas_cmpxformseq_t *pxformseq;
11041243 jas_cmreal_t mat[3][4];
11051244 jas_cmshapmatlut_t lut;
1245+ jas_cmshapmatlut_init(&lut);
11061246
11071247 pxform = 0;
11081248 pxformseq = 0;
@@ -1117,22 +1257,32 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 8 unmodified lines
11171257 !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) ||
11181258 !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) ||
11191259 !(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");
11211262 goto error;
1263+ }
11221264 for (unsigned i = 0; i < 3; ++i) {
11231265 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");
11251268 goto error;
1269+ }
11261270 }
1127− if (!(pxform = jas_cmpxform_createshapmat()))
1271+ if (!(pxform = jas_cmpxform_createshapmat())) {
1272+ jas_logerrorf("error: jas_cmpxform_createshapmat failed\n");
11281273 goto error;
1274+ }
11291275 pxform->numinchans = 3;
11301276 pxform->numoutchans = 3;
11311277 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");
11331280 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");
11351284 goto error;
1285+ }
11361286 shapmat->mono = 0;
11371287 shapmat->useluts = 1;
11381288 shapmat->usemat = 1;
@@ -1143,11 +1293,14 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 4 unmodified lines
11431293 shapmat->mat[1][i] = (jas_cmreal_t)cols[i]->data.xyz.y / 65536.0;
11441294 shapmat->mat[2][i] = (jas_cmreal_t)cols[i]->data.xyz.z / 65536.0;
11451295 }
1146− for (unsigned i = 0; i < 3; ++i)
1296+ for (unsigned i = 0; i < 3; ++i) {
11471297 shapmat->mat[i][3] = 0.0;
1298+ }
11481299 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");
11501302 goto error;
1303+ }
11511304 }
11521305 } else {
11531306 shapmat->order = 1;
@@ -1156,16 +1309,23 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 2 unmodified lines
11561309 mat[1][i] = (jas_cmreal_t)cols[i]->data.xyz.y / 65536.0;
11571310 mat[2][i] = (jas_cmreal_t)cols[i]->data.xyz.z / 65536.0;
11581311 }
1159− for (unsigned i = 0; i < 3; ++i)
1312+ for (unsigned i = 0; i < 3; ++i) {
11601313 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");
11621317 goto error;
1318+ }
11631319 for (unsigned i = 0; i < 3; ++i) {
11641320 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");
11661323 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");
11681327 goto error;
1328+ }
11691329 jas_cmshapmatlut_cleanup(&lut);
11701330 }
11711331 }
@@ -1179,6 +1339,7 @@ static int triclr(const jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retp · 7 unmodified lines
11791339
11801340 error:
11811341
1342+ jas_cmshapmatlut_cleanup(&lut);
11821343 for (unsigned i = 0; i < 3; ++i) {
11831344 if (trcs[i]) {
11841345 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
12041365 v = **bufptr;
12051366 if (sgnd) {
12061367 m = (1 << (prec - 1));
1207− if (v < -m || v >= m)
1368+ if (v < -m || v >= m) {
12081369 return -1;
1370+ }
12091371 } else {
1210− if (v < 0 || v >= (1 << prec))
1372+ if (v < 0 || v >= (1 << prec)) {
12111373 return -1;
1374+ }
12121375 }
12131376 ++(*bufptr);
12141377 *val = v;
@@ -1220,11 +1383,13 @@ static int jas_cmputint(long **bufptr, int sgnd, unsigned prec, long val) · 5 unmodified lines
12201383 int m;
12211384 if (sgnd) {
12221385 m = (1 << (prec - 1));
1223− if (val < -m || val >= m)
1386+ if (val < -m || val >= m) {
12241387 return -1;
1388+ }
12251389 } else {
1226− if (val < 0 || val >= (1 << prec))
1390+ if (val < 0 || val >= (1 << prec)) {
12271391 return -1;
1392+ }
12281393 }
12291394 **bufptr = val;
12301395 ++(*bufptr);
@@ -1243,8 +1408,8 @@ unsigned jas_clrspc_numchans(jas_clrspc_t clrspc) · 12 unmodified lines
12431408 return 1;
12441409 default:
12451410 abort();
1411+ return 0;
12461412 }
1247− return -1;
12481413 }
12491414
12501415 jas_iccprof_t *jas_iccprof_createfromcmprof(const jas_cmprof_t *prof)
jas_debug.c+183−22
@@ -63,53 +63,214 @@ · 62 unmodified lines
6363 * Includes.
6464 \******************************************************************************/
6565
66+#define JAS_FOR_INTERNAL_USE_ONLY
67+
68+#include "jasper/jas_init.h"
69+#include "jasper/jas_compiler.h"
6670 #include "jasper/jas_debug.h"
6771 #include "jasper/jas_types.h"
72+#include "jasper/jas_log.h"
6873
6974 /******************************************************************************\
70−* Local data.
75+* Code for getting/setting the debug level.
7176 \******************************************************************************/
7277
73−static int jas_dbglevel = 0;
74−/* The debug level. */
78+/* Set the library debug level. */
79+JAS_DEPRECATED
80+int jas_setdbglevel(int level)
81+{
82+ jas_deprecated("jas_setdbglevel is deprecated\n");
83+ int old_level = jas_get_debug_level();
84+ jas_set_debug_level(level);
85+ return old_level;
86+}
7587
7688 /******************************************************************************\
77−* Code for getting/setting the debug level.
89+* Code.
7890 \******************************************************************************/
7991
80−/* Set the library debug level. */
81−int jas_setdbglevel(int dbglevel)
92+/* Perform formatted output to standard error. */
93+int jas_eprintf(const char *fmt, ...)
8294 {
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+}
84102
85− /* Save the old debug level. */
86− olddbglevel = jas_dbglevel;
103+/* Generate formatted error log message. */
104+int jas_logprintf(const char *fmt, ...)
105+{
106+ int ret;
107+ va_list ap;
108+ va_start(ap, fmt);
109+ ret = jas_vlogmsgf(jas_logtype_init(JAS_LOGTYPE_CLASS_NULL, 0), fmt,
110+ ap);
111+ va_end(ap);
112+ return ret;
113+}
87114
88− /* Change the debug level. */
89− jas_dbglevel = dbglevel;
115+/* Generate formatted error log message. */
116+int jas_logerrorf(const char *fmt, ...)
117+{
118+ int ret;
119+ va_list ap;
120+ va_start(ap, fmt);
121+ ret = jas_vlogmsgf(jas_logtype_init(JAS_LOGTYPE_CLASS_ERROR, 0), fmt,
122+ ap);
123+ va_end(ap);
124+ return ret;
125+}
90126
91− /* Return the old debug level. */
92− return olddbglevel;
127+/* Generate formatted warning log message. */
128+int jas_logwarnf(const char *fmt, ...)
129+{
130+ int ret;
131+ va_list ap;
132+ va_start(ap, fmt);
133+ ret = jas_vlogmsgf(jas_logtype_init(JAS_LOGTYPE_CLASS_WARN, 0), fmt,
134+ ap);
135+ va_end(ap);
136+ return ret;
93137 }
94138
95−/* Get the library debug level. */
96−int jas_getdbglevel()
139+/* Generate formatted informational log message. */
140+int jas_loginfof(const char *fmt, ...)
97141 {
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;
99257 }
100258
101259 /******************************************************************************\
102260 * Code.
103261 \******************************************************************************/
104262
105−/* Perform formatted output to standard error. */
106−int jas_eprintf(const char *fmt, ...)
263+void jas_deprecated(const char *fmt, ...)
107264 {
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: ");
109272 va_list ap;
110−
111273 va_start(ap, fmt);
112− ret = vfprint(2, fmt, ap);
274+ vfprintf(stderr, fmt, ap);
113275 va_end(ap);
114− return ret;
115276 }
jas_icc.c+435−239
@@ -59,12 +59,23 @@ · 58 unmodified lines
5959 * __END_OF_JASPER_LICENSE__
6060 */
6161
62+/******************************************************************************\
63+* Includes.
64+\******************************************************************************/
65+
66+#define JAS_FOR_INTERNAL_USE_ONLY
67+
6268 #include "jasper/jas_icc.h"
6369 #include "jasper/jas_types.h"
6470 #include "jasper/jas_malloc.h"
6571 #include "jasper/jas_debug.h"
6672 #include "jasper/jas_cm.h"
6773 #include "jasper/jas_stream.h"
74+#include "jasper/jas_string.h"
75+
76+/******************************************************************************\
77+*
78+\******************************************************************************/
6879
6980 #define jas_iccputuint8(out, val) jas_iccputuint(out, 1, val)
7081 #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
8091 static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val);
8192 static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val);
8293 static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val);
83−//#ifdef JAS_ENABLE_ENCODER
8494 static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val);
8595 static int jas_iccputsint(jas_stream_t *out, unsigned n, jas_longlong val);
86−//#endif /* JAS_ENABLE_ENCODER */
8796 static jas_iccprof_t *jas_iccprof_create(void);
8897 static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr);
89−//#ifdef JAS_ENABLE_ENCODER
9098 static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr);
91−//#endif
9299 static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab);
93100 static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab);
94101 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
104111 static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in,
105112 unsigned cnt);
106113 static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval);
107−//#ifdef JAS_ENABLE_ENCODER
108114 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);
110116
111117 static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval);
112118 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
114120 static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in,
115121 unsigned cnt);
116122 static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval);
117−//#ifdef JAS_ENABLE_ENCODER
118123 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);
120125
121126 static void jas_icctxt_destroy(jas_iccattrval_t *attrval);
122127 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
124129 static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in,
125130 unsigned cnt);
126131 static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval);
127−//#ifdef JAS_ENABLE_ENCODER
128132 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);
130134
131135 static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in,
132136 unsigned cnt);
133137 static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval);
134−//#ifdef JAS_ENABLE_ENCODER
135138 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);
137140
138141 static jas_iccattrtab_t *jas_iccattrtab_create(void);
139142 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
143146 static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, unsigned i,
144147 jas_iccuint32_t name, jas_iccattrval_t *val);
145148 static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, unsigned i);
146−//#ifdef JAS_ENABLE_ENCODER
147149 static unsigned jas_iccpadtomult(unsigned x, unsigned y);
148150 static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i,
149151 jas_iccattrname_t *name, jas_iccattrval_t **val);
150152 static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab);
151−//#endif /* JAS_ENABLE_ENCODER */
152153
153154 static void jas_icclut16_destroy(jas_iccattrval_t *attrval);
154155 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
156157 static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in,
157158 unsigned cnt);
158159 static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval);
159−//#ifdef JAS_ENABLE_ENCODER
160160 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);
162162
163163 static void jas_icclut8_destroy(jas_iccattrval_t *attrval);
164164 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
166166 static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in,
167167 unsigned cnt);
168168 static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval);
169−//#ifdef JAS_ENABLE_ENCODER
170169 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);
172171
173−//#ifdef JAS_ENABLE_ENCODER
174172 static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *ctime);
175173 static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz);
176−//#endif /* JAS_ENABLE_ENCODER */
177174
178175 static unsigned jas_iccpowi(unsigned x, unsigned n);
179176
180177 static char *jas_iccsigtostr(unsigned sig, char *buf);
181178
179+/******************************************************************************\
180+* Data.
181+\******************************************************************************/
182182
183183 static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = {
184184 {
@@ -186,10 +186,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 1 unmodified line
186186 jas_icccurv_destroy,
187187 jas_icccurv_copy,
188188 jas_icccurv_input,
189−//#ifdef JAS_ENABLE_ENCODER
190189 jas_icccurv_output,
191−//#endif
192190 jas_icccurv_getsize,
191+ jas_icccurv_dump,
193192 },
194193 },
195194 {
@@ -198,10 +197,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines
198197 0,
199198 0,
200199 jas_iccxyz_input,
201−//#ifdef JAS_ENABLE_ENCODER
202200 jas_iccxyz_output,
203−//#endif
204201 jas_iccxyz_getsize,
202+ jas_iccxyz_dump,
205203 },
206204 },
207205 {
@@ -210,10 +208,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines
210208 jas_icctxtdesc_destroy,
211209 jas_icctxtdesc_copy,
212210 jas_icctxtdesc_input,
213−//#ifdef JAS_ENABLE_ENCODER
214211 jas_icctxtdesc_output,
215−//#endif
216212 jas_icctxtdesc_getsize,
213+ jas_icctxtdesc_dump,
217214 },
218215 },
219216 {
@@ -222,10 +219,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines
222219 jas_icctxt_destroy,
223220 jas_icctxt_copy,
224221 jas_icctxt_input,
225−//#ifdef JAS_ENABLE_ENCODER
226222 jas_icctxt_output,
227−//#endif
228223 jas_icctxt_getsize,
224+ jas_icctxt_dump,
229225 },
230226 },
231227 {
@@ -234,10 +230,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines
234230 jas_icclut8_destroy,
235231 jas_icclut8_copy,
236232 jas_icclut8_input,
237−//#ifdef JAS_ENABLE_ENCODER
238233 jas_icclut8_output,
239−//#endif
240234 jas_icclut8_getsize,
235+ jas_icclut8_dump,
241236 },
242237 },
243238 {
@@ -245,10 +240,9 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 1 unmodified line
245240 jas_icclut16_destroy,
246241 jas_icclut16_copy,
247242 jas_icclut16_input,
248−//#ifdef JAS_ENABLE_ENCODER
249243 jas_icclut16_output,
250−//#endif
251244 jas_icclut16_getsize,
245+ jas_icclut16_dump,
252246 },
253247 },
254248 {
@@ -257,9 +251,8 @@ static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { · 2 unmodified lines
257251 0,
258252 0,
259253 0,
260−//#ifdef JAS_ENABLE_ENCODER
261254 0,
262−//#endif
255+ 0,
263256 0,
264257 },
265258 }
@@ -275,46 +268,58 @@ static jas_iccprof_t *jas_iccprof_create() · 9 unmodified lines
275268 if (!(prof = jas_malloc(sizeof(jas_iccprof_t)))) {
276269 goto error;
277270 }
278− if (!(prof->attrtab = jas_iccattrtab_create()))
279− goto error;
280− memset(&prof->hdr, 0, sizeof(jas_icchdr_t));
281271 prof->tagtab.numents = 0;
282272 prof->tagtab.ents = 0;
273+ if (!(prof->attrtab = jas_iccattrtab_create())) {
274+ goto error;
275+ }
276+ memset(&prof->hdr, 0, sizeof(jas_icchdr_t));
283277 return prof;
284278 error:
285− if (prof)
279+ if (prof) {
286280 jas_iccprof_destroy(prof);
281+ }
287282 return 0;
288283 }
289284
290285 jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof)
291286 {
292287 jas_iccprof_t *newprof;
293− if (!(newprof = jas_iccprof_create()))
288+ if (!(newprof = jas_iccprof_create())) {
294289 goto error;
290+ }
295291 newprof->hdr = prof->hdr;
296292 newprof->tagtab.numents = 0;
297293 newprof->tagtab.ents = 0;
298294 assert(newprof->attrtab);
299295 jas_iccattrtab_destroy(newprof->attrtab);
300− if (!(newprof->attrtab = jas_iccattrtab_copy(prof->attrtab)))
296+ if (!(newprof->attrtab = jas_iccattrtab_copy(prof->attrtab))) {
301297 goto error;
298+ }
302299 return newprof;
303300 error:
304− if (newprof)
301+ if (newprof) {
305302 jas_iccprof_destroy(newprof);
303+ }
306304 return 0;
307305 }
308306
309307 void jas_iccprof_destroy(jas_iccprof_t *prof)
310308 {
311− if (prof->attrtab)
309+ if (prof->attrtab) {
312310 jas_iccattrtab_destroy(prof->attrtab);
313− if (prof->tagtab.ents)
311+ }
312+ if (prof->tagtab.ents) {
314313 jas_free(prof->tagtab.ents);
314+ }
315315 jas_free(prof);
316316 }
317317
318+void jas_iccprof_dump(const jas_iccprof_t *prof, FILE *out)
319+{
320+ jas_iccattrtab_dump(prof->attrtab, out);
321+}
322+
318323 jas_iccprof_t *jas_iccprof_load(jas_stream_t *in)
319324 {
320325 jas_iccprof_t *prof;
@@ -332,11 +337,11 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 11 unmodified lines
332337 }
333338
334339 if (jas_iccprof_readhdr(in, &prof->hdr)) {
335− jas_eprintf("cannot get header\n");
340+ jas_logerrorf("cannot get header\n");
336341 goto error;
337342 }
338343 if (jas_iccprof_gettagtab(in, &prof->tagtab)) {
339− jas_eprintf("cannot get tab table\n");
344+ jas_logerrorf("cannot get tab table\n");
340345 goto error;
341346 }
342347 jas_iccprof_sorttagtab(&prof->tagtab);
@@ -349,23 +354,24 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 6 unmodified lines
349354 const jas_icctagtabent_t *tagtabent = &prof->tagtab.ents[i];
350355 if (tagtabent->off == JAS_CAST(jas_iccuint32_t, prevoff)) {
351356 if (prevattrval) {
352− if (!(attrval = jas_iccattrval_clone(prevattrval)))
357+ if (!(attrval = jas_iccattrval_clone(prevattrval))) {
353358 goto error;
354− if (jas_iccprof_setattr(prof, tagtabent->tag, attrval))
359+ }
360+ if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) {
355361 goto error;
362+ }
356363 jas_iccattrval_destroy(attrval);
357364 attrval = 0;
358365 } else {
359−#if 0
360− jas_eprintf("warning: skipping unknown tag type\n");
361−#endif
366+ jas_logwarnf("warning: skipping unknown tag type\n");
362367 }
363368 continue;
364369 }
365370 reloff = tagtabent->off - curoff;
366371 if (reloff > 0) {
367− if (jas_stream_gobble(in, reloff) != reloff)
372+ if (jas_stream_gobble(in, reloff) != reloff) {
368373 goto error;
374+ }
369375 curoff += reloff;
370376 } else if (reloff < 0) {
371377 goto error;
@@ -379,9 +385,7 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 7 unmodified lines
379385 }
380386 curoff += 8;
381387 if (!jas_iccattrvalinfo_lookup(type)) {
382−#if 0
383− jas_eprintf("warning: skipping unknown tag type\n");
384−#endif
388+ jas_logwarnf("warning: skipping unknown tag type\n");
385389 prevattrval = 0;
386390 continue;
387391 }
@@ -404,16 +408,17 @@ jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) · 16 unmodified lines
404408 return prof;
405409
406410 error:
407− if (prof)
411+ if (prof) {
408412 jas_iccprof_destroy(prof);
409− if (attrval)
413+ }
414+ if (attrval) {
410415 jas_iccattrval_destroy(attrval);
416+ }
411417 return 0;
412418 }
413419
414420 int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out)
415421 {
416−//#ifdef JAS_ENABLE_ENCODER
417422 long curoff;
418423 long reloff;
419424 long newoff;
@@ -426,14 +431,16 @@ int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out) · 6 unmodified lines
426431
427432 tagtab = &prof->tagtab;
428433 if (!(tagtab->ents = jas_alloc2(prof->attrtab->numattrs,
429− sizeof(jas_icctagtabent_t))))
434+ sizeof(jas_icctagtabent_t)))) {
430435 goto error;
436+ }
431437 tagtab->numents = prof->attrtab->numattrs;
432438 curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents;
433439 for (unsigned i = 0; i < tagtab->numents; ++i) {
434440 tagtabent = &tagtab->ents[i];
435− if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval))
441+ if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) {
436442 goto error;
443+ }
437444 assert(attrval->ops->output);
438445 tagtabent->tag = attrname;
439446 tagtabent->data = &attrval->data;
@@ -462,49 +469,49 @@ int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out) · 22 unmodified lines
462469 jas_iccattrval_destroy(attrval);
463470 }
464471 prof->hdr.size = curoff;
465− if (jas_iccprof_writehdr(out, &prof->hdr))
472+ if (jas_iccprof_writehdr(out, &prof->hdr)) {
466473 goto error;
467− if (jas_iccprof_puttagtab(out, &prof->tagtab))
474+ }
475+ if (jas_iccprof_puttagtab(out, &prof->tagtab)) {
468476 goto error;
477+ }
469478 curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents;
470479 for (unsigned i = 0; i < tagtab->numents;) {
471480 tagtabent = &tagtab->ents[i];
472481 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)) {
474483 goto error;
484+ }
475485 if (jas_iccputuint32(out, attrval->type) || jas_stream_pad(out,
476− 4, 0) != 4)
486+ 4, 0) != 4) {
477487 goto error;
478− if ((*attrval->ops->output)(attrval, out))
488+ }
489+ if ((*attrval->ops->output)(attrval, out)) {
479490 goto error;
491+ }
480492 jas_iccattrval_destroy(attrval);
481493 curoff += tagtabent->len;
482494 ++i;
483− while (i < tagtab->numents &&
484− tagtab->ents[i].first)
495+ while (i < tagtab->numents && tagtab->ents[i].first) {
485496 ++i;
497+ }
486498 newoff = (i < tagtab->numents) ?
487499 tagtab->ents[i].off : prof->hdr.size;
488500 reloff = newoff - curoff;
489501 assert(reloff >= 0);
490502 if (reloff > 0) {
491− if (jas_stream_pad(out, reloff, 0) != reloff)
503+ if (jas_stream_pad(out, reloff, 0) != reloff) {
492504 goto error;
505+ }
493506 curoff += reloff;
494507 }
495508 }
496509 return 0;
497510 error:
498511 /* XXX - need to free some resources here */
499−//#else
500−// (void)prof;
501−// (void)out;
502−//#endif /* JAS_ENABLE_ENCODER */
503512 return -1;
504513 }
505514
506−//#ifdef JAS_ENABLE_ENCODER
507−
508515 static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr)
509516 {
510517 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
523530 jas_iccputuint32(out, hdr->intent) ||
524531 jas_iccputxyz(out, &hdr->illum) ||
525532 jas_iccputuint32(out, hdr->creator) ||
526− jas_stream_pad(out, 44, 0) != 44)
533+ jas_stream_pad(out, 44, 0) != 44) {
527534 return -1;
535+ }
528536 return 0;
529537 }
530538
531539 static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab)
532540 {
533541 jas_icctagtabent_t *tagtabent;
534− if (jas_iccputuint32(out, tagtab->numents))
542+ if (jas_iccputuint32(out, tagtab->numents)) {
535543 goto error;
544+ }
536545 for (unsigned i = 0; i < tagtab->numents; ++i) {
537546 tagtabent = &tagtab->ents[i];
538547 if (jas_iccputuint32(out, tagtabent->tag) ||
539548 jas_iccputuint32(out, tagtabent->off) ||
540− jas_iccputuint32(out, tagtabent->len))
549+ jas_iccputuint32(out, tagtabent->len)) {
541550 goto error;
551+ }
542552 }
543553 return 0;
544554 error:
545555 return -1;
546556 }
547557
548−//#endif
549−
550558 static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr)
551559 {
552560 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
565573 jas_iccgetuint32(in, &hdr->intent) ||
566574 jas_iccgetxyz(in, &hdr->illum) ||
567575 jas_iccgetuint32(in, &hdr->creator) ||
568− jas_stream_gobble(in, 44) != 44)
576+ jas_stream_gobble(in, 44) != 44) {
569577 return -1;
578+ }
570579 return 0;
571580 }
572581
@@ -578,17 +587,20 @@ static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab) · 5 unmodified lines
578587 jas_free(tagtab->ents);
579588 tagtab->ents = 0;
580589 }
581− if (jas_iccgetuint32(in, &tagtab->numents))
590+ if (jas_iccgetuint32(in, &tagtab->numents)) {
582591 goto error;
592+ }
583593 if (!(tagtab->ents = jas_alloc2(tagtab->numents,
584− sizeof(jas_icctagtabent_t))))
594+ sizeof(jas_icctagtabent_t)))) {
585595 goto error;
596+ }
586597 tagtabent = tagtab->ents;
587598 for (unsigned i = 0; i < tagtab->numents; ++i) {
588599 if (jas_iccgetuint32(in, &tagtabent->tag) ||
589600 jas_iccgetuint32(in, &tagtabent->off) ||
590− jas_iccgetuint32(in, &tagtabent->len))
601+ jas_iccgetuint32(in, &tagtabent->len)) {
591602 goto error;
603+ }
592604 ++tagtabent;
593605 }
594606 return 0;
@@ -605,10 +617,12 @@ jas_iccattrval_t *jas_iccprof_getattr(const jas_iccprof_t *prof, · 10 unmodified lines
605617 {
606618 int i;
607619 jas_iccattrval_t *attrval;
608− if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) < 0)
620+ if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) < 0) {
609621 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))) {
611624 goto error;
625+ }
612626 return attrval;
613627 error:
614628 return 0;
@@ -620,15 +634,17 @@ int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name, · 5 unmodified lines
620634 int i;
621635 if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) >= 0) {
622636 if (val) {
623− if (jas_iccattrtab_replace(prof->attrtab, i, name, val))
637+ if (jas_iccattrtab_replace(prof->attrtab, i, name, val)) {
624638 goto error;
639+ }
625640 } else {
626641 jas_iccattrtab_delete(prof->attrtab, i);
627642 }
628643 } else {
629644 if (val) {
630− if (jas_iccattrtab_add(prof->attrtab, -1, name, val))
645+ if (jas_iccattrtab_add(prof->attrtab, -1, name, val)) {
631646 goto error;
647+ }
632648 } else {
633649 /* NOP */
634650 }
@@ -658,8 +674,10 @@ static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab) · 23 unmodified lines
658674
659675 static int jas_icctagtabent_cmp(const void *src, const void *dst)
660676 {
661− const jas_icctagtabent_t *srctagtabent = JAS_CAST(const jas_icctagtabent_t *, src);
662− const jas_icctagtabent_t *dsttagtabent = JAS_CAST(const jas_icctagtabent_t *, dst);
677+ const jas_icctagtabent_t *srctagtabent =
678+ JAS_CAST(const jas_icctagtabent_t *, src);
679+ const jas_icctagtabent_t *dsttagtabent =
680+ JAS_CAST(const jas_icctagtabent_t *, dst);
663681 if (srctagtabent->off > dsttagtabent->off) {
664682 return 1;
665683 } 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
702720 return 0;
703721 }
704722
705−//#ifdef JAS_ENABLE_ENCODER
706−
707723 static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *time)
708724 {
709− jas_iccputuint16(out, time->year);
710− jas_iccputuint16(out, time->month);
711− jas_iccputuint16(out, time->day);
712− jas_iccputuint16(out, time->hour);
713− jas_iccputuint16(out, time->min);
714− jas_iccputuint16(out, time->sec);
725+ if (jas_iccputuint16(out, time->year) ||
726+ jas_iccputuint16(out, time->month) ||
727+ jas_iccputuint16(out, time->day) ||
728+ jas_iccputuint16(out, time->hour) ||
729+ jas_iccputuint16(out, time->min) ||
730+ jas_iccputuint16(out, time->sec)) {
731+ return -1;
732+ }
715733 return 0;
716734 }
717735
718736 static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz)
719737 {
720− jas_iccputuint32(out, xyz->x);
721− jas_iccputuint32(out, xyz->y);
722− jas_iccputuint32(out, xyz->z);
738+ if (jas_iccputuint32(out, xyz->x) ||
739+ jas_iccputuint32(out, xyz->y) ||
740+ jas_iccputuint32(out, xyz->z)) {
741+ return -1;
742+ }
723743 return 0;
724744 }
725745
726−//#endif /* JAS_ENABLE_ENCODER */
727−
728746 /******************************************************************************\
729747 * attribute table class
730748 \******************************************************************************/
@@ -732,29 +750,34 @@ static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz) · 1 unmodified line
732750 static jas_iccattrtab_t *jas_iccattrtab_create()
733751 {
734752 jas_iccattrtab_t *tab;
735− if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t))))
753+ if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t)))) {
736754 goto error;
755+ }
737756 tab->maxattrs = 0;
738757 tab->numattrs = 0;
739758 tab->attrs = 0;
740− if (jas_iccattrtab_resize(tab, 32))
759+ if (jas_iccattrtab_resize(tab, 32)) {
741760 goto error;
761+ }
742762 return tab;
743763 error:
744− if (tab)
764+ if (tab) {
745765 jas_iccattrtab_destroy(tab);
766+ }
746767 return 0;
747768 }
748769
749770 static jas_iccattrtab_t *jas_iccattrtab_copy(const jas_iccattrtab_t *attrtab)
750771 {
751772 jas_iccattrtab_t *newattrtab;
752− if (!(newattrtab = jas_iccattrtab_create()))
773+ if (!(newattrtab = jas_iccattrtab_create())) {
753774 return NULL;
775+ }
754776 for (unsigned i = 0; i < attrtab->numattrs; ++i) {
755777 if (jas_iccattrtab_add(newattrtab, i, attrtab->attrs[i].name,
756− attrtab->attrs[i].val))
778+ attrtab->attrs[i].val)) {
757779 goto error;
780+ }
758781 }
759782 return newattrtab;
760783 error:
@@ -773,6 +796,29 @@ static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab) · 12 unmodified lines
773796 jas_free(tab);
774797 }
775798
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+
776822 static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, unsigned maxents)
777823 {
778824 jas_iccattr_t *newattrs;
@@ -801,12 +847,14 @@ static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i, · 22 unmodified lines
801847 return -1;
802848 }
803849 }
804− if (!(tmpattrval = jas_iccattrval_clone(val)))
850+ if (!(tmpattrval = jas_iccattrval_clone(val))) {
805851 return -1;
852+ }
806853 const unsigned n = attrtab->numattrs - i;
807− if (n > 0)
854+ if (n > 0) {
808855 memmove(&attrtab->attrs[i + 1], &attrtab->attrs[i],
809856 n * sizeof(jas_iccattr_t));
857+ }
810858 attr = &attrtab->attrs[i];
811859 attr->name = name;
812860 attr->val = tmpattrval;
@@ -819,8 +867,9 @@ static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, unsigned i, · 6 unmodified lines
819867 {
820868 jas_iccattrval_t *newval;
821869 jas_iccattr_t *attr;
822− if (!(newval = jas_iccattrval_clone(val)))
870+ if (!(newval = jas_iccattrval_clone(val))) {
823871 goto error;
872+ }
824873 attr = &attrtab->attrs[i];
825874 jas_iccattrval_destroy(attr->val);
826875 attr->name = name;
@@ -834,28 +883,29 @@ static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, unsigned i) · 7 unmodified lines
834883 {
835884 unsigned n;
836885 jas_iccattrval_destroy(attrtab->attrs[i].val);
837− if ((n = attrtab->numattrs - i - 1) > 0)
886+ if ((n = attrtab->numattrs - i - 1) > 0) {
838887 memmove(&attrtab->attrs[i], &attrtab->attrs[i + 1],
839888 n * sizeof(jas_iccattr_t));
889+ }
840890 --attrtab->numattrs;
841891 }
842892
843−//#ifdef JAS_ENABLE_ENCODER
844893 static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i,
845894 jas_iccattrname_t *name, jas_iccattrval_t **val)
846895 {
847896 jas_iccattr_t *attr;
848− if (i >= attrtab->numattrs)
897+ if (i >= attrtab->numattrs) {
849898 goto error;
899+ }
850900 attr = &attrtab->attrs[i];
851901 *name = attr->name;
852− if (!(*val = jas_iccattrval_clone(attr->val)))
902+ if (!(*val = jas_iccattrval_clone(attr->val))) {
853903 goto error;
904+ }
854905 return 0;
855906 error:
856907 return -1;
857908 }
858−//#endif /* JAS_ENABLE_ENCODER */
859909
860910 static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab,
861911 jas_iccuint32_t name)
@@ -863,8 +913,9 @@ static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, · 1 unmodified line
863913 jas_iccattr_t *attr;
864914 for (unsigned i = 0; i < attrtab->numattrs; ++i) {
865915 attr = &attrtab->attrs[i];
866− if (attr->name == name)
916+ if (attr->name == name) {
867917 return i;
918+ }
868919 }
869920 return -1;
870921 }
@@ -878,10 +929,12 @@ jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type) · 7 unmodified lines
878929 jas_iccattrval_t *attrval;
879930 const jas_iccattrvalinfo_t *info;
880931
881− if (!(info = jas_iccattrvalinfo_lookup(type)))
932+ if (!(info = jas_iccattrvalinfo_lookup(type))) {
882933 goto error;
883− if (!(attrval = jas_iccattrval_create0()))
934+ }
935+ if (!(attrval = jas_iccattrval_create0())) {
884936 goto error;
937+ }
885938 attrval->ops = &info->ops;
886939 attrval->type = type;
887940 ++attrval->refcnt;
@@ -903,25 +956,39 @@ void jas_iccattrval_destroy(jas_iccattrval_t *attrval) · 15 unmodified lines
903956 jas_eprintf("refcnt=%d\n", attrval->refcnt);
904957 #endif
905958 if (--attrval->refcnt <= 0) {
906− if (attrval->ops->destroy)
959+ if (attrval->ops->destroy) {
907960 (*attrval->ops->destroy)(attrval);
961+ }
908962 jas_free(attrval);
909963 }
910964 }
911965
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+
912977 int jas_iccattrval_allowmodify(jas_iccattrval_t **attrvalx)
913978 {
914979 jas_iccattrval_t *newattrval;
915980 jas_iccattrval_t *attrval = *attrvalx;
916981 if (attrval->refcnt > 1) {
917− if (!(newattrval = jas_iccattrval_create0()))
982+ if (!(newattrval = jas_iccattrval_create0())) {
918983 goto error;
984+ }
919985 newattrval->ops = attrval->ops;
920986 newattrval->type = attrval->type;
921987 ++newattrval->refcnt;
922988 if (newattrval->ops->copy) {
923− if ((*newattrval->ops->copy)(newattrval, attrval))
989+ if ((*newattrval->ops->copy)(newattrval, attrval)) {
924990 goto error;
991+ }
925992 } else {
926993 memcpy(&newattrval->data, &attrval->data,
927994 sizeof(newattrval->data));
@@ -939,8 +1006,9 @@ error: · 11 unmodified lines
9391006 static jas_iccattrval_t *jas_iccattrval_create0()
9401007 {
9411008 jas_iccattrval_t *attrval;
942− if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t))))
1009+ if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t)))) {
9431010 return 0;
1011+ }
9441012 memset(attrval, 0, sizeof(jas_iccattrval_t));
9451013 attrval->refcnt = 0;
9461014 attrval->ops = 0;
@@ -955,31 +1023,36 @@ static jas_iccattrval_t *jas_iccattrval_create0() · 8 unmodified lines
9551023 static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in,
9561024 unsigned len)
9571025 {
958− assert(len == 4 * 3);
959− (void)len;
1026+ if (len != 4 * 3) {
1027+ return -1;
1028+ }
9601029 return jas_iccgetxyz(in, &attrval->data.xyz);
9611030 }
9621031
963−//#ifdef JAS_ENABLE_ENCODER
9641032 static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out)
9651033 {
9661034 const jas_iccxyz_t *xyz = &attrval->data.xyz;
9671035 if (jas_iccputuint32(out, xyz->x) ||
9681036 jas_iccputuint32(out, xyz->y) ||
969− jas_iccputuint32(out, xyz->z))
1037+ jas_iccputuint32(out, xyz->z)) {
9701038 return -1;
1039+ }
9711040 return 0;
9721041 }
973−//#endif /* JAS_ENABLE_ENCODER */
9741042
9751043 static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval)
9761044 {
977− /* Avoid compiler warnings about unused parameters. */
978− USED(attrval);
979−
1045+ JAS_UNUSED(attrval);
9801046 return 12;
9811047 }
9821048
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+
9831056 /******************************************************************************\
9841057 * attribute table class
9851058 \******************************************************************************/
@@ -996,9 +1069,8 @@ static void jas_icccurv_destroy(jas_iccattrval_t *attrval) · 10 unmodified lines
9961069 static int jas_icccurv_copy(jas_iccattrval_t *attrval,
9971070 const jas_iccattrval_t *othattrval)
9981071 {
999− /* Avoid compiler warnings about unused parameters. */
1000− USED(attrval);
1001− USED(othattrval);
1072+ JAS_UNUSED(attrval);
1073+ JAS_UNUSED(othattrval);
10021074
10031075 /* Not yet implemented. */
10041076 abort();
@@ -1013,17 +1085,21 @@ static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 8 unmodified lines
10131085 curv->numents = 0;
10141086 curv->ents = 0;
10151087
1016− if (jas_iccgetuint32(in, &curv->numents))
1088+ if (jas_iccgetuint32(in, &curv->numents)) {
10171089 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)))) {
10191092 goto error;
1093+ }
10201094 for (unsigned i = 0; i < curv->numents; ++i) {
1021− if (jas_iccgetuint16(in, &curv->ents[i]))
1095+ if (jas_iccgetuint16(in, &curv->ents[i])) {
10221096 goto error;
1097+ }
10231098 }
10241099
1025− if (4 + 2 * curv->numents != cnt)
1100+ if (4 + 2 * curv->numents != cnt) {
10261101 goto error;
1102+ }
10271103 return 0;
10281104
10291105 error:
@@ -1037,22 +1113,37 @@ static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval) · 7 unmodified lines
10371113 return 4 + 2 * curv->numents;
10381114 }
10391115
1040−//#ifdef JAS_ENABLE_ENCODER
10411116 static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out)
10421117 {
10431118 const jas_icccurv_t *curv = &attrval->data.curv;
10441119
1045− if (jas_iccputuint32(out, curv->numents))
1120+ if (jas_iccputuint32(out, curv->numents)) {
10461121 goto error;
1122+ }
10471123 for (unsigned i = 0; i < curv->numents; ++i) {
1048− if (jas_iccputuint16(out, curv->ents[i]))
1124+ if (jas_iccputuint16(out, curv->ents[i])) {
10491125 goto error;
1126+ }
10501127 }
10511128 return 0;
10521129 error:
10531130 return -1;
10541131 }
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+}
10561147
10571148 /******************************************************************************\
10581149 *
@@ -1076,10 +1167,9 @@ static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval, · 17 unmodified lines
10761167 {
10771168 jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
10781169
1079− /* Avoid compiler warnings about unused parameters. */
1080− USED(attrval);
1081− USED(othattrval);
1082− USED(txtdesc);
1170+ JAS_UNUSED(attrval);
1171+ JAS_UNUSED(othattrval);
1172+ JAS_UNUSED(txtdesc);
10831173
10841174 /* Not yet implemented. */
10851175 abort();
@@ -1093,31 +1183,41 @@ static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 7 unmodified lines
10931183 jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
10941184 txtdesc->ascdata = 0;
10951185 txtdesc->ucdata = 0;
1096− if (jas_iccgetuint32(in, &txtdesc->asclen))
1186+ if (jas_iccgetuint32(in, &txtdesc->asclen)) {
10971187 goto error;
1098− if (txtdesc->asclen < 1)
1188+ }
1189+ if (txtdesc->asclen < 1) {
10991190 goto error;
1100− if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen)))
1191+ }
1192+ if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen))) {
11011193 goto error;
1194+ }
11021195 if (jas_stream_read(in, txtdesc->ascdata, txtdesc->asclen) !=
1103− txtdesc->asclen)
1196+ txtdesc->asclen) {
11041197 goto error;
1198+ }
11051199 txtdesc->ascdata[txtdesc->asclen - 1] = '\0';
11061200 if (jas_iccgetuint32(in, &txtdesc->uclangcode) ||
1107− jas_iccgetuint32(in, &txtdesc->uclen))
1201+ jas_iccgetuint32(in, &txtdesc->uclen)) {
11081202 goto error;
1109− if (!(txtdesc->ucdata = jas_alloc2(txtdesc->uclen, 2)))
1203+ }
1204+ if (!(txtdesc->ucdata = jas_alloc2(txtdesc->uclen, 2))) {
11101205 goto error;
1206+ }
11111207 if (jas_stream_read(in, txtdesc->ucdata, txtdesc->uclen * 2) !=
1112− txtdesc->uclen * 2)
1208+ txtdesc->uclen * 2) {
11131209 goto error;
1114− if (jas_iccgetuint16(in, &txtdesc->sccode))
1210+ }
1211+ if (jas_iccgetuint16(in, &txtdesc->sccode)) {
11151212 goto error;
1116− if ((c = jas_stream_getc(in)) == EOF)
1213+ }
1214+ if ((c = jas_stream_getc(in)) == EOF) {
11171215 goto error;
1216+ }
11181217 txtdesc->maclen = c;
1119− if (jas_stream_read(in, txtdesc->macdata, 67) != 67)
1218+ if (jas_stream_read(in, txtdesc->macdata, 67) != 67) {
11201219 goto error;
1220+ }
11211221 txtdesc->asclen = JAS_CAST(jas_iccuint32_t, strlen(txtdesc->ascdata) + 1);
11221222 #define WORKAROUND_BAD_PROFILES
11231223 #ifdef WORKAROUND_BAD_PROFILES
@@ -1126,12 +1226,14 @@ static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 2 unmodified lines
11261226 return -1;
11271227 }
11281228 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)) {
11301230 goto error;
1231+ }
11311232 }
11321233 #else
1133− if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt)
1234+ if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt) {
11341235 return -1;
1236+ }
11351237 #endif
11361238 return 0;
11371239 error:
@@ -1145,7 +1247,6 @@ static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval) · 7 unmodified lines
11451247 return strlen(txtdesc->ascdata) + 1 + txtdesc->uclen * 2 + 15 + 67;
11461248 }
11471249
1148−//#ifdef JAS_ENABLE_ENCODER
11491250 static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out)
11501251 {
11511252 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
11541255 jas_stream_putc(out, 0) == EOF ||
11551256 jas_iccputuint32(out, txtdesc->uclangcode) ||
11561257 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 ||
11581260 jas_iccputuint16(out, txtdesc->sccode) ||
1159− jas_stream_putc(out, txtdesc->maclen) == EOF)
1261+ jas_stream_putc(out, txtdesc->maclen) == EOF) {
11601262 goto error;
1263+ }
11611264 if (txtdesc->maclen > 0) {
1162− if (jas_stream_write(out, txtdesc->macdata, 67) != 67)
1265+ if (jas_stream_write(out, txtdesc->macdata, 67) != 67) {
11631266 goto error;
1267+ }
11641268 } else {
1165− if (jas_stream_pad(out, 67, 0) != 67)
1269+ if (jas_stream_pad(out, 67, 0) != 67) {
11661270 goto error;
1271+ }
11671272 }
11681273 return 0;
11691274 error:
11701275 return -1;
11711276 }
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+}
11731287
11741288 /******************************************************************************\
11751289 *
@@ -1189,8 +1303,9 @@ static int jas_icctxt_copy(jas_iccattrval_t *attrval, · 13 unmodified lines
11891303 {
11901304 jas_icctxt_t *txt = &attrval->data.txt;
11911305 const jas_icctxt_t *othtxt = &othattrval->data.txt;
1192− if (!(txt->string = strdup(othtxt->string)))
1306+ if (!(txt->string = jas_strdup(othtxt->string))) {
11931307 return -1;
1308+ }
11941309 return 0;
11951310 }
11961311
@@ -1199,13 +1314,16 @@ static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 2 unmodified lines
11991314 {
12001315 jas_icctxt_t *txt = &attrval->data.txt;
12011316 txt->string = 0;
1202− if (!(txt->string = jas_malloc(cnt)))
1317+ if (!(txt->string = jas_malloc(cnt))) {
12031318 goto error;
1204− if (jas_stream_read(in, txt->string, cnt) != cnt)
1319+ }
1320+ if (jas_stream_read(in, txt->string, cnt) != cnt) {
12051321 goto error;
1322+ }
12061323 txt->string[cnt - 1] = '\0';
1207− if (strlen(txt->string) + 1 != cnt)
1324+ if (strlen(txt->string) + 1 != cnt) {
12081325 goto error;
1326+ }
12091327 return 0;
12101328 error:
12111329 jas_icctxt_destroy(attrval);
@@ -1218,16 +1336,21 @@ static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval) · 6 unmodified lines
12181336 return strlen(txt->string) + 1;
12191337 }
12201338
1221−//#ifdef JAS_ENABLE_ENCODER
12221339 static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out)
12231340 {
12241341 const jas_icctxt_t *txt = &attrval->data.txt;
12251342 if (jas_stream_puts(out, txt->string) ||
1226− jas_stream_putc(out, 0) == EOF)
1343+ jas_stream_putc(out, 0) == EOF) {
12271344 return -1;
1345+ }
12281346 return 0;
12291347 }
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+}
12311354
12321355 /******************************************************************************\
12331356 *
@@ -1261,9 +1384,8 @@ static void jas_icclut8_destroy(jas_iccattrval_t *attrval) · 27 unmodified lines
12611384 static int jas_icclut8_copy(jas_iccattrval_t *attrval,
12621385 const jas_iccattrval_t *othattrval)
12631386 {
1264− /* Avoid compiler warnings about unused parameters. */
1265− USED(attrval);
1266− USED(othattrval);
1387+ JAS_UNUSED(attrval);
1388+ JAS_UNUSED(othattrval);
12671389 abort();
12681390 return -1;
12691391 }
@@ -1280,54 +1402,64 @@ static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 10 unmodified lines
12801402 if (jas_iccgetuint8(in, &lut8->numinchans) ||
12811403 jas_iccgetuint8(in, &lut8->numoutchans) ||
12821404 jas_iccgetuint8(in, &lut8->clutlen) ||
1283− jas_stream_getc(in) == EOF)
1405+ jas_stream_getc(in) == EOF) {
12841406 goto error;
1407+ }
12851408 for (unsigned i = 0; i < 3; ++i) {
12861409 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])) {
12881411 goto error;
1412+ }
12891413 }
12901414 }
12911415 if (jas_iccgetuint16(in, &lut8->numintabents) ||
1292− jas_iccgetuint16(in, &lut8->numouttabents))
1416+ jas_iccgetuint16(in, &lut8->numouttabents)) {
12931417 goto error;
1418+ }
12941419 const unsigned clutsize = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans;
12951420 if (!(lut8->clut = jas_alloc2(clutsize, sizeof(jas_iccuint8_t))) ||
12961421 !(lut8->intabsbuf = jas_alloc3(lut8->numinchans,
12971422 lut8->numintabents, sizeof(jas_iccuint8_t))) ||
12981423 !(lut8->intabs = jas_alloc2(lut8->numinchans,
1299− sizeof(jas_iccuint8_t *))))
1424+ sizeof(jas_iccuint8_t *)))) {
13001425 goto error;
1426+ }
13011427 for (unsigned i = 0; i < lut8->numinchans; ++i)
13021428 lut8->intabs[i] = &lut8->intabsbuf[i * lut8->numintabents];
13031429 if (!(lut8->outtabsbuf = jas_alloc3(lut8->numoutchans,
13041430 lut8->numouttabents, sizeof(jas_iccuint8_t))) ||
13051431 !(lut8->outtabs = jas_alloc2(lut8->numoutchans,
1306− sizeof(jas_iccuint8_t *))))
1432+ sizeof(jas_iccuint8_t *)))) {
13071433 goto error;
1308− for (unsigned i = 0; i < lut8->numoutchans; ++i)
1434+ }
1435+ for (unsigned i = 0; i < lut8->numoutchans; ++i) {
13091436 lut8->outtabs[i] = &lut8->outtabsbuf[i * lut8->numouttabents];
1437+ }
13101438 for (unsigned i = 0; i < lut8->numinchans; ++i) {
13111439 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])) {
13131441 goto error;
1442+ }
13141443 }
13151444 }
13161445 for (unsigned i = 0; i < lut8->numoutchans; ++i) {
13171446 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])) {
13191448 goto error;
1449+ }
13201450 }
13211451 }
13221452 for (unsigned i = 0; i < clutsize; ++i) {
1323− if (jas_iccgetuint8(in, &lut8->clut[i]))
1453+ if (jas_iccgetuint8(in, &lut8->clut[i])) {
13241454 goto error;
1455+ }
13251456 }
13261457 if (44 + lut8->numinchans * lut8->numintabents +
13271458 lut8->numoutchans * lut8->numouttabents +
13281459 jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans !=
1329− cnt)
1460+ cnt) {
13301461 goto error;
1462+ }
13311463 return 0;
13321464 error:
13331465 jas_icclut8_destroy(attrval);
@@ -1342,7 +1474,6 @@ static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval) · 8 unmodified lines
13421474 jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans;
13431475 }
13441476
1345−//#ifdef JAS_ENABLE_ENCODER
13461477 static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out)
13471478 {
13481479 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
13541485 if (jas_stream_putc(out, lut8->numinchans) == EOF ||
13551486 jas_stream_putc(out, lut8->numoutchans) == EOF ||
13561487 jas_stream_putc(out, lut8->clutlen) == EOF ||
1357− jas_stream_putc(out, 0) == EOF)
1488+ jas_stream_putc(out, 0) == EOF) {
13581489 goto error;
1490+ }
13591491 for (unsigned i = 0; i < 3; ++i) {
13601492 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])) {
13621494 goto error;
1495+ }
13631496 }
13641497 }
13651498 if (jas_iccputuint16(out, lut8->numintabents) ||
1366− jas_iccputuint16(out, lut8->numouttabents))
1499+ jas_iccputuint16(out, lut8->numouttabents)) {
13671500 goto error;
1368− for (unsigned i = 0, n = lut8->numinchans * lut8->numintabents; i < n; ++i) {
1369− if (jas_iccputuint8(out, lut8->intabsbuf[i]))
1501+ }
1502+ for (unsigned i = 0, n = lut8->numinchans * lut8->numintabents; i < n;
1503+ ++i) {
1504+ if (jas_iccputuint8(out, lut8->intabsbuf[i])) {
13701505 goto error;
1506+ }
13711507 }
1372− for (unsigned i = 0, n = lut8->numoutchans * lut8->numouttabents; i < n; ++i) {
1373− if (jas_iccputuint8(out, lut8->outtabsbuf[i]))
1508+ for (unsigned i = 0, n = lut8->numoutchans * lut8->numouttabents; i < n;
1509+ ++i) {
1510+ if (jas_iccputuint8(out, lut8->outtabsbuf[i])) {
13741511 goto error;
1512+ }
13751513 }
1376− for (unsigned i = 0, n = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; i < n; ++i) {
1377− if (jas_iccputuint8(out, lut8->clut[i]))
1514+ for (unsigned i = 0, n = jas_iccpowi(lut8->clutlen, lut8->numinchans) *
1515+ lut8->numoutchans; i < n; ++i) {
1516+ if (jas_iccputuint8(out, lut8->clut[i])) {
13781517 goto error;
1518+ }
13791519 }
13801520 return 0;
13811521 error:
13821522 return -1;
13831523 }
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+}
13851539
13861540 /******************************************************************************\
13871541 *
@@ -1415,9 +1569,9 @@ static void jas_icclut16_destroy(jas_iccattrval_t *attrval) · 27 unmodified lines
14151569 static int jas_icclut16_copy(jas_iccattrval_t *attrval,
14161570 const jas_iccattrval_t *othattrval)
14171571 {
1418− /* Avoid compiler warnings about unused parameters. */
1419− USED(attrval);
1420− USED(othattrval);
1572+ JAS_UNUSED(attrval);
1573+ JAS_UNUSED(othattrval);
1574+
14211575 /* Not yet implemented. */
14221576 abort();
14231577 return -1;
@@ -1435,54 +1589,66 @@ static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in, · 11 unmodified lines
14351589 if (jas_iccgetuint8(in, &lut16->numinchans) ||
14361590 jas_iccgetuint8(in, &lut16->numoutchans) ||
14371591 jas_iccgetuint8(in, &lut16->clutlen) ||
1438− jas_stream_getc(in) == EOF)
1592+ jas_stream_getc(in) == EOF) {
14391593 goto error;
1594+ }
14401595 for (unsigned i = 0; i < 3; ++i) {
14411596 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])) {
14431598 goto error;
1599+ }
14441600 }
14451601 }
14461602 if (jas_iccgetuint16(in, &lut16->numintabents) ||
1447− jas_iccgetuint16(in, &lut16->numouttabents))
1603+ jas_iccgetuint16(in, &lut16->numouttabents)) {
14481604 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;
14501608 if (!(lut16->clut = jas_alloc2(clutsize, sizeof(jas_iccuint16_t))) ||
14511609 !(lut16->intabsbuf = jas_alloc3(lut16->numinchans,
14521610 lut16->numintabents, sizeof(jas_iccuint16_t))) ||
14531611 !(lut16->intabs = jas_alloc2(lut16->numinchans,
1454− sizeof(jas_iccuint16_t *))))
1612+ sizeof(jas_iccuint16_t *)))) {
14551613 goto error;
1456− for (unsigned i = 0; i < lut16->numinchans; ++i)
1614+ }
1615+ for (unsigned i = 0; i < lut16->numinchans; ++i) {
14571616 lut16->intabs[i] = &lut16->intabsbuf[i * lut16->numintabents];
1617+ }
14581618 if (!(lut16->outtabsbuf = jas_alloc3(lut16->numoutchans,
14591619 lut16->numouttabents, sizeof(jas_iccuint16_t))) ||
14601620 !(lut16->outtabs = jas_alloc2(lut16->numoutchans,
1461− sizeof(jas_iccuint16_t *))))
1621+ sizeof(jas_iccuint16_t *)))) {
14621622 goto error;
1463− for (unsigned i = 0; i < lut16->numoutchans; ++i)
1623+ }
1624+ for (unsigned i = 0; i < lut16->numoutchans; ++i) {
14641625 lut16->outtabs[i] = &lut16->outtabsbuf[i * lut16->numouttabents];
1626+ }
14651627 for (unsigned i = 0; i < lut16->numinchans; ++i) {
14661628 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])) {
14681630 goto error;
1631+ }
14691632 }
14701633 }
14711634 for (unsigned i = 0; i < lut16->numoutchans; ++i) {
14721635 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])) {
14741637 goto error;
1638+ }
14751639 }
14761640 }
14771641 for (unsigned i = 0; i < clutsize; ++i) {
1478− if (jas_iccgetuint16(in, &lut16->clut[i]))
1642+ if (jas_iccgetuint16(in, &lut16->clut[i])) {
14791643 goto error;
1644+ }
14801645 }
14811646 if (44 + 2 * (lut16->numinchans * lut16->numintabents +
1482− lut16->numoutchans * lut16->numouttabents +
1483− jas_iccpowi(lut16->clutlen, lut16->numinchans) *
1484− lut16->numoutchans) != cnt)
1647+ lut16->numoutchans * lut16->numouttabents +
1648+ jas_iccpowi(lut16->clutlen, lut16->numinchans) *
1649+ lut16->numoutchans) != cnt) {
14851650 goto error;
1651+ }
14861652 return 0;
14871653 error:
14881654 jas_icclut16_destroy(attrval);
@@ -1497,41 +1663,63 @@ static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval) · 8 unmodified lines
14971663 jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans);
14981664 }
14991665
1500−//#ifdef JAS_ENABLE_ENCODER
15011666 static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out)
15021667 {
15031668 const jas_icclut16_t *lut16 = &attrval->data.lut16;
15041669 if (jas_stream_putc(out, lut16->numinchans) == EOF ||
15051670 jas_stream_putc(out, lut16->numoutchans) == EOF ||
15061671 jas_stream_putc(out, lut16->clutlen) == EOF ||
1507− jas_stream_putc(out, 0) == EOF)
1672+ jas_stream_putc(out, 0) == EOF) {
15081673 goto error;
1674+ }
15091675 for (unsigned i = 0; i < 3; ++i) {
15101676 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])) {
15121678 goto error;
1679+ }
15131680 }
15141681 }
15151682 if (jas_iccputuint16(out, lut16->numintabents) ||
1516− jas_iccputuint16(out, lut16->numouttabents))
1683+ jas_iccputuint16(out, lut16->numouttabents)) {
15171684 goto error;
1518− for (unsigned i = 0, n = lut16->numinchans * lut16->numintabents; i < n; ++i) {
1519− if (jas_iccputuint16(out, lut16->intabsbuf[i]))
1685+ }
1686+ for (unsigned i = 0, n = lut16->numinchans * lut16->numintabents; i < n;
1687+ ++i) {
1688+ if (jas_iccputuint16(out, lut16->intabsbuf[i])) {
15201689 goto error;
1690+ }
15211691 }
1522− for (unsigned i = 0, n = lut16->numoutchans * lut16->numouttabents; i < n; ++i) {
1523− if (jas_iccputuint16(out, lut16->outtabsbuf[i]))
1692+ for (unsigned i = 0, n = lut16->numoutchans * lut16->numouttabents; i < n;
1693+ ++i) {
1694+ if (jas_iccputuint16(out, lut16->outtabsbuf[i])) {
15241695 goto error;
1696+ }
15251697 }
1526− for (unsigned i = 0, n = jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans; i < n; ++i) {
1527− if (jas_iccputuint16(out, lut16->clut[i]))
1698+ for (unsigned i = 0, n = jas_iccpowi(lut16->clutlen, lut16->numinchans) *
1699+ lut16->numoutchans; i < n; ++i) {
1700+ if (jas_iccputuint16(out, lut16->clut[i])) {
15281701 goto error;
1702+ }
15291703 }
15301704 return 0;
15311705 error:
15321706 return -1;
15331707 }
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+}
15351723
15361724 /******************************************************************************\
15371725 *
@@ -1543,8 +1731,9 @@ static int jas_iccgetuint(jas_stream_t *in, unsigned n, jas_ulonglong *val) · 5 unmodified lines
15431731 jas_ulonglong v;
15441732 v = 0;
15451733 for (unsigned i = n; i > 0; --i) {
1546− if ((c = jas_stream_getc(in)) == EOF)
1734+ if ((c = jas_stream_getc(in)) == EOF) {
15471735 return -1;
1736+ }
15481737 v = (v << 8) | c;
15491738 }
15501739 *val = v;
@@ -1554,8 +1743,9 @@ static int jas_iccgetuint(jas_stream_t *in, unsigned n, jas_ulonglong *val) · 3 unmodified lines
15541743 static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val)
15551744 {
15561745 int c;
1557− if ((c = jas_stream_getc(in)) == EOF)
1746+ if ((c = jas_stream_getc(in)) == EOF) {
15581747 return -1;
1748+ }
15591749 *val = c;
15601750 return 0;
15611751 }
@@ -1563,8 +1753,9 @@ static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val) · 1 unmodified line
15631753 static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val)
15641754 {
15651755 jas_ulonglong tmp;
1566− if (jas_iccgetuint(in, 2, &tmp))
1756+ if (jas_iccgetuint(in, 2, &tmp)) {
15671757 return -1;
1758+ }
15681759 *val = (jas_iccuint16_t)tmp;
15691760 return 0;
15701761 }
@@ -1572,8 +1763,9 @@ static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val) · 1 unmodified line
15721763 static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val)
15731764 {
15741765 jas_ulonglong tmp;
1575− if (jas_iccgetuint(in, 4, &tmp))
1766+ if (jas_iccgetuint(in, 4, &tmp)) {
15761767 return -1;
1768+ }
15771769 *val = (tmp & 0x80000000) ? (-JAS_CAST(jas_longlong, (((~tmp) &
15781770 0x7fffffff) + 1))) : JAS_CAST(jas_longlong, tmp);
15791771 return 0;
@@ -1582,8 +1774,9 @@ static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val) · 2 unmodified lines
15821774 static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val)
15831775 {
15841776 jas_ulonglong tmp;
1585− if (jas_iccgetuint(in, 4, &tmp))
1777+ if (jas_iccgetuint(in, 4, &tmp)) {
15861778 return -1;
1779+ }
15871780 *val = (jas_iccuint32_t)tmp;
15881781 return 0;
15891782 }
@@ -1591,21 +1784,21 @@ static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val) · 1 unmodified line
15911784 static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val)
15921785 {
15931786 jas_ulonglong tmp;
1594− if (jas_iccgetuint(in, 8, &tmp))
1787+ if (jas_iccgetuint(in, 8, &tmp)) {
15951788 return -1;
1789+ }
15961790 *val = (jas_iccuint64_t)tmp;
15971791 return 0;
15981792 }
15991793
1600−//#ifdef JAS_ENABLE_ENCODER
1601−
16021794 static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val)
16031795 {
16041796 int c;
16051797 for (unsigned i = n; i > 0; --i) {
16061798 c = (val >> (8 * (i - 1))) & 0xff;
1607− if (jas_stream_putc(out, c) == EOF)
1799+ if (jas_stream_putc(out, c) == EOF) {
16081800 return -1;
1801+ }
16091802 }
16101803 return 0;
16111804 }
@@ -1618,8 +1811,6 @@ static int jas_iccputsint(jas_stream_t *out, unsigned n, jas_longlong val) · 6 unmodified lines
16181811 return jas_iccputuint(out, n, tmp);
16191812 }
16201813
1621−//#endif /* JAS_ENABLE_ENCODER */
1622−
16231814 /******************************************************************************\
16241815 *
16251816 \******************************************************************************/
@@ -1631,7 +1822,8 @@ static char *jas_iccsigtostr(unsigned sig, char *buf) · 5 unmodified lines
16311822 bufptr = buf;
16321823 for (unsigned n = 4; n > 0; --n) {
16331824 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))) {
16351827 *bufptr++ = c;
16361828 }
16371829 sig <<= 8;
@@ -1640,36 +1832,40 @@ static char *jas_iccsigtostr(unsigned sig, char *buf) · 2 unmodified lines
16401832 return buf;
16411833 }
16421834
1643−//#ifdef JAS_ENABLE_ENCODER
16441835 static unsigned jas_iccpadtomult(unsigned x, unsigned y)
16451836 {
16461837 return ((x + y - 1) / y) * y;
16471838 }
1648−//#endif /* JAS_ENABLE_ENCODER */
16491839
16501840 static unsigned jas_iccpowi(unsigned x, unsigned n)
16511841 {
16521842 unsigned y;
16531843 y = 1;
1654− while (n-- > 0)
1844+ while (n-- > 0) {
16551845 y *= x;
1846+ }
16561847 return y;
16571848 }
16581849
16591850
16601851 jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len)
16611852 {
1853+ assert(buf);
1854+ assert(len > 0);
16621855 jas_stream_t *in;
16631856 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))) {
16651858 goto error;
1666− if (!(prof = jas_iccprof_load(in)))
1859+ }
1860+ if (!(prof = jas_iccprof_load(in))) {
16671861 goto error;
1862+ }
16681863 jas_stream_close(in);
16691864 return prof;
16701865 error:
1671− if (in)
1866+ if (in) {
16721867 jas_stream_close(in);
1868+ }
16731869 return 0;
16741870 }
16751871
jas_iccdata.c+10−0
@@ -59,9 +59,19 @@ · 58 unmodified lines
5959 * __END_OF_JASPER_LICENSE__
6060 */
6161
62+/******************************************************************************\
63+* Includes.
64+\******************************************************************************/
65+
66+//#define JAS_FOR_INTERNAL_USE_ONLY
67+
6268 #include <jasper/jas_config.h> /* IWYU pragma: keep */
6369 #include <jasper/jas_types.h>
6470
71+/******************************************************************************\
72+* Data.
73+\******************************************************************************/
74+
6575 const jas_uchar jas_iccprofdata_srgb[] =
6676 {
6777 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f,
jas_image.c+404−203
@@ -71,9 +71,13 @@ · 70 unmodified lines
7171 * Includes.
7272 \******************************************************************************/
7373
74+#define JAS_FOR_INTERNAL_USE_ONLY
75+
76+#include "jasper/jas_init.h"
7477 #include "jasper/jas_image.h"
7578 #include "jasper/jas_math.h"
7679 #include "jasper/jas_malloc.h"
80+#include "jasper/jas_string.h"
7781 #include "jasper/jas_debug.h"
7882
7983 /******************************************************************************\
@@ -90,7 +94,8 @@ static jas_image_cmpt_t *jas_image_cmpt_create0(void); · 10 unmodified lines
9094 static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt);
9195 static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx,
9296 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);
9499 static void jas_image_setbbox(jas_image_t *image);
95100 static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt);
96101 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
102107 static long downtomult(long x, long y);
103108 static long convert(long val, bool oldsgnd, unsigned oldprec, bool newsgnd,
104109 unsigned newprec);
105−static void jas_image_calcbbox2(const jas_image_t *image, jas_image_coord_t *tlx,
106− jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry);
107−
108−/******************************************************************************\
109−* Global data.
110−\******************************************************************************/
111−
112−static unsigned jas_image_numfmts = 0;
113−static jas_image_fmtinfo_t jas_image_fmtinfos[JAS_IMAGE_MAXFMTS];
110+static void jas_image_calcbbox2(const jas_image_t *image,
111+ jas_image_coord_t *tlx, jas_image_coord_t *tly, jas_image_coord_t *brx,
112+ jas_image_coord_t *bry);
113+static void jas_image_fmtinfo_init(jas_image_fmtinfo_t *fmtinfo);
114+static void jas_image_fmtinfo_cleanup(jas_image_fmtinfo_t *fmtinfo);
114115
115116 /******************************************************************************\
116117 * Create and destroy operations.
117118 \******************************************************************************/
118119
119−jas_image_t *jas_image_create(unsigned numcmpts, const jas_image_cmptparm_t *cmptparms,
120− jas_clrspc_t clrspc)
120+jas_image_t *jas_image_create(unsigned numcmpts,
121+ const jas_image_cmptparm_t *cmptparms, jas_clrspc_t clrspc)
121122 {
122123 jas_image_t *image;
123124 size_t rawsize;
124125 unsigned cmptno;
125126 const jas_image_cmptparm_t *cmptparm;
126127
127− JAS_DBGLOG(100, ("jas_image_create(%d, %p, %d)\n", numcmpts, cmptparms,
128− clrspc));
128+
129+ JAS_LOGDEBUGF(100, "jas_image_create(%d, %p, %d)\n", numcmpts, cmptparms,
130+ clrspc);
129131
130132 if (!(image = jas_image_create0())) {
131133 goto error;
@@ -133,6 +135,7 @@ jas_image_t *jas_image_create(unsigned numcmpts, const jas_image_cmptparm_t *cmp · 1 unmodified line
133135
134136 image->clrspc_ = clrspc;
135137 image->maxcmpts_ = numcmpts;
138+// image->inmem_ = true;
136139
137140 /* Allocate memory for the per-component information. */
138141 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
144147 image->cmpts_[cmptno] = 0;
145148 }
146149
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+
147163 /* Create the individual image components. */
148164 for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno,
149165 ++cmptparm) {
@@ -152,10 +168,11 @@ jas_image_t *jas_image_create(unsigned numcmpts, const jas_image_cmptparm_t *cmp · 2 unmodified lines
152168 goto error;
153169 }
154170 rawsize /= 8;
171+ const bool inmem = (rawsize < JAS_IMAGE_INMEMTHRESH);
155172 if (!(image->cmpts_[cmptno] = jas_image_cmpt_create(cmptparm->tlx,
156173 cmptparm->tly, cmptparm->hstep, cmptparm->vstep,
157174 cmptparm->width, cmptparm->height, cmptparm->prec,
158− cmptparm->sgnd))) {
175+ cmptparm->sgnd, inmem))) {
159176 goto error;
160177 }
161178 ++image->numcmpts_;
@@ -190,6 +207,7 @@ jas_image_t *jas_image_create0() · 28 unmodified lines
190207 image->numcmpts_ = 0;
191208 image->maxcmpts_ = 0;
192209 image->cmpts_ = 0;
210+// image->inmem_ = true;
193211 image->cmprof_ = 0;
194212
195213 return image;
@@ -207,7 +225,8 @@ jas_image_t *jas_image_copy(jas_image_t *image) · 11 unmodified lines
207225 goto error;
208226 }
209227 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]))) {
211230 goto error;
212231 }
213232 ++newimage->numcmpts_;
@@ -216,8 +235,9 @@ jas_image_t *jas_image_copy(jas_image_t *image) · 2 unmodified lines
216235 jas_image_setbbox(newimage);
217236
218237 if (image->cmprof_) {
219− if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_)))
238+ if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_))) {
220239 goto error;
240+ }
221241 }
222242
223243 return newimage;
@@ -259,13 +279,13 @@ static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt) · 35 unmodified lines
259279 if (!(newcmpt->stream_ = jas_stream_memopen(0, 0))) {
260280 goto error;
261281 }
262− if (jas_stream_seek(cmpt->stream_, 0, 0)) {
282+ if (jas_stream_seek(cmpt->stream_, 0, SEEK_SET)) {
263283 goto error;
264284 }
265285 if (jas_stream_copy(newcmpt->stream_, cmpt->stream_, -1)) {
266286 goto error;
267287 }
268− if (jas_stream_seek(newcmpt->stream_, 0, 0)) {
288+ if (jas_stream_seek(newcmpt->stream_, 0, SEEK_SET)) {
269289 goto error;
270290 }
271291 return newcmpt;
@@ -283,20 +303,22 @@ void jas_image_destroy(jas_image_t *image) · 11 unmodified lines
283303 }
284304 jas_free(image->cmpts_);
285305 }
286− if (image->cmprof_)
306+ if (image->cmprof_) {
287307 jas_cmprof_destroy(image->cmprof_);
308+ }
288309 jas_free(image);
289310 }
290311
291312 static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx,
292313 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)
294316 {
295317 jas_image_cmpt_t *cmpt;
296318 size_t size;
297319
298− JAS_DBGLOG(100, (
299− "jas_image_cmpt_create(%ld, %ld, %ld, %ld, %ld, %ld, %d, %d)\n",
320+ JAS_LOGDEBUGF(100,
321+ "jas_image_cmpt_create(%ld, %ld, %ld, %ld, %ld, %ld, %d, %d, %d)\n",
300322 JAS_CAST(long, tlx),
301323 JAS_CAST(long, tly),
302324 JAS_CAST(long, hstep),
@@ -305,7 +327,8 @@ static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, · 2 unmodified lines
305327 JAS_CAST(long, height),
306328 JAS_CAST(int, depth),
307329 sgnd,
308− ));
330+ inmem
331+ );
309332
310333 if (depth < 1U + sgnd) {
311334 /* 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
340363 cmpt->stream_ = 0;
341364 cmpt->cps_ = (depth + 7) / 8;
342365
343− // Compute the number of samples in the image component, while protecting
344− // against overflow.
345− // size = cmpt->width_ * cmpt->height_ * cmpt->cps_;
366+ /*
367+ * Compute the number of samples in the image component, while protecting
368+ * against overflow.
369+ * size = cmpt->width_ * cmpt->height_ * cmpt->cps_;
370+ */
346371 if (!jas_safe_size_mul3(cmpt->width_, cmpt->height_, cmpt->cps_, &size)) {
347372 goto error;
348373 }
349− cmpt->stream_ = jas_stream_memopen2(0, size);
374+ cmpt->stream_ = (inmem) ? jas_stream_memopen(0, size) :
375+ jas_stream_tmpfile();
350376 if (!cmpt->stream_) {
351377 goto error;
352378 }
@@ -358,9 +384,9 @@ static jas_image_cmpt_t *jas_image_cmpt_create(int_fast32_t tlx, · 5 unmodified lines
358384 if (size - 1 > LONG_MAX) {
359385 goto error;
360386 }
361− if (jas_stream_seek(cmpt->stream_, size - 1, 0) < 0 ||
387+ if (jas_stream_seek(cmpt->stream_, size - 1, SEEK_SET) < 0 ||
362388 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) {
364390 goto error;
365391 }
366392 }
@@ -393,25 +419,24 @@ jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr) · 26 unmodified lines
393419
394420 /* If possible, try to determine the format of the input data. */
395421 if (fmt < 0) {
396− if ((fmt = jas_image_getfmt(in)) < 0){
397− werrstr("unknown format");
422+ if ((fmt = jas_image_getfmt(in)) < 0) {
423+ jas_logerrorf("jas_image_decode: cannot determine image format\n");
398424 goto error;
399425 }
400426 }
401427
402428 /* Is it possible to decode an image represented in this format? */
403− if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))){
404− werrstr("unsupported format");
429+ if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) {
405430 goto error;
406431 }
407− if (!fmtinfo->ops.decode){
408− werrstr("no decoder for the format");
432+ if (!fmtinfo->ops.decode) {
433+ jas_logerrorf("jas_image_decode: no decode operation available\n");
409434 goto error;
410435 }
411436
412437 /* Decode the image. */
413− if (!(image = (*fmtinfo->ops.decode)(in, optstr))){
414− werrstr("failed to decode");
438+ if (!(image = (*fmtinfo->ops.decode)(in, optstr))) {
439+ jas_logerrorf("jas_image_decode: decode operation failed\n");
415440 goto error;
416441 }
417442
@@ -419,16 +444,18 @@ jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr) · 1 unmodified line
419444 if (!jas_clrspc_isunknown(image->clrspc_) &&
420445 !jas_clrspc_isgeneric(image->clrspc_) && !image->cmprof_) {
421446 if (!(image->cmprof_ =
422− jas_cmprof_createfromclrspc(jas_image_clrspc(image)))){
423− werrstr("failed to create colorspace");
447+ jas_cmprof_createfromclrspc(jas_image_clrspc(image)))) {
448+ jas_logerrorf("jas_image_decode: cannot create CM profile\n");
424449 goto error;
425450 }
426451 }
427452
428453 return image;
454+
429455 error:
430− if (image)
456+ if (image) {
431457 jas_image_destroy(image);
458+ }
432459 return 0;
433460 }
434461
@@ -437,7 +464,7 @@ int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, · 2 unmodified lines
437464 {
438465 const jas_image_fmtinfo_t *fmtinfo;
439466 if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) {
440− jas_eprintf("format lookup failed\n");
467+ jas_logerrorf("format lookup failed\n");
441468 return -1;
442469 }
443470 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
460487 jas_seqent_t *dr;
461488 jas_seqent_t *d;
462489
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",
464491 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);
466493
467494 if(data == NULL) {
468495 return -1;
@@ -483,7 +510,8 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 14 unmodified lines
483510 return -1;
484511 }
485512
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) {
487515 if (jas_matrix_resize(data, height, width)) {
488516 return -1;
489517 }
@@ -497,9 +525,13 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 7 unmodified lines
497525
498526 dr = jas_matrix_getref(data, 0, 0);
499527 const uint_least32_t drs = jas_matrix_rowstep(data);
528+
529+ jas_uchar stack_buffer[16384];
530+
500531 for (i = 0; i < height; ++i, dr += drs) {
501532 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) {
503535 return -1;
504536 }
505537
@@ -507,13 +539,15 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 1 unmodified line
507539 /* fast path for 1 byte per sample and
508540 unsigned with bulk reads */
509541
510− jas_uchar buffer[16384];
542+ jas_uchar *buffer = stack_buffer;
511543
512− if (jas_stream_read(stream, buffer, width) != width)
544+ if (jas_stream_read(stream, buffer, width) != width) {
513545 return -1;
546+ }
514547
515− for (j = 0; j < width; ++j)
548+ for (j = 0; j < width; ++j) {
516549 d[j] = buffer[j];
550+ }
517551
518552 continue;
519553 }
@@ -533,9 +567,9 @@ int jas_image_readcmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x, · 13 unmodified lines
533567 return 0;
534568 }
535569
536−int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x,
537− jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
538− const jas_matrix_t *data)
570+int jas_image_writecmpt(jas_image_t *image, unsigned cmptno,
571+ jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width,
572+ jas_image_coord_t height, const jas_matrix_t *data)
539573 {
540574 jas_image_cmpt_t *cmpt;
541575 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
543577 jas_seqent_t v;
544578 int c;
545579
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",
547581 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);
549583
550584 if (cmptno >= image->numcmpts_) {
551585 return -1;
@@ -575,9 +609,13 @@ int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x · 23 unmodified lines
575609
576610 const jas_seqent_t *dr = jas_matrix_getref(data, 0, 0);
577611 const uint_least32_t drs = jas_matrix_rowstep(data);
612+
613+ jas_uchar stack_buffer[16384];
614+
578615 for (i = 0; i < height; ++i, dr += drs) {
579616 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) {
581619 return -1;
582620 }
583621
@@ -585,7 +623,7 @@ int jas_image_writecmpt(jas_image_t *image, unsigned cmptno, jas_image_coord_t x · 1 unmodified line
585623 /* fast path for 1 byte per sample and
586624 unsigned with bulk writes */
587625
588− jas_uchar buffer[16384];
626+ jas_uchar *buffer = stack_buffer;
589627
590628 for (j = 0; j < width; ++j)
591629 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
614652 * File format operations.
615653 \******************************************************************************/
616654
617−void jas_image_clearfmts()
655+static void jas_image_fmtinfo_init(jas_image_fmtinfo_t *fmtinfo)
618656 {
619− jas_image_fmtinfo_t *fmtinfo;
620− for (unsigned i = 0; i < jas_image_numfmts; ++i) {
621− fmtinfo = &jas_image_fmtinfos[i];
622− if (fmtinfo->name) {
623− jas_free(fmtinfo->name);
624− fmtinfo->name = 0;
625− }
626− if (fmtinfo->ext) {
627− jas_free(fmtinfo->ext);
628− fmtinfo->ext = 0;
629− }
630− if (fmtinfo->desc) {
631− jas_free(fmtinfo->desc);
632− fmtinfo->desc = 0;
633− }
634− }
635− jas_image_numfmts = 0;
657+ fmtinfo->id = -1;
658+ fmtinfo->name = 0;
659+ fmtinfo->ext = 0;
660+ fmtinfo->exts = 0;
661+ fmtinfo->max_exts = 0;
662+ fmtinfo->num_exts = 0;
663+ fmtinfo->enabled = 0;
664+ fmtinfo->desc = 0;
665+ memset(&fmtinfo->ops, 0, sizeof(jas_image_fmtops_t));
636666 }
637667
638−int jas_image_addfmt(int id, const char *name, const char *ext,
639− const char *desc, const jas_image_fmtops_t *ops)
668+static void jas_image_fmtinfo_cleanup(jas_image_fmtinfo_t *fmtinfo)
640669 {
641− jas_image_fmtinfo_t *fmtinfo;
642− assert(id >= 0 && name && ext && ops);
643− if (jas_image_numfmts >= JAS_IMAGE_MAXFMTS) {
644− return -1;
645− }
646− fmtinfo = &jas_image_fmtinfos[jas_image_numfmts];
647− fmtinfo->id = id;
648− if (!(fmtinfo->name = strdup(name))) {
649− return -1;
650− }
651− if (!(fmtinfo->ext = strdup(ext))) {
670+ if (fmtinfo->name) {
652671 jas_free(fmtinfo->name);
653− return -1;
672+ fmtinfo->name = 0;
654673 }
655− if (!(fmtinfo->desc = strdup(desc))) {
656− jas_free(fmtinfo->name);
674+ if (fmtinfo->ext) {
657675 jas_free(fmtinfo->ext);
658− return -1;
676+ fmtinfo->ext = 0;
659677 }
660− fmtinfo->ops = *ops;
661− ++jas_image_numfmts;
678+ if (fmtinfo->exts) {
679+ assert(fmtinfo->max_exts > 0);
680+ for (int i = 0; i < fmtinfo->num_exts; ++i) {
681+ jas_free(fmtinfo->exts[i]);
682+ }
683+ jas_free(fmtinfo->exts);
684+ fmtinfo->exts = 0;
685+ }
686+ if (fmtinfo->desc) {
687+ jas_free(fmtinfo->desc);
688+ fmtinfo->desc = 0;
689+ }
690+}
691+
692+JAS_EXPORT
693+const jas_image_fmtinfo_t *jas_image_getfmtbyind(int index)
694+{
695+ jas_ctx_t *ctx = jas_get_ctx();
696+ assert(index >= 0 && index < ctx->image_numfmts);
697+ return &ctx->image_fmtinfos[index];
698+}
699+
700+JAS_EXPORT
701+int jas_image_getnumfmts(void)
702+{
703+ jas_ctx_t *ctx = jas_get_ctx();
704+ return ctx->image_numfmts;
705+}
706+
707+JAS_EXPORT
708+int jas_image_setfmtenable(int index, int enabled)
709+{
710+ jas_ctx_t *ctx = jas_get_ctx();
711+ ctx->image_fmtinfos[index].enabled = enabled;
662712 return 0;
663713 }
664714
665−int jas_image_addcmpt(jas_image_t *image, int cmptno,
666− const jas_image_cmptparm_t *cmptparm)
715+void jas_image_clearfmts_internal(jas_image_fmtinfo_t *image_fmtinfos,
716+ size_t *image_numfmts)
667717 {
668− jas_image_cmpt_t *newcmpt;
669− if (cmptno < 0) {
670− cmptno = image->numcmpts_;
718+ jas_image_fmtinfo_t *fmtinfo;
719+ for (int fmtind = 0; fmtind < *image_numfmts; ++fmtind) {
720+ fmtinfo = &image_fmtinfos[fmtind];
721+ jas_image_fmtinfo_cleanup(fmtinfo);
671722 }
672− assert(cmptno >= 0 && (unsigned)cmptno <= image->numcmpts_);
673− if (image->numcmpts_ >= image->maxcmpts_) {
674− if (jas_image_growcmpts(image, image->maxcmpts_ + 128)) {
675− return -1;
676− }
723+ *image_numfmts = 0;
724+}
725+
726+void jas_image_clearfmts()
727+{
728+ jas_ctx_t *ctx = jas_get_ctx();
729+ jas_image_clearfmts_internal(ctx->image_fmtinfos, &ctx->image_numfmts);
730+}
731+
732+int jas_image_addfmt_internal(jas_image_fmtinfo_t *image_fmtinfos,
733+ size_t *image_numfmts, int id, const char *name, const char *ext,
734+ const char *desc, const jas_image_fmtops_t *ops)
735+{
736+ const char delim[] = " \t";
737+ int ret = 0;
738+ jas_image_fmtinfo_t *fmtinfo = 0;
739+
740+ assert(id >= 0 && name && ext && ops);
741+ if (*image_numfmts >= JAS_IMAGE_MAXFMTS) {
742+ ret = -1;
743+ goto done;
677744 }
678− if (!(newcmpt = jas_image_cmpt_create(cmptparm->tlx,
679− cmptparm->tly, cmptparm->hstep, cmptparm->vstep,
680− cmptparm->width, cmptparm->height, cmptparm->prec,
681− cmptparm->sgnd))) {
682− return -1;
745+ fmtinfo = &image_fmtinfos[*image_numfmts];
746+ jas_image_fmtinfo_init(fmtinfo);
747+ fmtinfo->id = id;
748+ if (jas_stringtokenize(ext, delim, &fmtinfo->exts, &fmtinfo->max_exts,
749+ &fmtinfo->num_exts)) {
750+ assert(!fmtinfo->exts && !fmtinfo->max_exts && !fmtinfo->num_exts);
751+ ret = -1;
752+ goto done;
753+ }
754+ assert(fmtinfo->num_exts > 0);
755+ char *primary_ext = fmtinfo->exts[0];
756+ if (!(fmtinfo->name = jas_strdup(name))) {
757+ ret = -1;
758+ goto done;
759+ }
760+ if (!(fmtinfo->ext = jas_strdup(primary_ext))) {
761+ ret = -1;
762+ goto done;
763+ }
764+ if (!(fmtinfo->desc = jas_strdup(desc))) {
765+ ret = -1;
766+ goto done;
683767 }
684− if ((unsigned)cmptno < image->numcmpts_) {
685− memmove(&image->cmpts_[cmptno + 1], &image->cmpts_[cmptno],
686− (image->numcmpts_ - (unsigned)cmptno) * sizeof(jas_image_cmpt_t *));
768+ fmtinfo->ops = *ops;
769+ ++(*image_numfmts);
770+done:
771+ if (ret && fmtinfo) {
772+ jas_image_fmtinfo_cleanup(fmtinfo);
687773 }
688− image->cmpts_[cmptno] = newcmpt;
689− ++image->numcmpts_;
690−
691− jas_image_setbbox(image);
774+ return ret;
775+}
692776
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);
694783 }
695784
696785 /* This is for future consideration for addition to the library API. */
697786 #if 0
698−JAS_DLLEXPORT
787+JAS_EXPORT
699788 int jas_image_delfmt(int fmtid)
700789 {
701790 if (fmtid < 0 || fmtid >= JAS_CAST(int, jas_image_numfmts)) {
@@ -734,20 +823,21 @@ const char *jas_image_fmttostr(int fmt) · 32 unmodified lines
734823
735824 int jas_image_getfmt(jas_stream_t *in)
736825 {
826+ jas_ctx_t *ctx = jas_get_ctx();
737827 const jas_image_fmtinfo_t *fmtinfo;
738828
739829 /* Check for data in each of the supported formats. */
740830 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,
742832 ++fmtinfo) {
743− if (fmtinfo->ops.validate) {
833+ if (fmtinfo->enabled && fmtinfo->ops.validate) {
744834 /* 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);
746836 if (!(*fmtinfo->ops.validate)(in)) {
747− JAS_DBGLOG(20, ("test succeeded\n"));
837+ JAS_LOGDEBUGF(20, "test succeeded\n");
748838 return fmtinfo->id;
749839 }
750− JAS_DBGLOG(20, ("test failed\n"));
840+ JAS_LOGDEBUGF(20, "test failed\n");
751841 }
752842 }
753843 return -1;
@@ -755,6 +845,7 @@ int jas_image_getfmt(jas_stream_t *in) · 1 unmodified line
755845
756846 int jas_image_fmtfromname(const char *name)
757847 {
848+ jas_ctx_t *ctx = jas_get_ctx();
758849 const char *ext;
759850 const jas_image_fmtinfo_t *fmtinfo;
760851 /* Get the file name extension. */
@@ -764,10 +855,10 @@ int jas_image_fmtfromname(const char *name) · 3 unmodified lines
764855 ++ext;
765856 /* Try to find a format that uses this extension. */
766857 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,
768859 ++fmtinfo) {
769860 /* Do we have a match? */
770− if (!strcmp(ext, fmtinfo->ext)) {
861+ if (fmtinfo->enabled && !strcmp(ext, fmtinfo->ext)) {
771862 return fmtinfo->id;
772863 }
773864 }
@@ -824,12 +915,45 @@ void jas_image_delcmpt(jas_image_t *image, unsigned cmptno) · 50 unmodified lines
824915 jas_image_setbbox(image);
825916 }
826917
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+
827949 const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id)
828950 {
951+ jas_ctx_t *ctx = jas_get_ctx();
829952 unsigned i;
830953 const jas_image_fmtinfo_t *fmtinfo;
831954
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) {
833957 if (fmtinfo->id == id) {
834958 return fmtinfo;
835959 }
@@ -839,10 +963,11 @@ const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id) · 3 unmodified lines
839963
840964 const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name)
841965 {
966+ jas_ctx_t *ctx = jas_get_ctx();
842967 unsigned i;
843968 const jas_image_fmtinfo_t *fmtinfo;
844−
845− for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) {
969+ for (i = 0, fmtinfo = ctx->image_fmtinfos; i < ctx->image_numfmts;
970+ ++i, ++fmtinfo) {
846971 if (!strcmp(fmtinfo->name, name)) {
847972 return fmtinfo;
848973 }
@@ -853,7 +978,9 @@ const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name) · 4 unmodified lines
853978 static uint_fast32_t inttobits(jas_seqent_t v, unsigned prec, bool sgnd)
854979 {
855980 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);
857984 return ret;
858985 }
859986
@@ -945,8 +1072,39 @@ int jas_image_copycmpt(jas_image_t *dstimage, unsigned dstcmptno, · 85 unmodified lines
9451072 return 0;
9461073 }
9471074
948−int jas_image_depalettize(jas_image_t *image, unsigned cmptno, unsigned numlutents,
949− const int_fast32_t *lutents, unsigned dtype, unsigned newcmptno)
1075+int jas_image_dump(jas_image_t *image, FILE *out)
1076+{
1077+ long buf[1024];
1078+ jas_image_cmpt_t *cmpt;
1079+ for (unsigned cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
1080+ cmpt = image->cmpts_[cmptno];
1081+ fprintf(out, "prec=%d, sgnd=%d, cmpttype=%"PRIiFAST32"\n", cmpt->prec_,
1082+ cmpt->sgnd_, cmpt->type_);
1083+ const unsigned width = jas_image_cmptwidth(image, cmptno);
1084+ const unsigned height = jas_image_cmptheight(image, cmptno);
1085+ const unsigned n = JAS_MIN(16, width);
1086+ if (jas_image_readcmpt2(image, cmptno, 0, 0, n, 1, buf)) {
1087+ return -1;
1088+ }
1089+ for (unsigned i = 0; i < n; ++i) {
1090+ fprintf(out, " f(%d,%d)=%ld", i, 0, buf[i]);
1091+ }
1092+ fprintf(out, "\n");
1093+ if (jas_image_readcmpt2(image, cmptno, width - n, height - 1, n, 1,
1094+ buf)) {
1095+ return -1;
1096+ }
1097+ for (unsigned i = 0; i < n; ++i) {
1098+ fprintf(out, " f(%d,%d)=%ld", width - n + i, height - 1, buf[i]);
1099+ }
1100+ fprintf(out, "\n");
1101+ }
1102+ return 0;
1103+}
1104+
1105+int jas_image_depalettize(jas_image_t *image, unsigned cmptno,
1106+ unsigned numlutents, const int_fast32_t *lutents, unsigned dtype,
1107+ unsigned newcmptno)
9501108 {
9511109 jas_image_cmptparm_t cmptparms;
9521110 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
9941152
9951153 cmpt = image->cmpts_[cmptno];
9961154
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) {
9981157 return -1;
9991158 }
10001159 v = 0;
@@ -1016,7 +1175,8 @@ void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno, unsigned x, · 15 unmodified lines
10161175
10171176 cmpt = image->cmpts_[cmptno];
10181177
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) {
10201180 return;
10211181 }
10221182 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
10291189 }
10301190 }
10311191
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)
10331194 {
10341195 for (unsigned cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
10351196 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
10391200 return -1;
10401201 }
10411202
1042−
1043−
1044−
1045−
1046−
1047−
1048−
1049−
1050−
1051−
1052−
1053−
1054−
1055−
1056−
10571203 /***********************************************/
10581204 /***********************************************/
10591205 /***********************************************/
10601206 /***********************************************/
10611207
1062−int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, jas_image_coord_t x,
1063− jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
1064− long *buf)
1208+int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno,
1209+ jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width,
1210+ jas_image_coord_t height, long *buf)
10651211 {
10661212 jas_image_cmpt_t *cmpt;
10671213 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
10691215 long v;
10701216 long *bufptr;
10711217
1072− if (cmptno >= image->numcmpts_)
1218+ if (cmptno >= image->numcmpts_) {
10731219 goto error;
1220+ }
10741221 cmpt = image->cmpts_[cmptno];
10751222 if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ ||
10761223 width < 0 || height < 0 || x + width > cmpt->width_ ||
1077− y + height > cmpt->height_)
1224+ y + height > cmpt->height_) {
10781225 goto error;
1226+ }
10791227
10801228 bufptr = buf;
10811229 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) {
10831232 goto error;
1233+ }
10841234 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)) {
10861236 goto error;
1237+ }
10871238 *bufptr++ = v;
10881239 }
10891240 }
@@ -1093,31 +1244,36 @@ error: · 3 unmodified lines
10931244 return -1;
10941245 }
10951246
1096−int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, jas_image_coord_t x,
1097− jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
1098− const long *buf)
1247+int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno,
1248+ jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width,
1249+ jas_image_coord_t height, const long *buf)
10991250 {
11001251 jas_image_cmpt_t *cmpt;
11011252 jas_image_coord_t i;
11021253 jas_image_coord_t j;
11031254 long v;
11041255
1105− if (cmptno >= image->numcmpts_)
1256+ if (cmptno >= image->numcmpts_) {
11061257 goto error;
1258+ }
11071259 cmpt = image->cmpts_[cmptno];
11081260 if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ ||
11091261 width < 0 || height < 0 || x + width > cmpt->width_ ||
1110− y + height > cmpt->height_)
1262+ y + height > cmpt->height_) {
11111263 goto error;
1264+ }
11121265
11131266 const long *bufptr = buf;
11141267 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) {
11161270 goto error;
1271+ }
11171272 for (j = 0; j < width; ++j) {
11181273 v = *bufptr++;
1119− if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v))
1274+ if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v)) {
11201275 goto error;
1276+ }
11211277 }
11221278 }
11231279
@@ -1165,10 +1321,11 @@ int jas_image_sampcmpt(jas_image_t *image, unsigned cmptno, unsigned newcmptno, · 41 unmodified lines
11651321 cmptparm.height = height;
11661322 cmptparm.prec = prec;
11671323 cmptparm.sgnd = sgnd;
1168− if (jas_image_addcmpt(image, newcmptno, &cmptparm))
1324+ if (jas_image_addcmpt(image, newcmptno, &cmptparm)) {
11691325 goto error;
1170−cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_;
1171−cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_;
1326+ }
1327+ cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_;
1328+ cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_;
11721329 const jas_image_cmpt_t *const newcmpt = image->cmpts_[newcmptno];
11731330 jas_stream_rewind(newcmpt->stream_);
11741331 for (unsigned i = 0; i < height; ++i) {
@@ -1178,11 +1335,13 @@ cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; · 3 unmodified lines
11781335 ax = downtomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_;
11791336 ay = downtomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_;
11801337 bx = uptomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_;
1181− if (bx > cmptbrx)
1338+ if (bx > cmptbrx) {
11821339 bx = cmptbrx;
1340+ }
11831341 by = uptomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_;
1184− if (by > cmptbry)
1342+ if (by > cmptbry) {
11851343 by = cmptbry;
1344+ }
11861345 d0 = (ax - x) * (ax - x) + (ay - y) * (ay - y);
11871346 d1 = (bx - x) * (bx - x) + (ay - y) * (ay - y);
11881347 d2 = (bx - x) * (bx - x) + (by - y) * (by - y);
@@ -1202,19 +1361,23 @@ cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; · 13 unmodified lines
12021361 }
12031362 assert(oldx >= 0 && oldx < oldcmpt->width_ &&
12041363 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) {
12061366 goto error;
1367+ }
12071368 if (getint(oldcmpt->stream_, oldcmpt->sgnd_,
1208− oldcmpt->prec_, &v))
1369+ oldcmpt->prec_, &v)) {
12091370 goto error;
1371+ }
12101372 if (newcmpt->prec_ != oldcmpt->prec_ ||
12111373 newcmpt->sgnd_ != oldcmpt->sgnd_) {
12121374 v = convert(v, oldcmpt->sgnd_, oldcmpt->prec_,
12131375 newcmpt->sgnd_, newcmpt->prec_);
12141376 }
12151377 if (putint(newcmpt->stream_, newcmpt->sgnd_,
1216− newcmpt->prec_, v))
1378+ newcmpt->prec_, v)) {
12171379 goto error;
1380+ }
12181381 }
12191382 }
12201383 return 0;
@@ -1241,8 +1404,9 @@ int jas_image_ishomosamp(const jas_image_t *image) · 20 unmodified lines
12411404 }
12421405
12431406 /* Note: This function defines a bounding box differently. */
1244−static void jas_image_calcbbox2(const jas_image_t *image, jas_image_coord_t *tlx,
1245− jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry)
1407+static void jas_image_calcbbox2(const jas_image_t *image,
1408+ jas_image_coord_t *tlx, jas_image_coord_t *tly, jas_image_coord_t *brx,
1409+ jas_image_coord_t *bry)
12461410 {
12471411 jas_image_coord_t tmptlx;
12481412 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
12571421 tmpbry = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1);
12581422 for (unsigned i = 0; i < image->numcmpts_; ++i) {
12591423 cmpt = image->cmpts_[i];
1260− if (cmpt->tlx_ < tmptlx)
1424+ if (cmpt->tlx_ < tmptlx) {
12611425 tmptlx = cmpt->tlx_;
1262− if (cmpt->tly_ < tmptly)
1426+ }
1427+ if (cmpt->tly_ < tmptly) {
12631428 tmptly = cmpt->tly_;
1429+ }
12641430 t = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1);
1265− if (t > tmpbrx)
1431+ if (t > tmpbrx) {
12661432 tmpbrx = t;
1433+ }
12671434 t = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1);
1268− if (t > tmpbry)
1435+ if (t > tmpbry) {
12691436 tmpbry = t;
1437+ }
12701438 }
12711439 } else {
12721440 tmptlx = 0;
@@ -1285,7 +1453,7 @@ static inline long decode_twos_comp(jas_ulong c, unsigned prec) · 12 unmodified lines
12851453 {
12861454 long result;
12871455 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");
12891457 // NOTE: Is this correct?
12901458 result = (c & ((1 << (prec - 1)) - 1)) - (c & (1 << (prec - 1)));
12911459 return result;
@@ -1296,7 +1464,7 @@ static inline jas_ulong encode_twos_comp(long n, unsigned prec) · 4 unmodified lines
12961464 {
12971465 jas_ulong result;
12981466 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");
13001468 // NOTE: Is this correct?
13011469 if (n < 0) {
13021470 result = -n;
@@ -1315,8 +1483,9 @@ static int getint(jas_stream_t *in, bool sgnd, unsigned prec, long *val) · 12 unmodified lines
13151483 assert((!sgnd && prec >= 1) || (sgnd && prec >= 2));
13161484 v = 0;
13171485 for (unsigned n = (prec + 7) / 8; n-- > 0;) {
1318− if ((c = jas_stream_getc(in)) == EOF)
1486+ if ((c = jas_stream_getc(in)) == EOF) {
13191487 return -1;
1488+ }
13201489 v = (v << 8) | c;
13211490 }
13221491 v &= ((1 << prec) - 1);
@@ -1339,8 +1508,9 @@ static int putint(jas_stream_t *out, bool sgnd, unsigned prec, long val) · 16 unmodified lines
13391508 val &= (1 << prec) - 1;
13401509 for (unsigned n = (prec + 7) / 8; n-- > 0;) {
13411510 c = (val >> (n * 8)) & 0xff;
1342− if (jas_stream_putc(out, c) != c)
1511+ if (jas_stream_putc(out, c) != c) {
13431512 return -1;
1513+ }
13441514 }
13451515 return 0;
13461516 }
@@ -1348,6 +1518,7 @@ static int putint(jas_stream_t *out, bool sgnd, unsigned prec, long val) · 1 unmodified line
13481518 static long convert(long val, bool oldsgnd, unsigned oldprec, bool newsgnd,
13491519 unsigned newprec)
13501520 {
1521+ /* TODO: The following code looks suspicious (i.e., an empty if body). */
13511522 if (newsgnd != oldsgnd) {
13521523 }
13531524 if (newprec != oldprec) {
@@ -1372,8 +1543,8 @@ static long uptomult(long x, long y) · 18 unmodified lines
13721543 return ((x + y - 1) / y) * y;
13731544 }
13741545
1375−jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof,
1376− jas_cmxform_intent_t intent)
1546+jas_image_t *jas_image_chclrspc(jas_image_t *image,
1547+ const jas_cmprof_t *outprof, jas_cmxform_intent_t intent)
13771548 {
13781549 jas_image_t *inimage;
13791550 int k;
@@ -1387,16 +1558,25 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 7 unmodified lines
13871558 jas_cmcmptfmt_t *incmptfmts;
13881559 jas_cmcmptfmt_t *outcmptfmts;
13891560
1390− if (image->numcmpts_ == 0)
1391− /* can't work with a file with no components;
1392− continuing would crash because we'd attempt to
1393− obtain information about the first component */
1394− return NULL;
1561+#if 0
1562+ jas_eprintf("IMAGE\n");
1563+ jas_image_dump(image, stderr);
1564+#endif
1565+
1566+ if (image->numcmpts_ == 0) {
1567+ /*
1568+ can't work with a file with no components;
1569+ continuing would crash because we'd attempt to
1570+ obtain information about the first component
1571+ */
1572+ return 0;
1573+ }
13951574
13961575 outimage = 0;
13971576 xform = 0;
1398− if (!(inimage = jas_image_copy(image)))
1577+ if (!(inimage = jas_image_copy(image))) {
13991578 goto error;
1579+ }
14001580
14011581 if (!jas_image_ishomosamp(inimage)) {
14021582 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
14141594 unsigned n = jas_image_numcmpts(inimage);
14151595 for (unsigned i = 0; i < n; ++i) {
14161596 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))) {
14181599 goto error;
14191600 }
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);
14211603 jas_image_setcmpttype(inimage, i + 1, cmpttype);
14221604 jas_image_delcmpt(inimage, i);
14231605 }
@@ -1429,10 +1611,13 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 5 unmodified lines
14291611 const unsigned vstep = jas_image_cmptvstep(inimage, 0);
14301612
14311613 if (!(inprof = jas_image_cmprof(inimage))) {
1432− abort();
1614+ // formerly call to abort()
1615+ goto error;
14331616 }
1434− const unsigned numinclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(inprof));
1435− const unsigned numoutclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(outprof));
1617+ const unsigned numinclrchans =
1618+ jas_clrspc_numchans(jas_cmprof_clrspc(inprof));
1619+ const unsigned numoutclrchans =
1620+ jas_clrspc_numchans(jas_cmprof_clrspc(outprof));
14361621 const unsigned prec = 8;
14371622
14381623 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
14491634 cmptparm.height = height;
14501635 cmptparm.prec = prec;
14511636 cmptparm.sgnd = 0;
1452− if (jas_image_addcmpt(outimage, -1, &cmptparm))
1637+ if (jas_image_addcmpt(outimage, -1, &cmptparm)) {
14531638 goto error;
1639+ }
14541640 jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i));
14551641 }
14561642 #if 0
@@ -1463,8 +1649,9 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 6 unmodified lines
14631649 }
14641650 #endif
14651651
1466− if (!(tmpprof = jas_cmprof_copy(outprof)))
1652+ if (!(tmpprof = jas_cmprof_copy(outprof))) {
14671653 goto error;
1654+ }
14681655 assert(!jas_image_cmprof(outimage));
14691656 jas_image_setcmprof(outimage, tmpprof);
14701657 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
14761663
14771664 inpixmap.numcmpts = numinclrchans;
14781665 if (!(incmptfmts = jas_alloc2(numinclrchans, sizeof(jas_cmcmptfmt_t)))) {
1479− abort();
1666+ // formerly call to abort()
1667+ goto error;
14801668 }
14811669 inpixmap.cmptfmts = incmptfmts;
14821670 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
14921680
14931681 outpixmap.numcmpts = numoutclrchans;
14941682 if (!(outcmptfmts = jas_alloc2(numoutclrchans, sizeof(jas_cmcmptfmt_t)))) {
1495− abort();
1683+ // formerly call to abort()
1684+ goto error;
14961685 }
14971686 outpixmap.cmptfmts = outcmptfmts;
14981687
14991688 for (unsigned i = 0; i < numoutclrchans; ++i) {
15001689 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)))) {
15021691 goto error;
1692+ }
15031693 outcmptfmts[i].prec = jas_image_cmptprec(outimage, j);
15041694 outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j);
15051695 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
15101700 for (unsigned j = 0; j < numinclrchans; ++j) {
15111701 k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j));
15121702 if (jas_image_readcmpt2(inimage, k, 0, i, width, 1,
1513− incmptfmts[j].buf))
1703+ incmptfmts[j].buf)) {
15141704 goto error;
1705+ }
15151706 }
15161707 jas_cmxform_apply(xform, &inpixmap, &outpixmap);
15171708 for (unsigned j = 0; j < numoutclrchans; ++j) {
15181709 k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j));
15191710 if (jas_image_writecmpt2(outimage, k, 0, i, width, 1,
1520− outcmptfmts[j].buf))
1711+ outcmptfmts[j].buf)) {
15211712 goto error;
1713+ }
15221714 }
15231715 }
15241716
@@ -1533,13 +1725,22 @@ jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof, · 8 unmodified lines
15331725 jas_cmxform_destroy(xform);
15341726 jas_image_destroy(inimage);
15351727
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
15361734 return outimage;
15371735 error:
1538− if (xform)
1736+ if (xform) {
15391737 jas_cmxform_destroy(xform);
1540− if (inimage)
1738+ }
1739+ if (inimage) {
15411740 jas_image_destroy(inimage);
1542− if (outimage)
1741+ }
1742+ if (outimage) {
15431743 jas_image_destroy(outimage);
1744+ }
15441745 return 0;
15451746 }
jas_init.c+949−23
@@ -63,45 +63,971 @@ · 62 unmodified lines
6363 * Includes.
6464 \******************************************************************************/
6565
66+#define JAS_FOR_INTERNAL_USE_ONLY
67+
6668 #include "jasper/jas_init.h"
6769 #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+}
68824
69825 /******************************************************************************\
70826 * Code.
71827 \******************************************************************************/
72828
73829 /* Initialize the image format table. */
74−JAS_DLLEXPORT
75−int jas_init(void)
830+static int jas_init_codecs(jas_ctx_t *ctx)
76831 {
77− jas_image_fmtops_t fmtops;
78− int fmtid = 0;
832+ int ret = 0;
833+ int i;
834+ const jas_image_fmt_t *fmt;
835+ for (fmt = jas_global.conf.image_formats, i = 0;
836+ i < jas_global.conf.num_image_formats; ++fmt, ++i) {
837+ JAS_LOGDEBUGF(10, "adding image format %s %s\n", fmt->name, fmt->exts);
838+ if (jas_image_addfmt_internal(ctx->image_fmtinfos, &ctx->image_numfmts,
839+ i, fmt->name, fmt->exts, fmt->desc, &fmt->ops)) {
840+ ret = -1;
841+ break;
842+ }
843+ assert(ctx->image_fmtinfos[i].id == i);
844+ ctx->image_fmtinfos[i].enabled = fmt->enabled;
845+ }
846+ if (ret) {
847+ jas_image_clearfmts_internal(ctx->image_fmtinfos, &ctx->image_numfmts);
848+ }
849+ return ret;
850+}
79851
80−#if defined(JAS_INCLUDE_JP2_CODEC)
81− fmtops.decode = jp2_decode;
82− fmtops.validate = jp2_validate;
83− jas_image_addfmt(fmtid++, "jp2", "jp2",
84− "JPEG-2000 JP2 File Format Syntax (ISO/IEC 15444-1)", &fmtops);
852+/******************************************************************************\
853+* Context management (e.g., creation and destruction).
854+\******************************************************************************/
855+
856+void jas_ctx_init(jas_ctx_t *ctx)
857+{
858+ ctx->dec_default_max_samples = jas_conf.dec_default_max_samples;
859+ ctx->debug_level = jas_conf.debug_level;
860+ ctx->vlogmsgf = jas_conf.vlogmsgf;
861+ ctx->image_numfmts = 0;
862+ memset(ctx->image_fmtinfos, 0, sizeof(ctx->image_fmtinfos));
863+}
864+
865+jas_ctx_t *jas_ctx_create()
866+{
867+ jas_ctx_t *ctx;
868+ if (!(ctx = jas_malloc(sizeof(jas_ctx_t)))) {
869+ return 0;
870+ }
871+ jas_ctx_init(ctx);
872+ jas_init_codecs(ctx);
873+ return ctx;
874+}
875+
876+JAS_EXPORT
877+jas_context_t jas_context_create()
878+{
879+ return JAS_CAST(jas_context_t, jas_ctx_create());
880+}
881+
882+void jas_ctx_cleanup(jas_ctx_t *ctx)
883+{
884+ jas_image_clearfmts_internal(ctx->image_fmtinfos, &ctx->image_numfmts);
885+}
886+
887+void jas_ctx_destroy(jas_ctx_t *ctx)
888+{
889+ jas_ctx_cleanup(ctx);
890+ jas_free(ctx);
891+}
892+
893+JAS_EXPORT
894+void jas_context_destroy(jas_context_t context)
895+{
896+ jas_ctx_destroy(JAS_CAST(jas_ctx_t *, context));
897+}
898+
899+jas_ctx_t *jas_get_ctx_internal()
900+{
901+#if defined(JAS_THREADS)
902+ jas_ctx_t *ctx;
903+#if defined(JAS_HAVE_THREAD_LOCAL)
904+ ctx = JAS_CAST(jas_ctx_t *, jas_cur_ctx);
905+#else
906+ ctx = JAS_CAST(jas_ctx_t *, jas_tss_get(jas_global.cur_ctx_tss));
85907 #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+}
86917
87−#if defined(JAS_INCLUDE_JPC_CODEC) || defined(JAS_INCLUDE_JP2_CODEC)
88− fmtops.decode = jpc_decode;
89− fmtops.validate = jpc_validate;
90− jas_image_addfmt(fmtid, "jpc", "jpc",
91− "JPEG-2000 Code Stream Syntax (ISO/IEC 15444-1)", &fmtops);
918+JAS_EXPORT
919+jas_context_t jas_get_context()
920+{
921+ return JAS_CAST(jas_context_t, jas_get_ctx());
922+}
923+
924+JAS_EXPORT
925+jas_context_t jas_get_default_context()
926+{
927+ return JAS_CAST(jas_context_t, jas_get_default_ctx());
928+}
929+
930+JAS_EXPORT
931+void jas_set_context(jas_context_t context)
932+{
933+ jas_set_ctx(JAS_CAST(jas_ctx_t *, context));
934+}
935+
936+void jas_set_ctx(jas_ctx_t *ctx)
937+{
938+#if defined(JAS_THREADS)
939+#if defined(JAS_HAVE_THREAD_LOCAL)
940+ jas_cur_ctx = ctx;
941+#else
942+ if (jas_tss_set(jas_global.cur_ctx_tss, ctx)) {
943+ assert(0);
944+ abort();
945+ }
946+#endif
947+#else
948+ jas_global.ctx = JAS_CAST(jas_ctx_t *, ctx);
92949 #endif
950+}
93951
94− /* We must not register the JasPer library exit handler until after
95− at least one memory allocation is performed. This is desirable
96− as it ensures that the JasPer exit handler is called before the
97− debug memory allocator exit handler. */
98− atexit(jas_cleanup);
952+jas_ctx_t *jas_get_default_ctx()
953+{
954+ jas_ctx_t *ctx;
99955
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;
1011026 }
1021027
103−JAS_DLLEXPORT
104−void jas_cleanup(void)
1028+JAS_EXPORT
1029+jas_vlogmsgf_t *jas_get_vlogmsgf_internal(void)
1051030 {
106− jas_image_clearfmts();
1031+ jas_ctx_t *ctx = jas_get_ctx();
1032+ return ctx->vlogmsgf;
1071033 }
jas_malloc.c+651−0
@@ -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+}
jas_seq.c+9−7
@@ -71,9 +71,12 @@ · 70 unmodified lines
7171 * Includes.
7272 \******************************************************************************/
7373
74+#define JAS_FOR_INTERNAL_USE_ONLY
75+
7476 #include "jasper/jas_seq.h"
7577 #include "jasper/jas_malloc.h"
7678 #include "jasper/jas_math.h"
79+#include "jasper/jas_debug.h"
7780
7881 /******************************************************************************\
7982 * Constructors and destructors.
@@ -100,6 +103,7 @@ jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols) · 20 unmodified lines
100103 jas_matind_t i;
101104 size_t size;
102105
106+
103107 if (numrows < 0 || numcols < 0) {
104108 return NULL;
105109 }
@@ -132,9 +136,7 @@ jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols) · 26 unmodified lines
132136 sizeof(jas_seqent_t)))) {
133137 goto error;
134138 }
135−
136− memset(matrix->data_, 0,
137− matrix->datasize_ * sizeof(jas_seqent_t));
139+ memset(matrix->data_, 0, matrix->datasize_ * sizeof(jas_seqent_t));
138140 }
139141
140142 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
201203 jas_matind_t ystart, jas_matind_t xend, jas_matind_t yend)
202204 {
203205 if (xstart < s1->xstart_ || ystart < s1->ystart_ ||
204− xend > s1->xend_ || yend > s1->yend_)
206+ xend > s1->xend_ || yend > s1->yend_) {
205207 return -1;
206−
207− return jas_matrix_bindsub(s, s1, ystart - s1->ystart_, xstart - s1->xstart_,
208− yend - s1->ystart_ - 1, xend - s1->xstart_ - 1);
208+ }
209+ return jas_matrix_bindsub(s, s1, ystart - s1->ystart_,
210+ xstart - s1->xstart_, yend - s1->ystart_ - 1, xend - s1->xstart_ - 1);
209211 }
210212
211213 int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1,
jas_stream.c+413−157
@@ -71,12 +71,31 @@ · 70 unmodified lines
7171 * Includes.
7272 \******************************************************************************/
7373
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+
7483 #include "jasper/jas_stream.h"
7584 #include "jasper/jas_debug.h"
7685 #include "jasper/jas_types.h"
7786 #include "jasper/jas_malloc.h"
7887 #include "jasper/jas_math.h"
7988
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+
8099 /******************************************************************************\
81100 * Local function prototypes.
82101 \******************************************************************************/
@@ -87,13 +106,21 @@ static jas_stream_t *jas_stream_create(void); · 4 unmodified lines
87106 static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
88107 int bufsize);
89108
90−static int mem_read(jas_stream_obj_t *obj, char *buf, unsigned cnt);
91−static int mem_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt);
109+static ssize_t mem_read(jas_stream_obj_t *obj, char *buf, size_t cnt);
110+static ssize_t mem_write(jas_stream_obj_t *obj, const char *buf,
111+ size_t cnt);
92112 static long mem_seek(jas_stream_obj_t *obj, long offset, int origin);
93113 static int mem_close(jas_stream_obj_t *obj);
94114
95−static int file_read(jas_stream_obj_t *obj, char *buf, unsigned cnt);
96−static int file_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt);
115+static ssize_t sfile_read(jas_stream_obj_t *obj, char *buf, size_t cnt);
116+static ssize_t sfile_write(jas_stream_obj_t *obj, const char *buf,
117+ size_t cnt);
118+static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin);
119+static int sfile_close(jas_stream_obj_t *obj);
120+
121+static ssize_t file_read(jas_stream_obj_t *obj, char *buf, size_t cnt);
122+static ssize_t file_write(jas_stream_obj_t *obj, const char *buf,
123+ size_t cnt);
97124 static long file_seek(jas_stream_obj_t *obj, long offset, int origin);
98125 static int file_close(jas_stream_obj_t *obj);
99126
@@ -108,6 +135,13 @@ static const jas_stream_ops_t jas_stream_fileops = { · 8 unmodified lines
108135 file_close
109136 };
110137
138+static const jas_stream_ops_t jas_stream_sfileops = {
139+ sfile_read,
140+ sfile_write,
141+ sfile_seek,
142+ sfile_close
143+};
144+
111145 static const jas_stream_ops_t jas_stream_memops = {
112146 mem_read,
113147 mem_write,
@@ -142,17 +176,12 @@ static jas_stream_t *jas_stream_create() · 28 unmodified lines
142176 return stream;
143177 }
144178
145−/*
146−This function will eventually replace jas_stream_memopen.
147−For documentation of the interface for this function, see jas_stream.h.
148−*/
149−
150−jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize)
179+jas_stream_t *jas_stream_memopen(char *buf, size_t bufsize)
151180 {
152181 jas_stream_t *stream;
153182 jas_stream_memobj_t *obj;
154183
155− JAS_DBGLOG(100, ("jas_stream_memopen2(%p, %zu)\n", buf, bufsize));
184+ JAS_LOGDEBUGF(100, "jas_stream_memopen(%p, %zu)\n", buf, bufsize);
156185
157186 assert((buf && bufsize > 0) || (!buf));
158187
@@ -201,8 +230,8 @@ jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize) · 42 unmodified lines
201230 jas_stream_close(stream);
202231 return 0;
203232 }
204− JAS_DBGLOG(100, ("jas_stream_memopen2 buffer buf=%p myalloc=%d\n",
205− obj->buf_, obj->myalloc_));
233+ JAS_LOGDEBUGF(100, "jas_stream_memopen buffer buf=%p myalloc=%d\n",
234+ obj->buf_, obj->myalloc_);
206235
207236 if (bufsize > 0 && buf) {
208237 /* 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
218247 }
219248
220249 /*
221−NOTE:
222−The version of the function jas_stream_memopen only exists for backwards
223−compatibility.
224−Eventually, it should be replaced by jas_stream_memopen2.
225−In retrospect, it was a very poor choice to have specified the buffer
226−size parameter (bufsize) to have type int. On some machines, int may only
227−be a 16-bit integer. This precludes larger-sized buffer allocations, which
228−are needed in practice.
229−
230−If bufsize <= 0, the buffer is growable; otherwise, the buffer has a fixed
231−size of bufsize.
232−If buf is 0, the buffer is dynamically allocated with jas_malloc.
233−If buf is not 0 and bufsize <= 0 (which is not permitted in any
234−circumstances), bad things will happen (especially if the buf was not
235−allocated with jas_malloc).
250+This function is deprecated.
251+It will be removed eventually.
236252 */
237−jas_stream_t *jas_stream_memopen(char *buf, int bufsize)
253+jas_stream_t *jas_stream_memopen2(char *buf, size_t bufsize)
238254 {
239− char *new_buf;
240− size_t new_bufsize;
241−
242− JAS_DBGLOG(100, ("jas_stream_memopen(%p, %d)\n", buf, bufsize));
243− if (bufsize < 0 || (buf && bufsize <= 0)) {
244− jas_eprintf("Invalid use of jas_stream_memopen detected.\n");
245− return nil;
246− }
247− if (bufsize <= 0) {
248− new_bufsize = 0;
249− new_buf = 0;
250− } else {
251− new_bufsize = bufsize;
252− new_buf = buf;
253− }
254− return jas_stream_memopen2(new_buf, new_bufsize);
255+ jas_deprecated("jas_stream_memopen2 is deprecated\n");
256+ return jas_stream_memopen(buf, bufsize);
255257 }
256258
257259 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
260262 jas_stream_fileobj_t *obj;
261263 int openflags;
262264
263− JAS_DBGLOG(100, ("jas_stream_fopen(\"%s\", \"%s\")\n", filename, mode));
265+ JAS_LOGDEBUGF(100, "jas_stream_fopen(\"%s\", \"%s\")\n", filename, mode);
264266
265267 /* Allocate a stream object. */
266268 if (!(stream = jas_stream_create())) {
@@ -273,19 +275,25 @@ jas_stream_t *jas_stream_fopen(const char *filename, const char *mode) · 6 unmodified lines
273275 /* Determine the correct flags to use for opening the file. */
274276 if ((stream->openmode_ & JAS_STREAM_READ) &&
275277 (stream->openmode_ & JAS_STREAM_WRITE)) {
276− openflags = ORDWR;
278+ openflags = O_RDWR;
277279 } else if (stream->openmode_ & JAS_STREAM_READ) {
278− openflags = OREAD;
280+ openflags = O_RDONLY;
279281 } else if (stream->openmode_ & JAS_STREAM_WRITE) {
280− openflags = OWRITE;
282+ openflags = O_WRONLY;
281283 } else {
282284 openflags = 0;
283285 }
286+ if (stream->openmode_ & JAS_STREAM_APPEND) {
287+ openflags |= O_APPEND;
288+ }
289+ if (stream->openmode_ & JAS_STREAM_BINARY) {
290+ openflags |= O_BINARY;
291+ }
284292 if (stream->openmode_ & JAS_STREAM_CREATE) {
285− openflags |= OTRUNC;
293+ openflags |= O_CREAT | O_TRUNC;
286294 }
287295
288− openflags |= OCEXEC;
296+ openflags |= O_CLOEXEC;
289297
290298 /* Allocate space for the underlying file stream object. */
291299 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
294302 }
295303 obj->fd = -1;
296304 obj->flags = 0;
305+ obj->pathname[0] = '\0';
297306 stream->obj_ = (void *) obj;
298307
299308 /* Select the operations for a file stream object. */
300309 stream->ops_ = &jas_stream_fileops;
301310
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−
308311 /* Open the underlying file. */
309− if (obj->fd < 0) {
312+ if ((obj->fd = open(filename, openflags/*, JAS_STREAM_PERMS*/)) < 0) {
310313 // Free the underlying file object, since it will not otherwise
311314 // be freed.
312315 jas_free(obj);
313316 jas_stream_destroy(stream);
314317 return 0;
315318 }
316− if (stream->openmode_ & JAS_STREAM_APPEND) {
317− seek(obj->fd, 0, 2);
319+
320+ /* By default, use full buffering for this type of stream. */
321+ jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
322+
323+ return stream;
324+}
325+
326+jas_stream_t *jas_stream_freopen(const char *path, const char *mode, FILE *fp)
327+{
328+ jas_stream_t *stream;
329+
330+ JAS_LOGDEBUGF(100, "jas_stream_freopen(\"%s\", \"%s\", %p)\n", path, mode, fp);
331+
332+ JAS_UNUSED(path);
333+
334+ /* Allocate a stream object. */
335+ if (!(stream = jas_stream_create())) {
336+ return 0;
318337 }
319338
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+
320347 /* By default, use full buffering for this type of stream. */
321348 jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
322349
323350 return stream;
324351 }
325352
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+
326470 jas_stream_t *jas_stream_fdopen(int fd, const char *mode)
327471 {
328472 jas_stream_t *stream;
329473 jas_stream_fileobj_t *obj;
330474
331− JAS_DBGLOG(100, ("jas_stream_fdopen(%d, \"%s\")\n", fd, mode));
475+ JAS_LOGDEBUGF(100, "jas_stream_fdopen(%d, \"%s\")\n", fd, mode);
332476
333477 /* Allocate a stream object. */
334478 if (!(stream = jas_stream_create())) {
@@ -338,7 +482,7 @@ jas_stream_t *jas_stream_fdopen(int fd, const char *mode) · 3 unmodified lines
338482 /* Parse the mode string. */
339483 stream->openmode_ = jas_strtoopenmode(mode);
340484
341−#if defined(WIN32)
485+#if defined(_WIN32) || defined(JAS_HAVE_IO_H)
342486 /* Argh!!! Someone ought to banish text mode (i.e., O_TEXT) to the
343487 greatest depths of purgatory! */
344488 /* 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
362506 }
363507 obj->fd = fd;
364508 obj->flags = 0;
509+ obj->pathname[0] = '\0';
365510 stream->obj_ = (void *) obj;
366511
367512 /* 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
379524
380525 static void jas_stream_destroy(jas_stream_t *stream)
381526 {
382− JAS_DBGLOG(100, ("jas_stream_destroy(%p)\n", stream));
527+ JAS_LOGDEBUGF(100, "jas_stream_destroy(%p)\n", stream);
383528
384529 /* If the memory for the buffer was allocated with malloc, free
385530 this memory. */
386531 if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
387− JAS_DBGLOG(100, ("jas_stream_destroy freeing buffer %p\n",
388− stream->bufbase_));
532+ JAS_LOGDEBUGF(100, "jas_stream_destroy freeing buffer %p\n",
533+ stream->bufbase_);
389534 jas_free(stream->bufbase_);
390535 stream->bufbase_ = 0;
391536 }
@@ -394,7 +539,7 @@ static void jas_stream_destroy(jas_stream_t *stream) · 2 unmodified lines
394539
395540 int jas_stream_close(jas_stream_t *stream)
396541 {
397− JAS_DBGLOG(100, ("jas_stream_close(%p)\n", stream));
542+ JAS_LOGDEBUGF(100, "jas_stream_close(%p)\n", stream);
398543
399544 /* Flush buffer if necessary. */
400545 jas_stream_flush(stream);
@@ -451,16 +596,16 @@ int jas_stream_ungetc(jas_stream_t *stream, int c) · 50 unmodified lines
451596 return 0;
452597 }
453598
454−/* FIXME integral type */
455−unsigned jas_stream_read(jas_stream_t *stream, void *buf, unsigned cnt)
599+size_t jas_stream_read(jas_stream_t *stream, void *buf, size_t cnt)
456600 {
457601 int c;
458602 char *bufptr;
459603
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);
461605
462− if (cnt == 0)
606+ if (cnt == 0) {
463607 return 0;
608+ }
464609
465610 bufptr = buf;
466611
@@ -468,11 +613,13 @@ unsigned jas_stream_read(jas_stream_t *stream, void *buf, unsigned cnt) · 1 unmodified line
468613 jas_stream_is_input_buffer_empty(stream)) {
469614 /* fast path for unbuffered streams */
470615
471− if ((stream->flags_ & JAS_STREAM_ERRMASK) != 0)
616+ if ((stream->flags_ & JAS_STREAM_ERRMASK) != 0) {
472617 return 0;
618+ }
473619
474− if ((stream->openmode_ & JAS_STREAM_READ) == 0)
620+ if ((stream->openmode_ & JAS_STREAM_READ) == 0) {
475621 return 0;
622+ }
476623
477624 assert((stream->bufmode_ & JAS_STREAM_WRBUF) == 0);
478625
@@ -502,29 +649,32 @@ unsigned jas_stream_read(jas_stream_t *stream, void *buf, unsigned cnt) · 23 unmodified lines
502649 return n;
503650 }
504651
652+/* TODO: The return type should probably be changed to size_t. */
505653 unsigned jas_stream_peek(jas_stream_t *stream, void *buf, size_t cnt)
506654 {
507655 char *bufptr = buf;
508656
509− const unsigned n = jas_stream_read(stream, bufptr, cnt);
657+ const size_t n = jas_stream_read(stream, bufptr, cnt);
510658
511659 /* Put the characters read back onto the stream. */
512− for (unsigned i = n; i-- > 0;)
513− if (jas_stream_ungetc(stream, bufptr[i]) == EOF)
660+ for (size_t i = n; i-- > 0;) {
661+ if (jas_stream_ungetc(stream, bufptr[i]) == EOF) {
514662 return 0;
663+ }
664+ }
515665
516666 return n;
517667 }
518668
519−/* FIXME integral type */
520−unsigned jas_stream_write(jas_stream_t *stream, const void *buf, unsigned cnt)
669+size_t jas_stream_write(jas_stream_t *stream, const void *buf, size_t cnt)
521670 {
522671 const char *bufptr;
523672
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);
525674
526− if (cnt == 0)
675+ if (cnt == 0) {
527676 return 0;
677+ }
528678
529679 bufptr = buf;
530680
@@ -533,8 +683,9 @@ unsigned jas_stream_write(jas_stream_t *stream, const void *buf, unsigned cnt) · 2 unmodified lines
533683
534684 /* need to flush the output buffer before we do a raw
535685 write */
536− if (jas_stream_flushbuf(stream, EOF))
686+ if (jas_stream_flushbuf(stream, EOF)) {
537687 return 0;
688+ }
538689
539690 stream->bufmode_ |= JAS_STREAM_WRBUF;
540691
@@ -570,7 +721,7 @@ int jas_stream_printf(jas_stream_t *stream, const char *fmt, ...) · 29 unmodified lines
570721 int ret;
571722
572723 va_start(ap, fmt);
573− ret = vsnprint(buf, sizeof buf, fmt, ap);
724+ ret = vsnprintf(buf, sizeof buf, fmt, ap);
574725 jas_stream_puts(stream, buf);
575726 va_end(ap);
576727 return ret;
@@ -595,7 +746,7 @@ char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize) · 18 unmodified lines
595746 char *bufptr;
596747 assert(bufsize > 0);
597748
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);
599750
600751 bufptr = buf;
601752 while (bufsize > 1) {
@@ -612,17 +763,10 @@ char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize) · 10 unmodified lines
612763 return buf;
613764 }
614765
615−/* FIXME integral type */
616−int jas_stream_gobble(jas_stream_t *stream, int n)
766+ssize_t jas_stream_gobble(jas_stream_t *stream, size_t n)
617767 {
618− int m;
619−
620− JAS_DBGLOG(100, ("jas_stream_gobble(%p, %d)\n", stream, n));
621−
622− if (n < 0) {
623− jas_eprintf("negative count for jas_stream_gobble\n");
624− return 0;
625− }
768+ size_t m;
769+ JAS_LOGDEBUGF(100, "jas_stream_gobble(%p, %zu)\n", stream, n);
626770 for (m = n; m > 0; --m) {
627771 if (jas_stream_getc(stream) == EOF) {
628772 return n - m;
@@ -631,20 +775,14 @@ int jas_stream_gobble(jas_stream_t *stream, int n) · 2 unmodified lines
631775 return n;
632776 }
633777
634−/* FIXME integral type */
635−int jas_stream_pad(jas_stream_t *stream, int n, int c)
778+ssize_t jas_stream_pad(jas_stream_t *stream, size_t n, int c)
636779 {
637− int m;
638−
639− JAS_DBGLOG(100, ("jas_stream_pad(%p, %d, %d)\n", stream, n, c));
640−
641− if (n < 0) {
642− jas_eprintf("negative count for jas_stream_pad\n");
643− return 0;
644− }
780+ size_t m;
781+ JAS_LOGDEBUGF(100, "jas_stream_pad(%p, %zu, %d)\n", stream, n, c);
645782 for (m = n; m > 0; --m) {
646− if (jas_stream_putc(stream, c) == EOF)
783+ if (jas_stream_putc(stream, c) == EOF) {
647784 return n - m;
785+ }
648786 }
649787 return n;
650788 }
@@ -658,7 +796,7 @@ int jas_stream_isseekable(jas_stream_t *stream) · 7 unmodified lines
658796 if (stream->ops_ == &jas_stream_memops) {
659797 return 1;
660798 } 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) {
662800 return 0;
663801 }
664802 return 1;
@@ -669,16 +807,15 @@ int jas_stream_isseekable(jas_stream_t *stream) · 4 unmodified lines
669807
670808 int jas_stream_rewind(jas_stream_t *stream)
671809 {
672− JAS_DBGLOG(100, ("jas_stream_rewind(%p)\n", stream));
673− return jas_stream_seek(stream, 0, 0);
810+ JAS_LOGDEBUGF(100, "jas_stream_rewind(%p)\n", stream);
811+ return jas_stream_seek(stream, 0, SEEK_SET);
674812 }
675813
676814 long jas_stream_seek(jas_stream_t *stream, long offset, int origin)
677815 {
678816 long newpos;
679817
680− JAS_DBGLOG(100, ("jas_stream_seek(%p, %ld, %d)\n", stream, offset,
681− origin));
818+ JAS_LOGDEBUGF(100, "jas_stream_seek(%p, %ld, %d)\n", stream, offset, origin);
682819
683820 /* The buffer cannot be in use for both reading and writing. */
684821 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
688825 stream->flags_ &= ~JAS_STREAM_EOF;
689826
690827 if (stream->bufmode_ & JAS_STREAM_RDBUF) {
691− if (origin == 1) {
828+ if (origin == SEEK_CUR) {
692829 offset -= stream->cnt_;
693830 }
694831 } else if (stream->bufmode_ & JAS_STREAM_WRBUF) {
@@ -713,7 +850,7 @@ long jas_stream_tell(jas_stream_t *stream) · 18 unmodified lines
713850 int adjust;
714851 int offset;
715852
716− JAS_DBGLOG(100, ("jas_stream_tell(%p)\n", stream));
853+ JAS_LOGDEBUGF(100, "jas_stream_tell(%p)\n", stream);
717854
718855 if (stream->bufmode_ & JAS_STREAM_RDBUF) {
719856 adjust = -stream->cnt_;
@@ -723,7 +860,7 @@ long jas_stream_tell(jas_stream_t *stream) · 3 unmodified lines
723860 adjust = 0;
724861 }
725862
726− if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, 1)) < 0) {
863+ if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR)) < 0) {
727864 return -1;
728865 }
729866
@@ -910,10 +1047,9 @@ static int jas_strtoopenmode(const char *s) · 180 unmodified lines
9101047 return openmode;
9111048 }
9121049
913−/* FIXME integral type */
914−int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n)
1050+int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, ssize_t n)
9151051 {
916− int m;
1052+ ssize_t m;
9171053
9181054 const bool all = n < 0;
9191055
@@ -921,14 +1057,14 @@ int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n) · 1 unmodified line
9211057
9221058 m = n;
9231059 while (all || m > 0) {
924− unsigned nbytes = jas_stream_read(in, buffer,
925− JAS_MIN((size_t)m, sizeof(buffer)));
926− if (nbytes == 0)
1060+ size_t nbytes = jas_stream_read(in, buffer,
1061+ JAS_MIN((size_t)m, sizeof(buffer)));
1062+ if (nbytes == 0) {
9271063 return !all || jas_stream_error(in) ? -1 : 0;
928−
929− if (jas_stream_write(out, buffer, nbytes) != nbytes)
1064+ }
1065+ if (jas_stream_write(out, buffer, nbytes) != nbytes) {
9301066 return -1;
931−
1067+ }
9321068 m -= nbytes;
9331069 }
9341070
@@ -945,7 +1081,7 @@ long jas_stream_setrwcount(jas_stream_t *stream, long rwcnt) · 10 unmodified lines
9451081 return old;
9461082 }
9471083
948−JAS_DLLEXPORT
1084+JAS_EXPORT
9491085 long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit)
9501086 {
9511087 long old;
@@ -955,6 +1091,57 @@ long jas_stream_setrwlimit(jas_stream_t *stream, long rwlimit) · 3 unmodified lines
9551091 return old;
9561092 }
9571093
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+
9581145 long jas_stream_length(jas_stream_t *stream)
9591146 {
9601147 long oldpos;
@@ -962,13 +1149,13 @@ long jas_stream_length(jas_stream_t *stream) · 1 unmodified line
9621149 if ((oldpos = jas_stream_tell(stream)) < 0) {
9631150 return -1;
9641151 }
965− if (jas_stream_seek(stream, 0, 2) < 0) {
1152+ if (jas_stream_seek(stream, 0, SEEK_END) < 0) {
9661153 return -1;
9671154 }
9681155 if ((pos = jas_stream_tell(stream)) < 0) {
9691156 return -1;
9701157 }
971− if (jas_stream_seek(stream, oldpos, 0) < 0) {
1158+ if (jas_stream_seek(stream, oldpos, SEEK_SET) < 0) {
9721159 return -1;
9731160 }
9741161 return pos;
@@ -978,13 +1165,12 @@ long jas_stream_length(jas_stream_t *stream) · 3 unmodified lines
9781165 * Memory stream object.
9791166 \******************************************************************************/
9801167
981−/* FIXME integral type */
982−static int mem_read(jas_stream_obj_t *obj, char *buf, unsigned cnt)
1168+static ssize_t mem_read(jas_stream_obj_t *obj, char *buf, size_t cnt)
9831169 {
9841170 jas_stream_memobj_t *m;
9851171 assert(buf);
9861172
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);
9881174 m = (jas_stream_memobj_t *)obj;
9891175 size_t n = m->len_ - m->pos_;
9901176 cnt = JAS_MIN(n, cnt);
@@ -997,11 +1183,9 @@ static int mem_resize(jas_stream_memobj_t *m, size_t bufsize) · 6 unmodified lines
9971183 {
9981184 unsigned char *buf;
9991185
1000− //assert(m->buf_);
1001−
1002− JAS_DBGLOG(100, ("mem_resize(%p, %zu)\n", m, bufsize));
1186+ JAS_LOGDEBUGF(100, "mem_resize(%p, %zu)\n", m, bufsize);
10031187 if (!bufsize) {
1004− jas_eprintf(
1188+ jas_logerrorf(
10051189 "mem_resize was not really designed to handle a buffer of size 0\n"
10061190 "This may not work.\n"
10071191 );
@@ -1009,17 +1193,17 @@ static int mem_resize(jas_stream_memobj_t *m, size_t bufsize) · 1 unmodified line
10091193
10101194 if (!(buf = jas_realloc2(m->buf_, bufsize, sizeof(unsigned char))) &&
10111195 bufsize) {
1012− JAS_DBGLOG(100, ("mem_resize realloc failed\n"));
1196+ JAS_LOGDEBUGF(100, "mem_resize realloc failed\n");
10131197 return -1;
10141198 }
1015− JAS_DBGLOG(100, ("mem_resize realloc succeeded\n"));
1199+ JAS_LOGDEBUGF(100, "mem_resize realloc succeeded\n");
10161200 m->buf_ = buf;
10171201 m->bufsize_ = bufsize;
10181202 return 0;
10191203 }
10201204
1021−/* FIXME integral type */
1022−static int mem_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt)
1205+static ssize_t mem_write(jas_stream_obj_t *obj, const char *buf,
1206+ size_t cnt)
10231207 {
10241208 size_t n;
10251209 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
10281212
10291213 assert(buf);
10301214
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);
10321216 newpos = m->pos_ + cnt;
10331217 if (newpos > m->bufsize_ && m->growable_) {
10341218 newbufsize = m->bufsize_;
10351219 while (newbufsize < newpos) {
1036− //newbufsize <<= 1;
1220+ /* Attempt to double the buffer size. */
10371221 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");
10391223 return -1;
10401224 }
10411225 }
1042− JAS_DBGLOG(100, ("mem_write resizing from %d to %zu\n", m->bufsize_,
1043− newbufsize));
1226+ JAS_LOGDEBUGF(100, "mem_write resizing from %d to %zu\n", m->bufsize_,
1227+ newbufsize);
10441228 assert(newbufsize > 0);
10451229 if (mem_resize(m, newbufsize)) {
10461230 return -1;
@@ -1078,15 +1262,15 @@ static long mem_seek(jas_stream_obj_t *obj, long offset, int origin) · 31 unmodified lines
10781262 jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
10791263 long newpos;
10801264
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);
10821266 switch (origin) {
1083− case 0:
1267+ case SEEK_SET:
10841268 newpos = offset;
10851269 break;
1086− case 2:
1270+ case SEEK_END:
10871271 newpos = m->len_ - offset;
10881272 break;
1089− case 1:
1273+ case SEEK_CUR:
10901274 newpos = m->pos_ + offset;
10911275 break;
10921276 default:
@@ -1104,11 +1288,11 @@ static int mem_close(jas_stream_obj_t *obj) · 11 unmodified lines
11041288 {
11051289 jas_stream_memobj_t *m;
11061290
1107− JAS_DBGLOG(100, ("mem_close(%p)\n", obj));
1291+ JAS_LOGDEBUGF(100, "mem_close(%p)\n", obj);
11081292 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_);
11101294 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_);
11121296 jas_free(m->buf_);
11131297 m->buf_ = 0;
11141298 }
@@ -1120,20 +1304,19 @@ static int mem_close(jas_stream_obj_t *obj) · 5 unmodified lines
11201304 * File stream object.
11211305 \******************************************************************************/
11221306
1123−/* FIXME integral type */
1124−static int file_read(jas_stream_obj_t *obj, char *buf, unsigned cnt)
1307+static ssize_t file_read(jas_stream_obj_t *obj, char *buf, size_t cnt)
11251308 {
11261309 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);
11281311 fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
11291312 return read(fileobj->fd, buf, cnt);
11301313 }
11311314
1132−/* FIXME integral type */
1133−static int file_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt)
1315+static ssize_t file_write(jas_stream_obj_t *obj, const char *buf,
1316+ size_t cnt)
11341317 {
11351318 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);
11371320 fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
11381321 return write(fileobj->fd, buf, cnt);
11391322 }
@@ -1142,18 +1325,91 @@ static int file_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt) · 2 unmodified lines
11421325 static long file_seek(jas_stream_obj_t *obj, long offset, int origin)
11431326 {
11441327 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);
11461329 fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1147− return seek(fileobj->fd, offset, origin);
1330+ return lseek(fileobj->fd, offset, origin);
11481331 }
11491332
11501333 static int file_close(jas_stream_obj_t *obj)
11511334 {
1152− int ret;
1335+ int ret = 0;
11531336 jas_stream_fileobj_t *fileobj;
1154− JAS_DBGLOG(100, ("file_close(%p)\n", obj));
1337+ JAS_LOGDEBUGF(100, "file_close(%p)\n", obj);
11551338 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+ }
11571345 jas_free(fileobj);
11581346 return ret;
11591347 }
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+}
jas_string.c+216−0
@@ -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+}
jas_tvp.c+234−0
@@ -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+}
jas_version.c+69−0
@@ -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+}
jasper/jas_cm.h+249−21
@@ -67,18 +67,39 @@ · 66 unmodified lines
6767 #ifndef JAS_CM_H
6868 #define JAS_CM_H
6969
70+/******************************************************************************\
71+*
72+\******************************************************************************/
73+
7074 /* The configuration header file should be included first. */
7175 #include <jasper/jas_config.h>
7276
77+#include <jasper/jas_types.h>
7378 #include <jasper/jas_icc.h>
7479
7580 #ifdef __cplusplus
7681 extern "C" {
7782 #endif
7883
84+/*!
85+ * @addtogroup module_cm
86+ * @{
87+ */
88+
89+/******************************************************************************\
90+* Types and Macros.
91+\******************************************************************************/
92+
93+/*!
94+@brief
95+Color space.
96+*/
7997 typedef unsigned jas_clrspc_t;
8098
81−/* transform operations */
99+/*!
100+@brief
101+Transform operations
102+*/
82103 typedef enum {
83104 JAS_CMXFORM_OP_FWD = 0,
84105 JAS_CMXFORM_OP_REV = 1,
@@ -86,7 +107,10 @@ typedef enum { · 1 unmodified line
86107 JAS_CMXFORM_OP_GAMUT = 3,
87108 } jas_cmxform_op_t;
88109
89−/* rendering intents */
110+/*!
111+@brief
112+Rendering intents.
113+*/
90114 typedef enum {
91115 JAS_CMXFORM_INTENT_PER = 0,
92116 JAS_CMXFORM_INTENT_RELCLR = 1,
@@ -94,24 +118,58 @@ typedef enum { · 1 unmodified line
94118 JAS_CMXFORM_INTENT_SAT = 3,
95119 } jas_cmxform_intent_t;
96120
121+/*!
122+@brief
123+Number of rendering intents.
124+*/
97125 #define JAS_CMXFORM_NUMINTENTS 4
98126
127+/*!
128+@brief
129+Transform optimization.
130+*/
99131 typedef enum {
100132 JAS_CMXFORM_OPTM_SPEED = 0,
101133 JAS_CMXFORM_OPTM_SIZE = 1,
102134 JAS_CMXFORM_OPTM_ACC = 2,
103135 } jas_cmxform_optm_t;
104136
105−
137+/*!
138+@brief
139+Create a color space.
140+*/
106141 #define jas_clrspc_create(fam, mbr) (((fam) << 8) | (mbr))
142+
143+/*!
144+@brief
145+Get the family of a color space.
146+*/
147+
107148 #define jas_clrspc_fam(clrspc) ((clrspc) >> 8)
149+
150+/*!
151+@brief
152+Get the (family) member of a color space.
153+*/
108154 #define jas_clrspc_mbr(clrspc) ((clrspc) & 0xff)
155+
156+/*!
157+@brief
158+Test if a color space is generic.
159+*/
109160 #define jas_clrspc_isgeneric(clrspc) (!jas_clrspc_mbr(clrspc))
161+
162+/*!
163+@brief
164+Test if a color space is unknown.
165+*/
110166 #define jas_clrspc_isunknown(clrspc) ((clrspc) & JAS_CLRSPC_UNKNOWNMASK)
111167
112168 #define JAS_CLRSPC_UNKNOWNMASK 0x4000
113169
114−/* color space families */
170+/*!
171+@brief Color space families.
172+*/
115173 #define JAS_CLRSPC_FAM_UNKNOWN 0
116174 #define JAS_CLRSPC_FAM_XYZ 1
117175 #define JAS_CLRSPC_FAM_LAB 2
@@ -119,7 +177,9 @@ typedef enum { · 1 unmodified line
119177 #define JAS_CLRSPC_FAM_RGB 4
120178 #define JAS_CLRSPC_FAM_YCBCR 5
121179
122−/* specific color spaces */
180+/*!
181+@brief Specific color spaces.
182+*/
123183 #define JAS_CLRSPC_UNKNOWN JAS_CLRSPC_UNKNOWNMASK
124184 #define JAS_CLRSPC_CIEXYZ jas_clrspc_create(JAS_CLRSPC_FAM_XYZ, 1)
125185 #define JAS_CLRSPC_CIELAB jas_clrspc_create(JAS_CLRSPC_FAM_LAB, 1)
@@ -127,7 +187,9 @@ typedef enum { · 1 unmodified line
127187 #define JAS_CLRSPC_SRGB jas_clrspc_create(JAS_CLRSPC_FAM_RGB, 1)
128188 #define JAS_CLRSPC_SYCBCR jas_clrspc_create(JAS_CLRSPC_FAM_YCBCR, 1)
129189
130−/* generic color spaces */
190+/*!
191+@brief Generic color spaces.
192+*/
131193 #define JAS_CLRSPC_GENRGB jas_clrspc_create(JAS_CLRSPC_FAM_RGB, 0)
132194 #define JAS_CLRSPC_GENGRAY jas_clrspc_create(JAS_CLRSPC_FAM_GRAY, 0)
133195 #define JAS_CLRSPC_GENYCBCR jas_clrspc_create(JAS_CLRSPC_FAM_YCBCR, 0)
@@ -142,10 +204,17 @@ typedef enum { · 8 unmodified lines
142204
143205 #define JAS_CLRSPC_CHANIND_GRAY_Y 0
144206
207+/*!
208+Real-number type.
209+*/
145210 typedef double jas_cmreal_t;
146211
147212 struct jas_cmpxform_s;
148213
214+/*!
215+@brief
216+Component format.
217+*/
149218 typedef struct {
150219 long *buf;
151220 unsigned prec;
@@ -154,21 +223,38 @@ typedef struct { · 2 unmodified lines
154223 unsigned height;
155224 } jas_cmcmptfmt_t;
156225
226+/*!
227+@brief
228+Pixmap (i.e., multicomponent) format.
229+*/
157230 typedef struct {
158231 unsigned numcmpts;
159232 jas_cmcmptfmt_t *cmptfmts;
160233 } jas_cmpixmap_t;
161234
235+/*!
236+@brief
237+Transform operations.
238+*/
162239 typedef struct {
163240 void (*destroy)(struct jas_cmpxform_s *pxform);
164241 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);
165243 } jas_cmpxformops_t;
166244
245+/*!
246+@brief
247+Shaper matrix look-up table (LUT).
248+*/
167249 typedef struct {
168250 jas_cmreal_t *data;
169251 unsigned size;
170252 } jas_cmshapmatlut_t;
171253
254+/*!
255+@brief
256+Shaper matrix.
257+*/
172258 typedef struct {
173259 int mono;
174260 int order;
@@ -178,36 +264,54 @@ typedef struct { · 3 unmodified lines
178264 jas_cmreal_t mat[3][4];
179265 } jas_cmshapmat_t;
180266
267+/*!
268+@brief
269+Shaper look-up table (LUT).
270+*/
181271 typedef struct {
182272 int order;
183273 } jas_cmshaplut_t;
184274
275+/*!
276+@brief
277+Color space conversion.
278+*/
185279 typedef struct {
186280 unsigned inclrspc;
187281 unsigned outclrspc;
188282 } jas_cmclrspcconv_t;
189283
190−#define jas_align_t double
191−
284+/*!
285+@brief
286+Transform class.
287+*/
192288 typedef struct jas_cmpxform_s {
193289 unsigned refcnt;
194290 const jas_cmpxformops_t *ops;
195291 unsigned numinchans;
196292 unsigned numoutchans;
197293 union {
198− jas_align_t dummy;
294+ max_align_t dummy;
199295 jas_cmshapmat_t shapmat;
200296 jas_cmshaplut_t shaplut;
201297 jas_cmclrspcconv_t clrspcconv;
202298 } data;
203299 } jas_cmpxform_t;
204300
301+/*!
302+@brief
303+Primitive transform sequence class.
304+*/
205305 typedef struct {
206306 unsigned numpxforms;
207307 unsigned maxpxforms;
208308 jas_cmpxform_t **pxforms;
209309 } jas_cmpxformseq_t;
210310
311+/*!
312+@brief
313+Primitive transform class.
314+*/
211315 typedef struct {
212316 unsigned numinchans;
213317 unsigned numoutchans;
@@ -219,6 +323,9 @@ typedef struct { · 5 unmodified lines
219323
220324 #define JAS_CMPROF_NUMPXFORMSEQS 13
221325
326+/*!
327+Color-management (CM) profile.
328+*/
222329 typedef struct {
223330 jas_clrspc_t clrspc;
224331 unsigned numchans;
@@ -228,6 +335,10 @@ typedef struct { · 3 unmodified lines
228335 jas_cmpxformseq_t *pxformseqs[JAS_CMPROF_NUMPXFORMSEQS];
229336 } jas_cmprof_t;
230337
338+/******************************************************************************\
339+*
340+\******************************************************************************/
341+
231342 #if 0
232343 typedef int_fast32_t jas_cmattrname_t;
233344 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
242353 void *jas_cm_prof_getattr(jas_cm_prof_t *prof, jas_cm_attrname_t name);
243354 #endif
244355
245−JAS_DLLEXPORT jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof, const jas_cmprof_t *outprof,
246− const jas_cmprof_t *proofprof, jas_cmxform_op_t op, jas_cmxform_intent_t intent, jas_cmxform_optm_t optimize);
356+/******************************************************************************\
357+* Color-management (CM) profile class.
358+\******************************************************************************/
247359
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+\******************************************************************************/
249427
250−/* Apply a transform to data. */
251−JAS_DLLEXPORT int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in,
428+/*!
429+@brief
430+Create a transform from a CM profile.
431+
432+@details
433+
434+@returns
435+If successful, a pointer to the created transform is returned.
436+Otherwise, a null pointer is returned.
437+*/
438+JAS_EXPORT
439+jas_cmxform_t *jas_cmxform_create(const jas_cmprof_t *inprof,
440+ const jas_cmprof_t *outprof, const jas_cmprof_t *proofprof,
441+ jas_cmxform_op_t op, jas_cmxform_intent_t intent,
442+ jas_cmxform_optm_t optimize);
443+
444+/*!
445+@brief
446+Destroy a transform.
447+
448+@details
449+*/
450+JAS_EXPORT
451+void jas_cmxform_destroy(jas_cmxform_t *xform);
452+
453+/*!
454+@brief
455+Apply a transform to data.
456+
457+@details
458+
459+@returns
460+If successful, zero is returned.
461+Otherwise, a nonzero value is returned.
462+*/
463+JAS_EXPORT
464+int jas_cmxform_apply(const jas_cmxform_t *xform, const jas_cmpixmap_t *in,
252465 jas_cmpixmap_t *out);
253466
254−/* Create a profile. */
255−JAS_DLLEXPORT jas_cmprof_t *jas_cmprof_createfromiccprof(const jas_iccprof_t *iccprof);
256−JAS_DLLEXPORT jas_cmprof_t *jas_cmprof_createfromclrspc(jas_clrspc_t clrspc);
467+/******************************************************************************\
468+* Miscellany.
469+\******************************************************************************/
470+
471+/*!
472+@brief
473+Get the number of channels associated with a particular color space.
257474
258−/* Destroy a profile. */
259−JAS_DLLEXPORT void jas_cmprof_destroy(jas_cmprof_t *prof);
475+@details
260476
477+@returns
478+*/
261479 unsigned jas_clrspc_numchans(jas_clrspc_t clrspc);
262−JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_createfromcmprof(const jas_cmprof_t *prof);
263480
481+/*!
482+@brief
483+Get the color space associated with a color-management profile.
484+
485+@details
486+
487+@returns
488+*/
264489 #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+ */
266494
267495 #ifdef __cplusplus
268496 }
jasper/jas_compiler.h+69−25
@@ -66,38 +66,82 @@ · 65 unmodified lines
6666 #include <jasper/jas_config.h>
6767
6868 #ifdef _MSC_VER
69−#ifndef __cplusplus
70−#undef inline
71−#define inline __inline
69+# ifndef __cplusplus
70+# undef inline
71+# define inline __inline
72+# endif
7273 #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
7397 #endif
7498
75−#ifdef __GNUC__
76−#define JAS_DEPRECATED __attribute__((deprecated))
77−#define JAS_ATTRIBUTE_CONST __attribute__((const))
78−#define JAS_ATTRIBUTE_PURE __attribute__((pure))
79−#define JAS_FORCE_INLINE inline __attribute__((always_inline))
80−#define JAS_UNREACHABLE() __builtin_unreachable()
81−#define JAS_LIKELY(x) __builtin_expect (!!(x), 1)
82−#define JAS_UNLIKELY(x) __builtin_expect (!!(x), 0)
99+#if defined(__GNUC__)
100+# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
101+# define JAS_UNREACHABLE() __builtin_unreachable()
102+# else
103+# define JAS_UNREACHABLE()
104+# endif
105+#elif defined(__clang__)
106+# define JAS_UNREACHABLE() __builtin_unreachable()
107+#elif defined(_MSC_VER)
108+# define JAS_UNREACHABLE() __assume(0)
83109 #else
84−#define JAS_DEPRECATED
85−#define JAS_ATTRIBUTE_CONST
86−#define JAS_ATTRIBUTE_PURE
87−#define JAS_FORCE_INLINE inline
88−#define JAS_UNREACHABLE()
89−#define JAS_LIKELY(x) (x)
90−#define JAS_UNLIKELY(x) (x)
110+# define JAS_UNREACHABLE()
91111 #endif
92112
93−#ifdef __clang__
94−#define JAS_ATTRIBUTE_DISABLE_USAN \
95− __attribute__((no_sanitize("undefined")))
96−#elif defined(__GNUC__) && __GNUC__ >= 6
97−#define JAS_ATTRIBUTE_DISABLE_USAN \
98− __attribute__((no_sanitize_undefined))
113+#if defined(__GNUC__)
114+# define JAS_LIKELY(x) __builtin_expect (!!(x), 1)
99115 #else
100−#define JAS_ATTRIBUTE_DISABLE_USAN
116+# define JAS_LIKELY(x) (x)
101117 #endif
102118
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+
103147 #endif
jasper/jas_config.h+73−3
@@ -4,17 +4,87 @@ · 3 unmodified lines
44 #include <u.h>
55 #include <libc.h>
66 #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+
773 #include <jasper/jas_compiler.h>
874 #include <jasper/jas_dll.h>
975
1076 #define JAS_VERSION "plan9"
77+#define JAS_DEFAULT_MAX_MEM_USAGE (512*1024*1024)
1178 #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
1381 #define JAS_INCLUDE_JPC_CODEC 1
82+#define JAS_INCLUDE_JP2_CODEC 1
1483 #define JAS_DEC_DEFAULT_MAX_SAMPLES (64 * ((size_t) 1048576))
1584 #define NDEBUG
16−#define NULL nil
85+#define JAS_EXPORT
1786
18−typedef usize size_t;
87+#define unlink remove
88+#define lseek seek
1989
2090 #endif
jasper/jas_debug.h+100−10
@@ -74,6 +74,9 @@ · 73 unmodified lines
7474 /* The configuration header file should be included first. */
7575 #include <jasper/jas_config.h>
7676
77+#include "jasper/jas_init.h"
78+#include "jasper/jas_debug.h"
79+
7780 #ifdef __cplusplus
7881 extern "C" {
7982 #endif
@@ -86,25 +89,112 @@ extern "C" { · 6 unmodified lines
8689 level is set sufficiently high. */
8790 #if !defined(NDEBUG)
8891 #define JAS_DBGLOG(n, x) \
89− ((jas_getdbglevel() >= (n)) ? (jas_eprintf x) : 0)
92+ ((jas_get_debug_level() >= (n)) ? (jas_eprintf x) : 0)
9093 #else
9194 #define JAS_DBGLOG(n, x)
9295 #endif
9396
94−/* Get the library debug level. */
95−JAS_ATTRIBUTE_CONST
96−JAS_DLLEXPORT int jas_getdbglevel(void);
97+#if !defined(NDEBUG)
98+#define JAS_LOGDEBUGF(n, ...) \
99+ ((jas_get_debug_level() >= (n)) ? jas_logdebugf((n), __VA_ARGS__) : 0)
100+#else
101+#define JAS_LOGDEBUGF(n, ...)
102+#endif
103+
104+/*!
105+@brief
106+Warn about the use of deprecated functionality.
107+*/
108+JAS_EXPORT
109+void jas_deprecated(const char *fmt, ...);
110+
111+/*!
112+@brief
113+Get the library debug level.
114+
115+@deprecated
116+This function is deprecated.
117+*/
118+JAS_DEPRECATED
119+static inline
120+int jas_getdbglevel(void)
121+{
122+ jas_deprecated("jas_getdbglevel is deprecated\n");
123+ return jas_get_debug_level();
124+}
125+
126+/*!
127+@brief
128+Set the library debug level.
129+*/
130+JAS_EXPORT
131+int jas_setdbglevel(int dbglevel);
132+
133+/*!
134+@brief
135+Print formatted text for the standard error stream (i.e., stderr).
136+*/
137+JAS_EXPORT
138+int jas_eprintf(const char *fmt, ...);
139+
140+/*!
141+@brief
142+Generate a generic log message.
143+*/
144+JAS_EXPORT
145+int jas_logprintf(const char *fmt, ...);
146+
147+/*!
148+@brief
149+Generate an error log message.
150+*/
151+JAS_EXPORT
152+int jas_logerrorf(const char *fmt, ...);
153+
154+/*!
155+@brief
156+Generate a warning log message.
157+*/
158+JAS_EXPORT
159+int jas_logwarnf(const char *fmt, ...);
160+
161+/*!
162+@brief
163+Generate an informational log message.
164+*/
165+JAS_EXPORT
166+int jas_loginfof(const char *fmt, ...);
97167
98−/* Set the library debug level. */
99−JAS_DLLEXPORT int jas_setdbglevel(int dbglevel);
168+/*!
169+@brief
170+Generate a debugging log message.
171+*/
172+JAS_EXPORT
173+int jas_logdebugf(int priority, const char *fmt, ...);
100174
101−/* Perform formatted output to standard error. */
102−JAS_DLLEXPORT int jas_eprintf(const char *fmt, ...);
175+/*!
176+@brief
177+Dump memory.
178+*/
179+int jas_logmemdump(const void *data, size_t len);
103180
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+*/
105192 #define JAS_STRINGIFY(x) #x
106193
107−/* Convert to a string literal after macro expansion */
194+/*!
195+@brief
196+Convert to a string literal after macro expansion.
197+*/
108198 #define JAS_STRINGIFYX(x) JAS_STRINGIFY(x)
109199
110200 #ifdef __cplusplus
jasper/jas_dll.h+4−24
@@ -65,29 +65,9 @@ · 64 unmodified lines
6565 /* The configuration header file should be included first. */
6666 #include <jasper/jas_config.h>
6767
68−#if defined(JAS_DLL)
69− #if defined(_WIN32)
70− #if defined(JAS_BUILDING_DLL)
71− #define JAS_DLLEXPORT __declspec(dllexport)
72− #else
73− #define JAS_DLLEXPORT __declspec(dllimport)
74− #endif
75− #define JAS_DLLLOCAL
76− #elif defined(JAS_HAVE_VISIBILITY)
77− #if defined(JAS_BUILDING_DLL)
78− #define JAS_DLLEXPORT __attribute__ ((visibility("default")))
79− #define JAS_DLLLOCAL __attribute__ ((visibility("hidden")))
80− #else
81− #define JAS_DLLEXPORT
82− #define JAS_DLLLOCAL
83− #endif
84− #else
85− #define JAS_DLLEXPORT
86− #define JAS_DLLLOCAL
87− #endif
88−#else
89− #define JAS_DLLEXPORT
90− #define JAS_DLLLOCAL
91−#endif
68+/* For backward compatibility only. */
69+#define JAS_DLLEXPORT JAS_EXPORT
70+/* For backward compatibility only. */
71+#define JAS_DLLLOCAL JAS_LOCAL
9272
9373 #endif
jasper/jas_fix.h+97−44
@@ -82,19 +82,52 @@ · 81 unmodified lines
8282 extern "C" {
8383 #endif
8484
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+
85118 /******************************************************************************\
86119 * Constants.
87120 \******************************************************************************/
88121
89−/* The representation of the value zero. */
122+/*! The representation of the value zero. */
90123 #define JAS_FIX_ZERO(fix_t, fracbits) \
91124 JAS_INTTOFIX(fix_t, fracbits, 0)
92125
93−/* The representation of the value one. */
126+/*! The representation of the value one. */
94127 #define JAS_FIX_ONE(fix_t, fracbits) \
95128 JAS_INTTOFIX(fix_t, fracbits, 1)
96129
97−/* The representation of the value one half. */
130+/*! The representation of the value one half. */
98131 #define JAS_FIX_HALF(fix_t, fracbits) \
99132 (JAS_CAST(fix_t, 1) << ((fracbits) - 1))
100133
@@ -102,19 +135,19 @@ extern "C" { · 1 unmodified line
102135 * Conversion operations.
103136 \******************************************************************************/
104137
105−/* Convert an int to a fixed-point number. */
138+/*! Convert an int to a fixed-point number. */
106139 #define JAS_INTTOFIX(fix_t, fracbits, x) \
107140 (JAS_CAST(fix_t, x) << (fracbits))
108141
109−/* Convert a fixed-point number to an int. */
142+/*! Convert a fixed-point number to an int. */
110143 #define JAS_FIXTOINT(fix_t, fracbits, x) \
111144 JAS_CAST(int, (x) >> (fracbits))
112145
113−/* Convert a fixed-point number to a double. */
146+/*! Convert a fixed-point number to a double. */
114147 #define JAS_FIXTODBL(fix_t, fracbits, x) \
115148 (JAS_CAST(double, x) / JAS_FIX_ONE(fix_t, fracbits))
116149
117−/* Convert a double to a fixed-point number. */
150+/*! Convert a double to a fixed-point number. */
118151 #define JAS_DBLTOFIX(fix_t, fracbits, x) \
119152 JAS_CAST(fix_t, ((x) * JAS_CAST(double, JAS_FIX_ONE(fix_t, fracbits))))
120153
@@ -128,17 +161,17 @@ extern "C" { · 7 unmodified lines
128161 * Only the generic macros should be invoked directly by application code.
129162 \******************************************************************************/
130163
131−/* Calculate the sum of two fixed-point numbers. */
164+/*! Calculate the sum of two fixed-point numbers. */
132165 #if !defined(DEBUG_OVERFLOW)
133166 #define JAS_FIX_ADD JAS_FIX_ADD_FAST
134167 #else
135168 #define JAS_FIX_ADD JAS_FIX_ADD_OFLOW
136169 #endif
137170
138−/* Calculate the sum of two fixed-point numbers without overflow checking. */
171+/*! Calculate the sum of two fixed-point numbers without overflow checking. */
139172 #define JAS_FIX_ADD_FAST(fix_t, fracbits, x, y) ((x) + (y))
140173
141−/* Calculate the sum of two fixed-point numbers with overflow checking. */
174+/*! Calculate the sum of two fixed-point numbers with overflow checking. */
142175 #define JAS_FIX_ADD_OFLOW(fix_t, fracbits, x, y) \
143176 ((x) >= 0) ? \
144177 (((y) >= 0) ? ((x) + (y) >= 0 || JAS_FIX_OFLOW(), (x) + (y)) : \
@@ -146,20 +179,20 @@ extern "C" { · 1 unmodified line
146179 (((y) >= 0) ? ((x) + (y)) : ((x) + (y) < 0 || JAS_FIX_OFLOW(), \
147180 (x) + (y)))
148181
149−/* Calculate the product of two fixed-point numbers. */
182+/*! Calculate the product of two fixed-point numbers. */
150183 #if !defined(DEBUG_OVERFLOW)
151184 #define JAS_FIX_MUL JAS_FIX_MUL_FAST
152185 #else
153186 #define JAS_FIX_MUL JAS_FIX_MUL_OFLOW
154187 #endif
155188
156−/* Calculate the product of two fixed-point numbers without overflow
189+/*! Calculate the product of two fixed-point numbers without overflow
157190 checking. */
158191 #define JAS_FIX_MUL_FAST(fix_t, fracbits, bigfix_t, x, y) \
159192 JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y)) >> \
160193 (fracbits))
161194
162−/* Calculate the product of two fixed-point numbers with overflow
195+/*! Calculate the product of two fixed-point numbers with overflow
163196 checking. */
164197 #define JAS_FIX_MUL_OFLOW(fix_t, fracbits, bigfix_t, x, y) \
165198 ((JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y) >> (fracbits)) == \
@@ -168,87 +201,87 @@ extern "C" { · 2 unmodified lines
168201 JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) * JAS_CAST(bigfix_t, y) >> \
169202 (fracbits))) : JAS_FIX_OFLOW())
170203
171−/* Calculate the product of a fixed-point number and an int. */
204+/*! Calculate the product of a fixed-point number and an int. */
172205 #if !defined(DEBUG_OVERFLOW)
173206 #define JAS_FIX_MULBYINT JAS_FIX_MULBYINT_FAST
174207 #else
175208 #define JAS_FIX_MULBYINT JAS_FIX_MULBYINT_OFLOW
176209 #endif
177210
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
179212 checking. */
180213 #define JAS_FIX_MULBYINT_FAST(fix_t, fracbits, x, y) \
181214 JAS_CAST(fix_t, ((x) * (y)))
182215
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
184217 checking. */
185218 #define JAS_FIX_MULBYINT_OFLOW(fix_t, fracbits, x, y) \
186219 JAS_FIX_MULBYINT_FAST(fix_t, fracbits, x, y)
187220
188−/* Calculate the quotient of two fixed-point numbers. */
221+/*! Calculate the quotient of two fixed-point numbers. */
189222 #if !defined(DEBUG_OVERFLOW)
190223 #define JAS_FIX_DIV JAS_FIX_DIV_FAST
191224 #else
192225 #define JAS_FIX_DIV JAS_FIX_DIV_UFLOW
193226 #endif
194227
195−/* Calculate the quotient of two fixed-point numbers without underflow
228+/*! Calculate the quotient of two fixed-point numbers without underflow
196229 checking. */
197230 #define JAS_FIX_DIV_FAST(fix_t, fracbits, bigfix_t, x, y) \
198231 JAS_CAST(fix_t, (JAS_CAST(bigfix_t, x) << (fracbits)) / (y))
199232
200−/* Calculate the quotient of two fixed-point numbers with underflow
233+/*! Calculate the quotient of two fixed-point numbers with underflow
201234 checking. */
202235 #define JAS_FIX_DIV_UFLOW(fix_t, fracbits, bigfix_t, x, y) \
203236 JAS_FIX_DIV_FAST(fix_t, fracbits, bigfix_t, x, y)
204237
205−/* Negate a fixed-point number. */
238+/*! Negate a fixed-point number. */
206239 #if !defined(DEBUG_OVERFLOW)
207240 #define JAS_FIX_NEG JAS_FIX_NEG_FAST
208241 #else
209242 #define JAS_FIX_NEG JAS_FIX_NEG_OFLOW
210243 #endif
211244
212−/* Negate a fixed-point number without overflow checking. */
245+/*! Negate a fixed-point number without overflow checking. */
213246 #define JAS_FIX_NEG_FAST(fix_t, fracbits, x) \
214247 (-(x))
215248
216−/* Negate a fixed-point number with overflow checking. */
249+/*! Negate a fixed-point number with overflow checking. */
217250 /* Yes, overflow is actually possible for two's complement representations,
218251 although highly unlikely to occur. */
219252 #define JAS_FIX_NEG_OFLOW(fix_t, fracbits, x) \
220253 (((x) < 0) ? (-(x) > 0 || JAS_FIX_OFLOW(), -(x)) : (-(x)))
221254
222−/* Perform an arithmetic shift left of a fixed-point number. */
255+/*! Perform an arithmetic shift left of a fixed-point number. */
223256 #if !defined(DEBUG_OVERFLOW)
224257 #define JAS_FIX_ASL JAS_FIX_ASL_FAST
225258 #else
226259 #define JAS_FIX_ASL JAS_FIX_ASL_OFLOW
227260 #endif
228261
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
230263 checking. */
231264 #define JAS_FIX_ASL_FAST(fix_t, fracbits, x, n) \
232265 ((x) << (n))
233266
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
235268 checking. */
236269 #define JAS_FIX_ASL_OFLOW(fix_t, fracbits, x, n) \
237270 ((((x) << (n)) >> (n)) == (x) || JAS_FIX_OFLOW(), (x) << (n))
238271
239−/* Perform an arithmetic shift right of a fixed-point number. */
272+/*! Perform an arithmetic shift right of a fixed-point number. */
240273 #if !defined(DEBUG_OVERFLOW)
241274 #define JAS_FIX_ASR JAS_FIX_ASR_FAST
242275 #else
243276 #define JAS_FIX_ASR JAS_FIX_ASR_UFLOW
244277 #endif
245278
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
247280 checking. */
248281 #define JAS_FIX_ASR_FAST(fix_t, fracbits, x, n) \
249282 ((x) >> (n))
250283
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
252285 checking. */
253286 #define JAS_FIX_ASR_UFLOW(fix_t, fracbits, x, n) \
254287 JAS_FIX_ASR_FAST(fix_t, fracbits, x, n)
@@ -257,19 +290,19 @@ extern "C" { · 2 unmodified lines
257290 * Other basic arithmetic operations.
258291 \******************************************************************************/
259292
260−/* Calculate the difference between two fixed-point numbers. */
293+/*! Calculate the difference between two fixed-point numbers. */
261294 #define JAS_FIX_SUB(fix_t, fracbits, x, y) \
262295 JAS_FIX_ADD(fix_t, fracbits, x, JAS_FIX_NEG(fix_t, fracbits, y))
263296
264−/* Add one fixed-point number to another. */
297+/*! Add one fixed-point number to another. */
265298 #define JAS_FIX_PLUSEQ(fix_t, fracbits, x, y) \
266299 ((x) = JAS_FIX_ADD(fix_t, fracbits, x, y))
267300
268−/* Subtract one fixed-point number from another. */
301+/*! Subtract one fixed-point number from another. */
269302 #define JAS_FIX_MINUSEQ(fix_t, fracbits, x, y) \
270303 ((x) = JAS_FIX_SUB(fix_t, fracbits, x, y))
271304
272−/* Multiply one fixed-point number by another. */
305+/*! Multiply one fixed-point number by another. */
273306 #define JAS_FIX_MULEQ(fix_t, fracbits, bigfix_t, x, y) \
274307 ((x) = JAS_FIX_MUL(fix_t, fracbits, bigfix_t, x, y))
275308
@@ -277,15 +310,15 @@ extern "C" { · 1 unmodified line
277310 * Miscellaneous operations.
278311 \******************************************************************************/
279312
280−/* Calculate the absolute value of a fixed-point number. */
313+/*! Calculate the absolute value of a fixed-point number. */
281314 #define JAS_FIX_ABS(fix_t, fracbits, x) \
282315 (((x) >= 0) ? (x) : (JAS_FIX_NEG(fix_t, fracbits, x)))
283316
284−/* Is a fixed-point number an integer? */
317+/*! Is a fixed-point number an integer? */
285318 #define JAS_FIX_ISINT(fix_t, fracbits, x) \
286319 (JAS_FIX_FLOOR(fix_t, fracbits, x) == (x))
287320
288−/* Get the sign of a fixed-point number. */
321+/*! Get the sign of a fixed-point number. */
289322 #define JAS_FIX_SGN(fix_t, fracbits, x) \
290323 ((x) >= 0 ? 1 : (-1))
291324
@@ -293,23 +326,23 @@ extern "C" { · 1 unmodified line
293326 * Relational operations.
294327 \******************************************************************************/
295328
296−/* Compare two fixed-point numbers. */
329+/*! Compare two fixed-point numbers. */
297330 #define JAS_FIX_CMP(fix_t, fracbits, x, y) \
298331 ((x) > (y) ? 1 : (((x) == (y)) ? 0 : (-1)))
299332
300−/* Less than. */
333+/*! Less than. */
301334 #define JAS_FIX_LT(fix_t, fracbits, x, y) \
302335 ((x) < (y))
303336
304−/* Less than or equal. */
337+/*! Less than or equal. */
305338 #define JAS_FIX_LTE(fix_t, fracbits, x, y) \
306339 ((x) <= (y))
307340
308−/* Greater than. */
341+/*! Greater than. */
309342 #define JAS_FIX_GT(fix_t, fracbits, x, y) \
310343 ((x) > (y))
311344
312−/* Greater than or equal. */
345+/*! Greater than or equal. */
313346 #define JAS_FIX_GTE(fix_t, fracbits, x, y) \
314347 ((x) >= (y))
315348
@@ -317,14 +350,14 @@ extern "C" { · 1 unmodified line
317350 * Rounding functions.
318351 \******************************************************************************/
319352
320−/* Round a fixed-point number to the nearest integer. */
353+/*! Round a fixed-point number to the nearest integer. */
321354 #define JAS_FIX_ROUND(fix_t, fracbits, x) \
322355 (((x) < 0) ? JAS_FIX_FLOOR(fix_t, fracbits, JAS_FIX_ADD(fix_t, fracbits, \
323356 (x), JAS_FIX_HALF(fix_t, fracbits))) : \
324357 JAS_FIX_NEG(fix_t, fracbits, JAS_FIX_FLOOR(fix_t, fracbits, \
325358 JAS_FIX_ADD(fix_t, fracbits, (-(x)), JAS_FIX_HALF(fix_t, fracbits)))))
326359
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
328361 negative infinity (i.e., the floor function). */
329362 #define JAS_FIX_FLOOR(fix_t, fracbits, x) \
330363 ((x) & (~(JAS_FIX_ONE(fix_t, fracbits) - 1)))
@@ -336,11 +369,31 @@ extern "C" { · 5 unmodified lines
336369
337370 /* Handle overflow. */
338371 #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__)
340373
341374 /* Handle underflow. */
342375 #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+ */
344397
345398 #ifdef __cplusplus
346399 }
jasper/jas_icc.h+142−20
@@ -77,6 +77,11 @@ · 76 unmodified lines
7777 extern "C" {
7878 #endif
7979
80+/*!
81+ * @addtogroup module_cm
82+ * @{
83+ */
84+
8085 /* Profile file signature. */
8186 #define JAS_ICC_MAGIC 0x61637370
8287
@@ -308,6 +313,7 @@ typedef struct { · 225 unmodified lines
308313 int (*output)(struct jas_iccattrval_s *, jas_stream_t *);
309314 //#endif
310315 unsigned (*getsize)(const struct jas_iccattrval_s *);
316+ void (*dump)(const struct jas_iccattrval_s *, FILE *);
311317 } jas_iccattrvalops_t;
312318
313319 /* Attribute value type (type and value information). */
@@ -381,29 +387,145 @@ typedef struct { · 67 unmodified lines
381387 jas_iccattrvalops_t ops;
382388 } jas_iccattrvalinfo_t;
383389
384−JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_load(jas_stream_t *in);
385−JAS_DLLEXPORT int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out);
386−JAS_DLLEXPORT void jas_iccprof_destroy(jas_iccprof_t *prof);
390+/*!
391+@brief
392+Read an ICC profile from a stream.
393+*/
394+JAS_EXPORT
395+jas_iccprof_t *jas_iccprof_load(jas_stream_t *in);
396+
397+/*!
398+@brief
399+Write an ICC profile to a stream.
400+*/
401+JAS_EXPORT
402+int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out);
403+
404+/*!
405+@brief
406+Destroy an ICC profile.
407+*/
408+JAS_EXPORT
409+void jas_iccprof_destroy(jas_iccprof_t *prof);
410+
411+/*!
412+@brief
413+Get an attribute of an ICC profile.
414+*/
387415 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,
389418 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,
391426 jas_iccattrval_t *val);
392−JAS_DLLEXPORT int jas_iccprof_gethdr(const jas_iccprof_t *prof, jas_icchdr_t *hdr);
393−JAS_DLLEXPORT int jas_iccprof_sethdr(jas_iccprof_t *prof, const jas_icchdr_t *hdr);
394−
395−JAS_DLLEXPORT void jas_iccattrval_destroy(jas_iccattrval_t *attrval);
396−JAS_DLLEXPORT int jas_iccattrval_allowmodify(jas_iccattrval_t **attrval);
397−JAS_DLLEXPORT jas_iccattrval_t *jas_iccattrval_clone(jas_iccattrval_t *attrval);
398−JAS_DLLEXPORT jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type);
399−
400−JAS_DLLEXPORT extern const jas_uchar jas_iccprofdata_srgb[];
401−JAS_DLLEXPORT extern const unsigned jas_iccprofdata_srgblen;
402−JAS_DLLEXPORT extern const jas_uchar jas_iccprofdata_sgray[];
403−JAS_DLLEXPORT extern const unsigned jas_iccprofdata_sgraylen;
404−JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len);
405−JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_createfromclrspc(unsigned clrspc);
406−JAS_DLLEXPORT jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof);
427+
428+/*!
429+@brief
430+Dump an ICC profile to a stream in human-readable format
431+for debugging purposes.
432+*/
433+JAS_EXPORT
434+void jas_iccprof_dump(const jas_iccprof_t *prof, FILE *out);
435+
436+/*!
437+@brief
438+Create a copy of an ICC profile.
439+*/
440+JAS_EXPORT
441+jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof);
442+
443+/*!
444+@brief
445+Get the header for an ICC profile.
446+*/
447+JAS_EXPORT
448+int jas_iccprof_gethdr(const jas_iccprof_t *prof, jas_icchdr_t *hdr);
449+
450+/*!
451+@brief
452+Set the header for an ICC profile.
453+*/
454+JAS_EXPORT
455+int jas_iccprof_sethdr(jas_iccprof_t *prof, const jas_icchdr_t *hdr);
456+
457+/*!
458+@brief
459+Destroy an ICC profile attribute.
460+*/
461+JAS_EXPORT
462+void jas_iccattrval_destroy(jas_iccattrval_t *attrval);
463+
464+/*!
465+@brief
466+*/
467+JAS_EXPORT
468+void jas_iccattrval_dump(const jas_iccattrval_t *attrval, FILE *out);
469+
470+/*!
471+@brief
472+
473+TODO/FIXME
474+*/
475+JAS_EXPORT
476+int jas_iccattrval_allowmodify(jas_iccattrval_t **attrval);
477+
478+/*!
479+@brief
480+Create a copy of an ICC profile attribute.
481+*/
482+JAS_EXPORT
483+jas_iccattrval_t *jas_iccattrval_clone(jas_iccattrval_t *attrval);
484+
485+/*!
486+@brief
487+Create an ICC profile attribute.
488+*/
489+JAS_EXPORT
490+jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type);
491+
492+/*!
493+@brief
494+Dump an ICC profile attribute to a stream in human-readable format
495+for debugging purposes.
496+*/
497+JAS_EXPORT
498+void jas_iccattrtab_dump(const jas_iccattrtab_t *attrtab, FILE *out);
499+
500+/*!
501+@brief
502+Create an ICC profile from a buffer in memory.
503+*/
504+JAS_EXPORT
505+jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len);
506+
507+/*!
508+@brief
509+Create an ICC profile from a color space.
510+*/
511+JAS_EXPORT
512+jas_iccprof_t *jas_iccprof_createfromclrspc(unsigned clrspc);
513+
514+JAS_EXPORT
515+extern const jas_uchar jas_iccprofdata_srgb[];
516+
517+JAS_EXPORT
518+extern const unsigned jas_iccprofdata_srgblen;
519+
520+JAS_EXPORT
521+extern const jas_uchar jas_iccprofdata_sgray[];
522+
523+JAS_EXPORT
524+extern const unsigned jas_iccprofdata_sgraylen;
525+
526+/*!
527+ * @}
528+ */
407529
408530 #ifdef __cplusplus
409531 }
jasper/jas_image.h+222−100
@@ -86,7 +86,7 @@ extern "C" { · 85 unmodified lines
8686 #endif
8787
8888 /*!
89− * @addtogroup image
89+ * @addtogroup module_images
9090 * @{
9191 */
9292
@@ -128,7 +128,8 @@ extern "C" { · 35 unmodified lines
128128 \******************************************************************************/
129129
130130 /*!
131−@brief Image coordinate. */
131+@brief Image coordinate.
132+*/
132133 typedef int_fast32_t jas_image_coord_t;
133134 #define JAS_IMAGE_COORD_MAX INT_FAST32_MAX
134135 #define JAS_IMAGE_COORD_MIN INT_FAST32_MIN
@@ -154,81 +155,95 @@ typedef int_fast16_t jas_image_smpltype_t; · 19 unmodified lines
154155 \******************************************************************************/
155156
156157 /*!
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.
158166 */
159167 typedef struct {
160168
161− jas_image_coord_t tlx_;
162169 /* The x-coordinate of the top-left corner of the component. */
170+ jas_image_coord_t tlx_;
163171
164− jas_image_coord_t tly_;
165172 /* The y-coordinate of the top-left corner of the component. */
173+ jas_image_coord_t tly_;
166174
167− jas_image_coord_t hstep_;
168175 /* The horizontal sampling period in units of the reference grid. */
176+ jas_image_coord_t hstep_;
169177
170− jas_image_coord_t vstep_;
171178 /* The vertical sampling period in units of the reference grid. */
179+ jas_image_coord_t vstep_;
172180
173− jas_image_coord_t width_;
174181 /* The component width in samples. */
182+ jas_image_coord_t width_;
175183
176− jas_image_coord_t height_;
177184 /* The component height in samples. */
185+ jas_image_coord_t height_;
178186
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. */
179189 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. */
183190
184− int sgnd_;
185191 /* The signedness of the sample data. */
192+ int sgnd_;
186193
187− jas_stream_t *stream_;
188194 /* The stream containing the component data. */
195+ jas_stream_t *stream_;
189196
190− unsigned cps_;
191197 /* The number of characters per sample in the stream. */
198+ unsigned cps_;
192199
193− jas_image_cmpttype_t type_;
194200 /* The type of component (e.g., opacity, red, green, blue, luma). */
201+ jas_image_cmpttype_t type_;
195202
196203 } jas_image_cmpt_t;
197204
198205 /*!
199206 @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.
200213 */
201214 typedef struct {
202215
203− jas_image_coord_t tlx_;
204216 /* The x-coordinate of the top-left corner of the image bounding box. */
217+ jas_image_coord_t tlx_;
205218
206− jas_image_coord_t tly_;
207219 /* The y-coordinate of the top-left corner of the image bounding box. */
220+ jas_image_coord_t tly_;
208221
209− jas_image_coord_t brx_;
210222 /* The x-coordinate of the bottom-right corner of the image bounding
211223 box (plus one). */
224+ jas_image_coord_t brx_;
212225
213− jas_image_coord_t bry_;
214226 /* The y-coordinate of the bottom-right corner of the image bounding
215227 box (plus one). */
228+ jas_image_coord_t bry_;
216229
217− unsigned numcmpts_;
218230 /* The number of components. */
231+ unsigned numcmpts_;
219232
220− unsigned maxcmpts_;
221233 /* The maximum number of components that this image can have (i.e., the
222234 allocated size of the components array). */
235+ unsigned maxcmpts_;
223236
224− jas_image_cmpt_t **cmpts_;
225237 /* Per-component information. */
238+ jas_image_cmpt_t **cmpts_;
226239
240+ /* The color space. */
227241 jas_clrspc_t clrspc_;
228242
243+ /* The CM profile. */
229244 jas_cmprof_t *cmprof_;
230245
231−// bool inmem_;
246+ //bool inmem_;
232247
233248 } jas_image_t;
234249
@@ -241,29 +256,29 @@ jas_image_create function. · 6 unmodified lines
241256 */
242257 typedef struct {
243258
244− jas_image_coord_t tlx;
245259 /* The x-coordinate of the top-left corner of the component. */
260+ jas_image_coord_t tlx;
246261
247− jas_image_coord_t tly;
248262 /* The y-coordinate of the top-left corner of the component. */
263+ jas_image_coord_t tly;
249264
250− jas_image_coord_t hstep;
251265 /* The horizontal sampling period in units of the reference grid. */
266+ jas_image_coord_t hstep;
252267
253− jas_image_coord_t vstep;
254268 /* The vertical sampling period in units of the reference grid. */
269+ jas_image_coord_t vstep;
255270
256− jas_image_coord_t width;
257271 /* The width of the component in samples. */
272+ jas_image_coord_t width;
258273
259− jas_image_coord_t height;
260274 /* The height of the component in samples. */
275+ jas_image_coord_t height;
261276
262− unsigned prec;
263277 /* The precision of the component sample data. */
278+ unsigned prec;
264279
265− int sgnd;
266280 /* The signedness of the component sample data. */
281+ int sgnd;
267282
268283 } jas_image_cmptparm_t;
269284
@@ -281,14 +296,14 @@ typedef struct { · 11 unmodified lines
281296 */
282297 typedef struct {
283298
299+ /*! Decode image data from a stream. */
284300 jas_image_t *(*decode)(jas_stream_t *in, const char *opts);
285− /* Decode image data from a stream. */
286301
302+ /*! Encode image data to a stream. */
287303 int (*encode)(jas_image_t *image, jas_stream_t *out, const char *opts);
288− /* Encode image data to a stream. */
289304
305+ /*! Determine if stream data is in a particular format. */
290306 int (*validate)(jas_stream_t *in);
291− /* Determine if stream data is in a particular format. */
292307
293308 } jas_image_fmtops_t;
294309
@@ -297,20 +312,29 @@ typedef struct { · 2 unmodified lines
297312 */
298313 typedef struct {
299314
315+ /*! The ID for this format. */
300316 int id;
301− /* The ID for this format. */
302317
318+ /*! The name by which this format is identified. */
303319 char *name;
304− /* The name by which this format is identified. */
305320
321+ /* The primary file name extension associated with this format. */
322+ /* This member only exists for backward compatibility. */
306323 char *ext;
307− /* The file name extension associated with this format. */
308324
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. */
309334 char *desc;
310− /* A brief description of the format. */
311335
336+ /*! The operations for this format. */
312337 jas_image_fmtops_t ops;
313− /* The operations for this format. */
314338
315339 } jas_image_fmtinfo_t;
316340
@@ -321,23 +345,27 @@ typedef struct { · 4 unmodified lines
321345 /*!
322346 @brief Create an image.
323347 */
324−JAS_DLLEXPORT jas_image_t *jas_image_create(unsigned numcmpts,
348+JAS_EXPORT
349+jas_image_t *jas_image_create(unsigned numcmpts,
325350 const jas_image_cmptparm_t *cmptparms, jas_clrspc_t clrspc);
326351
327352 /*!
328353 @brief Create an "empty" image.
329354 */
330−JAS_DLLEXPORT jas_image_t *jas_image_create0(void);
355+JAS_EXPORT
356+jas_image_t *jas_image_create0(void);
331357
332358 /*!
333359 @brief Clone an image.
334360 */
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);
336363
337364 /*!
338365 @brief Deallocate any resources associated with an image.
339366 */
340−JAS_DLLEXPORT void jas_image_destroy(jas_image_t *image);
367+JAS_EXPORT
368+void jas_image_destroy(jas_image_t *image);
341369
342370 /*!
343371 @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
470498 @brief Test if all components are specified at the same positions in space.
471499 */
472500 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);
474503
475504 /*!
476505 @brief Get the raw size of an image
477506 (i.e., the nominal size of the image without any compression.
478507 */
479508 JAS_ATTRIBUTE_PURE
480−JAS_DLLEXPORT
509+JAS_EXPORT
481510 uint_fast32_t jas_image_rawsize(const jas_image_t *image);
482511
483512 /*!
484513 @brief Create an image from a stream in some specified format.
485514 */
486−JAS_DLLEXPORT
515+JAS_EXPORT
487516 jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr);
488517
489518 /*!
490519 @brief Write an image to a stream in a specified format.
491520 */
492−JAS_DLLEXPORT
521+JAS_EXPORT
493522 int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt,
494523 const char *optstr);
495524
@@ -500,7 +529,7 @@ int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, · 4 unmodified lines
500529 The position and size of the rectangular region to be read is specified
501530 relative to the component's coordinate system.
502531 */
503−JAS_DLLEXPORT
532+JAS_EXPORT
504533 int jas_image_readcmpt(jas_image_t *image, unsigned cmptno,
505534 jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width,
506535 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
508537 /*!
509538 @brief Write a rectangular region of an image component.
510539 */
511−JAS_DLLEXPORT
540+JAS_EXPORT
512541 int jas_image_writecmpt(jas_image_t *image, unsigned cmptno,
513542 jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width,
514543 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
516545 /*!
517546 @brief Delete a component from an image.
518547 */
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);
520550
521551 /*!
522552 @brief Add a component to an image.
523553 */
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,
525556 const jas_image_cmptparm_t *cmptparm);
526557
527558 /*!
528559 @brief Copy a component from one image to another.
529560 */
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,
531563 jas_image_t *srcimage, unsigned srccmptno);
532564
533565 JAS_ATTRIBUTE_CONST
@@ -555,7 +587,8 @@ static inline uint_least8_t JAS_IMAGE_CDT_SETPREC(uint_least8_t dtype) · 21 unmodified lines
555587 }
556588
557589 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)
559592 {
560593 return JAS_IMAGE_CDT_SETSGND(image->cmpts_[cmptno]->sgnd_) |
561594 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
564597 /*!
565598 @brief Depalettize an image
566599 */
567−JAS_DLLEXPORT
600+JAS_EXPORT
568601 int jas_image_depalettize(jas_image_t *image, unsigned cmptno,
569602 unsigned numlutents, const int_fast32_t *lutents, unsigned dtype,
570603 unsigned newcmptno);
@@ -572,14 +605,14 @@ int jas_image_depalettize(jas_image_t *image, unsigned cmptno, · 1 unmodified line
572605 /*!
573606 @brief Read a component sample for an image.
574607 */
575−JAS_DLLEXPORT
608+JAS_EXPORT
576609 int jas_image_readcmptsample(jas_image_t *image, unsigned cmptno, unsigned x,
577610 unsigned y);
578611
579612 /*!
580613 @brief Write a component sample for an image.
581614 */
582−JAS_DLLEXPORT
615+JAS_EXPORT
583616 void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno,
584617 unsigned x, unsigned y, int_fast32_t v);
585618
@@ -587,7 +620,7 @@ void jas_image_writecmptsample(jas_image_t *image, unsigned cmptno, · 1 unmodified line
587620 @brief Get an image component by its type.
588621 */
589622 JAS_ATTRIBUTE_PURE
590−JAS_DLLEXPORT
623+JAS_EXPORT
591624 int jas_image_getcmptbytype(const jas_image_t *image, jas_image_cmpttype_t ctype);
592625
593626 /******************************************************************************\
@@ -597,75 +630,122 @@ int jas_image_getcmptbytype(const jas_image_t *image, jas_image_cmpttype_t ctype · 3 unmodified lines
597630 /*!
598631 @brief Clear the table of image formats.
599632 */
600−JAS_DLLEXPORT
633+JAS_EXPORT
601634 void jas_image_clearfmts(void);
602635
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+
603674 /*!
604675 @brief Add entry to table of image formats.
605676 */
606−JAS_DLLEXPORT
677+JAS_EXPORT
607678 int jas_image_addfmt(int id, const char *name, const char *ext,
608679 const char *desc, const jas_image_fmtops_t *ops);
609680
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+
610687 /*!
611688 @brief Get the ID for the image format with the specified name.
612689 */
613690 JAS_ATTRIBUTE_PURE
614−JAS_DLLEXPORT
691+JAS_EXPORT
615692 int jas_image_strtofmt(const char *s);
616693
617694 /*!
618695 @brief Get the name of the image format with the specified ID.
619696 */
620697 JAS_ATTRIBUTE_CONST
621−JAS_DLLEXPORT
698+JAS_EXPORT
622699 const char *jas_image_fmttostr(int fmt);
623700
624701 /*!
625702 @brief Lookup image format information by the format ID.
626703 */
627704 JAS_ATTRIBUTE_CONST
628−JAS_DLLEXPORT
705+JAS_EXPORT
629706 const jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id);
630707
631708 /*!
632709 @brief Lookup image format information by the format name.
633710 */
634711 JAS_ATTRIBUTE_PURE
635−JAS_DLLEXPORT
712+JAS_EXPORT
636713 const jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name);
637714
638715 /*!
639716 @brief Guess the format of an image file based on its name.
640717 */
641718 JAS_ATTRIBUTE_PURE
642−JAS_DLLEXPORT
719+JAS_EXPORT
643720 int jas_image_fmtfromname(const char *filename);
644721
645722 /*!
646723 @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.
647727 */
648728 JAS_ATTRIBUTE_PURE
649−JAS_DLLEXPORT
729+JAS_EXPORT
650730 int jas_image_getfmt(jas_stream_t *in);
651731
652−
653732 /*!
654733 @brief Get the color management profile of an image.
655734 */
656735 #define jas_image_cmprof(image) ((image)->cmprof_)
657736
658737 /*!
659−@brief ???
738+@brief
739+Test if the sampling of the image is homogeneous.
660740 */
661741 JAS_ATTRIBUTE_PURE
662−JAS_DLLEXPORT
742+JAS_EXPORT
663743 int jas_image_ishomosamp(const jas_image_t *image);
664744
665745 /*!
666746 @brief ???
667747 */
668−JAS_DLLEXPORT
748+JAS_EXPORT
669749 int jas_image_sampcmpt(jas_image_t *image, unsigned cmptno, unsigned newcmptno,
670750 jas_image_coord_t ho, jas_image_coord_t vo, jas_image_coord_t hs,
671751 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
673753 /*!
674754 @brief Write sample data in a component of an image.
675755 */
676−JAS_DLLEXPORT int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno, jas_image_coord_t x,
677− jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
678− const long *buf);
756+JAS_EXPORT
757+int jas_image_writecmpt2(jas_image_t *image, unsigned cmptno,
758+ jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width,
759+ jas_image_coord_t height, const long *buf);
679760
680761 /*!
681762 @brief Read sample data in a component of an image.
682763 */
683−JAS_DLLEXPORT
764+JAS_EXPORT
684765 int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno,
685766 jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width,
686767 jas_image_coord_t height, long *buf);
@@ -693,8 +774,15 @@ int jas_image_readcmpt2(jas_image_t *image, unsigned cmptno, · 6 unmodified lines
693774 /*!
694775 @brief Change the color space for an image.
695776 */
696−JAS_DLLEXPORT jas_image_t *jas_image_chclrspc(jas_image_t *image, const jas_cmprof_t *outprof,
697− jas_cmxform_intent_t intent);
777+JAS_EXPORT
778+jas_image_t *jas_image_chclrspc(jas_image_t *image,
779+ const jas_cmprof_t *outprof, jas_cmxform_intent_t intent);
780+
781+/*!
782+@brief Dump the information for an image (for debugging).
783+*/
784+JAS_EXPORT
785+int jas_image_dump(jas_image_t *image, FILE *out);
698786
699787 /******************************************************************************\
700788 * 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
702790
703791 #if defined(JAS_INCLUDE_JPG_CODEC)
704792 /* Format-dependent operations for JPG support. */
705−JAS_DLLEXPORT jas_image_t *jpg_decode(jas_stream_t *in, const char *optstr);
706−JAS_DLLEXPORT int jpg_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
707−JAS_DLLEXPORT int jpg_validate(jas_stream_t *in);
793+//JAS_EXPORT
794+jas_image_t *jpg_decode(jas_stream_t *in, const char *optstr);
795+//JAS_EXPORT
796+int jpg_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
797+//JAS_EXPORT
798+int jpg_validate(jas_stream_t *in);
799+#endif
800+
801+#if defined(JAS_INCLUDE_HEIC_CODEC)
802+/* Format-dependent operations for HEIC support. */
803+//JAS_EXPORT
804+jas_image_t *jas_heic_decode(jas_stream_t *in, const char *optstr);
805+//JAS_EXPORT
806+int jas_heic_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
807+//JAS_EXPORT
808+int jas_heic_validate(jas_stream_t *in);
708809 #endif
709810
710811 #if defined(JAS_INCLUDE_MIF_CODEC)
711812 /* Format-dependent operations for MIF support. */
712−JAS_DLLEXPORT jas_image_t *mif_decode(jas_stream_t *in, const char *optstr);
713−JAS_DLLEXPORT int mif_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
714−JAS_DLLEXPORT int mif_validate(jas_stream_t *in);
813+//JAS_EXPORT
814+jas_image_t *mif_decode(jas_stream_t *in, const char *optstr);
815+//JAS_EXPORT
816+int mif_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
817+//JAS_EXPORT
818+int mif_validate(jas_stream_t *in);
715819 #endif
716820
717821 #if defined(JAS_INCLUDE_PNM_CODEC)
718822 /* Format-dependent operations for PNM support. */
719−JAS_DLLEXPORT jas_image_t *pnm_decode(jas_stream_t *in, const char *optstr);
720−JAS_DLLEXPORT int pnm_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
721−JAS_DLLEXPORT int pnm_validate(jas_stream_t *in);
823+//JAS_EXPORT
824+jas_image_t *pnm_decode(jas_stream_t *in, const char *optstr);
825+//JAS_EXPORT
826+int pnm_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
827+//JAS_EXPORT
828+int pnm_validate(jas_stream_t *in);
722829 #endif
723830
724831 #if defined(JAS_INCLUDE_RAS_CODEC)
725832 /* Format-dependent operations for Sun Rasterfile support. */
726−JAS_DLLEXPORT jas_image_t *ras_decode(jas_stream_t *in, const char *optstr);
727−JAS_DLLEXPORT int ras_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
728−JAS_DLLEXPORT int ras_validate(jas_stream_t *in);
833+//JAS_EXPORT
834+jas_image_t *ras_decode(jas_stream_t *in, const char *optstr);
835+//JAS_EXPORT
836+int ras_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
837+//JAS_EXPORT
838+int ras_validate(jas_stream_t *in);
729839 #endif
730840
731841 #if defined(JAS_INCLUDE_BMP_CODEC)
732842 /* Format-dependent operations for BMP support. */
733−JAS_DLLEXPORT jas_image_t *bmp_decode(jas_stream_t *in, const char *optstr);
734−JAS_DLLEXPORT int bmp_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
735−JAS_DLLEXPORT int bmp_validate(jas_stream_t *in);
843+//JAS_EXPORT
844+jas_image_t *bmp_decode(jas_stream_t *in, const char *optstr);
845+//JAS_EXPORT
846+int bmp_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
847+//JAS_EXPORT
848+int bmp_validate(jas_stream_t *in);
736849 #endif
737850
738851 #if defined(JAS_INCLUDE_JP2_CODEC)
739852 /* Format-dependent operations for JP2 support. */
740−JAS_DLLEXPORT jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr);
741−JAS_DLLEXPORT int jp2_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
742−JAS_DLLEXPORT int jp2_validate(jas_stream_t *in);
853+//JAS_EXPORT
854+jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr);
855+//JAS_EXPORT
856+int jp2_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
857+//JAS_EXPORT
858+int jp2_validate(jas_stream_t *in);
743859 #endif
744860
745861 #if defined(JAS_INCLUDE_JPC_CODEC)
746862 /* Format-dependent operations for JPEG-2000 code stream support. */
747−JAS_DLLEXPORT jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr);
748−JAS_DLLEXPORT int jpc_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
749−JAS_DLLEXPORT int jpc_validate(jas_stream_t *in);
863+//JAS_EXPORT
864+jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr);
865+//JAS_EXPORT
866+int jpc_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
867+//JAS_EXPORT
868+int jpc_validate(jas_stream_t *in);
750869 #endif
751870
752871 #if defined(JAS_INCLUDE_PGX_CODEC)
753872 /* Format-dependent operations for PGX support. */
754−JAS_DLLEXPORT jas_image_t *pgx_decode(jas_stream_t *in, const char *optstr);
755−JAS_DLLEXPORT int pgx_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
756−JAS_DLLEXPORT int pgx_validate(jas_stream_t *in);
873+//JAS_EXPORT
874+jas_image_t *pgx_decode(jas_stream_t *in, const char *optstr);
875+//JAS_EXPORT
876+int pgx_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
877+//JAS_EXPORT
878+int pgx_validate(jas_stream_t *in);
757879 #endif
758880
759881 /*!
jasper/jas_init.h+391−10
@@ -70,42 +70,423 @@ · 69 unmodified lines
7070 /* The configuration header file should be included first. */
7171 #include <jasper/jas_config.h>
7272
73+#include "jasper/jas_malloc.h"
74+#include "jasper/jas_image.h"
75+#include "jasper/jas_log.h"
76+
7377 #ifdef __cplusplus
7478 extern "C" {
7579 #endif
7680
7781 /*!
78− * @addtogroup init
82+ * @addtogroup module_init
7983 * @{
8084 */
8185
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+
82208 /******************************************************************************\
83−* Functions.
209+* Library Initialization and Cleanup.
84210 \******************************************************************************/
85211
86212 /*!
87−@brief Initialize the JasPer library.
213+@brief
214+Initialize the JasPer library with the current configuration settings.
88215
89216 @details
90−This function must be called before any other code in the JasPer library
91−is invoked.
92−This function registers the codecs that are enabled by default.
217+The library must be configured by invoking the jas_conf_clear() function
218+prior to calling jas_init_library().
93219
94220 @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().
96264 */
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
98308 int jas_init(void);
99309
100310 /*!
101−@brief Perform any clean up for the JasPer library.
311+@brief
312+Perform any clean up for the JasPer library.
102313
103314 @details
104315 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.
105323 */
106−JAS_DLLEXPORT
324+JAS_EXPORT
107325 void jas_cleanup(void);
108326
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+
109490 /*!
110491 * @}
111492 */
jasper/jas_log.h+168−0
@@ -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
jasper/jas_malloc.h+272−7
@@ -77,17 +77,282 @@ · 76 unmodified lines
7777 /* The configuration header file should be included first. */
7878 #include <jasper/jas_config.h>
7979
80+#include <jasper/jas_types.h>
81+#include <jasper/jas_thread.h>
82+
8083 #ifdef __cplusplus
8184 extern "C" {
8285 #endif
8386
84−#define jas_malloc malloc
85−#define jas_free free
86−#define jas_realloc realloc
87−#define jas_calloc calloc
88−#define jas_alloc2(ne, esz) malloc(ne*esz)
89−#define jas_alloc3(na, asz, esz) malloc(na*asz*esz)
90−#define jas_realloc2(p, ne, esz) realloc(p, ne*esz)
87+/*!
88+ * @addtogroup module_alloc
89+ * @{
90+ */
91+
92+/******************************************************************************\
93+* Types.
94+\******************************************************************************/
95+
96+/*!
97+@brief A memory allocator.
98+*/
99+typedef struct jas_allocator_s {
100+
101+ /*!
102+ Function to clean up the allocator when no longer needed.
103+ The allocator cannot be used after the clean-up operation is performed.
104+ This function pointer may be null, in which case the clean-up operation
105+ is treated as a no-op.
106+ */
107+ void (*cleanup)(struct jas_allocator_s *allocator);
108+
109+ /*!
110+ Function to allocate memory.
111+ This function should have behavior similar to malloc.
112+ */
113+ void *(*alloc)(struct jas_allocator_s *allocator, size_t size);
114+
115+ /*!
116+ Function to deallocate memory.
117+ This function should have behavior similar to free.
118+ */
119+ void (*free)(struct jas_allocator_s *allocator, void *pointer);
120+
121+ /*!
122+ Function to reallocate memory.
123+ This function should have behavior similar to realloc.
124+ */
125+ void *(*realloc)(struct jas_allocator_s *allocator, void *pointer,
126+ size_t new_size);
127+
128+ /*! For future use. */
129+ void (*(reserved[4]))(void);
130+
131+} jas_allocator_t;
132+
133+/*!
134+@brief The standard library allocator (i.e., a wrapper for malloc and friends).
135+
136+@details
137+Essentially, jas_std_allocator_t can be thought of as having an inheritance
138+relationship with jas_allocator_t.
139+In particular, jas_std_allocator_t is derived from jas_allocator_t.
140+*/
141+typedef struct {
142+
143+ /* The base class. */
144+ jas_allocator_t base;
145+
146+} jas_std_allocator_t;
147+
148+#if defined(JAS_FOR_INTERNAL_USE_ONLY)
149+/*
150+The allocator wrapper type.
151+This type is an allocator that adds memory usage tracking to another
152+allocator.
153+The allocator wrapper does not directly perform memory allocation itself.
154+Instead, it delegate to another allocator.
155+*/
156+typedef struct {
157+
158+ /* The base class. */
159+ jas_allocator_t base;
160+
161+ /* The delegated-to allocator. */
162+ jas_allocator_t *delegate;
163+
164+ /* The maximum amount of memory that can be used by the allocator. */
165+ size_t max_mem;
166+
167+ /* The current amount of memory in use by the allocator. */
168+ size_t mem;
169+
170+#if defined(JAS_THREADS)
171+ /* A mutex for synchronized access to the allocator. */
172+ jas_mutex_t mutex;
173+#endif
174+
175+} jas_basic_allocator_t;
176+#endif
177+
178+/******************************************************************************\
179+* Data.
180+\******************************************************************************/
181+
182+#if defined(JAS_FOR_INTERNAL_USE_ONLY)
183+extern jas_allocator_t *jas_allocator;
184+extern jas_std_allocator_t jas_std_allocator;
185+extern jas_basic_allocator_t jas_basic_allocator;
186+#endif
187+
188+/******************************************************************************\
189+* Functions.
190+\******************************************************************************/
191+
192+/*!
193+@brief
194+Allocate memory.
195+
196+@details
197+This function has an identical behavior as malloc (from the C standard
198+library), except that a zero-sized allocation returns a non-null pointer
199+(assuming no out-of-memory error occurs).
200+*/
201+JAS_EXPORT
202+void *jas_malloc(size_t size);
203+
204+/*!
205+@brief
206+Free memory.
207+
208+@details
209+This function has an identical behavior as free (from the C standard library).
210+*/
211+JAS_EXPORT
212+void jas_free(void *ptr);
213+
214+/*!
215+@brief
216+Resize a block of allocated memory.
217+
218+@details
219+This function has an identical behavior as realloc (from the C standard
220+library).
221+*/
222+JAS_EXPORT
223+void *jas_realloc(void *ptr, size_t size);
224+
225+/*!
226+@brief
227+Allocate a block of memory and initialize the contents to zero.
228+
229+@details
230+This function has an identical behavior as calloc (from the C standard
231+library).
232+*/
233+JAS_EXPORT
234+void *jas_calloc(size_t num_elements, size_t element_size);
235+
236+/*!
237+@brief
238+Allocate array (with overflow checking).
239+*/
240+JAS_EXPORT
241+void *jas_alloc2(size_t num_elements, size_t element_size);
242+
243+/*!
244+@brief
245+Allocate array of arrays (with overflow checking).
246+*/
247+JAS_EXPORT
248+void *jas_alloc3(size_t num_arrays, size_t array_size, size_t element_size);
249+
250+/*!
251+@brief
252+Resize a block of allocated memory (with overflow checking).
253+*/
254+JAS_EXPORT
255+void *jas_realloc2(void *ptr, size_t num_elements, size_t element_size);
256+
257+/*!
258+@brief
259+Set the maximum memory usage allowed by the allocator wrapper.
260+
261+@param max_mem
262+The maximum amount of memory (in bytes) that the allocator can use.
263+
264+
265+@details
266+This function sets the maximum amount of memory (in bytes) that the
267+allocator wrapper is permitted to use to @c max_mem.
268+If @c max_mem is zero, no limit is imposed on the amount of memory used by
269+allocator.
270+This function can only be called if the use of the allocator wrapper
271+is enabled.
272+Calling this function if the allocator wrapper is not enabled results
273+in undefined behavior.
274+The limit on the amount of memory that the allocator can use should
275+never be set to a value less than the amount of memory currently being
276+used by the allocator (as doing so results in undefined behavior).
277+*/
278+JAS_EXPORT
279+void jas_set_max_mem_usage(size_t max_mem);
280+
281+/*!
282+@brief
283+Get the current memory usage from the allocator wrapper.
284+
285+@details
286+This function queries the amount of memory currently in use by the allocator
287+wrapper.
288+This function can only be called if the use of the allocator wrapper
289+is enabled.
290+Calling this function if the allocator wrapper is not enabled results
291+in undefined behavior.
292+*/
293+JAS_EXPORT
294+size_t jas_get_mem_usage(void);
295+
296+/*!
297+@brief
298+Initialize a memory allocator that uses malloc and related functions
299+for managing memory.
300+
301+@param allocator
302+A pointer to the storage in memory that will hold the state associated
303+with the allocator.
304+
305+@details
306+The object referenced by @c allocator must have a lifetime that extends
307+until @c jas_allocator_cleanup is called for the allocator.
308+*/
309+JAS_EXPORT
310+void jas_std_allocator_init(jas_std_allocator_t *allocator);
311+
312+/*!
313+@brief
314+Clean up an allocator that is no longer needed.
315+
316+@details
317+This function cleans up an allocator, releasing any resources associated
318+with the allocator.
319+After clean up is performed, the allocator can no longer be used.
320+*/
321+JAS_EXPORT
322+void jas_allocator_cleanup(jas_allocator_t *allocator);
323+
324+#if defined(JAS_FOR_INTERNAL_USE_ONLY)
325+
326+/* This function is for internal library use only. */
327+void jas_set_allocator(jas_allocator_t* allocator);
328+
329+/* This function is for internal library use only. */
330+void jas_basic_allocator_init(jas_basic_allocator_t *allocator,
331+ jas_allocator_t *delegate, size_t max_mem);
332+
333+#endif
334+
335+/*!
336+@brief
337+Get the total amount of memory available on the system.
338+
339+@details
340+This function may be called prior to the library being initialized.
341+In fact, this function may be useful for determining a reasonable value
342+for the memory limit setting to be used during (run-time) library
343+configuration.
344+
345+@returns
346+The total amount of memory available (in bytes) is returned, if this can
347+be determined.
348+Otherwise, zero is returned.
349+*/
350+JAS_EXPORT
351+size_t jas_get_total_mem_size(void);
352+
353+/*!
354+ * @}
355+ */
91356
92357 #ifdef __cplusplus
93358 }
jasper/jas_math.h+401−32
@@ -75,6 +75,8 @@ · 74 unmodified lines
7575
7676 /* The configuration header file should be included first. */
7777 #include <jasper/jas_config.h>
78+
79+#include <jasper/jas_compiler.h>
7880 #include <jasper/jas_types.h>
7981
8082 #ifdef __cplusplus
@@ -109,6 +111,12 @@ extern "C" { · 28 unmodified lines
109111 set to one. */
110112 #define JAS_ONES(n) \
111113 ((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))
112120
113121 /******************************************************************************\
114122 *
@@ -122,78 +130,78 @@ extern "C" { · 7 unmodified lines
122130 #endif
123131
124132 JAS_ATTRIBUTE_CONST
125−JAS_ATTRIBUTE_DISABLE_USAN
133+JAS_ATTRIBUTE_DISABLE_UBSAN
126134 inline static int jas_int_asr(int x, unsigned n)
127135 {
128136 // Ensure that the shift of a negative value appears to behave as a
129137 // signed arithmetic shift.
130138 assert(((-1) >> 1) == -1);
131− // The behavior is undefined when x is negative. */
139+ // The behavior is undefined when x is negative.
132140 // We tacitly assume the behavior is equivalent to a signed
133141 // arithmetic right shift.
134142 return x >> n;
135143 }
136144
137145 JAS_ATTRIBUTE_CONST
138−JAS_ATTRIBUTE_DISABLE_USAN
146+JAS_ATTRIBUTE_DISABLE_UBSAN
139147 inline static int jas_int_asl(int x, unsigned n)
140148 {
141149 // Ensure that the shift of a negative value appears to behave as a
142150 // signed arithmetic shift.
143151 assert(((-1) << 1) == -2);
144− // The behavior is undefined when x is negative. */
152+ // The behavior is undefined when x is negative.
145153 // We tacitly assume the behavior is equivalent to a signed
146154 // arithmetic left shift.
147155 return x << n;
148156 }
149157
150158 JAS_ATTRIBUTE_CONST
151−JAS_ATTRIBUTE_DISABLE_USAN
159+JAS_ATTRIBUTE_DISABLE_UBSAN
152160 inline static int_least32_t jas_least32_asr(int_least32_t x, unsigned n)
153161 {
154162 // Ensure that the shift of a negative value appears to behave as a
155163 // signed arithmetic shift.
156164 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.
158166 // We tacitly assume the behavior is equivalent to a signed
159167 // arithmetic right shift.
160168 return x >> n;
161169 }
162170
163171 JAS_ATTRIBUTE_CONST
164−JAS_ATTRIBUTE_DISABLE_USAN
172+JAS_ATTRIBUTE_DISABLE_UBSAN
165173 inline static int_least32_t jas_least32_asl(int_least32_t x, unsigned n)
166174 {
167175 // Ensure that the shift of a negative value appears to behave as a
168176 // signed arithmetic shift.
169177 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.
171179 // We tacitly assume the behavior is equivalent to a signed
172180 // arithmetic left shift.
173181 return x << n;
174182 }
175183
176184 JAS_ATTRIBUTE_CONST
177−JAS_ATTRIBUTE_DISABLE_USAN
185+JAS_ATTRIBUTE_DISABLE_UBSAN
178186 inline static int_fast32_t jas_fast32_asr(int_fast32_t x, unsigned n)
179187 {
180188 // Ensure that the shift of a negative value appears to behave as a
181189 // signed arithmetic shift.
182190 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.
184192 // We tacitly assume the behavior is equivalent to a signed
185193 // arithmetic right shift.
186194 return x >> n;
187195 }
188196
189197 JAS_ATTRIBUTE_CONST
190−JAS_ATTRIBUTE_DISABLE_USAN
198+JAS_ATTRIBUTE_DISABLE_UBSAN
191199 inline static int_fast32_t jas_fast32_asl(int_fast32_t x, unsigned n)
192200 {
193201 // Ensure that the shift of a negative value appears to behave as a
194202 // signed arithmetic shift.
195203 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.
197205 // We tacitly assume the behavior is equivalent to a signed
198206 // arithmetic left shift.
199207 return x << n;
@@ -210,11 +218,13 @@ inline static int_fast32_t jas_fast32_asl(int_fast32_t x, unsigned n) · 10 unmodified lines
210218 /* Compute the product of two size_t integers with overflow checking. */
211219 inline static bool jas_safe_size_mul(size_t x, size_t y, size_t *result)
212220 {
213−#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5)
221+#if jas_has_builtin(__builtin_mul_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
214222 size_t result_buffer;
215− if (!result)
216− result = &result_buffer;
217− return !__builtin_mul_overflow(x, y, result);
223+ bool valid = !__builtin_mul_overflow(x, y, &result_buffer);
224+ if (valid && result) {
225+ *result = result_buffer;
226+ }
227+ return valid;
218228 #else
219229 /* Check if overflow would occur */
220230 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
246256 /* Compute the sum of two size_t integers with overflow checking. */
247257 inline static bool jas_safe_size_add(size_t x, size_t y, size_t *result)
248258 {
249−#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5)
259+#if jas_has_builtin(__builtin_add_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
250260 size_t result_buffer;
251− if (!result)
252− result = &result_buffer;
253− return !__builtin_add_overflow(x, y, result);
261+ bool valid = !__builtin_add_overflow(x, y, &result_buffer);
262+ if (valid && result) {
263+ *result = result_buffer;
264+ }
265+ return valid;
254266 #else
255267 if (y > SIZE_MAX - x) {
256268 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
265277 /* Compute the difference of two size_t integers with overflow checking. */
266278 inline static bool jas_safe_size_sub(size_t x, size_t y, size_t *result)
267279 {
268−#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5)
280+#if jas_has_builtin(__builtin_sub_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
269281 size_t result_buffer;
270− if (!result)
271− result = &result_buffer;
272− return !__builtin_sub_overflow(x, y, result);
282+ bool valid = !__builtin_sub_overflow(x, y, &result_buffer);
283+ if (valid && result) {
284+ *result = result_buffer;
285+ }
286+ return valid;
273287 #else
274288 if (y > x) {
275289 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
285299 inline static bool jas_safe_intfast32_mul(int_fast32_t x, int_fast32_t y,
286300 int_fast32_t *result)
287301 {
288−#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5)
302+#if jas_has_builtin(__builtin_mul_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
289303 int_fast32_t result_buffer;
290− if (!result)
291− result = &result_buffer;
292− return !__builtin_mul_overflow(x, y, result);
304+ bool valid = !__builtin_mul_overflow(x, y, &result_buffer);
305+ if (valid && result) {
306+ *result = result_buffer;
307+ }
308+ return valid;
293309 #else
294310 if (x > 0) {
295311 /* 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
344360 inline static bool jas_safe_intfast32_add(int_fast32_t x, int_fast32_t y,
345361 int_fast32_t *result)
346362 {
347−#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5)
363+#if jas_has_builtin(__builtin_add_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
348364 int_fast32_t result_buffer;
349− if (!result)
350− result = &result_buffer;
351− return !__builtin_add_overflow(x, y, result);
365+ bool valid = !__builtin_add_overflow(x, y, &result_buffer);
366+ if (valid && result) {
367+ *result = result_buffer;
368+ }
369+ return valid;
352370 #else
353371 if ((y > 0 && x > INT_FAST32_MAX - y) ||
354372 (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
361379 #endif
362380 }
363381
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+
364733 #ifdef __cplusplus
365734 }
366735 #endif
jasper/jas_seq.h+271−56
@@ -77,12 +77,18 @@ · 76 unmodified lines
7777 #include <jasper/jas_config.h> /* IWYU pragma: keep */
7878
7979 #include <jasper/jas_types.h>
80+#include <jasper/jas_fix.h>
8081 #include <jasper/jas_math.h>
8182
8283 #ifdef __cplusplus
8384 extern "C" {
8485 #endif
8586
87+/*!
88+ * @addtogroup module_seq
89+ * @{
90+ */
91+
8692 /******************************************************************************\
8793 * Constants.
8894 \******************************************************************************/
@@ -95,29 +101,17 @@ extern "C" { · 6 unmodified lines
95101 \******************************************************************************/
96102
97103 /* An element in a sequence. */
98−#ifdef JAS_ENABLE_32BIT
99−typedef int_least32_t jas_seqent_t;
100−#define PRIjas_seqent PRIiLEAST32
101−#else
102−typedef int_fast32_t jas_seqent_t;
103−#define PRIjas_seqent PRIiFAST32
104−#endif
104+typedef jas_fix_t jas_seqent_t;
105+#define PRIjas_seqent PRIjas_fix
105106
106107 /* An element in a matrix. */
107−#ifdef JAS_ENABLE_32BIT
108−typedef int_least32_t jas_matent_t;
109−#else
110−typedef int_fast32_t jas_matent_t;
111−#endif
108+typedef jas_fix_t jas_matent_t;
112109
113−#ifdef JAS_ENABLE_32BIT
114−typedef int_least32_t jas_matind_t;
115−#else
116−typedef int_fast32_t jas_matind_t;
117−#endif
118−
119−/* Matrix. */
110+typedef jas_fix_t jas_matind_t;
120111
112+/*!
113+@brief Matrix type.
114+*/
121115 typedef struct {
122116
123117 /* Additional state information. */
@@ -155,53 +149,86 @@ typedef struct { · 31 unmodified lines
155149
156150 } jas_matrix_t;
157151
152+/*!
153+@struct jas_seq2d_t
154+@brief Two-dimensional sequence type.
155+*/
158156 typedef jas_matrix_t jas_seq2d_t;
157+
158+/*!
159+@struct jas_seq_t
160+@brief One-dimensional sequence type.
161+*/
159162 typedef jas_matrix_t jas_seq_t;
160163
161164 /******************************************************************************\
162165 * Functions/macros for matrix class.
163166 \******************************************************************************/
164167
165−/* Get the number of rows. */
168+/*!
169+@brief
170+Get the number of rows in a matrix.
171+*/
166172 JAS_ATTRIBUTE_PURE
167173 static inline jas_matind_t jas_matrix_numrows(const jas_matrix_t *matrix)
168174 {
169175 return matrix->numrows_;
170176 }
171177
172−/* Get the number of columns. */
178+/*!
179+@brief Get the number of columns in a matrix.
180+*/
173181 JAS_ATTRIBUTE_PURE
174182 static inline jas_matind_t jas_matrix_numcols(const jas_matrix_t *matrix)
175183 {
176184 return matrix->numcols_;
177185 }
178186
187+/*!
188+@brief
189+Get the number of elements in a matrix.
190+*/
179191 JAS_ATTRIBUTE_PURE
180192 static inline jas_matind_t jas_matrix_size(const jas_matrix_t *matrix)
181193 {
182194 return jas_matrix_numcols(matrix) * jas_matrix_numrows(matrix);
183195 }
184196
197+/*!
198+@brief
199+Test if a matrix is empty (i.e., contains no elements).
200+*/
185201 JAS_ATTRIBUTE_PURE
186202 static inline bool jas_matrix_empty(const jas_matrix_t *matrix)
187203 {
188204 return jas_matrix_numcols(matrix) == 0 || jas_matrix_numrows(matrix) == 0;
189205 }
190206
191−/* Get a matrix element. */
207+/*!
208+@brief
209+Get a matrix element.
210+*/
192211 JAS_ATTRIBUTE_PURE
193212 static inline jas_seqent_t jas_matrix_get(const jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j)
194213 {
214+ assert(i >= 0 && i < matrix->numrows_ && j >= 0 && j < matrix->numcols_);
195215 return matrix->rows_[i][j];
196216 }
197217
198−/* Set a matrix element. */
218+/*!
219+@brief
220+Set a matrix element.
221+*/
199222 static inline void jas_matrix_set(jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j, jas_seqent_t v)
200223 {
224+ assert(i >= 0 && i < matrix->numrows_ && j >= 0 && j < matrix->numcols_);
201225 matrix->rows_[i][j] = v;
202226 }
203227
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+*/
205232 JAS_ATTRIBUTE_PURE
206233 static inline jas_seqent_t jas_matrix_getv(const jas_matrix_t *matrix, jas_matind_t i)
207234 {
@@ -210,7 +237,10 @@ static inline jas_seqent_t jas_matrix_getv(const jas_matrix_t *matrix, jas_matin · 2 unmodified lines
210237 : matrix->rows_[i][0];
211238 }
212239
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+*/
214244 static inline void jas_matrix_setv(jas_matrix_t *matrix, jas_matind_t i, jas_seqent_t v)
215245 {
216246 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
219249 matrix->rows_[i][0] = v;
220250 }
221251
222−/* Get the address of an element in a matrix. */
252+/*!
253+@brief
254+Get the address of an element in a matrix.
255+*/
223256 JAS_ATTRIBUTE_PURE
224257 static inline jas_seqent_t *jas_matrix_getref(const jas_matrix_t *matrix, jas_matind_t i, jas_matind_t j)
225258 {
226259 return &matrix->rows_[i][j];
227260 }
228261
262+/*!
263+@brief
264+Get a reference to a particular row of a 2-D sequence.
265+*/
229266 JAS_ATTRIBUTE_PURE
230267 static inline jas_seqent_t *jas_matrix_getvref(const jas_matrix_t *matrix, jas_matind_t i)
231268 {
@@ -234,50 +271,100 @@ static inline jas_seqent_t *jas_matrix_getvref(const jas_matrix_t *matrix, jas_m · 2 unmodified lines
234271 : jas_matrix_getref(matrix, 0, i);
235272 }
236273
237−/* Create a matrix with the specified dimensions. */
238−JAS_DLLEXPORT jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols);
274+/*!
275+@brief
276+Create a matrix with the specified dimensions.
277+*/
278+JAS_EXPORT
279+jas_matrix_t *jas_matrix_create(jas_matind_t numrows, jas_matind_t numcols);
239280
240−/* Destroy a matrix. */
241−JAS_DLLEXPORT void jas_matrix_destroy(jas_matrix_t *matrix);
281+/*!
282+@brief
283+Destroy a matrix.
284+*/
285+JAS_EXPORT
286+void jas_matrix_destroy(jas_matrix_t *matrix);
242287
243−/* Resize a matrix. The previous contents of the matrix are lost. */
244−JAS_DLLEXPORT int jas_matrix_resize(jas_matrix_t *matrix, jas_matind_t numrows, jas_matind_t numcols);
288+/*!
289+@brief
290+Resize a matrix. The previous contents of the matrix are lost.
291+*/
292+JAS_EXPORT
293+int jas_matrix_resize(jas_matrix_t *matrix, jas_matind_t numrows, jas_matind_t numcols);
245294
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);
247301
248−/* Create a matrix that references part of another matrix. */
249−JAS_DLLEXPORT int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r0,
302+/*!
303+@brief
304+Create a matrix that references part of another matrix.
305+*/
306+JAS_EXPORT
307+int jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r0,
250308 jas_matind_t c0, jas_matind_t r1, jas_matind_t c1);
251309
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+*/
253314 static inline int jas_matrix_bindrow(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t r)
254315 {
255316 return jas_matrix_bindsub(mat0, mat1, r, 0, r, mat1->numcols_ - 1);
256317 }
257318
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+*/
259323 static inline int jas_matrix_bindcol(jas_matrix_t *mat0, jas_matrix_t *mat1, jas_matind_t c)
260324 {
261325 return jas_matrix_bindsub(mat0, mat1, 0, c, mat1->numrows_ - 1, c);
262326 }
263327
264−/* Clip the values of matrix elements to the specified range. */
265−JAS_DLLEXPORT void jas_matrix_clip(jas_matrix_t *matrix, jas_seqent_t minval,
328+/*!
329+@brief
330+Clip the values of matrix elements to the specified range.
331+*/
332+JAS_EXPORT
333+void jas_matrix_clip(jas_matrix_t *matrix, jas_seqent_t minval,
266334 jas_seqent_t maxval);
267335
268−/* Arithmetic shift left of all elements in a matrix. */
269−JAS_DLLEXPORT void jas_matrix_asl(jas_matrix_t *matrix, unsigned n);
336+/*!
337+@brief
338+Arithmetic shift left of all elements in a matrix.
339+*/
340+JAS_EXPORT
341+void jas_matrix_asl(jas_matrix_t *matrix, unsigned n);
270342
271−/* Arithmetic shift right of all elements in a matrix. */
272−JAS_DLLEXPORT void jas_matrix_asr(jas_matrix_t *matrix, unsigned n);
343+/*!
344+@brief
345+Arithmetic shift right of all elements in a matrix.
346+*/
347+JAS_EXPORT
348+void jas_matrix_asr(jas_matrix_t *matrix, unsigned n);
273349
274−/* Almost-but-not-quite arithmetic shift right of all elements in a matrix. */
275−JAS_DLLEXPORT void jas_matrix_divpow2(jas_matrix_t *matrix, unsigned n);
350+/*!
351+@brief
352+Almost-but-not-quite arithmetic shift right of all elements in a matrix.
353+*/
354+JAS_EXPORT
355+void jas_matrix_divpow2(jas_matrix_t *matrix, unsigned n);
276356
277−/* Set all elements of a matrix to the specified value. */
278−JAS_DLLEXPORT void jas_matrix_setall(jas_matrix_t *matrix, jas_seqent_t val);
357+/*!
358+@brief
359+Set all elements of a matrix to the specified value.
360+*/
361+JAS_EXPORT
362+void jas_matrix_setall(jas_matrix_t *matrix, jas_seqent_t val);
279363
280−/* The spacing between rows of a matrix. */
364+/*!
365+@brief
366+The spacing between rows of a matrix.
367+*/
281368 JAS_ATTRIBUTE_PURE
282369 static inline size_t jas_matrix_rowstep(const jas_matrix_t *matrix)
283370 {
@@ -286,7 +373,10 @@ static inline size_t jas_matrix_rowstep(const jas_matrix_t *matrix) · 2 unmodified lines
286373 : 0u;
287374 }
288375
289−/* The spacing between columns of a matrix. */
376+/*!
377+@brief
378+The spacing between columns of a matrix.
379+*/
290380 JAS_ATTRIBUTE_PURE
291381 static inline size_t jas_matrix_step(const jas_matrix_t *matrix)
292382 {
@@ -295,101 +385,181 @@ static inline size_t jas_matrix_step(const jas_matrix_t *matrix) · 2 unmodified lines
295385 : 1;
296386 }
297387
298−/* Compare two matrices for equality. */
299−JAS_DLLEXPORT int jas_matrix_cmp(jas_matrix_t *mat0, jas_matrix_t *mat1);
388+/*!
389+@brief
390+Compare two matrices for equality.
391+*/
392+JAS_EXPORT
393+int jas_matrix_cmp(jas_matrix_t *mat0, jas_matrix_t *mat1);
300394
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);
302401
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 *);
304408
409+/*!
410+@brief
411+*/
305412 JAS_ATTRIBUTE_CONST
306413 static inline jas_seqent_t jas_seqent_asl(jas_seqent_t x, unsigned n)
307414 {
415+#if 0
308416 #ifdef JAS_ENABLE_32BIT
309417 return jas_least32_asl(x, n);
310418 #else
311419 return jas_fast32_asl(x, n);
312420 #endif
421+#endif
422+ return jas_fix_asl(x, n);
313423 }
314424
425+/*!
426+@brief
427+*/
315428 JAS_ATTRIBUTE_CONST
316429 static inline jas_seqent_t jas_seqent_asr(jas_seqent_t x, unsigned n)
317430 {
431+#if 0
318432 #ifdef JAS_ENABLE_32BIT
319433 return jas_least32_asr(x, n);
320434 #else
321435 return jas_fast32_asr(x, n);
322436 #endif
437+#endif
438+ return jas_fix_asr(x, n);
323439 }
324440
325441 /******************************************************************************\
326442 * Functions/macros for 2-D sequence class.
327443 \******************************************************************************/
328444
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);
330451
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,
332458 jas_matind_t xend, jas_matind_t yend);
333459
460+/*!
461+@brief
462+Destroy a 2-D sequence.
463+*/
334464 static inline void jas_seq2d_destroy(jas_seq2d_t *s)
335465 {
336466 jas_matrix_destroy(s);
337467 }
338468
469+/*!
470+@brief
471+Get the starting x-coordinate of the sequence.
472+*/
339473 JAS_ATTRIBUTE_PURE
340474 static inline jas_matind_t jas_seq2d_xstart(const jas_seq2d_t *s)
341475 {
342476 return s->xstart_;
343477 }
344478
479+/*!
480+@brief
481+Get the starting y-coordinate of the sequence.
482+*/
345483 JAS_ATTRIBUTE_PURE
346484 static inline jas_matind_t jas_seq2d_ystart(const jas_seq2d_t *s)
347485 {
348486 return s->ystart_;
349487 }
350488
489+/*!
490+@brief
491+Get the ending x-coordinate of the sequence.
492+*/
351493 JAS_ATTRIBUTE_PURE
352494 static inline jas_matind_t jas_seq2d_xend(const jas_seq2d_t *s)
353495 {
354496 return s->xend_;
355497 }
356498
499+/*!
500+@brief
501+Get the ending y-coordinate of the sequence.
502+*/
357503 JAS_ATTRIBUTE_PURE
358504 static inline jas_matind_t jas_seq2d_yend(const jas_seq2d_t *s)
359505 {
360506 return s->yend_;
361507 }
362508
509+/*!
510+@brief
511+Get a pointer (i.e., reference) to an element of a 2-D sequence.
512+*/
363513 JAS_ATTRIBUTE_PURE
364514 static inline jas_seqent_t *jas_seq2d_getref(const jas_seq2d_t *s, jas_matind_t x, jas_matind_t y)
365515 {
366516 return jas_matrix_getref(s, y - s->ystart_, x - s->xstart_);
367517 }
368518
519+/*!
520+@brief
521+Get an element of a 2-D sequence.
522+*/
369523 JAS_ATTRIBUTE_PURE
370524 static inline jas_seqent_t jas_seq2d_get(const jas_seq2d_t *s, jas_matind_t x, jas_matind_t y)
371525 {
372526 return jas_matrix_get(s, y - s->ystart_, x - s->xstart_);
373527 }
374528
529+/*!
530+@brief
531+Get the stride between successive rows in the sequence.
532+*/
375533 JAS_ATTRIBUTE_PURE
376534 static inline size_t jas_seq2d_rowstep(const jas_seq2d_t *s)
377535 {
378536 return jas_matrix_rowstep(s);
379537 }
380538
539+/*!
540+@brief
541+Get the number of columns in the sequence.
542+*/
381543 JAS_ATTRIBUTE_PURE
382544 static inline unsigned jas_seq2d_width(const jas_seq2d_t *s)
383545 {
384546 return (unsigned)(s->xend_ - s->xstart_);
385547 }
386548
549+/*!
550+@brief
551+Get the number of rows in the sequence.
552+*/
387553 JAS_ATTRIBUTE_PURE
388554 static inline unsigned jas_seq2d_height(const jas_seq2d_t *s)
389555 {
390556 return (unsigned)(s->yend_ - s->ystart_);
391557 }
392558
559+/*!
560+@brief
561+Set the shift (i.e., starting x- and y-coordinates) of the sequence.
562+*/
393563 static inline void jas_seq2d_setshift(jas_seq2d_t *s, jas_matind_t x, jas_matind_t y)
394564 {
395565 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
398568 s->yend_ = s->ystart_ + s->numrows_;
399569 }
400570
571+/*!
572+@brief
573+Get the number of elements in the sequence.
574+*/
401575 JAS_ATTRIBUTE_PURE
402576 static inline jas_matind_t jas_seq2d_size(const jas_seq2d_t *s)
403577 {
404578 return jas_seq2d_width(s) * jas_seq2d_height(s);
405579 }
406580
581+/*!
582+@brief
583+Test if the sequence is empty (i.e., contains no elements).
584+*/
407585 JAS_ATTRIBUTE_PURE
408586 static inline bool jas_seq2d_empty(const jas_seq2d_t *s)
409587 {
410588 return jas_seq2d_width(s) == 0 || jas_seq2d_height(s) == 0;
411589 }
412590
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,
414597 jas_matind_t ystart, jas_matind_t xend, jas_matind_t yend);
415598
416599 /******************************************************************************\
417600 * Functions/macros for 1-D sequence class.
418601 \******************************************************************************/
419602
603+/*!
604+@brief
605+Create a 1-D sequence.
606+*/
420607 static inline jas_seq_t *jas_seq_create(jas_matind_t start, jas_matind_t end)
421608 {
422609 return jas_seq2d_create(start, 0, end, 1);
423610 }
424611
612+/*!
613+@brief
614+Destroy a 1-D sequence.
615+*/
425616 static inline void jas_seq_destroy(jas_seq_t *seq)
426617 {
427618 jas_seq2d_destroy(seq);
428619 }
429620
621+/*!
622+@brief
623+Set an element of a sequence.
624+*/
430625 static inline void jas_seq_set(jas_seq_t *seq, jas_matind_t i, jas_seqent_t v)
431626 {
432627 seq->rows_[0][i - seq->xstart_] = v;
433628 }
434629
630+/*!
631+@brief
632+Get a pointer (i.e., reference) to an element of a sequence.
633+*/
435634 JAS_ATTRIBUTE_PURE
436635 static inline jas_seqent_t *jas_seq_getref(const jas_seq_t *seq, jas_matind_t i)
437636 {
438637 return &seq->rows_[0][i - seq->xstart_];
439638 }
440639
640+/*!
641+@brief
642+Get an element of a sequence.
643+*/
441644 JAS_ATTRIBUTE_PURE
442645 static inline jas_seqent_t jas_seq_get(const jas_seq_t *seq, jas_matind_t i)
443646 {
444647 return seq->rows_[0][i - seq->xstart_];
445648 }
446649
650+/*!
651+@brief
652+Get the starting index of a sequence.
653+*/
447654 JAS_ATTRIBUTE_PURE
448655 static inline jas_matind_t jas_seq_start(const jas_seq_t *seq)
449656 {
450657 return seq->xstart_;
451658 }
452659
660+/*!
661+@brief
662+Get the ending index of a sequence.
663+*/
453664 JAS_ATTRIBUTE_PURE
454665 static inline jas_matind_t jas_seq_end(const jas_seq_t *seq)
455666 {
456667 return seq->xend_;
457668 }
458669
670+/*!
671+ * @}
672+ */
673+
459674 #ifdef __cplusplus
460675 }
461676 #endif
jasper/jas_stream.h+201−77
@@ -75,6 +75,10 @@ · 74 unmodified lines
7575
7676 /* The configuration header file should be included first. */
7777 #include <jasper/jas_config.h> /* IWYU pragma: export */
78+
79+#if defined(JAS_HAVE_FCNTL_H)
80+#include <fcntl.h>
81+#endif
7882 #include <jasper/jas_types.h>
7983
8084 #ifdef __cplusplus
@@ -82,7 +86,7 @@ extern "C" { · 1 unmodified line
8286 #endif
8387
8488 /*!
85− * @addtogroup iostreams
89+ * @addtogroup module_iostreams
8690 * @{
8791 */
8892
@@ -95,8 +99,6 @@ extern "C" { · 6 unmodified lines
9599 #define O_BINARY 0
96100 #endif
97101
98−#define EOF (-1)
99−
100102 /*
101103 * Stream open flags.
102104 */
@@ -176,10 +178,10 @@ typedef void jas_stream_obj_t; · 73 unmodified lines
176178 typedef struct {
177179
178180 /* 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);
180182
181183 /* 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);
183185
184186 /* Set the position for a file object. */
185187 long (*seek_)(jas_stream_obj_t *obj, long offset, int origin);
@@ -189,8 +191,15 @@ typedef struct { · 3 unmodified lines
189191
190192 } jas_stream_ops_t;
191193
192−/*
193− * Stream object.
194+/*!
195+@brief
196+I/O stream object.
197+
198+@warning
199+Library users should never directly access any of the members of this
200+class.
201+The functions/macros provided by the JasPer library API should always
202+be used.
194203 */
195204
196205 typedef struct {
@@ -248,6 +257,7 @@ typedef struct { · 51 unmodified lines
248257 typedef struct {
249258 int fd;
250259 int flags;
260+ char pathname[L_tmpnam + 1];
251261 } jas_stream_fileobj_t;
252262
253263 /* Delete underlying file object upon stream close. */
@@ -268,10 +278,10 @@ typedef struct { · 14 unmodified lines
268278 size_t bufsize_;
269279
270280 /* The length of the file. */
271− uint_fast32_t len_;
281+ size_t len_;
272282
273283 /* The seek position. */
274− uint_fast32_t pos_;
284+ size_t pos_;
275285
276286 /* Is the buffer growable? */
277287 int growable_;
@@ -299,7 +309,7 @@ C standard library. · 21 unmodified lines
299309 Upon success, a pointer to the opened stream is returned.
300310 Otherwise, a null pointer is returned.
301311 */
302−JAS_DLLEXPORT
312+JAS_EXPORT
303313 jas_stream_t *jas_stream_fopen(const char *filename, const char *mode);
304314
305315 /*!
@@ -325,26 +335,20 @@ If buffer is not 0: · 19 unmodified lines
325335 buffer_size (which, in this case, is not currently allowed to be zero) is
326336 the size of the (nongrowable) buffer pointed to by buffer.
327337 </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.
338338 */
339−JAS_DLLEXPORT
340−jas_stream_t *jas_stream_memopen(char *buffer, int buffer_size);
339+JAS_EXPORT
340+jas_stream_t *jas_stream_memopen(char *buffer, size_t buffer_size);
341341
342342 /*!
343−@warning
344−This function will be renamed jas_stream_memopen in a future release.
343+@brief
344+Do not use.
345+@deprecated
345346 Do not use this function.
347+This function is deprecated.
348+Use jas_stream_memopen instead.
346349 */
347−JAS_DLLEXPORT
350+JAS_DEPRECATED
351+JAS_EXPORT
348352 jas_stream_t *jas_stream_memopen2(char *buffer, size_t buffer_size);
349353
350354 /*!
@@ -361,9 +365,51 @@ in the C standard library. · 10 unmodified lines
361365 Upon success, a pointer to the opened stream is returned.
362366 Otherwise, a null pointer is returned.
363367 */
364−JAS_DLLEXPORT
368+JAS_EXPORT
365369 jas_stream_t *jas_stream_fdopen(int fd, const char *mode);
366370
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+
367413 /*!
368414 @brief Close a stream.
369415
@@ -382,7 +428,7 @@ can fail is due to an I/O error when flushing buffered output. · 12 unmodified lines
382428 If no errors are encountered when closing the stream, 0 is returned.
383429 Otherwise, a nonzero value is returned.
384430 */
385−JAS_DLLEXPORT
431+JAS_EXPORT
386432 int jas_stream_close(jas_stream_t *stream);
387433
388434 /******************************************************************************\
@@ -404,6 +450,7 @@ A nonzero value indicates that the stream has encountered EOF. · 15 unmodified lines
404450
405451 /*!
406452 @brief Get the error indicator for a stream.
453+
407454 @param stream
408455 The stream whose error indicator is to be queried.
409456 @return
@@ -417,6 +464,7 @@ Note that EOF is not an error. · 7 unmodified lines
417464
418465 /*!
419466 @brief Clear the error indicator for a stream.
467+
420468 @param stream
421469 The stream whose error indicator is to be cleared.
422470
@@ -441,6 +489,7 @@ effectively infinite). · 18 unmodified lines
441489
442490 /*!
443491 @brief Set the read/write limit for a stream.
492+
444493 @param stream
445494 A pointer to the stream whose read/write limit is to be set.
446495 @param rwlimit
@@ -453,7 +502,7 @@ A negative read/write limit is treated as if it were infinity · 6 unmodified lines
453502 @return
454503 The old read/write limit is returned.
455504 */
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);
457506
458507 /*!
459508 @brief Get the read/write count for a stream.
@@ -470,6 +519,7 @@ This operation cannot fail. · 10 unmodified lines
470519
471520 /*!
472521 @brief Set the read/write count for a stream.
522+
473523 @param stream
474524 A pointer to the stream whose read/write count is to be set.
475525 @param rw_count
@@ -480,7 +530,8 @@ This operation cannot fail. · 4 unmodified lines
480530 @todo
481531 TODO/FIXME: Should this macro evaluate to void?
482532 */
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);
484535
485536 /******************************************************************************\
486537 * 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
491542 /*!
492543 @brief jas_stream_getc
493544 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.
494552 */
495553 #define jas_stream_getc(stream) jas_stream_getc_func(stream)
496554 #else
@@ -502,6 +560,16 @@ Read a character from a stream. · 5 unmodified lines
502560 /*!
503561 @brief jas_stream_putc
504562 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.
505573 */
506574 #define jas_stream_putc(stream, c) jas_stream_putc_func(stream, c)
507575 #else
@@ -525,6 +593,9 @@ stream @c stream into the buffer starting at @c buffer. · 17 unmodified lines
525593 The number of characters read can be less than @c count, due to
526594 end-of-file (EOF) or an I/O error.
527595
596+(This function is analogous to fread with the two read-count
597+parameters combined into a single size.)
598+
528599 @return
529600 The number of characters read is returned.
530601 In the case that the number of characters read is less than @c count,
@@ -535,18 +606,16 @@ to distinguish between: · 4 unmodified lines
535606 <li>a failure due to the read/write limit being exceeded
536607 <li>EOF.
537608 </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.)
539612
540−@warning
541−TODO/FIXME/CHECK: jas_stream_error should be true if RWLIMIT exceeded?
542−or need a jas_stream_rwlimit predicate?
543−
544−@warning
545−TODO/FIXME: In the future, the type of the count parameter and the
546−return type will be changed to size_t.
613+@todo
614+TODO: should jas_stream_error be true if RWLIMIT exceeded?
615+or maybe introduce a jas_stream_rwlimit predicate?
547616 */
548−JAS_DLLEXPORT
549−unsigned jas_stream_read(jas_stream_t *stream, void *buffer, unsigned count);
617+JAS_EXPORT
618+size_t jas_stream_read(jas_stream_t *stream, void *buffer, size_t count);
550619
551620 /*!
552621 @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
569638 or EOF.
570639
571640 @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+
573644 */
574−JAS_DLLEXPORT
645+JAS_EXPORT
575646 unsigned jas_stream_peek(jas_stream_t *stream, void *buffer, size_t count);
576647
577648 /*!
@@ -590,6 +661,9 @@ from the buffer starting at @c buffer to the stream @c stream. · 12 unmodified lines
590661 The number of characters written can be less than @c count due to
591662 an I/O error or the read/write limit being exceeded.
592663
664+(This function is analogous to fwrite with the two write-count
665+parameters combined into a single size.)
666+
593667 @return
594668 Upon success, the number of characters successfully written is returned.
595669 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
599673 <li>failure due to an I/O error
600674 <li>failure due to the read/write limit being exceeded
601675 </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.
607676 */
608−JAS_DLLEXPORT
609−unsigned jas_stream_write(jas_stream_t *stream, const void *buffer,
610− unsigned count);
677+JAS_EXPORT
678+size_t jas_stream_write(jas_stream_t *stream, const void *buffer,
679+ size_t count);
611680
612681 /*!
613682 @brief Write formatted output to a stream.
@@ -630,7 +699,7 @@ If an error is encountered, a negative value is returned. · 16 unmodified lines
630699 I think that the return type of int is okay here.
631700 It is consistent with printf and friends.
632701 */
633−JAS_DLLEXPORT
702+JAS_EXPORT
634703 int jas_stream_printf(jas_stream_t *stream, const char *format, ...);
635704
636705 /*!
@@ -644,11 +713,14 @@ A pointer to a null-terminated string for output. · 7 unmodified lines
644713 @details
645714 The null character is not output.
646715
716+(This function is analogous to fputs for C standard library streams.)
717+
647718 @return
648719 Upon success, a nonnegative value is returned.
649720 Upon failure, a negative value is returned.
650721 */
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);
652724
653725 /*!
654726 @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
666738 Since the buffer may be too small to hold the input,
667739 this operation can fail due to attempted buffer overrun.
668740
741+(This function is analogous to fgets for C standard library streams.)
742+
669743 @return
670744 If the operation fails (e.g., due to an I/O error or attempted buffer overrun),
671745 a null pointer is returned.
672746 Otherwise, buffer is returned.
673747 */
674−JAS_DLLEXPORT char *
675−jas_stream_gets(jas_stream_t *stream, char *buffer, int buffer_size);
748+JAS_EXPORT
749+char *jas_stream_gets(jas_stream_t *stream, char *buffer, int buffer_size);
676750
677751 /*!
678752 @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
719793 Upon success, zero is returned.
720794 If the specified character cannot be pushed back, a negative value is returned.
721795 */
722−JAS_DLLEXPORT int
723−jas_stream_ungetc(jas_stream_t *stream, int c);
796+JAS_EXPORT
797+int jas_stream_ungetc(jas_stream_t *stream, int c);
724798
725799 /******************************************************************************\
726800 * 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
741815 positive value is returned.
742816 Otherwise, 0 is returned.
743817 */
744−JAS_ATTRIBUTE_PURE JAS_DLLEXPORT
818+JAS_EXPORT
819+JAS_ATTRIBUTE_PURE
745820 int jas_stream_isseekable(jas_stream_t *stream);
746821
747822 /*!
@@ -763,37 +838,46 @@ in a similar fashion as the fseek function in the C standard library · 15 unmodified lines
763838 Upon success, the new stream position is returned.
764839 Upon failure, a negative value is returned.
765840 */
766−JAS_DLLEXPORT
841+JAS_EXPORT
767842 long jas_stream_seek(jas_stream_t *stream, long offset, int origin);
768843
769844 /*!
770845 @brief Get the current position within the stream.
846+
771847 @param stream
772848 A pointer to the stream whose current position is to be queried.
773849
774850 @details
775851 The current position of the stream is returned.
776852
853+(This function is analogous to ftell for C standard library streams.)
854+
777855 @return
778856 Upon success, the current stream position is returned.
779857 If an error is encountered, a negative value is returned.
780858 */
781−JAS_ATTRIBUTE_PURE JAS_DLLEXPORT
859+JAS_EXPORT
782860 long jas_stream_tell(jas_stream_t *stream);
783861
784862 /*!
785863 @brief Seek to the beginning of a stream.
864+
786865 @param stream
787866 A pointer to the stream whose position is to be set.
867+
788868 @details
789869 The stream position is set to the start of the stream.
790870 This function is equivalent to returning the value
791871 of jas_stream_seek(stream, 0, SEEK_SET).
872+
873+(This function is analogous to frewind for C standard library streams.)
874+
792875 @return
793876 Upon success, the new stream position is returned.
794877 Otherwise, a negative value is returned.
795878 */
796−JAS_DLLEXPORT int jas_stream_rewind(jas_stream_t *stream);
879+JAS_EXPORT
880+int jas_stream_rewind(jas_stream_t *stream);
797881
798882 /******************************************************************************\
799883 * Macros/functions for flushing.
@@ -801,15 +885,21 @@ JAS_DLLEXPORT int jas_stream_rewind(jas_stream_t *stream); · 1 unmodified line
801885
802886 /*!
803887 @brief Flush any pending output to a stream.
888+
804889 @param stream
805890 A pointer to the stream for which output should be flushed.
891+
806892 @details
807893 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+
808897 @return
809898 Upon success, zero is returned.
810899 Otherwise, a negative value is returned.
811900 */
812−JAS_DLLEXPORT int jas_stream_flush(jas_stream_t *stream);
901+JAS_EXPORT
902+int jas_stream_flush(jas_stream_t *stream);
813903
814904 /******************************************************************************\
815905 * Miscellaneous macros/functions.
@@ -828,14 +918,50 @@ The number of characters to copy. · 12 unmodified lines
828918 @details
829919 The function copies the specified number of characters from the
830920 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.
831927
832928 @return
833929 Upon success, 0 is returned; otherwise, -1 is returned.
834930
835931 @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?
837936 */
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);
839965
840966 /*!
841967 @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
855981 will be less than count.
856982 To distinguish EOF from an I/O error, jas_stream_eof() and jas_stream_error()
857983 can be used.
858−
859−@warning
860−TODO/FIXME: count be size_t and return type should be ssize_t
861984 */
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);
863987
864988 /*!
865989 @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
8811005 returned.
8821006 If this value is less than the specified count, an error must have
8831007 occurred.
884−
885−@todo
886−TODO: should the count be size_t; return type maybe size_t?
8871008 */
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);
8891011
8901012 /*!
8911013 @brief Get the size of the file associated with the specified stream.
8921014
8931015 @param stream
1016+A pointer to the stream.
8941017
8951018 @details
8961019 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
9011024 Upon success, the size of the stream is returned.
9021025 If an error occurs, a negative value is returned.
9031026
904−@warning
905−TODO/FIXME: the return type should be ssize_t?
1027+@todo
1028+Should the return type be long or ssize_t? long is consistent with the
1029+type used for seek offsets.
9061030 */
907−JAS_ATTRIBUTE_PURE JAS_DLLEXPORT
1031+JAS_EXPORT
9081032 long jas_stream_length(jas_stream_t *stream);
9091033
9101034 /******************************************************************************\
@@ -917,10 +1041,10 @@ directly, you will die a horrible, miserable, and painful death! */ · 6 unmodified lines
9171041 /* These prototypes need to be here for the sake of the stream_getc and
9181042 stream_putc macros. */
9191043 /* Library users must not invoke these functions directly. */
920−JAS_DLLEXPORT int jas_stream_fillbuf(jas_stream_t *stream, int getflag);
921−JAS_DLLEXPORT int jas_stream_flushbuf(jas_stream_t *stream, int c);
922−JAS_DLLEXPORT int jas_stream_getc_func(jas_stream_t *stream);
923−JAS_DLLEXPORT int jas_stream_putc_func(jas_stream_t *stream, int c);
1044+JAS_EXPORT int jas_stream_fillbuf(jas_stream_t *stream, int getflag);
1045+JAS_EXPORT int jas_stream_flushbuf(jas_stream_t *stream, int c);
1046+JAS_EXPORT int jas_stream_getc_func(jas_stream_t *stream);
1047+JAS_EXPORT int jas_stream_putc_func(jas_stream_t *stream, int c);
9241048
9251049 /* Read a character from a stream. */
9261050 static inline int jas_stream_getc2(jas_stream_t *stream)
jasper/jas_string.h+150−0
@@ -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
jasper/jas_thread.h+795−0
@@ -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
jasper/jas_tvp.h+200−0
@@ -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
jasper/jas_types.h+109−35
@@ -72,47 +72,71 @@ · 71 unmodified lines
7272 /* The configuration header file should be included first. */
7373 #include <jasper/jas_config.h>
7474
75−#define INT_MAX 0x7fffffff
76−#define UINT_FAST32_MAX 0xffffffff
77−#define SIZE_MAX UINT_FAST32_MAX
78−#define INT_FAST32_MIN ((s32int)0x80000000)
79−#define INT_FAST32_MAX INT_MAX
80−#define LONG_MAX INT_MAX
81−
82−typedef s8int int_least8_t;
83−typedef s16int int_fast16_t;
84−typedef s32int int_fast32_t;
85−typedef s32int int_least32_t;
86−typedef s64int int_fast64_t;
87−
88−typedef u8int uint_least8_t;
89−typedef u8int uint_fast8_t;
90−typedef u16int uint_fast16_t;
91−typedef u16int uint_least16_t;
92−typedef u32int uint_fast32_t;
93−typedef u32int uint_least32_t;
94−typedef u64int uint_least64_t;
95−typedef u64int uint_fast64_t;
96−
97−typedef unsigned char jas_uchar;
98−typedef unsigned int jas_uint;
99−typedef unsigned long jas_ulong;
100−typedef long long jas_longlong;
101−typedef unsigned long long jas_ulonglong;
102−
103−typedef enum { false, true } bool;
75+#if defined(JAS_HAVE_SYS_TYPES_H)
76+#include <sys/types.h> /* IWYU pragma: export */
77+#endif
78+
79+#ifdef __cplusplus
80+extern "C" {
81+#endif
82+
83+#define jas_uchar unsigned char
84+#define jas_uint unsigned int
85+#define jas_ulong unsigned long
86+#define jas_longlong long long
87+#define jas_ulonglong unsigned long long
88+
89+#if !defined(JAS_NO_SET_SSIZE_T)
90+# if !defined(SSIZE_MAX)
91+# if (JAS_SIZEOF_INT == JAS_SIZEOF_SIZE_T)
92+# define ssize_t int
93+# define SSIZE_MAX INT_MAX
94+# elif (JAS_SIZEOF_LONG == JAS_SIZEOF_SIZE_T)
95+# define ssize_t long
96+# define SSIZE_MAX LONG_MAX
97+# else
98+# define ssize_t jas_longlong
99+# define SSIZE_MAX LLONG_MAX
100+# endif
101+# endif
102+#endif
103+
104+#if 0
105+#if defined(JAS_HAVE_SSIZE_T)
106+#define jas_ssize_t ssize_t
107+#define JAS_SSIZE_MAX SSIZE_MAX
108+#else
109+#define jas_ssize_t jas_longlong
110+#define JAS_SSIZE_MAX LLONG_MAX
111+#endif
112+#endif
113+
114+#if defined(_MSC_VER) && (_MSC_VER < 1800)
115+#define bool int
116+#define false 0
117+#define true 1
104118
105119 #define PRIxFAST32 "x"
106120 #define PRIxFAST16 PRIxFAST32
107121 #define PRIuFAST32 "u"
108122 #define PRIuFAST16 PRIuFAST32
109123 #define PRIiFAST32 "i"
110−#define PRIiLEAST32 PRIiFAST32
111−#define PRIxLEAST16 "x"
112−#define PRIdPTR "lld"
113−#define _HUGE_ENUF 1e+300
124+#ifdef _WIN64
125+ #define PRIdPTR "lld"
126+#else
127+ #define PRIdPTR "d"
128+#endif
129+
130+#ifndef _HUGE_ENUF
131+ #define _HUGE_ENUF 1e+300
132+#endif
133+
114134 #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
115135
136+#define strtoull _strtoui64
137+
138+#endif
139+
116140 /* The below macro is intended to be used for type casts. By using this
117141 macro, type casts can be easily located in the source code with
118142 tools like "grep". */
@@ -123,10 +147,60 @@ typedef enum { false, true } bool; · 4 unmodified lines
123147 /* NOTE: This could underestimate the size on some exotic architectures. */
124148 #define JAS_UINTFAST32_NUMBITS (8 * sizeof(uint_fast32_t))
125149
126−#ifdef __cplusplus
127−extern "C" {
150+#if 0
151+#if defined(JAS_HAVE_MAX_ALIGN_T)
152+#define jas_max_align_t max_align_t
153+#else
154+#define jas_max_align_t long double
155+#endif
156+#endif
157+
158+/*
159+Assume that a compiler claiming to be compliant with C11 or a later version
160+of the C standard provides a suitable definition of max_align_t.
161+The JAS_NO_SET_MAX_ALIGN_T preprocessor symbol can be used to override
162+this behavior.
163+*/
164+#if defined(JAS_NO_SET_MAX_ALIGN_T)
165+ /*
166+ The user of this header is assuming responsibility for providing a
167+ suitable definition for max_align_t.
168+ */
169+#elif defined(_MSC_VER)
170+ /*
171+ Define max_align_t as a preprocessor symbol since using typedef will
172+ cause problems.
173+ */
174+# define max_align_t long double
175+#elif !(defined(__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 201112L))
176+# define max_align_t long double
128177 #endif
129178
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+
130204 #ifdef __cplusplus
131205 }
132206 #endif
jasper/jas_version.h+113−0
@@ -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
jasper/jasper.h+6−0
@@ -73,6 +73,7 @@ · 72 unmodified lines
7373 #include <jasper/jas_config.h>
7474
7575 #include <jasper/jas_types.h>
76+#include <jasper/jas_version.h>
7677
7778 #include <jasper/jas_init.h>
7879 #include <jasper/jas_cm.h>
@@ -84,6 +85,11 @@ · 5 unmodified lines
8485 #include <jasper/jas_malloc.h>
8586 #include <jasper/jas_seq.h>
8687 #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>
8793
8894 #pragma lib "./libjp2.a"
8995
jp2.c+4−1
@@ -34,7 +34,10 @@ main(int argc, char **argv) · 33 unmodified lines
3434 usage();
3535
3636 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();
3841
3942 if((cp = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)) == nil){
4043 werrstr("failed to create color space");
jp2_cod.c+160−50
@@ -75,13 +75,12 @@ · 74 unmodified lines
7575
7676 #include "jasper/jas_malloc.h"
7777 #include "jasper/jas_debug.h"
78+#include "jasper/jas_types.h"
7879
7980 /******************************************************************************\
8081 * Function prototypes.
8182 \******************************************************************************/
8283
83−#define ONES(n) ((1 << (n)) - 1)
84−
8584 static const jp2_boxinfo_t *jp2_boxinfolookup(int type);
8685
8786 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
9594
9695 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val);
9796
97+static void jp2_box_dump(const jp2_box_t *box);
98+
9899 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in);
99100 static int jp2_jp_putdata(const jp2_box_t *box, jas_stream_t *out);
100101 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
106107 static int jp2_bpcc_putdata(const jp2_box_t *box, jas_stream_t *out);
107108 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in);
108109 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);
109111 static void jp2_colr_destroy(jp2_box_t *box);
110112 static void jp2_cdef_destroy(jp2_box_t *box);
111113 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in);
112114 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);
113116 static void jp2_cmap_destroy(jp2_box_t *box);
114117 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in);
115118 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);
116120 static void jp2_pclr_destroy(jp2_box_t *box);
117121 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in);
118122 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+}
119133
120134 /******************************************************************************\
121135 * Local data.
122136 \******************************************************************************/
123137
124138 static const jp2_boxinfo_t jp2_boxinfos[] = {
125− {JP2_BOX_JP, 0, "JP", {0, 0, jp2_jp_getdata, jp2_jp_putdata}},
126− {JP2_BOX_FTYP, 0, "FTYP", {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata}},
127− {JP2_BOX_JP2H, JP2_BOX_SUPER, "JP2H", {0, 0, 0, 0}},
128− {JP2_BOX_IHDR, 0, "IHDR", {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata}},
129− {JP2_BOX_BPCC, 0, "BPCC", {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata}},
130− {JP2_BOX_COLR, 0, "COLR", {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata}},
131− {JP2_BOX_PCLR, 0, "PCLR", {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata}},
132− {JP2_BOX_CMAP, 0, "CMAP", {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata}},
133− {JP2_BOX_CDEF, 0, "CDEF", {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata}},
134− {JP2_BOX_RES, JP2_BOX_SUPER, "RES", {0, 0, 0, 0}},
135− {JP2_BOX_RESC, 0, "RESC", {0, 0, 0, 0}},
136− {JP2_BOX_RESD, 0, "RESD", {0, 0, 0, 0}},
137− {JP2_BOX_JP2C, JP2_BOX_NODATA, "JP2C", {0, 0, 0, 0}},
138− {JP2_BOX_JP2I, 0, "JP2I", {0, 0, 0, 0}},
139− {JP2_BOX_XML, 0, "XML", {0, 0, 0, 0}},
140− {JP2_BOX_UUID, 0, "UUID", {0, 0, 0, 0}},
141− {JP2_BOX_UINF, JP2_BOX_SUPER, "UINF", {0, 0, 0, 0}},
142− {JP2_BOX_ULST, 0, "ULST", {0, 0, 0, 0}},
143− {JP2_BOX_URL, 0, "URL", {0, 0, 0, 0}},
144− {0, 0, 0, {0, 0, 0, 0}},
139+ {JP2_BOX_JP, 0, "JP",
140+ {0, 0, jp2_jp_getdata, jp2_jp_putdata, 0}},
141+ {JP2_BOX_FTYP, 0, "FTYP",
142+ {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata, 0}},
143+ {JP2_BOX_JP2H, JP2_BOX_SUPER, "JP2H",
144+ {0, 0, 0, 0, 0}},
145+ {JP2_BOX_IHDR, 0, "IHDR",
146+ {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata, 0}},
147+ {JP2_BOX_BPCC, 0, "BPCC",
148+ {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata, 0}},
149+ {JP2_BOX_COLR, 0, "COLR",
150+ {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata, jp2_colr_dumpdata}},
151+ {JP2_BOX_PCLR, 0, "PCLR",
152+ {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata, jp2_pclr_dumpdata}},
153+ {JP2_BOX_CMAP, 0, "CMAP",
154+ {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata, jp2_cmap_dumpdata}},
155+ {JP2_BOX_CDEF, 0, "CDEF",
156+ {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata, jp2_cdef_dumpdata}},
157+ {JP2_BOX_RES, JP2_BOX_SUPER, "RES",
158+ {0, 0, 0, 0, 0}},
159+ {JP2_BOX_RESC, 0, "RESC",
160+ {0, 0, 0, 0, 0}},
161+ {JP2_BOX_RESD, 0, "RESD",
162+ {0, 0, 0, 0, 0}},
163+ {JP2_BOX_JP2C, JP2_BOX_NODATA, "JP2C",
164+ {0, 0, 0, 0, 0}},
165+ {JP2_BOX_JP2I, 0, "JP2I",
166+ {0, 0, 0, 0, 0}},
167+ {JP2_BOX_XML, 0, "XML",
168+ {0, 0, 0, 0, 0}},
169+ {JP2_BOX_UUID, 0, "UUID",
170+ {0, 0, 0, 0, 0}},
171+ {JP2_BOX_UINF, JP2_BOX_SUPER, "UINF",
172+ {0, 0, 0, 0, 0}},
173+ {JP2_BOX_ULST, 0, "ULST",
174+ {0, 0, 0, 0, 0}},
175+ {JP2_BOX_URL, 0, "URL",
176+ {0, 0, 0, 0, 0}},
177+ {0, 0, 0, {0, 0, 0, 0, 0}},
145178 };
146179
147180 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}
149182 };
150183
151184 /******************************************************************************\
@@ -239,19 +272,19 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 87 unmodified lines
239272 boxinfo = jp2_boxinfolookup(box->type);
240273 box->info = boxinfo;
241274 box->len = len;
242− JAS_DBGLOG(10, (
275+ JAS_LOGDEBUGF(10,
243276 "preliminary processing of JP2 box: "
244277 "type=%c%s%c (0x%08x); length=%"PRIuFAST32"\n",
245278 '"', boxinfo->name, '"', box->type, box->len
246− ));
279+ );
247280 size_t hdrlen;
248281 if (box->len == 1) {
249− JAS_DBGLOG(10, ("big length\n"));
282+ JAS_LOGDEBUGF(10, "big length\n");
250283 if (jp2_getuint64(in, &extlen)) {
251284 goto error;
252285 }
253286 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");
255288 goto error;
256289 }
257290 box->len = extlen;
@@ -262,10 +295,9 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 4 unmodified lines
262295 if (box->len != 0 && box->len < 8) {
263296 goto error;
264297 }
265− if (box->len > 0x7fffffffUL) {
266− /* this limit is the largest value which can
267− be passed to jas_stream_copy() without
268− overflowing */
298+ if (box->len > SSIZE_MAX) {
299+ /* This limit is the largest value which can be passed to
300+ jas_stream_copy() without overflowing. */
269301 goto error;
270302 }
271303
@@ -280,7 +312,7 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 8 unmodified lines
280312 goto error;
281313 }
282314 if (jas_stream_copy(tmpstream, in, box->datalen)) {
283− jas_eprintf("cannot copy box data\n");
315+ jas_logerrorf("cannot copy box data\n");
284316 goto error;
285317 }
286318 jas_stream_rewind(tmpstream);
@@ -291,13 +323,17 @@ jp2_box_t *jp2_box_get(jas_stream_t *in) · 4 unmodified lines
291323
292324 if (box->ops->getdata) {
293325 if ((*box->ops->getdata)(box, tmpstream)) {
294− jas_eprintf("cannot parse box data\n");
326+ jas_logerrorf("cannot parse box data\n");
295327 goto error;
296328 }
297329 }
298330 jas_stream_close(tmpstream);
299331 }
300332
333+ if (jas_get_debug_level() >= 1) {
334+ jp2_box_dump(box);
335+ }
336+
301337 return box;
302338
303339 error:
@@ -310,6 +346,19 @@ error: · 6 unmodified lines
310346 return 0;
311347 }
312348
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+
313362 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in)
314363 {
315364 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
376425 return 0;
377426 }
378427
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+
379442 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in)
380443 {
381444 if (box->datalen < 3)
@@ -388,23 +451,33 @@ static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) · 6 unmodified lines
388451
389452 if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) ||
390453 jp2_getuint8(in, &colr->approx)) {
454+ jas_logerrorf("cannot get COLR box data\n");
391455 return -1;
392456 }
393457 switch (colr->method) {
394458 case JP2_COLR_ENUM:
395459 if (jp2_getuint32(in, &colr->csid)) {
460+ jas_logerrorf("cannot get CSID\n");
396461 return -1;
397462 }
398463 break;
399464 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);
400470 colr->iccplen = box->datalen - 3;
401− if (colr->iccplen > 1024 * 1024)
471+#if 0
472+ if (colr->iccplen > 1024 * 1024) {
402473 /* refuse to read ICC profiles larger than 1
403474 MB (I have no idea how large ICC profiles
404475 can get, but I believe this limit might be
405476 very pessimistic and should be lowered
406477 further) */
407478 return -1;
479+ }
480+#endif
408481 if (!(colr->iccp = jas_alloc2(colr->iccplen, sizeof(uint_fast8_t)))) {
409482 return -1;
410483 }
@@ -416,6 +489,17 @@ static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) · 5 unmodified lines
416489 return 0;
417490 }
418491
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+
419503 static void jp2_colr_destroy(jp2_box_t *box)
420504 {
421505 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
472556 box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN(false);
473557 jas_stream_rewind(tmpstream);
474558 }
475− extlen = (box->len >= (((uint_fast64_t)1) << 32)) != 0;
559+ extlen = 0;
476560 if (jp2_putuint32(out, extlen ? 1 : box->len)) {
477561 goto error;
478562 }
@@ -488,7 +572,7 @@ int jp2_box_put(jp2_box_t *box, jas_stream_t *out) · 9 unmodified lines
488572 if (dataflag) {
489573 if (jas_stream_copy(out, tmpstream, box->len -
490574 JP2_BOX_HDRLEN(false))) {
491− jas_eprintf("cannot copy box data\n");
575+ jas_logerrorf("cannot copy box data\n");
492576 goto error;
493577 }
494578 jas_stream_close(tmpstream);
@@ -703,10 +787,6 @@ static const jp2_boxinfo_t *jp2_boxinfolookup(int type) · 208 unmodified lines
703787 return &jp2_boxinfo_unk;
704788 }
705789
706−
707−
708−
709−
710790 static void jp2_cmap_destroy(jp2_box_t *box)
711791 {
712792 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
746826
747827 static int jp2_cmap_putdata(const jp2_box_t *box, jas_stream_t *out)
748828 {
749− /* Eliminate compiler warning about unused variables. */
750− USED(box);
751− USED(out);
752−
829+ JAS_UNUSED(box);
830+ JAS_UNUSED(out);
753831 return -1;
754832 }
755833
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+
756846 static void jp2_pclr_destroy(jp2_box_t *box)
757847 {
758848 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
813903 #if 0
814904 const jp2_pclr_t *pclr = &box->data.pclr;
815905 #endif
816− /* Eliminate warning about unused variable. */
817− USED(box);
818− USED(out);
906+ JAS_UNUSED(box);
907+ JAS_UNUSED(out);
819908 return -1;
820909 }
821910
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+
822926 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val)
823927 {
824928 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
828932
829933 m = (n + 7) / 8;
830934
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+
831941 v = 0;
832942 for (i = 0; i < m; ++i) {
833943 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
835945 }
836946 v = (v << 8) | c;
837947 }
838− v &= ONES(n);
948+ v &= ones(n);
839949 if (s) {
840950 int sb;
841− sb = v & (1 << (8 * m - 1));
842− *val = ((~v) + 1) & ONES(8 * m);
951+ sb = v & (JAS_CAST(uint_fast32_t, 1) << (8 * m - 1));
952+ *val = ((~v) + 1) & ones(8 * m);
843953 if (sb) {
844954 *val = -*val;
845955 }
jp2_cod.h+2−2
@@ -245,7 +245,7 @@ typedef struct { · 244 unmodified lines
245245 uint_fast32_t type;
246246
247247 /* The length of the box including the (variable-length) header. */
248− uint_fast64_t len;
248+ uint_fast32_t len;
249249
250250 /* The length of the box data. */
251251 uint_fast32_t datalen;
@@ -268,6 +268,7 @@ typedef struct jp2_boxops_s { · 16 unmodified lines
268268 void (*destroy)(jp2_box_t *box);
269269 int (*getdata)(jp2_box_t *box, jas_stream_t *in);
270270 int (*putdata)(const jp2_box_t *box, jas_stream_t *out);
271+ void (*dumpdata)(const jp2_box_t *box);
271272 } jp2_boxops_t;
272273
273274 /******************************************************************************\
@@ -308,5 +309,4 @@ static inline uint_least8_t JP2_BPCTODTYPE(uint_least8_t bpc) · 34 unmodified lines
308309
309310 const jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo);
310311
311−
312312 #endif
jp2_dec.c+113−59
@@ -81,7 +81,9 @@ · 80 unmodified lines
8181 #include "jasper/jas_malloc.h"
8282 #include "jasper/jas_types.h"
8383
84−#define JP2_VALIDATELEN (JAS_MIN(JP2_JP_LEN + 16, JAS_STREAM_MAXPUTBACK))
84+/******************************************************************************\
85+* Function prototypes.
86+\******************************************************************************/
8587
8688 static jp2_dec_t *jp2_dec_create(void);
8789 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
104106 unsigned int i;
105107 jp2_cmap_t *cmapd;
106108 jp2_pclr_t *pclrd;
109+#if 0
110+ /* The following code appears to no longer be needed. */
107111 jp2_cdef_t *cdefd;
112+#endif
108113 unsigned int channo;
109114 int newcmptno;
110115 int_fast32_t *lutents;
@@ -117,8 +122,9 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 6 unmodified lines
117122 jas_iccprof_t *iccprof;
118123
119124 box = 0;
125+ image = 0;
120126
121− JAS_DBGLOG(100, ("jp2_decode(%p, \"%s\")\n", in, optstr));
127+ JAS_LOGDEBUGF(100, "jp2_decode(%p, \"%s\")\n", in, optstr);
122128
123129 if (!(dec = jp2_dec_create())) {
124130 goto error;
@@ -126,25 +132,28 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line
126132
127133 /* Get the first box. This should be a JP box. */
128134 if (!(box = jp2_box_get(in))) {
129− jas_eprintf("error: cannot get box\n");
135+ jas_logerrorf("error: cannot get box\n");
130136 goto error;
131137 }
132138 if (box->type != JP2_BOX_JP) {
133− jas_eprintf("error: expecting signature box\n");
139+ jas_logerrorf("error: expecting signature box\n");
134140 goto error;
135141 }
136142 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));
138146 goto error;
139147 }
140148 jp2_box_destroy(box);
141149
142150 /* Get the second box. This should be a FTYP box. */
143151 if (!(box = jp2_box_get(in))) {
152+ jas_logerrorf("error: cannot get box\n");
144153 goto error;
145154 }
146155 if (box->type != JP2_BOX_FTYP) {
147− jas_eprintf("expecting file type box\n");
156+ jas_logerrorf("expecting file type box\n");
148157 goto error;
149158 }
150159 jp2_box_destroy(box);
@@ -152,8 +161,8 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line
152161 /* Get more boxes... */
153162 found = 0;
154163 while ((box = jp2_box_get(in))) {
155− if (jas_getdbglevel() >= 1) {
156− jas_eprintf("got box type %s\n", box->info->name);
164+ if (jas_get_debug_level() >= 1) {
165+ jas_logdebugf(1, "got box type %s\n", box->info->name);
157166 }
158167 switch (box->type) {
159168 case JP2_BOX_JP2C:
@@ -206,18 +215,18 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 46 unmodified lines
206215 }
207216
208217 if (!found) {
209− jas_eprintf("error: no code stream found\n");
218+ jas_logerrorf("error: no code stream found\n");
210219 goto error;
211220 }
212221
213222 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");
215224 goto error;
216225 }
217226
218227 /* An IHDR box must be present. */
219228 if (!dec->ihdr) {
220− jas_eprintf("error: missing IHDR box\n");
229+ jas_logerrorf("error: missing IHDR box\n");
221230 goto error;
222231 }
223232
@@ -225,12 +234,13 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line
225234 the value specified in the code stream? */
226235 if (dec->ihdr->data.ihdr.numcmpts != JAS_CAST(jas_uint,
227236 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;
229239 }
230240
231241 /* At least one component must be present. */
232242 if (!jas_image_numcmpts(dec->image)) {
233− jas_eprintf("error: no components\n");
243+ jas_logerrorf("error: no components\n");
234244 goto error;
235245 }
236246
@@ -248,21 +258,23 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 11 unmodified lines
248258 with the data in the code stream? */
249259 if ((samedtype && dec->ihdr->data.ihdr.bpc != JP2_DTYPETOBPC(dtype)) ||
250260 (!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;
252263 }
253264
254265 /* Is the compression type supported? */
255266 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");
257268 goto error;
258269 }
259270
260271 if (dec->bpcc) {
261272 /* Is the number of components indicated in the BPCC box
262273 consistent with the code stream data? */
263− if (dec->bpcc->data.bpcc.numcmpts != JAS_CAST(jas_uint, jas_image_numcmpts(
264− dec->image))) {
265− jas_eprintf("warning: number of components mismatch\n");
274+ if (dec->bpcc->data.bpcc.numcmpts !=
275+ JAS_CAST(jas_uint, jas_image_numcmpts(dec->image))) {
276+ jas_logerrorf("error: number of components mismatch (BPCC)\n");
277+ goto error;
266278 }
267279 /* Is the component data type information indicated in the BPCC
268280 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
271283 ++i) {
272284 if (jas_image_cmptdtype(dec->image, i) !=
273285 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;
275288 }
276289 }
277290 } else {
278− jas_eprintf("warning: superfluous BPCC box\n");
291+ jas_logwarnf("warning: superfluous BPCC box\n");
279292 }
280293 }
281294
282295 /* A COLR box must be present. */
283296 if (!dec->colr) {
284− jas_eprintf("error: no COLR box\n");
297+ jas_logerrorf("error: no COLR box\n");
285298 goto error;
286299 }
287300
@@ -293,16 +306,17 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 5 unmodified lines
293306 iccprof = jas_iccprof_createfrombuf(dec->colr->data.colr.iccp,
294307 dec->colr->data.colr.iccplen);
295308 if (!iccprof) {
296− jas_eprintf("error: failed to parse ICC profile\n");
309+ jas_logerrorf("error: failed to parse ICC profile\n");
297310 goto error;
298311 }
299312 jas_iccprof_gethdr(iccprof, &icchdr);
300− //jas_eprintf("ICC Profile CS %08x\n", icchdr.colorspc);
301− jas_image_setclrspc(dec->image, fromiccpcs(icchdr.colorspc));
313+ JAS_LOGDEBUGF(2, "ICC Profile CS %08x\n", icchdr.colorspc);
302314 dec->image->cmprof_ = jas_cmprof_createfromiccprof(iccprof);
303315 if (!dec->image->cmprof_) {
304− jas_iccprof_destroy(iccprof);
305− goto error;
316+ jas_image_setclrspc(dec->image, JAS_CLRSPC_UNKNOWN);
317+ jas_logwarnf("warning: cannot create CM profile from ICC profile\n");
318+ } else {
319+ jas_image_setclrspc(dec->image, fromiccpcs(icchdr.colorspc));
306320 }
307321 jas_iccprof_destroy(iccprof);
308322 break;
@@ -310,14 +324,14 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 1 unmodified line
310324
311325 /* If a CMAP box is present, a PCLR box must also be present. */
312326 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");
314328 jp2_box_destroy(dec->cmap);
315329 dec->cmap = 0;
316330 }
317331
318332 /* If a CMAP box is not present, a PCLR box must not be present. */
319333 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");
321335 jp2_box_destroy(dec->pclr);
322336 dec->pclr = 0;
323337 }
@@ -333,13 +347,13 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 9 unmodified lines
333347 /* Is the component number reasonable? */
334348 if (dec->cmap->data.cmap.ents[i].cmptno >= JAS_CAST(jas_uint,
335349 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");
337351 goto error;
338352 }
339353 /* Is the LUT index reasonable? */
340354 if (dec->cmap->data.cmap.ents[i].pcol >=
341355 dec->pclr->data.pclr.numchans) {
342− jas_eprintf("error: invalid CMAP LUT index\n");
356+ jas_logerrorf("error: invalid CMAP LUT index\n");
343357 goto error;
344358 }
345359 }
@@ -348,7 +362,7 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 2 unmodified lines
348362 /* Allocate space for the channel-number to component-number LUT. */
349363 if (!(dec->chantocmptlut = jas_alloc2(dec->numchans,
350364 sizeof(uint_fast16_t)))) {
351− jas_eprintf("error: no memory\n");
365+ jas_logerrorf("error: no memory\n");
352366 goto error;
353367 }
354368
@@ -357,30 +371,48 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 2 unmodified lines
357371 dec->chantocmptlut[i] = i;
358372 }
359373 } 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+
360380 cmapd = &dec->cmap->data.cmap;
361381 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
362386 for (channo = 0; channo < cmapd->numchans; ++channo) {
363387 cmapent = &cmapd->ents[channo];
364388 if (cmapent->map == JP2_CMAP_DIRECT) {
365389 dec->chantocmptlut[channo] = channo;
366390 } else if (cmapent->map == JP2_CMAP_PALETTE) {
367391 if (!pclrd->numlutents) {
392+ jas_logerrorf("error: empty LUT\n");
368393 goto error;
369394 }
370− lutents = jas_alloc2(pclrd->numlutents, sizeof(int_fast32_t));
371− if (!lutents) {
395+ if (!(lutents = jas_alloc2(pclrd->numlutents,
396+ sizeof(int_fast32_t)))) {
397+ jas_logerrorf("error: cannot allocate LUT\n");
372398 goto error;
373399 }
374400 for (i = 0; i < pclrd->numlutents; ++i) {
375401 lutents[i] = pclrd->lutdata[cmapent->pcol + i * pclrd->numchans];
376402 }
377403 newcmptno = jas_image_numcmpts(dec->image);
378− jas_image_depalettize(dec->image, cmapent->cmptno,
404+ if (jas_image_depalettize(dec->image, cmapent->cmptno,
379405 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+ }
381412 dec->chantocmptlut[channo] = newcmptno;
382413 jas_free(lutents);
383414 #if 0
415+ /* The following code appears to no longer be needed. */
384416 if (dec->cdef) {
385417 cdefent = jp2_cdef_lookup(cdefd, channo);
386418 if (!cdefent) {
@@ -390,17 +422,25 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 3 unmodified lines
390422 } else {
391423 jas_image_setcmpttype(dec->image, newcmptno, jp2_getct(jas_image_clrspc(dec->image), 0, channo + 1));
392424 }
393−#else
394− /* suppress -Wunused-but-set-variable */
395− (void)cdefd;
396425 #endif
397426 } else {
398− jas_eprintf("error: invalid MTYP in CMAP box\n");
427+ jas_logerrorf("error: invalid MTYP in CMAP box\n");
399428 goto error;
400429 }
401430 }
402431 }
403432
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+
404444 /* Mark all components as being of unknown type. */
405445
406446 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
410450 /* Determine the type of each component. */
411451 if (dec->cdef) {
412452 for (i = 0; i < dec->cdef->data.cdef.numchans; ++i) {
453+ uint_fast16_t channo = dec->cdef->data.cdef.ents[i].channo;
413454 /* Is the channel number reasonable? */
414− if (dec->cdef->data.cdef.ents[i].channo >= dec->numchans) {
415− jas_eprintf("error: invalid channel number in CDEF box\n");
455+ if (channo >= dec->numchans) {
456+ jas_logerrorf("error: invalid channel number in CDEF box (%d)\n",
457+ channo);
416458 goto error;
417459 }
418− jas_image_setcmpttype(dec->image,
419− dec->chantocmptlut[dec->cdef->data.cdef.ents[i].channo],
460+ unsigned compno = dec->chantocmptlut[channo];
461+ if (compno >= jas_image_numcmpts(dec->image)) {
462+ jas_logerrorf(
463+ "error: invalid component reference in CDEF box (%d)\n",
464+ compno);
465+ goto error;
466+ }
467+ jas_image_setcmpttype(dec->image, compno,
420468 jp2_getct(jas_image_clrspc(dec->image),
421469 dec->cdef->data.cdef.ents[i].type,
422470 dec->cdef->data.cdef.ents[i].assoc));
423471 }
424472 } else {
425473 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,
427481 jp2_getct(jas_image_clrspc(dec->image), 0, i + 1));
428482 }
429483 }
@@ -437,12 +491,9 @@ jas_image_t *jp2_decode(jas_stream_t *in, const char *optstr) · 7 unmodified lines
437491
438492 /* Ensure that some components survived. */
439493 if (!jas_image_numcmpts(dec->image)) {
440− jas_eprintf("error: no components\n");
494+ jas_logerrorf("error: no components\n");
441495 goto error;
442496 }
443−#if 0
444−jas_eprintf("no of components is %d\n", jas_image_numcmpts(dec->image));
445−#endif
446497
447498 /* Prevent the image from being destroyed later. */
448499 image = dec->image;
@@ -453,6 +504,9 @@ jas_eprintf("no of components is %d\n", jas_image_numcmpts(dec->image)); · 4 unmodified lines
453504 return image;
454505
455506 error:
507+ if (image) {
508+ jas_image_destroy(image);
509+ }
456510 if (box) {
457511 jp2_box_destroy(box);
458512 }
@@ -462,25 +516,25 @@ error: · 3 unmodified lines
462516 return 0;
463517 }
464518
519+#define JP2_VALIDATE_LEN JAS_MIN(JP2_JP_LEN + 4, JAS_STREAM_MAXPUTBACK)
465520 int jp2_validate(jas_stream_t *in)
466521 {
467− unsigned char buf[JP2_VALIDATELEN];
468−#if 0
469− jas_stream_t *tmpstream;
470− jp2_box_t *box;
471−#endif
472−
473− assert(JAS_STREAM_MAXPUTBACK >= JP2_VALIDATELEN);
522+ unsigned char buf[JP2_VALIDATE_LEN];
474523
475524 /* Read the validation data (i.e., the data used for detecting
476525 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)) {
478528 return -1;
529+ }
479530
480531 /* Is the box type correct? */
481− if ((((uint_least32_t)buf[4] << 24) | ((uint_least32_t)buf[5] << 16) | ((uint_least32_t)buf[6] << 8) | (uint_least32_t)buf[7]) !=
482− JP2_BOX_JP)
483− {
532+ assert(JP2_VALIDATE_LEN >= 8);
533+ if (((JAS_CAST(uint_least32_t, buf[4]) << 24) |
534+ (JAS_CAST(uint_least32_t, buf[5]) << 16) |
535+ (JAS_CAST(uint_least32_t, buf[6] << 8)) |
536+ (JAS_CAST(uint_least32_t, buf[7]))) !=
537+ JP2_BOX_JP) {
484538 return -1;
485539 }
486540
jp2_enc.c+494−0
@@ -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+}
jpc_bs.c+7−4
@@ -166,9 +166,9 @@ static jpc_bitstream_t *jpc_bitstream_alloc() · 165 unmodified lines
166166 int jpc_bitstream_getbit_func(jpc_bitstream_t *bitstream)
167167 {
168168 int ret;
169− JAS_DBGLOG(1000, ("jpc_bitstream_getbit_func(%p)\n", bitstream));
169+ JAS_LOGDEBUGF(1000, "jpc_bitstream_getbit_func(%p)\n", bitstream);
170170 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);
172172 return ret;
173173 }
174174
@@ -176,9 +176,9 @@ int jpc_bitstream_getbit_func(jpc_bitstream_t *bitstream) · 1 unmodified line
176176 int jpc_bitstream_putbit_func(jpc_bitstream_t *bitstream, int b)
177177 {
178178 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);
180180 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);
182182 return ret;
183183 }
184184
@@ -362,6 +362,7 @@ int jpc_bitstream_inalign(jpc_bitstream_t *bitstream, int fillmask, · 177 unmodified lines
362362 }
363363 if (n > 0) {
364364 if ((u = jpc_bitstream_getbits(bitstream, n)) < 0) {
365+ JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed\n");
365366 return -1;
366367 }
367368 m += n;
@@ -369,6 +370,7 @@ int jpc_bitstream_inalign(jpc_bitstream_t *bitstream, int fillmask, · 1 unmodified line
369370 }
370371 if ((bitstream->buf_ & 0xff) == 0xff) {
371372 if ((u = jpc_bitstream_getbits(bitstream, 7)) < 0) {
373+ JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed\n");
372374 return -1;
373375 }
374376 v = (v << 7) | u;
@@ -382,6 +384,7 @@ int jpc_bitstream_inalign(jpc_bitstream_t *bitstream, int fillmask, · 7 unmodified lines
382384 }
383385 if (((~(v ^ filldata)) & fillmask) != fillmask) {
384386 /* The actual fill pattern does not match the expected one. */
387+ JAS_LOGDEBUGF(1, "jpc_bitstream_inalign failed (mismatch)\n");
385388 return 1;
386389 }
387390
jpc_bs.h+2−2
@@ -212,12 +212,12 @@ int jpc_bitstream_putbit_func(jpc_bitstream_t *bitstream, int v); · 211 unmodified lines
212212 int jpc_bitstream_fillbuf(jpc_bitstream_t *bitstream);
213213
214214 #define jpc_bitstream_getbit_macro(bitstream) \
215− ((--(bitstream)->cnt_ >= 0) ? \
215+ ( (--(bitstream)->cnt_ >= 0) ? \
216216 ((int)(((bitstream)->buf_ >> (bitstream)->cnt_) & 1)) : \
217217 jpc_bitstream_fillbuf(bitstream))
218218
219219 #define jpc_bitstream_putbit_macro(bitstream, bit) \
220− ((--(bitstream)->cnt_ < 0) ? \
220+ ( (--(bitstream)->cnt_ < 0) ? \
221221 ((bitstream)->buf_ = ((bitstream)->buf_ << 8) & 0xffff, \
222222 (bitstream)->cnt_ = ((bitstream)->buf_ == 0xff00) ? 6 : 7, \
223223 (bitstream)->buf_ |= ((bit) & 1) << (bitstream)->cnt_, \
jpc_cod.c+109−0
@@ -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+}
jpc_cod.h+4−0
@@ -68,6 +68,8 @@ · 67 unmodified lines
6868 #ifndef JPC_COD_H
6969 #define JPC_COD_H
7070
71+#include "jpc_t1cod.h"
72+
7173 /******************************************************************************\
7274 * Constants.
7375 \******************************************************************************/
@@ -75,4 +77,6 @@ · 1 unmodified line
7577 /* The nominal word size used by this implementation. */
7678 #define JPC_PREC 32
7779
80+void jpc_init(void);
81+
7882 #endif
jpc_cs.c+312−77
@@ -94,6 +94,7 @@ typedef struct { · 93 unmodified lines
9494
9595 static const jpc_mstabent_t *jpc_mstab_lookup(int id);
9696
97+static int jpc_poc_dumpparms(jpc_ms_t *ms);
9798 static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
9899 static int jpc_poc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
99100 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
126127 static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
127128 static int jpc_com_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
128129
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+
129144 static void jpc_siz_destroyparms(jpc_ms_t *ms);
130145 static void jpc_qcd_destroyparms(jpc_ms_t *ms);
131146 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
153168 \******************************************************************************/
154169
155170 static const jpc_mstabent_t jpc_mstab[] = {
156− {JPC_MS_SOC, "SOC", {0, 0, 0}},
157− {JPC_MS_SOT, "SOT", {0, jpc_sot_getparms, jpc_sot_putparms}},
158− {JPC_MS_SOD, "SOD", {0, 0, 0}},
159− {JPC_MS_EOC, "EOC", {0, 0, 0}},
160− {JPC_MS_SIZ, "SIZ", {jpc_siz_destroyparms, jpc_siz_getparms, jpc_siz_putparms}},
161− {JPC_MS_COD, "COD", {jpc_cod_destroyparms, jpc_cod_getparms, jpc_cod_putparms}},
162− {JPC_MS_COC, "COC", {jpc_coc_destroyparms, jpc_coc_getparms, jpc_coc_putparms}},
163− {JPC_MS_RGN, "RGN", {0, jpc_rgn_getparms, jpc_rgn_putparms}},
164− {JPC_MS_QCD, "QCD", {jpc_qcd_destroyparms, jpc_qcd_getparms, jpc_qcd_putparms}},
165− {JPC_MS_QCC, "QCC", {jpc_qcc_destroyparms, jpc_qcc_getparms, jpc_qcc_putparms}},
166− {JPC_MS_POC, "POC", {jpc_poc_destroyparms, jpc_poc_getparms, jpc_poc_putparms}},
167− {JPC_MS_TLM, "TLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms,}},
168− {JPC_MS_PLM, "PLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms}},
169− {JPC_MS_PPM, "PPM", {jpc_ppm_destroyparms, jpc_ppm_getparms, jpc_ppm_putparms}},
170− {JPC_MS_PPT, "PPT", {jpc_ppt_destroyparms, jpc_ppt_getparms, jpc_ppt_putparms}},
171− {JPC_MS_SOP, "SOP", {0, jpc_sop_getparms, jpc_sop_putparms}},
172− {JPC_MS_EPH, "EPH", {0, 0, 0}},
173− {JPC_MS_CRG, "CRG", {jpc_crg_destroyparms, jpc_crg_getparms, jpc_crg_putparms}},
174− {JPC_MS_COM, "COM", {jpc_com_destroyparms, jpc_com_getparms, jpc_com_putparms}},
175− {-1, "UNKNOWN", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms}}
171+ {JPC_MS_SOC, "SOC", {0, 0, 0, 0}},
172+ {JPC_MS_SOT, "SOT", {0, jpc_sot_getparms, jpc_sot_putparms,
173+ jpc_sot_dumpparms}},
174+ {JPC_MS_SOD, "SOD", {0, 0, 0, 0}},
175+ {JPC_MS_EOC, "EOC", {0, 0, 0, 0}},
176+ {JPC_MS_SIZ, "SIZ", {jpc_siz_destroyparms, jpc_siz_getparms,
177+ jpc_siz_putparms, jpc_siz_dumpparms}},
178+ {JPC_MS_COD, "COD", {jpc_cod_destroyparms, jpc_cod_getparms,
179+ jpc_cod_putparms, jpc_cod_dumpparms}},
180+ {JPC_MS_COC, "COC", {jpc_coc_destroyparms, jpc_coc_getparms,
181+ jpc_coc_putparms, jpc_coc_dumpparms}},
182+ {JPC_MS_RGN, "RGN", {0, jpc_rgn_getparms, jpc_rgn_putparms,
183+ jpc_rgn_dumpparms}},
184+ {JPC_MS_QCD, "QCD", {jpc_qcd_destroyparms, jpc_qcd_getparms,
185+ jpc_qcd_putparms, jpc_qcd_dumpparms}},
186+ {JPC_MS_QCC, "QCC", {jpc_qcc_destroyparms, jpc_qcc_getparms,
187+ jpc_qcc_putparms, jpc_qcc_dumpparms}},
188+ {JPC_MS_POC, "POC", {jpc_poc_destroyparms, jpc_poc_getparms,
189+ jpc_poc_putparms, jpc_poc_dumpparms}},
190+ {JPC_MS_TLM, "TLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms, 0}},
191+ {JPC_MS_PLM, "PLM", {jpc_unk_destroyparms, jpc_unk_getparms, jpc_unk_putparms, 0}},
192+ {JPC_MS_PPM, "PPM", {jpc_ppm_destroyparms, jpc_ppm_getparms,
193+ jpc_ppm_putparms, jpc_ppm_dumpparms}},
194+ {JPC_MS_PPT, "PPT", {jpc_ppt_destroyparms, jpc_ppt_getparms,
195+ jpc_ppt_putparms, jpc_ppt_dumpparms}},
196+ {JPC_MS_SOP, "SOP", {0, jpc_sop_getparms, jpc_sop_putparms,
197+ jpc_sop_dumpparms}},
198+ {JPC_MS_EPH, "EPH", {0, 0, 0, 0}},
199+ {JPC_MS_CRG, "CRG", {jpc_crg_destroyparms, jpc_crg_getparms,
200+ jpc_crg_putparms, jpc_crg_dumpparms}},
201+ {JPC_MS_COM, "COM", {jpc_com_destroyparms, jpc_com_getparms,
202+ jpc_com_putparms, jpc_com_dumpparms}},
203+ {-1, "UNKNOWN", {jpc_unk_destroyparms, jpc_unk_getparms,
204+ jpc_unk_putparms, jpc_unk_dumpparms}}
176205 };
177206
178207 /******************************************************************************\
@@ -238,7 +267,7 @@ jpc_ms_t *jpc_getms(jas_stream_t *in, jpc_cstate_t *cstate) · 59 unmodified lines
238267 return 0;
239268 }
240269 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) {
242271 jas_stream_close(tmpstream);
243272 jpc_ms_destroy(ms);
244273 return 0;
@@ -251,8 +280,12 @@ jpc_ms_t *jpc_getms(jas_stream_t *in, jpc_cstate_t *cstate) · 6 unmodified lines
251280 return 0;
252281 }
253282
283+ if (jas_get_debug_level() > 0) {
284+ jpc_ms_dump(ms);
285+ }
286+
254287 if (JAS_CAST(jas_ulong, jas_stream_tell(tmpstream)) != ms->len) {
255− jas_eprintf(
288+ jas_logwarnf(
256289 "warning: trailing garbage in marker segment (%ld bytes)\n",
257290 ms->len - jas_stream_tell(tmpstream));
258291 }
@@ -263,6 +296,10 @@ jpc_ms_t *jpc_getms(jas_stream_t *in, jpc_cstate_t *cstate) · 4 unmodified lines
263296 } else {
264297 /* There are no marker segment parameters. */
265298 ms->len = 0;
299+
300+ if (jas_get_debug_level() > 0) {
301+ jpc_ms_dump(ms);
302+ }
266303 }
267304
268305 /* 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
306343 ms->len = len;
307344 /* Write the marker segment length and parameter data to
308345 the output stream. */
309− if (jas_stream_seek(tmpstream, 0, 0) < 0 ||
346+ if (jas_stream_seek(tmpstream, 0, SEEK_SET) < 0 ||
310347 jpc_putuint16(out, ms->len + 2) ||
311348 jas_stream_copy(out, tmpstream, ms->len) < 0) {
312349 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
322359 cstate->numcomps = ms->parms.siz.numcomps;
323360 }
324361
362+ if (jas_get_debug_level() > 0) {
363+ jpc_ms_dump(ms);
364+ }
365+
325366 return 0;
326367 }
327368
@@ -355,6 +396,24 @@ void jpc_ms_destroy(jpc_ms_t *ms) · 27 unmodified lines
355396 jas_free(ms);
356397 }
357398
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+
358417 /******************************************************************************\
359418 * SOT marker segment operations.
360419 \******************************************************************************/
@@ -363,8 +422,7 @@ static int jpc_sot_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 2 unmodified lines
363422 {
364423 jpc_sot_t *sot = &ms->parms.sot;
365424
366− /* Eliminate compiler warning about unused variables. */
367− (void)cstate;
425+ JAS_UNUSED(cstate);
368426
369427 if (jpc_getuint16(in, &sot->tileno) ||
370428 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
385443 {
386444 jpc_sot_t *sot = &ms->parms.sot;
387445
388− /* Eliminate compiler warning about unused variables. */
389− (void)cstate;
446+ JAS_UNUSED(cstate);
390447
391448 if (jpc_putuint16(out, sot->tileno) ||
392449 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
397454 return 0;
398455 }
399456
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+
400466 /******************************************************************************\
401467 * SIZ marker segment operations.
402468 \******************************************************************************/
@@ -418,8 +484,7 @@ static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 15 unmodified lines
418484
419485 siz->comps = 0;
420486
421− /* Eliminate compiler warning about unused variables. */
422− (void)cstate;
487+ JAS_UNUSED(cstate);
423488
424489 if (jpc_getuint16(in, &siz->caps) ||
425490 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
434499 goto error;
435500 }
436501 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");
438503 goto error;
439504 }
440505 if (!siz->tilewidth || !siz->tileheight) {
441− jas_eprintf("tile cannot have zero area\n");
506+ jas_logerrorf("tile cannot have zero area\n");
442507 goto error;
443508 }
444509 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");
446511 goto error;
447512 }
448513 if (siz->xoff >= siz->width) {
449− jas_eprintf("XOsiz not in permissible range\n");
514+ jas_logerrorf("XOsiz not in permissible range\n");
450515 goto error;
451516 }
452517 if (siz->yoff >= siz->height) {
453− jas_eprintf("YOsiz not in permissible range\n");
518+ jas_logerrorf("YOsiz not in permissible range\n");
454519 goto error;
455520 }
456521 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");
458523 goto error;
459524 }
460525 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");
462527 goto error;
463528 }
464529
@@ -472,11 +537,11 @@ static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, · 7 unmodified lines
472537 goto error;
473538 }
474539 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);
476541 goto error;
477542 }
478543 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);
480545 goto error;
481546 }
482547 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
485550 samples and 2 bits for signed samples */
486551 if (siz->comps[i].prec < 1U + siz->comps[i].sgnd ||
487552 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);
489554 goto error;
490555 }
491556 }
@@ -506,8 +571,7 @@ static int jpc_siz_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 14 unmodified lines
506571 jpc_siz_t *siz = &ms->parms.siz;
507572 unsigned int i;
508573
509− /* Eliminate compiler warning about unused variables. */
510− (void)cstate;
574+ JAS_UNUSED(cstate);
511575
512576 assert(siz->width && siz->height && siz->tilewidth &&
513577 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
534598 return 0;
535599 }
536600
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+
537621 /******************************************************************************\
538622 * COD marker segment operations.
539623 \******************************************************************************/
@@ -587,6 +671,28 @@ static int jpc_cod_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 47 unmodified lines
587671 return 0;
588672 }
589673
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+
590696 /******************************************************************************\
591697 * COC marker segment operations.
592698 \******************************************************************************/
@@ -647,14 +753,23 @@ static int jpc_coc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 54 unmodified lines
647753 return 0;
648754 }
649755
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+}
650766 /******************************************************************************\
651767 * COD/COC marker segment operation helper functions.
652768 \******************************************************************************/
653769
654770 static void jpc_cox_destroycompparms(jpc_coxcp_t *compparms)
655771 {
656− /* Eliminate compiler warning about unused variables. */
657− USED(compparms);
772+ JAS_UNUSED(compparms);
658773 }
659774
660775 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
663778 uint_fast8_t tmp;
664779 int i;
665780
666− /* Eliminate compiler warning about unused variables. */
667− USED(ms);
668− USED(cstate);
781+ JAS_UNUSED(ms);
782+ JAS_UNUSED(cstate);
669783
670784 if (jpc_getuint8(in, &compparms->numdlvls) ||
671785 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
711825 int i;
712826 assert(compparms->numdlvls <= 32);
713827
714− /* Eliminate compiler warning about unused variables. */
715− USED(ms);
716− USED(cstate);
828+ JAS_UNUSED(ms);
829+ JAS_UNUSED(cstate);
717830
718831 if (jpc_putuint8(out, compparms->numdlvls) ||
719832 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
778891 return 0;
779892 }
780893
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+
781902 /******************************************************************************\
782903 * QCD marker segment operations.
783904 \******************************************************************************/
@@ -800,6 +921,20 @@ static int jpc_qcd_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 16 unmodified lines
800921 return jpc_qcx_putcompparms(compparms, cstate, out);
801922 }
802923
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+
803938 /******************************************************************************\
804939 * QCC marker segment operations.
805940 \******************************************************************************/
@@ -856,6 +991,21 @@ static int jpc_qcc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 50 unmodified lines
856991 return 0;
857992 }
858993
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+
8591009 /******************************************************************************\
8601010 * QCD/QCC marker segment helper functions.
8611011 \******************************************************************************/
@@ -874,8 +1024,7 @@ static int jpc_qcx_getcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate, · 12 unmodified lines
8741024 int n;
8751025 int i;
8761026
877− /* Eliminate compiler warning about unused variables. */
878− (void)cstate;
1027+ JAS_UNUSED(cstate);
8791028
8801029 n = 0;
8811030 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
9361085 {
9371086 int i;
9381087
939− /* Eliminate compiler warning about unused variables. */
940− (void)cstate;
1088+ JAS_UNUSED(cstate);
9411089
9421090 if (jpc_putuint8(out, ((compparms->numguard & 7) << 5) | compparms->qntsty)) {
9431091 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
9651113 {
9661114 jpc_sop_t *sop = &ms->parms.sop;
9671115
968− /* Eliminate compiler warning about unused variable. */
969− (void)cstate;
1116+ JAS_UNUSED(cstate);
9701117
9711118 if (jpc_getuint16(in, &sop->seqno)) {
9721119 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
9781125 {
9791126 jpc_sop_t *sop = &ms->parms.sop;
9801127
981− /* Eliminate compiler warning about unused variable. */
982− (void)cstate;
1128+ JAS_UNUSED(cstate);
9831129
9841130 if (jpc_putuint16(out, sop->seqno)) {
9851131 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
9871133 return 0;
9881134 }
9891135
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+
9901143 /******************************************************************************\
9911144 * PPM marker segment operations.
9921145 \******************************************************************************/
@@ -1003,8 +1156,7 @@ static int jpc_ppm_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 10 unmodified lines
10031156 {
10041157 jpc_ppm_t *ppm = &ms->parms.ppm;
10051158
1006− /* Eliminate compiler warning about unused variables. */
1007− (void)cstate;
1159+ JAS_UNUSED(cstate);
10081160
10091161 ppm->data = 0;
10101162
@@ -1037,8 +1189,7 @@ static int jpc_ppm_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 26 unmodified lines
10371189 {
10381190 jpc_ppm_t *ppm = &ms->parms.ppm;
10391191
1040− /* Eliminate compiler warning about unused variables. */
1041− (void)cstate;
1192+ JAS_UNUSED(cstate);
10421193
10431194 if (JAS_CAST(jas_uint, jas_stream_write(out, (char *) ppm->data, ppm->len)) != ppm->len) {
10441195 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
10461197 return 0;
10471198 }
10481199
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+
10491211 /******************************************************************************\
10501212 * PPT marker segment operations.
10511213 \******************************************************************************/
@@ -1062,8 +1224,7 @@ static int jpc_ppt_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 10 unmodified lines
10621224 {
10631225 jpc_ppt_t *ppt = &ms->parms.ppt;
10641226
1065− /* Eliminate compiler warning about unused variables. */
1066− (void)cstate;
1227+ JAS_UNUSED(cstate);
10671228
10681229 ppt->data = 0;
10691230
@@ -1095,8 +1256,7 @@ static int jpc_ppt_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 25 unmodified lines
10951256 {
10961257 jpc_ppt_t *ppt = &ms->parms.ppt;
10971258
1098− /* Eliminate compiler warning about unused variable. */
1099− (void)cstate;
1259+ JAS_UNUSED(cstate);
11001260
11011261 if (jpc_putuint8(out, ppt->ind)) {
11021262 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
11071267 return 0;
11081268 }
11091269
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+
11101281 /******************************************************************************\
11111282 * POC marker segment operations.
11121283 \******************************************************************************/
@@ -1197,6 +1368,23 @@ static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 84 unmodified lines
11971368 return 0;
11981369 }
11991370
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+
12001388 /******************************************************************************\
12011389 * CRG marker segment operations.
12021390 \******************************************************************************/
@@ -1235,8 +1423,7 @@ static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *ou · 32 unmodified lines
12351423 int compno;
12361424 jpc_crgcomp_t *comp;
12371425
1238− /* Eliminate compiler warning about unused variables. */
1239− (void)cstate;
1426+ JAS_UNUSED(cstate);
12401427
12411428 for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno,
12421429 ++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
12481435 return 0;
12491436 }
12501437
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+
12511451 /******************************************************************************\
12521452 * Operations for COM marker segment.
12531453 \******************************************************************************/
@@ -1264,8 +1464,7 @@ static int jpc_com_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 10 unmodified lines
12641464 {
12651465 jpc_com_t *com = &ms->parms.com;
12661466
1267− /* Eliminate compiler warning about unused variables. */
1268− (void)cstate;
1467+ JAS_UNUSED(cstate);
12691468
12701469 if (jpc_getuint16(in, &com->regid)) {
12711470 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
12881487 {
12891488 jpc_com_t *com = &ms->parms.com;
12901489
1291− /* Eliminate compiler warning about unused variables. */
1292− (void)cstate;
1490+ JAS_UNUSED(cstate);
12931491
12941492 if (jpc_putuint16(out, com->regid)) {
12951493 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
13001498 return 0;
13011499 }
13021500
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+
13031524 /******************************************************************************\
13041525 * Operations for unknown types of marker segments.
13051526 \******************************************************************************/
@@ -1318,8 +1539,7 @@ static int jpc_unk_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in · 12 unmodified lines
13181539
13191540 unk->data = 0;
13201541
1321− /* Eliminate compiler warning about unused variables. */
1322− (void)cstate;
1542+ JAS_UNUSED(cstate);
13231543
13241544 if (ms->len > 0) {
13251545 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
13391559
13401560 static int jpc_unk_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
13411561 {
1342− /* Eliminate compiler warning about unused variables. */
1343− USED(cstate);
1344− USED(ms);
1345− USED(out);
1562+ JAS_UNUSED(cstate);
1563+ JAS_UNUSED(ms);
1564+ JAS_UNUSED(out);
13461565
13471566 /* If this function is called, we are trying to write an unsupported
13481567 type of marker segment. Return with an error indication. */
13491568 return -1;
13501569 }
13511570
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+
13521581 /******************************************************************************\
13531582 * Primitive I/O operations.
13541583 \******************************************************************************/
@@ -1430,6 +1659,12 @@ int jpc_validate(jas_stream_t *in) · 75 unmodified lines
14301659 {
14311660 unsigned char buf[2];
14321661
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+
14331668 assert(JAS_STREAM_MAXPUTBACK >= 2);
14341669
14351670 if (jas_stream_peek(in, buf, sizeof(buf)) != sizeof(buf))
jpc_cs.h+6−0
@@ -726,6 +726,9 @@ typedef struct jpc_msops_s { · 725 unmodified lines
726726 /* Put the marker segment parameters to a stream. */
727727 int (*putparms)(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
728728
729+ /* Dump the marker segment parameters (for debugging). */
730+ int (*dumpparms)(jpc_ms_t *ms);
731+
729732 } jpc_msops_t;
730733
731734 /******************************************************************************\
@@ -771,6 +774,9 @@ int jpc_getdata(jas_stream_t *in, jas_stream_t *out, long n); · 39 unmodified lines
771774 /* Copy code stream data from one stream to another. */
772775 int jpc_putdata(jas_stream_t *out, jas_stream_t *in, long n);
773776
777+/* Dump a marker segment (for debugging). */
778+void jpc_ms_dump(jpc_ms_t *ms);
779+
774780 /* Read a 8-bit unsigned integer from a stream. */
775781 int jpc_getuint8(jas_stream_t *in, uint_fast8_t *val);
776782
jpc_dec.c+415−112
@@ -78,8 +78,10 @@ · 77 unmodified lines
7878 #include "jpc_t1dec.h"
7979 #include "jpc_math.h"
8080
81+#include "jasper/jas_init.h"
8182 #include "jasper/jas_types.h"
8283 #include "jasper/jas_math.h"
84+#include "jasper/jas_tvp.h"
8385 #include "jasper/jas_malloc.h"
8486 #include "jasper/jas_debug.h"
8587
@@ -131,6 +133,8 @@ typedef struct { · 45 unmodified lines
131133 * Local function prototypes.
132134 \******************************************************************************/
133135
136+static int jpc_dec_dump(const jpc_dec_t *dec);
137+
134138 static jpc_ppxstab_t *jpc_ppxstab_create(void);
135139 static void jpc_ppxstab_destroy(jpc_ppxstab_t *tab);
136140 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
197201
198202 static const jpc_dec_mstabent_t *jpc_dec_mstab_lookup(uint_fast16_t id);
199203
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+
200210 /******************************************************************************\
201211 * Global data.
202212 \******************************************************************************/
@@ -236,13 +246,14 @@ jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr) · 33 unmodified lines
236246
237247 dec = 0;
238248
239− JAS_DBGLOG(100, ("jpc_decode(%p, \"%s\")\n", in, optstr));
249+ JAS_LOGDEBUGF(100, "jpc_decode(%p, \"%s\")\n", in, optstr);
240250
241251 if (!(opts = jpc_dec_opts_create(optstr))) {
242252 goto error;
243253 }
244254
245− jpc_initluts();
255+ jpc_init();
256+ //jpc_initluts();
246257
247258 if (!(dec = jpc_dec_create(opts, in))) {
248259 goto error;
@@ -290,11 +301,27 @@ error: · 41 unmodified lines
290301 return 0;
291302 }
292303
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+
293319 static jpc_dec_importopts_t *jpc_dec_opts_create(const char *optstr)
294320 {
295321 jpc_dec_importopts_t *opts;
322+ jas_tvparser_t *tvp;
323+
296324
297− USED(optstr);
298325 if (!(opts = jas_malloc(sizeof(jpc_dec_importopts_t)))) {
299326 goto error;
300327 }
@@ -302,7 +329,35 @@ static jpc_dec_importopts_t *jpc_dec_opts_create(const char *optstr) · 1 unmodified line
302329 opts->debug = 0;
303330 opts->maxlyrs = JPC_MAXLYRS;
304331 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);
306361
307362 return opts;
308363
@@ -353,7 +408,7 @@ static int jpc_dec_decode(jpc_dec_t *dec) · 44 unmodified lines
353408
354409 /* Get the next marker segment in the code stream. */
355410 if (!(ms = jpc_getms(dec->in, cstate))) {
356− jas_eprintf("cannot get marker segment\n");
411+ jas_logerrorf("cannot get marker segment\n");
357412 return -1;
358413 }
359414
@@ -363,7 +418,7 @@ static int jpc_dec_decode(jpc_dec_t *dec) · 3 unmodified lines
363418 /* Ensure that this type of marker segment is permitted
364419 at this point in the code stream. */
365420 if (!(dec->state & mstabent->validstates)) {
366− jas_eprintf("unexpected marker segment type\n");
421+ jas_logerrorf("unexpected marker segment type\n");
367422 jpc_ms_destroy(ms);
368423 return -1;
369424 }
@@ -407,15 +462,14 @@ static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms) · 37 unmodified lines
407462 cmpt->vsubstep = crg->comps[cmptno].voff;
408463 */
409464 /* suppress -Wunused-but-set-variable */
410− USED(crg);
465+ JAS_UNUSED(crg);
411466 }
412467 return 0;
413468 }
414469
415470 static int jpc_dec_process_soc(jpc_dec_t *dec, jpc_ms_t *ms)
416471 {
417− /* Eliminate warnings about unused variables. */
418− (void)ms;
472+ JAS_UNUSED(ms);
419473
420474 /* We should expect to encounter a SIZ marker segment next. */
421475 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
478532 }
479533
480534 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");
482536 return -1;
483537 }
484538 /* 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
529583 jpc_dec_tile_t *tile;
530584 int pos;
531585
532− /* Eliminate compiler warnings about unused variables. */
533− (void)ms;
586+ JAS_UNUSED(ms);
534587
535588 if (!(tile = dec->curtile)) {
536589 return -1;
@@ -564,18 +617,22 @@ static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms) · 27 unmodified lines
564617 }
565618 }
566619 pos = jas_stream_tell(tile->pkthdrstream);
567− jas_stream_seek(tile->pkthdrstream, 0, 2);
620+ jas_stream_seek(tile->pkthdrstream, 0, SEEK_END);
568621 if (jpc_pptstabwrite(tile->pkthdrstream, tile->pptstab)) {
569622 return -1;
570623 }
571− jas_stream_seek(tile->pkthdrstream, pos, 0);
624+ jas_stream_seek(tile->pkthdrstream, pos, SEEK_SET);
572625 jpc_ppxstab_destroy(tile->pptstab);
573626 tile->pptstab = 0;
574627 }
575628
629+ if (jas_get_debug_level() >= 10) {
630+ jpc_dec_dump(dec);
631+ }
632+
576633 if (jpc_dec_decodepkts(dec, (tile->pkthdrstream) ? tile->pkthdrstream :
577634 dec->in, dec->in)) {
578− jas_eprintf("jpc_dec_decodepkts failed\n");
635+ jas_logerrorf("jpc_dec_decodepkts failed\n");
579636 return -1;
580637 }
581638
@@ -586,17 +643,17 @@ static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms) · 4 unmodified lines
586643 curoff = jas_stream_getrwcount(dec->in);
587644 if (curoff < dec->curtileendoff) {
588645 n = dec->curtileendoff - curoff;
589− jas_eprintf("warning: ignoring trailing garbage (%lu bytes)\n",
646+ jas_logwarnf("warning: ignoring trailing garbage (%lu bytes)\n",
590647 (unsigned long) n);
591648
592649 while (n-- > 0) {
593650 if (jas_stream_getc(dec->in) == EOF) {
594− jas_eprintf("read error\n");
651+ jas_logerrorf("read error\n");
595652 return -1;
596653 }
597654 }
598655 } 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",
600657 (unsigned long) curoff - dec->curtileendoff);
601658 }
602659
@@ -653,6 +710,11 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 50 unmodified lines
653710 uint_fast32_t tmpyend;
654711 jpc_tsfb_band_t bnds[JPC_MAXBANDS];
655712 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+ }
656718
657719 const jpc_dec_cp_t *cp = tile->cp;
658720 tile->realmode = 0;
@@ -665,27 +727,37 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 6 unmodified lines
665727 for (compno = 0, tcomp = tile->tcomps, cmpt = dec->cmpts; compno <
666728 dec->numcomps; ++compno, ++tcomp, ++cmpt) {
667729 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+ }
668733 if (ccp->qmfbid == JPC_COX_INS) {
669734 tile->realmode = 1;
670735 }
671736 tcomp->numrlvls = ccp->numrlvls;
672737 if (!(tcomp->rlvls = jas_alloc2(tcomp->numrlvls,
673738 sizeof(jpc_dec_rlvl_t)))) {
674− return -1;
739+ retval = -1;
740+ goto done;
675741 }
676742 for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls;
677743 ++rlvlno, ++rlvl) {
744+#if 0
678745 rlvl->bands = NULL;
746+#else
747+ jpc_rlvl_init(rlvl);
748+#endif
679749 }
680750 if (!(tcomp->data = jas_seq2d_create(JPC_CEILDIV(tile->xstart,
681751 cmpt->hstep), JPC_CEILDIV(tile->ystart, cmpt->vstep),
682752 JPC_CEILDIV(tile->xend, cmpt->hstep), JPC_CEILDIV(tile->yend,
683753 cmpt->vstep)))) {
684− return -1;
754+ retval = -1;
755+ goto done;
685756 }
686757 if (!(tcomp->tsfb = jpc_cod_gettsfb(ccp->qmfbid,
687758 tcomp->numrlvls - 1))) {
688− return -1;
759+ retval = -1;
760+ goto done;
689761 }
690762 {
691763 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
719791 rlvl->prcheightexpn;
720792 rlvl->numprcs = rlvl->numhprcs * rlvl->numvprcs;
721793
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+
722804 if (rlvl->numprcs >= 64 * 1024) {
723805 /* avoid out-of-memory due to
724806 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
747829 if (rlvl->prcwidthexpn < 1 || rlvl->prcheightexpn < 1) {
748830 /* the control block width/height offset
749831 exponent must not be negative */
750− return -1;
832+ retval = -1;
833+ goto done;
751834 }
752835 rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1;
753836 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
760843 rlvl->numbands = (!rlvlno) ? 1 : 3;
761844 if (!(rlvl->bands = jas_alloc2(rlvl->numbands,
762845 sizeof(jpc_dec_band_t)))) {
763− return -1;
846+ retval = -1;
847+ goto done;
764848 }
765849 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
766856 for (bandno = 0, band = rlvl->bands;
767857 bandno < rlvl->numbands; ++bandno, ++band) {
768858 unsigned bndno = (!rlvlno) ? 0 : (3 * (rlvlno - 1) +
769859 bandno + 1);
770860 const jpc_tsfb_band_t *bnd = &bnds[bndno];
771861
862+ if (jas_get_debug_level() >= 10) {
863+ jas_logdebugf(10, "[compno %d rlvlno %d bandno %d]\n", compno, rlvlno, bandno);
864+ }
865+
772866 band->orient = bnd->orient;
773867 band->stepsize = ccp->stepsizes[bndno];
774868 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
785879 continue;
786880 }
787881 if (!(band->data = jas_seq2d_create(0, 0, 0, 0))) {
788− return -1;
882+ retval = -1;
883+ goto done;
789884 }
790885 if (jas_seq2d_bindsub(band->data, tcomp->data, bnd->locxstart,
791886 bnd->locystart, bnd->locxend, bnd->locyend)) {
792− return -1;
887+ retval = -1;
888+ goto done;
793889 }
794890 jas_seq2d_setshift(band->data, bnd->xstart, bnd->ystart);
795891
@@ -797,14 +893,25 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 1 unmodified line
797893
798894 if (!(band->prcs = jas_alloc2(rlvl->numprcs,
799895 sizeof(jpc_dec_prc_t)))) {
800− return -1;
896+ retval = -1;
897+ goto done;
801898 }
802899
803900 /************************************************/
804901 cbgxstart = tlcbgxstart;
805902 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;
807906 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+ }
808915 cbgxend = cbgxstart + (1 << rlvl->cbgwidthexpn);
809916 cbgyend = cbgystart + (1 << rlvl->cbgheightexpn);
810917 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
831938 prc->numcblks = prc->numhcblks * prc->numvcblks;
832939 assert(prc->numcblks > 0);
833940
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+
834948 if (!(prc->incltagtree = jpc_tagtree_create(
835949 prc->numhcblks, prc->numvcblks))) {
836− return -1;
950+ retval = -1;
951+ goto done;
837952 }
838953 if (!(prc->numimsbstagtree = jpc_tagtree_create(
839954 prc->numhcblks, prc->numvcblks))) {
840− return -1;
955+ retval = -1;
956+ goto done;
841957 }
842958 if (!(prc->cblks = jas_alloc2(prc->numcblks,
843959 sizeof(jpc_dec_cblk_t)))) {
844− return -1;
960+ retval = -1;
961+ goto done;
845962 }
846963
847964 cblkxstart = cbgxstart;
848965 cblkystart = cbgystart;
849966 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
850973 for (cblkcnt = prc->numcblks, cblk = prc->cblks;
851974 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+ }
852978 cblkxend = cblkxstart + (1 << rlvl->cblkwidthexpn);
853979 cblkyend = cblkystart + (1 << rlvl->cblkheightexpn);
854980 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
865991 cblk->numlenbits = 3;
866992 if (!(cblk->data = jas_seq2d_create(0, 0, 0,
867993 0))) {
868− return -1;
994+ retval = -1;
995+ goto done;
869996 }
870997 if (jas_seq2d_bindsub(cblk->data, band->data,
871998 tmpxstart, tmpystart, tmpxend, tmpyend)) {
872− return -1;
999+ retval = -1;
1000+ goto done;
8731001 }
8741002 ++cblk;
8751003 --cblkcnt;
@@ -899,7 +1027,8 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 23 unmodified lines
8991027 }
9001028
9011029 if (!(tile->pi = jpc_dec_pi_create(dec, tile))) {
902− return -1;
1030+ retval = -1;
1031+ goto done;
9031032 }
9041033
9051034 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
9101039 }
9111040 jpc_pi_init(tile->pi);
9121041
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;
9141049 }
9151050
9161051 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
9201055 jpc_dec_seg_t *seg;
9211056 jpc_dec_cblk_t *cblk;
9221057
923− if (tile->tcomps) {
1058+ if (jas_get_debug_level() >= 1) {
1059+ jas_logdebugf(1, "jpc_dec_tilefini called\n");
1060+ }
9241061
1062+ if (tile->tcomps) {
9251063 unsigned compno;
9261064 for (compno = 0, tcomp = tile->tcomps; compno < dec->numcomps;
9271065 ++compno, ++tcomp) {
928− const jpc_dec_rlvl_t *rlvl;
929− for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls;
930− ++rlvlno, ++rlvl) {
931− if (!rlvl->bands) {
932− continue;
933− }
934− unsigned bandno;
935− const jpc_dec_band_t *band;
936− for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands;
937− ++bandno, ++band) {
938− if (band->prcs) {
939− unsigned prcno;
940− const jpc_dec_prc_t *prc;
941− for (prcno = 0, prc = band->prcs; prcno <
942− rlvl->numprcs; ++prcno, ++prc) {
943− if (!prc->cblks) {
944− continue;
945− }
946− unsigned cblkno;
947− for (cblkno = 0, cblk = prc->cblks; cblkno <
948− prc->numcblks; ++cblkno, ++cblk) {
949−
950− while (cblk->segs.head) {
951− seg = cblk->segs.head;
952− jpc_seglist_remove(&cblk->segs, seg);
953− jpc_seg_destroy(seg);
1066+ if (tcomp->rlvls) {
1067+ const jpc_dec_rlvl_t *rlvl;
1068+ for (rlvlno = 0, rlvl = tcomp->rlvls; rlvlno < tcomp->numrlvls;
1069+ ++rlvlno, ++rlvl) {
1070+ if (!rlvl->bands) {
1071+ continue;
1072+ }
1073+ unsigned bandno;
1074+ const jpc_dec_band_t *band;
1075+ for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands;
1076+ ++bandno, ++band) {
1077+ if (band->prcs) {
1078+ unsigned prcno;
1079+ const jpc_dec_prc_t *prc;
1080+ for (prcno = 0, prc = band->prcs; prcno <
1081+ rlvl->numprcs; ++prcno, ++prc) {
1082+ if (prc->cblks) {
1083+ unsigned cblkno;
1084+ for (cblkno = 0, cblk = prc->cblks; cblkno <
1085+ prc->numcblks; ++cblkno, ++cblk) {
1086+ while (cblk->segs.head) {
1087+ seg = cblk->segs.head;
1088+ jpc_seglist_remove(&cblk->segs, seg);
1089+ jpc_seg_destroy(seg);
1090+ }
1091+ if (cblk->data) {
1092+ jas_matrix_destroy(cblk->data);
1093+ }
1094+ }
1095+ jas_free(prc->cblks);
1096+ }
1097+ if (prc->incltagtree) {
1098+ jpc_tagtree_destroy(prc->incltagtree);
1099+ }
1100+ if (prc->numimsbstagtree) {
1101+ jpc_tagtree_destroy(prc->numimsbstagtree);
9541102 }
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);
9651103 }
9661104 }
1105+ if (band->data) {
1106+ jas_matrix_destroy(band->data);
1107+ }
1108+ if (band->prcs) {
1109+ jas_free(band->prcs);
1110+ }
9671111 }
968− if (band->data) {
969− jas_matrix_destroy(band->data);
970− }
971− if (band->prcs) {
972− jas_free(band->prcs);
1112+ if (rlvl->bands) {
1113+ jas_free(rlvl->bands);
9731114 }
9741115 }
975− if (rlvl->bands) {
976− jas_free(rlvl->bands);
977− }
9781116 }
9791117 if (tcomp->rlvls) {
9801118 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
10201158 int v;
10211159
10221160 if (jpc_dec_decodecblks(dec, tile)) {
1023− jas_eprintf("jpc_dec_decodecblks failed\n");
1161+ jas_logerrorf("jpc_dec_decodecblks failed\n");
10241162 return -1;
10251163 }
10261164
@@ -1065,11 +1203,11 @@ static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile) · 38 unmodified lines
10651203 switch (tile->cp->mctid) {
10661204 case JPC_MCT_RCT:
10671205 if (dec->numcomps < 3) {
1068− jas_eprintf("RCT requires at least three components\n");
1206+ jas_logerrorf("RCT requires at least three components\n");
10691207 return -1;
10701208 }
10711209 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");
10731211 return -1;
10741212 }
10751213 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
10771215 break;
10781216 case JPC_MCT_ICT:
10791217 if (dec->numcomps < 3) {
1080− jas_eprintf("ICT requires at least three components\n");
1218+ jas_logerrorf("ICT requires at least three components\n");
10811219 return -1;
10821220 }
10831221 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");
10851223 return -1;
10861224 }
10871225 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
11541292 JPC_CEILDIV(dec->xstart, cmpt->hstep), tcomp->ystart -
11551293 JPC_CEILDIV(dec->ystart, cmpt->vstep), jas_matrix_numcols(
11561294 tcomp->data), jas_matrix_numrows(tcomp->data), tcomp->data)) {
1157− jas_eprintf("write component failed\n");
1295+ jas_logerrorf("write component failed\n");
11581296 return -1;
11591297 }
11601298 }
@@ -1166,8 +1304,7 @@ static int jpc_dec_process_eoc(jpc_dec_t *dec, jpc_ms_t *ms) · 5 unmodified lines
11661304 {
11671305 jpc_dec_tile_t *tile;
11681306
1169− /* Eliminate compiler warnings about unused variables. */
1170− (void)ms;
1307+ JAS_UNUSED(ms);
11711308
11721309 unsigned tileno;
11731310 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
12041341 size_t total_samples;
12051342 if (!jas_safe_size_mul(siz->width, siz->height, &total_samples) ||
12061343 (dec->max_samples > 0 && total_samples > dec->max_samples)) {
1207− jas_eprintf("image too large\n");
1344+ jas_logerrorf("image too large\n");
12081345 return -1;
12091346 }
12101347
12111348 size_t tile_samples;
12121349 if (!jas_safe_size_mul(siz->tilewidth, siz->tileheight, &tile_samples) ||
12131350 (dec->max_samples > 0 && tile_samples > dec->max_samples)) {
1214− jas_eprintf("tile too large\n");
1351+ jas_logerrorf("tile too large\n");
12151352 return -1;
12161353 }
12171354
@@ -1248,18 +1385,22 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms) · 30 unmodified lines
12481385 cmpt->hsubstep = 0;
12491386 cmpt->vsubstep = 0;
12501387
1388+ if (!cmpt->width || !cmpt->height) {
1389+ jas_logerrorf("image component has no samples\n");
1390+ return -1;
1391+ }
12511392 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");
12531394 return -1;
12541395 }
12551396 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");
12571398 return -1;
12581399 }
12591400 }
12601401
12611402 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",
12631404 num_samples, dec->max_samples);
12641405 return -1;
12651406 }
@@ -1287,8 +1428,8 @@ static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms) · 21 unmodified lines
12871428 return -1;
12881429 }
12891430 dec->numtiles = size;
1290− JAS_DBGLOG(10, ("numtiles = %d; numhtiles = %d; numvtiles = %d;\n",
1291− dec->numtiles, dec->numhtiles, dec->numvtiles));
1431+ JAS_LOGDEBUGF(10, "numtiles = %d; numhtiles = %d; numvtiles = %d;\n",
1432+ dec->numtiles, dec->numhtiles, dec->numvtiles);
12921433 if (!(dec->tiles = jas_alloc2(dec->numtiles, sizeof(jpc_dec_tile_t)))) {
12931434 return -1;
12941435 }
@@ -1377,7 +1518,7 @@ static int jpc_dec_process_coc(jpc_dec_t *dec, jpc_ms_t *ms) · 82 unmodified lines
13771518 jpc_dec_tile_t *tile;
13781519
13791520 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");
13811522 return -1;
13821523 }
13831524 switch (dec->state) {
@@ -1403,7 +1544,7 @@ static int jpc_dec_process_rgn(jpc_dec_t *dec, jpc_ms_t *ms) · 19 unmodified lines
14031544 jpc_dec_tile_t *tile;
14041545
14051546 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");
14071548 return -1;
14081549 }
14091550 switch (dec->state) {
@@ -1452,7 +1593,7 @@ static int jpc_dec_process_qcc(jpc_dec_t *dec, jpc_ms_t *ms) · 42 unmodified lines
14521593 jpc_dec_tile_t *tile;
14531594
14541595 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");
14561597 return -1;
14571598 }
14581599 switch (dec->state) {
@@ -1551,19 +1692,17 @@ static int jpc_dec_process_ppt(jpc_dec_t *dec, jpc_ms_t *ms) · 92 unmodified lines
15511692
15521693 static int jpc_dec_process_com(jpc_dec_t *dec, jpc_ms_t *ms)
15531694 {
1554− /* Eliminate compiler warnings about unused variables. */
1555− USED(dec);
1556− USED(ms);
1695+ JAS_UNUSED(dec);
1696+ JAS_UNUSED(ms);
15571697
15581698 return 0;
15591699 }
15601700
15611701 static int jpc_dec_process_unk(jpc_dec_t *dec, jpc_ms_t *ms)
15621702 {
1563− /* Eliminate compiler warnings about unused variables. */
1564− USED(dec);
1703+ JAS_UNUSED(dec);
15651704
1566− jas_eprintf("warning: ignoring unknown marker segment (0x%x)\n",
1705+ jas_logwarnf("warning: ignoring unknown marker segment (0x%x)\n",
15671706 ms->id);
15681707 return 0;
15691708 }
@@ -1586,6 +1725,7 @@ static jpc_dec_cp_t *jpc_dec_cp_create(uint_fast16_t numcomps) · 16 unmodified lines
15861725 cp->numlyrs = 0;
15871726 cp->mctid = 0;
15881727 cp->csty = 0;
1728+ cp->pchglist = 0;
15891729 if (!(cp->ccps = jas_alloc2(cp->numcomps, sizeof(jpc_dec_ccp_t)))) {
15901730 goto error;
15911731 }
@@ -1694,7 +1834,11 @@ static int calcstepsizes(uint_fast16_t refstepsize, unsigned numrlvls, · 102 unmodified lines
16941834 mant = JPC_QCX_GETMANT(refstepsize);
16951835 const unsigned numbands = 3 * numrlvls - 2;
16961836 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
16981842 const unsigned r = (bandno + 2) / 3;
16991843 const unsigned nb = (r == 0) ? (numrlvls - 1) - r : (numrlvls - 1) - r + 1;
17001844 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
17581902 {
17591903 int rlvlno;
17601904
1761− /* Eliminate compiler warnings about unused variables. */
1762− USED(cp);
1905+ JAS_UNUSED(cp);
17631906
17641907 if ((flags & JPC_COC) || !(ccp->flags & JPC_COC)) {
17651908 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
18031946 {
18041947 int bandno;
18051948
1806− /* Eliminate compiler warnings about unused variables. */
1807− USED(cp);
1949+ JAS_UNUSED(cp);
18081950
18091951 /* Sanity check to prevent buffer overflow */
18101952 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
18862028 // a reconstruction parameter defined in E 1.1.2 of the ISO/IEC 15444-1
18872029 jpc_fix_t recparam = JPC_FIX_HALF;
18882030
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+
18902040 if (absstepsize == jpc_inttofix(1)) {
18912041 return;
18922042 }
@@ -1920,7 +2070,7 @@ static void jpc_undo_roi(jas_matrix_t *x, int roishift, int bgshift, unsigned nu · 27 unmodified lines
19202070 if (roishift < 0) {
19212071 /* We could instead return an error here. */
19222072 /* 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 "
19242074 "(bitstream is probably corrupt)\n");
19252075 roishift = 0;
19262076 }
@@ -1953,7 +2103,7 @@ static void jpc_undo_roi(jas_matrix_t *x, int roishift, int bgshift, unsigned nu · 26 unmodified lines
19532103 Here we ensure that any such bits are masked off. */
19542104 if (mag & (~mask)) {
19552105 if (!warn) {
1956− jas_eprintf("warning: possibly corrupt code stream\n");
2106+ jas_logwarnf("warning: possibly corrupt code stream\n");
19572107 warn = true;
19582108 }
19592109 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
19922142 dec->cp = 0;
19932143 dec->maxlyrs = impopts->maxlyrs;
19942144 dec->maxpkts = impopts->maxpkts;
1995−dec->numpkts = 0;
2145+ dec->numpkts = 0;
19962146 dec->ppmseqno = 0;
19972147 dec->state = 0;
19982148 dec->cmpts = 0;
@@ -2001,6 +2151,10 @@ dec->numpkts = 0; · 2 unmodified lines
20012151 dec->curtileendoff = 0;
20022152 dec->max_samples = impopts->max_samples;
20032153
2154+ if (jas_get_debug_level() >= 1) {
2155+ jas_logdebugf(1, "debug %d\n", jas_get_debug_level());
2156+ }
2157+
20042158 return dec;
20052159 }
20062160
@@ -2119,6 +2273,83 @@ void jpc_seg_destroy(jpc_dec_seg_t *seg) · 112 unmodified lines
21192273 jas_free(seg);
21202274 }
21212275
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+
21222353 static jpc_streamlist_t *jpc_streamlist_create()
21232354 {
21242355 jpc_streamlist_t *streamlist;
@@ -2366,3 +2597,75 @@ static void jpc_ppxstabent_destroy(jpc_ppxstabent_t *ent) · 241 unmodified lines
23662597 }
23672598 jas_free(ent);
23682599 }
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+}
jpc_dec.h+1−0
@@ -77,6 +77,7 @@ · 76 unmodified lines
7777 #include "jasper/jas_stream.h"
7878 #include "jasper/jas_image.h"
7979
80+#include "jpc_cod.h"
8081 #include "jpc_tsfb.h"
8182 #include "jpc_tagtree.h"
8283 #include "jpc_cs.h"
jpc_enc.c+2665−0
@@ -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+}
jpc_enc.h+650−0
@@ -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.

jpc_fix.h+28−15

This diff is large: its 68 lines aren’t shown here.

jpc_math.c+34−0

This diff is large: its 38 lines aren’t shown here.

jpc_math.h+8−0

This diff is large: its 15 lines aren’t shown here.

jpc_mqdec.c+22−4

This diff is large: its 45 lines aren’t shown here.

jpc_mqdec.h+7−0

This diff is large: its 14 lines aren’t shown here.

jpc_mqenc.c+386−0

This diff is large: its 387 lines aren’t shown here.

jpc_mqenc.h+217−0

This diff is large: its 218 lines aren’t shown here.

jpc_qmfb.c+131−141

This diff is large: its 522 lines aren’t shown here.

jpc_t1cod.c+18−15

This diff is large: its 103 lines aren’t shown here.

jpc_t1cod.h+2−0

This diff is large: its 9 lines aren’t shown here.

jpc_t1dec.c+19−17

This diff is large: its 99 lines aren’t shown here.

jpc_t1enc.c+895−0

This diff is large: its 896 lines aren’t shown here.

jpc_t1enc.h+86−0

This diff is large: its 87 lines aren’t shown here.

jpc_t2cod.c+153−53

This diff is large: its 340 lines aren’t shown here.

jpc_t2cod.h+6−0

This diff is large: its 11 lines aren’t shown here.

jpc_t2dec.c+47−21

This diff is large: its 250 lines aren’t shown here.

jpc_t2enc.c+656−0

This diff is large: its 657 lines aren’t shown here.

jpc_t2enc.h+105−0

This diff is large: its 106 lines aren’t shown here.

jpc_tagtree.c+21−6

This diff is large: its 52 lines aren’t shown here.

jpc_tagtree.h+3−0

This diff is large: its 8 lines aren’t shown here.

jpc_tsfb.c+9−4

This diff is large: its 48 lines aren’t shown here.

jpc_util.c+186−0

This diff is large: its 187 lines aren’t shown here.

jpc_util.h+82−0

This diff is large: its 83 lines aren’t shown here.

mklib+35−0

This diff is large: its 61 lines aren’t shown here.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t