1#include "mupdf/fitz.h"
2#include "mupdf/pdf.h"
3
4static void
5fz_md5_image(fz_context *ctx, fz_image *image, unsigned char digest[16])
6{
7 fz_pixmap *pixmap;
8 fz_md5 state;
9 int h;
10 unsigned char *d;
11
12 pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
13 fz_md5_init(&state);
14 d = pixmap->samples;
15 h = pixmap->h;
16 while (h--)
17 {
18 fz_md5_update(&state, d, pixmap->w * pixmap->n);
19 d += pixmap->stride;
20 }
21 fz_md5_final(&state, digest);
22 fz_drop_pixmap(ctx, pixmap);
23}
24
25/* Image specific methods */
26static void
27pdf_preload_image_resources(fz_context *ctx, pdf_document *doc)
28{
29 int len, k;
30 pdf_obj *obj = NULL;
31 pdf_obj *type;
32 fz_image *image = NULL;
33 unsigned char digest[16];
34
35 fz_var(obj);
36 fz_var(image);
37
38 fz_try(ctx)
39 {
40 len = pdf_count_objects(ctx, doc);
41 for (k = 1; k < len; k++)
42 {
43 obj = pdf_new_indirect(ctx, doc, k, 0);
44 type = pdf_dict_get(ctx, obj, PDF_NAME(Subtype));
45 if (pdf_name_eq(ctx, type, PDF_NAME(Image)))
46 {
47 image = pdf_load_image(ctx, doc, obj);
48 fz_md5_image(ctx, image, digest);
49 fz_drop_image(ctx, image);
50 image = NULL;
51
52 /* Don't allow overwrites. */
53 if (!fz_hash_find(ctx, doc->resources.images, digest))
54 fz_hash_insert(ctx, doc->resources.images, digest, pdf_keep_obj(ctx, obj));
55 }
56 pdf_drop_obj(ctx, obj);
57 obj = NULL;
58 }
59 }
60 fz_always(ctx)
61 {
62 fz_drop_image(ctx, image);
63 pdf_drop_obj(ctx, obj);
64 }
65 fz_catch(ctx)
66 {
67 fz_rethrow(ctx);
68 }
69}
70
71static void pdf_drop_obj_as_void(fz_context *ctx, void *obj)
72{
73 pdf_drop_obj(ctx, obj);
74}
75
76pdf_obj *
77pdf_find_image_resource(fz_context *ctx, pdf_document *doc, fz_image *item, unsigned char digest[16])
78{
79 pdf_obj *res;
80
81 if (!doc->resources.images)
82 {
83 doc->resources.images = fz_new_hash_table(ctx, 4096, 16, -1, pdf_drop_obj_as_void);
84 pdf_preload_image_resources(ctx, doc);
85 }
86
87 /* Create md5 and see if we have the item in our table */
88 fz_md5_image(ctx, item, digest);
89 res = fz_hash_find(ctx, doc->resources.images, digest);
90 if (res)
91 pdf_keep_obj(ctx, res);
92 return res;
93}
94
95pdf_obj *
96pdf_insert_image_resource(fz_context *ctx, pdf_document *doc, unsigned char digest[16], pdf_obj *obj)
97{
98 pdf_obj *res = fz_hash_insert(ctx, doc->resources.images, digest, obj);
99 if (res)
100 fz_warn(ctx, "warning: image resource already present");
101 else
102 res = pdf_keep_obj(ctx, obj);
103 return pdf_keep_obj(ctx, res);
104}
105
106/* We do need to come up with an effective way to see what is already in the
107 * file to avoid adding to what is already there. This is avoided for pdfwrite
108 * as we check as we add each font. For adding text to an existing file though
109 * it may be more problematic. */
110
111pdf_obj *
112pdf_find_font_resource(fz_context *ctx, pdf_document *doc, int type, int encoding, fz_font *item, unsigned char digest[16])
113{
114 pdf_obj *res;
115
116 if (!doc->resources.fonts)
117 doc->resources.fonts = fz_new_hash_table(ctx, 4096, 16, -1, pdf_drop_obj_as_void);
118
119 fz_font_digest(ctx, item, digest);
120
121 digest[0] += type;
122 digest[1] += encoding;
123
124 res = fz_hash_find(ctx, doc->resources.fonts, digest);
125 if (res)
126 pdf_keep_obj(ctx, res);
127 return res;
128}
129
130pdf_obj *
131pdf_insert_font_resource(fz_context *ctx, pdf_document *doc, unsigned char digest[16], pdf_obj *obj)
132{
133 pdf_obj *res = fz_hash_insert(ctx, doc->resources.fonts, digest, obj);
134 if (res)
135 fz_warn(ctx, "warning: font resource already present");
136 else
137 res = pdf_keep_obj(ctx, obj);
138 return pdf_keep_obj(ctx, res);
139}
140
141void
142pdf_drop_resource_tables(fz_context *ctx, pdf_document *doc)
143{
144 if (doc)
145 {
146 fz_drop_hash_table(ctx, doc->resources.fonts);
147 fz_drop_hash_table(ctx, doc->resources.images);
148 }
149}
150