Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
/*
2
 * pdfdraw -- command line tool for drawing pdf documents
3
 */
4
 
5
#include "fitz.h"
6
#include "mupdf.h"
7
 
8
#ifdef _MSC_VER
9
#include 
10
#else
11
#include 
12
#endif
13
 
14
char *output = NULL;
15
float resolution = 72;
16
float rotation = 0;
17
 
18
int showxml = 0;
19
int showtext = 0;
20
int showtime = 0;
21
int showmd5 = 0;
22
int savealpha = 0;
23
int uselist = 1;
24
int alphabits = 8;
25
float gamma_value = 1;
26
int invert = 0;
27
 
28
fz_colorspace *colorspace;
29
fz_glyph_cache *glyphcache;
30
char *filename;
31
 
32
struct {
33
	int count, total;
34
	int min, max;
35
	int minpage, maxpage;
36
} timing;
37
 
38
static void die(fz_error error)
39
{
40
	fz_catch(error, "aborting");
41
	exit(1);
42
}
43
 
44
static void usage(void)
45
{
46
	fprintf(stderr,
47
		"usage: pdfdraw [options] input.pdf [pages]\n"
48
		"\t-o -\toutput filename (%%d for page number)\n"
49
		"\t\tsupported formats: pgm, ppm, pam, png, pbm\n"
50
		"\t-p -\tpassword\n"
51
		"\t-r -\tresolution in dpi (default: 72)\n"
52
		"\t-A\tdisable accelerated functions\n"
53
		"\t-a\tsave alpha channel (only pam and png)\n"
54
		"\t-b -\tnumber of bits of antialiasing (0 to 8)\n"
55
		"\t-g\trender in grayscale\n"
56
		"\t-m\tshow timing information\n"
57
		"\t-t\tshow text (-tt for xml)\n"
58
		"\t-x\tshow display list\n"
59
		"\t-d\tdisable use of display list\n"
60
		"\t-5\tshow md5 checksums\n"
61
		"\t-R -\trotate clockwise by given number of degrees\n"
62
		"\t-G gamma\tgamma correct output\n"
63
		"\t-I\tinvert output\n"
64
		"\tpages\tcomma separated list of ranges\n");
65
	exit(1);
66
}
67
 
68
static int gettime(void)
69
{
70
	static struct timeval first;
71
	static int once = 1;
72
	struct timeval now;
73
	if (once)
74
	{
75
		gettimeofday(&first, NULL);
76
		once = 0;
77
	}
78
	gettimeofday(&now, NULL);
79
	return (now.tv_sec - first.tv_sec) * 1000 + (now.tv_usec - first.tv_usec) / 1000;
80
}
81
 
82
static int isrange(char *s)
83
{
84
	while (*s)
85
	{
86
		if ((*s < '0' || *s > '9') && *s != '-' && *s != ',')
87
			return 0;
88
		s++;
89
	}
90
	return 1;
91
}
92
 
