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 |
14 | static 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 | |
185 | typedef struct fz_sgilog16_s fz_sgilog16; |
186 | |
187 | struct fz_sgilog16_s |
188 | { |
189 | fz_stream *chain; |
190 | int run, n, c, w; |
191 | uint16_t *temp; |
192 | }; |
193 | |
194 | static inline int |
195 | sgilog16val(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 | |
213 | static int |
214 | next_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 | |
300 | static void |
301 | close_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 | |
311 | fz_stream * |
312 | fz_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 | |
337 | typedef struct fz_sgilog24_s fz_sgilog24; |
338 | |
339 | struct fz_sgilog24_s |
340 | { |
341 | fz_stream *chain; |
342 | int err, w; |
343 | uint8_t *temp; |
344 | }; |
345 | |
346 | static int |
347 | uv_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 | |
375 | static inline int |
376 | sgilog24val(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 | |
430 | static int |
431 | next_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 | |
467 | static void |
468 | close_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 | |
478 | fz_stream * |
479 | fz_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 | |
502 | typedef struct fz_sgilog32_s fz_sgilog32; |
503 | |
504 | struct fz_sgilog32_s |
505 | { |
506 | fz_stream *chain; |
507 | int run, n, c, w; |
508 | uint32_t *temp; |
509 | }; |
510 | |
511 | static inline void |
512 | sgilog32val(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 | |
550 | static int |
551 | next_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 | |
638 | static void |
639 | close_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 | |
647 | fz_stream * |
648 | fz_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 | |