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