~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/gdevjpeg.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
 
   All Rights Reserved.
3
 
  
4
 
   This software is provided AS-IS with no warranty, either express or
5
 
   implied.
6
 
 
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.
12
 
*/
13
 
/* $Id: gdevjpeg.c 8250 2007-09-25 13:31:24Z giles $ */
14
 
/* JPEG output driver */
15
 
#include "stdio_.h"             /* for jpeglib.h */
16
 
#include "jpeglib_.h"
17
 
#include "gdevprn.h"
18
 
#include "stream.h"
19
 
#include "strimpl.h"
20
 
#include "sdct.h"
21
 
#include "sjpeg.h"
22
 
 
23
 
/* Structure for the JPEG-writing device. */
24
 
typedef struct gx_device_jpeg_s {
25
 
    gx_device_common;
26
 
    gx_prn_device_common;
27
 
    /* Additional parameters */
28
 
    int JPEGQ;                  /* quality on IJG scale */
29
 
    float QFactor;              /* quality per DCTEncode conventions */
30
 
    /* JPEGQ overrides QFactor if both are specified. */    
31
 
 
32
 
    /** 1.0 default 2.0 is twice as big 
33
 
     */
34
 
    gs_point ViewScale;
35
 
 
36
 
    /** translation needs to have scalefactor multiplied in.
37
 
     */
38
 
    gs_point ViewTrans;
39
 
 
40
 
} gx_device_jpeg;
41
 
 
42
 
/* The device descriptor */
43
 
static dev_proc_get_params(jpeg_get_params);
44
 
static dev_proc_get_initial_matrix(jpeg_get_initial_matrix);
45
 
static dev_proc_put_params(jpeg_put_params);
46
 
static dev_proc_print_page(jpeg_print_page);
47
 
static dev_proc_map_color_rgb(jpegcmyk_map_color_rgb);
48
 
static dev_proc_map_cmyk_color(jpegcmyk_map_cmyk_color);
49
 
 
50
 
/* ------ The device descriptors ------ */
51
 
 
52
 
/* Default X and Y resolution. */
53
 
#ifndef X_DPI
54
 
#  define X_DPI 72
55
 
#endif
56
 
#ifndef Y_DPI
57
 
#  define Y_DPI 72
58
 
#endif
59
 
 
60
 
/* 24-bit color */
61
 
 
62
 
static const gx_device_procs jpeg_procs =
63
 
{
64
 
    gdev_prn_open,
65
 
    jpeg_get_initial_matrix,    /* get_initial_matrix */
66
 
    NULL,                       /* sync_output */
67
 
    gdev_prn_output_page,
68
 
    gdev_prn_close,
69
 
    gx_default_rgb_map_rgb_color,/* map_rgb_color */
70
 
    gx_default_rgb_map_color_rgb,
71
 
    NULL,                       /* fill_rectangle */
72
 
    NULL,                       /* tile_rectangle */
73
 
    NULL,                       /* copy_mono */
74
 
    NULL,                       /* copy_color */
75
 
    NULL,                       /* draw_line */
76
 
    NULL,                       /* get_bits */
77
 
    jpeg_get_params,
78
 
    jpeg_put_params,
79
 
    NULL,
80
 
    NULL,                       /* get_xfont_procs */
81
 
    NULL,                       /* get_xfont_device */
82
 
    NULL,                       /* map_rgb_alpha_color */
83
 
    gx_page_device_get_page_device
84
 
};
85
 
 
86
 
const gx_device_jpeg gs_jpeg_device =
87
 
{prn_device_std_body(gx_device_jpeg, jpeg_procs, "jpeg",
88
 
                     DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
89
 
                     X_DPI, Y_DPI, 0, 0, 0, 0, 24, jpeg_print_page),
90
 
 0,                             /* JPEGQ: 0 indicates not specified */
91
 
 0.0,                           /* QFactor: 0 indicates not specified */
92
 
 { 1.0, 1.0 },                  /* ViewScale 1 to 1 */ 
93
 
 { 0.0, 0.0 }                   /* translation 0 */ 
94
 
};
95
 
 
96
 
/* 8-bit gray */
97
 
 
98
 
static const gx_device_procs jpeggray_procs =
99
 
