1
2 /*************************************************************************
3 *
4 * This software module was originally contributed by Microsoft
5 * Corporation in the course of development of the
6 * ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
7 * reference purposes and its performance may not have been optimized.
8 *
9 * This software module is an implementation of one or more
10 * tools as specified by the JPEG XR standard.
11 *
12 * ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
13 * copyright license to copy, distribute, and make derivative works
14 * of this software module or modifications thereof for use in
15 * products claiming conformance to the JPEG XR standard as
16 * specified by ITU-T T.832 | ISO/IEC 29199-2.
17 *
18 * ITU/ISO/IEC give users the same free license to this software
19 * module or modifications thereof for research purposes and further
20 * ITU/ISO/IEC standardization.
21 *
22 * Those intending to use this software module in products are advised
23 * that its use may infringe existing patents. ITU/ISO/IEC have no
24 * liability for use of this software module or modifications thereof.
25 *
26 * Copyright is not released for products that do not conform to
27 * to the JPEG XR standard as specified by ITU-T T.832 |
28 * ISO/IEC 29199-2.
29 *
30 * Microsoft Corporation retains full right to modify and use the code
31 * for its own purpose, to assign or donate the code to a third party,
32 * and to inhibit third parties from using the code for products that
33 * do not conform to the JPEG XR standard as specified by ITU-T T.832 |
34 * ISO/IEC 29199-2.
35 *
36 * This copyright notice must be included in all copies or derivative
37 * works.
38 *
39 * Copyright (c) ITU-T/ISO/IEC 2008, 2009.
40 **********************************************************************/
41
42 #ifdef _MSC_VER
43 #pragma comment (user,"$Id: file.c,v 1.15 2008/03/17 23:34:54 steve Exp $")
44 #else
45 #ident "$Id: file.c,v 1.15 2008/03/17 23:34:54 steve Exp $"
46 #endif
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <stdarg.h>
51 #include <string.h>
52 #include <ctype.h>
53 #include <assert.h>
54 #include "jpegxr.h"
55 # include "jxr_priv.h"
56
57 #ifndef _MSC_VER
58 # include <stdint.h>
59 #else
60 /* MSVC (as of 2008) does not support C99 or the stdint.h header
61 file. So include a private little header file here that does the
62 minimal typedefs that we need. */
63 # include "stdint_minimal.h"
64 /* MSVC doesn't have strcasecmp. Use _stricmp instead */
65 # define strcasecmp _stricmp
66 #endif
67
68 typedef struct context{
69 const char *name; /* name of TIFF or PNM file */
70 int wid; /* image width in pixels */
71 int hei; /* image height in pixels */
72 int ncomp; /* num of color components, 1, 3, or 4 */
73 int bpi; /* bits per component, 1..16 */
74 int ycc_bd10_flag; /* flag to distinguish RGB101010 from YCC BD10 formats*/
75 int ycc_format; /* ycc format, 0 (Not Applicable), 1 (YUV420), 2 (YUV422), 3 (YUV444)*/
76 short sf; /* sample format, 1 (UINT), 2 (FixedPoint), 3 (float) or 4 (RGBE)*/
77 int format; /* component format code 0..15 */
78 unsigned swap : 1; /* byte swapping required ? */
79 FILE *file; /* input or output file pointer */
80 void *buf; /* source or destination data buffer */
81 int my; /* last MB strip (of 16 lines) read, init to -1 */
82 int nstrips; /* num of TIFF strips, 0 for PNM */
83 int strip; /* index of the current TIFF strip, 0 for PNM */
84 int nlines; /* num of lines per TIFF strip, height for PNM */
85 int line; /* index of current line in current strip */
86 short photometric; /* PhotometricInterpretation:
87 WhiteIsZero 0
88 BlackIsZero 1
89 RGB 2
90 RGB Palette 3
91 Transparency mask 4
92 CMYK 5
93 YCbCr 6
94 CIELab 8
95 */
96 uint32_t offoff; /* offset in TIFF file of StripOffsets ifd entry*/
97 int padBytes;
98 int alpha; /* with alpha channel */
99 unsigned int isBgr;
100 int top_pad;
101 int top_pad_remaining;
102 int left_pad;
103 }context;
104
error(char * format,...)105 static void error(char *format,...)
106 {
107 va_list args;
108 fprintf(stderr, "Error: ");
109 va_start(args, format);
110 vfprintf(stderr, format, args);
111 va_end(args);
112 fprintf(stderr, "\n");
113 abort();
114 }
115
116 /* YCC/CMYKDIRECT format tests */
117
isOutputYUV444(jxr_image_t image)118 unsigned int isOutputYUV444(jxr_image_t image)
119 {
120 switch (jxr_get_pixel_format(image))
121 {
122 case JXRC_FMT_24bppYCC444:
123 case JXRC_FMT_30bppYCC444:
124 case JXRC_FMT_48bppYCC444:
125 case JXRC_FMT_48bppYCC444FixedPoint:
126 case JXRC_FMT_32bppYCC444Alpha:
127 case JXRC_FMT_40bppYCC444Alpha:
128 case JXRC_FMT_64bppYCC444Alpha:
129 case JXRC_FMT_64bppYCC444AlphaFixedPoint:
130 return 1;
131 default:
132 return 0;
133 }
134 }
135
isOutputYUV422(jxr_image_t image)136 unsigned int isOutputYUV422(jxr_image_t image)
137 {
138 switch (jxr_get_pixel_format(image))
139 {
140 case JXRC_FMT_16bppYCC422:
141 case JXRC_FMT_20bppYCC422:
142 case JXRC_FMT_32bppYCC422:
143 case JXRC_FMT_24bppYCC422Alpha:
144 case JXRC_FMT_30bppYCC422Alpha:
145 case JXRC_FMT_48bppYCC422Alpha:
146 return 1;
147 default:
148 return 0;
149 }
150 }
151
isOutputYUV420(jxr_image_t image)152 unsigned int isOutputYUV420(jxr_image_t image)
153 {
154 switch (jxr_get_pixel_format(image))
155 {
156 case JXRC_FMT_12bppYCC420:
157 case JXRC_FMT_20bppYCC420Alpha:
158 return 1;
159 default:
160 return 0;
161 }
162 }
163
isOutputCMYKDirect(jxr_image_t image)164 unsigned int isOutputCMYKDirect(jxr_image_t image)
165 {
166 switch (jxr_get_pixel_format(image))
167 {
168 case JXRC_FMT_32bppCMYKDIRECT:
169 case JXRC_FMT_64bppCMYKDIRECT:
170 case JXRC_FMT_40bppCMYKDIRECTAlpha:
171 case JXRC_FMT_80bppCMYKDIRECTAlpha:
172 return 1;
173 default:
174 return 0;
175 }
176 }
177
178 /* File Reading Primitives: */
179
read_data(context * con,void * buf,int size,int count)180 static void read_data(context *con, void *buf, int size, int count)
181 {
182 size_t rc = fread(buf, size, count, con->file);
183 if (rc!=count)
184 error("premature EOF in input file %s", con->name);
185 }
186
read_uint8(context * con,uint8_t * buf,int count)187 static inline void read_uint8(context *con, uint8_t *buf, int count)
188 {
189 read_data(con, buf, 1, count);
190 }
191
read_uint16(context * con,uint16_t * buf,int count)192 static void read_uint16(context *con, uint16_t *buf, int count)
193 {
194 read_data(con, buf, 2, count);
195 if (con->swap) {
196 uint8_t *p, *plim, t;
197 for (p=(uint8_t*)buf, plim=p+count*2; p<plim; p+=2)
198 t=p[0], p[0]=p[1], p[1]=t;
199 }
200 }
201
read_uint32(context * con,uint32_t * buf,int count)202 static void read_uint32(context *con, uint32_t *buf, int count)
203 {
204 read_data(con, buf, 4, count);
205 if (con->swap) {
206 uint8_t *p, *plim, t;
207 for (p=(uint8_t*)buf, plim=p+count*4; p<plim; p+=4)
208 t=p[0], p[0]=p[3], p[3]=t, t=p[1], p[1]=p[2], p[2]=t;
209 }
210 }
211
get_uint8(context * con)212 static inline uint8_t get_uint8(context *con)
213 {
214 uint8_t c;
215 read_uint8(con, &c, 1);
216 return c;
217 }
218
get_uint16(context * con)219 static inline uint16_t get_uint16(context *con)
220 {
221 uint16_t c;
222 read_uint16(con, &c, 1);
223 return c;
224 }
225
get_uint32(context * con)226 static inline uint32_t get_uint32(context *con)
227 {
228 uint32_t c;
229 read_uint32(con, &c, 1);
230 return c;
231 }
232
seek_file(context * con,long offset,int whence)233 static void seek_file(context *con, long offset, int whence)
234 {
235 int rc = fseek(con->file, offset, whence);
236 if (rc!=0)
237 error("cannot seek to desired offset in input file %s", con->name);
238 }
239
240 /* File Writing Primitives: */
241
write_data(context * con,const void * buf,int size,int count)242 static void write_data(context *con, const void *buf, int size, int count)
243 {
244 size_t rc = fwrite(buf, size, count, con->file);
245 if (rc!=count)
246 error("unable to write to output file %s", con->name);
247 }
248
write_uint8(context * con,const uint8_t * buf,int count)249 static inline void write_uint8(context *con, const uint8_t *buf, int count)
250 {
251 write_data(con, buf, 1, count);
252 }
253
write_uint16(context * con,uint16_t * buf,int count)254 static void write_uint16(context *con, uint16_t *buf, int count)
255 {
256 if (con->swap) { /* destructive ! */
257 char *p, *plim, t;
258 for (p=(char*)buf, plim=p+count*2; p<plim; p+=2)
259 t=p[0], p[0]=p[1], p[1]=t;
260 }
261 write_data(con, buf, 2, count);
262 }
263
write_uint32(context * con,uint32_t * buf,int count)264 static void write_uint32(context *con, uint32_t *buf, int count)
265 {
266 if (con->swap) { /* destructive ! */
267 char *p, *plim, t;
268 for (p=(char*)buf, plim=p+count*4; p<plim; p+=4)
269 t=p[0], p[0]=p[3], p[3]=t, t=p[1], p[1]=p[2], p[2]=t;
270 }
271 write_data(con, buf, 4, count);
272 }
273
put_uint8(context * con,const uint8_t value)274 static inline void put_uint8(context *con, const uint8_t value)
275 {
276 write_uint8(con, &value, 1);
277 }
278
put_uint16(context * con,const uint16_t value)279 static inline void put_uint16(context *con, const uint16_t value)
280 {
281 uint16_t buf = value;
282 write_uint16(con, &buf, 1);
283 }
284
put_uint32(context * con,const uint32_t value)285 static inline void put_uint32(context *con, const uint32_t value)
286 {
287 uint32_t buf = value;
288 write_uint32(con, &buf, 1);
289 }
290
291 /* PNM File Header Operations: */
292
read_pnm_number(context * con)293 static unsigned read_pnm_number(context *con)
294 {
295 int c;
296 unsigned n=0;
297
298 while (1) {
299 c = get_uint8(con);
300 if (c=='#')
301 while (get_uint8(con)!='\n');
302 else if (isdigit(c)) break;
303 else if (!isspace(c))
304 error("unexpected character 0x%02x (%c) found in PNM file %s", c, c, con->name);
305 }
306 do {
307 n = 10*n+c-'0';
308 c = get_uint8(con);
309 }
310 while (isdigit(c));
311 if (!isspace(c))
312 error("unexpected character 0x%02x (%c) following max value in PNM file %s", c, c, con->name);
313 return n;
314 }
315
open_pnm_input_file(context * con)316 static void open_pnm_input_file(context *con)
317 {
318 int c, max, one=1;
319
320 rewind(con->file);
321 c=get_uint8(con);
322 if (c!='P')
323 error("unexpected character 0x%02x (%c) at start of PNM file %s", c, c, con->name);
324 switch (c=get_uint8(con)) {
325 case '1' :
326 case '2' :
327 case '3' :
328 case '4' : error("unsupported PNM file type P%c in PNM file %s", c, con->name);
329 case '5' : con->ncomp = 1; break;
330 case '6' : con->ncomp = 3; break;
331 default : error("unexpected character 0x%02x (%c) following 'P' in PNM file %s", c, c, con->name);
332 }
333
334 con->wid = read_pnm_number(con);
335 if (con->wid<=0)
336 error("invalid image width %d in PNM file %s",con->wid, con->name);
337 con->hei = read_pnm_number(con);
338 if (con->hei<=0)
339 error("invalid image height %d in PNM file %s", con->hei, con->name);
340 max=read_pnm_number(con);
341 if (max>=0x10000)
342 error("invalid maximum value 0x%02x (%d) in PNM file %s", max, max, con->name);
343 if (max<0x100) con->swap = 0;
344 else con->swap = *(char*)&one==1;
345 for (con->bpi=1; max>(1<<con->bpi); con->bpi++);
346
347 con->nlines = con->hei;
348 }
349
start_pnm_output_file(context * con)350 static void start_pnm_output_file(context *con)
351 {
352 int max, one=1;
353 con->file = fopen(con->name, "wb");
354 if (con->file==0)
355 error("cannot create PNM output file %s",con->name);
356 max = (1<<con->bpi)-1;
357 if (max<256) con->swap = 0;
358 else con->swap = *(char*)&one==1;
359 fprintf(con->file, "P%c\n%d %d\n%d\n", con->ncomp==1?'5':'6', con->wid, con->hei, max);
360 }
361
362 /* TIFF File Header Operations: */
363
364 #define ImageWidth 256
365 #define ImageLength 257
366 #define BitsPerSample 258
367 #define Compression 259
368 #define Photometric 262
369 #define StripOffsets 273
370 #define SamplesPerPixel 277
371 #define RowsPerStrip 278
372 #define StripByteCounts 279
373 #define SampleFormat 339
374 #define InkSet 332
375
read_tif_ifd_entry(context * con,uint32_t ifdoff,uint16_t * tag,uint16_t * type,uint32_t * count)376 static void read_tif_ifd_entry(context *con, uint32_t ifdoff, uint16_t *tag, uint16_t *type, uint32_t *count)
377 {
378 seek_file(con, ifdoff, SEEK_SET);
379 read_uint16(con, tag, 1);
380 read_uint16(con, type, 1);
381 read_uint32(con, count, 1);
382 }
383
read_tif_data(context * con,uint16_t type,uint32_t count,int index,int nval,void * buf)384 static void read_tif_data(context *con, uint16_t type, uint32_t count, int index, int nval, void *buf)
385 {
386 int size=0;
387
388 switch (type) {
389 case 3 : size = 2; break;
390 case 4 : size = 4; break;
391 default : return;
392 }
393
394 if (index+nval>(int)count)
395 error("data array is to small for read request in TIFF file %s", con->name);
396
397 index *= size;
398 size *= count;
399 uint32_t offset = ftell(con->file);
400 if (size>4)
401 read_uint32(con, &offset, 1);
402 seek_file(con, offset+index, SEEK_SET);
403 switch (type) {
404 case 3 : read_uint16(con, (uint16_t*)buf, nval); break;
405 case 4 : read_uint32(con, (uint32_t*)buf, nval);
406 }
407 }
408
read_tif_datum(context * con,uint16_t type,uint32_t count,int index)409 static uint32_t read_tif_datum(context *con, uint16_t type, uint32_t count, int index)
410 {
411 uint8_t buf[4];
412
413 read_tif_data(con, type, count, index, 1, buf);
414 switch (type) {
415 case 3 : return (uint32_t)*(uint16_t*)buf;
416 case 4 : return (uint32_t)*(uint32_t*)buf;
417 default : return 0;
418 }
419 }
420
get_tif_datum(context * con,uint32_t ifdoff,int index)421 static uint32_t get_tif_datum(context *con, uint32_t ifdoff, int index)
422 {
423 uint16_t tag, type;
424 uint32_t count;
425
426 read_tif_ifd_entry(con, ifdoff, &tag, &type, &count);
427 return read_tif_datum(con, type, count, index);
428 }
429
open_tif_input_file(context * con)430 static void open_tif_input_file(context *con)
431 {
432 int i, one=1;
433 uint16_t magic, nentry, tag, type;
434 uint32_t count, diroff;
435
436 rewind(con->file);
437 read_uint16(con, &magic, 1);
438 switch (magic) {
439 case 0x4949 : con->swap = *(char*)&one!=1; break;
440 case 0x4d4d : con->swap = *(char*)&one==1; break;
441 default : error("bad magic number 0x%04x found at start of TIFF file %s", magic, con->name);
442 }
443 read_uint16(con, &magic, 1);
444 if (magic!=42)
445 error("magic number 42 not found in TIFF file %s", con->name);
446 read_uint32(con, &diroff, 1);
447
448 seek_file(con, diroff, SEEK_SET);
449 read_uint16(con, &nentry, 1);
450 for (i=0; i<nentry; i++) {
451 int ifdoff = diroff+2+12*i;
452 read_tif_ifd_entry(con, ifdoff, &tag, &type, &count);
453 uint32_t data = read_tif_datum(con, type, count, 0);
454 switch (tag) {
455 case ImageWidth:
456 con->wid = data;
457 break;
458 case ImageLength:
459 con->hei = data;
460 break;
461 case BitsPerSample:
462 con->bpi = data;
463 break;
464 case SamplesPerPixel:
465 con->ncomp = data;
466 break;
467 case Compression:
468 if (data!=1)
469 error("TIFF input file %s is compressed", con->name);
470 break;
471 case StripOffsets:
472 con->nstrips = count;
473 con->offoff = ifdoff;
474 break;
475 case RowsPerStrip:
476 con->nlines = data;
477 break;
478 case SampleFormat:
479 con->sf = data;
480 break;
481 case Photometric:
482 con->photometric = data;
483 break;
484
485 }
486 }
487
488 if (con->wid<=0)
489 error("valid ImageWidth entry not found in directory of TIFF file %s", con->name);
490 if (con->hei<=0)
491 error("valid ImageLength entry not found in directory of TIFF file %s", con->name);
492 if (con->ncomp!=1 && con->ncomp!=3 && con->ncomp!=4 && con->ncomp!=5)
493 error("valid SamplesPerPixel entry (1, 3, 4, or 5) not found in directory of TIFF file %s", con->name);
494 if (con->bpi>32)
495 error("valid BitsPerSample entry not found in directory of TIFF file %s", con->name);
496 if (con->nstrips<=0 || con->offoff==0)
497 error("valid StripOffsets entry not found in directory of TIFF file %s", con->name);
498 if (con->nlines<=0)
499 error("valid RowsPerStrip entry not found in directory of TIFF file %s", con->name);
500 con->line = con->nlines;
501 }
502
503
put_ifd_entry(context * con,int tag,int type,int count,uint32_t offset)504 static void put_ifd_entry(context *con, int tag, int type, int count, uint32_t offset)
505 {
506 put_uint16(con, tag);
507 put_uint16(con, type);
508 put_uint32(con, count);
509 if (type==3 && count==1) {
510 put_uint16(con, offset);
511 put_uint16(con, 0);
512 }
513 else put_uint32(con, offset);
514 }
515
validate_tif_output(jxrc_t_pixelFormat ePixelFormat)516 unsigned int validate_tif_output(jxrc_t_pixelFormat ePixelFormat)
517 {
518 switch(ePixelFormat)
519 {
520 case JXRC_FMT_24bppRGB:return 1;
521 case JXRC_FMT_24bppBGR: return 0;
522 case JXRC_FMT_32bppBGR:return 0;
523 case JXRC_FMT_48bppRGB:return 1;
524 case JXRC_FMT_48bppRGBFixedPoint: return 1;
525 case JXRC_FMT_48bppRGBHalf: return 1;
526 case JXRC_FMT_96bppRGBFixedPoint:return 1;
527 case JXRC_FMT_64bppRGBFixedPoint:return 1;
528 case JXRC_FMT_64bppRGBHalf:return 1;
529 case JXRC_FMT_128bppRGBFixedPoint:return 1;
530 case JXRC_FMT_128bppRGBFloat:return 1;
531 case JXRC_FMT_32bppBGRA:return 0;
532 case JXRC_FMT_64bppRGBA:return 1;
533 case JXRC_FMT_64bppRGBAFixedPoint:return 1;
534 case JXRC_FMT_64bppRGBAHalf:return 1;
535 case JXRC_FMT_128bppRGBAFixedPoint:return 1;
536 case JXRC_FMT_128bppRGBAFloat:return 1;
537 case JXRC_FMT_32bppPBGRA:return 0;
538 case JXRC_FMT_64bppPRGBA:return 0;
539 case JXRC_FMT_128bppPRGBAFloat:return 0;
540 case JXRC_FMT_32bppCMYK:return 1;
541 case JXRC_FMT_40bppCMYKAlpha:return 1;
542 case JXRC_FMT_64bppCMYK:return 1;
543 case JXRC_FMT_80bppCMYKAlpha:return 1;
544 case JXRC_FMT_24bpp3Channels:return 0;
545 case JXRC_FMT_32bpp4Channels:return 0;
546 case JXRC_FMT_40bpp5Channels:return 0;
547 case JXRC_FMT_48bpp6Channels:return 0;
548 case JXRC_FMT_56bpp7Channels:return 0;
549 case JXRC_FMT_64bpp8Channels:return 0;
550 case JXRC_FMT_32bpp3ChannelsAlpha:return 0;
551 case JXRC_FMT_40bpp4ChannelsAlpha:return 0;
552 case JXRC_FMT_48bpp5ChannelsAlpha:return 0;
553 case JXRC_FMT_56bpp6ChannelsAlpha:return 0;
554 case JXRC_FMT_64bpp7ChannelsAlpha:return 0;
555 case JXRC_FMT_72bpp8ChannelsAlpha:return 0;
556 case JXRC_FMT_48bpp3Channels:return 0;
557 case JXRC_FMT_64bpp4Channels:return 0;
558 case JXRC_FMT_80bpp5Channels:return 0;
559 case JXRC_FMT_96bpp6Channels:return 0;
560 case JXRC_FMT_112bpp7Channels:return 0;
561 case JXRC_FMT_128bpp8Channels:return 0;
562 case JXRC_FMT_64bpp3ChannelsAlpha:return 0;
563 case JXRC_FMT_80bpp4ChannelsAlpha:return 0;
564 case JXRC_FMT_96bpp5ChannelsAlpha:return 0;
565 case JXRC_FMT_112bpp6ChannelsAlpha:return 0;
566 case JXRC_FMT_128bpp7ChannelsAlpha:return 0;
567 case JXRC_FMT_144bpp8ChannelsAlpha:return 0;
568 case JXRC_FMT_8bppGray:return 1;
569 case JXRC_FMT_16bppGray:return 1;
570 case JXRC_FMT_16bppGrayFixedPoint:return 1;
571 case JXRC_FMT_16bppGrayHalf:return 1;
572 case JXRC_FMT_32bppGrayFixedPoint:return 1;
573 case JXRC_FMT_32bppGrayFloat:return 1;
574 case JXRC_FMT_BlackWhite:return 1;
575 case JXRC_FMT_16bppBGR555:return 0;
576 case JXRC_FMT_16bppBGR565:return 0;
577 case JXRC_FMT_32bppBGR101010:return 0;
578 case JXRC_FMT_32bppRGBE:return 0;
579 case JXRC_FMT_32bppCMYKDIRECT:return 0;
580 case JXRC_FMT_64bppCMYKDIRECT:return 0;
581 case JXRC_FMT_40bppCMYKDIRECTAlpha:return 0;
582 case JXRC_FMT_80bppCMYKDIRECTAlpha:return 0;
583 case JXRC_FMT_12bppYCC420:return 0;
584 case JXRC_FMT_16bppYCC422:return 0;
585 case JXRC_FMT_20bppYCC422:return 0;
586 case JXRC_FMT_32bppYCC422:return 0;
587 case JXRC_FMT_24bppYCC444:return 0;
588 case JXRC_FMT_30bppYCC444:return 0;
589 case JXRC_FMT_48bppYCC444:return 0;
590 case JXRC_FMT_48bppYCC444FixedPoint:return 0;
591 case JXRC_FMT_20bppYCC420Alpha:return 0;
592 case JXRC_FMT_24bppYCC422Alpha:return 0;
593 case JXRC_FMT_30bppYCC422Alpha:return 0;
594 case JXRC_FMT_48bppYCC422Alpha:return 0;
595 case JXRC_FMT_32bppYCC444Alpha:return 0;
596 case JXRC_FMT_40bppYCC444Alpha:return 0;
597 case JXRC_FMT_64bppYCC444Alpha:return 0;
598 case JXRC_FMT_64bppYCC444AlphaFixedPoint:return 0;
599 default: return 0;
600 }
601 }
validate_pnm_output(jxrc_t_pixelFormat ePixelFormat)602 unsigned int validate_pnm_output(jxrc_t_pixelFormat ePixelFormat)
603 {
604 switch(ePixelFormat)
605 {
606 case JXRC_FMT_24bppRGB:return 1;
607 case JXRC_FMT_8bppGray:return 1;
608 default: return 0;
609 }
610 }
611
start_tif_output_file(context * con)612 static void start_tif_output_file(context *con)
613 {
614 con->file = fopen(con->name, "wb");
615 if (con->file==0)
616 error("cannot create TIFF output file %s", con->name);
617 con->swap = 0;
618
619 int one = 1;
620 char magic = *(char*)&one==1 ? 'I' : 'M';
621 int nentry = 10;
622 if (con->ncomp == 4 && !con->alpha) /* CMYK */
623 nentry += 1;
624 int bitsize = con->ncomp>=3 ? 2*con->ncomp : 0;
625 int bitoff = 8 + 2 + 12*nentry + 4;
626 int datoff = bitoff + bitsize;
627
628 put_uint8(con, magic);
629 put_uint8(con, magic);
630 put_uint16(con, 42);
631 put_uint32(con, 8);
632 put_uint16(con, nentry);
633 put_ifd_entry(con, ImageWidth, 4, 1, con->wid);
634 put_ifd_entry(con, ImageLength, 4, 1, con->hei);
635 put_ifd_entry(con, BitsPerSample, 3, con->ncomp, con->ncomp>=3 ? bitoff : con->bpi);
636 switch (con->format)
637 {
638 case 0: /* BD1WHITE1*/
639 case 1: /* BD8 */
640 case 2: /* BD16 */
641 /* case 5: Reserved */
642 case 8: /* BD5 */
643 case 9: /* BD10 */
644 case 15: /* BD1BLACK1 */
645 con->sf = 1;
646 break;
647 case 3: /* BD16S */
648 case 6: /* BD32S */
649 con->sf = 2;
650 break;
651 case 4: /* BD16F */
652 case 7: /* BD32F */
653 con->sf = 3;
654 break;
655 default:
656 assert(0);
657 }
658 put_ifd_entry(con, SampleFormat, 3, 1, con->sf);
659 put_ifd_entry(con, Compression, 3, 1, 1);
660 put_ifd_entry(con, Photometric, 3, 1, con->photometric);
661 put_ifd_entry(con, StripOffsets, 4, 1, datoff);
662 if(!con->padBytes)
663 put_ifd_entry(con, SamplesPerPixel, 3, 1, con->ncomp);
664 else
665 put_ifd_entry(con, SamplesPerPixel, 3, 1, con->ncomp + 1);
666
667 put_ifd_entry(con, RowsPerStrip, 4, 1, con->hei);
668 if(con->bpi == 1)
669 put_ifd_entry(con, StripByteCounts, 4, 1, ((con->wid+7)>>3) * con->hei * con->ncomp);
670 else if(!con->padBytes)
671 put_ifd_entry(con, StripByteCounts, 4, 1, con->wid * con->hei * con->ncomp * ((con->bpi+7)/8));
672 else
673 put_ifd_entry(con, StripByteCounts, 4, 1, con->wid * con->hei * (con->ncomp + 1)* ((con->bpi+7)/8));
674
675 if (con->ncomp == 4 && !con->alpha)
676 put_ifd_entry(con, InkSet, 3, 1, 1);
677
678 put_uint32(con, 0);
679 assert(ftell(con->file)==bitoff);
680 if (con->ncomp>=3) {
681 int i;
682 for (i=0; i<con->ncomp; i++)
683 put_uint16(con, con->bpi);
684 }
685 assert(ftell(con->file)==datoff);
686 }
687
start_raw_output_file(context * con)688 static void start_raw_output_file(context *con)
689 {
690 con->file = fopen(con->name, "w+b");
691 if (con->file==0)
692 error("cannot create RAW output file %s", con->name);
693 con->swap = 0;
694 }
695
696 /* Generic File Header Operations: */
697
open_input_file(const char * name,const raw_info * raw_info_t,int * alpha_mode,int * padded_format)698 void *open_input_file(const char *name, const raw_info *raw_info_t, int *alpha_mode, int *padded_format)
699 {
700 context *con;
701
702 con = (context*)malloc(sizeof(context));
703 if (con==0)
704 error("unable to allocate memory");
705
706 con->name = name;
707 con->wid = 0;
708 con->hei = 0;
709 con->ncomp = 0;
710 con->bpi = 0;
711 con->format = 0;
712 con->sf = 1;
713 con->swap = 0;
714 con->buf = 0;
715 con->my = -1;
716 con->nstrips = 0;
717 con->strip = 0;
718 con->nlines = 0;
719 con->line = 0;
720 con->photometric = 0;
721 con->offoff = 0;
722 con->ycc_bd10_flag = 0;
723 con->ycc_format = 0;
724
725 con->file = fopen(name, "rb");
726 if (con->file==0)
727 error("cannot find input file %s", name);
728
729 if (!raw_info_t->is_raw) {
730 switch (get_uint8(con)) {
731 case 'P' : open_pnm_input_file(con); break;
732 case 'I' :
733 case 'M' : open_tif_input_file(con); break;
734 default : error("format of input file %s is unrecognized", name);
735 }
736
737 con->padBytes = 0;
738 if(con->photometric == 2 && con->ncomp == 4) /* RGBA */
739 if( *padded_format == 1) { /* for RGB_NULL, there is a padding channel */
740 con->padBytes = 1;
741 con->ncomp --;
742 if(*alpha_mode != 0)
743 {
744 *alpha_mode = 0; /* Turn off alpha mode */
745 fprintf(stderr, "Setting alpha_mode to 0 to encode a padded format \n");
746 }
747 }
748 else
749 {
750 if(*alpha_mode == 0)
751 {
752 *alpha_mode = 2; /* Turn on separate alpha */
753 }
754 }
755 }
756 else { /* raw input */
757 con->wid = raw_info_t->raw_width;
758 con->hei = raw_info_t->raw_height;
759 con->nlines = con->hei;
760 con->bpi = raw_info_t->raw_bpc;
761 con->sf = 1; /* UINT */
762 con->padBytes = 0;
763 if (con->bpi == 10 && raw_info_t->raw_format > 18) {
764 con->ycc_bd10_flag = 1;
765 con->bpi = 16;
766 }
767
768 if ((raw_info_t->raw_format >= 3) && (raw_info_t->raw_format <= 8)) { /* N-channel */
769 con->ncomp = raw_info_t->raw_format;
770 }
771 else if ((raw_info_t->raw_format >= 9) && (raw_info_t->raw_format <= 14)) { /* N-channel with Alpha */
772 con->ncomp = raw_info_t->raw_format - 5;
773 }
774 else if (15 == raw_info_t->raw_format) {/* RGBE */
775 con->ncomp = 4;
776 con->sf = 4;
777 }
778 else if (16 == raw_info_t->raw_format) {/* 555 */
779 con->ncomp = 3;
780 con->bpi = 5;
781 }
782 else if (17 == raw_info_t->raw_format) {/* 565 */
783 con->ncomp = 3;
784 con->bpi = 6;
785 }
786 else if (18 == raw_info_t->raw_format) {/* 101010 */
787 con->ncomp = 3;
788 con->bpi = 10;
789 }
790 else if (19 == raw_info_t->raw_format) {
791 con->ncomp = 3;
792 con->ycc_format = 1;
793 }
794 else if (20 == raw_info_t->raw_format) {
795 con->ncomp = 3;
796 con->ycc_format = 2;
797 }
798 else if (21 == raw_info_t->raw_format) {
799 con->ncomp = 3;
800 con->ycc_format = 3;
801 }
802 else if (22 == raw_info_t->raw_format) {
803 con->ncomp = 3;
804 con->sf = 2; /* SINT */
805 con->ycc_format = 3;
806 }
807 else if (23 == raw_info_t->raw_format) {
808 con->ncomp = 4;
809 con->ycc_format = 1;
810 }
811 else if (24 == raw_info_t->raw_format) {
812 con->ncomp = 4;
813 con->ycc_format = 2;
814 }
815 else if (25 == raw_info_t->raw_format) {
816 con->ncomp = 4;
817 con->ycc_format = 3;
818 }
819 else if (26 == raw_info_t->raw_format) {
820 con->ncomp = 4;
821 con->sf = 2; /* SINT */
822 con->ycc_format = 3;
823 }
824 else if (27 == raw_info_t->raw_format) {
825 con->ncomp = 4;
826 }
827 else if (28 == raw_info_t->raw_format) {
828 con->ncomp = 5;
829 }
830 else if(29 == raw_info_t->raw_format) {/* 24bppBGR */
831 con->ncomp = 3;
832 con->bpi = 8;
833 }
834 else if(30 == raw_info_t->raw_format) {/* 32bppBGR */
835 con->ncomp = 3;
836 con->bpi = 8;
837 con->padBytes = 1;
838 *padded_format = 1;
839 }
840 else if(31 == raw_info_t->raw_format) {/* 32bppBGRA */
841 con->ncomp = 4;
842 con->bpi = 8;
843 }
844 else if(32 == raw_info_t->raw_format) {/* 32bppPBGRA */
845 con->ncomp = 4;
846 con->bpi = 8;
847 }
848 else if(33 == raw_info_t->raw_format) {/* 64bppPRGBA */
849 con->ncomp = 4;
850 con->bpi = 16;
851 }
852 else if(34 == raw_info_t->raw_format) {/* 128bppPRGBAFloat */
853 con->ncomp = 4;
854 con->bpi = 32;
855 con->sf = 3;
856 con->photometric = 2;
857 }
858 }
859
860 if(con->padBytes == 0 && *padded_format)
861 {
862 *padded_format = 0;
863 fprintf(stderr, "Ignoring -p option from command line \n");
864 }
865
866 size_t strip_bytes;
867 if (con->ycc_format == 1)
868 strip_bytes = 8 * ((4*con->ncomp-6) + con->padBytes) * ((con->bpi+7)/8) * ((con->wid+15)&~15)/2;
869 else if (con->ycc_format == 2)
870 strip_bytes = 16 * ((2*con->ncomp-2) + con->padBytes) * ((con->bpi+7)/8) * ((con->wid+15)&~15)/2;
871 else
872 strip_bytes = 16 * (con->ncomp + con->padBytes) * ((con->bpi+7)/8) * ((con->wid+15)&~15);
873
874 if (con->bpi == 1)
875 strip_bytes >>= 3;
876 else if ((con->bpi == 5) || (con->bpi == 6) || (con->bpi == 10 && !con->ycc_bd10_flag))
877 strip_bytes = (strip_bytes << 1) / 3; /* external buffer */
878
879 con->buf = calloc(strip_bytes, 1);
880 if (con->buf==0)
881 error("cannot allocate memory");
882
883 return con;
884 }
set_ncomp(void * input_handle,int ncomp)885 void set_ncomp(void *input_handle, int ncomp)
886 {
887 context *con = (context *)input_handle;
888 con->ncomp = ncomp;
889 }
890
open_output_file(const char * name)891 void *open_output_file(const char *name)
892 {
893 context *con = (context*)malloc(sizeof(context));
894 if (con==0)
895 error("unable to allocate memory");
896 con->file = 0;
897 con->name = name;
898 con->wid = 0;
899 con->hei = 0;
900 con->ncomp = 0;
901 con->bpi = 0;
902 con->format = 0;
903 con->swap = 0;
904 con->buf = 0;
905 return con;
906 }
907
close_file(void * handle)908 void close_file(void *handle)
909 {
910 if(handle == NULL)
911 return;
912 context *con = (context*)handle;
913 if (con->file) fclose(con->file);
914 if (con->buf) free(con->buf);
915 free(con);
916 }
917
get_file_parameters(void * handle,int * wid,int * hei,int * ncomp,int * bpi,short * sf,short * photometric,int * padBytes)918 void get_file_parameters(void *handle, int *wid, int *hei, int *ncomp, int *bpi, short *sf, short *photometric, int *padBytes)
919 {
920 context *con = (context*)handle;
921 if (wid) *wid = con->wid;
922 if (hei) *hei = con->hei;
923 if (ncomp) *ncomp = con->ncomp;
924 if (bpi) *bpi = con->bpi;
925 if (sf) *sf = con->sf;
926 if (photometric) *photometric = con->photometric;
927 if (padBytes) *padBytes = con->padBytes;
928 }
929
set_photometric_interp(context * con,jxrc_t_pixelFormat pixelFormat)930 void set_photometric_interp(context *con, jxrc_t_pixelFormat pixelFormat)
931 {
932 switch(pixelFormat)
933 {
934 case JXRC_FMT_32bppCMYK:
935 case JXRC_FMT_40bppCMYKAlpha:
936 case JXRC_FMT_64bppCMYK:
937 case JXRC_FMT_80bppCMYKAlpha:
938 con->photometric = 5;
939 return;
940 case JXRC_FMT_8bppGray:
941 case JXRC_FMT_16bppGray:
942 case JXRC_FMT_16bppGrayFixedPoint:
943 case JXRC_FMT_16bppGrayHalf:
944 case JXRC_FMT_32bppGrayFixedPoint:
945 case JXRC_FMT_32bppGrayFloat:
946 case JXRC_FMT_BlackWhite:
947 con->photometric = 1;
948 return;
949 default:
950 con->photometric = 2;
951 return;
952 }
953 }
954
start_output_file(context * con,int ext_width,int ext_height,int width,int height,int ncomp,int format,jxrc_t_pixelFormat pixelFormat)955 static void start_output_file(context *con, int ext_width, int ext_height, int width, int height, int ncomp, int format, jxrc_t_pixelFormat pixelFormat)
956 {
957 int bpi=0;
958 switch (format) {
959 case 0 : bpi=1; break;
960 case 1 : bpi=8; break;
961 case 2 :
962 case 3 :
963 case 4 : bpi=16; break;
964 case 5 :
965 case 6 :
966 case 7 : bpi=32; break;
967 case 8 : bpi=5; break;
968 case 9 : bpi=10; break;
969 case 10 : bpi=6; break;
970 case 15 : bpi=1; break;
971 default : error("invalid component format code (%d) for output file %s", format, con->name);
972 }
973
974 if (bpi<1 || bpi>32)
975 error("invalid bits per sample (%d) for output file %s", bpi, con->name);
976 if (width<=0 || height<=0)
977 error("invalid dimensions (%d X %d) for output file %s", width, height, con->name);
978
979 con->wid = width;
980 con->hei = height;
981 con->ncomp = ncomp;
982 con->bpi = bpi;
983 con->format = format;
984 /* Add one extra component for possible padding channel */
985 con->buf = malloc(((ext_width)/16) * 256 * (ncomp + 1) * ((con->bpi+7)/8));
986 if (con->buf==0) error("unable to allocate memory");
987
988 const char *p = strrchr(con->name, '.');
989 if (p==0)
990 error("output file name %s needs a suffix to determine its format", con->name);
991 if (!strcasecmp(p, ".pnm") || !strcasecmp(p, ".pgm") || !strcasecmp(p, ".ppm"))
992 {
993 if(!validate_pnm_output(pixelFormat))
994 {
995 printf("User error: PixelFormat is incompatible with pnm output, use .raw or .tif extension for output file\n");
996 assert(0);
997 }
998 start_pnm_output_file(con);
999 }
1000 else if (!strcasecmp(p, ".tif"))
1001 {
1002 if(!validate_tif_output(pixelFormat) && ncomp != 1)
1003 {
1004 printf("User error: PixelFormat is incompatible with tif output, use .raw extension for output file\n");
1005 assert(0);
1006 }
1007 set_photometric_interp(con, pixelFormat);
1008 start_tif_output_file(con);
1009 }
1010 else if (!strcasecmp(p, ".raw"))
1011 start_raw_output_file(con);
1012 else error("unrecognized suffix on output file name %s", con->name);
1013 }
1014
1015 /* File Read and Write Operations: */
1016
PreScalingBD16F(int hHalf)1017 static int PreScalingBD16F(int hHalf)
1018 {
1019 int s;
1020 s = (hHalf >> 31);
1021 hHalf = ((hHalf & 0x7fff) ^ s) - s;
1022 return hHalf;
1023 }
1024
PreScalingBD32F(int f,const char _c,const unsigned char _lm)1025 static int PreScalingBD32F(int f, const char _c, const unsigned char _lm)
1026 {
1027 int _h, e, e1, m, s;
1028
1029 if (f == 0)
1030 {
1031 _h = 0;
1032 }
1033 else
1034 {
1035 e = (f >> 23) & 0x000000ff;/* here set e as e, not s! e includes s: [s e] 9 bits [31..23] */
1036 m = (f & 0x007fffff) | 0x800000; /* actual mantissa, with normalizer */
1037 if (e == 0) { /* denormal-land */
1038 m ^= 0x800000; /* actual mantissa, removing normalizer */
1039 e++; /* actual exponent -126 */
1040 }
1041
1042 e1 = e - 127 + _c; /* this is basically a division or quantization to a different exponent */
1043
1044 if (e1 <= 1) { /* denormal */
1045 if (e1 < 1)
1046 m >>= (1 - e1); /* shift mantissa right to make exponent 1 */
1047 e1 = 1;
1048 if ((m & 0x800000) == 0) /* if denormal, set e1 to zero else to 1 */
1049 e1 = 0;
1050 }
1051 m &= 0x007fffff;
1052
1053 _h = (e1 << _lm) + ((m + (1 << (23 - _lm - 1))) >> (23 - _lm));/* take 23-bit m, shift (23-lm), get lm-bit m */
1054 s = (f >> 31);
1055 /* padding to int-32: */
1056 _h = (_h ^ s) - s;
1057 }
1058
1059 return _h;
1060 }
1061
forwardRGBE(int RGB,int E)1062 int forwardRGBE (int RGB, int E)
1063 {
1064 int iResult = 0, iAppend = 1;
1065
1066 if (E == 0)
1067 return 0;
1068
1069 E--;
1070 while (((RGB & 0x80) == 0) && (E > 0)) {
1071 RGB = (RGB << 1) + iAppend;
1072 iAppend = 0;
1073 E--;
1074 }
1075
1076 if (E == 0) {
1077 iResult = RGB;
1078 }
1079 else {
1080 E++;
1081 iResult = (RGB & 0x7f) + (E << 7);
1082 }
1083
1084 return iResult;
1085 }
1086
set_pad_bytes(context * con,jxr_image_t image)1087 void set_pad_bytes(context *con, jxr_image_t image)
1088 {
1089 /* Incomplete: Add padding data for other formats as we go */
1090 switch (jxr_get_pixel_format(image))
1091 {
1092 case JXRC_FMT_128bppRGBFloat:
1093 case JXRC_FMT_128bppRGBFixedPoint:
1094 con->padBytes = 32;
1095 break;
1096 case JXRC_FMT_64bppRGBFixedPoint:
1097 case JXRC_FMT_64bppRGBHalf:
1098 con->padBytes = 16;
1099 break;
1100 case JXRC_FMT_32bppBGR:
1101 con->padBytes = 8;
1102 break;
1103 default:
1104 con->padBytes = 0;
1105 break;
1106 }
1107
1108 }
1109
set_bgr_flag(context * con,jxr_image_t image)1110 void set_bgr_flag(context *con, jxr_image_t image)
1111 {
1112 con->isBgr = 0;
1113 switch (jxr_get_pixel_format(image))
1114 {
1115 case JXRC_FMT_24bppBGR:
1116 case JXRC_FMT_32bppBGR:
1117 case JXRC_FMT_32bppBGRA:
1118 case JXRC_FMT_32bppPBGRA:
1119 con->isBgr = 1;
1120 break;
1121 default:
1122 break;
1123 }
1124 return;
1125 }
1126
switch_r_b(void * data,int bpi)1127 void switch_r_b(void *data, int bpi)
1128 {
1129 uint32_t tmp;
1130 data = (uint8_t*)data;
1131 if(bpi == 8)
1132 {
1133 uint8_t *p = (uint8_t*)data;
1134 tmp = p[0];
1135 p[0] = p[2];
1136 p[2] = tmp;
1137
1138 }
1139
1140 else if(bpi == 16)
1141 {
1142 uint16_t *p = (uint16_t*)data;
1143 tmp = p[0];
1144 p[0] = p[2];
1145 p[2] = tmp;
1146 }
1147 else if(bpi == 32)
1148 {
1149 uint32_t *p = (uint32_t *)data;
1150 tmp = p[0];
1151 p[0] = p[2];
1152 p[2] = tmp;
1153 }
1154 else
1155 {
1156 assert(!"Invalid bpi\n");
1157 }
1158 }
1159
read_setup(context * con)1160 static void read_setup(context *con)
1161 {
1162 if (con->line == con->nlines) {
1163 if (con->strip == con->nstrips)
1164 error("unexpected end of data encountered in input file %s", con->name);
1165 seek_file(con, get_tif_datum(con, con->offoff, con->strip), SEEK_SET);
1166 con->strip++;
1167 }
1168 con->line++;
1169 }
1170
read_file_YCC(jxr_image_t image,int mx,int my,int * data)1171 void read_file_YCC(jxr_image_t image, int mx, int my, int *data) {
1172 /* There are 3 or 4 buffers, depending on whether there is an alpha channel or not */
1173 context *con = (context*) jxr_get_user_data(image);
1174 int num_channels = con->ncomp;
1175
1176 unsigned int widthY = con->wid, heightY = con->hei;
1177 unsigned int widthUV = con->wid >> ((con->ycc_format == 1 || con->ycc_format == 2) ? 1 : 0);
1178 unsigned int heightUV = con->hei >> (con->ycc_format == 1 ? 1 : 0);
1179 unsigned int MBheightY = 16;
1180 unsigned int MBheightUV = con->ycc_format == 1 ? 8 : 16;
1181 unsigned int sizeY = widthY * heightY;
1182 unsigned int sizeUV = widthUV * heightUV;
1183
1184 if (my != con->my) {
1185 if (con->bpi == 8) {
1186 unsigned int offsetY = my * MBheightY * widthY;
1187 unsigned int offsetU = sizeY + my * MBheightUV * widthUV;
1188 unsigned int offsetV = sizeY + sizeUV + my * MBheightUV * widthUV;
1189 unsigned int offsetA = sizeY + 2 * sizeUV + my * MBheightY * widthY;
1190
1191 uint8_t *sp = (uint8_t*)con->buf;
1192
1193 seek_file(con, offsetY, SEEK_SET);
1194 memset(sp, 0, widthY * MBheightY);
1195 read_data(con, sp, 1, widthY * MBheightY);
1196 sp += widthY * MBheightY;
1197
1198 seek_file(con, offsetU, SEEK_SET);
1199 memset(sp, 0, widthUV * MBheightUV);
1200 read_data(con, sp, 1, widthUV * MBheightUV);
1201 sp += widthUV * MBheightUV;
1202
1203 seek_file(con, offsetV, SEEK_SET);
1204 memset(sp, 0, widthUV * MBheightUV);
1205 read_data(con, sp, 1, widthUV * MBheightUV);
1206 sp += widthUV * MBheightUV;
1207
1208 if (con->ncomp == 4) {
1209 seek_file(con, offsetA, SEEK_SET);
1210 memset(sp, 0, widthY * MBheightY);
1211 read_data(con, sp, 1, widthY * MBheightY);
1212 sp += widthY * MBheightY;
1213 }
1214 }
1215 else if (con->bpi == 16) {
1216 unsigned int offsetY = 2 * (my * MBheightY * widthY);
1217 unsigned int offsetU = 2 * (sizeY + my * MBheightUV * widthUV);
1218 unsigned int offsetV = 2 * (sizeY + sizeUV + my * MBheightUV * widthUV);
1219 unsigned int offsetA = 2 * (sizeY + 2 * sizeUV + my * MBheightY * widthY);
1220
1221 uint16_t *sp = (uint16_t*)con->buf;
1222
1223 seek_file(con, offsetY, SEEK_SET);
1224 memset(sp, 0, 2 * widthY * MBheightY);
1225 read_data(con, sp, 2, widthY * MBheightY);
1226 sp += widthY * MBheightY;
1227
1228 seek_file(con, offsetU, SEEK_SET);
1229 memset(sp, 0, 2 * widthUV * MBheightUV);
1230 read_data(con, sp, 2, widthUV * MBheightUV);
1231 sp += widthUV * MBheightUV;
1232
1233 seek_file(con, offsetV, SEEK_SET);
1234 memset(sp, 0, 2 * widthUV * MBheightUV);
1235 read_data(con, sp, 2, widthUV * MBheightUV);
1236 sp += widthUV * MBheightUV;
1237
1238 if (con->ncomp == 4) {
1239 seek_file(con, offsetA, SEEK_SET);
1240 memset(sp, 0, 2 * widthY * MBheightY);
1241 read_data(con, sp, 2, widthY * MBheightY);
1242 sp += widthY * MBheightY;
1243 }
1244 }
1245 con->my = my;
1246 }
1247
1248 int idx1, idx2;
1249 int xDiv = 16;
1250 int yDiv = 16;
1251
1252 if (con->bpi == 8) {
1253 /* Y */
1254 uint8_t *sp = (uint8_t*)con->buf + xDiv*mx;
1255 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1256 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1257 data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
1258 sp += widthY;
1259 }
1260
1261 if (con->ycc_format == 2)
1262 xDiv = 8;
1263
1264 if (con->ycc_format == 1)
1265 xDiv = yDiv = 8;
1266
1267 /* U */
1268 sp = (uint8_t*)con->buf + widthY * MBheightY + xDiv*mx;
1269 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1270 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1271 data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
1272 sp += widthUV;
1273 }
1274
1275 /* V */
1276 sp = (uint8_t*)con->buf + widthY * MBheightY + widthUV * MBheightUV + xDiv*mx;
1277 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1278 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1279 data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
1280 sp += widthUV;
1281 }
1282
1283 if(con->ncomp == 4)
1284 {
1285 xDiv = yDiv = 16;
1286 sp = (uint8_t*)con->buf + widthY * MBheightY + 2 * widthUV * MBheightUV + xDiv*mx;
1287 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1288 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1289 data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
1290 sp += widthY;
1291 }
1292 }
1293 }
1294 else if (con->bpi == 16 || con->bpi == 10) {
1295 if (con->sf == 1) {
1296 /* Y */
1297 uint16_t *sp = (uint16_t*)con->buf + xDiv*mx;
1298 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1299 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1300 data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
1301 sp += widthY;
1302 }
1303
1304 if (con->ycc_format == 2)
1305 xDiv = 8;
1306
1307 if (con->ycc_format == 1)
1308 xDiv = yDiv = 8;
1309
1310 /* U */
1311 sp = (uint16_t*)con->buf + widthY * MBheightY + xDiv*mx;
1312 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1313 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1314 data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
1315 sp += widthUV;
1316 }
1317
1318 /* V */
1319 sp = (uint16_t*)con->buf + widthY * MBheightY + widthUV * MBheightUV + xDiv*mx;
1320 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1321 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1322 data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
1323 sp += widthUV;
1324 }
1325
1326 if(con->ncomp == 4)
1327 {
1328 xDiv = yDiv = 16;
1329 sp = (uint16_t*)con->buf + widthY * MBheightY + 2 * widthUV * MBheightUV + xDiv*mx;
1330 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1331 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1332 data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
1333 sp += widthY;
1334 }
1335 }
1336 }
1337 else if (con->sf == 2) {
1338 /* Y */
1339 short *sp = (short*)con->buf + xDiv*mx;
1340 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1341 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1342 data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
1343 sp += widthY;
1344 }
1345
1346 if (con->ycc_format == 2)
1347 xDiv = 8;
1348
1349 if (con->ycc_format == 1)
1350 xDiv = yDiv = 8;
1351
1352 /* U */
1353 sp = (short*)con->buf + widthY * MBheightY + xDiv*mx;
1354 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1355 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1356 data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
1357 sp += widthUV;
1358 }
1359
1360 /* V */
1361 sp = (short*)con->buf + widthY * MBheightY + widthUV * MBheightUV + xDiv*mx;
1362 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1363 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1364 data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
1365 sp += widthUV;
1366 }
1367
1368 if(con->ncomp == 4)
1369 {
1370 xDiv = yDiv = 16;
1371 sp = (short*)con->buf + widthY * MBheightY + 2 * widthUV * MBheightUV + xDiv*mx;
1372 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1373 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1374 data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
1375 sp += widthY;
1376 }
1377 }
1378 }
1379 }
1380 }
1381
read_file_CMYK(jxr_image_t image,int mx,int my,int * data)1382 void read_file_CMYK(jxr_image_t image, int mx, int my, int *data) {
1383 /* There are 4 or 5 buffers, depending on whether there is an alpha channel or not */
1384 context *con = (context*) jxr_get_user_data(image);
1385 int num_channels = con->ncomp;
1386
1387 unsigned int width = con->wid, height = con->hei;
1388 unsigned int MBheight = 16;
1389 unsigned int size = width * height;
1390
1391 if (my != con->my) {
1392 if (con->bpi == 8) {
1393 unsigned int offsetC = my * MBheight * width + 0 * size;
1394 unsigned int offsetM = my * MBheight * width + 1 * size;
1395 unsigned int offsetY = my * MBheight * width + 2 * size;
1396 unsigned int offsetK = my * MBheight * width + 3 * size;
1397 unsigned int offsetA = my * MBheight * width + 4 * size;
1398
1399 uint8_t *sp = (uint8_t*)con->buf;
1400
1401 seek_file(con, offsetC, SEEK_SET);
1402 memset(sp, 0, width * MBheight);
1403 read_data(con, sp, 1, width * MBheight);
1404 sp += width * MBheight;
1405
1406 seek_file(con, offsetM, SEEK_SET);
1407 memset(sp, 0, width * MBheight);
1408 read_data(con, sp, 1, width * MBheight);
1409 sp += width * MBheight;
1410
1411 seek_file(con, offsetY, SEEK_SET);
1412 memset(sp, 0, width * MBheight);
1413 read_data(con, sp, 1, width * MBheight);
1414 sp += width * MBheight;
1415
1416 seek_file(con, offsetK, SEEK_SET);
1417 memset(sp, 0, width * MBheight);
1418 read_data(con, sp, 1, width * MBheight);
1419 sp += width * MBheight;
1420
1421 if (con->ncomp == 5) {
1422 seek_file(con, offsetA, SEEK_SET);
1423 memset(sp, 0, width * MBheight);
1424 read_data(con, sp, 1, width * MBheight);
1425 sp += width * MBheight;
1426 }
1427 }
1428 else if (con->bpi == 16) {
1429 unsigned int offsetC = 2 * (my * MBheight * width + 0 * size);
1430 unsigned int offsetM = 2 * (my * MBheight * width + 1 * size);
1431 unsigned int offsetY = 2 * (my * MBheight * width + 2 * size);
1432 unsigned int offsetK = 2 * (my * MBheight * width + 3 * size);
1433 unsigned int offsetA = 2 * (my * MBheight * width + 4 * size);
1434
1435 uint16_t *sp = (uint16_t*)con->buf;
1436
1437 seek_file(con, offsetC, SEEK_SET);
1438 memset(sp, 0, 2 * width * MBheight);
1439 read_data(con, sp, 2, width * MBheight);
1440 sp += width * MBheight;
1441
1442 seek_file(con, offsetM, SEEK_SET);
1443 memset(sp, 0, 2 * width * MBheight);
1444 read_data(con, sp, 2, width * MBheight);
1445 sp += width * MBheight;
1446
1447 seek_file(con, offsetY, SEEK_SET);
1448 memset(sp, 0, 2 * width * MBheight);
1449 read_data(con, sp, 2, width * MBheight);
1450 sp += width * MBheight;
1451
1452 seek_file(con, offsetK, SEEK_SET);
1453 memset(sp, 0, 2 * width * MBheight);
1454 read_data(con, sp, 2, width * MBheight);
1455 sp += width * MBheight;
1456
1457 if (con->ncomp == 5) {
1458 seek_file(con, offsetA, SEEK_SET);
1459 memset(sp, 0, 2 * width * MBheight);
1460 read_data(con, sp, 2, width * MBheight);
1461 sp += width * MBheight;
1462 }
1463 }
1464 con->my = my;
1465 }
1466
1467 int idx1, idx2;
1468 int xDiv = 16;
1469 int yDiv = 16;
1470
1471 if (con->bpi == 8) {
1472 /* C */
1473 uint8_t *sp = (uint8_t*)con->buf + xDiv*mx + 0 * width * MBheight;
1474 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1475 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1476 data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
1477 sp += width;
1478 }
1479
1480 /* M */
1481 sp = (uint8_t*)con->buf + xDiv*mx + 1 * width * MBheight;
1482 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1483 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1484 data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
1485 sp += width;
1486 }
1487
1488 /* Y */
1489 sp = (uint8_t*)con->buf + xDiv*mx + 2 * width * MBheight;
1490 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1491 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1492 data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
1493 sp += width;
1494 }
1495
1496 /* K */
1497 sp = (uint8_t*)con->buf + xDiv*mx + 3 * width * MBheight;
1498 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1499 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1500 data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
1501 sp += width;
1502 }
1503
1504 if(con->ncomp == 5)
1505 {
1506 sp = (uint8_t*)con->buf + xDiv*mx + 4 * width * MBheight;
1507 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1508 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1509 data[(idx1 * xDiv + idx2) * num_channels + 4] = sp[idx2];
1510 sp += width;
1511 }
1512 }
1513 }
1514 else if (con->bpi == 16) {
1515 /* C */
1516 uint16_t *sp = (uint16_t*)con->buf + xDiv*mx + 0 * width * MBheight;
1517 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1518 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1519 data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
1520 sp += width;
1521 }
1522
1523 /* M */
1524 sp = (uint16_t*)con->buf + xDiv*mx + 1 * width * MBheight;
1525 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1526 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1527 data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
1528 sp += width;
1529 }
1530
1531 /* Y */
1532 sp = (uint16_t*)con->buf + xDiv*mx + 2 * width * MBheight;
1533 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1534 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1535 data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
1536 sp += width;
1537 }
1538
1539 /* K */
1540 sp = (uint16_t*)con->buf + xDiv*mx + 3 * width * MBheight;
1541 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1542 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1543 data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
1544 sp += width;
1545 }
1546
1547 if(con->ncomp == 5)
1548 {
1549 sp = (uint16_t*)con->buf + xDiv*mx + 4 * width * MBheight;
1550 for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
1551 for (idx2 = 0; idx2 < xDiv; idx2 += 1)
1552 data[(idx1 * xDiv + idx2) * num_channels + 4] = sp[idx2];
1553 sp += width;
1554 }
1555 }
1556 }
1557 }
1558
1559
read_file(jxr_image_t image,int mx,int my,int * data)1560 void read_file(jxr_image_t image, int mx, int my, int *data)
1561 {
1562 context *con = (context*) jxr_get_user_data(image);
1563 unsigned char uExternalNcomp = con->ncomp + con->padBytes;
1564 int block_wid = uExternalNcomp * ((con->wid+15)&~15);
1565
1566 if((isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image)) && jxr_get_IMAGE_CHANNELS(image) == 3)
1567 {
1568 /* Use special YCC format only for primary image */
1569 read_file_YCC(image, mx, my, data);
1570 return;
1571 }
1572 else if(isOutputCMYKDirect(image) && jxr_get_IMAGE_CHANNELS(image) == 4)
1573 {
1574 /* Use special YCC format only for primary image */
1575 read_file_CMYK(image, mx, my, data);
1576 return;
1577 }
1578
1579 if(con->ncomp == 3 || con->ncomp == 4)
1580 {
1581 set_bgr_flag(con, image);
1582 }
1583 else
1584 {
1585 con->isBgr = 0;
1586 }
1587
1588 if (my != con->my) {
1589 int trans = (my*16 + 16 > con->hei) ? con->hei%16 : 16;
1590 int line_wid = uExternalNcomp * con->wid;
1591 int idx;
1592 if (con->bpi == 1) {
1593 uint8_t *sp = (uint8_t*)con->buf;
1594 line_wid = ((line_wid + 7) >> 3);
1595 block_wid >>= 3;
1596 for (idx = 0; idx < trans; idx += 1) {
1597 read_setup(con);
1598 read_uint8(con, sp, line_wid);
1599 sp += block_wid;
1600 }
1601 }
1602 else if ((con->bpi == 5) || (con->bpi == 6)) {
1603 uint16_t *sp = (uint16_t*)con->buf;
1604 block_wid = ((con->wid+15)&~15);
1605 for (idx = 0; idx < trans; idx += 1) {
1606 read_setup(con);
1607 read_uint16(con, sp, con->wid);
1608 sp += block_wid;
1609 }
1610 }
1611 else if (con->bpi == 8) {
1612 uint8_t *sp = (uint8_t*)con->buf;
1613 for (idx = 0; idx < trans; idx += 1) {
1614 read_setup(con);
1615 read_uint8(con, sp, line_wid);
1616 if(con->isBgr)
1617 {
1618 int i;
1619 for(i = 0; i < con->wid; i ++)
1620 {
1621 int tmp = sp[i*(uExternalNcomp)] ;
1622 sp[i*(uExternalNcomp)] = sp[i*(uExternalNcomp)+ 2];
1623 sp[i*(uExternalNcomp)+ 2] = tmp;
1624 }
1625 }
1626 sp += block_wid;
1627 }
1628 }
1629 else if (con->bpi == 10) {
1630 uint32_t *sp = (uint32_t*)con->buf;
1631 block_wid = ((con->wid+15)&~15);
1632 for (idx = 0; idx < trans; idx += 1) {
1633 read_setup(con);
1634 read_uint32(con, sp, con->wid);
1635 sp += block_wid;
1636 }
1637 }
1638 else if (con->bpi == 16) {
1639 if (con->sf == 1) { /* UINT */
1640 uint16_t *sp = (uint16_t*)con->buf;
1641 for (idx = 0; idx < trans; idx += 1) {
1642 read_setup(con);
1643 read_uint16(con, sp, line_wid);
1644 sp += block_wid;
1645 }
1646 }
1647 else if (con->sf == 2) { /* fixed point */
1648 short *sp = (short*)con->buf;
1649 for (idx = 0; idx < trans; idx += 1) {
1650 read_setup(con);
1651 read_uint16(con, (uint16_t *)sp, line_wid);
1652 sp += block_wid;
1653 }
1654 }
1655 else if (con->sf == 3) { /* Half float */
1656 short *sp = (short*)con->buf;
1657 for (idx = 0; idx < trans; idx += 1) {
1658 read_setup(con);
1659 read_uint16(con, (uint16_t *)sp, line_wid);
1660 sp += block_wid;
1661 }
1662 }
1663 }
1664 else if (con->bpi == 32) {
1665 if (con->sf == 2) { /* fixed point */
1666 uint32_t *sp = (uint32_t*)con->buf;
1667 for (idx = 0; idx < trans; idx += 1) {
1668 read_setup(con);
1669 read_uint32(con, sp, line_wid);
1670 sp += block_wid;
1671 }
1672 }
1673 else if (con->sf == 3) { /* float */
1674 uint32_t *sp = (uint32_t*)con->buf;
1675 for (idx = 0; idx < trans; idx += 1) {
1676 read_setup(con);
1677 read_uint32(con, sp, line_wid);
1678 sp += block_wid;
1679 }
1680 }
1681 }
1682 con->my = my;
1683 }
1684
1685 int xdx, ydx, sxdx;
1686 if (con->bpi == 1) {
1687 block_wid = (((con->wid+15)&~15) >> 3);
1688 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1689 if (con->sf == 1) {
1690 uint8_t *sp = (uint8_t*)con->buf + ydx*block_wid + ((con->ncomp*16*mx) >> 3);
1691 int *dp = data + con->ncomp*16*ydx;
1692 if (!con->photometric) {
1693 for (xdx = 0 ; xdx < con->ncomp*16 ; xdx++)
1694 dp[xdx] = ((sp[xdx >> 3] >> (7 - (xdx & 7))) & 1);
1695 }
1696 else {
1697 for (xdx = 0 ; xdx < con->ncomp*16 ; xdx++)
1698 dp[xdx] = (((~sp[xdx >> 3]) >> (7 - (xdx & 7))) & 1);
1699 }
1700 }
1701 }
1702 }
1703 else if (con->bpi == 5) {
1704 block_wid = ((con->wid+15)&~15);
1705 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1706 uint16_t *sp = (uint16_t*)con->buf + ydx*block_wid + 16*mx;
1707 int *dp = data + uExternalNcomp*16*ydx;
1708 for (xdx = 0, sxdx = 0; xdx < uExternalNcomp*16 ; xdx += uExternalNcomp, sxdx++) {
1709 dp[xdx] = (sp[sxdx] & 0x1f);
1710 dp[xdx + 1] = ((sp[sxdx] >> 5) & 0x1f);
1711 dp[xdx + 2] = ((sp[sxdx] >> 10) & 0x1f);
1712 }
1713 }
1714 }
1715 else if (con->bpi == 6) {
1716 block_wid = ((con->wid+15)&~15);
1717 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1718 uint16_t *sp = (uint16_t*)con->buf + ydx*block_wid + 16*mx;
1719 int *dp = data + uExternalNcomp*16*ydx;
1720 for (xdx = 0, sxdx = 0; xdx < uExternalNcomp*16 ; xdx += uExternalNcomp, sxdx++) {
1721 dp[xdx] = ((sp[sxdx] & 0x1f) << 1);
1722 dp[xdx + 1] = ((sp[sxdx] >> 5) & 0x3f);
1723 dp[xdx + 2] = (((sp[sxdx] >> 11) & 0x1f) << 1);
1724 }
1725 }
1726 }
1727 else if (con->bpi == 8) {
1728 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1729 if (con->sf == 1) { /* UINT */
1730 uint8_t *sp = (uint8_t*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
1731 int *dp = data + con->ncomp*16*ydx;
1732 int iCh;
1733 for (xdx = 0 ; xdx < 16 ; xdx++) {
1734 for (iCh = 0; iCh < con->ncomp; iCh ++){
1735 dp[iCh] = (sp[iCh] >> image->shift_bits);
1736 }
1737 dp += con->ncomp;
1738 sp += uExternalNcomp;
1739 }
1740 }
1741 else if (con->sf == 4){ /* RGBE */
1742 uint8_t *sp = (uint8_t*)con->buf + ydx*block_wid + con->ncomp*16*mx; /* external ncomp is 4, internal is 3 */
1743 int *dp = data + 3*16*ydx;
1744 for (xdx = 0, sxdx = 0 ; xdx < 3*16 ; xdx += 3, sxdx +=4) {
1745 dp[xdx] = forwardRGBE((int)sp[sxdx], (int)sp[sxdx + 3]);
1746 dp[xdx + 1] = forwardRGBE((int)sp[sxdx + 1], (int)sp[sxdx + 3]);
1747 dp[xdx + 2] = forwardRGBE((int)sp[sxdx + 2], (int)sp[sxdx + 3]);
1748 }
1749 }
1750 }
1751 }
1752 else if (con->bpi == 10) {
1753 block_wid = ((con->wid+15)&~15);
1754 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1755 uint32_t *sp = (uint32_t*)con->buf + ydx*block_wid + 16*mx;
1756 int *dp = data + uExternalNcomp*16*ydx;
1757 for (xdx = 0, sxdx = 0; xdx < uExternalNcomp*16 ; xdx += uExternalNcomp, sxdx++) {
1758 dp[xdx] = (sp[sxdx] & 0x3ff);
1759 dp[xdx + 1] = ((sp[sxdx] >> 10) & 0x3ff);
1760 dp[xdx + 2] = ((sp[sxdx] >> 20) & 0x3ff);
1761 }
1762 }
1763 }
1764 else if (con->bpi == 16) {
1765 if (con->sf == 1) { /* UINT */
1766 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1767 uint16_t *sp = (uint16_t*)con->buf + ydx*block_wid + con->ncomp*16*mx;
1768 int *dp = data + con->ncomp*16*ydx;
1769 for (xdx = 0 ; xdx < con->ncomp*16 ; xdx++)
1770 dp[xdx] = (sp[xdx] >> image->shift_bits);
1771 }
1772 }
1773 else if (con->sf == 2) { /* fixed point */
1774 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1775 short *sp = (short*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
1776 int *dp = data + con->ncomp*16*ydx;
1777 int iCh;
1778 for (xdx = 0 ; xdx < 16 ; xdx++) {
1779 for (iCh = 0; iCh < con->ncomp; iCh ++){
1780 dp[iCh] = (sp[iCh] >> image->shift_bits);
1781 }
1782 dp += con->ncomp;
1783 sp += uExternalNcomp;
1784 }
1785 }
1786 }
1787 else if (con->sf == 3) { /* Half float */
1788 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1789 short *sp = (short*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
1790 int *dp = data + con->ncomp*16*ydx;
1791 int iCh;
1792 for (xdx = 0 ; xdx < 16 ; xdx++) {
1793 for (iCh = 0; iCh < con->ncomp; iCh ++) {
1794 dp[iCh] = PreScalingBD16F((int)sp[iCh]);
1795 }
1796 dp += con->ncomp;
1797 sp += uExternalNcomp;
1798 }
1799 }
1800 }
1801 }
1802 else if (con->bpi == 32) {
1803 /* no 32-UINT */
1804 if (con->sf == 2) { /* fixed point */
1805 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1806 int32_t *sp = (int32_t*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
1807 int *dp = data + con->ncomp*16*ydx;
1808 int iCh;
1809 for (xdx = 0 ; xdx < 16 ; xdx++) {
1810 for (iCh = 0; iCh < con->ncomp; iCh ++) {
1811 dp[iCh] = (sp[iCh] >> image->shift_bits);
1812 }
1813 dp += con->ncomp;
1814 sp += uExternalNcomp;
1815 }
1816 }
1817 }
1818 else if (con->sf == 3) { /* float */
1819 for (ydx = 0 ; ydx < 16 ; ydx += 1) {
1820 int *sp = (int*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
1821 int *dp = data + con->ncomp*16*ydx;
1822 int iCh;
1823 for (xdx = 0 ; xdx < 16 ; xdx++) {
1824 for (iCh = 0; iCh < con->ncomp; iCh ++) {
1825 dp[iCh] = PreScalingBD32F(sp[iCh], image->exp_bias, image->len_mantissa);
1826 }
1827 dp += con->ncomp;
1828 sp += uExternalNcomp;
1829 }
1830 }
1831 }
1832 }
1833 }
1834
write_file_YCC(jxr_image_t image,int mx,int my,int * data)1835 void write_file_YCC(jxr_image_t image, int mx, int my, int* data)
1836 {
1837 /* There are 3 or 4 buffers, depending on whether there is an alpha channel or not */
1838 /* Write each individual component to its own file and then concatenate(not interleave these files together */
1839
1840 int *dataY = data;
1841 int *dataU = dataY + 256;
1842 int *dataV = dataU + 256;
1843 int *dataA = dataV + 256;
1844 static context *conY = NULL;
1845 static context *conU = NULL;
1846 static context *conV = NULL;
1847 static context *conA = NULL;
1848 context *con = (context*) jxr_get_user_data(image);
1849
1850
1851 if (con->file==0)
1852 {
1853 con->alpha = jxr_get_ALPHACHANNEL_FLAG(image);
1854
1855 conY = (context *)malloc(sizeof(context));
1856 conU = (context *)malloc(sizeof(context));
1857 conV = (context *)malloc(sizeof(context));
1858 if(con->alpha)
1859 conA = (context *)malloc(sizeof(context));
1860 memcpy(conY, con, sizeof(context));
1861 memcpy(conU, con, sizeof(context));
1862 memcpy(conV, con, sizeof(context));
1863 if(con->alpha)
1864 memcpy(conA, con, sizeof(context));
1865 conY->name = "Y.raw";
1866 conU->name = "U.raw";
1867 conV->name = "V.raw";
1868 if(con->alpha)
1869 conA->name = "A.raw";
1870
1871 con->left_pad = image->window_extra_left;
1872 con->top_pad_remaining = image->window_extra_top;
1873 con->top_pad = image->window_extra_top;
1874
1875 con->ncomp = conY->ncomp = conU->ncomp = conV->ncomp =1;
1876 if(con->alpha)
1877 conA->ncomp = 1;
1878 start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
1879 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
1880 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
1881 start_output_file(conY, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
1882 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
1883 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
1884 start_output_file(conU, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
1885 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
1886 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
1887 start_output_file(conV, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
1888 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
1889 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
1890 if(con->alpha)
1891 start_output_file(conA, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
1892 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
1893 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
1894
1895 }
1896
1897 int idx;
1898 int strip_blocks = (image->extended_width)/16;
1899 int dy = 16*strip_blocks;
1900
1901 if (con->bpi == 8) {
1902
1903 int xDiv = 16;
1904 int yDiv = 16;
1905 /* Y */
1906 uint8_t *dp = (uint8_t*)conY->buf + xDiv*mx;
1907 for (idx = 0; idx < xDiv*yDiv; idx += 1) {
1908 int dix = (idx/xDiv)*dy + (idx%xDiv);
1909 dp[dix] = dataY[idx];
1910 }
1911
1912 if(isOutputYUV422(image))
1913 {
1914 dy = 8*strip_blocks;
1915 xDiv = 8;
1916 }
1917
1918 if(isOutputYUV420(image))
1919 {
1920 dy = 8*strip_blocks;
1921 xDiv = yDiv = 8;
1922 }
1923
1924 /* U */
1925 dp = (uint8_t*)conU->buf + xDiv*mx;
1926 for (idx = 0; idx < xDiv*yDiv; idx += 1) {
1927 int dix = (idx/xDiv)*dy + (idx%xDiv);
1928 dp[dix] = dataU[idx];
1929 }
1930 /* V */
1931 dp = (uint8_t*)conV->buf + xDiv*mx;
1932 for (idx = 0; idx < xDiv*yDiv; idx += 1) {
1933 int dix = (idx/xDiv)*dy + (idx%xDiv);
1934 dp[dix] = dataV[idx];
1935 }
1936
1937 if(con->alpha)
1938 {
1939 xDiv = yDiv = 16;
1940 dy = 16*strip_blocks;
1941 dp = (uint8_t*)conA->buf + xDiv*mx;
1942 for (idx = 0; idx < xDiv*yDiv; idx += 1) {
1943 int dix = (idx/xDiv)*dy + (idx%xDiv);
1944 dp[dix] = dataA[idx];
1945 }
1946 }
1947
1948 }
1949 else if(con->bpi == 16 || con->bpi == 10) {
1950
1951 int xDiv = 16;
1952 int yDiv = 16;
1953 /* Y */
1954 uint16_t *dp = (uint16_t*)conY->buf + xDiv*mx;
1955 for (idx = 0; idx < xDiv*yDiv; idx += 1) {
1956 int dix = (idx/xDiv)*dy + (idx%xDiv);
1957 dp[dix] = dataY[idx];
1958 }
1959
1960 if(isOutputYUV422(image))
1961 {
1962 dy = 8*strip_blocks;
1963 xDiv = 8;
1964 }
1965
1966 if(isOutputYUV420(image))
1967 {
1968 assert(!"There is no 420 pixel format with bitdepth 16\n");
1969 dy = 8*strip_blocks;
1970 xDiv = yDiv = 8;
1971 }
1972
1973 /* U */
1974 dp = (uint16_t*)conU->buf + xDiv*mx;
1975 for (idx = 0; idx < xDiv*yDiv; idx += 1) {
1976 int dix = (idx/xDiv)*dy + (idx%xDiv);
1977 dp[dix] = dataU[idx];
1978 }
1979 /* V */
1980 dp = (uint16_t*)conV->buf + xDiv*mx;
1981 for (idx = 0; idx < xDiv*yDiv; idx += 1) {
1982 int dix = (idx/xDiv)*dy + (idx%xDiv);
1983 dp[dix] = dataV[idx];
1984 }
1985
1986 if(con->alpha)
1987 {
1988 xDiv = yDiv = 16;
1989 dy = 16*strip_blocks;
1990 dp = (uint16_t*)conA->buf + xDiv*mx;
1991 for (idx = 0; idx < xDiv*yDiv; idx += 1) {
1992 int dix = (idx/xDiv)*dy + (idx%xDiv);
1993 dp[dix] = dataA[idx];
1994 }
1995 }
1996
1997 }
1998 else
1999 {
2000 assert(!"Unsupported bitdepth\n");
2001 }
2002
2003 if (mx+1 == strip_blocks) {
2004
2005 int xDiv = 16;
2006 int yDiv = 16;
2007 int subX = 1;
2008 int subY = 1;
2009
2010 if(con->bpi == 8)
2011 {
2012 /* Y */
2013 int left_pad_shift = con->left_pad;
2014 int first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining;
2015 int trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%yDiv : yDiv;
2016 dy = 16*strip_blocks;
2017 for (idx = first; idx < trans; idx += 1) {
2018 uint8_t *dp = (uint8_t*)conY->buf + idx*dy + con->left_pad;
2019 write_uint8(conY, dp, conY->wid );
2020 }
2021 /* U */
2022 if(isOutputYUV422(image))
2023 {
2024 dy = 8*strip_blocks;
2025 xDiv = 8;
2026 subX = 2;
2027 left_pad_shift >>= 1;
2028 }
2029
2030 if(isOutputYUV420(image))
2031 {
2032 dy = 8*strip_blocks;
2033 xDiv = yDiv = 8;
2034 subX = subY = 2;
2035 left_pad_shift >>= 1;
2036 }
2037 first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining/subY;
2038 trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? ((con->hei + con->top_pad)/subY)%yDiv : yDiv;
2039 for (idx = first; idx < trans; idx += 1) {
2040 uint8_t *dp = (uint8_t*)conU->buf + idx*dy + left_pad_shift;
2041 write_uint8(conU, dp, (conU->wid)/subX );
2042 }
2043 /* V */
2044 trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? ((con->hei + con->top_pad)/subY)%yDiv : yDiv;
2045 for (idx = first; idx < trans; idx += 1) {
2046 uint8_t *dp = (uint8_t*)conV->buf + idx*dy + left_pad_shift;
2047 write_uint8(conV, dp, (conV->wid)/subX );
2048 }
2049 /* A */
2050 if(con->alpha)
2051 {
2052 dy = 16*strip_blocks;
2053 xDiv = yDiv = 16;
2054 first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining;
2055 trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%yDiv : yDiv;
2056 for (idx = first; idx < trans; idx += 1) {
2057 uint8_t *dp = (uint8_t*)conA->buf + idx*dy + con->left_pad;
2058 write_uint8(conA, dp, conA->wid);
2059 }
2060 }
2061 first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
2062 con->top_pad_remaining -= first;
2063 }
2064 else if(con->bpi == 16 || con->bpi == 10)
2065 {
2066 /* Y */
2067 int left_pad_shift = con->left_pad;
2068 int first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining;
2069 int trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%yDiv : yDiv;
2070 dy = 16*strip_blocks;
2071 for (idx = first; idx < trans; idx += 1) {
2072 uint16_t *dp = (uint16_t*)conY->buf + idx*dy + con->left_pad;
2073 write_uint16(conY, dp, conY->wid );
2074 }
2075 /* U */
2076 if(isOutputYUV422(image))
2077 {
2078 dy = 8*strip_blocks;
2079 xDiv = 8;
2080 subX = 2;
2081 left_pad_shift >>= 1;
2082 }
2083
2084 if(isOutputYUV420(image))
2085 {
2086 dy = 8*strip_blocks;
2087 xDiv = yDiv = 8;
2088 subX = subY = 2;
2089 left_pad_shift >>= 1;
2090 }
2091 first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining/subY;
2092 trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? ((con->hei + con->top_pad)/subY)%yDiv : yDiv;
2093 for (idx = first; idx < trans; idx += 1) {
2094 uint16_t *dp = (uint16_t*)conU->buf + idx*dy + left_pad_shift;
2095 write_uint16(conU, dp, (conU->wid)/subX );
2096 }
2097 /* V */
2098 first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining/subY;
2099 trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? ((con->hei + con->top_pad)/subY)%yDiv : yDiv;
2100 for (idx = first; idx < trans; idx += 1) {
2101 uint16_t *dp = (uint16_t*)conV->buf + idx*dy + left_pad_shift;
2102 write_uint16(conV, dp, (conV->wid)/subX );
2103 }
2104 /* A */
2105 if(con->alpha)
2106 {
2107 dy = 16*strip_blocks;
2108 xDiv = yDiv = 16;
2109 first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining;
2110 trans = (my*yDiv + yDiv >(con->hei + con->top_pad)) ? (con->hei + con->top_pad)%yDiv : yDiv;
2111 for (idx = first; idx < trans; idx += 1) {
2112 uint16_t *dp = (uint16_t*)conA->buf + idx*dy + con->left_pad;
2113 write_uint16(conA, dp, conA->wid);
2114 }
2115 }
2116 first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
2117 con->top_pad_remaining -= first;
2118 }
2119 else
2120 assert(!"Unsupported bitdepth\n");
2121 }
2122 if(my*16 + 16 >= (con->hei + con->top_pad) && mx+1 == strip_blocks)
2123 {
2124 /* End of decode */
2125 long size = ftell(conY->file);
2126 fseek(conY->file, 0, 0);
2127 long ii;
2128 for(ii = 0; ii < size; ii++)
2129 {
2130 uint8_t val;
2131 fread(&val, 1, 1, conY->file);
2132 fwrite(&val, 1, 1, con->file);
2133 }
2134 size = ftell(conU->file);
2135 fseek(conU->file, 0, 0);
2136 for( ii = 0; ii < size; ii++)
2137 {
2138 uint8_t val;
2139 fread(&val, 1, 1, conU->file);
2140 fwrite(&val, 1, 1, con->file);
2141 }
2142 size = ftell(conV->file);
2143 fseek(conV->file, 0, 0);
2144 for( ii = 0; ii < size; ii++)
2145 {
2146 uint8_t val;
2147 fread(&val, 1, 1, conV->file);
2148 fwrite(&val, 1, 1, con->file);
2149 }
2150 if(con->alpha)
2151 {
2152 size = ftell(conA->file);
2153 fseek(conA->file, 0, 0);
2154 for( ii = 0; ii < size && con->alpha; ii++)
2155 {
2156 uint8_t val;
2157 fread(&val, 1, 1, conA->file);
2158 fwrite(&val, 1, 1, con->file);
2159 }
2160 }
2161 fclose(conY->file);
2162 fclose(conU->file);
2163 fclose(conV->file);
2164 if(con->alpha)
2165 fclose(conA->file);
2166
2167 free(conY->buf);
2168 free(conU->buf);
2169 free(conV->buf);
2170 if(con->alpha)
2171 free(conA->buf);
2172
2173 free(conY);
2174 free(conU);
2175 free(conV);
2176 if(con->alpha)
2177 free(conA);
2178
2179 remove("Y.raw");
2180 remove("U.raw");
2181 remove("V.raw");
2182 if(con->alpha)
2183 remove("A.raw");
2184
2185 }
2186 }
2187
write_file_CMYK(jxr_image_t image,int mx,int my,int * data)2188 void write_file_CMYK(jxr_image_t image, int mx, int my, int* data)
2189 {
2190 /* There are 4 or 5 buffers, depending on whether there is an alpha channel or not */
2191 /* Write each individual component to its own file and then concatenate(not interleave these files together */
2192
2193 int *dataC = data;
2194 int *dataM = dataC + 256;
2195 int *dataY = dataM + 256;
2196 int *dataK = dataY + 256;
2197 int *dataA = dataK + 256;
2198 static context *conC = NULL;
2199 static context *conM = NULL;
2200 static context *conY = NULL;
2201 static context *conK = NULL;
2202 static context *conA = NULL;
2203 context *con = (context*) jxr_get_user_data(image);
2204 if (con->file==0)
2205 {
2206 con->alpha = jxr_get_ALPHACHANNEL_FLAG(image);
2207
2208 conC = (context *)malloc(sizeof(context));
2209 conM = (context *)malloc(sizeof(context));
2210 conY = (context *)malloc(sizeof(context));
2211 conK = (context *)malloc(sizeof(context));
2212 if(con->alpha)
2213 conA = (context *)malloc(sizeof(context));
2214 memcpy(conC, con, sizeof(context));
2215 memcpy(conM, con, sizeof(context));
2216 memcpy(conY, con, sizeof(context));
2217 memcpy(conK, con, sizeof(context));
2218 if(con->alpha)
2219 memcpy(conA, con, sizeof(context));
2220 conC->name = "C.raw";
2221 conM->name = "M.raw";
2222 conY->name = "Y.raw";
2223 conK->name = "K.raw";
2224 if(con->alpha)
2225 conA->name = "A.raw";
2226
2227 con->left_pad = image->window_extra_left;
2228 con->top_pad_remaining = image->window_extra_top;
2229 con->top_pad = image->window_extra_top;
2230
2231 con->ncomp = conC->ncomp = conM->ncomp = conY->ncomp = conK->ncomp = 1;
2232 if(con->alpha)
2233 conA->ncomp = 1;
2234 start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2235 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2236 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
2237 start_output_file(conC, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2238 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2239 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
2240 start_output_file(conM, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2241 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2242 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
2243 start_output_file(conY, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2244 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2245 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
2246 start_output_file(conK, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2247 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2248 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
2249
2250 if(con->alpha)
2251 start_output_file(conA, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2252 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2253 1 , jxr_get_OUTPUT_BITDEPTH(image),jxr_get_pixel_format(image));
2254
2255 }
2256
2257 int idx;
2258 int strip_blocks = (image->extended_width)/16;
2259 int dy = 16*strip_blocks;
2260
2261 if (con->bpi == 8) {
2262
2263 /* C */
2264 uint8_t *dp = (uint8_t*)conC->buf + 16*mx;
2265 for (idx = 0; idx < 256; idx += 1) {
2266 int dix = (idx/16)*dy + (idx%16);
2267 dp[dix] = dataC[idx];
2268 }
2269
2270 /* M */
2271 dp = (uint8_t*)conM->buf + 16*mx;
2272 for (idx = 0; idx < 256; idx += 1) {
2273 int dix = (idx/16)*dy + (idx%16);
2274 dp[dix] = dataM[idx];
2275 }
2276 /* Y */
2277 dp = (uint8_t*)conY->buf + 16*mx;
2278 for (idx = 0; idx < 256; idx += 1) {
2279 int dix = (idx/16)*dy + (idx%16);
2280 dp[dix] = dataY[idx];
2281 }
2282 /* K */
2283 dp = (uint8_t*)conK->buf + 16*mx;
2284 for (idx = 0; idx < 256; idx += 1) {
2285 int dix = (idx/16)*dy + (idx%16);
2286 dp[dix] = dataK[idx];
2287 }
2288
2289
2290 if(con->alpha)
2291 {
2292 dp = (uint8_t*)conA->buf + 16*mx;
2293 for (idx = 0; idx < 256; idx += 1) {
2294 int dix = (idx/16)*dy + (idx%16);
2295 dp[dix] = dataA[idx];
2296 }
2297 }
2298
2299 }
2300 else if(con->bpi == 16 || con->bpi == 10) {
2301
2302 /* C */
2303 uint16_t *dp = (uint16_t*)conC->buf + 16*mx;
2304 for (idx = 0; idx < 256; idx += 1) {
2305 int dix = (idx/16)*dy + (idx%16);
2306 dp[dix] = dataC[idx];
2307 }
2308
2309 /* M */
2310 dp = (uint16_t*)conM->buf + 16*mx;
2311 for (idx = 0; idx < 256; idx += 1) {
2312 int dix = (idx/16)*dy + (idx%16);
2313 dp[dix] = dataM[idx];
2314 }
2315 /* Y */
2316 dp = (uint16_t*)conY->buf + 16*mx;
2317 for (idx = 0; idx < 256; idx += 1) {
2318 int dix = (idx/16)*dy + (idx%16);
2319 dp[dix] = dataY[idx];
2320 }
2321 /* K */
2322 dp = (uint16_t*)conK->buf + 16*mx;
2323 for (idx = 0; idx < 256; idx += 1) {
2324 int dix = (idx/16)*dy + (idx%16);
2325 dp[dix] = dataK[idx];
2326 }
2327
2328 /* A */
2329 if(con->alpha)
2330 {
2331 dp = (uint16_t*)conA->buf + 16*mx;
2332 for (idx = 0; idx < 256; idx += 1) {
2333 int dix = (idx/16)*dy + (idx%16);
2334 dp[dix] = dataA[idx];
2335 }
2336 }
2337 }
2338 else
2339 {
2340 assert(!"Unsupported bitdepth\n");
2341 }
2342
2343 if (mx+1 == strip_blocks) {
2344
2345 if(con->bpi == 8)
2346 {
2347 int first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
2348 int trans = (my*16 + 16 > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%16 : 16;
2349
2350 dy = 16*strip_blocks;
2351 for (idx = first; idx < trans; idx += 1) {
2352 uint8_t *dp = (uint8_t*)conC->buf + idx*dy + con->left_pad;
2353 write_uint8(conC, dp, conC->wid );
2354 }
2355 for (idx = first; idx < trans; idx += 1) {
2356 uint8_t *dp = (uint8_t*)conM->buf + idx*dy + con->left_pad;
2357 write_uint8(conM, dp, (conM->wid));
2358 }
2359 for (idx = first; idx < trans; idx += 1) {
2360 uint8_t *dp = (uint8_t*)conY->buf + idx*dy + con->left_pad;
2361 write_uint8(conY, dp, (conY->wid));
2362 }
2363 for (idx = first; idx < trans; idx += 1) {
2364 uint8_t *dp = (uint8_t*)conK->buf + idx*dy + con->left_pad;
2365 write_uint8(conK, dp, (conK->wid));
2366 }
2367
2368 if(con->alpha)
2369 {
2370 for (idx = first; idx < trans; idx += 1) {
2371 uint8_t *dp = (uint8_t*)conA->buf + idx*dy + con->left_pad;
2372 write_uint8(conA, dp, conA->wid);
2373 }
2374 }
2375 con->top_pad_remaining -= first;
2376 }
2377 else if(con->bpi == 16 || con->bpi == 10)
2378 {
2379 int first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
2380 int trans = (my*16 + 16 > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%16 : 16;
2381 dy = 16*strip_blocks;
2382 for (idx = first; idx < trans; idx += 1) {
2383 uint16_t *dp = (uint16_t*)conC->buf + idx*dy + con->left_pad;
2384 write_uint16(conC, dp, conC->wid );
2385 }
2386
2387 for (idx = first; idx < trans; idx += 1) {
2388 uint16_t *dp = (uint16_t*)conM->buf + idx*dy + con->left_pad;
2389 write_uint16(conM, dp, (conM->wid) );
2390 }
2391
2392 for (idx = first; idx < trans; idx += 1) {
2393 uint16_t *dp = (uint16_t*)conY->buf + idx*dy + con->left_pad;
2394 write_uint16(conY, dp, (conY->wid) );
2395 }
2396
2397 for (idx = first; idx < trans; idx += 1) {
2398 uint16_t *dp = (uint16_t*)conK->buf + idx*dy + con->left_pad;
2399 write_uint16(conK, dp, (conK->wid) );
2400 }
2401
2402 if(con->alpha)
2403 {
2404 for (idx = first; idx < trans; idx += 1) {
2405 uint16_t *dp = (uint16_t*)conA->buf + idx*dy + con->left_pad;
2406 write_uint16(conA, dp, conA->wid);
2407 }
2408 }
2409 con->top_pad_remaining -= first;
2410 }
2411 else
2412 assert(!"Unsupported bitdepth\n");
2413 }
2414 if(my*16 + 16 >= (con->hei + con->top_pad) && mx+1 == strip_blocks)
2415 {
2416 /* End of decode */
2417 long size = ftell(conC->file);
2418 long ii;
2419 fseek(conC->file, 0, 0);
2420 for( ii = 0; ii < size; ii++)
2421 {
2422 uint8_t val;
2423 fread(&val, 1, 1, conC->file);
2424 fwrite(&val, 1, 1, con->file);
2425 }
2426 size = ftell(conM->file);
2427 fseek(conM->file, 0, 0);
2428 for( ii = 0; ii < size; ii++)
2429 {
2430 uint8_t val;
2431 fread(&val, 1, 1, conM->file);
2432 fwrite(&val, 1, 1, con->file);
2433 }
2434 size = ftell(conY->file);
2435 fseek(conY->file, 0, 0);
2436 for( ii = 0; ii < size; ii++)
2437 {
2438 uint8_t val;
2439 fread(&val, 1, 1, conY->file);
2440 fwrite(&val, 1, 1, con->file);
2441 }
2442 size = ftell(conK->file);
2443 fseek(conK->file, 0, 0);
2444 for( ii = 0; ii < size; ii++)
2445 {
2446 uint8_t val;
2447 fread(&val, 1, 1, conK->file);
2448 fwrite(&val, 1, 1, con->file);
2449 }
2450 if(con->alpha)
2451 {
2452 size = ftell(conA->file);
2453 fseek(conA->file, 0, 0);
2454 for( ii = 0; ii < size && con->alpha; ii++)
2455 {
2456 uint8_t val;
2457 fread(&val, 1, 1, conA->file);
2458 fwrite(&val, 1, 1, con->file);
2459 }
2460 }
2461 fclose(conC->file);
2462 fclose(conM->file);
2463 fclose(conY->file);
2464 fclose(conK->file);
2465 if(con->alpha)
2466 fclose(conA->file);
2467
2468 free(conC->buf);
2469 free(conM->buf);
2470 free(conY->buf);
2471 free(conK->buf);
2472 if(con->alpha)
2473 free(conA->buf);
2474
2475 free(conC);
2476 free(conM);
2477 free(conY);
2478 free(conK);
2479 if(con->alpha)
2480 free(conA);
2481
2482 remove("C.raw");
2483 remove("M.raw");
2484 remove("Y.raw");
2485 remove("K.raw");
2486 if(con->alpha)
2487 remove("A.raw");
2488 }
2489 }
2490
write_file(jxr_image_t image,int mx,int my,int * data)2491 void write_file(jxr_image_t image, int mx, int my, int*data)
2492 {
2493 context *con = (context*) jxr_get_user_data(image);
2494
2495 if((isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image)) && jxr_get_IMAGE_CHANNELS(image) == 3)
2496 {
2497 /* Use special YCC format only for primary image */
2498 write_file_YCC(image, mx, my, data);
2499 return;
2500 }
2501 else if(isOutputCMYKDirect(image) && jxr_get_IMAGE_CHANNELS(image) == 4)
2502 {
2503 /* Use special YCC format only for primary image */
2504 write_file_CMYK(image, mx, my, data);
2505 return;
2506 }
2507
2508 if (con->file==0)
2509 {
2510 int channels = jxr_get_IMAGE_CHANNELS(image);
2511 if( channels == 3)
2512 set_bgr_flag(con, image);
2513 else
2514 con->isBgr = 0;
2515
2516 if(jxr_get_pixel_format(image) == JXRC_FMT_32bppRGBE)
2517 {
2518 channels++;
2519 }
2520
2521 set_pad_bytes(con, image);
2522
2523 con->left_pad = image->window_extra_left;
2524 con->top_pad_remaining = image->window_extra_top;
2525 con->top_pad = image->window_extra_top;
2526
2527 con->alpha = jxr_get_ALPHACHANNEL_FLAG(image);
2528 if (con->alpha) /* with alpha channel */
2529 channels ++;
2530
2531 start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2532 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2533 channels, jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
2534 }
2535
2536 int idx, jdx;
2537 int strip_blocks = (image->extended_width)/16;
2538 int dy = 16*con->ncomp*strip_blocks;
2539 if(con->padBytes !=0)
2540 dy = dy+16*strip_blocks;
2541 if (con->bpi == 1 || con->bpi == 5 || con->bpi == 6 || con->bpi == 8) {
2542 uint8_t *dp = (uint8_t*)con->buf + 16*con->ncomp*mx;
2543 if(con->padBytes != 0)
2544 {
2545 dp = dp + 16*mx; /* Add padding channel offset */
2546 }
2547 for (idx = 0; idx < 256; idx += 1) {
2548 int dix = (idx/16)*dy + (idx%16)*con->ncomp;
2549 if(con->padBytes)
2550 dix +=(idx%16);
2551 int six = idx*con->ncomp;
2552 int pl;
2553 for (pl = 0 ; pl < con->ncomp ; pl += 1)
2554 dp[dix + pl] = data[six + pl];
2555 if(con->padBytes != 0)
2556 dp[dix + pl] = 0; /* Padding data after all n channels */
2557 if(con->isBgr)
2558 switch_r_b(dp+dix, con->bpi);
2559 }
2560 }
2561 else if(con->bpi == 10 || con->bpi == 16){
2562 uint16_t *dp = (uint16_t*)con->buf + 16*con->ncomp*mx;
2563 if(con->padBytes != 0)
2564 {
2565 dp = dp + 16*mx; /* Add padding channel offset */
2566 }
2567
2568 for (idx = 0; idx < 256; idx += 1) {
2569 int dix = (idx/16)*dy + (idx%16)*con->ncomp;
2570 if(con->padBytes)
2571 dix +=(idx%16);
2572 int six = idx*con->ncomp;
2573 int pl;
2574 for (pl = 0 ; pl < con->ncomp ; pl += 1)
2575 dp[dix + pl] = data[six + pl];
2576 if(con->padBytes != 0)
2577 dp[dix + pl] = 0; /* Padding data after all n channels */
2578 if(con->isBgr)
2579 switch_r_b(dp + dix, con->bpi);
2580 }
2581 }
2582 else if(con->bpi ==32) {
2583 uint32_t *dp = (uint32_t*)con->buf + 16*con->ncomp*mx;
2584 if(con->padBytes != 0)
2585 {
2586 dp = dp + 16*mx; /* Add padding channel offset */
2587 }
2588 for (idx = 0; idx < 256; idx += 1) {
2589 int dix = (idx/16)*dy + (idx%16)*con->ncomp;
2590 if(con->padBytes)
2591 dix +=(idx%16);
2592 int six = idx*con->ncomp;
2593 int pl;
2594 for (pl = 0 ; pl < con->ncomp ; pl += 1)
2595 dp[dix + pl] = data[six + pl];
2596 if(con->padBytes != 0)
2597 dp[dix + pl] = 0; /* Padding data after all n channels */
2598 if(con->isBgr)
2599 switch_r_b(dp + dix, con->bpi);
2600 }
2601 }
2602 else
2603 {
2604 assert(!"Unsupported bitdepth\n");
2605 }
2606
2607 if (mx+1 == strip_blocks) {
2608 int first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
2609 con->top_pad_remaining -= first; /* skip the padding rows */
2610 int trans = (my*16 + 16 > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%16 : 16;
2611 if(con->bpi == 1)
2612 {
2613 /* ClipAndPackBD1BorW */
2614 /* Clipping is already handled in scale_and_emit_top, so just pack */
2615 for (idx = first; idx < trans; idx += 1) {
2616 uint8_t *dp = (uint8_t*)con->buf + idx*dy;
2617 for(jdx = con->left_pad; jdx < (con->wid + con->left_pad); jdx = jdx + 8)
2618 {
2619 uint8_t buff[8];
2620 uint8_t iResult = 0;
2621 int end = jdx + 8 > con->wid? con->wid:jdx + 8;
2622 memset(buff, 0, 8 * sizeof(uint8_t));
2623 memcpy(buff, dp+jdx, (end-jdx) * sizeof(uint8_t));
2624 if (jxr_get_OUTPUT_BITDEPTH(image) == JXR_BD1BLACK1)
2625 {
2626 iResult = (1-buff[7]) + ((1 - buff[6]) << 1) + ((1 - buff[5]) << 2) +
2627 ((1 - buff[4]) << 3) + ((1 - buff[3]) << 4) + ((1 - buff[2]) << 5) +
2628 ((1 - buff[1]) << 6) + ((1 - buff[0]) << 7);
2629 }
2630 else/* jxr_output_bitdepth(image) = = BD1WHITE1 */
2631 {
2632 iResult = buff[7] + (buff[6] << 1) + (buff[5] << 2) +
2633 (buff[4] << 3) + (buff[3] << 4) + (buff[2] << 5) +
2634 (buff[1] << 6) + (buff[0] << 7);
2635 }
2636
2637 write_uint8(con, &iResult,1 );
2638 }
2639 }
2640 }
2641 else if(con->bpi == 5)
2642 {
2643 /* ClipAndPack555 */
2644 /* Clipping is already handled in scale_and_emit_top, so just pack */
2645 for (idx = first; idx < trans; idx += 1) {
2646 uint8_t *dp = (uint8_t*)con->buf + idx*dy;
2647 assert(con->ncomp == 3);
2648 for(jdx = con->left_pad*con->ncomp; jdx < (con->wid + con->left_pad)*con->ncomp; jdx = jdx + con->ncomp)
2649 {
2650 uint16_t iResult = 0;
2651 iResult = (uint16_t)dp[jdx] + (((uint16_t)dp[jdx + 1])<<5) + (((uint16_t)dp[jdx + 2])<<10);
2652 write_uint16(con, &iResult,1 );
2653 }
2654 }
2655 }
2656 else if(con->bpi == 6)
2657 {
2658 /* ClipAndPack565 */
2659 /* Clipping is already handled in scale_and_emit_top, so just pack */
2660 for (idx = first; idx < trans; idx += 1) {
2661 uint8_t *dp = (uint8_t*)con->buf + idx*dy;
2662 assert(con->ncomp == 3);
2663 for(jdx = con->left_pad*con->ncomp; jdx < (con->wid + con->left_pad)*con->ncomp; jdx = jdx + con->ncomp)
2664 {
2665 uint16_t iResult = 0;
2666 iResult = (uint16_t)dp[jdx] + (((uint16_t)dp[jdx + 1])<<5) + (((uint16_t)dp[jdx + 2])<<11);
2667 write_uint16(con, &iResult,1 );
2668 }
2669 }
2670 }
2671 else if (con->bpi==8)
2672 for (idx = first; idx < trans; idx += 1) {
2673 uint8_t *dp = (uint8_t*)con->buf + idx*dy + con->left_pad*con->ncomp;
2674 int padComp = con->ncomp;
2675 if(con->padBytes != 0 )
2676 padComp ++;
2677 write_uint8(con, dp, con->wid*padComp); }
2678 else if(con->bpi == 10 && con->ncomp == 3)
2679 {
2680 /* ClipAndPack10 */
2681 /* Clipping is already handled in scale_and_emit_top, so just pack */
2682 for (idx = first; idx < trans; idx += 1) {
2683 uint16_t *dp = (uint16_t*)con->buf + idx*dy;
2684 for(jdx = con->left_pad*con->ncomp; jdx < (con->wid + con->left_pad)*con->ncomp; jdx = jdx + con->ncomp)
2685 {
2686 uint32_t iResult = 0;
2687 iResult = (uint32_t)dp[jdx] + (((uint32_t)dp[jdx + 1])<<10) + (((uint32_t)dp[jdx + 2])<<20);
2688 write_uint32(con, &iResult,1 );
2689 }
2690 }
2691 }
2692 else if(con->bpi == 10 && con->ncomp == 1)/*Alpha image decoding for JXR_30bppYCC422Alpha JXR_40bppYCC4444Alpha */
2693 {
2694 /* ClipAndPack10 */
2695 /* Clipping is already handled in scale_and_emit_top, so just pack */
2696 for (idx = 0; idx < trans; idx += 1) {
2697 uint16_t *dp = (uint16_t*)con->buf + idx*dy;
2698 for(jdx = con->left_pad*con->ncomp; jdx < (con->wid + con->left_pad)*con->ncomp; jdx = jdx + con->ncomp)
2699 {
2700 uint16_t iResult = 0;
2701 iResult = (uint16_t)dp[jdx];
2702 write_uint16(con, &iResult,1 );
2703 }
2704 }
2705 }
2706 else if(con->bpi==16)
2707 for (idx = first; idx < trans; idx += 1) {
2708 uint16_t *dp = (uint16_t*)con->buf + idx*dy + con->left_pad*con->ncomp; /* dy already contains offset for padding data */
2709 int padComp = con->ncomp;
2710 if(con->padBytes != 0 )
2711 padComp ++;
2712 write_uint16(con, dp, con->wid*padComp );
2713 }
2714 else if(con->bpi == 32)
2715 for (idx = first; idx < trans; idx += 1) {
2716 uint32_t *dp = (uint32_t*)con->buf + idx*dy + con->left_pad*con->ncomp;
2717 int padComp = con->ncomp;
2718 if(con->padBytes != 0 )
2719 padComp ++;
2720 write_uint32(con, dp, con->wid*padComp );
2721 }
2722 else
2723 assert(!"Unsupported bitdepth\n");
2724 }
2725 }
2726
2727
concatenate_primary_alpha(jxr_image_t image,FILE * fpPrimary,FILE * fpAlpha)2728 void concatenate_primary_alpha(jxr_image_t image, FILE *fpPrimary, FILE *fpAlpha)
2729 {
2730 context *con = (context*) jxr_get_user_data(image);
2731 if (con->file==0)
2732 {
2733 set_pad_bytes(con, image);
2734 /* Add 1 to number of channels for alpha */
2735 con->alpha = 1;
2736 start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2737 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2738 jxr_get_IMAGE_CHANNELS(image) + 1, jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
2739 }
2740 fseek(fpPrimary, 0, SEEK_END);
2741 long size = ftell(fpPrimary);
2742 fseek(fpPrimary, 0, SEEK_SET);
2743 long i;
2744 for(i = 0; i < size; i++)
2745 {
2746 uint8_t val;
2747 fread(&val, 1, 1, fpPrimary);
2748 fwrite(&val, 1, 1, con->file);
2749 }
2750 fseek(fpAlpha, 0, SEEK_END);
2751 size = ftell(fpAlpha);
2752 fseek(fpAlpha, 0, SEEK_SET);
2753 for(i = 0; i < size; i++)
2754 {
2755 uint8_t val;
2756 fread(&val, 1, 1, fpAlpha);
2757 fwrite(&val, 1, 1, con->file);
2758 }
2759 }
2760
2761
2762
write_file_combine_primary_alpha(jxr_image_t image,FILE * fpPrimary,FILE * fpAlpha)2763 void write_file_combine_primary_alpha(jxr_image_t image, FILE *fpPrimary, FILE *fpAlpha)
2764 {
2765 context *con = (context*) jxr_get_user_data(image);
2766 int i;
2767
2768 if(isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image) || isOutputCMYKDirect(image))
2769 {
2770 concatenate_primary_alpha(image, fpPrimary, fpAlpha);
2771 return;
2772 }
2773 if (con->file==0)
2774 {
2775 set_pad_bytes(con, image);
2776 /* Add 1 to number of channels for alpha */
2777 con->alpha = 1;
2778 start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
2779 jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
2780 jxr_get_IMAGE_CHANNELS(image) + 1, jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
2781 }
2782 int numPixels = jxr_get_IMAGE_WIDTH(image) * jxr_get_IMAGE_HEIGHT(image);
2783 int nPrimaryComp = jxr_get_IMAGE_CHANNELS(image);
2784 if(con->padBytes)
2785 nPrimaryComp ++;
2786 if (con->bpi == 8) {
2787 for (i=0; i<numPixels; i++) {
2788 unsigned char combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
2789 fread(&combine[0],sizeof(char),nPrimaryComp, fpPrimary);
2790 fread(&(combine[nPrimaryComp]),sizeof(char), 1,fpAlpha);
2791 write_uint8(con, combine, nPrimaryComp+1);
2792 }
2793 }
2794 else if(con->bpi == 16)
2795 {
2796 for (i=0; i<numPixels; i++) {
2797 uint16_t combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
2798 fread(&combine[0],sizeof(uint16_t),nPrimaryComp, fpPrimary);
2799 fread(&(combine[nPrimaryComp]),sizeof(uint16_t), 1,fpAlpha);
2800 write_uint16(con, combine, nPrimaryComp+1);
2801 }
2802 }
2803 else if(con->bpi == 32)
2804 {
2805 for (i=0; i<numPixels; i++) {
2806 uint32_t combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
2807 fread(&combine[0],sizeof(uint32_t),nPrimaryComp, fpPrimary);
2808 fread(&(combine[nPrimaryComp]),sizeof(uint32_t), 1,fpAlpha);
2809 write_uint32(con, combine,nPrimaryComp+1);
2810 }
2811 }
2812 else
2813 assert(!"Unsupported bitdepth\n");
2814 }
2815
2816
split_primary_alpha(jxr_image_t image,void * input_handle,context * con_primary,context * con_alpha,jxr_container_t container)2817 void split_primary_alpha(jxr_image_t image,void *input_handle, context *con_primary, context *con_alpha, jxr_container_t container)
2818 {
2819 /* Used for YCCA and CMYKA */
2820 int wid, hei, ncomp, bpi;
2821 short sf, photometric;
2822 int padBytes;
2823
2824 get_file_parameters(input_handle, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
2825 int numPixels = wid * hei;
2826 int nPrimaryComp = ncomp-1;
2827 context *con = (context *)input_handle;
2828 read_setup(con);
2829
2830 int i;
2831
2832 start_output_file(con_primary, wid, hei, wid, hei, con_primary->ncomp, jxr_get_OUTPUT_BITDEPTH(image), jxrc_get_pixel_format(container));
2833 start_output_file(con_alpha, wid, hei, wid, hei, con_alpha->ncomp, jxr_get_OUTPUT_BITDEPTH(image), jxrc_get_pixel_format(container));
2834
2835 if(isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image) || isOutputCMYKDirect(image))
2836 {
2837 //16 * (con->ncomp + con->padBytes) * ((con->bpi+7)/8) * ((con->wid+15)&~15);
2838 unsigned bytes = (con->bpi+7)/8;
2839 unsigned size_luma = numPixels * bytes;
2840 unsigned size_chroma = size_luma;
2841 if (isOutputYUV422(image))
2842 size_chroma >>= 1;
2843 if (isOutputYUV420(image))
2844 size_chroma >>= 2;
2845
2846 uint8_t * combine = 0;
2847 combine = (uint8_t*)malloc(size_luma);
2848 assert(combine != 0);
2849
2850 read_uint8(con, combine, size_luma);
2851 write_uint8(con_primary, combine, size_luma);
2852
2853 for (i = 1; i < nPrimaryComp; i++) {
2854 read_uint8(con, combine, size_chroma);
2855 write_uint8(con_primary, combine, size_chroma);
2856 }
2857
2858 read_uint8(con, combine, size_luma);
2859 write_uint8(con_alpha, combine, size_luma);
2860
2861 free(combine);
2862 }
2863 else
2864 {
2865 for (i=0; i<numPixels; i++)
2866 {
2867 if (con->bpi == 8) {
2868
2869 unsigned char combine[MAX_CHANNELS + 1];/*+ 1 for padded channel */
2870 read_uint8(con, &combine[0],nPrimaryComp);
2871 write_uint8(con_primary, combine, nPrimaryComp);
2872
2873 }
2874 else if(con->bpi == 16)
2875 {
2876
2877 uint16_t combine[MAX_CHANNELS + 1];/*+ 1 for padded channel */
2878 read_uint16(con, &combine[0],nPrimaryComp);
2879 write_uint16(con_primary, combine, nPrimaryComp);
2880
2881 }
2882 else if(con->bpi == 32)
2883 {
2884
2885 uint32_t combine[MAX_CHANNELS + 1];/*+ 1 for padded channel */
2886 read_uint32(con, &combine[0],nPrimaryComp);
2887 write_uint32(con_primary, combine, nPrimaryComp);
2888
2889 }
2890 else
2891 assert(!"Unsupported bitdepth\n");
2892 }
2893 for (i=0; i<numPixels; i++)
2894 {
2895 if (con->bpi == 8) {
2896
2897 unsigned char combine[1];
2898 read_uint8(con, &combine[0],1);
2899 write_uint8(con_alpha, combine, 1);
2900
2901 }
2902 else if(con->bpi == 16)
2903 {
2904
2905 uint16_t combine[1];
2906 read_uint16(con, &combine[0],1);
2907 write_uint16(con_alpha, combine, 1);
2908
2909 }
2910 else if(con->bpi == 32)
2911 {
2912
2913 uint32_t combine[1];
2914 read_uint32(con, &combine[0],1);
2915 write_uint32(con_alpha, combine, 1);
2916
2917 }
2918 else
2919 assert(!"Unsupported bitdepth\n");
2920 }
2921 }
2922 close_file(con_primary);
2923 close_file(con_alpha);
2924 }
2925
2926
separate_primary_alpha(jxr_image_t image,void * input_handle,char * path_out,char * path_primary,char * path_alpha,jxr_container_t container)2927 void separate_primary_alpha(jxr_image_t image, void *input_handle, char *path_out, char * path_primary, char *path_alpha, jxr_container_t container)
2928 {
2929
2930 context *con;
2931
2932 int i;
2933 int wid, hei, ncomp, bpi;
2934 short sf, photometric;
2935 int padBytes;
2936
2937 con = (context *)input_handle;
2938 read_setup(con);
2939
2940
2941 context *con_primary = (context *)malloc(sizeof(context));
2942 assert(con_primary != NULL);
2943 context *con_alpha = (context *)malloc(sizeof(context));
2944 assert(con_alpha != NULL);
2945
2946 memcpy(con_primary, con, sizeof(*con));
2947 memcpy(con_alpha, con, sizeof(*con));
2948 con_primary->alpha = con_alpha->alpha = 0;
2949 con_primary->buf = con_alpha->buf = 0;
2950 con_primary->ncomp = con->ncomp - 1;
2951 con_alpha->ncomp = 1;
2952
2953 get_file_parameters(con, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
2954
2955 const char *p = strrchr(con->name, '.');
2956 if (p==0)
2957 error("output file name %s needs a suffix to determine its format", con->name);
2958 if (!strcasecmp(p, ".pnm") || !strcasecmp(p, ".pgm") || !strcasecmp(p, ".ppm"))
2959 {
2960 error("Alpha channel not supported by PNM, PGM and PPM");
2961 }
2962 else if (!strcasecmp(p, ".tif"))
2963 {
2964 strcpy(path_primary, path_out);
2965 strcat(path_primary, "_input_primary.tif");
2966 strcpy(path_alpha, path_out);
2967 strcat(path_alpha, "_input_alpha.tif");
2968
2969 }
2970 else if (!strcasecmp(p, ".raw"))
2971 {
2972 strcpy(path_primary, path_out);
2973 strcat(path_primary, "_input_primary.raw");
2974 strcpy(path_alpha, path_out);
2975 strcat(path_alpha, "_input_alpha.raw");
2976 }
2977 else error("unrecognized suffix on output file name %s", con->name);
2978
2979 con_primary->name = path_primary;
2980 con_alpha->name = path_alpha;
2981
2982
2983 if(isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image) || isOutputCMYKDirect(image))
2984 {
2985 split_primary_alpha(image, input_handle,con_primary, con_alpha, container);
2986 return;
2987 }
2988
2989 start_output_file(con_primary, wid, hei, wid, hei, con_primary->ncomp, jxr_get_OUTPUT_BITDEPTH(image), jxrc_get_pixel_format(container));
2990 start_output_file(con_alpha, wid, hei, wid, hei, con_alpha->ncomp, jxr_get_OUTPUT_BITDEPTH(image), jxrc_get_pixel_format(container));
2991
2992 int numPixels = wid * hei;
2993 int nPrimaryComp = ncomp-1;
2994
2995 if (con->bpi == 8) {
2996 for (i=0; i<numPixels; i++) {
2997 unsigned char combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
2998 read_uint8(con, &combine[0],ncomp);
2999 write_uint8(con_primary, combine, nPrimaryComp);
3000 write_uint8(con_alpha, &(combine[nPrimaryComp]), 1);
3001
3002 }
3003 }
3004 else if(con->bpi == 16)
3005 {
3006 for (i=0; i<numPixels; i++) {
3007 uint16_t combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
3008 read_uint16(con, &combine[0],ncomp);
3009 write_uint16(con_primary, combine, nPrimaryComp);
3010 write_uint16(con_alpha, &(combine[nPrimaryComp]), 1);
3011 }
3012 }
3013 else if(con->bpi == 32)
3014 {
3015 for (i=0; i<numPixels; i++) {
3016 uint32_t combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
3017 read_uint32(con, &combine[0],ncomp);
3018 write_uint32(con_primary, combine, nPrimaryComp);
3019 write_uint32(con_alpha, &(combine[nPrimaryComp]), 1);
3020 }
3021 }
3022 else
3023 assert(!"Unsupported bitdepth\n");
3024 close_file(con_primary);
3025 close_file(con_alpha);
3026 }
3027
3028 /*
3029 * $Log: file.c,v $
3030 * Revision 1.17 2009/05/29 12:00:00 microsoft
3031 * Reference Software v1.6 updates.
3032 *
3033 * Revision 1.16 2009/04/13 12:00:00 microsoft
3034 * Reference Software v1.5 updates.
3035 *
3036 * Revision 1.15 2008/03/17 23:34:54 steve
3037 * Support output of CMYK TIFF images.
3038 *
3039 * Revision 1.14 2008/03/06 09:33:47 rick
3040 * Add support for reading multi-strip TIFF files; fix TIFF reader bug.
3041 *
3042 * Revision 1.13 2008/03/05 19:32:02 gus
3043 * *** empty log message ***
3044 *
3045 * Revision 1.12 2008/03/05 06:58:10 gus
3046 * *** empty log message ***
3047 *
3048 * Revision 1.11 2008/03/03 03:16:18 rick
3049 * Re-implement BDx to bpi mapping.
3050 *
3051 * Revision 1.10 2008/03/03 01:57:34 steve
3052 * Fix BDx to bpi mapping.
3053 *
3054 * Revision 1.9 2008/03/03 01:51:40 rick
3055 * Allow output file depths other than 8.
3056 *
3057 * Revision 1.8 2008/02/29 01:03:31 steve
3058 * MSC doesnt have strcasecmp. Use stricmp instead.
3059 *
3060 * Revision 1.7 2008/02/29 00:45:21 steve
3061 * Portability, esp w/ C++ compilers.
3062 *
3063 * Revision 1.6 2008/02/27 06:15:49 rick
3064 * Replace macro ASSERT, which had optional arguments.
3065 *
3066 * Revision 1.5 2008/02/26 23:52:44 steve
3067 * Remove ident for MS compilers.
3068 *
3069 * Revision 1.4 2008/02/26 23:44:25 steve
3070 * Handle the special case of compiling via MS C.
3071 *
3072 * Revision 1.3 2008/02/23 08:45:07 rick
3073 * Changed some types to avoid compiler warnings.
3074 *
3075 * Revision 1.2 2008/01/31 23:20:14 rick
3076 * Fix bug in read_file() affecting color input images.
3077 *
3078 * Revision 1.1 2008/01/19 02:30:46 rick
3079 * Re-implement and extend file interface.
3080 *
3081 */
3082
3083