1
// Copyright (C) 2007-2011 Christian Stehno
2
// This file is part of the "Irrlicht Engine".
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
5
#include "CImageLoaderPPM.h"
7
#ifdef _IRR_COMPILE_WITH_PPM_LOADER_
10
#include "CColorConverter.h"
13
#include "fast_atof.h"
23
CImageLoaderPPM::CImageLoaderPPM()
26
setDebugName("CImageLoaderPPM");
31
//! returns true if the file maybe is able to be loaded by this class
32
//! based on the file extension (e.g. ".tga")
33
bool CImageLoaderPPM::isALoadableFileExtension(const io::path& filename) const
35
return core::hasFileExtension ( filename, "ppm", "pgm", "pbm" );
39
//! returns true if the file maybe is able to be loaded by this class
40
bool CImageLoaderPPM::isALoadableFileFormat(io::IReadFile* file) const
44
return (id[0]=='P' && id[1]>'0' && id[1]<'7');
48
//! creates a surface from the file
49
IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const
53
if (file->getSize() < 12)
59
if (id[0]!='P' || id[1]<'1' || id[1]>'6')
62
const u8 format = id[1] - '0';
63
const bool binary = format>3;
66
getNextToken(file, token);
67
const u32 width = core::strtoul10(token.c_str());
69
getNextToken(file, token);
70
const u32 height = core::strtoul10(token.c_str());
73
const u32 size = width*height;
74
if (format==1 || format==4)
76
skipToNextToken(file); // go to start of data
78
const u32 bytesize = size/8+(size & 3)?1:0;
81
if (file->getSize()-file->getPos() < (long)bytesize)
83
data = new u8[bytesize];
84
file->read(data, bytesize);
88
if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test
90
data = new u8[bytesize];
91
memset(data, 0, bytesize);
93
for (u32 i=0; i<size; ++i)
95
getNextToken(file, token);
97
data[i/8] |= (0x01 << shift);
102
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
104
CColorConverter::convert1BitTo16Bit(data, (s16*)image->lock(), width, height);
108
getNextToken(file, token);
109
const u32 maxDepth = core::strtoul10(token.c_str());
110
if (maxDepth > 255) // no double bytes yet
113
skipToNextToken(file); // go to start of data
115
if (format==2 || format==5)
119
if (file->getSize()-file->getPos() < (long)size)
122
file->read(data, size);
123
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
126
u8* ptr = (u8*)image->lock();
127
for (u32 i=0; i<size; ++i)
138
if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test
140
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
143
u8* ptr = (u8*)image->lock();
144
for (u32 i=0; i<size; ++i)
146
getNextToken(file, token);
147
const u8 num = (u8)core::strtoul10(token.c_str());
158
const u32 bytesize = 3*size;
161
if (file->getSize()-file->getPos() < (long)bytesize)
163
data = new u8[bytesize];
164
file->read(data, bytesize);
165
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
168
u8* ptr = (u8*)image->lock();
169
for (u32 i=0; i<size; ++i)
172
*ptr++ = data[3*i+1];
173
*ptr++ = data[3*i+2];
180
if (file->getSize()-file->getPos() < (long)(2*bytesize)) // optimistic test
182
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
185
u8* ptr = (u8*)image->lock();
186
for (u32 i=0; i<size; ++i)
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());
210
//! read the next token from file
211
void CImageLoaderPPM::getNextToken(io::IReadFile* file, core::stringc& token) const
215
while(file->getPos()<file->getSize())
220
while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
223
else if (!core::isspace(c))
229
while(file->getPos()<file->getSize())
234
while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
237
else if (!core::isspace(c))
245
//! skip to next token (skip whitespace)
246
void CImageLoaderPPM::skipToNextToken(io::IReadFile* file) const
249
while(file->getPos()<file->getSize())
254
while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
257
else if (!core::isspace(c))
259
file->seek(-1, true); // put back
266
//! creates a loader which is able to load windows bitmaps
267
IImageLoader* createImageLoaderPPM()
269
return new CImageLoaderPPM;
273
} // end namespace video
274
} // end namespace irr