1#include "mupdf/fitz.h"
2
3#include <math.h>
4#include <string.h>
5
6/* Table stolen from LibTiff */
7#define UV_SQSIZ 0.003500f
8#define UV_NDIVS 16289
9#define UV_VSTART 0.016940f
10#define UV_NVS 163
11#define U_NEU 0.210526316f
12#define V_NEU 0.473684211f
13#define UVSCALE 410
14static struct {
15 float ustart;
16 short nus, ncum;
17} uv_row[UV_NVS] = {
18 { 0.247663f, 4, 0 },
19 { 0.243779f, 6, 4 },
20 { 0.241684f, 7, 10 },
21 { 0.237874f, 9, 17 },
22 { 0.235906f, 10, 26 },
23 { 0.232153f, 12, 36 },
24 { 0.228352f, 14, 48 },
25 { 0.226259f, 15, 62 },
26 { 0.222371f, 17, 77 },
27 { 0.220410f, 18, 94 },
28 { 0.214710f, 21, 112 },
29 { 0.212714f, 22, 133 },
30 { 0.210721f, 23, 155 },
31 { 0.204976f, 26, 178 },
32 { 0.202986f, 27, 204 },
33 { 0.199245f, 29, 231 },
34 { 0.195525f, 31, 260 },
35 { 0.193560f, 32, 291 },
36 { 0.189878f, 34, 323 },
37 { 0.186216f, 36, 357 },
38 { 0.186216f, 36, 393 },
39 { 0.182592f, 38, 429 },
40 { 0.179003f, 40, 467 },
41 { 0.175466f, 42, 507 },
42 { 0.172001f, 44, 549 },
43 { 0.172001f, 44, 593 },
44 { 0.168612f, 46, 637 },
45 { 0.168612f, 46, 683 },
46 { 0.163575f, 49, 729 },
47 { 0.158642f, 52, 778 },
48 { 0.158642f, 52, 830 },
49 { 0.158642f, 52, 882 },
50 { 0.153815f, 55, 934 },
51 { 0.153815f, 55, 989 },
52 { 0.149097f, 58, 1044 },
53 { 0.149097f, 58, 1102 },
54 { 0.142746f, 62, 1160 },
55 { 0.142746f, 62, 1222 },
56 { 0.142746f, 62, 1284 },
57 { 0.138270f, 65, 1346 },
58 { 0.138270f, 65, 1411 },
59 { 0.138270f, 65, 1476 },
60 { 0.132166f, 69, 1541 },
61 { 0.132166f, 69, 1610 },
62 { 0.126204f, 73, 1679 },
63 { 0.126204f, 73, 1752 },
64 { 0.126204f, 73, 1825 },
65 { 0.120381f, 77, 1898 },
66 { 0.120381f, 77, 1975 },
67 { 0.120381f, 77, 2052 },
68 { 0.120381f, 77, 2129 },
69 { 0.112962f, 82, 2206 },
70 { 0.112962f, 82, 2288 },
71 { 0.112962f, 82, 2370 },
72 { 0.107450f, 86, 2452 },
73 { 0.107450f, 86, 2538 },
74 { 0.107450f, 86, 2624 },
75 { 0.107450f, 86, 2710 },
76 { 0.100343f, 91, 2796 },
77 { 0.100343f, 91, 2887 },
78 { 0.100343f, 91, 2978 },
79 { 0.095126f, 95, 3069 },
80 { 0.095126f, 95, 3164 },
81 { 0.095126f, 95, 3259 },
82 { 0.095126f, 95, 3354 },
83 { 0.088276f, 100, 3449 },
84 { 0.088276f, 100, 3549 },
85 { 0.088276f, 100, 3649 },
86 { 0.088276f, 100, 3749 },
87 { 0.081523f, 105, 3849 },
88 { 0.081523f, 105, 3954 },
89 { 0.081523f, 105, 4059 },
90 { 0.081523f, 105, 4164 },
91 { 0.074861f, 110, 4269 },
92 { 0.074861f, 110, 4379 },
93 { 0.074861f, 110, 4489 },
94 { 0.074861f, 110, 4599 },
95 { 0.068290f, 115, 4709 },
96 { 0.068290f, 115, 4824 },
97 { 0.068290f, 115, 4939 },
98 { 0.068290f, 115, 5054 },
99 { 0.063573f, 119, 5169 },
100 { 0.063573f, 119, 5288 },
101 { 0.063573f, 119, 5407 },
102 { 0.063573f, 119, 5526 },
103 { 0.057219f, 124, 5645 },
104 { 0.057219f, 124, 5769 },
105 { 0.057219f, 124, 5893 },
106 { 0.057219f, 124, 6017 },
107 { 0.050985f, 129, 6141 },
108 { 0.050985f, 129, 6270 },
109 { 0.050985f, 129, 6399 },
110 { 0.050985f, 129, 6528 },
111 { 0.050985f, 129, 6657 },
112 { 0.044859f, 134, 6786 },
113 { 0.044859f, 134, 6920 },
114 { 0.044859f, 134, 7054 },
115 { 0.044859f, 134, 7188 },
116 { 0.040571f, 138, 7322 },
117 { 0.040571f, 138, 7460 },
118 { 0.040571f, 138, 7598 },
119 { 0.040571f, 138, 7736 },
120 { 0.036339f, 142, 7874 },
121 { 0.036339f, 142, 8016 },
122 { 0.036339f, 142, 8158 },
123 { 0.036339f, 142, 8300 },
124 { 0.032139f, 146, 8442 },
125 { 0.032139f, 146, 8588 },
126 { 0.032139f, 146, 8734 },
127 { 0.032139f, 146, 8880 },
128 { 0.027947f, 150, 9026 },
129 { 0.027947f, 150, 9176 },
130 { 0.027947f, 150, 9326 },
131 { 0.023739f, 154, 9476 },
132 { 0.023739f, 154, 9630 },
133 { 0.023739f, 154, 9784 },
134 { 0.023739f, 154, 9938 },
135 { 0.019504f, 158, 10092 },
136 { 0.019504f, 158, 10250 },
137 { 0.019504f, 158, 10408 },
138 { 0.016976f, 161, 10566 },
139 { 0.016976f, 161, 10727 },
140 { 0.016976f, 161, 10888 },
141 { 0.016976f, 161, 11049 },
142 { 0.012639f, 165, 11210 },
143 { 0.012639f, 165, 11375 },
144 { 0.012639f, 165, 11540 },
145 { 0.009991f, 168, 11705 },
146 { 0.009991f, 168, 11873 },
147 { 0.009991f, 168, 12041 },
148 { 0.009016f, 170, 12209 },
149 { 0.009016f, 170, 12379 },
150 { 0.009016f, 170, 12549 },
151 { 0.006217f, 173, 12719 },
152 { 0.006217f, 173, 12892 },
153 { 0.005097f, 175, 13065 },
154 { 0.005097f, 175, 13240 },
155 { 0.005097f, 175, 13415 },
156 { 0.003909f, 177, 13590 },
157 { 0.003909f, 177, 13767 },
158 { 0.002340f, 177, 13944 },
159 { 0.002389f, 170, 14121 },
160 { 0.001068f, 164, 14291 },
161 { 0.001653f, 157, 14455 },
162 { 0.000717f, 150, 14612 },
163 { 0.001614f, 143, 14762 },
164 { 0.000270f, 136, 14905 },
165 { 0.000484f, 129, 15041 },
166 { 0.001103f, 123, 15170 },
167 { 0.001242f, 115, 15293 },
168 { 0.001188f, 109, 15408 },
169 { 0.001011f, 103, 15517 },
170 { 0.000709f, 97, 15620 },
171 { 0.000301f, 89, 15717 },
172 { 0.002416f, 82, 15806 },
173 { 0.003251f, 76, 15888 },
174 { 0.003246f, 69, 15964 },
175 { 0.004141f, 62, 16033 },
176 { 0.005963f, 55, 16095 },
177 { 0.008839f, 47, 16150 },
178 { 0.010490f, 40, 16197 },
179 { 0.016994f, 31, 16237 },
180 { 0.023659f, 21, 16268 },
181};
182
183/* SGI Log 16bit (greyscale) */
184
185typedef struct fz_sgilog16_s fz_sgilog16;
186
187struct fz_sgilog16_s
188{
189 fz_stream *chain;
190 int run, n, c, w;
191 uint16_t *temp;
192};
193
194static inline int
195sgilog16val(fz_context *ctx, uint16_t v)
196{
197 int Le;
198 float Y;
199
200 Le = v & 0x7fff;
201 if (!Le)
202 Y = 0;
203 else
204 {
205 Y = expf(FZ_LN2/256 * (Le + .5f) - FZ_LN2*64);
206 if (v & 0x8000)
207 Y = -Y;
208 }
209
210 return ((Y <= 0) ? 0 : (Y >= 1) ? 255 : (int)(256*sqrtf(Y)));
211}
212
213static int
214next_sgilog16(fz_context *ctx, fz_stream *stm, size_t max)
215{
216 fz_sgilog16 *state = stm->state;
217 uint16_t *p;
218 uint16_t *ep;
219 uint8_t *q;
220 int shift;
221
222 (void)max;
223
224 if (state->run < 0)
225 return EOF;
226
227 memset(state->temp, 0, state->w * sizeof(uint16_t));
228
229 for (shift = 8; shift >= 0; shift -= 8)
230 {
231 p = state->temp;
232 ep = p + state->w;
233 while (p < ep)
234 {
235 if (state->n == 0)
236 {
237 state->run = fz_read_byte(ctx, state->chain);
238 if (state->run < 0)
239 {
240 state->run = -1;
241 fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
242 }
243 if (state->run < 128)
244 state->n = state->run;
245 else
246 {
247 state->n = state->run - 126;
248 state->c = fz_read_byte(ctx, state->chain);
249 if (state->c < 0)
250 {
251 state->run = -1;
252 fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
253 }
254 }
255 }
256
257 if (state->run < 128)
258 {
259 while (p < ep && state->n)
260 {
261 int c = fz_read_byte(ctx, state->chain);
262 if (c < 0)
263 {
264 state->run = -1;
265 fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
266 }
267 *p++ |= c<<shift;
268 state->n--;
269 }
270 }
271 else
272 {
273 while (p < ep && state->n)
274 {
275 *p++ |= state->c<<shift;
276 state->n--;
277 }
278 }
279 }
280 }
281
282 p = state->temp;
283 q = (uint8_t *)p;
284 ep = p + state->w;
285 while (p < ep)
286 {
287 *q++ = sgilog16val(ctx, *p++);
288 }
289
290 stm->rp = (uint8_t *)(state->temp);
291 stm->wp = q;
292 stm->pos += q - stm->rp;
293
294 if (q == stm->rp)
295 return EOF;
296
297 return *stm->rp++;
298}
299
300static void
301close_sgilog16(fz_context *ctx, void *state_)
302{
303 fz_sgilog16 *state = (fz_sgilog16 *)state_;
304 fz_stream *chain = state->chain;
305
306 fz_free(ctx, state->temp);
307 fz_free(ctx, state);
308 fz_drop_stream(ctx, chain);
309}
310
311fz_stream *
312fz_open_sgilog16(fz_context *ctx, fz_stream *chain, int w)
313{
314 fz_sgilog16 *state = fz_malloc_struct(ctx, fz_sgilog16);
315
316 fz_try(ctx)
317 {
318 state->run = 0;
319 state->n = 0;
320 state->c = 0;
321 state->w = w;
322 state->temp = fz_malloc(ctx, w * sizeof(uint16_t));
323 state->chain = fz_keep_stream(ctx, chain);
324 }
325 fz_catch(ctx)
326 {
327 fz_free(ctx, state->temp);
328 fz_free(ctx, state);
329 fz_rethrow(ctx);
330 }
331
332 return fz_new_stream(ctx, state, next_sgilog16, close_sgilog16);
333}
334
335/* SGI Log 24bit (LUV) */
336
337typedef struct fz_sgilog24_s fz_sgilog24;
338
339struct fz_sgilog24_s
340{
341 fz_stream *chain;
342 int err, w;
343 uint8_t *temp;
344};
345
346static int
347uv_decode(float *up, float *vp, int c) /* decode (u',v') index */
348{
349 int upper, lower;
350 register int ui, vi;
351
352 if (c < 0 || c >= UV_NDIVS)
353 return (-1);
354 lower = 0; /* binary search */
355 upper = UV_NVS;
356 while (upper - lower > 1) {
357 vi = (lower + upper) >> 1;
358 ui = c - uv_row[vi].ncum;
359 if (ui > 0)
360 lower = vi;
361 else if (ui < 0)
362 upper = vi;
363 else {
364 lower = vi;
365 break;
366 }
367 }
368 vi = lower;
369 ui = c - uv_row[vi].ncum;
370 *up = uv_row[vi].ustart + (ui+.5f)*UV_SQSIZ;
371 *vp = UV_VSTART + (vi+.5f)*UV_SQSIZ;
372 return (0);
373}
374
375static inline int
376sgilog24val(fz_context *ctx, fz_stream *chain, uint8_t *rgb)
377{
378 int b0, b1, b2;
379 int luv, p;
380 float u, v, s, x, y, X, Y, Z;
381 float r, g, b;
382
383 b0 = fz_read_byte(ctx, chain);
384 if (b0 < 0)
385 return b0;
386 b1 = fz_read_byte(ctx, chain);
387 if (b1 < 0)
388 return b1;
389 b2 = fz_read_byte(ctx, chain);
390 if (b2 < 0)
391 return b2;
392
393 luv = (b0<<16) | (b1<<8) | b2;
394
395 /* decode luminance */
396 p = (luv>>14) & 0x3ff;
397 Y = (p == 0 ? 0 : expf(FZ_LN2/64*(p+.5f) - FZ_LN2*12));
398 if (Y <= 0)
399 {
400 X = Y = Z = 0;
401 }
402 else
403 {
404 /* decode color */
405 if (uv_decode(&u, &v, luv & 0x3fff) < 0) {
406 u = U_NEU; v = V_NEU;
407 }
408 s = 6*u - 16*v + 12;
409 x = 9*u;
410 y = 4*v;
411 /* convert to XYZ */
412 X = x/y * Y;
413 Z = (s-x-y)/y * Y;
414 }
415
416 /* assume CCIR-709 primaries */
417 r = 2.690f*X + -1.276f*Y + -0.414f*Z;
418 g = -1.022f*X + 1.978f*Y + 0.044f*Z;
419 b = 0.061f*X + -0.224f*Y + 1.163f*Z;
420
421 /* assume 2.0 gamma for speed */
422 /* could use integer sqrt approx., but this is probably faster */
423 rgb[0] = (uint8_t)((r<=0) ? 0 : (r >= 1) ? 255 : (int)(256*sqrtf(r)));
424 rgb[1] = (uint8_t)((g<=0) ? 0 : (g >= 1) ? 255 : (int)(256*sqrtf(g)));
425 rgb[2] = (uint8_t)((b<=0) ? 0 : (b >= 1) ? 255 : (int)(256*sqrtf(b)));
426
427 return 0;
428}
429
430static int
431next_sgilog24(fz_context *ctx, fz_stream *stm, size_t max)
432{
433 fz_sgilog24 *state = stm->state;
434 uint8_t *p;
435 uint8_t *ep;
436
437 (void)max;
438
439 if (state->err)
440 return EOF;
441
442 memset(state->temp, 0, state->w * 3);
443
444 p = state->temp;
445 ep = p + state->w * 3;
446 while (p < ep)
447 {
448 int c = sgilog24val(ctx, state->chain, p);
449 if (c < 0)
450 {
451 state->err = 1;
452 fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
453 }
454 p += 3;
455 }
456
457 stm->rp = state->temp;
458 stm->wp = p;
459 stm->pos += p - stm->rp;
460
461 if (p == stm->rp)
462 return EOF;
463
464 return *stm->rp++;
465}
466
467static void
468close_sgilog24(fz_context *ctx, void *state_)
469{
470 fz_sgilog24 *state = (fz_sgilog24 *)state_;
471 fz_stream *chain = state->chain;
472
473 fz_free(ctx, state->temp);
474 fz_free(ctx, state);
475 fz_drop_stream(ctx, chain);
476}
477
478fz_stream *
479fz_open_sgilog24(fz_context *ctx, fz_stream *chain, int w)
480{
481 fz_sgilog24 *state = fz_malloc_struct(ctx, fz_sgilog24);
482
483 fz_try(ctx)
484 {
485 state->err = 0;
486 state->w = w;
487 state->temp = fz_malloc(ctx, w * 3);
488 state->chain = fz_keep_stream(ctx, chain);
489 }
490 fz_catch(ctx)
491 {
492 fz_free(ctx, state->temp);
493 fz_free(ctx, state);
494 fz_rethrow(ctx);
495 }
496
497 return fz_new_stream(ctx, state, next_sgilog24, close_sgilog24);
498}
499
500/* SGI Log 32bit */
501
502typedef struct fz_sgilog32_s fz_sgilog32;
503
504struct fz_sgilog32_s
505{
506 fz_stream *chain;
507 int run, n, c, w;
508 uint32_t *temp;
509};
510
511static inline void
512sgilog32val(fz_context *ctx, uint32_t p, uint8_t *rgb)
513{
514 float r, g, b;
515 float u, v, s, x, y;
516 float X, Y, Z;
517
518 if (p>>31)
519 {
520 X = Y = Z = 0;
521 }
522 else
523 {
524 int Le = (p>>16) & 0x7fff;
525 Y = !Le ? 0 : expf(FZ_LN2/256*(Le+.5f) - FZ_LN2*64);
526 /* decode color */
527 u = (1.f/UVSCALE) * ((p>>8 & 0xff) + .5f);
528 v = (1.f/UVSCALE) * ((p & 0xff) + .5f);
529 s = 6*u - 16*v + 12;
530 x = 9 * u;
531 y = 4 * v;
532
533 /* convert to XYZ */
534 X = x/y * Y;
535 Z = (s-x-y)/y * Y;
536 }
537
538 /* assume CCIR-709 primaries */
539 r = 2.690f*X + -1.276f*Y + -0.414f*Z;
540 g = -1.022f*X + 1.978f*Y + 0.044f*Z;
541 b = 0.061f*X + -0.224f*Y + 1.163f*Z;
542
543 /* assume 2.0 gamma for speed */
544 /* could use integer sqrt approx., but this is probably faster */
545 rgb[0] = (uint8_t)((r<=0) ? 0 : (r >= 1) ? 255 : (int)(256*sqrtf(r)));
546 rgb[1] = (uint8_t)((g<=0) ? 0 : (g >= 1) ? 255 : (int)(256*sqrtf(g)));
547 rgb[2] = (uint8_t)((b<=0) ? 0 : (b >= 1) ? 255 : (int)(256*sqrtf(b)));
548}
549
550static int
551next_sgilog32(fz_context *ctx, fz_stream *stm, size_t max)
552{
553 fz_sgilog32 *state = stm->state;
554 uint32_t *p;
555 uint32_t *ep;
556 uint8_t *q;
557 int shift;
558
559 (void)max;
560
561 if (state->run < 0)
562 return EOF;
563
564 memset(state->temp, 0, state->w * sizeof(uint32_t));
565
566 for (shift = 24; shift >= 0; shift -= 8)
567 {
568 p = state->temp;
569 ep = p + state->w;
570 while (p < ep)
571 {
572 if (state->n == 0)
573 {
574 state->run = fz_read_byte(ctx, state->chain);
575 if (state->run < 0)
576 {
577 state->run = -1;
578 fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
579 }
580 if (state->run < 128)
581 state->n = state->run;
582 else
583 {
584 state->n = state->run - 126;
585 state->c = fz_read_byte(ctx, state->chain);
586 if (state->c < 0)
587 {
588 state->run = -1;
589 fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
590 }
591 }
592 }
593
594 if (state->run < 128)
595 {
596 while (p < ep && state->n)
597 {
598 int c = fz_read_byte(ctx, state->chain);
599 if (c < 0)
600 {
601 state->run = -1;
602 fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
603 }
604 *p++ |= c<<shift;
605 state->n--;
606 }
607 }
608 else
609 {
610 while (p < ep && state->n)
611 {
612 *p++ |= state->c<<shift;
613 state->n--;
614 }
615 }
616 }
617 }
618
619 p = state->temp;
620 q = (uint8_t *)p;
621 ep = p + state->w;
622 while (p < ep)
623 {
624 sgilog32val(ctx, *p++, q);
625 q += 3;
626 }
627
628 stm->rp = (uint8_t *)(state->temp);
629 stm->wp = q;
630 stm->pos += q - stm->rp;
631
632 if (q == stm->rp)
633 return EOF;
634
635 return *stm->rp++;
636}
637
638static void
639close_sgilog32(fz_context *ctx, void *state_)
640{
641 fz_sgilog32 *state = (fz_sgilog32 *)state_;
642 fz_drop_stream(ctx, state->chain);
643 fz_free(ctx, state->temp);
644 fz_free(ctx, state);
645}
646
647fz_stream *
648fz_open_sgilog32(fz_context *ctx, fz_stream *chain, int w)
649{
650 fz_sgilog32 *state = fz_malloc_struct(ctx, fz_sgilog32);
651 fz_try(ctx)
652 {
653 state->run = 0;
654 state->n = 0;
655 state->c = 0;
656 state->w = w;
657 state->temp = fz_malloc(ctx, w * sizeof(uint32_t));
658 state->chain = fz_keep_stream(ctx, chain);
659 }
660 fz_catch(ctx)
661 {
662 fz_free(ctx, state->temp);
663 fz_free(ctx, state);
664 fz_rethrow(ctx);
665 }
666 return fz_new_stream(ctx, state, next_sgilog32, close_sgilog32);
667}
668