summaryrefslogtreecommitdiff
path: root/source/fitz
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2017-03-22 14:38:35 +0100
committerRobin Watts <Robin.Watts@artifex.com>2017-03-23 17:09:19 -0400
commit031c7035652d3c967321c9c308dea7cfb1c0e6fa (patch)
tree58e1d638c18e935e7c98f0ec13034376582fc721 /source/fitz
parent185d530d3b3a6f8be63dd7cfc3f2b7784066707c (diff)
downloadmupdf-031c7035652d3c967321c9c308dea7cfb1c0e6fa.tar.xz
Add generic pixmap document writer.
Allow mutool convert to output all image formats we can write. Add sanity checks for pbm and pkm writers.
Diffstat (limited to 'source/fitz')
-rw-r--r--source/fitz/bitmap.c64
-rw-r--r--source/fitz/halftone.c5
-rw-r--r--source/fitz/output-cbz.c79
-rw-r--r--source/fitz/output-png.c71
-rw-r--r--source/fitz/output-pnm.c4
-rw-r--r--source/fitz/writer.c19
6 files changed, 155 insertions, 87 deletions
diff --git a/source/fitz/bitmap.c b/source/fitz/bitmap.c
index 9db6a1df..9780b1dd 100644
--- a/source/fitz/bitmap.c
+++ b/source/fitz/bitmap.c
@@ -326,21 +326,41 @@ pkm_write_header(fz_context *ctx, fz_band_writer *writer)
void
fz_write_bitmap_as_pbm(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
{
- fz_band_writer *writer = fz_new_pbm_band_writer(ctx, out);
+ fz_band_writer *writer;
- fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, 0, 0, 0);
- fz_write_band(ctx, writer, bitmap->stride, bitmap->h, bitmap->samples);
- fz_drop_band_writer(ctx, writer);
+ if (bitmap->n != 1)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "bitmap must be monochrome to save as PBM");
+
+ writer = fz_new_pbm_band_writer(ctx, out);
+ fz_try(ctx)
+ {
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, 0, 0, 0);
+ fz_write_band(ctx, writer, bitmap->stride, bitmap->h, bitmap->samples);
+ }
+ fz_always(ctx)
+ fz_drop_band_writer(ctx, writer);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
}
void
fz_write_bitmap_as_pkm(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
{
- fz_band_writer *writer = fz_new_pkm_band_writer(ctx, out);
+ fz_band_writer *writer;
+
+ if (bitmap->n != 4)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "bitmap must be CMYK to save as PKM");
- fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, 0, 0, 0);
- fz_write_band(ctx, writer, bitmap->stride, bitmap->h, bitmap->samples);
- fz_drop_band_writer(ctx, writer);
+ writer = fz_new_pkm_band_writer(ctx, out);
+ fz_try(ctx)
+ {
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, 4, 0, 0, 0, 0);
+ fz_write_band(ctx, writer, bitmap->stride, bitmap->h, bitmap->samples);
+ }
+ fz_always(ctx)
+ fz_drop_band_writer(ctx, writer);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
}
static void
@@ -421,7 +441,7 @@ fz_band_writer *fz_new_pkm_band_writer(fz_context *ctx, fz_output *out)
}
void
-fz_save_bitmap_as_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename)
+fz_save_bitmap_as_pbm(fz_context *ctx, fz_bitmap *bitmap, const char *filename)
{
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
fz_try(ctx)
@@ -433,7 +453,7 @@ fz_save_bitmap_as_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename)
}
void
-fz_save_bitmap_as_pkm(fz_context *ctx, fz_bitmap *bitmap, char *filename)
+fz_save_bitmap_as_pkm(fz_context *ctx, fz_bitmap *bitmap, const char *filename)
{
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
fz_try(ctx)
@@ -444,6 +464,30 @@ fz_save_bitmap_as_pkm(fz_context *ctx, fz_bitmap *bitmap, char *filename)
fz_rethrow(ctx);
}
+void
+fz_save_pixmap_as_pbm(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
+{
+ fz_bitmap *bitmap = fz_new_bitmap_from_pixmap(ctx, pixmap, NULL);
+ fz_try(ctx)
+ fz_save_bitmap_as_pbm(ctx, bitmap, filename);
+ fz_always(ctx)
+ fz_drop_bitmap(ctx, bitmap);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+}
+
+void
+fz_save_pixmap_as_pkm(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
+{
+ fz_bitmap *bitmap = fz_new_bitmap_from_pixmap(ctx, pixmap, NULL);
+ fz_try(ctx)
+ fz_save_bitmap_as_pkm(ctx, bitmap, filename);
+ fz_always(ctx)
+ fz_drop_bitmap(ctx, bitmap);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+}
+
void fz_bitmap_details(fz_bitmap *bit, int *w, int *h, int *n, int *stride)
{
if (!bit)
diff --git a/source/fitz/halftone.c b/source/fitz/halftone.c
index f0705790..58153fcf 100644
--- a/source/fitz/halftone.c
+++ b/source/fitz/halftone.c
@@ -528,7 +528,8 @@ fz_bitmap *fz_new_bitmap_from_pixmap_band(fz_context *ctx, fz_pixmap *pix, fz_ha
if (!pix)
return NULL;
- assert(pix->alpha == 0);
+ if (pix->alpha != 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap may not have alpha channel to convert to bitmap");
fz_var(ht_line);
fz_var(out);
@@ -544,7 +545,7 @@ fz_bitmap *fz_new_bitmap_from_pixmap_band(fz_context *ctx, fz_pixmap *pix, fz_ha
thresh = &do_threshold_4;
break;
default:
- assert(!"Unsupported number of components");
+ fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or CMYK to convert to bitmap");
return NULL;
}
diff --git a/source/fitz/output-cbz.c b/source/fitz/output-cbz.c
index 43be16cb..7268a805 100644
--- a/source/fitz/output-cbz.c
+++ b/source/fitz/output-cbz.c
@@ -87,3 +87,82 @@ fz_new_cbz_writer(fz_context *ctx, const char *path, const char *options)
return (fz_document_writer*)wri;
}
+
+/* generic image file output writer */
+
+typedef struct fz_pixmap_writer_s fz_pixmap_writer;
+
+struct fz_pixmap_writer_s
+{
+ fz_document_writer super;
+ fz_draw_options options;
+ fz_pixmap *pixmap;
+ void (*save)(fz_context *ctx, fz_pixmap *pix, const char *filename);
+ int count;
+ char *path;
+};
+
+static fz_device *
+pixmap_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox)
+{
+ fz_pixmap_writer *wri = (fz_pixmap_writer*)wri_;
+ return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, &wri->pixmap);
+}
+
+static void
+pixmap_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev)
+{
+ fz_pixmap_writer *wri = (fz_pixmap_writer*)wri_;
+ char path[PATH_MAX];
+
+ fz_close_device(ctx, dev);
+ fz_drop_device(ctx, dev);
+
+ wri->count += 1;
+
+ fz_format_output_path(ctx, path, sizeof path, wri->path, wri->count);
+ wri->save(ctx, wri->pixmap, path);
+ fz_drop_pixmap(ctx, wri->pixmap);
+ wri->pixmap = NULL;
+}
+
+static void
+pixmap_drop_writer(fz_context *ctx, fz_document_writer *wri_)
+{
+ fz_pixmap_writer *wri = (fz_pixmap_writer*)wri_;
+ fz_drop_pixmap(ctx, wri->pixmap);
+ fz_free(ctx, wri->path);
+}
+
+fz_document_writer *
+fz_new_pixmap_writer(fz_context *ctx, const char *path, const char *options,
+ const char *default_path, int n,
+ void (*save)(fz_context *ctx, fz_pixmap *pix, const char *filename))
+{
+ fz_pixmap_writer *wri;
+
+ wri = fz_malloc_struct(ctx, fz_pixmap_writer);
+ wri->super.begin_page = pixmap_begin_page;
+ wri->super.end_page = pixmap_end_page;
+ wri->super.drop_writer = pixmap_drop_writer;
+
+ fz_try(ctx)
+ {
+ fz_parse_draw_options(ctx, &wri->options, options);
+ wri->path = fz_strdup(ctx, path ? path : default_path);
+ wri->save = save;
+ switch (n)
+ {
+ case 1: wri->options.colorspace = fz_device_gray(ctx); break;
+ case 3: wri->options.colorspace = fz_device_rgb(ctx); break;
+ case 4: wri->options.colorspace = fz_device_cmyk(ctx); break;
+ }
+ }
+ fz_catch(ctx)
+ {
+ fz_free(ctx, wri);
+ fz_rethrow(ctx);
+ }
+
+ return (fz_document_writer*)wri;
+}
diff --git a/source/fitz/output-png.c b/source/fitz/output-png.c
index de5500c9..c8972b25 100644
--- a/source/fitz/output-png.c
+++ b/source/fitz/output-png.c
@@ -299,74 +299,3 @@ fz_new_buffer_from_pixmap_as_png(fz_context *ctx, fz_pixmap *pix)
{
return png_from_pixmap(ctx, pix, 0);
}
-
-/* PNG output writer */
-
-typedef struct fz_png_writer_s fz_png_writer;
-
-struct fz_png_writer_s
-{
- fz_document_writer super;
- fz_draw_options options;
- fz_pixmap *pixmap;
- int count;
- char *path;
-};
-
-const char *fz_png_write_options_usage = "";
-
-static fz_device *
-png_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox)
-{
- fz_png_writer *wri = (fz_png_writer*)wri_;
- return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, &wri->pixmap);
-}
-
-static void
-png_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev)
-{
- fz_png_writer *wri = (fz_png_writer*)wri_;
- char path[PATH_MAX];
-
- fz_close_device(ctx, dev);
- fz_drop_device(ctx, dev);
-
- wri->count += 1;
-
- fz_format_output_path(ctx, path, sizeof path, wri->path, wri->count);
- fz_save_pixmap_as_png(ctx, wri->pixmap, path);
- fz_drop_pixmap(ctx, wri->pixmap);
- wri->pixmap = NULL;
-}
-
-static void
-png_drop_writer(fz_context *ctx, fz_document_writer *wri_)
-{
- fz_png_writer *wri = (fz_png_writer*)wri_;
- fz_drop_pixmap(ctx, wri->pixmap);
- fz_free(ctx, wri->path);
-}
-
-fz_document_writer *
-fz_new_png_writer(fz_context *ctx, const char *path, const char *options)
-{
- fz_png_writer *wri;
-
- wri = fz_malloc_struct(ctx, fz_png_writer);
- wri->super.begin_page = png_begin_page;
- wri->super.end_page = png_end_page;
- wri->super.drop_writer = png_drop_writer;
-
- fz_try(ctx)
- {
- fz_parse_draw_options(ctx, &wri->options, options);
- wri->path = fz_strdup(ctx, path ? path : "out-%04d.png");
- }
- fz_catch(ctx)
- {
- fz_free(ctx, wri);
- fz_rethrow(ctx);
- }
-
- return (fz_document_writer*)wri;
-}
diff --git a/source/fitz/output-pnm.c b/source/fitz/output-pnm.c
index dbc521b7..455a5358 100644
--- a/source/fitz/output-pnm.c
+++ b/source/fitz/output-pnm.c
@@ -129,7 +129,7 @@ fz_write_pixmap_as_pnm(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
}
void
-fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename)
+fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
{
fz_band_writer *writer = NULL;
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
@@ -226,7 +226,7 @@ fz_write_pixmap_as_pam(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
}
void
-fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename)
+fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
{
fz_band_writer *writer = NULL;
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
diff --git a/source/fitz/writer.c b/source/fitz/writer.c
index 6ef40ffb..3c53f633 100644
--- a/source/fitz/writer.c
+++ b/source/fitz/writer.c
@@ -65,11 +65,26 @@ fz_new_document_writer(fz_context *ctx, const char *path, const char *format, co
if (!fz_strcasecmp(format, "pdf"))
return fz_new_pdf_writer(ctx, path, options);
#endif
- if (!fz_strcasecmp(format, "png"))
- return fz_new_png_writer(ctx, path, options);
if (!fz_strcasecmp(format, "svg"))
return fz_new_svg_writer(ctx, path, options);
+ if (!fz_strcasecmp(format, "png"))
+ return fz_new_pixmap_writer(ctx, path, options, "out-%04.png", 0, fz_save_pixmap_as_png);
+ if (!fz_strcasecmp(format, "tga"))
+ return fz_new_pixmap_writer(ctx, path, options, "out-%04.tga", 0, fz_save_pixmap_as_tga);
+ if (!fz_strcasecmp(format, "pam"))
+ return fz_new_pixmap_writer(ctx, path, options, "out-%04.pam", 0, fz_save_pixmap_as_pam);
+ if (!fz_strcasecmp(format, "pnm"))
+ return fz_new_pixmap_writer(ctx, path, options, "out-%04.pnm", 0, fz_save_pixmap_as_pnm);
+ if (!fz_strcasecmp(format, "pgm"))
+ return fz_new_pixmap_writer(ctx, path, options, "out-%04.pgm", 1, fz_save_pixmap_as_pnm);
+ if (!fz_strcasecmp(format, "ppm"))
+ return fz_new_pixmap_writer(ctx, path, options, "out-%04.ppm", 3, fz_save_pixmap_as_pnm);
+ if (!fz_strcasecmp(format, "pbm"))
+ return fz_new_pixmap_writer(ctx, path, options, "out-%04.pbm", 1, fz_save_pixmap_as_pbm);
+ if (!fz_strcasecmp(format, "pkm"))
+ return fz_new_pixmap_writer(ctx, path, options, "out-%04.pkm", 4, fz_save_pixmap_as_pkm);
+
fz_throw(ctx, FZ_ERROR_GENERIC, "unknown output document format: %s", format);
}