1#include "fitz-imp.h"
2
3#include <string.h>
4#include <math.h>
5#include <assert.h>
6
7/* TODO: here or public? */
8static int
9fz_key_storable_needs_reaping(fz_context *ctx, const fz_key_storable *ks)
10{
11 return ks == NULL ? 0 : (ks->store_key_refs == ks->storable.refs);
12}
13
14#define SANE_DPI 72.0f
15#define INSANE_DPI 4800.0f
16
17#define SCALABLE_IMAGE_DPI 96
18
19struct fz_compressed_image_s
20{
21 fz_image super;
22 fz_pixmap *tile;
23 fz_compressed_buffer *buffer;
24};
25
26struct fz_pixmap_image_s
27{
28 fz_image super;
29 fz_pixmap *tile;
30};
31
32typedef struct fz_image_key_s fz_image_key;
33
34struct fz_image_key_s {
35 int refs;
36 fz_image *image;
37 int l2factor;
38 fz_irect rect;
39};
40
41fz_image *
42fz_keep_image(fz_context *ctx, fz_image *image)
43{
44 return fz_keep_key_storable(ctx, &image->key_storable);
45}
46
47fz_image *
48fz_keep_image_store_key(fz_context *ctx, fz_image *image)
49{
50 return fz_keep_key_storable_key(ctx, &image->key_storable);
51}
52
53void
54fz_drop_image_store_key(fz_context *ctx, fz_image *image)
55{
56 fz_drop_key_storable_key(ctx, &image->key_storable);
57}
58
59static int
60fz_make_hash_image_key(fz_context *ctx, fz_store_hash *hash, void *key_)
61{
62 fz_image_key *key = (fz_image_key *)key_;
63 hash->u.pir.ptr = key->image;
64 hash->u.pir.i = key->l2factor;
65 hash->u.pir.r = key->rect;
66 return 1;
67}
68
69static void *
70fz_keep_image_key(fz_context *ctx, void *key_)
71{
72 fz_image_key *key = (fz_image_key *)key_;
73 return fz_keep_imp(ctx, key, &key->refs);
74}
75
76static void
77fz_drop_image_key(fz_context *ctx, void *key_)
78{
79 fz_image_key *key = (fz_image_key *)key_;
80 if (fz_drop_imp(ctx, key, &key->refs))
81 {
82 fz_drop_image_store_key(ctx, key->image);
83 fz_free(ctx, key);
84 }
85}
86
87static int
88fz_cmp_image_key(fz_context *ctx, void *k0_, void *k1_)
89{
90 fz_image_key *k0 = (fz_image_key *)k0_;
91 fz_image_key *k1 = (fz_image_key *)k1_;
92 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;
93}
94
95static void
96fz_format_image_key(fz_context *ctx, char *s, int n, void *key_)
97{
98 fz_image_key *key = (fz_image_key *)key_;
99 fz_snprintf(s, n, "(image %d x %d sf=%d)", key->image->w, key->image->h, key->l2factor);
100}
101
102static int
103fz_needs_reap_image_key(fz_context *ctx, void *key_)
104{
105 fz_image_key *key = (fz_image_key *)key_;
106
107 return fz_key_storable_needs_reaping(ctx, &key->image->key_storable);
108}
109
110static const fz_store_type fz_image_store_type =
111{
112 fz_make_hash_image_key,
113 fz_keep_image_key,
114 fz_drop_image_key,
115 fz_cmp_image_key,
116 fz_format_image_key,
117 fz_needs_reap_image_key
118};
119
120void
121fz_drop_image(fz_context *ctx, fz_image *image)
122{
123 fz_drop_key_storable(ctx, &image->key_storable);
124}
125
126static void
127fz_mask_color_key(fz_pixmap *pix, int n, const int *colorkey)
128{
129 unsigned char *p = pix->samples;
130 int w;
131 int k, t;
132 int h = pix->h;
133 int stride = pix->stride - pix->w * pix->n;
134 if (pix->w == 0)
135 return;
136 while (h--)
137 {
138 w = pix->w;
139 do
140 {
141 t = 1;
142 for (k = 0; k < n; k++)
143 if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
144 t = 0;
145 if (t)
146 for (k = 0; k < pix->n; k++)
147 p[k] = 0;
148 p += pix->n;
149 }
150 while (--w);
151 p += stride;
152 }
153}
154
155static void
156fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image, const fz_irect *isa)
157{
158 fz_pixmap *mask;
159 unsigned char *s, *d = tile->samples;
160 int n = tile->n;
161 int k;
162 int sstride, dstride = tile->stride - tile->w * tile->n;
163 int h;
164 fz_irect subarea;
165
166 /* We need at least as much of the mask as there was of the tile. */
167 if (isa)
168 subarea = *isa;
169 else
170 {
171 subarea.x0 = 0;
172 subarea.y0 = 0;
173 subarea.x1 = tile->w;
174 subarea.y1 = tile->h;
175 }
176
177 mask = fz_get_pixmap_from_image(ctx, image->mask, &subarea, NULL, NULL, NULL);
178 s = mask->samples;
179 /* RJW: Urgh, bit of nastiness here. fz_pixmap_from_image will either return
180 * an exact match for the subarea we asked for, or the full image, and the
181 * normal way to know is that the matrix will be updated. That doesn't help
182 * us here. */
183 if (image->mask->w == mask->w && image->mask->h == mask->h) {
184 subarea.x0 = 0;
185 subarea.y0 = 0;
186 }
187 if (isa)
188 s += (isa->x0 - subarea.x0) * mask->n + (isa->y0 - subarea.y0) * mask->stride;
189 sstride = mask->stride - tile->w * mask->n;
190 h = tile->h;
191
192 if (tile->w != 0)
193 {
194 while (h--)
195 {
196 int w = tile->w;
197 do
198 {
199 if (*s == 0)
200 for (k = 0; k < image->n; k++)
201 d[k] = image->colorkey[k];
202 else
203 for (k = 0; k < image->n; k++)
204 d[k] = fz_clampi(image->colorkey[k] + (d[k] - image->colorkey[k]) * 255 / *s, 0, 255);
205 s++;
206 d += n;
207 }
208 while (--w);
209 s += sstride;
210 d += dstride;
211 }
212 }
213
214 fz_drop_pixmap(ctx, mask);
215}
216
217static void fz_adjust_image_subarea(fz_context *ctx, fz_image *image, fz_irect *subarea, int l2factor)
218{
219 int f = 1<<l2factor;
220 int bpp = image->bpc * image->n;
221 int mask;
222
223 switch (bpp)
224 {
225 case 1: mask = 8*f; break;
226 case 2: mask = 4*f; break;
227 case 4: mask = 2*f; break;
228 default: mask = (bpp & 7) == 0 ? f : 0; break;
229 }
230
231 if (mask != 0)
232 {
233 subarea->x0 &= ~(mask - 1);
234 subarea->x1 = (subarea->x1 + mask - 1) & ~(mask - 1);
235 }
236 else
237 {
238 /* Awkward case - mask cannot be a power of 2. */
239 mask = bpp*f;
240 switch (bpp)
241 {
242 case 3:
243 case 5:
244 case 7:
245 case 9:
246 case 11:
247 case 13:
248 case 15:
249 default:
250 mask *= 8;
251 break;
252 case 6:
253 case 10:
254 case 14:
255 mask *= 4;
256 break;
257 case 12:
258 mask *= 2;
259 break;
260 }
261 subarea->x0 = (subarea->x0 / mask) * mask;
262 subarea->x1 = ((subarea->x1 + mask - 1) / mask) * mask;
263 }
264
265 subarea->y0 &= ~(f - 1);
266 if (subarea->x1 > image->w)
267 subarea->x1 = image->w;
268 subarea->y1 = (subarea->y1 + f - 1) & ~(f - 1);
269 if (subarea->y1 > image->h)
270 subarea->y1 = image->h;
271}
272
273static void fz_compute_image_key(fz_context *ctx, fz_image *image, fz_matrix *ctm,
274 fz_image_key *key, const fz_irect *subarea, int l2factor, int *w, int *h, int *dw, int *dh)
275{
276 key->refs = 1;
277 key->image = image;
278 key->l2factor = l2factor;
279
280 if (subarea == NULL)
281 {
282 key->rect.x0 = 0;
283 key->rect.y0 = 0;
284 key->rect.x1 = image->w;
285 key->rect.y1 = image->h;
286 }
287 else
288 {
289 key->rect = *subarea;
290 ctx->tuning->image_decode(ctx->tuning->image_decode_arg, image->w, image->h, key->l2factor, &key->rect);
291 fz_adjust_image_subarea(ctx, image, &key->rect, key->l2factor);
292 }
293
294 /* Based on that subarea, recalculate the extents */
295 if (ctm)
296 {
297 float frac_w = (float) (key->rect.x1 - key->rect.x0) / image->w;
298 float frac_h = (float) (key->rect.y1 - key->rect.y0) / image->h;
299 float a = ctm->a * frac_w;
300 float b = ctm->b * frac_h;
301 float c = ctm->c * frac_w;
302 float d = ctm->d * frac_h;
303 *w = sqrtf(a * a + b * b);
304 *h = sqrtf(c * c + d * d);
305 }
306 else
307 {
308 *w = image->w;
309 *h = image->h;
310 }
311
312 /* Return the true sizes to the caller */
313 if (dw)
314 *dw = *w;
315 if (dh)
316 *dh = *h;
317 if (*w > image->w)
318 *w = image->w;
319 if (*h > image->h)
320 *h = image->h;
321
322 if (*w == 0 || *h == 0)
323 key->l2factor = 0;
324}
325
326fz_pixmap *
327fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_compressed_image *cimg, fz_irect *subarea, int indexed, int l2factor)
328{
329 fz_image *image = &cimg->super;
330 fz_pixmap *tile = NULL;
331 size_t stride, len, i;
332 unsigned char *samples = NULL;
333 int f = 1<<l2factor;
334 int w = image->w;
335 int h = image->h;
336 int matte = image->use_colorkey && image->mask;
337
338 if (matte)
339 {
340 /* Can't do l2factor decoding */
341 if (image->w != image->mask->w || image->h != image->mask->h)
342 {
343 fz_warn(ctx, "mask must be of same size as image for /Matte");
344 matte = 0;
345 }
346 assert(l2factor == 0);
347 }
348 if (subarea)
349 {
350 fz_adjust_image_subarea(ctx, image, subarea, l2factor);
351 w = (subarea->x1 - subarea->x0);
352 h = (subarea->y1 - subarea->y0);
353 }
354 w = (w + f - 1) >> l2factor;
355 h = (h + f - 1) >> l2factor;
356
357 fz_var(tile);
358 fz_var(samples);
359
360 fz_try(ctx)
361 {
362 int alpha = (image->colorspace == NULL);
363 if (image->use_colorkey)
364 alpha = 1;
365 tile = fz_new_pixmap(ctx, image->colorspace, w, h, NULL, alpha);
366 if (image->interpolate & FZ_PIXMAP_FLAG_INTERPOLATE)
367 tile->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
368 else
369 tile->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
370
371 stride = (w * image->n * image->bpc + 7) / 8;
372 if (h > SIZE_MAX / stride)
373 fz_throw(ctx, FZ_ERROR_MEMORY, "image too large");
374 samples = fz_malloc(ctx, h * stride);
375
376 if (subarea)
377 {
378 int hh;
379 unsigned char *s = samples;
380 int stream_w = (image->w + f - 1)>>l2factor;
381 size_t stream_stride = (stream_w * image->n * image->bpc + 7) / 8;
382 int l_margin = subarea->x0 >> l2factor;
383 int t_margin = subarea->y0 >> l2factor;
384 int r_margin = (image->w + f - 1 - subarea->x1) >> l2factor;
385 int b_margin = (image->h + f - 1 - subarea->y1) >> l2factor;
386 int l_skip = (l_margin * image->n * image->bpc)/8;
387 int r_skip = (r_margin * image->n * image->bpc + 7)/8;
388 size_t t_skip = t_margin * stream_stride + l_skip;
389 size_t b_skip = b_margin * stream_stride + r_skip;
390 size_t l = fz_skip(ctx, stm, t_skip);
391 len = 0;
392 if (l == t_skip)
393 {
394 hh = h;
395 do
396 {
397 l = fz_read(ctx, stm, s, stride);
398 s += l;
399 len += l;
400 if (l < stride)
401 break;
402 if (--hh == 0)
403 break;
404 l = fz_skip(ctx, stm, r_skip + l_skip);
405 if (l < (size_t)(r_skip + l_skip))
406 break;
407 }
408 while (1);
409 (void)fz_skip(ctx, stm, r_skip + b_skip);
410 }
411 }
412 else
413 {
414 len = fz_read(ctx, stm, samples, h * stride);
415 }
416
417 /* Pad truncated images */
418 if (len < stride * h)
419 {
420 fz_warn(ctx, "padding truncated image");
421 memset(samples + len, 0, stride * h - len);
422 }
423
424 /* Invert 1-bit image masks */
425 if (image->imagemask)
426 {
427 /* 0=opaque and 1=transparent so we need to invert */
428 unsigned char *p = samples;
429 len = h * stride;
430 for (i = 0; i < len; i++)
431 p[i] = ~p[i];
432 }
433
434 fz_unpack_tile(ctx, tile, samples, image->n, image->bpc, stride, indexed);
435
436 fz_free(ctx, samples);
437 samples = NULL;
438
439 /* color keyed transparency */
440 if (image->use_colorkey && !image->mask)
441 fz_mask_color_key(tile, image->n, image->colorkey);
442
443 if (indexed)
444 {
445 fz_pixmap *conv;
446 fz_decode_indexed_tile(ctx, tile, image->decode, (1 << image->bpc) - 1);
447 conv = fz_convert_indexed_pixmap_to_base(ctx, tile);
448 fz_drop_pixmap(ctx, tile);
449 tile = conv;
450 }
451 else if (image->use_decode)
452 {
453 fz_decode_tile(ctx, tile, image->decode);
454 }
455
456 /* pre-blended matte color */
457 if (matte)
458 fz_unblend_masked_tile(ctx, tile, image, subarea);
459 }
460 fz_catch(ctx)
461 {
462 fz_drop_pixmap(ctx, tile);
463 fz_free(ctx, samples);
464 fz_rethrow(ctx);
465 }
466
467 return tile;
468}
469
470void
471fz_drop_image_base(fz_context *ctx, fz_image *image)
472{
473 fz_drop_colorspace(ctx, image->colorspace);
474 fz_drop_image(ctx, image->mask);
475 fz_free(ctx, image);
476}
477
478void
479fz_drop_image_imp(fz_context *ctx, fz_storable *image_)
480{
481 fz_image *image = (fz_image *)image_;
482
483 image->drop_image(ctx, image);
484 fz_drop_image_base(ctx, image);
485}
486
487static void
488drop_compressed_image(fz_context *ctx, fz_image *image_)
489{
490 fz_compressed_image *image = (fz_compressed_image *)image_;
491
492 fz_drop_pixmap(ctx, image->tile);
493 fz_drop_compressed_buffer(ctx, image->buffer);
494}
495
496static void
497drop_pixmap_image(fz_context *ctx, fz_image *image_)
498{
499 fz_pixmap_image *image = (fz_pixmap_image *)image_;
500
501 fz_drop_pixmap(ctx, image->tile);
502}
503
504static fz_pixmap *
505compressed_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
506{
507 fz_compressed_image *image = (fz_compressed_image *)image_;
508 int native_l2factor;
509 fz_stream *stm;
510 int indexed;
511 fz_pixmap *tile;
512 int can_sub = 0;
513 int local_l2factor;
514
515 /* If we are using matte, then the decode code requires both image and tile sizes
516 * to match. The simplest way to ensure this is to do no native l2factor decoding.
517 */
518 if (image->super.use_colorkey && image->super.mask)
519 {
520 local_l2factor = 0;
521 l2factor = &local_l2factor;
522 }
523
524 /* We need to make a new one. */
525 /* First check for ones that we can't decode using streams */
526 switch (image->buffer->params.type)
527 {
528 case FZ_IMAGE_PNG:
529 tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
530 break;
531 case FZ_IMAGE_GIF:
532 tile = fz_load_gif(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
533 break;
534 case FZ_IMAGE_BMP:
535 tile = fz_load_bmp(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
536 break;
537 case FZ_IMAGE_TIFF:
538 tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
539 break;
540 case FZ_IMAGE_PNM:
541 tile = fz_load_pnm(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
542 break;
543 case FZ_IMAGE_JXR:
544 tile = fz_load_jxr(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
545 break;
546 case FZ_IMAGE_JPX:
547 tile = fz_load_jpx(ctx, image->buffer->buffer->data, image->buffer->buffer->len, NULL);
548 break;
549 case FZ_IMAGE_JPEG:
550 /* Scan JPEG stream and patch missing height values in header */
551 {
552 unsigned char *s = image->buffer->buffer->data;
553 unsigned char *e = s + image->buffer->buffer->len;
554 unsigned char *d;
555 for (d = s + 2; s < d && d < e - 9 && d[0] == 0xFF; d += (d[2] << 8 | d[3]) + 2)
556 {
557 if (d[1] < 0xC0 || (0xC3 < d[1] && d[1] < 0xC9) || 0xCB < d[1])
558 continue;
559 if ((d[5] == 0 && d[6] == 0) || ((d[5] << 8) | d[6]) > image->super.h)
560 {
561 d[5] = (image->super.h >> 8) & 0xFF;
562 d[6] = image->super.h & 0xFF;
563 }
564 }
565 }
566 /* fall through */
567
568 default:
569 native_l2factor = l2factor ? *l2factor : 0;
570 stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, l2factor);
571 fz_try(ctx)
572 {
573 if (l2factor)
574 native_l2factor -= *l2factor;
575 indexed = fz_colorspace_is_indexed(ctx, image->super.colorspace);
576 can_sub = 1;
577 tile = fz_decomp_image_from_stream(ctx, stm, image, subarea, indexed, native_l2factor);
578 }
579 fz_always(ctx)
580 fz_drop_stream(ctx, stm);
581 fz_catch(ctx)
582 fz_rethrow(ctx);
583
584 /* CMYK JPEGs in XPS documents have to be inverted */
585 if (image->super.invert_cmyk_jpeg &&
586 image->buffer->params.type == FZ_IMAGE_JPEG &&
587 fz_colorspace_is_cmyk(ctx, image->super.colorspace) &&
588 image->buffer->params.u.jpeg.color_transform)
589 {
590 fz_invert_pixmap(ctx, tile);
591 }
592
593 break;
594 }
595
596 if (can_sub == 0 && subarea != NULL)
597 {
598 subarea->x0 = 0;
599 subarea->y0 = 0;
600 subarea->x1 = image->super.w;
601 subarea->y1 = image->super.h;
602 }
603
604 return tile;
605}
606
607static fz_pixmap *
608pixmap_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
609{
610 fz_pixmap_image *image = (fz_pixmap_image *)image_;
611
612 /* 'Simple' images created direct from pixmaps will have no buffer
613 * of compressed data. We cannot do any better than just returning
614 * a pointer to the original 'tile'.
615 */
616 return fz_keep_pixmap(ctx, image->tile); /* That's all we can give you! */
617}
618
619static void
620update_ctm_for_subarea(fz_matrix *ctm, const fz_irect *subarea, int w, int h)
621{
622 fz_matrix m;
623
624 if (subarea->x0 == 0 && subarea->y0 == 0 && subarea->x1 == w && subarea->y1 == h)
625 return;
626
627 m.a = (float) (subarea->x1 - subarea->x0) / w;
628 m.b = 0;
629 m.c = 0;
630 m.d = (float) (subarea->y1 - subarea->y0) / h;
631 m.e = (float) subarea->x0 / w;
632 m.f = (float) subarea->y0 / h;
633 *ctm = fz_concat(m, *ctm);
634}
635
636void fz_default_image_decode(void *arg, int w, int h, int l2factor, fz_irect *subarea)
637{
638 (void)arg;
639
640 if ((subarea->x1-subarea->x0)*(subarea->y1-subarea->y0) >= (w*h/10)*9)
641 {
642 /* Either no subarea specified, or a subarea 90% or more of the
643 * whole area specified. Use the whole image. */
644 subarea->x0 = 0;
645 subarea->y0 = 0;
646 subarea->x1 = w;
647 subarea->y1 = h;
648 }
649 else
650 {
651 /* Clip to the edges if they are within 1% */
652 if (subarea->x0 <= w/100)
653 subarea->x0 = 0;
654 if (subarea->y0 <= h/100)
655 subarea->y0 = 0;
656 if (subarea->x1 >= w*99/100)
657 subarea->x1 = w;
658 if (subarea->y1 >= h*99/100)
659 subarea->y1 = h;
660 }
661}
662
663static fz_pixmap *
664fz_find_image_tile(fz_context *ctx, fz_image *image, fz_image_key *key, fz_matrix *ctm)
665{
666 fz_pixmap *tile;
667 do
668 {
669 tile = fz_find_item(ctx, fz_drop_pixmap_imp, key, &fz_image_store_type);
670 if (tile)
671 {
672 update_ctm_for_subarea(ctm, &key->rect, image->w, image->h);
673 return tile;
674 }
675 key->l2factor--;
676 }
677 while (key->l2factor >= 0);
678 return NULL;
679}
680
681/*
682 Called to get a handle to a pixmap from an image.
683
684 image: The image to retrieve a pixmap from.
685
686 color_params: The color parameters (or NULL for defaults).
687
688 subarea: The subarea of the image that we actually care about (or NULL
689 to indicate the whole image).
690
691 trans: Optional, unless subarea is given. If given, then on entry this is
692 the transform that will be applied to the complete image. It should be
693 updated on exit to the transform to apply to the given subarea of the
694 image. This is used to calculate the desired width/height for subsampling.
695
696 w: If non-NULL, a pointer to an int to be updated on exit to the
697 width (in pixels) that the scaled output will cover.
698
699 h: If non-NULL, a pointer to an int to be updated on exit to the
700 height (in pixels) that the scaled output will cover.
701
702 Returns a non NULL pixmap pointer. May throw exceptions.
703*/
704fz_pixmap *
705fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, const fz_irect *subarea, fz_matrix *ctm, int *dw, int *dh)
706{
707 fz_pixmap *tile;
708 int l2factor, l2factor_remaining;
709 fz_image_key key;
710 fz_image_key *keyp = NULL;
711 int w;
712 int h;
713
714 fz_var(keyp);
715
716 if (!image)
717 return NULL;
718
719 /* Figure out the extent. */
720 if (ctm)
721 {
722 w = sqrtf(ctm->a * ctm->a + ctm->b * ctm->b);
723 h = sqrtf(ctm->c * ctm->c + ctm->d * ctm->d);
724 }
725 else
726 {
727 w = image->w;
728 h = image->h;
729 }
730
731 if (image->scalable)
732 {
733 /* If the image is scalable, we always want to re-render and never cache. */
734 fz_irect subarea_copy;
735 if (subarea)
736 subarea_copy = *subarea;
737 l2factor_remaining = 0;
738 if (dw) *dw = w;
739 if (dh) *dh = h;
740 return image->get_pixmap(ctx, image, subarea ? &subarea_copy : NULL, image->w, image->h, &l2factor_remaining);
741 }
742
743 /* Clamp requested image size, since we never want to magnify images here. */
744 if (w > image->w)
745 w = image->w;
746 if (h > image->h)
747 h = image->h;
748
749 if (image->decoded)
750 {
751 /* If the image is already decoded, then we can't offer a subarea,
752 * or l2factor, and we don't want to cache. */
753 l2factor_remaining = 0;
754 if (dw) *dw = w;
755 if (dh) *dh = h;
756 return image->get_pixmap(ctx, image, NULL, image->w, image->h, &l2factor_remaining);
757 }
758
759 /* What is our ideal factor? We search for the largest factor where
760 * we can subdivide and stay larger than the required size. We add
761 * a fudge factor of +2 here to allow for the possibility of
762 * expansion due to grid fitting. */
763 l2factor = 0;
764 if (w > 0 && h > 0)
765 {
766 while (image->w>>(l2factor+1) >= w+2 && image->h>>(l2factor+1) >= h+2 && l2factor < 6)
767 l2factor++;
768 }
769
770 /* First, look through the store for existing tiles */
771 if (subarea)
772 {
773 fz_compute_image_key(ctx, image, ctm, &key, subarea, l2factor, &w, &h, dw, dh);
774 tile = fz_find_image_tile(ctx, image, &key, ctm);
775 if (tile)
776 return tile;
777 }
778
779 /* No subarea given, or no tile for subarea found; try entire image */
780 fz_compute_image_key(ctx, image, ctm, &key, NULL, l2factor, &w, &h, dw, dh);
781 tile = fz_find_image_tile(ctx, image, &key, ctm);
782 if (tile)
783 return tile;
784
785 /* Neither subarea nor full image tile found; prepare the subarea key again */
786 if (subarea)
787 fz_compute_image_key(ctx, image, ctm, &key, subarea, l2factor, &w, &h, dw, dh);
788
789 /* We'll have to decode the image; request the correct amount of downscaling. */
790 l2factor_remaining = l2factor;
791 tile = image->get_pixmap(ctx, image, &key.rect, w, h, &l2factor_remaining);
792
793 /* Update the ctm to allow for subareas. */
794 if (ctm)
795 update_ctm_for_subarea(ctm, &key.rect, image->w, image->h);
796
797 /* l2factor_remaining is updated to the amount of subscaling left to do */
798 assert(l2factor_remaining >= 0 && l2factor_remaining <= 6);
799 if (l2factor_remaining)
800 {
801 fz_try(ctx)
802 fz_subsample_pixmap(ctx, tile, l2factor_remaining);
803 fz_catch(ctx)
804 {
805 fz_drop_pixmap(ctx, tile);
806 fz_rethrow(ctx);
807 }
808 }
809
810 fz_try(ctx)
811 {
812 fz_pixmap *existing_tile;
813
814 /* Now we try to cache the pixmap. Any failure here will just result
815 * in us not caching. */
816 keyp = fz_malloc_struct(ctx, fz_image_key);
817 keyp->refs = 1;
818 keyp->image = fz_keep_image_store_key(ctx, image);
819 keyp->l2factor = l2factor;
820 keyp->rect = key.rect;
821
822 existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
823 if (existing_tile)
824 {
825 /* We already have a tile. This must have been produced by a
826 * racing thread. We'll throw away ours and use that one. */
827 fz_drop_pixmap(ctx, tile);
828 tile = existing_tile;
829 }
830 }
831 fz_always(ctx)
832 {
833 fz_drop_image_key(ctx, keyp);
834 }
835 fz_catch(ctx)
836 {
837 /* Do nothing */
838 }
839
840 return tile;
841}
842
843static size_t
844pixmap_image_get_size(fz_context *ctx, fz_image *image)
845{
846 fz_pixmap_image *im = (fz_pixmap_image *)image;
847
848 if (image == NULL)
849 return 0;
850
851 return sizeof(fz_pixmap_image) + fz_pixmap_size(ctx, im->tile);
852}
853
854size_t fz_image_size(fz_context *ctx, fz_image *im)
855{
856 if (im == NULL)
857 return 0;
858
859 return im->get_size(ctx, im);
860}
861
862/*
863 Create an image from the given
864 pixmap.
865
866 pixmap: The pixmap to base the image upon. A new reference
867 to this is taken.
868
869 mask: NULL, or another image to use as a mask for this one.
870 A new reference is taken to this image. Supplying a masked
871 image as a mask to another image is illegal!
872*/
873fz_image *
874fz_new_image_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, fz_image *mask)
875{
876 fz_pixmap_image *image;
877
878 image = fz_new_derived_image(ctx, pixmap->w, pixmap->h, 8, pixmap->colorspace,
879 pixmap->xres, pixmap->yres, 0, 0,
880 NULL, NULL, mask, fz_pixmap_image,
881 pixmap_image_get_pixmap,
882 pixmap_image_get_size,
883 drop_pixmap_image);
884 image->tile = fz_keep_pixmap(ctx, pixmap);
885 image->super.decoded = 1;
886
887 return &image->super;
888}
889
890/*
891 Internal function to make a new fz_image structure
892 for a derived class.
893
894 w,h: Width and height of the created image.
895
896 bpc: Bits per component.
897
898 colorspace: The colorspace (determines the number of components,
899 and any color conversions required while decoding).
900
901 xres, yres: The X and Y resolutions respectively.
902
903 interpolate: 1 if interpolation should be used when decoding
904 this image, 0 otherwise.
905
906 imagemask: 1 if this is an imagemask (i.e. transparent), 0
907 otherwise.
908
909 decode: NULL, or a pointer to to a decode array. The default
910 decode array is [0 1] (repeated n times, for n color components).
911
912 colorkey: NULL, or a pointer to a colorkey array. The default
913 colorkey array is [0 255] (repeatd n times, for n color
914 components).
915
916 mask: NULL, or another image to use as a mask for this one.
917 A new reference is taken to this image. Supplying a masked
918 image as a mask to another image is illegal!
919
920 size: The size of the required allocated structure (the size of
921 the derived structure).
922
923 get: The function to be called to obtain a decoded pixmap.
924
925 get_size: The function to be called to return the storage size
926 used by this image.
927
928 drop: The function to be called to dispose of this image once
929 the last reference is dropped.
930
931 Returns a pointer to an allocated structure of the required size,
932 with the first sizeof(fz_image) bytes initialised as appropriate
933 given the supplied parameters, and the other bytes set to zero.
934*/
935fz_image *
936fz_new_image_of_size(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace,
937 int xres, int yres, int interpolate, int imagemask, float *decode,
938 int *colorkey, fz_image *mask, int size,
939 fz_image_get_pixmap_fn *get_pixmap,
940 fz_image_get_size_fn *get_size,
941 fz_drop_image_fn *drop)
942{
943 fz_image *image;
944 int i;
945
946 assert(mask == NULL || mask->mask == NULL);
947 assert(size >= sizeof(fz_image));
948
949 image = Memento_label(fz_calloc(ctx, 1, size), "fz_image");
950 FZ_INIT_KEY_STORABLE(image, 1, fz_drop_image_imp);
951 image->drop_image = drop;
952 image->get_pixmap = get_pixmap;
953 image->get_size = get_size;
954 image->w = w;
955 image->h = h;
956 image->xres = xres;
957 image->yres = yres;
958 image->bpc = bpc;
959 image->n = (colorspace ? fz_colorspace_n(ctx, colorspace) : 1);
960 image->colorspace = fz_keep_colorspace(ctx, colorspace);
961 image->invert_cmyk_jpeg = 1;
962 image->interpolate = interpolate;
963 image->imagemask = imagemask;
964 image->use_colorkey = (colorkey != NULL);
965 if (colorkey)
966 memcpy(image->colorkey, colorkey, sizeof(int)*image->n*2);
967 image->use_decode = 0;
968 if (decode)
969 {
970 memcpy(image->decode, decode, sizeof(float)*image->n*2);
971 }
972 else
973 {
974 float maxval = fz_colorspace_is_indexed(ctx, colorspace) ? (1 << bpc) - 1 : 1;
975 for (i = 0; i < image->n; i++)
976 {
977 image->decode[2*i] = 0;
978 image->decode[2*i+1] = maxval;
979 }
980 }
981 /* ICC spaces have the default decode arrays pickled into them.
982 * For most spaces this is fine, because [ 0 1 0 1 0 1 ] is
983 * idempotent. For Lab, however, we need to adjust it. */
984 if (fz_colorspace_is_lab_icc(ctx, colorspace))
985 {
986 /* Undo the default decode array of [0 100 -128 127 -128 127] */
987 image->decode[0] = image->decode[0]/100.0f;
988 image->decode[1] = image->decode[1]/100.0f;
989 image->decode[2] = (image->decode[2]+128)/255.0f;
990 image->decode[3] = (image->decode[3]+128)/255.0f;
991 image->decode[4] = (image->decode[4]+128)/255.0f;
992 image->decode[5] = (image->decode[5]+128)/255.0f;
993 }
994 for (i = 0; i < image->n; i++)
995 {
996 if (image->decode[i * 2] != 0 || image->decode[i * 2 + 1] != 1)
997 break;
998 }
999 if (i != image->n)
1000 image->use_decode = 1;
1001 image->mask = fz_keep_image(ctx, mask);
1002
1003 return image;
1004}
1005
1006static size_t
1007compressed_image_get_size(fz_context *ctx, fz_image *image)
1008{
1009 fz_compressed_image *im = (fz_compressed_image *)image;
1010
1011 if (image == NULL)
1012 return 0;
1013
1014 return sizeof(fz_pixmap_image) + fz_pixmap_size(ctx, im->tile) + (im->buffer && im->buffer->buffer ? im->buffer->buffer->cap : 0);
1015}
1016
1017/*
1018 Create an image based on
1019 the data in the supplied compressed buffer.
1020
1021 w,h: Width and height of the created image.
1022
1023 bpc: Bits per component.
1024
1025 colorspace: The colorspace (determines the number of components,
1026 and any color conversions required while decoding).
1027
1028 xres, yres: The X and Y resolutions respectively.
1029
1030 interpolate: 1 if interpolation should be used when decoding
1031 this image, 0 otherwise.
1032
1033 imagemask: 1 if this is an imagemask (i.e. transparency bitmap mask), 0 otherwise.
1034
1035 decode: NULL, or a pointer to to a decode array. The default
1036 decode array is [0 1] (repeated n times, for n color components).
1037
1038 colorkey: NULL, or a pointer to a colorkey array. The default
1039 colorkey array is [0 255] (repeatd n times, for n color
1040 components).
1041
1042 buffer: Buffer of compressed data and compression parameters.
1043 Ownership of this reference is passed in.
1044
1045 mask: NULL, or another image to use as a mask for this one.
1046 A new reference is taken to this image. Supplying a masked
1047 image as a mask to another image is illegal!
1048*/
1049fz_image *
1050fz_new_image_from_compressed_buffer(fz_context *ctx, int w, int h,
1051 int bpc, fz_colorspace *colorspace,
1052 int xres, int yres, int interpolate, int imagemask, float *decode,
1053 int *colorkey, fz_compressed_buffer *buffer, fz_image *mask)
1054{
1055 fz_compressed_image *image;
1056
1057 fz_try(ctx)
1058 {
1059 image = fz_new_derived_image(ctx, w, h, bpc,
1060 colorspace, xres, yres,
1061 interpolate, imagemask, decode,
1062 colorkey, mask, fz_compressed_image,
1063 compressed_image_get_pixmap,
1064 compressed_image_get_size,
1065 drop_compressed_image);
1066 image->buffer = buffer;
1067 }
1068 fz_catch(ctx)
1069 {
1070 fz_drop_compressed_buffer(ctx, buffer);
1071 fz_rethrow(ctx);
1072 }
1073
1074 return &image->super;
1075}
1076
1077/*
1078 Retrieve the underlying compressed
1079 data for an image.
1080
1081 Returns a pointer to the underlying data buffer for an image,
1082 or NULL if this image is not based upon a compressed data
1083 buffer.
1084
1085 This is not a reference counted structure, so no reference is
1086 returned. Lifespan is limited to that of the image itself.
1087*/
1088fz_compressed_buffer *fz_compressed_image_buffer(fz_context *ctx, fz_image *image)
1089{
1090 if (image == NULL || image->get_pixmap != compressed_image_get_pixmap)
1091 return NULL;
1092 return ((fz_compressed_image *)image)->buffer;
1093}
1094
1095void fz_set_compressed_image_buffer(fz_context *ctx, fz_compressed_image *image, fz_compressed_buffer *buf)
1096{
1097 assert(image != NULL && image->super.get_pixmap == compressed_image_get_pixmap);
1098 ((fz_compressed_image *)image)->buffer = buf; /* Note: compressed buffers are not reference counted */
1099}
1100
1101fz_pixmap *fz_compressed_image_tile(fz_context *ctx, fz_compressed_image *image)
1102{
1103 if (image == NULL || image->super.get_pixmap != compressed_image_get_pixmap)
1104 return NULL;
1105 return ((fz_compressed_image *)image)->tile;
1106}
1107
1108void fz_set_compressed_image_tile(fz_context *ctx, fz_compressed_image *image, fz_pixmap *pix)
1109{
1110 assert(image != NULL && image->super.get_pixmap == compressed_image_get_pixmap);
1111 fz_drop_pixmap(ctx, ((fz_compressed_image *)image)->tile);
1112 ((fz_compressed_image *)image)->tile = fz_keep_pixmap(ctx, pix);
1113}
1114
1115/*
1116 Retried the underlying fz_pixmap
1117 for an image.
1118
1119 Returns a pointer to the underlying fz_pixmap for an image,
1120 or NULL if this image is not based upon an fz_pixmap.
1121
1122 No reference is returned. Lifespan is limited to that of
1123 the image itself. If required, use fz_keep_pixmap to take
1124 a reference to keep it longer.
1125*/
1126fz_pixmap *fz_pixmap_image_tile(fz_context *ctx, fz_pixmap_image *image)
1127{
1128 if (image == NULL || image->super.get_pixmap != pixmap_image_get_pixmap)
1129 return NULL;
1130 return ((fz_pixmap_image *)image)->tile;
1131}
1132
1133void fz_set_pixmap_image_tile(fz_context *ctx, fz_pixmap_image *image, fz_pixmap *pix)
1134{
1135 assert(image != NULL && image->super.get_pixmap == pixmap_image_get_pixmap);
1136 ((fz_pixmap_image *)image)->tile = pix;
1137}
1138
1139int
1140fz_recognize_image_format(fz_context *ctx, unsigned char p[8])
1141{
1142 if (p[0] == 'P' && p[1] >= '1' && p[1] <= '7')
1143 return FZ_IMAGE_PNM;
1144 if (p[0] == 0xff && p[1] == 0x4f)
1145 return FZ_IMAGE_JPX;
1146 if (p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c &&
1147 p[4] == 0x6a && p[5] == 0x50 && p[6] == 0x20 && p[7] == 0x20)
1148 return FZ_IMAGE_JPX;
1149 if (p[0] == 0xff && p[1] == 0xd8)
1150 return FZ_IMAGE_JPEG;
1151 if (p[0] == 137 && p[1] == 80 && p[2] == 78 && p[3] == 71 &&
1152 p[4] == 13 && p[5] == 10 && p[6] == 26 && p[7] == 10)
1153 return FZ_IMAGE_PNG;
1154 if (p[0] == 'I' && p[1] == 'I' && p[2] == 0xBC)
1155 return FZ_IMAGE_JXR;
1156 if (p[0] == 'I' && p[1] == 'I' && p[2] == 42 && p[3] == 0)
1157 return FZ_IMAGE_TIFF;
1158 if (p[0] == 'M' && p[1] == 'M' && p[2] == 0 && p[3] == 42)
1159 return FZ_IMAGE_TIFF;
1160 if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F')
1161 return FZ_IMAGE_GIF;
1162 if (p[0] == 'B' && p[1] == 'M')
1163 return FZ_IMAGE_BMP;
1164 if (p[0] == 0x97 && p[1] == 'J' && p[2] == 'B' && p[3] == '2' &&
1165 p[4] == '\r' && p[5] == '\n' && p[6] == 0x1a && p[7] == '\n')
1166 return FZ_IMAGE_JBIG2;
1167 return FZ_IMAGE_UNKNOWN;
1168}
1169
1170/*
1171 Create a new image from a
1172 buffer of data, inferring its type from the format
1173 of the data.
1174*/
1175fz_image *
1176fz_new_image_from_buffer(fz_context *ctx, fz_buffer *buffer)
1177{
1178 fz_compressed_buffer *bc;
1179 int w, h, xres, yres;
1180 fz_colorspace *cspace;
1181 size_t len = buffer->len;
1182 unsigned char *buf = buffer->data;
1183 fz_image *image = NULL;
1184 int type;
1185
1186 if (len < 8)
1187 fz_throw(ctx, FZ_ERROR_GENERIC, "unknown image file format");
1188
1189 type = fz_recognize_image_format(ctx, buf);
1190 switch (type)
1191 {
1192 case FZ_IMAGE_PNM:
1193 fz_load_pnm_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1194 break;
1195 case FZ_IMAGE_JPX:
1196 fz_load_jpx_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1197 break;
1198 case FZ_IMAGE_JPEG:
1199 fz_load_jpeg_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1200 break;
1201 case FZ_IMAGE_PNG:
1202 fz_load_png_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1203 break;
1204 case FZ_IMAGE_JXR:
1205 fz_load_jxr_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1206 break;
1207 case FZ_IMAGE_TIFF:
1208 fz_load_tiff_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1209 break;
1210 case FZ_IMAGE_GIF:
1211 fz_load_gif_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1212 break;
1213 case FZ_IMAGE_BMP:
1214 fz_load_bmp_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1215 break;
1216 case FZ_IMAGE_JBIG2:
1217 fz_load_jbig2_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1218 break;
1219 default:
1220 fz_throw(ctx, FZ_ERROR_GENERIC, "unknown image file format");
1221 }
1222
1223 fz_try(ctx)
1224 {
1225 bc = fz_malloc_struct(ctx, fz_compressed_buffer);
1226 bc->buffer = fz_keep_buffer(ctx, buffer);
1227 bc->params.type = type;
1228 if (type == FZ_IMAGE_JPEG)
1229 bc->params.u.jpeg.color_transform = -1;
1230 image = fz_new_image_from_compressed_buffer(ctx, w, h, 8, cspace, xres, yres, 0, 0, NULL, NULL, bc, NULL);
1231 }
1232 fz_always(ctx)
1233 fz_drop_colorspace(ctx, cspace);
1234 fz_catch(ctx)
1235 fz_rethrow(ctx);
1236
1237 return image;
1238}
1239
1240/*
1241 Create a new image from the contents
1242 of a file, inferring its type from the format of the
1243 data.
1244*/
1245fz_image *
1246fz_new_image_from_file(fz_context *ctx, const char *path)
1247{
1248 fz_buffer *buffer;
1249 fz_image *image = NULL;
1250
1251 buffer = fz_read_file(ctx, path);
1252 fz_try(ctx)
1253 image = fz_new_image_from_buffer(ctx, buffer);
1254 fz_always(ctx)
1255 fz_drop_buffer(ctx, buffer);
1256 fz_catch(ctx)
1257 fz_rethrow(ctx);
1258
1259 return image;
1260}
1261
1262/*
1263 Request the natural resolution
1264 of an image.
1265
1266 xres, yres: Pointers to ints to be updated with the
1267 natural resolution of an image (or a sensible default
1268 if not encoded).
1269*/
1270void
1271fz_image_resolution(fz_image *image, int *xres, int *yres)
1272{
1273 *xres = image->xres;
1274 *yres = image->yres;
1275 if (*xres < 0 || *yres < 0 || (*xres == 0 && *yres == 0))
1276 {
1277 /* If neither xres or yres is sane, pick a sane value */
1278 *xres = SANE_DPI; *yres = SANE_DPI;
1279 }
1280 else if (*xres == 0)
1281 {
1282 *xres = *yres;
1283 }
1284 else if (*yres == 0)
1285 {
1286 *yres = *xres;
1287 }
1288
1289 /* Scale xres and yres up until we get believable values */
1290 if (*xres < SANE_DPI || *yres < SANE_DPI || *xres > INSANE_DPI || *yres > INSANE_DPI)
1291 {
1292 if (*xres == *yres)
1293 {
1294 *xres = SANE_DPI;
1295 *yres = SANE_DPI;
1296 }
1297 else if (*xres < *yres)
1298 {
1299 *yres = *yres * SANE_DPI / *xres;
1300 *xres = SANE_DPI;
1301 }
1302 else
1303 {
1304 *xres = *xres * SANE_DPI / *yres;
1305 *yres = SANE_DPI;
1306 }
1307 }
1308}
1309
1310typedef struct fz_display_list_image_s
1311{
1312 fz_image super;
1313 fz_matrix transform;
1314 fz_display_list *list;
1315} fz_display_list_image;
1316
1317static fz_pixmap *
1318display_list_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
1319{
1320 fz_display_list_image *image = (fz_display_list_image *)image_;
1321 fz_matrix ctm;
1322 fz_device *dev;
1323 fz_pixmap *pix;
1324
1325 fz_var(dev);
1326
1327 if (subarea)
1328 {
1329 /* So, the whole image should be scaled to w * h, but we only want the
1330 * given subarea of it. */
1331 int l = (subarea->x0 * w) / image->super.w;
1332 int t = (subarea->y0 * h) / image->super.h;
1333 int r = (subarea->x1 * w + image->super.w - 1) / image->super.w;
1334 int b = (subarea->y1 * h + image->super.h - 1) / image->super.h;
1335
1336 pix = fz_new_pixmap(ctx, image->super.colorspace, r-l, b-t, NULL, 0);
1337 pix->x = l;
1338 pix->y = t;
1339 }
1340 else
1341 {
1342 pix = fz_new_pixmap(ctx, image->super.colorspace, w, h, NULL, 0);
1343 }
1344
1345 /* If we render the display list into pix with the image matrix, we'll get a unit
1346 * square result. Therefore scale by w, h. */
1347 ctm = fz_pre_scale(image->transform, w, h);
1348
1349 fz_clear_pixmap(ctx, pix); /* clear to transparent */
1350 fz_try(ctx)
1351 {
1352 dev = fz_new_draw_device(ctx, ctm, pix);
1353 fz_run_display_list(ctx, image->list, dev, fz_identity, fz_infinite_rect, NULL);
1354 fz_close_device(ctx, dev);
1355 }
1356 fz_always(ctx)
1357 fz_drop_device(ctx, dev);
1358 fz_catch(ctx)
1359 {
1360 fz_drop_pixmap(ctx, pix);
1361 fz_rethrow(ctx);
1362 }
1363
1364 /* Never do more subsampling, cos we've already given them the right size */
1365 if (l2factor)
1366 *l2factor = 0;
1367
1368 return pix;
1369}
1370
1371static void drop_display_list_image(fz_context *ctx, fz_image *image_)
1372{
1373 fz_display_list_image *image = (fz_display_list_image *)image_;
1374
1375 if (image == NULL)
1376 return;
1377 fz_drop_display_list(ctx, image->list);
1378}
1379
1380static size_t
1381display_list_image_get_size(fz_context *ctx, fz_image *image_)
1382{
1383 fz_display_list_image *image = (fz_display_list_image *)image_;
1384
1385 if (image == NULL)
1386 return 0;
1387
1388 return sizeof(fz_display_list_image) + 4096; /* FIXME */
1389}
1390
1391/*
1392 Create a new image from a display list.
1393
1394 w, h: The conceptual width/height of the image.
1395
1396 transform: The matrix that needs to be applied to the given
1397 list to make it render to the unit square.
1398
1399 list: The display list.
1400*/
1401fz_image *fz_new_image_from_display_list(fz_context *ctx, float w, float h, fz_display_list *list)
1402{
1403 fz_display_list_image *image;
1404 int iw, ih;
1405
1406 iw = w * SCALABLE_IMAGE_DPI / 72;
1407 ih = h * SCALABLE_IMAGE_DPI / 72;
1408
1409 image = fz_new_derived_image(ctx, iw, ih, 8, fz_device_rgb(ctx),
1410 SCALABLE_IMAGE_DPI, SCALABLE_IMAGE_DPI, 0, 0,
1411 NULL, NULL, NULL, fz_display_list_image,
1412 display_list_image_get_pixmap,
1413 display_list_image_get_size,
1414 drop_display_list_image);
1415 image->super.scalable = 1;
1416 image->transform = fz_scale(1 / w, 1 / h);
1417 image->list = fz_keep_display_list(ctx, list);
1418
1419 return &image->super;
1420}
1421