93
static void drawpage(pdf_xref *xref, int pagenum)
94
{
95
	fz_error error;
96
	pdf_page *page;
97
	fz_display_list *list;
98
	fz_device *dev;
99
	int start;
100
 
101
	if (showtime)
102
	{
103
		start = gettime();
104
	}
105
 
106
	error = pdf_load_page(&page, xref, pagenum - 1);
107
	if (error)
108
		die(fz_rethrow(error, "cannot load page %d in file '%s'", pagenum, filename));
109
 
110
	list = NULL;
111
 
112
	if (uselist)
113
	{
114
		list = fz_new_display_list();
115
		dev = fz_new_list_device(list);
116
		error = pdf_run_page(xref, page, dev, fz_identity);
117
		if (error)
118
			die(fz_rethrow(error, "cannot draw page %d in file '%s'", pagenum, filename));
119
		fz_free_device(dev);
120
	}
121
 
122
	if (showxml)
123
	{
124
		dev = fz_new_trace_device();
125
		printf("\n", pagenum);
126
		if (list)
127
			fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
128
		else
129
			pdf_run_page(xref, page, dev, fz_identity);
130
		printf("\n");
131
		fz_free_device(dev);
132
	}
133
 
134
	if (showtext)
135
	{
136
		fz_text_span *text = fz_new_text_span();
137
		dev = fz_new_text_device(text);
138
		if (list)
139
			fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
140
		else
141
			pdf_run_page(xref, page, dev, fz_identity);
142
		fz_free_device(dev);
143
		printf("[Page %d]\n", pagenum);
144
		if (showtext > 1)
145
			fz_debug_text_span_xml(text);
146
		else
147
			fz_debug_text_span(text);
148
		printf("\n");
149
		fz_free_text_span(text);
150
	}
151
 
152
	if (showmd5 || showtime)
153
		printf("page %s %d", filename, pagenum);
154
 
155
	if (output || showmd5 || showtime)
156
	{
157
		float zoom;
158
		fz_matrix ctm;
159
		fz_bbox bbox;
160
		fz_pixmap *pix;
161
 
162
		zoom = resolution / 72;
163
		ctm = fz_translate(0, -page->mediabox.y1);
164
		ctm = fz_concat(ctm, fz_scale(zoom, -zoom));
165
		ctm = fz_concat(ctm, fz_rotate(page->rotate));
166
		ctm = fz_concat(ctm, fz_rotate(rotation));
167
		bbox = fz_round_rect(fz_transform_rect(ctm, page->mediabox));
168
 
169
		/* TODO: banded rendering and multi-page ppm */
170
 
171
		pix = fz_new_pixmap_with_rect(colorspace, bbox);
172
 
173
		if (savealpha)
174
			fz_clear_pixmap(pix);
175
		else
176
			fz_clear_pixmap_with_color(pix, 255);
177
 
178
		dev = fz_new_draw_device(glyphcache, pix);
179
		if (list)
180
			fz_execute_display_list(list, dev, ctm, bbox);
181
		else
182
			pdf_run_page(xref, page, dev, ctm);
183
		fz_free_device(dev);
184
 
185
		if (invert)
186
			fz_invert_pixmap(pix);
187
		if (gamma_value != 1)
188
			fz_gamma_pixmap(pix, gamma_value);
189
 
190
		if (output)
191
		{
192
			char buf[512];
193
			sprintf(buf, output, pagenum);
194
			if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm"))
195
				fz_write_pnm(pix, buf);
196
			else if (strstr(output, ".pam"))
197
				fz_write_pam(pix, buf, savealpha);
198
			else if (strstr(output, ".png"))
199
				fz_write_png(pix, buf, savealpha);
200
			else if (strstr(output, ".pbm")) {
201
				fz_halftone *ht = fz_get_default_halftone(1);
202
				fz_bitmap *bit = fz_halftone_pixmap(pix, ht);
203
				fz_write_pbm(bit, buf);
204
				fz_drop_bitmap(bit);
205
				fz_drop_halftone(ht);
206
			}
207
		}
208
 
209
		if (showmd5)
210
		{
211
			fz_md5 md5;
212
			unsigned char digest[16];
213
			int i;
214
 
215
			fz_md5_init(&md5);
216
			fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n);
217
			fz_md5_final(&md5, digest);
218
 
219
			printf(" ");
220
			for (i = 0; i < 16; i++)
221
				printf("%02x", digest[i]);
222
		}
223
 
224
		fz_drop_pixmap(pix);
225
	}
226
 
227
	if (list)
228
		fz_free_display_list(list);
229
 
230
	pdf_free_page(page);
231
 
232
	if (showtime)
233
	{
234
		int end = gettime();
235
		int diff = end - start;
236
 
237
		if (diff < timing.min)
238
		{
239
			timing.min = diff;
240
			timing.minpage = pagenum;
241
		}
242
		if (diff > timing.max)
243
		{
244
			timing.max = diff;
245
			timing.maxpage = pagenum;
246
		}
247
		timing.total += diff;
248
		timing.count ++;
249
 
250
		printf(" %dms", diff);
251
	}
252
 
253
	if (showmd5 || showtime)
254
		printf("\n");
255
 
256
	pdf_age_store(xref->store, 3);
257
 
258
	fz_flush_warnings();
259
}
260
 
