diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2011-03-30 19:58:40 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2011-03-30 19:58:40 +0200 |
commit | 60a940e170eb1b3e00e28b76f1b9a86741ef9a25 (patch) | |
tree | 3b59c16197efdd0e282c970b89f2b3ffed9f31ba | |
parent | a903a2ed5572b86deb323cb5471520aba05a0189 (diff) | |
download | mupdf-60a940e170eb1b3e00e28b76f1b9a86741ef9a25.tar.xz |
xps: Decode and draw images.
-rw-r--r-- | xps/muxps.h | 1 | ||||
-rw-r--r-- | xps/xpsimage.c | 96 | ||||
-rw-r--r-- | xps/xpsjpeg.c | 118 | ||||
-rw-r--r-- | xps/xpstiff.c | 515 | ||||
-rw-r--r-- | xps/xpstile.c | 4 |
5 files changed, 289 insertions, 445 deletions
diff --git a/xps/muxps.h b/xps/muxps.h index c778be37..ba826b10 100644 --- a/xps/muxps.h +++ b/xps/muxps.h @@ -115,6 +115,7 @@ struct xps_image_s byte *samples; byte *profile; int profilesize; + fz_pixmap *pixmap; }; int xps_decode_jpeg(xps_context *ctx, byte *rbuf, int rlen, xps_image *image); diff --git a/xps/xpsimage.c b/xps/xpsimage.c index 8add170e..a4305734 100644 --- a/xps/xpsimage.c +++ b/xps/xpsimage.c @@ -17,111 +17,47 @@ xps_decode_image(xps_context *ctx, xps_part *part, xps_image *image) { error = xps_decode_jpeg(ctx, buf, len, image); if (error) - return fz_rethrow(error, "could not decode image"); + return fz_rethrow(error, "could not decode jpeg image"); } else if (memcmp(buf, "\211PNG\r\n\032\n", 8) == 0) { error = xps_decode_png(ctx, buf, len, image); if (error) - return fz_rethrow(error, "could not decode image"); + return fz_rethrow(error, "could not decode png image"); } else if (memcmp(buf, "II", 2) == 0 && buf[2] == 0xBC) { error = xps_decode_jpegxr(ctx, buf, len, image); if (error) - return fz_rethrow(error, "could not decode image"); + return fz_rethrow(error, "could not decode JPEG-XR image"); } else if (memcmp(buf, "MM", 2) == 0 || memcmp(buf, "II", 2) == 0) { error = xps_decode_tiff(ctx, buf, len, image); if (error) - return fz_rethrow(error, "could not decode image"); + return fz_rethrow(error, "could not decode TIFF image"); } else return fz_throw("unknown image file format"); - return fz_okay; -} - -static void -xps_paint_image_brush_imp(xps_context *ctx, fz_matrix ctm, xps_image *image) -{ - fz_colorspace *colorspace; - unsigned int count; - byte *samples; + image->pixmap = fz_newpixmap(image->colorspace, 0, 0, image->width, image->height); + fz_unpacktile(image->pixmap, image->samples, image->comps, image->bits, image->stride, 1); + fz_free(image->samples); + image->samples = NULL; - colorspace = image->colorspace; - samples = image->samples; - count = image->stride * image->height; - -printf("xps_paint_image_brush_imp!\n"); + return fz_okay; } static void xps_paint_image_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *root, void *vimage) { -#if 0 xps_image *image = vimage; - int code; - - if (ctx->opacity_only) - { - if (image->alpha) - { - code = xps_paint_image_brush_imp(ctx, image, 1); - if (code < 0) - return fz_rethrow(code, "cannot draw alpha channel image"); - } - return 0; - } - - if (image->alpha) - { - gs_transparency_mask_params params; - gs_transparency_group_params tgp; - fz_rect bbox; - - xps_bounds_in_user_space(ctx, &bbox); - - code = gs_gsave(ctx->pgs); - if (code < 0) - return fz_rethrow(code, "cannot gsave before transparency group"); - - gs_setcolorspace(ctx->pgs, ctx->gray); - gs_trans_mask_params_init(¶ms, TRANSPARENCY_MASK_Luminosity); - gs_begin_transparency_mask(ctx->pgs, ¶ms, &bbox, 0); - code = xps_paint_image_brush_imp(ctx, image, 1); - if (code < 0) - { - gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); - gs_grestore(ctx->pgs); - return fz_rethrow(code, "cannot draw alpha channel image"); - } - gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); - - gs_setcolorspace(ctx->pgs, image->colorspace); - gs_trans_group_params_init(&tgp); - gs_begin_transparency_group(ctx->pgs, &tgp, &bbox); - code = xps_paint_image_brush_imp(ctx, image, 0); - if (code < 0) - { - gs_end_transparency_group(ctx->pgs); - gs_grestore(ctx->pgs); - return fz_rethrow(code, "cannot draw color channel image"); - } - gs_end_transparency_group(ctx->pgs); - - code = gs_grestore(ctx->pgs); - if (code < 0) - return fz_rethrow(code, "cannot grestore after transparency group"); - } - else - { - code = xps_paint_image_brush_imp(ctx, image, 0); - if (code < 0) - return fz_rethrow(code, "cannot draw image"); - } -#endif + float xs = image->width * 96.0 / image->xres; + float ys = image->height * 96.0 / image->yres; + fz_matrix im = fz_scale(xs, -ys); + im.f = ys; + ctm = fz_concat(im, ctm); + ctx->dev->fillimage(ctx->dev->user, image->pixmap, ctm, 1.0); } static int @@ -232,6 +168,8 @@ void xps_free_image(xps_context *ctx, xps_image *image) { // TODO: refcount image->colorspace + if (image->pixmap) + fz_droppixmap(image->pixmap); if (image->samples) fz_free(image->samples); if (image->profile) diff --git a/xps/xpsjpeg.c b/xps/xpsjpeg.c index f89c2207..41534eeb 100644 --- a/xps/xpsjpeg.c +++ b/xps/xpsjpeg.c @@ -4,8 +4,124 @@ #include <jpeglib.h> #include <setjmp.h> +struct jpeg_error_mgr_jmp +{ + struct jpeg_error_mgr super; + jmp_buf env; + char msg[JMSG_LENGTH_MAX]; +}; + +static void error_exit(j_common_ptr cinfo) +{ + struct jpeg_error_mgr_jmp *err = (struct jpeg_error_mgr_jmp *)cinfo->err; + cinfo->err->format_message(cinfo, err->msg); + longjmp(err->env, 1); +} + +static void init_source(j_decompress_ptr cinfo) +{ + /* nothing to do */ +} + +static void term_source(j_decompress_ptr cinfo) +{ + /* nothing to do */ +} + +static boolean fill_input_buffer(j_decompress_ptr cinfo) +{ + static unsigned char eoi[2] = { 0xFF, JPEG_EOI }; + struct jpeg_source_mgr *src = cinfo->src; + src->next_input_byte = eoi; + src->bytes_in_buffer = 2; + return 1; +} + +static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + struct jpeg_source_mgr *src = cinfo->src; + if (num_bytes > 0) + { + src->next_input_byte += num_bytes; + src->bytes_in_buffer -= num_bytes; + } +} + int xps_decode_jpeg(xps_context *ctx, byte *rbuf, int rlen, xps_image *image) { - return fz_throw("jpeg not available"); + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr_jmp err; + struct jpeg_source_mgr src; + unsigned char *buffer[1]; + + if (setjmp(err.env)) + { + if (image->samples) + fz_free(image->samples); + image->samples = NULL; + return fz_throw("jpeg error: %s", err.msg); + } + + cinfo.err = jpeg_std_error(&err.super); + err.super.error_exit = error_exit; + + jpeg_create_decompress(&cinfo); + + cinfo.src = &src; + src.init_source = init_source; + src.fill_input_buffer = fill_input_buffer; + src.skip_input_data = skip_input_data; + src.resync_to_restart = jpeg_resync_to_restart; + src.term_source = term_source; + src.next_input_byte = rbuf; + src.bytes_in_buffer = rlen; + + jpeg_read_header(&cinfo, 1); + + jpeg_start_decompress(&cinfo); + + image->width = cinfo.output_width; + image->height = cinfo.output_height; + image->comps = cinfo.output_components; + image->stride = cinfo.output_width * cinfo.output_components; + image->bits = 8; + image->samples = fz_calloc(image->height, image->stride); + + if (image->comps == 1) + image->colorspace = fz_devicegray; + if (image->comps == 3) + image->colorspace = fz_devicergb; + if (image->comps == 4) + image->colorspace = fz_devicecmyk; + + if (cinfo.density_unit == 1) + { + image->xres = cinfo.X_density; + image->yres = cinfo.Y_density; + } + else if (cinfo.density_unit == 2) + { + image->xres = cinfo.X_density * 2.54; + image->yres = cinfo.Y_density * 2.54; + } + else + { + image->xres = 96; + image->yres = 96; + } + + memset(image->samples, 127, image->stride * image->height); + + buffer[0] = image->samples; + while (cinfo.output_scanline < cinfo.output_height) + { + jpeg_read_scanlines(&cinfo, buffer, 1); + buffer[0] += image->comps * image->width; + } + + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + return fz_okay; } diff --git a/xps/xpstiff.c b/xps/xpstiff.c index 7ab684fc..562f1747 100644 --- a/xps/xpstiff.c +++ b/xps/xpstiff.c @@ -1,26 +1,6 @@ #include "fitz.h" #include "muxps.h" -int -xps_decode_tiff(xps_context *ctx, byte *buf, int len, xps_image *image) -{ - return fz_throw("TIFF codec is not available"); -} - -#if 0 - -#include "stream.h" -#include "strimpl.h" -#include "gsstate.h" -#include "jpeglib_.h" -#include "sdct.h" -#include "sjpeg.h" -#include "srlx.h" -#include "slzwx.h" -#include "szlibx.h" -#include "scfx.h" -#include "memory_.h" - /* * TIFF image loader. Should be enough to support TIFF files in XPS. * Baseline TIFF 6.0 plus CMYK, LZW, Flate and JPEG support. @@ -86,33 +66,33 @@ enum TRATIONAL = 5 }; -#define NewSubfileType 254 -#define ImageWidth 256 -#define ImageLength 257 -#define BitsPerSample 258 -#define Compression 259 -#define PhotometricInterpretation 262 -#define FillOrder 266 -#define StripOffsets 273 -#define SamplesPerPixel 277 -#define RowsPerStrip 278 -#define StripByteCounts 279 -#define XResolution 282 -#define YResolution 283 -#define PlanarConfiguration 284 -#define T4Options 292 -#define T6Options 293 -#define ResolutionUnit 296 -#define Predictor 317 -#define ColorMap 320 -#define TileWidth 322 -#define TileLength 323 -#define TileOffsets 324 -#define TileByteCounts 325 -#define ExtraSamples 338 -#define JPEGTables 347 -#define YCbCrSubSampling 520 -#define ICCProfile 34675 +#define NewSubfileType 254 +#define ImageWidth 256 +#define ImageLength 257 +#define BitsPerSample 258 +#define Compression 259 +#define PhotometricInterpretation 262 +#define FillOrder 266 +#define StripOffsets 273 +#define SamplesPerPixel 277 +#define RowsPerStrip 278 +#define StripByteCounts 279 +#define XResolution 282 +#define YResolution 283 +#define PlanarConfiguration 284 +#define T4Options 292 +#define T6Options 293 +#define ResolutionUnit 296 +#define Predictor 317 +#define ColorMap 320 +#define TileWidth 322 +#define TileLength 323 +#define TileOffsets 324 +#define TileByteCounts 325 +#define ExtraSamples 338 +#define JPEGTables 347 +#define YCbCrSubSampling 520 +#define ICCProfile 34675 static const byte bitrev[256] = { @@ -151,293 +131,92 @@ static const byte bitrev[256] = }; static int -xps_report_error(stream_state * st, const char *str) -{ - (void) fz_throw("%s", str); - return 0; -} - -static inline int -readbyte(xps_tiff *tiff) -{ - if (tiff->rp < tiff->ep) - return *tiff->rp++; - return EOF; -} - -static inline unsigned -readshort(xps_tiff *tiff) -{ - unsigned a = readbyte(tiff); - unsigned b = readbyte(tiff); - if (tiff->order == TII) - return (b << 8) | a; - return (a << 8) | b; -} - -static inline unsigned -readlong(xps_tiff *tiff) +xps_decode_tiff_uncompressed(xps_context *ctx, xps_tiff *tiff, fz_stream *stm, byte *wp, int wlen) { - unsigned a = readbyte(tiff); - unsigned b = readbyte(tiff); - unsigned c = readbyte(tiff); - unsigned d = readbyte(tiff); - if (tiff->order == TII) - return (d << 24) | (c << 16) | (b << 8) | a; - return (a << 24) | (b << 16) | (c << 8) | d; + int n = fz_read(stm, wp, wlen); + if (n < 0) + return fz_rethrow(n, "cannot read uncompressed strip"); + return fz_okay; } static int -xps_decode_tiff_uncompressed(xps_context *ctx, xps_tiff *tiff, byte *rp, byte *rl, byte *wp, byte *wl) +xps_decode_tiff_packbits(xps_context *ctx, xps_tiff *tiff, fz_stream *chain, byte *wp, int wlen) { - memcpy(wp, rp, wl - wp); - return gs_okay; + fz_stream *stm = fz_openrld(chain); + int n = fz_read(stm, wp, wlen); + fz_close(stm); + if (n < 0) + return fz_rethrow(n, "cannot read packbits strip"); + return fz_okay; } static int -xps_decode_tiff_packbits(xps_context *ctx, xps_tiff *tiff, byte *rp, byte *rl, byte *wp, byte *wl) +xps_decode_tiff_lzw(xps_context *ctx, xps_tiff *tiff, fz_stream *chain, byte *wp, int wlen) { - stream_RLD_state state; - stream_cursor_read scr; - stream_cursor_write scw; - int code; - - s_init_state((stream_state*)&state, &s_RLD_template, ctx->memory); - state.report_error = xps_report_error; - - s_RLD_template.set_defaults((stream_state*)&state); - s_RLD_template.init((stream_state*)&state); - - scr.ptr = rp - 1; - scr.limit = rl - 1; - scw.ptr = wp - 1; - scw.limit = wl - 1; - - code = s_RLD_template.process((stream_state*)&state, &scr, &scw, true); - if (code == ERRC) - return fz_throw("error in packbits data (code = %d)", code); - - return gs_okay; + fz_stream *stm = fz_openlzwd(chain, NULL); + int n = fz_read(stm, wp, wlen); + fz_close(stm); + if (n < 0) + return fz_rethrow(n, "cannot read lzw strip"); + return fz_okay; } - static int -xps_decode_tiff_lzw(xps_context *ctx, xps_tiff *tiff, byte *rp, byte *rl, byte *wp, byte *wl) +xps_decode_tiff_flate(xps_context *ctx, xps_tiff *tiff, fz_stream *chain, byte *wp, int wlen) { - stream_LZW_state state; - stream_cursor_read scr; - stream_cursor_write scw; - int code; - - s_init_state((stream_state*)&state, &s_LZWD_template, ctx->memory); - state.report_error = xps_report_error; - - s_LZWD_template.set_defaults((stream_state*)&state); - - /* old-style TIFF 5.0 reversed bit order, late change */ - if (rp[0] == 0 && rp[1] & 0x01) - { - state.EarlyChange = 0; - state.FirstBitLowOrder = 1; - } - - /* new-style TIFF 6.0 normal bit order, early change */ - else - { - state.EarlyChange = 1; - state.FirstBitLowOrder = 0; - } - - s_LZWD_template.init((stream_state*)&state); - - scr.ptr = rp - 1; - scr.limit = rl - 1; - scw.ptr = wp - 1; - scw.limit = wl - 1; - - code = s_LZWD_template.process((stream_state*)&state, &scr, &scw, true); - if (code == ERRC) - { - s_LZWD_template.release((stream_state*)&state); - return fz_throw("error in lzw data (code = %d)", code); - } - - s_LZWD_template.release((stream_state*)&state); - - return gs_okay; + fz_stream *stm = fz_openflated(chain); + int n = fz_read(stm, wp, wlen); + fz_close(stm); + if (n < 0) + return fz_rethrow(n, "cannot read flate strip"); + return fz_okay; } static int -xps_decode_tiff_flate(xps_context *ctx, xps_tiff *tiff, byte *rp, byte *rl, byte *wp, byte *wl) +xps_decode_tiff_fax(xps_context *ctx, xps_tiff *tiff, int comp, fz_stream *chain, byte *wp, int wlen) { - stream_zlib_state state; - stream_cursor_read scr; - stream_cursor_write scw; - int code; - - s_init_state((stream_state*)&state, &s_zlibD_template, ctx->memory); - state.report_error = xps_report_error; - - s_zlibD_template.set_defaults((stream_state*)&state); - - s_zlibD_template.init((stream_state*)&state); - - scr.ptr = rp - 1; - scr.limit = rl - 1; - scw.ptr = wp - 1; - scw.limit = wl - 1; - - code = s_zlibD_template.process((stream_state*)&state, &scr, &scw, true); - if (code == ERRC) - { - s_zlibD_template.release((stream_state*)&state); - return fz_throw("error in flate data (code = %d)", code); - } - - s_zlibD_template.release((stream_state*)&state); - return gs_okay; + fz_stream *stm; + fz_obj *params; + fz_obj *columns, *rows, *blackis1, *k, *encodedbytealign; + int n; + + columns = fz_newint(tiff->imagewidth); + rows = fz_newint(tiff->imagelength); + blackis1 = fz_newbool(tiff->photometric == 0); + k = fz_newint(comp == 4 ? -1 : 0); + encodedbytealign = fz_newbool(comp == 2); + + params = fz_newdict(5); + fz_dictputs(params, "Columns", columns); + fz_dictputs(params, "Rows", rows); + fz_dictputs(params, "BlackIs1", blackis1); + fz_dictputs(params, "K", k); + fz_dictputs(params, "EncodedByteAlign", encodedbytealign); + + fz_dropobj(columns); + fz_dropobj(rows); + fz_dropobj(blackis1); + fz_dropobj(k); + fz_dropobj(encodedbytealign); + + stm = fz_openfaxd(chain, params); + n = fz_read(stm, wp, wlen); + fz_close(stm); + fz_dropobj(params); + + if (n < 0) + return fz_rethrow(n, "cannot read fax strip"); + return fz_okay; } static int -xps_decode_tiff_fax(xps_context *ctx, xps_tiff *tiff, int comp, byte *rp, byte *rl, byte *wp, byte *wl) +xps_decode_tiff_jpeg(xps_context *ctx, xps_tiff *tiff, fz_stream *chain, byte *wp, int wlen) { - stream_CFD_state state; - stream_cursor_read scr; - stream_cursor_write scw; - int code; - - s_init_state((stream_state*)&state, &s_CFD_template, ctx->memory); - state.report_error = xps_report_error; - - s_CFD_template.set_defaults((stream_state*)&state); - - state.EndOfLine = false; - state.EndOfBlock = false; - state.Columns = tiff->imagewidth; - state.Rows = tiff->imagelength; - state.BlackIs1 = tiff->photometric == 0; - - state.K = 0; - if (comp == 4) - state.K = -1; - if (comp == 2) - state.EncodedByteAlign = true; - - s_CFD_template.init((stream_state*)&state); - - scr.ptr = rp - 1; - scr.limit = rl - 1; - scw.ptr = wp - 1; - scw.limit = wl - 1; - - code = s_CFD_template.process((stream_state*)&state, &scr, &scw, true); - if (code == ERRC) - { - s_CFD_template.release((stream_state*)&state); - return fz_throw("error in fax data (code = %d)", code); - } - - s_CFD_template.release((stream_state*)&state); - return gs_okay; -} - -/* - * We need more find control over JPEG decoding parameters than - * the s_DCTD_template filter will give us. So we abuse the - * filter, and take control after the filter setup (which sets up - * the memory manager and error handling) and call the gs_jpeg - * wrappers directly for doing the actual decoding. - */ - -static int -xps_decode_tiff_jpeg(xps_context *ctx, xps_tiff *tiff, byte *rp, byte *rl, byte *wp, byte *wl) -{ - stream_DCT_state state; /* used by gs_jpeg_* wrappers */ - jpeg_decompress_data jddp; - struct jpeg_source_mgr *srcmgr; - JSAMPROW scanlines[1]; - int stride; - int code; - - /* - * Set up the JPEG and DCT filter voodoo. - */ - - s_init_state((stream_state*)&state, &s_DCTD_template, ctx->memory); - state.report_error = xps_report_error; - s_DCTD_template.set_defaults((stream_state*)&state); - - state.jpeg_memory = ctx->memory; - state.data.decompress = &jddp; - - jddp.template = s_DCTD_template; - jddp.memory = ctx->memory; - jddp.scanline_buffer = NULL; - - if ((code = gs_jpeg_create_decompress(&state)) < 0) - return fz_throw("error in gs_jpeg_create_decompress"); - - s_DCTD_template.init((stream_state*)&state); - - srcmgr = jddp.dinfo.src; - - /* - * Read the abbreviated table file. - */ - - if (tiff->jpegtables) - { - srcmgr->next_input_byte = tiff->jpegtables; - srcmgr->bytes_in_buffer = tiff->jpegtableslen; - - code = gs_jpeg_read_header(&state, FALSE); - if (code != JPEG_HEADER_TABLES_ONLY) - return fz_throw("error in jpeg table data"); - } - - /* - * Read the image jpeg header. - */ - - srcmgr->next_input_byte = rp; - srcmgr->bytes_in_buffer = rl - rp; - - if ((code = gs_jpeg_read_header(&state, TRUE)) < 0) - return fz_throw("error in jpeg_read_header"); - - /* when TIFF says RGB and libjpeg says YCbCr, libjpeg is wrong */ - if (tiff->photometric == 2 && jddp.dinfo.jpeg_color_space == JCS_YCbCr) - { - jddp.dinfo.jpeg_color_space = JCS_RGB; - } - - /* - * Decode the strip image data. - */ - - if ((code = gs_jpeg_start_decompress(&state)) < 0) - return fz_throw("error in jpeg_start_decompress"); - - stride = jddp.dinfo.output_width * jddp.dinfo.output_components; - - while (wp + stride <= wl && jddp.dinfo.output_scanline < jddp.dinfo.output_height) - { - scanlines[0] = wp; - code = gs_jpeg_read_scanlines(&state, scanlines, 1); - if (code < 0) - return gs_throw(01, "error in jpeg_read_scanlines"); - wp += stride; - } - - /* - * Clean up. - */ - - if ((code = gs_jpeg_finish_decompress(&state)) < 0) - return fz_throw("error in jpeg_finish_decompress"); - - gs_jpeg_destroy(&state); - - return gs_okay; + fz_stream *stm = fz_opendctd(chain, NULL); + int n = fz_read(stm, wp, wlen); + fz_close(stm); + if (n < 0) + return fz_rethrow(n, "cannot read jpeg strip"); + return fz_okay; } static inline int @@ -572,12 +351,14 @@ xps_expand_colormap(xps_context *ctx, xps_tiff *tiff, xps_image *image) image->stride = stride; image->samples = samples; - return gs_okay; + return fz_okay; } static int xps_decode_tiff_strips(xps_context *ctx, xps_tiff *tiff, xps_image *image) { + fz_buffer buf; + fz_stream *stm; int error; /* switch on compression to create a filter */ @@ -609,23 +390,23 @@ xps_decode_tiff_strips(xps_context *ctx, xps_tiff *tiff, xps_image *image) switch (tiff->photometric) { case 0: /* WhiteIsZero -- inverted */ - image->colorspace = ctx->gray; + image->colorspace = fz_devicegray; break; case 1: /* BlackIsZero */ - image->colorspace = ctx->gray; + image->colorspace = fz_devicegray; break; case 2: /* RGB */ - image->colorspace = ctx->srgb; + image->colorspace = fz_devicergb; break; case 3: /* RGBPal */ - image->colorspace = ctx->srgb; + image->colorspace = fz_devicergb; break; case 5: /* CMYK */ - image->colorspace = ctx->cmyk; + image->colorspace = fz_devicecmyk; break; case 6: /* YCbCr */ /* it's probably a jpeg ... we let jpeg convert to rgb */ - image->colorspace = ctx->srgb; + image->colorspace = fz_devicergb; break; default: return fz_throw("unknown photometric: %d", tiff->photometric); @@ -656,8 +437,6 @@ xps_decode_tiff_strips(xps_context *ctx, xps_tiff *tiff, xps_image *image) } image->samples = fz_malloc(image->stride * image->height); - if (!image->samples) - return fz_throw("could not allocate image samples"); memset(image->samples, 0x55, image->stride * image->height); @@ -682,39 +461,49 @@ xps_decode_tiff_strips(xps_context *ctx, xps_tiff *tiff, xps_image *image) for (i = 0; i < rlen; i++) rp[i] = bitrev[rp[i]]; + /* create a fz_buffer on the stack */ + buf.refs = 1; + buf.data = rp; + buf.len = rlen; + buf.cap = rlen; + + stm = fz_openbuffer(&buf); + switch (tiff->compression) { case 1: - error = xps_decode_tiff_uncompressed(ctx, tiff, rp, rp + rlen, wp, wp + wlen); + error = xps_decode_tiff_uncompressed(ctx, tiff, stm, wp, wlen); break; case 2: - error = xps_decode_tiff_fax(ctx, tiff, 2, rp, rp + rlen, wp, wp + wlen); + error = xps_decode_tiff_fax(ctx, tiff, 2, stm, wp, wlen); break; case 3: - error = xps_decode_tiff_fax(ctx, tiff, 3, rp, rp + rlen, wp, wp + wlen); + error = xps_decode_tiff_fax(ctx, tiff, 3, stm, wp, wlen); break; case 4: - error = xps_decode_tiff_fax(ctx, tiff, 4, rp, rp + rlen, wp, wp + wlen); + error = xps_decode_tiff_fax(ctx, tiff, 4, stm, wp, wlen); break; case 5: - error = xps_decode_tiff_lzw(ctx, tiff, rp, rp + rlen, wp, wp + wlen); + error = xps_decode_tiff_lzw(ctx, tiff, stm, wp, wlen); break; case 6: error = fz_throw("deprecated JPEG in TIFF compression not supported"); break; case 7: - error = xps_decode_tiff_jpeg(ctx, tiff, rp, rp + rlen, wp, wp + wlen); + error = xps_decode_tiff_jpeg(ctx, tiff, stm, wp, wlen); break; case 8: - error = xps_decode_tiff_flate(ctx, tiff, rp, rp + rlen, wp, wp + wlen); + error = xps_decode_tiff_flate(ctx, tiff, stm, wp, wlen); break; case 32773: - error = xps_decode_tiff_packbits(ctx, tiff, rp, rp + rlen, wp, wp + wlen); + error = xps_decode_tiff_packbits(ctx, tiff, stm, wp, wlen); break; default: error = fz_throw("unknown TIFF compression: %d", tiff->compression); } + fz_close(stm); + if (error) return fz_rethrow(error, "could not decode strip %d", row / tiff->rowsperstrip); @@ -769,7 +558,34 @@ xps_decode_tiff_strips(xps_context *ctx, xps_tiff *tiff, xps_image *image) image->hasalpha = 1; } - return gs_okay; + return fz_okay; +} + +static inline int readbyte(xps_tiff *tiff) +{ + if (tiff->rp < tiff->ep) + return *tiff->rp++; + return EOF; +} + +static inline unsigned readshort(xps_tiff *tiff) +{ + unsigned a = readbyte(tiff); + unsigned b = readbyte(tiff); + if (tiff->order == TII) + return (b << 8) | a; + return (a << 8) | b; +} + +static inline unsigned readlong(xps_tiff *tiff) +{ + unsigned a = readbyte(tiff); + unsigned b = readbyte(tiff); + unsigned c = readbyte(tiff); + unsigned d = readbyte(tiff); + if (tiff->order == TII) + return (d << 24) | (c << 16) | (b << 8) | a; + return (a << 24) | (b << 16) | (c << 8) | d; } static void @@ -778,11 +594,8 @@ xps_read_tiff_bytes(unsigned char *p, xps_tiff *tiff, unsigned ofs, unsigned n) tiff->rp = tiff->bp + ofs; if (tiff->rp > tiff->ep) tiff->rp = tiff->bp; - while (n--) - { *p++ = readbyte(tiff); - } } static void @@ -888,8 +701,6 @@ xps_read_tiff_tag(xps_context *ctx, xps_tiff *tiff, unsigned offset) break; case ICCProfile: tiff->profile = fz_malloc(count); - if (!tiff->profile) - return fz_throw("could not allocate embedded icc profile"); /* ICC profile data type is set to UNDEFINED. * TBYTE reading not correct in xps_read_tiff_tag_value */ xps_read_tiff_bytes(tiff->profile, tiff, value, count); @@ -897,6 +708,7 @@ xps_read_tiff_tag(xps_context *ctx, xps_tiff *tiff, unsigned offset) break; case JPEGTables: + fz_warn("jpeg tables in tiff not implemented"); tiff->jpegtables = tiff->bp + value; tiff->jpegtableslen = count; break; @@ -933,7 +745,7 @@ xps_read_tiff_tag(xps_context *ctx, xps_tiff *tiff, unsigned offset) break; } - return gs_okay; + return fz_okay; } static void @@ -1011,7 +823,7 @@ xps_decode_tiff_header(xps_context *ctx, xps_tiff *tiff, byte *buf, int len) offset += 12; } - return gs_okay; + return fz_okay; } int @@ -1059,28 +871,5 @@ xps_decode_tiff(xps_context *ctx, byte *buf, int len, xps_image *image) if (tiff->stripoffsets) fz_free(tiff->stripoffsets); if (tiff->stripbytecounts) fz_free(tiff->stripbytecounts); - return gs_okay; -} - -int -xps_tiff_has_alpha(xps_context *ctx, byte *buf, int len) -{ - int error; - xps_tiff tiffst; - xps_tiff *tiff = &tiffst; - - error = xps_decode_tiff_header(ctx, tiff, buf, len); - if (error) - { - gs_catch(error, "cannot decode tiff header"); - return 0; - } - - if (tiff->profile) fz_free(tiff->profile); - if (tiff->colormap) fz_free(tiff->colormap); - if (tiff->stripoffsets) fz_free(tiff->stripoffsets); - if (tiff->stripbytecounts) fz_free(tiff->stripbytecounts); - - return tiff->extrasamples == 2 || tiff->extrasamples == 1; + return fz_okay; } -#endif diff --git a/xps/xpstile.c b/xps/xpstile.c index 0bfff9b0..db6e6655 100644 --- a/xps/xpstile.c +++ b/xps/xpstile.c @@ -165,9 +165,9 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, int x, y; /* TODO: loop in visible area */ - for (y = -10; y < 20; y++) + for (y = 0; y < 2; y++) { - for (x = -10; x < 20; x++) + for (x = 0; x < 2; x++) { ttm = fz_concat(fz_translate(w*x, h*y), ctm); xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c); |