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