Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/jpegxr/cr_parse.c
Line
Count
Source
1
2
3
/*************************************************************************
4
*
5
* This software module was originally contributed by Microsoft
6
* Corporation in the course of development of the
7
* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
8
* reference purposes and its performance may not have been optimized.
9
*
10
* This software module is an implementation of one or more
11
* tools as specified by the JPEG XR standard.
12
*
13
* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
14
* copyright license to copy, distribute, and make derivative works
15
* of this software module or modifications thereof for use in
16
* products claiming conformance to the JPEG XR standard as
17
* specified by ITU-T T.832 | ISO/IEC 29199-2.
18
*
19
* ITU/ISO/IEC give users the same free license to this software
20
* module or modifications thereof for research purposes and further
21
* ITU/ISO/IEC standardization.
22
*
23
* Those intending to use this software module in products are advised
24
* that its use may infringe existing patents. ITU/ISO/IEC have no
25
* liability for use of this software module or modifications thereof.
26
*
27
* Copyright is not released for products that do not conform to
28
* to the JPEG XR standard as specified by ITU-T T.832 |
29
* ISO/IEC 29199-2.
30
*
31
******** Section to be removed when the standard is published ************
32
*
33
* Assurance that the contributed software module can be used
34
* (1) in the ITU-T "T.JXR" | ISO/IEC 29199 ("JPEG XR") standard once the
35
* standard has been adopted; and
36
* (2) to develop the JPEG XR standard:
37
*
38
* Microsoft Corporation and any subsequent contributors to the development
39
* of this software grant ITU/ISO/IEC all rights necessary to include
40
* the originally developed software module or modifications thereof in the
41
* JPEG XR standard and to permit ITU/ISO/IEC to offer such a royalty-free,
42
* worldwide, non-exclusive copyright license to copy, distribute, and make
43
* derivative works of this software module or modifications thereof for
44
* use in products claiming conformance to the JPEG XR standard as
45
* specified by ITU-T T.832 | ISO/IEC 29199-2, and to the extent that
46
* such originally developed software module or portions of it are included
47
* in an ITU/ISO/IEC standard. To the extent that the original contributors
48
* may own patent rights that would be required to make, use, or sell the
49
* originally developed software module or portions thereof included in the
50
* ITU/ISO/IEC standard in a conforming product, the contributors will
51
* assure ITU/ISO/IEC that they are willing to negotiate licenses under
52
* reasonable and non-discriminatory terms and conditions with
53
* applicants throughout the world and in accordance with their patent
54
* rights declarations made to ITU/ISO/IEC (if any).
55
*
56
* Microsoft, any subsequent contributors, and ITU/ISO/IEC additionally
57
* gives You a free license to this software module or modifications
58
* thereof for the sole purpose of developing the JPEG XR standard.
59
*
60
******** end of section to be removed when the standard is published *****
61
*
62
* Microsoft Corporation retains full right to modify and use the code
63
* for its own purpose, to assign or donate the code to a third party,
64
* and to inhibit third parties from using the code for products that
65
* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
66
* ISO/IEC 29199-2.
67
*
68
* This copyright notice must be included in all copies or derivative
69
* works.
70
*
71
* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
72
***********************************************************************/
73
74
#ifdef _MSC_VER
75
#pragma comment (user,"$Id: cr_parse.c,v 1.12 2012-03-17 20:03:45 thor Exp $")
76
#endif
77
78
# include "jxr_priv.h"
79
# include <string.h>
80
# include <stdlib.h>
81
# include <assert.h>
82
83
static int read_ifd(jxr_container_t container, FILE*fd, int image_number, uint32_t*ifd_next);
84
85
jxr_container_t jxr_create_container(void)
86
0
{
87
0
    return jxr_create_container_alloc(NULL);
88
0
}
89
90
jxr_container_t jxr_create_container_alloc(jxr_alloc *alloc)
91
0
{
92
0
    jxr_container_t res = (jxr_container_t)
93
0
        jxr_calloc(alloc, 1, sizeof (struct jxr_container));
94
0
    if (res)
95
0
        res->alloc = alloc;
96
0
    return res;
97
0
}
98
99
void jxr_destroy_container(jxr_container_t container)
100
0
{
101
0
  int i;
102
103
0
  if(container == NULL)
104
0
    return;
105
106
0
  if (container->table) {
107
0
    for(i = 0;i < container->image_count;i++) {
108
0
      struct ifd_table *cur = container->table[i];
109
0
      if (cur && container->table_cnt) {
110
0
        int idx = container->table_cnt[i];
111
0
        while(idx--) {
112
0
          switch (cur[idx].type) {
113
0
          case 1: /* BYTE */
114
0
          case 2: /* UTF8 */
115
0
          case 6: /* SBYTE */
116
0
          case 7: /* UNDEFINED */
117
0
            if (cur[idx].cnt > 4)
118
0
              jxr_free(container->alloc, cur[idx].value_.p_byte);
119
0
            break;
120
0
          case 3: /* USHORT */
121
0
          case 8: /* SSHORT */
122
0
            if (cur[idx].cnt > 2)
123
0
              jxr_free(container->alloc, cur[idx].value_.p_short);
124
0
            break;
125
0
          case 4: /* ULONG */
126
0
          case 9: /* SLONG */
127
0
          case 11: /* FLOAT */
128
0
            if (cur[idx].cnt > 1)
129
0
              jxr_free(container->alloc, cur[idx].value_.p_long);
130
0
            break;
131
0
          case 5: /* URATIONAL */
132
0
          case 10: /* SRATIONAL */
133
0
          case 12: /* DOUBLE */
134
0
            jxr_free(container->alloc, cur[idx].value_.p_rational);
135
0
            break;
136
0
          }
137
0
        }
138
0
        jxr_free(container->alloc, cur);
139
0
      }
140
0
    }
141
0
    jxr_free(container->alloc, container->table);
142
0
  }
143
144
0
  if (container->table_cnt)
145
0
    jxr_free(container->alloc, container->table_cnt);
146
147
0
  jxr_free(container->alloc, container);
148
0
}
149
150
int jxr_read_image_container(jxr_container_t container, FILE*fd)
151
0
{
152
0
  unsigned char buf[4];
153
0
  size_t rc;
154
0
  int irc;
155
0
  uint32_t ifd_off;
156
157
0
  rc = fread(buf, 1, 4, fd);
158
0
  if (rc < 4)
159
0
    return JXR_EC_BADMAGIC;
160
161
0
  if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 12) {
162
0
    unsigned char buf2[8];
163
0
    rc = fread(buf2, 1, sizeof(buf2), fd);
164
0
    if (rc < sizeof(buf2))
165
0
      return JXR_EC_BADMAGIC;
166
    /*
167
    ** Support for the ISO box container
168
    */
169
0
    if (buf2[0] == 0x6a && buf2[1] == 0x50 && buf2[2] == 0x20 && buf2[3] == 0x20 &&
170
0
        buf2[4] == 0x0d && buf2[5] == 0x0a && buf2[6] == 0x87 && buf2[7] == 0x0a) {
171
0
      return jxr_read_image_container_boxed(container,fd);
172
0
    }
173
0
    return JXR_EC_BADMAGIC;
174
0
  }
175
0
  if (buf[0] != 0x49) return JXR_EC_BADMAGIC;
176
0
  if (buf[1] != 0x49) return JXR_EC_BADMAGIC;
177
0
  if (buf[2] != 0xbc) return JXR_EC_BADMAGIC;
178
0
  if (buf[3] > 0x01) return JXR_EC_BADMAGIC; /* Version. */
179
180
0
  rc = fread(buf, 1, 4, fd);
181
0
  if (rc != 4) return JXR_EC_IO;
182
183
0
  ifd_off = (buf[3] << 24) + (buf[2]<<16) + (buf[1]<<8) + (buf[0]<<0);
184
0
  container->image_count = 0;
185
186
0
  while (ifd_off != 0) {
187
0
    uint32_t ifd_next;
188
189
0
    container->image_count += 1;
190
0
    container->table_cnt = (unsigned*)jxr_realloc(container->alloc, container->table_cnt,
191
0
                                              container->image_count * sizeof(unsigned));
192
0
    container->table = (struct ifd_table**)jxr_realloc(container->alloc, container->table,
193
0
                                                    container->image_count * sizeof(struct ifd_table*));
194
195
0
    if (ifd_off & 0x1) return JXR_EC_IO;
196
0
    irc = fseek(fd, ifd_off, SEEK_SET);
197
0
    if (irc < 0) return (int) irc;
198
0
    irc = read_ifd(container, fd, container->image_count-1, &ifd_next);
199
0
    if (irc < 0) return (int) irc;
200
201
0
    ifd_off = ifd_next;
202
0
  }
