CImageFreeImageLoader.h
Code: Select all
// Copyright (C) 2004 Murphy McCauley
// Copyright (C) 2007-2009 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
/*
Thanks to:
Max McGuire for his Flipcode article about WAL textures
Nikolaus Gebhardt for the Irrlicht 3D engine
*/
#ifndef __C_IMAGE_FREEIMAGE_LOADER_H_INCLUDED__
#define __C_IMAGE_FREEIMAGE_LOADER_H_INCLUDED__
#include "IrrCompileConfig.h"
#include "IImageLoader.h"
#include "FreeImage/FreeImage.h"
#define FREEIMAGE_LIB
#pragma comment(lib,"FreeImage/FreeImage.lib")
#define _IRR_COMPILE_WITH_FREEIMAGE_LOADER_
#define _IRR_COMPILE_WITH_FREEIMAGE_WRITER_
namespace irr
{
namespace video
{
#if defined(_IRR_COMPILE_WITH_FREEIMAGE_LOADER_) || defined(_IRR_COMPILE_WITH_FREEIMAGE_WRITER_)
#endif // defined with loader or writer
#ifdef _IRR_COMPILE_WITH_FREEIMAGE_LOADER_
/*!
Surface Loader for Windows bitmaps
*/
class CFreeImageLoader : public IImageLoader
{
public:
//! constructor
CFreeImageLoader();
//! Destructor
virtual ~CFreeImageLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const;
private:
protected:
};
#endif // compiled with loader
} // end namespace video
} // end namespace irr
#endif
Code: Select all
// Copyright (C) 2002-2009 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CImageFreeImageLoader.h"
#ifdef _IRR_COMPILE_WITH_FREEIMAGE_LOADER_
#include "IReadFile.h"
#include "SColor.h"
#include "CColorConverter.h"
#include "CImage.h"
#include "os.h"
#include "irrString.h"
namespace irr
{
namespace video
{
// ----------------------------------------------------------
/** Generic image loader
@param lpszPathName Pointer to the full file name
@param flag Optional load flag constant
@return Returns the loaded dib if successful, returns NULL otherwise
*/
FIBITMAP* GenericLoader(const core::stringc lpszPathName, int flag) {
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
//core::stringc filename;
//lpszPathName = file->getFileName();
// check the file signature and deduce its format
// (the second argument is currently not used by FreeImage)
fif = FreeImage_GetFileType(lpszPathName.c_str(), 0);
if(fif == FIF_UNKNOWN) {
// no signature ?
// try to guess the file format from the file extension
fif = FreeImage_GetFIFFromFilename(lpszPathName.c_str());
}
// check that the plugin has reading capabilities ...
if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
// ok, let's load the file
FIBITMAP *dib = FreeImage_Load(fif, lpszPathName.c_str(), flag);
// unless a bad file format, we are done !
return dib;
}
return NULL;
}
/** Generic image writer
@param dib Pointer to the dib to be saved
@param lpszPathName Pointer to the full file name
@param flag Optional save flag constant
@return Returns true if successful, returns false otherwise
*/
bool GenericWriter(FIBITMAP* dib, const core::stringc lpszPathName, int flag) {
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
BOOL bSuccess = FALSE;
if(dib) {
// try to guess the file format from the file extension
fif = FreeImage_GetFIFFromFilename(lpszPathName.c_str());
if(fif != FIF_UNKNOWN ) {
// check that the plugin has sufficient writing and export capabilities ...
WORD bpp = FreeImage_GetBPP(dib);
if(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)) {
// ok, we can save the file
bSuccess = FreeImage_Save(fif, dib, lpszPathName.c_str(), flag);
// unless an abnormal bug, we are done !
}
}
}
return (bSuccess == TRUE) ? true : false;
}
// ----------------------------------------------------------
//! constructor
CFreeImageLoader::CFreeImageLoader()
{
#ifdef _DEBUG
setDebugName("CImageFreeImageLoader");
#endif
// call this ONLY when linking with FreeImage as a static library
#ifdef FREEIMAGE_LIB
FreeImage_Initialise();
#endif // FREEIMAGE_LIB
}
CFreeImageLoader::~CFreeImageLoader()
{
// call this ONLY when linking with FreeImage as a static library
#ifdef FREEIMAGE_LIB
FreeImage_DeInitialise();
#endif // FREEIMAGE_LIB
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CFreeImageLoader::isALoadableFileExtension(const io::path& filename) const
{
//image format
return core::hasFileExtension( filename, "bmp", "jpg", "tga" ) ||
core::hasFileExtension( filename, "pcx", "png", "gif" );
}
//! returns true if the file maybe is able to be loaded by this class
bool CFreeImageLoader::isALoadableFileFormat(io::IReadFile* file) const
{
u16 headerID;
if (!file)
return false;
file->read(&headerID, sizeof(u16));
return false;
}
//! creates a surface from the file
//IImage* CFreeImageLoader::loadImage(const io::path& file) const;
IImage* CFreeImageLoader::loadImage(io::IReadFile* file) const
{
u8* data = new u8[file->getSize()];
s32 len = file->getPos();
FIMEMORY *mem = NULL;
FIBITMAP *img = NULL;
IImage* retval = 0;
FIBITMAP *dib = GenericLoader(file->getFileName(), 0);
if(!dib) os::Printer::log("You have to use a range from 0 to 64 of FadeID", irr::ELL_ERROR);
mem = FreeImage_OpenMemory((BYTE*)data, len);
if (mem == 0)
os::Printer::log("Unable to open memory stream, FreeImage_OpenMemory failed", irr::ELL_ERROR);
FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(mem, len);
if (fif == FIF_UNKNOWN) // it may be that it's TARGA or MNG
{
fif = FIF_TARGA;
img = FreeImage_LoadFromMemory(fif, mem, 0);
if (img == 0)
{
fif = FIF_MNG;
img = FreeImage_LoadFromMemory(fif, mem, 0);
}
}
else
img = FreeImage_LoadFromMemory(fif, mem, 0);
if (img == 0)
os::Printer::log("Unable to load image, FreeImage_LoadFromMemory failed", irr::ELL_ERROR);
FIBITMAP *newImg = FreeImage_ConvertTo32Bits(img);
if (newImg == 0)
os::Printer::log("Unable to convert image, FreeImage_ConvertTo32Bits failed", irr::ELL_ERROR);
FreeImage_Unload(img);
img = newImg;
newImg = 0;
// FreeImage pixel format for little-endian architecture (which CEGUI
// supports) is like BGRA. We need to convert that to RGBA.
//
// It is now:
// RED_MASK 0x00FF0000
// GREEN_MASK 0x0000FF00
// BLUE_MASK 0x000000FF
// ALPHA_MASK 0xFF000000
//
// It should be:
// RED_MASK 0x000000FF
// GREEN_MASK 0x0000FF00
// BLUE_MASK 0x00FF0000
// ALPHA_MASK 0xFF000000
// read image
u32 pitch = FreeImage_GetPitch(img);
u32 height = FreeImage_GetHeight(img);
u32 width = FreeImage_GetWidth(img);
u8 *rawBuf = new u8[width * height << 2];
// convert the bitmap to raw bits (top-left pixel first)
FreeImage_ConvertToRawBits(rawBuf, img, pitch, 32,
FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, true);
// We need to convert pixel format a little
// NB: little endian only - I think(!)
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
for (u32 i = 0; i < height; ++i)
{
for (u32 j = 0; j < width; ++j)
{
s32 p = *(((s32*)(rawBuf + i * pitch)) + j);
s32 r = (p >> 16) & 0x000000FF;
s32 b = (p << 16) & 0x00FF0000;
p &= 0xFF00FF00;
p |= r | b;
// write the adjusted pixel back
*(((s32*)(rawBuf + i * pitch)) + j) = p;
}
}
#endif
FreeImage_Unload(img);
img = 0;
// no default constructor from packed area! ARM problem!
core::dimension2d<u32> dim;
dim.Width = width;
dim.Height = height;
IImage* image = 0;
//image = new CImage(ECF_A8R8G8B8, dim, rawBuf);
image = new CImage(ECF_A8R8G8B8, dim);
if (image)
CColorConverter::convert32BitTo32Bit((s32*)rawBuf, (s32*)image->lock(), width, height, pitch, true);
if (image)
image->unlock();
// clean up
delete [] rawBuf;
if (img != 0) FreeImage_Unload(img);
if (mem != 0) FreeImage_CloseMemory(mem);
return image;
}
//! creates a loader which is able to load windows bitmaps
IImageLoader* createFreeImageLoader()
{
return new CFreeImageLoader();
}
} // end namespace video
} // end namespace irr
#endifThanks