Coverage Report

Created: 2026-04-09 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/jpegxr/cw_emit_boxed.c
Line
Count
Source
1
/*************************************************************************
2
*
3
* This software module was originally contributed by Microsoft
4
* Corporation in the course of development of the
5
* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
6
* reference purposes and its performance may not have been optimized.
7
*
8
* This software module is an implementation of one or more
9
* tools as specified by the JPEG XR standard.
10
*
11
* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
12
* copyright license to copy, distribute, and make derivative works
13
* of this software module or modifications thereof for use in
14
* products claiming conformance to the JPEG XR standard as
15
* specified by ITU-T T.832 | ISO/IEC 29199-2.
16
*
17
* ITU/ISO/IEC give users the same free license to this software
18
* module or modifications thereof for research purposes and further
19
* ITU/ISO/IEC standardization.
20
*
21
* Those intending to use this software module in products are advised
22
* that its use may infringe existing patents. ITU/ISO/IEC have no
23
* liability for use of this software module or modifications thereof.
24
*
25
* Copyright is not released for products that do not conform to
26
* to the JPEG XR standard as specified by ITU-T T.832 |
27
* ISO/IEC 29199-2.
28
*
29
******** Section to be removed when the standard is published ************
30
*
31
* Assurance that the contributed software module can be used
32
* (1) in the ITU-T "T.JXR" | ISO/IEC 29199 ("JPEG XR") standard once the
33
*     standard has been adopted; and
34
* (2) to develop the JPEG XR standard:
35
*
36
* Microsoft Corporation and any subsequent contributors to the development
37
* of this software grant ITU/ISO/IEC all rights necessary to include
38
* the originally developed software module or modifications thereof in the
39
* JPEG XR standard and to permit ITU/ISO/IEC to offer such a royalty-free,
40
* worldwide, non-exclusive copyright license to copy, distribute, and make
41
* derivative works of this software module or modifications thereof for
42
* use in products claiming conformance to the JPEG XR standard as
43
* specified by ITU-T T.832 | ISO/IEC 29199-2, and to the extent that
44
* such originally developed software module or portions of it are included
45
* in an ITU/ISO/IEC standard.  To the extent that the original contributors
46
* may own patent rights that would be required to make, use, or sell the
47
* originally developed software module or portions thereof included in the
48
* ITU/ISO/IEC standard in a conforming product, the contributors will
49
* assure ITU/ISO/IEC that they are willing to negotiate licenses under
50
* reasonable and non-discriminatory terms and conditions with
51
* applicants throughout the world and in accordance with their patent
52
* rights declarations made to ITU/ISO/IEC (if any).
53
*
54
* Microsoft, any subsequent contributors, and ITU/ISO/IEC additionally
55
* gives You a free license to this software module or modifications
56
* thereof for the sole purpose of developing the JPEG XR standard.
57
*
58
******** end of section to be removed when the standard is published *****
59
*
60
* Microsoft Corporation retains full right to modify and use the code
61
* for its own purpose, to assign or donate the code to a third party,
62
* and to inhibit third parties from using the code for products that
63
* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
64
* ISO/IEC 29199-2.
65
*
66
* This copyright notice must be included in all copies or derivative
67
* works.
68
*
69
* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
70
***********************************************************************/
71
72
#ifdef _MSC_VER
73
#pragma comment (user,"$Id: cw_emit_boxed.c,v 1.10 2012-03-18 18:29:23 thor Exp $")
74
#endif
75
76
# include  "jxr_priv.h"
77
# include  <stdlib.h>
78
# include  <string.h>
79
# include  <assert.h>
80
81
/*
82
** This file writes the JPX (ISO) box-based format for JPEG-XR.
83
**
84
*/
85
86
/*
87
** Generate a box-ID from the four-character identifier
88
*/
89
90
0
#define MAKE_ID(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | ((d) << 0))
91
92
/*
93
** prototypes
94
*/
95
static int get_bpc(jxr_container_t cp);
96
static int is_black_on_white_pxfmt(jxr_container_t cp);
97
static int is_white_on_black_pxfmt(jxr_container_t cp);
98
99
int jxrc_set_image_profile(jxr_container_t cp,int profile)
100
0
{
101
0
  cp->profile_idc = profile;
102
0
  return 0;
103
0
}
104
105
int jxrc_set_inverted_bw(jxr_container_t cp,int inverted)
106
0
{
107
0
  cp->black_is_one = inverted;
108
0
  return 0;
109
0
}
110
111
/*
112
** Write four bytes in big-endian format.
113
*/
114
static void jxrc_write_ULONG(jxr_container_t cp,uint32_t d)
115
0
{
116
0
  char buffer[4];
117
118
0
  buffer[0] = (d >> 24) & 0xff;
119
0
  buffer[1] = (d >> 16) & 0xff;
120
0
  buffer[2] = (d >>  8) & 0xff;
121
0
  buffer[3] = (d >>  0) & 0xff;
122
123
0
  if (cp->fd)
124
0
    fwrite(buffer,1,sizeof(buffer),cp->fd);
125
0
  cp->size_counter += 4;
126
0
}
127
128
static void jxrc_write_UBYTE(jxr_container_t cp,uint32_t d)
129
0
{
130
0
  char buffer[1];
131
132
0
  buffer[0] = (d >>  0) & 0xff;
133
134
0
  if (cp->fd)
135
0
    fwrite(buffer,1,sizeof(buffer),cp->fd);
136
0
  cp->size_counter += 1;
137
0
}
138
139
static void jxrc_write_UWORD(jxr_container_t cp,uint32_t d)
140
0
{
141
0
  char buffer[2];
142
143
0
  buffer[0] = (d >>  8) & 0xff;
144
0
  buffer[1] = (d >>  0) & 0xff;
145
146
0
  if (cp->fd)
147
0
    fwrite(buffer,1,sizeof(buffer),cp->fd);
148
0
  cp->size_counter += 2;
149
0
}
150
151
152
/*
153
** write a box header for the given box type and the box length.
154
*/
155
static void jxrc_write_box_header(jxr_container_t cp,uint32_t boxtype,uint32_t boxsize)
156
0
{
157
0
  cp->size_counter = 0;
158
0
  jxrc_write_ULONG(cp,boxsize);
159
0
  jxrc_write_ULONG(cp,boxtype);
160
0
}
161
162
/*
163
** write the JP2 signature box
164
*/
165
static void jxrc_write_signature_box(jxr_container_t cp)
166
0
{
167
0
  jxrc_write_box_header(cp,MAKE_ID('j','P',' ',' '),12);
168
0
  if (cp->fd) {
169
0
    fputc(0x0d,cp->fd);
170
0
    fputc(0x0a,cp->fd);
171
0
    fputc(0x87,cp->fd);
172
0
    fputc(0x0a,cp->fd);
173
0
  } else {
174
0
    cp->size_counter += 4;
175
0
  }
176
0
}
177
178
/*
179
** write the JPX file type box
180
*/
181
static void jxrc_write_file_type_box(jxr_container_t cp)
182
0
{
183
0
  jxrc_write_box_header(cp,MAKE_ID('f','t','y','p'),8+3*4);
184
  /* brand version: yes, this is jpx as it is defined in 15444-2 */
185
0
  jxrc_write_ULONG(cp,MAKE_ID('j','p','x',' '));
186
  /* version */
187
0
  jxrc_write_ULONG(cp,0);
188
  /* compatibility */
189
0
  if (cp->profile_idc <= 44) {
190
    /* sub-baseline */
191
0
    jxrc_write_ULONG(cp,MAKE_ID('j','x','r','0'));
192
0
  } else if (cp->profile_idc <= 55) {
193
    /* baseline */
194
0
    jxrc_write_ULONG(cp,MAKE_ID('j','x','r','1'));
195
0
  } else if (cp->profile_idc <= 66) {
196
    /* main */
197
0
    jxrc_write_ULONG(cp,MAKE_ID('j','x','r','2'));
198
0
  } else {
199
    /* all of it. */
200
0
    jxrc_write_ULONG(cp,MAKE_ID('j','x','r','c'));
201
0
  }
202
0
}
203
204
/*
205
** check whether the pixel format equals a specific indexed format.
206
*/
207
static int is_pxfmt(jxr_container_t cp,int which)
208
0
{
209
0
  if (!memcmp(cp->pixel_format,jxr_guids[which],16))
210
0
    return 1;
211
0
  return 0;
212
0
}
213
214
215
/*
216
** Test whether the pixel format specifies a fixed point type
217
*/
218
static int is_fixpt_pxfmt(jxr_container_t cp)
219
0
{
220
0
  if (is_pxfmt(cp,JXRC_FMT_48bppRGBFixedPoint)    ||
221
0
      is_pxfmt(cp,JXRC_FMT_96bppRGBFixedPoint)    ||
222
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBFixedPoint)    ||
223
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBFixedPoint)   ||
224
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBAFixedPoint)   ||
225
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBAFixedPoint)  ||
226
0
      is_pxfmt(cp,JXRC_FMT_16bppGrayFixedPoint)   ||
