1% writeimg.w
2%
3% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
4% Copyright 2006-2012 Taco Hoekwater <taco@@luatex.org>
5%
6% This file is part of LuaTeX.
7%
8% LuaTeX is free software; you can redistribute it and/or modify it under
9% the terms of the GNU General Public License as published by the Free
10% Software Foundation; either version 2 of the License, or (at your
11% option) any later version.
12%
13% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
14% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15% FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16% License for more details.
17%
18% You should have received a copy of the GNU General Public License along
19% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
20
21@* Image inclusion.
22
23@ @c
24
25
26#include "ptexlib.h"
27#include <assert.h>
28#include <kpathsea/c-auto.h>
29#include <kpathsea/c-memstr.h>
30
31@ @c
32#include "image/image.h"
33#include "image/writejpg.h"
34#include "image/writejp2.h"
35#include "image/writepng.h"
36#include "image/writejbig2.h"
37
38#include "lua.h"          /* for |LUA_NOREF| */
39#include "lauxlib.h"
40
41@ @c
42#define pdf_image_resolution int_par(pdf_image_resolution_code)
43#define pdf_pagebox int_par(pdf_pagebox_code)
44
45@* Patch ImageTypeDetection 2003/02/08 by Heiko Oberdiek.
46
47  Function |readimage| performs some basic initializations.
48  Then it looks at the file extension to determine the
49  image type and calls specific code/functions.
50
51    The main disadvantage is that standard file extensions
52  have to be used, otherwise pdfTeX is not able to detect
53  the correct image type.
54
55  The patch now looks at the file header first regardless of
56  the file extension. This is implemented in function
57  |check_type_by_header|. If this check fails, the traditional
58  test of standard file extension is tried, done in function
59  |check_type_by_extension|.
60
61  Magic headers:
62
63  * "PNG (Portable Network Graphics) Specification", Version 1.2
64    (http://www.libpng.org/pub/png):
65
66     3.1. PNG file signature
67
68        The first eight bytes of a PNG file always contain the following
69        (decimal) values:
70
71           137 80 78 71 13 10 26 10
72
73  Translation to C: |"\x89PNG\r\n\x1A\n"|
74
75  * "JPEG File Interchange Format", Version 1.02:
76
77   o you can identify a JFIF file by looking for the following
78     sequence: X'FF', SOI X'FF', APP0, <2 bytes to be skipped>,
79     "JFIF", X'00'.
80
81  Function |check_type_by_header| only looks at the first two bytes:
82    |"\xFF\xD8"|
83
84  * ISO/IEC JTC 1/SC 29/WG 1
85    (ITU-T SG8)
86    Coding of Still Pictures
87    Title: 14492 FCD
88    Source: JBIG Committee
89    Project: JTC 1.29.10
90    Status: Final Committee Draft
91
92   D.4.1, ID string
93
94   This is an 8-byte sequence containing 0x97 0x4A 0x42 0x32 0x0D 0x0A
95   0x1A 0x0A.
96
97  * "PDF Reference", third edition:
98
99    * The first line should contain "\%PDF-1.0" until "\%PDF-1.4"
100      (section 3.4.1 "File Header").
101    * The "implementation notes" say:
102
103     3.4.1,  File Header
104       12. Acrobat viewers require only that the header appear
105           somewhere within the first 1024 bytes of the file.
106       13. Acrobat viewers will also accept a header of the form
107               \%!PS-Adobe-N.n PDF-M.m
108
109    The check in function |check_type_by_header| only implements
110    the first issue. The implementation notes are not considered.
111    Therefore files with garbage at start of file must have the
112    standard extension.
113
114    Functions |check_type_by_header| and |check_type_by_extension|:
115    |img_type(img)| is set to |IMG_TYPE_NONE| by |new_image_dict()|.
116    Both functions try to detect a type and set |img_type(img)|.
117    Thus a value other than |IMG_TYPE_NONE| indicates that a
118    type has been found.
119
120@c
121#define HEADER_JPG "\xFF\xD8"
122#define HEADER_PNG "\x89PNG\r\n\x1A\n"
123#define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A"
124#define HEADER_JP2 "\x6A\x50\x20\x20"
125#define HEADER_PDF "%PDF-1."
126#define MAX_HEADER (sizeof(HEADER_PNG)-1)
127
128idict_entry *idict_array;
129
130static void check_type_by_header(image_dict * idict)
131{
132    int i;
133    FILE *file = NULL;
134    char header[MAX_HEADER];
135
136    assert(idict != NULL);
137    if (img_type(idict) != IMG_TYPE_NONE)       /* nothing to do */
138        return;
139    /* read the header */
140    file = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
141    for (i = 0; (unsigned) i < MAX_HEADER; i++) {
142        header[i] = (char) xgetc(file);
143        if (feof(file))
144            luatex_fail("reading image file failed");
145    }
146    xfclose(file, img_filepath(idict));
147    /* tests */
148    if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0)
149        img_type(idict) = IMG_TYPE_JPG;
150    else if (strncmp(header + 4, HEADER_JP2, sizeof(HEADER_JP2) - 1) == 0)
151        img_type(idict) = IMG_TYPE_JP2;
152    else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0)
153        img_type(idict) = IMG_TYPE_PNG;
154    else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0)
155        img_type(idict) = IMG_TYPE_JBIG2;
156    else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF) - 1) == 0)
157        img_type(idict) = IMG_TYPE_PDF;
158}
159
160@ @c
161static void check_type_by_extension(image_dict * idict)
162{
163    char *image_suffix;
164
165    assert(idict != NULL);
166    if (img_type(idict) != IMG_TYPE_NONE)       /* nothing to do */
167        return;
168    /* tests */
169    if ((image_suffix = strrchr(img_filename(idict), '.')) == 0)
170        img_type(idict) = IMG_TYPE_NONE;
171    else if (strcasecmp(image_suffix, ".png") == 0)
172        img_type(idict) = IMG_TYPE_PNG;
173    else if (strcasecmp(image_suffix, ".jpg") == 0 ||
174             strcasecmp(image_suffix, ".jpeg") == 0)
175        img_type(idict) = IMG_TYPE_JPG;
176    else if (strcasecmp(image_suffix, ".jp2") == 0)
177        img_type(idict) = IMG_TYPE_JP2;
178    else if (strcasecmp(image_suffix, ".jbig2") == 0 ||
179             strcasecmp(image_suffix, ".jb2") == 0)
180        img_type(idict) = IMG_TYPE_JBIG2;
181    else if (strcasecmp(image_suffix, ".pdf") == 0)
182        img_type(idict) = IMG_TYPE_PDF;
183}
184
185@ @c
186void new_img_pdfstream_struct(image_dict * p)
187{
188    assert(p != NULL);
189    assert(img_pdfstream_ptr(p) == NULL);
190    img_pdfstream_ptr(p) = xtalloc(1, pdf_stream_struct);
191    img_pdfstream_stream(p) = NULL;
192}
193
194@ @c
195static void init_image(image * p)
196{
197    assert(p != NULL);
198    set_wd_running(p);
199    set_ht_running(p);
200    set_dp_running(p);
201    img_transform(p) = 0;
202    img_dict(p) = NULL;
203    img_dictref(p) = LUA_NOREF;
204}
205
206@ @c
207image *new_image(void)
208{
209    image *p = xtalloc(1, image);
210    init_image(p);
211    return p;
212}
213
214@ @c
215static void init_image_dict(image_dict * p)
216{
217    assert(p != NULL);
218    memset(p, 0, sizeof(image_dict));
219    set_wd_running(p);
220    set_ht_running(p);
221    set_dp_running(p);
222    img_transform(p) = 0;
223    img_pagenum(p) = 1;
224    img_type(p) = IMG_TYPE_NONE;
225    img_pagebox(p) = PDF_BOX_SPEC_MEDIA;
226    img_unset_bbox(p);
227    img_unset_group(p);
228    img_state(p) = DICT_NEW;
229    img_index(p) = -1;          /* -1 = unused, used count from 0 */
230}
231
232@ @c
233image_dict *new_image_dict(void)
234{
235    image_dict *p = xtalloc(1, image_dict);
236    init_image_dict(p);
237    return p;
238}
239
240@ @c
241static void free_dict_strings(image_dict * p)
242{
243    xfree(img_filename(p));
244    xfree(img_filepath(p));
245    xfree(img_attr(p));
246    xfree(img_pagename(p));
247}
248
249@ @c
250void free_image_dict(image_dict * p)
251{
252    if (ini_version)
253        return;                 /* The image may be \.{\\dump}ed to a format */
254    /* called from limglib.c */
255    assert(img_state(p) < DICT_REFERED);
256    switch (img_type(p)) {
257    case IMG_TYPE_PDF:
258        unrefPdfDocument(img_filepath(p));
259        break;
260    case IMG_TYPE_PNG:         /* assuming |IMG_CLOSEINBETWEEN| */
261        assert(img_png_ptr(p) == NULL);
262        break;
263    case IMG_TYPE_JPG:         /* assuming |IMG_CLOSEINBETWEEN| */
264        assert(img_jpg_ptr(p) == NULL);
265        break;
266    case IMG_TYPE_JP2:         /* */
267        assert(img_jp2_ptr(p) == NULL);
268        break;
269    case IMG_TYPE_JBIG2:       /* todo: writejbig2.w cleanup */
270        break;
271    case IMG_TYPE_PDFSTREAM:
272        if (img_pdfstream_ptr(p) != NULL) {
273            xfree(img_pdfstream_stream(p));
274            xfree(img_pdfstream_ptr(p));
275        }
276        break;
277    case IMG_TYPE_NONE:
278        break;
279    default:
280        assert(0);
281    }
282    free_dict_strings(p);
283    assert(img_file(p) == NULL);
284    xfree(p);
285}
286
287@ @c
288void read_img(PDF pdf,
289              image_dict * idict, int minor_version, int inclusion_errorlevel)
290{
291    char *filepath = NULL;
292    int callback_id;
293    assert(idict != NULL);
294    if (img_filename(idict) == NULL)
295        luatex_fail("image file name missing");
296    callback_id = callback_defined(find_image_file_callback);
297    if (img_filepath(idict) == NULL) {
298        if (callback_id > 0
299            && run_callback(callback_id, "S->S", img_filename(idict),
300                            &filepath)) {
301            if (filepath && (strlen(filepath) > 0))
302                img_filepath(idict) = strdup(filepath);
303        } else
304            img_filepath(idict) =
305                kpse_find_file(img_filename(idict), kpse_tex_format, true);
306        if (img_filepath(idict) == NULL)
307            luatex_fail("cannot find image file '%s'", img_filename(idict));
308    }
309    recorder_record_input(img_filename(idict));
310    /* type checks */
311    check_type_by_header(idict);
312    check_type_by_extension(idict);
313    /* read image */
314    switch (img_type(idict)) {
315    case IMG_TYPE_PDF:
316        assert(pdf != NULL);    /* TODO! */
317        read_pdf_info(idict, minor_version, inclusion_errorlevel,
318                      IMG_CLOSEINBETWEEN);
319        break;
320    case IMG_TYPE_PNG:
321        read_png_info(idict, IMG_CLOSEINBETWEEN);
322        break;
323    case IMG_TYPE_JPG:
324        read_jpg_info(pdf, idict, IMG_CLOSEINBETWEEN);
325        break;
326    case IMG_TYPE_JP2:
327        read_jp2_info(idict, IMG_CLOSEINBETWEEN);
328        break;
329    case IMG_TYPE_JBIG2:
330        if (minor_version < 4) {
331            luatex_fail
332                ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i",
333                 (int) minor_version);
334        }
335        read_jbig2_info(idict);
336        break;
337    default:
338        luatex_fail("internal error: unknown image type (2)");
339    }
340    cur_file_name = NULL;
341    if (img_state(idict) < DICT_FILESCANNED)
342        img_state(idict) = DICT_FILESCANNED;
343}
344
345@ @c
346static image_dict *read_image(PDF pdf, char *file_name, int page_num,
347                              char *page_name, int colorspace,
348                              int page_box, int minor_version,
349                              int inclusion_errorlevel)
350{
351    image *a = new_image();
352    image_dict *idict = img_dict(a) = new_image_dict();
353    pdf->ximage_count++;
354    img_objnum(idict) = pdf_create_obj(pdf, obj_type_ximage, pdf->ximage_count);
355    img_index(idict) = pdf->ximage_count;
356    set_obj_data_ptr(pdf, img_objnum(idict), img_index(idict));
357    idict_to_array(idict);
358    img_colorspace(idict) = colorspace;
359    img_pagenum(idict) = page_num;
360    img_pagename(idict) = page_name;
361    assert(file_name != NULL);
362    cur_file_name = file_name;
363    img_filename(idict) = file_name;
364    img_pagebox(idict) = page_box;
365    read_img(pdf, idict, minor_version, inclusion_errorlevel);
366    return idict;
367}
368
369@ scans PDF pagebox specification
370@c
371static pdfboxspec_e scan_pdf_box_spec(void)
372{
373    if (scan_keyword("mediabox"))
374        return PDF_BOX_SPEC_MEDIA;
375    else if (scan_keyword("cropbox"))
376        return PDF_BOX_SPEC_CROP;
377    else if (scan_keyword("bleedbox"))
378        return PDF_BOX_SPEC_BLEED;
379    else if (scan_keyword("trimbox"))
380        return PDF_BOX_SPEC_TRIM;
381    else if (scan_keyword("artbox"))
382        return PDF_BOX_SPEC_ART;
383    return PDF_BOX_SPEC_NONE;
384}
385
386@ @c
387void scan_pdfximage(PDF pdf)
388{
389    scaled_whd alt_rule;
390    image_dict *idict;
391    int transform = 0, page = 1, pagebox, colorspace = 0;
392    char *named = NULL, *attr = NULL, *file_name = NULL;
393    alt_rule = scan_alt_rule(); /* scans |<rule spec>| to |alt_rule| */
394    if (scan_keyword("attr")) {
395        scan_pdf_ext_toks();
396        attr = tokenlist_to_cstring(def_ref, true, NULL);
397        delete_token_ref(def_ref);
398    }
399    if (scan_keyword("named")) {
400        scan_pdf_ext_toks();
401        named = tokenlist_to_cstring(def_ref, true, NULL);
402        delete_token_ref(def_ref);
403        page = 0;
404    } else if (scan_keyword("page")) {
405        scan_int();
406        page = cur_val;
407    }
408    if (scan_keyword("colorspace")) {
409        scan_int();
410        colorspace = cur_val;
411    }
412    pagebox = scan_pdf_box_spec();
413    if (pagebox == PDF_BOX_SPEC_NONE) {
414        pagebox = pdf_pagebox;
415        if (pagebox == PDF_BOX_SPEC_NONE)
416            pagebox = PDF_BOX_SPEC_CROP;
417    }
418    scan_pdf_ext_toks();
419    file_name = tokenlist_to_cstring(def_ref, true, NULL);
420    assert(file_name != NULL);
421    delete_token_ref(def_ref);
422    idict =
423        read_image(pdf, file_name, page, named, colorspace, pagebox,
424                   pdf_minor_version, pdf_inclusion_errorlevel);
425    img_attr(idict) = attr;
426    img_dimen(idict) = alt_rule;
427    img_transform(idict) = transform;
428    pdf_last_ximage = img_objnum(idict);
429    pdf_last_ximage_pages = img_totalpages(idict);
430    pdf_last_ximage_colordepth = img_colordepth(idict);
431}
432
433@ @c
434#define tail          cur_list.tail_field
435
436void scan_pdfrefximage(PDF pdf)
437{
438    int transform = 0;          /* one could scan transform as well */
439    image_dict *idict;
440    scaled_whd alt_rule, dim;
441    alt_rule = scan_alt_rule(); /* scans |<rule spec>| to |alt_rule| */
442    scan_int();
443    check_obj_type(pdf, obj_type_ximage, cur_val);
444    new_whatsit(pdf_refximage_node);
445    idict = idict_array[obj_data_ptr(pdf, cur_val)];
446    if (alt_rule.wd != null_flag || alt_rule.ht != null_flag
447        || alt_rule.dp != null_flag)
448        dim = scale_img(idict, alt_rule, transform);
449    else
450        dim = scale_img(idict, img_dimen(idict), img_transform(idict));
451    width(tail) = dim.wd;
452    height(tail) = dim.ht;
453    depth(tail) = dim.dp;
454    pdf_ximage_transform(tail) = transform;
455    pdf_ximage_index(tail) = img_index(idict);
456}
457
458@ |tex_scale()| sequence of decisions:
459
460{\obeylines\obeyspaces\tt
461wd ht dp : res = tex;
462wd ht --
463wd -- dp
464wd -- --
465-- ht dp
466-- ht --
467-- -- dp
468-- -- -- : res = nat;
469}
470
471@c
472scaled_whd tex_scale(scaled_whd nat, scaled_whd tex)
473{
474    scaled_whd res;
475    if (!is_running(tex.wd) && !is_running(tex.ht) && !is_running(tex.dp)) {
476        /* width, height, and depth specified */
477        res = tex;
478    } else /* max. 2 dimensions are specified */ if (!is_running(tex.wd)) {
479        res.wd = tex.wd;
480        if (!is_running(tex.ht)) {
481            res.ht = tex.ht;
482            /* width and height specified */
483            res.dp = ext_xn_over_d(tex.ht, nat.dp, nat.ht);
484        } else if (!is_running(tex.dp)) {
485            res.dp = tex.dp;
486            /* width and depth specified */
487            res.ht = ext_xn_over_d(tex.wd, nat.ht + nat.dp, nat.wd) - tex.dp;
488        } else {
489            /* only width specified */
490            res.ht = ext_xn_over_d(tex.wd, nat.ht, nat.wd);
491            res.dp = ext_xn_over_d(tex.wd, nat.dp, nat.wd);
492        }
493    } else if (!is_running(tex.ht)) {
494        res.ht = tex.ht;
495        if (!is_running(tex.dp)) {
496            res.dp = tex.dp;
497            /* height and depth specified */
498            res.wd = ext_xn_over_d(tex.ht + tex.dp, nat.wd, nat.ht + nat.dp);
499        } else {
500            /* only height specified */
501            res.wd = ext_xn_over_d(tex.ht, nat.wd, nat.ht);
502            res.dp = ext_xn_over_d(tex.ht, nat.dp, nat.ht);
503        }
504    } else if (!is_running(tex.dp)) {
505        res.dp = tex.dp;
506        /* only depth specified */
507        res.ht = nat.ht - (tex.dp - nat.dp);
508        res.wd = nat.wd;
509    } else {
510        /* nothing specified */
511        res = nat;
512    }
513    return res;
514}
515
516@ Within |scale_img()| only image width and height matter;
517the offsets and positioning are not interesting here.
518But one needs rotation info to swap width and height.
519|img_rotation()| comes from the optional /Rotate key in the PDF file.
520
521@c
522scaled_whd scale_img(image_dict * idict, scaled_whd alt_rule, int transform)
523{
524    int x, y, xr, yr, tmp;      /* size and resolution of image */
525    scaled_whd nat;             /* natural size corresponding to image resolution */
526    int default_res;
527    assert(idict != NULL);
528    if ((img_type(idict) == IMG_TYPE_PDF
529         || img_type(idict) == IMG_TYPE_PDFSTREAM) && img_is_bbox(idict)) {
530        x = img_xsize(idict) = img_bbox(idict)[2] - img_bbox(idict)[0]; /* dimensions from image.bbox */
531        y = img_ysize(idict) = img_bbox(idict)[3] - img_bbox(idict)[1];
532        img_xorig(idict) = img_bbox(idict)[0];
533        img_yorig(idict) = img_bbox(idict)[1];
534    } else {
535        x = img_xsize(idict);   /* dimensions, resolutions from image file */
536        y = img_ysize(idict);
537    }
538    xr = img_xres(idict);
539    yr = img_yres(idict);
540    if (x <= 0 || y <= 0 || xr < 0 || yr < 0)
541        luatex_fail("ext1: invalid image dimensions");
542    if (xr > 65535 || yr > 65535) {
543        xr = 0;
544        yr = 0;
545        luatex_warn("ext1: too large image resolution ignored");
546    }
547    if (((transform - img_rotation(idict)) & 1) == 1) {
548        tmp = x;
549        x = y;
550        y = tmp;
551        tmp = xr;
552        xr = yr;
553        yr = tmp;
554    }
555    nat.dp = 0;                 /* always for images */
556    if (img_type(idict) == IMG_TYPE_PDF
557        || img_type(idict) == IMG_TYPE_PDFSTREAM) {
558        nat.wd = x;
559        nat.ht = y;
560    } else {
561        default_res = fix_int(pdf_image_resolution, 0, 65535);
562        if (default_res > 0 && (xr == 0 || yr == 0)) {
563            xr = default_res;
564            yr = default_res;
565        }
566        if (xr > 0 && yr > 0) {
567            nat.wd = ext_xn_over_d(one_hundred_inch, x, 100 * xr);
568            nat.ht = ext_xn_over_d(one_hundred_inch, y, 100 * yr);
569        } else {
570            nat.wd = ext_xn_over_d(one_hundred_inch, x, 7200);
571            nat.ht = ext_xn_over_d(one_hundred_inch, y, 7200);
572        }
573    }
574    return tex_scale(nat, alt_rule);
575}
576
577@ @c
578void write_img(PDF pdf, image_dict * idict)
579{
580    assert(idict != NULL);
581    if (img_state(idict) < DICT_WRITTEN) {
582        report_start_file(filetype_image, img_filepath(idict));
583        switch (img_type(idict)) {
584        case IMG_TYPE_PNG:
585            write_png(pdf, idict);
586            break;
587        case IMG_TYPE_JPG:
588            write_jpg(pdf, idict);
589            break;
590        case IMG_TYPE_JP2:
591            write_jp2(pdf, idict);
592            break;
593        case IMG_TYPE_JBIG2:
594            write_jbig2(pdf, idict);
595            break;
596        case IMG_TYPE_PDF:
597            write_epdf(pdf, idict);
598            break;
599        case IMG_TYPE_PDFSTREAM:
600            write_pdfstream(pdf, idict);
601            break;
602        default:
603            luatex_fail("internal error: unknown image type (1)");
604        }
605        report_stop_file(filetype_image);
606        if (img_type(idict) == IMG_TYPE_PNG) {
607            write_additional_png_objects(pdf);
608        }
609    }
610    if (img_state(idict) < DICT_WRITTEN)
611        img_state(idict) = DICT_WRITTEN;
612}
613
614@ write an image
615@c
616void pdf_write_image(PDF pdf, int n)
617{
618    if (pdf->draftmode == 0)
619        write_img(pdf, idict_array[obj_data_ptr(pdf, n)]);
620}
621
622@ @c
623void check_pdfstream_dict(image_dict * idict)
624{
625    if (!img_is_bbox(idict))
626        luatex_fail("image.stream: no bbox given");
627    if (img_state(idict) < DICT_FILESCANNED)
628        img_state(idict) = DICT_FILESCANNED;
629}
630
631@ @c
632void write_pdfstream(PDF pdf, image_dict * idict)
633{
634    assert(img_pdfstream_ptr(idict) != NULL);
635    assert(img_is_bbox(idict));
636    pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER);
637    pdf_begin_dict(pdf);
638    pdf_dict_add_name(pdf, "Type", "XObject");
639    pdf_dict_add_name(pdf, "Subtype", "Form");
640    if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
641        pdf_printf(pdf, "\n%s\n", img_attr(idict));
642    pdf_dict_add_int(pdf, "FormType", 1);
643    pdf_add_name(pdf, "BBox");
644    pdf_begin_array(pdf);
645    copyReal(pdf, sp2bp(img_bbox(idict)[0]));
646    copyReal(pdf, sp2bp(img_bbox(idict)[1]));
647    copyReal(pdf, sp2bp(img_bbox(idict)[2]));
648    copyReal(pdf, sp2bp(img_bbox(idict)[3]));
649    pdf_end_array(pdf);
650    pdf_dict_add_streaminfo(pdf);
651    pdf_end_dict(pdf);
652    pdf_begin_stream(pdf);
653    if (img_pdfstream_stream(idict) != NULL)
654        pdf_puts(pdf, img_pdfstream_stream(idict));
655    pdf_end_stream(pdf);
656    pdf_end_obj(pdf);
657}
658
659@ @c
660/* define |idict_ptr|, |idict_array|, and |idict_limit| */
661idict_entry *idict_ptr, *idict_array = NULL;
662size_t idict_limit;
663
664void idict_to_array(image_dict * idict)
665{
666    assert(idict != NULL);
667    if (idict_ptr - idict_array == 0) { /* align to count from 1 */
668        alloc_array(idict, 1, SMALL_BUF_SIZE);  /* /Im0 unused */
669        idict_ptr++;
670    }
671    alloc_array(idict, 1, SMALL_BUF_SIZE);
672    *idict_ptr = idict;
673    assert(img_index(idict) == idict_ptr - idict_array);
674    idict_ptr++;
675}
676
677void pdf_dict_add_img_filename(PDF pdf, image_dict * idict)
678{
679    char s[21], *p;
680    assert(idict != NULL);
681    /* for now PTEX.FileName only for PDF, but prepared for JPG, PNG, ... */
682    if (img_type(idict) != IMG_TYPE_PDF)
683        return;
684    if (img_visiblefilename(idict) != NULL) {
685        if (strlen(img_visiblefilename(idict)) == 0)
686            return;             /* empty string blocks PTEX.FileName output */
687        else
688            p = img_visiblefilename(idict);
689    } else
690        p = img_filepath(idict);
691    // write additional information
692    snprintf(s, 20, "%s.FileName", pdfkeyprefix);
693    pdf_add_name(pdf, s);
694    pdf_printf(pdf, " (%s)", convertStringToPDFString(p, strlen(p)));
695}
696
697@ To allow the use of \.{\\pdfrefximage} inside saved boxes in -ini mode,
698the information in the array has to be (un)dumped with the format.
699The next two routines take care of that.
700
701Most of the work involved in setting up the images is simply
702executed again. This solves the many possible errors resulting from
703the split in two separate runs.
704
705There was only one problem remaining: The pdfversion and
706pdfinclusionerrorlevel can have changed inbetween the call to
707|readimage()| and dump time. That is why they are passed as arguments
708to undumpimagemeta once more.
709
710some of the dumped values are really type int, not integer,
711but since the macro falls back to |generic_dump| anyway, that
712does not matter.
713
714@c
715#define dumpinteger generic_dump
716#define undumpinteger generic_undump
717
718@ (un)dumping a string means dumping the allocation size, followed
719 by the bytes. The trailing \.{\\0} is dumped as well, because that
720 makes the code simpler.
721
722@c
723#define dumpcharptr(a)                          \
724  do {                                          \
725    int x;                                      \
726    if (a!=NULL) {                              \
727	x = (int)strlen(a)+1;			\
728      dumpinteger(x);  dump_things(*a, x);      \
729    } else {                                    \
730      x = 0; dumpinteger(x);                    \
731    }                                           \
732  } while (0)
733
734#define undumpcharptr(s)                        \
735  do {                                          \
736    int x;                                      \
737    char *a;                                    \
738    undumpinteger (x);                          \
739    if (x>0) {                                  \
740      a = xmalloc((unsigned)x);  		\
741      undump_things(*a,x);                      \
742      s = a ;                                   \
743    } else { s = NULL; }                        \
744  } while (0)
745
746@ @c
747void dumpimagemeta(void)
748{
749    int cur_index, i;
750    image_dict *idict;
751
752    i = (int) idict_limit;
753    dumpinteger(i);
754    cur_index = (int) (idict_ptr - idict_array);
755    dumpinteger(cur_index);
756
757    for (i = 1; i < cur_index; i++) {
758        idict = idict_array[i];
759        assert(idict != NULL);
760        dumpcharptr(img_filename(idict));
761        dumpinteger(img_type(idict));
762        dumpinteger(img_procset(idict));
763        dumpinteger(img_xsize(idict));
764        dumpinteger(img_ysize(idict));
765        dumpinteger(img_xres(idict));
766        dumpinteger(img_yres(idict));
767        dumpinteger(img_totalpages(idict));
768        dumpinteger(img_colorspace(idict));
769
770        /* the |image_struct| is not dumped at all, except for a few
771           variables that are needed to restore the contents */
772
773        if (img_type(idict) == IMG_TYPE_PDF) {
774            dumpinteger(img_pagebox(idict));
775            dumpinteger(img_pagenum(idict));
776        } else if (img_type(idict) == IMG_TYPE_JBIG2) {
777            dumpinteger(img_pagenum(idict));
778        }
779
780    }
781}
782
783@ @c
784void undumpimagemeta(PDF pdf, int pdfversion, int pdfinclusionerrorlevel)
785{
786    int cur_index, i;
787    image_dict *idict;
788
789    assert(pdf != NULL);
790    undumpinteger(i);
791    idict_limit = (size_t) i;
792
793    idict_array = xtalloc(idict_limit, idict_entry);
794    undumpinteger(cur_index);
795    idict_ptr = idict_array + cur_index;
796
797    for (i = 1; i < cur_index; i++) {
798        idict = new_image_dict();
799        assert(idict != NULL);
800        assert(img_index(idict) == -1);
801        idict_to_array(idict);
802        undumpcharptr(img_filename(idict));
803        undumpinteger(img_type(idict));
804        undumpinteger(img_procset(idict));
805        undumpinteger(img_xsize(idict));
806        undumpinteger(img_ysize(idict));
807        undumpinteger(img_xres(idict));
808        undumpinteger(img_yres(idict));
809        undumpinteger(img_totalpages(idict));
810        undumpinteger(img_colorspace(idict));
811
812        switch (img_type(idict)) {
813        case IMG_TYPE_PDF:
814            undumpinteger(img_pagebox(idict));
815            undumpinteger(img_pagenum(idict));
816            break;
817        case IMG_TYPE_PNG:
818        case IMG_TYPE_JPG:
819        case IMG_TYPE_JP2:
820            break;
821        case IMG_TYPE_JBIG2:
822            if (pdfversion < 4) {
823                luatex_fail
824                    ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i",
825                     (int) pdfversion);
826            }
827            undumpinteger(img_pagenum(idict));
828            break;
829        default:
830            luatex_fail("unknown type of image");
831        }
832        read_img(pdf, idict, pdfversion, pdfinclusionerrorlevel);
833    }
834}
835
836@ scan rule spec to |alt_rule|
837@c
838scaled_whd scan_alt_rule(void)
839{
840    boolean loop;
841    scaled_whd alt_rule;
842    alt_rule.wd = null_flag;
843    alt_rule.ht = null_flag;
844    alt_rule.dp = null_flag;
845    do {
846        loop = false;
847        if (scan_keyword("width")) {
848            scan_normal_dimen();
849            alt_rule.wd = cur_val;
850            loop = true;
851        } else if (scan_keyword("height")) {
852            scan_normal_dimen();
853            alt_rule.ht = cur_val;
854            loop = true;
855        } else if (scan_keyword("depth")) {
856            scan_normal_dimen();
857            alt_rule.dp = cur_val;
858            loop = true;
859        }
860    } while (loop);
861    return alt_rule;
862}
863
864@ copy file of arbitrary size to PDF buffer and flush as needed
865@c
866size_t read_file_to_buf(PDF pdf, FILE * f, size_t len)
867{
868    size_t i, j, k = 0;
869    while (len > 0) {
870        i = (size_t) (len > pdf->buf->size) ? (size_t) pdf->buf->size : len;
871        pdf_room(pdf, (int) i);
872        j = fread(pdf->buf->p, 1, i, f);
873        pdf->buf->p += j;
874        k += j;
875        len -= j;
876        if (i != j)
877            break;
878    }
879    return k;
880}
881