mirror of
https://github.com/microsoft/DirectXTex
synced 2024-11-21 20:10:05 +00:00
Add support for reading non-standard BMP files with DXTn data
This commit is contained in:
parent
2b2f90259a
commit
06816df22c
@ -13,8 +13,6 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#define NODRAWTEXT
|
||||
#define NOGDI
|
||||
#define NOBITMAP
|
||||
#define NOMCX
|
||||
#define NOSERVICE
|
||||
#define NOHELP
|
||||
@ -428,6 +426,10 @@ namespace
|
||||
{
|
||||
inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }
|
||||
|
||||
struct handle_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) CloseHandle(h); } };
|
||||
|
||||
typedef std::unique_ptr<void, handle_closer> ScopedHandle;
|
||||
|
||||
struct find_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) FindClose(h); } };
|
||||
|
||||
typedef public std::unique_ptr<void, find_closer> ScopedFindHandle;
|
||||
@ -952,6 +954,128 @@ namespace
|
||||
float normalizedLinear = pow(std::max(pow(abs(ST2084), 1.0f / 78.84375f) - 0.8359375f, 0.0f) / (18.8515625f - 18.6875f * pow(abs(ST2084), 1.0f / 78.84375f)), 1.0f / 0.1593017578f);
|
||||
return normalizedLinear;
|
||||
}
|
||||
|
||||
|
||||
HRESULT ReadData(_In_z_ const wchar_t* szFile, std::unique_ptr<uint8_t []>& blob, size_t& bmpSize)
|
||||
{
|
||||
blob.reset();
|
||||
|
||||
ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
|
||||
FILE_FLAG_SEQUENTIAL_SCAN, nullptr)));
|
||||
if (!hFile)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
// Get the file size
|
||||
FILE_STANDARD_INFO fileInfo;
|
||||
if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo)))
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
// File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough)
|
||||
if (fileInfo.EndOfFile.HighPart > 0)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
|
||||
}
|
||||
|
||||
// Zero-sized files assumed to be invalid
|
||||
if (fileInfo.EndOfFile.LowPart < 1)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Read file
|
||||
blob.reset(new (std::nothrow) uint8_t[fileInfo.EndOfFile.LowPart]);
|
||||
if (!blob)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
DWORD bytesRead = 0;
|
||||
if (!ReadFile(hFile.get(), blob.get(), fileInfo.EndOfFile.LowPart, &bytesRead, nullptr))
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
if (bytesRead != fileInfo.EndOfFile.LowPart)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
bmpSize = fileInfo.EndOfFile.LowPart;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT LoadFromExtendedBMPMemory(_In_reads_bytes_(size) const void* pSource, _In_ size_t size, _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image)
|
||||
{
|
||||
// This loads from non-standard BMP files that are not supported by WIC
|
||||
image.Release();
|
||||
|
||||
if (size < (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)))
|
||||
return E_FAIL;
|
||||
|
||||
// Valid BMP files always start with 'BM' at the top
|
||||
auto filehdr = reinterpret_cast<const BITMAPFILEHEADER*>(pSource);
|
||||
if (filehdr->bfType != 0x4D42)
|
||||
return E_FAIL;
|
||||
|
||||
if (size < filehdr->bfOffBits)
|
||||
return E_FAIL;
|
||||
|
||||
auto header = reinterpret_cast<const BITMAPINFOHEADER*>(reinterpret_cast<const uint8_t*>(pSource) + sizeof(BITMAPFILEHEADER));
|
||||
if (header->biSize != sizeof(BITMAPINFOHEADER))
|
||||
return E_FAIL;
|
||||
|
||||
if (header->biWidth < 1 || header->biHeight < 1 || header->biPlanes != 1 || header->biBitCount != 16)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
||||
switch (header->biCompression)
|
||||
{
|
||||
case 0x31545844: // FourCC "DXT1"
|
||||
format = DXGI_FORMAT_BC1_UNORM;
|
||||
break;
|
||||
case 0x33545844: // FourCC "DXT3"
|
||||
format = DXGI_FORMAT_BC2_UNORM;
|
||||
break;
|
||||
case 0x35545844: // FourCC "DXT5"
|
||||
format = DXGI_FORMAT_BC3_UNORM;
|
||||
break;
|
||||
|
||||
default:
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
HRESULT hr = image.Initialize2D(format, header->biWidth, header->biHeight, 1, 1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (header->biSizeImage != image.GetPixelsSize())
|
||||
return E_UNEXPECTED;
|
||||
|
||||
size_t remaining = size - filehdr->bfOffBits;
|
||||
if (!remaining)
|
||||
return E_FAIL;
|
||||
|
||||
if (remaining < image.GetPixelsSize())
|
||||
return E_UNEXPECTED;
|
||||
|
||||
auto pixels = reinterpret_cast<const uint8_t*>(pSource) + filehdr->bfOffBits;
|
||||
|
||||
memcpy(image.GetPixels(), pixels, image.GetPixelsSize());
|
||||
|
||||
if (metadata)
|
||||
{
|
||||
*metadata = image.GetMetadata();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1578,6 +1702,28 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
image->OverrideFormat(info.format);
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(ext, L".bmp") == 0)
|
||||
{
|
||||
std::unique_ptr<uint8_t []> bmpData;
|
||||
size_t bmpSize;
|
||||
hr = ReadData(pConv->szSrc, bmpData, bmpSize);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = LoadFromWICMemory(bmpData.get(), bmpSize, dwFilter, &info, *image);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (SUCCEEDED(LoadFromExtendedBMPMemory(bmpData.get(), bmpSize, &info, *image)))
|
||||
{
|
||||
hr = S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(ext, L".tga") == 0)
|
||||
{
|
||||
hr = LoadFromTGAFile(pConv->szSrc, &info, *image);
|
||||
|
Loading…
Reference in New Issue
Block a user