227
0
      is_pxfmt(cp,JXRC_FMT_32bppGrayFixedPoint)   ||
228
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC444FixedPoint) ||
229
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444AlphaFixedPoint)) {
230
0
    return 1;
231
0
  }
232
0
  return 0;
233
0
}
234
235
/*
236
** Test whether the pixel format specifies a floating point type
237
*/
238
static int is_float_pxfmt(jxr_container_t cp)
239
0
{
240
0
  if (is_pxfmt(cp,JXRC_FMT_48bppRGBHalf)          ||
241
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBHalf)          ||
242
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBFloat)        ||
243
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBAHalf)         ||
244
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBAFloat)       ||
245
0
      is_pxfmt(cp,JXRC_FMT_128bppPRGBAFloat)      ||
246
0
      is_pxfmt(cp,JXRC_FMT_16bppGrayHalf)         ||
247
0
      is_pxfmt(cp,JXRC_FMT_32bppGrayFloat)) {
248
0
    return 1;
249
0
  }
250
0
  return 0;
251
0
}
252
253
/*
254
** Return information whether the data in here is
255
** signed or unsigned.
256
*/
257
static int is_signed(jxr_container_t cp)
258
0
{
259
0
  if (is_float_pxfmt(cp) || is_fixpt_pxfmt(cp))
260
0
    return 1;
261
0
  return 0;
262
0
}
263
264
/*
265
** Return the pixel format for the samples in the encoding of
266
** the pixel format box.
267
*/
268
int _jxrc_get_boxed_pixel_format(jxr_container_t cp)
269
0
{
270
0
  if (is_fixpt_pxfmt(cp)) {
271
0
    if (get_bpc(cp) == 16) {
272
0
      return 0x300d; /* 13 fractional bits, fixpoint */
273
0
    } else if (get_bpc(cp) == 32) {
274
0
      return 0x3018; /* 24 fractional bits, fixpoint */
275
0
    }
276
0
    assert(!"invalid pixel format");
277
0
  } else if (is_float_pxfmt(cp)) {
278
0
    if (get_bpc(cp) == 16) {
279
0
      return 0x400a; /* 10 mantissa bits, half float */
280
0
    } else if (get_bpc(cp) == 32) {
281
0
      return 0x4017; /* 23 mantissa bits, float */
282
0
    }
283
0
    assert(!"invalid pixel format");
284
0
  } else if (is_pxfmt(cp,JXRC_FMT_32bppRGBE)) {
285
0
    return 0x1000;
286
0
  }
287
288
  /* Everything else is integer, RGBE must be handled separately */
289
0
  return 0;
290
0
}
291
292
/*
293
** Test whether the pixel format requires the scRGB color space
294
*/
295
static int is_scrgb_pxfmt(jxr_container_t cp)
296
0
{
297
0
  if (is_fixpt_pxfmt(cp))
298
0
    return 1;
299
0
  if (is_float_pxfmt(cp))
300
0
    return 1;
301
0
  if (is_pxfmt(cp,JXRC_FMT_48bppRGB)           ||
302
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBA)          ||
303
0
      is_pxfmt(cp,JXRC_FMT_64bppPRGBA)         ||
304
0
      is_pxfmt(cp,JXRC_FMT_32bppRGBE))
305
0
    return 1;
306
0
  return 0;
307
0
}
308
309
/*
310
** Test whether this pixel format defines the greyscale color space.
311
*/
312
static int is_grey_pxfmt(jxr_container_t cp)
313
0
{
314
0
  if (is_pxfmt(cp,JXRC_FMT_8bppGray)            ||
315
0
      is_pxfmt(cp,JXRC_FMT_16bppGray)           ||
316
0
      is_pxfmt(cp,JXRC_FMT_16bppGrayFixedPoint) ||
317
0
      is_pxfmt(cp,JXRC_FMT_16bppGrayHalf)       ||
318
0
      is_pxfmt(cp,JXRC_FMT_32bppGrayFixedPoint) ||
319
0
      is_pxfmt(cp,JXRC_FMT_32bppGrayFloat))
320
0
    return 1;
321
0
  return 0;
322
0
}
323
324
/*
325
** Test whether the pixel format indicates an RGB color space
326
*/
327
static int is_rgb_pxfmt(jxr_container_t cp)
328
0
{
329
0
  if (is_pxfmt(cp,JXRC_FMT_24bppRGB)    ||
330
0
      is_pxfmt(cp,JXRC_FMT_24bppBGR)    ||
331
0
      is_pxfmt(cp,JXRC_FMT_32bppBGR)    ||
332
0
      is_pxfmt(cp,JXRC_FMT_32bppBGRA)   ||
333
0
      is_pxfmt(cp,JXRC_FMT_32bppPBGRA)  ||
334
0
      is_pxfmt(cp,JXRC_FMT_16bppBGR555) ||
335
0
      is_pxfmt(cp,JXRC_FMT_16bppBGR565) ||
336
0
      is_pxfmt(cp,JXRC_FMT_32bppBGR101010))
337
0
    return 1;
338
0
  return 0;
339
0
}
340
341
/*
342
** Test whether this pixel format is a generic profile that requires
343
** an additional profile to define it.
344
*/
345
static int is_generic_pxfmt(jxr_container_t cp)
346
0
{
347
0
  if (is_pxfmt(cp,JXRC_FMT_24bpp3Channels) ||
348
0
      is_pxfmt(cp,JXRC_FMT_32bpp4Channels) ||
349
0
      is_pxfmt(cp,JXRC_FMT_40bpp5Channels) ||
350
0
      is_pxfmt(cp,JXRC_FMT_48bpp6Channels) ||
351
0
      is_pxfmt(cp,JXRC_FMT_56bpp7Channels) ||
352
0
      is_pxfmt(cp,JXRC_FMT_64bpp8Channels) ||
353
0
      is_pxfmt(cp,JXRC_FMT_32bpp3ChannelsAlpha) ||
354
0
      is_pxfmt(cp,JXRC_FMT_40bpp4ChannelsAlpha) ||
355
0
      is_pxfmt(cp,JXRC_FMT_48bpp5ChannelsAlpha) ||
356
0
      is_pxfmt(cp,JXRC_FMT_56bpp6ChannelsAlpha) ||
357
0
      is_pxfmt(cp,JXRC_FMT_64bpp7ChannelsAlpha) ||
358
0
      is_pxfmt(cp,JXRC_FMT_72bpp8ChannelsAlpha) ||
359
0
      is_pxfmt(cp,JXRC_FMT_48bpp3Channels) ||
360
0
      is_pxfmt(cp,JXRC_FMT_64bpp4Channels) ||
361
0
      is_pxfmt(cp,JXRC_FMT_80bpp5Channels) ||
362
0
      is_pxfmt(cp,JXRC_FMT_96bpp6Channels) ||
363
0
      is_pxfmt(cp,JXRC_FMT_112bpp7Channels) ||
364
0
      is_pxfmt(cp,JXRC_FMT_128bpp8Channels) ||
365
0
      is_pxfmt(cp,JXRC_FMT_64bpp3ChannelsAlpha) ||
366
0
      is_pxfmt(cp,JXRC_FMT_80bpp4ChannelsAlpha) ||
367
0
      is_pxfmt(cp,JXRC_FMT_96bpp5ChannelsAlpha) ||
368
0
      is_pxfmt(cp,JXRC_FMT_112bpp6ChannelsAlpha) ||
369
0
      is_pxfmt(cp,JXRC_FMT_128bpp7ChannelsAlpha) ||
370
0
      is_pxfmt(cp,JXRC_FMT_144bpp8ChannelsAlpha))
371
0
    return 1;
372
0
  return 0;
373
0
}
374
375
/*
376
** Test whether the pixel format specifies unmultiplied opacity
377
*/
378
int _jxrc_is_alpha_pxfmt(jxr_container_t cp)
379
0
{
380
0
  if (is_pxfmt(cp,JXRC_FMT_32bppBGRA)            ||
381
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBA)            ||
382
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBAFixedPoint)  ||
383
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBAHalf)        ||
384
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBAFixedPoint) ||
385
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBAFloat)      ||
386
0
      is_pxfmt(cp,JXRC_FMT_40bppCMYKAlpha)       ||
