153 lines
3.5 KiB
C
153 lines
3.5 KiB
C
#include "mupdf/fitz.h"
|
|
#include "mupdf/pdf.h"
|
|
|
|
static void
|
|
fz_md5_image(fz_context *ctx, fz_image *image, unsigned char digest[16])
|
|
{
|
|
fz_pixmap *pixmap;
|
|
fz_md5 state;
|
|
int h;
|
|
unsigned char *d;
|
|
|
|
pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
|
|
fz_md5_init(&state);
|
|
d = pixmap->samples;
|
|
h = pixmap->h;
|
|
while (h--)
|
|
{
|
|
fz_md5_update(&state, d, pixmap->w * pixmap->n);
|
|
d += pixmap->stride;
|
|
}
|
|
fz_md5_final(&state, digest);
|
|
fz_drop_pixmap(ctx, pixmap);
|
|
}
|
|
|
|
/* Image specific methods */
|
|
static void
|
|
pdf_preload_image_resources(fz_context *ctx, pdf_document *doc)
|
|
{
|
|
int len, k;
|
|
pdf_obj *obj = NULL;
|
|
pdf_obj *type;
|
|
fz_image *image = NULL;
|
|
unsigned char digest[16];
|
|
|
|
fz_var(obj);
|
|
fz_var(image);
|
|
|
|
fz_try(ctx)
|
|
{
|
|
len = pdf_count_objects(ctx, doc);
|
|
for (k = 1; k < len; k++)
|
|
{
|
|
obj = pdf_new_indirect(ctx, doc, k, 0);
|
|
type = pdf_dict_get(ctx, obj, PDF_NAME(Subtype));
|
|
if (pdf_name_eq(ctx, type, PDF_NAME(Image)))
|
|
{
|
|
image = pdf_load_image(ctx, doc, obj);
|
|
fz_md5_image(ctx, image, digest);
|
|
fz_drop_image(ctx, image);
|
|
image = NULL;
|
|
|
|
/* Don't allow overwrites. */
|
|
if (!fz_hash_find(ctx, doc->resources.images, digest))
|
|
{
|
|
fz_hash_insert(ctx, doc->resources.images, digest, obj);
|
|
obj = NULL;
|
|
}
|
|
}
|
|
pdf_drop_obj(ctx, obj);
|
|
obj = NULL;
|
|
}
|
|
}
|
|
fz_always(ctx)
|
|
{
|
|
fz_drop_image(ctx, image);
|
|
pdf_drop_obj(ctx, obj);
|
|
}
|
|
fz_catch(ctx)
|
|
{
|
|
fz_rethrow(ctx);
|
|
}
|
|
}
|
|
|
|
static void pdf_drop_obj_as_void(fz_context *ctx, void *obj)
|
|
{
|
|
pdf_drop_obj(ctx, obj);
|
|
}
|
|
|
|
pdf_obj *
|
|
pdf_find_image_resource(fz_context *ctx, pdf_document *doc, fz_image *item, unsigned char digest[16])
|
|
{
|
|
pdf_obj *res;
|
|
|
|
if (!doc->resources.images)
|
|
{
|
|
doc->resources.images = fz_new_hash_table(ctx, 4096, 16, -1, pdf_drop_obj_as_void);
|
|
pdf_preload_image_resources(ctx, doc);
|
|
}
|
|
|
|
/* Create md5 and see if we have the item in our table */
|
|
fz_md5_image(ctx, item, digest);
|
|
res = fz_hash_find(ctx, doc->resources.images, digest);
|
|
if (res)
|
|
pdf_keep_obj(ctx, res);
|
|
return res;
|
|
}
|
|
|
|
pdf_obj *
|
|
pdf_insert_image_resource(fz_context *ctx, pdf_document *doc, unsigned char digest[16], pdf_obj *obj)
|
|
{
|
|
pdf_obj *res = fz_hash_insert(ctx, doc->resources.images, digest, obj);
|
|
if (res)
|
|
fz_warn(ctx, "warning: image resource already present");
|
|
else
|
|
res = pdf_keep_obj(ctx, obj);
|
|
return pdf_keep_obj(ctx, res);
|
|
}
|
|
|
|
/* We do need to come up with an effective way to see what is already in the
|
|
* file to avoid adding to what is already there. This is avoided for pdfwrite
|
|
* as we check as we add each font. For adding text to an existing file though
|
|
* it may be more problematic. */
|
|
|
|
pdf_obj *
|
|
pdf_find_font_resource(fz_context *ctx, pdf_document *doc, int type, int encoding, fz_font *item, unsigned char digest[16])
|
|
{
|
|
pdf_obj *res;
|
|
|
|
if (!doc->resources.fonts)
|
|
doc->resources.fonts = fz_new_hash_table(ctx, 4096, 16, -1, pdf_drop_obj_as_void);
|
|
|
|
fz_font_digest(ctx, item, digest);
|
|
|
|
digest[0] += type;
|
|
digest[1] += encoding;
|
|
|
|
res = fz_hash_find(ctx, doc->resources.fonts, digest);
|
|
if (res)
|
|
pdf_keep_obj(ctx, res);
|
|
return res;
|
|
}
|
|
|
|
pdf_obj *
|
|
pdf_insert_font_resource(fz_context *ctx, pdf_document *doc, unsigned char digest[16], pdf_obj *obj)
|
|
{
|
|
pdf_obj *res = fz_hash_insert(ctx, doc->resources.fonts, digest, obj);
|
|
if (res)
|
|
fz_warn(ctx, "warning: font resource already present");
|
|
else
|
|
res = pdf_keep_obj(ctx, obj);
|
|
return pdf_keep_obj(ctx, res);
|
|
}
|
|
|
|
void
|
|
pdf_drop_resource_tables(fz_context *ctx, pdf_document *doc)
|
|
{
|
|
if (doc)
|
|
{
|
|
fz_drop_hash_table(ctx, doc->resources.fonts);
|
|
fz_drop_hash_table(ctx, doc->resources.images);
|
|
}
|
|
}
|