STB Memory functions for fonts

Add the ability to read and write to a stream.
This commit is contained in:
marauder2k7 2024-01-20 22:15:17 +00:00
parent 7216ba8530
commit 106346630d
4 changed files with 129 additions and 15 deletions

View file

@ -1206,6 +1206,20 @@ bool GBitmap::readBitmap(const String& bmType, const Torque::Path& path)
return regInfo->readFunc(path, this);
}
bool GBitmap::readBitmapStream(const String& bmType, Stream& ioStream, U32 len)
{
PROFILE_SCOPE(ResourceGBitmap_readBitmapStream);
const GBitmap::Registration* regInfo = GBitmap::sFindRegInfo(bmType);
if (regInfo == NULL)
{
Con::errorf("[GBitmap::readBitmap] unable to find registration for extension [%s]", bmType.c_str());
return false;
}
return regInfo->readStreamFunc(ioStream, this, len);
}
bool GBitmap::writeBitmap( const String &bmType, const Torque::Path& path, U32 compressionLevel )
{
FileStream stream;
@ -1230,6 +1244,19 @@ bool GBitmap::writeBitmap( const String &bmType, const Torque::Path& path, U32
return regInfo->writeFunc(path, this, (compressionLevel == U32_MAX) ? regInfo->defaultCompression : compressionLevel );
}
bool GBitmap::writeBitmapStream(const String& bmType, Stream& ioStream, U32 compressionLevel)
{
const GBitmap::Registration* regInfo = GBitmap::sFindRegInfo(bmType);
if (regInfo == NULL)
{
Con::errorf("[GBitmap::writeBitmap] unable to find registration for extension [%s]", bmType.c_str());
return false;
}
return regInfo->writeStreamFunc(ioStream, this, (compressionLevel == U32_MAX) ? regInfo->defaultCompression : compressionLevel);
}
template<> void *Resource<GBitmap>::create(const Torque::Path &path)
{
PROFILE_SCOPE( ResourceGBitmap_create );

View file

@ -70,26 +70,31 @@ public:
struct Registration
{
/// The read function prototype.
/// The read functions prototype.
typedef bool(*ReadFunc)(const Torque::Path& path, GBitmap* bitmap);
/// The write function prototype. Compression levels are image-specific - see their registration declaration for details.
typedef bool(*ReadStreamFunc)(Stream& stream, GBitmap* bitmap, U32 len);
/// The write functions prototype. Compression levels are image-specific - see their registration declaration for details.
typedef bool(*WriteFunc)(const Torque::Path& path, GBitmap* bitmap, U32 compressionLevel);
typedef bool(*WriteStreamFunc)(Stream& stream, GBitmap* bitmap, U32 compressionLevel);
/// Used to sort the registrations so that
/// lookups occur in a fixed order.
U32 priority;
Vector<String> extensions; ///< the list of file extensions for this bitmap type [these should be lower case]
ReadFunc readFunc; ///< the read function to call for this bitmap type
WriteFunc writeFunc; ///< the write function to call for this bitmap type
U32 defaultCompression; ///< the default compression level [levels are image-specific - see their registration declaration for details]
ReadFunc readFunc; ///< the read function to read from a file.
WriteFunc writeFunc; ///< the write function to write to a file.
ReadStreamFunc readStreamFunc; ///< the read function to read from a stream.
WriteStreamFunc writeStreamFunc; ///< the write function to write to a stream.
U32 defaultCompression; ///< the default compression level [levels are image-specific - see their registration declaration for details]
Registration()
{
readFunc = NULL;
writeFunc = NULL;
readStreamFunc = NULL;
writeStreamFunc = NULL;
defaultCompression = 0;
priority = 0;
VECTOR_SET_ASSOCIATION( extensions );
@ -238,19 +243,24 @@ public:
//-------------------------------------- Input/Output interface
/// Read a bitmap from a stream
/// Read a bitmap from a file
/// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
/// @param ioStream The stream to read from
bool readBitmap(const String& bmType, const Torque::Path& path);
bool readBitmap(const String& bmType, const Torque::Path& path);
/// Write a bitmap to a stream
/// Sane as above but reads from a stream.
bool readBitmapStream(const String& bmType, Stream& ioStream, U32 len);
/// Write a bitmap to a file
/// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
/// @param ioStream The stream to read from
/// @param compressionLevel Image format specific compression level. For JPEG sets the quality level percentage, range 0 to 100.
/// For PNG compression level is 0 - 10
/// Not used for other image formats.
bool writeBitmap( const String &bmType, const Torque::Path& path, U32 compressionLevel = U32_MAX );
bool writeBitmap( const String &bmType, const Torque::Path& path, U32 compressionLevel = U32_MAX );
/// Sane as above but writes to a stream.
bool writeBitmapStream(const String& bmType, Stream& ioStream, U32 compressionLevel = U32_MAX);
bool readMNG(Stream& io_rStream); // located in bitmapMng.cc
bool writeMNG(Stream& io_rStream) const;

View file

@ -21,6 +21,7 @@
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/console.h"
#include "core/stream/fileStream.h"
#include "core/stream/memStream.h"
@ -40,7 +41,10 @@
#include "stb_image_write.h"
static bool sReadSTB(const Torque::Path& path, GBitmap* bitmap);
static bool sReadStreamSTB(Stream& stream, GBitmap* bitmap, U32 len);
static bool sWriteSTB(const Torque::Path& path, GBitmap* bitmap, U32 compressionLevel);
static bool sWriteStreamSTB(Stream& stream, GBitmap* bitmap, U32 compressionLevel);
static struct _privateRegisterSTB
{
@ -58,8 +62,10 @@ static struct _privateRegisterSTB
reg.extensions.push_back("tga");
reg.readFunc = sReadSTB;
reg.readStreamFunc = sReadStreamSTB;
reg.writeFunc = sWriteSTB;
reg.writeStreamFunc = sWriteStreamSTB;
// for png only.
reg.defaultCompression = 6;
@ -194,6 +200,41 @@ bool sReadSTB(const Torque::Path& path, GBitmap* bitmap)
return true;
}
bool sReadStreamSTB(Stream& stream, GBitmap* bitmap, U32 len)
{
PROFILE_SCOPE(sReadStreamSTB);
// only used for font at the moment.
U8* data = new U8[len];
stream.read(len, data);
S32 width, height, comp = 0;
unsigned char* pixelData = stbi_load_from_memory((const U8*)data, (int)len, &width, &height, &comp, 1);
if (!pixelData)
{
const char* stbErr = stbi_failure_reason();
if (!stbErr)
stbErr = "Unknown Error!";
Con::printf("sReadStreamSTB Error: %s", stbErr);
return false;
}
bitmap->deleteImage();
bitmap->allocateBitmap(256, 256, false, GFXFormatA8);
U8* pBase = bitmap->getWritableBits(0);
U32 rowBytes = bitmap->getByteSize();
dMemcpy(pBase, pixelData, rowBytes);
dFree(data);
dFree(pixelData);
return true;
}
/**
* Write bitmap to an image file.
*
@ -269,3 +310,28 @@ bool sWriteSTB(const Torque::Path& path, GBitmap* bitmap, U32 compressionLevel)
return false;
}
bool sWriteStreamSTB(Stream& stream, GBitmap* bitmap, U32 compressionLevel)
{
S32 len;
const U8* pData = bitmap->getBits();
unsigned char* png = stbi_write_png_to_mem(pData, 0, bitmap->getWidth(), bitmap->getHeight(), 1, &len);
if (!png)
{
const char* stbErr = stbi_failure_reason();
if (!stbErr)
stbErr = "Unknown Error!";
Con::printf("sReadStreamSTB Error: %s", stbErr);
return false;
}
stream.write(len);
stream.write(len, png);
dFree(png);
return true;
}

View file

@ -699,12 +699,21 @@ bool GFont::read(Stream& io_rStream)
for(i = 0; i < numSheets; i++)
{
GBitmap *bmp = new GBitmap;
String path = String::ToString("%s/%s %d %d (%s).png", Con::getVariable("$GUI::fontCacheDirectory"), mFaceName.c_str(), mSize, i, getCharSetName(mCharSet));
/*String path = String::ToString("%s/%s %d %d (%s).png", Con::getVariable("$GUI::fontCacheDirectory"), mFaceName.c_str(), mSize, i, getCharSetName(mCharSet));
if(!bmp->readBitmap("png", path))
{
delete bmp;
return false;
}*/
U32 len;
io_rStream.read(&len);
if (!bmp->readBitmapStream("png", io_rStream, len))
{
delete bmp;
return false;
}
GFXTexHandle handle = GFXTexHandle(bmp, &GFXFontTextureProfile, true, avar("%s() - Read Font Sheet for %s %d (line %d)", __FUNCTION__, mFaceName.c_str(), mSize, __LINE__));
//handle.setFilterNearest();
mTextureSheets.push_back(handle);
@ -779,7 +788,9 @@ bool GFont::write(Stream& stream)
for (i = 0; i < mTextureSheets.size(); i++)
{
String path = String::ToString("%s/%s %d %d (%s).png", Con::getVariable("$GUI::fontCacheDirectory"), mFaceName.c_str(), mSize, i, getCharSetName(mCharSet));
mTextureSheets[i].getBitmap()->writeBitmap("png", path);
//mTextureSheets[i].getBitmap()->writeBitmap("png", path);
mTextureSheets[i].getBitmap()->writeBitmapStream("png", stream);
}
stream.write(mCurX);