387
0
      is_pxfmt(cp,JXRC_FMT_80bppCMYKAlpha)       ||
388
0
      is_pxfmt(cp,JXRC_FMT_32bpp3ChannelsAlpha)  ||
389
0
      is_pxfmt(cp,JXRC_FMT_40bpp4ChannelsAlpha)  ||
390
0
      is_pxfmt(cp,JXRC_FMT_48bpp5ChannelsAlpha)  ||
391
0
      is_pxfmt(cp,JXRC_FMT_56bpp6ChannelsAlpha)  ||
392
0
      is_pxfmt(cp,JXRC_FMT_64bpp7ChannelsAlpha)  ||
393
0
      is_pxfmt(cp,JXRC_FMT_72bpp8ChannelsAlpha)  ||
394
0
      is_pxfmt(cp,JXRC_FMT_64bpp3ChannelsAlpha)  ||
395
0
      is_pxfmt(cp,JXRC_FMT_80bpp4ChannelsAlpha)  ||
396
0
      is_pxfmt(cp,JXRC_FMT_96bpp5ChannelsAlpha)  ||
397
0
      is_pxfmt(cp,JXRC_FMT_112bpp6ChannelsAlpha) ||
398
0
      is_pxfmt(cp,JXRC_FMT_128bpp7ChannelsAlpha) ||
399
0
      is_pxfmt(cp,JXRC_FMT_144bpp8ChannelsAlpha) ||
400
0
      is_pxfmt(cp,JXRC_FMT_40bppCMYKDIRECTAlpha) ||
401
0
      is_pxfmt(cp,JXRC_FMT_80bppCMYKDIRECTAlpha) ||
402
0
      is_pxfmt(cp,JXRC_FMT_20bppYCC420Alpha)     ||
403
0
      is_pxfmt(cp,JXRC_FMT_24bppYCC422Alpha)     ||
404
0
      is_pxfmt(cp,JXRC_FMT_30bppYCC422Alpha)     ||
405
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC422Alpha)     ||
406
0
      is_pxfmt(cp,JXRC_FMT_32bppYCC444Alpha)     ||
407
0
      is_pxfmt(cp,JXRC_FMT_40bppYCC444Alpha)     ||
408
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444Alpha)     ||
409
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444AlphaFixedPoint)) {
410
0
    return 1;
411
0
  }
412
0
  return 0;
413
0
}
414
415
int _jxrc_is_pre_alpha_pxfmt(jxr_container_t cp)
416
0
{
417
0
  if (is_pxfmt(cp,JXRC_FMT_32bppPBGRA) ||
418
0
      is_pxfmt(cp,JXRC_FMT_64bppPRGBA) ||
419
0
      is_pxfmt(cp,JXRC_FMT_128bppPRGBAFloat)) {
420
0
    return 1;
421
0
  }
422
0
  return 0;
423
0
}
424
425
static int is_black_on_white_pxfmt(jxr_container_t cp)
426
0
{
427
0
  if (is_pxfmt(cp,JXRC_FMT_BlackWhite)) {
428
0
    if (cp->black_is_one)
429
0
      return 1;
430
0
  }
431
0
  return 0;
432
0
}
433
434
static int is_white_on_black_pxfmt(jxr_container_t cp)
435
0
{
436
0
  if (is_pxfmt(cp,JXRC_FMT_BlackWhite)) {
437
0
    if (!cp->black_is_one)
438
0
      return 1;
439
0
  }
440
0
  return 0;
441
0
}
442
443
/*
444
** Test whether a pixel format is YCbCr. Unfortunately,
445
** this software does not yet write the PTM_COLOR_INFO, thus
446
** the nature of YCbCr is not defined. It is here assumed
447
** that YCbCr is always full range.
448
*/
449
static int is_ycbcr_pxfmt(jxr_container_t cp)
450
0
{
451
0
  if (is_pxfmt(cp,JXRC_FMT_12bppYCC420)           ||
452
0
      is_pxfmt(cp,JXRC_FMT_16bppYCC422)           ||
453
0
      is_pxfmt(cp,JXRC_FMT_20bppYCC422)           ||
454
0
      is_pxfmt(cp,JXRC_FMT_32bppYCC422)           ||
455
0
      is_pxfmt(cp,JXRC_FMT_24bppYCC444)           ||
456
0
      is_pxfmt(cp,JXRC_FMT_30bppYCC444)           ||
457
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC444)           ||
458
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC444FixedPoint) ||
459
0
      is_pxfmt(cp,JXRC_FMT_20bppYCC420Alpha)      ||
460
0
      is_pxfmt(cp,JXRC_FMT_24bppYCC422Alpha)      ||
461
0
      is_pxfmt(cp,JXRC_FMT_30bppYCC422Alpha)      ||
462
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC422Alpha)      ||
463
0
      is_pxfmt(cp,JXRC_FMT_32bppYCC444Alpha)      ||
464
0
      is_pxfmt(cp,JXRC_FMT_40bppYCC444Alpha)      ||
465
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444Alpha)      ||
466
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444AlphaFixedPoint))
467
0
    return 1;
468
0
  return 0;
