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