summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/image/writeimg.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image/writeimg.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writeimg.c677
1 files changed, 677 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.c b/Build/source/texk/web2c/luatexdir/image/writeimg.c
new file mode 100644
index 00000000000..66eb459bc0c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writeimg.c
@@ -0,0 +1,677 @@
+/*
+Copyright (c) 1996-2002, 2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+pdfTeX is free software;
+you can redistribute it and / or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writeimg.c 1119 2008-03-22 11:27:02Z hhenkel $
+*/
+
+#include <assert.h>
+#include "ptexlib.h"
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-memstr.h>
+
+#include "image.h"
+
+#include <../lua51/lua.h>
+#include <../lua51/lauxlib.h>
+
+extern void pdf_print_real(integer m, integer d);
+
+#define obj_aux(A) obj_tab[(A)].int4
+
+/**********************************************************************/
+/*
+ Patch ImageTypeDetection 2003/02/08 by Heiko Oberdiek.
+
+ Function "readimage" performs some basic initializations.
+ Then it looks at the file extension to determine the
+ image type and calls specific code/functions.
+ The main disadvantage is that standard file extensions
+ have to be used, otherwise pdfTeX is not able to detect
+ the correct image type.
+
+ The patch now looks at the file header first regardless of
+ the file extension. This is implemented in function
+ "check_type_by_header". If this check fails, the traditional
+ test of standard file extension is tried, done in function
+ "check_type_by_extension".
+
+ Magic headers:
+
+ * "PNG (Portable Network Graphics) Specification", Version 1.2
+ (http://www.libpng.org/pub/png):
+
+ | 3.1. PNG file signature
+ |
+ | The first eight bytes of a PNG file always contain the following
+ | (decimal) values:
+ |
+ | 137 80 78 71 13 10 26 10
+
+ Translation to C: "\x89PNG\r\n\x1A\n"
+
+ * "JPEG File Interchange Format", Version 1.02:
+
+ | o you can identify a JFIF file by looking for the following
+ | sequence: X'FF', SOI X'FF', APP0, <2 bytes to be skipped>,
+ | "JFIF", X'00'.
+
+ Function "check_type_by_header" only looks at the first two bytes:
+ "\xFF\xD8"
+
+ * ISO/IEC JTC 1/SC 29/WG 1
+ (ITU-T SG8)
+ Coding of Still Pictures
+ Title: 14492 FCD
+ Source: JBIG Committee
+ Project: JTC 1.29.10
+ Status: Final Committee Draft
+
+ | D.4.1, ID string
+ |
+ | This is an 8-byte sequence containing 0x97 0x4A 0x42 0x32 0x0D 0x0A
+ | 0x1A 0x0A.
+
+ * "PDF Reference", third edition:
+ * The first line should contain "%PDF-1.0" until "%PDF-1.4"
+ (section 3.4.1 "File Header").
+ * The "implementation notes" say:
+
+ | 3.4.1, File Header
+ | 12. Acrobat viewers require only that the header appear
+ | somewhere within the first 1024 bytes of the file.
+ | 13. Acrobat viewers will also accept a header of the form
+ | %!PS-Adobe-N.n PDF-M.m
+
+ The check in function "check_type_by_header" only implements
+ the first issue. The implementation notes are not considered.
+ Therefore files with garbage at start of file must have the
+ standard extension.
+
+ Functions "check_type_by_header" and "check_type_by_extension":
+ img_type(img) is set to IMAGE_TYPE_NONE by new_image_dict().
+ Both functions try to detect a type and set img_type(img).
+ Thus a value other than IMAGE_TYPE_NONE indicates that a
+ type has been found.
+*/
+
+#define HEADER_JPG "\xFF\xD8"
+#define HEADER_PNG "\x89PNG\r\n\x1A\n"
+#define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A"
+#define HEADER_PDF "%PDF-1."
+#define MAX_HEADER (sizeof(HEADER_PNG)-1)
+
+static void check_type_by_header(image_dict * idict)
+{
+ int i;
+ FILE *file = NULL;
+ char header[MAX_HEADER];
+
+ assert(idict != NULL);
+ if (img_type(idict) != IMAGE_TYPE_NONE) /* nothing to do */
+ return;
+ /* read the header */
+ file = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
+ for (i = 0; (unsigned) i < MAX_HEADER; i++) {
+ header[i] = xgetc(file);
+ if (feof(file))
+ pdftex_fail("reading image file failed");
+ }
+ xfclose(file, img_filepath(idict));
+ /* tests */
+ if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_JPG;
+ else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_PNG;
+ else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_JBIG2;
+ else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_PDF;
+}
+
+static void check_type_by_extension(image_dict * idict)
+{
+ char *image_suffix;
+
+ assert(idict != NULL);
+ if (img_type(idict) != IMAGE_TYPE_NONE) /* nothing to do */
+ return;
+ /* tests */
+ if ((image_suffix = strrchr(img_filename(idict), '.')) == 0)
+ img_type(idict) = IMAGE_TYPE_NONE;
+ else if (strcasecmp(image_suffix, ".png") == 0)
+ img_type(idict) = IMAGE_TYPE_PNG;
+ else if (strcasecmp(image_suffix, ".jpg") == 0 ||
+ strcasecmp(image_suffix, ".jpeg") == 0)
+ img_type(idict) = IMAGE_TYPE_JPG;
+ else if (strcasecmp(image_suffix, ".jbig2") == 0 ||
+ strcasecmp(image_suffix, ".jb2") == 0)
+ img_type(idict) = IMAGE_TYPE_JBIG2;
+ else if (strcasecmp(image_suffix, ".pdf") == 0)
+ img_type(idict) = IMAGE_TYPE_PDF;
+}
+
+/**********************************************************************/
+
+pdf_img_struct *new_pdf_img_struct()
+{
+ pdf_img_struct *p;
+ p = xtalloc(1, pdf_img_struct);
+ p->width = 0;
+ p->height = 0;
+ p->orig_x = 0;
+ p->orig_y = 0;
+ p->doc = NULL;
+ return p;
+}
+
+void init_image(image * p)
+{
+ assert(p != NULL);
+ set_wd_running(p);
+ set_ht_running(p);
+ set_dp_running(p);
+ img_transform(p) = 0;
+ img_flags(p) = 0;
+ img_unset_refered(p); /* wd/ht/dp may be modified */
+ img_unset_scaled(p);
+ img_dict(p) = NULL;
+ img_dictref(p) = LUA_NOREF;
+}
+
+image *new_image()
+{
+ image *p = xtalloc(1, image);
+ init_image(p);
+ return p;
+}
+
+void init_image_dict(image_dict * p)
+{
+ assert(p != NULL);
+ img_objnum(p) = 0;
+ img_index(p) = 0;
+ img_xsize(p) = 0;
+ img_ysize(p) = 0;
+ img_xres(p) = 0;
+ img_yres(p) = 0;
+ img_colorspace(p) = 0;
+ img_totalpages(p) = 0;
+ img_pagenum(p) = 1;
+ img_pagename(p) = NULL;
+ img_filename(p) = NULL;
+ img_filepath(p) = NULL;
+ img_attr(p) = NULL;
+ img_file(p) = NULL;
+ img_type(p) = IMAGE_TYPE_NONE;
+ img_color(p) = 0;
+ img_colordepth(p) = 0;
+ img_pagebox(p) = PDF_BOX_SPEC_MEDIA;
+ img_state(p) = DICT_NEW;
+ img_pdf_ptr(p) = NULL; /* union */
+}
+
+image_dict *new_image_dict()
+{
+ image_dict *p = xtalloc(1, image_dict);
+ init_image_dict(p);
+ return p;
+}
+
+void free_dict_strings(image_dict * p)
+{
+ if (img_filename(p) != NULL)
+ xfree(img_filename(p));
+ img_filename(p) = NULL;
+ if (img_filepath(p) != NULL)
+ xfree(img_filepath(p));
+ img_filepath(p) = NULL;
+ if (img_attr(p) != NULL)
+ xfree(img_attr(p));
+ img_attr(p) = NULL;
+ if (img_pagename(p) != NULL)
+ xfree(img_pagename(p));
+ img_pagename(p) = NULL;
+}
+
+void free_image_dict(image_dict * p)
+{
+ free_dict_strings(p);
+ if (img_type(p) == IMAGE_TYPE_PDF)
+ epdf_delete(p);
+ assert(img_file(p) == NULL);
+ xfree(p);
+}
+
+/**********************************************************************/
+
+void pdf_print_resname_prefix()
+{
+ if (pdf_resname_prefix != 0)
+ pdf_printf(makecstring(pdf_resname_prefix));
+}
+
+void read_img(image_dict * idict, integer pdf_minor_version,
+ integer pdf_inclusion_errorlevel)
+{
+ char *filepath;
+ int callback_id;
+ assert(idict != NULL);
+ if (img_filename(idict) == NULL)
+ pdftex_fail("image file name missing");
+ callback_id = callback_defined(find_image_file_callback);
+ if (img_filepath(idict) == NULL) {
+ if (callback_id > 0
+ && run_callback(callback_id, "S->S", img_filename(idict),
+ &filepath)) {
+ if (filepath && (strlen(filepath) > 0))
+ img_filepath(idict) = strdup(filepath);
+ } else
+ img_filepath(idict) =
+ kpse_find_file(img_filename(idict), kpse_tex_format, true);
+ }
+ if (img_filepath(idict) == NULL)
+ pdftex_fail("cannot find image file");
+ /* type checks */
+ check_type_by_header(idict);
+ check_type_by_extension(idict);
+ /* read image */
+ switch (img_type(idict)) {
+ case IMAGE_TYPE_PDF:
+ read_pdf_info(idict, pdf_minor_version, pdf_inclusion_errorlevel);
+ break;
+ case IMAGE_TYPE_PNG:
+ read_png_info(idict, IMG_CLOSEINBETWEEN);
+ break;
+ case IMAGE_TYPE_JPG:
+ read_jpg_info(idict, IMG_CLOSEINBETWEEN);
+ break;
+ case IMAGE_TYPE_JBIG2:
+ if (pdf_minor_version < 4) {
+ pdftex_fail
+ ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i",
+ (int) pdf_minor_version);
+ }
+ read_jbig2_info(idict);
+ break;
+ default:
+ pdftex_fail("internal error: unknown image type");
+ }
+ cur_file_name = NULL;
+ if (img_state(idict) < DICT_FILESCANNED)
+ img_state(idict) = DICT_FILESCANNED;
+}
+
+void scale_img(image * img)
+{
+ integer x, y, xr, yr; /* size and resolution of image */
+ scaled w, h; /* indeed size corresponds to image resolution */
+ integer default_res;
+ assert(img != NULL);
+ image_dict *idict = img_dict(img);
+ assert(idict != NULL);
+ x = img_xsize(idict); /* dimensions, resolutions from image file */
+ y = img_ysize(idict);
+ xr = img_xres(idict);
+ yr = img_yres(idict);
+ if ((img_transform(img) & 1) == 1) {
+ int tmp = x;
+ x = y;
+ y = tmp;
+ tmp = xr;
+ xr = yr;
+ yr = tmp;
+ }
+ if (xr > 65535 || yr > 65535) {
+ xr = 0;
+ yr = 0;
+ pdftex_warn("ext1: too large image resolution ignored");
+ }
+ if (x <= 0 || y <= 0 || xr < 0 || yr < 0)
+ pdftex_fail("ext1: invalid image dimensions");
+ if (img_type(idict) == IMAGE_TYPE_PDF) {
+ w = x;
+ h = y;
+ } else {
+ default_res = fix_int(get_pdf_image_resolution(), 0, 65535);
+ if (default_res > 0 && (xr == 0 || yr == 0)) {
+ xr = default_res;
+ yr = default_res;
+ }
+ if (is_wd_running(img) && is_ht_running(img)) {
+ if (xr > 0 && yr > 0) {
+ w = ext_xn_over_d(one_hundred_inch, x, 100 * xr);
+ h = ext_xn_over_d(one_hundred_inch, y, 100 * yr);
+ } else {
+ w = ext_xn_over_d(one_hundred_inch, x, 7200);
+ h = ext_xn_over_d(one_hundred_inch, y, 7200);
+ }
+ }
+ }
+ if (is_wd_running(img) && is_ht_running(img) && is_dp_running(img)) {
+ img_width(img) = w;
+ img_height(img) = h;
+ img_depth(img) = 0;
+ } else if (is_wd_running(img)) {
+ /* image depth or height is explicitly specified */
+ if (is_ht_running(img)) {
+ /* image depth is explicitly specified */
+ img_width(img) = ext_xn_over_d(h, x, y);
+ img_height(img) = h - img_depth(img);
+ } else if (is_dp_running(img)) {
+ /* image height is explicitly specified */
+ img_width(img) = ext_xn_over_d(img_height(img), x, y);
+ img_depth(img) = 0;
+ } else {
+ /* both image depth and height are explicitly specified */
+ img_width(img) =
+ ext_xn_over_d(img_height(img) + img_depth(img), x, y);
+ }
+ } else {
+ /* image width is explicitly specified */
+ if (is_ht_running(img) && is_dp_running(img)) {
+ /* both image depth and height are not specified */
+ img_height(img) = ext_xn_over_d(img_width(img), y, x);
+ img_depth(img) = 0;
+ }
+ /* image depth is explicitly specified */
+ else if (is_ht_running(img)) {
+ img_height(img) =
+ ext_xn_over_d(img_width(img), y, x) - img_depth(img);
+ }
+ /* image height is explicitly specified */
+ else if (is_dp_running(img)) {
+ img_depth(img) = 0;
+ }
+ /* else both image depth and height are explicitly specified */
+ }
+ img_set_scaled(img);
+}
+
+void out_img(image * img, scaled hpos, scaled vpos)
+{
+ float a[7]; /* transformation matrix (todo: indices should be reduced!) */
+ int r; /* number of digits after the decimal point */
+ assert(img != 0);
+ image_dict *idict = img_dict(img);
+ assert(idict != 0);
+ scaled wd = img_width(img);
+ scaled ht = img_height(img);
+ scaled dp = img_depth(img);
+ if (img_type(idict) == IMAGE_TYPE_PDF) {
+ a[1] = wd * 1.0e6 / img_xsize(idict);
+ a[2] = 0;
+ a[3] = 0;
+ a[4] = (ht + dp) * 1.0e6 / img_ysize(idict);
+ a[5] = hpos -
+ (float) wd *bp2int(img_pdf_orig_x(idict)) / img_xsize(idict);
+ a[6] = vpos -
+ (float) ht *bp2int(img_pdf_orig_y(idict)) / img_ysize(idict);
+ r = 6;
+ } else {
+ a[1] = wd * 1.0e6 / one_hundred_bp;
+ a[2] = 0;
+ a[3] = 0;
+ a[4] = (ht + dp) * 1.0e6 / one_hundred_bp;
+ a[5] = hpos;
+ a[6] = vpos;
+ r = 4;
+ }
+ if ((img_transform(img) & 1) == 1) {
+ if (ht == -dp)
+ pdftex_fail("image transform: division by zero (height == -depth)");
+ if (wd == 0)
+ pdftex_fail("image transform: division by zero (width == 0)");
+ }
+ switch (img_transform(img) & 7) {
+ case 0: /* unrotated */
+ break;
+ case 1: /* rot. 90 deg. (counterclockwise) */
+ a[2] = a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = -a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[5] += wd;
+ break;
+ case 2: /* rot. 180 deg. */
+ a[1] = -a[1];
+ a[4] = -a[4];
+ a[5] += wd;
+ a[6] += ht + dp;
+ break;
+ case 3: /* rot. 270 deg. */
+ a[2] = -a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[6] += ht + dp;
+ break;
+ case 4: /* mirrored, unrotated */
+ a[1] = -a[1];
+ a[5] += wd;
+ break;
+ case 5: /* mirrored, then rot. 90 deg. */
+ a[2] = -a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = -a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[5] += wd;
+ a[6] += ht + dp;
+ break;
+ case 6: /* mirrored, then rot. 180 deg. */
+ a[4] = -a[4];
+ a[6] += ht + dp;
+ break;
+ case 7: /* mirrored, then rot. 270 deg. */
+ a[2] = a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = a[4] * wd / (ht + dp);
+ a[4] = 0;
+ break;
+ default:
+ assert(0);
+ }
+ pdf_end_text();
+ pdf_printf("q\n");
+ pdf_print_real((integer) a[1], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[2], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[3], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[4], r);
+ pdfout(' ');
+ pdf_print_bp((integer) a[5]);
+ pdfout(' ');
+ pdf_print_bp((integer) a[6]);
+ pdf_printf(" cm\n/Im");
+ pdf_print_int(img_index(idict));
+ pdf_print_resname_prefix();
+ pdf_printf(" Do\nQ\n");
+ if (img_state(idict) < DICT_OUTIMG)
+ img_state(idict) = DICT_OUTIMG;
+}
+
+void write_img(image_dict * idict)
+{
+ assert(idict != NULL);
+ if (img_state(idict) < DICT_WRITTEN) {
+ if (tracefilenames)
+ tex_printf(" <%s", img_filepath(idict));
+ switch (img_type(idict)) {
+ case IMAGE_TYPE_PNG:
+ write_png(idict);
+ break;
+ case IMAGE_TYPE_JPG:
+ write_jpg(idict);
+ break;
+ case IMAGE_TYPE_JBIG2:
+ write_jbig2(idict);
+ break;
+ case IMAGE_TYPE_PDF:
+ write_epdf(idict);
+ break;
+ default:
+ pdftex_fail("internal error: unknown image type");
+ }
+ if (tracefilenames)
+ tex_printf(">");
+ }
+ if (img_state(idict) < DICT_WRITTEN)
+ img_state(idict) = DICT_WRITTEN;
+}
+
+/**********************************************************************/
+
+typedef image *img_entry;
+/* define img_ptr, img_array, & img_limit */
+define_array(img); /* array of pointers to image structures */
+
+integer img_to_array(image * img)
+{
+ assert(img != NULL);
+ alloc_array(img, 1, SMALL_BUF_SIZE);
+ *img_ptr = img;
+ return img_ptr++ - img_array; /* now img is read-only */
+}
+
+/**********************************************************************/
+/* stuff to be accessible from TeX */
+
+integer read_image(integer objnum, integer index, strnumber filename,
+ integer page_num,
+ strnumber attr,
+ strnumber page_name,
+ integer colorspace, integer page_box,
+ integer pdf_minor_version, integer pdf_inclusion_errorlevel)
+{
+ integer ref;
+ image *a = new_image();
+ ref = img_to_array(a);
+ image_dict *idict = img_dict(a) = new_image_dict();
+ assert(idict != NULL);
+ img_objnum(idict) = objnum;
+ img_index(idict) = index;
+ /* img_xsize, img_ysize, img_xres, img_yres set by read_img() */
+ img_colorspace(idict) = colorspace;
+ img_pagenum(idict) = page_num;
+ /* img_totalpages set by read_img() */
+ if (page_name != 0)
+ img_pagename(idict) = xstrdup(makecstring(page_name));
+ cur_file_name = makecfilename(filename);
+ assert(cur_file_name != NULL);
+ img_filename(idict) = xstrdup(cur_file_name);
+ if (attr != 0)
+ img_attr(idict) = xstrdup(makecstring(attr));
+ img_pagebox(idict) = page_box;
+ read_img(idict, pdf_minor_version, pdf_inclusion_errorlevel);
+ img_unset_scaled(a);
+ img_set_refered(a);
+ return ref;
+}
+
+void set_image_dimensions(integer ref, integer wd, integer ht, integer dp)
+{
+ image *a = img_array[ref];
+ img_width(a) = wd;
+ img_height(a) = ht;
+ img_depth(a) = dp;
+}
+
+void scale_image(integer ref)
+{
+ scale_img(img_array[ref]);
+}
+
+void out_image(integer ref, scaled hpos, scaled vpos)
+{
+ image *a = img_array[ref];
+ out_img(a, hpos, vpos);
+}
+
+void write_image(integer ref)
+{
+ write_img(img_dict(img_array[ref]));
+}
+
+integer image_pages(integer ref)
+{
+ return img_totalpages(img_dict(img_array[ref]));
+}
+
+integer image_colordepth(integer ref)
+{
+ return img_colordepth(img_dict(img_array[ref]));
+}
+
+integer epdf_orig_x(integer ref)
+{
+ return bp2int(img_pdf_orig_x(img_dict(img_array[ref])));
+}
+
+integer epdf_orig_y(integer ref)
+{
+ return bp2int(img_pdf_orig_y(img_dict(img_array[ref])));
+}
+
+integer image_objnum(integer ref)
+{
+ return img_objnum(img_dict(img_array[ref]));
+}
+
+integer image_index(integer ref)
+{
+ return img_index(img_dict(img_array[ref]));
+}
+
+integer image_width(integer ref)
+{
+ return img_width(img_array[ref]);
+}
+
+integer image_height(integer ref)
+{
+ return img_height(img_array[ref]);
+}
+
+integer image_depth(integer ref)
+{
+ return img_depth(img_array[ref]);
+}
+
+void update_image_procset(integer ref)
+{
+ pdf_image_procset |= img_color(img_dict(img_array[ref]));
+}
+
+/**********************************************************************/
+
+boolean check_image_b(integer procset)
+{
+ return procset & IMAGE_COLOR_B;
+}
+
+boolean check_image_c(integer procset)
+{
+ return procset & IMAGE_COLOR_C;
+}
+
+boolean check_image_i(integer procset)
+{
+ return procset & IMAGE_COLOR_I;
+}