469
0
}
470
471
static int is_cmyk_pxfmt(jxr_container_t cp)
472
0
{
473
0
  if (is_pxfmt(cp,JXRC_FMT_32bppCMYK)            ||
474
0
      is_pxfmt(cp,JXRC_FMT_40bppCMYKAlpha)       ||
475
0
      is_pxfmt(cp,JXRC_FMT_64bppCMYK)            ||
476
0
      is_pxfmt(cp,JXRC_FMT_80bppCMYKAlpha)       ||
477
0
      is_pxfmt(cp,JXRC_FMT_32bppCMYKDIRECT)      ||
478
0
      is_pxfmt(cp,JXRC_FMT_64bppCMYKDIRECT)      ||
479
0
      is_pxfmt(cp,JXRC_FMT_40bppCMYKDIRECTAlpha) ||
480
0
      is_pxfmt(cp,JXRC_FMT_80bppCMYKDIRECTAlpha)) {
481
0
    return 1;
482
0
  }
483
0
  return 0;
484
0
}
485
486
/*
487
** Return the number of channels in the container including any
488
** alpha channel.
489
*/
490
int _jxrc_PixelFormatToChannels(jxr_container_t cp)
491
0
{
492
0
  if (is_pxfmt(cp,JXRC_FMT_24bppRGB)            ||
493
0
      is_pxfmt(cp,JXRC_FMT_24bppBGR)            ||
494
0
      is_pxfmt(cp,JXRC_FMT_32bppBGR)            ||
495
0
      is_pxfmt(cp,JXRC_FMT_48bppRGB)            ||
496
0
      is_pxfmt(cp,JXRC_FMT_48bppRGBFixedPoint)  ||
497
0
      is_pxfmt(cp,JXRC_FMT_48bppRGBHalf)        ||
498
0
      is_pxfmt(cp,JXRC_FMT_96bppRGBFixedPoint)  ||
499
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBFixedPoint)  ||
500
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBHalf)        ||
501
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBFixedPoint) ||
502
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBFloat)) {
503
0
    return 3;
504
0
  }
505
506
0
  if (is_pxfmt(cp,JXRC_FMT_32bppBGRA)            ||
507
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBA)            ||
508
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBAFixedPoint)  ||
509
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBAHalf)        ||
510
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBAFixedPoint) ||
511
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBAFloat)      ||
512
0
      is_pxfmt(cp,JXRC_FMT_32bppPBGRA)           ||
513
0
      is_pxfmt(cp,JXRC_FMT_64bppPRGBA)           ||
514
0
      is_pxfmt(cp,JXRC_FMT_128bppPRGBAFloat)) {
515
0
    return 4;
516
0
  }
517
518
0
  if (is_pxfmt(cp,JXRC_FMT_32bppCMYK)       ||
519
0
      is_pxfmt(cp,JXRC_FMT_64bppCMYK)       ||
520
0
      is_pxfmt(cp,JXRC_FMT_32bppCMYKDIRECT) ||
521
0
      is_pxfmt(cp,JXRC_FMT_64bppCMYKDIRECT)) {
522
0
    return 4;
523
0
  }
524
525
0
  if (is_pxfmt(cp,JXRC_FMT_40bppCMYKAlpha)       ||
526
0
      is_pxfmt(cp,JXRC_FMT_80bppCMYKAlpha)       ||
527
0
      is_pxfmt(cp,JXRC_FMT_40bppCMYKDIRECTAlpha) ||
528
0
      is_pxfmt(cp,JXRC_FMT_80bppCMYKDIRECTAlpha)) {
529
0
    return 5;
530
0
  }
531
532
0
  if (is_pxfmt(cp,JXRC_FMT_24bpp3Channels) ||
533
0
      is_pxfmt(cp,JXRC_FMT_48bpp3Channels))
534
0
    return 3;
535
536
0
  if (is_pxfmt(cp,JXRC_FMT_32bpp4Channels) ||
537
0
      is_pxfmt(cp,JXRC_FMT_64bpp4Channels))
538
0
    return 4;
539
540
0
  if (is_pxfmt(cp,JXRC_FMT_40bpp5Channels) ||
541
0
      is_pxfmt(cp,JXRC_FMT_80bpp5Channels))
542
0
    return 5;
543
544
0
  if (is_pxfmt(cp,JXRC_FMT_48bpp6Channels) ||
545
0
      is_pxfmt(cp,JXRC_FMT_96bpp6Channels))
546
0
    return 6;
547
548
0
  if (is_pxfmt(cp,JXRC_FMT_56bpp7Channels) ||
549
0
      is_pxfmt(cp,JXRC_FMT_112bpp7Channels))
550
0
    return 7;
551
552
0
  if (is_pxfmt(cp,JXRC_FMT_64bpp8Channels) ||
553
0
      is_pxfmt(cp,JXRC_FMT_128bpp8Channels))
554
0
    return 8;
555
556
0
  if (is_pxfmt(cp,JXRC_FMT_32bpp3ChannelsAlpha) ||
557
0
      is_pxfmt(cp,JXRC_FMT_64bpp3ChannelsAlpha)) {
558
0
    return 4;
559
0
  }
560
561
0
  if (is_pxfmt(cp,JXRC_FMT_40bpp4ChannelsAlpha) ||
562
0
      is_pxfmt(cp,JXRC_FMT_80bpp4ChannelsAlpha)) {
563
0
    return 5;
564
0
  }
565
566
0
  if (is_pxfmt(cp,JXRC_FMT_48bpp5ChannelsAlpha) ||
567
0
      is_pxfmt(cp,JXRC_FMT_96bpp5ChannelsAlpha)) {
568
0
    return 6;
569
0
  }
570
571
0
  if (is_pxfmt(cp,JXRC_FMT_56bpp6ChannelsAlpha) ||
572
0
      is_pxfmt(cp,JXRC_FMT_112bpp6ChannelsAlpha)) {
573
0
    return 7;
574
0
  }
575
576
0
  if (is_pxfmt(cp,JXRC_FMT_64bpp7ChannelsAlpha) ||
577
0
      is_pxfmt(cp,JXRC_FMT_128bpp7ChannelsAlpha)) {
578
0
    return 8;
579
0
  }
580
581
0
  if (is_pxfmt(cp,JXRC_FMT_72bpp8ChannelsAlpha) ||
582
0
      is_pxfmt(cp,JXRC_FMT_144bpp8ChannelsAlpha)) {
583
0
    return 9;
584
0
  }
585
586
0
  if (is_pxfmt(cp,JXRC_FMT_8bppGray)            ||
587
0
      is_pxfmt(cp,JXRC_FMT_16bppGray)           ||
588
0
      is_pxfmt(cp,JXRC_FMT_16bppGrayFixedPoint) ||
589
0
      is_pxfmt(cp,JXRC_FMT_16bppGrayHalf)       ||
590
0
      is_pxfmt(cp,JXRC_FMT_32bppGrayFixedPoint) ||
591
0
      is_pxfmt(cp,JXRC_FMT_32bppGrayFloat)      ||
592
0
      is_pxfmt(cp,JXRC_FMT_BlackWhite))
593
0
    return 1;
594
595
0
  if (is_pxfmt(cp,JXRC_FMT_16bppBGR555) ||
596
0
      is_pxfmt(cp,JXRC_FMT_16bppBGR565) ||
597
0
      is_pxfmt(cp,JXRC_FMT_32bppBGR101010))
598
0
    return 3;
599
600
0
  if (is_pxfmt(cp,JXRC_FMT_32bppRGBE))
601
0
    return 4; /* Number of components in the codestream. Though only three colors */
602
603
0
  if (is_pxfmt(cp,JXRC_FMT_12bppYCC420) ||
604
0
      is_pxfmt(cp,JXRC_FMT_16bppYCC422) ||
605
0
      is_pxfmt(cp,JXRC_FMT_20bppYCC422) ||
606
0
      is_pxfmt(cp,JXRC_FMT_32bppYCC422) ||
607
0
      is_pxfmt(cp,JXRC_FMT_24bppYCC444) ||
608
0
      is_pxfmt(cp,JXRC_FMT_30bppYCC444) ||
609
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC444) ||
610
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC444FixedPoint))
611
0
    return 3;