203
204
0
  return 0;
205
0
}
206
207
int jxrc_image_count(jxr_container_t container)
208
0
{
209
0
  return container->image_count;
210
0
}
211
212
int jxrc_document_name(jxr_container_t container, int image, char ** string)
213
0
{
214
215
0
    unsigned ifd_cnt;
216
0
    struct ifd_table*ifd;
217
0
    unsigned idx;
218
219
0
    assert(image < container->image_count);
220
221
    /*
222
    ** The boxed-based file format could support this by labels,
223
    ** but it currently does not.
224
    */
225
0
    if (container->table == NULL) {
226
0
      return -1;
227
0
    } else {
228
0
      ifd_cnt = container->table_cnt[image];
229
0
      ifd = container->table[image];
230
231
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
232
0
        if (ifd[idx].tag == 0x010d)
233
0
          break;
234
0
      }
235
236
0
      if (idx >= ifd_cnt) return -1;
237
0
      if (ifd[idx].tag != 0x010d) return -1;
238
0
      assert(ifd[idx].type == 2);
239
240
0
      assert(string[0] == 0);
241
0
      string[0] = (char *)jxr_malloc(container->alloc, ifd[idx].cnt * sizeof(char));
242
0
      if (string[0] == NULL)
243
0
          return -1;
244
245
0
      if (ifd[idx].cnt <= 4) {
246
0
        unsigned i;
247
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
248
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
249
0
      }
250
0
      else {
251
0
        unsigned i;
252
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
253
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
254
0
      }
255
256
0
      return 0;
257
0
    }
258
0
}
259
260
int jxrc_image_description(jxr_container_t container, int image, char ** string)
261
0
{
262
0
    unsigned ifd_cnt;
263
0
    struct ifd_table*ifd;
264
0
    unsigned idx;
265
266
0
    assert(image < container->image_count);
267
268
    /*
269
    ** The ISO box based format could support this by UUID or XML boxes,
270
    ** but it currently does not.
271
    */
272
0
    if (container->table == NULL) {
273
0
      return -1;
274
0
    } else {
275
0
      ifd_cnt = container->table_cnt[image];
276
0
      ifd = container->table[image];
277
278
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
279
0
        if (ifd[idx].tag == 0x010e)
280
0
          break;
281
0
      }
282
283
0
      if (idx >= ifd_cnt) return -1;
284
0
      if (ifd[idx].tag != 0x010e) return -1;
285
0
      assert(ifd[idx].type == 2);
286
287
0
      assert(string[0] == 0);
288
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
289
0
      assert(string[0] != 0);
290
291
0
      if (ifd[idx].cnt <= 4) {
292
0
        unsigned i;
293
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
294
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
295
0
      }
296
0
      else {
297
0
        unsigned i;
298
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
299
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
300
0
      }
301
302
0
      return 0;
303
0
    }
304
0
}
305
306
int jxrc_equipment_make(jxr_container_t container, int image, char ** string)
307
0
{
308
0
    unsigned ifd_cnt;
309
0
    struct ifd_table*ifd;
310
0
    unsigned idx;
311
312
0
    assert(image < container->image_count);
313
314
    /*
315
    ** The box-based format could support this by means of XML or UUID
316
    ** boxes, but it currently does not.
317
    */
318
0
    if (container->table == NULL) {
319
0
      return -1;
320
0
    } else {
321
0
      ifd_cnt = container->table_cnt[image];
322
0
      ifd = container->table[image];
323
324
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
325
0
        if (ifd[idx].tag == 0x010f)
326
0
          break;
327
0
      }
328
329
0
      if (idx >= ifd_cnt) return -1;
330
0
      if (ifd[idx].tag != 0x010f) return -1;
331
0
      assert(ifd[idx].type == 2);
332
333
0
      assert(string[0] == 0);
334
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
335
0
      assert(string[0] != 0);
336
337
0
      if (ifd[idx].cnt <= 4) {
338
0
        unsigned i;
339
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
340
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
341
0
      }
342
0
      else {
343
0
        unsigned i;
344
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
345
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
346
0
      }
347
348
0
      return 0;
349
0
    }
350
0
}
351
352
int jxrc_equipment_model(jxr_container_t container, int image, char ** string)
353
0
{
354
0
    unsigned ifd_cnt;
355
0
    struct ifd_table*ifd;
356
0
    unsigned idx;
357
358
0
    assert(image < container->image_count);
359
360
    /*
361
    ** The container could support this by means of XML or UUID boxes, but it
362
    ** currently does not.
363
    */
364
0
    if (container->table == NULL) {
365
0
      return -1;
366
0
    } else {
367
0
      ifd_cnt = container->table_cnt[image];
368
0
      ifd = container->table[image];
369
370
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
371
0
        if (ifd[idx].tag == 0x0110)
372
0
          break;
373
0
      }
374
375
0
      if (idx >= ifd_cnt) return -1;
376
0
      if (ifd[idx].tag != 0x0110) return -1;
377
0
      assert(ifd[idx].type == 2);
378
379
0
      assert(string[0] == 0);
380
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
381
0
      assert(string[0] != 0);
382
383
0
      if (ifd[idx].cnt <= 4) {
384
0
        unsigned i;
385
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
386
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
387
0
      }
388
0
      else {
389
0
        unsigned i;
390
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
391
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
392
0
      }
393
394
0
      return 0;
395
0
    }
396
0
}
397
398
int jxrc_page_name(jxr_container_t container, int image, char ** string)
399
0
{
400
0
    unsigned ifd_cnt;
401
0
    struct ifd_table*ifd;
402
0
    unsigned idx;
403
404
0
    assert(image < container->image_count);
405
406
0
    if (container->table == NULL) {
407
0
      return -1;
408
0
    } else {
409
0
      ifd_cnt = container->table_cnt[image];
410
0
      ifd = container->table[image];
411
412
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
413
0
        if (ifd[idx].tag == 0x011d)
414
0
          break;
415
0
      }
416
417
0
      if (idx >= ifd_cnt) return -1;
418
0
      if (ifd[idx].tag != 0x011d) return -1;
419
0
      assert(ifd[idx].type == 2);
420
421
0
      assert(string[0] == 0);
422
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
423
0
      assert(string[0] != 0);
424
425
0
      if (ifd[idx].cnt <= 4) {
426
0
        unsigned i;
427
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
428
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
429
0
      }
430
0
      else {
431
0
        unsigned i;
432
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
433
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
434
0
      }
435
436
0
      return 0;
437
0
    }
438
0
}
439
440
int jxrc_page_number(jxr_container_t container, int image, unsigned short * value)
441
0
{
442
0
    unsigned ifd_cnt;
443
0
    struct ifd_table*ifd;
444
0
    unsigned idx;
445
446
0
    assert(image < container->image_count);
447
448
0
    if (container->table == NULL) {
449
0
      return -1;
450
0
    } else {
451
0
      ifd_cnt = container->table_cnt[image];
452
0
      ifd = container->table[image];
453
454
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
455
0
        if (ifd[idx].tag == 0x0129)
456
0
          break;
457
0
      }
458
459
0
      if (idx >= ifd_cnt) return -1;
460
0
      if (ifd[idx].tag != 0x0129) return -1;
461
0
      assert(ifd[idx].cnt == 2);
462
0
      assert(ifd[idx].type == 3);
463
464
0
      value[0] = ifd[idx].value_.v_short[0];
465
0
      value[1] = ifd[idx].value_.v_short[1];
466
467
0
      return 0;
468
0
    }
