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: gdevpsim.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* PostScript image output device */
24
* There are two drivers in this file, both of which produce PostScript
25
* output consisting of a single bitmap per page. The psmono/psgray
26
* driver produces monochrome Level 1 images using home-grown run length
27
* compression; the psrgb driver produces planar RGB Level 2 images
28
* using the RunLengthEncode filter.
31
/* ---------------- Shared code ---------------- */
33
/* Define the device parameters. */
41
/* Write the file (if necessary) and page headers. */
43
ps_image_write_headers(FILE *f, gx_device_printer *pdev,
44
const char *const setup[],
45
gx_device_pswrite_common_t *pdpc)
47
if (gdev_prn_file_is_new(pdev)) {
52
bbox.q.x = pdev->width / pdev->HWResolution[0] * 72.0;
53
bbox.q.y = pdev->height / pdev->HWResolution[1] * 72.0;
54
psw_begin_file_header(f, (gx_device *)pdev, &bbox, pdpc, false);
55
psw_print_lines(f, setup);
56
psw_end_file_header(f);
59
byte buf[100]; /* arbitrary */
62
s_init(&s, pdev->memory);
63
swrite_file(&s, f, buf, sizeof(buf));
64
psw_write_page_header(&s, (gx_device *)pdev, pdpc, true, pdev->PageCount + 1, 10);
69
/* ---------------- Level 1 monochrome driver ---------------- */
72
* This driver produces a bitmap in the form of a PostScript file that can
73
* be fed to any PostScript printer. It uses a run-length compression
74
* method that executes quickly (unlike some produced by PostScript
77
* There are two devices here, one for 1-bit black-and-white and one
78
* for 8-bit gray. In fact, the same code could also handle 2- and
82
/* The device descriptor */
83
static dev_proc_print_page(psmono_print_page);
84
static dev_proc_close_device(psmono_close);
86
const gx_device_printer gs_psmono_device =
87
prn_device(prn_std_procs, "psmono",
88
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
90
0, 0, 0, 0, /* margins */
91
1, psmono_print_page);
93
static const gx_device_procs psgray_procs =
94
prn_color_procs(gdev_prn_open, gdev_prn_output_page, psmono_close,
95
gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb);
97
const gx_device_printer gs_psgray_device = {
98
prn_device_body(gx_device_printer, psgray_procs, "psgray",
99
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
101
0, 0, 0, 0, /* margins */
102
1, 8, 255, 0, 256, 1, psmono_print_page)
105
static const char *const psmono_setup[] = {
106
/* Initialize the strings for filling runs. */
107
"/.ImageFills [ 0 1 255 {",
108
" 256 string dup 0 1 7 { 3 index put dup } for { 8 16 32 64 128 } {",
109
" 2 copy 0 exch getinterval putinterval dup",
110
" } forall pop exch pop",
112
/* Initialize the procedure table for input dispatching. */
114
/* Stack: <buffer> <file> <xdigits> <previous> <byte> */
115
" 32 { { pop .ImageItem } } repeat",
116
" 16 { {", /* 0x20-0x2f: (N-0x20) data bytes follow */
117
" 32 sub 3 -1 roll add 3 index exch 0 exch getinterval 2 index exch",
118
" readhexstring pop exch pop 0 exch dup",
120
" 16 { {", /* 0x30-0x3f: prefix hex digit (N-0x30) to next count */
121
" 48 sub 3 -1 roll add 4 bitshift exch .ImageItem",
123
" 32 { {", /* 0x40-0x5f: repeat last data byte (N-0x40) times */
124
" 64 sub 3 -1 roll add .ImageFills 2 index dup length 1 sub get get",
125
" exch 0 exch getinterval 0 3 1 roll",
127
" 160 { { pop .ImageItem } } repeat",
129
/* Read one item from a compressed image. */
130
/* Stack contents: <buffer> <file> <xdigits> <previous> */
132
" 2 index read pop dup .ImageProcs exch get exec",
134
/* Read and print an entire compressed image. */
135
"/.ImageRead {" /* <width> <height> <bpc> .ImageRead - */
137
/* Stack: width height bpc -mark- */
138
" 1 0 0 -1 0 7 index",
139
/* Stack: width height bpc -mark- 1 0 0 -1 0 height */
141
/* Stack: width height bpc <matrix> <proc> */
142
" 4 index 3 index mul 7 add 8 idiv string currentfile 0 ()",
143
/* Stack: width height bpc <matrix> <proc> <buffer> <file> 0 () */
145
/* Stack: <buffer> <file> 0 () width height bpc <matrix> <proc> */
146
" image pop pop pop pop grestore",
150
static const gx_device_pswrite_common_t psmono_values =
151
PSWRITE_COMMON_VALUES(1, 0 /*false*/, 1);
153
#define data_run_code 0x20
154
#define xdigit_code 0x30
155
#define max_data_per_line 35
156
#define repeat_run_code 0x40
157
#define max_repeat_run_code 31
158
#define max_repeat_run 255
160
/* Send the page to the printer. */
161
static void write_data_run(const byte *, int, FILE *, byte);
163
psmono_print_page(gx_device_printer * pdev, FILE * prn_stream)
165
int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
167
byte *line = gs_alloc_bytes(pdev->memory, line_size, "psmono_print_page");
168
byte invert = (pdev->color_info.depth == 1 ? 0xff : 0);
169
gx_device_pswrite_common_t pswrite_common;
172
return_error(gs_error_VMerror);
173
pswrite_common = psmono_values;
175
/* If this is the first page of the file, */
176
/* write the setup code. */
177
ps_image_write_headers(prn_stream, pdev, psmono_setup, &pswrite_common);
179
/* Write the .ImageRead command. */
181
"%d %d %d .ImageRead\n",
182
pdev->width, pdev->height, pdev->color_info.depth);
184
/* Compress each scan line in turn. */
185
for (lnum = 0; lnum < pdev->height; lnum++) {
187
int left = line_size;
190
gdev_prn_get_bits(pdev, lnum, line, &data);
192
/* Loop invariant: p + left = data + line_size. */
193
#define min_repeat_run 10
194
while (left >= min_repeat_run) { /* Detect a maximal run of non-repeated data. */
198
int count, count_left;
200
while (left1 >= min_repeat_run &&
201
((b = *p1) != p1[1] ||
202
b != p1[2] || b != p1[3] || b != p1[4] ||
203
b != p1[5] || b != p1[6] || b != p1[7] ||
204
b != p1[8] || b != p1[9])
207
if (left1 < min_repeat_run)
208
break; /* no repeated data left */
209
write_data_run(p, (int)(p1 - p + 1), prn_stream,
211
/* Detect a maximal run of repeated data. */
212
p = ++p1 + (min_repeat_run - 1);
213
left = --left1 - (min_repeat_run - 1);
214
while (left > 0 && *p == b)
216
for (count = p - p1; count > 0;
219
count_left = min(count, max_repeat_run);
220
if (count_left > max_repeat_run_code)
221
fputc(xdigit_code + (count_left >> 4),
223
fputc(repeat_run_code + (count_left & 0xf),
226
putc(repeat_run_code + count_left,
229
if (ferror(prn_stream))
230
return_error(gs_error_ioerror);
232
/* Write the remaining data, if any. */
233
write_data_run(p, left, prn_stream, invert);
236
/* Clean up and return. */
237
fputs("\n", prn_stream);
238
psw_write_page_trailer(prn_stream, 1, true);
239
gs_free_object(pdev->memory, line, "psmono_print_page");
240
if (ferror(prn_stream))
241
return_error(gs_error_ioerror);
245
/* Close the file. */
247
psmono_close(gx_device *dev)
249
int code = psw_end_file(((gx_device_printer *)dev)->file, dev,
250
&psmono_values, NULL, dev->PageCount);
254
return gdev_prn_close(dev);
257
/* Write a run of data on the file. */
259
write_data_run(const byte * data, int count, FILE * f, byte invert)
261
const byte *p = data;
262
const char *const hex_digits = "0123456789abcdef";
264
char line[sizeof(count) * 2 + max_data_per_line * 2 + 3];
267
/* Write the count. */
272
int shift = sizeof(count) * 8;
274
while ((shift -= 4) > 0 && (count >> shift) == 0);
275
for (; shift > 0; shift -= 4)
276
*q++ = xdigit_code + ((count >> shift) & 0xf);
277
*q++ = data_run_code + (count & 0xf);
280
/* Write the data. */
283
register int wcount = min(left, max_data_per_line);
286
for (; wcount > 0; ++p, --wcount) {
287
byte b = *p ^ invert;
289
*q++ = hex_digits[b >> 4];
290
*q++ = hex_digits[b & 0xf];
293
fwrite(line, 1, q - line, f);
299
/* ---------------- Level 2 RGB driver ---------------- */
302
* This driver produces plane-separated, run-length-encoded, 24-bit RGB
303
* images suitable for a PostScript Level 2 printer. LZW compression would
304
* be better, but Unisys' claim to own the compression algorithm and their
305
* demand for licensing and payment even for freely distributed software
309
/* The device descriptor */
310
static dev_proc_print_page(psrgb_print_page);
311
static dev_proc_close_device(psrgb_close);
313
static const gx_device_procs psrgb_procs =
314
prn_color_procs(gdev_prn_open, gdev_prn_output_page, psrgb_close,
315
gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
317
const gx_device_printer gs_psrgb_device = {
318
prn_device_body(gx_device_printer, psrgb_procs, "psrgb",
319
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
321
0, 0, 0, 0, /* margins */
322
3, 24, 255, 255, 256, 256, psrgb_print_page)
325
static const char *const psrgb_setup[] = {
326
"/rgbimage {", /* <width> <height> rgbimage - */
327
" gsave 2 copy scale /h exch def /w exch def",
328
" /s1 w string def /s2 w string def /s3 w string def",
329
" /f currentfile /ASCII85Decode filter /RunLengthDecode filter def",
330
" w h 8 [w 0 0 h neg 0 h]",
331
" {f s1 readstring pop} {f s2 readstring pop} {f s3 readstring pop}",
332
" true 3 colorimage grestore",
336
static const gx_device_pswrite_common_t psrgb_values =
337
PSWRITE_COMMON_VALUES(2, 0 /*false*/, 1);
339
/* Send the page to the printer. */
341
psrgb_print_page(gx_device_printer * pdev, FILE * prn_stream)
343
gs_memory_t *mem = pdev->memory;
344
int width = pdev->width;
345
byte *lbuf = gs_alloc_bytes(mem, width * 3,
346
"psrgb_print_page(lbuf)");
348
stream fs, a85s, rls;
349
stream_A85E_state a85state;
350
stream_RLE_state rlstate;
351
byte fsbuf[200]; /* arbitrary, must be >2 */
352
byte a85sbuf[100]; /* arbitrary, must be >=6 */
353
byte rlsbuf[200]; /* arbitrary, must be >128 */
354
gx_device_pswrite_common_t pswrite_common;
355
pswrite_common = psrgb_values;
358
return_error(gs_error_VMerror);
359
ps_image_write_headers(prn_stream, pdev, psrgb_setup, &pswrite_common);
360
fprintf(prn_stream, "%d %d rgbimage\n", width, pdev->height);
362
swrite_file(&fs, prn_stream, fsbuf, sizeof(fsbuf));
365
if (s_A85E_template.set_defaults)
366
(*s_A85E_template.set_defaults) ((stream_state *) & a85state);
368
s_std_init(&a85s, a85sbuf, sizeof(a85sbuf), &s_filter_write_procs,
372
a85state.template = &s_A85E_template;
373
(*s_A85E_template.init) ((stream_state *) & a85state);
374
a85s.state = (stream_state *) & a85state;
375
a85s.procs.process = s_A85E_template.process;
378
(*s_RLE_template.set_defaults) ((stream_state *) & rlstate);
380
s_std_init(&rls, rlsbuf, sizeof(rlsbuf), &s_filter_write_procs,
384
rlstate.template = &s_RLE_template;
385
(*s_RLE_template.init) ((stream_state *) & rlstate);
386
rls.state = (stream_state *) & rlstate;
387
rls.procs.process = s_RLE_template.process;
390
for (lnum = 0; lnum < pdev->height; ++lnum) {
394
gdev_prn_get_bits(pdev, lnum, lbuf, &data);
395
for (c = 0; c < 3; ++c) {
398
for (i = 0, p = data + c; i < width; ++i, p += 3)
400
if (rls.end_status == ERRC)
401
return_error(gs_error_ioerror);
407
fputs("\n", prn_stream);
408
psw_write_page_trailer(prn_stream, 1, true);
409
gs_free_object(mem, lbuf, "psrgb_print_page(lbuf)");
410
if (ferror(prn_stream))
411
return_error(gs_error_ioerror);
415
/* Close the file. */
417
psrgb_close(gx_device *dev)
419
int code = psw_end_file(((gx_device_printer *)dev)->file, dev,
420
&psrgb_values, NULL, dev->PageCount);
424
return gdev_prn_close(dev);