261
static void drawrange(pdf_xref *xref, char *range)
262
{
263
	int page, spage, epage;
264
	char *spec, *dash;
265
 
266
	spec = fz_strsep(&range, ",");
267
	while (spec)
268
	{
269
		dash = strchr(spec, '-');
270
 
271
		if (dash == spec)
272
			spage = epage = pdf_count_pages(xref);
273
		else
274
			spage = epage = atoi(spec);
275
 
276
		if (dash)
277
		{
278
			if (strlen(dash) > 1)
279
				epage = atoi(dash + 1);
280
			else
281
				epage = pdf_count_pages(xref);
282
		}
283
 
284
		spage = CLAMP(spage, 1, pdf_count_pages(xref));
285
		epage = CLAMP(epage, 1, pdf_count_pages(xref));
286
 
287
		if (spage < epage)
288
			for (page = spage; page <= epage; page++)
289
				drawpage(xref, page);
290
		else
291
			for (page = spage; page >= epage; page--)
292
				drawpage(xref, page);
293
 
294
		spec = fz_strsep(&range, ",");
295
	}
296
}
297
 
298
int main(int argc, char **argv)
299
{
300
	char *password = "";
301
	int grayscale = 0;
302
	int accelerate = 1;
303
	pdf_xref *xref;
304
	fz_error error;
305
	int c;
306
 
307
	while ((c = fz_getopt(argc, argv, "o:p:r:R:Aab:dgmtx5G:I")) != -1)
308
	{
309
		switch (c)
310
		{
311
		case 'o': output = fz_optarg; break;
312
		case 'p': password = fz_optarg; break;
313
		case 'r': resolution = atof(fz_optarg); break;
314
		case 'R': rotation = atof(fz_optarg); break;
315
		case 'A': accelerate = 0; break;
316
		case 'a': savealpha = 1; break;
317
		case 'b': alphabits = atoi(fz_optarg); break;
318
		case 'm': showtime++; break;
319
		case 't': showtext++; break;
320
		case 'x': showxml++; break;
321
		case '5': showmd5++; break;
322
		case 'g': grayscale++; break;
323
		case 'd': uselist = 0; break;
324
		case 'G': gamma_value = atof(fz_optarg); break;
325
		case 'I': invert++; break;
326
		default: usage(); break;
327
		}
328
	}
329
 
330
	fz_set_aa_level(alphabits);
331
 
332
	if (fz_optind == argc)
333
		usage();
334
 
335
	if (!showtext && !showxml && !showtime && !showmd5 && !output)
336
	{
337
		printf("nothing to do\n");
338
		exit(0);
339
	}
340
 
341
	if (accelerate)
342
		fz_accelerate();
343
 
344
	glyphcache = fz_new_glyph_cache();
345
 
346
	colorspace = fz_device_rgb;
347
	if (grayscale)
348
		colorspace = fz_device_gray;
349
	if (output && strstr(output, ".pgm"))
350
		colorspace = fz_device_gray;
351
	if (output && strstr(output, ".ppm"))
352
		colorspace = fz_device_rgb;
353
	if (output && strstr(output, ".pbm"))
354
		colorspace = fz_device_gray;
355
 
356
	timing.count = 0;
357
	timing.total = 0;
358
	timing.min = 1 << 30;
359
	timing.max = 0;
360
	timing.minpage = 0;
361
	timing.maxpage = 0;
362
 
363
	if (showxml)
364
		printf("\n");
365
 
366
	while (fz_optind < argc)
367
	{
368
		filename = argv[fz_optind++];
369
 
370
		error = pdf_open_xref(&xref, filename, password);
371
		if (error)
372
			die(fz_rethrow(error, "cannot open document: %s", filename));
373
 
374
		error = pdf_load_page_tree(xref);
375
		if (error)
376
			die(fz_rethrow(error, "cannot load page tree: %s", filename));
377
 
378
		if (showxml)
379
			printf("\n", filename);
380
 
381
		if (fz_optind == argc || !isrange(argv[fz_optind]))
382
			drawrange(xref, "1-");
383
		if (fz_optind < argc && isrange(argv[fz_optind]))
384
			drawrange(xref, argv[fz_optind++]);
385
 
386
		if (showxml)
387
			printf("\n");
388
 
389
		pdf_free_xref(xref);
390
	}
391
 
392
	if (showtime)
393
	{
394
		printf("total %dms / %d pages for an average of %dms\n",
395
			timing.total, timing.count, timing.total / timing.count);
396
		printf("fastest page %d: %dms\n", timing.minpage, timing.min);
397
		printf("slowest page %d: %dms\n", timing.maxpage, timing.max);
398
	}
399
 
400
	fz_free_glyph_cache(glyphcache);
401
 
402
	fz_flush_warnings();
403
 
404
	return 0;
405
}