1#include "mupdf/fitz.h"
2
3#include <zlib.h>
4
5#include <limits.h>
6
7#ifndef PATH_MAX
8#define PATH_MAX 4096
9#endif
10
11typedef struct fz_cbz_writer_s fz_cbz_writer;
12
13struct fz_cbz_writer_s
14{
15 fz_document_writer super;
16 fz_draw_options options;
17 fz_pixmap *pixmap;
18 int count;
19 fz_zip_writer *zip;
20};
21
22static fz_device *
23cbz_begin_page(fz_context *ctx, fz_document_writer *wri_, fz_rect mediabox)
24{
25 fz_cbz_writer *wri = (fz_cbz_writer*)wri_;
26 return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, &wri->pixmap);
27}
28
29static void
30cbz_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev)
31{
32 fz_cbz_writer *wri = (fz_cbz_writer*)wri_;
33 fz_buffer *buffer = NULL;
34 char name[40];
35
36 fz_var(buffer);
37
38 fz_try(ctx)
39 {
40 fz_close_device(ctx, dev);
41 wri->count += 1;
42 fz_snprintf(name, sizeof name, "p%04d.png", wri->count);
43 buffer = fz_new_buffer_from_pixmap_as_png(ctx, wri->pixmap, fz_default_color_params);
44 fz_write_zip_entry(ctx, wri->zip, name, buffer, 0);
45 }
46 fz_always(ctx)
47 {
48 fz_drop_device(ctx, dev);
49 fz_drop_buffer(ctx, buffer);
50 fz_drop_pixmap(ctx, wri->pixmap);
51 wri->pixmap = NULL;
52 }
53 fz_catch(ctx)
54 fz_rethrow(ctx);
55}
56
57static void
58cbz_close_writer(fz_context *ctx, fz_document_writer *wri_)
59{
60 fz_cbz_writer *wri = (fz_cbz_writer*)wri_;
61 fz_close_zip_writer(ctx, wri->zip);
62}
63
64static void
65cbz_drop_writer(fz_context *ctx, fz_document_writer *wri_)
66{
67 fz_cbz_writer *wri = (fz_cbz_writer*)wri_;
68 fz_drop_zip_writer(ctx, wri->zip);
69 fz_drop_pixmap(ctx, wri->pixmap);
70}
71
72fz_document_writer *
73fz_new_cbz_writer(fz_context *ctx, const char *path, const char *options)
74{
75 fz_cbz_writer *wri = fz_new_derived_document_writer(ctx, fz_cbz_writer, cbz_begin_page, cbz_end_page, cbz_close_writer, cbz_drop_writer);
76
77 fz_try(ctx)
78 {
79 fz_parse_draw_options(ctx, &wri->options, options);
80 wri->zip = fz_new_zip_writer(ctx, path ? path : "out.cbz");
81 }
82 fz_catch(ctx)
83 {
84 fz_free(ctx, wri);
85 fz_rethrow(ctx);
86 }
87
88 return (fz_document_writer*)wri;
89}
90
91/* generic image file output writer */
92
93typedef struct fz_pixmap_writer_s fz_pixmap_writer;
94
95struct fz_pixmap_writer_s
96{
97 fz_document_writer super;
98 fz_draw_options options;
99 fz_pixmap *pixmap;
100 void (*save)(fz_context *ctx, fz_pixmap *pix, const char *filename);
101 int count;
102 char *path;
103};
104
105static fz_device *
106pixmap_begin_page(fz_context *ctx, fz_document_writer *wri_, fz_rect mediabox)
107{
108 fz_pixmap_writer *wri = (fz_pixmap_writer*)wri_;
109 return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, &wri->pixmap);
110}
111
112static void
113pixmap_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev)
114{
115 fz_pixmap_writer *wri = (fz_pixmap_writer*)wri_;
116 char path[PATH_MAX];
117
118 fz_try(ctx)
119 {
120 fz_close_device(ctx, dev);
121 wri->count += 1;
122 fz_format_output_path(ctx, path, sizeof path, wri->path, wri->count);
123 wri->save(ctx, wri->pixmap, path);
124 }
125 fz_always(ctx)
126 {
127 fz_drop_device(ctx, dev);
128 fz_drop_pixmap(ctx, wri->pixmap);
129 wri->pixmap = NULL;
130 }
131 fz_catch(ctx)
132 fz_rethrow(ctx);
133}
134
135static void
136pixmap_drop_writer(fz_context *ctx, fz_document_writer *wri_)
137{
138 fz_pixmap_writer *wri = (fz_pixmap_writer*)wri_;
139 fz_drop_pixmap(ctx, wri->pixmap);
140 fz_free(ctx, wri->path);
141}
142
143fz_document_writer *
144fz_new_pixmap_writer(fz_context *ctx, const char *path, const char *options,
145 const char *default_path, int n,
146 void (*save)(fz_context *ctx, fz_pixmap *pix, const char *filename))
147{
148 fz_pixmap_writer *wri = fz_new_derived_document_writer(ctx, fz_pixmap_writer, pixmap_begin_page, pixmap_end_page, NULL, pixmap_drop_writer);
149
150 fz_try(ctx)
151 {
152 fz_parse_draw_options(ctx, &wri->options, options);
153 wri->path = fz_strdup(ctx, path ? path : default_path);
154 wri->save = save;
155 switch (n)
156 {
157 case 1: wri->options.colorspace = fz_device_gray(ctx); break;
158 case 3: wri->options.colorspace = fz_device_rgb(ctx); break;
159 case 4: wri->options.colorspace = fz_device_cmyk(ctx); break;
160 }
161 }
162 fz_catch(ctx)
163 {
164 fz_free(ctx, wri);
165 fz_rethrow(ctx);
166 }
167
168 return (fz_document_writer*)wri;
169}
170