{
100
 
    gdev_prn_open,
101
 
    jpeg_get_initial_matrix,    /* get_initial_matrix */
102
 
    NULL,                       /* sync_output */
103
 
    gdev_prn_output_page,
104
 
    gdev_prn_close,
105
 
    gx_default_gray_map_rgb_color,/* map_rgb_color */
106
 
    gx_default_gray_map_color_rgb,
107
 
    NULL,                       /* fill_rectangle */
108
 
    NULL,                       /* tile_rectangle */
109
 
    NULL,                       /* copy_mono */
110
 
    NULL,                       /* copy_color */
111
 
    NULL,                       /* draw_line */
112
 
    NULL,                       /* get_bits */
113
 
    jpeg_get_params,
114
 
    jpeg_put_params,
115
 
    NULL,
116
 
    NULL,                       /* get_xfont_procs */
117
 
    NULL,                       /* get_xfont_device */
118
 
    NULL,                       /* map_rgb_alpha_color */
119
 
    gx_page_device_get_page_device
120
 
};
121
 
 
122
 
const gx_device_jpeg gs_jpeggray_device =
123
 
{prn_device_body(gx_device_jpeg, jpeggray_procs, "jpeggray",
124
 
                 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
125
 
                 X_DPI, Y_DPI, 0, 0, 0, 0,
126
 
                 1, 8, 255, 0, 256, 0,
127
 
                 jpeg_print_page),
128
 
 0,                             /* JPEGQ: 0 indicates not specified */
129
 
 0.0,                           /* QFactor: 0 indicates not specified */
130
 
 { 1.0, 1.0 },                  /* ViewScale 1 to 1 */ 
131
 
 { 0.0, 0.0 }                   /* translation 0 */ 
132
 
};
133
 
/* 32-bit CMYK */
134
 
 
135
 
static const gx_device_procs jpegcmyk_procs =
136
 
{       gdev_prn_open,
137
 
        gx_default_get_initial_matrix,
138
 
        NULL,   /* sync_output */
139
 
        gdev_prn_output_page,
140
 
        gdev_prn_close,
141
 
        NULL,
142
 
        jpegcmyk_map_color_rgb,
143
 
        NULL,   /* fill_rectangle */
144
 
        NULL,   /* tile_rectangle */
145
 
        NULL,   /* copy_mono */
146
 
        NULL,   /* copy_color */
147
 
        NULL,   /* draw_line */
148
 
        NULL,   /* get_bits */
149
 
        jpeg_get_params,
150
 
        jpeg_put_params,
151
 
        jpegcmyk_map_cmyk_color,
152
 
        NULL,   /* get_xfont_procs */
153
 
        NULL,   /* get_xfont_device */
154
 
        NULL,   /* map_rgb_alpha_color */
155
 
        gx_page_device_get_page_device  /* get_page_device */
156
 
};
157
 
 
158
 
const gx_device_jpeg gs_jpegcmyk_device =
159
 
{prn_device_std_body(gx_device_jpeg, jpegcmyk_procs, "jpegcmyk",
160
 
                     DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
161
 
                     X_DPI, Y_DPI, 0, 0, 0, 0, 32, jpeg_print_page),
162
 
 0,                             /* JPEGQ: 0 indicates not specified */
163
 
 0.0,                           /* QFactor: 0 indicates not specified */
164
 
 { 1.0, 1.0 },                  /* ViewScale 1 to 1 */ 
165
 
 { 0.0, 0.0 }                   /* translation 0 */ 
166
 
};
167
 
 
168
 
 
169
 
/* Apparently Adobe Photoshop and some other applications that  */
170
 
/* accept JPEG CMYK images expect color values to be inverted.  */
171
 
static int
172
 
jpegcmyk_map_color_rgb(gx_device * dev, gx_color_index color,
173
 
                        gx_color_value prgb[3])
174
 
{
175
 
    int
176
 
        not_k = color & 0xff,
177
 
        r = not_k - ~(color >> 24),
178
 
        g = not_k - ~((color >> 16) & 0xff),
179
 
        b = not_k - ~((color >> 8) & 0xff); 
180
 
 
181
 
    prgb[0] = (r < 0 ? 0 : gx_color_value_from_byte(r));
182
 
    prgb[1] = (g < 0 ? 0 : gx_color_value_from_byte(g));
183
 
    prgb[2] = (b < 0 ? 0 : gx_color_value_from_byte(b));
184
 
    return 0;
185
 
}
186
 
 
187
 
