diff options
-rw-r--r-- | include/mupdf/fitz.h | 1 | ||||
-rw-r--r-- | include/mupdf/fitz/output-tga.h | 10 | ||||
-rw-r--r-- | source/fitz/pixmap.c | 79 | ||||
-rw-r--r-- | source/tools/mudraw.c | 12 |
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; } |