|
1 #include <cstring> |
|
2 #include <cstdio> |
|
3 |
|
4 extern "C" |
|
5 { |
|
6 #include <stdio.h> |
|
7 #include <jpeglib.h> |
|
8 } |
|
9 |
|
10 #include "FloatPlane.h" |
|
11 #include "Image.h" |
|
12 #include "JPEGFile.h" |
|
13 |
|
14 JPEGFile::JPEGFile(const char *_filename) |
|
15 { |
|
16 using namespace std; |
|
17 filename = new char[std::strlen(_filename) + 1]; |
|
18 std::strcpy(filename, _filename); |
|
19 srcinfo = new jpeg_decompress_struct; |
|
20 jsrcerr = new jpeg_error_mgr; |
|
21 } |
|
22 |
|
23 void JPEGFile::readHeader() |
|
24 { |
|
25 srcinfo->err = jpeg_std_error(jsrcerr); |
|
26 |
|
27 jpeg_create_decompress(srcinfo); |
|
28 |
|
29 inputh = fopen(filename, "rb"); |
|
30 |
|
31 jpeg_stdio_src(srcinfo, inputh); |
|
32 jpeg_read_header(srcinfo, TRUE); |
|
33 } |
|
34 |
|
35 Image *JPEGFile::getiDCTImage() |
|
36 { |
|
37 readHeader(); |
|
38 |
|
39 /* Set our JPEG decompression parameters */ |
|
40 srcinfo->dct_method = JDCT_FLOAT; |
|
41 |
|
42 /* jpeglib don't do any postprocessing (scaling/colorq). */ |
|
43 srcinfo->raw_data_out = TRUE; |
|
44 |
|
45 /* Start decompression of pixels */ |
|
46 jpeg_start_decompress(srcinfo); |
|
47 |
|
48 unsigned int nplanes = srcinfo->num_components; |
|
49 |
|
50 /* Create the planes */ |
|
51 FloatPlane *planes = new FloatPlane[nplanes]; |
|
52 unsigned int width[nplanes]; |
|
53 unsigned int height[nplanes]; |
|
54 unsigned int max_width_in_blocks = 0; |
|
55 |
|
56 /* Get the pointers to the planes */ |
|
57 float *bmp[srcinfo->out_color_components]; |
|
58 for (unsigned int i=0; i < nplanes; i++) |
|
59 { |
|
60 /* get the dimensions for every plane*/ |
|
61 width[i] = srcinfo->comp_info[i].downsampled_width; |
|
62 height[i] = srcinfo->comp_info[i].downsampled_height; |
|
63 |
|
64 if (srcinfo->comp_info[i].width_in_blocks > max_width_in_blocks) |
|
65 max_width_in_blocks = srcinfo->comp_info[i].width_in_blocks; |
|
66 /* Allocate and prepare bmp[] */ |
|
67 planes[i].allocate(width[i], height[i]); |
|
68 bmp[i] = planes[i].ptr; |
|
69 } |
|
70 |
|
71 /* The function jpeg_read_raw_data will return an MCU per call */ |
|
72 int nscanlines = srcinfo->max_v_samp_factor*DCTSIZE; |
|
73 |
|
74 /* Get memory for the buffer scanline pointers */ |
|
75 JSAMPARRAY *scanplanes = new JSAMPARRAY[nplanes]; |
|
76 |
|
77 /* Get memory for each scanline in the buffer */ |
|
78 for (unsigned int plane = 0; plane < nplanes; ++plane) |
|
79 { |
|
80 scanplanes[plane] = new JSAMPROW[nscanlines]; |
|
81 for (int isl = 0; isl < nscanlines; ++isl) |
|
82 scanplanes[plane][isl] = new JSAMPLE[max_width_in_blocks * DCTSIZE]; |
|
83 } |
|
84 |
|
85 unsigned int row[nplanes]; |
|
86 unsigned int div_v_factor[nplanes]; |
|
87 for (unsigned int plane = 0; plane < nplanes; ++plane) |
|
88 { |
|
89 row[plane] = 0; |
|
90 div_v_factor[plane] = srcinfo->max_v_samp_factor / |
|
91 srcinfo->comp_info[plane].v_samp_factor; |
|
92 } |
|
93 |
|
94 while (srcinfo->output_scanline < srcinfo->output_height) { |
|
95 int read_scanlines = |
|
96 jpeg_read_raw_data(srcinfo, scanplanes, nscanlines); |
|
97 for (unsigned int plane = 0; plane < nplanes; ++plane) |
|
98 { |
|
99 if (row[plane] >= height[plane]) |
|
100 continue; |
|
101 for (int isl = 0; isl < (read_scanlines / (int) div_v_factor[plane]); ++isl) |
|
102 { |
|
103 for (unsigned int column = 0; column < width[plane]; |
|
104 ++column) { |
|
105 bmp[plane][row[plane] * width[plane] + column] = |
|
106 scanplanes[plane][isl][column]; |
|
107 } |
|
108 ++row[plane]; |
|
109 } |
|
110 } |
|
111 } |
|
112 |
|
113 jpeg_destroy_decompress(srcinfo); |
|
114 |
|
115 fclose(inputh); |
|
116 |
|
117 Image *i = new Image(planes, nplanes); |
|
118 |
|
119 delete[] planes; |
|
120 for (unsigned int plane = 0; plane < nplanes; ++plane) |
|
121 { |
|
122 for (int isl = 0; isl < nscanlines; ++isl) |
|
123 delete[] scanplanes[plane][isl]; |
|
124 delete[] scanplanes[plane]; |
|
125 } |
|
126 delete[] scanplanes; |
|
127 |
|
128 return i; |
|
129 } |
|
130 |
|
131 Image *JPEGFile::getUnpackedImage() |
|
132 { |
|
133 readHeader(); |
|
134 |
|
135 /* Set our JPEG decompression parameters */ |
|
136 srcinfo->do_fancy_upsampling = 1; |
|
137 srcinfo->dct_method = JDCT_FLOAT; |
|
138 |
|
139 /* Get the number of planes */ |
|
140 if (srcinfo->num_components == 1 && |
|
141 srcinfo->jpeg_color_space == JCS_GRAYSCALE) { |
|
142 srcinfo->out_color_components = 1; |
|
143 srcinfo->out_color_space = JCS_GRAYSCALE; |
|
144 } |
|
145 else { |
|
146 srcinfo->out_color_components = 3; |
|
147 srcinfo->out_color_space = JCS_RGB; |
|
148 } |
|
149 |
|
150 /* Start decompression of pixels */ |
|
151 jpeg_start_decompress(srcinfo); |
|
152 |
|
153 unsigned int nplanes = srcinfo->out_color_components; |
|
154 |
|
155 /* Create the planes */ |
|
156 FloatPlane *planes = new FloatPlane[nplanes]; |
|
157 |
|
158 /* Get the pointers to the planes */ |
|
159 float *bmp[srcinfo->out_color_components]; |
|
160 for (unsigned int i=0; i < nplanes; i++) |
|
161 { |
|
162 planes[i].allocate(srcinfo->output_width, srcinfo->output_height); |
|
163 bmp[i] = planes[i].ptr; |
|
164 } |
|
165 |
|
166 /* Get the recommended number of buffer scanlines */ |
|
167 int nscanlines = srcinfo->rec_outbuf_height; |
|
168 |
|
169 /* Get memory for the buffer scanline pointers */ |
|
170 JSAMPROW *scanlines = new JSAMPROW[nscanlines]; |
|
171 |
|
172 /* Get memory for each scanline in the buffer */ |
|
173 for (int isl = 0; isl < nscanlines; ++isl) |
|
174 { |
|
175 scanlines[isl] = new JSAMPLE[srcinfo->output_width * nplanes]; |
|
176 } |
|
177 |
|
178 int row = 0; |
|
179 while (srcinfo->output_scanline < srcinfo->output_height) { |
|
180 int read_scanlines = |
|
181 jpeg_read_scanlines(srcinfo, scanlines, nscanlines); |
|
182 for (int isl = 0; isl < read_scanlines; ++isl) |
|
183 { |
|
184 for (unsigned int column = 0; column < srcinfo->output_width; |
|
185 ++column) { |
|
186 for (unsigned int plane = 0; plane < nplanes; plane++) |
|
187 bmp[plane][row * srcinfo->output_width + column] = |
|
188 scanlines[isl][column * srcinfo->out_color_components |
|
189 + plane]; |
|
190 } |
|
191 ++row; |
|
192 } |
|
193 } |
|
194 |
|
195 jpeg_destroy_decompress(srcinfo); |
|
196 |
|
197 fclose(inputh); |
|
198 |
|
199 Image *i = new Image(planes, nplanes); |
|
200 |
|
201 delete[] planes; |
|
202 for (int isl = 0; isl < nscanlines; ++isl) |
|
203 delete[] scanlines[isl]; |
|
204 delete[] scanlines; |
|
205 |
|
206 return i; |
|
207 } |
|
208 |
|
209 JPEGFile::~JPEGFile() |
|
210 { |
|
211 delete[] filename; |
|
212 delete srcinfo; |
|
213 delete jsrcerr; |
|
214 } |