static gx_color_index
188
 
jpegcmyk_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
189
 
{
190
 
    gx_color_index color = ~(
191
 
        gx_color_value_to_byte(cv[3]) +
192
 
        ((uint)gx_color_value_to_byte(cv[2]) << 8) +
193
 
        ((uint)gx_color_value_to_byte(cv[1]) << 16) +
194
 
        ((uint)gx_color_value_to_byte(cv[0]) << 24));
195
 
    
196
 
    return (color == gx_no_color_index ? color ^ 1 : color);
197
 
}
198
 
 
199
 
/* Get parameters. */
200
 
static int
201
 
jpeg_get_params(gx_device * dev, gs_param_list * plist)
202
 
{
203
 
    gx_device_jpeg *jdev = (gx_device_jpeg *) dev;
204
 
    int code = gdev_prn_get_params(dev, plist);
205
 
    int ecode;
206
 
    float float2double;
207
 
    if (code < 0)
208
 
        return code;
209
 
 
210
 
    if ((ecode = param_write_int(plist, "JPEGQ", &jdev->JPEGQ)) < 0)
211
 
        code = ecode;
212
 
    if ((ecode = param_write_float(plist, "QFactor", &jdev->QFactor)) < 0)
213
 
        code = ecode;
214
 
    float2double = jdev->ViewScale.x;
215
 
    if ((ecode = param_write_float(plist, "ViewScaleX", &float2double)) < 0)
216
 
        code = ecode;
217
 
    float2double = jdev->ViewScale.y;
218
 
    if ((ecode = param_write_float(plist, "ViewScaleY", &float2double)) < 0)
219
 
        code = ecode;
220
 
    float2double = jdev->ViewTrans.x;
221
 
    if ((ecode = param_write_float(plist, "ViewTransX", &float2double)) < 0)
222
 
        code = ecode;
223
 
    float2double = jdev->ViewTrans.y;
224
 
    if ((ecode = param_write_float(plist, "ViewTransY", &float2double)) < 0)
225
 
        code = ecode;
226
 
 
227
 
    return code;
228
 
}
229
 
 
230
 
/* Put parameters. */
231
 
static int
232
 
jpeg_put_params(gx_device * dev, gs_param_list * plist)
233
 