469
0
}
470
471
int jxrc_software_name_version(jxr_container_t container, int image, char ** string)
472
0
{
473
0
    unsigned ifd_cnt;
474
0
    struct ifd_table*ifd;
475
0
    unsigned idx;
476
477
0
    assert(image < container->image_count);
478
479
0
    if (container->table == NULL) {
480
0
      return -1;
481
0
    } else {
482
0
      ifd_cnt = container->table_cnt[image];
483
0
      ifd = container->table[image];
484
485
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
486
0
        if (ifd[idx].tag == 0x0131)
487
0
          break;
488
0
      }
489
490
0
      if (idx >= ifd_cnt) return -1;
491
0
      if (ifd[idx].tag != 0x0131) return -1;
492
0
      assert(ifd[idx].type == 2);
493
494
0
      assert(string[0] == 0);
495
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
496
0
      assert(string[0] != 0);
497
498
0
      if (ifd[idx].cnt <= 4) {
499
0
        unsigned i;
500
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
501
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
502
0
      }
503
0
      else {
504
0
        unsigned i;
505
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
506
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
507
0
      }
508
509
0
      return 0;
510
0
    }
511
0
}
512
513
int jxrc_date_time(jxr_container_t container, int image, char ** string)
514
0
{
515
0
    unsigned ifd_cnt;
516
0
    struct ifd_table*ifd;
517
0
    unsigned idx;
518
0
    unsigned i;
519
0
    assert(image < container->image_count);
520
521
0
    if (container->table == NULL) {
522
0
      return -1;
523
0
    } else {
524
0
      ifd_cnt = container->table_cnt[image];
525
0
      ifd = container->table[image];
526
527
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
528
0
        if (ifd[idx].tag == 0x0132)
529
0
          break;
530
0
      }
531
532
0
      if (idx >= ifd_cnt) return -1;
533
0
      if (ifd[idx].tag != 0x0132) return -1;
534
0
      assert(ifd[idx].type == 2);
535
536
0
      assert(string[0] == 0);
537
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
538
0
      assert(string[0] != 0);
539
0
      assert(ifd[idx].cnt == 20);
540
541
0
      for (i = 0 ; i < ifd[idx].cnt ; i++)
542
0
        string[0][i] = ifd[idx].value_.p_sbyte[i];
543
544
0
      assert(string[0][4] == 0x3a && string[0][7] == 0x3a && string[0][13] == 0x3a && string[0][16] == 0x3a);
545
0
      assert(string[0][10] == 0x20);
546
0
      assert((string[0][5] == '0' && (string[0][6] >= '1' && string[0][6] <= '9')) || (string[0][5] == '1' && (string[0][6] >= '0' && string[0][6] <= '2')));
547
0
      assert((string[0][8] == '0' && (string[0][9] >= '1' && string[0][9] <= '9')) || ((string[0][8] == '1' || string[0][8] == '2') && (string[0][9] >= '0' && string[0][9] <= '9')) || (string[0][8] == '3' && (string[0][9] >= '0' && string[0][9] <= '1')));
548
0
      assert(((string[0][11] == '0' || string[0][11] == '1') && (string[0][12] >= '0' && string[0][12] <= '9')) || (string[0][11] == '2' && (string[0][12] >= '0' && string[0][12] <= '3')));
549
0
      assert(string[0][14] >= '0' && string[0][14] < '6');
550
0
      assert(string[0][15] >= '0' && string[0][15] <= '9');
551
0
      assert(string[0][17] >= '0' && string[0][17] < '6');
552
0
      assert(string[0][18] >= '0' && string[0][18] <= '9');
553
554
0
      return 0;
555
0
    }
556
0
}
557
558
int jxrc_artist_name(jxr_container_t container, int image, char ** string)
559
0
{
560
0
    unsigned ifd_cnt;
561
0
    struct ifd_table*ifd;
562
0
    unsigned idx;
563
564
0
    assert(image < container->image_count);
565
566
0
    if (container->table == NULL) {
567
0
      return -1;
568
0
    } else {
569
0
      ifd_cnt = container->table_cnt[image];
570
0
      ifd = container->table[image];
571
572
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
573
0
        if (ifd[idx].tag == 0x013b)
574
0
          break;
575
0
      }
576
577
0
      if (idx >= ifd_cnt) return -1;
578
0
      if (ifd[idx].tag != 0x013b) return -1;
579
0
      assert(ifd[idx].type == 2);
580
581
0
      assert(string[0] == 0);
582
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
583
0
      assert(string[0] != 0);
584
585
0
      if (ifd[idx].cnt <= 4) {
586
0
        unsigned i;
587
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
588
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
589
0
      }
590
0
      else {
591
0
        unsigned i;
592
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
593
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
594
0
      }
595
596
0
      return 0;
597
0
    }
598
0
}
599
600
int jxrc_host_computer(jxr_container_t container, int image, char ** string)
601
0
{
602
0
    unsigned ifd_cnt;
603
0
    struct ifd_table*ifd;
604
0
    unsigned idx;
605
606
0
    assert(image < container->image_count);
607
608
0
    if (container->table == NULL) {
609
0
      return -1;
610
0
    } else {
611
0
      ifd_cnt = container->table_cnt[image];
612
0
      ifd = container->table[image];
613
614
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
615
0
        if (ifd[idx].tag == 0x013c)
616
0
          break;
617
0
      }
618
619
0
      if (idx >= ifd_cnt) return -1;
620
0
      if (ifd[idx].tag != 0x013c) return -1;
621
0
      assert(ifd[idx].type == 2);
622
623
0
      assert(string[0] == 0);
624
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
625
0
      assert(string[0] != 0);
626
627
0
      if (ifd[idx].cnt <= 4) {
628
0
        unsigned i;
629
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
630
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
631
0
      }
632
0
      else {
633
0
        unsigned i;
634
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
635
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
636
0
      }
637
638
0
      return 0;
639
0
    }
640
0
}
641
642
int jxrc_copyright_notice(jxr_container_t container, int image, char ** string)
643
0
{
644
0
    unsigned ifd_cnt;
645
0
    struct ifd_table*ifd;
646
0
    unsigned idx;
647
648
0
    assert(image < container->image_count);
649
650
    /*
651
    ** Once implemented, this might go into the IPR box.
652
    */
653
0
    if (container->table == NULL) {
654
0
      return -1;
655
0
    } else {
656
0
      ifd_cnt = container->table_cnt[image];
657
0
      ifd = container->table[image];
658
659
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
660
0
        if (ifd[idx].tag == 0x8298)
661
0
          break;
662
0
      }
663
664
0
      if (idx >= ifd_cnt) return -1;
665
0
      if (ifd[idx].tag != 0x8298) return -1;
666
0
      assert(ifd[idx].type == 2);
667
668
0
      assert(string[0] == 0);
669
0
      string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
670
0
      assert(string[0] != 0);
671
672
0
      if (ifd[idx].cnt <= 4) {
673
0
        unsigned i;
674
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
675
0
          string[0][i] = ifd[idx].value_.v_sbyte[i];
676
0
      }
677
0
      else {
678
0
        unsigned i;
679
0
        for (i = 0 ; i < ifd[idx].cnt ; i++)
680
0
          string[0][i] = ifd[idx].value_.p_sbyte[i];
681
0
      }
682
683
0
      return 0;
684
0
    }
685
0
}
686
687
/*
688
** This shall return 1 if the image is in sRGB, -1 otherwise, or 0 if
689
** unknown.
690
*/
691
unsigned short jxrc_color_space(jxr_container_t container, int image)
692
0
{
693
0
    unsigned ifd_cnt;
694
0
    struct ifd_table*ifd;
695
0
    unsigned idx;
696
0
    unsigned short value;
697
698
0
    assert(image < container->image_count);
699
700
701
0
    if (container->table == NULL) {
702
0
      if (container->color == 25) /* ISO indicator for sRGB */
703
0
        return 1;
704
0
      return 0xffff;
705
0
    }
706
707
0
    ifd_cnt = container->table_cnt[image];
708
0
    ifd = container->table[image];
709
710
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
711
0
        if (ifd[idx].tag == 0xa001)
712
0
            break;
713
0
    }
714
715
0
    if (idx >= ifd_cnt) return 0;
716
0
    if (ifd[idx].tag != 0xa001) return 0;
717
0
    assert(ifd[idx].cnt == 1);
718
0
    assert(ifd[idx].type == 3);
719
720
0
    value = ifd[idx].value_.v_short[0];
721
0
    if (value != 0x0001)
722
0
        value = 0xffff;
723
0
    if (value == 0x0001) {
724
0
        switch(_jxrc_image_pixelformat(container, image)) {
725
0
            case JXRC_FMT_24bppRGB:
726
0
            case JXRC_FMT_24bppBGR:
727
0
            case JXRC_FMT_32bppBGR:
728
0
            case JXRC_FMT_48bppRGB:
729
0
            case JXRC_FMT_32bppBGRA:
730
0
            case JXRC_FMT_64bppRGBA:
731
0
            case JXRC_FMT_32bppPBGRA:
732
0
            case JXRC_FMT_64bppPRGBA:
733
0
            case JXRC_FMT_32bppCMYK:
734
0
            case JXRC_FMT_40bppCMYKAlpha:
735
0
            case JXRC_FMT_64bppCMYK:
736
0
            case JXRC_FMT_80bppCMYKAlpha:
737
0
            case JXRC_FMT_24bpp3Channels:
738
0
            case JXRC_FMT_32bpp4Channels:
739
0
            case JXRC_FMT_40bpp5Channels:
740
0
            case JXRC_FMT_48bpp6Channels:
741
0
            case JXRC_FMT_56bpp7Channels:
742
0
            case JXRC_FMT_64bpp8Channels:
743
0
            case JXRC_FMT_32bpp3ChannelsAlpha:
744
0
            case JXRC_FMT_40bpp4ChannelsAlpha:
745
0
            case JXRC_FMT_48bpp5ChannelsAlpha:
746
0
            case JXRC_FMT_56bpp6ChannelsAlpha:
747
0
            case JXRC_FMT_64bpp7ChannelsAlpha:
748
0
            case JXRC_FMT_72bpp8ChannelsAlpha:
749
0
            case JXRC_FMT_48bpp3Channels:
750
0
            case JXRC_FMT_64bpp4Channels:
751
0
            case JXRC_FMT_80bpp5Channels:
752
0
            case JXRC_FMT_96bpp6Channels:
753
0
            case JXRC_FMT_112bpp7Channels:
754
0
            case JXRC_FMT_128bpp8Channels:
755
0
            case JXRC_FMT_64bpp3ChannelsAlpha:
756
0
            case JXRC_FMT_80bpp4ChannelsAlpha:
757
0
            case JXRC_FMT_96bpp5ChannelsAlpha:
758
0
            case JXRC_FMT_112bpp6ChannelsAlpha:
759
0
            case JXRC_FMT_128bpp7ChannelsAlpha:
760
0
            case JXRC_FMT_144bpp8ChannelsAlpha:
761
0
            case JXRC_FMT_8bppGray:
762
0
            case JXRC_FMT_16bppGray:
763
0
            case JXRC_FMT_BlackWhite:
764
0
            case JXRC_FMT_16bppBGR555:
765
0
            case JXRC_FMT_16bppBGR565:
766
0
            case JXRC_FMT_32bppBGR101010:
767
0
            case JXRC_FMT_32bppCMYKDIRECT:
768
0
            case JXRC_FMT_64bppCMYKDIRECT:
769
0
            case JXRC_FMT_40bppCMYKDIRECTAlpha:
770
0
            case JXRC_FMT_80bppCMYKDIRECTAlpha:
771
0
            case JXRC_FMT_12bppYCC420:
772
0
            case JXRC_FMT_16bppYCC422:
773
0
            case JXRC_FMT_20bppYCC422:
774
0
            case JXRC_FMT_32bppYCC422:
775
0
            case JXRC_FMT_24bppYCC444:
776
0
            case JXRC_FMT_30bppYCC444:
777
0
            case JXRC_FMT_48bppYCC444:
778
0
            case JXRC_FMT_20bppYCC420Alpha:
779
0
            case JXRC_FMT_24bppYCC422Alpha:
780
0
            case JXRC_FMT_30bppYCC422Alpha:
781
0
            case JXRC_FMT_48bppYCC422Alpha:
782
0
            case JXRC_FMT_32bppYCC444Alpha:
783
0
            case JXRC_FMT_40bppYCC444Alpha:
784
0
            case JXRC_FMT_64bppYCC444Alpha:
785
0
                break;
786
0
            default:
787
                /* Color space tag can equal 1 only if format is UINT  */
788
0
                assert(0);
789
0
                break;
790
0
        }
791
0
    }
792
0
    return value;
793
0
}
794
795
jxrc_t_pixelFormat _jxrc_image_pixelformat(jxr_container_t container, int imagenum)
796
0
{
797
0
    unsigned ifd_cnt;
798
0
    struct ifd_table*ifd;
799
0
    unsigned idx;
800
801
0
    unsigned char guid[16];
802
0
    int i;
803
0
    assert(imagenum < container->image_count);
804
0
    assert(container->table);
805
806
0
    if (container->table == NULL)
807
0
      return (jxrc_t_pixelFormat)-1;
808
809
0
    ifd_cnt = container->table_cnt[imagenum];
810
0
    ifd = container->table[imagenum];
811
812
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
813
0
        if (ifd[idx].tag == 0xbc01)
814
0
            break;
815
0
    }
816
817
0
    assert(idx < ifd_cnt);
818
0
    assert(ifd[idx].tag == 0xbc01);
819
0
    assert(ifd[idx].cnt == 16);
820
0
    memcpy(guid, ifd[idx].value_.p_byte, 16);
821
0
    for(i=0; i< NUM_GUIDS; i++)
822
0
    {
823
0
      if(isEqualGUID(guid, jxr_guids[i]))
824
0
      {
825
0
        break;
826
0
      }
827
0
    }
828
0
    if(i==NUM_GUIDS)
829
0
        assert(0);
830
0
    return (jxrc_t_pixelFormat)i;
831
832
0
}
833
834
/*
835
** Returns the spatial orientation of the image
836
*/
837
unsigned long jxrc_spatial_xfrm_primary(jxr_container_t container, int image)
838
0
{
839
0
    unsigned ifd_cnt;
840
0
    struct ifd_table*ifd;
841
0
    unsigned idx;
842
0
    unsigned long spatial_xfrm;
843
844
0
    assert(image < container->image_count);
845
846
0
    if (container->table == NULL) {
847
      /* Even though the file format defines a mechanism to support
848
      ** rotation, this is currently not implemented in this software.
849
      */
850
0
      return 0;
851
0
    }
852
853
0
    ifd_cnt = container->table_cnt[image];
854
0
    ifd = container->table[image];
855
856
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
857
0
        if (ifd[idx].tag == 0xbc02)
858
0
            break;
859
0
    }
860
861
0
    if (idx >= ifd_cnt) return 0;
862
0
    if (ifd[idx].tag != 0xbc02) return 0;
863
0
    assert(ifd[idx].cnt == 1);
864
865
0
    switch (ifd[idx].type) {
866
0
        case 4: /* ULONG */
867
0
            spatial_xfrm = (unsigned long) ifd[idx].value_.v_long;
868
0
            break;
869
0
        case 3: /* USHORT */
870
0
            spatial_xfrm = (unsigned long) ifd[idx].value_.v_short[0];
871
0
            break;
872
0
        case 1: /* BYTE */
873
0
            spatial_xfrm = (unsigned long) ifd[idx].value_.v_byte[0];
874
0
            break;
875
0
        default:
876
0
            assert(0);
877
0
            spatial_xfrm = 0; /* silence warning */
878
0
            break;
879
0
    }
880
881
0
    if (spatial_xfrm > 7 /*|| spatial_xfrm < 0*/)
882
0
        spatial_xfrm = 0;
883
0
    return spatial_xfrm;
884
0
}
885
886
unsigned long jxrc_image_type(jxr_container_t container, int image)
887
0
{
888
0
    unsigned ifd_cnt;
889
0
    struct ifd_table*ifd;
890
0
    unsigned idx;
891
0
    unsigned long image_type;
892
893
0
    assert(image < container->image_count);
894
895
0
    if (container->table == NULL) {
896
0
      return 0; /* neither a preview nor a page of a multipage image sequence,
897
                ** the latter would be supported by JPX, though not by this implementation.
898
                */
899
0
    }
900
901
0
    ifd_cnt = container->table_cnt[image];
902
0
    ifd = container->table[image];
903
904
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
905
0
        if (ifd[idx].tag == 0xbc04)
906
0
            break;
907
0
    }
908
909
0
    if (idx >= ifd_cnt) return 0;
910
0
    if (ifd[idx].tag != 0xbc04) return 0;
911
0
    assert(ifd[idx].cnt == 1);
912
0
    assert(ifd[idx].type == 4);
913
914
0
    image_type = ifd[idx].value_.v_long;
915
0
    image_type &= 0x00000003;
916
0
    return image_type;
