summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)