trunk 20080912
[gitenigma.git] / lib / picviewer / crw.cpp
blob4faaff3e5667ce7b3d06b3d50f79874d8197fc2f
1 #ifndef DISABLE_FILE
2 #include <lib/picviewer/format_config.h>
3 #ifdef FBV_SUPPORT_CRW
4 #include <lib/picviewer/pictureviewer.h>
5 #include <fcntl.h>
7 extern "C" {
8 #include <jpeglib.h>
10 #include <setjmp.h>
13 Get a 2-byte integer, making no assumptions about CPU byte order.
14 Nor should we assume that the compiler evaluates left-to-right.
16 unsigned short fget2 (FILE *f, int order)
18 unsigned char a, b;
20 a = fgetc(f);
21 b = fgetc(f);
22 if (order == 0x4949) /* "II" means little-endian */
23 return a + (b << 8);
24 else /* "MM" means big-endian */
25 return (a << 8) + b;
29 Same for a 4-byte integer.
31 int fget4 (FILE *f, int order)
33 unsigned char a, b, c, d;
35 a = fgetc(f);
36 b = fgetc(f);
37 c = fgetc(f);
38 d = fgetc(f);
39 if (order == 0x4949)
40 return a + (b << 8) + (c << 16) + (d << 24);
41 else
42 return (a << 24) + (b << 16) + (c << 8) + d;
45 int fh_crw_parsedirs(FILE *fh, int pos, int length, int order)
47 fseek(fh, pos + length - 4, SEEK_SET);
48 int off = pos + fget4(fh, order);
49 fseek(fh, off, SEEK_SET);
50 int nEntrys = fget2(fh, order);
52 for (int i = 0; i < nEntrys; i++)
54 int type = fget2(fh, order);
55 int len = fget4(fh, order);
56 int roff = fget4(fh, order);
58 switch(type)
60 case 0x2005: // Image
61 break;
62 case 0x2007: // Thumbnail
63 fseek(fh, pos + roff, SEEK_SET);
64 return 1;
65 break;
66 case 0x0810: // Owner
67 break;
68 case 0x0816: // Filename
69 break;
70 case 0x0817: // Thumbname
71 break;
72 case 0x580b: // SerNo.
73 break;
74 case 0x0805: // comment, if subdir 0x300a. "EOS 300D DIGITAL CMOS RAW" if subdir 0x2804
75 break;
76 case 0x080a: // vendor \0 name of the camera
77 break;
78 case 0x080b: // firmware
79 break;
80 case 0x0815:
81 break;
82 case 0x180e: // time
83 break;
84 case 0x102a: // White balance
85 break;
86 case 0x1031: // size of the image
87 break;
88 case 0x1835: // decoder table
89 break;
90 default:
91 if (type >> 8 == 0x28 || type >> 8 == 0x30) // Subdirs
93 if (fh_crw_parsedirs(fh, pos + roff, len, order) == 1)
95 return 1;
100 return 0;
103 void fh_crw_find_jpeg_thumbnail(FILE *fh)
105 char header[26];
106 int order = 0;
107 long fsize = 0;
108 long hlength = 0;
110 fseek (fh, 0, SEEK_SET);
111 fread (header, 1, 26, fh);
112 fseek (fh, 0, SEEK_END);
113 fsize = ftell(fh);
114 fseek (fh, 0, SEEK_SET);
116 order = *((unsigned short *)header);
118 if (order == 0x4949)
119 hlength = header[2] + (header[3] << 8) + (header[4] << 16) + (header[5] << 24);
120 else
121 hlength = (header[2] << 24) + (header[3] << 16) + (header[4] << 8) + header[5];
123 fh_crw_parsedirs(fh, hlength, fsize - hlength, order);
126 struct r_crw_jpeg_error_mgr
128 struct jpeg_error_mgr pub;
129 jmp_buf envbuffer;
132 int fh_crw_id(const char *name)
134 // dbout("fh_crw_id {\n");
135 int fd;
136 unsigned char id[14];
137 fd = open(name, O_RDONLY);
138 if (fd == -1)
139 return(0);
140 read(fd, id, 14);
141 close(fd);
142 // dbout("fh_crw_id }\n");
143 if (id[6] == 'H' && id[7] == 'E' && id[8] == 'A' && id[9] == 'P' &&
144 id[10] == 'C' && id[11] == 'C' && id[12] == 'D' && id[13] == 'R')
145 return(1);
147 return(0);
151 void crw_cb_error_exit(j_common_ptr cinfo)
153 // dbout("crw_cb_error_exit {\n");
154 struct r_crw_jpeg_error_mgr *mptr;
155 mptr = (struct r_crw_jpeg_error_mgr *) cinfo->err;
156 (*cinfo->err->output_message) (cinfo);
157 longjmp(mptr->envbuffer, 1);
158 // dbout("crw_cb_error_exit }\n");
161 int fh_crw_load(const char *filename, unsigned char *buffer, int x, int y)
163 // dbout("fh_crw_load (%d/%d) {\n",x,y);
164 struct jpeg_decompress_struct cinfo;
165 struct jpeg_decompress_struct *ciptr;
166 struct r_crw_jpeg_error_mgr emgr;
167 unsigned char *bp;
168 int px, py, c;
169 FILE *fh;
170 JSAMPLE *lb;
172 ciptr = &cinfo;
173 if (!(fh = fopen(filename, "rb")))
174 return(FH_ERROR_FILE);
175 ciptr->err = jpeg_std_error(&emgr.pub);
176 emgr.pub.error_exit = crw_cb_error_exit;
177 if (setjmp(emgr.envbuffer) == 1)
179 // FATAL ERROR - Free the object and return...
180 jpeg_destroy_decompress(ciptr);
181 fclose(fh);
182 // dbout("fh_crw_load } - FATAL ERROR\n");
183 return(FH_ERROR_FORMAT);
186 jpeg_create_decompress(ciptr);
187 fh_crw_find_jpeg_thumbnail(fh);
188 jpeg_stdio_src(ciptr, fh);
189 jpeg_read_header(ciptr, TRUE);
190 ciptr->out_color_space = JCS_RGB;
191 if (x == (int)ciptr->image_width)
192 ciptr->scale_denom = 1;
193 else
194 if (abs(x * 2 - ciptr->image_width) < 2)
195 ciptr->scale_denom = 2;
196 else
197 if (abs(x * 4 - ciptr->image_width) < 4)
198 ciptr->scale_denom = 4;
199 else
200 if (abs(x * 8 - ciptr->image_width) < 8)
201 ciptr->scale_denom = 8;
202 else
203 ciptr->scale_denom = 1;
205 jpeg_start_decompress(ciptr);
207 px = ciptr->output_width; py = ciptr->output_height;
208 c = ciptr->output_components;
210 if (c == 3)
212 lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, c * px);
213 bp = buffer;
214 while (ciptr->output_scanline < ciptr->output_height)
216 jpeg_read_scanlines(ciptr, &lb, 1);
217 memcpy(bp, lb, px * c);
218 bp += px * c;
221 jpeg_finish_decompress(ciptr);
222 jpeg_destroy_decompress(ciptr);
223 fclose(fh);
224 // dbout("fh_crw_load }\n");
225 return(FH_ERROR_OK);
228 int fh_crw_getsize(const char *filename, int *x, int *y, int wanted_width, int wanted_height)
230 // dbout("fh_crw_getsize {\n");
231 struct jpeg_decompress_struct cinfo;
232 struct jpeg_decompress_struct *ciptr;
233 struct r_crw_jpeg_error_mgr emgr;
235 int px, py, c;
236 FILE *fh;
238 ciptr = &cinfo;
239 if (!(fh = fopen(filename, "rb")))
240 return(FH_ERROR_FILE);
242 ciptr->err = jpeg_std_error(&emgr.pub);
243 emgr.pub.error_exit = crw_cb_error_exit;
244 if (setjmp(emgr.envbuffer) == 1)
246 // FATAL ERROR - Free the object and return...
247 jpeg_destroy_decompress(ciptr);
248 fclose(fh);
249 // dbout("fh_crw_getsize } - FATAL ERROR\n");
250 return(FH_ERROR_FORMAT);
253 jpeg_create_decompress(ciptr);
254 fh_crw_find_jpeg_thumbnail(fh);
255 jpeg_stdio_src(ciptr, fh);
256 jpeg_read_header(ciptr, TRUE);
257 ciptr->out_color_space = JCS_RGB;
258 // should be more flexible...
259 if ((int)ciptr->image_width / 8 >= wanted_width ||
260 (int)ciptr->image_height / 8 >= wanted_height)
261 ciptr->scale_denom = 8;
262 else
263 if ((int)ciptr->image_width / 4 >= wanted_width ||
264 (int)ciptr->image_height / 4 >= wanted_height)
265 ciptr->scale_denom = 4;
266 else
267 if ((int)ciptr->image_width / 2 >= wanted_width ||
268 (int)ciptr->image_height / 2 >= wanted_height)
269 ciptr->scale_denom = 2;
270 else
271 ciptr->scale_denom = 1;
273 jpeg_start_decompress(ciptr);
274 px = ciptr->output_width; py = ciptr->output_height;
275 c = ciptr->output_components;
276 *x = px; *y = py;
277 // jpeg_finish_decompress(ciptr);
278 jpeg_destroy_decompress(ciptr);
279 fclose(fh);
280 // dbout("fh_crw_getsize }\n");
281 return(FH_ERROR_OK);
284 #endif
285 #endif