Last active
September 20, 2018 03:45
-
-
Save Ohmnivore/1d2c497664869e2f8e94f5fa77e4d4a3 to your computer and use it in GitHub Desktop.
stb_image.h (.png, .jpg, etc) loader for oryol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define STB_IMAGE_IMPLEMENTATION | |
#define STBI_ONLY_PNG | |
#define STBI_NO_STDIO | |
#define STBI_NO_FAILURE_STRINGS | |
#include "stb/stb_image.h" | |
#include "IO/IO.h" | |
#include "Gfx/Gfx.h" | |
#include "Gfx/private/gfxResourceContainer.h" | |
#include "STBTextureLoader.h" | |
namespace Oryol { | |
//------------------------------------------------------------------------------ | |
STBTextureLoader::STBTextureLoader(const TextureSetup& setup_) : | |
TextureLoaderBase(setup_) { | |
// empty | |
} | |
//------------------------------------------------------------------------------ | |
STBTextureLoader::STBTextureLoader(const TextureSetup& setup_, LoadedFunc loadedFunc_) : | |
TextureLoaderBase(setup_, loadedFunc_) { | |
// empty | |
} | |
//------------------------------------------------------------------------------ | |
STBTextureLoader::~STBTextureLoader() { | |
o_assert_dbg(!this->ioRequest); | |
} | |
//------------------------------------------------------------------------------ | |
void | |
STBTextureLoader::Cancel() { | |
if (this->ioRequest) { | |
this->ioRequest->Cancelled = true; | |
this->ioRequest = nullptr; | |
} | |
} | |
//------------------------------------------------------------------------------ | |
Id | |
STBTextureLoader::Start() { | |
this->resId = Gfx::resource()->prepareAsync(this->setup); | |
this->ioRequest = IO::LoadFile(setup.Locator.Location()); | |
return this->resId; | |
} | |
//------------------------------------------------------------------------------ | |
ResourceState::Code | |
STBTextureLoader::Continue() { | |
o_assert_dbg(this->resId.IsValid()); | |
o_assert_dbg(this->ioRequest.isValid()); | |
ResourceState::Code result = ResourceState::Pending; | |
if (this->ioRequest->Handled) { | |
if (IOStatus::OK == this->ioRequest->Status) { | |
// yeah, IO is done, let stb_image parse the texture data | |
// and create the texture resource | |
const uint8_t* data = this->ioRequest->Data.Data(); | |
const int numBytes = this->ioRequest->Data.Size(); | |
int width, height, numComponents; | |
unsigned char* imgData = stbi_load_from_memory(data, numBytes, &width, &height, &numComponents, 0); | |
if (imgData != NULL) { | |
const int size = width * height * numComponents; | |
TextureSetup texSetup = this->buildSetup(this->setup, width, height, numComponents, imgData, size); | |
// call the Loaded callback if defined, this | |
// gives the app a chance to look at the | |
// setup object, and possibly modify it | |
if (this->onLoaded) { | |
this->onLoaded(texSetup); | |
} | |
// NOTE: the prepared texture resource might have already been | |
// destroyed at this point, if this happens, initAsync will | |
// silently fail and return ResourceState::InvalidState | |
// (the same for failedAsync) | |
result = Gfx::resource()->initAsync(this->resId, texSetup, imgData, size); | |
// Free data! | |
stbi_image_free(imgData); | |
} | |
else { | |
result = Gfx::resource()->failedAsync(this->resId); | |
} | |
} | |
else { | |
// IO had failed | |
result = Gfx::resource()->failedAsync(this->resId); | |
} | |
this->ioRequest = nullptr; | |
} | |
return result; | |
} | |
//------------------------------------------------------------------------------ | |
TextureSetup | |
STBTextureLoader::buildSetup(const TextureSetup& blueprint, | |
const int width, const int height, const int numComponents, | |
const uint8_t* data, const int size) | |
{ | |
PixelFormat::Code pixelFormat = PixelFormat::InvalidPixelFormat; | |
if (numComponents == 3) | |
pixelFormat = PixelFormat::RGB8; | |
else if (numComponents == 4) | |
pixelFormat = PixelFormat::RGBA8; | |
o_assert(PixelFormat::InvalidPixelFormat != pixelFormat); | |
TextureSetup newSetup; | |
newSetup = TextureSetup::FromPixelData2D(width, height, 1, pixelFormat, this->setup); | |
// setup mipmap offsets | |
newSetup.ImageData.Offsets[0][0] = 0; | |
newSetup.ImageData.Sizes[0][0] = size; | |
return newSetup; | |
} | |
} // namespace Oryol |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "Gfx/TextureLoaderBase.h" | |
#include "IO/private/ioRequests.h" | |
namespace Oryol { | |
class STBTextureLoader : public TextureLoaderBase { | |
OryolClassDecl(STBTextureLoader); | |
public: | |
/// constructor without success-callback | |
STBTextureLoader(const TextureSetup& setup); | |
/// constructor with success callback | |
STBTextureLoader(const TextureSetup& setup, LoadedFunc onLoaded); | |
/// destructor | |
~STBTextureLoader(); | |
/// start loading, return a resource id | |
virtual Id Start() override; | |
/// continue loading, return resource state (Pending, Valid, Failed) | |
virtual ResourceState::Code Continue() override; | |
/// cancel the load process | |
virtual void Cancel() override; | |
private: | |
/// convert image context attrs into a TextureSetup object | |
TextureSetup buildSetup(const TextureSetup& blueprint, | |
const int width, const int height, const int numComponents, | |
const uint8_t* data, const int size); | |
Id resId; | |
Ptr<IORead> ioRequest; | |
}; | |
} // namespace Oryol |
Make sure to setup your own #define
statements and include path in STBTextureLoader.cc
according to your needs. The docs for the #defines can be found in stb_image.h
.
Also, only supports 2D textures with no mipmaps. (No texture arrays either)
Supports only RGB and RGBA channel configuration.
Note: I had forgotten to call stbi_image_free(imgData);
. This created a memory leak :(
This is now fixed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on https://github.com/floooh/oryol/blob/master/code/Modules/Assets/Gfx/TextureLoader.h and https://github.com/floooh/oryol/blob/master/code/Modules/Assets/Gfx/TextureLoader.cc
Uses https://github.com/nothings/stb/blob/master/stb_image.h