fix getsup (HH)
[luatex.git] / source / texk / web2c / luatexdir / image / writeimg.w
blob0944509c044495ab21240f6e51f6ea55d353b717
1 % writeimg.w
3 % Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
4 % Copyright 2006-2012 Taco Hoekwater <taco@@luatex.org>
6 % This file is part of LuaTeX.
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.
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.
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/>.
21 @* Image inclusion.
23 @ @c
24 #include "ptexlib.h"
25 #include <kpathsea/c-auto.h>
26 #include <kpathsea/c-memstr.h>
28 @ @c
29 #include "image/image.h"
30 #include "image/writejpg.h"
31 #include "image/writejp2.h"
32 #include "image/writepng.h"
33 #include "image/writejbig2.h"
35 #include "lua.h" /* for |LUA_NOREF| */
36 #include "lauxlib.h"
38 @* Patch ImageTypeDetection 2003/02/08 by Heiko Oberdiek.
40 Function |readimage| performs some basic initializations. Then it looks at the
41 file extension to determine the image type and calls specific code/functions. The
42 main disadvantage is that standard file extensions have to be used, otherwise
43 pdfTeX is not able to detect the correct image type. The patch now looks at the
44 file header first regardless of the file extension. This is implemented in
45 function |check_type_by_header|. If this check fails, the traditional test of
46 standard file extension is tried, done in function |check_type_by_extension|.
48 Magic headers:
50 * "PNG (Portable Network Graphics) Specification", Version 1.2
51 (http://www.libpng.org/pub/png):
53 3.1. PNG file signature
55 The first eight bytes of a PNG file always contain the following
56 (decimal) values: 137 80 78 71 13 10 26 10
58 Translation to C: |"\x89PNG\r\n\x1A\n"|
60 * "JPEG File Interchange Format", Version 1.02:
62 * you can identify a JFIF file by looking for the following sequence:
63 X'FF', SOI X'FF', APP0, <2 bytes to be skipped>, "JFIF", X'00'.
65 Function |check_type_by_header| only looks at the first two bytes: |"\xFF\xD8"|
67 * ISO/IEC JTC 1/SC 29/WG 1
68 (ITU-T SG8)
69 Coding of Still Pictures
70 Title: 14492 FCD
71 Source: JBIG Committee
72 Project: JTC 1.29.10
73 Status: Final Committee Draft
75 D.4.1, ID string
77 This is an 8-byte sequence containing 0x97 0x4A 0x42 0x32 0x0D 0x0A 0x1A 0x0A.
79 * "PDF Reference", third edition:
81 * The first line should contain \%PDF-1.0 -- \%PDF-1.4 (section 3.4.1 "File Header").
82 * The "implementation notes" say:
84 3.4.1, File Header
85 12. Acrobat viewers require only that the header appear somewhere within the
86 first 1024 bytes of the file.
87 13. Acrobat viewers will also accept a header of the form \%!PS-Adobe-N.n PDF-M.m
89 The check in function |check_type_by_header| only implements the first issue. The
90 implementation notes are not considered. Therefore files with garbage at start of
91 file must have the standard extension.
93 Functions |check_type_by_header| and |check_type_by_extension|: |img_type(img)|
94 is set to |IMG_TYPE_NONE| by |new_image_dict()|. Both functions try to detect a
95 type and set |img_type(img)|. Thus a value other than |IMG_TYPE_NONE| indicates
96 that a type has been found.
99 #define HEADER_JPG "\xFF\xD8"
100 #define HEADER_PNG "\x89PNG\r\n\x1A\n"
101 #define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A"
102 #define HEADER_JP2 "\x6A\x50\x20\x20"
103 #define HEADER_PDF "%PDF-1."
104 #define MAX_HEADER (sizeof(HEADER_PNG)-1)
105 #define HEADER_PDF_MEMSTREAM "data:application/pdf," /* see epdf.h */
106 #define LEN_PDF_MEMSTREAM 21 /* see epdf.h */
108 static void check_type_by_header(image_dict * idict)
110 int i;
111 FILE *file = NULL;
112 char header[MAX_HEADER];
113 char prefix[LEN_PDF_MEMSTREAM+1];
114 if (idict == NULL)
115 return;
116 if (img_type(idict) != IMG_TYPE_NONE)
117 return;
118 /* here we read the and also check for a memstream object */
119 if (!img_filepath(idict) || !FOPEN_RBIN_MODE) {
120 normal_error("pdf backend","reading image file failed");
122 file = fopen(img_filepath(idict), FOPEN_RBIN_MODE);
123 if (file == NULL) {
124 /* check the prefix of img_filepath(idict) */
125 for (i = 0; (unsigned) i < LEN_PDF_MEMSTREAM; i++) {
126 prefix[i] = (char) (img_filepath(idict)[i]);
128 prefix[LEN_PDF_MEMSTREAM]='\0';
129 if (strncmp(prefix, HEADER_PDF_MEMSTREAM, LEN_PDF_MEMSTREAM) == 0) {
130 img_type(idict) = IMG_TYPE_PDFMEMSTREAM;
131 return;
132 } else {
133 formatted_error("pdf backend","reading image file '%s' failed",img_filepath(idict));
136 /* a valid file, but perhaps unsupported */
137 for (i = 0; (unsigned) i < MAX_HEADER; i++) {
138 header[i] = (char) xgetc(file);
139 if (feof(file)) {
140 normal_error("pdf backend","reading image file failed");
143 xfclose(file, img_filepath(idict));
144 /* tests */
145 if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0)
146 img_type(idict) = IMG_TYPE_JPG;
147 else if (strncmp(header + 4, HEADER_JP2, sizeof(HEADER_JP2) - 1) == 0)
148 img_type(idict) = IMG_TYPE_JP2;
149 else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0)
150 img_type(idict) = IMG_TYPE_PNG;
151 else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0)
152 img_type(idict) = IMG_TYPE_JBIG2;
153 else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF) - 1) == 0)
154 img_type(idict) = IMG_TYPE_PDF;
157 @ @c
158 static void check_type_by_extension(image_dict * idict)
160 char *image_suffix;
161 if (idict != NULL)
162 return;
163 if (img_type(idict) != IMG_TYPE_NONE) /* nothing to do */
164 return;
165 /* tests */
166 if ((image_suffix = strrchr(img_filename(idict), '.')) == 0)
167 img_type(idict) = IMG_TYPE_NONE;
168 else if (strcasecmp(image_suffix, ".png") == 0)
169 img_type(idict) = IMG_TYPE_PNG;
170 else if (strcasecmp(image_suffix, ".jpg") == 0 ||
171 strcasecmp(image_suffix, ".jpeg") == 0)
172 img_type(idict) = IMG_TYPE_JPG;
173 else if (strcasecmp(image_suffix, ".jp2") == 0)
174 img_type(idict) = IMG_TYPE_JP2;
175 else if (strcasecmp(image_suffix, ".jbig2") == 0 ||
176 strcasecmp(image_suffix, ".jb2") == 0)
177 img_type(idict) = IMG_TYPE_JBIG2;
178 else if (strcasecmp(image_suffix, ".pdf") == 0)
179 img_type(idict) = IMG_TYPE_PDF;
182 @ @c
183 void new_img_pdfstream_struct(image_dict * p)
185 img_pdfstream_ptr(p) = xtalloc(1, pdf_stream_struct);
186 img_pdfstream_stream(p) = NULL;
189 @ @c
190 image *new_image(void)
192 image *p = xtalloc(1, image);
193 set_wd_running(p);
194 set_ht_running(p);
195 set_dp_running(p);
196 img_transform(p) = 0;
197 img_dict(p) = NULL;
198 img_dictref(p) = LUA_NOREF;
199 return p;
202 @ @c
203 image_dict *new_image_dict(void)
205 image_dict *p = xtalloc(1, image_dict);
206 memset(p, 0, sizeof(image_dict));
207 set_wd_running(p);
208 set_ht_running(p);
209 set_dp_running(p);
210 img_transform(p) = 0;
211 img_pagenum(p) = 1;
212 img_type(p) = IMG_TYPE_NONE;
213 img_pagebox(p) = PDF_BOX_SPEC_MEDIA;
214 img_unset_bbox(p);
215 img_unset_group(p);
216 img_state(p) = DICT_NEW;
217 img_index(p) = -1; /* -1 = unused, used count from 0 */
218 img_luaref(p) = 0;
219 img_errorlevel(p) = pdf_inclusion_errorlevel;
220 fix_pdf_minorversion(static_pdf);
221 img_pdfminorversion(p) = pdf_minor_version;
222 return p;
225 @ @c
226 static void free_dict_strings(image_dict * p)
228 xfree(img_filename(p));
229 xfree(img_filepath(p));
230 xfree(img_attr(p));
231 xfree(img_pagename(p));
234 @ @c
235 void free_image_dict(image_dict * p)
237 if (ini_version)
238 return; /* The image may be \.{\\dump}ed to a format */
239 /* called from limglib.c */
240 switch (img_type(p)) {
241 case IMG_TYPE_PDFMEMSTREAM:
242 case IMG_TYPE_PDF:
243 flush_pdf_info(p);
244 break;
245 case IMG_TYPE_PNG:
246 flush_png_info(p);
247 break;
248 case IMG_TYPE_JPG:
249 flush_jpg_info(p);
250 break;
251 case IMG_TYPE_JP2:
252 flush_jp2_info(p);
253 break;
254 case IMG_TYPE_JBIG2:
255 flush_jbig2_info(p);
256 break;
257 case IMG_TYPE_PDFSTREAM:
258 /* flush_pdfstream_info(p); */
259 if (img_pdfstream_ptr(p) != NULL) {
260 xfree(img_pdfstream_stream(p));
261 xfree(img_pdfstream_ptr(p));
263 break;
264 case IMG_TYPE_NONE:
265 break;
266 default:
267 normal_error("pdf backend","unknown image type");
269 free_dict_strings(p);
270 xfree(p);
273 @ @c
274 void read_img(image_dict * idict)
276 char *filepath = NULL;
277 int callback_id;
278 if (img_filename(idict) == NULL) {
279 normal_error("pdf backend","image file name missing");
281 callback_id = callback_defined(find_image_file_callback);
282 if (img_filepath(idict) == NULL) {
283 if (callback_id > 0) {
284 /* we always callback, also for a mem stream */
285 if (run_callback(callback_id, "S->S", img_filename(idict),&filepath)) {
286 if (filepath && (strlen(filepath) > 0)) {
287 img_filepath(idict) = strdup(filepath);
291 if (img_filepath(idict) == NULL && (strstr(img_filename(idict),"data:application/pdf,") != NULL)) {
292 /* we need to check here for a pdf memstream */
293 img_filepath(idict) = strdup(img_filename(idict));
294 } else if (callback_id == 0) {
295 /* otherwise we use kpse but only when we don't callback */
296 img_filepath(idict) = kpse_find_file(img_filename(idict), kpse_tex_format, true);
298 if (img_filepath(idict) == NULL) {
299 /* in any case we need a name */
300 formatted_error("pdf backend","cannot find image file '%s'", img_filename(idict));
303 recorder_record_input(img_filename(idict));
304 /* type checks */
305 check_type_by_header(idict);
306 check_type_by_extension(idict);
307 /* read image */
308 switch (img_type(idict)) {
309 case IMG_TYPE_PDFMEMSTREAM:
310 case IMG_TYPE_PDF:
311 read_pdf_info(idict);
312 break;
313 case IMG_TYPE_PNG:
314 read_png_info(idict);
315 break;
316 case IMG_TYPE_JPG:
317 read_jpg_info(idict);
318 break;
319 case IMG_TYPE_JP2:
320 read_jp2_info(idict);
321 break;
322 case IMG_TYPE_JBIG2:
323 read_jbig2_info(idict);
324 break;
325 default:
326 img_type(idict) = IMG_TYPE_NONE;
327 if (pdf_ignore_unknown_images) {
328 normal_warning("pdf backend","internal error: ignoring unknown image type");
329 } else {
330 normal_error("pdf backend","internal error: unknown image type");
332 break;
334 cur_file_name = NULL;
335 if (img_type(idict) == IMG_TYPE_NONE) {
336 img_state(idict) = DICT_NEW;
337 } else if (img_state(idict) < DICT_FILESCANNED) {
338 img_state(idict) = DICT_FILESCANNED;
342 @ @c
343 static image_dict *read_image(char *file_name, int page_num, char *page_name, int colorspace, int page_box)
345 image *a = new_image();
346 image_dict *idict = img_dict(a) = new_image_dict();
347 static_pdf->ximage_count++;
348 img_objnum(idict) = pdf_create_obj(static_pdf, obj_type_ximage, static_pdf->ximage_count);
349 img_index(idict) = static_pdf->ximage_count;
350 set_obj_data_ptr(static_pdf, img_objnum(idict), img_index(idict));
351 idict_to_array(idict);
352 img_colorspace(idict) = colorspace;
353 img_pagenum(idict) = page_num;
354 img_pagename(idict) = page_name;
355 if (file_name == NULL) {
356 normal_error("pdf backend","no image filename given");
358 cur_file_name = file_name;
359 img_filename(idict) = file_name;
360 img_pagebox(idict) = page_box;
361 read_img(idict);
362 return idict;
365 @ scans PDF pagebox specification
367 static pdfboxspec_e scan_pdf_box_spec(void)
369 if (scan_keyword("mediabox"))
370 return PDF_BOX_SPEC_MEDIA;
371 else if (scan_keyword("cropbox"))
372 return PDF_BOX_SPEC_CROP;
373 else if (scan_keyword("bleedbox"))
374 return PDF_BOX_SPEC_BLEED;
375 else if (scan_keyword("trimbox"))
376 return PDF_BOX_SPEC_TRIM;
377 else if (scan_keyword("artbox"))
378 return PDF_BOX_SPEC_ART;
379 else
380 return PDF_BOX_SPEC_NONE;
383 @ @c
384 void scan_pdfximage(PDF pdf) /* static_pdf */
386 scaled_whd alt_rule;
387 image_dict *idict;
388 int transform = 0, page = 1, pagebox, colorspace = 0;
389 char *named = NULL, *attr = NULL, *file_name = NULL;
390 alt_rule = scan_alt_rule(); /* scans |<rule spec>| to |alt_rule| */
391 if (scan_keyword("attr")) {
392 scan_toks(false, true);
393 attr = tokenlist_to_cstring(def_ref, true, NULL);
394 delete_token_ref(def_ref);
396 if (scan_keyword("named")) {
397 scan_toks(false, true);
398 named = tokenlist_to_cstring(def_ref, true, NULL);
399 delete_token_ref(def_ref);
400 page = 0;
401 } else if (scan_keyword("page")) {
402 scan_int();
403 page = cur_val;
405 if (scan_keyword("colorspace")) {
406 scan_int();
407 colorspace = cur_val;
409 pagebox = scan_pdf_box_spec();
410 if (pagebox == PDF_BOX_SPEC_NONE) {
411 pagebox = pdf_pagebox;
412 if (pagebox == PDF_BOX_SPEC_NONE)
413 pagebox = PDF_BOX_SPEC_CROP;
415 scan_toks(false, true);
416 file_name = tokenlist_to_cstring(def_ref, true, NULL);
417 if (file_name == NULL) {
418 normal_error("pdf backend","no image filename given");
420 delete_token_ref(def_ref);
421 idict = read_image(file_name, page, named, colorspace, pagebox);
422 img_attr(idict) = attr;
423 img_dimen(idict) = alt_rule;
424 img_transform(idict) = transform;
425 last_saved_image_index = img_objnum(idict);
426 last_saved_image_pages = img_totalpages(idict);
429 @ @c
430 void scan_pdfrefximage(PDF pdf)
432 int transform = 0; /* one could scan transform as well */
433 image_dict *idict;
434 scaled_whd alt_rule, dim;
435 alt_rule = scan_alt_rule(); /* scans |<rule spec>| to |alt_rule| */
436 scan_int();
437 check_obj_type(pdf, obj_type_ximage, cur_val);
438 tail_append(new_rule(image_rule));
439 idict = idict_array[obj_data_ptr(pdf, cur_val)];
440 if (img_state(idict) == DICT_NEW) {
441 normal_warning("image","don't rely on the image data to be okay");
442 width(tail_par) = 0;
443 height(tail_par) = 0;
444 depth(tail_par) = 0;
445 } else {
446 if (alt_rule.wd != null_flag || alt_rule.ht != null_flag || alt_rule.dp != null_flag) {
447 dim = scale_img(idict, alt_rule, transform);
448 } else {
449 dim = scale_img(idict, img_dimen(idict), img_transform(idict));
451 width(tail_par) = dim.wd;
452 height(tail_par) = dim.ht;
453 depth(tail_par) = dim.dp;
454 rule_transform(tail_par) = transform;
455 rule_index(tail_par) = img_index(idict);
459 @ |tex_scale()| sequence of decisions:
461 {\obeylines\obeyspaces\tt
462 wd ht dp : res = tex;
463 wd ht --
464 wd -- dp
465 wd -- --
466 -- ht dp
467 -- ht --
468 -- -- dp
469 -- -- -- : res = nat;
473 scaled_whd tex_scale(scaled_whd nat, scaled_whd tex)
475 scaled_whd res;
476 if (!is_running(tex.wd) && !is_running(tex.ht) && !is_running(tex.dp)) {
477 /* width, height, and depth specified */
478 res = tex;
479 } else /* max. 2 dimensions are specified */ if (!is_running(tex.wd)) {
480 res.wd = tex.wd;
481 if (!is_running(tex.ht)) {
482 res.ht = tex.ht;
483 /* width and height specified */
484 res.dp = ext_xn_over_d(tex.ht, nat.dp, nat.ht);
485 } else if (!is_running(tex.dp)) {
486 res.dp = tex.dp;
487 /* width and depth specified */
488 res.ht = ext_xn_over_d(tex.wd, nat.ht + nat.dp, nat.wd) - tex.dp;
489 } else {
490 /* only width specified */
491 res.ht = ext_xn_over_d(tex.wd, nat.ht, nat.wd);
492 res.dp = ext_xn_over_d(tex.wd, nat.dp, nat.wd);
494 } else if (!is_running(tex.ht)) {
495 res.ht = tex.ht;
496 if (!is_running(tex.dp)) {
497 res.dp = tex.dp;
498 /* height and depth specified */
499 res.wd = ext_xn_over_d(tex.ht + tex.dp, nat.wd, nat.ht + nat.dp);
500 } else {
501 /* only height specified */
502 res.wd = ext_xn_over_d(tex.ht, nat.wd, nat.ht);
503 res.dp = ext_xn_over_d(tex.ht, nat.dp, nat.ht);
505 } else if (!is_running(tex.dp)) {
506 res.dp = tex.dp;
507 /* only depth specified */
508 res.ht = nat.ht - (tex.dp - nat.dp);
509 res.wd = nat.wd;
510 } else {
511 /* nothing specified */
512 res = nat;
514 return res;
517 @ Within |scale_img()| only image width and height matter;
518 the offsets and positioning are not interesting here.
519 But one needs rotation info to swap width and height.
520 |img_rotation()| comes from the optional /Rotate key in the PDF file.
523 scaled_whd scale_img(image_dict * idict, scaled_whd alt_rule, int transform)
525 int x, y, xr, yr, tmp; /* size and resolution of image */
526 scaled_whd nat; /* natural size corresponding to image resolution */
527 int default_res;
528 if ((img_type(idict) == IMG_TYPE_PDF || img_type(idict) == IMG_TYPE_PDFMEMSTREAM
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);
538 xr = img_xres(idict);
539 yr = img_yres(idict);
540 if (x <= 0 || y <= 0 || xr < 0 || yr < 0)
541 normal_error("pdf backend","invalid image dimensions");
542 if (xr > 65535 || yr > 65535) {
543 xr = 0;
544 yr = 0;
545 normal_warning("pdf backend","too large image resolution ignored");
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;
555 nat.dp = 0; /* always for images */
556 if (img_type(idict) == IMG_TYPE_PDF || img_type(idict) == IMG_TYPE_PDFMEMSTREAM
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;
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);
574 return tex_scale(nat, alt_rule);
577 @ @c
578 void write_img(PDF pdf, image_dict * idict)
580 if (img_state(idict) < DICT_WRITTEN) {
581 report_start_file(filetype_image, img_filepath(idict));
582 switch (img_type(idict)) {
583 case IMG_TYPE_PNG:
584 write_png(pdf, idict);
585 break;
586 case IMG_TYPE_JPG:
587 write_jpg(pdf, idict);
588 break;
589 case IMG_TYPE_JP2:
590 write_jp2(pdf, idict);
591 break;
592 case IMG_TYPE_JBIG2:
593 write_jbig2(pdf, idict);
594 break;
595 case IMG_TYPE_PDFMEMSTREAM:
596 case IMG_TYPE_PDF:
597 write_epdf(pdf, idict,(int) pdf_suppress_optional_info);
598 break;
599 case IMG_TYPE_PDFSTREAM:
600 write_pdfstream(pdf, idict);
601 break;
602 default:
603 normal_error("pdf backend","internal error: writing unknown image type");
605 report_stop_file(filetype_image);
606 if (img_type(idict) == IMG_TYPE_PNG) {
607 write_additional_png_objects(pdf);
610 if (img_state(idict) < DICT_WRITTEN)
611 img_state(idict) = DICT_WRITTEN;
614 @ write an image
616 void pdf_write_image(PDF pdf, int n)
618 if (pdf->draftmode == 0)
619 write_img(pdf, idict_array[obj_data_ptr(pdf, n)]);
622 @ @c
623 void check_pdfstream_dict(image_dict * idict)
625 if (!img_is_bbox(idict))
626 normal_error("pdf backend","image.stream: no bbox given");
627 if (img_state(idict) < DICT_FILESCANNED)
628 img_state(idict) = DICT_FILESCANNED;
631 @ @c
632 void write_pdfstream(PDF pdf, image_dict * idict)
634 pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER);
635 pdf_begin_dict(pdf);
636 pdf_dict_add_name(pdf, "Type", "XObject");
637 pdf_dict_add_name(pdf, "Subtype", "Form");
638 if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
639 pdf_printf(pdf, "\n%s\n", img_attr(idict));
640 pdf_dict_add_int(pdf, "FormType", 1);
641 pdf_add_name(pdf, "BBox");
642 pdf_begin_array(pdf);
643 copyReal(pdf, sp2bp(img_bbox(idict)[0]));
644 copyReal(pdf, sp2bp(img_bbox(idict)[1]));
645 copyReal(pdf, sp2bp(img_bbox(idict)[2]));
646 copyReal(pdf, sp2bp(img_bbox(idict)[3]));
647 pdf_end_array(pdf);
648 pdf_dict_add_streaminfo(pdf);
649 pdf_end_dict(pdf);
650 pdf_begin_stream(pdf);
651 if (img_pdfstream_stream(idict) != NULL)
652 pdf_puts(pdf, img_pdfstream_stream(idict));
653 pdf_end_stream(pdf);
654 pdf_end_obj(pdf);
657 @ @c
658 idict_entry *idict_ptr, *idict_array = NULL;
659 size_t idict_limit;
661 void idict_to_array(image_dict * idict)
663 if (idict_ptr - idict_array == 0) { /* align to count from 1 */
664 alloc_array(idict, 1, SMALL_BUF_SIZE); /* /Im0 unused */
665 idict_ptr++;
667 alloc_array(idict, 1, SMALL_BUF_SIZE);
668 *idict_ptr = idict;
669 idict_ptr++;
672 void pdf_dict_add_img_filename(PDF pdf, image_dict * idict)
674 char *p;
675 if ((pdf_image_addfilename > 0) && ((pdf_suppress_optional_info & 2) == 0)) {
676 /* for now PTEX.FileName only for PDF, but prepared for JPG, PNG, ... */
677 if (! ( (img_type(idict) == IMG_TYPE_PDF) || (img_type(idict) == IMG_TYPE_PDFMEMSTREAM) ))
678 return;
679 if (img_visiblefilename(idict) != NULL) {
680 if (strlen(img_visiblefilename(idict)) == 0) {
681 return; /* empty string blocks PTEX.FileName output */
682 } else {
683 p = img_visiblefilename(idict);
685 } else {
686 /* unset so let's use the default */
687 p = img_filepath(idict);
689 // write additional information
690 pdf_add_name(pdf, "PTEX.FileName");
691 pdf_printf(pdf, " (%s)", convertStringToPDFString(p, strlen(p)));
695 /* hh: why store images in the format ... let's get rid of this */
697 @ To allow the use of box resources inside saved boxes in -ini mode,
698 the information in the array has to be (un)dumped with the format.
699 The next two routines take care of that.
701 Most of the work involved in setting up the images is simply
702 executed again. This solves the many possible errors resulting from
703 the split in two separate runs.
705 There was only one problem remaining: The pdfversion and
706 pdfinclusionerrorlevel can have changed inbetween the call to
707 |readimage()| and dump time.
709 some of the dumped values are really type int, not integer,
710 but since the macro falls back to |generic_dump| anyway, that
711 does not matter.
714 #define dumpinteger generic_dump
715 #define undumpinteger generic_undump
717 @ (un)dumping a string means dumping the allocation size, followed
718 by the bytes. The trailing \.{\\0} is dumped as well, because that
719 makes the code simpler.
721 @ scan rule spec to |alt_rule|
723 scaled_whd scan_alt_rule(void)
725 boolean loop;
726 scaled_whd alt_rule;
727 alt_rule.wd = null_flag;
728 alt_rule.ht = null_flag;
729 alt_rule.dp = null_flag;
730 do {
731 loop = false;
732 if (scan_keyword("width")) {
733 scan_normal_dimen();
734 alt_rule.wd = cur_val;
735 loop = true;
736 } else if (scan_keyword("height")) {
737 scan_normal_dimen();
738 alt_rule.ht = cur_val;
739 loop = true;
740 } else if (scan_keyword("depth")) {
741 scan_normal_dimen();
742 alt_rule.dp = cur_val;
743 loop = true;
745 } while (loop);
746 return alt_rule;
749 @ copy file of arbitrary size to PDF buffer and flush as needed
751 size_t read_file_to_buf(PDF pdf, FILE * f, size_t len)
753 size_t i, j, k = 0;
754 while (len > 0) {
755 i = (size_t) (len > pdf->buf->size) ? (size_t) pdf->buf->size : len;
756 pdf_room(pdf, (int) i);
757 j = fread(pdf->buf->p, 1, i, f);
758 pdf->buf->p += j;
759 k += j;
760 len -= j;
761 if (i != j)
762 break;
764 return k;