612
613
0
  if (is_pxfmt(cp,JXRC_FMT_20bppYCC420Alpha) ||
614
0
      is_pxfmt(cp,JXRC_FMT_24bppYCC422Alpha) ||
615
0
      is_pxfmt(cp,JXRC_FMT_30bppYCC422Alpha) ||
616
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC422Alpha) ||
617
0
      is_pxfmt(cp,JXRC_FMT_32bppYCC444Alpha) ||
618
0
      is_pxfmt(cp,JXRC_FMT_40bppYCC444Alpha) ||
619
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444Alpha) ||
620
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444AlphaFixedPoint)) {
621
0
    return 4;
622
0
  }
623
624
0
  return 0;
625
0
}
626
627
/*
628
** Number of components including the alpha channel
629
** if it is interleaved.
630
*/
631
static int get_num_components(jxr_container_t cp)
632
0
{
633
0
  int channels = _jxrc_PixelFormatToChannels(cp);
634
635
0
  if (_jxrc_is_alpha_pxfmt(cp) || _jxrc_is_pre_alpha_pxfmt(cp)) {
636
0
    if (cp->separate_alpha_image_plane) {
637
      /* alpha channel goes into a separate image */
638
0
      channels--;
639
0
    }
640
0
  }
641
642
0
  return channels;
643
0
}
644
645
/*
646
** get the number of bits per component, return 6 for
647
** the 565 mode.
648
*/
649
int _jxrc_PixelFormatToBpp(jxr_container_t cp)
650
0
{
651
0
  int bpc = get_bpc(cp);
652
653
0
  if (bpc == 256)
654
0
    return 6;
655
656
0
  return bpc;
657
0
}
658
659
/*
660
** get the number of bits per component, or return 256
661
** for the strange 565 format.
662
*/
663
static int get_bpc(jxr_container_t cp)
664
0
{
665
0
  if (is_pxfmt(cp,JXRC_FMT_24bppRGB)             ||
666
0
      is_pxfmt(cp,JXRC_FMT_24bppBGR)             ||
667
0
      is_pxfmt(cp,JXRC_FMT_32bppBGR)             ||
668
0
      is_pxfmt(cp,JXRC_FMT_32bppBGRA)            ||
669
0
      is_pxfmt(cp,JXRC_FMT_32bppPBGRA)           ||
670
0
      is_pxfmt(cp,JXRC_FMT_32bppCMYK)            ||
671
0
      is_pxfmt(cp,JXRC_FMT_40bppCMYKAlpha)       ||
672
0
      is_pxfmt(cp,JXRC_FMT_24bpp3Channels)       ||
673
0
      is_pxfmt(cp,JXRC_FMT_32bpp4Channels)       ||
674
0
      is_pxfmt(cp,JXRC_FMT_40bpp5Channels)       ||
675
0
      is_pxfmt(cp,JXRC_FMT_48bpp6Channels)       ||
676
0
      is_pxfmt(cp,JXRC_FMT_56bpp7Channels)       ||
677
0
      is_pxfmt(cp,JXRC_FMT_64bpp8Channels)       ||
678
0
      is_pxfmt(cp,JXRC_FMT_32bpp3ChannelsAlpha)  ||
679
0
      is_pxfmt(cp,JXRC_FMT_40bpp4ChannelsAlpha)  ||
680
0
      is_pxfmt(cp,JXRC_FMT_48bpp5ChannelsAlpha)  ||
681
0
      is_pxfmt(cp,JXRC_FMT_56bpp6ChannelsAlpha)  ||
682
0
      is_pxfmt(cp,JXRC_FMT_64bpp7ChannelsAlpha)  ||
683
0
      is_pxfmt(cp,JXRC_FMT_72bpp8ChannelsAlpha)  ||
684
0
      is_pxfmt(cp,JXRC_FMT_8bppGray)             ||
685
0
      is_pxfmt(cp,JXRC_FMT_32bppCMYKDIRECT)      ||
686
0
      is_pxfmt(cp,JXRC_FMT_40bppCMYKDIRECTAlpha) ||
687
0
      is_pxfmt(cp,JXRC_FMT_12bppYCC420)          ||
688
0
      is_pxfmt(cp,JXRC_FMT_16bppYCC422)          ||
689
0
      is_pxfmt(cp,JXRC_FMT_24bppYCC444)          ||
690
0
      is_pxfmt(cp,JXRC_FMT_20bppYCC420Alpha)     ||
691
0
      is_pxfmt(cp,JXRC_FMT_24bppYCC422Alpha)     ||
692
0
      is_pxfmt(cp,JXRC_FMT_32bppYCC444Alpha))
693
0
    return 8;
694
695
0
  if (is_pxfmt(cp,JXRC_FMT_48bppRGB)             ||
696
0
      is_pxfmt(cp,JXRC_FMT_48bppRGBFixedPoint)   ||
697
0
      is_pxfmt(cp,JXRC_FMT_48bppRGBHalf)         ||
698
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBFixedPoint)   ||
699
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBAFixedPoint)  ||
700
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBHalf)         ||
701
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBAHalf)        ||
702
0
      is_pxfmt(cp,JXRC_FMT_64bppRGBA)            ||
703
0
      is_pxfmt(cp,JXRC_FMT_64bppPRGBA)           ||
704
0
      is_pxfmt(cp,JXRC_FMT_64bppCMYK)            ||
705
0
      is_pxfmt(cp,JXRC_FMT_80bppCMYKAlpha)       ||
706
0
      is_pxfmt(cp,JXRC_FMT_48bpp3Channels)       ||
707
0
      is_pxfmt(cp,JXRC_FMT_64bpp4Channels)       ||
708
0
      is_pxfmt(cp,JXRC_FMT_80bpp5Channels)       ||
709
0
      is_pxfmt(cp,JXRC_FMT_96bpp6Channels)       ||
710
0
      is_pxfmt(cp,JXRC_FMT_112bpp7Channels)      ||
711
0
      is_pxfmt(cp,JXRC_FMT_128bpp8Channels)      ||
712
0
      is_pxfmt(cp,JXRC_FMT_64bpp3ChannelsAlpha)  ||
713
0
      is_pxfmt(cp,JXRC_FMT_80bpp4ChannelsAlpha)  ||
714
0
      is_pxfmt(cp,JXRC_FMT_96bpp5ChannelsAlpha)  ||
715
0
      is_pxfmt(cp,JXRC_FMT_112bpp6ChannelsAlpha) ||
716
0
      is_pxfmt(cp,JXRC_FMT_128bpp7ChannelsAlpha) ||
717
0
      is_pxfmt(cp,JXRC_FMT_144bpp8ChannelsAlpha) ||
718
0
      is_pxfmt(cp,JXRC_FMT_16bppGray)            ||
719
0
      is_pxfmt(cp,JXRC_FMT_16bppGrayFixedPoint)  ||
720
0
      is_pxfmt(cp,JXRC_FMT_16bppGrayHalf)        ||
721
0
      is_pxfmt(cp,JXRC_FMT_64bppCMYKDIRECT)      ||
722
0
      is_pxfmt(cp,JXRC_FMT_80bppCMYKDIRECTAlpha) ||
723
0
      is_pxfmt(cp,JXRC_FMT_32bppYCC422)          ||
724
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC444)          ||
725
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC444FixedPoint)||
726
0
      is_pxfmt(cp,JXRC_FMT_48bppYCC422Alpha)     ||
