summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Bünzli <zeniko@gmail.com>2013-09-25 17:05:45 +0200
committerRobin Watts <robin.watts@artifex.com>2013-09-27 17:09:48 +0100
commitc301f0b3b493935fcf1d7ff58543486b7c6b2773 (patch)
treede2cd90c3a3d58b5dd2777b3afe01855d6e7a83f
parent728034546726798d8a31fcb046846b662f5073b5 (diff)
downloadmupdf-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.
-rw-r--r--include/mupdf/fitz.h1
-rw-r--r--include/mupdf/fitz/output-tga.h10
-rw-r--r--source/fitz/pixmap.c79
-rw-r--r--source/tools/mudraw.c12
4 files changed, 99 insertions, 3 deletions
diff --git a/include/mupdf/fitz.h b/include/mupdf/fitz.h
index 6cc13efe..00458e8c 100644
--- a/include/mupdf/fitz.h
+++ b/include/mupdf/fitz.h
@@ -54,5 +54,6 @@
#include "mupdf/fitz/output-pwg.h"
#include "mupdf/fitz/output-pcl.h"
#include "mupdf/fitz/output-svg.h"
+#include "mupdf/fitz/output-tga.h"
#endif
diff --git a/include/mupdf/fitz/output-tga.h b/include/mupdf/fitz/output-tga.h
new file mode 100644
index 00000000..316eb182
--- /dev/null
+++ b/include/mupdf/fitz/output-tga.h
@@ -0,0 +1,10 @@
+#ifndef MUPDF_FITZ_OUTPUT_TGA_H
+#define MUPDF_FITZ_OUTPUT_TGA_H
+
+#include "mupdf/fitz/system.h"
+#include "mupdf/fitz/context.h"
+#include "mupdf/fitz/pixmap.h"
+
+void fz_write_tga(fz_context *ctx, fz_pixmap *pixmap, const char *filename, int savealpha);
+
+#endif
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)
{
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 81222993..c95be5e3 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -14,7 +14,7 @@
enum { TEXT_PLAIN = 1, TEXT_HTML = 2, TEXT_XML = 3 };
-enum { OUT_PNG, OUT_PPM, OUT_PNM, OUT_PAM, OUT_PGM, OUT_PBM, OUT_SVG, OUT_PWG, OUT_PCL, OUT_PDF };
+enum { OUT_PNG, OUT_PPM, OUT_PNM, OUT_PAM, OUT_PGM, OUT_PBM, OUT_SVG, OUT_PWG, OUT_PCL, OUT_PDF, OUT_TGA };
enum { CS_INVALID, CS_UNSET, CS_MONO, CS_GRAY, CS_GRAYALPHA, CS_RGB, CS_RGBA };
@@ -36,6 +36,7 @@ static const suffix_t suffix_table[] =
{ ".pwg", OUT_PWG },
{ ".pcl", OUT_PCL },
{ ".pdf", OUT_PDF },
+ { ".tga", OUT_TGA },
};
typedef struct
@@ -77,7 +78,8 @@ static const format_cs_table_t format_cs_table[] =
{ OUT_SVG, CS_RGB, { CS_RGB } },
{ OUT_PWG, CS_RGB, { CS_MONO, CS_GRAY, CS_RGB } },
{ OUT_PCL, CS_MONO, { CS_MONO } },
- { OUT_PDF, CS_RGB, { CS_RGB } }
+ { OUT_PDF, CS_RGB, { CS_RGB } },
+ { OUT_TGA, CS_RGB, { CS_GRAY, CS_GRAYALPHA, CS_RGB, CS_RGBA } },
};
/*
@@ -183,7 +185,7 @@ static void usage(void)
"usage: mudraw [options] input [pages]\n"
"\t-o -\toutput filename (%%d for page number)\n"
"\t-F -\toutput format (if no -F, -o will be examined)\n"
- "\t\tsupported formats: pgm, ppm, pam, png, pbm\n"
+ "\t\tsupported formats: pgm, ppm, pam, png, pbm, tga\n"
"\t-p -\tpassword\n"
"\t-r -\tresolution in dpi (default: 72)\n"
"\t-w -\twidth (in pixels) (maximum width if -r is specified)\n"
@@ -758,6 +760,10 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
fz_write_pbm(ctx, bit, filename_buf);
fz_drop_bitmap(ctx, bit);
}
+ else if (output_format == OUT_TGA)
+ {
+ fz_write_tga(ctx, pix, filename_buf, savealpha);
+ }
}
ctm.f -= drawheight;
}