aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPNG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPNG.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPNG.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPNG.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPNG.cpp
new file mode 100644
index 0000000..3dbbe1c
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPNG.cpp
@@ -0,0 +1,290 @@
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 "CImageLoaderPNG.h"
6
7#ifdef _IRR_COMPILE_WITH_PNG_LOADER_
8
9#ifdef _IRR_COMPILE_WITH_LIBPNG_
10 #ifndef _IRR_USE_NON_SYSTEM_LIB_PNG_
11 #include <png.h> // use system lib png
12 #else // _IRR_USE_NON_SYSTEM_LIB_PNG_
13 #include "libpng/png.h" // use irrlicht included lib png
14 #endif // _IRR_USE_NON_SYSTEM_LIB_PNG_
15#endif // _IRR_COMPILE_WITH_LIBPNG_
16
17#include "CImage.h"
18#include "CReadFile.h"
19#include "os.h"
20
21namespace irr
22{
23namespace video
24{
25
26#ifdef _IRR_COMPILE_WITH_LIBPNG_
27// PNG function for error handling
28static void png_cpexcept_error(png_structp png_ptr, png_const_charp msg)
29{
30 os::Printer::log("PNG fatal error", msg, ELL_ERROR);
31 longjmp(png_jmpbuf(png_ptr), 1);
32}
33
34// PNG function for warning handling
35static void png_cpexcept_warn(png_structp png_ptr, png_const_charp msg)
36{
37 os::Printer::log("PNG warning", msg, ELL_WARNING);
38}
39
40// PNG function for file reading
41void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t length)
42{
43 png_size_t check;
44
45 // changed by zola {
46 io::IReadFile* file=(io::IReadFile*)png_get_io_ptr(png_ptr);
47 check=(png_size_t) file->read((void*)data,(u32)length);
48 // }
49
50 if (check != length)
51 png_error(png_ptr, "Read Error");
52}
53#endif // _IRR_COMPILE_WITH_LIBPNG_
54
55
56//! returns true if the file maybe is able to be loaded by this class
57//! based on the file extension (e.g. ".tga")
58bool CImageLoaderPng::isALoadableFileExtension(const io::path& filename) const
59{
60#ifdef _IRR_COMPILE_WITH_LIBPNG_
61 return core::hasFileExtension ( filename, "png" );
62#else
63 return false;
64#endif // _IRR_COMPILE_WITH_LIBPNG_
65}
66
67
68//! returns true if the file maybe is able to be loaded by this class
69bool CImageLoaderPng::isALoadableFileFormat(io::IReadFile* file) const
70{
71#ifdef _IRR_COMPILE_WITH_LIBPNG_
72 if (!file)
73 return false;
74
75 png_byte buffer[8];
76 // Read the first few bytes of the PNG file
77 if (file->read(buffer, 8) != 8)
78 return false;
79
80 // Check if it really is a PNG file
81 return !png_sig_cmp(buffer, 0, 8);
82#else
83 return false;
84#endif // _IRR_COMPILE_WITH_LIBPNG_
85}
86
87
88// load in the image data
89IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
90{
91#ifdef _IRR_COMPILE_WITH_LIBPNG_
92 if (!file)
93 return 0;
94
95 video::IImage* image = 0;
96 //Used to point to image rows
97 u8** RowPointers = 0;
98
99 png_byte buffer[8];
100 // Read the first few bytes of the PNG file
101 if( file->read(buffer, 8) != 8 )
102 {
103 os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR);
104 return 0;
105 }
106
107 // Check if it really is a PNG file
108 if( png_sig_cmp(buffer, 0, 8) )
109 {
110 os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR);
111 return 0;
112 }
113
114 // Allocate the png read struct
115 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
116 NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn);
117 if (!png_ptr)
118 {
119 os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR);
120 return 0;
121 }
122
123 // Allocate the png info struct
124 png_infop info_ptr = png_create_info_struct(png_ptr);
125 if (!info_ptr)
126 {
127 os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR);
128 png_destroy_read_struct(&png_ptr, NULL, NULL);
129 return 0;
130 }
131
132 // for proper error handling
133 if (setjmp(png_jmpbuf(png_ptr)))
134 {
135 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
136 if (RowPointers)
137 delete [] RowPointers;
138 return 0;
139 }
140
141 // changed by zola so we don't need to have public FILE pointers
142 png_set_read_fn(png_ptr, file, user_read_data_fcn);
143
144 png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature
145
146 png_read_info(png_ptr, info_ptr); // Read the info section of the png file
147
148 u32 Width;
149 u32 Height;
150 s32 BitDepth;
151 s32 ColorType;
152 {
153 // Use temporary variables to avoid passing casted pointers
154 png_uint_32 w,h;
155 // Extract info
156 png_get_IHDR(png_ptr, info_ptr,
157 &w, &h,
158 &BitDepth, &ColorType, NULL, NULL, NULL);
159 Width=w;
160 Height=h;
161 }
162
163 // Convert palette color to true color
164 if (ColorType==PNG_COLOR_TYPE_PALETTE)
165 png_set_palette_to_rgb(png_ptr);
166
167 // Convert low bit colors to 8 bit colors
168 if (BitDepth < 8)
169 {
170 if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
171 png_set_expand_gray_1_2_4_to_8(png_ptr);
172 else
173 png_set_packing(png_ptr);
174 }
175
176 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
177 png_set_tRNS_to_alpha(png_ptr);
178
179 // Convert high bit colors to 8 bit colors
180 if (BitDepth == 16)
181 png_set_strip_16(png_ptr);
182
183 // Convert gray color to true color
184 if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
185 png_set_gray_to_rgb(png_ptr);
186
187 int intent;
188 const double screen_gamma = 2.2;
189
190 if (png_get_sRGB(png_ptr, info_ptr, &intent))
191 png_set_gamma(png_ptr, screen_gamma, 0.45455);
192 else
193 {
194 double image_gamma;
195 if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
196 png_set_gamma(png_ptr, screen_gamma, image_gamma);
197 else
198 png_set_gamma(png_ptr, screen_gamma, 0.45455);
199 }
200
201 // Update the changes in between, as we need to get the new color type
202 // for proper processing of the RGBA type
203 png_read_update_info(png_ptr, info_ptr);
204 {
205 // Use temporary variables to avoid passing casted pointers
206 png_uint_32 w,h;
207 // Extract info
208 png_get_IHDR(png_ptr, info_ptr,
209 &w, &h,
210 &BitDepth, &ColorType, NULL, NULL, NULL);
211 Width=w;
212 Height=h;
213 }
214
215 // Convert RGBA to BGRA
216 if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
217 {
218#ifdef __BIG_ENDIAN__
219 png_set_swap_alpha(png_ptr);
220#else
221 png_set_bgr(png_ptr);
222#endif
223 }
224
225 // Create the image structure to be filled by png data
226 if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
227 image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(Width, Height));
228 else
229 image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(Width, Height));
230 if (!image)
231 {
232 os::Printer::log("LOAD PNG: Internal PNG create image struct failure\n", file->getFileName(), ELL_ERROR);
233 png_destroy_read_struct(&png_ptr, NULL, NULL);
234 return 0;
235 }
236
237 // Create array of pointers to rows in image data
238 RowPointers = new png_bytep[Height];
239 if (!RowPointers)
240 {
241 os::Printer::log("LOAD PNG: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR);
242 png_destroy_read_struct(&png_ptr, NULL, NULL);
243 delete image;
244 return 0;
245 }
246
247 // Fill array of pointers to rows in image data
248 unsigned char* data = (unsigned char*)image->lock();
249 for (u32 i=0; i<Height; ++i)
250 {
251 RowPointers[i]=data;
252 data += image->getPitch();
253 }
254
255 // for proper error handling
256 if (setjmp(png_jmpbuf(png_ptr)))
257 {
258 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
259 delete [] RowPointers;
260 image->unlock();
261 delete [] image;
262 return 0;
263 }
264
265 // Read data using the library function that handles all transformations including interlacing
266 png_read_image(png_ptr, RowPointers);
267
268 png_read_end(png_ptr, NULL);
269 delete [] RowPointers;
270 image->unlock();
271 png_destroy_read_struct(&png_ptr,&info_ptr, 0); // Clean up memory
272
273 return image;
274#else
275 return 0;
276#endif // _IRR_COMPILE_WITH_LIBPNG_
277}
278
279
280IImageLoader* createImageLoaderPNG()
281{
282 return new CImageLoaderPng();
283}
284
285
286}// end namespace irr
287}//end namespace video
288
289#endif
290