summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-10-11 21:10:21 +0100
committerRobin Watts <robin.watts@artifex.com>2016-10-12 12:37:48 +0100
commit80308eae9964e71b66a18f3de6ebcd2ebf0d306b (patch)
tree6aa51f6f53fca59d3c7afcb727f36cf627249e7a
parent7de80f5eea6c9475b1db2b4fd905fd69ed3795e7 (diff)
downloadmupdf-80308eae9964e71b66a18f3de6ebcd2ebf0d306b.tar.xz
Regularize band writer interface.
We have various functions that, for different image formats, write a header, then a band, then (sometimes) a trailer. Push them all through a single interface. This change also fixes potential problems caused by the trailer writing being an implicit destructor, which can cause problems in cleanup code if the trailer writing throws an error.
-rw-r--r--include/mupdf/fitz/output-pcl.h16
-rw-r--r--include/mupdf/fitz/output-png.h10
-rw-r--r--include/mupdf/fitz/output-pnm.h16
-rw-r--r--include/mupdf/fitz/output-ps.h8
-rw-r--r--include/mupdf/fitz/output.h33
-rw-r--r--source/fitz/bitmap.c94
-rw-r--r--source/fitz/output-pcl.c280
-rw-r--r--source/fitz/output-png.c146
-rw-r--r--source/fitz/output-pnm.c112
-rw-r--r--source/fitz/output-ps.c135
-rw-r--r--source/fitz/output.c48
-rw-r--r--source/tools/mudraw.c79
-rw-r--r--source/tools/muraster.c57
13 files changed, 614 insertions, 420 deletions
diff --git a/include/mupdf/fitz/output-pcl.h b/include/mupdf/fitz/output-pcl.h
index 309bfc23..338d7553 100644
--- a/include/mupdf/fitz/output-pcl.h
+++ b/include/mupdf/fitz/output-pcl.h
@@ -90,25 +90,13 @@ void fz_pcl_preset(fz_context *ctx, fz_pcl_options *opts, const char *preset);
*/
void fz_pcl_option(fz_context *ctx, fz_pcl_options *opts, const char *option, int val);
-typedef struct fz_mono_pcl_output_context_s fz_mono_pcl_output_context;
-
-fz_mono_pcl_output_context *fz_write_mono_pcl_header(fz_context *ctx, fz_output *out, int w, int h, int xres, int yres, int pagenum, const fz_pcl_options *options);
-
-void fz_write_mono_pcl_band(fz_context *ctx, fz_output *out, fz_mono_pcl_output_context *poc, const fz_bitmap *bitmap);
-
-void fz_write_mono_pcl_trailer(fz_context *ctx, fz_output *out, fz_mono_pcl_output_context *pcoc);
+fz_band_writer *fz_new_mono_pcl_band_writer(fz_context *ctx, fz_output *out, const fz_pcl_options *options);
void fz_write_bitmap_as_pcl(fz_context *ctx, fz_output *out, const fz_bitmap *bitmap, const fz_pcl_options *pcl);
void fz_save_bitmap_as_pcl(fz_context *ctx, fz_bitmap *bitmap, char *filename, int append, const fz_pcl_options *pcl);
-typedef struct fz_color_pcl_output_context_s fz_color_pcl_output_context;
-
-fz_color_pcl_output_context *fz_write_color_pcl_header(fz_context *ctx, fz_output *out, int w, int h, int n, int xres, int yres, int pagenum, const fz_pcl_options *options);
-
-void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *poc, int w, int h, int n, int stride, int band_start, int bandheight, unsigned char *samples);
-
-void fz_write_color_pcl_trailer(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *pcoc);
+fz_band_writer *fz_new_color_pcl_band_writer(fz_context *ctx, fz_output *out, const fz_pcl_options *options);
void fz_write_pixmap_as_pcl(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap, const fz_pcl_options *pcl);
diff --git a/include/mupdf/fitz/output-png.h b/include/mupdf/fitz/output-png.h
index d98d7c7f..60283c7c 100644
--- a/include/mupdf/fitz/output-png.h
+++ b/include/mupdf/fitz/output-png.h
@@ -20,11 +20,11 @@ void fz_save_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap, const char *filen
*/
void fz_write_pixmap_as_png(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap);
-typedef struct fz_png_output_context_s fz_png_output_context;
-
-fz_png_output_context *fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha);
-void fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, int stride, int band_start, int bandheight, unsigned char *samples);
-void fz_write_png_trailer(fz_context *ctx, fz_output *out, fz_png_output_context *poc);
+/*
+ fz_new_png_band_writer: Obtain a fz_band_writer instance
+ for producing PNG output.
+*/
+fz_band_writer *fz_new_png_band_writer(fz_context *ctx, fz_output *out);
/*
Create a new buffer containing the image/pixmap in PNG format.
diff --git a/include/mupdf/fitz/output-pnm.h b/include/mupdf/fitz/output-pnm.h
index 09cad4ef..66198325 100644
--- a/include/mupdf/fitz/output-pnm.h
+++ b/include/mupdf/fitz/output-pnm.h
@@ -13,8 +13,8 @@
void fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename);
void fz_write_pixmap_as_pnm(fz_context *ctx, fz_output *out, fz_pixmap *pixmap);
-void fz_write_pnm_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha);
-void fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha, int stride, int band_start, int bandheight, unsigned char *p);
+
+fz_band_writer *fz_new_pnm_band_writer(fz_context *ctx, fz_output *out);
/*
fz_save_pixmap_as_pam: Save a pixmap as a PAM image file.
@@ -22,8 +22,8 @@ void fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int
void fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename);
void fz_write_pixmap_as_pam(fz_context *ctx, fz_output *out, fz_pixmap *pixmap);
-void fz_write_pam_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha);
-void fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha, int stride, int band_start, int bandheight, unsigned char *sp);
+
+fz_band_writer *fz_new_pam_band_writer(fz_context *ctx, fz_output *out);
/*
fz_save_bitmap_as_pbm: Save a bitmap as a PBM image file.
@@ -32,9 +32,7 @@ void fz_save_bitmap_as_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename);
void fz_write_bitmap_as_pbm(fz_context *ctx, fz_output *out, fz_bitmap *bitmap);
-void fz_write_pbm_header(fz_context *ctx, fz_output *out, int w, int h);
-
-void fz_write_pbm_band(fz_context *ctx, fz_output *out, fz_bitmap *bitmap);
+fz_band_writer *fz_new_pbm_band_writer(fz_context *ctx, fz_output *out);
/*
fz_save_bitmap_as_pkm: Save a 4bpp cmyk bitmap as a PAM image file.
@@ -43,8 +41,6 @@ void fz_save_bitmap_as_pkm(fz_context *ctx, fz_bitmap *bitmap, char *filename);
void fz_write_bitmap_as_pkm(fz_context *ctx, fz_output *out, fz_bitmap *bitmap);
-void fz_write_pkm_header(fz_context *ctx, fz_output *out, int w, int h);
-
-void fz_write_pkm_band(fz_context *ctx, fz_output *out, fz_bitmap *bitmap);
+fz_band_writer *fz_new_pkm_band_writer(fz_context *ctx, fz_output *out);
#endif
diff --git a/include/mupdf/fitz/output-ps.h b/include/mupdf/fitz/output-ps.h
index 7caed53b..1f187663 100644
--- a/include/mupdf/fitz/output-ps.h
+++ b/include/mupdf/fitz/output-ps.h
@@ -6,8 +6,6 @@
#include "mupdf/fitz/output.h"
#include "mupdf/fitz/pixmap.h"
-typedef struct fz_ps_output_context_s fz_ps_output_context;
-
/*
PS (image) output
*/
@@ -17,11 +15,7 @@ void fz_save_pixmap_as_ps(fz_context *ctx, fz_pixmap *pixmap, char *filename, in
void fz_write_ps_file_header(fz_context *ctx, fz_output *out);
-fz_ps_output_context *fz_write_ps_header(fz_context *ctx, fz_output *out, int w, int h, int n, int xres, int yres, int pagenum);
-
-void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int stride, int band_start, int bandheight, unsigned char *samples);
-
-void fz_write_ps_trailer(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc);
+fz_band_writer *fz_new_ps_band_writer(fz_context *ctx, fz_output *out);
void fz_write_ps_file_trailer(fz_context *ctx, fz_output *out, int pages);
diff --git a/include/mupdf/fitz/output.h b/include/mupdf/fitz/output.h
index d4abd712..ffa140f9 100644
--- a/include/mupdf/fitz/output.h
+++ b/include/mupdf/fitz/output.h
@@ -164,4 +164,37 @@ void fz_new_output_context(fz_context *ctx);
void fz_drop_output_context(fz_context *ctx);
fz_output_context *fz_keep_output_context(fz_context *ctx);
+/*
+ fz_band_writer
+*/
+typedef struct fz_band_writer_s fz_band_writer;
+
+typedef void (fz_write_header_fn)(fz_context *ctx, fz_band_writer *writer);
+typedef void (fz_write_band_fn)(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int bandheight, const unsigned char *samples);
+typedef void (fz_write_trailer_fn)(fz_context *ctx, fz_band_writer *writer);
+typedef void (fz_drop_band_writer_fn)(fz_context *ctx, fz_band_writer *writer);
+
+struct fz_band_writer_s
+{
+ fz_drop_band_writer_fn *drop;
+ fz_write_header_fn *header;
+ fz_write_band_fn *band;
+ fz_write_trailer_fn *trailer;
+ fz_output *out;
+ int w;
+ int h;
+ int n;
+ int alpha;
+ int xres;
+ int yres;
+ int pagenum;
+};
+
+fz_band_writer *fz_new_band_writer_of_size(fz_context *ctx, size_t size, fz_output *out);
+#define fz_new_band_writer(C,M,O) ((M *)Memento_label(fz_new_band_writer_of_size(ctx, sizeof(M), O), #M))
+void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int n, int alpha, int xres, int yres, int pagenum);
+void fz_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int bandheight, const unsigned char *samples);
+void fz_write_trailer(fz_context *ctx, fz_band_writer *writer);
+void fz_drop_band_writer(fz_context *ctx, fz_band_writer *writer);
+
#endif
diff --git a/source/fitz/bitmap.c b/source/fitz/bitmap.c
index dc2645ec..46cfa533 100644
--- a/source/fitz/bitmap.c
+++ b/source/fitz/bitmap.c
@@ -303,72 +303,81 @@ fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit)
memset(bit->samples, 0, bit->stride * bit->h);
}
-void
-fz_write_pbm_header(fz_context *ctx, fz_output *out, int w, int h)
+static void
+pbm_write_header(fz_context *ctx, fz_band_writer *writer)
{
+ fz_output *out = writer->out;
+ int w = writer->w;
+ int h = writer->h;
+
fz_printf(ctx, out, "P4\n%d %d\n", w, h);
}
-void
-fz_write_pkm_header(fz_context *ctx, fz_output *out, int w, int h)
+static void
+pkm_write_header(fz_context *ctx, fz_band_writer *writer)
{
+ fz_output *out = writer->out;
+ int w = writer->w;
+ int h = writer->h;
+
fz_printf(ctx, out, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\nTUPLTYPE CMYK\nENDHDR\n", w, h);
}
void
fz_write_bitmap_as_pbm(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
{
- fz_write_pbm_header(ctx, out, bitmap->w, bitmap->h);
+ fz_band_writer *writer = fz_new_pbm_band_writer(ctx, out);
- fz_write_pbm_band(ctx, out, bitmap);
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, 0, 0, 1);
+ fz_write_band(ctx, writer, bitmap->stride, 0, bitmap->h, bitmap->samples);
+ fz_write_trailer(ctx, writer);
+ fz_drop_band_writer(ctx, writer);
}
void
fz_write_bitmap_as_pkm(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
{
- fz_write_pkm_header(ctx, out, bitmap->w, bitmap->h);
+ fz_band_writer *writer = fz_new_pkm_band_writer(ctx, out);
- fz_write_pkm_band(ctx, out, bitmap);
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, 0, 0, 1);
+ fz_write_band(ctx, writer, bitmap->stride, 0, bitmap->h, bitmap->samples);
+ fz_write_trailer(ctx, writer);
+ fz_drop_band_writer(ctx, writer);
}
-void
-fz_write_pbm_band(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
+static void
+pbm_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int bandheight, const unsigned char *p)
{
- unsigned char *p;
- int h, bytestride;
+ fz_output *out = writer->out;
+ int w = writer->w;
+ int h = writer->h;
+ int n = writer->n;
+ int bytestride;
- if (bitmap->n != 1)
+ if (n != 1)
fz_throw(ctx, FZ_ERROR_GENERIC, "too many color components in bitmap");
- if (!out)
- return;
-
- p = bitmap->samples;
- h = bitmap->h;
- bytestride = (bitmap->w + 7) >> 3;
+ bytestride = (w + 7) >> 3;
while (h--)
{
fz_write(ctx, out, p, bytestride);
- p += bitmap->stride;
+ p += stride;
}
}
-void
-fz_write_pkm_band(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
+static void
+pkm_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int bandheight, const unsigned char *p)
{
- unsigned char *p;
- int w, h, bytestride;
+ fz_output *out = writer->out;
+ int w = writer->w;
+ int h = writer->h;
+ int n = writer->n;
+ int bytestride;
- if (bitmap->n != 4)
+ if (n != 4)
fz_throw(ctx, FZ_ERROR_GENERIC, "wrong number of color components in bitmap");
- if (!out)
- return;
-
- p = bitmap->samples;
- h = bitmap->h;
- w = bitmap->w;
- bytestride = bitmap->stride - (w>>1);
+ bytestride = stride - (w>>1);
while (h--)
{
int ww = w-1;
@@ -383,6 +392,27 @@ fz_write_pkm_band(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
}
}
+fz_band_writer *fz_new_pbm_band_writer(fz_context *ctx, fz_output *out)
+{
+ fz_band_writer *writer = fz_new_band_writer(ctx, fz_band_writer, out);
+
+ writer->header = pbm_write_header;
+ writer->band = pbm_write_band;
+
+ return writer;
+}
+
+
+fz_band_writer *fz_new_pkm_band_writer(fz_context *ctx, fz_output *out)
+{
+ fz_band_writer *writer = fz_new_band_writer(ctx, fz_band_writer, out);
+
+ writer->header = pkm_write_header;
+ writer->band = pkm_write_band;
+
+ return writer;
+}
+
void
fz_save_bitmap_as_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename)
{
diff --git a/source/fitz/output-pcl.c b/source/fitz/output-pcl.c
index c0858299..96e7c973 100644
--- a/source/fitz/output-pcl.c
+++ b/source/fitz/output-pcl.c
@@ -680,22 +680,27 @@ delta_compression(unsigned char *curr, unsigned char *prev, unsigned char *comp,
void
fz_write_pixmap_as_pcl(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap, const fz_pcl_options *pcl)
{
- fz_color_pcl_output_context *pcoc;
+ fz_band_writer *writer;
if (!pixmap || !out)
return;
- pcoc = fz_write_color_pcl_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->xres, pixmap->yres, 0, pcl);
+ writer = fz_new_color_pcl_band_writer(ctx, out, pcl);
fz_try(ctx)
- fz_write_color_pcl_band(ctx, out, pcoc, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, 0, pixmap->samples);
+ {
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 1);
+ fz_write_band(ctx, writer, pixmap->stride, 0, 0, pixmap->samples);
+ fz_write_trailer(ctx, writer);
+ }
fz_always(ctx)
- fz_write_color_pcl_trailer(ctx, out, pcoc);
+ fz_drop_band_writer(ctx, writer);
fz_catch(ctx)
fz_rethrow(ctx);
}
-struct fz_color_pcl_output_context_s
+typedef struct color_pcl_band_writer_s
{
+ fz_band_writer super;
fz_pcl_options options;
unsigned char *linebuf;
unsigned char *compbuf;
@@ -703,42 +708,32 @@ struct fz_color_pcl_output_context_s
unsigned char *curr;
int fill;
int seed_valid;
-};
+} color_pcl_band_writer;
-fz_color_pcl_output_context *fz_write_color_pcl_header(fz_context *ctx, fz_output *out, int w, int h, int n, int xres, int yres, int pagenum, const fz_pcl_options *options)
+static void
+color_pcl_write_header(fz_context *ctx, fz_band_writer *writer_)
{
- fz_color_pcl_output_context *pcoc = fz_malloc_struct(ctx, fz_color_pcl_output_context);
-
- if (!out)
- return NULL;
+ color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_;
+ fz_output *out = writer->super.out;
+ int w = writer->super.w;
+ int h = writer->super.h;
+ int n = writer->super.n;
+ int xres = writer->super.xres;
+ int yres = writer->super.yres;
if (n != 4)
fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be rgb to write as pcl");
- if (options)
- pcoc->options = *options;
- else
- fz_pcl_preset(ctx, &pcoc->options, "generic");
+ writer->linebuf = fz_malloc(ctx, w * 3 * 2);
+ writer->compbuf = fz_malloc(ctx, 32767);
+ writer->prev = writer->linebuf;
+ writer->curr = writer->linebuf + w * 3;
+ writer->fill = 0;
+ writer->seed_valid = 0;
- fz_try(ctx)
- {
- pcoc->linebuf = fz_malloc(ctx, w * 3 * 2);
- pcoc->compbuf = fz_malloc(ctx, 32767);
- pcoc->prev = pcoc->linebuf;
- pcoc->curr = pcoc->linebuf + w * 3;
- pcoc->fill = 0;
- pcoc->seed_valid = 0;
- }
- fz_catch(ctx)
- {
- fz_free(ctx, pcoc->linebuf);
- fz_free(ctx, pcoc->compbuf);
- fz_rethrow(ctx);
- }
-
- guess_paper_size(&pcoc->options, w, h, xres, yres);
+ guess_paper_size(&writer->options, w, h, xres, yres);
- pcl_header(ctx, out, &pcoc->options, 1, xres, yres, w, h);
+ pcl_header(ctx, out, &writer->options, 1, xres, yres, w, h);
/* Raster presentation */
/* Print in orientation of the logical page */
@@ -773,28 +768,28 @@ fz_color_pcl_output_context *fz_write_color_pcl_header(fz_context *ctx, fz_outpu
/* Now output the actual bitmap */
/* Adaptive Compression */
fz_printf(ctx, out, "\033*b5M");
-
- return pcoc;
}
-void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *pcoc, int w, int h, int n, int stride, int band_start, int bandheight, unsigned char *sp)
+static void
+color_pcl_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_start, int bandheight, const unsigned char *sp)
{
+ color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_;
+ fz_output *out = writer->super.out;
+ int w = writer->super.w;
+ int h = writer->super.h;
int y, ss, ds, seed_valid, fill;
unsigned char *prev;
unsigned char *curr;
unsigned char *comp;
- if (!out || !pcoc)
- return;
-
ds = w * 3;
ss = w * 4;
- prev = pcoc->prev;
- curr = pcoc->curr;
- fill = pcoc->fill;
- comp = pcoc->compbuf;
- seed_valid = pcoc->seed_valid;
+ prev = writer->prev;
+ curr = writer->curr;
+ fill = writer->fill;
+ comp = writer->compbuf;
+ seed_valid = writer->seed_valid;
if (band_start+bandheight >= h)
bandheight = h - band_start;
@@ -904,30 +899,53 @@ void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_outpu
}
}
- pcoc->prev = prev;
- pcoc->curr = curr;
- pcoc->fill = fill;
- pcoc->compbuf = comp;
- pcoc->seed_valid = seed_valid;
+ writer->prev = prev;
+ writer->curr = curr;
+ writer->fill = fill;
+ writer->compbuf = comp;
+ writer->seed_valid = seed_valid;
}
-void fz_write_color_pcl_trailer(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *pcoc)
+static void
+color_pcl_write_trailer(fz_context *ctx, fz_band_writer *writer_)
{
- if (!pcoc)
- return;
+ color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_;
+ fz_output *out = writer->super.out;
- if (pcoc->fill)
+ if (writer->fill)
{
- fz_printf(ctx, out, "\033*b%dW", pcoc->fill);
- fz_write(ctx, out, pcoc->compbuf, pcoc->fill);
+ fz_printf(ctx, out, "\033*b%dW", writer->fill);
+ fz_write(ctx, out, writer->compbuf, writer->fill);
}
/* End Raster Graphics */
fz_printf(ctx, out, "\033*rC");
+}
+
+static void
+color_pcl_drop_band_writer(fz_context *ctx, fz_band_writer *writer_)
+{
+ color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_;
+
+ fz_free(ctx, writer->compbuf);
+ fz_free(ctx, writer->linebuf);
+}
+
+fz_band_writer *fz_new_color_pcl_band_writer(fz_context *ctx, fz_output *out, const fz_pcl_options *options)
+{
+ color_pcl_band_writer *writer = fz_new_band_writer(ctx, color_pcl_band_writer, out);
+
+ writer->super.header = color_pcl_write_header;
+ writer->super.band = color_pcl_write_band;
+ writer->super.trailer = color_pcl_write_trailer;
+ writer->super.drop = color_pcl_drop_band_writer;
+
+ if (options)
+ writer->options = *options;
+ else
+ fz_pcl_preset(ctx, &writer->options, "generic");
- fz_free(ctx, pcoc->compbuf);
- fz_free(ctx, pcoc->linebuf);
- fz_free(ctx, pcoc);
+ return &writer->super;
}
/*
@@ -941,7 +959,7 @@ void fz_write_color_pcl_trailer(fz_context *ctx, fz_output *out, fz_color_pcl_ou
* where N is the original byte count (end_row - row).
*/
int
-mode2compress(unsigned char *out, unsigned char *in, int in_len)
+mode2compress(unsigned char *out, const unsigned char *in, int in_len)
{
int x;
int out_len = 0;
@@ -1050,81 +1068,79 @@ void wind(void)
void
fz_write_bitmap_as_pcl(fz_context *ctx, fz_output *out, const fz_bitmap *bitmap, const fz_pcl_options *pcl)
{
- fz_mono_pcl_output_context *pcoc;
+ fz_band_writer *writer;
if (!bitmap || !out)
return;
- pcoc = fz_write_mono_pcl_header(ctx, out, bitmap->w, bitmap->h, bitmap->xres, bitmap->yres, 0, pcl);
+ writer = fz_new_mono_pcl_band_writer(ctx, out, pcl);
fz_try(ctx)
- fz_write_mono_pcl_band(ctx, out, pcoc, bitmap);
+ {
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, bitmap->xres, bitmap->yres, 0);
+ fz_write_band(ctx, writer, bitmap->stride, 0, bitmap->h, bitmap->samples);
+ fz_write_trailer(ctx, writer);
+ }
fz_always(ctx)
- fz_write_mono_pcl_trailer(ctx, out, pcoc);
+ fz_drop_band_writer(ctx, writer);
fz_catch(ctx)
fz_rethrow(ctx);
}
-struct fz_mono_pcl_output_context_s
+typedef struct mono_pcl_band_writer_s
{
+ fz_band_writer super;
fz_pcl_options options;
unsigned char *prev;
unsigned char *mode2buf;
unsigned char *mode3buf;
int top_of_page;
int num_blank_lines;
-};
+} mono_pcl_band_writer;
-fz_mono_pcl_output_context *fz_write_mono_pcl_header(fz_context *ctx, fz_output *out, int w, int h, int xres, int yres, int pagenum, const fz_pcl_options *options)
+static void
+mono_pcl_write_header(fz_context *ctx, fz_band_writer *writer_)
{
- fz_mono_pcl_output_context *pcoc = fz_malloc_struct(ctx, fz_mono_pcl_output_context);
+ mono_pcl_band_writer *writer = (mono_pcl_band_writer *)writer_;
+ fz_output *out = writer->super.out;
+ int w = writer->super.w;
+ int h = writer->super.h;
+ int xres = writer->super.xres;
+ int yres = writer->super.yres;
int line_size;
int max_mode_2_size;
int max_mode_3_size;
- if (!out)
- return NULL;
-
- if (options)
- pcoc->options = *options;
- else
- fz_pcl_preset(ctx, &pcoc->options, "generic");
-
line_size = (w + 7)/8;
max_mode_2_size = line_size + (line_size/127) + 1;
max_mode_3_size = line_size + (line_size/8) + 1;
- fz_try(ctx)
- {
- pcoc->prev = fz_calloc(ctx, line_size, sizeof(unsigned char));
- pcoc->mode2buf = fz_calloc(ctx, max_mode_2_size, sizeof(unsigned char));
- pcoc->mode3buf = fz_calloc(ctx, max_mode_3_size, sizeof(unsigned char));
- pcoc->num_blank_lines = 0;
- pcoc->top_of_page = 1;
- }
- fz_catch(ctx)
- {
- fz_free(ctx, pcoc->prev);
- fz_free(ctx, pcoc->mode2buf);
- fz_free(ctx, pcoc->mode3buf);
- fz_rethrow(ctx);
- }
+ writer->prev = fz_calloc(ctx, line_size, sizeof(unsigned char));
+ writer->mode2buf = fz_calloc(ctx, max_mode_2_size, sizeof(unsigned char));
+ writer->mode3buf = fz_calloc(ctx, max_mode_3_size, sizeof(unsigned char));
+ writer->num_blank_lines = 0;
+ writer->top_of_page = 1;
- guess_paper_size(&pcoc->options, w, h, xres, yres);
+ guess_paper_size(&writer->options, w, h, xres, yres);
- if (pcoc->options.features & HACK__IS_A_OCE9050)
+ if (writer->options.features & HACK__IS_A_OCE9050)
{
/* Enter HPGL/2 mode, begin plot, Initialise (start plot), Enter PCL mode */
fz_puts(ctx, out, "\033%1BBPIN;\033%1A");
}
- pcl_header(ctx, out, &pcoc->options, 1, xres, yres, w, h);
- return pcoc;
+ pcl_header(ctx, out, &writer->options, 1, xres, yres, w, h);
}
-void fz_write_mono_pcl_band(fz_context *ctx, fz_output *out, fz_mono_pcl_output_context *poc, const fz_bitmap *bitmap)
+static void
+mono_pcl_write_band(fz_context *ctx, fz_band_writer *writer_, int ss, int band_start, int bandheight, const unsigned char *data)
{
- unsigned char *data, *out_data;
- int y, ss, rmask, line_size;
+ mono_pcl_band_writer *writer = (mono_pcl_band_writer *)writer_;
+ fz_output *out = writer->super.out;
+ int w = writer->super.w;
+ int h = writer->super.h;
+ int yres = writer->super.yres;
+ const unsigned char *out_data;
+ int y, rmask, line_size;
int num_blank_lines;
int compression = -1;
unsigned char *prev = NULL;
@@ -1133,23 +1149,18 @@ void fz_write_mono_pcl_band(fz_context *ctx, fz_output *out, fz_mono_pcl_output_
int out_count;
const fz_pcl_options *pcl;
- if (!out || !bitmap)
- return;
-
- num_blank_lines = poc->num_blank_lines;
- rmask = ~0 << (-bitmap->w & 7);
- line_size = (bitmap->w + 7)/8;
- prev = poc->prev;
- mode2buf = poc->mode2buf;
- mode3buf = poc->mode3buf;
- pcl = &poc->options;
+ num_blank_lines = writer->num_blank_lines;
+ rmask = ~0 << (-w & 7);
+ line_size = (w + 7)/8;
+ prev = writer->prev;
+ mode2buf = writer->mode2buf;
+ mode3buf = writer->mode3buf;
+ pcl = &writer->options;
/* Transfer raster graphics. */
- data = bitmap->samples;
- ss = bitmap->stride;
- for (y = 0; y < bitmap->h; y++, data += ss)
+ for (y = 0; y < h; y++, data += ss)
{
- unsigned char *end_data = data + line_size;
+ const unsigned char *end_data = data + line_size;
if ((end_data[-1] & rmask) == 0)
{
@@ -1166,9 +1177,9 @@ void fz_write_mono_pcl_band(fz_context *ctx, fz_output *out, fz_mono_pcl_output_
/* We've reached a non-blank line. */
/* Put out a spacing command if necessary. */
- if (poc->top_of_page)
+ if (writer->top_of_page)
{
- poc->top_of_page = 0;
+ writer->top_of_page = 0;
/* We're at the top of a page. */
if (pcl->features & PCL_ANY_SPACING)
{
@@ -1232,7 +1243,7 @@ void fz_write_mono_pcl_band(fz_context *ctx, fz_output *out, fz_mono_pcl_output_
}
}
else if (pcl->features & PCL3_SPACING)
- fz_printf(ctx, out, "\033*p+%dY", num_blank_lines * bitmap->yres);
+ fz_printf(ctx, out, "\033*p+%dY", num_blank_lines * yres);
else
fz_printf(ctx, out, "\033*b%dY", num_blank_lines);
/* Clear the seed row (only matters for mode 3 compression). */
@@ -1284,27 +1295,50 @@ void fz_write_mono_pcl_band(fz_context *ctx, fz_output *out, fz_mono_pcl_output_
fz_write(ctx, out, out_data, out_count);
}
- poc->num_blank_lines = num_blank_lines;
+ writer->num_blank_lines = num_blank_lines;
}
-void fz_write_mono_pcl_trailer(fz_context *ctx, fz_output *out, fz_mono_pcl_output_context *pcoc)
+static void
+mono_pcl_write_trailer(fz_context *ctx, fz_band_writer *writer_)
{
- if (!pcoc || !out)
- return;
+ mono_pcl_band_writer *writer = (mono_pcl_band_writer *)writer_;
+ fz_output *out = writer->super.out;
/* end raster graphics and eject page */
fz_puts(ctx, out, "\033*rB\f");
- if (pcoc->options.features & HACK__IS_A_OCE9050)
+ if (writer->options.features & HACK__IS_A_OCE9050)
{
/* Pen up, pen select, advance full page, reset */
fz_puts(ctx, out, "\033%1BPUSP0PG;\033E");
}
+}
+
+static void
+mono_pcl_drop_band_writer(fz_context *ctx, fz_band_writer *writer_)
+{
+ mono_pcl_band_writer *writer = (mono_pcl_band_writer *)writer_;
+
+ fz_free(ctx, writer->prev);
+ fz_free(ctx, writer->mode2buf);
+ fz_free(ctx, writer->mode3buf);
+}
+
+fz_band_writer *fz_new_mono_pcl_band_writer(fz_context *ctx, fz_output *out, const fz_pcl_options *options)
+{
+ mono_pcl_band_writer *writer = fz_new_band_writer(ctx, mono_pcl_band_writer, out);
+
+ writer->super.header = mono_pcl_write_header;
+ writer->super.band = mono_pcl_write_band;
+ writer->super.trailer = mono_pcl_write_trailer;
+ writer->super.drop = mono_pcl_drop_band_writer;
+
+ if (options)
+ writer->options = *options;
+ else
+ fz_pcl_preset(ctx, &writer->options, "generic");
- fz_free(ctx, pcoc->prev);
- fz_free(ctx, pcoc->mode2buf);
- fz_free(ctx, pcoc->mode3buf);
- fz_free(ctx, pcoc);
+ return &writer->super;
}
void
diff --git a/source/fitz/output-png.c b/source/fitz/output-png.c
index d5e0b48f..620fa811 100644
--- a/source/fitz/output-png.c
+++ b/source/fitz/output-png.c
@@ -30,18 +30,20 @@ void
fz_save_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
{
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
- fz_png_output_context *poc = NULL;
+ fz_band_writer *writer = NULL;
- fz_var(poc);
+ fz_var(writer);
fz_try(ctx)
{
- poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha);
- fz_write_png_band(ctx, out, poc, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ writer = fz_new_png_band_writer(ctx, out);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 1);
+ fz_write_band(ctx, writer, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_write_trailer(ctx, writer);
}
fz_always(ctx)
{
- fz_write_png_trailer(ctx, out, poc);
+ fz_drop_band_writer(ctx, writer);
fz_drop_output(ctx, out);
}
fz_catch(ctx)
@@ -53,20 +55,22 @@ fz_save_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
void
fz_write_pixmap_as_png(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap)
{
- fz_png_output_context *poc;
+ fz_band_writer *writer;
if (!out)
return;
- poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha);
+ writer = fz_new_png_band_writer(ctx, out);
fz_try(ctx)
{
- fz_write_png_band(ctx, out, poc, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 1);
+ fz_write_band(ctx, writer, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_write_trailer(ctx, writer);
}
fz_always(ctx)
{
- fz_write_png_trailer(ctx, out, poc);
+ fz_drop_band_writer(ctx, writer);
}
fz_catch(ctx)
{
@@ -74,28 +78,27 @@ fz_write_pixmap_as_png(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap)
}
}
-struct fz_png_output_context_s
+typedef struct png_band_writer_s
{
+ fz_band_writer super;
unsigned char *udata;
unsigned char *cdata;
uLong usize, csize;
z_stream stream;
- int w;
- int h;
- int n;
- int alpha;
-};
+} png_band_writer;
-fz_png_output_context *
-fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha)
+static void
+png_write_header(fz_context *ctx, fz_band_writer *writer_)
{
+ png_band_writer *writer = (png_band_writer *)(void *)writer_;
+ fz_output *out = writer->super.out;
+ int w = writer->super.w;
+ int h = writer->super.h;
+ int n = writer->super.n;
+ int alpha = writer->super.alpha;
static const unsigned char pngsig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
unsigned char head[13];
int color;
- fz_png_output_context *poc;
-
- if (!out)
- return NULL;
/* Treat alpha only as greyscale */
if (n == 1 && alpha)
@@ -109,12 +112,6 @@ fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int al
fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
}
- poc = fz_malloc_struct(ctx, fz_png_output_context);
- poc->w = w;
- poc->h = h;
- poc->n = n;
- poc->alpha = alpha;
-
big32(head+0, w);
big32(head+4, h);
head[8] = 8; /* depth */
@@ -125,55 +122,42 @@ fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int al
fz_write(ctx, out, pngsig, 8);
putchunk(ctx, out, "IHDR", head, 13);
-
- return poc;
}
-void
-fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, int stride, int band_start, int bandheight, unsigned char *sp)
+static void
+png_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_start, int bandheight, const unsigned char *sp)
{
+ png_band_writer *writer = (png_band_writer *)(void *)writer_;
+ fz_output *out = writer->super.out;
unsigned char *dp;
int y, x, k, err, finalband;
int w, h, n;
- if (!out || !sp || !poc)
- return;
-
- w = poc->w;
- h = poc->h;
- n = poc->n;
+ w = writer->super.w;
+ h = writer->super.h;
+ n = writer->super.n;
finalband = (band_start+bandheight >= h);
if (finalband)
bandheight = h - band_start;
- if (poc->udata == NULL)
+ if (writer->udata == NULL)
{
- poc->usize = (w * n + 1) * bandheight;
+ writer->usize = (w * n + 1) * bandheight;
/* Sadly the bound returned by compressBound is just for a
* single usize chunk; if you compress a sequence of them
* the buffering can result in you suddenly getting a block
* larger than compressBound outputted in one go, even if you
* take all the data out each time. */
- poc->csize = compressBound(poc->usize);
- fz_try(ctx)
- {
- poc->udata = fz_malloc(ctx, poc->usize);
- poc->cdata = fz_malloc(ctx, poc->csize);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, poc->udata);
- poc->udata = NULL;
- poc->cdata = NULL;
- fz_rethrow(ctx);
- }
- err = deflateInit(&poc->stream, Z_DEFAULT_COMPRESSION);
+ writer->csize = compressBound(writer->usize);
+ writer->udata = fz_malloc(ctx, writer->usize);
+ writer->cdata = fz_malloc(ctx, writer->csize);
+ err = deflateInit(&writer->stream, Z_DEFAULT_COMPRESSION);
if (err != Z_OK)
fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
}
- dp = poc->udata;
+ dp = writer->udata;
stride -= w*n;
for (y = 0; y < bandheight; y++)
{
@@ -193,52 +177,68 @@ fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, i
sp += stride;
}
- poc->stream.next_in = (Bytef*)poc->udata;
- poc->stream.avail_in = (uInt)(dp - poc->udata);
+ writer->stream.next_in = (Bytef*)writer->udata;
+ writer->stream.avail_in = (uInt)(dp - writer->udata);
do
{
- poc->stream.next_out = poc->cdata;
- poc->stream.avail_out = (uInt)poc->csize;
+ writer->stream.next_out = writer->cdata;
+ writer->stream.avail_out = (uInt)writer->csize;
if (!finalband)
{
- err = deflate(&poc->stream, Z_NO_FLUSH);
+ err = deflate(&writer->stream, Z_NO_FLUSH);
if (err != Z_OK)
fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
}
else
{
- err = deflate(&poc->stream, Z_FINISH);
+ err = deflate(&writer->stream, Z_FINISH);
if (err != Z_STREAM_END)
fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
}
- if (poc->stream.next_out != poc->cdata)
- putchunk(ctx, out, "IDAT", poc->cdata, poc->stream.next_out - poc->cdata);
+ if (writer->stream.next_out != writer->cdata)
+ putchunk(ctx, out, "IDAT", writer->cdata, writer->stream.next_out - writer->cdata);
}
- while (poc->stream.avail_out == 0);
+ while (writer->stream.avail_out == 0);
}
-void
-fz_write_png_trailer(fz_context *ctx, fz_output *out, fz_png_output_context *poc)
+static void
+png_write_trailer(fz_context *ctx, fz_band_writer *writer_)
{
+ png_band_writer *writer = (png_band_writer *)(void *)writer_;
+ fz_output *out = writer->super.out;
unsigned char block[1];
int err;
- if (!out || !poc)
- return;
-
- err = deflateEnd(&poc->stream);
+ err = deflateEnd(&writer->stream);
if (err != Z_OK)
fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
- fz_free(ctx, poc->cdata);
- fz_free(ctx, poc->udata);
- fz_free(ctx, poc);
-
putchunk(ctx, out, "IEND", block, 0);
}
+static void
+png_drop_band_writer(fz_context *ctx, fz_band_writer *writer_)
+{
+ png_band_writer *writer = (png_band_writer *)(void *)writer_;
+
+ fz_free(ctx, writer->cdata);
+ fz_free(ctx, writer->udata);
+}
+
+fz_band_writer *fz_new_png_band_writer(fz_context *ctx, fz_output *out)
+{
+ png_band_writer *writer = fz_new_band_writer(ctx, png_band_writer, out);
+
+ writer->super.header = png_write_header;
+ writer->super.band = png_write_band;
+ writer->super.trailer = png_write_trailer;
+ writer->super.drop = png_drop_band_writer;
+
+ return &writer->super;
+}
+
/* We use an auxiliary function to do pixmap_as_png, as it can enable us to
* drop pix early in the case where we have to convert, potentially saving
* us having to have 2 copies of the pixmap and a buffer open at once. */
diff --git a/source/fitz/output-pnm.c b/source/fitz/output-pnm.c
index 2d1acd23..b5796ab2 100644
--- a/source/fitz/output-pnm.c
+++ b/source/fitz/output-pnm.c
@@ -3,10 +3,15 @@
/*
* Write pixmap to PNM file (without alpha channel)
*/
-
-void
-fz_write_pnm_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha)
+static void
+pnm_write_header(fz_context *ctx, fz_band_writer *writer)
{
+ fz_output *out = writer->out;
+ int w = writer->w;
+ int h = writer->h;
+ int n = writer->n;
+ int alpha = writer->alpha;
+
n -= alpha;
if (n != 1 && n != 3)
fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pnm");
@@ -19,9 +24,14 @@ fz_write_pnm_header(fz_context *ctx, fz_output *out, int w, int h, int n, int al
fz_printf(ctx, out, "255\n");
}
-void
-fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha, int stride, int band_start, int bandheight, unsigned char *p)
+static void
+pnm_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int bandheight, const unsigned char *p)
{
+ fz_output *out = writer->out;
+ int w = writer->w;
+ int h = writer->h;
+ int n = writer->n;
+ int alpha = writer->alpha;
char buffer[2*3*4*5*6]; /* Buffer must be a multiple of 2 and 3 at least. */
int len;
int end = band_start + bandheight;
@@ -29,9 +39,6 @@ fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int alph
if (n-alpha != 1 && n-alpha != 3)
fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pnm");
- if (!out)
- return;
-
if (end > h)
end = h;
end -= band_start;
@@ -96,29 +103,63 @@ fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int alph
}
}
+fz_band_writer *fz_new_pnm_band_writer(fz_context *ctx, fz_output *out)
+{
+ fz_band_writer *writer = fz_new_band_writer(ctx, fz_band_writer, out);
+
+ writer->header = pnm_write_header;
+ writer->band = pnm_write_band;
+
+ return writer;
+}
+
void
fz_write_pixmap_as_pnm(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
{
- fz_write_pnm_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha);
- fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_band_writer *writer = fz_new_pnm_band_writer(ctx, out);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 1);
+ fz_write_band(ctx, writer, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_write_trailer(ctx, writer);
+ fz_drop_band_writer(ctx, writer);
}
void
fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename)
{
+ fz_band_writer *writer = NULL;
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
- fz_write_pnm_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha);
- fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->stride, 0, pixmap->h, pixmap->samples);
- fz_drop_output(ctx, out);
+
+ fz_var(writer);
+
+ fz_try(ctx)
+ {
+ writer = fz_new_pnm_band_writer(ctx, out);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 1);
+ fz_write_band(ctx, writer, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_write_trailer(ctx, writer);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_band_writer(ctx, writer);
+ fz_drop_output(ctx, out);
+ }
+ fz_catch(ctx)
+ fz_rethrow(ctx);
}
/*
* Write pixmap to PAM file (with or without alpha channel)
*/
-void
-fz_write_pam_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha)
+static void
+pam_write_header(fz_context *ctx, fz_band_writer *writer)
{
+ fz_output *out = writer->out;
+ int w = writer->w;
+ int h = writer->h;
+ int n = writer->n;
+ int alpha = writer->alpha;
+
fz_printf(ctx, out, "P7\n");
fz_printf(ctx, out, "WIDTH %d\n", w);
fz_printf(ctx, out, "HEIGHT %d\n", h);
@@ -137,15 +178,16 @@ fz_write_pam_header(fz_context *ctx, fz_output *out, int w, int h, int n, int al
fz_printf(ctx, out, "ENDHDR\n");
}
-void
-fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha, int stride, int band_start, int bandheight, unsigned char *sp)
+static void
+pam_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int bandheight, const unsigned char *sp)
{
+ fz_output *out = writer->out;
+ int w = writer->w;
+ int h = writer->h;
+ int n = writer->n;
int y;
int end = band_start + bandheight;
- if (!out)
- return;
-
if (end > h)
end = h;
end -= band_start;
@@ -157,24 +199,46 @@ fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int alph
}
}
+fz_band_writer *fz_new_pam_band_writer(fz_context *ctx, fz_output *out)
+{
+ fz_band_writer *writer = fz_new_band_writer(ctx, fz_band_writer, out);
+
+ writer->header = pam_write_header;
+ writer->band = pam_write_band;
+
+ return writer;
+}
+
void
fz_write_pixmap_as_pam(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
{
- fz_write_pam_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha);
- fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_band_writer *writer = fz_new_pam_band_writer(ctx, out);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 1);
+ fz_write_band(ctx, writer, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_write_trailer(ctx, writer);
+ fz_drop_band_writer(ctx, writer);
}
void
fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename)
{
+ fz_band_writer *writer = NULL;
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
+
+ fz_var(writer);
+
fz_try(ctx)
{
- fz_write_pam_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha);
- fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ writer = fz_new_pam_band_writer(ctx, out);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 1);
+ fz_write_band(ctx, writer, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_write_trailer(ctx, writer);
}
fz_always(ctx)
+ {
+ fz_drop_band_writer(ctx, writer);
fz_drop_output(ctx, out);
+ }
fz_catch(ctx)
fz_rethrow(ctx);
}
diff --git a/source/fitz/output-ps.c b/source/fitz/output-ps.c
index d183adf6..6e63110c 100644
--- a/source/fitz/output-ps.c
+++ b/source/fitz/output-ps.c
@@ -2,14 +2,15 @@
#include <zlib.h>
-struct fz_ps_output_context_s
+typedef struct ps_band_writer_s
{
+ fz_band_writer super;
z_stream stream;
int input_size;
unsigned char *input;
int output_size;
unsigned char *output;
-};
+} ps_band_writer;
void
fz_write_ps_file_header(fz_context *ctx, fz_output *out)
@@ -39,20 +40,35 @@ void fz_write_ps_file_trailer(fz_context *ctx, fz_output *out, int pages)
fz_printf(ctx, out, "%%%%Trailer\n%%%%Pages: %d\n%%%%EOF\n", pages);
}
-fz_ps_output_context *fz_write_ps_header(fz_context *ctx, fz_output *out, int w, int h, int n, int xres, int yres, int pagenum)
+static void
+ps_write_header(fz_context *ctx, fz_band_writer *writer_)
{
+ ps_band_writer *writer = (ps_band_writer *)writer_;
+ fz_output *out = writer->super.out;
+ int w = writer->super.w;
+ int h = writer->super.h;
+ int n = writer->super.n;
+ int alpha = writer->super.alpha;
+ int xres = writer->super.xres;
+ int yres = writer->super.yres;
+ int pagenum = writer->super.pagenum;
int w_points = (w * 72 + (xres>>1)) / xres;
int h_points = (h * 72 + (yres>>1)) / yres;
float sx = w/(float)w_points;
float sy = h/(float)h_points;
- fz_ps_output_context *psoc;
int err;
- psoc = fz_malloc_struct(ctx, fz_ps_output_context);
- err = deflateInit(&psoc->stream, Z_DEFAULT_COMPRESSION);
+ if (alpha != 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Postscript output cannot have alpha");
+
+ writer->super.w = w;
+ writer->super.h = h;
+ writer->super.n = n;
+
+ err = deflateInit(&writer->stream, Z_DEFAULT_COMPRESSION);
if (err != Z_OK)
{
- fz_free(ctx, psoc);
+ fz_free(ctx, writer);
fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
}
@@ -90,49 +106,54 @@ fz_ps_output_context *fz_write_ps_header(fz_context *ctx, fz_output *out, int w,
">>\n"
"image\n"
, w, h, sx, sy, h);
-
- return psoc;
}
-void fz_write_ps_trailer(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc)
+static void
+ps_write_trailer(fz_context *ctx, fz_band_writer *writer_)
{
- if (psoc)
- {
- int err;
+ ps_band_writer *writer = (ps_band_writer *)writer_;
+ fz_output *out = writer->super.out;
+ int err;
- psoc->stream.next_in = NULL;
- psoc->stream.avail_in = 0;
- psoc->stream.next_out = (Bytef*)psoc->output;
- psoc->stream.avail_out = (uInt)psoc->output_size;
+ writer->stream.next_in = NULL;
+ writer->stream.avail_in = 0;
+ writer->stream.next_out = (Bytef*)writer->output;
+ writer->stream.avail_out = (uInt)writer->output_size;
- err = deflate(&psoc->stream, Z_FINISH);
- if (err != Z_STREAM_END)
- fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
+ err = deflate(&writer->stream, Z_FINISH);
+ if (err != Z_STREAM_END)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
- fz_write(ctx, out, psoc->output, psoc->output_size - psoc->stream.avail_out);
- fz_free(ctx, psoc->input);
- fz_free(ctx, psoc->output);
- fz_free(ctx, psoc);
- }
+ fz_write(ctx, out, writer->output, writer->output_size - writer->stream.avail_out);
fz_printf(ctx, out, "\nshowpage\n%%%%PageTrailer\n%%%%EndPageTrailer\n\n");
+}
+static void
+ps_drop_band_writer(fz_context *ctx, fz_band_writer *writer_)
+{
+ ps_band_writer *writer = (ps_band_writer *)writer_;
+
+ fz_free(ctx, writer->input);
+ fz_free(ctx, writer->output);
}
void fz_write_pixmap_as_ps(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap)
{
- fz_ps_output_context *psoc;
+ fz_band_writer *writer;
fz_write_ps_file_header(ctx, out);
- psoc = fz_write_ps_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->xres, pixmap->yres, 1);
+ writer = fz_new_ps_band_writer(ctx, out);
fz_try(ctx)
{
- fz_write_ps_band(ctx, out, psoc, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, 0, pixmap->samples);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 1);
+ fz_write_band(ctx, writer, pixmap->stride, 0, pixmap->h, pixmap->samples);
+ fz_write_trailer(ctx, writer);
}
fz_always(ctx)
{
- fz_write_ps_trailer(ctx, out, psoc);
+ fz_drop_band_writer(ctx, writer);
}
fz_catch(ctx)
{
@@ -153,8 +174,14 @@ void fz_save_pixmap_as_ps(fz_context *ctx, fz_pixmap *pixmap, char *filename, in
fz_rethrow(ctx);
}
-void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int stride, int band_start, int bandheight, unsigned char *samples)
+static void
+ps_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_start, int bandheight, const unsigned char *samples)
{
+ ps_band_writer *writer = (ps_band_writer *)writer_;
+ fz_output *out = writer->super.out;
+ int w = writer->super.w;
+ int h = writer->super.h;
+ int n = writer->super.n;
int x, y, i, err;
int required_input;
int required_output;
@@ -164,25 +191,25 @@ void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *pso
bandheight = h - band_start;
required_input = w*(n-1)*bandheight;
- required_output = (int)deflateBound(&psoc->stream, required_input);
+ required_output = (int)deflateBound(&writer->stream, required_input);
- if (psoc->input == NULL || psoc->input_size < required_input)
+ if (writer->input == NULL || writer->input_size < required_input)
{
- fz_free(ctx, psoc->input);
- psoc->input = NULL;
- psoc->input = fz_malloc(ctx, required_input);
- psoc->input_size = required_input;
+ fz_free(ctx, writer->input);
+ writer->input = NULL;
+ writer->input = fz_malloc(ctx, required_input);
+ writer->input_size = required_input;
}
- if (psoc->output == NULL || psoc->output_size < required_output)
+ if (writer->output == NULL || writer->output_size < required_output)
{
- fz_free(ctx, psoc->output);
- psoc->output = NULL;
- psoc->output = fz_malloc(ctx, required_output);
- psoc->output_size = required_output;
+ fz_free(ctx, writer->output);
+ writer->output = NULL;
+ writer->output = fz_malloc(ctx, required_output);
+ writer->output_size = required_output;
}
- o = psoc->input;
+ o = writer->input;
for (y = 0; y < bandheight; y++)
{
for (x = 0; x < w; x++)
@@ -194,14 +221,26 @@ void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *pso
samples += stride - w*n;
}
- psoc->stream.next_in = (Bytef*)psoc->input;
- psoc->stream.avail_in = required_input;
- psoc->stream.next_out = (Bytef*)psoc->output;
- psoc->stream.avail_out = (uInt)psoc->output_size;
+ writer->stream.next_in = (Bytef*)writer->input;
+ writer->stream.avail_in = required_input;
+ writer->stream.next_out = (Bytef*)writer->output;
+ writer->stream.avail_out = (uInt)writer->output_size;
- err = deflate(&psoc->stream, Z_NO_FLUSH);
+ err = deflate(&writer->stream, Z_NO_FLUSH);
if (err != Z_OK)
fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
- fz_write(ctx, out, psoc->output, psoc->output_size - psoc->stream.avail_out);
+ fz_write(ctx, out, writer->output, writer->output_size - writer->stream.avail_out);
+}
+
+fz_band_writer *fz_new_ps_band_writer(fz_context *ctx, fz_output *out)
+{
+ fz_band_writer *writer = fz_new_band_writer(ctx, fz_band_writer, out);
+
+ writer->header = ps_write_header;
+ writer->band = ps_write_band;
+ writer->trailer = ps_write_trailer;
+ writer->drop = ps_drop_band_writer;
+
+ return writer;
}
diff --git a/source/fitz/output.c b/source/fitz/output.c
index 0fc4fc09..d5dfb47e 100644
--- a/source/fitz/output.c
+++ b/source/fitz/output.c
@@ -292,3 +292,51 @@ fz_save_buffer(fz_context *ctx, fz_buffer *buf, const char *filename)
fz_catch(ctx)
fz_rethrow(ctx);
}
+
+fz_band_writer *fz_new_band_writer_of_size(fz_context *ctx, size_t size, fz_output *out)
+{
+ fz_band_writer *writer = fz_calloc(ctx, size, 1);
+
+ assert(size >= sizeof(*writer));
+
+ writer->out = out;
+
+ return writer;
+}
+
+void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int n, int alpha, int xres, int yres, int pagenum)
+{
+ if (writer == NULL || writer->band == NULL)
+ return;
+ writer->w = w;
+ writer->h = h;
+ writer->n = n;
+ writer->alpha = alpha;
+ writer->xres = xres;
+ writer->yres = yres;
+ writer->pagenum = pagenum;
+ writer->header(ctx, writer);
+}
+
+void fz_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int band_height, const unsigned char *samples)
+{
+ if (writer == NULL || writer->band == NULL)
+ return;
+ writer->band(ctx, writer, stride, band_start, band_height, samples);
+}
+
+void fz_write_trailer(fz_context *ctx, fz_band_writer *writer)
+{
+ if (writer == NULL || writer->trailer == NULL)
+ return;
+ writer->trailer(ctx, writer);
+}
+
+void fz_drop_band_writer(fz_context *ctx, fz_band_writer *writer)
+{
+ if (writer == NULL)
+ return;
+ if (writer->drop != NULL)
+ writer->drop(ctx, writer);
+ fz_free(ctx, writer);
+}
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 1b5300d9..4708516a 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -760,17 +760,11 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
fz_irect ibounds;
fz_pixmap *pix = NULL;
int w, h;
- fz_png_output_context *poc = NULL;
- fz_ps_output_context *psoc = NULL;
- fz_mono_pcl_output_context *pmcoc = NULL;
- fz_color_pcl_output_context *pccoc = NULL;
+ fz_band_writer *bander = NULL;
fz_bitmap *bit = NULL;
fz_var(pix);
- fz_var(poc);
- fz_var(psoc);
- fz_var(pmcoc);
- fz_var(pccoc);
+ fz_var(bander);
fz_var(bit);
fz_bound_page(ctx, page, &bounds);
@@ -878,24 +872,26 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
if (output)
{
if (output_format == OUT_PGM || output_format == OUT_PPM || output_format == OUT_PNM)
- fz_write_pnm_header(ctx, out, pix->w, totalheight, pix->n, pix->alpha);
+ bander = fz_new_pnm_band_writer(ctx, out);
else if (output_format == OUT_PAM)
- fz_write_pam_header(ctx, out, pix->w, totalheight, pix->n, pix->alpha);
+ bander = fz_new_pam_band_writer(ctx, out);
else if (output_format == OUT_PNG)
- poc = fz_write_png_header(ctx, out, pix->w, totalheight, pix->n, pix->alpha);
+ bander = fz_new_png_band_writer(ctx, out);
else if (output_format == OUT_PBM)
- fz_write_pbm_header(ctx, out, pix->w, totalheight);
+ bander = fz_new_pbm_band_writer(ctx, out);
else if (output_format == OUT_PKM)
- fz_write_pkm_header(ctx, out, pix->w, totalheight);
+ bander = fz_new_pkm_band_writer(ctx, out);
else if (output_format == OUT_PS)
- psoc = fz_write_ps_header(ctx, out, pix->w, totalheight, pix->n, pix->xres, pix->yres, ++output_pagenum);
+ bander = fz_new_ps_band_writer(ctx, out);
else if (output_format == OUT_PCL)
{
if (out_cs == CS_MONO)
- pmcoc = fz_write_mono_pcl_header(ctx, out, pix->w, totalheight, pix->xres, pix->yres, ++output_pagenum, NULL);
+ bander = fz_new_mono_pcl_band_writer(ctx, out, NULL);
else
- pccoc = fz_write_color_pcl_header(ctx, out, pix->w, totalheight, pix->n, pix->xres, pix->yres, ++output_pagenum, NULL);
+ bander = fz_new_color_pcl_band_writer(ctx, out, NULL);
}
+ if (bander)
+ fz_write_header(ctx, bander, pix->w, totalheight, pix->n, pix->alpha, pix->xres, pix->yres, ++output_pagenum);
}
for (band = 0; band < bands; band++)
@@ -915,43 +911,14 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
if (output)
{
- if (output_format == OUT_PGM || output_format == OUT_PPM || output_format == OUT_PNM)
- fz_write_pnm_band(ctx, out, pix->w, totalheight, pix->n, pix->alpha, pix->stride, band * bandheight, drawheight, pix->samples);
- else if (output_format == OUT_PAM)
- fz_write_pam_band(ctx, out, pix->w, totalheight, pix->n, pix->alpha, pix->stride, band * bandheight, drawheight, pix->samples);
- else if (output_format == OUT_PNG)
- fz_write_png_band(ctx, out, poc, pix->stride, band * bandheight, drawheight, pix->samples);
+ if (bander)
+ fz_write_band(ctx, bander, bit ? bit->stride : pix->stride, band * bandheight, drawheight, bit ? bit->samples : pix->samples);
else if (output_format == OUT_PWG)
fz_write_pixmap_as_pwg(ctx, out, pix, NULL);
- else if (output_format == OUT_PCL)
- {
- if (out_cs == CS_MONO)
- {
- fz_write_mono_pcl_band(ctx, out, pmcoc, bit);
- fz_drop_bitmap(ctx, bit);
- bit = NULL;
- }
- else
- fz_write_color_pcl_band(ctx, out, pccoc, pix->w, totalheight, pix->n, pix->stride, band * bandheight, drawheight, pix->samples);
- }
- else if (output_format == OUT_PS)
- fz_write_ps_band(ctx, out, psoc, pix->w, totalheight, pix->n, pix->stride, band * bandheight, drawheight, pix->samples);
- else if (output_format == OUT_PBM)
- {
- fz_write_pbm_band(ctx, out, bit);
- fz_drop_bitmap(ctx, bit);
- bit = NULL;
- }
- else if (output_format == OUT_PKM)
- {
- fz_write_pkm_band(ctx, out, bit);
- fz_drop_bitmap(ctx, bit);
- bit = NULL;
- }
else if (output_format == OUT_TGA)
- {
fz_write_pixmap_as_tga(ctx, out, pix);
- }
+ fz_drop_bitmap(ctx, bit);
+ bit = NULL;
}
if (num_workers > 0 && band + num_workers < bands)
@@ -982,21 +949,13 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
/* Any page level trailers go here */
if (output)
{
- if (output_format == OUT_PNG)
- fz_write_png_trailer(ctx, out, poc);
- if (output_format == OUT_PS)
- fz_write_ps_trailer(ctx, out, psoc);
- if (output_format == OUT_PCL)
- {
- if (out_cs == CS_MONO)
- fz_write_mono_pcl_trailer(ctx, out, pmcoc);
- else
- fz_write_color_pcl_trailer(ctx, out, pccoc);
- }
+ if (bander)
+ fz_write_trailer(ctx, bander);
}
}
fz_always(ctx)
{
+ fz_drop_band_writer(ctx, bander);
fz_drop_bitmap(ctx, bit);
bit = NULL;
if (num_workers > 0)
diff --git a/source/tools/muraster.c b/source/tools/muraster.c
index 07c64b72..a2fc7204 100644
--- a/source/tools/muraster.c
+++ b/source/tools/muraster.c
@@ -604,6 +604,12 @@ typedef struct render_details
* will start at the maximum value, and may drop to 0
* if we have problems with memory. */
int num_workers;
+
+ /* The band writer to output the page */
+ fz_band_writer *bander;
+
+ /* Number of components in image */
+ int n;
} render_details;
enum
@@ -784,6 +790,7 @@ static int dodrawpage(fz_context *ctx, int pagenum, fz_cookie *cookie, render_de
pix = fz_new_pixmap_with_bbox(ctx, colorspace, &ibounds, 0);
fz_set_pixmap_resolution(ctx, pix, x_resolution, y_resolution);
}
+ fz_write_header(ctx, render->bander, pix->w, total_height, pix->n, pix->alpha, pix->xres, pix->yres, pagenum);
for (band = 0; band < bands; band++)
{
@@ -818,22 +825,9 @@ static int dodrawpage(fz_context *ctx, int pagenum, fz_cookie *cookie, render_de
{
/* If we get any errors while outputting the bands, retrying won't help. */
errors_are_fatal = 1;
- if (output_format == OUT_PGM || output_format == OUT_PPM)
- fz_write_pnm_band(ctx, out, pix->w, total_height, pix->n, pix->alpha, pix->stride, band_start, draw_height, pix->samples);
- else if (output_format == OUT_PAM)
- fz_write_pam_band(ctx, out, pix->w, total_height, pix->n, pix->alpha, pix->stride, band_start, draw_height, pix->samples);
- else if (output_format == OUT_PBM)
- {
- fz_write_pbm_band(ctx, out, bit);
- fz_drop_bitmap(ctx, bit);
- bit = NULL;
- }
- else if (output_format == OUT_PKM)
- {
- fz_write_pkm_band(ctx, out, bit);
- fz_drop_bitmap(ctx, bit);
- bit = NULL;
- }
+ fz_write_band(ctx, render->bander, bit ? bit->stride : pix->stride, band_start, draw_height, bit ? bit->samples : pix->samples);
+ fz_drop_bitmap(ctx, bit);
+ bit = NULL;
errors_are_fatal = 0;
}
@@ -899,14 +893,7 @@ static int try_render_page(fz_context *ctx, int pagenum, fz_cookie *cookie, int
{
int w = render->ibounds.x1 - render->ibounds.x0;
int h = render->ibounds.y1 - render->ibounds.y0;
- if (output_format == OUT_PGM || output_format == OUT_PPM)
- fz_write_pnm_header(ctx, out, w, h, output_format == OUT_PGM ? 1 : 3, 0);
- else if (output_format == OUT_PAM)
- fz_write_pam_header(ctx, out, w, h, 4, 0);
- else if (output_format == OUT_PBM)
- fz_write_pbm_header(ctx, out, w, h);
- else if (output_format == OUT_PKM)
- fz_write_pkm_header(ctx, out, w, h);
+ fz_write_header(ctx, render->bander, w, h, render->n, 0, 0, 0, 0);
}
fz_catch(ctx)
{
@@ -960,6 +947,7 @@ static int try_render_page(fz_context *ctx, int pagenum, fz_cookie *cookie, int
fz_drop_page(ctx, render->page);
fz_drop_display_list(ctx, render->list);
+ fz_drop_band_writer(ctx, render->bander);
if (showtime)
{
@@ -1175,6 +1163,27 @@ initialise_banding(fz_context *ctx, render_details *render, int color)
render->band_height_multiple = reps;
render->bands_rendered = 0;
+
+ if (output_format == OUT_PGM || output_format == OUT_PPM)
+ {
+ render->bander = fz_new_pnm_band_writer(ctx, out);
+ render->n = OUT_PGM ? 1 : 3;
+ }
+ else if (output_format == OUT_PAM)
+ {
+ render->bander = fz_new_pam_band_writer(ctx, out);
+ render->n = 4;
+ }
+ else if (output_format == OUT_PBM)
+ {
+ render->bander = fz_new_pbm_band_writer(ctx, out);
+ render->n = 1;
+ }
+ else if (output_format == OUT_PKM)
+ {
+ render->bander = fz_new_pkm_band_writer(ctx, out);
+ render->n = 4;
+ }
}
static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)