Tue, 25 Mar 2003 09:36:56 +0000
*** empty log message ***
1 /*
2 * tumble: build a PDF file from image files
3 *
4 * $Id: tumble_jpeg.c,v 1.4 2003/03/20 06:55:27 eric Exp $
5 * Copyright 2003 Eric Smith <eric@brouhaha.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. Note that permission is
10 * not granted to redistribute this program under the terms of any
11 * other version of the General Public License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
21 */
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <strings.h> /* strcasecmp() is a BSDism */
28 #include <jpeglib.h>
31 #include "semantics.h"
32 #include "tumble.h"
33 #include "bitblt.h"
34 #include "pdf.h"
35 #include "tumble_input.h"
38 static FILE *jpeg_f;
40 static struct jpeg_decompress_struct cinfo;
41 static struct jpeg_error_mgr jerr;
44 static bool match_jpeg_suffix (char *suffix)
45 {
46 return ((strcasecmp (suffix, ".jpg") == 0) ||
47 (strcasecmp (suffix, ".jpeg") == 0));
48 }
50 static bool close_jpeg_input_file (void)
51 {
52 return (1);
53 }
56 static bool open_jpeg_input_file (FILE *f, char *name)
57 {
58 uint8_t buf [2];
59 size_t l;
61 l = fread (& buf [0], 1, sizeof (buf), f);
62 if (l != sizeof (buf))
63 return (0);
65 rewind (f);
67 if ((buf [0] != 0xff) || (buf [1] != 0xd8))
68 return (0);
70 cinfo.err = jpeg_std_error (& jerr);
71 jpeg_create_decompress (& cinfo);
73 jpeg_stdio_src (& cinfo, f);
75 jpeg_read_header (& cinfo, TRUE);
77 rewind (f);
79 jpeg_f = f;
81 return (1);
82 }
85 static bool last_jpeg_input_page (void)
86 {
87 return (1);
88 }
91 static bool get_jpeg_image_info (int image,
92 input_attributes_t input_attributes,
93 image_info_t *image_info)
94 {
95 double unit;
97 #ifdef DEBUG_JPEG
98 printf ("color space: %d\n", cinfo.jpeg_color_space);
99 printf ("components: %d\n", cinfo.num_components);
100 printf ("density unit: %d\n", cinfo.density_unit);
101 printf ("x density: %d\n", cinfo.X_density);
102 printf ("y density: %d\n", cinfo.Y_density);
103 printf ("width: %d\n", cinfo.image_width);
104 printf ("height: %d\n", cinfo.image_height);
105 #endif
107 switch (cinfo.jpeg_color_space)
108 {
109 case JCS_GRAYSCALE:
110 if (cinfo.num_components != 1)
111 {
112 fprintf (stderr, "JPEG grayscale image has %d components, should have 1\n",
113 cinfo.num_components);
114 return (0);
115 }
116 image_info->color = 0;
117 break;
118 case JCS_RGB:
119 case JCS_YCbCr:
120 if (cinfo.num_components != 3)
121 {
122 fprintf (stderr, "JPEG RGB or YCbCr image has %d components, should have 3\n",
123 cinfo.num_components);
124 return (0);
125 }
126 image_info->color = 1;
127 break;
128 default:
129 fprintf (stderr, "JPEG color space %d not supported\n", cinfo.jpeg_color_space);
130 return (0);
131 }
132 image_info->width_samples = cinfo.image_width;
133 image_info->height_samples = cinfo.image_height;
135 if (cinfo.saw_JFIF_marker & cinfo.density_unit)
136 {
137 switch (cinfo.density_unit)
138 {
139 case 1: /* samples per inch */
140 unit = 1.0;
141 break;
142 case 2: /* samples per cm */
143 unit = 2.54;
144 break;
145 default:
146 fprintf (stderr, "JFIF density unit %d not supported\n", cinfo.density_unit);
147 return (0);
148 }
149 image_info->width_points = ((image_info->width_samples * POINTS_PER_INCH) /
150 (cinfo.X_density * unit));
151 image_info->height_points = ((image_info->height_samples * POINTS_PER_INCH) /
152 (cinfo.Y_density * unit));
153 }
154 else
155 {
156 /* assume 300 DPI - not great, but what else can we do? */
157 image_info->width_points = (image_info->width_samples * POINTS_PER_INCH) / 300.0;
158 image_info->height_points = (image_info->height_samples * POINTS_PER_INCH) / 300.0;
159 }
161 return (1);
162 }
165 static bool process_jpeg_image (int image, /* range 1 .. n */
166 input_attributes_t input_attributes,
167 image_info_t *image_info,
168 pdf_page_handle page)
169 {
170 pdf_write_jpeg_image (page,
171 0, 0, /* x, y */
172 image_info->width_points,
173 image_info->height_points,
174 image_info->color,
175 image_info->width_samples,
176 image_info->height_samples,
177 jpeg_f);
179 return (1);
180 }
183 input_handler_t jpeg_handler =
184 {
185 match_jpeg_suffix,
186 open_jpeg_input_file,
187 close_jpeg_input_file,
188 last_jpeg_input_page,
189 get_jpeg_image_info,
190 process_jpeg_image
191 };
194 void init_jpeg_handler (void)
195 {
196 install_input_handler (& jpeg_handler);
197 }