diff options
author | Tor Andersson <tor@ghostscript.com> | 2010-07-15 14:35:34 +0000 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2010-07-15 14:35:34 +0000 |
commit | 53237faa9e4a81794180a9a5d9c922d0af808d24 (patch) | |
tree | a6ae802355aaf211e7d5362ba829ab88fa36cb21 /fitz | |
parent | 4520fd49b5cfd3b2796b374a2251f031b21f7008 (diff) | |
download | mupdf-53237faa9e4a81794180a9a5d9c922d0af808d24.tar.xz |
Add pixmap writing functions for PNM, PAM and PNG (without libpng) formats.
Diffstat (limited to 'fitz')
-rw-r--r-- | fitz/fitz.h | 7 | ||||
-rw-r--r-- | fitz/res_pixmap.c | 269 |
2 files changed, 188 insertions, 88 deletions
diff --git a/fitz/fitz.h b/fitz/fitz.h index 2d2aa003..e8fb9efe 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -697,12 +697,15 @@ fz_pixmap * fz_newpixmapwithrect(fz_colorspace *, fz_bbox bbox); fz_pixmap * fz_newpixmap(fz_colorspace *, int x, int y, int w, int h); fz_pixmap *fz_keeppixmap(fz_pixmap *map); void fz_droppixmap(fz_pixmap *map); - -void fz_debugpixmap(fz_pixmap *map, char *prefix); void fz_clearpixmap(fz_pixmap *map, unsigned char value); +void fz_gammapixmap(fz_pixmap *pix, float gamma); fz_pixmap * fz_scalepixmap(fz_pixmap *src, int xdenom, int ydenom); +fz_error fz_writepnm(fz_pixmap *pixmap, char *filename); +fz_error fz_writepam(fz_pixmap *pixmap, char *filename); +fz_error fz_writepng(fz_pixmap *pixmap, char *filename, int alpha); + /* * Colorspace resources. */ diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index c6a299f9..ed596d7b 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -72,116 +72,213 @@ fz_gammapixmap(fz_pixmap *pix, float gamma) } } -void -fz_debugpixmap(fz_pixmap *pix, char *prefix) +/* + * Write pixmap to PNM file (without alpha channel) + */ + +fz_error +fz_writepnm(fz_pixmap *pixmap, char *filename) { - static int counter = 0; - char colorname[40]; - char alphaname[40]; - FILE *color = NULL; - FILE *alpha = NULL; - int x, y; + FILE *fp; + unsigned char *p; + int len; - sprintf(alphaname, "%s-%04d-alpha.pgm", prefix, counter); - alpha = fopen(alphaname, "wb"); - if (!alpha) - goto cleanup; + if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4) + return fz_throw("pixmap must be grayscale or rgb to write as pnm"); - fprintf(stderr, "saving debug pixmap %s-%04d (%s)\n", prefix, counter, pix->colorspace->name); + fp = fopen(filename, "wb"); + if (!fp) + return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); - if (pix->n > 1) - { - if (pix->n > 2) - sprintf(colorname, "%s-%04d-color.ppm", prefix, counter); - else - sprintf(colorname, "%s-%04d-color.pgm", prefix, counter); - - color = fopen(colorname, "wb"); - if (!color) - goto cleanup; - } + if (pixmap->n == 1 || pixmap->n == 2) + fprintf(fp, "P5\n"); + if (pixmap->n == 4) + fprintf(fp, "P6\n"); + fprintf(fp, "%d %d\n", pixmap->w, pixmap->h); + fprintf(fp, "255\n"); - counter ++; + len = pixmap->w * pixmap->h; + p = pixmap->samples; - if (pix->n == 5) + switch (pixmap->n) { - fprintf(alpha, "P5\n%d %d\n255\n", pix->w, pix->h); - fprintf(color, "P6\n%d %d\n255\n", pix->w, pix->h); - - for (y = 0; y < pix->h; y++) + case 1: + fwrite(p, 1, len, fp); + break; + case 2: + while (len--) { - for (x = 0; x < pix->w; x++) - { - int cc = pix->samples[x * pix->n + y * pix->w * pix->n + 0]; - int mm = pix->samples[x * pix->n + y * pix->w * pix->n + 1]; - int yy = pix->samples[x * pix->n + y * pix->w * pix->n + 2]; - int kk = pix->samples[x * pix->n + y * pix->w * pix->n + 3]; - int a = pix->samples[x * pix->n + y * pix->w * pix->n + 4]; - int r = 255 - MIN(cc + kk, 255); - int g = 255 - MIN(mm + kk, 255); - int b = 255 - MIN(yy + kk, 255); - fputc(a, alpha); - fputc(r, color); - fputc(g, color); - fputc(b, color); - } + putc(p[0], fp); + p += 2; + } + break; + case 4: + while (len--) + { + putc(p[0], fp); + putc(p[1], fp); + putc(p[2], fp); + p += 4; } } - else if (pix->n == 4) - { - fprintf(alpha, "P5\n%d %d\n255\n", pix->w, pix->h); - fprintf(color, "P6\n%d %d\n255\n", pix->w, pix->h); + fclose(fp); + return fz_okay; +} - for (y = 0; y < pix->h; y++) - { - for (x = 0; x < pix->w; x++) - { - int r = pix->samples[x * pix->n + y * pix->w * pix->n + 0]; - int g = pix->samples[x * pix->n + y * pix->w * pix->n + 1]; - int b = pix->samples[x * pix->n + y * pix->w * pix->n + 2]; - int a = pix->samples[x * pix->n + y * pix->w * pix->n + 3]; - fputc(a, alpha); - fputc(r, color); - fputc(g, color); - fputc(b, color); - } - } +/* + * Write pixmap to PAM file (with alpha channel) + */ + +fz_error +fz_writepam(fz_pixmap *pixmap, char *filename) +{ + FILE *fp; + + fp = fopen(filename, "wb"); + if (!fp) + return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); + + fprintf(fp, "P7\n"); + fprintf(fp, "WIDTH %d\n", pixmap->w); + fprintf(fp, "HEGIHT %d\n", pixmap->h); + fprintf(fp, "DEPTH %d\n", pixmap->n); + fprintf(fp, "MAXVAL 255\n"); + switch (pixmap->n) + { + case 1: fprintf(fp, "TUPLTYPE GRAYSCALE\n"); break; + case 2: fprintf(fp, "TUPLTYPE GRAYSCALE_ALPHA\n"); break; + case 4: fprintf(fp, "TUPLTYPE RGB_ALPHA\n"); break; + case 5: fprintf(fp, "TUPLTYPE CMYK_ALPHA\n"); break; } + fprintf(fp, "ENDHDR\n"); + + fwrite(pixmap->samples, pixmap->w * pixmap->n, pixmap->h, fp); + + fclose(fp); + + return fz_okay; +} + +/* + * Write pixmap to PNG file (with or without alpha channel) + */ + +#include <zlib.h> - else if (pix->n == 2) +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 inline void put32(unsigned int v, FILE *fp) +{ + putc(v >> 24, fp); + putc(v >> 16, fp); + putc(v >> 8, fp); + putc(v, fp); +} + +static void putchunk(char *tag, unsigned char *data, int size, FILE *fp) +{ + unsigned int sum; + put32(size, fp); + fwrite(tag, 1, 4, fp); + fwrite(data, 1, size, fp); + sum = crc32(0, NULL, 0); + sum = crc32(sum, (unsigned char*)tag, 4); + sum = crc32(sum, data, size); + put32(sum, fp); +} + +fz_error +fz_writepng(fz_pixmap *pixmap, char *filename, int alpha) +{ + static const unsigned char pngsig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; + FILE *fp; + unsigned char head[13]; + unsigned char *udata, *cdata, *sp, *dp; + uLong usize, csize; + int y, x, k, sn, dn; + int color; + int err; + + if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4) + return fz_throw("pixmap must be grayscale or rgb to write as png"); + + sn = pixmap->n; + dn = pixmap->n; + if (!alpha && dn > 1) + dn--; + + switch (dn) { - fprintf(alpha, "P5\n%d %d\n255\n", pix->w, pix->h); - fprintf(color, "P5\n%d %d\n255\n", pix->w, pix->h); + default: + case 1: color = 0; break; + case 2: color = 4; break; + case 3: color = 2; break; + case 4: color = 6; break; + } + + usize = (pixmap->w * dn + 1) * pixmap->h; + csize = compressBound(usize); + udata = fz_malloc(usize); + cdata = fz_malloc(csize); - for (y = 0; y < pix->h; y++) + sp = pixmap->samples; + dp = udata; + for (y = 0; y < pixmap->h; y++) + { + *dp++ = 1; /* sub prediction filter */ + for (x = 0; x < pixmap->w; x++) { - for (x = 0; x < pix->w; x++) + for (k = 0; k < dn; k++) { - int g = pix->samples[x * pix->n + y * pix->w * pix->n + 0]; - int a = pix->samples[x * pix->n + y * pix->w * pix->n + 1]; - fputc(a, alpha); - fputc(g, color); + if (x == 0) + dp[k] = sp[k]; + else + dp[k] = sp[k] - sp[k-sn]; } + sp += sn; + dp += dn; } } - else if (pix->n == 1) + err = compress(cdata, &csize, udata, usize); + if (err != Z_OK) { - fprintf(alpha, "P5\n%d %d\n255\n", pix->w, pix->h); + fz_free(udata); + fz_free(cdata); + return fz_throw("cannot compress image data"); + } - for (y = 0; y < pix->h; y++) - { - for (x = 0; x < pix->w; x++) - { - int g = pix->samples[x * pix->n + y * pix->w * pix->n + 0]; - fputc(g, alpha); - } - } + + fp = fopen(filename, "wb"); + if (!fp) + { + fz_free(udata); + fz_free(cdata); + return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); } -cleanup: - if (alpha) fclose(alpha); - if (color) fclose(color); -} + big32(head+0, pixmap->w); + big32(head+4, pixmap->h); + head[8] = 8; /* depth */ + head[9] = color; + head[10] = 0; /* compression */ + head[11] = 0; /* filter */ + head[12] = 0; /* interlace */ + + fwrite(pngsig, 1, 8, fp); + putchunk("IHDR", head, 13, fp); + putchunk("IDAT", cdata, csize, fp); + putchunk("IEND", head, 0, fp); + fclose(fp); + fz_free(udata); + fz_free(cdata); + return fz_okay; +} |