{
234
 
    gx_device_jpeg *jdev = (gx_device_jpeg *) dev;
235
 
    int ecode = 0;
236
 
    int code;
237
 
    gs_param_name param_name;
238
 
    int jq = jdev->JPEGQ;
239
 
    float qf = jdev->QFactor;
240
 
    float fparam;
241
 
 
242
 
    switch (code = param_read_int(plist, (param_name = "JPEGQ"), &jq)) {
243
 
        case 0:
244
 
            if (jq < 0 || jq > 100)
245
 
                ecode = gs_error_limitcheck;
246
 
            else
247
 
                break;
248
 
            goto jqe;
249
 
        default:
250
 
            ecode = code;
251
 
          jqe:param_signal_error(plist, param_name, ecode);
252
 
        case 1:
253
 
            break;
254
 
    }
255
 
 
256
 
    switch (code = param_read_float(plist, (param_name = "QFactor"), &qf)) {
257
 
        case 0:
258
 
            if (qf < 0.0 || qf > 1.0e6)
259
 
                ecode = gs_error_limitcheck;
260
 
            else
261
 
                break;
262
 
            goto qfe;
263
 
        default:
264
 
            ecode = code;
265
 
          qfe:param_signal_error(plist, param_name, ecode);
266
 
        case 1:
267
 
            break;
268
 
    }
269
 
 
270
 
 
271
 
    code = param_read_float(plist, (param_name = "ViewScaleX"), &fparam);
272
 
    if ( code == 0 ) {
273
 
        if (fparam < 1.0)
274
 
            param_signal_error(plist, param_name, gs_error_limitcheck);
275
 
        else
276
 
            jdev->ViewScale.x = fparam;
277
 
    }
278
 
    else if ( code < 1 ) {
279
 
        ecode = code;
280
 
        param_signal_error(plist, param_name, code);
281
 
    }
282
 
 
283
 
    code = param_read_float(plist, (param_name = "ViewScaleY"), &fparam);
284
 
    if ( code == 0 ) {
285
 
        if (fparam < 1.0)
286
 
            param_signal_error(plist, param_name, gs_error_limitcheck);
287
 
        else
288
 
            jdev->ViewScale.y = fparam;
289
 
    }
290
 
    else if ( code < 1 ) {
291
 
        ecode = code;
292
 
        param_signal_error(plist, param_name, code);
293
 
    }
294
 
 
295
 
    /* pixels in desired dpi, auto negative ( moves up and left ) */ 
296
 
    code = param_read_float(plist, (param_name = "ViewTransX"), &fparam);
297
 
    if ( code == 0 ) {
298
 
        jdev->ViewTrans.x = fparam;
299
 
    }
300
 
    else if ( code < 1 ) {
301
 
        ecode = code;
302
 
        param_signal_error(plist, param_name, code);
303
 
    }
304
 
 
305
 
    code = param_read_float(plist, (param_name = "ViewTransY"), &fparam);
306
 
    if ( code == 0 ) {
307
 
        jdev->ViewTrans.y = fparam;
308
 
    }
309
 
    else if ( code < 1 ) {
310
 
        ecode = code;
311
 
        param_signal_error(plist, param_name, code);
312
 
    }  
313
 
    code = gdev_prn_put_params(dev, plist);
314
 
    if (code < 0)
315
 
        return code;
316
 
 
317
 
    if (ecode < 0)
318
 
        return ecode;
319
 
 
320
 
    jdev->JPEGQ = jq;
321
 
    jdev->QFactor = qf;
322
 
    return 0;
323
 
}
324
 
 
325
 
/******************************************************************
326
 
 This device supports translation and scaling.
327
 
 
328
 
0123456  
329
 
 
330
 
0PPPPPPP  0 is origin
331
 
PPPPPPPP  1 is x1,y1 (2,2)
332
 
PP1vvvPP  2 is x2,y2 (6,6)
333
 
PPvvvvPP  v is viewport, P is original page
334
 
PPvvvvPP
335
 
PPPPPP2P
336
 
PPPPPPPP
337
 
  
338
 
Given a view port in pixels starting at x1,y1   
339
 
where x1 < width, y1 < height in pixels
340
 
 
341
 
ViewScaleX = desired Resolution / HWResolution ; 1.0 default 
342
 
ViewScaleY = desired Resolution / HWResolution
343
 
 
344
 
HWResolutionX = desired dpi at 1:1 scaling     ; 72dpi default  
345
 
HWResolutionY = desired dpi at 1:1 scaling
346
 
 
347
 
ViewTransX = x1 * ViewScaleX                   ; 0.0 default 
348
 
ViewTransY = y1 * ViewScaleY
349
 
 
350
 
if initial matrix multiplies ViewScaleX in then translation is limited to
351
 
multiples of the HWResolution.
352
 
 
353
 
***************************************************************************/
354
 
 
355
 
static void
356
 
jpeg_get_initial_matrix(gx_device *dev, gs_matrix *pmat)
357
 
