trunk 20080912
[gitenigma.git] / lib / picviewer / jpeg.cpp
blob53660e87a02fca7cafa8111fa45254b9c112ff20
1 #ifndef DISABLE_FILE
2 #include <lib/picviewer/format_config.h>
3 #ifdef FBV_SUPPORT_JPEG
4 #include <lib/picviewer/pictureviewer.h>
5 #include <fcntl.h>
7 extern "C" {
8 #include <jpeglib.h>
10 #include <setjmp.h>
12 struct r_jpeg_error_mgr
14 struct jpeg_error_mgr pub;
15 jmp_buf envbuffer;
18 int fh_jpeg_id(const char *name)
20 // dbout("fh_jpeg_id {\n");
21 int fd;
22 unsigned char id[10];
23 fd = open(name,O_RDONLY);
24 if (fd == -1)
25 return(0);
26 read(fd, id, 10);
27 close(fd);
28 // dbout("fh_jpeg_id }\n");
29 if (id[6] == 'J' && id[7] == 'F' && id[8] == 'I' && id[9] == 'F')
30 return(1);
31 if (id[0] == 0xff && id[1] == 0xd8 && id[2] == 0xff)
32 return(1);
33 return(0);
36 void jpeg_cb_error_exit(j_common_ptr cinfo)
38 // dbout("jpeg_cd_error_exit {\n");
39 struct r_jpeg_error_mgr *mptr;
40 mptr = (struct r_jpeg_error_mgr *) cinfo->err;
41 (*cinfo->err->output_message) (cinfo);
42 longjmp(mptr->envbuffer, 1);
43 // dbout("jpeg_cd_error_exit }\n");
46 int fh_jpeg_load(const char *filename, unsigned char *buffer, int x, int y)
48 // dbout("fh_jpeg_load (%d/%d) {\n",x,y);
49 struct jpeg_decompress_struct cinfo;
50 struct jpeg_decompress_struct *ciptr;
51 struct r_jpeg_error_mgr emgr;
52 unsigned char *bp;
53 int px, py, c;
54 FILE *fh;
55 JSAMPLE *lb;
57 ciptr = &cinfo;
58 if (!(fh = fopen(filename, "rb")))
59 return(FH_ERROR_FILE);
60 ciptr->err = jpeg_std_error(&emgr.pub);
61 emgr.pub.error_exit = jpeg_cb_error_exit;
62 if (setjmp(emgr.envbuffer) == 1)
64 // FATAL ERROR - Free the object and return...
65 jpeg_destroy_decompress(ciptr);
66 fclose(fh);
67 // dbout("fh_jpeg_load } - FATAL ERROR\n");
68 return(FH_ERROR_FORMAT);
71 jpeg_create_decompress(ciptr);
72 jpeg_stdio_src(ciptr, fh);
73 jpeg_read_header(ciptr, TRUE);
74 ciptr->out_color_space = JCS_RGB;
75 if (x == (int)ciptr->image_width)
76 ciptr->scale_denom = 1;
77 else
78 if (abs(x * 2 - ciptr->image_width) < 2)
79 ciptr->scale_denom = 2;
80 else
81 if (abs(x * 4 - ciptr->image_width) < 4)
82 ciptr->scale_denom = 4;
83 else
84 if (abs(x * 8 - ciptr->image_width) < 8)
85 ciptr->scale_denom = 8;
86 else
87 ciptr->scale_denom = 1;
89 jpeg_start_decompress(ciptr);
91 px = ciptr->output_width; py = ciptr->output_height;
92 c = ciptr->output_components;
94 if (c == 3)
96 lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, c * px);
97 bp = buffer;
98 while (ciptr->output_scanline < ciptr->output_height)
100 jpeg_read_scanlines(ciptr, &lb, 1);
101 memcpy(bp, lb, px * c);
102 bp += px * c;
105 jpeg_finish_decompress(ciptr);
106 jpeg_destroy_decompress(ciptr);
107 fclose(fh);
108 // dbout("fh_jpeg_load }\n");
109 return(FH_ERROR_OK);
112 int fh_jpeg_save (JSAMPLE * image_buffer, char * filename, int quality, int image_height, int image_width)
114 struct jpeg_compress_struct cinfo;
115 struct jpeg_error_mgr jerr;
116 FILE * outfile; /* target file */
117 JSAMPROW row_pointer[1];/* pointer to JSAMPLE row[s] */
118 int row_stride; /* physical row width in image buffer */
120 cinfo.err = jpeg_std_error(&jerr);
121 jpeg_create_compress(&cinfo);
123 if ((outfile = fopen(filename, "wb")) == NULL)
125 eDebug("can't open %s", filename);
126 return -1;
128 jpeg_stdio_dest(&cinfo, outfile);
130 cinfo.image_width = image_width; /* image width and height, in pixels */
131 cinfo.image_height = image_height;
132 cinfo.input_components = 3; /* # of color components per pixel */
133 cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
135 jpeg_set_defaults(&cinfo);
136 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
137 jpeg_start_compress(&cinfo, TRUE);
138 row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
139 while (cinfo.next_scanline < cinfo.image_height)
141 row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
142 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
144 jpeg_finish_compress(&cinfo);
145 fclose(outfile);
146 jpeg_destroy_compress(&cinfo);
147 return 0;
150 int fh_jpeg_getsize(const char *filename, int *x, int *y, int wanted_width, int wanted_height)
152 // dbout("fh_jpeg_getsize {\n");
153 struct jpeg_decompress_struct cinfo;
154 struct jpeg_decompress_struct *ciptr;
155 struct r_jpeg_error_mgr emgr;
157 int px, py, c;
158 FILE *fh;
160 ciptr = &cinfo;
161 if (!(fh = fopen(filename, "rb")))
162 return(FH_ERROR_FILE);
164 ciptr->err = jpeg_std_error(&emgr.pub);
165 emgr.pub.error_exit = jpeg_cb_error_exit;
166 if (setjmp(emgr.envbuffer) == 1)
168 // FATAL ERROR - Free the object and return...
169 jpeg_destroy_decompress(ciptr);
170 fclose(fh);
171 // dbout("fh_jpeg_getsize } - FATAL ERROR\n");
172 return(FH_ERROR_FORMAT);
175 jpeg_create_decompress(ciptr);
176 jpeg_stdio_src(ciptr, fh);
177 jpeg_read_header(ciptr, TRUE);
178 ciptr->out_color_space = JCS_RGB;
179 // should be more flexible...
180 if ((int)ciptr->image_width / 8 >= wanted_width || (int)ciptr->image_height / 8 >= wanted_height)
181 ciptr->scale_denom = 8;
182 else
183 if ((int)ciptr->image_width / 4 >= wanted_width || (int)ciptr->image_height / 4 >= wanted_height)
184 ciptr->scale_denom = 4;
185 else
186 if ((int)ciptr->image_width / 2 >= wanted_width || (int)ciptr->image_height / 2 >= wanted_height)
187 ciptr->scale_denom = 2;
188 else
189 ciptr->scale_denom = 1;
191 jpeg_start_decompress(ciptr);
192 px = ciptr->output_width; py = ciptr->output_height;
193 c = ciptr->output_components;
194 *x = px; *y = py;
195 // jpeg_finish_decompress(ciptr);
196 jpeg_destroy_decompress(ciptr);
197 fclose(fh);
198 // dbout("fh_jpeg_getsize }\n");
199 return(FH_ERROR_OK);
201 #endif
202 #endif