Mon, 14 Dec 2009 16:17:02 +0000
change VERSION to 0.33-philpem1
1 /*
2 * tumble: build a PDF file from image files
3 *
4 * Copyright 2004 Daniel Gloeckner
5 *
6 * Derived from tumble_jpeg.c written 2003 by Eric Smith <eric at brouhaha.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation. Note that permission is
11 * not granted to redistribute this program under the terms of any
12 * other version of the General Public License.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
22 */
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <strings.h> /* strcasecmp() is a BSDism */
32 #include "semantics.h"
33 #include "tumble.h"
34 #include "bitblt.h"
35 #include "pdf.h"
36 #include "tumble_input.h"
39 static bool match_jp2_suffix (char *suffix)
40 {
41 return (strcasecmp (suffix, ".jp2") == 0);
42 }
44 static bool close_jp2_input_file (void)
45 {
46 return (1);
47 }
49 static struct {
50 FILE *f;
51 uint32_t width,height;
52 struct {
53 double VR,HR;
54 } res[2];
55 } jp2info;
57 struct box {
58 char TBox[4];
59 bool (*func)(uint64_t size, void *cparam);
60 void *cparam;
61 };
63 #define BE32(p) (((p)[0]<<24)+((p)[1]<<16)+((p)[2]<<8)+(p)[3])
64 #define BE16(p) (((p)[2]<<8)+(p)[3])
66 static bool skipbox(uint64_t size, void *cparam)
67 {
68 if(size==~0)
69 fseek(jp2info.f,0,SEEK_END);
70 else {
71 if(cparam)
72 size-=*(int *)cparam;
73 fseek(jp2info.f,size,SEEK_CUR); /*FIXME: size is 64bit*/
74 }
75 return 1;
76 }
78 static bool read_res(uint64_t size, void *cparam)
79 {
80 int read=0;
81 bool ret=1;
82 if(size>=10) {
83 int i;
84 unsigned char buf[10];
86 ret=0;
87 i=(int)cparam;
88 read=fread(buf,1,10,jp2info.f);
89 if(read==10) {
90 uint16_t vrn,vrd,hrn,hrd;
91 int8_t vre,hre;
92 vrn=BE16(buf);
93 vrd=BE16(buf+2);
94 hrn=BE16(buf+4);
95 hrd=BE16(buf+6);
96 vre=((signed char *)buf)[8];
97 hre=((signed char *)buf)[9];
98 if(vrn && vrd && hrn && hrd) {
99 jp2info.res[i].VR=vrn*pow(10.0,vre)/vrd;
100 jp2info.res[i].HR=hrn*pow(10.0,hre)/hrd;
101 ret=1;
102 }
103 }
104 }
105 skipbox(size,&read);
106 return ret;
107 }
109 static bool read_ihdr(uint64_t size, void *cparam)
110 {
111 int read=0;
112 bool ret=1;
113 if(size>=8) {
114 unsigned char buf[8];
115 read=fread(buf,1,8,jp2info.f);
116 if(read==8) {
117 jp2info.height=BE32(buf);
118 jp2info.width=BE32(buf+4);
119 } else
120 ret=0;
121 }
122 skipbox(size,&read);
123 return ret;
124 }
126 static bool superbox(uint64_t size, void *cparam)
127 {
128 while(size>=8) {
129 static unsigned char buf[12];
130 int r;
131 uint64_t s;
132 struct box *l;
134 r=fread(buf+4,1,8,jp2info.f);
135 if(r<8)
136 return (size==~0 && r==0);
138 s=BE32(buf+4);
139 if(s==1 && size>=16) {
140 r=fread(buf,1,8,jp2info.f);
141 if(r<8)
142 return 0;
143 s=((uint64_t)BE32(buf)<<32)+BE32(buf+4);
144 }
145 if(s && s<8)
146 return 0;
147 if(size!=~0) {
148 if(!s)
149 return 0;
150 size-=s;
151 } else if(!s)
152 size=0;
153 s=s?s-8:~0;
155 for(l=(struct box *)cparam;l->func;l++)
156 if(!memcmp(l->TBox,buf+8,4))
157 break;
158 if(l->func) {
159 if(!l->func(s,l->cparam))
160 return 0;
161 }else
162 if(!skipbox(s,NULL))
163 return 0;
164 }
166 return size==0;
167 }
169 static const struct box res_boxes[]={
170 {"resc",read_res,(void *)0},
171 {"resd",read_res,(void *)1},
172 {"",NULL,NULL}
173 };
175 static const struct box jp2h_boxes[]={
176 {"ihdr",read_ihdr,NULL},
177 {"res ",superbox,(void *)res_boxes},
178 {"",NULL,NULL}
179 };
181 static const struct box root[]={
182 {"jp2h",superbox,(void *)jp2h_boxes},
183 {"",NULL,NULL}
184 };
186 static bool open_jp2_input_file (FILE *f, char *name)
187 {
188 int s;
189 const char sig[12]="\0\0\0\xCjP \r\n\x87\n";
190 char buf[12];
192 memset(&jp2info,0,sizeof(jp2info));
193 jp2info.f=f;
195 s=fread(buf,1,12,f);
196 rewind(f);
197 return (s==12 && !memcmp(buf,sig,12));
198 }
201 static bool last_jp2_input_page (void)
202 {
203 return 1;
204 }
207 static bool get_jp2_image_info (int image,
208 input_attributes_t input_attributes,
209 image_info_t *image_info)
210 {
211 int i;
213 if(!superbox(~0,(void *)root))
214 return 0;
215 rewind(jp2info.f);
217 #ifdef DEBUG_JPEG
218 printf ("capture x density: %d pixel/m\n", jp2info.res[0].HR);
219 printf ("capture y density: %d pixel/m\n", jp2info.res[0].VR);
220 printf ("display x density: %d pixel/m\n", jp2info.res[1].HR);
221 printf ("display y density: %d pixel/m\n", jp2info.res[1].VR);
222 printf ("width: %d\n", jp2info.width);
223 printf ("height: %d\n", jp2info.height);
224 #endif
226 image_info->color = 1;
227 image_info->width_samples = jp2info.width;
228 image_info->height_samples = jp2info.height;
230 image_info->width_points = (image_info->width_samples * POINTS_PER_INCH) / 300.0;
231 image_info->height_points = (image_info->height_samples * POINTS_PER_INCH) / 300.0;
233 for(i=2;i--;)
234 if(jp2info.res[i].VR > 0.0 && jp2info.res[i].HR > 0.0) {
235 image_info->width_points = (image_info->width_samples * POINTS_PER_INCH * 10000)/(jp2info.res[i].HR * 254);
236 image_info->height_points = (image_info->height_samples * POINTS_PER_INCH * 10000)/(jp2info.res[i].VR * 254);
237 break;
238 }
240 return 1;
241 }
244 static bool process_jp2_image (int image, /* range 1 .. n */
245 input_attributes_t input_attributes,
246 image_info_t *image_info,
247 pdf_page_handle page)
248 {
249 pdf_write_jp2_image (page,
250 0, 0, /* x, y */
251 image_info->width_points,
252 image_info->height_points,
253 image_info->width_samples,
254 image_info->height_samples,
255 jp2info.f);
257 return (1);
258 }
261 input_handler_t jp2_handler =
262 {
263 match_jp2_suffix,
264 open_jp2_input_file,
265 close_jp2_input_file,
266 last_jp2_input_page,
267 get_jp2_image_info,
268 process_jp2_image
269 };
272 void init_jp2_handler (void)
273 {
274 install_input_handler (& jp2_handler);
275 }