727
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444Alpha)     ||
728
0
      is_pxfmt(cp,JXRC_FMT_64bppYCC444AlphaFixedPoint))
729
0
    return 16;
730
731
0
  if (is_pxfmt(cp,JXRC_FMT_96bppRGBFixedPoint)   ||
732
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBFixedPoint)  ||
733
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBAFixedPoint) ||
734
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBFloat)       ||
735
0
      is_pxfmt(cp,JXRC_FMT_128bppRGBAFloat)      ||
736
0
      is_pxfmt(cp,JXRC_FMT_128bppPRGBAFloat)     ||
737
0
      is_pxfmt(cp,JXRC_FMT_32bppGrayFixedPoint)  ||
738
0
      is_pxfmt(cp,JXRC_FMT_32bppGrayFloat))
739
0
    return 32;
740
741
0
  if (is_pxfmt(cp,JXRC_FMT_BlackWhite))
742
0
    return 1;
743
744
0
  if (is_pxfmt(cp,JXRC_FMT_16bppBGR555))
745
0
    return 5; /* bit depths varies. */
746
747
0
  if (is_pxfmt(cp,JXRC_FMT_16bppBGR565))
748
0
    return 256; /* bit depths varies */
749
750
0
  if (is_pxfmt(cp,JXRC_FMT_32bppBGR101010) ||
751
0
      is_pxfmt(cp,JXRC_FMT_20bppYCC422)    ||
752
0
      is_pxfmt(cp,JXRC_FMT_30bppYCC444)    ||
753
0
      is_pxfmt(cp,JXRC_FMT_30bppYCC422Alpha) ||
754
0
      is_pxfmt(cp,JXRC_FMT_40bppYCC444Alpha))
755
0
    return 10;
756
757
0
  if (is_pxfmt(cp,JXRC_FMT_32bppRGBE))
758
0
    return 8;
759
760
0
  assert(!"unknown pixel format");
761
0
  return 0;
