/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 | | */ |