120 _Inout_opt_ DWORD* convFlags )
129 return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
132 auto pHeader =
reinterpret_cast<const TGA_HEADER*
>( pSource );
134 if ( pHeader->bColorMapType != 0
135 || pHeader->wColorMapLength != 0 )
137 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
142 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
145 if ( !pHeader->wWidth || !pHeader->wHeight )
147 return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
150 switch ( pHeader->bImageType )
154 switch( pHeader->bBitsPerPixel )
157 metadata.format = DXGI_FORMAT_B5G5R5A1_UNORM;
161 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
168 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
181 switch( pHeader->bBitsPerPixel )
184 metadata.format = DXGI_FORMAT_R8_UNORM;
188 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
200 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
203 return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
206 metadata.width = pHeader->wWidth;
207 metadata.height = pHeader->wHeight;
208 metadata.depth = metadata.arraySize = metadata.mipLevels = 1;
222 if ( pHeader->bIDLength != 0 )
224 offset += pHeader->bIDLength;
238 auto pPixels =
reinterpret_cast<uint8_t*
>( image->pixels );
242 for(
size_t y = 0;
y < image->height; ++
y )
245 pPixels += image->rowPitch;
257 assert( pSource && size > 0 );
259 if ( !image || !image->pixels )
266 rowPitch = image->width * 3;
274 auto sPtr =
reinterpret_cast<const uint8_t*
>( pSource );
277 switch( image->format )
280 case DXGI_FORMAT_R8_UNORM:
281 for(
size_t y=0;
y < image->height; ++
y )
284 assert( offset < rowPitch);
290 for(
size_t x=0; x < image->width; )
292 if ( sPtr >= endPtr )
298 size_t j = (*sPtr & 0x7F) + 1;
299 if ( ++sPtr >= endPtr )
302 for( ; j > 0; --j, ++x )
304 if ( x >= image->width )
320 size_t j = (*sPtr & 0x7F) + 1;
323 if ( sPtr+j > endPtr )
326 for( ; j > 0; --j, ++x )
328 if ( x >= image->width )
344 case DXGI_FORMAT_B5G5R5A1_UNORM:
346 bool nonzeroa =
false;
347 for(
size_t y=0;
y < image->height; ++
y )
350 assert( offset*2 < rowPitch);
352 uint16_t* dPtr =
reinterpret_cast<uint16_t*
>(
reinterpret_cast<uint8_t*
>( image->pixels )
356 for(
size_t x=0; x < image->width; )
358 if ( sPtr >= endPtr )
364 size_t j = (*sPtr & 0x7F) + 1;
367 if ( sPtr+1 >= endPtr )
370 uint16_t t = *sPtr | (*(sPtr+1) << 8);
375 for( ; j > 0; --j, ++x )
377 if ( x >= image->width )
391 size_t j = (*sPtr & 0x7F) + 1;
394 if ( sPtr+(j*2) > endPtr )
397 for( ; j > 0; --j, ++x )
399 if ( x >= image->width )
402 uint16_t t = *sPtr | (*(sPtr+1) << 8);
428 case DXGI_FORMAT_R8G8B8A8_UNORM:
430 bool nonzeroa =
false;
431 for(
size_t y=0;
y < image->height; ++
y )
435 uint32_t* dPtr =
reinterpret_cast<uint32_t*
>(
reinterpret_cast<uint8_t*
>( image->pixels )
439 for(
size_t x=0; x < image->width; )
441 if ( sPtr >= endPtr )
447 size_t j = (*sPtr & 0x7F) + 1;
451 if ( convFlags & CONV_FLAGS_EXPAND )
453 assert( offset*3 < rowPitch);
455 if ( sPtr+2 >= endPtr )
459 t = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | 0xFF000000;
466 assert( offset*4 < rowPitch);
468 if ( sPtr+3 >= endPtr )
472 t = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | ( *(sPtr+3) << 24 );
480 for( ; j > 0; --j, ++x )
482 if ( x >= image->width )
496 size_t j = (*sPtr & 0x7F) + 1;
499 if ( convFlags & CONV_FLAGS_EXPAND )
501 if ( sPtr+(j*3) > endPtr )
506 if ( sPtr+(j*4) > endPtr )
510 for( ; j > 0; --j, ++x )
512 if ( x >= image->width )
515 if ( convFlags & CONV_FLAGS_EXPAND )
517 assert( offset*3 < rowPitch);
519 if ( sPtr+2 >= endPtr )
523 *dPtr = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | 0xFF000000;
530 assert( offset*4 < rowPitch);
532 if ( sPtr+3 >= endPtr )
536 *dPtr = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | ( *(sPtr+3) << 24 );
577 assert( pSource && size > 0 );
579 if ( !image || !image->pixels )
586 rowPitch = image->width * 3;
594 const uint8_t* sPtr =
reinterpret_cast<const uint8_t*
>( pSource );
597 switch( image->format )
600 case DXGI_FORMAT_R8_UNORM:
601 for(
size_t y=0;
y < image->height; ++
y )
604 assert( offset < rowPitch);
610 for(
size_t x=0; x < image->width; ++x )
612 if ( sPtr >= endPtr )
626 case DXGI_FORMAT_B5G5R5A1_UNORM:
628 bool nonzeroa =
false;
629 for(
size_t y=0;
y < image->height; ++
y )
632 assert( offset*2 < rowPitch);
634 uint16_t* dPtr =
reinterpret_cast<uint16_t*
>(
reinterpret_cast<uint8_t*
>( image->pixels )
638 for(
size_t x=0; x < image->width; ++x )
640 if ( sPtr+1 >= endPtr )
643 uint16_t t = *sPtr | (*(sPtr+1) << 8);
668 case DXGI_FORMAT_R8G8B8A8_UNORM:
670 bool nonzeroa =
false;
671 for(
size_t y=0;
y < image->height; ++
y )
675 uint32_t* dPtr =
reinterpret_cast<uint32_t*
>(
reinterpret_cast<uint8_t*
>( image->pixels )
679 for(
size_t x=0; x < image->width; ++x )
681 if ( convFlags & CONV_FLAGS_EXPAND )
683 assert( offset*3 < rowPitch);
685 if ( sPtr+2 >= endPtr )
689 *dPtr = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | 0xFF000000;
696 assert( offset*4 < rowPitch);
698 if ( sPtr+3 >= endPtr )
702 *dPtr = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | ( *(sPtr+3) << 24 );
743 if ( (image.width > 0xFFFF)
744 || (image.height > 0xFFFF) )
746 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
749 header.wWidth =
static_cast<uint16_t
>( image.width );
750 header.wHeight =
static_cast<uint16_t
>( image.height );
752 switch( image.format )
754 case DXGI_FORMAT_R8G8B8A8_UNORM:
755 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
757 header.bBitsPerPixel = 32;
762 case DXGI_FORMAT_B8G8R8A8_UNORM:
763 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
765 header.bBitsPerPixel = 32;
769 case DXGI_FORMAT_B8G8R8X8_UNORM:
770 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
772 header.bBitsPerPixel = 24;
777 case DXGI_FORMAT_R8_UNORM:
778 case DXGI_FORMAT_A8_UNORM:
780 header.bBitsPerPixel = 8;
784 case DXGI_FORMAT_B5G5R5A1_UNORM:
786 header.bBitsPerPixel = 16;
791 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
801 #pragma warning(suppress: 6001 6101) // In the case where outSize is insufficient we do not write to pDestination
805 assert( pDestination && outSize > 0 );
806 assert( pSource && inSize > 0 );
808 assert( pDestination != pSource );
810 const uint32_t * __restrict sPtr =
reinterpret_cast<const uint32_t*
>(pSource);
811 uint8_t * __restrict dPtr =
reinterpret_cast<uint8_t*
>(pDestination);
813 if ( inSize >= 4 && outSize >= 3 )
819 uint32_t t = *(sPtr++);
821 if ( dPtr+3 > endPtr )
825 *(dPtr++) =
uint8_t((t & 0xFF00) >> 8);
826 *(dPtr++) =
uint8_t((t & 0xFF0000) >> 16);
839 _Use_decl_annotations_
842 if ( !pSource || size == 0 )
849 _Use_decl_annotations_
855 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
859 FILE_FLAG_SEQUENTIAL_SCAN, 0 ) ) );
863 return HRESULT_FROM_WIN32( GetLastError() );
867 LARGE_INTEGER fileSize = {0};
869 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
870 FILE_STANDARD_INFO fileInfo;
871 if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo,
sizeof(fileInfo) ) )
873 return HRESULT_FROM_WIN32( GetLastError() );
875 fileSize = fileInfo.EndOfFile;
877 if ( !GetFileSizeEx( hFile.get(), &fileSize ) )
879 return HRESULT_FROM_WIN32( GetLastError() );
884 if ( fileSize.HighPart > 0 )
886 return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
890 if ( fileSize.LowPart < (
sizeof(
TGA_HEADER) ) )
898 if ( !ReadFile( hFile.get(), header,
sizeof(
TGA_HEADER), &bytesRead, 0 ) )
900 return HRESULT_FROM_WIN32( GetLastError() );
911 _Use_decl_annotations_
914 if ( !pSource || size == 0 )
929 auto pPixels =
reinterpret_cast<LPCVOID
>(
reinterpret_cast<const uint8_t*
>(pSource) + offset );
931 size_t remaining = size - offset;
932 if ( remaining == 0 )
964 _Use_decl_annotations_
972 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
976 FILE_FLAG_SEQUENTIAL_SCAN, 0 ) ) );
980 return HRESULT_FROM_WIN32( GetLastError() );
984 LARGE_INTEGER fileSize = {0};
986 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
987 FILE_STANDARD_INFO fileInfo;
988 if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo,
sizeof(fileInfo) ) )
990 return HRESULT_FROM_WIN32( GetLastError() );
992 fileSize = fileInfo.EndOfFile;
994 if ( !GetFileSizeEx( hFile.get(), &fileSize ) )
996 return HRESULT_FROM_WIN32( GetLastError() );
1001 if ( fileSize.HighPart > 0 )
1003 return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
1014 DWORD bytesRead = 0;
1015 if ( !ReadFile( hFile.get(), header,
sizeof(
TGA_HEADER), &bytesRead, 0 ) )
1017 return HRESULT_FROM_WIN32( GetLastError() );
1021 DWORD convFlags = 0;
1023 HRESULT hr =
_DecodeTGAHeader( header, bytesRead, mdata, offset, &convFlags );
1028 DWORD remaining =
static_cast<DWORD
>( fileSize.LowPart - offset );
1029 if ( remaining == 0 )
1035 LARGE_INTEGER filePos = {
static_cast<DWORD
>(offset), 0 };
1036 if ( !SetFilePointerEx( hFile.get(), filePos, 0, FILE_BEGIN ) )
1038 return HRESULT_FROM_WIN32( GetLastError() );
1051 if ( !ReadFile( hFile.get(), image.
GetPixels(),
static_cast<DWORD
>( image.
GetPixelsSize() ), &bytesRead, 0 ) )
1054 return HRESULT_FROM_WIN32( GetLastError() );
1065 case DXGI_FORMAT_R8G8B8A8_UNORM:
1073 uint8_t *pPixels = img->pixels;
1077 size_t rowPitch = img->rowPitch;
1080 bool nonzeroa =
false;
1082 for(
size_t h = 0; h < img->height; ++h )
1084 const uint32_t* sPtr =
reinterpret_cast<const uint32_t*
>( pPixels );
1086 for(
size_t x=0; x < img->width; ++x )
1088 if ( (*sPtr) & 0xff000000 )
1100 pPixels += rowPitch;
1106 pPixels = img->pixels;
1108 for(
size_t h = 0; h < img->height; ++h )
1111 pPixels += rowPitch;
1118 case DXGI_FORMAT_B5G5R5A1_UNORM:
1126 bool nonzeroa =
false;
1128 const uint8_t *pPixels = img->pixels;
1132 size_t rowPitch = img->rowPitch;
1134 for(
size_t h = 0; h < img->height; ++h )
1136 const uint16_t* sPtr =
reinterpret_cast<const uint16_t*
>( pPixels );
1138 for(
size_t x=0; x < img->width; ++x )
1140 if ( *sPtr & 0x8000 )
1152 pPixels += rowPitch;
1168 std::unique_ptr<uint8_t[]> temp(
new (std::nothrow)
uint8_t[ remaining ] );
1172 return E_OUTOFMEMORY;
1175 if ( !ReadFile( hFile.get(), temp.get(), remaining, &bytesRead, 0 ) )
1178 return HRESULT_FROM_WIN32( GetLastError() );
1181 if ( bytesRead != remaining )
1213 _Use_decl_annotations_
1220 DWORD convFlags = 0;
1228 size_t rowPitch, slicePitch;
1231 rowPitch = image.
width * 3;
1232 slicePitch = image.
height * rowPitch;
1249 auto pPixels =
reinterpret_cast<const uint8_t*
>( image.
pixels );
1252 for(
size_t y = 0;
y < image.
height; ++
y )
1255 if ( convFlags & CONV_FLAGS_888 )
1279 _Use_decl_annotations_
1283 return E_INVALIDARG;
1289 DWORD convFlags = 0;
1295 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
1302 return HRESULT_FROM_WIN32( GetLastError() );
1306 size_t rowPitch, slicePitch;
1309 rowPitch = image.
width * 3;
1310 slicePitch = image.
height * rowPitch;
1317 if ( slicePitch < 65535 )
1327 const DWORD bytesToWrite =
static_cast<DWORD
>( blob.
GetBufferSize() );
1330 &bytesWritten, 0 ) )
1332 return HRESULT_FROM_WIN32( GetLastError() );
1335 if ( bytesWritten != bytesToWrite )
1343 std::unique_ptr<uint8_t[]> temp(
new (std::nothrow)
uint8_t[ rowPitch ] );
1345 return E_OUTOFMEMORY;
1349 if ( !WriteFile( hFile.get(), &tga_header,
sizeof(
TGA_HEADER), &bytesWritten, 0 ) )
1351 return HRESULT_FROM_WIN32( GetLastError() );
1358 auto pPixels =
reinterpret_cast<const uint8_t*
>( image.
pixels );
1360 for(
size_t y = 0;
y < image.
height; ++
y )
1363 if ( convFlags & CONV_FLAGS_888 )
1378 if ( !WriteFile( hFile.get(), temp.get(),
static_cast<DWORD
>( rowPitch ), &bytesWritten, 0 ) )
1380 return HRESULT_FROM_WIN32( GetLastError() );
1383 if ( bytesWritten != rowPitch )
HRESULT LoadFromTGAFile(_In_z_ LPCWSTR szFile, _Out_opt_ TexMetadata *metadata, _Out_ ScratchImage &image)
uint16_t dwExtensionOffset
HRESULT GetMetadataFromTGAFile(_In_z_ LPCWSTR szFile, _Out_ TexMetadata &metadata)
const Image * GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const
public std::unique_ptr< void, handle_closer > ScopedHandle
void _CopyScanline(_When_(pDestination==pSource, _Inout_updates_bytes_(outSize)) _When_(pDestination!=pSource, _Out_writes_bytes_(outSize)) LPVOID pDestination, _In_ size_t outSize, _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize, _In_ DXGI_FORMAT format, _In_ DWORD flags)
size_t GetPixelsSize() const
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_ DWORD flags assert(pDestination &&outSize > 0)
HRESULT Initialize(_In_ size_t size)
static HRESULT _CopyPixels(_In_reads_bytes_(size) LPCVOID pSource, size_t size, _In_ const Image *image, _In_ DWORD convFlags)
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
HRESULT Initialize2D(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags=CP_FLAGS_NONE)
void * GetBufferPointer() const
HRESULT SaveToTGAMemory(_In_ const Image &image, _Out_ Blob &blob)
size_t GetImageCount() const
HRESULT LoadFromTGAMemory(_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _Out_opt_ TexMetadata *metadata, _Out_ ScratchImage &image)
_In_ size_t _In_ const TexMetadata & metadata
_Use_decl_annotations_ void _SwizzleScanline(LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t inSize, DXGI_FORMAT format, DWORD flags)
void ComputePitch(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _Out_ size_t &rowPitch, _Out_ size_t &slicePitch, _In_ DWORD flags=CP_FLAGS_NONE)
static HRESULT _UncompressPixels(_In_reads_bytes_(size) LPCVOID pSource, size_t size, _In_ const Image *image, _In_ DWORD convFlags)
size_t _In_ DXGI_FORMAT size_t inSize
size_t _In_ DXGI_FORMAT _In_reads_bytes_(inSize) LPCVOID pSource
static void _Copy24bppScanline(_Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize, _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize)
const char * g_TGA20_Signature
static HRESULT _DecodeTGAHeader(_In_reads_bytes_(size) LPCVOID pSource, size_t size, _Out_ TexMetadata &metadata, size_t &offset, _Inout_opt_ DWORD *convFlags)
HRESULT SaveToTGAFile(_In_ const Image &image, _In_z_ LPCWSTR szFile)
HANDLE safe_handle(HANDLE h)
static HRESULT _SetAlphaChannelToOpaque(_In_ const Image *image)
uint8_t * GetPixels() const
uint16_t wPixelDenominator
static HRESULT _EncodeTGAHeader(_In_ const Image &image, _Out_ TGA_HEADER &header, _Inout_ DWORD &convFlags)
uint16_t dwDeveloperOffset
_In_ size_t _In_ size_t size
HRESULT GetMetadataFromTGAMemory(_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _Out_ TexMetadata &metadata)
size_t GetBufferSize() const
char szAuthorComment[324]
uint16_t wGammaDenominator