917
0
}
918
919
int jxrc_ptm_color_info(jxr_container_t container, int image, unsigned char * buf)
920
0
{
921
0
    unsigned ifd_cnt;
922
0
    struct ifd_table*ifd;
923
0
    unsigned idx;
924
0
    uint32_t i;
925
926
0
    assert(image < container->image_count);
927
0
    assert(buf);
928
929
0
    if (container->table == NULL) {
930
0
      return -1; /* Expressible by the color spec box, though not by this implementation. */
931
0
    }
932
933
0
    ifd_cnt = container->table_cnt[image];
934
0
    ifd = container->table[image];
935
936
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
937
0
        if (ifd[idx].tag == 0xbc05)
938
0
            break;
939
0
    }
940
941
0
    if (idx >= ifd_cnt) return -1;
942
0
    if (ifd[idx].tag != 0xbc05) return -1;
943
0
    assert(ifd[idx].cnt == 4);
944
0
    assert(ifd[idx].type == 1);
945
946
0
    for (i = 0 ; i < 4 ; i += 1)
947
0
        buf[i] = ifd[idx].value_.v_byte[i];
948
949
0
    return 0;
950
0
}
951
952
int jxrc_profile_level_container(jxr_container_t container, int image, unsigned char * profile, unsigned char * level)
953
0
{
954
0
    unsigned ifd_cnt;
955
0
    struct ifd_table*ifd;
956
0
    unsigned idx;
957
0
    unsigned char * data;
958
0
    uint32_t count_remaining;
959
0
    uint8_t last, last_flag;
960
961
0
    assert(image < container->image_count);
962
0
    assert(profile);
963
0
    assert(level);
964
965
0
    if (container->table == NULL) {
966
      /* Parsed to here for the box-based file format */
967
0
      return container->profile_idc;
968
0
    }
969
970
0
    ifd_cnt = container->table_cnt[image];
971
0
    ifd = container->table[image];
972
973
0
    data = 0;
974
975
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
976
0
        if (ifd[idx].tag == 0xbc06)
977
0
            break;
978
0
    }
979
980
0
    if (idx >= ifd_cnt) return -1;
981
0
    if (ifd[idx].tag != 0xbc06) return -1;
982
0
    assert(ifd[idx].type == 1);
983
0
    assert(ifd[idx].cnt > 3);
984
985
0
    if (ifd[idx].cnt <= 4) {
986
0
      data = (unsigned char *) (ifd[idx].value_.v_sbyte);
987
0
    }
988
0
    else {
989
0
      data = (unsigned char *) (ifd[idx].value_.p_sbyte);
990
0
    }
991
992
0
    count_remaining = ifd[idx].cnt;
993
0
    for (last = 0 ; last == 0 ; last = last_flag) {
994
0
        profile[0] = data[0];
995
0
        level[0] = data[1];
996
0
        last_flag = (data[3] & 0x1);
997
0
        data += 4;
998
0
        count_remaining -= 4;
999
0
        assert(count_remaining == 0 || count_remaining > 3);
1000
0
    }
1001
1002
0
    return 0;
1003
0
}
1004
1005
unsigned long jxrc_image_width(jxr_container_t container, int image)
1006
0
{
1007
0
    unsigned ifd_cnt;
1008
0
    struct ifd_table*ifd;
1009
0
    unsigned idx;
1010
0
    unsigned long width;
1011
1012
0
    assert(image < container->image_count);
1013
1014
0
    if (container->table == NULL) {
1015
0
      return container->wid;
1016
0
    }
1017
1018
0
    ifd_cnt = container->table_cnt[image];
1019
0
    ifd = container->table[image];
1020
1021
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1022
0
        if (ifd[idx].tag == 0xbc80)
1023
0
            break;
1024
0
    }
1025
1026
0
    assert(idx < ifd_cnt);
1027
0
    assert(ifd[idx].tag == 0xbc80);
1028
0
    assert(ifd[idx].cnt == 1);
1029
1030
0
    switch (ifd[idx].type) {
1031
0
        case 4: /* ULONG */
1032
0
            width = (unsigned long) ifd[idx].value_.v_long;
1033
0
            break;
1034
0
        case 3: /* USHORT */
1035
0
            width = (unsigned long) ifd[idx].value_.v_short[0];
1036
0
            break;
1037
0
        case 1: /* BYTE */
1038
0
            width = (unsigned long) ifd[idx].value_.v_byte[0];
1039
0
            break;
1040
0
        default:
1041
0
            assert(0);
1042
0
            width = 0; /* silence warning */
1043
0
            break;
1044
0
    }
1045
1046
0
    return width;
1047
0
}
1048
1049
unsigned long jxrc_image_height(jxr_container_t container, int image)
1050
0
{
1051
0
    unsigned ifd_cnt;
1052
0
    struct ifd_table*ifd;
1053
0
    unsigned idx;
1054
0
    unsigned long height;
1055
1056
0
    assert(image < container->image_count);
1057
1058
0
    if (container->table == NULL) {
1059
0
      return container->hei;
1060
0
    }
1061
1062
0
    ifd_cnt = container->table_cnt[image];
1063
0
    ifd = container->table[image];
1064
1065
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1066
0
        if (ifd[idx].tag == 0xbc81)
1067
0
            break;
1068
0
    }
1069
1070
0
    assert(idx < ifd_cnt);
1071
0
    assert(ifd[idx].tag == 0xbc81);
1072
0
    assert(ifd[idx].cnt == 1);
1073
1074
0
    switch (ifd[idx].type) {
1075
0
        case 4: /* ULONG */
1076
0
            height = (unsigned long) ifd[idx].value_.v_long;
1077
0
            break;
1078
0
        case 3: /* USHORT */
1079
0
            height = (unsigned long) ifd[idx].value_.v_short[0];
1080
0
            break;
1081
0
        case 1: /* BYTE */
1082
0
            height = (unsigned long) ifd[idx].value_.v_byte[0];
1083
0
            break;
1084
0
        default:
1085
0
            assert(0);
1086
0
            height = 0; /* silence warning */
1087
0
            break;
1088
0
    }
1089
1090
0
    return height;
1091
0
}
1092
1093
float jxrc_width_resolution(jxr_container_t container, int image)
1094
0
{
1095
0
    unsigned ifd_cnt;
1096
0
    struct ifd_table*ifd;
1097
0
    unsigned idx;
1098
0
    float width_resolution;
1099
1100
0
    assert(image < container->image_count);
1101
1102
0
    if (container->table == NULL) {
1103
      /* This is representable by the resolution box, but this implementation does currently
1104
      ** not write a resolution box nor does it parse one.
1105
      ** Anyhow, metric units would surely be preferably here...
1106
      */
1107
0
      return 96.0;
1108
0
    }
1109
1110
0
    ifd_cnt = container->table_cnt[image];
1111
0
    ifd = container->table[image];
1112
1113
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1114
0
        if (ifd[idx].tag == 0xbc82)
1115
0
            break;
1116
0
    }
1117
1118
0
    if (idx >= ifd_cnt) return 96.0;
1119
0
    if (ifd[idx].tag != 0xbc82) return 96.0;
1120
0
    assert(ifd[idx].cnt == 1);
1121
0
    assert(ifd[idx].type == 11);
1122
1123
0
    width_resolution = ifd[idx].value_.v_float;
1124
0
    if (width_resolution == 0.0)
1125
0
        width_resolution = 96.0;
1126
0
    return width_resolution;
1127
0
}
1128
1129
float jxrc_height_resolution(jxr_container_t container, int image)
1130
0
{
1131
0
    unsigned ifd_cnt;
1132
0
    struct ifd_table*ifd;
1133
0
    unsigned idx;
1134
0
    float height_resolution;
1135
1136
0
    assert(image < container->image_count);
1137
1138
0
    if (container->table == NULL) {
1139
      /* This is representable by the resolution box, but this implementation does currently
1140
      ** not write a resolution box nor does it parse one.
1141
      ** Anyhow, metric units would surely be preferably here...
1142
      */
1143
0
      return 96.0;
1144
0
    }
1145
1146
0
    ifd_cnt = container->table_cnt[image];
1147
0
    ifd = container->table[image];
1148
1149
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1150
0
        if (ifd[idx].tag == 0xbc83)
1151
0
            break;
1152
0
    }
1153
1154
0
    if (idx >= ifd_cnt) return 96.0;
1155
0
    if (ifd[idx].tag != 0xbc83) return 96.0;
1156
0
    assert(ifd[idx].cnt == 1);
1157
0
    assert(ifd[idx].type == 11);
1158
1159
0
    height_resolution = ifd[idx].value_.v_float;
1160
0
    if (height_resolution == 0.0)
1161
0
        height_resolution = 96.0;
1162
0
    return height_resolution;
1163
0
}
1164
1165
unsigned long jxrc_image_offset(jxr_container_t container, int image)
1166
0
{
1167
0
    unsigned ifd_cnt;
1168
0
    struct ifd_table*ifd;
1169
0
    unsigned idx;
1170
0
    unsigned long pos;
1171
1172
0
    assert(image < container->image_count);
1173
1174
0
    if (container->table == NULL) {
1175
0
      if (image == 0)
1176
0
        return container->image_offset;
1177
0
      return 0;
1178
0
    } else {
1179
0
      ifd_cnt = container->table_cnt[image];
1180
0
      ifd = container->table[image];
1181
1182
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1183
0
        if (ifd[idx].tag == 0xbcc0)
1184
0
          break;
1185
0
      }
1186
1187
0
      assert(idx < ifd_cnt);
1188
0
      assert(ifd[idx].tag == 0xbcc0);
1189
0
      assert(ifd[idx].cnt == 1);
1190
1191
0
      switch (ifd[idx].type) {
1192
0
      case 4: /* ULONG */
1193
0
        pos = (unsigned long) ifd[idx].value_.v_long;
1194
0
        break;
1195
0
      case 3: /* USHORT */
1196
0
        pos = (unsigned long) ifd[idx].value_.v_short[0];
1197
0
        break;
1198
0
      case 1: /* BYTE */
1199
0
        pos = (unsigned long) ifd[idx].value_.v_byte[0];
1200
0
        break;
1201
0
      default:
1202
0
        assert(0);
1203
0
        pos = 0; /* silence warning */
1204
0
        break;
1205
0
      }
1206
1207
0
      return pos;
1208
0
    }
1209
0
}
1210
1211
unsigned long jxrc_image_bytecount(jxr_container_t container, int image)
1212
0
{
1213
0
    unsigned ifd_cnt;
1214
0
    struct ifd_table*ifd;
1215
0
    unsigned idx;
1216
0
    unsigned long pos;
1217
1218
0
    assert(image < container->image_count);
1219
1220
0
    if (container->table == NULL) {
1221
0
      if (image == 0)
1222
0
        return container->image_size;
1223
0
      return 0;
1224
0
    } else {
1225
0
      ifd_cnt = container->table_cnt[image];
1226
0
      ifd = container->table[image];
1227
1228
0
      for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1229
0
        if (ifd[idx].tag == 0xbcc1)
1230
0
          break;
1231
0
      }
1232
1233
0
      assert(idx < ifd_cnt);
1234
0
      assert(ifd[idx].tag == 0xbcc1);
1235
0
      assert(ifd[idx].cnt == 1);
1236
1237
0
      switch (ifd[idx].type) {
1238
0
      case 4: /* ULONG */
1239
0
        pos = (unsigned long) ifd[idx].value_.v_long;
1240
0
        break;
1241
0
      case 3: /* USHORT */
1242
0
        pos = (unsigned long) ifd[idx].value_.v_short[0];
1243
0
        break;
1244
0
      case 1: /* BYTE */
1245
0
        pos = (unsigned long) ifd[idx].value_.v_byte[0];
1246
0
        break;
1247
0
      default:
1248
0
        assert(0);
1249
0
        pos = 0; /* silence warning */
1250
0
        break;
1251
0
      }
1252
1253
0
      return pos;
1254
0
    }
1255
0
}
1256
1257
unsigned long jxrc_alpha_offset(jxr_container_t container, int image)
1258
0
{
1259
0
    unsigned ifd_cnt;
1260
0
    struct ifd_table*ifd;
1261
0
    unsigned idx;
1262
0
    unsigned long pos;
1263
1264
0
    assert(image < container->image_count);
1265
1266
0
    if (container->table == NULL) {
1267
0
      if (image == 0)
1268
0
        return container->alpha_offset;
1269
0
      return 0;
1270
0
    }
1271
1272
0
    ifd_cnt = container->table_cnt[image];
1273
0
    ifd = container->table[image];
1274
1275
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1276
0
        if (ifd[idx].tag == 0xBCC2)
1277
0
            break;
1278
0
    }
1279
1280
0
    if (idx >= ifd_cnt) return 0; /* No alpha coded image */
1281
0
    if (ifd[idx].tag != 0xbcc2) return 0;
1282
0
    assert(ifd[idx].cnt == 1);
1283
1284
0
    switch (ifd[idx].type) {
1285
0
        case 4: /* ULONG */
1286
0
            pos = (unsigned long) ifd[idx].value_.v_long;
1287
0
            break;
1288
0
        case 3: /* USHORT */
1289
0
            pos = (unsigned long) ifd[idx].value_.v_short[0];
1290
0
            break;
1291
0
        case 1: /* BYTE */
1292
0
            pos = (unsigned long) ifd[idx].value_.v_byte[0];
1293
0
            break;
1294
0
        default:
1295
0
            assert(0);
1296
0
            pos = 0; /* silence warning */
1297
0
            break;
1298
0
    }
1299
1300
0
    return pos;
1301
0
}
1302
1303
unsigned long jxrc_alpha_bytecount(jxr_container_t container, int image)
1304
0
{
1305
0
    unsigned ifd_cnt;
1306
0
    struct ifd_table*ifd;
1307
0
    unsigned idx;
1308
0
    unsigned long pos;
1309
1310
0
    assert(image < container->image_count);
1311
1312
0
    if (container->table == NULL) {
1313
0
      if (image == 0)
1314
0
        return container->alpha_size;
1315
0
      return 0;
1316
0
    }
1317
1318
0
    ifd_cnt = container->table_cnt[image];
1319
0
    ifd = container->table[image];
1320
1321
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1322
0
        if (ifd[idx].tag == 0xbcc3)
1323
0
            break;
1324
0
    }
1325
1326
1327
0
    if (idx >= ifd_cnt) return 0; /* No alpha coded image */
1328
0
    if (ifd[idx].tag != 0xbcc3) return 0;
1329
0
    assert(ifd[idx].cnt == 1);
1330
1331
0
    switch (ifd[idx].type) {
1332
0
        case 4: /* ULONG */
1333
0
            pos = (unsigned long) ifd[idx].value_.v_long;
1334
0
            break;
1335
0
        case 3: /* USHORT */
1336
0
            pos = (unsigned long) ifd[idx].value_.v_short[0];
1337
0
            break;
1338
0
        case 1: /* BYTE */
1339
0
            pos = (unsigned long) ifd[idx].value_.v_byte[0];
1340
0
            break;
1341
0
        default:
1342
0
            assert(0);
1343
0
            pos = 0; /* silence warning */
1344
0
            break;
1345
0
    }
1346
1347
0
    return pos;
1348
0
}
1349
1350
unsigned char jxrc_image_band_presence(jxr_container_t container, int image)
1351
0
{
1352
0
    unsigned ifd_cnt;
1353
0
    struct ifd_table*ifd;
1354
0
    unsigned idx;
1355
1356
0
    assert(image < container->image_count);
1357
1358
0
    if (container->table == NULL) {
1359
      /* This one is not represented by the file format, nor does it need to.
1360
      ** it is in the codestream anyhow...
1361
      */
1362
0
      return 0;
1363
0
    }
1364
0
    ifd_cnt = container->table_cnt[image];
1365
0
    ifd = container->table[image];
1366
1367
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1368
0
        if (ifd[idx].tag == 0xbcc4)
1369
0
            break;
1370
0
    }
1371
1372
    /*
1373
    ** THOR fix: returned -1, but the standard says that 0 shall be inferred if
1374
    ** this entry is not present.
1375
    */
1376
1377
0
    if (idx >= ifd_cnt) return 0;
1378
0
    if (ifd[idx].tag != 0xbcc4) return 0;
1379
0
    assert(ifd[idx].cnt == 1);
1380
0
    assert(ifd[idx].type == 1);
1381
1382
0
    return ifd[idx].value_.v_byte[0];
