summaryrefslogtreecommitdiff
path: root/source/fitz/pixmap.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-06-16 11:16:57 +0200
committerRobin Watts <robin.watts@artifex.com>2016-06-16 18:08:15 +0100
commit840f6ab0becba39a3a5a3a570e1055607dc1364c (patch)
tree73d16b479571bf1879f6e3bd95e7bd975a68246a /source/fitz/pixmap.c
parentae0e385406e5f0b82bec97fcf8021b6690acb949 (diff)
downloadmupdf-840f6ab0becba39a3a5a3a570e1055607dc1364c.tar.xz
Split image output functions into separate files.
Diffstat (limited to 'source/fitz/pixmap.c')
-rw-r--r--source/fitz/pixmap.c588
1 files changed, 0 insertions, 588 deletions
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c
index 8e62b3d5..186cd6d0 100644
--- a/source/fitz/pixmap.c
+++ b/source/fitz/pixmap.c
@@ -843,594 +843,6 @@ fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma)
}
}
-/*
- * 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)
-{
- n -= alpha;
- if (n != 1 && n != 3)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pnm");
-
- if (n == 1)
- fz_printf(ctx, out, "P5\n");
- if (n == 3)
- fz_printf(ctx, out, "P6\n");
- fz_printf(ctx, out, "%d %d\n", w, h);
- 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, int bandheight, unsigned char *p)
-{
- char buffer[2*3*4*5*6]; /* Buffer must be a multiple of 2 and 3 at least. */
- int len;
- int start = band * bandheight;
- int end = start + bandheight;
-
- 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 -= start;
-
- /* Tests show that writing single bytes out at a time
- * is appallingly slow. We get a huge improvement
- * by collating stuff into buffers first. */
-
- while (end--)
- {
- len = w;
- while (len)
- {
- int num_written = len;
-
- switch (n)
- {
- case 1:
- /* No collation required */
- fz_write(ctx, out, p, num_written);
- p += num_written;
- break;
- case 2:
- {
- char *o = buffer;
- int count;
-
- if (num_written > sizeof(buffer))
- num_written = sizeof(buffer);
-
- for (count = num_written; count; count--)
- {
- *o++ = *p;
- p += 2;
- }
- fz_write(ctx, out, buffer, num_written);
- break;
- }
- case 3:
- case 4:
- {
- char *o = buffer;
- int count;
-
- if (num_written > sizeof(buffer)/3)
- num_written = sizeof(buffer)/3;
-
- for (count = num_written; count; count--)
- {
- *o++ = p[0];
- *o++ = p[1];
- *o++ = p[2];
- p += n;
- }
- fz_write(ctx, out, buffer, num_written * 3);
- break;
- }
- }
- len -= num_written;
- }
- p += stride - w*n;
- }
-}
-
-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);
-}
-
-void
-fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename)
-{
- 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);
-}
-
-/*
- * 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, int savealpha)
-{
- int sn = n;
- int dn = n - alpha;
- if (!alpha)
- savealpha = 0;
-
- dn += savealpha;
-
- fz_printf(ctx, out, "P7\n");
- fz_printf(ctx, out, "WIDTH %d\n", w);
- fz_printf(ctx, out, "HEIGHT %d\n", h);
- fz_printf(ctx, out, "DEPTH %d\n", dn);
- fz_printf(ctx, out, "MAXVAL 255\n");
- if (dn == 1) fz_printf(ctx, out, "TUPLTYPE GRAYSCALE\n");
- else if (dn == 2 && sn == 2) fz_printf(ctx, out, "TUPLTYPE GRAYSCALE_ALPHA\n");
- else if (dn == 3 && sn == 3) fz_printf(ctx, out, "TUPLTYPE RGB\n");
- else if (dn == 4 && sn == 3) fz_printf(ctx, out, "TUPLTYPE RGB_ALPHA\n");
- else if (dn == 4 && sn == 4) fz_printf(ctx, out, "TUPLTYPE CMYK\n");
- else if (dn == 5 && sn == 4) fz_printf(ctx, out, "TUPLTYPE CMYK_ALPHA\n");
- 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, int bandheight, unsigned char *sp, int savealpha)
-{
- int y, x;
- int start = band * bandheight;
- int end = start + bandheight;
- int sn = n;
- int dn = n - alpha;
- if (!alpha)
- savealpha = 0;
-
- dn += savealpha;
-
- if (!out)
- return;
-
- if (end > h)
- end = h;
- end -= start;
-
- for (y = 0; y < end; y++)
- {
- x = w;
- while (x--)
- {
- fz_write(ctx, out, sp, dn);
- sp += sn;
- }
- sp += stride - w*n;
- }
-}
-
-void
-fz_write_pixmap_as_pam(fz_context *ctx, fz_output *out, fz_pixmap *pixmap, int savealpha)
-{
- fz_write_pam_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, savealpha);
- fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->stride, 0, pixmap->h, pixmap->samples, savealpha);
-}
-
-void
-fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha)
-{
- fz_output *out = fz_new_output_with_path(ctx, filename, 0);
- fz_try(ctx)
- {
- fz_write_pam_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, savealpha);
- fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->stride, 0, pixmap->h, pixmap->samples, savealpha);
- }
- fz_always(ctx)
- fz_drop_output(ctx, out);
- fz_catch(ctx)
- fz_rethrow(ctx);
-}
-
-/*
- * Write pixmap to PNG file (with or without alpha channel)
- */
-
-#include <zlib.h>
-
-static inline void big32(unsigned char *buf, unsigned int v)
-{
- buf[0] = (v >> 24) & 0xff;
- buf[1] = (v >> 16) & 0xff;
- buf[2] = (v >> 8) & 0xff;
- buf[3] = (v) & 0xff;
-}
-
-static void putchunk(fz_context *ctx, fz_output *out, char *tag, unsigned char *data, int size)
-{
- unsigned int sum;
- fz_write_int32_be(ctx, out, size);
- fz_write(ctx, out, tag, 4);
- fz_write(ctx, out, data, size);
- sum = crc32(0, NULL, 0);
- sum = crc32(sum, (unsigned char*)tag, 4);
- sum = crc32(sum, data, size);
- fz_write_int32_be(ctx, out, sum);
-}
-
-void
-fz_save_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap, const char *filename, int savealpha)
-{
- fz_output *out = fz_new_output_with_path(ctx, filename, 0);
- fz_png_output_context *poc = NULL;
-
- fz_var(poc);
-
- fz_try(ctx)
- {
- poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, savealpha);
- fz_write_png_band(ctx, out, poc, pixmap->stride, 0, pixmap->h, pixmap->samples);
- }
- fz_always(ctx)
- {
- fz_write_png_trailer(ctx, out, poc);
- fz_drop_output(ctx, out);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-void
-fz_write_pixmap_as_png(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap, int savealpha)
-{
- fz_png_output_context *poc;
-
- if (!out)
- return;
-
- poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, savealpha);
-
- fz_try(ctx)
- {
- fz_write_png_band(ctx, out, poc, pixmap->stride, 0, pixmap->h, pixmap->samples);
- }
- fz_always(ctx)
- {
- fz_write_png_trailer(ctx, out, poc);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-struct fz_png_output_context_s
-{
- unsigned char *udata;
- unsigned char *cdata;
- uLong usize, csize;
- z_stream stream;
- int w;
- int h;
- int n;
- int alpha;
- int savealpha;
-};
-
-fz_png_output_context *
-fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha, int savealpha)
-{
- 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)
- alpha = 0;
-
- switch (n - alpha)
- {
- case 1: color = (alpha ? 4 : 0); break; /* 0 = Greyscale, 4 = Greyscale + Alpha */
- case 3: color = (alpha ? 6 : 2); break; /* 2 = RGB, 6 = RGBA */
- default:
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
- }
-
- /* If we have no alpha, save no alpha */
- if (!alpha)
- savealpha = 0;
-
- poc = fz_malloc_struct(ctx, fz_png_output_context);
- poc->w = w;
- poc->h = h;
- poc->n = n;
- poc->alpha = alpha;
- poc->savealpha = savealpha;
-
- big32(head+0, w);
- big32(head+4, h);
- head[8] = 8; /* depth */
- head[9] = color;
- head[10] = 0; /* compression */
- head[11] = 0; /* filter */
- head[12] = 0; /* interlace */
-
- 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, int bandheight, unsigned char *sp)
-{
- unsigned char *dp;
- int y, x, k, sn, dn, err, finalband;
- int w, h, n, alpha, savealpha;
-
- if (!out || !sp || !poc)
- return;
-
- w = poc->w;
- h = poc->h;
- n = poc->n;
- alpha = poc->alpha;
- savealpha = poc->savealpha;
-
- band *= bandheight;
- finalband = (band+bandheight >= h);
- if (finalband)
- bandheight = h - band;
-
- sn = n;
- dn = n - alpha + savealpha;
-
- if (poc->udata == NULL)
- {
- poc->usize = (w * dn + 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);
- if (err != Z_OK)
- fz_throw(ctx, FZ_ERROR_GENERIC, "compression error %d", err);
- }
-
- dp = poc->udata;
- stride -= w*sn;
- for (y = 0; y < bandheight; y++)
- {
- *dp++ = 1; /* sub prediction filter */
- for (x = 0; x < w; x++)
- {
- for (k = 0; k < dn; k++)
- {
- if (x == 0)
- dp[k] = sp[k];
- else
- dp[k] = sp[k] - sp[k-sn];
- }
- sp += sn;
- dp += dn;
- }
- sp += stride;
- }
-
- poc->stream.next_in = (Bytef*)poc->udata;
- poc->stream.avail_in = (uInt)(dp - poc->udata);
- do
- {
- poc->stream.next_out = poc->cdata;
- poc->stream.avail_out = (uInt)poc->csize;
-
- if (!finalband)
- {
- err = deflate(&poc->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);
- 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);
- }
- while (poc->stream.avail_out == 0);
-}
-
-void
-fz_write_png_trailer(fz_context *ctx, fz_output *out, fz_png_output_context *poc)
-{
- unsigned char block[1];
- int err;
-
- if (!out || !poc)
- return;
-
- err = deflateEnd(&poc->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);
-}
-
-/* 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. */
-static fz_buffer *
-png_from_pixmap(fz_context *ctx, fz_pixmap *pix, int drop)
-{
- fz_buffer *buf = NULL;
- fz_output *out;
- fz_pixmap *pix2 = NULL;
-
- fz_var(buf);
- fz_var(out);
- fz_var(pix2);
-
- if (pix->w == 0 || pix->h == 0)
- return NULL;
-
- fz_try(ctx)
- {
- if (pix->colorspace && pix->colorspace != fz_device_gray(ctx) && pix->colorspace != fz_device_rgb(ctx))
- {
- pix2 = fz_new_pixmap(ctx, fz_device_rgb(ctx), pix->w, pix->h, 1);
- fz_convert_pixmap(ctx, pix2, pix);
- if (drop)
- fz_drop_pixmap(ctx, pix);
- pix = pix2;
- }
- buf = fz_new_buffer(ctx, 1024);
- out = fz_new_output_with_buffer(ctx, buf);
- fz_write_pixmap_as_png(ctx, out, pix, 1);
- }
- fz_always(ctx)
- {
- fz_drop_pixmap(ctx, drop ? pix : pix2);
- fz_drop_output(ctx, out);
- }
- fz_catch(ctx)
- {
- fz_drop_buffer(ctx, buf);
- fz_rethrow(ctx);
- }
- return buf;
-}
-
-fz_buffer *
-fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image)
-{
- return png_from_pixmap(ctx, fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL), 1);
-}
-
-fz_buffer *
-fz_new_buffer_from_pixmap_as_png(fz_context *ctx, fz_pixmap *pix)
-{
- return png_from_pixmap(ctx, pix, 0);
-}
-
-/*
- * Write pixmap to TGA file (with or without alpha channel)
- */
-
-static inline void tga_put_pixel(fz_context *ctx, fz_output *out, unsigned char *data, int n, int is_bgr)
-{
- if (n >= 3 && !is_bgr)
- {
- fz_putc(ctx, out, data[2]);
- fz_putc(ctx, out, data[1]);
- fz_putc(ctx, out, data[0]);
- if (n == 4)
- fz_putc(ctx, out, data[3]);
- return;
- }
- if (n == 2)
- {
- fz_putc(ctx, out, data[0]);
- fz_putc(ctx, out, data[0]);
- }
- fz_write(ctx, out, data, n);
-}
-
-void
-fz_save_pixmap_as_tga(fz_context *ctx, fz_pixmap *pixmap, const char *filename, int savealpha)
-{
- fz_output *out = fz_new_output_with_path(ctx, filename, 0);
- fz_try(ctx)
- fz_write_pixmap_as_tga(ctx, out, pixmap, savealpha);
- fz_always(ctx)
- fz_drop_output(ctx, out);
- fz_catch(ctx)
- fz_rethrow(ctx);
-}
-
-void
-fz_write_pixmap_as_tga(fz_context *ctx, fz_output *out, fz_pixmap *pixmap, int savealpha)
-{
- unsigned char head[18];
- int n = pixmap->n;
- int d = savealpha || n == 1 ? n : n - 1;
- int is_bgr = pixmap->colorspace == fz_device_bgr(ctx);
- int k;
-
- if (pixmap->colorspace && pixmap->colorspace != fz_device_gray(ctx) &&
- pixmap->colorspace != fz_device_rgb(ctx) && pixmap->colorspace != fz_device_bgr(ctx))
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as tga");
- }
-
- memset(head, 0, sizeof(head));
- head[2] = n == 4 ? 10 : 11;
- head[12] = pixmap->w & 0xFF; head[13] = (pixmap->w >> 8) & 0xFF;
- head[14] = pixmap->h & 0xFF; head[15] = (pixmap->h >> 8) & 0xFF;
- head[16] = d * 8;
- head[17] = savealpha && n > 1 ? 8 : 0;
- if (savealpha && d == 2)
- head[16] = 32;
-
- fz_write(ctx, out, head, sizeof(head));
- for (k = 1; k <= pixmap->h; k++)
- {
- int i, j;
- unsigned char *line = pixmap->samples + pixmap->w * n * (pixmap->h - k);
- for (i = 0, j = 1; i < pixmap->w; i += j, j = 1)
- {
- for (; i + j < pixmap->w && j < 128 && !memcmp(line + i * n, line + (i + j) * n, d); j++);
- if (j > 1)
- {
- fz_putc(ctx, out, j - 1 + 128);
- tga_put_pixel(ctx, out, line + i * n, d, is_bgr);
- }
- else
- {
- for (; i + j < pixmap->w && j <= 128 && memcmp(line + (i + j - 1) * n, line + (i + j) * n, d) != 0; j++);
- if (i + j < pixmap->w || j > 128)
- j--;
- fz_putc(ctx, out, j - 1);
- for (; j > 0; j--, i++)
- tga_put_pixel(ctx, out, line + i * n, d, is_bgr);
- }
- }
- }
- fz_write(ctx, out, "\0\0\0\0\0\0\0\0TRUEVISION-XFILE.\0", 26);
-}
-
size_t
fz_pixmap_size(fz_context *ctx, fz_pixmap * pix)
{