Coverage Report

Created: 2026-04-09 07:06

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