1383
0
}
1384
1385
unsigned char jxrc_alpha_band_presence(jxr_container_t container, int image)
1386
0
{
1387
0
    unsigned ifd_cnt;
1388
0
    struct ifd_table*ifd;
1389
0
    unsigned idx;
1390
1391
0
    assert(image < container->image_count);
1392
1393
0
    if (container->table == NULL) {
1394
      /* This one is not represented by the file format, nor does it need to.
1395
      ** it is in the codestream anyhow...
1396
      */
1397
0
      return 0;
1398
0
    }
1399
1400
0
    ifd_cnt = container->table_cnt[image];
1401
0
    ifd = container->table[image];
1402
1403
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1404
0
        if (ifd[idx].tag == 0xbcc5)
1405
0
            break;
1406
0
    }
1407
1408
1409
0
    if (idx >= ifd_cnt) return 0; /* tag is not present. THOR FIX: Shall be zero if not present. */
1410
0
    if (ifd[idx].tag != 0xbcc5) return 0; /* fix, too */
1411
0
    assert(ifd[idx].cnt == 1);
1412
0
    assert(ifd[idx].type == 1);
1413
1414
0
    return ifd[idx].value_.v_byte[0];
1415
0
}
1416
1417
int jxrc_padding_data(jxr_container_t container, int image)
1418
0
{
1419
0
    unsigned ifd_cnt;
1420
0
    struct ifd_table*ifd;
1421
0
    unsigned idx;
1422
1423
0
    assert(image < container->image_count);
1424
1425
0
    if (container->table == NULL) {
1426
      /* Unclear why an application should ever go here.
1427
      ** Padding data is representable by the 'free' box,
1428
      ** though a standard parser shall ignore it anyhow...
1429
      */
1430
0
      return -1;
1431
0
    }
1432
1433
1434
0
    ifd_cnt = container->table_cnt[image];
1435
0
    ifd = container->table[image];
1436
1437
0
    for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
1438
0
        if (ifd[idx].tag == 0xea1c)
1439
0
            break;
1440
0
    }
1441
1442
0
    if (idx >= ifd_cnt) return -1;
1443
0
    if (ifd[idx].tag != 0xea1c) return -1;
1444
0
    assert(ifd[idx].type == 7);
1445
0
    assert(ifd[idx].cnt > 1);
1446
1447
#ifndef NDEBUG
1448
    {
1449
        unsigned char * data;
1450
        if (ifd[idx].cnt <= 4)
1451
            data = (unsigned char *) ifd[idx].value_.v_sbyte;
1452
        else
1453
            data = (unsigned char *) ifd[idx].value_.p_sbyte;
1454
1455
        assert(data[0] == 0x1c);
1456
        assert(data[1] == 0xea);
1457
    }
1458
#endif
1459
1460
0
    return 0;
