From 7206038cc58e2b5a85bab1ebd1241650a79e9a04 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 23 Jan 2023 06:54:58 -0500 Subject: [PATCH] Image fixes --- BeefySysLib/ResLib.cpp | 71 ++++++++++++++++++++++++++++++++---- BeefySysLib/img/JPEGData.cpp | 60 +++++++++++++++--------------- 2 files changed, 93 insertions(+), 38 deletions(-) diff --git a/BeefySysLib/ResLib.cpp b/BeefySysLib/ResLib.cpp index 7b4b72f8..846278c9 100644 --- a/BeefySysLib/ResLib.cpp +++ b/BeefySysLib/ResLib.cpp @@ -6,6 +6,10 @@ #include "util/PerfTimer.h" #include "util/TLSingleton.h" #include "img/JPEGData.h" +#include "img/TGAData.h" +#include "img/PNGData.h" +#include "img/PVRData.h" +#include "img/BFIData.h" #pragma warning(disable:4190) @@ -15,7 +19,7 @@ static TLSingleton gResLib_TLStrReturn; BF_EXPORT PSDReader* BF_CALLTYPE Res_OpenPSD(const char* fileName) { - //gPerfManager->StartRecording(); + //gPerfManager->StartRecording(); PSDReader* aPSDReader = new PSDReader(); if (!aPSDReader->Init(fileName)) @@ -41,7 +45,7 @@ BF_EXPORT TextureSegment* BF_CALLTYPE Res_PSD_GetLayerTexture(PSDReader* pSDRead if (texture == NULL) return NULL; - TextureSegment* textureSegment = new TextureSegment(); + TextureSegment* textureSegment = new TextureSegment(); textureSegment->InitFromTexture(texture); return textureSegment; } @@ -55,7 +59,7 @@ BF_EXPORT TextureSegment* BF_CALLTYPE Res_PSD_GetMergedLayerTexture(PSDReader* p if (texture == NULL) return NULL; - TextureSegment* textureSegment = new TextureSegment(); + TextureSegment* textureSegment = new TextureSegment(); textureSegment->InitFromTexture(texture); return textureSegment; } @@ -71,21 +75,21 @@ BF_EXPORT PSDLayerInfo* BF_CALLTYPE Res_PSD_GetLayerInfo(PSDReader* pSDReader, i } BF_EXPORT void BF_CALLTYPE Res_PSDLayer_GetSize(PSDLayerInfo* layerInfo, int* x, int* y, int* width, int* height) -{ +{ *x = layerInfo->mX; *y = layerInfo->mY; *width = layerInfo->mWidth; - *height = layerInfo->mHeight; + *height = layerInfo->mHeight; } BF_EXPORT int BF_CALLTYPE Res_PSDLayer_GetLayerId(PSDLayerInfo* layerInfo) -{ +{ return layerInfo->mLayerId; } BF_EXPORT const char* BF_CALLTYPE Res_PSDLayer_GetName(PSDLayerInfo* layerInfo) -{ - return layerInfo->mName.c_str(); +{ + return layerInfo->mName.c_str(); } BF_EXPORT int BF_CALLTYPE Res_PSDLayer_IsVisible(PSDLayerInfo* layerInfo) @@ -95,6 +99,57 @@ BF_EXPORT int BF_CALLTYPE Res_PSDLayer_IsVisible(PSDLayerInfo* layerInfo) /// +BF_EXPORT uint32* BF_CALLTYPE Res_LoadImage(char* inFileName, int& width, int& height) +{ + String fileName = inFileName; + + int dotPos = (int)fileName.LastIndexOf('.'); + String ext; + if (dotPos != -1) + ext = fileName.Substring(dotPos); + + ImageData* imageData = NULL; + bool handled = false; + bool failed = false; + + if (fileName == "!white") + { + imageData = new ImageData(); + imageData->CreateNew(1, 1, true); + imageData->mBits[0] = 0xFFFFFFFF; + handled = true; + } + else if (ext == ".tga") + imageData = new TGAData(); + else if (ext == ".png") + imageData = new PNGData(); + else if (ext == ".jpg") + imageData = new JPEGData(); + else if (ext == ".pvr") + imageData = new PVRData(); + else + { + BF_FATAL("Unknown texture format"); + return NULL; // Unknown format + } + + if (!imageData->LoadFromFile(fileName)) + { + imageData->Deref(); + BF_FATAL("Failed to load image"); + return NULL; + } + + uint32* bits = imageData->mBits; + imageData->mBits = NULL; + + width = imageData->mWidth; + height = imageData->mHeight; + imageData->Deref(); + + return bits; +} + BF_EXPORT StringView BF_CALLTYPE Res_JPEGCompress(uint32* bits, int width, int height, int quality) { String& outString = *gResLib_TLStrReturn.Get(); diff --git a/BeefySysLib/img/JPEGData.cpp b/BeefySysLib/img/JPEGData.cpp index c139b04d..8fc21c85 100644 --- a/BeefySysLib/img/JPEGData.cpp +++ b/BeefySysLib/img/JPEGData.cpp @@ -20,40 +20,40 @@ USING_NS_BF; // JPEG error handling // Will "longjmp" on error_exit. // ----------------------------------------------------------------------- - + struct ErrorHandler { /** "subclass" of jpeg_error_mgr */ struct jpeg_error_mgr errorMgr; jmp_buf setjmpBuffer; - + ErrorHandler( j_decompress_ptr cinfo ) { Init( (j_common_ptr)cinfo ); } - + ErrorHandler( j_compress_ptr cinfo ) { Init( (j_common_ptr)cinfo ); } - + void Init( j_common_ptr cinfo ) { // setup the standard error handling. cinfo->err = jpeg_std_error( &errorMgr ); - + // then hook up our error_exit function. errorMgr.error_exit = &ErrorHandler::OnErrorExit; } - + static void OnErrorExit( j_common_ptr cinfo ) { // recover the pointer to "derived class" instance ErrorHandler* errorHandler = (ErrorHandler*)cinfo->err; - + // use the default error message output. (*cinfo->err->output_message)( cinfo ); - + // return control to the setjmp point. longjmp( errorHandler->setjmpBuffer, 1 ); } @@ -64,14 +64,14 @@ struct JpegMemSource JpegMemSource(JPEGData* buffer, j_decompress_ptr cinfo ) { struct jpeg_source_mgr * src; - + if ( cinfo->src == NULL ) { // Have the jpeg library allocate the source manager object so // that it is automatically deallocated by the decompressor. cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)( (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr) ); } - + src = cinfo->src; src->init_source = &JpegMemSource::InitSource; src->fill_input_buffer = &JpegMemSource::FillInputBuffer; @@ -88,16 +88,16 @@ struct JpegMemSource // completely skip the destruction of this C++ data source wrapper, // but that is OK so long as there is no actual cleanup to do. } - + static void InitSource( j_decompress_ptr cinfo ) { /* no work necessary here */ } - + static boolean FillInputBuffer( j_decompress_ptr cinfo ) { static JOCTET mybuffer[4]; - + /* The whole JPEG data is expected to reside in the supplied memory * buffer, so any request for more data beyond the given buffer size * is treated as an error. @@ -106,17 +106,17 @@ struct JpegMemSource /* Insert a fake EOI marker */ mybuffer[0] = (JOCTET) 0xFF; mybuffer[1] = (JOCTET) JPEG_EOI; - + cinfo->src->next_input_byte = mybuffer; cinfo->src->bytes_in_buffer = 2; - + return TRUE; } static void SkipInputData( j_decompress_ptr cinfo, long num_bytes ) { struct jpeg_source_mgr * src = cinfo->src; - + /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. @@ -133,12 +133,12 @@ struct JpegMemSource src->bytes_in_buffer -= (size_t) num_bytes; } } - + static void TermSource( j_decompress_ptr cinfo ) { /* no work necessary here */ } - + }; #define JPEGMEMDEST_BLOCK_SIZE 16384 @@ -148,9 +148,9 @@ struct JpegMemDest : jpeg_destination_mgr Array mData; JpegMemDest(JPEGData* buffer, j_compress_ptr cinfo) - { + { if (cinfo->dest == NULL) - { + { cinfo->dest = this; } @@ -160,7 +160,7 @@ struct JpegMemDest : jpeg_destination_mgr } ~JpegMemDest() - { + { } static void InitDestination(j_compress_ptr cinfo) @@ -189,14 +189,14 @@ struct JpegMemDest : jpeg_destination_mgr }; bool JPEGData::ReadData() -{ +{ jpeg_decompress_struct cinfo; ErrorHandler err( &cinfo ); if ( setjmp( err.setjmpBuffer ) ) { // ErrorHandler::OnErrorExit will longjmp back to here from // within the ReadImage call below. - jpeg_destroy_decompress( &cinfo ); + jpeg_destroy_decompress( &cinfo ); return false; } @@ -257,7 +257,7 @@ bool JPEGData::ReadData() void JPEGData::Compress(int quality) { jpeg_compress_struct cinfo; - + /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); @@ -310,23 +310,23 @@ void JPEGData::Compress(int quality) * more if you wish, though. */ int row_stride = mWidth * 3; /* JSAMPLEs per row in image_buffer */ - + uint8* line = new uint8[mWidth * 3]; row_pointer[0] = (JSAMPROW)line; - while (cinfo.next_scanline < cinfo.image_height) - { - uint8* src = (uint8*)&mBits[(mHeight - cinfo.next_scanline - 1) * mWidth]; + while (cinfo.next_scanline < cinfo.image_height) + { + uint8* src = (uint8*)&mBits[cinfo.next_scanline * mWidth]; uint8* dest = line; for (int x = 0; x < mWidth; x++) { *(dest++) = src[2]; *(dest++) = src[1]; - *(dest++) = src[0]; + *(dest++) = src[0]; src += 4; } - + (void)jpeg_write_scanlines(&cinfo, row_pointer, 1); }