summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2008-09-08 10:26:58 +0930
committerAdrian Johnson <ajohnson@redneon.com>2008-11-02 20:12:29 +1030
commit3707178fa48e23b85c5640f3cee72e19f49c700b (patch)
treefc8b1878c585d3695a70778e8247d25223887568
parent3c684347f49a581bfba35202ec61a5f6334acd4a (diff)
PDF: Implement JPEG image embedding
-rw-r--r--src/Makefile.sources2
-rw-r--r--src/cairo-jpeg-info-private.h54
-rw-r--r--src/cairo-jpeg-info.c142
-rw-r--r--src/cairo-pdf-surface.c55
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;