diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2008-09-08 10:26:58 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2008-11-02 20:12:29 +1030 |
commit | 3707178fa48e23b85c5640f3cee72e19f49c700b (patch) | |
tree | fc8b1878c585d3695a70778e8247d25223887568 | |
parent | 3c684347f49a581bfba35202ec61a5f6334acd4a (diff) |
PDF: Implement JPEG image embedding
-rw-r--r-- | src/Makefile.sources | 2 | ||||
-rw-r--r-- | src/cairo-jpeg-info-private.h | 54 | ||||
-rw-r--r-- | src/cairo-jpeg-info.c | 142 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 55 |
4 files changed, 253 insertions, 0 deletions
diff --git a/src/Makefile.sources b/src/Makefile.sources index 082b6af8c..6a0e93b99 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -64,6 +64,7 @@ cairo_private = \ cairo-freelist-private.h \ cairo-gstate-private.h \ cairo-hash-private.h \ + cairo-jpeg-info-private.h \ cairo-malloc-private.h \ cairo-meta-surface-private.h \ cairo-mutex-impl-private.h \ @@ -109,6 +110,7 @@ cairo_sources = \ cairo-hash.c \ cairo-hull.c \ cairo-image-surface.c \ + cairo-jpeg-info.c \ cairo-lzw.c \ cairo-matrix.c \ cairo-meta-surface.c \ diff --git a/src/cairo-jpeg-info-private.h b/src/cairo-jpeg-info-private.h new file mode 100644 index 000000000..1a376c93c --- /dev/null +++ b/src/cairo-jpeg-info-private.h @@ -0,0 +1,54 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2008 Adrian Johnson + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson <ajohnson@redneon.com> + */ + +#ifndef CAIRO_JPEG_INFO_PRIVATE_H +#define CAIRO_JPEG_INFO_PRIVATE_H + +#include "cairoint.h" + +typedef struct _cairo_jpeg_info { + int width; + int height; + int num_components; + int bits_per_component; +} cairo_jpeg_info_t; + +cairo_private cairo_int_status_t +_cairo_jpeg_get_info (unsigned char *data, + long length, + cairo_jpeg_info_t *info); + + +#endif /* CAIRO_JPEG_INFO_PRIVATE_H */ diff --git a/src/cairo-jpeg-info.c b/src/cairo-jpeg-info.c new file mode 100644 index 000000000..75dc0bf22 --- /dev/null +++ b/src/cairo-jpeg-info.c @@ -0,0 +1,142 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2008 Adrian Johnson + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson <ajohnson@redneon.com> + */ + +#include "cairoint.h" +#include "cairo-jpeg-info-private.h" + +/* Markers with no parameters. All other markers are followed by a two + * byte length of the parameters. */ +#define TEM 0x01 +#define RST_begin 0xd0 +#define RST_end 0xd7 +#define SOI 0xd8 +#define EOI 0xd9 + +/* Start of frame markers. */ +#define SOF0 0xc0 +#define SOF1 0xc1 +#define SOF2 0xc2 +#define SOF3 0xc3 +#define SOF5 0xc5 +#define SOF6 0xc6 +#define SOF7 0xc7 +#define SOF9 0xc9 +#define SOF10 0xca +#define SOF11 0xcb +#define SOF13 0xcd +#define SOF14 0xce +#define SOF15 0xcf + +static unsigned char * +_skip_segment (unsigned char *p) +{ + int len; + + p++; + len = p[0] << 8; + len |= p[1]; + + return p + len; +} + +static void +_extract_info (cairo_jpeg_info_t *info, unsigned char *p) +{ + info->width = (p[6] << 8) + p[7]; + info->height = (p[4] << 8) + p[5];; + info->num_components = p[8]; + info->bits_per_component = p[3]; +} + +cairo_int_status_t +_cairo_jpeg_get_info (unsigned char *data, + long length, + cairo_jpeg_info_t *info) +{ + unsigned char *p = data; + + while (p + 1 < data + length) { + if (*p != 0xff) + return CAIRO_INT_STATUS_UNSUPPORTED; + p++; + + switch (*p) { + /* skip fill bytes */ + case 0xff: + p++; + break; + + case TEM: + case SOI: + case EOI: + p++; + break; + + case SOF0: + case SOF1: + case SOF2: + case SOF3: + case SOF5: + case SOF6: + case SOF7: + case SOF9: + case SOF10: + case SOF11: + case SOF13: + case SOF14: + case SOF15: + /* Start of frame found. Extract the image parameters. */ + if (p + 8 > data + length) + return CAIRO_INT_STATUS_UNSUPPORTED; + + _extract_info (info, p); + return CAIRO_STATUS_SUCCESS; + + default: + if (*p >= RST_begin && *p <= RST_end) { + p++; + break; + } + + if (p + 2 > data + length) + return CAIRO_INT_STATUS_UNSUPPORTED; + + p = _skip_segment (p); + break; + } + } + + return CAIRO_STATUS_SUCCESS; +} diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 27fcbe081..827c9eac2 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -50,6 +50,7 @@ #include "cairo-paginated-private.h" #include "cairo-scaled-font-subsets-private.h" #include "cairo-type3-glyph-surface-private.h" +#include "cairo-jpeg-info-private.h" #include <time.h> #include <zlib.h> @@ -1550,6 +1551,55 @@ CLEANUP: return status; } +static cairo_int_status_t +_cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface, + cairo_surface_t *source, + cairo_pdf_resource_t *res, + int *width, + int *height) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_jpeg_info_t info; + + if (source->jpeg_data == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + + status = _cairo_jpeg_get_info (source->jpeg_data, + source->jpeg_data_length, + &info); + if (status) + return status; + + if (info.num_components != 1 && info.num_components != 3) + return CAIRO_INT_STATUS_UNSUPPORTED; + + status = _cairo_pdf_surface_open_stream (surface, + NULL, + FALSE, + " /Type /XObject\n" + " /Subtype /Image\n" + " /Width %d\n" + " /Height %d\n" + " /ColorSpace %s\n" + " /BitsPerComponent %d\n" + " /Filter /DCTDecode\n", + info.width, + info.height, + info.num_components == 1 ? "/DeviceGray" : "/DeviceRGB", + info.bits_per_component); + + *res = surface->pdf_stream.self; + _cairo_output_stream_write (surface->output, + source->jpeg_data, + source->jpeg_data_length); + status = _cairo_pdf_surface_close_stream (surface); + + *width = info.width; + *height = info.height; + + return status; +} + static cairo_status_t _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern, @@ -1567,6 +1617,11 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface, int x = 0; int y = 0; + status = _cairo_pdf_surface_emit_jpeg_image (surface, pattern->surface, + resource, width, height); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); if (status) goto BAIL; |