aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPPM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPPM.cpp')
-rw-r--r--libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPPM.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPPM.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPPM.cpp
new file mode 100644
index 0000000..a0776fa
--- /dev/null
+++ b/libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPPM.cpp
@@ -0,0 +1,277 @@
1// Copyright (C) 2007-2012 Christian Stehno
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 "CImageLoaderPPM.h"
6
7#ifdef _IRR_COMPILE_WITH_PPM_LOADER_
8
9#include "IReadFile.h"
10#include "CColorConverter.h"
11#include "CImage.h"
12#include "os.h"
13#include "fast_atof.h"
14#include "coreutil.h"
15
16namespace irr
17{
18namespace video
19{
20
21
22//! constructor
23CImageLoaderPPM::CImageLoaderPPM()
24{
25 #ifdef _DEBUG
26 setDebugName("CImageLoaderPPM");
27 #endif
28}
29
30
31//! returns true if the file maybe is able to be loaded by this class
32//! based on the file extension (e.g. ".tga")
33bool CImageLoaderPPM::isALoadableFileExtension(const io::path& filename) const
34{
35 return core::hasFileExtension ( filename, "ppm", "pgm", "pbm" );
36}
37
38
39//! returns true if the file maybe is able to be loaded by this class
40bool CImageLoaderPPM::isALoadableFileFormat(io::IReadFile* file) const
41{
42 c8 id[2]={0};
43 file->read(&id, 2);
44 return (id[0]=='P' && id[1]>'0' && id[1]<'7');
45}
46
47
48//! creates a surface from the file
49IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const
50{
51 IImage* image;
52
53 if (file->getSize() < 12)
54 return 0;
55
56 c8 id[2];
57 file->read(&id, 2);
58
59 if (id[0]!='P' || id[1]<'1' || id[1]>'6')
60 return 0;
61
62 const u8 format = id[1] - '0';
63 const bool binary = format>3;
64
65 core::stringc token;
66 getNextToken(file, token);
67 const u32 width = core::strtoul10(token.c_str());
68
69 getNextToken(file, token);
70 const u32 height = core::strtoul10(token.c_str());
71
72 u8* data = 0;
73 const u32 size = width*height;
74 if (format==1 || format==4)
75 {
76 skipToNextToken(file); // go to start of data
77
78 const u32 bytesize = size/8+(size & 3)?1:0;
79 if (binary)
80 {
81 if (file->getSize()-file->getPos() < (long)bytesize)
82 return 0;
83 data = new u8[bytesize];
84 file->read(data, bytesize);
85 }
86 else
87 {
88 if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test
89 return 0;
90 data = new u8[bytesize];
91 memset(data, 0, bytesize);
92 u32 shift=0;
93 for (u32 i=0; i<size; ++i)
94 {
95 getNextToken(file, token);
96 if (token == "1")
97 data[i/8] |= (0x01 << shift);
98 if (++shift == 8)
99 shift=0;
100 }
101 }
102 image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
103 if (image)
104 CColorConverter::convert1BitTo16Bit(data, (s16*)image->lock(), width, height);
105 }
106 else
107 {
108 getNextToken(file, token);
109 const u32 maxDepth = core::strtoul10(token.c_str());
110 if (maxDepth > 255) // no double bytes yet
111 return 0;
112
113 skipToNextToken(file); // go to start of data
114
115 if (format==2 || format==5)
116 {
117 if (binary)
118 {
119 if (file->getSize()-file->getPos() < (long)size)
120 return 0;
121 data = new u8[size];
122 file->read(data, size);
123 image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
124 if (image)
125 {
126 u8* ptr = (u8*)image->lock();
127 for (u32 i=0; i<size; ++i)
128 {
129 *ptr++ = data[i];
130 *ptr++ = data[i];
131 *ptr++ = data[i];
132 *ptr++ = 255;
133 }
134 }
135 }
136 else
137 {
138 if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test
139 return 0;
140 image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
141 if (image)
142 {
143 u8* ptr = (u8*)image->lock();
144 for (u32 i=0; i<size; ++i)
145 {
146 getNextToken(file, token);
147 const u8 num = (u8)core::strtoul10(token.c_str());
148 *ptr++ = num;
149 *ptr++ = num;
150 *ptr++ = num;
151 *ptr++ = 255;
152 }
153 }
154 }
155 }
156 else
157 {
158 const u32 bytesize = 3*size;
159 if (binary)
160 {
161 if (file->getSize()-file->getPos() < (long)bytesize)
162 return 0;
163 data = new u8[bytesize];
164 file->read(data, bytesize);
165 image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
166 if (image)
167 {
168 u8* ptr = (u8*)image->lock();
169 for (u32 i=0; i<size; ++i)
170 {
171 *ptr++ = data[3*i];
172 *ptr++ = data[3*i+1];
173 *ptr++ = data[3*i+2];
174 *ptr++ = 255;
175 }
176 }
177 }
178 else
179 {
180 if (file->getSize()-file->getPos() < (long)(2*bytesize)) // optimistic test
181 return 0;
182 image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
183 if (image)
184 {
185 u8* ptr = (u8*)image->lock();
186 for (u32 i=0; i<size; ++i)
187 {
188 getNextToken(file, token);
189 *ptr++ = (u8)core::strtoul10(token.c_str());
190 getNextToken(file, token);
191 *ptr++ = (u8)core::strtoul10(token.c_str());
192 getNextToken(file, token);
193 *ptr++ = (u8)core::strtoul10(token.c_str());
194 *ptr++ = 255;
195 }
196 }
197 }
198 }
199 }
200
201 if (image)
202 image->unlock();
203
204 delete [] data;
205
206 return image;
207}
208
209
210//! read the next token from file
211void CImageLoaderPPM::getNextToken(io::IReadFile* file, core::stringc& token) const
212{
213 token = "";
214 c8 c;
215 while(file->getPos()<file->getSize())
216 {
217 file->read(&c, 1);
218 if (c=='#')
219 {
220 while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
221 file->read(&c, 1);
222 }
223 else if (!core::isspace(c))
224 {
225 token.append(c);
226 break;
227 }
228 }
229 while(file->getPos()<file->getSize())
230 {
231 file->read(&c, 1);
232 if (c=='#')
233 {
234 while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
235 file->read(&c, 1);
236 }
237 else if (!core::isspace(c))
238 token.append(c);
239 else
240 break;
241 }
242}
243
244
245//! skip to next token (skip whitespace)
246void CImageLoaderPPM::skipToNextToken(io::IReadFile* file) const
247{
248 c8 c;
249 while(file->getPos()<file->getSize())
250 {
251 file->read(&c, 1);
252 if (c=='#')
253 {
254 while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
255 file->read(&c, 1);
256 }
257 else if (!core::isspace(c))
258 {
259 file->seek(-1, true); // put back
260 break;
261 }
262 }
263}
264
265
266//! creates a loader which is able to load windows bitmaps
267IImageLoader* createImageLoaderPPM()
268{
269 return new CImageLoaderPPM;
270}
271
272
273} // end namespace video
274} // end namespace irr
275
276#endif
277