mirror of
https://github.com/microsoft/DirectXTex
synced 2024-11-21 12:00:06 +00:00
Add CompressEx and ConvertEx methods that report progress (#375)
This commit is contained in:
parent
7e7b11db04
commit
1d1d4d0134
@ -664,12 +664,26 @@ namespace DirectX
|
||||
constexpr float TEX_THRESHOLD_DEFAULT = 0.5f;
|
||||
// Default value for alpha threshold used when converting to 1-bit alpha
|
||||
|
||||
struct ConvertOptions
|
||||
{
|
||||
TEX_FILTER_FLAGS filter;
|
||||
float threshold;
|
||||
};
|
||||
|
||||
HRESULT __cdecl Convert(
|
||||
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_FILTER_FLAGS filter, _In_ float threshold,
|
||||
_Out_ ScratchImage& image) noexcept;
|
||||
HRESULT __cdecl Convert(
|
||||
_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||
_In_ DXGI_FORMAT format, _In_ TEX_FILTER_FLAGS filter, _In_ float threshold, _Out_ ScratchImage& result) noexcept;
|
||||
|
||||
HRESULT __cdecl ConvertEx(
|
||||
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ const ConvertOptions& options,
|
||||
_Out_ ScratchImage& image, _In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||
HRESULT __cdecl ConvertEx(
|
||||
_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||
_In_ DXGI_FORMAT format, _In_ const ConvertOptions& options, _Out_ ScratchImage& result,
|
||||
_In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||
// Convert the image to a new format
|
||||
|
||||
HRESULT __cdecl ConvertToSinglePlane(_In_ const Image& srcImage, _Out_ ScratchImage& image) noexcept;
|
||||
@ -756,6 +770,16 @@ namespace DirectX
|
||||
// Compress is free to use multithreading to improve performance (by default it does not use multithreading)
|
||||
};
|
||||
|
||||
constexpr float TEX_ALPHA_WEIGHT_DEFAULT = 1.0f;
|
||||
// Default value for alpha weight used for GPU BC7 compression
|
||||
|
||||
struct CompressOptions
|
||||
{
|
||||
TEX_COMPRESS_FLAGS flags;
|
||||
float threshold;
|
||||
float alphaWeight;
|
||||
};
|
||||
|
||||
HRESULT __cdecl Compress(
|
||||
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float threshold,
|
||||
_Out_ ScratchImage& cImage) noexcept;
|
||||
@ -764,6 +788,14 @@ namespace DirectX
|
||||
_In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float threshold, _Out_ ScratchImage& cImages) noexcept;
|
||||
// Note that threshold is only used by BC1. TEX_THRESHOLD_DEFAULT is a typical value to use
|
||||
|
||||
HRESULT __cdecl CompressEx(
|
||||
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ const CompressOptions& options,
|
||||
_Out_ ScratchImage& cImage, _In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||
HRESULT __cdecl CompressEx(
|
||||
_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||
_In_ DXGI_FORMAT format, _In_ const CompressOptions& options, _Out_ ScratchImage& cImages,
|
||||
_In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||
|
||||
#if defined(__d3d11_h__) || defined(__d3d11_x_h__)
|
||||
HRESULT __cdecl Compress(
|
||||
_In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress,
|
||||
@ -772,6 +804,14 @@ namespace DirectX
|
||||
_In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||
_In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float alphaWeight, _Out_ ScratchImage& cImages) noexcept;
|
||||
// DirectCompute-based compression (alphaWeight is only used by BC7. 1.0 is the typical value to use)
|
||||
|
||||
HRESULT __cdecl CompressEx(
|
||||
_In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ const CompressOptions& options,
|
||||
_Out_ ScratchImage& image, _In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||
HRESULT __cdecl CompressEx(
|
||||
_In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||
_In_ DXGI_FORMAT format, _In_ const CompressOptions& options, _Out_ ScratchImage& cImages,
|
||||
_In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||
#endif
|
||||
|
||||
HRESULT __cdecl Decompress(_In_ const Image& cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image) noexcept;
|
||||
|
@ -74,7 +74,8 @@ namespace
|
||||
const Image& result,
|
||||
uint32_t bcflags,
|
||||
TEX_FILTER_FLAGS srgb,
|
||||
float threshold) noexcept
|
||||
float threshold,
|
||||
const std::function<bool __cdecl(size_t, size_t)>& statusCallback) noexcept
|
||||
{
|
||||
if (!image.pixels || !result.pixels)
|
||||
return E_POINTER;
|
||||
@ -111,6 +112,14 @@ namespace
|
||||
const size_t rowPitch = image.rowPitch;
|
||||
for (size_t h = 0; h < image.height; h += 4)
|
||||
{
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(h, image.height))
|
||||
{
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t *sptr = pSrc;
|
||||
uint8_t* dptr = pDest;
|
||||
const size_t ph = std::min<size_t>(4, image.height - h);
|
||||
@ -203,7 +212,8 @@ namespace
|
||||
const Image& result,
|
||||
uint32_t bcflags,
|
||||
TEX_FILTER_FLAGS srgb,
|
||||
float threshold) noexcept
|
||||
float threshold,
|
||||
const std::function<bool __cdecl(size_t, size_t)>& statusCallback) noexcept
|
||||
{
|
||||
if (!image.pixels || !result.pixels)
|
||||
return E_POINTER;
|
||||
@ -239,9 +249,22 @@ namespace
|
||||
|
||||
bool fail = false;
|
||||
|
||||
#pragma omp parallel for
|
||||
size_t progress = 0;
|
||||
bool abort = false;
|
||||
|
||||
const size_t progressTotal = std::max<size_t>(1, (image.height + 3) / 4);
|
||||
|
||||
#pragma omp parallel for shared(progress)
|
||||
for (int nb = 0; nb < static_cast<int>(nBlocks); ++nb)
|
||||
{
|
||||
#pragma omp flush (abort)
|
||||
if (abort)
|
||||
{
|
||||
// Short circuit the loop body if an abort is requested.
|
||||
// OpenMP 2.0 does not support cancellation of a 'parallel for' loop.
|
||||
continue;
|
||||
}
|
||||
|
||||
const int nbWidth = std::max<int>(1, int((image.width + 3) / 4));
|
||||
|
||||
int y = nb / nbWidth;
|
||||
@ -323,9 +346,29 @@ namespace
|
||||
pfEncode(pDest, temp, bcflags);
|
||||
else
|
||||
D3DXEncodeBC1(pDest, temp, threshold, bcflags);
|
||||
|
||||
// Report progress when a new row is reached.
|
||||
if (x == 0 && statusCallback)
|
||||
{
|
||||
#pragma omp atomic
|
||||
progress += 4;
|
||||
|
||||
if (!statusCallback(progress, progressTotal))
|
||||
{
|
||||
abort = true;
|
||||
#pragma omp flush (abort)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (fail) ? E_FAIL : S_OK;
|
||||
if (abort)
|
||||
{
|
||||
return E_ABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (fail) ? E_FAIL : S_OK;
|
||||
}
|
||||
}
|
||||
#endif // _OPENMP
|
||||
|
||||
@ -592,6 +635,38 @@ HRESULT DirectX::Compress(
|
||||
TEX_COMPRESS_FLAGS compress,
|
||||
float threshold,
|
||||
ScratchImage& image) noexcept
|
||||
{
|
||||
CompressOptions options = {};
|
||||
options.flags = compress;
|
||||
options.threshold = threshold;
|
||||
|
||||
return CompressEx(srcImage, format, options, image, nullptr);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::Compress(
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DXGI_FORMAT format,
|
||||
TEX_COMPRESS_FLAGS compress,
|
||||
float threshold,
|
||||
ScratchImage& cImages) noexcept
|
||||
{
|
||||
CompressOptions options = {};
|
||||
options.flags = compress;
|
||||
options.threshold = threshold;
|
||||
|
||||
return CompressEx(srcImages, nimages, metadata, format, options, cImages, nullptr);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CompressEx(
|
||||
const Image& srcImage,
|
||||
DXGI_FORMAT format,
|
||||
const CompressOptions& options,
|
||||
ScratchImage& image,
|
||||
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||
{
|
||||
if (IsCompressed(srcImage.format) || !IsCompressed(format))
|
||||
return E_INVALIDARG;
|
||||
@ -612,35 +687,56 @@ HRESULT DirectX::Compress(
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(0, img->height))
|
||||
{
|
||||
image.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
// Compress single image
|
||||
if (compress & TEX_COMPRESS_PARALLEL)
|
||||
if (options.flags & TEX_COMPRESS_PARALLEL)
|
||||
{
|
||||
#ifndef _OPENMP
|
||||
return E_NOTIMPL;
|
||||
hr = E_NOTIMPL;
|
||||
#else
|
||||
hr = CompressBC_Parallel(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold);
|
||||
hr = CompressBC_Parallel(srcImage, *img, GetBCFlags(options.flags), GetSRGBFlags(options.flags), options.threshold, statusCallback);
|
||||
#endif // _OPENMP
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = CompressBC(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold);
|
||||
hr = CompressBC(srcImage, *img, GetBCFlags(options.flags), GetSRGBFlags(options.flags), options.threshold, statusCallback);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
image.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
return hr;
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(img->height, img->height))
|
||||
{
|
||||
image.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::Compress(
|
||||
HRESULT DirectX::CompressEx(
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DXGI_FORMAT format,
|
||||
TEX_COMPRESS_FLAGS compress,
|
||||
float threshold,
|
||||
ScratchImage& cImages) noexcept
|
||||
const CompressOptions& options,
|
||||
ScratchImage& cImages,
|
||||
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||
{
|
||||
if (!srcImages || !nimages)
|
||||
return E_INVALIDARG;
|
||||
@ -654,6 +750,19 @@ HRESULT DirectX::Compress(
|
||||
|
||||
cImages.Release();
|
||||
|
||||
if (statusCallback
|
||||
&& nimages == 1
|
||||
&& !metadata.IsVolumemap()
|
||||
&& metadata.mipLevels == 1
|
||||
&& metadata.arraySize == 1)
|
||||
{
|
||||
// If progress reporting is requested when compressing a single 1D or 2D image, call
|
||||
// the CompressEx overload that takes a single image.
|
||||
// This provides a better user experience as progress will be reported as the image
|
||||
// is being processed, instead of after processing has been completed.
|
||||
return CompressEx(srcImages[0], format, options, cImages, statusCallback);
|
||||
}
|
||||
|
||||
TexMetadata mdata2 = metadata;
|
||||
mdata2.format = format;
|
||||
HRESULT hr = cImages.Initialize(mdata2);
|
||||
@ -673,6 +782,15 @@ HRESULT DirectX::Compress(
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(0, nimages))
|
||||
{
|
||||
cImages.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < nimages; ++index)
|
||||
{
|
||||
assert(dest[index].format == format);
|
||||
@ -685,33 +803,44 @@ HRESULT DirectX::Compress(
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if ((compress & TEX_COMPRESS_PARALLEL))
|
||||
if (options.flags & TEX_COMPRESS_PARALLEL)
|
||||
{
|
||||
#ifndef _OPENMP
|
||||
return E_NOTIMPL;
|
||||
hr = E_NOTIMPL;
|
||||
#else
|
||||
if (compress & TEX_COMPRESS_PARALLEL)
|
||||
{
|
||||
hr = CompressBC_Parallel(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), threshold);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
hr = CompressBC_Parallel(src, dest[index], GetBCFlags(options.flags), GetSRGBFlags(options.flags), options.threshold, nullptr);
|
||||
#endif // _OPENMP
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = CompressBC(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), threshold);
|
||||
if (FAILED(hr))
|
||||
hr = CompressBC(src, dest[index], GetBCFlags(options.flags), GetSRGBFlags(options.flags), options.threshold, nullptr);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(index, nimages))
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(nimages, nimages))
|
||||
{
|
||||
cImages.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -219,6 +219,40 @@ HRESULT DirectX::Compress(
|
||||
TEX_COMPRESS_FLAGS compress,
|
||||
float alphaWeight,
|
||||
ScratchImage& image) noexcept
|
||||
{
|
||||
CompressOptions options = {};
|
||||
options.flags = compress;
|
||||
options.alphaWeight = alphaWeight;
|
||||
|
||||
return CompressEx(pDevice, srcImage, format, options, image, nullptr);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::Compress(
|
||||
ID3D11Device* pDevice,
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DXGI_FORMAT format,
|
||||
TEX_COMPRESS_FLAGS compress,
|
||||
float alphaWeight,
|
||||
ScratchImage& cImages) noexcept
|
||||
{
|
||||
CompressOptions options = {};
|
||||
options.flags = compress;
|
||||
options.alphaWeight = alphaWeight;
|
||||
|
||||
return CompressEx(pDevice, srcImages, nimages, metadata, format, options, cImages);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CompressEx(
|
||||
ID3D11Device* pDevice,
|
||||
const Image& srcImage,
|
||||
DXGI_FORMAT format,
|
||||
const CompressOptions& options,
|
||||
ScratchImage& image,
|
||||
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||
{
|
||||
if (!pDevice || IsCompressed(srcImage.format) || !IsCompressed(format))
|
||||
return E_INVALIDARG;
|
||||
@ -236,7 +270,7 @@ HRESULT DirectX::Compress(
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = gpubc->Prepare(srcImage.width, srcImage.height, compress, format, alphaWeight);
|
||||
hr = gpubc->Prepare(srcImage.width, srcImage.height, options.flags, format, options.alphaWeight);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
@ -252,23 +286,45 @@ HRESULT DirectX::Compress(
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
hr = GPUCompress(gpubc.get(), srcImage, *img, compress);
|
||||
if (FAILED(hr))
|
||||
image.Release();
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(0, 100))
|
||||
{
|
||||
image.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
hr = GPUCompress(gpubc.get(), srcImage, *img, options.flags);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
image.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(100, 100))
|
||||
{
|
||||
image.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::Compress(
|
||||
HRESULT DirectX::CompressEx(
|
||||
ID3D11Device* pDevice,
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DXGI_FORMAT format,
|
||||
TEX_COMPRESS_FLAGS compress,
|
||||
float alphaWeight,
|
||||
ScratchImage& cImages) noexcept
|
||||
const CompressOptions& options,
|
||||
ScratchImage& cImages,
|
||||
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||
{
|
||||
if (!pDevice || !srcImages || !nimages)
|
||||
return E_INVALIDARG;
|
||||
@ -311,6 +367,15 @@ HRESULT DirectX::Compress(
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(0, nimages))
|
||||
{
|
||||
cImages.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
// Process images (ordered by size)
|
||||
switch (metadata.dimension)
|
||||
{
|
||||
@ -319,10 +384,11 @@ HRESULT DirectX::Compress(
|
||||
{
|
||||
size_t w = metadata.width;
|
||||
size_t h = metadata.height;
|
||||
size_t progress = 0;
|
||||
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
hr = gpubc->Prepare(w, h, compress, format, alphaWeight);
|
||||
hr = gpubc->Prepare(w, h, options.flags, format, options.alphaWeight);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
cImages.Release();
|
||||
@ -348,12 +414,21 @@ HRESULT DirectX::Compress(
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
|
||||
hr = GPUCompress(gpubc.get(), src, dest[index], options.flags);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(progress++, nimages))
|
||||
{
|
||||
cImages.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (h > 1)
|
||||
@ -370,10 +445,11 @@ HRESULT DirectX::Compress(
|
||||
size_t w = metadata.width;
|
||||
size_t h = metadata.height;
|
||||
size_t d = metadata.depth;
|
||||
size_t progress = 0;
|
||||
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
hr = gpubc->Prepare(w, h, compress, format, alphaWeight);
|
||||
hr = gpubc->Prepare(w, h, options.flags, format, options.alphaWeight);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
cImages.Release();
|
||||
@ -399,12 +475,21 @@ HRESULT DirectX::Compress(
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
|
||||
hr = GPUCompress(gpubc.get(), src, dest[index], options.flags);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(progress++, nimages))
|
||||
{
|
||||
cImages.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (h > 1)
|
||||
@ -423,5 +508,14 @@ HRESULT DirectX::Compress(
|
||||
return HRESULT_E_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(nimages, nimages))
|
||||
{
|
||||
cImages.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -4798,7 +4798,8 @@ namespace
|
||||
_In_ TEX_FILTER_FLAGS filter,
|
||||
_In_ const Image& destImage,
|
||||
_In_ float threshold,
|
||||
size_t z) noexcept
|
||||
size_t z,
|
||||
const std::function<bool __cdecl(size_t, size_t)>& statusCallback) noexcept
|
||||
{
|
||||
assert(srcImage.width == destImage.width);
|
||||
assert(srcImage.height == destImage.height);
|
||||
@ -4822,6 +4823,14 @@ namespace
|
||||
|
||||
for (size_t h = 0; h < srcImage.height; ++h)
|
||||
{
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(h, srcImage.height))
|
||||
{
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
|
||||
@ -4845,6 +4854,14 @@ namespace
|
||||
// Ordered dithering
|
||||
for (size_t h = 0; h < srcImage.height; ++h)
|
||||
{
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(h, srcImage.height))
|
||||
{
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
|
||||
@ -4862,6 +4879,14 @@ namespace
|
||||
// No dithering
|
||||
for (size_t h = 0; h < srcImage.height; ++h)
|
||||
{
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(h, srcImage.height))
|
||||
{
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
|
||||
@ -5061,6 +5086,21 @@ HRESULT DirectX::Convert(
|
||||
TEX_FILTER_FLAGS filter,
|
||||
float threshold,
|
||||
ScratchImage& image) noexcept
|
||||
{
|
||||
ConvertOptions options = {};
|
||||
options.filter = filter;
|
||||
options.threshold = threshold;
|
||||
|
||||
return ConvertEx(srcImage, format, options, image, nullptr);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::ConvertEx(
|
||||
const Image& srcImage,
|
||||
DXGI_FORMAT format,
|
||||
const ConvertOptions& options,
|
||||
ScratchImage& image,
|
||||
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||
{
|
||||
if ((srcImage.format == format) || !IsValid(format))
|
||||
return E_INVALIDARG;
|
||||
@ -5088,14 +5128,23 @@ HRESULT DirectX::Convert(
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
WICPixelFormatGUID pfGUID, targetGUID;
|
||||
if (UseWICConversion(filter, srcImage.format, format, pfGUID, targetGUID))
|
||||
if (statusCallback)
|
||||
{
|
||||
hr = ConvertUsingWIC(srcImage, pfGUID, targetGUID, filter, threshold, *rimage);
|
||||
if (!statusCallback(0, rimage->height))
|
||||
{
|
||||
image.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
WICPixelFormatGUID pfGUID, targetGUID;
|
||||
if (UseWICConversion(options.filter, srcImage.format, format, pfGUID, targetGUID))
|
||||
{
|
||||
hr = ConvertUsingWIC(srcImage, pfGUID, targetGUID, options.filter, options.threshold, *rimage);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = ConvertCustom(srcImage, filter, *rimage, threshold, 0);
|
||||
hr = ConvertCustom(srcImage, options.filter, *rimage, options.threshold, 0, statusCallback);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
@ -5104,6 +5153,15 @@ HRESULT DirectX::Convert(
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(rimage->height, rimage->height))
|
||||
{
|
||||
image.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -5120,6 +5178,23 @@ HRESULT DirectX::Convert(
|
||||
TEX_FILTER_FLAGS filter,
|
||||
float threshold,
|
||||
ScratchImage& result) noexcept
|
||||
{
|
||||
ConvertOptions options = {};
|
||||
options.filter = filter;
|
||||
options.threshold = threshold;
|
||||
|
||||
return ConvertEx(srcImages, nimages, metadata, format, options, result, nullptr);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::ConvertEx(
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DXGI_FORMAT format,
|
||||
const ConvertOptions& options,
|
||||
ScratchImage& result,
|
||||
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||
{
|
||||
if (!srcImages || !nimages || (metadata.format == format) || !IsValid(format))
|
||||
return E_INVALIDARG;
|
||||
@ -5133,6 +5208,19 @@ HRESULT DirectX::Convert(
|
||||
if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (statusCallback
|
||||
&& nimages == 1
|
||||
&& !metadata.IsVolumemap()
|
||||
&& metadata.mipLevels == 1
|
||||
&& metadata.arraySize == 1)
|
||||
{
|
||||
// If progress reporting is requested when converting a single 1D or 2D image, call
|
||||
// the ConvertEx overload that takes a single image.
|
||||
// This provides a better user experience as progress will be reported as the image
|
||||
// is being processed, instead of after processing has been completed.
|
||||
return ConvertEx(srcImages[0], format, options, result, statusCallback);
|
||||
}
|
||||
|
||||
TexMetadata mdata2 = metadata;
|
||||
mdata2.format = format;
|
||||
HRESULT hr = result.Initialize(mdata2);
|
||||
@ -5152,8 +5240,17 @@ HRESULT DirectX::Convert(
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(0, nimages))
|
||||
{
|
||||
result.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
WICPixelFormatGUID pfGUID, targetGUID;
|
||||
const bool usewic = !metadata.IsPMAlpha() && UseWICConversion(filter, metadata.format, format, pfGUID, targetGUID);
|
||||
const bool usewic = !metadata.IsPMAlpha() && UseWICConversion(options.filter, metadata.format, format, pfGUID, targetGUID);
|
||||
|
||||
switch (metadata.dimension)
|
||||
{
|
||||
@ -5185,11 +5282,11 @@ HRESULT DirectX::Convert(
|
||||
|
||||
if (usewic)
|
||||
{
|
||||
hr = ConvertUsingWIC(src, pfGUID, targetGUID, filter, threshold, dst);
|
||||
hr = ConvertUsingWIC(src, pfGUID, targetGUID, options.filter, options.threshold, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = ConvertCustom(src, filter, dst, threshold, 0);
|
||||
hr = ConvertCustom(src, options.filter, dst, options.threshold, 0, nullptr);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
@ -5197,6 +5294,15 @@ HRESULT DirectX::Convert(
|
||||
result.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(index, nimages))
|
||||
{
|
||||
result.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -5238,11 +5344,11 @@ HRESULT DirectX::Convert(
|
||||
|
||||
if (usewic)
|
||||
{
|
||||
hr = ConvertUsingWIC(src, pfGUID, targetGUID, filter, threshold, dst);
|
||||
hr = ConvertUsingWIC(src, pfGUID, targetGUID, options.filter, options.threshold, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = ConvertCustom(src, filter, dst, threshold, slice);
|
||||
hr = ConvertCustom(src, options.filter, dst, options.threshold, slice, nullptr);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
@ -5250,6 +5356,15 @@ HRESULT DirectX::Convert(
|
||||
result.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(index, nimages))
|
||||
{
|
||||
result.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (d > 1)
|
||||
@ -5263,6 +5378,15 @@ HRESULT DirectX::Convert(
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (statusCallback)
|
||||
{
|
||||
if (!statusCallback(nimages, nimages))
|
||||
{
|
||||
result.Release();
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user