diff options
author | Simon Bünzli <zeniko@gmail.com> | 2013-09-25 17:05:45 +0200 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-09-27 17:09:48 +0100 |
commit | c301f0b3b493935fcf1d7ff58543486b7c6b2773 (patch) | |
tree | de2cd90c3a3d58b5dd2777b3afe01855d6e7a83f /source/fitz | |
parent | 728034546726798d8a31fcb046846b662f5073b5 (diff) | |
download | mupdf-c301f0b3b493935fcf1d7ff58543486b7c6b2773.tar.xz |
add support for .tga output to mudraw
SumatraPDF's testsuite uses Targa images as output because they're
compressed while still far easier to compare than PNG and have better
tool support than PCL/PWG.
Diffstat (limited to 'source/fitz')
-rw-r--r-- | source/fitz/pixmap.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c index 8b3ac6a6..8692a468 100644 --- a/source/fitz/pixmap.c +++ b/source/fitz/pixmap.c @@ -841,6 +841,85 @@ fz_image_as_png(fz_context *ctx, fz_image *image, int w, int h) return buf; } +/* + * Write pixmap to TGA file (with or without alpha channel) + */ + +static inline void tga_put_pixel(unsigned char *data, int n, int is_bgr, fz_output *out) +{ + if (n >= 3 && !is_bgr) + { + fz_putc(out, data[2]); + fz_putc(out, data[1]); + fz_putc(out, data[0]); + if (n == 4) + fz_putc(out, data[3]); + return; + } + if (n == 2) + { + fz_putc(out, data[0]); + fz_putc(out, data[0]); + } + fz_write(out, data, n); +} + +void +fz_write_tga(fz_context *ctx, fz_pixmap *pixmap, const char *filename, int savealpha) +{ + fz_output *out; + 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"); + } + + out = fz_new_output_to_filename(ctx, filename); + + 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(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(out, j - 1 + 128); + tga_put_pixel(line + i * n, d, is_bgr, out); + } + 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(out, j - 1); + for (; j > 0; j--, i++) + tga_put_pixel(line + i * n, d, is_bgr, out); + } + } + } + fz_write(out, "\0\0\0\0\0\0\0\0TRUEVISION-XFILE.\0", 26); + + fz_close_output(out); +} + unsigned int fz_pixmap_size(fz_context *ctx, fz_pixmap * pix) { |