diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderJPG.cpp | 612 |
1 files changed, 306 insertions, 306 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderJPG.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderJPG.cpp index 8fc5222..877a4d7 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderJPG.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderJPG.cpp | |||
@@ -1,306 +1,306 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "CImageLoaderJPG.h" | 5 | #include "CImageLoaderJPG.h" |
6 | 6 | ||
7 | #ifdef _IRR_COMPILE_WITH_JPG_LOADER_ | 7 | #ifdef _IRR_COMPILE_WITH_JPG_LOADER_ |
8 | 8 | ||
9 | #include "IReadFile.h" | 9 | #include "IReadFile.h" |
10 | #include "CImage.h" | 10 | #include "CImage.h" |
11 | #include "os.h" | 11 | #include "os.h" |
12 | #include "irrString.h" | 12 | #include "irrString.h" |
13 | 13 | ||
14 | namespace irr | 14 | namespace irr |
15 | { | 15 | { |
16 | namespace video | 16 | namespace video |
17 | { | 17 | { |
18 | 18 | ||
19 | // Static members | 19 | // Static members |
20 | io::path CImageLoaderJPG::Filename; | 20 | io::path CImageLoaderJPG::Filename; |
21 | 21 | ||
22 | //! constructor | 22 | //! constructor |
23 | CImageLoaderJPG::CImageLoaderJPG() | 23 | CImageLoaderJPG::CImageLoaderJPG() |
24 | { | 24 | { |
25 | #ifdef _DEBUG | 25 | #ifdef _DEBUG |
26 | setDebugName("CImageLoaderJPG"); | 26 | setDebugName("CImageLoaderJPG"); |
27 | #endif | 27 | #endif |
28 | } | 28 | } |
29 | 29 | ||
30 | 30 | ||
31 | 31 | ||
32 | //! destructor | 32 | //! destructor |
33 | CImageLoaderJPG::~CImageLoaderJPG() | 33 | CImageLoaderJPG::~CImageLoaderJPG() |
34 | { | 34 | { |
35 | } | 35 | } |
36 | 36 | ||
37 | 37 | ||
38 | 38 | ||
39 | //! returns true if the file maybe is able to be loaded by this class | 39 | //! returns true if the file maybe is able to be loaded by this class |
40 | //! based on the file extension (e.g. ".tga") | 40 | //! based on the file extension (e.g. ".tga") |
41 | bool CImageLoaderJPG::isALoadableFileExtension(const io::path& filename) const | 41 | bool CImageLoaderJPG::isALoadableFileExtension(const io::path& filename) const |
42 | { | 42 | { |
43 | return core::hasFileExtension ( filename, "jpg", "jpeg" ); | 43 | return core::hasFileExtension ( filename, "jpg", "jpeg" ); |
44 | } | 44 | } |
45 | 45 | ||
46 | 46 | ||
47 | #ifdef _IRR_COMPILE_WITH_LIBJPEG_ | 47 | #ifdef _IRR_COMPILE_WITH_LIBJPEG_ |
48 | 48 | ||
49 | // struct for handling jpeg errors | 49 | // struct for handling jpeg errors |
50 | struct irr_jpeg_error_mgr | 50 | struct irr_jpeg_error_mgr |
51 | { | 51 | { |
52 | // public jpeg error fields | 52 | // public jpeg error fields |
53 | struct jpeg_error_mgr pub; | 53 | struct jpeg_error_mgr pub; |
54 | 54 | ||
55 | // for longjmp, to return to caller on a fatal error | 55 | // for longjmp, to return to caller on a fatal error |
56 | jmp_buf setjmp_buffer; | 56 | jmp_buf setjmp_buffer; |
57 | }; | 57 | }; |
58 | 58 | ||
59 | void CImageLoaderJPG::init_source (j_decompress_ptr cinfo) | 59 | void CImageLoaderJPG::init_source (j_decompress_ptr cinfo) |
60 | { | 60 | { |
61 | // DO NOTHING | 61 | // DO NOTHING |
62 | } | 62 | } |
63 | 63 | ||
64 | 64 | ||
65 | 65 | ||
66 | boolean CImageLoaderJPG::fill_input_buffer (j_decompress_ptr cinfo) | 66 | boolean CImageLoaderJPG::fill_input_buffer (j_decompress_ptr cinfo) |
67 | { | 67 | { |
68 | // DO NOTHING | 68 | // DO NOTHING |
69 | return 1; | 69 | return 1; |
70 | } | 70 | } |
71 | 71 | ||
72 | 72 | ||
73 | 73 | ||
74 | void CImageLoaderJPG::skip_input_data (j_decompress_ptr cinfo, long count) | 74 | void CImageLoaderJPG::skip_input_data (j_decompress_ptr cinfo, long count) |
75 | { | 75 | { |
76 | jpeg_source_mgr * src = cinfo->src; | 76 | jpeg_source_mgr * src = cinfo->src; |
77 | if(count > 0) | 77 | if(count > 0) |
78 | { | 78 | { |
79 | src->bytes_in_buffer -= count; | 79 | src->bytes_in_buffer -= count; |
80 | src->next_input_byte += count; | 80 | src->next_input_byte += count; |
81 | } | 81 | } |
82 | } | 82 | } |
83 | 83 | ||
84 | 84 | ||
85 | 85 | ||
86 | void CImageLoaderJPG::term_source (j_decompress_ptr cinfo) | 86 | void CImageLoaderJPG::term_source (j_decompress_ptr cinfo) |
87 | { | 87 | { |
88 | // DO NOTHING | 88 | // DO NOTHING |
89 | } | 89 | } |
90 | 90 | ||
91 | 91 | ||
92 | void CImageLoaderJPG::error_exit (j_common_ptr cinfo) | 92 | void CImageLoaderJPG::error_exit (j_common_ptr cinfo) |
93 | { | 93 | { |
94 | // unfortunately we need to use a goto rather than throwing an exception | 94 | // unfortunately we need to use a goto rather than throwing an exception |
95 | // as gcc crashes under linux crashes when using throw from within | 95 | // as gcc crashes under linux crashes when using throw from within |
96 | // extern c code | 96 | // extern c code |
97 | 97 | ||
98 | // Always display the message | 98 | // Always display the message |
99 | (*cinfo->err->output_message) (cinfo); | 99 | (*cinfo->err->output_message) (cinfo); |
100 | 100 | ||
101 | // cinfo->err really points to a irr_error_mgr struct | 101 | // cinfo->err really points to a irr_error_mgr struct |
102 | irr_jpeg_error_mgr *myerr = (irr_jpeg_error_mgr*) cinfo->err; | 102 | irr_jpeg_error_mgr *myerr = (irr_jpeg_error_mgr*) cinfo->err; |
103 | 103 | ||
104 | longjmp(myerr->setjmp_buffer, 1); | 104 | longjmp(myerr->setjmp_buffer, 1); |
105 | } | 105 | } |
106 | 106 | ||
107 | 107 | ||
108 | void CImageLoaderJPG::output_message(j_common_ptr cinfo) | 108 | void CImageLoaderJPG::output_message(j_common_ptr cinfo) |
109 | { | 109 | { |
110 | // display the error message. | 110 | // display the error message. |
111 | c8 temp1[JMSG_LENGTH_MAX]; | 111 | c8 temp1[JMSG_LENGTH_MAX]; |
112 | (*cinfo->err->format_message)(cinfo, temp1); | 112 | (*cinfo->err->format_message)(cinfo, temp1); |
113 | core::stringc errMsg("JPEG FATAL ERROR in "); | 113 | core::stringc errMsg("JPEG FATAL ERROR in "); |
114 | errMsg += core::stringc(Filename); | 114 | errMsg += core::stringc(Filename); |
115 | os::Printer::log(errMsg.c_str(),temp1, ELL_ERROR); | 115 | os::Printer::log(errMsg.c_str(),temp1, ELL_ERROR); |
116 | } | 116 | } |
117 | #endif // _IRR_COMPILE_WITH_LIBJPEG_ | 117 | #endif // _IRR_COMPILE_WITH_LIBJPEG_ |
118 | 118 | ||
119 | //! returns true if the file maybe is able to be loaded by this class | 119 | //! returns true if the file maybe is able to be loaded by this class |
120 | bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const | 120 | bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const |
121 | { | 121 | { |
122 | #ifndef _IRR_COMPILE_WITH_LIBJPEG_ | 122 | #ifndef _IRR_COMPILE_WITH_LIBJPEG_ |
123 | return false; | 123 | return false; |
124 | #else | 124 | #else |
125 | 125 | ||
126 | if (!file) | 126 | if (!file) |
127 | return false; | 127 | return false; |
128 | 128 | ||
129 | s32 jfif = 0; | 129 | s32 jfif = 0; |
130 | file->seek(6); | 130 | file->seek(6); |
131 | file->read(&jfif, sizeof(s32)); | 131 | file->read(&jfif, sizeof(s32)); |
132 | return (jfif == 0x4a464946 || jfif == 0x4649464a); | 132 | return (jfif == 0x4a464946 || jfif == 0x4649464a); |
133 | 133 | ||
134 | #endif | 134 | #endif |
135 | } | 135 | } |
136 | 136 | ||
137 | //! creates a surface from the file | 137 | //! creates a surface from the file |
138 | IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const | 138 | IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const |
139 | { | 139 | { |
140 | #ifndef _IRR_COMPILE_WITH_LIBJPEG_ | 140 | #ifndef _IRR_COMPILE_WITH_LIBJPEG_ |
141 | os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_:", file->getFileName(), ELL_DEBUG); | 141 | os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_:", file->getFileName(), ELL_DEBUG); |
142 | return 0; | 142 | return 0; |
143 | #else | 143 | #else |
144 | 144 | ||
145 | if (!file) | 145 | if (!file) |
146 | return 0; | 146 | return 0; |
147 | 147 | ||
148 | Filename = file->getFileName(); | 148 | Filename = file->getFileName(); |
149 | 149 | ||
150 | u8 **rowPtr=0; | 150 | u8 **rowPtr=0; |
151 | u8* input = new u8[file->getSize()]; | 151 | u8* input = new u8[file->getSize()]; |
152 | file->read(input, file->getSize()); | 152 | file->read(input, file->getSize()); |
153 | 153 | ||
154 | // allocate and initialize JPEG decompression object | 154 | // allocate and initialize JPEG decompression object |
155 | struct jpeg_decompress_struct cinfo; | 155 | struct jpeg_decompress_struct cinfo; |
156 | struct irr_jpeg_error_mgr jerr; | 156 | struct irr_jpeg_error_mgr jerr; |
157 | 157 | ||
158 | //We have to set up the error handler first, in case the initialization | 158 | //We have to set up the error handler first, in case the initialization |
159 | //step fails. (Unlikely, but it could happen if you are out of memory.) | 159 | //step fails. (Unlikely, but it could happen if you are out of memory.) |
160 | //This routine fills in the contents of struct jerr, and returns jerr's | 160 | //This routine fills in the contents of struct jerr, and returns jerr's |
161 | //address which we place into the link field in cinfo. | 161 | //address which we place into the link field in cinfo. |
162 | 162 | ||
163 | cinfo.err = jpeg_std_error(&jerr.pub); | 163 | cinfo.err = jpeg_std_error(&jerr.pub); |
164 | cinfo.err->error_exit = error_exit; | 164 | cinfo.err->error_exit = error_exit; |
165 | cinfo.err->output_message = output_message; | 165 | cinfo.err->output_message = output_message; |
166 | 166 | ||
167 | // compatibility fudge: | 167 | // compatibility fudge: |
168 | // we need to use setjmp/longjmp for error handling as gcc-linux | 168 | // we need to use setjmp/longjmp for error handling as gcc-linux |
169 | // crashes when throwing within external c code | 169 | // crashes when throwing within external c code |
170 | if (setjmp(jerr.setjmp_buffer)) | 170 | if (setjmp(jerr.setjmp_buffer)) |
171 | { | 171 | { |
172 | // If we get here, the JPEG code has signaled an error. | 172 | // If we get here, the JPEG code has signaled an error. |
173 | // We need to clean up the JPEG object and return. | 173 | // We need to clean up the JPEG object and return. |
174 | 174 | ||
175 | jpeg_destroy_decompress(&cinfo); | 175 | jpeg_destroy_decompress(&cinfo); |
176 | 176 | ||
177 | delete [] input; | 177 | delete [] input; |
178 | // if the row pointer was created, we delete it. | 178 | // if the row pointer was created, we delete it. |
179 | if (rowPtr) | 179 | if (rowPtr) |
180 | delete [] rowPtr; | 180 | delete [] rowPtr; |
181 | 181 | ||
182 | // return null pointer | 182 | // return null pointer |
183 | return 0; | 183 | return 0; |
184 | } | 184 | } |
185 | 185 | ||
186 | // Now we can initialize the JPEG decompression object. | 186 | // Now we can initialize the JPEG decompression object. |
187 | jpeg_create_decompress(&cinfo); | 187 | jpeg_create_decompress(&cinfo); |
188 | 188 | ||
189 | // specify data source | 189 | // specify data source |
190 | jpeg_source_mgr jsrc; | 190 | jpeg_source_mgr jsrc; |
191 | 191 | ||
192 | // Set up data pointer | 192 | // Set up data pointer |
193 | jsrc.bytes_in_buffer = file->getSize(); | 193 | jsrc.bytes_in_buffer = file->getSize(); |
194 | jsrc.next_input_byte = (JOCTET*)input; | 194 | jsrc.next_input_byte = (JOCTET*)input; |
195 | cinfo.src = &jsrc; | 195 | cinfo.src = &jsrc; |
196 | 196 | ||
197 | jsrc.init_source = init_source; | 197 | jsrc.init_source = init_source; |
198 | jsrc.fill_input_buffer = fill_input_buffer; | 198 | jsrc.fill_input_buffer = fill_input_buffer; |
199 | jsrc.skip_input_data = skip_input_data; | 199 | jsrc.skip_input_data = skip_input_data; |
200 | jsrc.resync_to_restart = jpeg_resync_to_restart; | 200 | jsrc.resync_to_restart = jpeg_resync_to_restart; |
201 | jsrc.term_source = term_source; | 201 | jsrc.term_source = term_source; |
202 | 202 | ||
203 | // Decodes JPG input from whatever source | 203 | // Decodes JPG input from whatever source |
204 | // Does everything AFTER jpeg_create_decompress | 204 | // Does everything AFTER jpeg_create_decompress |
205 | // and BEFORE jpeg_destroy_decompress | 205 | // and BEFORE jpeg_destroy_decompress |
206 | // Caller is responsible for arranging these + setting up cinfo | 206 | // Caller is responsible for arranging these + setting up cinfo |
207 | 207 | ||
208 | // read file parameters with jpeg_read_header() | 208 | // read file parameters with jpeg_read_header() |
209 | jpeg_read_header(&cinfo, TRUE); | 209 | jpeg_read_header(&cinfo, TRUE); |
210 | 210 | ||
211 | bool useCMYK=false; | 211 | bool useCMYK=false; |
212 | if (cinfo.jpeg_color_space==JCS_CMYK) | 212 | if (cinfo.jpeg_color_space==JCS_CMYK) |
213 | { | 213 | { |
214 | cinfo.out_color_space=JCS_CMYK; | 214 | cinfo.out_color_space=JCS_CMYK; |
215 | cinfo.out_color_components=4; | 215 | cinfo.out_color_components=4; |
216 | useCMYK=true; | 216 | useCMYK=true; |
217 | } | 217 | } |
218 | else | 218 | else |
219 | { | 219 | { |
220 | cinfo.out_color_space=JCS_RGB; | 220 | cinfo.out_color_space=JCS_RGB; |
221 | cinfo.out_color_components=3; | 221 | cinfo.out_color_components=3; |
222 | } | 222 | } |
223 | cinfo.output_gamma=2.2; | 223 | cinfo.output_gamma=2.2; |
224 | cinfo.do_fancy_upsampling=FALSE; | 224 | cinfo.do_fancy_upsampling=FALSE; |
225 | 225 | ||
226 | // Start decompressor | 226 | // Start decompressor |
227 | jpeg_start_decompress(&cinfo); | 227 | jpeg_start_decompress(&cinfo); |
228 | 228 | ||
229 | // Get image data | 229 | // Get image data |
230 | u16 rowspan = cinfo.image_width * cinfo.out_color_components; | 230 | u16 rowspan = cinfo.image_width * cinfo.out_color_components; |
231 | u32 width = cinfo.image_width; | 231 | u32 width = cinfo.image_width; |
232 | u32 height = cinfo.image_height; | 232 | u32 height = cinfo.image_height; |
233 | 233 | ||
234 | // Allocate memory for buffer | 234 | // Allocate memory for buffer |
235 | u8* output = new u8[rowspan * height]; | 235 | u8* output = new u8[rowspan * height]; |
236 | 236 | ||
237 | // Here we use the library's state variable cinfo.output_scanline as the | 237 | // Here we use the library's state variable cinfo.output_scanline as the |
238 | // loop counter, so that we don't have to keep track ourselves. | 238 | // loop counter, so that we don't have to keep track ourselves. |
239 | // Create array of row pointers for lib | 239 | // Create array of row pointers for lib |
240 | rowPtr = new u8* [height]; | 240 | rowPtr = new u8* [height]; |
241 | 241 | ||
242 | for( u32 i = 0; i < height; i++ ) | 242 | for( u32 i = 0; i < height; i++ ) |
243 | rowPtr[i] = &output[ i * rowspan ]; | 243 | rowPtr[i] = &output[ i * rowspan ]; |
244 | 244 | ||
245 | u32 rowsRead = 0; | 245 | u32 rowsRead = 0; |
246 | 246 | ||
247 | while( cinfo.output_scanline < cinfo.output_height ) | 247 | while( cinfo.output_scanline < cinfo.output_height ) |
248 | rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead ); | 248 | rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead ); |
249 | 249 | ||
250 | delete [] rowPtr; | 250 | delete [] rowPtr; |
251 | // Finish decompression | 251 | // Finish decompression |
252 | 252 | ||
253 | jpeg_finish_decompress(&cinfo); | 253 | jpeg_finish_decompress(&cinfo); |
254 | 254 | ||
255 | // Release JPEG decompression object | 255 | // Release JPEG decompression object |
256 | // This is an important step since it will release a good deal of memory. | 256 | // This is an important step since it will release a good deal of memory. |
257 | jpeg_destroy_decompress(&cinfo); | 257 | jpeg_destroy_decompress(&cinfo); |
258 | 258 | ||
259 | // convert image | 259 | // convert image |
260 | IImage* image = 0; | 260 | IImage* image = 0; |
261 | if (useCMYK) | 261 | if (useCMYK) |
262 | { | 262 | { |
263 | image = new CImage(ECF_R8G8B8, | 263 | image = new CImage(ECF_R8G8B8, |
264 | core::dimension2d<u32>(width, height)); | 264 | core::dimension2d<u32>(width, height)); |
265 | const u32 size = 3*width*height; | 265 | const u32 size = 3*width*height; |
266 | u8* data = (u8*)image->lock(); | 266 | u8* data = (u8*)image->lock(); |
267 | if (data) | 267 | if (data) |
268 | { | 268 | { |
269 | for (u32 i=0,j=0; i<size; i+=3, j+=4) | 269 | for (u32 i=0,j=0; i<size; i+=3, j+=4) |
270 | { | 270 | { |
271 | // Also works without K, but has more contrast with K multiplied in | 271 | // Also works without K, but has more contrast with K multiplied in |
272 | // data[i+0] = output[j+2]; | 272 | // data[i+0] = output[j+2]; |
273 | // data[i+1] = output[j+1]; | 273 | // data[i+1] = output[j+1]; |
274 | // data[i+2] = output[j+0]; | 274 | // data[i+2] = output[j+0]; |
275 | data[i+0] = (char)(output[j+2]*(output[j+3]/255.f)); | 275 | data[i+0] = (char)(output[j+2]*(output[j+3]/255.f)); |
276 | data[i+1] = (char)(output[j+1]*(output[j+3]/255.f)); | 276 | data[i+1] = (char)(output[j+1]*(output[j+3]/255.f)); |
277 | data[i+2] = (char)(output[j+0]*(output[j+3]/255.f)); | 277 | data[i+2] = (char)(output[j+0]*(output[j+3]/255.f)); |
278 | } | 278 | } |
279 | } | 279 | } |
280 | image->unlock(); | 280 | image->unlock(); |
281 | delete [] output; | 281 | delete [] output; |
282 | } | 282 | } |
283 | else | 283 | else |
284 | image = new CImage(ECF_R8G8B8, | 284 | image = new CImage(ECF_R8G8B8, |
285 | core::dimension2d<u32>(width, height), output); | 285 | core::dimension2d<u32>(width, height), output); |
286 | 286 | ||
287 | delete [] input; | 287 | delete [] input; |
288 | 288 | ||
289 | return image; | 289 | return image; |
290 | 290 | ||
291 | #endif | 291 | #endif |
292 | } | 292 | } |
293 | 293 | ||
294 | 294 | ||
295 | 295 | ||
296 | //! creates a loader which is able to load jpeg images | 296 | //! creates a loader which is able to load jpeg images |
297 | IImageLoader* createImageLoaderJPG() | 297 | IImageLoader* createImageLoaderJPG() |
298 | { | 298 | { |
299 | return new CImageLoaderJPG(); | 299 | return new CImageLoaderJPG(); |
300 | } | 300 | } |
301 | 301 | ||
302 | } // end namespace video | 302 | } // end namespace video |
303 | } // end namespace irr | 303 | } // end namespace irr |
304 | 304 | ||
305 | #endif | 305 | #endif |
306 | 306 | ||