4
$(gx_h) $(gsccolor_h) $(gsdcolor_h) $(gxiparam_h) $(gserrors_h)\
5
$(gxcspace_h) $(gxdevice_h) $(gxpath_h)\
6
$(gdevpxat_h) $(gdevpxen_h) $(gdevpxop_h) $(gdevpxut_h) $(gdevvec_h)\
7
- $(srlx_h) $(strimpl_h)
8
+ $(srlx_h) $(strimpl_h) $(jpeglib__h) $(sdct_h) $(sjpeg_h)
9
$(DEVCC) $(DEVO_)gdevpx.$(OBJ) $(C_) $(DEVVECSRC)gdevpx.c
11
# Scalable Vector Graphics (SVG) output device
12
--- a/devices/vector/gdevpx.c
13
+++ b/devices/vector/gdevpx.c
18
+#include "jpeglib_.h"
27
int state_rotated; /* 0, 1, 2, -1, mutiple of 90 deg */
28
- int CompressMode; /* std PXL enum: None=0, RLE=1, DeltaRow=3; JPEG=2 not used */
29
+ int CompressMode; /* std PXL enum: None=0, RLE=1, JPEG=2, DeltaRow=3 */
31
floatp x_scale; /* chosen so that max(x) is scaled to 0x7FFF, to give max distinction between x values */
34
px_put_bytes(s, (const byte *)"\000\000\000\000", -(int)width_bytes & 3);
39
+pclxl_write_image_data_JPEG(gx_device_pclxl * xdev, const byte * base,
40
+ int data_bit, uint raster, uint width_bits, int y,
43
+ stream *s = pclxl_stream(xdev);
44
+ uint width_bytes = (width_bits + 7) >> 3;
49
+ /* cannot handle data_bit not multiple of 8, but we don't invoke this routine that way */
50
+ int offset = data_bit >> 3;
51
+ const byte *data = base + offset;
52
+ jpeg_compress_data *jcdp =
53
+ gs_alloc_struct_immovable(xdev->v_memory, jpeg_compress_data,
54
+ &st_jpeg_compress_data,
55
+ "pclxl_write_image_data_JPEG(jpeg_compress_data)");
56
+ stream_DCT_state state;
57
+ stream_cursor_read r;
58
+ stream_cursor_write w;
59
+ /* Approx. The worse case is ~ header + width_bytes * height.
60
+ Apparently minimal SOI/DHT/DQT/SOS/EOI is 341 bytes. TO CHECK. */
61
+ int buffersize = 341 + width_bytes * height;
63
+ byte *buf = gs_alloc_bytes(xdev->v_memory, buffersize,
64
+ "pclxl_write_image_data_JPEG(buf)");
65
+ /* RLE can write uncompressed without extra-allocation */
66
+ if ((buf == 0) || (jcdp == 0)) {
67
+ goto failed_so_use_rle_instead;
69
+ /* Create the DCT encoder state. */
70
+ jcdp->templat = s_DCTE_template;
71
+ s_init_state((stream_state *) & state, &jcdp->templat, 0);
72
+ if (state.templat->set_defaults) {
73
+ state.memory = xdev->v_memory;
74
+ (*state.templat->set_defaults) ((stream_state *) & state);
75
+ state.memory = NULL;
77
+ state.ColorTransform = (xdev->color_info.num_components == 3 ? 1 : 0);
78
+ state.data.compress = jcdp;
79
+ state.icc_profile = NULL;
80
+ jcdp->memory = state.jpeg_memory = xdev->v_memory;
81
+ if ((code = gs_jpeg_create_compress(&state)) < 0)
82
+ goto cleanup_and_use_rle;
83
+ /* image-specific info */
84
+ jcdp->cinfo.image_width = width_bytes / xdev->color_info.num_components;
85
+ jcdp->cinfo.image_height = height;
86
+ switch (xdev->color_info.num_components) {
88
+ jcdp->cinfo.input_components = 3;
89
+ jcdp->cinfo.in_color_space = JCS_RGB;
92
+ jcdp->cinfo.input_components = 1;
93
+ jcdp->cinfo.in_color_space = JCS_GRAYSCALE;
96
+ goto cleanup_and_use_rle;
99
+ /* Set compression parameters. */
100
+ if ((code = gs_jpeg_set_defaults(&state)) < 0)
101
+ goto cleanup_and_use_rle;
103
+ if (state.templat->init)
104
+ (*state.templat->init) ((stream_state *)&state);
105
+ state.scan_line_size = jcdp->cinfo.input_components *
106
+ jcdp->cinfo.image_width;
107
+ jcdp->templat.min_in_size =
108
+ max(s_DCTE_template.min_in_size, state.scan_line_size);
109
+ jcdp->templat.min_out_size =
110
+ max(s_DCTE_template.min_out_size, state.Markers.size);
113
+ w.limit = w.ptr + buffersize;
114
+ for (i = 0; i < height; ++i) {
115
+ r.ptr = data + i * raster - 1;
116
+ r.limit = r.ptr + width_bytes;
117
+ if (((code = (*state.templat->process)
118
+ ((stream_state *) & state, &r, &w, false)) != 0 && code != EOFC) || r.ptr != r.limit)
119
+ goto cleanup_and_use_rle;
121
+ count = w.ptr + 1 - buf;
122
+ px_put_usa(s, y, pxaStartLine);
123
+ px_put_usa(s, height, pxaBlockHeight);
124
+ px_put_ub(s, eJPEGCompression);
125
+ px_put_ac(s, pxaCompressMode, pxtReadImage);
126
+ px_put_data_length(s, count);
127
+ px_put_bytes(s, buf, count);
129
+ gs_free_object(xdev->v_memory, buf,
130
+ "pclxl_write_image_data_JPEG(buf)");
132
+ gs_jpeg_destroy(&state); /* frees *jcdp */
135
+ cleanup_and_use_rle:
136
+ /* cleans up - something went wrong after allocation */
137
+ gs_free_object(xdev->v_memory, buf,
138
+ "pclxl_write_image_data_JPEG(buf)");
140
+ gs_jpeg_destroy(&state); /* frees *jcdp */
141
+ /* fall through to redo in RLE */
142
+ failed_so_use_rle_instead:
143
+ /* the RLE routine can write without new allocation - use as fallback. */
144
+ pclxl_write_image_data_RLE(xdev, data, data_bit, raster, width_bits, y,
149
/* DeltaRow compression (also called "mode 3"):
150
drawn heavily from gdevcljc.c:cljc_print_page(),
151
This is simplier since PCL XL does not allow
152
@@ -769,24 +884,38 @@
156
+/* calling from copy_mono/copy_color/fill_mask should never do lossy compression */
158
-pclxl_write_image_data(gx_device_pclxl * xdev, const byte * data, int data_bit,
159
- uint raster, uint width_bits, int y, int height)
160
+pclxl_write_image_data(gx_device_pclxl * xdev, const byte * data,
161
+ int data_bit, uint raster, uint width_bits, int y,
162
+ int height, bool allow_lossy)
164
- /* If we only have 1 line, it does not make sense to do DeltaRow */
165
+ /* If we only have 1 line, it does not make sense to do JPEG/DeltaRow */
167
- pclxl_write_image_data_RLE(xdev, data, data_bit, raster, width_bits, y, height);
171
- switch(xdev->CompressMode){
172
- case eDeltaRowCompression:
173
- pclxl_write_image_data_DeltaRow(xdev, data, data_bit, raster, width_bits, y, height);
175
- case eRLECompression:
177
- pclxl_write_image_data_RLE(xdev, data, data_bit, raster, width_bits, y, height);
179
+ pclxl_write_image_data_RLE(xdev, data, data_bit, raster, width_bits,
184
+ switch (xdev->CompressMode) {
185
+ case eDeltaRowCompression:
186
+ pclxl_write_image_data_DeltaRow(xdev, data, data_bit, raster,
187
+ width_bits, y, height);
189
+ case eJPEGCompression:
190
+ /* JPEG should not be used for mask or other data */
192
+ pclxl_write_image_data_JPEG(xdev, data, data_bit, raster,
193
+ width_bits, y, height);
195
+ pclxl_write_image_data_RLE(xdev, data, data_bit, raster,
196
+ width_bits, y, height);
198
+ case eRLECompression:
200
+ pclxl_write_image_data_RLE(xdev, data, data_bit, raster,
201
+ width_bits, y, height);
206
@@ -1590,7 +1719,7 @@
209
pclxl_write_begin_image(xdev, w, h, w, h);
210
- pclxl_write_image_data(xdev, data, data_x, raster, w, 0, h);
211
+ pclxl_write_image_data(xdev, data, data_x, raster, w, 0, h, false);
212
pclxl_write_end_image(xdev);
215
@@ -1652,7 +1781,7 @@
217
pclxl_write_begin_image(xdev, w, h, w, h);
218
pclxl_write_image_data(xdev, base, source_bit, raster,
219
- w * dev->color_info.depth, 0, h);
220
+ w * dev->color_info.depth, 0, h, false);
221
pclxl_write_end_image(xdev);
224
@@ -1719,7 +1848,7 @@
227
pclxl_write_begin_image(xdev, w, h, w, h);
228
- pclxl_write_image_data(xdev, data, data_x, raster, w, 0, h);
229
+ pclxl_write_image_data(xdev, data, data_x, raster, w, 0, h, false);
230
pclxl_write_end_image(xdev);
233
@@ -2080,8 +2209,10 @@
236
pclxl_write_begin_image(xdev, pie->width, h, dw, dh);
237
+ /* 8-bit gray image may compress with jpeg, but we
238
+ cannot tell if it is 8-bit gray or 8-bit indexed */
239
pclxl_write_image_data(xdev, pie->rows.data + offset_lastflippedstrip, 0, rows_raster,
240
- rows_raster << 3, 0, h);
241
+ rows_raster << 3, 0, h, (pie->bits_per_pixel==24 ? true : false));
242
pclxl_write_end_image(xdev);
245
--- a/doc/Devices.htm
246
+++ b/doc/Devices.htm
251
-<dt><code>-dCompressMode=<em>1 | 3</em></code> (default is 1)
252
-<dd>Set the compression algorithm used for bitmap graphics. RLE=1, DeltaRow=3. (JPEG=2 is unimplemented)
253
+<dt><code>-dCompressMode=<em>1 | 2 | 3</em></code> (default is 1)
254
+<dd>Set the compression algorithm used for bitmap graphics. RLE=1, JPEG=2, DeltaRow=3.
255
+When JPEG=2 is on, it is applied only to full-color images; indexed-color graphics
256
+and masks continues to be compressed with RLE.
259
<h3><a name="TXT"></a>Text output</h3>