{
358
 
    gx_device_jpeg *pdev = (gx_device_jpeg *)dev;
359
 
    floatp fs_res = (dev->HWResolution[0] / 72.0) * pdev->ViewScale.x; 
360
 
    floatp ss_res = (dev->HWResolution[1] / 72.0) * pdev->ViewScale.y; 
361
 
 
362
 
    /* NB this device has no paper margins */
363
 
 
364
 
    switch(pdev->LeadingEdge) {
365
 
    case 1:
366
 
        pmat->xx = 0;
367
 
        pmat->xy = -ss_res;
368
 
        pmat->yx = -fs_res;
369
 
        pmat->yy = 0;
370
 
        pmat->tx = (pdev->width * pdev->ViewScale.x) - pdev->ViewTrans.x;
371
 
        pmat->ty = (pdev->height * pdev->ViewScale.y) - pdev->ViewTrans.y;
372
 
        break;
373
 
    case 2:
374
 
        pmat->xx = -fs_res;
375
 
        pmat->xy = 0;
376
 
        pmat->yx = 0;
377
 
        pmat->yy = ss_res;
378
 
        pmat->tx = (pdev->width * pdev->ViewScale.x) - pdev->ViewTrans.x;
379
 
        pmat->ty = -pdev->ViewTrans.x;
380
 
        break;
381
 
    case 3:
382
 
        pmat->xx = 0;
383
 
        pmat->xy = ss_res;
384
 
        pmat->yx = fs_res;
385
 
        pmat->yy = 0;
386
 
        pmat->tx = -pdev->ViewTrans.x;
387
 
        pmat->ty = -pdev->ViewTrans.y;
388
 
        break;
389
 
    default:
390
 
    case 0:
391
 
        pmat->xx = fs_res;
392
 
        pmat->xy = 0;
393
 
        pmat->yx = 0;
394
 
        pmat->yy = -ss_res;
395
 
        pmat->tx = -pdev->ViewTrans.x;
396
 
        pmat->ty = (pdev->height * pdev->ViewScale.y) - pdev->ViewTrans.y;
397
 
        break;
398
 
    }
399
 
 
400
 
}
401
 
 
402
 
/* Send the page to the file. */
403
 
static int
404
 
jpeg_print_page(gx_device_printer * pdev, FILE * prn_stream)
405
 
