Add getImageSize for all image loaders
This commit is contained in:
parent
c698d4a601
commit
eace871c66
@ -43,8 +43,7 @@ public:
|
||||
/** \param file File handle to check.
|
||||
\return Pointer to newly created image, or 0 upon error. */
|
||||
virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const = 0;
|
||||
virtual core::dimension2du getImageSize(io::IReadFile* file) const { return core::dimension2du(0, 0); }
|
||||
virtual bool supportThreadedLoading() const { return false; }
|
||||
virtual bool getImageSize(io::IReadFile* file, core::dimension2du* dim) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,6 +42,7 @@ namespace io
|
||||
//! Get name of file.
|
||||
/** \return File name as zero terminated character string. */
|
||||
virtual const io::path& getFileName() const = 0;
|
||||
virtual void* getFileHandle() const { return NULL; }
|
||||
};
|
||||
|
||||
//! Internal function, please do not use.
|
||||
|
@ -214,12 +214,11 @@ void CImageLoaderBMP::decompress4BitRLE(u8*& bmpData, s32 size, s32 width, s32 h
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderBMP::loadImage(io::IReadFile* file, bool skip_checking) const
|
||||
SBMPHeader CImageLoaderBMP::getHeader(io::IReadFile* file) const
|
||||
{
|
||||
SBMPHeader header;
|
||||
|
||||
file->seek(0);
|
||||
file->read(&header, sizeof(header));
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
@ -238,6 +237,27 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file, bool skip_checking) cons
|
||||
header.Colors = os::Byteswap::byteswap(header.Colors);
|
||||
header.ImportantColors = os::Byteswap::byteswap(header.ImportantColors);
|
||||
#endif
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
bool CImageLoaderBMP::getImageSize(io::IReadFile* file, core::dimension2du* dim) const
|
||||
{
|
||||
if (!file || !dim)
|
||||
return false;
|
||||
SBMPHeader header = getHeader(file);
|
||||
if (header.Id != 0x4d42)
|
||||
return false;
|
||||
*dim = core::dimension2du(header.Width, header.Height);
|
||||
file->seek(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderBMP::loadImage(io::IReadFile* file, bool skip_checking) const
|
||||
{
|
||||
SBMPHeader header = getHeader(file);
|
||||
|
||||
s32 pitch = 0;
|
||||
|
||||
|
@ -83,11 +83,14 @@ public:
|
||||
//! creates a surface from the file
|
||||
virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const;
|
||||
|
||||
virtual bool getImageSize(io::IReadFile* file, core::dimension2du* dim) const;
|
||||
private:
|
||||
|
||||
void decompress8BitRLE(u8*& BmpData, s32 size, s32 width, s32 height, s32 pitch) const;
|
||||
|
||||
void decompress4BitRLE(u8*& BmpData, s32 size, s32 width, s32 height, s32 pitch) const;
|
||||
|
||||
SBMPHeader getHeader(io::IReadFile* file) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
@ -43,6 +45,78 @@ bool CImageLoaderJPG::isALoadableFileExtension(const io::path& filename) const
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_LIBJPEG_
|
||||
|
||||
/* portions derived from IJG code */
|
||||
|
||||
#define readbyte(a,b) do if(((a)=getc((b))) == EOF) return 0; while (0)
|
||||
#define readword(a,b) do { int cc_=0,dd_=0; \
|
||||
if((cc_=getc((b))) == EOF \
|
||||
|| (dd_=getc((b))) == EOF) return 0; \
|
||||
(a) = (cc_<<8) + (dd_); \
|
||||
} while(0)
|
||||
|
||||
int scanhead (FILE * infile, unsigned * image_width, unsigned * image_height) {
|
||||
int marker=0;
|
||||
int dummy=0;
|
||||
if ( !infile || getc(infile) != 0xFF || getc(infile) != 0xD8 )
|
||||
return 0;
|
||||
|
||||
for (;
|
||||
;){
|
||||
|
||||
int discarded_bytes=0;
|
||||
readbyte(marker,infile);
|
||||
while (marker != 0xFF) {
|
||||
discarded_bytes++;
|
||||
readbyte(marker,infile);
|
||||
}
|
||||
do readbyte(marker,infile); while (marker == 0xFF);
|
||||
|
||||
if (discarded_bytes != 0) return 0;
|
||||
|
||||
switch (marker) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF: {
|
||||
readword(dummy,infile); /* usual parameter length count */
|
||||
readbyte(dummy,infile);
|
||||
readword((*image_height),infile);
|
||||
readword((*image_width),infile);
|
||||
readbyte(dummy,infile);
|
||||
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
case 0xDA:
|
||||
case 0xD9:
|
||||
return 0;
|
||||
default: {
|
||||
int length = 0;
|
||||
readword(length,infile);
|
||||
|
||||
if (length < 2)
|
||||
return 0;
|
||||
length -= 2;
|
||||
while (length > 0) {
|
||||
readbyte(dummy, infile);
|
||||
length--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// struct for handling jpeg errors
|
||||
struct irr_jpeg_error_mgr
|
||||
{
|
||||
@ -283,7 +357,19 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file, bool skip_checking) cons
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CImageLoaderJPG::getImageSize(io::IReadFile* file, core::dimension2du* dim) const
|
||||
{
|
||||
#ifndef _IRR_COMPILE_WITH_LIBJPEG_
|
||||
return false;
|
||||
#else
|
||||
if (!dim || !file || !isALoadableFileFormat(file))
|
||||
return false;
|
||||
file->seek(0);
|
||||
scanhead((FILE*)file->getFileHandle(), &dim->Width, &dim->Height);
|
||||
file->seek(0);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//! creates a loader which is able to load jpeg images
|
||||
IImageLoader* createImageLoaderJPG()
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
//! creates a surface from the file
|
||||
virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const;
|
||||
|
||||
virtual bool getImageSize(io::IReadFile* file, core::dimension2du* dim) const;
|
||||
private:
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_LIBJPEG_
|
||||
|
@ -252,24 +252,23 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file, bool skip_checking) cons
|
||||
#endif // _IRR_COMPILE_WITH_LIBPNG_
|
||||
}
|
||||
|
||||
core::dimension2du CImageLoaderPng::getImageSize(io::IReadFile* file) const
|
||||
bool CImageLoaderPng::getImageSize(io::IReadFile* file, core::dimension2du* dim) const
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_LIBPNG_
|
||||
if (!file || !isALoadableFileFormat(file))
|
||||
return core::dimension2du(0, 0);
|
||||
core::dimension2d<u32> dim;
|
||||
if (!dim || !file || !isALoadableFileFormat(file))
|
||||
return false;
|
||||
file->seek(16);
|
||||
file->read(&dim.Width, 4);
|
||||
file->read(&dim->Width, 4);
|
||||
file->seek(20);
|
||||
file->read(&dim.Height, 4);
|
||||
file->read(&dim->Height, 4);
|
||||
file->seek(0);
|
||||
#ifndef __BIG_ENDIAN__
|
||||
dim.Width = os::Byteswap::byteswap(dim.Width);
|
||||
dim.Height = os::Byteswap::byteswap(dim.Height);
|
||||
dim->Width = os::Byteswap::byteswap(dim->Width);
|
||||
dim->Height = os::Byteswap::byteswap(dim->Height);
|
||||
#endif
|
||||
return dim;
|
||||
return true;
|
||||
#else
|
||||
return core::dimension2du(0, 0);
|
||||
return false;
|
||||
#endif // _IRR_COMPILE_WITH_LIBPNG_
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,8 @@ public:
|
||||
|
||||
//! creates a surface from the file
|
||||
virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const;
|
||||
virtual core::dimension2du getImageSize(io::IReadFile* file) const;
|
||||
virtual bool supportThreadedLoading() const { return true; }
|
||||
|
||||
virtual bool getImageSize(io::IReadFile* file, core::dimension2du* dim) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -64,25 +64,23 @@ bool CImageLoaderSVG::isALoadableFileFormat(io::IReadFile* file) const
|
||||
}
|
||||
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderSVG::loadImage(io::IReadFile* file, bool skip_checking) const
|
||||
struct NSVGimage* CImageLoaderSVG::getSVGImage(io::IReadFile* file, float* scale) const
|
||||
{
|
||||
// check IMG_LoadSVG_RW
|
||||
if (!file)
|
||||
return NULL;
|
||||
file->seek(0);
|
||||
struct NSVGimage *img = 0;
|
||||
struct NSVGrasterizer *rasterizer = 0;
|
||||
video::IImage* image = 0;
|
||||
int w, h;
|
||||
|
||||
// read all the characters in the svg file to data
|
||||
long filesize = file->getSize();
|
||||
char* data = new char[filesize+1];
|
||||
int readsize = file->read(data,filesize);
|
||||
data[filesize] = '\0';
|
||||
|
||||
|
||||
if( (long)readsize != filesize) {
|
||||
os::Printer::log("Couldn't read SVG image file", file->getFileName(), ELL_ERROR);
|
||||
delete[] data;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// parse the svg image
|
||||
@ -90,10 +88,57 @@ IImage* CImageLoaderSVG::loadImage(io::IReadFile* file, bool skip_checking) cons
|
||||
if ( !img ) {
|
||||
os::Printer::log("Couldn't parse SVG image", ELL_ERROR);
|
||||
delete[] data;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
delete[] data;
|
||||
|
||||
// only rescale the icons
|
||||
if ( strstr(file->getFileName().c_str(),"gui/icons/") )
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
// determine scaling based on screen size
|
||||
float screen_height = (float)GE::getDriver()->getCurrentRenderTargetSize().Height;
|
||||
float desired_icon_size = 0.21*screen_height + 30.0f; // phenomenological
|
||||
*scale = desired_icon_size/img->height;
|
||||
#endif
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
core::dimension2du CImageLoaderSVG::getImageSize(struct NSVGimage* img, float scale) const
|
||||
{
|
||||
core::dimension2du dim;
|
||||
dim.Width = (unsigned)(img->width*scale);
|
||||
dim.Height = (unsigned)(img->height*scale);
|
||||
return dim;
|
||||
}
|
||||
|
||||
|
||||
bool CImageLoaderSVG::getImageSize(io::IReadFile* file, core::dimension2du* dim) const
|
||||
{
|
||||
if (!dim || !file || !isALoadableFileFormat(file))
|
||||
return false;
|
||||
float scale = 1.0f;
|
||||
struct NSVGimage *img = getSVGImage(file, &scale);
|
||||
if (!img)
|
||||
return false;
|
||||
*dim = getImageSize(img, scale);
|
||||
nsvgDelete(img);
|
||||
file->seek(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderSVG::loadImage(io::IReadFile* file, bool skip_checking) const
|
||||
{
|
||||
// check IMG_LoadSVG_RW
|
||||
float scale = 1.0f;
|
||||
struct NSVGimage *img = getSVGImage(file, &scale);
|
||||
struct NSVGrasterizer *rasterizer = 0;
|
||||
video::IImage* image = 0;
|
||||
|
||||
rasterizer = nsvgCreateRasterizer();
|
||||
if ( !rasterizer ) {
|
||||
os::Printer::log("Couldn't create SVG rasterizer", ELL_ERROR);
|
||||
@ -101,22 +146,7 @@ IImage* CImageLoaderSVG::loadImage(io::IReadFile* file, bool skip_checking) cons
|
||||
return 0;
|
||||
}
|
||||
|
||||
float scale =1.0f;
|
||||
// only rescale the icons
|
||||
if ( strstr(file->getFileName().c_str(),"gui/icons/") )
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
// determine scaling based on screen size
|
||||
float screen_height = (float)GE::getDriver()->getCurrentRenderTargetSize().Height;
|
||||
float desired_icon_size = 0.21*screen_height + 30.0f; // phenomenological
|
||||
scale = desired_icon_size/img->height;
|
||||
#endif
|
||||
}
|
||||
|
||||
// create surface
|
||||
w = (int)(img->width*scale);
|
||||
h = (int)(img->height*scale);
|
||||
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(w, h));
|
||||
image = new CImage(ECF_A8R8G8B8, getImageSize(img, scale));
|
||||
if ( !image ) {
|
||||
os::Printer::log("LOAD SVG: create image struct failure", file->getFileName(), ELL_ERROR);
|
||||
nsvgDeleteRasterizer( rasterizer );
|
||||
|
@ -48,6 +48,11 @@ public:
|
||||
//! creates a surface from the file
|
||||
virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const;
|
||||
|
||||
virtual bool getImageSize(io::IReadFile* file, core::dimension2du* dim) const;
|
||||
private:
|
||||
struct NSVGimage* getSVGImage(io::IReadFile* file, float* scale) const;
|
||||
|
||||
core::dimension2du getImageSize(struct NSVGimage* img, float scale) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -47,6 +47,8 @@ namespace io
|
||||
//! returns name of file
|
||||
virtual const io::path& getFileName() const;
|
||||
|
||||
virtual void* getFileHandle() const { return (void*)File; }
|
||||
|
||||
private:
|
||||
|
||||
//! opens the file
|
||||
|
Loading…
Reference in New Issue
Block a user