Skip to content

Commit b1f280a

Browse files
committed
Added support for export to PBM/PGM/ICO.
1 parent f796aa4 commit b1f280a

File tree

6 files changed

+2539
-1746
lines changed

6 files changed

+2539
-1746
lines changed

Src/Files/SL2StdFile.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ namespace sl2 {
123123
*/
124124
virtual bool WriteToFile( const uint8_t * _pui8Data, size_t _tsSize );
125125

126+
/**
127+
* Gets the internal FILE handle.
128+
*
129+
* \return Returns the internal pointer to the FILE object.
130+
**/
131+
virtual FILE * Handle() { return m_pfFile; }
132+
126133
/**
127134
* Loads the opened file to memory, storing the result in _vResult.
128135
*

Src/Image/SL2Image.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,27 @@ namespace sl2 {
546546
for ( size_t M = 0; M < iTmp.Mipmaps(); ++M ) {
547547
for ( size_t A = 0; A < iTmp.ArraySize(); ++A ) {
548548
for ( size_t F = 0; F < iTmp.Faces(); ++F ) {
549+
if ( !_pkifFormat->bFloatFormat ||
550+
_pkifFormat->vfVulkanFormat == SL2_VK_FORMAT_B10G11R11_UFLOAT_PACK32 || _pkifFormat->vfVulkanFormat == SL2_VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 ||
551+
_pkifFormat->vfVulkanFormat == SL2_VK_FORMAT_D32_SFLOAT || _pkifFormat->vfVulkanFormat == SL2_VK_FORMAT_D32_SFLOAT_S8_UINT ||
552+
_pkifFormat->kifInternalFormat == SL2_GL_DEPTH32F_STENCIL8_NV || _pkifFormat->kifInternalFormat == SL2_GL_DEPTH_COMPONENT32F_NV ||
553+
_pkifFormat->kifInternalFormat == SL2_GL_LUMINANCE_ALPHA32F_ARB || _pkifFormat->kifInternalFormat == SL2_GL_LUMINANCE_ALPHA16F_ARB ||
554+
_pkifFormat->kifInternalFormat == SL2_GL_LUMINANCE32F_ARB || _pkifFormat->kifInternalFormat == SL2_GL_LUMINANCE16F_ARB ||
555+
_pkifFormat->kifInternalFormat == SL2_GL_ALPHA32F_ARB || _pkifFormat->kifInternalFormat == SL2_GL_ALPHA16F_ARB ) {
556+
double dLow = 0.0, dHi = 1.0;
557+
if ( _pkifFormat->ui64PvrPixelFmt == PVRTLVT_SignedByteNorm ||
558+
_pkifFormat->ui64PvrPixelFmt == PVRTLVT_SignedByte ||
559+
_pkifFormat->ui64PvrPixelFmt == PVRTLVT_SignedShortNorm ||
560+
_pkifFormat->ui64PvrPixelFmt == PVRTLVT_SignedShort ||
561+
_pkifFormat->ui64PvrPixelFmt == PVRTLVT_SignedIntegerNorm ||
562+
_pkifFormat->ui64PvrPixelFmt == PVRTLVT_SignedInteger ) {
563+
dLow = -1.0;
564+
}
565+
Clamp( reinterpret_cast<double *>(iTmp.Data( M, 0, A, F )),
566+
iTmp.m_vMipMaps[M]->Width() * iTmp.m_vMipMaps[M]->Height() * iTmp.m_vMipMaps[M]->Depth(),
567+
dLow, dHi );
568+
}
569+
549570
if ( m_kKernel.Size() ) {
550571
if ( !ConvertToNormalMap( reinterpret_cast<CFormat::SL2_RGBA64F *>(iTmp.Data( M, 0, A, F )), iTmp.m_vMipMaps[M]->Width(), iTmp.m_vMipMaps[M]->Height(), iTmp.m_vMipMaps[M]->Depth() ) ) { return SL2_E_OUTOFMEMORY; }
551572
}
@@ -1110,6 +1131,26 @@ namespace sl2 {
11101131
}
11111132
}
11121133

1134+
/**
1135+
* Clamps the given texture between the high and low values.
1136+
*
1137+
* \param _pdBuffer The pointer to the RGBA64F buffer to clamp.
1138+
* \param _sTotal The number of texels in the given buffer.
1139+
* \param _dLow The low clamp value.
1140+
* \param _dHigh The high clamp value.
1141+
**/
1142+
bool CImage::Clamp( double * _pdBuffer, size_t _sTotal, double _dLow, double _dHigh ) {
1143+
if ( size_t( _sTotal * 4 ) <= _sTotal ) { return false; }
1144+
_sTotal *= 4;
1145+
while ( _sTotal-- ) {
1146+
if SL2_UNLIKELY( _pdBuffer[0] < _dLow ) { _pdBuffer[0] = _dLow; }
1147+
else if SL2_UNLIKELY( _pdBuffer[0] > _dHigh ) { _pdBuffer[0] = _dHigh; }
1148+
1149+
_pdBuffer++;
1150+
}
1151+
return true;
1152+
}
1153+
11131154
/**
11141155
* Applies an ICC colorspace transfer function to a given RGBA64F buffer.
11151156
*
@@ -1415,7 +1456,7 @@ namespace sl2 {
14151456
FREE_IMAGE_FORMAT fifFormat = ::FreeImage_GetFileTypeFromMemory( fiImage.pmMemory, 0 );
14161457
if ( FIF_UNKNOWN == fifFormat ) { return SL2_E_INVALIDFILETYPE; }
14171458

1418-
if ( fifFormat == FIF_GIF ) {
1459+
if ( fifFormat == FIF_GIF || fifFormat == FIF_ICO || fifFormat == FIF_TIFF ) {
14191460
SL2_FREEIMAGE_LOAD_MULTI_BIPMAP_FROM_MEMORY flmbfmData( fiImage );
14201461
int iFrameCount = ::FreeImage_GetPageCount( flmbfmData.pbBitmap );
14211462

Src/Image/SL2Image.h

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/**
1+
/**
22
* Copyright L. Spiro 2024
33
*
44
* Written by: Shawn (L. Spiro) Wilcoxen
@@ -109,6 +109,21 @@ namespace sl2 {
109109
FIMULTIBITMAP * pbBitmap;
110110
};
111111

112+
/** Wraps FreeImage_OpenMultiBitmapFromHandle(). */
113+
struct SL2_FREEIMAGE_OPEN_MULTI_BIPMAP_FROM_HANDLE {
114+
SL2_FREEIMAGE_OPEN_MULTI_BIPMAP_FROM_HANDLE( FREE_IMAGE_FORMAT _fiF, FreeImageIO * _pfiIo, fi_handle _hHandle, int _iFlags FI_DEFAULT( 0 ) ) :
115+
pbBitmap( ::FreeImage_OpenMultiBitmapFromHandle( _fiF, _pfiIo, _hHandle, _iFlags ) ) {
116+
}
117+
~SL2_FREEIMAGE_OPEN_MULTI_BIPMAP_FROM_HANDLE() {
118+
::FreeImage_CloseMultiBitmap( pbBitmap );
119+
pbBitmap = nullptr;
120+
}
121+
122+
123+
// == Members.
124+
FIMULTIBITMAP * pbBitmap;
125+
};
126+
112127
/** Wraps FreeImage_Allocate(). */
113128
struct SL2_FREEIMAGE_ALLOCATE {
114129
SL2_FREEIMAGE_ALLOCATE( int _iWidth, int _iHeight, int _iBpp, unsigned _uRedMask FI_DEFAULT(0), unsigned _uGreenMask FI_DEFAULT(0), unsigned _uBlueMask FI_DEFAULT(0) ) :
@@ -806,7 +821,53 @@ namespace sl2 {
806821
static double ApplyKernel( double * _pdImage, uint32_t _ui32X, uint32_t _ui32Y, uint32_t _ui32W, uint32_t _ui32H, uint32_t _ui32D, const CKernel &_kKernel,
807822
SL2_TEXTURE_ADDRESSING _taAddressW, SL2_TEXTURE_ADDRESSING _taAddressH, double _dBorder );
808823

809-
824+
/**
825+
* FreeImage read handler.
826+
*
827+
* \param _pvBuffer Pointer to the array where the read objects are stored.
828+
* \param _uSize Size of each object in bytes.
829+
* \param _uCount The number of the objects to be read.
830+
* \param _hHandle The stream to read.
831+
* \return Number of objects read successfully, which may be less than _uCount if an error or end-of-file condition occurs. If _uSize or _uCount is zero, fread returns zero and performs no other action.
832+
**/
833+
static unsigned DLL_CALLCONV FI_Read( void * _pvBuffer, unsigned _uSize, unsigned _uCount, fi_handle _hHandle ) {
834+
return static_cast<unsigned>(::fread( _pvBuffer, _uSize, _uCount, reinterpret_cast<FILE *>(_hHandle)));
835+
}
836+
837+
/**
838+
* FreeImage write handler.
839+
*
840+
* \param _pvBuffer Pointer to the first object in the array to be written.
841+
* \param _uSize Size of each object.
842+
* \param _uCount The number of the objects to be written.
843+
* \param _hHandle Pointer to the output stream.
844+
* \return The number of objects written successfully, which may be less than _uCount if an error occurs. If _uSize or _uCount is zero, fwrite returns zero and performs no other action.
845+
**/
846+
static unsigned DLL_CALLCONV FI_Write( void * _pvBuffer, unsigned _uSize, unsigned _uCount, fi_handle _hHandle ) {
847+
return static_cast<unsigned>(::fwrite( _pvBuffer, _uSize, _uCount, reinterpret_cast<FILE *>(_hHandle)));
848+
}
849+
850+
/**
851+
* Sets the file position indicator for the file stream stream to the value pointed to by _uOffset.
852+
*
853+
* \param _hHandle File stream to modify
854+
* \param _uOffset Number of characters to shift the position relative to origin.
855+
* \param _uOrigin Position to which offset is added. It can have one of the following values: SEEK_SET, SEEK_CUR, SEEK_END.
856+
* \return ​0​ upon success, nonzero value otherwise.
857+
**/
858+
static int DLL_CALLCONV FI_Seek( fi_handle _hHandle, long _uOffset, int _uOrigin ) {
859+
return static_cast<int>(::fseek( reinterpret_cast<FILE *>(_hHandle), _uOffset, _uOrigin));
860+
}
861+
862+
/**
863+
* Returns the file position indicator for the file stream _hHandle.
864+
*
865+
* \param _hHandle File stream to examine.
866+
* \return File position indicator on success or -1L if failure occurs.
867+
**/
868+
static long DLL_CALLCONV FI_Tell( fi_handle _hHandle ) {
869+
return static_cast<long>(::ftell( reinterpret_cast<FILE *>(_hHandle) ));
870+
}
810871

811872

812873
protected :
@@ -935,6 +996,16 @@ namespace sl2 {
935996
**/
936997
void BakeGamma( uint8_t * _pui8Buffer, double _dGamma, uint32_t _ui32Width, uint32_t _ui32Height, uint32_t _ui32Depth, CFormat::SL2_TRANSFER_FUNCS _ptfGamma );
937998

999+
/**
1000+
* Clamps the given texture between the high and low values.
1001+
*
1002+
* \param _pdBuffer The pointer to the RGBA64F buffer to clamp.
1003+
* \param _sTotal The number of texels in the given buffer.
1004+
* \param _dLow The low clamp value.
1005+
* \param _dHigh The high clamp value.
1006+
**/
1007+
static bool Clamp( double * _pdBuffer, size_t _sTotal, double _dLow = 0.0, double _dHigh = 1.0 );
1008+
9381009
/**
9391010
* Applies an ICC colorspace transfer function to a given RGBA64F buffer.
9401011
*

Src/OS/SL2Windows.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
#define SL2_EXPECT( COND, VAL ) (COND)
5151
#define SL2_PREFETCH_LINE( ADDR ) _mm_prefetch( reinterpret_cast<const char *>(ADDR), _MM_HINT_T0 )
5252
#define SL2_PREFETCH_LINE_WRITE( ADDR )
53+
#define SL2_LIKELY( x ) ( x ) [[likely]]
54+
#define SL2_UNLIKELY( x ) ( x ) [[unlikely]]
5355

5456
#ifndef SL2_WIN64
5557
// Mercilessly ripped from: https://stackoverflow.com/a/46924301

0 commit comments

Comments
 (0)