2 |
- |
1 |
/* Copyright (C) 1992, 1993, 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gdevbmp.c,v 1.12 2005/10/20 19:42:18 ray Exp $ */
|
|
|
18 |
/* .BMP file format output drivers */
|
|
|
19 |
#include "gdevprn.h"
|
|
|
20 |
#include "gdevpccm.h"
|
|
|
21 |
#include "gdevbmp.h"
|
|
|
22 |
|
|
|
23 |
/* ------ The device descriptors ------ */
|
|
|
24 |
|
|
|
25 |
private dev_proc_print_page(bmp_print_page);
|
|
|
26 |
private dev_proc_print_page(bmp_cmyk_print_page);
|
|
|
27 |
|
|
|
28 |
/* Monochrome. */
|
|
|
29 |
|
|
|
30 |
const gx_device_printer gs_bmpmono_device =
|
|
|
31 |
prn_device(prn_std_procs, "bmpmono",
|
|
|
32 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
33 |
X_DPI, Y_DPI,
|
|
|
34 |
0, 0, 0, 0, /* margins */
|
|
|
35 |
1, bmp_print_page);
|
|
|
36 |
|
|
|
37 |
/* 8-bit (SuperVGA-style) grayscale . */
|
|
|
38 |
/* (Uses a fixed palette of 256 gray levels.) */
|
|
|
39 |
|
|
|
40 |
private const gx_device_procs bmpgray_procs =
|
|
|
41 |
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
|
|
|
42 |
gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb);
|
|
|
43 |
const gx_device_printer gs_bmpgray_device = {
|
|
|
44 |
prn_device_body(gx_device_printer, bmpgray_procs, "bmpgray",
|
|
|
45 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
46 |
X_DPI, Y_DPI,
|
|
|
47 |
0, 0, 0, 0, /* margins */
|
|
|
48 |
1, 8, 255, 0, 256, 0, bmp_print_page)
|
|
|
49 |
};
|
|
|
50 |
|
|
|
51 |
/* 1-bit-per-plane separated CMYK color. */
|
|
|
52 |
|
|
|
53 |
#define bmp_cmyk_procs(p_map_color_rgb, p_map_cmyk_color)\
|
|
|
54 |
gdev_prn_open, NULL, NULL, gdev_prn_output_page, gdev_prn_close,\
|
|
|
55 |
NULL, p_map_color_rgb, NULL, NULL, NULL, NULL, NULL, NULL,\
|
|
|
56 |
gdev_prn_get_params, gdev_prn_put_params,\
|
|
|
57 |
p_map_cmyk_color, NULL, NULL, NULL, gx_page_device_get_page_device
|
|
|
58 |
|
|
|
59 |
private const gx_device_procs bmpsep1_procs = {
|
|
|
60 |
bmp_cmyk_procs(cmyk_1bit_map_color_rgb, cmyk_1bit_map_cmyk_color)
|
|
|
61 |
};
|
|
|
62 |
const gx_device_printer gs_bmpsep1_device = {
|
|
|
63 |
prn_device_body(gx_device_printer, bmpsep1_procs, "bmpsep1",
|
|
|
64 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
65 |
X_DPI, Y_DPI,
|
|
|
66 |
0,0,0,0, /* margins */
|
|
|
67 |
4, 4, 1, 1, 2, 2, bmp_cmyk_print_page)
|
|
|
68 |
};
|
|
|
69 |
|
|
|
70 |
/* 8-bit-per-plane separated CMYK color. */
|
|
|
71 |
|
|
|
72 |
private const gx_device_procs bmpsep8_procs = {
|
|
|
73 |
bmp_cmyk_procs(cmyk_8bit_map_color_rgb, cmyk_8bit_map_cmyk_color)
|
|
|
74 |
};
|
|
|
75 |
const gx_device_printer gs_bmpsep8_device = {
|
|
|
76 |
prn_device_body(gx_device_printer, bmpsep8_procs, "bmpsep8",
|
|
|
77 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
78 |
X_DPI, Y_DPI,
|
|
|
79 |
0,0,0,0, /* margins */
|
|
|
80 |
4, 32, 255, 255, 256, 256, bmp_cmyk_print_page)
|
|
|
81 |
};
|
|
|
82 |
|
|
|
83 |
/* 4-bit planar (EGA/VGA-style) color. */
|
|
|
84 |
|
|
|
85 |
private const gx_device_procs bmp16_procs =
|
|
|
86 |
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
|
|
|
87 |
pc_4bit_map_rgb_color, pc_4bit_map_color_rgb);
|
|
|
88 |
const gx_device_printer gs_bmp16_device = {
|
|
|
89 |
prn_device_body(gx_device_printer, bmp16_procs, "bmp16",
|
|
|
90 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
91 |
X_DPI, Y_DPI,
|
|
|
92 |
0, 0, 0, 0, /* margins */
|
|
|
93 |
3, 4, 1, 1, 2, 2, bmp_print_page)
|
|
|
94 |
};
|
|
|
95 |
|
|
|
96 |
/* 8-bit (SuperVGA-style) color. */
|
|
|
97 |
/* (Uses a fixed palette of 3,3,2 bits.) */
|
|
|
98 |
|
|
|
99 |
private const gx_device_procs bmp256_procs =
|
|
|
100 |
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
|
|
|
101 |
pc_8bit_map_rgb_color, pc_8bit_map_color_rgb);
|
|
|
102 |
const gx_device_printer gs_bmp256_device = {
|
|
|
103 |
prn_device_body(gx_device_printer, bmp256_procs, "bmp256",
|
|
|
104 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
105 |
X_DPI, Y_DPI,
|
|
|
106 |
0, 0, 0, 0, /* margins */
|
|
|
107 |
3, 8, 5, 5, 6, 6, bmp_print_page)
|
|
|
108 |
};
|
|
|
109 |
|
|
|
110 |
/* 24-bit color. */
|
|
|
111 |
|
|
|
112 |
private const gx_device_procs bmp16m_procs =
|
|
|
113 |
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
|
|
|
114 |
bmp_map_16m_rgb_color, bmp_map_16m_color_rgb);
|
|
|
115 |
const gx_device_printer gs_bmp16m_device =
|
|
|
116 |
prn_device(bmp16m_procs, "bmp16m",
|
|
|
117 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
118 |
X_DPI, Y_DPI,
|
|
|
119 |
0, 0, 0, 0, /* margins */
|
|
|
120 |
24, bmp_print_page);
|
|
|
121 |
|
|
|
122 |
/* 32-bit CMYK color (outside the BMP specification). */
|
|
|
123 |
|
|
|
124 |
private const gx_device_procs bmp32b_procs = {
|
|
|
125 |
bmp_cmyk_procs(cmyk_8bit_map_color_rgb, gx_default_cmyk_map_cmyk_color)
|
|
|
126 |
};
|
|
|
127 |
const gx_device_printer gs_bmp32b_device =
|
|
|
128 |
prn_device(bmp32b_procs, "bmp32b",
|
|
|
129 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
|
|
|
130 |
X_DPI, Y_DPI,
|
|
|
131 |
0, 0, 0, 0, /* margins */
|
|
|
132 |
32, bmp_print_page);
|
|
|
133 |
|
|
|
134 |
/* ------ Private definitions ------ */
|
|
|
135 |
|
|
|
136 |
/* Write out a page in BMP format. */
|
|
|
137 |
/* This routine is used for all non-separated formats. */
|
|
|
138 |
private int
|
|
|
139 |
bmp_print_page(gx_device_printer * pdev, FILE * file)
|
|
|
140 |
{
|
|
|
141 |
uint raster = gdev_prn_raster(pdev);
|
|
|
142 |
/* BMP scan lines are padded to 32 bits. */
|
|
|
143 |
uint bmp_raster = raster + (-(int)raster & 3);
|
|
|
144 |
byte *row = gs_alloc_bytes(pdev->memory, bmp_raster, "bmp file buffer");
|
|
|
145 |
int y;
|
|
|
146 |
int code; /* return code */
|
|
|
147 |
|
|
|
148 |
if (row == 0) /* can't allocate row buffer */
|
|
|
149 |
return_error(gs_error_VMerror);
|
|
|
150 |
memset(row+raster, 0, bmp_raster - raster); /* clear the padding bytes */
|
|
|
151 |
|
|
|
152 |
/* Write the file header. */
|
|
|
153 |
|
|
|
154 |
code = write_bmp_header(pdev, file);
|
|
|
155 |
if (code < 0)
|
|
|
156 |
goto done;
|
|
|
157 |
|
|
|
158 |
/* Write the contents of the image. */
|
|
|
159 |
/* BMP files want the image in bottom-to-top order! */
|
|
|
160 |
|
|
|
161 |
for (y = pdev->height - 1; y >= 0; y--) {
|
|
|
162 |
gdev_prn_copy_scan_lines(pdev, y, row, raster);
|
|
|
163 |
fwrite((const char *)row, bmp_raster, 1, file);
|
|
|
164 |
}
|
|
|
165 |
|
|
|
166 |
done:
|
|
|
167 |
gs_free_object(pdev->memory, row, "bmp file buffer");
|
|
|
168 |
|
|
|
169 |
return code;
|
|
|
170 |
}
|
|
|
171 |
|
|
|
172 |
/* Write out a page in separated CMYK format. */
|
|
|
173 |
/* This routine is used for all formats. */
|
|
|
174 |
private int
|
|
|
175 |
bmp_cmyk_print_page(gx_device_printer * pdev, FILE * file)
|
|
|
176 |
{
|
|
|
177 |
int plane_depth = pdev->color_info.depth / 4;
|
|
|
178 |
uint raster = (pdev->width * plane_depth + 7) >> 3;
|
|
|
179 |
/* BMP scan lines are padded to 32 bits. */
|
|
|
180 |
uint bmp_raster = raster + (-(int)raster & 3);
|
|
|
181 |
byte *row = gs_alloc_bytes(pdev->memory, bmp_raster, "bmp file buffer");
|
|
|
182 |
int y;
|
|
|
183 |
int code = 0; /* return code */
|
|
|
184 |
int plane;
|
|
|
185 |
|
|
|
186 |
if (row == 0) /* can't allocate row buffer */
|
|
|
187 |
return_error(gs_error_VMerror);
|
|
|
188 |
memset(row+raster, 0, bmp_raster - raster); /* clear the padding bytes */
|
|
|
189 |
|
|
|
190 |
for (plane = 0; plane <= 3; ++plane) {
|
|
|
191 |
gx_render_plane_t render_plane;
|
|
|
192 |
|
|
|
193 |
/* Write the page header. */
|
|
|
194 |
|
|
|
195 |
code = write_bmp_separated_header(pdev, file);
|
|
|
196 |
if (code < 0)
|
|
|
197 |
break;
|
|
|
198 |
|
|
|
199 |
/* Write the contents of the image. */
|
|
|
200 |
/* BMP files want the image in bottom-to-top order! */
|
|
|
201 |
|
|
|
202 |
gx_render_plane_init(&render_plane, (gx_device *)pdev, plane);
|
|
|
203 |
for (y = pdev->height - 1; y >= 0; y--) {
|
|
|
204 |
byte *actual_data;
|
|
|
205 |
uint actual_raster;
|
|
|
206 |
|
|
|
207 |
code = gdev_prn_get_lines(pdev, y, 1, row, bmp_raster,
|
|
|
208 |
&actual_data, &actual_raster,
|
|
|
209 |
&render_plane);
|
|
|
210 |
if (code < 0)
|
|
|
211 |
goto done;
|
|
|
212 |
fwrite((const char *)actual_data, bmp_raster, 1, file);
|
|
|
213 |
}
|
|
|
214 |
}
|
|
|
215 |
|
|
|
216 |
done:
|
|
|
217 |
gs_free_object(pdev->memory, row, "bmp file buffer");
|
|
|
218 |
|
|
|
219 |
return code;
|
|
|
220 |
}
|