{
406
 
    gx_device_jpeg *jdev = (gx_device_jpeg *) pdev;
407
 
    gs_memory_t *mem = pdev->memory;
408
 
    int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
409
 
    byte *in = gs_alloc_bytes(mem, line_size, "jpeg_print_page(in)");
410
 
    jpeg_compress_data *jcdp = gs_alloc_struct_immovable(mem, jpeg_compress_data,
411
 
      &st_jpeg_compress_data, "jpeg_print_page(jpeg_compress_data)");
412
 
    byte *fbuf = 0;
413
 
    uint fbuf_size;
414
 
    byte *jbuf = 0;
415
 
    uint jbuf_size;
416
 
    int lnum;
417
 
    int code;
418
 
    stream_DCT_state state;
419
 
    stream fstrm, jstrm;
420
 
 
421
 
    if (jcdp == 0 || in == 0) {
422
 
        code = gs_note_error(gs_error_VMerror);
423
 
        goto fail;
424
 
    }
425
 
    /* Create the DCT encoder state. */
426
 
    jcdp->template = s_DCTE_template;
427
 
    s_init_state((stream_state *)&state, &jcdp->template, 0);
428
 
    if (state.template->set_defaults)
429
 
        (*state.template->set_defaults) ((stream_state *) & state);
430
 
    state.QFactor = 1.0;        /* disable quality adjustment in zfdcte.c */
431
 
    state.ColorTransform = 1;   /* default for RGB */
432
 
    /* We insert no markers, allowing the IJG library to emit */
433
 
    /* the format it thinks best. */
434
 
    state.NoMarker = true;      /* do not insert our own Adobe marker */
435
 
    state.Markers.data = 0;
436
 
    state.Markers.size = 0;
437
 
    state.data.compress = jcdp;
438
 
    jcdp->memory = state.jpeg_memory = mem;
439
 
    if ((code = gs_jpeg_create_compress(&state)) < 0)
440
 
        goto fail;
441
 
    jcdp->cinfo.image_width = pdev->width;
442
 
    jcdp->cinfo.image_height = pdev->height;
443
 
    switch (pdev->color_info.depth) {
444
 
        case 32:
445
 
            jcdp->cinfo.input_components = 4;
446
 
            jcdp->cinfo.in_color_space = JCS_CMYK;
447
 
            break;
448
 
        case 24:
449
 
            jcdp->cinfo.input_components = 3;
450
 
            jcdp->cinfo.in_color_space = JCS_RGB;
451
 
            break;
452
 
        case 8:
453
 
            jcdp->cinfo.input_components = 1;
454
 
            jcdp->cinfo.in_color_space = JCS_GRAYSCALE;
455
 
            break;
456
 
    }
457
 
    /* Set compression parameters. */
458
 
    if ((code = gs_jpeg_set_defaults(&state)) < 0)
459
 
        goto done;
460
 
    if (jdev->JPEGQ > 0) {
461
 
        code = gs_jpeg_set_quality(&state, jdev->JPEGQ, TRUE);
462
 
        if (code < 0)
463
 
            goto done;
464
 
    } else if (jdev->QFactor > 0.0) {
465
 
        code = gs_jpeg_set_linear_quality(&state,
466
 
                                          (int)(min(jdev->QFactor, 100.0)
467
 
                                                * 100.0 + 0.5),
468
 
                                          TRUE);
469
 
        if (code < 0)
470
 
            goto done;
471
 
    }
472
 
    jcdp->cinfo.restart_interval = 0;
473
 
    jcdp->cinfo.density_unit = 1;       /* dots/inch (no #define or enum) */
474
 
    jcdp->cinfo.X_density = (UINT16)pdev->HWResolution[0];
475
 
    jcdp->cinfo.Y_density = (UINT16)pdev->HWResolution[1];
476
 
    /* Create the filter. */
477
 
    /* Make sure we get at least a full scan line of input. */
478
 
    state.scan_line_size = jcdp->cinfo.input_components *
479
 
        jcdp->cinfo.image_width;
480
 
    jcdp->template.min_in_size =
481
 
        max(s_DCTE_template.min_in_size, state.scan_line_size);
482
 
    /* Make sure we can write the user markers in a single go. */
483
 
    jcdp->template.min_out_size =
484
 
        max(s_DCTE_template.min_out_size, state.Markers.size);
485
 
 
486
 
    /* Set up the streams. */
487
 
    fbuf_size = max(512 /* arbitrary */ , jcdp->template.min_out_size);
488
 
    jbuf_size = jcdp->template.min_in_size;
489
 
    if ((fbuf = gs_alloc_bytes(mem, fbuf_size, "jpeg_print_page(fbuf)")) == 0 ||
490
 
        (jbuf = gs_alloc_bytes(mem, jbuf_size, "jpeg_print_page(jbuf)")) == 0
491
 
        ) {
492
 
        code = gs_note_error(gs_error_VMerror);
493
 
        goto done;
494
 
    }
495
 
    s_init(&fstrm, mem);
496
 
    swrite_file(&fstrm, prn_stream, fbuf, fbuf_size);
497
 
    s_init(&jstrm, mem);
498
 
    s_std_init(&jstrm, jbuf, jbuf_size, &s_filter_write_procs,
499
 
               s_mode_write);
500
 
    jstrm.state = (stream_state *) & state;
501
 
    jstrm.procs.process = state.template->process;
502
 
    jstrm.strm = &fstrm;
503
 
    if (state.template->init)
504
 
        (*state.template->init) (jstrm.state);
505
 
 
506
 
    /* Copy the data to the output. */
507
 
    for (lnum = 0; lnum < pdev->height; ++lnum) {
508
 
        byte *data;
509
 
        uint ignore_used;
510
 
 
511
 
        if (jstrm.end_status) {
512
 
            code = gs_note_error(gs_error_ioerror);
513
 
            goto done;
514
 
        }
515
 
        gdev_prn_get_bits(pdev, lnum, in, &data);
516
 
        sputs(&jstrm, data, state.scan_line_size, &ignore_used);
517
 
    }
518
 
 
519
 
    /* Wrap up. */
520
 
    sclose(&jstrm);
521
 
    sflush(&fstrm);
522
 
    jcdp = 0;
523
 
  done:
524
 
    gs_free_object(mem, jbuf, "jpeg_print_page(jbuf)");
525
 
    gs_free_object(mem, fbuf, "jpeg_print_page(fbuf)");
526
 
    if (jcdp)
527
 
        gs_jpeg_destroy(&state);        /* frees *jcdp */
528
 
    gs_free_object(mem, in, "jpeg_print_page(in)");
529
 
    return code;
530
 
  fail:
531
 
    if (jcdp)
532
 
        gs_free_object(mem, jcdp, "jpeg_print_page(jpeg_compress_data)");
533
 
    gs_free_object(mem, in, "jpeg_print_page(in)");
534
 
    return code;
535
 
}