comparison mupdf-source/source/fitz/image.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2025 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24
25 #include "context-imp.h"
26 #include "image-imp.h"
27 #include "pixmap-imp.h"
28
29 #include <string.h>
30 #include <math.h>
31 #include <assert.h>
32
33 /* TODO: here or public? */
34 static int
35 fz_key_storable_needs_reaping(fz_context *ctx, const fz_key_storable *ks)
36 {
37 return ks == NULL ? 0 : (ks->store_key_refs == ks->storable.refs);
38 }
39
40 #define SANE_DPI 72.0f
41 #define INSANE_DPI 4800.0f
42
43 #define SCALABLE_IMAGE_DPI 96
44
45 struct fz_compressed_image
46 {
47 fz_image super;
48 fz_compressed_buffer *buffer;
49 };
50
51 struct fz_pixmap_image
52 {
53 fz_image super;
54 fz_pixmap *tile;
55 };
56
57 typedef struct
58 {
59 int refs;
60 fz_image *image;
61 int l2factor;
62 fz_irect rect;
63 } fz_image_key;
64
65 fz_image *
66 fz_keep_image(fz_context *ctx, fz_image *image)
67 {
68 return fz_keep_key_storable(ctx, &image->key_storable);
69 }
70
71 fz_image *
72 fz_keep_image_store_key(fz_context *ctx, fz_image *image)
73 {
74 return fz_keep_key_storable_key(ctx, &image->key_storable);
75 }
76
77 void
78 fz_drop_image_store_key(fz_context *ctx, fz_image *image)
79 {
80 fz_drop_key_storable_key(ctx, &image->key_storable);
81 }
82
83 static int
84 fz_make_hash_image_key(fz_context *ctx, fz_store_hash *hash, void *key_)
85 {
86 fz_image_key *key = (fz_image_key *)key_;
87 hash->u.pir.ptr = key->image;
88 hash->u.pir.i = key->l2factor;
89 hash->u.pir.r = key->rect;
90 return 1;
91 }
92
93 static void *
94 fz_keep_image_key(fz_context *ctx, void *key_)
95 {
96 fz_image_key *key = (fz_image_key *)key_;
97 return fz_keep_imp(ctx, key, &key->refs);
98 }
99
100 static void
101 fz_drop_image_key(fz_context *ctx, void *key_)
102 {
103 fz_image_key *key = (fz_image_key *)key_;
104 if (fz_drop_imp(ctx, key, &key->refs))
105 {
106 fz_drop_image_store_key(ctx, key->image);
107 fz_free(ctx, key);
108 }
109 }
110
111 static int
112 fz_cmp_image_key(fz_context *ctx, void *k0_, void *k1_)
113 {
114 fz_image_key *k0 = (fz_image_key *)k0_;
115 fz_image_key *k1 = (fz_image_key *)k1_;
116 return k0->image == k1->image && k0->l2factor == k1->l2factor && k0->rect.x0 == k1->rect.x0 && k0->rect.y0 == k1->rect.y0 && k0->rect.x1 == k1->rect.x1 && k0->rect.y1 == k1->rect.y1;
117 }
118
119 static void
120 fz_format_image_key(fz_context *ctx, char *s, size_t n, void *key_)
121 {
122 fz_image_key *key = (fz_image_key *)key_;
123 fz_snprintf(s, n, "(image %d x %d sf=%d)", key->image->w, key->image->h, key->l2factor);
124 }
125
126 static int
127 fz_needs_reap_image_key(fz_context *ctx, void *key_)
128 {
129 fz_image_key *key = (fz_image_key *)key_;
130
131 return fz_key_storable_needs_reaping(ctx, &key->image->key_storable);
132 }
133
134 static const fz_store_type fz_image_store_type =
135 {
136 "fz_image",
137 fz_make_hash_image_key,
138 fz_keep_image_key,
139 fz_drop_image_key,
140 fz_cmp_image_key,
141 fz_format_image_key,
142 fz_needs_reap_image_key
143 };
144
145 void
146 fz_drop_image(fz_context *ctx, fz_image *image)
147 {
148 fz_drop_key_storable(ctx, &image->key_storable);
149 }
150
151 static void
152 fz_mask_color_key(fz_context *ctx, fz_pixmap *pix, int n, int bpc, const int *colorkey_in, int indexed)
153 {
154 unsigned char *p = pix->samples;
155 int w;
156 int k, t;
157 int h = pix->h;
158 size_t stride = pix->stride - pix->w * (size_t)pix->n;
159 int colorkey[FZ_MAX_COLORS * 2];
160 int scale, shift, max;
161
162 if (pix->w == 0)
163 return;
164
165 if (indexed)
166 {
167 /* no upscaling or downshifting needed for indexed images */
168 scale = 1;
169 shift = 0;
170 }
171 else
172 {
173 switch (bpc)
174 {
175 case 1: scale = 255; shift = 0; break;
176 case 2: scale = 85; shift = 0; break;
177 case 4: scale = 17; shift = 0; break;
178 default:
179 case 8: scale = 1; shift = 0; break;
180 case 16: scale = 1; shift = 8; break;
181 case 24: scale = 1; shift = 16; break;
182 case 32: scale = 1; shift = 24; break;
183 }
184 }
185
186 switch (bpc)
187 {
188 case 1: max = 1; break;
189 case 2: max = 3; break;
190 case 4: max = 15; break;
191 default:
192 case 8: max = 0xff; break;
193 case 16: max = 0xffff; break;
194 case 24: max = 0xffffff; break;
195 case 32: max = 0xffffffff; break;
196 }
197
198 for (k = 0; k < 2 * n; k++)
199 {
200 colorkey[k] = colorkey_in[k];
201
202 if (colorkey[k] > max)
203 {
204 if (indexed && bpc == 1)
205 {
206 if (k == 0)
207 {
208 fz_warn(ctx, "first color key masking value out of range in 1bpc indexed image, ignoring color key masking");
209 return;
210 }
211 fz_warn(ctx, "later color key masking value out of range in 1bpc indexed image, assumed to be 1");
212 colorkey[k] = 1;
213 }
214 else if (bpc != 1)
215 {
216 fz_warn(ctx, "color key masking value out of range, masking to valid range");
217 colorkey[k] &= max;
218 }
219 }
220
221 if (colorkey[k] < 0 || colorkey[k] > max)
222 {
223 fz_warn(ctx, "color key masking value out of range, clamping to valid range");
224 colorkey[k] = fz_clampi(colorkey[k], 0, max);
225 }
226
227 if (scale > 1)
228 {
229 /* scale up color key masking value so it can be compared with samples. */
230 colorkey[k] *= scale;
231 }
232 else if (shift > 0)
233 {
234 /* shifting down color key masking value so it can be compared with samples. */
235 colorkey[k] >>= shift;
236 }
237 }
238
239 while (h--)
240 {
241 w = pix->w;
242 do
243 {
244 t = 1;
245 for (k = 0; k < n; k++)
246 if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
247 t = 0;
248 if (t)
249 for (k = 0; k < pix->n; k++)
250 p[k] = 0;
251 p += pix->n;
252 }
253 while (--w);
254 p += stride;
255 }
256 }
257
258 static void
259 fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image, const fz_irect *isa)
260 {
261 fz_pixmap *mask;
262 unsigned char *s, *d = tile->samples;
263 int n = tile->n;
264 int k;
265 size_t sstride, dstride = tile->stride - tile->w * (size_t)tile->n;
266 int h;
267 fz_irect subarea;
268
269 /* We need at least as much of the mask as there was of the tile. */
270 if (isa)
271 subarea = *isa;
272 else
273 {
274 subarea.x0 = 0;
275 subarea.y0 = 0;
276 subarea.x1 = tile->w;
277 subarea.y1 = tile->h;
278 }
279
280 mask = fz_get_pixmap_from_image(ctx, image->mask, &subarea, NULL, NULL, NULL);
281 s = mask->samples;
282 /* RJW: Urgh, bit of nastiness here. fz_pixmap_from_image will either return
283 * an exact match for the subarea we asked for, or the full image, and the
284 * normal way to know is that the matrix will be updated. That doesn't help
285 * us here. */
286 if (image->mask->w == mask->w && image->mask->h == mask->h) {
287 subarea.x0 = 0;
288 subarea.y0 = 0;
289 }
290 if (isa)
291 s += (isa->x0 - subarea.x0) * (size_t)mask->n + (isa->y0 - subarea.y0) * (size_t)mask->stride;
292 sstride = mask->stride - tile->w * (size_t)mask->n;
293 h = tile->h;
294
295 if (tile->w != 0)
296 {
297 while (h--)
298 {
299 int w = tile->w;
300 do
301 {
302 if (*s == 0)
303 for (k = 0; k < image->n; k++)
304 d[k] = image->colorkey[k];
305 else
306 for (k = 0; k < image->n; k++)
307 d[k] = fz_clampi(image->colorkey[k] + (d[k] - image->colorkey[k]) * 255 / *s, 0, 255);
308 s++;
309 d += n;
310 }
311 while (--w);
312 s += sstride;
313 d += dstride;
314 }
315 }
316
317 fz_drop_pixmap(ctx, mask);
318 }
319
320 static void fz_adjust_image_subarea(fz_context *ctx, fz_image *image, fz_irect *subarea, int l2factor)
321 {
322 int f = 1<<l2factor;
323 int bpp = image->bpc * image->n;
324 int mask;
325
326 switch (bpp)
327 {
328 case 1: mask = 8*f; break;
329 case 2: mask = 4*f; break;
330 case 4: mask = 2*f; break;
331 default: mask = (bpp & 7) == 0 ? f : 0; break;
332 }
333
334 if (mask != 0)
335 {
336 subarea->x0 &= ~(mask - 1);
337 subarea->x1 = (subarea->x1 + mask - 1) & ~(mask - 1);
338 }
339 else
340 {
341 /* Awkward case - mask cannot be a power of 2. */
342 mask = bpp*f;
343 switch (bpp)
344 {
345 case 3:
346 case 5:
347 case 7:
348 case 9:
349 case 11:
350 case 13:
351 case 15:
352 default:
353 mask *= 8;
354 break;
355 case 6:
356 case 10:
357 case 14:
358 mask *= 4;
359 break;
360 case 12:
361 mask *= 2;
362 break;
363 }
364 subarea->x0 = (subarea->x0 / mask) * mask;
365 subarea->x1 = ((subarea->x1 + mask - 1) / mask) * mask;
366 }
367
368 subarea->y0 &= ~(f - 1);
369 if (subarea->x1 > image->w)
370 subarea->x1 = image->w;
371 subarea->y1 = (subarea->y1 + f - 1) & ~(f - 1);
372 if (subarea->y1 > image->h)
373 subarea->y1 = image->h;
374 }
375
376 static void fz_compute_image_key(fz_context *ctx, fz_image *image, fz_matrix *ctm,
377 fz_image_key *key, const fz_irect *subarea, int l2factor, int *w, int *h, int *dw, int *dh)
378 {
379 key->refs = 1;
380 key->image = image;
381 key->l2factor = l2factor;
382
383 if (subarea == NULL)
384 {
385 key->rect.x0 = 0;
386 key->rect.y0 = 0;
387 key->rect.x1 = image->w;
388 key->rect.y1 = image->h;
389 }
390 else
391 {
392 key->rect = *subarea;
393 ctx->tuning->image_decode(ctx->tuning->image_decode_arg, image->w, image->h, key->l2factor, &key->rect);
394 fz_adjust_image_subarea(ctx, image, &key->rect, key->l2factor);
395 }
396
397 /* Based on that subarea, recalculate the extents */
398 if (ctm)
399 {
400 float frac_w = (float) (key->rect.x1 - key->rect.x0) / image->w;
401 float frac_h = (float) (key->rect.y1 - key->rect.y0) / image->h;
402 float a = ctm->a * frac_w;
403 float b = ctm->b * frac_w;
404 float c = ctm->c * frac_h;
405 float d = ctm->d * frac_h;
406 *w = sqrtf(a * a + b * b);
407 *h = sqrtf(c * c + d * d);
408 }
409 else
410 {
411 *w = image->w;
412 *h = image->h;
413 }
414
415 /* Return the true sizes to the caller */
416 if (dw)
417 *dw = *w;
418 if (dh)
419 *dh = *h;
420 if (*w > image->w)
421 *w = image->w;
422 if (*h > image->h)
423 *h = image->h;
424
425 if (*w == 0 || *h == 0)
426 key->l2factor = 0;
427 }
428
429 typedef struct {
430 fz_stream *src;
431 size_t l_skip; /* Number of bytes to skip on the left. */
432 size_t r_skip; /* Number of bytes to skip on the right. */
433 size_t b_skip; /* Number of bytes to skip on the bottom. */
434 int lines; /* Number of lines left to copy. */
435 size_t stride; /* Number of bytes to read in the image. */
436 size_t nskip; /* Number of bytes left to skip on this line. */
437 size_t nread; /* Number of bytes left to read on this line. */
438 } subarea_state;
439
440 static int
441 subarea_next(fz_context *ctx, fz_stream *stm, size_t len)
442 {
443 subarea_state *state = stm->state;
444 size_t n;
445
446 stm->wp = stm->rp = NULL;
447
448 while (state->nskip > 0)
449 {
450 n = fz_skip(ctx, state->src, state->nskip);
451 if (n == 0)
452 return EOF;
453 state->nskip -= n;
454 }
455 if (state->lines == 0)
456 return EOF;
457 n = fz_available(ctx, state->src, state->nread);
458 if (n > state->nread)
459 n = state->nread;
460 if (n == 0)
461 return EOF;
462 stm->rp = state->src->rp;
463 stm->wp = stm->rp + n;
464 stm->pos += n;
465 state->src->rp = stm->wp;
466 state->nread -= n;
467 if (state->nread == 0)
468 {
469 state->lines--;
470 if (state->lines == 0)
471 state->nskip = state->r_skip + state->b_skip;
472 else
473 state->nskip = state->l_skip + state->r_skip;
474 state->nread = state->stride;
475 }
476 return *stm->rp++;
477 }
478
479 static void
480 subarea_drop(fz_context *ctx, void *state)
481 {
482 fz_free(ctx, state);
483 }
484
485 static fz_stream *
486 subarea_stream(fz_context *ctx, fz_stream *stm, fz_image *image, const fz_irect *subarea, int l2factor)
487 {
488 subarea_state *state;
489 int f = 1<<l2factor;
490 int stream_w = (image->w + f - 1)>>l2factor;
491 size_t stream_stride = (stream_w * (size_t)image->n * image->bpc + 7) / 8;
492 int l_margin = subarea->x0 >> l2factor;
493 int t_margin = subarea->y0 >> l2factor;
494 int r_margin = (image->w + f - 1 - subarea->x1) >> l2factor;
495 int b_margin = (image->h + f - 1 - subarea->y1) >> l2factor;
496 size_t l_skip = (l_margin * (size_t)image->n * image->bpc)/8;
497 size_t r_skip = (r_margin * (size_t)image->n * image->bpc + 7)/8;
498 size_t t_skip = t_margin * stream_stride;
499 size_t b_skip = b_margin * stream_stride;
500 int h = (subarea->y1 - subarea->y0 + f - 1) >> l2factor;
501 int w = (subarea->x1 - subarea->x0 + f - 1) >> l2factor;
502 size_t stride = (w * (size_t)image->n * image->bpc + 7) / 8;
503
504 state = fz_malloc_struct(ctx, subarea_state);
505 state->src = stm;
506 state->l_skip = l_skip;
507 state->r_skip = r_skip;
508 state->b_skip = b_skip;
509 state->lines = h;
510 state->nskip = l_skip+t_skip;
511 state->stride = stride;
512 state->nread = stride;
513
514 return fz_new_stream(ctx, state, subarea_next, subarea_drop);
515 }
516
517 typedef struct
518 {
519 fz_stream *src;
520 int w; /* Width in source pixels. */
521 int h; /* Height (remaining) in scanlines. */
522 int n; /* Number of components. */
523 int f; /* Fill level (how many scanlines we've copied in). */
524 size_t r; /* How many samples Remain to be filled in this line. */
525 int l2; /* The amount of subsampling we're doing. */
526 unsigned char data[1];
527 } l2sub_state;
528
529 static void
530 subsample_drop(fz_context *ctx, void *state)
531 {
532 fz_free(ctx, state);
533 }
534
535 static int
536 subsample_next(fz_context *ctx, fz_stream *stm, size_t len)
537 {
538 l2sub_state *state = (l2sub_state *)stm->state;
539 size_t fill;
540
541 stm->rp = stm->wp = &state->data[0];
542 if (state->h == 0)
543 return EOF;
544
545 /* Copy in data */
546 do
547 {
548 if (state->r == 0)
549 state->r = state->w * (size_t)state->n;
550
551 while (state->r > 0)
552 {
553 size_t a;
554 a = fz_available(ctx, state->src, state->r);
555 if (a == 0)
556 return EOF;
557 if (a > state->r)
558 a = state->r;
559 memcpy(&state->data[state->w * (size_t)state->n * (state->f+1) - state->r],
560 state->src->rp, a);
561 state->src->rp += a;
562 state->r -= a;
563 }
564 state->f++;
565 state->h--;
566 }
567 while (state->h > 0 && state->f != (1<<state->l2));
568
569 /* Perform the subsample */
570 fz_subsample_pixblock(state->data, state->w, state->f, state->n, state->l2, state->w * (size_t)state->n);
571 state->f = 0;
572
573 /* Update data pointers. */
574 fill = ((state->w + (1<<state->l2) - 1)>>state->l2) * (size_t)state->n;
575 stm->pos += fill;
576 stm->rp = &state->data[0];
577 stm->wp = &state->data[fill];
578
579 return *stm->rp++;
580 }
581
582 static fz_stream *
583 subsample_stream(fz_context *ctx, fz_stream *src, int w, int h, int n, int l2extra)
584 {
585 l2sub_state *state = fz_malloc(ctx, sizeof(l2sub_state) + w*(size_t)(n<<l2extra));
586
587 state->src = src;
588 state->w = w;
589 state->h = h;
590 state->n = n;
591 state->f = 0;
592 state->r = 0;
593 state->l2 = l2extra;
594
595 return fz_new_stream(ctx, state, subsample_next, subsample_drop);
596 }
597
598 /* l2factor is the amount of subsampling that the decoder is going to be
599 * doing for us already. (So for JPEG 0,1,2,3 corresponding to 1, 2, 4,
600 * 8. For other formats, probably 0.). l2extra is the additional amount
601 * of subsampling we should perform here. */
602 fz_pixmap *
603 fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_compressed_image *cimg, fz_irect *subarea, int indexed, int l2factor, int *l2extra)
604 {
605 fz_image *image = &cimg->super;
606 fz_pixmap *tile = NULL;
607 size_t stride, len, i;
608 unsigned char *samples = NULL;
609 int f = 1<<l2factor;
610 int w = image->w;
611 int h = image->h;
612 int matte = image->use_colorkey && image->mask;
613 fz_stream *read_stream = stm;
614 fz_stream *sstream = NULL;
615 fz_stream *l2stream = NULL;
616 fz_stream *unpstream = NULL;
617
618 if (matte)
619 {
620 /* Can't do l2factor decoding */
621 if (image->w != image->mask->w || image->h != image->mask->h)
622 {
623 fz_warn(ctx, "mask must be of same size as image for /Matte");
624 matte = 0;
625 }
626 assert(l2factor == 0);
627 }
628 if (subarea)
629 {
630 if (subarea->x0 == 0 && subarea->x1 == image->w &&
631 subarea->y0 == 0 && subarea->y1 == image->h)
632 subarea = NULL;
633 else
634 {
635 fz_adjust_image_subarea(ctx, image, subarea, l2factor);
636 w = (subarea->x1 - subarea->x0);
637 h = (subarea->y1 - subarea->y0);
638 }
639 }
640 w = (w + f - 1) >> l2factor;
641 h = (h + f - 1) >> l2factor;
642
643 fz_var(tile);
644 fz_var(samples);
645 fz_var(sstream);
646 fz_var(unpstream);
647 fz_var(l2stream);
648
649 fz_try(ctx)
650 {
651 int alpha = (image->colorspace == NULL);
652 if (image->use_colorkey)
653 alpha = 1;
654
655 if (subarea)
656 read_stream = sstream = subarea_stream(ctx, stm, image, subarea, l2factor);
657 if (image->bpc != 8 || image->use_colorkey)
658 read_stream = unpstream = fz_unpack_stream(ctx, read_stream, image->bpc, w, h, image->n, indexed, image->use_colorkey, 0);
659 if (l2extra && *l2extra && !indexed)
660 {
661 read_stream = l2stream = subsample_stream(ctx, read_stream, w, h, image->n + image->use_colorkey, *l2extra);
662 w = (w + (1<<*l2extra) - 1)>>*l2extra;
663 h = (h + (1<<*l2extra) - 1)>>*l2extra;
664 *l2extra = 0;
665 }
666
667 tile = fz_new_pixmap(ctx, image->colorspace, w, h, NULL, alpha);
668 if (image->interpolate & FZ_PIXMAP_FLAG_INTERPOLATE)
669 tile->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
670 else
671 tile->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
672
673 samples = tile->samples;
674 stride = tile->stride;
675
676 len = fz_read(ctx, read_stream, samples, h * stride);
677
678 /* Pad truncated images */
679 if (len < stride * h)
680 {
681 fz_warn(ctx, "padding truncated image");
682 memset(samples + len, 0, stride * h - len);
683 }
684
685 /* Invert 1-bit image masks */
686 if (image->imagemask)
687 {
688 /* 0=opaque and 1=transparent so we need to invert */
689 unsigned char *p = samples;
690 len = h * stride;
691 for (i = 0; i < len; i++)
692 p[i] = ~p[i];
693 }
694
695 /* color keyed transparency */
696 if (image->use_colorkey && !image->mask)
697 fz_mask_color_key(ctx, tile, image->n, image->bpc, image->colorkey, indexed);
698
699 if (indexed)
700 {
701 fz_pixmap *conv;
702 fz_decode_indexed_tile(ctx, tile, image->decode, (1 << image->bpc) - 1);
703 conv = fz_convert_indexed_pixmap_to_base(ctx, tile);
704 fz_drop_pixmap(ctx, tile);
705 tile = conv;
706 }
707 else if (image->use_decode)
708 {
709 fz_decode_tile(ctx, tile, image->decode);
710 }
711
712 /* pre-blended matte color */
713 if (matte)
714 fz_unblend_masked_tile(ctx, tile, image, subarea);
715 }
716 fz_always(ctx)
717 {
718 fz_drop_stream(ctx, sstream);
719 fz_drop_stream(ctx, unpstream);
720 fz_drop_stream(ctx, l2stream);
721 }
722 fz_catch(ctx)
723 {
724 fz_drop_pixmap(ctx, tile);
725 fz_rethrow(ctx);
726 }
727
728 return tile;
729 }
730
731 void
732 fz_drop_image_base(fz_context *ctx, fz_image *image)
733 {
734 fz_drop_colorspace(ctx, image->colorspace);
735 fz_drop_image(ctx, image->mask);
736 fz_free(ctx, image);
737 }
738
739 void
740 fz_drop_image_imp(fz_context *ctx, fz_storable *image_)
741 {
742 fz_image *image = (fz_image *)image_;
743
744 image->drop_image(ctx, image);
745 fz_drop_image_base(ctx, image);
746 }
747
748 static void
749 drop_compressed_image(fz_context *ctx, fz_image *image_)
750 {
751 fz_compressed_image *image = (fz_compressed_image *)image_;
752
753 fz_drop_compressed_buffer(ctx, image->buffer);
754 }
755
756 static void
757 drop_pixmap_image(fz_context *ctx, fz_image *image_)
758 {
759 fz_pixmap_image *image = (fz_pixmap_image *)image_;
760
761 fz_drop_pixmap(ctx, image->tile);
762 }
763
764 int
765 fz_is_lossy_image(fz_context *ctx, fz_image *image)
766 {
767 fz_compressed_buffer *cbuf = fz_compressed_image_buffer(ctx, image);
768 if (cbuf)
769 {
770 switch (cbuf->params.type)
771 {
772 case FZ_IMAGE_JPEG:
773 case FZ_IMAGE_JPX:
774 case FZ_IMAGE_JXR:
775 return 1;
776 }
777 }
778 return 0;
779 }
780
781 static fz_pixmap *
782 compressed_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
783 {
784 fz_compressed_image *image = (fz_compressed_image *)image_;
785 int native_l2factor;
786 fz_stream *stm;
787 int indexed;
788 fz_pixmap *tile;
789 int can_sub = 0;
790 int local_l2factor;
791
792 /* If we are using matte, then the decode code requires both image and tile sizes
793 * to match. The simplest way to ensure this is to do no native l2factor decoding.
794 */
795 if (image->super.use_colorkey && image->super.mask)
796 {
797 local_l2factor = 0;
798 l2factor = &local_l2factor;
799 }
800
801 /* We need to make a new one. */
802 /* First check for ones that we can't decode using streams */
803 switch (image->buffer->params.type)
804 {
805 case FZ_IMAGE_PNG:
806 tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
807 break;
808 case FZ_IMAGE_GIF:
809 tile = fz_load_gif(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
810 break;
811 case FZ_IMAGE_BMP:
812 tile = fz_load_bmp(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
813 break;
814 case FZ_IMAGE_TIFF:
815 tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
816 break;
817 case FZ_IMAGE_PNM:
818 tile = fz_load_pnm(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
819 break;
820 case FZ_IMAGE_JXR:
821 tile = fz_load_jxr(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
822 break;
823 case FZ_IMAGE_JPX:
824 tile = fz_load_jpx(ctx, image->buffer->buffer->data, image->buffer->buffer->len, image->super.colorspace);
825 break;
826 case FZ_IMAGE_PSD:
827 tile = fz_load_psd(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
828 break;
829 case FZ_IMAGE_JPEG:
830 /* Scan JPEG stream and patch missing height values in header */
831 {
832 unsigned char *s = image->buffer->buffer->data;
833 unsigned char *e = s + image->buffer->buffer->len;
834 unsigned char *d;
835 for (d = s + 2; s < d && d + 9 < e && d[0] == 0xFF; d += (d[2] << 8 | d[3]) + 2)
836 {
837 if (d[1] < 0xC0 || (0xC3 < d[1] && d[1] < 0xC9) || 0xCB < d[1])
838 continue;
839 if ((d[5] == 0 && d[6] == 0) || ((d[5] << 8) | d[6]) > image->super.h)
840 {
841 d[5] = (image->super.h >> 8) & 0xFF;
842 d[6] = image->super.h & 0xFF;
843 }
844 }
845 }
846 /* fall through */
847
848 default:
849 native_l2factor = l2factor ? *l2factor : 0;
850 stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, l2factor);
851 fz_try(ctx)
852 {
853 if (l2factor)
854 native_l2factor -= *l2factor;
855 indexed = fz_colorspace_is_indexed(ctx, image->super.colorspace);
856 can_sub = 1;
857 tile = fz_decomp_image_from_stream(ctx, stm, image, subarea, indexed, native_l2factor, l2factor);
858 }
859 fz_always(ctx)
860 fz_drop_stream(ctx, stm);
861 fz_catch(ctx)
862 fz_rethrow(ctx);
863
864 break;
865 }
866
867 if (can_sub == 0 && subarea != NULL)
868 {
869 subarea->x0 = 0;
870 subarea->y0 = 0;
871 subarea->x1 = image->super.w;
872 subarea->y1 = image->super.h;
873 }
874
875 return tile;
876 }
877
878 static fz_pixmap *
879 pixmap_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
880 {
881 fz_pixmap_image *image = (fz_pixmap_image *)image_;
882
883 /* 'Simple' images created direct from pixmaps will have no buffer
884 * of compressed data. We cannot do any better than just returning
885 * a pointer to the original 'tile'.
886 */
887 return fz_keep_pixmap(ctx, image->tile); /* That's all we can give you! */
888 }
889
890 static void
891 update_ctm_for_subarea(fz_matrix *ctm, const fz_irect *subarea, int w, int h)
892 {
893 fz_matrix m;
894
895 if (ctm == NULL || (subarea->x0 == 0 && subarea->y0 == 0 && subarea->x1 == w && subarea->y1 == h))
896 return;
897
898 m.a = (float) (subarea->x1 - subarea->x0) / w;
899 m.b = 0;
900 m.c = 0;
901 m.d = (float) (subarea->y1 - subarea->y0) / h;
902 m.e = (float) subarea->x0 / w;
903 m.f = (float) subarea->y0 / h;
904 *ctm = fz_concat(m, *ctm);
905 }
906
907 void fz_default_image_decode(void *arg, int w, int h, int l2factor, fz_irect *subarea)
908 {
909 (void)arg;
910
911 if ((subarea->x1-subarea->x0)*(subarea->y1-subarea->y0) >= (w*h/10)*9)
912 {
913 /* Either no subarea specified, or a subarea 90% or more of the
914 * whole area specified. Use the whole image. */
915 subarea->x0 = 0;
916 subarea->y0 = 0;
917 subarea->x1 = w;
918 subarea->y1 = h;
919 }
920 else
921 {
922 /* Clip to the edges if they are within 1% */
923 if (subarea->x0 <= w/100)
924 subarea->x0 = 0;
925 if (subarea->y0 <= h/100)
926 subarea->y0 = 0;
927 if (subarea->x1 >= w*99/100)
928 subarea->x1 = w;
929 if (subarea->y1 >= h*99/100)
930 subarea->y1 = h;
931 }
932 }
933
934 static fz_pixmap *
935 fz_find_image_tile(fz_context *ctx, fz_image *image, fz_image_key *key, fz_matrix *ctm)
936 {
937 fz_pixmap *tile;
938 do
939 {
940 tile = fz_find_item(ctx, fz_drop_pixmap_imp, key, &fz_image_store_type);
941 if (tile)
942 {
943 update_ctm_for_subarea(ctm, &key->rect, image->w, image->h);
944 return tile;
945 }
946 key->l2factor--;
947 }
948 while (key->l2factor >= 0);
949 return NULL;
950 }
951
952 fz_pixmap *
953 fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, const fz_irect *subarea, fz_matrix *ctm, int *dw, int *dh)
954 {
955 fz_pixmap *tile;
956 int l2factor, l2factor_remaining;
957 fz_image_key key;
958 fz_image_key *keyp = NULL;
959 int w;
960 int h;
961
962 fz_var(keyp);
963
964 if (!image)
965 return NULL;
966
967 /* Figure out the extent. */
968 if (ctm)
969 {
970 w = sqrtf(ctm->a * ctm->a + ctm->b * ctm->b);
971 h = sqrtf(ctm->c * ctm->c + ctm->d * ctm->d);
972 }
973 else
974 {
975 w = image->w;
976 h = image->h;
977 }
978
979 if (image->scalable)
980 {
981 /* If the image is scalable, we always want to re-render and never cache. */
982 fz_irect subarea_copy;
983 if (subarea)
984 subarea_copy = *subarea;
985 l2factor_remaining = 0;
986 if (dw) *dw = w;
987 if (dh) *dh = h;
988 return image->get_pixmap(ctx, image, subarea ? &subarea_copy : NULL, image->w, image->h, &l2factor_remaining);
989 }
990
991 /* Clamp requested image size, since we never want to magnify images here. */
992 if (w > image->w)
993 w = image->w;
994 if (h > image->h)
995 h = image->h;
996
997 if (image->decoded)
998 {
999 /* If the image is already decoded, then we can't offer a subarea,
1000 * or l2factor, and we don't want to cache. */
1001 l2factor_remaining = 0;
1002 if (dw) *dw = w;
1003 if (dh) *dh = h;
1004 return image->get_pixmap(ctx, image, NULL, image->w, image->h, &l2factor_remaining);
1005 }
1006
1007 /* What is our ideal factor? We search for the largest factor where
1008 * we can subdivide and stay larger than the required size. We add
1009 * a fudge factor of +2 here to allow for the possibility of
1010 * expansion due to grid fitting. */
1011 l2factor = 0;
1012 if (w > 0 && h > 0)
1013 {
1014 while (image->w>>(l2factor+1) >= w+2 && image->h>>(l2factor+1) >= h+2 && l2factor < 6)
1015 l2factor++;
1016 }
1017
1018 /* First, look through the store for existing tiles */
1019 if (subarea)
1020 {
1021 fz_compute_image_key(ctx, image, ctm, &key, subarea, l2factor, &w, &h, dw, dh);
1022 tile = fz_find_image_tile(ctx, image, &key, ctm);
1023 if (tile)
1024 return tile;
1025 }
1026
1027 /* No subarea given, or no tile for subarea found; try entire image */
1028 fz_compute_image_key(ctx, image, ctm, &key, NULL, l2factor, &w, &h, dw, dh);
1029 tile = fz_find_image_tile(ctx, image, &key, ctm);
1030 if (tile)
1031 return tile;
1032
1033 /* Neither subarea nor full image tile found; prepare the subarea key again */
1034 if (subarea)
1035 fz_compute_image_key(ctx, image, ctm, &key, subarea, l2factor, &w, &h, dw, dh);
1036
1037 /* We'll have to decode the image; request the correct amount of downscaling. */
1038 l2factor_remaining = l2factor;
1039 tile = image->get_pixmap(ctx, image, &key.rect, w, h, &l2factor_remaining);
1040
1041 /* Update the ctm to allow for subareas. */
1042 update_ctm_for_subarea(ctm, &key.rect, image->w, image->h);
1043
1044 /* l2factor_remaining is updated to the amount of subscaling left to do */
1045 assert(l2factor_remaining >= 0 && l2factor_remaining <= 6);
1046 if (l2factor_remaining)
1047 {
1048 fz_try(ctx)
1049 fz_subsample_pixmap(ctx, tile, l2factor_remaining);
1050 fz_catch(ctx)
1051 {
1052 fz_drop_pixmap(ctx, tile);
1053 fz_rethrow(ctx);
1054 }
1055 }
1056
1057 fz_try(ctx)
1058 {
1059 fz_pixmap *existing_tile;
1060
1061 /* Now we try to cache the pixmap. Any failure here will just result
1062 * in us not caching. */
1063 keyp = fz_malloc_struct(ctx, fz_image_key);
1064 keyp->refs = 1;
1065 keyp->image = fz_keep_image_store_key(ctx, image);
1066 keyp->l2factor = l2factor;
1067 keyp->rect = key.rect;
1068
1069 existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
1070 if (existing_tile)
1071 {
1072 /* We already have a tile. This must have been produced by a
1073 * racing thread. We'll throw away ours and use that one. */
1074 fz_drop_pixmap(ctx, tile);
1075 tile = existing_tile;
1076 }
1077 }
1078 fz_always(ctx)
1079 {
1080 fz_drop_image_key(ctx, keyp);
1081 }
1082 fz_catch(ctx)
1083 {
1084 /* Do nothing */
1085 fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
1086 fz_report_error(ctx);
1087 }
1088
1089 return tile;
1090 }
1091
1092 fz_pixmap *
1093 fz_get_unscaled_pixmap_from_image(fz_context *ctx, fz_image *image)
1094 {
1095 return fz_get_pixmap_from_image(ctx, image, NULL /*subarea*/, NULL /*ctm*/, NULL /*dw*/, NULL /*dh*/);
1096 }
1097
1098 static size_t
1099 pixmap_image_get_size(fz_context *ctx, fz_image *image)
1100 {
1101 fz_pixmap_image *im = (fz_pixmap_image *)image;
1102
1103 if (image == NULL)
1104 return 0;
1105
1106 return sizeof(fz_pixmap_image) + fz_pixmap_size(ctx, im->tile);
1107 }
1108
1109 size_t fz_image_size(fz_context *ctx, fz_image *im)
1110 {
1111 if (im == NULL)
1112 return 0;
1113
1114 return im->get_size(ctx, im);
1115 }
1116
1117 fz_image *
1118 fz_new_image_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, fz_image *mask)
1119 {
1120 fz_pixmap_image *image;
1121
1122 image = fz_new_derived_image(ctx, pixmap->w, pixmap->h, 8, pixmap->colorspace,
1123 pixmap->xres, pixmap->yres, 0, 0,
1124 NULL, NULL, mask, fz_pixmap_image,
1125 pixmap_image_get_pixmap,
1126 pixmap_image_get_size,
1127 drop_pixmap_image);
1128 image->tile = fz_keep_pixmap(ctx, pixmap);
1129 image->super.decoded = 1;
1130
1131 return &image->super;
1132 }
1133
1134 fz_image *
1135 fz_new_image_of_size(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace,
1136 int xres, int yres, int interpolate, int imagemask, const float *decode,
1137 const int *colorkey, fz_image *mask, size_t size,
1138 fz_image_get_pixmap_fn *get_pixmap,
1139 fz_image_get_size_fn *get_size,
1140 fz_drop_image_fn *drop)
1141 {
1142 fz_image *image;
1143 int i;
1144
1145 assert(mask == NULL || mask->mask == NULL);
1146 assert(size >= sizeof(fz_image));
1147
1148 image = Memento_label(fz_calloc(ctx, 1, size), "fz_image");
1149 FZ_INIT_KEY_STORABLE(image, 1, fz_drop_image_imp);
1150 image->drop_image = drop;
1151 image->get_pixmap = get_pixmap;
1152 image->get_size = get_size;
1153 image->w = w;
1154 image->h = h;
1155 image->xres = xres;
1156 image->yres = yres;
1157 image->bpc = bpc;
1158 image->n = (colorspace ? fz_colorspace_n(ctx, colorspace) : 1);
1159 image->colorspace = fz_keep_colorspace(ctx, colorspace);
1160 image->interpolate = interpolate;
1161 image->imagemask = imagemask;
1162 image->intent = 0;
1163 image->has_intent = 0;
1164 image->use_colorkey = (colorkey != NULL);
1165 if (colorkey)
1166 memcpy(image->colorkey, colorkey, sizeof(int)*image->n*2);
1167 image->use_decode = 0;
1168 if (decode)
1169 {
1170 memcpy(image->decode, decode, sizeof(float)*image->n*2);
1171 }
1172 else
1173 {
1174 float maxval = fz_colorspace_is_indexed(ctx, colorspace) ? (1 << bpc) - 1 : 1;
1175 for (i = 0; i < image->n; i++)
1176 {
1177 image->decode[2*i] = 0;
1178 image->decode[2*i+1] = maxval;
1179 }
1180 }
1181 /* ICC spaces have the default decode arrays pickled into them.
1182 * For most spaces this is fine, because [ 0 1 0 1 0 1 ] is
1183 * idempotent. For Lab, however, we need to adjust it. */
1184 if (fz_colorspace_is_lab_icc(ctx, colorspace))
1185 {
1186 /* Undo the default decode array of [0 100 -128 127 -128 127] */
1187 image->decode[0] = image->decode[0]/100.0f;
1188 image->decode[1] = image->decode[1]/100.0f;
1189 image->decode[2] = (image->decode[2]+128)/255.0f;
1190 image->decode[3] = (image->decode[3]+128)/255.0f;
1191 image->decode[4] = (image->decode[4]+128)/255.0f;
1192 image->decode[5] = (image->decode[5]+128)/255.0f;
1193 }
1194 for (i = 0; i < image->n; i++)
1195 {
1196 if (image->decode[i * 2] != 0 || image->decode[i * 2 + 1] != 1)
1197 break;
1198 }
1199 if (i != image->n)
1200 image->use_decode = 1;
1201 image->mask = fz_keep_image(ctx, mask);
1202
1203 return image;
1204 }
1205
1206 static size_t
1207 compressed_image_get_size(fz_context *ctx, fz_image *image)
1208 {
1209 fz_compressed_image *im = (fz_compressed_image *)image;
1210
1211 if (image == NULL)
1212 return 0;
1213
1214 return sizeof(fz_pixmap_image) + (im->buffer && im->buffer->buffer ? im->buffer->buffer->cap : 0);
1215 }
1216
1217 fz_image *
1218 fz_new_image_from_compressed_buffer(fz_context *ctx, int w, int h,
1219 int bpc, fz_colorspace *colorspace,
1220 int xres, int yres, int interpolate, int imagemask, const float *decode,
1221 const int *colorkey, fz_compressed_buffer *buffer, fz_image *mask)
1222 {
1223 fz_compressed_image *image;
1224
1225 fz_try(ctx)
1226 {
1227 image = fz_new_derived_image(ctx, w, h, bpc,
1228 colorspace, xres, yres,
1229 interpolate, imagemask, decode,
1230 colorkey, mask, fz_compressed_image,
1231 compressed_image_get_pixmap,
1232 compressed_image_get_size,
1233 drop_compressed_image);
1234 image->buffer = buffer;
1235 }
1236 fz_catch(ctx)
1237 {
1238 fz_drop_compressed_buffer(ctx, buffer);
1239 fz_rethrow(ctx);
1240 }
1241
1242 return &image->super;
1243 }
1244
1245 fz_compressed_buffer *fz_compressed_image_buffer(fz_context *ctx, fz_image *image)
1246 {
1247 if (image == NULL || image->get_pixmap != compressed_image_get_pixmap)
1248 return NULL;
1249 return ((fz_compressed_image *)image)->buffer;
1250 }
1251
1252 void fz_set_compressed_image_buffer(fz_context *ctx, fz_compressed_image *image, fz_compressed_buffer *buf)
1253 {
1254 assert(image != NULL && image->super.get_pixmap == compressed_image_get_pixmap);
1255 ((fz_compressed_image *)image)->buffer = buf; /* Note: compressed buffers are not reference counted */
1256 }
1257
1258 fz_pixmap *fz_pixmap_image_tile(fz_context *ctx, fz_pixmap_image *image)
1259 {
1260 if (image == NULL || image->super.get_pixmap != pixmap_image_get_pixmap)
1261 return NULL;
1262 return ((fz_pixmap_image *)image)->tile;
1263 }
1264
1265 void fz_set_pixmap_image_tile(fz_context *ctx, fz_pixmap_image *image, fz_pixmap *pix)
1266 {
1267 assert(image != NULL && image->super.get_pixmap == pixmap_image_get_pixmap);
1268 ((fz_pixmap_image *)image)->tile = pix;
1269 }
1270
1271 const char *
1272 fz_image_type_name(int type)
1273 {
1274 switch (type)
1275 {
1276 default:
1277 case FZ_IMAGE_UNKNOWN: return "unknown";
1278 case FZ_IMAGE_RAW: return "raw";
1279 case FZ_IMAGE_FAX: return "fax";
1280 case FZ_IMAGE_FLATE: return "flate";
1281 case FZ_IMAGE_LZW: return "lzw";
1282 case FZ_IMAGE_RLD: return "rld";
1283 case FZ_IMAGE_BROTLI: return "brotli";
1284 case FZ_IMAGE_BMP: return "bmp";
1285 case FZ_IMAGE_GIF: return "gif";
1286 case FZ_IMAGE_JBIG2: return "jbig2";
1287 case FZ_IMAGE_JPEG: return "jpeg";
1288 case FZ_IMAGE_JPX: return "jpx";
1289 case FZ_IMAGE_JXR: return "jxr";
1290 case FZ_IMAGE_PNG: return "png";
1291 case FZ_IMAGE_PNM: return "pnm";
1292 case FZ_IMAGE_TIFF: return "tiff";
1293 }
1294 }
1295
1296 int
1297 fz_lookup_image_type(const char *type)
1298 {
1299 if (type == NULL) return FZ_IMAGE_UNKNOWN;
1300 if (!strcmp(type, "raw")) return FZ_IMAGE_RAW;
1301 if (!strcmp(type, "fax")) return FZ_IMAGE_FAX;
1302 if (!strcmp(type, "flate")) return FZ_IMAGE_FLATE;
1303 if (!strcmp(type, "lzw")) return FZ_IMAGE_LZW;
1304 if (!strcmp(type, "rld")) return FZ_IMAGE_RLD;
1305 if (!strcmp(type, "brotli")) return FZ_IMAGE_BROTLI;
1306 if (!strcmp(type, "bmp")) return FZ_IMAGE_BMP;
1307 if (!strcmp(type, "gif")) return FZ_IMAGE_GIF;
1308 if (!strcmp(type, "jbig2")) return FZ_IMAGE_JBIG2;
1309 if (!strcmp(type, "jpeg")) return FZ_IMAGE_JPEG;
1310 if (!strcmp(type, "jpx")) return FZ_IMAGE_JPX;
1311 if (!strcmp(type, "jxr")) return FZ_IMAGE_JXR;
1312 if (!strcmp(type, "png")) return FZ_IMAGE_PNG;
1313 if (!strcmp(type, "pnm")) return FZ_IMAGE_PNM;
1314 if (!strcmp(type, "tiff")) return FZ_IMAGE_TIFF;
1315 return FZ_IMAGE_UNKNOWN;
1316 }
1317
1318 int
1319 fz_recognize_image_format(fz_context *ctx, unsigned char p[8])
1320 {
1321 if (p[0] == 'P' && p[1] >= '1' && p[1] <= '7')
1322 return FZ_IMAGE_PNM;
1323 if (p[0] == 'P' && (p[1] == 'F' || p[1] == 'f'))
1324 return FZ_IMAGE_PNM;
1325 if (p[0] == 0xff && p[1] == 0x4f)
1326 return FZ_IMAGE_JPX;
1327 if (p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c &&
1328 p[4] == 0x6a && p[5] == 0x50 && p[6] == 0x20 && p[7] == 0x20)
1329 return FZ_IMAGE_JPX;
1330 if (p[0] == 0xff && p[1] == 0xd8)
1331 return FZ_IMAGE_JPEG;
1332 if (p[0] == 137 && p[1] == 80 && p[2] == 78 && p[3] == 71 &&
1333 p[4] == 13 && p[5] == 10 && p[6] == 26 && p[7] == 10)
1334 return FZ_IMAGE_PNG;
1335 if (p[0] == 'I' && p[1] == 'I' && p[2] == 0xBC)
1336 return FZ_IMAGE_JXR;
1337 if (p[0] == 'I' && p[1] == 'I' && p[2] == 42 && p[3] == 0)
1338 return FZ_IMAGE_TIFF;
1339 if (p[0] == 'M' && p[1] == 'M' && p[2] == 0 && p[3] == 42)
1340 return FZ_IMAGE_TIFF;
1341 if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F')
1342 return FZ_IMAGE_GIF;
1343 if (p[0] == 'B' && p[1] == 'M')
1344 return FZ_IMAGE_BMP;
1345 if (p[0] == 'B' && p[1] == 'A')
1346 return FZ_IMAGE_BMP;
1347 if (p[0] == 0x97 && p[1] == 'J' && p[2] == 'B' && p[3] == '2' &&
1348 p[4] == '\r' && p[5] == '\n' && p[6] == 0x1a && p[7] == '\n')
1349 return FZ_IMAGE_JBIG2;
1350 if (p[0] == '8' && p[1] == 'B' && p[2] == 'P' && p[3] == 'S')
1351 return FZ_IMAGE_PSD;
1352 return FZ_IMAGE_UNKNOWN;
1353 }
1354
1355 fz_image *
1356 fz_new_image_from_buffer(fz_context *ctx, fz_buffer *buffer)
1357 {
1358 fz_compressed_buffer *bc;
1359 int w, h, xres, yres;
1360 fz_colorspace *cspace;
1361 size_t len = buffer->len;
1362 unsigned char *buf = buffer->data;
1363 fz_image *image = NULL;
1364 int type;
1365 int bpc;
1366 uint8_t orientation = 0;
1367
1368 if (len < 8)
1369 fz_throw(ctx, FZ_ERROR_FORMAT, "unknown image file format");
1370
1371 type = fz_recognize_image_format(ctx, buf);
1372 bpc = 8;
1373 switch (type)
1374 {
1375 case FZ_IMAGE_PNM:
1376 fz_load_pnm_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1377 break;
1378 case FZ_IMAGE_JPX:
1379 fz_load_jpx_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1380 break;
1381 case FZ_IMAGE_JPEG:
1382 fz_load_jpeg_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace, &orientation);
1383 break;
1384 case FZ_IMAGE_PNG:
1385 fz_load_png_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1386 break;
1387 case FZ_IMAGE_PSD:
1388 fz_load_psd_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1389 break;
1390 case FZ_IMAGE_JXR:
1391 fz_load_jxr_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1392 break;
1393 case FZ_IMAGE_TIFF:
1394 fz_load_tiff_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1395 break;
1396 case FZ_IMAGE_GIF:
1397 fz_load_gif_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1398 break;
1399 case FZ_IMAGE_BMP:
1400 fz_load_bmp_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1401 break;
1402 case FZ_IMAGE_JBIG2:
1403 fz_load_jbig2_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1404 bpc = 1;
1405 break;
1406 default:
1407 fz_throw(ctx, FZ_ERROR_FORMAT, "unknown image file format");
1408 }
1409
1410 fz_try(ctx)
1411 {
1412 bc = fz_new_compressed_buffer(ctx);
1413 bc->buffer = fz_keep_buffer(ctx, buffer);
1414 bc->params.type = type;
1415 if (type == FZ_IMAGE_JPEG)
1416 {
1417 bc->params.u.jpeg.color_transform = -1;
1418 bc->params.u.jpeg.invert_cmyk = 1;
1419 }
1420 image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, cspace, xres, yres, 0, 0, NULL, NULL, bc, NULL);
1421 image->orientation = orientation;
1422 }
1423 fz_always(ctx)
1424 fz_drop_colorspace(ctx, cspace);
1425 fz_catch(ctx)
1426 fz_rethrow(ctx);
1427
1428 return image;
1429 }
1430
1431 int
1432 fz_compressed_image_type(fz_context *ctx, fz_image *image)
1433 {
1434 fz_compressed_image *cim;
1435
1436 if (image == NULL || image->drop_image != drop_compressed_image)
1437 return FZ_IMAGE_UNKNOWN;
1438
1439 cim = (fz_compressed_image *)image;
1440
1441 return cim->buffer->params.type;
1442 }
1443
1444 fz_image *
1445 fz_new_image_from_file(fz_context *ctx, const char *path)
1446 {
1447 fz_buffer *buffer;
1448 fz_image *image = NULL;
1449
1450 buffer = fz_read_file(ctx, path);
1451 fz_try(ctx)
1452 image = fz_new_image_from_buffer(ctx, buffer);
1453 fz_always(ctx)
1454 fz_drop_buffer(ctx, buffer);
1455 fz_catch(ctx)
1456 fz_rethrow(ctx);
1457
1458 return image;
1459 }
1460
1461 void
1462 fz_image_resolution(fz_image *image, int *xres, int *yres)
1463 {
1464 *xres = image->xres;
1465 *yres = image->yres;
1466 if (*xres < 0 || *yres < 0 || (*xres == 0 && *yres == 0))
1467 {
1468 /* If neither xres or yres is sane, pick a sane value */
1469 *xres = SANE_DPI; *yres = SANE_DPI;
1470 }
1471 else if (*xres == 0)
1472 {
1473 *xres = *yres;
1474 }
1475 else if (*yres == 0)
1476 {
1477 *yres = *xres;
1478 }
1479
1480 /* Scale xres and yres up until we get believable values */
1481 if (*xres < SANE_DPI || *yres < SANE_DPI || *xres > INSANE_DPI || *yres > INSANE_DPI)
1482 {
1483 if (*xres < *yres)
1484 {
1485 *yres = *yres * SANE_DPI / *xres;
1486 *xres = SANE_DPI;
1487 }
1488 else
1489 {
1490 *xres = *xres * SANE_DPI / *yres;
1491 *yres = SANE_DPI;
1492 }
1493
1494 if (*xres == *yres || *xres < SANE_DPI || *yres < SANE_DPI || *xres > INSANE_DPI || *yres > INSANE_DPI)
1495 {
1496 *xres = SANE_DPI;
1497 *yres = SANE_DPI;
1498 }
1499 }
1500 }
1501
1502 uint8_t fz_image_orientation(fz_context *ctx, fz_image *image)
1503 {
1504 return image ? image->orientation : 0;
1505 }
1506
1507 fz_matrix fz_image_orientation_matrix(fz_context *ctx, fz_image *image)
1508 {
1509 fz_matrix m;
1510
1511 switch (image ? image->orientation : 0)
1512 {
1513 case 0:
1514 case 1: /* 0 degree rotation */
1515 m.a = 1; m.b = 0;
1516 m.c = 0; m.d = 1;
1517 m.e = 0; m.f = 0;
1518 break;
1519 case 2: /* 90 degree ccw */
1520 m.a = 0; m.b = -1;
1521 m.c = 1; m.d = 0;
1522 m.e = 0; m.f = 1;
1523 break;
1524 case 3: /* 180 degree ccw */
1525 m.a = -1; m.b = 0;
1526 m.c = 0; m.d = -1;
1527 m.e = 1; m.f = 1;
1528 break;
1529 case 4: /* 270 degree ccw */
1530 m.a = 0; m.b = 1;
1531 m.c = -1; m.d = 0;
1532 m.e = 1; m.f = 0;
1533 break;
1534 case 5: /* flip on X */
1535 m.a = -1; m.b = 0;
1536 m.c = 0; m.d = 1;
1537 m.e = 1; m.f = 0;
1538 break;
1539 case 6: /* flip on X, then rotate ccw by 90 degrees */
1540 m.a = 0; m.b = 1;
1541 m.c = 1; m.d = 0;
1542 m.e = 0; m.f = 0;
1543 break;
1544 case 7: /* flip on X, then rotate ccw by 180 degrees */
1545 m.a = 1; m.b = 0;
1546 m.c = 0; m.d = -1;
1547 m.e = 0; m.f = 1;
1548 break;
1549 case 8: /* flip on X, then rotate ccw by 270 degrees */
1550 m.a = 0; m.b = -1;
1551 m.c = -1; m.d = 0;
1552 m.e = 1; m.f = 1;
1553 break;
1554 }
1555
1556 return m;
1557 }
1558
1559 typedef struct fz_display_list_image_s
1560 {
1561 fz_image super;
1562 fz_matrix transform;
1563 fz_display_list *list;
1564 } fz_display_list_image;
1565
1566 static fz_pixmap *
1567 display_list_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
1568 {
1569 fz_display_list_image *image = (fz_display_list_image *)image_;
1570 fz_matrix ctm;
1571 fz_device *dev;
1572 fz_pixmap *pix;
1573
1574 fz_var(dev);
1575
1576 if (subarea)
1577 {
1578 /* So, the whole image should be scaled to w * h, but we only want the
1579 * given subarea of it. */
1580 int l = (subarea->x0 * w) / image->super.w;
1581 int t = (subarea->y0 * h) / image->super.h;
1582 int r = (subarea->x1 * w + image->super.w - 1) / image->super.w;
1583 int b = (subarea->y1 * h + image->super.h - 1) / image->super.h;
1584
1585 pix = fz_new_pixmap(ctx, image->super.colorspace, r-l, b-t, NULL, 0);
1586 pix->x = l;
1587 pix->y = t;
1588 }
1589 else
1590 {
1591 pix = fz_new_pixmap(ctx, image->super.colorspace, w, h, NULL, 0);
1592 }
1593
1594 /* If we render the display list into pix with the image matrix, we'll get a unit
1595 * square result. Therefore scale by w, h. */
1596 ctm = fz_pre_scale(image->transform, w, h);
1597
1598 fz_clear_pixmap(ctx, pix); /* clear to transparent */
1599 fz_try(ctx)
1600 {
1601 dev = fz_new_draw_device(ctx, ctm, pix);
1602 fz_run_display_list(ctx, image->list, dev, fz_identity, fz_infinite_rect, NULL);
1603 fz_close_device(ctx, dev);
1604 }
1605 fz_always(ctx)
1606 fz_drop_device(ctx, dev);
1607 fz_catch(ctx)
1608 {
1609 fz_drop_pixmap(ctx, pix);
1610 fz_rethrow(ctx);
1611 }
1612
1613 /* Never do more subsampling, cos we've already given them the right size */
1614 if (l2factor)
1615 *l2factor = 0;
1616
1617 return pix;
1618 }
1619
1620 static void drop_display_list_image(fz_context *ctx, fz_image *image_)
1621 {
1622 fz_display_list_image *image = (fz_display_list_image *)image_;
1623
1624 if (image == NULL)
1625 return;
1626 fz_drop_display_list(ctx, image->list);
1627 }
1628
1629 static size_t
1630 display_list_image_get_size(fz_context *ctx, fz_image *image_)
1631 {
1632 fz_display_list_image *image = (fz_display_list_image *)image_;
1633
1634 if (image == NULL)
1635 return 0;
1636
1637 return sizeof(fz_display_list_image) + 4096; /* FIXME */
1638 }
1639
1640 fz_image *fz_new_image_from_display_list(fz_context *ctx, float w, float h, fz_display_list *list)
1641 {
1642 fz_display_list_image *image;
1643 int iw, ih;
1644
1645 iw = w * SCALABLE_IMAGE_DPI / 72;
1646 ih = h * SCALABLE_IMAGE_DPI / 72;
1647
1648 image = fz_new_derived_image(ctx, iw, ih, 8, fz_device_rgb(ctx),
1649 SCALABLE_IMAGE_DPI, SCALABLE_IMAGE_DPI, 0, 0,
1650 NULL, NULL, NULL, fz_display_list_image,
1651 display_list_image_get_pixmap,
1652 display_list_image_get_size,
1653 drop_display_list_image);
1654 image->super.scalable = 1;
1655 image->transform = fz_scale(1 / w, 1 / h);
1656 image->list = fz_keep_display_list(ctx, list);
1657
1658 return &image->super;
1659 }