static fz_pixmap * standard_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h, int *l2factor) { int native_l2factor; fz_stream *stm; int indexed; fz_pixmap *tile; /* We need to make a new one. */ /* First check for ones that we can't decode using streams */ switch (image->buffer->params.type) { case FZ_IMAGE_PNG: tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_GIF: tile = fz_load_gif(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_TIFF: tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_JXR: tile = fz_load_jxr(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_JPEG: /* Scan JPEG stream and patch missing height values in header */ { unsigned char *s = image->buffer->buffer->data; unsigned char *e = s + image->buffer->buffer->len; unsigned char *d; for (d = s + 2; s < d && d < e - 9 && d[0] == 0xFF; d += (d[2] << 8 | d[3]) + 2) { if (d[1] < 0xC0 || (0xC3 < d[1] && d[1] < 0xC9) || 0xCB < d[1]) continue; if ((d[5] == 0 && d[6] == 0) || ((d[5] << 8) | d[6]) > image->h) { d[5] = (image->h >> 8) & 0xFF; d[6] = image->h & 0xFF; } } } /* fall through */ default: native_l2factor = l2factor ? *l2factor : 0; stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, l2factor); if (l2factor) native_l2factor -= *l2factor; indexed = fz_colorspace_is_indexed(ctx, image->colorspace); tile = fz_decomp_image_from_stream(ctx, stm, image, indexed, native_l2factor); /* CMYK JPEGs in XPS documents have to be inverted */ if (image->invert_cmyk_jpeg && image->buffer->params.type == FZ_IMAGE_JPEG && image->colorspace == fz_device_cmyk(ctx) && image->buffer->params.u.jpeg.color_transform) { fz_invert_pixmap(ctx, tile); } break; }
fz_pixmap * fz_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h) { fz_pixmap *tile; fz_stream *stm; int l2factor; fz_image_key key; int native_l2factor; int indexed; fz_image_key *keyp; /* Check for 'simple' images which are just pixmaps */ if (image->buffer == NULL) { tile = image->tile; if (!tile) return NULL; return fz_keep_pixmap(ctx, tile); /* That's all we can give you! */ } /* Ensure our expectations for tile size are reasonable */ if (w > image->w) w = image->w; if (h > image->h) h = image->h; /* What is our ideal factor? */ if (w == 0 || h == 0) l2factor = 0; else for (l2factor=0; image->w>>(l2factor+1) >= w && image->h>>(l2factor+1) >= h && l2factor < 8; l2factor++); /* Can we find any suitable tiles in the cache? */ key.refs = 1; key.image = image; key.l2factor = l2factor; do { tile = fz_find_item(ctx, fz_free_pixmap_imp, &key, &fz_image_store_type); if (tile) return tile; key.l2factor--; } while (key.l2factor >= 0); /* We need to make a new one. */ /* First check for ones that we can't decode using streams */ switch (image->buffer->params.type) { case FZ_IMAGE_PNG: tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_TIFF: tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; default: native_l2factor = l2factor; stm = fz_open_image_decomp_stream(ctx, image->buffer, &native_l2factor); indexed = fz_colorspace_is_indexed(image->colorspace); tile = fz_decomp_image_from_stream(ctx, stm, image, 0, indexed, l2factor, native_l2factor); break; } /* Now we try to cache the pixmap. Any failure here will just result * in us not caching. */ fz_var(keyp); fz_try(ctx) { fz_pixmap *existing_tile; keyp = fz_malloc_struct(ctx, fz_image_key); keyp->refs = 1; keyp->image = fz_keep_image(ctx, image); keyp->l2factor = l2factor; existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type); if (existing_tile) { /* We already have a tile. This must have been produced by a * racing thread. We'll throw away ours and use that one. */ fz_drop_pixmap(ctx, tile); tile = existing_tile; } } fz_always(ctx) { fz_drop_image_key(ctx, keyp); } fz_catch(ctx) { /* Do nothing */ } return tile; }