1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gdevpdfb.c 8611 2008-03-27 08:37:58Z ken $ */
15
/* Low-level bitmap image handling for PDF-writing driver */
21
#include "gdevpdfo.h" /* for data stream */
27
/* We need this color space type for constructing temporary color spaces. */
28
extern const gs_color_space_type gs_color_space_type_Indexed;
30
/* ---------------- Utilities ---------------- */
32
/* Fill in the image parameters for a bitmap image. */
34
pdf_make_bitmap_image(gs_image_t * pim, int x, int y, int w, int h)
38
pdf_make_bitmap_matrix(&pim->ImageMatrix, x, y, w, h, h);
41
/* ---------------- Driver procedures ---------------- */
43
/* Copy a mask bitmap. for_pattern = -1 means put the image in-line, */
44
/* 1 means put the image in a resource. */
46
pdf_copy_mask_data(gx_device_pdf * pdev, const byte * base, int sourcex,
47
int raster, gx_bitmap_id id, int x, int y, int w, int h,
48
gs_image_t *pim, pdf_image_writer *piw,
57
gs_image_t_init_mask(pim, true);
58
pdf_make_bitmap_image(pim, x, y, w, h);
59
nbytes = ((ulong)w * h + 7) / 8;
63
* Patterns must be emitted in order of increasing user Y, i.e.,
64
* the opposite of PDF's standard image order.
66
row_base = base + (h - 1) * raster;
68
in_line = for_pattern < 0;
72
in_line = nbytes < pdev->MaxInlineImageSize;
73
pdf_put_image_matrix(pdev, &pim->ImageMatrix, 1.0);
75
* Check whether we've already made an XObject resource for this
78
if (id != gx_no_bitmap_id) {
79
piw->pres = pdf_find_resource_by_gs_id(pdev, resourceXObject, id);
85
* We have to be able to control whether to put Pattern images in line,
86
* to avoid trying to create an XObject resource while we're in the
87
* middle of writing a Pattern resource.
90
stream_puts(pdev->strm, "q ");
91
pdf_image_writer_init(piw);
92
pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
93
if ((code = pdf_begin_write_image(pdev, piw, id, w, h, NULL, in_line)) < 0 ||
94
(code = psdf_setup_lossless_filters((gx_device_psdf *) pdev,
96
(gs_pixel_image_t *)pim, in_line)) < 0 ||
97
(code = pdf_begin_image_data(pdev, piw, (const gs_pixel_image_t *)pim,
101
pdf_copy_mask_bits(piw->binary[0].strm, row_base, sourcex, row_step, w, h, 0);
102
pdf_end_image_binary(pdev, piw, piw->height);
103
return pdf_end_write_image(pdev, piw);
107
set_image_color(gx_device_pdf *pdev, gx_color_index c)
109
pdf_set_pure_color(pdev, c, &pdev->saved_fill_color,
110
&pdev->fill_used_process_color,
111
&psdf_set_fill_color_commands);
112
if (!pdev->HaveStrokeColor)
113
pdf_set_pure_color(pdev, c, &pdev->saved_stroke_color,
114
&pdev->stroke_used_process_color,
115
&psdf_set_stroke_color_commands);
118
/* Copy a monochrome bitmap or mask. */
120
pdf_copy_mono(gx_device_pdf *pdev,
121
const byte *base, int sourcex, int raster, gx_bitmap_id id,
122
int x, int y, int w, int h, gx_color_index zero,
123
gx_color_index one, const gx_clip_path *pcpath)
126
gs_color_space *pcs = NULL;
127
cos_value_t cs_value;
128
cos_value_t *pcsvalue;
129
byte palette[arch_sizeof_color_index * 2];
131
pdf_image_writer writer;
132
pdf_stream_position_t ipos;
133
pdf_resource_t *pres = 0;
135
bool in_line = false;
137
/* Update clipping. */
138
if (pdf_must_put_clip_path(pdev, pcpath)) {
139
code = pdf_open_page(pdev, PDF_IN_STREAM);
142
code = pdf_put_clip_path(pdev, pcpath);
146
/* We have 3 cases: mask, inverse mask, and solid. */
147
if (zero == gx_no_color_index) {
148
if (one == gx_no_color_index)
150
/* If a mask has an id, assume it's a character. */
151
if (id != gx_no_bitmap_id && sourcex == 0) {
152
pres = pdf_find_resource_by_gs_id(pdev, resourceCharProc, id);
153
if (pres == 0) { /* Define the character in an embedded font. */
154
pdf_char_proc_t *pcp;
158
gs_image_t_init_mask(&image, false);
160
pdf_make_bitmap_image(&image, x, y, w, h);
161
y_offset = pdf_char_image_y_offset(pdev, x, y, h);
163
* The Y axis of the text matrix is inverted,
164
* so we need to negate the Y offset appropriately.
166
code = pdf_begin_char_proc(pdev, w, h, 0, y_offset, id,
170
y_offset = -y_offset;
171
x_offset = psdf_round(pdev->char_width.x, 100, 10); /* See
172
pdf_write_Widths about rounding. We need to provide
173
a compatible data for Tj. */
174
pprintg1(pdev->strm, "%g ", x_offset);
175
pprintd3(pdev->strm, "0 0 %d %d %d d1\n", y_offset, w, h + y_offset);
176
pprintd3(pdev->strm, "%d 0 0 %d 0 %d cm\n", w, h,
178
pdf_image_writer_init(&writer);
179
code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, true);
182
pres = (pdf_resource_t *) pcp;
184
} else if (pdev->pte) {
185
/* We're under pdf_text_process. It set a high level color. */
187
set_image_color(pdev, one);
188
pdf_make_bitmap_matrix(&image.ImageMatrix, x, y, w, h, h);
191
set_image_color(pdev, one);
192
gs_image_t_init_mask(&image, false);
194
} else if (one == gx_no_color_index) {
195
gs_image_t_init_mask(&image, false);
196
set_image_color(pdev, zero);
197
} else if (zero == pdev->black && one == pdev->white) {
198
pcs = gs_cspace_new_DeviceGray(pdev->memory);
199
gs_image_t_init(&image, pcs);
200
} else if (zero == pdev->white && one == pdev->black) {
201
pcs = gs_cspace_new_DeviceGray(pdev->memory);
202
gs_image_t_init(&image, pcs);
206
* We think this code is never executed when interpreting PostScript
207
* or PDF: the library never uses monobit non-mask images
208
* internally, and high-level images don't go through this code.
209
* However, we still want the code to work.
211
gs_color_space *pcs_base;
214
int ncomp = pdev->color_info.num_components;
217
code = pdf_cspace_init_Device(pdev->memory, &pcs_base, ncomp);
220
c[0] = psdf_adjust_color_index((gx_device_vector *)pdev, zero);
221
c[1] = psdf_adjust_color_index((gx_device_vector *)pdev, one);
222
pcs = gs_cspace_alloc(pdev->memory, &gs_color_space_type_Indexed);
224
rc_decrement(pcs_base, "pdf_copy_mono");
225
return_error(gs_error_VMerror);
227
pcs->base_space = pcs_base;
228
pcs->params.indexed.hival = 1;
229
pcs->params.indexed.n_comps = ncomp;
231
for (i = 0; i < 2; ++i)
232
for (j = ncomp - 1; j >= 0; --j)
233
*p++ = (byte)(c[i] >> (j * 8));
234
pcs->params.indexed.lookup.table.data = palette;
235
pcs->params.indexed.lookup.table.size = p - palette;
236
pcs->params.indexed.use_proc = false;
237
gs_image_t_init(&image, pcs);
238
image.BitsPerComponent = 1;
240
pdf_make_bitmap_image(&image, x, y, w, h);
242
ulong nbytes = (ulong) ((w + 7) >> 3) * h;
244
in_line = nbytes < pdev->MaxInlineImageSize;
246
pdf_put_image_matrix(pdev, &image.ImageMatrix, 1.0);
247
code = pdf_open_page(pdev, PDF_IN_STREAM);
250
pdf_image_writer_init(&writer);
251
code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, in_line);
260
* We don't have to worry about color space scaling: the color
261
* space is always a Device space.
263
code = pdf_color_space(pdev, &cs_value, NULL, pcs,
264
&writer.pin->color_spaces, in_line);
267
pcsvalue = &cs_value;
270
* There are 3 different cases at this point:
271
* - Writing an in-line image (pres == 0, writer.pres == 0);
272
* - Writing an XObject image (pres == 0, writer.pres != 0);
273
* - Writing the image for a CharProc (pres != 0).
274
* We handle them with in-line code followed by a switch,
275
* rather than making the shared code into a procedure,
276
* simply because there would be an awful lot of parameters
277
* that would need to be passed.
281
* Always use CCITTFax 2-D for character bitmaps. It takes less
282
* space to invert the data with Decode than to set BlackIs1.
284
float d0 = image.Decode[0];
286
image.Decode[0] = image.Decode[1];
287
image.Decode[1] = d0;
288
psdf_CFE_binary(&writer.binary[0], image.Width, image.Height, true);
291
/* Use the Distiller compression parameters. */
292
pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
293
psdf_setup_image_filters((gx_device_psdf *) pdev, &writer.binary[0],
294
(gs_pixel_image_t *)&image, NULL, NULL, true, in_line);
296
pdf_begin_image_data(pdev, &writer, (const gs_pixel_image_t *)&image,
298
code = pdf_copy_mask_bits(writer.binary[0].strm, base, sourcex, raster,
302
pdf_end_image_binary(pdev, &writer, writer.height);
304
switch ((code = pdf_end_write_image(pdev, &writer))) {
310
return pdf_do_image(pdev, writer.pres, &image.ImageMatrix,
314
writer.end_string = ""; /* no Q */
315
switch ((code = pdf_end_write_image(pdev, &writer))) {
318
case 0: /* not possible */
319
return_error(gs_error_Fatal);
323
code = pdf_end_char_proc(pdev, &ipos);
329
imat = image.ImageMatrix;
334
return pdf_do_char_image(pdev, (const pdf_char_proc_t *)pres, &imat);
338
gdev_pdf_copy_mono(gx_device * dev,
339
const byte * base, int sourcex, int raster, gx_bitmap_id id,
340
int x, int y, int w, int h, gx_color_index zero,
343
gx_device_pdf *pdev = (gx_device_pdf *) dev;
345
if (w <= 0 || h <= 0)
347
return pdf_copy_mono(pdev, base, sourcex, raster, id, x, y, w, h,
351
/* Copy a color bitmap. for_pattern = -1 means put the image in-line, */
352
/* 1 means put the image in a resource, 2 means image is a rasterized shading. */
354
pdf_copy_color_data(gx_device_pdf * pdev, const byte * base, int sourcex,
355
int raster, gx_bitmap_id id, int x, int y, int w, int h,
356
gs_image_t *pim, pdf_image_writer *piw,
359
int depth = pdev->color_info.depth;
360
int bytes_per_pixel = depth >> 3;
362
cos_value_t cs_value;
364
int code = pdf_cspace_init_Device(pdev->memory, &pcs, bytes_per_pixel);
365
const byte *row_base;
370
return code; /* can't happen */
371
gs_image_t_init(pim, pcs);
372
pdf_make_bitmap_image(pim, x, y, w, h);
373
pim->BitsPerComponent = 8;
374
nbytes = (ulong)w * bytes_per_pixel * h;
376
if (for_pattern == 1) {
378
* Patterns must be emitted in order of increasing user Y, i.e.,
379
* the opposite of PDF's standard image order.
381
row_base = base + (h - 1) * raster;
383
in_line = for_pattern < 0;
387
in_line = nbytes < pdev->MaxInlineImageSize;
388
pdf_put_image_matrix(pdev, &pim->ImageMatrix, 1.0);
390
* Check whether we've already made an XObject resource for this
393
if (id != gx_no_bitmap_id) {
394
piw->pres = pdf_find_resource_by_gs_id(pdev, resourceXObject, id);
400
* We have to be able to control whether to put Pattern images in line,
401
* to avoid trying to create an XObject resource while we're in the
402
* middle of writing a Pattern resource.
405
stream_puts(pdev->strm, "q ");
407
* We don't have to worry about color space scaling: the color
408
* space is always a Device space.
410
pdf_image_writer_init(piw);
411
pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
412
if ((code = pdf_begin_write_image(pdev, piw, id, w, h, NULL, in_line)) < 0 ||
413
(code = pdf_color_space(pdev, &cs_value, NULL, pcs,
414
&piw->pin->color_spaces, in_line)) < 0 ||
415
(for_pattern < 2 || nbytes < 512000 ?
416
(code = psdf_setup_lossless_filters((gx_device_psdf *) pdev,
417
&piw->binary[0], (gs_pixel_image_t *)pim, false)) :
418
(code = psdf_setup_image_filters((gx_device_psdf *) pdev,
419
&piw->binary[0], (gs_pixel_image_t *)pim, NULL, NULL, false, false))
421
(code = pdf_begin_image_data(pdev, piw, (const gs_pixel_image_t *)pim,
425
pdf_copy_color_bits(piw->binary[0].strm, row_base, sourcex, row_step, w, h,
427
pdf_end_image_binary(pdev, piw, piw->height);
428
return pdf_end_write_image(pdev, piw);
432
gdev_pdf_copy_color(gx_device * dev, const byte * base, int sourcex,
433
int raster, gx_bitmap_id id, int x, int y, int w, int h)
435
gx_device_pdf *pdev = (gx_device_pdf *) dev;
437
pdf_image_writer writer;
440
if (w <= 0 || h <= 0)
442
code = pdf_open_page(pdev, PDF_IN_STREAM);
445
/* Make sure we aren't being clipped. */
446
code = pdf_put_clip_path(pdev, NULL);
449
code = pdf_copy_color_data(pdev, base, sourcex, raster, id, x, y, w, h,
453
return code; /* error */
457
return pdf_do_image(pdev, writer.pres, NULL, true);
463
gdev_pdf_fill_mask(gx_device * dev,
464
const byte * data, int data_x, int raster, gx_bitmap_id id,
465
int x, int y, int width, int height,
466
const gx_drawing_color * pdcolor, int depth,
467
gs_logical_operation_t lop, const gx_clip_path * pcpath)
469
gx_device_pdf *pdev = (gx_device_pdf *) dev;
471
if (width <= 0 || height <= 0)
473
if (depth > 1 || (!gx_dc_is_pure(pdcolor) != 0 && pdcolor->type != &gx_dc_pattern))
474
return gx_default_fill_mask(dev, data, data_x, raster, id,
475
x, y, width, height, pdcolor, depth, lop,
477
return pdf_copy_mono(pdev, data, data_x, raster, id, x, y, width, height,
478
gx_no_color_index, gx_dc_pure_color(pdcolor),
482
/* Tile with a bitmap. This is important for pattern fills. */
484
gdev_pdf_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
485
int x, int y, int w, int h,
486
gx_color_index color0, gx_color_index color1,
489
gx_device_pdf *const pdev = (gx_device_pdf *) dev;
490
int tw = tiles->rep_width, th = tiles->rep_height;
491
double xscale = pdev->HWResolution[0] / 72.0,
492
yscale = pdev->HWResolution[1] / 72.0;
495
int (*copy_data)(gx_device_pdf *, const byte *, int, int,
496
gx_bitmap_id, int, int, int, int,
497
gs_image_t *, pdf_image_writer *, int);
498
pdf_resource_t *pres;
499
cos_value_t cs_value;
502
if (tiles->id == gx_no_bitmap_id || tiles->shift != 0 ||
503
(w < tw && h < th) ||
504
color0 != gx_no_color_index
507
if (color1 != gx_no_color_index) {
508
/* This is a mask pattern. */
511
copy_data = pdf_copy_mask_data;
512
code = pdf_cs_Pattern_uncolored(pdev, &cs_value);
514
/* This is a colored pattern. */
516
depth = pdev->color_info.depth;
517
copy_data = pdf_copy_color_data;
518
code = pdf_cs_Pattern_colored(pdev, &cs_value);
522
pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, tiles->id);
524
/* Create the Pattern resource. */
526
long image_id, length_id, start, end;
529
pdf_image_writer writer;
530
long image_bytes = ((long)tw * depth + 7) / 8 * th;
531
bool in_line = image_bytes < pdev->MaxInlineImageSize;
533
(tw == tiles->size.x && th == tiles->size.y ? tiles->id :
538
else if (image_bytes > 65500) {
540
* Acrobat Reader can't handle image Patterns with more than
545
/* Write the image as an XObject resource now. */
546
code = copy_data(pdev, tiles->data, 0, tiles->raster,
547
tile_id, 0, 0, tw, th, &image, &writer, 1);
550
image_id = pdf_resource_id(writer.pres);
552
code = pdf_begin_resource(pdev, resourcePattern, tiles->id, &pres);
556
pprintd1(s, "/PatternType 1/PaintType %d/TilingType 1/Resources<<\n",
559
pprintld2(s, "/XObject<</R%ld %ld 0 R>>", image_id, image_id);
560
pprints1(s, "/ProcSet[/PDF/Image%s]>>\n", (mask ? "B" : "C"));
562
* Because of bugs in Acrobat Reader's Print function, we can't use
563
* the natural BBox and Step here: they have to be 1.
565
pprintg2(s, "/Matrix[%g 0 0 %g 0 0]", tw / xscale, th / yscale);
566
stream_puts(s, "/BBox[0 0 1 1]/XStep 1/YStep 1/Length ");
568
char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */
570
sprintf(buf, "/R%ld Do\n", image_id);
571
pprintd1(s, "%d>>stream\n", strlen(buf));
573
pprints1(s, "%s\nendstream\n", buf);
575
pprints1(s, "%sendstream\n", buf);
576
pdf_end_resource(pdev);
578
length_id = pdf_obj_ref(pdev);
579
pprintld1(s, "%ld 0 R>>stream\n", length_id);
580
start = pdf_stell(pdev);
581
code = copy_data(pdev, tiles->data, 0, tiles->raster,
582
tile_id, 0, 0, tw, th, &image, &writer, -1);
585
return code; /* error */
588
case 0: /* not possible */
589
return_error(gs_error_Fatal);
591
end = pdf_stell(pdev);
592
stream_puts(s, "\nendstream\n");
593
pdf_end_resource(pdev);
594
pdf_open_separate(pdev, length_id);
595
pprintld1(pdev->strm, "%ld\n", end - start);
596
pdf_end_separate(pdev);
598
pres->object->written = true; /* don't write at end of page */
600
/* Fill the rectangle with the Pattern. */
602
int code = pdf_open_page(pdev, PDF_IN_STREAM);
607
/* Make sure we aren't being clipped. */
608
code = pdf_put_clip_path(pdev, NULL);
613
* Because of bugs in Acrobat Reader's Print function, we can't
614
* leave the CTM alone here: we have to reset it to the default.
616
pprintg2(s, "q %g 0 0 %g 0 0 cm\n", xscale, yscale);
617
cos_value_write(&cs_value, pdev);
618
stream_puts(s, " cs");
620
pprintg3(s, " %g %g %g", (int)(color1 >> 16) / 255.0,
621
(int)((color1 >> 8) & 0xff) / 255.0,
622
(int)(color1 & 0xff) / 255.0);
623
pprintld1(s, "/R%ld scn", pdf_resource_id(pres));
624
pprintg4(s, " %g %g %g %g re f Q\n",
625
x / xscale, y / yscale, w / xscale, h / xscale);
629
return gx_default_strip_tile_rectangle(dev, tiles, x, y, w, h,
630
color0, color1, px, py);