762
0
}
763
764
/*
765
** write the reader requirements box
766
*/
767
static void jxrc_write_rreq_box(jxr_container_t cp)
768
0
{
769
0
  int features[16] = {0};
770
0
  int *f = features;
771
0
  int bits,mask;
772
773
0
  if (_jxrc_is_alpha_pxfmt(cp)) {
774
0
    *f++ = 9;  /* unmultiplied alpha */
775
0
    if (cp->separate_alpha_image_plane)
776
0
      *f++ = 2;
777
0
  }
778
0
  if (_jxrc_is_pre_alpha_pxfmt(cp)) {
779
0
    *f++ = 10; /* premultiplied alpha */
780
0
    if (cp->separate_alpha_image_plane)
781
0
      *f++ = 2;
782
0
  }
783
784
0
  *f++ = 75; /* is 29199-2 */
785
0
  if (cp->profile_idc <= 44) {
786
0
    *f++ = 76; /* subbaseline profile */
787
0
  } else if (cp->profile_idc <= 55) {
788
0
    *f++ = 77; /* baseline profile */
789
0
  } else if (cp->profile_idc <= 66) {
790
0
    *f++ = 78; /* main profile */
791
0
  } else {
792
0
    *f++ = 79; /* advanced profile */
793
0
  }
794
795
0
  if (is_fixpt_pxfmt(cp)) {
796
0
    *f++ = 80; /* pixel format fixpoint is used */
797
0
  }
798
0
  if (is_float_pxfmt(cp)) {
799
0
    *f++ = 81; /* floating point is used */
800
0
  }
801
0
  if (is_pxfmt(cp,JXRC_FMT_32bppRGBE)) {
802
0
    *f++ = 82; /* exponent or mantissa is used */
803
0
  }
804
0
  if (is_scrgb_pxfmt(cp)) {
805
0
    *f++ = 83; /* scRGB pixel format */
806
0
  }
807
808
0
  if (is_black_on_white_pxfmt(cp)) { /* 1 is black */
809
0
    *f++ = 47; /* bi-level 1 */
810
0
  }
811
0
  if (is_white_on_black_pxfmt(cp)) { /* 0 is black */
812
0
    *f++ = 48; /* bi-level 2 */
813
0
  }
814
0
  if (is_ycbcr_pxfmt(cp)) {
815
0
    *f++ = 50;  /* ycbcr(2), full range. */
816
0
  }
817
0
  if (is_cmyk_pxfmt(cp)) {
818
0
    *f++ = 55; /* cmyk */
819
0
  }
820
0
  *f++ = 0;
821
822
0
  bits = f - features - 1;
823
0
  mask = (1 << bits) - 1;
824
825
0
  jxrc_write_box_header(cp,MAKE_ID('r','r','e','q'),8 + 1 + 1 + 1 + 2 + 3 * bits + 2);
826
827
  /* mask length = 1 */
828
0
  jxrc_write_UBYTE(cp,1);
829
  /* FUAM */
830
0
  jxrc_write_UBYTE(cp,mask);
831
  /* If the topmost bit encodes alpha, do not set in the decode
832
  ** correctly. Alpha is not strictly needed .
833
  */
834
0
  if (_jxrc_is_alpha_pxfmt(cp) || _jxrc_is_pre_alpha_pxfmt(cp)) {
835
0
    jxrc_write_UBYTE(cp,mask & ~1);
836
0
  } else {
837
0
    jxrc_write_UBYTE(cp,mask);
838
0
  }
839
  /*
840
  ** Number of standard flags
841
  */
842
0
  jxrc_write_UWORD(cp,bits);
843
0
  for(f = features,mask = 1 << (f - features);*f;f++,mask <<= 1) {
844
0
    jxrc_write_UWORD(cp,*f);
845
0
    jxrc_write_UBYTE(cp,mask);
846
0
  }
847
  /* Number of vendor flags
848
   */
849
0
  jxrc_write_UWORD(cp,0);
850
0
}
851
852
/*
853
** write the image header box
854
*/
855
static void jxrc_write_ihdr(jxr_container_t cp)
856
0
{
857
0
  jxrc_write_box_header(cp,MAKE_ID('i','h','d','r'),8 + 4 + 4 + 2 + 1 + 1 + 1 + 1);
858
859
  /* image dimensions */
860
0
  jxrc_write_ULONG(cp,cp->hei);
861
0
  jxrc_write_ULONG(cp,cp->wid);
862
863
0
  jxrc_write_UWORD(cp,get_num_components(cp));
864
0
  jxrc_write_UBYTE(cp,(get_bpc(cp)-1) | (is_signed(cp)?(128):(0)));
865
0
  jxrc_write_UBYTE(cp,11); /* compression type is XR */
866
0
  jxrc_write_UBYTE(cp,1);  /* color space is guessed */
867
0
  jxrc_write_UBYTE(cp,0);  /* no rights information present */
868
0
}
869
870
static void jxrc_write_bpc(jxr_container_t cp)
871
0
{
872
0
  if (is_pxfmt(cp,JXRC_FMT_16bppBGR565)) {
873
    /* Only in this case the BPC box is required */
874
0
    jxrc_write_box_header(cp,MAKE_ID('b','p','c','c'),8 + 3);
875
0
    jxrc_write_UBYTE(cp,5-1);
876
0
    jxrc_write_UBYTE(cp,6-1);
877
0
    jxrc_write_UBYTE(cp,5-1);
878
0
  } else {
879
0
    cp->size_counter = 0;
880
0
  }
881
0
}
882
883
/*
884
** Return the enumerated color space index.
885
*/
886
int _jxrc_enumerated_colorspace(jxr_container_t cp)
887
0
{
888
0
  if (is_scrgb_pxfmt(cp)) {
889
0
    return 25; /* scRGB color space */
890
0
  } else if (is_black_on_white_pxfmt(cp)) {
891
0
    return 0; /* bi-level 1 */
892
0
  } else if (is_white_on_black_pxfmt(cp)) {
893
0
    return 15;
894
0
  } else if (is_ycbcr_pxfmt(cp)) {
895
0
    return 3; /* YCbCr */
896
0
  } else if (is_cmyk_pxfmt(cp)) {
897
0
    return 12; /* CMYK */
898
0
  } else if (is_grey_pxfmt(cp)) {
899
0
    return 17; /* grey-scale */
900
0
  } else if (is_rgb_pxfmt(cp)) {
901
0
    return 16; /* RGB */
902
0
  }
903
0
  return -1;
904
0
}
905
906
static void jxrc_write_colorspec(jxr_container_t cp)
907
0
{
908
0
  if (!is_generic_pxfmt(cp)) {
909
0
    jxrc_write_box_header(cp,MAKE_ID('c','o','l','r'),8 + 3 + ((is_generic_pxfmt(cp))?(0):(4)));
910
0
    jxrc_write_UBYTE(cp,1); /* enumerated method */
911
0
    jxrc_write_UBYTE(cp,1); /* precedence */
912
0
    jxrc_write_UBYTE(cp,3); /* approx. The best we know */
913
914
0
    cp->color = _jxrc_enumerated_colorspace(cp);
915
916
0
    jxrc_write_ULONG(cp,cp->color);
917
0
  } else {
918
0
    cp->size_counter = 0;
919
0
  }
920
0
}
921
922
/*
923
** write the jp2 channel definition box.
924
*/
925
static void jxrc_write_cdef(jxr_container_t cp)
926
0
{
927
0
  int i;
928
0
  int c     = _jxrc_PixelFormatToChannels(cp);
929
0
  int alpha = _jxrc_is_alpha_pxfmt(cp) || _jxrc_is_pre_alpha_pxfmt(cp);
930
0
  int rgbe  = 0;
931
932
0
  jxrc_write_box_header(cp,MAKE_ID('c','d','e','f'),8 + 2 + 2 * 3 * c);
933
0
  jxrc_write_UWORD(cp,c); /* number of channel descriptions */
934
  /* first, write all but the alpha channel descriptions */
935
0
  for(i = 0;i < c-alpha;i++) {
936
0
    if (i == 3 && rgbe) {
937
0
      jxrc_write_UWORD(cp,i); /* channel index */
938
0
      jxrc_write_UWORD(cp,0); /* channel type: color */
939
0
      jxrc_write_UWORD(cp,0); /* exponent channel: all of the image */
940
0
    } else {
941
0
      jxrc_write_UWORD(cp,i); /* channel index */
942
0
      jxrc_write_UWORD(cp,0); /* channel type: color */
943
0
      jxrc_write_UWORD(cp,i+1); /* channel association: just the canonical */
944
0
    }
945
0
  }
946
0
  if (alpha) {
947
    /* Finally, include the alpha channel */
948
0
    jxrc_write_UWORD(cp,c-1); /* channel index: the last one */
949
0
    if (_jxrc_is_pre_alpha_pxfmt(cp))
950
0
      jxrc_write_UWORD(cp,2); /* premultiplied alpha */
951
0
    else
952
0
      jxrc_write_UWORD(cp,1); /* alpha */
953
0
    jxrc_write_UWORD(cp,0); /* association: all of the image */
954
0
  }
955
0
}
956
957
/*
958
** Write the pixel format box
959
*/
960
static void jxrc_write_pxfm(jxr_container_t cp)
961
0
{
962
0
  int rgbe  = 0;
963
0
  int c     = _jxrc_PixelFormatToChannels(cp);
964
965
0
  jxrc_write_box_header(cp,MAKE_ID('p','x','f','m'),8 + 2 + (2 + 2) * c);
966
0
  jxrc_write_UWORD(cp,c);
967
0
  if (rgbe) {
968
0
    jxrc_write_UWORD(cp,0);
969
0
    jxrc_write_UWORD(cp,0x1000); /* mantissa */
970
0
    jxrc_write_UWORD(cp,1);
971
0
    jxrc_write_UWORD(cp,0x1000); /* mantissa */
972
0
    jxrc_write_UWORD(cp,2);
973
0
    jxrc_write_UWORD(cp,0x1000); /* mantissa */
974
0
    jxrc_write_UWORD(cp,3);
975
0
    jxrc_write_UWORD(cp,0x2000); /* exponent */
976
0
  } else {
977
0
    int i,pxfm = _jxrc_get_boxed_pixel_format(cp);
978
0
    for(i = 0;i < c;i++) {
979
0
      jxrc_write_UWORD(cp,i);
980
0
      jxrc_write_UWORD(cp,pxfm);
981
0
    }
982
0
  }
983
0
}
984
985
/*
986
** Write the jp2-header box
987
*/
988
static void jxrc_write_jp2h(jxr_container_t cp)
989
0
{
990
0
  FILE *fp = cp->fd;
991
0
  int size = 8; /* the box header. */
992
993
0
  cp->fd = NULL;
994
995
0
  jxrc_write_colorspec(cp);
996
0
  size  += cp->size_counter;
997
0
  jxrc_write_cdef(cp);
998
0
  size  += cp->size_counter;
999
0
  jxrc_write_pxfm(cp);
1000
0
  size  += cp->size_counter;
1001
1002
1003
  /*
1004
  ** Now write the boxes
1005
  */
1006
0
  cp->fd = fp;
1007
0
  jxrc_write_box_header(cp,MAKE_ID('j','p','2','h'),size);
1008
0
  jxrc_write_colorspec(cp);
1009
0
  jxrc_write_cdef(cp);
1010
0
  jxrc_write_pxfm(cp);
1011
0
}
1012
1013
/*
1014
** In case we are compositing the layer from several codestreams
1015
** by one that contains the alpha channel, write a compositing layer
1016
** header box.
1017
*/
1018
static void jxrc_write_jplh(jxr_container_t cp)
1019
0
{
1020
0
  if (cp->separate_alpha_image_plane) {
1021
0
    jxrc_write_box_header(cp,MAKE_ID('j','p','l','h'),8 + 8 + 4 + (2 + 4) * 2);
1022
0
    jxrc_write_box_header(cp,MAKE_ID('c','r','e','g'),8 + 4 + (2 + 4) * 2);
1023
    /* Grid width is simply 1 */
1024
0
    jxrc_write_UWORD(cp,1);
1025
0
    jxrc_write_UWORD(cp,1);
1026
0
    jxrc_write_UWORD(cp,0); /* first codestream */
1027
0
    jxrc_write_UBYTE(cp,1); /* scaling is 1-1 */
1028
0
    jxrc_write_UBYTE(cp,1); /* scaling is 1-1 */
1029
0
    jxrc_write_UBYTE(cp,0); /* offset is zero */
1030
0
    jxrc_write_UBYTE(cp,0); /* offset is zero */
1031
0
    jxrc_write_UWORD(cp,1); /* second codestream */
1032
0
    jxrc_write_UBYTE(cp,1); /* scaling is 1-1 */
1033
0
    jxrc_write_UBYTE(cp,1); /* scaling is 1-1 */
1034
0
    jxrc_write_UBYTE(cp,0); /* offset is zero */
1035
0
    jxrc_write_UBYTE(cp,0); /* offset is zero */
1036
0
  }
1037
0
}
1038
1039
/*
1040
** Write the first codestream header box or the only codestream header box if
1041
** there are more than one codestreams (separate alpha)
1042
*/
1043
static void jxrc_write_jpch(jxr_container_t cp)
1044
0
{
1045
0
  FILE *fp = cp->fd;
1046
0
  int size = 8; /* the box header. */
1047
1048
0
  cp->fd = NULL;
1049
0
  jxrc_write_ihdr(cp);
1050
0
  size  += cp->size_counter;
1051
0
  jxrc_write_bpc(cp);
1052
0
  size  += cp->size_counter;
1053
1054
0
  cp->fd = fp;
1055
0
  jxrc_write_box_header(cp,MAKE_ID('j','p','c','h'),size);
1056
0
  jxrc_write_ihdr(cp);
1057
0
  jxrc_write_bpc(cp);
1058
0
}
1059
1060
/*
1061
** Write the second codestream header box for the separate alpha channel
1062
** if required.
1063
*/
1064
static void jxrc_write_jpch_alpha(jxr_container_t cp)
1065
0
{
1066
0
  if (_jxrc_is_pre_alpha_pxfmt(cp) || _jxrc_is_alpha_pxfmt(cp)) {
1067
0
    if (cp->separate_alpha_image_plane) {
1068
0
      jxrc_write_box_header(cp,MAKE_ID('j','p','c','h'),8 + 8 + 4 + 4 + 2 + 1 + 1 + 1 + 1);
1069
0
      jxrc_write_box_header(cp,MAKE_ID('i','h','d','r'),8 + 4 + 4 + 2 + 1 + 1 + 1 + 1);
1070
0
      jxrc_write_ULONG(cp,cp->hei);
1071
0
      jxrc_write_ULONG(cp,cp->wid);
1072
1073
0
      jxrc_write_UWORD(cp,1);
1074
0
      jxrc_write_UBYTE(cp,get_bpc(cp)-1);
1075
0
      jxrc_write_UBYTE(cp,11); /* compression type is XR */
1076
0
      jxrc_write_UBYTE(cp,1);  /* color space is guessed */
1077
0
      jxrc_write_UBYTE(cp,0);  /* no rights information present */
1078
0
    }
1079
0
  }
1080
0
}
1081
1082
1083
int jxrc_start_file_boxed(jxr_container_t cp, FILE*fd)
1084
0
{
1085
0
  assert(cp->fd == 0);
1086
1087
  /* initializations */
1088
0
  cp->image_count_mark = 0;
1089
0
  cp->alpha_count_mark = 0;
1090
0
  cp->alpha_offset_mark = 0;
1091
0
  cp->alpha_band = 0;
1092
1093
0
  cp->fd = fd;
1094
1095
1096
0
  jxrc_write_signature_box(cp);
1097
0
  jxrc_write_file_type_box(cp);
1098
0
  jxrc_write_rreq_box(cp);
1099
0
  jxrc_write_jp2h(cp);
1100
0
  jxrc_write_jpch(cp);
1101
0
  jxrc_write_jpch_alpha(cp);
1102
0
  jxrc_write_jplh(cp);
1103
1104
  /* The first codestream. The length is fixed later. */
1105
0
  cp->image_offset_mark = ftell(cp->fd);
1106
0
  jxrc_write_box_header(cp,MAKE_ID('j','p','2','c'),0);
1107
0
  return 0;
1108
0
}
1109
1110
int jxrc_begin_image_data_boxed(jxr_container_t cp)
1111
0
{
1112
0
  return 0;
1113
0
}
1114
1115
int jxrc_write_container_post_boxed(jxr_container_t cp)
1116
0
{
1117
0
      uint32_t mark = ftell(cp->fd);
1118
0
      uint32_t count;
1119
1120
0
      assert(mark > cp->image_offset_mark);
1121
0
      count = mark - cp->image_offset_mark; /* 8 is the box header */
1122
1123
0
      DEBUG("CONTAINER: measured bitstream count=%u\n", count);
1124
1125
0
      fflush(cp->fd);
1126
0
      fseek(cp->fd, cp->image_offset_mark, SEEK_SET);
1127
0
      jxrc_write_ULONG(cp,count);
1128
1129
0
      if(cp->separate_alpha_image_plane) {
1130
0
        fseek(cp->fd, mark, SEEK_SET);
1131
0
        cp->alpha_offset_mark = mark;
1132
0
        jxrc_write_box_header(cp,MAKE_ID('j','p','2','c'),0);
1133
0
      }
1134
0
      return 0;
1135
0
}
1136
1137
int jxrc_write_container_post_alpha_boxed(jxr_container_t cp)
1138
0
{
1139
0
      uint32_t mark  = ftell(cp->fd);
1140
0
      uint32_t count = mark - cp->alpha_offset_mark;
1141
0
      DEBUG("CONTAINER: measured alpha count=%u\n", count);
1142
1143
0
      if(cp->separate_alpha_image_plane) {
1144
0
        fflush(cp->fd);
1145
        fseek(cp->fd, cp->alpha_offset_mark, SEEK_SET);
1146
0
        jxrc_write_ULONG(cp,count);
1147
0
      }
1148
0
      return 0;
1149
0
}
1150
/*
1151
* $Log: cw_emit_boxed.c,v $
1152
* Revision 1.10  2012-03-18 18:29:23  thor
1153
* Fixed the separation of alpha planes and the concatenation of alpha planes,
1154
* the number of channels was set incorrectly.
1155
*
1156
* Revision 1.9  2012-03-18 00:09:21  thor
1157
* Fixed handling of YCC.
1158
*
1159
* Revision 1.8  2012-03-17 20:03:45  thor
1160
* Fixed a lot of issues in the box parser - seems to work now in simple cases.
1161
*
1162
* Revision 1.7  2012-02-16 16:36:25  thor
1163
* Heavily reworked, but not yet tested.
1164
*
1165
* Revision 1.6  2012-02-13 21:11:03  thor
1166
* Tested now for most color formats.
1167
*
1168
* Revision 1.5  2012-02-13 18:56:44  thor
1169
* Fixed parsing 565 tiff files.
1170
*
1171
* Revision 1.4  2012-02-13 18:23:43  thor
1172
* Fixed writer in simple cases. Not everything explored yet.
1173
*
1174
* Revision 1.3  2012-02-13 17:36:50  thor
1175
* Fixed syntax errors, not yet debugged. Added option for box output.
1176
*
1177
* Revision 1.2  2012-02-13 16:25:18  thor
1178
* Updated the boxed functions.
1179
*
1180
* Revision 1.1  2012-02-11 04:24:20  thor
1181
* Added incomplete box writer.
1182
*
1183
* Revision 1.10  2011-11-19 20:52:34  thor
1184
* Fixed decoding of YUV422 in 10bpp, fixed 10bpp tiff reading and writing.
1185
*
1186
* Revision 1.9  2011-04-28 08:45:42  thor
1187
* Fixed compiler warnings, ported to gcc 4.4, removed obsolete files.
1188
*
1189
* Revision 1.8  2010-10-03 13:14:42  thor
1190
* Fixed missing preshift for BD32 images, added alpha-quantizer
1191
* parameter. Fixed alpha plane container offset.
1192
*
1193
* Revision 1.7  2010-10-03 12:35:27  thor
1194
* Fixed misaligned container sizes.
1195
*
1196
* Revision 1.6  2010-03-31 07:50:58  thor
1197
* Replaced by the latest MS version.
1198
*
1199
* Revision 1.2 2009/05/29 12:00:00 microsoft
1200
* Reference Software v1.6 updates.
1201
*
1202
* Revision 1.1 2009/04/13 12:00:00 microsoft
1203
* Reference Software v1.5 updates.
1204
*
1205
*/