PNG loading and major refactoring.
PNG loading is not working properly yet.
This commit is contained in:
parent
d0893cba3a
commit
28bd73a1f7
17 changed files with 254 additions and 43 deletions
143
src/texture.cpp
143
src/texture.cpp
|
@ -8,12 +8,31 @@
|
|||
#include <ciso646>
|
||||
#include <png.h>
|
||||
|
||||
#define lengthof(a) (static_cast<int32_t>(sizeof(a)) / static_cast<int32_t>(sizeof(a[0])))
|
||||
|
||||
namespace cloonel {
|
||||
namespace {
|
||||
enum GraphicFormat {
|
||||
GraphicFormat_Unknown,
|
||||
GraphicFormat_Png
|
||||
};
|
||||
|
||||
enum ColorChannelMask {
|
||||
#if SDL_BYTE_ORDER == SDL_BIGENDIAN
|
||||
ColorChannelMask_Red = 0xff000000,
|
||||
ColorChannelMask_Green = 0xff0000,
|
||||
ColorChannelMask_Blue = 0xff00,
|
||||
ColorChannelMask_Alpha = 0xff
|
||||
#elif SDL_BYTE_ORDER == SDL_LITTLEENDIAN
|
||||
ColorChannelMask_Red = 0xff,
|
||||
ColorChannelMask_Green = 0xff00,
|
||||
ColorChannelMask_Blue = 0xff0000,
|
||||
ColorChannelMask_Alpha = 0xff000000
|
||||
#else
|
||||
# error "Unknonwn endianness"
|
||||
#endif
|
||||
};
|
||||
|
||||
struct GraphicFormatItem {
|
||||
const char* extension;
|
||||
size_t length;
|
||||
|
@ -26,8 +45,34 @@ namespace cloonel {
|
|||
|
||||
GraphicFormat GuessGraphicFormatFromName (const std::string& parPath) __attribute__((pure));
|
||||
|
||||
///--------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------
|
||||
///----------------------------------------------------------------------
|
||||
///----------------------------------------------------------------------
|
||||
SDL_Surface* SurfaceFromPngRGBA (ushort2 parSize, int parBpp, const png_structp& parPngPtr, const png_infop& parInfoPtr) {
|
||||
const png_size_t stride = png_get_rowbytes(parPngPtr, parInfoPtr);
|
||||
assert(stride > 0);
|
||||
|
||||
std::unique_ptr<uint8_t[]> image(new uint8_t[stride * parSize.y()]);
|
||||
uint8_t* const imagePtr = image.get();
|
||||
for (uint16_t y = 0; y < parSize.y(); ++y) {
|
||||
png_read_row(parPngPtr, imagePtr + stride * y, nullptr);
|
||||
}
|
||||
|
||||
SDL_Surface* const retSurf = SDL_CreateRGBSurfaceFrom(
|
||||
imagePtr,
|
||||
parSize.x(),
|
||||
parSize.y(),
|
||||
parBpp,
|
||||
static_cast<int>(stride),
|
||||
ColorChannelMask_Red,
|
||||
ColorChannelMask_Green,
|
||||
ColorChannelMask_Blue,
|
||||
ColorChannelMask_Alpha
|
||||
);
|
||||
return retSurf;
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------
|
||||
///----------------------------------------------------------------------
|
||||
GraphicFormat GuessGraphicFormatFromName (const std::string& parPath) {
|
||||
const size_t dotPos = parPath.find_last_of('.');
|
||||
if (parPath.npos == dotPos) {
|
||||
|
@ -44,27 +89,82 @@ namespace cloonel {
|
|||
return GraphicFormat_Unknown;
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------
|
||||
///----------------------------------------------------------------------
|
||||
///----------------------------------------------------------------------
|
||||
void ReadDataFromInputStream (png_structp parPngPtr, png_bytep parOutBytes, png_size_t parByteCountToRead) {
|
||||
if (not png_get_io_ptr(parPngPtr))
|
||||
return;
|
||||
PhysicsFSFile& rawfile = *static_cast<PhysicsFSFile*>(png_get_io_ptr(parPngPtr));
|
||||
|
||||
const int64_t read = rawfile.Read(static_cast<void*>(parOutBytes), static_cast<uint32_t>(parByteCountToRead), 1);
|
||||
if (read != static_cast<int64_t>(parByteCountToRead))
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------
|
||||
///http://blog.hammerian.net/2009/reading-png-images-from-memory/
|
||||
///----------------------------------------------------------------------
|
||||
SDL_Surface* LoadNewPngSurface (const std::string& parPath) {
|
||||
PhysicsFSFile rawfile(parPath.c_str(), PhysicsFSFile::OpenMode_Read, "graphics");
|
||||
unsigned char header[8];
|
||||
assert(rawfile.IsOpen());
|
||||
|
||||
rawfile.Read(header, 8, 1);
|
||||
if (png_sig_cmp(header, 0, 8))
|
||||
//Read the signature from the input stream
|
||||
rawfile.Read(header, lengthof(header), 1);
|
||||
if (png_sig_cmp(header, 0, lengthof(header)))
|
||||
return nullptr;
|
||||
|
||||
png_structp pngptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (not pngptr)
|
||||
return nullptr;
|
||||
//Get the file info struct
|
||||
png_structp pngptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (not pngptr)
|
||||
return nullptr;
|
||||
|
||||
return nullptr;
|
||||
//Get the data info struct
|
||||
png_infop infoptr = png_create_info_struct(pngptr);
|
||||
if (not infoptr) {
|
||||
png_destroy_read_struct(&pngptr, nullptr, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//Set the function that will be called to read data from the stream
|
||||
png_set_read_fn(pngptr, &rawfile, ReadDataFromInputStream);
|
||||
//Tell the lib we already verified the signature
|
||||
png_set_sig_bytes(pngptr, lengthof(header));
|
||||
|
||||
//Read the header
|
||||
png_uint_32 width, height;
|
||||
int bitDepth, colorType;
|
||||
png_read_info(pngptr, infoptr);
|
||||
const png_uint_32 headerGetInfoRetVal = png_get_IHDR(pngptr, infoptr, &width, &height, &bitDepth, &colorType, nullptr, nullptr, nullptr);
|
||||
if (static_cast<png_uint_32>(-1) == headerGetInfoRetVal) {
|
||||
png_destroy_read_struct(&pngptr, &infoptr, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDL_Surface* retSurf;
|
||||
switch (colorType) {
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
retSurf = nullptr; //SurfaceFromPngRGB();
|
||||
assert(false); //not implemented
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
retSurf = SurfaceFromPngRGBA(ushort2(static_cast<uint8_t>(width), static_cast<uint8_t>(height)), bitDepth * 4, pngptr, infoptr);
|
||||
break;
|
||||
|
||||
default:
|
||||
png_destroy_read_struct(&pngptr, &infoptr, nullptr);
|
||||
retSurf = nullptr;
|
||||
}
|
||||
|
||||
return retSurf;
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
///------------------------------------------------------------------------
|
||||
///------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
Texture::Texture (const std::string& parPath, SDLMain* parMain, bool parLoadNow) :
|
||||
m_path(parPath),
|
||||
m_texture(nullptr),
|
||||
|
@ -74,14 +174,14 @@ namespace cloonel {
|
|||
Reload();
|
||||
}
|
||||
|
||||
///------------------------------------------------------------------------
|
||||
///------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
Texture::~Texture() noexcept {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
///------------------------------------------------------------------------
|
||||
///------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
void Texture::Destroy() noexcept {
|
||||
if (m_texture) {
|
||||
SDL_DestroyTexture(m_texture);
|
||||
|
@ -89,8 +189,8 @@ namespace cloonel {
|
|||
}
|
||||
}
|
||||
|
||||
///------------------------------------------------------------------------
|
||||
///------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
void Texture::Reload() {
|
||||
const GraphicFormat fmt = GuessGraphicFormatFromName(m_path);
|
||||
Destroy();
|
||||
|
@ -99,6 +199,7 @@ namespace cloonel {
|
|||
switch (fmt) {
|
||||
case GraphicFormat_Png:
|
||||
surf = LoadNewPngSurface(m_path.c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error(std::string("Unsupported file format for \"") + m_path + "\"");
|
||||
|
@ -116,9 +217,9 @@ namespace cloonel {
|
|||
}
|
||||
}
|
||||
|
||||
///------------------------------------------------------------------------
|
||||
///------------------------------------------------------------------------
|
||||
void Texture::Render (const int2& parPos) {
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
void Texture::Render (int2 parPos) const {
|
||||
assert(IsLoaded());
|
||||
const SDL_Rect dest = { parPos.x(), parPos.y(), m_size.x(), m_size.y() };
|
||||
SDL_RenderCopy(m_sdlmain->GetRenderer(), m_texture, nullptr, &dest);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue