summaryrefslogtreecommitdiff
path: root/source/fitz/output-pnm.c
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 /source/fitz/output-pnm.c
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.
Diffstat (limited to 'source/fitz/output-pnm.c')
-rw-r--r--source/fitz/output-pnm.c112
1 files changed, 88 insertions, 24 deletions
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);
}