1461
0
}
1462
1463
static
1464
uint16_t bytes2_to_off(uint8_t*bp)
1465
0
{
1466
0
    return (bp[1]<<8) + (bp[0]);
1467
0
}
1468
1469
static
1470
uint32_t bytes4_to_off(uint8_t*bp)
1471
0
{
1472
0
    return (bp[3]<<24) + (bp[2]<<16) + (bp[1]<<8) + (bp[0]);
1473
0
}
1474
1475
static void
1476
fread0(uint8_t *buf, size_t size, FILE *fd)
1477
0
{
1478
0
  size_t n = fread(buf, 1, size, fd);
1479
0
  if (n != size)
1480
0
    memset(buf + n, 0, size - n);
1481
0
}
1482
1483
static int read_ifd(jxr_container_t container, FILE*fd, int image_number, uint32_t*ifd_next)
1484
0
{
1485
0
    unsigned char buf[16];
1486
0
    size_t rc;
1487
0
    int idx;
1488
0
    int ifd_tag_prev = 0;
1489
0
    int alpha_tag_check = 0;
1490
0
    uint32_t ifd_off;
1491
0
    struct ifd_table*cur;
1492
0
    uint16_t entry_count;
1493
1494
0
    *ifd_next = 0;
1495
1496
0
    rc = fread(buf, 1, 2, fd);
1497
0
    if (rc != 2) return -1;
1498
1499
0
    entry_count = (buf[1]<<8) + (buf[0]<<0);
1500
0
    container->table_cnt[image_number] = entry_count;
1501
1502
0
    cur = (struct ifd_table*)jxr_calloc(container->alloc, entry_count, sizeof(struct ifd_table));
1503
0
    if (cur == NULL)
1504
0
        return -1;
1505
1506
0
    container->table[image_number] = cur;
1507
1508
    /* First read in the entire directory. Don't interpret the
1509
    types yet, just save the values as v_bytes. We will go
1510
    through the types later and interpret the values more
1511
    precisely. */
1512
0
    for (idx = 0 ; idx < entry_count ; idx += 1) {
1513
0
        uint16_t ifd_tag;
1514
0
        uint16_t ifd_type;
1515
0
        uint32_t ifd_cnt;
1516
1517
0
        rc = fread(buf, 1, 12, fd);
1518
0
        assert(rc == 12);
1519
1520
0
        ifd_tag = (buf[1]<<8) + (buf[0]<<0);
1521
0
        if (ifd_tag == 0xbcc2)
1522
0
            alpha_tag_check += 1;
1523
0
        if (ifd_tag == 0xbcc3)
1524
0
            alpha_tag_check += 2;
1525
0
        if (ifd_tag == 0xbcc5)
1526
0
            alpha_tag_check += 4;
1527
0
        ifd_type = (buf[3]<<8) + (buf[2]<<0);
1528
0
        if (ifd_type == 7)
1529
0
            assert (ifd_tag == 0x8773 || ifd_tag == 0xea1c);
1530
0
        ifd_cnt = (buf[7]<<24) + (buf[6]<<16) + (buf[5]<<8) + buf[4];
1531
1532
0
        assert(ifd_tag > ifd_tag_prev);
1533
0
        if (ifd_tag <= ifd_tag_prev)
1534
0
            return -1;
1535
0
        ifd_tag_prev = ifd_tag;
1536
1537
0
        cur[idx].tag = ifd_tag;
1538
0
        cur[idx].type = ifd_type;
1539
0
        cur[idx].cnt = ifd_cnt;
1540
1541
0
        cur[idx].value_.v_byte[0] = buf[8];
1542
0
        cur[idx].value_.v_byte[1] = buf[9];
1543
0
        cur[idx].value_.v_byte[2] = buf[10];
1544
0
        cur[idx].value_.v_byte[3] = buf[11];
1545
0
    }
1546
    /* verify alpha ifd tags appear only in allowed combinations */
1547
0
    assert(alpha_tag_check == 0 || alpha_tag_check == 3 || alpha_tag_check == 7);
1548
1549
0
    rc = fread(buf, 1, 4, fd);
1550
0
    assert(rc == 4);
1551
1552
    /* Now interpret the tag types/values for easy access later. */
1553
0
    for (idx = 0 ; idx < entry_count ; idx += 1) {
1554
0
        switch (cur[idx].type) {
1555
1556
0
        case 1: /* BYTE */
1557
0
        case 2: /* UTF8 */
1558
0
        case 6: /* SBYTE */
1559
0
        case 7: /* UNDEFINED */
1560
0
            DODEBUG("Container %d: tag 0x%04x BYTE:", image_number, cur[idx].tag);
1561
0
            if (cur[idx].cnt > 4) {
1562
0
                ifd_off = bytes4_to_off(cur[idx].value_.v_byte);
1563
0
                assert((ifd_off & 1) == 0);
1564
0
                fseek(fd, ifd_off, SEEK_SET);
1565
0
                cur[idx].value_.p_byte = (uint8_t*)jxr_malloc(container->alloc, cur[idx].cnt);
1566
0
                if (cur[idx].value_.p_byte == NULL)
1567
0
                    return -1;
1568
0
                fread0(cur[idx].value_.p_byte, cur[idx].cnt, fd);
1569
#if defined(DETAILED_DEBUG)
1570
                {
1571
                int bb;
1572
                for (bb = 0 ; bb < cur[idx].cnt ; bb += 1)
1573
                    DODEBUG("%02x", cur[idx].value_.p_byte[bb]);
1574
                }
1575
#endif
1576
0
                if (cur[idx].type == 2) {
1577
0
                    int cc;
1578
0
                    for (cc = 1 ; cc < cur[idx].cnt ; cc += 1)
1579
0
                        assert((cur[idx].value_.p_byte[cc - 1] != 0) || (cur[idx].value_.p_byte[cc] != 0));
1580
0
                }
1581
0
            }
1582
0
            else {
1583
0
                if (cur[idx].type == 2) {
1584
0
                    int cc;
1585
0
                    for (cc = 1 ; cc < cur[idx].cnt ; cc += 1)
1586
0
                        assert((cur[idx].value_.v_byte[cc - 1] != 0) || (cur[idx].value_.v_byte[cc] != 0));
1587
0
                }
1588
0
            }
1589
            /* No action required to access individual bytes */
1590
0
            DODEBUG("\n");
1591
0
            break;
1592
1593
0
        case 3: /* USHORT */
1594
0
        case 8: /* SSHORT */
1595
0
            if (cur[idx].cnt <= 2) {
1596
0
                cur[idx].value_.v_short[0] = bytes2_to_off(cur[idx].value_.v_byte + 0);
1597
0
                cur[idx].value_.v_short[1] = bytes2_to_off(cur[idx].value_.v_byte + 2);
1598
0
                DODEBUG("Container %d: tag 0x%04x SHORT %u SHORT %u\n", image_number,
1599
0
                    cur[idx].tag, cur[idx].value_.v_short[0], cur[idx].value_.v_short[1]);
1600
0
            } else {
1601
0
                uint16_t cdx;
1602
1603
0
                ifd_off = bytes4_to_off(cur[idx].value_.v_byte);
1604
0
                assert((ifd_off & 1) == 0);
1605
0
                fseek(fd, ifd_off, SEEK_SET);
1606
0
                cur[idx].value_.p_short = (uint16_t*)jxr_calloc(container->alloc, cur[idx].cnt, sizeof(uint16_t));
1607
0
                if (cur[idx].value_.p_short == NULL)
1608
0
                    return -1;
1609
1610
0
                DODEBUG("Container %d: tag 0x%04x SHORT\n", image_number,
1611
0
                    cur[idx].tag);
1612
0
                for (cdx = 0 ; cdx < cur[idx].cnt ; cdx += 1) {
1613
0
                    uint8_t buf[2];
1614
0
                    fread0(buf, 2, fd);
1615
0
                    cur[idx].value_.p_short[cdx] = bytes2_to_off(buf);
1616
0
                    DODEBUG(" %u", cur[idx].value_.p_short[cdx]);
1617
0
                }
1618
0
                DODEBUG("\n");
1619
0
            }
1620
0
            break;
1621
1622
0
        case 4: /* ULONG */
1623
0
        case 9: /* SLONG */
1624
0
        case 11: /* FLOAT */
1625
0
            if (cur[idx].cnt == 1) {
1626
0
                cur[idx].value_.v_long = bytes4_to_off(cur[idx].value_.v_byte);
1627
0
                DODEBUG("Container %d: tag 0x%04x LONG %u\n", image_number,
1628
0
                    cur[idx].tag, cur[idx].value_.v_long);
1629
0
            } else {
1630
0
                uint32_t cdx;
1631
1632
0
                ifd_off = bytes4_to_off(cur[idx].value_.v_byte);
1633
0
                assert((ifd_off & 1) == 0);
1634
0
                fseek(fd, ifd_off, SEEK_SET);
1635
0
                cur[idx].value_.p_long = (uint32_t*) jxr_calloc(container->alloc, cur[idx].cnt, sizeof(uint32_t));
1636
0
                if (cur[idx].value_.p_long == NULL)
1637
0
                    return -1;
1638
1639
0
                DODEBUG("Container %d: tag 0x%04x LONG\n", image_number,
1640
0
                    cur[idx].tag);
1641
0
                for (cdx = 0 ; cdx < cur[idx].cnt ; cdx += 1) {
1642
0
                    uint8_t buf[4];
1643
0
                    fread0(buf, 4, fd);
1644
0
                    cur[idx].value_.p_long[cdx] = bytes4_to_off(buf);
1645
0
                    DODEBUG(" %u", cur[idx].value_.p_long[cdx]);
1646
0
                }
1647
0
                DODEBUG("\n");
1648
0
            }
1649
0
            break;
1650
1651
0
        case 5: /* URATIONAL */
1652
0
        case 10: /* SRATIONAL */
1653
0
        case 12: /* DOUBLE */
1654
0
          {
1655
0
            uint64_t cdx;
1656
1657
            /* Always offset */
1658
0
            ifd_off = bytes4_to_off(cur[idx].value_.v_byte);
1659
0
            assert((ifd_off & 1) == 0);
1660
0
            fseek(fd, ifd_off, SEEK_SET);
1661
0
            cur[idx].value_.p_rational = (uint64_t*)jxr_calloc(container->alloc, cur[idx].cnt, sizeof(uint64_t));
1662
0
            if (cur[idx].value_.p_rational == NULL)
1663
0
                return -1;
1664
1665
0
            DODEBUG("Container %d: tag 0x%04x LONG\n", image_number,
1666
0
                cur[idx].tag);
1667
0
            for (cdx = 0 ; cdx < cur[idx].cnt ; cdx += 1) {
1668
0
                uint8_t buf[4];
1669
0
                fread0(buf, 4, fd);
1670
0
                cur[idx].value_.p_long[2 * cdx + 0] = bytes4_to_off(buf);
1671
0
                fread0(buf, 4, fd);
1672
0
                cur[idx].value_.p_long[2 * cdx + 1] = bytes4_to_off(buf);
1673
0
                DODEBUG(" %u", cur[idx].value_.p_rational[cdx]);
1674
0
            }
1675
0
            DODEBUG("\n");
1676
0
          }
1677
0
            break;
1678
1679
0
        default:
1680
0
            DODEBUG("Container %d: tag 0x%04x type=%u\n", image_number, cur[idx].tag, cur[idx].type);
1681
0
            break;
1682
0
        }
1683
0
    }
1684
1685
    /* Tell the caller about the next ifd. */
1686
0
    *ifd_next = (buf[3] << 24) + (buf[2]<<16) + (buf[1]<<8) + (buf[0]<<0);
1687
1688
0
    return 0;
1689
0
}
1690
1691
1692
/*
1693
* $Log: cr_parse.c,v $
1694
* Revision 1.12  2012-03-17 20:03:45  thor
1695
* Fixed a lot of issues in the box parser - seems to work now in simple cases.
1696
*
1697
* Revision 1.11  2012-02-16 16:36:25  thor
1698
* Heavily reworked, but not yet tested.
1699
*
1700
* Revision 1.10  2012-02-14 22:06:36  thor
1701
* Started box parser.
1702
*
1703
* Revision 1.9  2011-04-28 08:45:42  thor
1704
* Fixed compiler warnings, ported to gcc 4.4, removed obsolete files.
1705
*
1706
* Revision 1.8  2010-06-19 11:48:36  thor
1707
* Fixed memory leaks.
1708
*
1709
* Revision 1.7  2010-05-22 22:14:35  thor
1710
* Fixed memory leaks in the TIFF parser.
1711
*
1712
* Revision 1.6  2010-03-31 07:50:58  thor
1713
* Replaced by the latest MS version.
1714
*
1715
* Revision 1.11 2009/05/29 12:00:00 microsoft
1716
* Reference Software v1.6 updates.
1717
*
1718
* Revision 1.10 2009/04/13 12:00:00 microsoft
1719
* Reference Software v1.5 updates.
1720
*
1721
* Revision 1.9 2008/03/21 21:23:14 steve
1722
* Some debug dump of the container.
1723
*
1724
* Revision 1.8 2008/03/05 19:32:02 gus
1725
* *** empty log message ***
1726
*
1727
* Revision 1.7 2008/03/01 02:46:08 steve
1728
* Add support for JXR container.
1729
*
1730
* Revision 1.6 2008/02/28 18:50:31 steve
1731
* Portability fixes.
1732
*
1733
* Revision 1.5 2008/02/26 23:52:44 steve
1734
* Remove ident for MS compilers.
1735
*
1736
* Revision 1.4 2007/11/26 01:47:15 steve
1737
* Add copyright notices per MS request.
1738
*
1739
* Revision 1.3 2007/11/07 18:11:35 steve
1740
* Accept magic number version 0
1741
*
1742
* Revision 1.2 2007/07/30 23:09:57 steve
1743
* Interleave FLEXBITS within HP block.
1744
*
1745
* Revision 1.1 2007/06/06 17:19:12 steve
1746
* Introduce to CVS.
1747
*
1748
*/
1749