mirror of
https://github.com/openharmony/third_party_astc-encoder.git
synced 2026-07-19 18:23:37 -04:00
First phase of the front-end to codec API split (#125)
This phase introduces the first phase of the API split between the API front-end and the CODEC backed. However, some aspects of the final design are not yet supported: This build only only supports automatic multi-threading; no user owned thread pools are supported. Some memory allocations still tied to the compression pass, not the context, so reusing the context will have higher than planned CPU overhead due to the repeated memory allocation (although the impact is probably small unless compression small image). The input image layout is still the legacy format and must be pre-padded by the caller for any pass using the area-based perceptual metrics.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
__pycache__
|
||||
Binaries
|
||||
Source/*.o
|
||||
Source/*.so
|
||||
Source/astcenc-*
|
||||
Source/astcenc-*
|
||||
Source/VS2019/*Release
|
||||
@@ -14,3 +15,5 @@ Test/DocOut
|
||||
Test/Images/Kodak
|
||||
Test/Images/Scratch*
|
||||
TestOutput
|
||||
Docs/LibraryInterface.md
|
||||
Docs/Profiling.md
|
||||
|
||||
+55
-41
@@ -33,35 +33,37 @@ VEC?=avx2
|
||||
DBG?=0
|
||||
|
||||
SOURCES = \
|
||||
astc_averages_and_directions.cpp \
|
||||
astc_block_sizes2.cpp \
|
||||
astc_color_quantize.cpp \
|
||||
astc_color_unquantize.cpp \
|
||||
astc_compress_symbolic.cpp \
|
||||
astc_compute_variance.cpp \
|
||||
astc_decompress_symbolic.cpp \
|
||||
astc_encoding_choice_error.cpp \
|
||||
astc_error_metrics.cpp \
|
||||
astc_find_best_partitioning.cpp \
|
||||
astc_ideal_endpoints_and_weights.cpp \
|
||||
astc_image.cpp \
|
||||
astc_image_load_store.cpp \
|
||||
astc_integer_sequence.cpp \
|
||||
astc_kmeans_partitioning.cpp \
|
||||
astc_main.cpp \
|
||||
astc_mathlib.cpp \
|
||||
astc_mathlib_softfloat.cpp \
|
||||
astc_partition_tables.cpp \
|
||||
astc_percentile_tables.cpp \
|
||||
astc_pick_best_endpoint_format.cpp \
|
||||
astc_platform_isa_detection.cpp \
|
||||
astc_platform_dependents.cpp \
|
||||
astc_quantization.cpp \
|
||||
astc_symbolic_physical.cpp \
|
||||
astc_toplevel.cpp \
|
||||
astc_toplevel_help.cpp \
|
||||
astc_weight_align.cpp \
|
||||
astc_weight_quant_xfer_tables.cpp
|
||||
astcenc_averages_and_directions.cpp \
|
||||
astcenc_block_sizes2.cpp \
|
||||
astcenc_color_quantize.cpp \
|
||||
astcenc_color_unquantize.cpp \
|
||||
astcenc_compress_symbolic.cpp \
|
||||
astcenc_compute_variance.cpp \
|
||||
astcenc_decompress_symbolic.cpp \
|
||||
astcenc_encoding_choice_error.cpp \
|
||||
astcenc_entry.cpp \
|
||||
astcenc_find_best_partitioning.cpp \
|
||||
astcenc_ideal_endpoints_and_weights.cpp \
|
||||
astcenc_image.cpp \
|
||||
astcenc_integer_sequence.cpp \
|
||||
astcenc_kmeans_partitioning.cpp \
|
||||
astcenc_mathlib.cpp \
|
||||
astcenc_mathlib_softfloat.cpp \
|
||||
astcenc_partition_tables.cpp \
|
||||
astcenc_percentile_tables.cpp \
|
||||
astcenc_pick_best_endpoint_format.cpp \
|
||||
astcenc_platform_dependents.cpp \
|
||||
astcenc_platform_isa_detection.cpp \
|
||||
astcenc_quantization.cpp \
|
||||
astcenc_symbolic_physical.cpp \
|
||||
astcenc_weight_align.cpp \
|
||||
astcenc_weight_quant_xfer_tables.cpp \
|
||||
astcenccli_error_metrics.cpp \
|
||||
astcenccli_image.cpp \
|
||||
astcenccli_image_load_store.cpp \
|
||||
astcenccli_platform_dependents.cpp \
|
||||
astcenccli_toplevel.cpp \
|
||||
astcenccli_toplevel_help.cpp
|
||||
|
||||
EXTERNAL_SOURCES = \
|
||||
stb_image.h \
|
||||
@@ -69,8 +71,10 @@ EXTERNAL_SOURCES = \
|
||||
tinyexr.h
|
||||
|
||||
HEADERS = \
|
||||
astc_codec_internals.h \
|
||||
astc_mathlib.h \
|
||||
astcenc.h \
|
||||
astcenc_internal.h \
|
||||
astcenc_mathlib.h \
|
||||
astcenccli_internal.h \
|
||||
stb_image.h \
|
||||
stb_image_write.h \
|
||||
tinyexr.h
|
||||
@@ -81,28 +85,28 @@ EXTERNAL_OBJECTS = $(EXTERNAL_SOURCES:.h=-$(VEC).o)
|
||||
|
||||
BINARY = astcenc-$(VEC)
|
||||
|
||||
CXXFLAGS = -std=c++14 -mfpmath=sse \
|
||||
CXXFLAGS = -std=c++14 -fvisibility=hidden -mfpmath=sse \
|
||||
-Wall -Wextra -Wpedantic -Werror -Werror=shadow -Wdouble-promotion
|
||||
|
||||
# Validate that the DBG parameter is a supported value, and patch CXXFLAGS
|
||||
ifeq ($(DBG),0)
|
||||
CXXFLAGS += -O3
|
||||
CXXFLAGS += -O3 -DNDEBUG
|
||||
else
|
||||
CXXFLAGS += -O0 -g
|
||||
endif
|
||||
|
||||
# Validate that the VEC parameter is a supported value, and patch CXXFLAGS
|
||||
ifeq ($(VEC),nointrin)
|
||||
CXXFLAGS += -msse2 -DASTC_SSE=0 -DASTC_AVX=0 -DASTC_POPCNT=0
|
||||
CXXFLAGS += -msse2 -DASTCENC_SSE=0 -DASTCENC_AVX=0 -DASTCENC_POPCNT=0
|
||||
else
|
||||
ifeq ($(VEC),sse2)
|
||||
CXXFLAGS += -msse2 -DASTC_SSE=20 -DASTC_AVX=0 -DASTC_POPCNT=0
|
||||
CXXFLAGS += -msse2 -DASTCENC_SSE=20 -DASTCENC_AVX=0 -DASTCENC_POPCNT=0
|
||||
else
|
||||
ifeq ($(VEC),sse4.2)
|
||||
CXXFLAGS += -msse4.2 -mpopcnt -DASTC_SSE=42 -DASTC_AVX=0 -DASTC_POPCNT=1
|
||||
CXXFLAGS += -msse4.2 -mpopcnt -DASTCENC_SSE=42 -DASTCENC_AVX=0 -DASTCENC_POPCNT=1
|
||||
else
|
||||
ifeq ($(VEC),avx2)
|
||||
CXXFLAGS += -mavx2 -mpopcnt -DASTC_SSE=42 -DASTC_AVX=2 -DASTC_POPCNT=1
|
||||
CXXFLAGS += -mavx2 -mpopcnt -DASTCENC_SSE=42 -DASTCENC_AVX=2 -DASTCENC_POPCNT=1
|
||||
else
|
||||
$(error Unsupported VEC target, use VEC=nointrin/sse2/sse4.2/avx2)
|
||||
endif
|
||||
@@ -117,29 +121,39 @@ CXXFLAGS_EXTERNAL = \
|
||||
-Wno-double-promotion \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# ==================================================
|
||||
# Build rules for the command line wrapper
|
||||
$(BINARY): $(EXTERNAL_OBJECTS) $(OBJECTS)
|
||||
@$(CXX) -o $@ $^ $(CXXFLAGS) -lpthread
|
||||
@echo "[Link] $@ (using $(VEC), debug=$(DBG))"
|
||||
|
||||
# Note: ensure NDEBUG is undefined; all three libraries are weak at runtime
|
||||
# handling of corrupt files, relying on asserts to handle bd file input.
|
||||
# Compiling with NDEBUG is a potential security risk.
|
||||
stb_image-$(VEC).o: stb_image.h
|
||||
@$(CXX) -c -x c++ -o $@ $< $(CXXFLAGS_EXTERNAL) -DSTB_IMAGE_IMPLEMENTATION \
|
||||
-DSTBI_NO_PSD -DSTBI_NO_GIF -DSTBI_NO_PIC -DSTBI_NO_PNM
|
||||
-DSTBI_NO_PSD -DSTBI_NO_GIF -DSTBI_NO_PIC -DSTBI_NO_PNM -UNDEBUG
|
||||
@echo "[C++] $<"
|
||||
|
||||
stb_image_write-$(VEC).o: stb_image_write.h
|
||||
@$(CXX) -c -x c++ -o $@ $< $(CXXFLAGS_EXTERNAL) -DSTB_IMAGE_WRITE_IMPLEMENTATION
|
||||
@$(CXX) -c -x c++ -o $@ $< $(CXXFLAGS_EXTERNAL) -DSTB_IMAGE_WRITE_IMPLEMENTATION \
|
||||
-UNDEBUG
|
||||
@echo "[C++] $<"
|
||||
|
||||
tinyexr-$(VEC).o: tinyexr.h
|
||||
@$(CXX) -c -x c++ -o $@ $< $(CXXFLAGS) -DTINYEXR_IMPLEMENTATION
|
||||
@$(CXX) -c -x c++ -o $@ $< $(CXXFLAGS) -DTINYEXR_IMPLEMENTATION -UNDEBUG
|
||||
@echo "[C++] $<"
|
||||
|
||||
$(OBJECTS): %-$(VEC).o: %.cpp $(HEADERS)
|
||||
@$(CXX) -c -o $@ $< $(CXXFLAGS)
|
||||
@$(CXX) -c -o $@ $(abspath $<) $(CXXFLAGS)
|
||||
@echo "[C++] $<"
|
||||
|
||||
# ==================================================
|
||||
# Generic utility rules
|
||||
|
||||
clean:
|
||||
@rm -f *-$(VEC).o
|
||||
@rm -f *-$(VEC).so
|
||||
@rm -f *-$(VEC).obj
|
||||
@rm -f $(BINARY)
|
||||
@rm -f $(BINARY).exe
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
<ClCompile Include="..\astc_weight_quant_xfer_tables.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_mathlib.cpp">
|
||||
<ClCompile Include="..\astcenc_mathlib.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_platform_dependents.cpp">
|
||||
@@ -96,7 +96,7 @@
|
||||
<ClCompile Include="..\astc_error_metrics.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_mathlib_softfloat.cpp">
|
||||
<ClCompile Include="..\astcenc_mathlib_softfloat.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_toplevel_help.cpp">
|
||||
@@ -107,14 +107,14 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\astc_codec_internals.h">
|
||||
<ClInclude Include="..\astcenc_internal.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\stb_image.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\astc_mathlib.h">
|
||||
<ClInclude Include="..\astcenc_mathlib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -11,40 +11,46 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\astc_averages_and_directions.cpp" />
|
||||
<ClCompile Include="..\astc_block_sizes2.cpp" />
|
||||
<ClCompile Include="..\astc_color_quantize.cpp" />
|
||||
<ClCompile Include="..\astc_color_unquantize.cpp" />
|
||||
<ClCompile Include="..\astc_compress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astc_compute_variance.cpp" />
|
||||
<ClCompile Include="..\astc_decompress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astc_encoding_choice_error.cpp" />
|
||||
<ClCompile Include="..\astc_error_metrics.cpp" />
|
||||
<ClCompile Include="..\astc_find_best_partitioning.cpp" />
|
||||
<ClCompile Include="..\astc_ideal_endpoints_and_weights.cpp" />
|
||||
<ClCompile Include="..\astc_image.cpp" />
|
||||
<ClCompile Include="..\astc_image_load_store.cpp" />
|
||||
<ClCompile Include="..\astc_integer_sequence.cpp" />
|
||||
<ClCompile Include="..\astc_kmeans_partitioning.cpp" />
|
||||
<ClCompile Include="..\astc_main.cpp" />
|
||||
<ClCompile Include="..\astc_mathlib.cpp" />
|
||||
<ClCompile Include="..\astc_mathlib_softfloat.cpp" />
|
||||
<ClCompile Include="..\astc_partition_tables.cpp" />
|
||||
<ClCompile Include="..\astc_percentile_tables.cpp" />
|
||||
<ClCompile Include="..\astc_pick_best_endpoint_format.cpp" />
|
||||
<ClCompile Include="..\astc_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astc_platform_isa_detection.cpp" />
|
||||
<ClCompile Include="..\astc_quantization.cpp" />
|
||||
<ClCompile Include="..\astc_symbolic_physical.cpp" />
|
||||
<ClCompile Include="..\astc_toplevel.cpp" />
|
||||
<ClCompile Include="..\astc_toplevel_help.cpp" />
|
||||
<ClCompile Include="..\astc_weight_align.cpp" />
|
||||
<ClCompile Include="..\astc_weight_quant_xfer_tables.cpp" />
|
||||
<ClInclude Include="..\astcenc.h" />
|
||||
<ClInclude Include="..\astcenccli_internal.h" />
|
||||
<ClInclude Include="..\astcenc_internal.h" />
|
||||
<ClInclude Include="..\astcenc_mathlib.h" />
|
||||
<ClInclude Include="..\stb_image.h" />
|
||||
<ClInclude Include="..\stb_image_write.h" />
|
||||
<ClInclude Include="..\tinyexr.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\astc_codec_internals.h" />
|
||||
<ClInclude Include="..\astc_mathlib.h" />
|
||||
<ClInclude Include="..\stb_image.h" />
|
||||
<ClCompile Include="..\astcenccli_error_metrics.cpp" />
|
||||
<ClCompile Include="..\astcenccli_image.cpp" />
|
||||
<ClCompile Include="..\astcenccli_image_load_store.cpp" />
|
||||
<ClCompile Include="..\astcenccli_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astcenccli_toplevel.cpp" />
|
||||
<ClCompile Include="..\astcenccli_toplevel_help.cpp" />
|
||||
<ClCompile Include="..\astcenc_averages_and_directions.cpp" />
|
||||
<ClCompile Include="..\astcenc_block_sizes2.cpp" />
|
||||
<ClCompile Include="..\astcenc_color_quantize.cpp" />
|
||||
<ClCompile Include="..\astcenc_color_unquantize.cpp" />
|
||||
<ClCompile Include="..\astcenc_compress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astcenc_compute_variance.cpp" />
|
||||
<ClCompile Include="..\astcenc_decompress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astcenc_encoding_choice_error.cpp" />
|
||||
<ClCompile Include="..\astcenc_entry.cpp" />
|
||||
<ClCompile Include="..\astcenc_find_best_partitioning.cpp" />
|
||||
<ClCompile Include="..\astcenc_ideal_endpoints_and_weights.cpp" />
|
||||
<ClCompile Include="..\astcenc_image.cpp" />
|
||||
<ClCompile Include="..\astcenc_integer_sequence.cpp" />
|
||||
<ClCompile Include="..\astcenc_kmeans_partitioning.cpp" />
|
||||
<ClCompile Include="..\astcenc_mathlib.cpp" />
|
||||
<ClCompile Include="..\astcenc_mathlib_softfloat.cpp" />
|
||||
<ClCompile Include="..\astcenc_partition_tables.cpp" />
|
||||
<ClCompile Include="..\astcenc_percentile_tables.cpp" />
|
||||
<ClCompile Include="..\astcenc_pick_best_endpoint_format.cpp" />
|
||||
<ClCompile Include="..\astcenc_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astcenc_platform_isa_detection.cpp" />
|
||||
<ClCompile Include="..\astcenc_quantization.cpp" />
|
||||
<ClCompile Include="..\astcenc_symbolic_physical.cpp" />
|
||||
<ClCompile Include="..\astcenc_weight_align.cpp" />
|
||||
<ClCompile Include="..\astcenc_weight_quant_xfer_tables.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{BCA178CD-C714-484E-A02A-0489DC3C49B2}</ProjectGuid>
|
||||
@@ -92,7 +98,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;ASTC_SSE=42;ASTC_AVX=2;ASTC_POPCNT=1;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;ASTCENC_SSE=42;ASTCENC_AVX=2;ASTCENC_POPCNT=1;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
@@ -112,7 +118,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;ASTC_SSE=42;ASTC_AVX=2;ASTC_POPCNT=1;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;ASTCENC_SSE=42;ASTCENC_AVX=2;ASTCENC_POPCNT=1;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
<ClCompile Include="..\astc_weight_quant_xfer_tables.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_mathlib.cpp">
|
||||
<ClCompile Include="..\astcenc_mathlib.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_platform_dependents.cpp">
|
||||
@@ -96,7 +96,7 @@
|
||||
<ClCompile Include="..\astc_error_metrics.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_mathlib_softfloat.cpp">
|
||||
<ClCompile Include="..\astcenc_mathlib_softfloat.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_toplevel_help.cpp">
|
||||
@@ -107,14 +107,14 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\astc_codec_internals.h">
|
||||
<ClInclude Include="..\astcenc_internal.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\stb_image.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\astc_mathlib.h">
|
||||
<ClInclude Include="..\astcenc_mathlib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -11,40 +11,46 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\astc_averages_and_directions.cpp" />
|
||||
<ClCompile Include="..\astc_block_sizes2.cpp" />
|
||||
<ClCompile Include="..\astc_color_quantize.cpp" />
|
||||
<ClCompile Include="..\astc_color_unquantize.cpp" />
|
||||
<ClCompile Include="..\astc_compress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astc_compute_variance.cpp" />
|
||||
<ClCompile Include="..\astc_decompress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astc_encoding_choice_error.cpp" />
|
||||
<ClCompile Include="..\astc_error_metrics.cpp" />
|
||||
<ClCompile Include="..\astc_find_best_partitioning.cpp" />
|
||||
<ClCompile Include="..\astc_ideal_endpoints_and_weights.cpp" />
|
||||
<ClCompile Include="..\astc_image.cpp" />
|
||||
<ClCompile Include="..\astc_image_load_store.cpp" />
|
||||
<ClCompile Include="..\astc_integer_sequence.cpp" />
|
||||
<ClCompile Include="..\astc_kmeans_partitioning.cpp" />
|
||||
<ClCompile Include="..\astc_main.cpp" />
|
||||
<ClCompile Include="..\astc_mathlib.cpp" />
|
||||
<ClCompile Include="..\astc_mathlib_softfloat.cpp" />
|
||||
<ClCompile Include="..\astc_partition_tables.cpp" />
|
||||
<ClCompile Include="..\astc_percentile_tables.cpp" />
|
||||
<ClCompile Include="..\astc_pick_best_endpoint_format.cpp" />
|
||||
<ClCompile Include="..\astc_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astc_platform_isa_detection.cpp" />
|
||||
<ClCompile Include="..\astc_quantization.cpp" />
|
||||
<ClCompile Include="..\astc_symbolic_physical.cpp" />
|
||||
<ClCompile Include="..\astc_toplevel.cpp" />
|
||||
<ClCompile Include="..\astc_toplevel_help.cpp" />
|
||||
<ClCompile Include="..\astc_weight_align.cpp" />
|
||||
<ClCompile Include="..\astc_weight_quant_xfer_tables.cpp" />
|
||||
<ClInclude Include="..\astcenc.h" />
|
||||
<ClInclude Include="..\astcenccli_internal.h" />
|
||||
<ClInclude Include="..\astcenc_internal.h" />
|
||||
<ClInclude Include="..\astcenc_mathlib.h" />
|
||||
<ClInclude Include="..\stb_image.h" />
|
||||
<ClInclude Include="..\stb_image_write.h" />
|
||||
<ClInclude Include="..\tinyexr.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\astc_codec_internals.h" />
|
||||
<ClInclude Include="..\astc_mathlib.h" />
|
||||
<ClInclude Include="..\stb_image.h" />
|
||||
<ClCompile Include="..\astcenccli_error_metrics.cpp" />
|
||||
<ClCompile Include="..\astcenccli_image.cpp" />
|
||||
<ClCompile Include="..\astcenccli_image_load_store.cpp" />
|
||||
<ClCompile Include="..\astcenccli_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astcenccli_toplevel.cpp" />
|
||||
<ClCompile Include="..\astcenccli_toplevel_help.cpp" />
|
||||
<ClCompile Include="..\astcenc_averages_and_directions.cpp" />
|
||||
<ClCompile Include="..\astcenc_block_sizes2.cpp" />
|
||||
<ClCompile Include="..\astcenc_color_quantize.cpp" />
|
||||
<ClCompile Include="..\astcenc_color_unquantize.cpp" />
|
||||
<ClCompile Include="..\astcenc_compress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astcenc_compute_variance.cpp" />
|
||||
<ClCompile Include="..\astcenc_decompress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astcenc_encoding_choice_error.cpp" />
|
||||
<ClCompile Include="..\astcenc_entry.cpp" />
|
||||
<ClCompile Include="..\astcenc_find_best_partitioning.cpp" />
|
||||
<ClCompile Include="..\astcenc_ideal_endpoints_and_weights.cpp" />
|
||||
<ClCompile Include="..\astcenc_image.cpp" />
|
||||
<ClCompile Include="..\astcenc_integer_sequence.cpp" />
|
||||
<ClCompile Include="..\astcenc_kmeans_partitioning.cpp" />
|
||||
<ClCompile Include="..\astcenc_mathlib.cpp" />
|
||||
<ClCompile Include="..\astcenc_mathlib_softfloat.cpp" />
|
||||
<ClCompile Include="..\astcenc_partition_tables.cpp" />
|
||||
<ClCompile Include="..\astcenc_percentile_tables.cpp" />
|
||||
<ClCompile Include="..\astcenc_pick_best_endpoint_format.cpp" />
|
||||
<ClCompile Include="..\astcenc_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astcenc_platform_isa_detection.cpp" />
|
||||
<ClCompile Include="..\astcenc_quantization.cpp" />
|
||||
<ClCompile Include="..\astcenc_symbolic_physical.cpp" />
|
||||
<ClCompile Include="..\astcenc_weight_align.cpp" />
|
||||
<ClCompile Include="..\astcenc_weight_quant_xfer_tables.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D6D60D86-0502-446A-8498-888F78B869C2}</ProjectGuid>
|
||||
@@ -92,7 +98,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;ASTC_SSE=20;ASTC_AVX=0;ASTC_POPCNT=0;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;ASTCENC_SSE=20;ASTCENC_AVX=0;ASTCENC_POPCNT=0;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
@@ -112,7 +118,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;ASTC_SSE=20;ASTC_AVX=0;ASTC_POPCNT=0;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;ASTCENC_SSE=20;ASTCENC_AVX=0;ASTCENC_POPCNT=0;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
<ClCompile Include="..\astc_weight_quant_xfer_tables.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_mathlib.cpp">
|
||||
<ClCompile Include="..\astcenc_mathlib.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_platform_dependents.cpp">
|
||||
@@ -96,7 +96,7 @@
|
||||
<ClCompile Include="..\astc_error_metrics.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_mathlib_softfloat.cpp">
|
||||
<ClCompile Include="..\astcenc_mathlib_softfloat.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\astc_toplevel_help.cpp">
|
||||
@@ -107,14 +107,14 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\astc_codec_internals.h">
|
||||
<ClInclude Include="..\astcenc_internal.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\stb_image.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\astc_mathlib.h">
|
||||
<ClInclude Include="..\astcenc_mathlib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -11,40 +11,46 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\astc_averages_and_directions.cpp" />
|
||||
<ClCompile Include="..\astc_block_sizes2.cpp" />
|
||||
<ClCompile Include="..\astc_color_quantize.cpp" />
|
||||
<ClCompile Include="..\astc_color_unquantize.cpp" />
|
||||
<ClCompile Include="..\astc_compress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astc_compute_variance.cpp" />
|
||||
<ClCompile Include="..\astc_decompress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astc_encoding_choice_error.cpp" />
|
||||
<ClCompile Include="..\astc_error_metrics.cpp" />
|
||||
<ClCompile Include="..\astc_find_best_partitioning.cpp" />
|
||||
<ClCompile Include="..\astc_ideal_endpoints_and_weights.cpp" />
|
||||
<ClCompile Include="..\astc_image.cpp" />
|
||||
<ClCompile Include="..\astc_image_load_store.cpp" />
|
||||
<ClCompile Include="..\astc_integer_sequence.cpp" />
|
||||
<ClCompile Include="..\astc_kmeans_partitioning.cpp" />
|
||||
<ClCompile Include="..\astc_main.cpp" />
|
||||
<ClCompile Include="..\astc_mathlib.cpp" />
|
||||
<ClCompile Include="..\astc_mathlib_softfloat.cpp" />
|
||||
<ClCompile Include="..\astc_partition_tables.cpp" />
|
||||
<ClCompile Include="..\astc_percentile_tables.cpp" />
|
||||
<ClCompile Include="..\astc_pick_best_endpoint_format.cpp" />
|
||||
<ClCompile Include="..\astc_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astc_platform_isa_detection.cpp" />
|
||||
<ClCompile Include="..\astc_quantization.cpp" />
|
||||
<ClCompile Include="..\astc_symbolic_physical.cpp" />
|
||||
<ClCompile Include="..\astc_toplevel.cpp" />
|
||||
<ClCompile Include="..\astc_toplevel_help.cpp" />
|
||||
<ClCompile Include="..\astc_weight_align.cpp" />
|
||||
<ClCompile Include="..\astc_weight_quant_xfer_tables.cpp" />
|
||||
<ClInclude Include="..\astcenc.h" />
|
||||
<ClInclude Include="..\astcenccli_internal.h" />
|
||||
<ClInclude Include="..\astcenc_internal.h" />
|
||||
<ClInclude Include="..\astcenc_mathlib.h" />
|
||||
<ClInclude Include="..\stb_image.h" />
|
||||
<ClInclude Include="..\stb_image_write.h" />
|
||||
<ClInclude Include="..\tinyexr.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\astc_codec_internals.h" />
|
||||
<ClInclude Include="..\astc_mathlib.h" />
|
||||
<ClInclude Include="..\stb_image.h" />
|
||||
<ClCompile Include="..\astcenccli_error_metrics.cpp" />
|
||||
<ClCompile Include="..\astcenccli_image.cpp" />
|
||||
<ClCompile Include="..\astcenccli_image_load_store.cpp" />
|
||||
<ClCompile Include="..\astcenccli_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astcenccli_toplevel.cpp" />
|
||||
<ClCompile Include="..\astcenccli_toplevel_help.cpp" />
|
||||
<ClCompile Include="..\astcenc_averages_and_directions.cpp" />
|
||||
<ClCompile Include="..\astcenc_block_sizes2.cpp" />
|
||||
<ClCompile Include="..\astcenc_color_quantize.cpp" />
|
||||
<ClCompile Include="..\astcenc_color_unquantize.cpp" />
|
||||
<ClCompile Include="..\astcenc_compress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astcenc_compute_variance.cpp" />
|
||||
<ClCompile Include="..\astcenc_decompress_symbolic.cpp" />
|
||||
<ClCompile Include="..\astcenc_encoding_choice_error.cpp" />
|
||||
<ClCompile Include="..\astcenc_entry.cpp" />
|
||||
<ClCompile Include="..\astcenc_find_best_partitioning.cpp" />
|
||||
<ClCompile Include="..\astcenc_ideal_endpoints_and_weights.cpp" />
|
||||
<ClCompile Include="..\astcenc_image.cpp" />
|
||||
<ClCompile Include="..\astcenc_integer_sequence.cpp" />
|
||||
<ClCompile Include="..\astcenc_kmeans_partitioning.cpp" />
|
||||
<ClCompile Include="..\astcenc_mathlib.cpp" />
|
||||
<ClCompile Include="..\astcenc_mathlib_softfloat.cpp" />
|
||||
<ClCompile Include="..\astcenc_partition_tables.cpp" />
|
||||
<ClCompile Include="..\astcenc_percentile_tables.cpp" />
|
||||
<ClCompile Include="..\astcenc_pick_best_endpoint_format.cpp" />
|
||||
<ClCompile Include="..\astcenc_platform_dependents.cpp" />
|
||||
<ClCompile Include="..\astcenc_platform_isa_detection.cpp" />
|
||||
<ClCompile Include="..\astcenc_quantization.cpp" />
|
||||
<ClCompile Include="..\astcenc_symbolic_physical.cpp" />
|
||||
<ClCompile Include="..\astcenc_weight_align.cpp" />
|
||||
<ClCompile Include="..\astcenc_weight_quant_xfer_tables.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9FB06FB7-F57D-4B12-9AE9-91CD50FD4879}</ProjectGuid>
|
||||
@@ -92,7 +98,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;ASTC_SSE=42;ASTC_AVX=0;ASTC_POPCNT=1;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;ASTCENC_SSE=42;ASTCENC_AVX=0;ASTCENC_POPCNT=1;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
@@ -112,7 +118,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;ASTC_SSE=42;ASTC_AVX=0;ASTC_POPCNT=1;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;ASTCENC_SSE=42;ASTCENC_AVX=0;ASTCENC_POPCNT=1;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2020 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Application entry point.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
) {
|
||||
return astc_main(argc, argv);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,347 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2020 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief The core astcenc codec library interface.
|
||||
*
|
||||
* This interface is the entry point to the core astcenc codec. It aims to be
|
||||
* easy to use for non-experts, but also to allow experts to have fine control
|
||||
* over the compressor heuristics. The core codec only handles compression and
|
||||
* decompression, transferring all inputs and outputs via memory buffers.
|
||||
*
|
||||
* While the aim is that we keep this interface mostly stable, it should be
|
||||
* viewed as a mutable interface tied to a specific source version. We are not
|
||||
* trying to maintain backwards compatibility across codec versions.
|
||||
*
|
||||
* The API state management is based around an explicit context object. The
|
||||
* context is the container for all allocated resources -- memory and threads
|
||||
* -- needed to compress and decompress for a single image configuration. A
|
||||
* context keeps the state needed to process one image at a time, but can be
|
||||
* used to sequentially compress multiple images using the same configuration.
|
||||
* This allows setup overheads to be amortized over multiple images, which is
|
||||
* particularly important when images are small. An application can process
|
||||
* multiple images concurrently by allocating multiple contexts.
|
||||
*
|
||||
* The API allows compression of a single image by using multiple threads
|
||||
* within the scope of a single context. The API supports two mechanisms for
|
||||
* this: automatic and manual. Automatic threading uses threads created and
|
||||
* managed by the codec itself; no user setup needed - just configure the
|
||||
* thread count and call compress from a single application thread.
|
||||
* Manual threading uses user-created threads, which is a common pattern in
|
||||
* some developer tools using persistent pools of worker threads. For this
|
||||
* configure the codec with the maximum thread count you'll use and then invoke
|
||||
* compress from each worker thread.
|
||||
*
|
||||
* To catch obvious input/output buffer sizing issues, which can cause security
|
||||
* and stability problems, all transfer buffers are explicitly sized.
|
||||
*
|
||||
* Automatic threading
|
||||
* ===================
|
||||
*
|
||||
* In pseudocode, the usage for automatic threading looks like this:
|
||||
*
|
||||
* // Configure the compressor run
|
||||
* astcenc_config my_config;
|
||||
* astcenc_init_config(..., &my_config);
|
||||
*
|
||||
* // Power users can modify the config after it is initialized and
|
||||
* // before allocating the context with it.
|
||||
*
|
||||
* // Allocate working state given config and thread_count
|
||||
* astcenc_context* my_context;
|
||||
* astcenc_context_alloc(&my_config, thread_count, &my_context);
|
||||
*
|
||||
* // Compress the image with automatic multithreading
|
||||
* foreach image:
|
||||
* astc_image input;
|
||||
* uint8_t* output;
|
||||
* astcenc_compress_image(&my_context, &input, output, -1);
|
||||
*
|
||||
* // Clean up
|
||||
* astcenc_context_free(my_context);
|
||||
*
|
||||
* Manual threading
|
||||
* ================
|
||||
*
|
||||
* In pseudocode, the usage for manual user threading looks like this:
|
||||
*
|
||||
* // Configure the compressor run
|
||||
* astcenc_config my_config;
|
||||
* astcenc_flags my_flags = ASTCENC_USE_USER_THREADS | ...;
|
||||
* astcenc_init_config(..., my_flags, &my_config);
|
||||
*
|
||||
* // Allocate working state given config and thread_count
|
||||
* astcenc_context* my_context;
|
||||
* astcenc_context_alloc(&my_config, thread_count, &my_context);
|
||||
*
|
||||
* // Compress the image with manually managed multithreading
|
||||
* foreach image:
|
||||
* astc_image input;
|
||||
* uint8_t* output;
|
||||
* for i in range(0, thread_count):
|
||||
* astcenc_compress_image(&my_context, &input, output, i);
|
||||
*
|
||||
* // Wait for all threads to complete one image
|
||||
* barrier();
|
||||
*
|
||||
* // Clean up
|
||||
* astcenc_context_free(my_context);
|
||||
*/
|
||||
|
||||
#ifndef ASTCENC_INCLUDED
|
||||
#define ASTCENC_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
/* ============================================================================
|
||||
Data declarations
|
||||
============================================================================ */
|
||||
struct astcenc_context;
|
||||
|
||||
// Return codes
|
||||
enum astcenc_error {
|
||||
ASTCENC_SUCCESS = 0,
|
||||
ASTCENC_ERR_OUT_OF_MEM,
|
||||
ASTCENC_ERR_BAD_CPU_FLOAT,
|
||||
ASTCENC_ERR_BAD_CPU_ISA,
|
||||
ASTCENC_ERR_BAD_PARAM,
|
||||
ASTCENC_ERR_BAD_BLOCK_SIZE,
|
||||
ASTCENC_ERR_BAD_PROFILE,
|
||||
ASTCENC_ERR_BAD_PRESET,
|
||||
ASTCENC_ERR_BAD_SWIZZLE,
|
||||
ASTCENC_ERR_BAD_FLAGS,
|
||||
ASTCENC_ERR_NOT_IMPLEMENTED
|
||||
};
|
||||
|
||||
// Compression color feature profile
|
||||
enum astcenc_profile {
|
||||
ASTCENC_PRF_LDR_SRGB = 0,
|
||||
ASTCENC_PRF_LDR,
|
||||
ASTCENC_PRF_HDR_RGB_LDR_A,
|
||||
ASTCENC_PRF_HDR
|
||||
};
|
||||
|
||||
// Compression quality preset
|
||||
enum astcenc_preset {
|
||||
ASTCENC_PRE_FAST = 0,
|
||||
ASTCENC_PRE_MEDIUM,
|
||||
ASTCENC_PRE_THOROUGH,
|
||||
ASTCENC_PRE_EXHAUSTIVE
|
||||
};
|
||||
|
||||
// Image channel data type
|
||||
enum astcenc_type {
|
||||
ASTCENC_TYP_U8 = 0,
|
||||
ASTCENC_TYP_F16
|
||||
};
|
||||
|
||||
// Image channel swizzles
|
||||
enum astcenc_swz {
|
||||
ASTCENC_SWZ_R = 0,
|
||||
ASTCENC_SWZ_G = 1,
|
||||
ASTCENC_SWZ_B = 2,
|
||||
ASTCENC_SWZ_A = 3,
|
||||
ASTCENC_SWZ_0 = 4,
|
||||
ASTCENC_SWZ_1 = 5,
|
||||
ASTCENC_SWZ_Z = 6
|
||||
};
|
||||
|
||||
// Image channel swizzles
|
||||
struct astcenc_swizzle {
|
||||
astcenc_swz r;
|
||||
astcenc_swz g;
|
||||
astcenc_swz b;
|
||||
astcenc_swz a;
|
||||
};
|
||||
|
||||
// Config mode flags
|
||||
static const unsigned int ASTCENC_FLG_MAP_NORMAL = 1 << 0;
|
||||
static const unsigned int ASTCENC_FLG_MAP_MASK = 1 << 1;
|
||||
static const unsigned int ASTCENC_FLG_USE_ALPHA_WEIGHT = 1 << 2;
|
||||
static const unsigned int ASTCENC_FLG_USE_PERCEPTUAL = 1 << 3;
|
||||
static const unsigned int ASTCENC_FLG_USE_USER_THREADS = 1 << 4;
|
||||
static const unsigned int ASTCENC_FLG_USE_LINEARIZED_SRGB = 1 << 5;
|
||||
|
||||
static const unsigned int ASTCENC_ALL_FLAGS =
|
||||
ASTCENC_FLG_MAP_NORMAL |
|
||||
ASTCENC_FLG_MAP_MASK |
|
||||
ASTCENC_FLG_USE_ALPHA_WEIGHT |
|
||||
ASTCENC_FLG_USE_PERCEPTUAL |
|
||||
ASTCENC_FLG_USE_USER_THREADS |
|
||||
ASTCENC_FLG_USE_LINEARIZED_SRGB;
|
||||
|
||||
// Config structure
|
||||
struct astcenc_config {
|
||||
astcenc_profile profile;
|
||||
unsigned int flags;
|
||||
unsigned int block_x;
|
||||
unsigned int block_y;
|
||||
unsigned int block_z;
|
||||
unsigned int v_rgba_radius;
|
||||
float v_rgba_mean_stdev_mix;
|
||||
float v_rgb_power;
|
||||
float v_rgb_base;
|
||||
float v_rgb_mean;
|
||||
float v_rgb_stdev;
|
||||
float v_a_power;
|
||||
float v_a_base;
|
||||
float v_a_mean;
|
||||
float v_a_stdev;
|
||||
float cw_r_weight;
|
||||
float cw_g_weight;
|
||||
float cw_b_weight;
|
||||
float cw_a_weight;
|
||||
unsigned int a_scale_radius;
|
||||
float b_deblock_weight;
|
||||
unsigned int tune_partition_limit;
|
||||
unsigned int tune_block_mode_limit;
|
||||
unsigned int tune_refinement_limit;
|
||||
float tune_db_limit;
|
||||
float tune_partition_early_out_limit;
|
||||
float tune_two_plane_early_out_limit;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure to store an uncompressed 2D image, or a slice from a 3D image.
|
||||
*
|
||||
* @param dim_x The x dimension of the image, in texels.
|
||||
* @param dim_y The y dimension of the image, in texels.
|
||||
* @param dim_z The z dimension of the image, in texels.
|
||||
* @param channels The number of color channels.
|
||||
*/
|
||||
struct astcenc_image {
|
||||
unsigned int dim_x;
|
||||
unsigned int dim_y;
|
||||
unsigned int dim_z;
|
||||
unsigned int dim_pad;
|
||||
uint8_t ***data8;
|
||||
uint16_t ***data16;
|
||||
};
|
||||
|
||||
/**
|
||||
* Populate a compressor config based on default settings.
|
||||
*
|
||||
* Power users can edit the returned config struct to apply manual fine tuning
|
||||
* before creating the context.
|
||||
*
|
||||
* @param profile The color profile.
|
||||
* @param block_x The ASTC block size X dimension.
|
||||
* @param block_y The ASTC block size Y dimension.
|
||||
* @param block_z The ASTC block size Z dimension.
|
||||
* @param preset The search quality preset.
|
||||
* @param flags Any ASTCENC_FLG_* flag bits.
|
||||
* @param config The output config struct to populate.
|
||||
*
|
||||
* @return ASTCENC_SUCCESS on success, or an error if the inputs are invalid
|
||||
* either individually, or in combination.
|
||||
*/
|
||||
astcenc_error astcenc_init_config(
|
||||
astcenc_profile profile,
|
||||
unsigned int block_x,
|
||||
unsigned int block_y,
|
||||
unsigned int block_z,
|
||||
astcenc_preset preset,
|
||||
unsigned int flags,
|
||||
astcenc_config& config);
|
||||
|
||||
/**
|
||||
* Allocate a new compressor context based on the settings in the config.
|
||||
*
|
||||
* This function allocates all of the memory resources and threads needed by
|
||||
* the compressor. This can be slow, so it is recommended that contexts are
|
||||
* reused to serially compress multiple images in order to amortize setup cost.
|
||||
*
|
||||
* @param config The codec config.
|
||||
* @param thread_count The thread count to configure for. This will allocate
|
||||
* new threads unless config created with USE_USER_THREADS.
|
||||
* If thread count is zero, the compressor will auto-set
|
||||
* the thread count to the host CPU count.
|
||||
* @param context Output location to store an opaque context pointer.
|
||||
*
|
||||
* @return ASTCENC_SUCCESS on success, or an error if context creation failed.
|
||||
*/
|
||||
astcenc_error astcenc_context_alloc(
|
||||
const astcenc_config& config,
|
||||
unsigned int thread_count,
|
||||
astcenc_context** context);
|
||||
|
||||
/**
|
||||
* Compress an image.
|
||||
*
|
||||
* Note: User must allocate all output memory before calling this function.
|
||||
*
|
||||
* @param context The codec context.
|
||||
* @param image The input image.
|
||||
* @param data_out Pointer to byte array to store the output.
|
||||
* @param data_len Length of the data array, in bytes.
|
||||
* @param thread_index The thread index [0..N-1] of the calling thread. All
|
||||
* N threads must call this function exactly once per
|
||||
* decompression, and all threads must exit this function
|
||||
* before a new image can be compressed or decompressed
|
||||
*
|
||||
* @return ASTCENC_SUCCESS on success, or an error if compression failed.
|
||||
*/
|
||||
astcenc_error astcenc_compress_image(
|
||||
astcenc_context* context,
|
||||
astcenc_image& image,
|
||||
astcenc_swizzle swizzle,
|
||||
uint8_t* data_out,
|
||||
size_t data_len,
|
||||
unsigned int thread_index);
|
||||
|
||||
/**
|
||||
* Decompress an image.
|
||||
*
|
||||
* Note: User must allocate all output memory before calling this function.
|
||||
*
|
||||
* @param context The codec context.
|
||||
* @param data Pointer to compressed data.
|
||||
* @param data_len Length of the compressed data, in bytes.
|
||||
* @param image_out The output image.
|
||||
* @param thread_index The thread index [0..N-1] of the calling thread. All
|
||||
* N threads must call this function exactly once per
|
||||
* decompression, and all threads must exit this function
|
||||
* before a new image can be compressed or decompressed.
|
||||
*
|
||||
* @return ASTCENC_SUCCESS on success, or an error if decompression failed.
|
||||
*/
|
||||
astcenc_error astcenc_decompress_image(
|
||||
astcenc_context* context,
|
||||
uint8_t* data,
|
||||
size_t data_len,
|
||||
astcenc_image& image_out,
|
||||
astcenc_swizzle swizzle,
|
||||
unsigned int thread_index);
|
||||
|
||||
/**
|
||||
* Free the compressor context.
|
||||
*/
|
||||
void astcenc_context_free(
|
||||
astcenc_context* context);
|
||||
|
||||
/**
|
||||
* Utility to get a string for specific status code.
|
||||
*
|
||||
* @param status The status value.
|
||||
*
|
||||
* @return A human readable nul-terminated string.
|
||||
*/
|
||||
const char* astcenc_get_error_string(
|
||||
astcenc_error status);
|
||||
|
||||
#endif
|
||||
+13
-10
@@ -19,7 +19,7 @@
|
||||
* @brief Functions for finding dominant direction of a set of colors.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
#ifdef DEBUG_CAPTURE_NAN
|
||||
#ifndef _GNU_SOURCE
|
||||
@@ -99,20 +99,22 @@ void compute_averages_and_directions_rgba(
|
||||
|
||||
float4 best_vector = sum_xp;
|
||||
float best_sum = prod_xp;
|
||||
|
||||
if (prod_yp > best_sum)
|
||||
{
|
||||
best_vector = sum_yp;
|
||||
best_sum = prod_yp;
|
||||
}
|
||||
|
||||
if (prod_zp > best_sum)
|
||||
{
|
||||
best_vector = sum_zp;
|
||||
best_sum = prod_zp;
|
||||
}
|
||||
|
||||
if (prod_wp > best_sum)
|
||||
{
|
||||
best_vector = sum_wp;
|
||||
best_sum = prod_wp;
|
||||
}
|
||||
|
||||
directions_rgba[partition] = best_vector;
|
||||
@@ -184,15 +186,16 @@ void compute_averages_and_directions_rgb(
|
||||
|
||||
float3 best_vector = sum_xp;
|
||||
float best_sum = prod_xp;
|
||||
|
||||
if (prod_yp > best_sum)
|
||||
{
|
||||
best_vector = sum_yp;
|
||||
best_sum = prod_yp;
|
||||
}
|
||||
|
||||
if (prod_zp > best_sum)
|
||||
{
|
||||
best_vector = sum_zp;
|
||||
best_sum = prod_zp;
|
||||
}
|
||||
|
||||
directions_rgb[partition] = best_vector;
|
||||
@@ -298,19 +301,23 @@ void compute_averages_and_directions_3_components(
|
||||
|
||||
float3 best_vector = sum_xp;
|
||||
float best_sum = prod_xp;
|
||||
|
||||
if (prod_yp > best_sum)
|
||||
{
|
||||
best_vector = sum_yp;
|
||||
best_sum = prod_yp;
|
||||
}
|
||||
|
||||
if (prod_zp > best_sum)
|
||||
{
|
||||
best_vector = sum_zp;
|
||||
best_sum = prod_zp;
|
||||
}
|
||||
|
||||
if (dot(best_vector, best_vector) < 1e-18f)
|
||||
{
|
||||
best_vector = float3(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
directions[partition] = best_vector;
|
||||
}
|
||||
|
||||
@@ -345,16 +352,12 @@ void compute_averages_and_directions_2_components(
|
||||
data_vr = blk->data_r;
|
||||
data_vg = blk->data_b;
|
||||
}
|
||||
else if (component1 == 1 && component2 == 2)
|
||||
else // (component1 == 1 && component2 == 2)
|
||||
{
|
||||
texel_weights = ewb->texel_weight_gb;
|
||||
data_vr = blk->data_g;
|
||||
data_vg = blk->data_b;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
|
||||
for (partition = 0; partition < partition_count; partition++)
|
||||
{
|
||||
@@ -400,10 +403,10 @@ void compute_averages_and_directions_2_components(
|
||||
|
||||
float2 best_vector = sum_xp;
|
||||
float best_sum = prod_xp;
|
||||
|
||||
if (prod_yp > best_sum)
|
||||
{
|
||||
best_vector = sum_yp;
|
||||
best_sum = prod_yp;
|
||||
}
|
||||
|
||||
directions[partition] = best_vector;
|
||||
@@ -19,7 +19,7 @@
|
||||
* @brief Functions to generate block size descriptor and decimation tables.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
// return 0 on invalid mode, 1 on valid mode.
|
||||
static int decode_block_mode_2d(
|
||||
@@ -21,11 +21,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/*
|
||||
quantize an LDR RGB color. Since this is a fall-back encoding, we cannot actually
|
||||
@@ -1109,14 +1105,10 @@ static void quantize_hdr_rgbo3(
|
||||
int s_uquantval;
|
||||
|
||||
quantize_and_unquantize_retain_top_four_bits(quantization_level, s_lowbits, &s_quantval, &s_uquantval);
|
||||
|
||||
s_intval = (s_intval & ~0x1f) | (s_uquantval & 0x1f);
|
||||
s_fval = s_intval * mode_rscale;
|
||||
output[0] = r_quantval;
|
||||
output[1] = g_quantval;
|
||||
output[2] = b_quantval;
|
||||
output[3] = s_quantval;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1866,16 +1858,6 @@ int pack_color_endpoints(
|
||||
int* output,
|
||||
int quantization_level
|
||||
) {
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s : format=%d quantization_level=%d\n", __func__, format, quantization_level);
|
||||
printf("Color 0: <%g %g %g %g>\n", color0.x, color0.y, color0.z, color0.w);
|
||||
printf("Color 1: <%g %g %g %g>\n", color1.x, color1.y, color1.z, color1.w);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// we do not support negative colors.
|
||||
color0.x = MAX(color0.x, 0.0f);
|
||||
color0.y = MAX(color0.y, 0.0f);
|
||||
@@ -1886,8 +1868,9 @@ int pack_color_endpoints(
|
||||
color1.z = MAX(color1.z, 0.0f);
|
||||
color1.w = MAX(color1.w, 0.0f);
|
||||
|
||||
int retval;
|
||||
int retval = 0;
|
||||
|
||||
// TODO: Make format an endpoint_fmt enum type
|
||||
switch (format)
|
||||
{
|
||||
case FMT_RGB:
|
||||
@@ -1994,23 +1977,7 @@ int pack_color_endpoints(
|
||||
quantize_hdr_rgb_alpha3(color0, color1, output, quantization_level);
|
||||
retval = FMT_HDR_RGBA;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
int i;
|
||||
printf("Quantized to format %d\n", retval);
|
||||
printf("Quantized color:");
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
printf(" %X", output[i]);
|
||||
printf("\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
* @brief Functions for color unquantization.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
static int rgb_delta_unpack(
|
||||
const int input[6],
|
||||
@@ -795,8 +795,7 @@ static void hdr_rgb_hdr_alpha_unpack3(
|
||||
}
|
||||
|
||||
void unpack_color_endpoints(
|
||||
const astc_codec_image* image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
int format,
|
||||
int quantization_level,
|
||||
const int* input,
|
||||
@@ -808,6 +807,7 @@ void unpack_color_endpoints(
|
||||
) {
|
||||
*nan_endpoint = 0;
|
||||
|
||||
// TODO: Make format the correct enum type
|
||||
switch (format)
|
||||
{
|
||||
case FMT_LUMINANCE:
|
||||
@@ -905,14 +905,11 @@ void unpack_color_endpoints(
|
||||
*alpha_hdr = 1;
|
||||
hdr_rgb_hdr_alpha_unpack3(input, quantization_level, output0, output1);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
|
||||
if (*alpha_hdr == -1)
|
||||
{
|
||||
if (image->alpha_force_use_of_hdr)
|
||||
if (decode_mode == ASTCENC_PRF_HDR)
|
||||
{
|
||||
output0->w = 0x7800;
|
||||
output1->w = 0x7800;
|
||||
@@ -928,7 +925,7 @@ void unpack_color_endpoints(
|
||||
|
||||
switch (decode_mode)
|
||||
{
|
||||
case DECODE_LDR_SRGB:
|
||||
case ASTCENC_PRF_LDR_SRGB:
|
||||
if (*rgb_hdr == 1)
|
||||
{
|
||||
output0->x = 0xFF00;
|
||||
@@ -955,7 +952,7 @@ void unpack_color_endpoints(
|
||||
*alpha_hdr = 0;
|
||||
break;
|
||||
|
||||
case DECODE_LDR:
|
||||
case ASTCENC_PRF_LDR:
|
||||
if (*rgb_hdr == 1)
|
||||
{
|
||||
output0->x = 0xFFFF;
|
||||
@@ -983,8 +980,8 @@ void unpack_color_endpoints(
|
||||
*alpha_hdr = 0;
|
||||
break;
|
||||
|
||||
case DECODE_HDR:
|
||||
case DECODE_HDRA:
|
||||
case ASTCENC_PRF_HDR_RGB_LDR_A:
|
||||
case ASTCENC_PRF_HDR:
|
||||
if (*rgb_hdr == 0)
|
||||
{
|
||||
output0->x *= 257;
|
||||
@@ -19,10 +19,11 @@
|
||||
* @brief Functions to compress a symbolic block.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef DEBUG_CAPTURE_NAN
|
||||
#ifndef _GNU_SOURCE
|
||||
@@ -40,8 +41,7 @@
|
||||
* quality by moving each weight up by one or down by one quantization step.
|
||||
*/
|
||||
static int realign_weights(
|
||||
const astc_codec_image* image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
const block_size_descriptor* bsd,
|
||||
const imageblock* blk,
|
||||
const error_weight_block* ewb,
|
||||
@@ -78,8 +78,7 @@ static int realign_weights(
|
||||
|
||||
for (int pa_idx = 0; pa_idx < partition_count; pa_idx++)
|
||||
{
|
||||
unpack_color_endpoints(image,
|
||||
decode_mode,
|
||||
unpack_color_endpoints(decode_mode,
|
||||
scb->color_formats[pa_idx],
|
||||
scb->color_quantization_level,
|
||||
scb->color_values[pa_idx],
|
||||
@@ -207,8 +206,7 @@ static int realign_weights(
|
||||
function for compressing a block symbolically, given that we have already decided on a partition
|
||||
*/
|
||||
static void compress_symbolic_block_fixed_partition_1_plane(
|
||||
const astc_codec_image* image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
float mode_cutoff,
|
||||
int max_refinement_iters,
|
||||
const block_size_descriptor* bsd,
|
||||
@@ -306,8 +304,6 @@ static void compress_symbolic_block_fixed_partition_1_plane(
|
||||
weight_high_value[i] = 1.0f;
|
||||
|
||||
int decimation_mode = bsd->block_modes[i].decimation_mode;
|
||||
if (bsd->decimation_mode_percentile[decimation_mode] > mode_cutoff)
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
|
||||
// compute weight bitcount for the mode
|
||||
int bits_used_by_weights = compute_ise_bitcount(ixtab2[decimation_mode]->num_weights,
|
||||
@@ -330,11 +326,6 @@ static void compress_symbolic_block_fixed_partition_1_plane(
|
||||
|
||||
// then, compute weight-errors for the weight mode.
|
||||
qwt_errors[i] = compute_error_of_weight_set(&(eix[decimation_mode]), ixtab2[decimation_mode], flt_quantized_decimated_quantized_weights + MAX_WEIGHTS_PER_BLOCK * i);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Block mode %d -> weight error = %f\n", i, qwt_errors[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// for each weighting mode, determine the optimal combination of color endpoint encodings
|
||||
@@ -364,16 +355,6 @@ static void compress_symbolic_block_fixed_partition_1_plane(
|
||||
int decimation_mode = bsd->block_modes[quantized_weight[i]].decimation_mode;
|
||||
int weight_quantization_mode = bsd->block_modes[quantized_weight[i]].quantization_mode;
|
||||
const decimation_table *it = ixtab2[decimation_mode];
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("Selected mode = %d\n", quantized_weight[i]);
|
||||
printf("Selected decimation mode = %d\n", decimation_mode);
|
||||
printf("Selected weight-quantization mode = %d\n", weight_quantization_mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
u8_weight_src = u8_quantized_decimated_quantized_weights + MAX_WEIGHTS_PER_BLOCK * quantized_weight[i];
|
||||
|
||||
weights_to_copy = it->num_weights;
|
||||
@@ -441,7 +422,7 @@ static void compress_symbolic_block_fixed_partition_1_plane(
|
||||
|
||||
// perform a final pass over the weights to try to improve them.
|
||||
int adjustments = realign_weights(
|
||||
image, decode_mode, bsd, blk, ewb, scb, u8_weight_src, nullptr);
|
||||
decode_mode, bsd, blk, ewb, scb, u8_weight_src, nullptr);
|
||||
|
||||
if (adjustments == 0)
|
||||
break;
|
||||
@@ -455,8 +436,7 @@ static void compress_symbolic_block_fixed_partition_1_plane(
|
||||
}
|
||||
|
||||
static void compress_symbolic_block_fixed_partition_2_planes(
|
||||
const astc_codec_image* image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
float mode_cutoff,
|
||||
int max_refinement_iters,
|
||||
const block_size_descriptor* bsd,
|
||||
@@ -730,7 +710,7 @@ static void compress_symbolic_block_fixed_partition_2_planes(
|
||||
}
|
||||
|
||||
int adjustments = realign_weights(
|
||||
image, decode_mode, bsd, blk, ewb, scb, u8_weight1_src, u8_weight2_src);
|
||||
decode_mode, bsd, blk, ewb, scb, u8_weight1_src, u8_weight2_src);
|
||||
|
||||
if (adjustments == 0)
|
||||
break;
|
||||
@@ -747,22 +727,21 @@ static void compress_symbolic_block_fixed_partition_2_planes(
|
||||
}
|
||||
|
||||
void expand_block_artifact_suppression(
|
||||
int xdim,
|
||||
int ydim,
|
||||
int zdim,
|
||||
unsigned int xdim,
|
||||
unsigned int ydim,
|
||||
unsigned int zdim,
|
||||
error_weighting_params* ewp
|
||||
) {
|
||||
int x, y, z;
|
||||
float centerpos_x = (xdim - 1) * 0.5f;
|
||||
float centerpos_y = (ydim - 1) * 0.5f;
|
||||
float centerpos_z = (zdim - 1) * 0.5f;
|
||||
float *bef = ewp->block_artifact_suppression_expanded;
|
||||
|
||||
for (z = 0; z < zdim; z++)
|
||||
for (unsigned int z = 0; z < zdim; z++)
|
||||
{
|
||||
for (y = 0; y < ydim; y++)
|
||||
for (unsigned int y = 0; y < ydim; y++)
|
||||
{
|
||||
for (x = 0; x < xdim; x++)
|
||||
for (unsigned int x = 0; x < xdim; x++)
|
||||
{
|
||||
float xdif = (x - centerpos_x) / xdim;
|
||||
float ydif = (y - centerpos_y) / ydim;
|
||||
@@ -1018,8 +997,7 @@ static void prepare_block_statistics(
|
||||
for (i = 0; i < texels_per_block; i++)
|
||||
{
|
||||
float weight = ewb->texel_weight[i];
|
||||
if (weight < 0.0f)
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
assert(weight >= 0.0f);
|
||||
weight_sum += weight;
|
||||
|
||||
float r = blk->data_r[i];
|
||||
@@ -1106,13 +1084,9 @@ static void prepare_block_statistics(
|
||||
*is_normal_map = nf_sum < (0.2f * (float)texels_per_block);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
int block_mode_histogram[2048];
|
||||
#endif
|
||||
|
||||
float compress_symbolic_block(
|
||||
const astc_codec_image* input_image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
const block_size_descriptor* bsd,
|
||||
const error_weighting_params* ewp,
|
||||
const imageblock* blk,
|
||||
@@ -1124,39 +1098,13 @@ float compress_symbolic_block(
|
||||
int ypos = blk->ypos;
|
||||
int zpos = blk->zpos;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("Diagnostics of block of dimension %d x %d x %d\n\n", xdim, ydim, zdim);
|
||||
|
||||
printf("XPos: %d YPos: %d ZPos: %d\n", xpos, ypos, zpos);
|
||||
|
||||
printf("Red-min: %f Red-max: %f\n", blk->red_min, blk->red_max);
|
||||
printf("Green-min: %f Green-max: %f\n", blk->green_min, blk->green_max);
|
||||
printf("Blue-min: %f Blue-max: %f\n", blk->blue_min, blk->blue_max);
|
||||
printf("Alpha-min: %f Alpha-max: %f\n", blk->alpha_min, blk->alpha_max);
|
||||
printf("Grayscale: %d\n", blk->grayscale);
|
||||
|
||||
for (int z = 0; z < zdim; z++)
|
||||
for (int y = 0; y < ydim; y++)
|
||||
for (int x = 0; x < xdim; x++)
|
||||
{
|
||||
int idx = ((z * ydim + y) * xdim + x) * 4;
|
||||
printf("Texel (%d %d %d) : orig=< %g, %g, %g, %g >, work=< %g, %g, %g, %g >\n",
|
||||
x, y, z,
|
||||
blk->orig_data[idx], blk->orig_data[idx + 1], blk->orig_data[idx + 2], blk->orig_data[idx + 3],
|
||||
blk->data_r[idx], blk->data_g[idx], blk->data_b[idx], blk->data_a[idx]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (blk->red_min == blk->red_max && blk->green_min == blk->green_max && blk->blue_min == blk->blue_max && blk->alpha_min == blk->alpha_max)
|
||||
{
|
||||
// detected a constant-color block. Encode as FP16 if using HDR
|
||||
scb->error_block = 0;
|
||||
|
||||
if (input_image->rgb_force_use_of_hdr)
|
||||
if ((decode_mode == ASTCENC_PRF_HDR) ||
|
||||
(decode_mode == ASTCENC_PRF_HDR_RGB_LDR_A))
|
||||
{
|
||||
scb->block_mode = -1;
|
||||
scb->partition_count = 0;
|
||||
@@ -1201,16 +1149,6 @@ float compress_symbolic_block(
|
||||
scb->constant_color[3] = astc::flt2int_rtn(alpha * 65535.0f);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("Block is single-color <%4.4X %4.4X %4.4X %4.4X>\n", scb->constant_color[0], scb->constant_color[1], scb->constant_color[2], scb->constant_color[3]);
|
||||
}
|
||||
|
||||
if (print_tile_errors)
|
||||
printf("0\n");
|
||||
#endif
|
||||
|
||||
physical_compressed_block psb = symbolic_to_physical(bsd, scb);
|
||||
physical_to_symbolic(bsd, psb, scb);
|
||||
|
||||
@@ -1222,21 +1160,6 @@ float compress_symbolic_block(
|
||||
|
||||
float error_weight_sum = prepare_error_weight_block(input_image, bsd, ewp, blk, ewb, ewbo);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("\n");
|
||||
for (int z = 0; z < zdim; z++)
|
||||
for (int y = 0; y < ydim; y++)
|
||||
for (int x = 0; x < xdim; x++)
|
||||
{
|
||||
int idx = (z * ydim + y) * xdim + x;
|
||||
printf("ErrorWeight (%d %d %d) : < %g, %g, %g, %g >\n", x, y, z, ewb->error_weights[idx].x, ewb->error_weights[idx].y, ewb->error_weights[idx].z, ewb->error_weights[idx].w);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
symbolic_compressed_block *tempblocks = tmpbuf->tempblocks;
|
||||
|
||||
float error_of_best_block = 1e20f;
|
||||
@@ -1263,7 +1186,7 @@ float compress_symbolic_block(
|
||||
float best_errorval_in_mode;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
compress_symbolic_block_fixed_partition_1_plane(input_image, decode_mode, modecutoffs[i], ewp->max_refinement_iters, bsd, 1, // partition count
|
||||
compress_symbolic_block_fixed_partition_1_plane(decode_mode, modecutoffs[i], ewp->max_refinement_iters, bsd, 1, // partition count
|
||||
0, // partition index
|
||||
blk, ewb, tempblocks, tmpbuf->plane1);
|
||||
|
||||
@@ -1272,38 +1195,17 @@ float compress_symbolic_block(
|
||||
{
|
||||
if (tempblocks[j].error_block)
|
||||
continue;
|
||||
decompress_symbolic_block(input_image, decode_mode, bsd, xpos, ypos, zpos, tempblocks + j, temp);
|
||||
decompress_symbolic_block(decode_mode, bsd, xpos, ypos, zpos, tempblocks + j, temp);
|
||||
float errorval = compute_imageblock_difference(bsd, blk, temp, ewb) * errorval_mult[i];
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("\n-----------------------------------\n");
|
||||
printf("Single-weight partition test 0 (1 partition) completed\n");
|
||||
printf("Resulting error value: %g\n", errorval);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (errorval < best_errorval_in_mode)
|
||||
best_errorval_in_mode = errorval;
|
||||
|
||||
if (errorval < error_of_best_block)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Accepted as better than previous-best-error, which was %g\n", error_of_best_block);
|
||||
#endif
|
||||
|
||||
error_of_best_block = errorval;
|
||||
*scb = tempblocks[j];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("-----------------------------------\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
best_errorvals_in_modes[0] = best_errorval_in_mode;
|
||||
@@ -1331,7 +1233,7 @@ float compress_symbolic_block(
|
||||
if (!uses_alpha && i == 3)
|
||||
continue;
|
||||
|
||||
compress_symbolic_block_fixed_partition_2_planes(input_image, decode_mode, mode_cutoff, ewp->max_refinement_iters,
|
||||
compress_symbolic_block_fixed_partition_2_planes(decode_mode, mode_cutoff, ewp->max_refinement_iters,
|
||||
bsd, 1, // partition count
|
||||
0, // partition index
|
||||
i, // the color component to test a separate plane of weights for.
|
||||
@@ -1342,39 +1244,18 @@ float compress_symbolic_block(
|
||||
{
|
||||
if (tempblocks[j].error_block)
|
||||
continue;
|
||||
decompress_symbolic_block(input_image, decode_mode, bsd, xpos, ypos, zpos, tempblocks + j, temp);
|
||||
decompress_symbolic_block(decode_mode, bsd, xpos, ypos, zpos, tempblocks + j, temp);
|
||||
float errorval = compute_imageblock_difference(bsd, blk, temp, ewb);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("\n-----------------------------------\n");
|
||||
printf("Dual-weight partition test %d (1 partition) completed\n", i);
|
||||
printf("Resulting error value: %g\n", errorval);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (errorval < best_errorval_in_mode)
|
||||
best_errorval_in_mode = errorval;
|
||||
|
||||
if (errorval < error_of_best_block)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Accepted as better than previous-best-error, which was %g\n", error_of_best_block);
|
||||
#endif
|
||||
|
||||
error_of_best_block = errorval;
|
||||
*scb = tempblocks[j];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("-----------------------------------\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
best_errorvals_in_modes[i + 1] = best_errorval_in_mode;
|
||||
}
|
||||
|
||||
@@ -1395,7 +1276,7 @@ float compress_symbolic_block(
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
compress_symbolic_block_fixed_partition_1_plane(input_image, decode_mode, mode_cutoff, ewp->max_refinement_iters,
|
||||
compress_symbolic_block_fixed_partition_1_plane(decode_mode, mode_cutoff, ewp->max_refinement_iters,
|
||||
bsd, partition_count, partition_indices_1plane[i], blk, ewb, tempblocks, tmpbuf->plane1);
|
||||
|
||||
best_errorval_in_mode = 1e30f;
|
||||
@@ -1403,28 +1284,14 @@ float compress_symbolic_block(
|
||||
{
|
||||
if (tempblocks[j].error_block)
|
||||
continue;
|
||||
decompress_symbolic_block(input_image, decode_mode, bsd, xpos, ypos, zpos, tempblocks + j, temp);
|
||||
decompress_symbolic_block(decode_mode, bsd, xpos, ypos, zpos, tempblocks + j, temp);
|
||||
float errorval = compute_imageblock_difference(bsd, blk, temp, ewb);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("\n-----------------------------------\n");
|
||||
printf("Single-weight partition test %d (%d partitions) completed\n", i, partition_count);
|
||||
printf("Resulting error value: %g\n", errorval);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (errorval < best_errorval_in_mode)
|
||||
best_errorval_in_mode = errorval;
|
||||
|
||||
if (errorval < error_of_best_block)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Accepted as better than previous-best-error, which was %g\n", error_of_best_block);
|
||||
#endif
|
||||
|
||||
error_of_best_block = errorval;
|
||||
*scb = tempblocks[j];
|
||||
}
|
||||
@@ -1432,18 +1299,10 @@ float compress_symbolic_block(
|
||||
|
||||
best_errorvals_in_modes[4 * (partition_count - 2) + 5 + i] = best_errorval_in_mode;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("-----------------------------------\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((error_of_best_block / error_weight_sum) < ewp->texel_avg_error_limit)
|
||||
goto END_OF_TESTS;
|
||||
}
|
||||
|
||||
|
||||
if (partition_count == 2 && !is_normal_map && MIN(best_errorvals_in_modes[5], best_errorvals_in_modes[6]) > (best_errorvals_in_modes[0] * ewp->partition_1_to_2_limit))
|
||||
goto END_OF_TESTS;
|
||||
|
||||
@@ -1455,7 +1314,7 @@ float compress_symbolic_block(
|
||||
{
|
||||
if (lowest_correl > ewp->lowest_correlation_cutoff)
|
||||
continue;
|
||||
compress_symbolic_block_fixed_partition_2_planes(input_image, decode_mode,
|
||||
compress_symbolic_block_fixed_partition_2_planes(decode_mode,
|
||||
mode_cutoff,
|
||||
ewp->max_refinement_iters,
|
||||
bsd,
|
||||
@@ -1468,29 +1327,16 @@ float compress_symbolic_block(
|
||||
{
|
||||
if (tempblocks[j].error_block)
|
||||
continue;
|
||||
decompress_symbolic_block(input_image, decode_mode, bsd, xpos, ypos, zpos, tempblocks + j, temp);
|
||||
|
||||
decompress_symbolic_block(decode_mode, bsd, xpos, ypos, zpos, tempblocks + j, temp);
|
||||
|
||||
float errorval = compute_imageblock_difference(bsd, blk, temp, ewb);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("\n-----------------------------------\n");
|
||||
printf("Dual-weight partition test %d (%d partitions) completed\n", i, partition_count);
|
||||
printf("Resulting error value: %g\n", errorval);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (errorval < best_errorval_in_mode)
|
||||
best_errorval_in_mode = errorval;
|
||||
|
||||
if (errorval < error_of_best_block)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Accepted as better than previous-best-error, which was %g\n", error_of_best_block);
|
||||
#endif
|
||||
|
||||
error_of_best_block = errorval;
|
||||
*scb = tempblocks[j];
|
||||
}
|
||||
@@ -1498,28 +1344,12 @@ float compress_symbolic_block(
|
||||
|
||||
best_errorvals_in_modes[4 * (partition_count - 2) + 5 + 2 + i] = best_errorval_in_mode;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("-----------------------------------\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((error_of_best_block / error_weight_sum) < ewp->texel_avg_error_limit)
|
||||
goto END_OF_TESTS;
|
||||
}
|
||||
}
|
||||
|
||||
END_OF_TESTS:
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (scb->block_mode >= 0)
|
||||
block_mode_histogram[scb->block_mode & 0x7ff]++;
|
||||
|
||||
if (print_tile_errors)
|
||||
printf("%g\n", (double)error_of_best_block);
|
||||
#endif
|
||||
|
||||
// compress/decompress to a physical block
|
||||
physical_compressed_block psb = symbolic_to_physical(bsd, scb);
|
||||
physical_to_symbolic(bsd, psb, scb);
|
||||
@@ -28,7 +28,7 @@
|
||||
* stability allowing us to use floats rather than doubles.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
#include <cassert>
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ struct pixel_region_variance_args
|
||||
/** The RGB data should be treated as sRGB. */
|
||||
int need_srgb_transform;
|
||||
/** The channel swizzle pattern. */
|
||||
swizzlepattern swz;
|
||||
astcenc_swizzle swz;
|
||||
/** Should the algorithm bother with Z axis processing? */
|
||||
int have_z;
|
||||
/** The kernel radius for average and variance. */
|
||||
@@ -162,7 +162,7 @@ static void compute_pixel_region_variance(
|
||||
float rgb_power = arg->rgb_power;
|
||||
float alpha_power = arg->alpha_power;
|
||||
int need_srgb_transform = arg->need_srgb_transform;
|
||||
swizzlepattern swz = arg->swz;
|
||||
astcenc_swizzle swz = arg->swz;
|
||||
int have_z = arg->have_z;
|
||||
|
||||
int size_x = arg->size.x;
|
||||
@@ -219,8 +219,8 @@ static void compute_pixel_region_variance(
|
||||
{
|
||||
// Swizzle data structure 4 = ZERO, 5 = ONE
|
||||
uint8_t data[6];
|
||||
data[4] = 0;
|
||||
data[5] = 255;
|
||||
data[ASTCENC_SWZ_0] = 0;
|
||||
data[ASTCENC_SWZ_1] = 255;
|
||||
|
||||
for (int z = zd_start; z < padsize_z; z++)
|
||||
{
|
||||
@@ -271,8 +271,8 @@ static void compute_pixel_region_variance(
|
||||
{
|
||||
// Swizzle data structure 4 = ZERO, 5 = ONE (in FP16)
|
||||
uint16_t data[6];
|
||||
data[4] = 0;
|
||||
data[5] = 0x3C00;
|
||||
data[ASTCENC_SWZ_0] = 0;
|
||||
data[ASTCENC_SWZ_1] = 0x3C00;
|
||||
|
||||
for (int z = zd_start; z < padsize_z; z++)
|
||||
{
|
||||
@@ -603,7 +603,7 @@ void compute_averages_and_variances(
|
||||
int avg_var_kernel_radius,
|
||||
int alpha_kernel_radius,
|
||||
int need_srgb_transform,
|
||||
swizzlepattern swz,
|
||||
astcenc_swizzle swz,
|
||||
int thread_count
|
||||
) {
|
||||
int size_x = img->xsize;
|
||||
@@ -612,9 +612,9 @@ void compute_averages_and_variances(
|
||||
int pixel_count = size_x * size_y * size_z;
|
||||
|
||||
// Perform memory allocations for the destination buffers
|
||||
if (img->input_averages) delete[] img->input_averages;
|
||||
if (img->input_variances) delete[] img->input_variances;
|
||||
if (img->input_alpha_averages) delete[] img->input_alpha_averages;
|
||||
delete[] img->input_averages;
|
||||
delete[] img->input_variances;
|
||||
delete[] img->input_alpha_averages;
|
||||
|
||||
img->input_averages = new float4[pixel_count];
|
||||
img->input_variances = new float4[pixel_count];
|
||||
@@ -19,7 +19,7 @@
|
||||
* @brief Functions to decompress a symbolic block.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -39,7 +39,7 @@ static int compute_value_of_texel_int(
|
||||
}
|
||||
|
||||
static uint4 lerp_color_int(
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
uint4 color0,
|
||||
uint4 color1,
|
||||
int weight,
|
||||
@@ -54,7 +54,7 @@ static uint4 lerp_color_int(
|
||||
|
||||
uint4 weight0 = uint4(64, 64, 64, 64) - weight1;
|
||||
|
||||
if (decode_mode == DECODE_LDR_SRGB)
|
||||
if (decode_mode == ASTCENC_PRF_LDR_SRGB)
|
||||
{
|
||||
color0 = uint4(color0.x >> 8, color0.y >> 8, color0.z >> 8, color0.w >> 8);
|
||||
color1 = uint4(color1.x >> 8, color1.y >> 8, color1.z >> 8, color1.w >> 8);
|
||||
@@ -63,7 +63,7 @@ static uint4 lerp_color_int(
|
||||
uint4 color = (color0 * weight0) + (color1 * weight1) + uint4(32, 32, 32, 32);
|
||||
color = uint4(color.x >> 6, color.y >> 6, color.z >> 6, color.w >> 6);
|
||||
|
||||
if (decode_mode == DECODE_LDR_SRGB)
|
||||
if (decode_mode == ASTCENC_PRF_LDR_SRGB)
|
||||
{
|
||||
color = color * 257;
|
||||
}
|
||||
@@ -72,8 +72,7 @@ static uint4 lerp_color_int(
|
||||
}
|
||||
|
||||
void decompress_symbolic_block(
|
||||
const astc_codec_image* image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
const block_size_descriptor* bsd,
|
||||
int xpos,
|
||||
int ypos,
|
||||
@@ -90,7 +89,7 @@ void decompress_symbolic_block(
|
||||
// if we detected an error-block, blow up immediately.
|
||||
if (scb->error_block)
|
||||
{
|
||||
if (decode_mode == DECODE_LDR_SRGB)
|
||||
if (decode_mode == ASTCENC_PRF_LDR_SRGB)
|
||||
{
|
||||
for (i = 0; i < bsd->texel_count; i++)
|
||||
{
|
||||
@@ -138,7 +137,7 @@ void decompress_symbolic_block(
|
||||
// For sRGB decoding a real decoder would just use the top 8 bits
|
||||
// for color conversion. We don't color convert, so linearly scale
|
||||
// the top 8 bits into the full 16 bit dynamic range
|
||||
if (decode_mode == DECODE_LDR_SRGB)
|
||||
if (decode_mode == ASTCENC_PRF_LDR_SRGB)
|
||||
{
|
||||
ired = (ired >> 8) * 257;
|
||||
igreen = (igreen >> 8) * 257;
|
||||
@@ -157,7 +156,7 @@ void decompress_symbolic_block(
|
||||
{
|
||||
switch (decode_mode)
|
||||
{
|
||||
case DECODE_LDR_SRGB:
|
||||
case ASTCENC_PRF_LDR_SRGB:
|
||||
red = 1.0f;
|
||||
green = 0.0f;
|
||||
blue = 1.0f;
|
||||
@@ -165,7 +164,7 @@ void decompress_symbolic_block(
|
||||
use_lns = 0;
|
||||
use_nan = 0;
|
||||
break;
|
||||
case DECODE_LDR:
|
||||
case ASTCENC_PRF_LDR:
|
||||
red = 0.0f;
|
||||
green = 0.0f;
|
||||
blue = 0.0f;
|
||||
@@ -173,8 +172,8 @@ void decompress_symbolic_block(
|
||||
use_lns = 0;
|
||||
use_nan = 1;
|
||||
break;
|
||||
case DECODE_HDR:
|
||||
case DECODE_HDRA:
|
||||
case ASTCENC_PRF_HDR_RGB_LDR_A:
|
||||
case ASTCENC_PRF_HDR:
|
||||
// constant-color block; unpack from FP16 to FP32.
|
||||
red = sf16_to_float(scb->constant_color[0]);
|
||||
green = sf16_to_float(scb->constant_color[1]);
|
||||
@@ -225,8 +224,7 @@ void decompress_symbolic_block(
|
||||
|
||||
for (i = 0; i < partition_count; i++)
|
||||
{
|
||||
unpack_color_endpoints(image,
|
||||
decode_mode,
|
||||
unpack_color_endpoints(decode_mode,
|
||||
scb->color_formats[i],
|
||||
scb->color_quantization_level,
|
||||
scb->color_values[i],
|
||||
@@ -37,11 +37,7 @@
|
||||
* the quantization step.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
// helper function to merge two endpoint-colors
|
||||
void merge_endpoints(
|
||||
@@ -115,13 +111,6 @@ void compute_encoding_choice_errors(
|
||||
|
||||
int texels_per_block = bsd->texel_count;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s : texels-per-block=%dx%dx%d, separate_component=%d, partition-count=%d\n", __func__, bsd->xdim, bsd->ydim, bsd->zdim, separate_component, partition_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
float3 averages[4];
|
||||
float3 directions_rgb[4];
|
||||
float4 error_weightings[4];
|
||||
@@ -169,17 +158,6 @@ void compute_encoding_choice_errors(
|
||||
luminance_lines[i].a = float3(0.0f, 0.0f, 0.0f);
|
||||
luminance_lines[i].b = normalize(csf);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("Partition %d\n", i);
|
||||
printf("Average = <%g %g %g>\n", averages[i].x, averages[i].y, averages[i].z);
|
||||
printf("Uncorr-rgb-line = <%g %g %g> + t<%g %g %g>\n",
|
||||
uncorr_rgb_lines[i].a.x, uncorr_rgb_lines[i].a.y, uncorr_rgb_lines[i].a.z, uncorr_rgb_lines[i].b.x, uncorr_rgb_lines[i].b.y, uncorr_rgb_lines[i].b.z);
|
||||
printf("Samechroma-line = t<%g %g %g>\n", samechroma_rgb_lines[i].b.x, samechroma_rgb_lines[i].b.y, samechroma_rgb_lines[i].b.z);
|
||||
}
|
||||
#endif
|
||||
|
||||
proc_uncorr_rgb_lines[i].amod = (uncorr_rgb_lines[i].a - uncorr_rgb_lines[i].b * dot(uncorr_rgb_lines[i].a, uncorr_rgb_lines[i].b)) * icsf;
|
||||
proc_uncorr_rgb_lines[i].bs = uncorr_rgb_lines[i].b * csf;
|
||||
proc_uncorr_rgb_lines[i].bis = uncorr_rgb_lines[i].b * icsf;
|
||||
@@ -211,14 +189,6 @@ void compute_encoding_choice_errors(
|
||||
rgb_luma_error[i] = compute_error_squared_rgb_single_partition(i, bsd, pi, pb, ewb, &(proc_rgb_luma_lines[i]));
|
||||
|
||||
luminance_rgb_error[i] = compute_error_squared_rgb_single_partition(i, bsd, pi, pb, ewb, &(proc_luminance_lines[i]));
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("Partition %d : uncorr-error=%g samechroma-error=%g rgb-luma-error=%g lum-error=%g\n",
|
||||
i, uncorr_rgb_error[i], samechroma_rgb_error[i], rgb_luma_error[i], luminance_rgb_error[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// compute the error that arises from just ditching alpha and RGB
|
||||
@@ -0,0 +1,823 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2020 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Functions for the library entrypoint.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
#include "astcenc.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
// The ASTC codec is written with the assumption that a float threaded through
|
||||
// the "if32" union will in fact be stored and reloaded as a 32-bit IEEE-754 single-precision
|
||||
// float, stored with round-to-nearest rounding. This is always the case in an
|
||||
// IEEE-754 compliant system, however not every system is actually IEEE-754 compliant
|
||||
// in the first place. As such, we run a quick test to check that this is actually the case
|
||||
// (e.g. gcc on 32-bit x86 will typically fail unless -msse2 -mfpmath=sse2 is specified).
|
||||
static astcenc_error validate_cpu_float()
|
||||
{
|
||||
if32 p;
|
||||
volatile float xprec_testval = 2.51f;
|
||||
p.f = xprec_testval + 12582912.0f;
|
||||
float q = p.f - 12582912.0f;
|
||||
|
||||
if (q != 3.0f)
|
||||
{
|
||||
return ASTCENC_ERR_BAD_CPU_FLOAT;
|
||||
}
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
static astcenc_error validate_cpu_isa()
|
||||
{
|
||||
#if ASTCENC_SSE >= 42
|
||||
if (!cpu_supports_sse42())
|
||||
{
|
||||
return ASTCENC_ERR_BAD_CPU_ISA;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASTCENC_POPCNT >= 1
|
||||
if (!cpu_supports_popcnt())
|
||||
{
|
||||
return ASTCENC_ERR_BAD_CPU_ISA;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASTCENC_AVX >= 2
|
||||
if (!cpu_supports_avx2())
|
||||
{
|
||||
return ASTCENC_ERR_BAD_CPU_ISA;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
static astcenc_error validate_profile(
|
||||
astcenc_profile profile
|
||||
) {
|
||||
switch(profile)
|
||||
{
|
||||
case ASTCENC_PRF_LDR_SRGB:
|
||||
case ASTCENC_PRF_LDR:
|
||||
case ASTCENC_PRF_HDR_RGB_LDR_A:
|
||||
case ASTCENC_PRF_HDR:
|
||||
return ASTCENC_SUCCESS;
|
||||
default:
|
||||
return ASTCENC_ERR_BAD_PROFILE;
|
||||
}
|
||||
}
|
||||
|
||||
static astcenc_error validate_block_size(
|
||||
unsigned int block_x,
|
||||
unsigned int block_y,
|
||||
unsigned int block_z
|
||||
) {
|
||||
if (((block_z <= 1) && is_legal_2d_block_size(block_x, block_y)) ||
|
||||
((block_z >= 2) && is_legal_3d_block_size(block_x, block_y, block_z)))
|
||||
{
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
return ASTCENC_ERR_BAD_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static astcenc_error validate_flags(
|
||||
unsigned int flags
|
||||
) {
|
||||
// Flags field must not contain any unknown flag bits
|
||||
unsigned int exMask = ~ASTCENC_ALL_FLAGS;
|
||||
if (astc::popcount(flags & exMask) != 0)
|
||||
{
|
||||
return ASTCENC_ERR_BAD_FLAGS;
|
||||
}
|
||||
|
||||
// Flags field must only contain at most a single map type
|
||||
exMask = ASTCENC_FLG_MAP_MASK | ASTCENC_FLG_MAP_NORMAL;
|
||||
if (astc::popcount(flags & exMask) > 1)
|
||||
{
|
||||
return ASTCENC_ERR_BAD_FLAGS;
|
||||
}
|
||||
|
||||
// TODO: We don't support user threads yet
|
||||
if (flags & ASTCENC_FLG_USE_USER_THREADS)
|
||||
{
|
||||
return ASTCENC_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
static astcenc_error validate_compression_swz(
|
||||
astcenc_swz swizzle
|
||||
) {
|
||||
switch(swizzle)
|
||||
{
|
||||
case ASTCENC_SWZ_R:
|
||||
case ASTCENC_SWZ_G:
|
||||
case ASTCENC_SWZ_B:
|
||||
case ASTCENC_SWZ_A:
|
||||
case ASTCENC_SWZ_0:
|
||||
case ASTCENC_SWZ_1:
|
||||
return ASTCENC_SUCCESS;
|
||||
default:
|
||||
return ASTCENC_ERR_BAD_SWIZZLE;
|
||||
}
|
||||
}
|
||||
|
||||
static astcenc_error validate_compression_swizzle(
|
||||
astcenc_swizzle swizzle
|
||||
) {
|
||||
if (validate_compression_swz(swizzle.r) ||
|
||||
validate_compression_swz(swizzle.g) ||
|
||||
validate_compression_swz(swizzle.b) ||
|
||||
validate_compression_swz(swizzle.a))
|
||||
{
|
||||
return ASTCENC_ERR_BAD_SWIZZLE;
|
||||
}
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
static astcenc_error validate_decompression_swz(
|
||||
astcenc_swz swizzle
|
||||
) {
|
||||
switch(swizzle)
|
||||
{
|
||||
case ASTCENC_SWZ_R:
|
||||
case ASTCENC_SWZ_G:
|
||||
case ASTCENC_SWZ_B:
|
||||
case ASTCENC_SWZ_A:
|
||||
case ASTCENC_SWZ_0:
|
||||
case ASTCENC_SWZ_1:
|
||||
case ASTCENC_SWZ_Z:
|
||||
return ASTCENC_SUCCESS;
|
||||
default:
|
||||
return ASTCENC_ERR_BAD_SWIZZLE;
|
||||
}
|
||||
}
|
||||
|
||||
static astcenc_error validate_decompression_swizzle(
|
||||
astcenc_swizzle swizzle
|
||||
) {
|
||||
if (validate_decompression_swz(swizzle.r) ||
|
||||
validate_decompression_swz(swizzle.g) ||
|
||||
validate_decompression_swz(swizzle.b) ||
|
||||
validate_decompression_swz(swizzle.a))
|
||||
{
|
||||
return ASTCENC_ERR_BAD_SWIZZLE;
|
||||
}
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an incoming configuration is in-spec.
|
||||
*
|
||||
* This function can respond in two ways:
|
||||
*
|
||||
* * Numerical inputs that have valid ranges are clamped to those valid
|
||||
* ranges. No error is thrown for out-of-range inputs in this case.
|
||||
* * Numerical inputs and logic inputs are are logically invalid and which
|
||||
* make no sense algorithmically will return an error.
|
||||
*/
|
||||
static astcenc_error validate_config(
|
||||
astcenc_config &config
|
||||
) {
|
||||
astcenc_error status;
|
||||
|
||||
status = validate_profile(config.profile);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = validate_flags(config.flags);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = validate_block_size(config.block_x, config.block_y, config.block_z);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
config.v_rgba_mean_stdev_mix = MAX(config.v_rgba_mean_stdev_mix, 0.0f);
|
||||
config.v_rgb_power = MAX(config.v_rgb_power, 0.0f);
|
||||
config.v_rgb_base = MAX(config.v_rgb_base, 0.0f);
|
||||
config.v_rgb_mean = MAX(config.v_rgb_mean, 0.0f);
|
||||
config.v_rgb_stdev = MAX(config.v_rgb_stdev, 0.0f);
|
||||
config.v_a_power = MAX(config.v_a_power, 0.0f);
|
||||
config.v_a_base = MAX(config.v_a_base, 0.0f);
|
||||
config.v_a_mean = MAX(config.v_a_mean, 0.0f);
|
||||
config.v_a_stdev = MAX(config.v_a_stdev, 0.0f);
|
||||
|
||||
config.b_deblock_weight = MAX(config.b_deblock_weight, 0.0f);
|
||||
|
||||
config.tune_partition_limit = astc::clampi(config.tune_partition_limit, 1, PARTITION_COUNT);
|
||||
config.tune_block_mode_limit = astc::clampi(config.tune_block_mode_limit, 1, 100);
|
||||
config.tune_refinement_limit = MAX(config.tune_refinement_limit, 1);
|
||||
config.tune_db_limit = MAX(config.tune_db_limit, 0.0f);
|
||||
config.tune_partition_early_out_limit = MAX(config.tune_partition_early_out_limit, 0.0f);
|
||||
config.tune_two_plane_early_out_limit = MAX(config.tune_two_plane_early_out_limit, 0.0f);
|
||||
|
||||
// Specifying a zero weight color component is not allowed; force to small value
|
||||
float max_weight = MAX(MAX(config.cw_r_weight, config.cw_g_weight),
|
||||
MAX(config.cw_b_weight, config.cw_a_weight));
|
||||
if (max_weight > 0.0f)
|
||||
{
|
||||
max_weight /= 1000.0f;
|
||||
config.cw_r_weight = MAX(config.cw_r_weight, max_weight);
|
||||
config.cw_g_weight = MAX(config.cw_g_weight, max_weight);
|
||||
config.cw_b_weight = MAX(config.cw_b_weight, max_weight);
|
||||
config.cw_a_weight = MAX(config.cw_a_weight, max_weight);
|
||||
}
|
||||
// If all color components error weights are zero then return an error
|
||||
else
|
||||
{
|
||||
return ASTCENC_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
astcenc_error astcenc_init_config(
|
||||
astcenc_profile profile,
|
||||
unsigned int block_x,
|
||||
unsigned int block_y,
|
||||
unsigned int block_z,
|
||||
astcenc_preset preset,
|
||||
unsigned int flags,
|
||||
astcenc_config& config
|
||||
) {
|
||||
astcenc_error status;
|
||||
|
||||
// Zero init all config fields; although most of will be over written
|
||||
std::memset(&config, 0, sizeof(config));
|
||||
|
||||
// Process the block size
|
||||
block_z = MAX(block_z, 1); // For 2D blocks Z==0 is accepted, but convert to 1
|
||||
status = validate_block_size(block_x, block_y, block_z);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
config.block_x = block_x;
|
||||
config.block_y = block_y;
|
||||
config.block_z = block_z;
|
||||
|
||||
float texels = static_cast<float>(block_x * block_y * block_z);
|
||||
float ltexels = logf(texels) / logf(10.0f);
|
||||
|
||||
// Process the performance preset; note that this must be done before we
|
||||
// process any additional settings, such as color profile and flags, which
|
||||
// may replace some of these settings with more use case tuned values
|
||||
switch(preset)
|
||||
{
|
||||
case ASTCENC_PRE_FAST:
|
||||
config.tune_partition_limit = 4;
|
||||
config.tune_block_mode_limit = 50;
|
||||
config.tune_refinement_limit = 1;
|
||||
config.tune_db_limit = MAX(85 - 35 * ltexels, 63 - 19 * ltexels);
|
||||
config.tune_partition_early_out_limit = 1.0f;
|
||||
config.tune_two_plane_early_out_limit = 0.5f;
|
||||
break;
|
||||
case ASTCENC_PRE_MEDIUM:
|
||||
config.tune_partition_limit = 25;
|
||||
config.tune_block_mode_limit = 75;
|
||||
config.tune_refinement_limit = 2;
|
||||
config.tune_db_limit = MAX(95 - 35 * ltexels, 70 - 19 * ltexels);
|
||||
config.tune_partition_early_out_limit = 1.2f;
|
||||
config.tune_two_plane_early_out_limit = 0.75f;
|
||||
break;
|
||||
case ASTCENC_PRE_THOROUGH:
|
||||
config.tune_partition_limit = 100;
|
||||
config.tune_block_mode_limit = 95;
|
||||
config.tune_refinement_limit = 4;
|
||||
config.tune_db_limit = MAX(105 - 35 * ltexels, 77 - 19 * ltexels);
|
||||
config.tune_partition_early_out_limit = 2.5f;
|
||||
config.tune_two_plane_early_out_limit = 0.95f;
|
||||
break;
|
||||
case ASTCENC_PRE_EXHAUSTIVE:
|
||||
config.tune_partition_limit = 1024;
|
||||
config.tune_block_mode_limit = 100;
|
||||
config.tune_refinement_limit = 4;
|
||||
config.tune_db_limit = 999.0f;
|
||||
config.tune_partition_early_out_limit = 1000.0f;
|
||||
config.tune_two_plane_early_out_limit = 0.99f;
|
||||
break;
|
||||
default:
|
||||
return ASTCENC_ERR_BAD_PRESET;
|
||||
}
|
||||
|
||||
// Set heuristics to the defaults for each color profile
|
||||
config.v_rgba_radius = 0;
|
||||
config.v_rgba_mean_stdev_mix = 0.0f;
|
||||
|
||||
config.cw_r_weight = 1.0f;
|
||||
config.cw_g_weight = 1.0f;
|
||||
config.cw_b_weight = 1.0f;
|
||||
config.cw_a_weight = 1.0f;
|
||||
|
||||
config.a_scale_radius = 0;
|
||||
|
||||
config.b_deblock_weight = 0.0f;
|
||||
|
||||
config.profile = profile;
|
||||
switch(profile)
|
||||
{
|
||||
case ASTCENC_PRF_LDR:
|
||||
case ASTCENC_PRF_LDR_SRGB:
|
||||
config.v_rgb_power = 1.0f;
|
||||
config.v_rgb_base = 1.0f;
|
||||
config.v_rgb_mean = 0.0f;
|
||||
config.v_rgb_stdev = 0.0f;
|
||||
|
||||
config.v_a_power = 1.0f;
|
||||
config.v_a_base = 1.0f;
|
||||
config.v_a_mean = 0.0f;
|
||||
config.v_a_stdev = 0.0f;
|
||||
break;
|
||||
case ASTCENC_PRF_HDR_RGB_LDR_A:
|
||||
config.v_rgb_power = 0.75f;
|
||||
config.v_rgb_base = 0.0f;
|
||||
config.v_rgb_mean = 1.0f;
|
||||
config.v_rgb_stdev = 0.0f;
|
||||
|
||||
config.v_a_power = 1.0f;
|
||||
config.v_a_base = 0.05f;
|
||||
config.v_a_mean = 0.0f;
|
||||
config.v_a_stdev = 0.0f;
|
||||
|
||||
config.tune_db_limit = 999.0f;
|
||||
break;
|
||||
case ASTCENC_PRF_HDR:
|
||||
config.v_rgb_power = 0.75f;
|
||||
config.v_rgb_base = 0.0f;
|
||||
config.v_rgb_mean = 1.0f;
|
||||
config.v_rgb_stdev = 0.0f;
|
||||
|
||||
config.v_a_power = 0.75f;
|
||||
config.v_a_base = 0.0f;
|
||||
config.v_a_mean = 1.0f;
|
||||
config.v_a_stdev = 0.0f;
|
||||
|
||||
config.tune_db_limit = 999.0f;
|
||||
break;
|
||||
default:
|
||||
return ASTCENC_ERR_BAD_PROFILE;
|
||||
}
|
||||
|
||||
// Flags field must not contain any unknown flag bits
|
||||
status = validate_flags(flags);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (flags & ASTCENC_FLG_MAP_NORMAL)
|
||||
{
|
||||
config.cw_r_weight = 1.0f;
|
||||
config.cw_g_weight = 0.0f;
|
||||
config.cw_b_weight = 0.0f;
|
||||
config.cw_a_weight = 1.0f;
|
||||
config.tune_partition_early_out_limit = 1000.0f;
|
||||
config.tune_two_plane_early_out_limit = 0.99f;
|
||||
|
||||
if (flags & ASTCENC_FLG_USE_PERCEPTUAL)
|
||||
{
|
||||
config.b_deblock_weight = 1.8f;
|
||||
config.v_rgba_radius = 3;
|
||||
config.v_rgba_mean_stdev_mix = 0.0f;
|
||||
config.v_rgb_mean = 0.0f;
|
||||
config.v_rgb_stdev = 50.0f;
|
||||
config.v_a_mean = 0.0f;
|
||||
config.v_a_stdev = 50.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & ASTCENC_FLG_MAP_MASK)
|
||||
{
|
||||
config.v_rgba_radius = 3;
|
||||
config.v_rgba_mean_stdev_mix = 0.03f;
|
||||
config.v_rgb_mean = 0.0f;
|
||||
config.v_rgb_stdev = 25.0f;
|
||||
config.v_a_mean = 0.0f;
|
||||
config.v_a_stdev = 25.0f;
|
||||
}
|
||||
|
||||
// TODO: We don't support user threads yet
|
||||
if (flags & ASTCENC_FLG_USE_USER_THREADS)
|
||||
{
|
||||
return ASTCENC_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
config.flags = flags;
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
astcenc_error astcenc_context_alloc(
|
||||
astcenc_config const& config,
|
||||
unsigned int thread_count,
|
||||
astcenc_context** context
|
||||
) {
|
||||
astcenc_error status;
|
||||
astcenc_context* ctx = nullptr;
|
||||
block_size_descriptor* bsd = nullptr;
|
||||
|
||||
status = validate_cpu_float();
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = validate_cpu_isa();
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (thread_count == 0)
|
||||
{
|
||||
thread_count = get_cpu_count();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ctx = new astcenc_context;
|
||||
ctx->thread_count = thread_count;
|
||||
ctx->config = config;
|
||||
|
||||
// Copy the config first and validate the copy (may modify it)
|
||||
status = validate_config(ctx->config);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
delete ctx;
|
||||
return status;
|
||||
}
|
||||
|
||||
bsd = new block_size_descriptor;
|
||||
init_block_size_descriptor(config.block_x, config.block_y, config.block_z, bsd);
|
||||
ctx->bsd = bsd;
|
||||
}
|
||||
catch(const std::bad_alloc&)
|
||||
{
|
||||
term_block_size_descriptor(bsd);
|
||||
delete bsd;
|
||||
delete ctx;
|
||||
*context = nullptr;
|
||||
return ASTCENC_ERR_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
*context = ctx;
|
||||
|
||||
// TODO: Currently static memory; should move to context memory
|
||||
prepare_angular_tables();
|
||||
build_quantization_mode_table();
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
void astcenc_context_free(
|
||||
astcenc_context* context
|
||||
) {
|
||||
if (context)
|
||||
{
|
||||
term_block_size_descriptor(context->bsd);
|
||||
delete context->bsd;
|
||||
delete context;
|
||||
}
|
||||
}
|
||||
|
||||
struct compress_astc_image_info
|
||||
{
|
||||
const block_size_descriptor* bsd;
|
||||
const error_weighting_params* ewp;
|
||||
uint8_t* buffer;
|
||||
int threadcount;
|
||||
astcenc_profile decode_mode;
|
||||
astcenc_swizzle swz_encode;
|
||||
const astc_codec_image* input_image;
|
||||
};
|
||||
|
||||
static void encode_astc_image_threadfunc(
|
||||
int thread_count,
|
||||
int thread_id,
|
||||
void* vblk
|
||||
) {
|
||||
const compress_astc_image_info *blk = (const compress_astc_image_info *)vblk;
|
||||
const block_size_descriptor *bsd = blk->bsd;
|
||||
int xdim = bsd->xdim;
|
||||
int ydim = bsd->ydim;
|
||||
int zdim = bsd->zdim;
|
||||
uint8_t *buffer = blk->buffer;
|
||||
const error_weighting_params *ewp = blk->ewp;
|
||||
astcenc_profile decode_mode = blk->decode_mode;
|
||||
astcenc_swizzle swz_encode = blk->swz_encode;
|
||||
const astc_codec_image *input_image = blk->input_image;
|
||||
|
||||
imageblock pb;
|
||||
int ctr = thread_id;
|
||||
|
||||
int x, y, z;
|
||||
int xsize = input_image->xsize;
|
||||
int ysize = input_image->ysize;
|
||||
int zsize = input_image->zsize;
|
||||
int xblocks = (xsize + xdim - 1) / xdim;
|
||||
int yblocks = (ysize + ydim - 1) / ydim;
|
||||
int zblocks = (zsize + zdim - 1) / zdim;
|
||||
|
||||
//allocate memory for temporary buffers
|
||||
compress_symbolic_block_buffers temp_buffers;
|
||||
temp_buffers.ewb = new error_weight_block;
|
||||
temp_buffers.ewbo = new error_weight_block_orig;
|
||||
temp_buffers.tempblocks = new symbolic_compressed_block[4];
|
||||
temp_buffers.temp = new imageblock;
|
||||
temp_buffers.planes2 = new compress_fixed_partition_buffers;
|
||||
temp_buffers.planes2->ei1 = new endpoints_and_weights;
|
||||
temp_buffers.planes2->ei2 = new endpoints_and_weights;
|
||||
temp_buffers.planes2->eix1 = new endpoints_and_weights[MAX_DECIMATION_MODES];
|
||||
temp_buffers.planes2->eix2 = new endpoints_and_weights[MAX_DECIMATION_MODES];
|
||||
temp_buffers.planes2->decimated_quantized_weights = new float[2 * MAX_DECIMATION_MODES * MAX_WEIGHTS_PER_BLOCK];
|
||||
temp_buffers.planes2->decimated_weights = new float[2 * MAX_DECIMATION_MODES * MAX_WEIGHTS_PER_BLOCK];
|
||||
temp_buffers.planes2->flt_quantized_decimated_quantized_weights = new float[2 * MAX_WEIGHT_MODES * MAX_WEIGHTS_PER_BLOCK];
|
||||
temp_buffers.planes2->u8_quantized_decimated_quantized_weights = new uint8_t[2 * MAX_WEIGHT_MODES * MAX_WEIGHTS_PER_BLOCK];
|
||||
temp_buffers.plane1 = temp_buffers.planes2;
|
||||
|
||||
for (z = 0; z < zblocks; z++)
|
||||
{
|
||||
for (y = 0; y < yblocks; y++)
|
||||
{
|
||||
for (x = 0; x < xblocks; x++)
|
||||
{
|
||||
if (ctr == 0)
|
||||
{
|
||||
int offset = ((z * yblocks + y) * xblocks + x) * 16;
|
||||
uint8_t *bp = buffer + offset;
|
||||
fetch_imageblock(decode_mode, input_image, &pb, bsd, x * xdim, y * ydim, z * zdim, swz_encode);
|
||||
symbolic_compressed_block scb;
|
||||
compress_symbolic_block(input_image, decode_mode, bsd, ewp, &pb, &scb, &temp_buffers);
|
||||
*(physical_compressed_block*) bp = symbolic_to_physical(bsd, &scb);
|
||||
ctr = thread_count - 1;
|
||||
}
|
||||
else
|
||||
ctr--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] temp_buffers.planes2->decimated_quantized_weights;
|
||||
delete[] temp_buffers.planes2->decimated_weights;
|
||||
delete[] temp_buffers.planes2->flt_quantized_decimated_quantized_weights;
|
||||
delete[] temp_buffers.planes2->u8_quantized_decimated_quantized_weights;
|
||||
delete[] temp_buffers.planes2->eix1;
|
||||
delete[] temp_buffers.planes2->eix2;
|
||||
delete temp_buffers.planes2->ei1;
|
||||
delete temp_buffers.planes2->ei2;
|
||||
delete temp_buffers.planes2;
|
||||
delete[] temp_buffers.tempblocks;
|
||||
delete temp_buffers.temp;
|
||||
delete temp_buffers.ewbo;
|
||||
delete temp_buffers.ewb;
|
||||
}
|
||||
|
||||
astcenc_error astcenc_compress_image(
|
||||
astcenc_context* context,
|
||||
astcenc_image& image,
|
||||
astcenc_swizzle swizzle,
|
||||
uint8_t* data_out,
|
||||
size_t data_len,
|
||||
unsigned int thread_index
|
||||
) {
|
||||
astcenc_error status;
|
||||
|
||||
status = validate_compression_swizzle(swizzle);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (context->config.flags & ASTCENC_FLG_USE_USER_THREADS)
|
||||
{
|
||||
if (thread_index >= context->thread_count)
|
||||
{
|
||||
return ASTCENC_ERR_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Replace error_weighting_params in the core codec with the config / context structs
|
||||
error_weighting_params ewp;
|
||||
ewp.rgb_power = context->config.v_rgb_power;
|
||||
ewp.rgb_base_weight = context->config.v_rgb_base;
|
||||
ewp.rgb_mean_weight = context->config.v_rgb_mean;
|
||||
ewp.rgb_stdev_weight = context->config.v_rgb_stdev;
|
||||
ewp.alpha_power = context->config.v_a_power;
|
||||
ewp.alpha_base_weight = context->config.v_a_base;
|
||||
ewp.alpha_mean_weight = context->config.v_a_mean;
|
||||
ewp.alpha_stdev_weight = context->config.v_a_stdev;
|
||||
ewp.rgb_mean_and_stdev_mixing = context->config.v_rgba_mean_stdev_mix;
|
||||
ewp.mean_stdev_radius = context->config.v_rgba_radius;
|
||||
ewp.enable_rgb_scale_with_alpha = context->config.flags & ASTCENC_FLG_USE_ALPHA_WEIGHT ? 1 : 0;
|
||||
ewp.alpha_radius = context->config.a_scale_radius;
|
||||
ewp.ra_normal_angular_scale = context->config.flags & ASTCENC_FLG_MAP_NORMAL ? 1 : 0;
|
||||
ewp.block_artifact_suppression = context->config.b_deblock_weight;
|
||||
ewp.rgba_weights[0] = context->config.cw_r_weight;
|
||||
ewp.rgba_weights[1] = context->config.cw_g_weight;
|
||||
ewp.rgba_weights[2] = context->config.cw_b_weight;
|
||||
ewp.rgba_weights[3] = context->config.cw_a_weight;
|
||||
ewp.partition_search_limit = context->config.tune_partition_limit;
|
||||
ewp.block_mode_cutoff = context->config.tune_block_mode_limit / 100.0f;
|
||||
ewp.partition_1_to_2_limit = context->config.tune_partition_early_out_limit;
|
||||
ewp.lowest_correlation_cutoff = context->config.tune_two_plane_early_out_limit;
|
||||
ewp.max_refinement_iters = context->config.tune_refinement_limit;
|
||||
|
||||
if ((context->config.profile == ASTCENC_PRF_LDR) || (context->config.profile == ASTCENC_PRF_LDR_SRGB))
|
||||
{
|
||||
ewp.texel_avg_error_limit = powf(0.1f, context->config.tune_db_limit * 0.1f) * 65535.0f * 65535.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
ewp.texel_avg_error_limit = 0.0f;
|
||||
}
|
||||
|
||||
// TODO: Replace astc_codec_image in the core codec with the astcenc_image struct
|
||||
astc_codec_image input_image;
|
||||
input_image.data8 = image.data8;
|
||||
input_image.data16 = image.data16;
|
||||
input_image.xsize = image.dim_x;
|
||||
input_image.ysize = image.dim_y;
|
||||
input_image.zsize = image.dim_z;
|
||||
input_image.padding = image.dim_pad;
|
||||
|
||||
// Need to agree what we do with linearize sRGB
|
||||
input_image.linearize_srgb = context->config.flags & ASTCENC_FLG_USE_LINEARIZED_SRGB ? 1 : 0;
|
||||
|
||||
input_image.input_averages = nullptr;
|
||||
input_image.input_variances = nullptr;
|
||||
input_image.input_alpha_averages = nullptr;
|
||||
|
||||
if (image.dim_pad > 0 ||
|
||||
ewp.rgb_mean_weight != 0.0f || ewp.rgb_stdev_weight != 0.0f ||
|
||||
ewp.alpha_mean_weight != 0.0f || ewp.alpha_stdev_weight != 0.0f)
|
||||
{
|
||||
compute_averages_and_variances(&input_image, ewp.rgb_power, ewp.alpha_power,
|
||||
ewp.mean_stdev_radius, ewp.alpha_radius,
|
||||
input_image.linearize_srgb, swizzle, context->thread_count);
|
||||
}
|
||||
|
||||
// TODO: This could be done once when the context is created
|
||||
expand_block_artifact_suppression(
|
||||
context->config.block_x, context->config.block_y, context->config.block_z, &ewp);
|
||||
|
||||
compress_astc_image_info ai;
|
||||
ai.bsd = context->bsd;
|
||||
ai.buffer = data_out;
|
||||
ai.ewp = &ewp;
|
||||
ai.decode_mode = context->config.profile;
|
||||
ai.swz_encode = swizzle;
|
||||
ai.input_image = &input_image;
|
||||
|
||||
// TODO: Add bounds checking
|
||||
(void)data_len;
|
||||
|
||||
// TODO: Implement user-thread pools
|
||||
launch_threads(context->thread_count, encode_astc_image_threadfunc, &ai);
|
||||
|
||||
// Clean up any memory allocated by compute_averages_and_variances
|
||||
delete[] input_image.input_averages;
|
||||
delete[] input_image.input_variances;
|
||||
delete[] input_image.input_alpha_averages;
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
astcenc_error astcenc_decompress_image(
|
||||
astcenc_context* context,
|
||||
uint8_t* data,
|
||||
size_t data_len,
|
||||
astcenc_image& image_out,
|
||||
astcenc_swizzle swizzle,
|
||||
unsigned int thread_index
|
||||
) {
|
||||
astcenc_error status;
|
||||
|
||||
status = validate_decompression_swizzle(swizzle);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (context->config.flags & ASTCENC_FLG_USE_USER_THREADS)
|
||||
{
|
||||
if (thread_index >= context->thread_count)
|
||||
{
|
||||
return ASTCENC_ERR_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int block_x = context->config.block_x;
|
||||
unsigned int block_y = context->config.block_y;
|
||||
unsigned int block_z = context->config.block_z;
|
||||
|
||||
unsigned int xblocks = (image_out.dim_x + block_x - 1) / block_x;
|
||||
unsigned int yblocks = (image_out.dim_y + block_y - 1) / block_y;
|
||||
unsigned int zblocks = (image_out.dim_z + block_z - 1) / block_z;
|
||||
|
||||
// TODO: Check output bounds
|
||||
(void)data_len;
|
||||
|
||||
// TODO: Handle custom threading
|
||||
(void)thread_index;
|
||||
|
||||
// TODO: Replace astc_codec_image in the core codec with the astcenc_image struct
|
||||
astc_codec_image image;
|
||||
image.data8 = image_out.data8;
|
||||
image.data16 = image_out.data16;
|
||||
image.xsize = image_out.dim_x;
|
||||
image.ysize = image_out.dim_y;
|
||||
image.zsize = image_out.dim_z;
|
||||
image.padding = image_out.dim_pad;
|
||||
|
||||
// Need to agree what we do with linearize sRGB
|
||||
image.linearize_srgb = (context->config.flags & ASTCENC_FLG_USE_LINEARIZED_SRGB) == 0 ? 0 : 1;
|
||||
|
||||
image.input_averages = nullptr;
|
||||
image.input_variances = nullptr;
|
||||
image.input_alpha_averages = nullptr;
|
||||
|
||||
imageblock pb;
|
||||
for (unsigned int z = 0; z < zblocks; z++)
|
||||
{
|
||||
for (unsigned int y = 0; y < yblocks; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < xblocks; x++)
|
||||
{
|
||||
unsigned int offset = (((z * yblocks + y) * xblocks) + x) * 16;
|
||||
uint8_t* bp = data + offset;
|
||||
physical_compressed_block pcb = *(physical_compressed_block *) bp;
|
||||
symbolic_compressed_block scb;
|
||||
physical_to_symbolic(context->bsd, pcb, &scb);
|
||||
decompress_symbolic_block(context->config.profile, context->bsd,
|
||||
x * block_x, y * block_y, z * block_z,
|
||||
&scb, &pb);
|
||||
write_imageblock(&image, &pb, context->bsd,
|
||||
x * block_x, y * block_y, z * block_z, swizzle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ASTCENC_SUCCESS;
|
||||
}
|
||||
|
||||
const char* astcenc_get_error_string(
|
||||
astcenc_error status
|
||||
) {
|
||||
switch(status)
|
||||
{
|
||||
case ASTCENC_ERR_OUT_OF_MEM:
|
||||
return "ASTCENC_ERR_OUT_OF_MEM";
|
||||
case ASTCENC_ERR_BAD_CPU_FLOAT:
|
||||
return "ASTCENC_ERR_BAD_CPU_FLOAT";
|
||||
case ASTCENC_ERR_BAD_CPU_ISA:
|
||||
return "ASTCENC_ERR_BAD_CPU_ISA";
|
||||
case ASTCENC_ERR_BAD_PARAM:
|
||||
return "ASTCENC_ERR_BAD_PARAM";
|
||||
case ASTCENC_ERR_BAD_BLOCK_SIZE:
|
||||
return "ASTCENC_ERR_BAD_BLOCK_SIZE";
|
||||
case ASTCENC_ERR_BAD_PROFILE:
|
||||
return "ASTCENC_ERR_BAD_PROFILE";
|
||||
case ASTCENC_ERR_BAD_PRESET:
|
||||
return "ASTCENC_ERR_BAD_PRESET";
|
||||
case ASTCENC_ERR_BAD_FLAGS:
|
||||
return "ASTCENC_ERR_BAD_FLAGS";
|
||||
case ASTCENC_ERR_BAD_SWIZZLE:
|
||||
return "ASTCENC_ERR_BAD_SWIZZLE";
|
||||
case ASTCENC_ERR_NOT_IMPLEMENTED:
|
||||
return "ASTCENC_ERR_NOT_IMPLEMENTED";
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
+13
-57
@@ -49,11 +49,7 @@
|
||||
* each element in the table is an uint8_t indicating partition index (0, 1, 2 or 3)
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
static void compute_alpha_minmax(
|
||||
int texels_per_block,
|
||||
@@ -234,10 +230,6 @@ void find_best_partitionings(
|
||||
|
||||
float weight_imprecision_estim_squared = weight_imprecision_estim * weight_imprecision_estim;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
printf("weight_imprecision_estim = %g\n", (double)weight_imprecision_estim);
|
||||
#endif
|
||||
|
||||
int uses_alpha = imageblock_uses_alpha(pb);
|
||||
|
||||
const partition_info* ptab = get_partition_table(bsd, partition_count);
|
||||
@@ -255,10 +247,6 @@ void find_best_partitionings(
|
||||
|
||||
if (uses_alpha)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Partition testing with alpha, %d partitions\n\n", partition_count);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < PARTITION_COUNT; i++)
|
||||
{
|
||||
@@ -267,11 +255,6 @@ void find_best_partitionings(
|
||||
|
||||
if (bk_partition_count < partition_count)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Partitioning %d-%d: invalid\n", partition_count, partition);
|
||||
#endif
|
||||
|
||||
uncorr_errors[i] = 1e35f;
|
||||
samechroma_errors[i] = 1e35f;
|
||||
separate_errors[i] = float4(1e35f, 1e35f, 1e35f, 1e35f);
|
||||
@@ -282,13 +265,7 @@ void find_best_partitionings(
|
||||
// than the sentinel value for invalid partitions
|
||||
if (i >= partition_search_limit)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Partitioning %d-%d: excluded from testing\n", partition_count, partition);
|
||||
#endif
|
||||
|
||||
defacto_search_limit = i;
|
||||
|
||||
uncorr_errors[i] = 1e34f;
|
||||
samechroma_errors[i] = 1e34f;
|
||||
separate_errors[i] = float4(1e34f, 1e34f, 1e34f, 1e34f);
|
||||
@@ -489,22 +466,10 @@ void find_best_partitionings(
|
||||
uncorr_errors[i] = uncorr_error;
|
||||
samechroma_errors[i] = samechroma_error;
|
||||
separate_errors[i] = separate_error;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Partitioning %d-%d errors: uncorr=%g, samechroma=%g, sep-alpha=%g\n",
|
||||
partition_count, i, (double)uncorr_error, (double)samechroma_error, (double)separate_error.w);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Partition testing without alpha, %d partitions\n", partition_count);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < PARTITION_COUNT; i++)
|
||||
{
|
||||
int partition = partition_sequence[i];
|
||||
@@ -512,11 +477,6 @@ void find_best_partitionings(
|
||||
int bk_partition_count = ptab[partition].partition_count;
|
||||
if (bk_partition_count < partition_count)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Partitioning %d-%d: invalid\n", partition_count, i);
|
||||
#endif
|
||||
|
||||
uncorr_errors[i] = 1e35f;
|
||||
samechroma_errors[i] = 1e35f;
|
||||
separate_errors[i] = float4(1e35f, 1e35f, 1e35f, 1e35f);
|
||||
@@ -527,11 +487,6 @@ void find_best_partitionings(
|
||||
// than the sentinel value for invalid partitions
|
||||
if (i >= partition_search_limit)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf(" Partitioning %d-%d: excluded from testing\n", partition_count, partition);
|
||||
#endif
|
||||
|
||||
defacto_search_limit = i;
|
||||
uncorr_errors[i] = 1e34f;
|
||||
samechroma_errors[i] = 1e34f;
|
||||
@@ -712,13 +667,6 @@ void find_best_partitionings(
|
||||
uncorr_errors[i] = uncorr_error;
|
||||
samechroma_errors[i] = samechroma_error;
|
||||
separate_errors[i] = float4(separate_error.x, separate_error.y, separate_error.z, 0.0f);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Partitioning %d-%d errors: uncorr=%f, samechroma=%f, sep-red=%f, sep-green=%f, sep-blue=%f\n",
|
||||
partition_count, partition, (double)uncorr_error, (double)samechroma_error,
|
||||
(double)separate_error.x, (double)separate_error.y, (double)separate_error.z);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,10 +746,18 @@ void find_best_partitionings(
|
||||
|
||||
switch(best_component)
|
||||
{
|
||||
case 0: separate_errors[best_partition].x = 1e30f; break;
|
||||
case 1: separate_errors[best_partition].y = 1e30f; break;
|
||||
case 2: separate_errors[best_partition].z = 1e30f; break;
|
||||
case 3: separate_errors[best_partition].w = 1e30f; break;
|
||||
case 0:
|
||||
separate_errors[best_partition].x = 1e30f;
|
||||
break;
|
||||
case 1:
|
||||
separate_errors[best_partition].y = 1e30f;
|
||||
break;
|
||||
case 2:
|
||||
separate_errors[best_partition].z = 1e30f;
|
||||
break;
|
||||
case 3:
|
||||
separate_errors[best_partition].w = 1e30f;
|
||||
break;
|
||||
}
|
||||
|
||||
best_partition = (best_component << PARTITION_BITS) | partition_sequence[best_partition & (PARTITION_COUNT - 1)];
|
||||
+11
-213
@@ -19,11 +19,9 @@
|
||||
* @brief Functions for computing color endpoints and texel weights.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include <cassert>
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
#ifdef DEBUG_CAPTURE_NAN
|
||||
#ifndef _GNU_SOURCE
|
||||
@@ -39,7 +37,7 @@ static void compute_endpoints_and_ideal_weights_1_component(
|
||||
const imageblock* blk,
|
||||
const error_weight_block* ewb,
|
||||
endpoints_and_weights* ei,
|
||||
int component
|
||||
unsigned int component
|
||||
) {
|
||||
int i;
|
||||
|
||||
@@ -54,6 +52,7 @@ static void compute_endpoints_and_ideal_weights_1_component(
|
||||
|
||||
const float *error_weights;
|
||||
const float* data_vr = nullptr;
|
||||
assert(component <= 3);
|
||||
switch (component)
|
||||
{
|
||||
case 0:
|
||||
@@ -72,8 +71,6 @@ static void compute_endpoints_and_ideal_weights_1_component(
|
||||
error_weights = ewb->texel_weight_a;
|
||||
data_vr = blk->data_a;
|
||||
break;
|
||||
default:
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
|
||||
for (i = 0; i < partition_count; i++)
|
||||
@@ -122,10 +119,7 @@ static void compute_endpoints_and_ideal_weights_1_component(
|
||||
|
||||
ei->weights[i] = value;
|
||||
ei->weight_error_scale[i] = partition_error_scale[partition] * error_weights[i];
|
||||
if (astc::isnan(ei->weight_error_scale[i]))
|
||||
{
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
assert(!astc::isnan(ei->weight_error_scale[i]));
|
||||
}
|
||||
|
||||
for (i = 0; i < partition_count; i++)
|
||||
@@ -152,27 +146,6 @@ static void compute_endpoints_and_ideal_weights_1_component(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// print all the data that this function computes.
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s: %dx%dx%d texels, %d partitions, component=%d\n", __func__, xdim, ydim, zdim, partition_count, component);
|
||||
printf("Endpoints:\n");
|
||||
for (i = 0; i < partition_count; i++)
|
||||
{
|
||||
printf("%d Low: <%g> => <%g %g %g %g>\n", i, lowvalues[i], ei->ep.endpt0[i].x, ei->ep.endpt0[i].y, ei->ep.endpt0[i].z, ei->ep.endpt0[i].w);
|
||||
printf("%d High: <%g> => <%g %g %g %g>\n", i, highvalues[i], ei->ep.endpt1[i].x, ei->ep.endpt1[i].y, ei->ep.endpt1[i].z, ei->ep.endpt1[i].w);
|
||||
}
|
||||
printf("Ideal-weights:\n");
|
||||
|
||||
for (i = 0; i < texels_per_block; i++)
|
||||
{
|
||||
printf("%3d <%2d %2d %2d>=> %g (weight=%g)\n", i, i % xdim, (i / xdim) % ydim, i / (xdim * ydim), ei->weights[i], ei->weight_error_scale[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void compute_endpoints_and_ideal_weights_2_components(
|
||||
@@ -209,16 +182,12 @@ static void compute_endpoints_and_ideal_weights_2_components(
|
||||
data_vr = blk->data_r;
|
||||
data_vg = blk->data_b;
|
||||
}
|
||||
else if (component1 == 1 && component2 == 2)
|
||||
else // (component1 == 1 && component2 == 2)
|
||||
{
|
||||
error_weights = ewb->texel_weight_gb;
|
||||
data_vr = blk->data_g;
|
||||
data_vg = blk->data_b;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
|
||||
int texels_per_block = bsd->texel_count;
|
||||
|
||||
@@ -408,32 +377,8 @@ static void compute_endpoints_and_ideal_weights_2_components(
|
||||
|
||||
ei->weights[i] = idx;
|
||||
ei->weight_error_scale[i] = length_squared[partition] * error_weights[i];
|
||||
if (astc::isnan(ei->weight_error_scale[i]))
|
||||
{
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
assert(!astc::isnan(ei->weight_error_scale[i]));
|
||||
}
|
||||
|
||||
// print all the data that this function computes.
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s: %dx%dx%d texels, %d partitions, component1=%d, component2=%d\n", __func__, xdim, ydim, zdim, partition_count, component1, component2);
|
||||
printf("Endpoints:\n");
|
||||
for (i = 0; i < partition_count; i++)
|
||||
{
|
||||
printf("%d Low: <%g %g> => <%g %g %g %g>\n", i, lowvalues[i].x, lowvalues[i].y, ei->ep.endpt0[i].x, ei->ep.endpt0[i].y, ei->ep.endpt0[i].z, ei->ep.endpt0[i].w);
|
||||
printf("%d High: <%g %g> => <%g %g %g %g>\n", i, highvalues[i].x, highvalues[i].y, ei->ep.endpt1[i].x, ei->ep.endpt1[i].y, ei->ep.endpt1[i].z, ei->ep.endpt1[i].w);
|
||||
}
|
||||
printf("Ideal-weights:\n");
|
||||
|
||||
for (i = 0; i < texels_per_block; i++)
|
||||
{
|
||||
printf("%3d <%2d %2d %2d>=> %g (weight=%g)\n", i, i % xdim, (i / xdim) % ydim, i / (xdim * ydim), ei->weights[i], ei->weight_error_scale[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void compute_endpoints_and_ideal_weights_3_components(
|
||||
@@ -666,32 +611,8 @@ static void compute_endpoints_and_ideal_weights_3_components(
|
||||
|
||||
ei->weights[i] = idx;
|
||||
ei->weight_error_scale[i] = length_squared[partition] * error_weights[i];
|
||||
if (astc::isnan(ei->weight_error_scale[i]))
|
||||
{
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
assert(!astc::isnan(ei->weight_error_scale[i]));
|
||||
}
|
||||
|
||||
// print all the data that this function computes.
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s: %dx%dx%d texels, %d partitions, component1=%d, component2=%d, component3=%d\n", __func__, xdim, ydim, zdim, partition_count, component1, component2, component3);
|
||||
printf("Endpoints:\n");
|
||||
for (i = 0; i < partition_count; i++)
|
||||
{
|
||||
printf("%d Low: <%g %g %f> => <%g %g %g %g>\n", i, lowvalues[i].x, lowvalues[i].y, lowvalues[i].z, ei->ep.endpt0[i].x, ei->ep.endpt0[i].y, ei->ep.endpt0[i].z, ei->ep.endpt0[i].w);
|
||||
printf("%d High: <%g %g %g> => <%g %g %g %g>\n", i, highvalues[i].x, highvalues[i].y, highvalues[i].z, ei->ep.endpt1[i].x, ei->ep.endpt1[i].y, ei->ep.endpt1[i].z, ei->ep.endpt1[i].w);
|
||||
}
|
||||
printf("Ideal-weights:\n");
|
||||
|
||||
for (i = 0; i < texels_per_block; i++)
|
||||
{
|
||||
printf("%3d <%2d %2d %2d>=> %g (weight=%g)\n", i, (i % xdim), (i / xdim) % ydim, i / (xdim * ydim), ei->weights[i], ei->weight_error_scale[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void compute_endpoints_and_ideal_weights_rgba(
|
||||
@@ -752,19 +673,6 @@ static void compute_endpoints_and_ideal_weights_rgba(
|
||||
lines[i].b = normalize(directions_rgba[i]);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
for (i = 0; i < partition_count; i++)
|
||||
{
|
||||
printf("Direction-vector %d: <%f %f %f %f>\n", i, directions_rgba[i].x, directions_rgba[i].y, directions_rgba[i].z, directions_rgba[i].w);
|
||||
printf("Line %d A: <%f %f %f %f>\n", i, lines[i].a.x, lines[i].a.y, lines[i].a.z, lines[i].a.w);
|
||||
printf("Line %d B: <%f %f %f %f>\n", i, lines[i].b.x, lines[i].b.y, lines[i].b.z, lines[i].b.w);
|
||||
printf("Scalefactors %d: <%f %f %f %f>\n", i, scalefactors[i].x, scalefactors[i].y, scalefactors[i].z, scalefactors[i].w);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < texels_per_block; i++)
|
||||
{
|
||||
if (error_weights[i] > 1e-10f)
|
||||
@@ -787,14 +695,6 @@ static void compute_endpoints_and_ideal_weights_rgba(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
for (i = 0; i < partition_count; i++)
|
||||
printf("Partition %d: Lowparam=%f Highparam=%f\n", i, lowparam[i], highparam[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < partition_count; i++)
|
||||
{
|
||||
float length = highparam[i] - lowparam[i];
|
||||
@@ -840,33 +740,8 @@ static void compute_endpoints_and_ideal_weights_rgba(
|
||||
idx = 0.0f;
|
||||
ei->weights[i] = idx;
|
||||
ei->weight_error_scale[i] = error_weights[i] * length_squared[partition];
|
||||
if (astc::isnan(ei->weight_error_scale[i]))
|
||||
{
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
assert(!astc::isnan(ei->weight_error_scale[i]));
|
||||
}
|
||||
|
||||
// print all the data that this function computes.
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s: %dx%dx%d texels, %d partitions\n", __func__, xdim, ydim, zdim, partition_count);
|
||||
printf("Endpoints:\n");
|
||||
for (i = 0; i < partition_count; i++)
|
||||
{
|
||||
printf("%d Low: <%g %g %g %g>\n", i, ei->ep.endpt0[i].x, ei->ep.endpt0[i].y, ei->ep.endpt0[i].z, ei->ep.endpt0[i].w);
|
||||
printf("%d High: <%g %g %g %g>\n", i, ei->ep.endpt1[i].x, ei->ep.endpt1[i].y, ei->ep.endpt1[i].z, ei->ep.endpt1[i].w);
|
||||
}
|
||||
printf("\nIdeal-weights:\n");
|
||||
|
||||
for (i = 0; i < texels_per_block; i++)
|
||||
{
|
||||
printf("%3d <%2d %2d %2d>=> %g (weight=%g)\n", i, i % xdim, (i / xdim) % ydim, i / (xdim * ydim), ei->weights[i], ei->weight_error_scale[i]);
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -883,11 +758,6 @@ void compute_endpoints_and_ideal_weights_1_plane(
|
||||
const error_weight_block* ewb,
|
||||
endpoints_and_weights* ei
|
||||
) {
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("%s: texels_per_block=%dx%dx%d\n\n", __func__, xdim, ydim, zdim);
|
||||
#endif
|
||||
|
||||
int uses_alpha = imageblock_uses_alpha(blk);
|
||||
if (uses_alpha)
|
||||
{
|
||||
@@ -908,11 +778,6 @@ void compute_endpoints_and_ideal_weights_2_planes(
|
||||
endpoints_and_weights* ei1,
|
||||
endpoints_and_weights* ei2
|
||||
) {
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("%s: texels_per_block=%dx%dx%d, separate_component=%d\n\n", __func__, xdim, ydim, zdim, separate_component);
|
||||
#endif
|
||||
|
||||
int uses_alpha = imageblock_uses_alpha(blk);
|
||||
switch (separate_component)
|
||||
{
|
||||
@@ -941,12 +806,8 @@ void compute_endpoints_and_ideal_weights_2_planes(
|
||||
break;
|
||||
|
||||
case 3: // separate weights for alpha
|
||||
if (uses_alpha == 0)
|
||||
{
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
assert(uses_alpha != 0);
|
||||
compute_endpoints_and_ideal_weights_3_components(bsd, pt, blk, ewb, ei1, 3);
|
||||
|
||||
compute_endpoints_and_ideal_weights_1_component(bsd, pt, blk, ewb, ei2, 3);
|
||||
break;
|
||||
}
|
||||
@@ -1150,19 +1011,6 @@ void compute_ideal_quantized_weights_for_decimation_table(
|
||||
int weight_count = it->num_weights;
|
||||
const quantization_and_transfer_table *qat = &(quant_and_xfer_tables[quantization_level]);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s : texels-per-block=%d, weights=%d, quantization-level=%d\n\n", __func__, texels_per_block, weight_count, quantization_level);
|
||||
|
||||
printf("Weight values before quantization:\n");
|
||||
for (i = 0; i < weight_count; i++)
|
||||
printf("%3d : %g\n", i, weight_set_in[i]);
|
||||
|
||||
printf("Low-bound: %f High-bound: %f\n", low_bound, high_bound);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const int quant_levels[12] = { 2,3,4,5,6,8,10,12,16,20,24,32 };
|
||||
float quant_level_m1 = (float)(quant_levels[quantization_level] - 1);
|
||||
|
||||
@@ -1186,7 +1034,7 @@ void compute_ideal_quantized_weights_for_decimation_table(
|
||||
|
||||
int i = 0;
|
||||
|
||||
#if ASTC_AVX >= 2
|
||||
#if ASTCENC_AVX >= 2
|
||||
// TODO: This is currently 4-wide. Could try 8?
|
||||
int clipped_weight_count = weight_count & ~3;
|
||||
__m128i shuf = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
@@ -1352,20 +1200,6 @@ void recompute_ideal_colors(
|
||||
|
||||
int partition_count = pi->partition_count;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s : %dx%dx%d texels_per_block, %d partitions, plane2-color-component=%d\n\n", __func__, xdim, ydim, zdim, partition_count, plane2_color_component);
|
||||
|
||||
printf("Pre-adjustment endpoint-colors: \n");
|
||||
for (int i = 0; i < partition_count; i++)
|
||||
{
|
||||
printf("%d Low <%g %g %g %g>\n", i, ep->endpt0[i].x, ep->endpt0[i].y, ep->endpt0[i].z, ep->endpt0[i].w);
|
||||
printf("%d High <%g %g %g %g>\n", i, ep->endpt1[i].x, ep->endpt1[i].y, ep->endpt1[i].z, ep->endpt1[i].w);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < partition_count; i++)
|
||||
{
|
||||
float4 rgba_sum = float4(1e-17f, 1e-17f, 1e-17f, 1e-17f);
|
||||
@@ -1603,14 +1437,6 @@ void recompute_ideal_colors(
|
||||
+ (2.0f * lmrs_sum.y * lmrs_sum.y)
|
||||
+ (lmrs_sum.z * lmrs_sum.z);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Plane-1 partition %d determinants: R=%g G=%g B=%g A=%g L=%g S=%g\n", i,
|
||||
(double)color_det1.x, (double)color_det1.y,
|
||||
(double)color_det1.z, (double)color_det1.w,
|
||||
(double)ls_det1, (double)ls_det1);
|
||||
#endif
|
||||
|
||||
float4 ep0 = (right_sum * color_vec_x - middle_sum * color_vec_y) * color_rdet1;
|
||||
float4 ep1 = (left_sum * color_vec_y - middle_sum * color_vec_x) * color_rdet1;
|
||||
|
||||
@@ -1695,12 +1521,6 @@ void recompute_ideal_colors(
|
||||
+ (2.0f * middle2_sum * middle2_sum)
|
||||
+ (right2_sum * right2_sum);
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("Plane-2 partition %d determinants: R=%g G=%g B=%g A=%g\n",
|
||||
i, (double)color_det2.x, (double)color_det2.y, (double)color_det2.z, (double)color_det2.w);
|
||||
#endif
|
||||
|
||||
float4 ep0 = (right2_sum * color_vec_x - middle2_sum * color_vec_y) * color_rdet2;
|
||||
float4 ep1 = (left2_sum * color_vec_y - middle2_sum * color_vec_x) * color_rdet2;
|
||||
|
||||
@@ -1751,26 +1571,4 @@ void recompute_ideal_colors(
|
||||
rgbo_vectors[i] = float4(ep0.x, ep0.y, ep0.z, avgdif);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("Post-adjustment endpoint-colors: \n");
|
||||
for (int i = 0; i < partition_count; i++)
|
||||
{
|
||||
printf("%d Low <%g %g %g %g>\n", i,
|
||||
(double)ep->endpt0[i].x, (double)ep->endpt0[i].y,
|
||||
(double)ep->endpt0[i].z, (double)ep->endpt0[i].w);
|
||||
printf("%d High <%g %g %g %g>\n", i,
|
||||
(double)ep->endpt1[i].x, (double)ep->endpt1[i].y,
|
||||
(double)ep->endpt1[i].z, (double)ep->endpt1[i].w);
|
||||
printf("%d RGBS: <%g %g %g %g>\n", i,
|
||||
(double)rgbs_vectors[i].x, (double)rgbs_vectors[i].y,
|
||||
(double)rgbs_vectors[i].z, (double)rgbs_vectors[i].w);
|
||||
printf("%d RGBO <%g %g %g %g>\n", i,
|
||||
(double)rgbo_vectors[i].x, (double)rgbo_vectors[i].y,
|
||||
(double)rgbo_vectors[i].z, (double)rgbo_vectors[i].w);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -19,256 +19,10 @@
|
||||
* @brief Functions for creating in-memory ASTC image structures.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include "astc_codec_internals.h"
|
||||
|
||||
astc_codec_image *alloc_image(
|
||||
int bitness,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int zsize,
|
||||
int padding
|
||||
) {
|
||||
int i, j;
|
||||
astc_codec_image *img = new astc_codec_image;
|
||||
img->xsize = xsize;
|
||||
img->ysize = ysize;
|
||||
img->zsize = zsize;
|
||||
img->padding = padding;
|
||||
|
||||
img->input_averages = nullptr;
|
||||
img->input_variances = nullptr;
|
||||
img->input_alpha_averages = nullptr;
|
||||
|
||||
img->linearize_srgb = 0;
|
||||
img->rgb_force_use_of_hdr = 0;
|
||||
img->alpha_force_use_of_hdr = 0;
|
||||
|
||||
int exsize = xsize + 2 * padding;
|
||||
int eysize = ysize + 2 * padding;
|
||||
int ezsize = (zsize == 1) ? 1 : zsize + 2 * padding;
|
||||
|
||||
if (bitness == 8)
|
||||
{
|
||||
img->data8 = new uint8_t **[ezsize];
|
||||
img->data8[0] = new uint8_t *[ezsize * eysize];
|
||||
img->data8[0][0] = new uint8_t[4 * ezsize * eysize * exsize];
|
||||
memset(img->data8[0][0], 0, 4 * ezsize * eysize * exsize);
|
||||
|
||||
for (i = 1; i < ezsize; i++)
|
||||
{
|
||||
img->data8[i] = img->data8[0] + i * eysize;
|
||||
img->data8[i][0] = img->data8[0][0] + 4 * i * exsize * eysize;
|
||||
}
|
||||
|
||||
for (i = 0; i < ezsize; i++)
|
||||
{
|
||||
for (j = 1; j < eysize; j++)
|
||||
{
|
||||
img->data8[i][j] = img->data8[i][0] + 4 * j * exsize;
|
||||
}
|
||||
}
|
||||
|
||||
img->data16 = nullptr;
|
||||
}
|
||||
else if (bitness == 16)
|
||||
{
|
||||
img->data16 = new uint16_t **[ezsize];
|
||||
img->data16[0] = new uint16_t *[ezsize * eysize];
|
||||
img->data16[0][0] = new uint16_t[4 * ezsize * eysize * exsize];
|
||||
memset(img->data16[0][0], 0, 8 * ezsize * eysize * exsize);
|
||||
|
||||
for (i = 1; i < ezsize; i++)
|
||||
{
|
||||
img->data16[i] = img->data16[0] + i * eysize;
|
||||
img->data16[i][0] = img->data16[0][0] + 4 * i * exsize * eysize;
|
||||
}
|
||||
|
||||
for (i = 0; i < ezsize; i++)
|
||||
{
|
||||
for (j = 1; j < eysize; j++)
|
||||
{
|
||||
img->data16[i][j] = img->data16[i][0] + 4 * j * exsize;
|
||||
}
|
||||
}
|
||||
|
||||
img->data8 = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
void free_image(astc_codec_image * img)
|
||||
{
|
||||
if (img == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (img->data8)
|
||||
{
|
||||
delete[] img->data8[0][0];
|
||||
delete[] img->data8[0];
|
||||
delete[] img->data8;
|
||||
}
|
||||
|
||||
if (img->data16)
|
||||
{
|
||||
delete[] img->data16[0][0];
|
||||
delete[] img->data16[0];
|
||||
delete[] img->data16;
|
||||
}
|
||||
|
||||
if (img->input_averages)
|
||||
{
|
||||
delete[] img->input_averages;
|
||||
}
|
||||
|
||||
if (img->input_variances)
|
||||
{
|
||||
delete[] img->input_variances;
|
||||
}
|
||||
|
||||
if (img->input_alpha_averages)
|
||||
{
|
||||
delete[] img->input_alpha_averages;
|
||||
}
|
||||
|
||||
delete img;
|
||||
}
|
||||
|
||||
|
||||
// fill the padding area of the input-file buffer with clamp-to-edge data
|
||||
// Done inefficiently, in that it will overwrite all the interior data at least once;
|
||||
// this is not considered a problem, since this makes up a very small part of total
|
||||
// running time.
|
||||
void fill_image_padding_area(astc_codec_image * img)
|
||||
{
|
||||
if (img->padding == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int x, y, z, i;
|
||||
int exsize = img->xsize + 2 * img->padding;
|
||||
int eysize = img->ysize + 2 * img->padding;
|
||||
int ezsize = (img->zsize == 1) ? 1 : (img->zsize + 2 * img->padding);
|
||||
|
||||
int xmin = img->padding;
|
||||
int ymin = img->padding;
|
||||
int zmin = (img->zsize == 1) ? 0 : img->padding;
|
||||
int xmax = img->xsize + img->padding - 1;
|
||||
int ymax = img->ysize + img->padding - 1;
|
||||
int zmax = (img->zsize == 1) ? 0 : img->zsize + img->padding - 1;
|
||||
|
||||
// This is a very simple implementation. Possible optimizations include:
|
||||
// * Testing if texel is outside the edge.
|
||||
// * Looping over texels that we know are outside the edge.
|
||||
if (img->data8)
|
||||
{
|
||||
for (z = 0; z < ezsize; z++)
|
||||
{
|
||||
int zc = MIN(MAX(z, zmin), zmax);
|
||||
for (y = 0; y < eysize; y++)
|
||||
{
|
||||
int yc = MIN(MAX(y, ymin), ymax);
|
||||
for (x = 0; x < exsize; x++)
|
||||
{
|
||||
int xc = MIN(MAX(x, xmin), xmax);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
img->data8[z][y][4 * x + i] = img->data8[zc][yc][4 * xc + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (img->data16)
|
||||
{
|
||||
for (z = 0; z < ezsize; z++)
|
||||
{
|
||||
int zc = MIN(MAX(z, zmin), zmax);
|
||||
for (y = 0; y < eysize; y++)
|
||||
{
|
||||
int yc = MIN(MAX(y, ymin), ymax);
|
||||
for (x = 0; x < exsize; x++)
|
||||
{
|
||||
int xc = MIN(MAX(x, xmin), xmax);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
img->data16[z][y][4 * x + i] = img->data16[zc][yc][4 * xc + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int determine_image_channels(const astc_codec_image * img)
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
int xsize = img->xsize;
|
||||
int ysize = img->ysize;
|
||||
int zsize = img->zsize;
|
||||
// scan through the image data
|
||||
// to determine how many color channels the image has.
|
||||
|
||||
int lum_mask;
|
||||
int alpha_mask;
|
||||
int alpha_mask_ref;
|
||||
if (img->data8)
|
||||
{
|
||||
alpha_mask_ref = 0xFF;
|
||||
alpha_mask = 0xFF;
|
||||
lum_mask = 0;
|
||||
for (z = 0; z < zsize; z++)
|
||||
{
|
||||
for (y = 0; y < ysize; y++)
|
||||
{
|
||||
for (x = 0; x < xsize; x++)
|
||||
{
|
||||
int r = img->data8[z][y][4 * x];
|
||||
int g = img->data8[z][y][4 * x + 1];
|
||||
int b = img->data8[z][y][4 * x + 2];
|
||||
int a = img->data8[z][y][4 * x + 3];
|
||||
lum_mask |= (r ^ g) | (r ^ b);
|
||||
alpha_mask &= a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // (bitness == 16)
|
||||
{
|
||||
alpha_mask_ref = 0xFFFF;
|
||||
alpha_mask = 0xFFFF;
|
||||
lum_mask = 0;
|
||||
for (z = 0; z < zsize; z++)
|
||||
{
|
||||
for (y = 0; y < ysize; y++)
|
||||
{
|
||||
for (x = 0; x < xsize; x++)
|
||||
{
|
||||
int r = img->data16[z][y][4 * x];
|
||||
int g = img->data16[z][y][4 * x + 1];
|
||||
int b = img->data16[z][y][4 * x + 2];
|
||||
int a = img->data16[z][y][4 * x + 3];
|
||||
lum_mask |= (r ^ g) | (r ^ b);
|
||||
alpha_mask &= (a ^ 0xC3FF); // a ^ 0xC3FF returns FFFF if and only if the input is 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int image_channels = 1 + (lum_mask == 0 ? 0 : 2) + (alpha_mask == alpha_mask_ref ? 0 : 1);
|
||||
|
||||
return image_channels;
|
||||
}
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
// conversion functions between the LNS representation and the FP16 representation.
|
||||
float float_to_lns(float p)
|
||||
@@ -493,6 +247,7 @@ void imageblock_initialize_orig_from_work(
|
||||
|
||||
// fetch an imageblock from the input file.
|
||||
void fetch_imageblock(
|
||||
astcenc_profile decode_mode,
|
||||
const astc_codec_image* img,
|
||||
imageblock* pb, // picture-block to initialize with image data
|
||||
const block_size_descriptor* bsd,
|
||||
@@ -500,7 +255,7 @@ void fetch_imageblock(
|
||||
int xpos,
|
||||
int ypos,
|
||||
int zpos,
|
||||
swizzlepattern swz
|
||||
astcenc_swizzle swz
|
||||
) {
|
||||
float *fptr = pb->orig_data;
|
||||
int xsize = img->xsize + 2 * img->padding;
|
||||
@@ -626,6 +381,7 @@ void fetch_imageblock(
|
||||
// perform sRGB-to-linear transform on input data, if requested.
|
||||
int pixelcount = bsd->texel_count;
|
||||
|
||||
// sRGB to Linear
|
||||
if (img->linearize_srgb)
|
||||
{
|
||||
fptr = pb->orig_data;
|
||||
@@ -686,18 +442,8 @@ void fetch_imageblock(
|
||||
fptr += 4;
|
||||
}
|
||||
|
||||
float max_rgb = MAX(max_red, MAX(max_green, max_blue));
|
||||
|
||||
// use LNS if:
|
||||
// * RGB-maximum is less than 0.15
|
||||
// * RGB-maximum is greater than 1
|
||||
// * Alpha-maximum is greater than 1
|
||||
int rgb_lns = (max_rgb < 0.15f || max_rgb > 1.0f || max_alpha > 1.0f) ? 1 : 0;
|
||||
int alpha_lns = rgb_lns ? (max_alpha > 1.0f || max_alpha < 0.15f) : 0;
|
||||
|
||||
// not yet though; for the time being, just obey the command line.
|
||||
rgb_lns = img->rgb_force_use_of_hdr;
|
||||
alpha_lns = img->alpha_force_use_of_hdr;
|
||||
int rgb_lns = (decode_mode == ASTCENC_PRF_HDR) || (decode_mode == ASTCENC_PRF_HDR_RGB_LDR_A);
|
||||
int alpha_lns = decode_mode == ASTCENC_PRF_HDR;
|
||||
|
||||
// impose the choice on every pixel when encoding.
|
||||
for (i = 0; i < pixelcount; i++)
|
||||
@@ -719,7 +465,7 @@ void write_imageblock(
|
||||
int xpos,
|
||||
int ypos,
|
||||
int zpos,
|
||||
swizzlepattern swz
|
||||
astcenc_swizzle swz
|
||||
) {
|
||||
const float *fptr = pb->orig_data;
|
||||
const uint8_t *nptr = pb->nan_texel;
|
||||
@@ -756,7 +502,7 @@ void write_imageblock(
|
||||
}
|
||||
else
|
||||
{
|
||||
// apply swizzle
|
||||
// Linear to sRGB
|
||||
if (img->linearize_srgb)
|
||||
{
|
||||
float r = fptr[0];
|
||||
@@ -853,7 +599,7 @@ void write_imageblock(
|
||||
|
||||
else
|
||||
{
|
||||
// apply swizzle
|
||||
// Linear to sRGB
|
||||
if (img->linearize_srgb)
|
||||
{
|
||||
float r = fptr[0];
|
||||
@@ -967,157 +713,3 @@ void update_imageblock_flags(
|
||||
pb->alpha_max = alpha_max;
|
||||
pb->grayscale = grayscale;
|
||||
}
|
||||
|
||||
// initialize an astc_codec_image data structure from a 2D array of RGBA float*4
|
||||
astc_codec_image* astc_img_from_floatx4_array(
|
||||
const float* image,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int padding,
|
||||
int y_flip
|
||||
) {
|
||||
astc_codec_image* astc_img = alloc_image(16, xsize, ysize, 1, padding);
|
||||
|
||||
for (int y = 0; y < ysize; y++)
|
||||
{
|
||||
int y_dst = y + padding;
|
||||
int y_src = y_flip ? (ysize - y - 1) : y;
|
||||
const float* src = image + 4 * xsize * y_src;
|
||||
|
||||
for (int x = 0; x < xsize; x++)
|
||||
{
|
||||
int x_dst = x + padding;
|
||||
astc_img->data16[0][y_dst][4 * x_dst] = float_to_sf16(src[4 * x], SF_NEARESTEVEN);
|
||||
astc_img->data16[0][y_dst][4 * x_dst + 1] = float_to_sf16(src[4 * x + 1], SF_NEARESTEVEN);
|
||||
astc_img->data16[0][y_dst][4 * x_dst + 2] = float_to_sf16(src[4 * x + 2], SF_NEARESTEVEN);
|
||||
astc_img->data16[0][y_dst][4 * x_dst + 3] = float_to_sf16(src[4 * x + 3], SF_NEARESTEVEN);
|
||||
}
|
||||
}
|
||||
|
||||
fill_image_padding_area(astc_img);
|
||||
return astc_img;
|
||||
}
|
||||
|
||||
// initialize an astc_codec_image data structure from a 2D array of UNORM8
|
||||
astc_codec_image* astc_img_from_unorm8x4_array(
|
||||
const uint8_t* imageptr,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int padding,
|
||||
int y_flip
|
||||
) {
|
||||
astc_codec_image *astc_img = alloc_image(8, xsize, ysize, 1, padding);
|
||||
|
||||
for (int y = 0; y < ysize; y++)
|
||||
{
|
||||
int y_dst = y + padding;
|
||||
int y_src = y_flip ? (ysize - y - 1) : y;
|
||||
const uint8_t* src = imageptr + 4 * xsize * y_src;
|
||||
|
||||
for (int x = 0; x < xsize; x++)
|
||||
{
|
||||
int x_dst = x + padding;
|
||||
astc_img->data8[0][y_dst][4 * x_dst] = src[4 * x];
|
||||
astc_img->data8[0][y_dst][4 * x_dst + 1] = src[4 * x + 1];
|
||||
astc_img->data8[0][y_dst][4 * x_dst + 2] = src[4 * x + 2];
|
||||
astc_img->data8[0][y_dst][4 * x_dst + 3] = src[4 * x + 3];
|
||||
}
|
||||
}
|
||||
|
||||
fill_image_padding_area(astc_img);
|
||||
return astc_img;
|
||||
}
|
||||
|
||||
// initialize a flattened array of float4 values from an ASTC codec image
|
||||
// The returned array is allocated with malloc() and needs to be freed with free().
|
||||
float* floatx4_array_from_astc_img(
|
||||
const astc_codec_image* img,
|
||||
int y_flip
|
||||
) {
|
||||
int xsize = img->xsize;
|
||||
int ysize = img->ysize;
|
||||
|
||||
float *buf = (float *)malloc(4 * sizeof(float) * xsize * ysize);
|
||||
|
||||
if (img->data8)
|
||||
{
|
||||
for (int y = 0; y < ysize; y++)
|
||||
{
|
||||
int ymod = y_flip ? ysize - y - 1 : y;
|
||||
const uint8_t* src = img->data8[0][ymod + img->padding] + (4 * img->padding);
|
||||
float* dst = buf + y * xsize * 4;
|
||||
for (int x = 0; x < xsize; x++)
|
||||
{
|
||||
dst[4 * x] = src[4 * x] * (1.0f / 255.0f);
|
||||
dst[4 * x + 1] = src[4 * x + 1] * (1.0f / 255.0f);
|
||||
dst[4 * x + 2] = src[4 * x + 2] * (1.0f / 255.0f);
|
||||
dst[4 * x + 3] = src[4 * x + 3] * (1.0f / 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < ysize; y++)
|
||||
{
|
||||
int ymod = y_flip ? ysize - y - 1 : y;
|
||||
const uint16_t *src = img->data16[0][ymod + img->padding] + (4 * img->padding);
|
||||
float *dst = buf + y * xsize * 4;
|
||||
for (int x = 0; x < xsize; x++)
|
||||
{
|
||||
dst[4 * x] = sf16_to_float(src[4 * x]);
|
||||
dst[4 * x + 1] = sf16_to_float(src[4 * x + 1]);
|
||||
dst[4 * x + 2] = sf16_to_float(src[4 * x + 2]);
|
||||
dst[4 * x + 3] = sf16_to_float(src[4 * x + 3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// initialize a flattened array of unorm8x4 values from an ASTC codec image
|
||||
// The returned array is allocated with malloc() and needs to be freed with free().
|
||||
uint8_t* unorm8x4_array_from_astc_img(
|
||||
const astc_codec_image* img,
|
||||
int y_flip
|
||||
) {
|
||||
int xsize = img->xsize;
|
||||
int ysize = img->ysize;
|
||||
|
||||
uint8_t* buf = (uint8_t*)malloc(4 * sizeof(uint8_t) * xsize * ysize);
|
||||
|
||||
if (img->data8)
|
||||
{
|
||||
for (int y = 0; y < ysize; y++)
|
||||
{
|
||||
int ymod = y_flip ? ysize-y-1 : y;
|
||||
const uint8_t* src = img->data8[0][ymod + img->padding] + (4 * img->padding);
|
||||
uint8_t* dst = buf + y * xsize * 4;
|
||||
for (int x = 0; x < xsize; x++)
|
||||
{
|
||||
dst[4 * x] = src[4 * x];
|
||||
dst[4 * x + 1] = src[4 * x + 1];
|
||||
dst[4 * x + 2] = src[4 * x + 2];
|
||||
dst[4 * x + 3] = src[4 * x + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < ysize; y++)
|
||||
{
|
||||
int ymod = y_flip ? ysize-y-1 : y;
|
||||
const uint16_t* src = img->data16[0][ymod + img->padding] + (4 * img->padding);
|
||||
uint8_t* dst = buf + y * xsize * 4;
|
||||
for (int x = 0; x < xsize; x++)
|
||||
{
|
||||
dst[4 * x] = (uint8_t)astc::flt2int_rtn(astc::clamp1f(sf16_to_float(src[4*x])) * 255.0f);
|
||||
dst[4 * x + 1] = (uint8_t)astc::flt2int_rtn(astc::clamp1f(sf16_to_float(src[4*x+1])) * 255.0f);
|
||||
dst[4 * x + 2] = (uint8_t)astc::flt2int_rtn(astc::clamp1f(sf16_to_float(src[4*x+2])) * 255.0f);
|
||||
dst[4 * x + 3] = (uint8_t)astc::flt2int_rtn(astc::clamp1f(sf16_to_float(src[4*x+3])) * 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -19,42 +19,42 @@
|
||||
* @brief Functions for encoding/decoding Bounded Integer Sequence Encoding.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
// unpacked quint triplets <low,middle,high> for each packed-quint value
|
||||
static const uint8_t quints_of_integer[128][3] = {
|
||||
{0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0},
|
||||
{4, 0, 0}, {0, 4, 0}, {4, 4, 0}, {4, 4, 4},
|
||||
{0, 1, 0}, {1, 1, 0}, {2, 1, 0}, {3, 1, 0},
|
||||
{4, 1, 0}, {1, 4, 0}, {4, 4, 1}, {4, 4, 4},
|
||||
{0, 2, 0}, {1, 2, 0}, {2, 2, 0}, {3, 2, 0},
|
||||
{4, 2, 0}, {2, 4, 0}, {4, 4, 2}, {4, 4, 4},
|
||||
{0, 3, 0}, {1, 3, 0}, {2, 3, 0}, {3, 3, 0},
|
||||
{4, 3, 0}, {3, 4, 0}, {4, 4, 3}, {4, 4, 4},
|
||||
{0, 0, 1}, {1, 0, 1}, {2, 0, 1}, {3, 0, 1},
|
||||
{4, 0, 1}, {0, 4, 1}, {4, 0, 4}, {0, 4, 4},
|
||||
{0, 1, 1}, {1, 1, 1}, {2, 1, 1}, {3, 1, 1},
|
||||
{4, 1, 1}, {1, 4, 1}, {4, 1, 4}, {1, 4, 4},
|
||||
{0, 2, 1}, {1, 2, 1}, {2, 2, 1}, {3, 2, 1},
|
||||
{4, 2, 1}, {2, 4, 1}, {4, 2, 4}, {2, 4, 4},
|
||||
{0, 3, 1}, {1, 3, 1}, {2, 3, 1}, {3, 3, 1},
|
||||
{4, 3, 1}, {3, 4, 1}, {4, 3, 4}, {3, 4, 4},
|
||||
{0, 0, 2}, {1, 0, 2}, {2, 0, 2}, {3, 0, 2},
|
||||
{4, 0, 2}, {0, 4, 2}, {2, 0, 4}, {3, 0, 4},
|
||||
{0, 1, 2}, {1, 1, 2}, {2, 1, 2}, {3, 1, 2},
|
||||
{4, 1, 2}, {1, 4, 2}, {2, 1, 4}, {3, 1, 4},
|
||||
{0, 2, 2}, {1, 2, 2}, {2, 2, 2}, {3, 2, 2},
|
||||
{4, 2, 2}, {2, 4, 2}, {2, 2, 4}, {3, 2, 4},
|
||||
{0, 3, 2}, {1, 3, 2}, {2, 3, 2}, {3, 3, 2},
|
||||
{4, 3, 2}, {3, 4, 2}, {2, 3, 4}, {3, 3, 4},
|
||||
{0, 0, 3}, {1, 0, 3}, {2, 0, 3}, {3, 0, 3},
|
||||
{4, 0, 3}, {0, 4, 3}, {0, 0, 4}, {1, 0, 4},
|
||||
{0, 1, 3}, {1, 1, 3}, {2, 1, 3}, {3, 1, 3},
|
||||
{4, 1, 3}, {1, 4, 3}, {0, 1, 4}, {1, 1, 4},
|
||||
{0, 2, 3}, {1, 2, 3}, {2, 2, 3}, {3, 2, 3},
|
||||
{4, 2, 3}, {2, 4, 3}, {0, 2, 4}, {1, 2, 4},
|
||||
{0, 3, 3}, {1, 3, 3}, {2, 3, 3}, {3, 3, 3},
|
||||
{4, 3, 3}, {3, 4, 3}, {0, 3, 4}, {1, 3, 4}
|
||||
{0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0},
|
||||
{4, 0, 0}, {0, 4, 0}, {4, 4, 0}, {4, 4, 4},
|
||||
{0, 1, 0}, {1, 1, 0}, {2, 1, 0}, {3, 1, 0},
|
||||
{4, 1, 0}, {1, 4, 0}, {4, 4, 1}, {4, 4, 4},
|
||||
{0, 2, 0}, {1, 2, 0}, {2, 2, 0}, {3, 2, 0},
|
||||
{4, 2, 0}, {2, 4, 0}, {4, 4, 2}, {4, 4, 4},
|
||||
{0, 3, 0}, {1, 3, 0}, {2, 3, 0}, {3, 3, 0},
|
||||
{4, 3, 0}, {3, 4, 0}, {4, 4, 3}, {4, 4, 4},
|
||||
{0, 0, 1}, {1, 0, 1}, {2, 0, 1}, {3, 0, 1},
|
||||
{4, 0, 1}, {0, 4, 1}, {4, 0, 4}, {0, 4, 4},
|
||||
{0, 1, 1}, {1, 1, 1}, {2, 1, 1}, {3, 1, 1},
|
||||
{4, 1, 1}, {1, 4, 1}, {4, 1, 4}, {1, 4, 4},
|
||||
{0, 2, 1}, {1, 2, 1}, {2, 2, 1}, {3, 2, 1},
|
||||
{4, 2, 1}, {2, 4, 1}, {4, 2, 4}, {2, 4, 4},
|
||||
{0, 3, 1}, {1, 3, 1}, {2, 3, 1}, {3, 3, 1},
|
||||
{4, 3, 1}, {3, 4, 1}, {4, 3, 4}, {3, 4, 4},
|
||||
{0, 0, 2}, {1, 0, 2}, {2, 0, 2}, {3, 0, 2},
|
||||
{4, 0, 2}, {0, 4, 2}, {2, 0, 4}, {3, 0, 4},
|
||||
{0, 1, 2}, {1, 1, 2}, {2, 1, 2}, {3, 1, 2},
|
||||
{4, 1, 2}, {1, 4, 2}, {2, 1, 4}, {3, 1, 4},
|
||||
{0, 2, 2}, {1, 2, 2}, {2, 2, 2}, {3, 2, 2},
|
||||
{4, 2, 2}, {2, 4, 2}, {2, 2, 4}, {3, 2, 4},
|
||||
{0, 3, 2}, {1, 3, 2}, {2, 3, 2}, {3, 3, 2},
|
||||
{4, 3, 2}, {3, 4, 2}, {2, 3, 4}, {3, 3, 4},
|
||||
{0, 0, 3}, {1, 0, 3}, {2, 0, 3}, {3, 0, 3},
|
||||
{4, 0, 3}, {0, 4, 3}, {0, 0, 4}, {1, 0, 4},
|
||||
{0, 1, 3}, {1, 1, 3}, {2, 1, 3}, {3, 1, 3},
|
||||
{4, 1, 3}, {1, 4, 3}, {0, 1, 4}, {1, 1, 4},
|
||||
{0, 2, 3}, {1, 2, 3}, {2, 2, 3}, {3, 2, 3},
|
||||
{4, 2, 3}, {2, 4, 3}, {0, 2, 4}, {1, 2, 4},
|
||||
{0, 3, 3}, {1, 3, 3}, {2, 3, 3}, {3, 3, 3},
|
||||
{4, 3, 3}, {3, 4, 3}, {0, 3, 4}, {1, 3, 4}
|
||||
};
|
||||
|
||||
// packed quint-value for every unpacked quint-triplet
|
||||
@@ -19,25 +19,29 @@
|
||||
* @brief Functions and data declarations.
|
||||
*/
|
||||
|
||||
#ifndef ASTC_CODEC_INTERNALS_INCLUDED
|
||||
#define ASTC_CODEC_INTERNALS_INCLUDED
|
||||
#ifndef ASTCENC_INTERNAL_INCLUDED
|
||||
#define ASTCENC_INTERNAL_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "astc_mathlib.h"
|
||||
|
||||
// Temporary workaround to build machine still running VS2013
|
||||
// Version 1910 is Visual Studio 2017
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1910)
|
||||
#define NORETURN [[noreturn]]
|
||||
#else
|
||||
#define NORETURN
|
||||
#define __func__ __FUNCTION__
|
||||
#ifndef ASTCENC_SSE
|
||||
#error ERROR: ASTCENC_SSE not defined
|
||||
#endif
|
||||
|
||||
#ifndef ASTCENC_POPCNT
|
||||
#error ERROR: ASTCENC_POPCNT not defined
|
||||
#endif
|
||||
|
||||
#ifndef ASTCENC_AVX
|
||||
#error ERROR: ASTCENC_AVX not defined
|
||||
#endif
|
||||
|
||||
#include "astcenc.h"
|
||||
#include "astcenc_mathlib.h"
|
||||
|
||||
// ASTC parameters
|
||||
#define MAX_TEXELS_PER_BLOCK 216
|
||||
#define MAX_WEIGHTS_PER_BLOCK 64
|
||||
@@ -51,32 +55,10 @@
|
||||
#define MAX_DECIMATION_MODES 87
|
||||
#define MAX_WEIGHT_MODES 2048
|
||||
|
||||
// error reporting for codec internal errors.
|
||||
#define ASTC_CODEC_INTERNAL_ERROR() astc_codec_internal_error(__FILE__, __LINE__)
|
||||
NORETURN void astc_codec_internal_error(const char *filename, int linenumber);
|
||||
|
||||
// uncomment this macro to enable checking for inappropriate NaNs;
|
||||
// works on Linux only, and slows down encoding significantly.
|
||||
// #define DEBUG_CAPTURE_NAN
|
||||
|
||||
// uncomment this macro to enable the ability to log diagnostics using the
|
||||
// -diag command line switch, which is useful for bug hunting in the encoder
|
||||
// #define DEBUG_PRINT_DIAGNOSTICS
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
extern int print_diagnostics;
|
||||
extern int print_tile_errors;
|
||||
extern int print_statistics;
|
||||
#endif
|
||||
|
||||
enum astc_decode_mode
|
||||
{
|
||||
DECODE_LDR_SRGB,
|
||||
DECODE_LDR,
|
||||
DECODE_HDR,
|
||||
DECODE_HDRA
|
||||
};
|
||||
|
||||
/*
|
||||
Partition table representation:
|
||||
For each block size, we have 3 tables, each with 1024 partitionings;
|
||||
@@ -367,7 +349,7 @@ enum endpoint_formats
|
||||
FMT_RGBA = 12,
|
||||
FMT_RGBA_DELTA = 13,
|
||||
FMT_HDR_RGB_LDR_ALPHA = 14,
|
||||
FMT_HDR_RGBA = 15,
|
||||
FMT_HDR_RGBA = 15
|
||||
};
|
||||
|
||||
struct symbolic_compressed_block
|
||||
@@ -391,15 +373,6 @@ struct physical_compressed_block
|
||||
uint8_t data[16];
|
||||
};
|
||||
|
||||
/* ============================================================================
|
||||
Functions for printing build info and help messages
|
||||
============================================================================ */
|
||||
void astcenc_print_header();
|
||||
|
||||
void astcenc_print_shorthelp();
|
||||
|
||||
void astcenc_print_longhelp();
|
||||
|
||||
/* ============================================================================
|
||||
Functions and data pertaining to quantization and encoding
|
||||
============================================================================ */
|
||||
@@ -643,62 +616,15 @@ struct astc_codec_image
|
||||
float4 *input_averages;
|
||||
float4 *input_variances;
|
||||
float *input_alpha_averages;
|
||||
|
||||
int linearize_srgb;
|
||||
int rgb_force_use_of_hdr;
|
||||
int alpha_force_use_of_hdr;
|
||||
};
|
||||
|
||||
astc_codec_image* alloc_image(
|
||||
int bitness,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int zsize,
|
||||
int padding);
|
||||
|
||||
void free_image(
|
||||
astc_codec_image* img);
|
||||
|
||||
void fill_image_padding_area(
|
||||
astc_codec_image* img);
|
||||
|
||||
int determine_image_channels(
|
||||
const astc_codec_image* img);
|
||||
|
||||
// helper functions to prepare an ASTC image object from a flat array
|
||||
// Used by the image loaders in "astc_file_load_store.cpp"
|
||||
astc_codec_image* astc_img_from_floatx4_array(
|
||||
const float* image,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int padding,
|
||||
int y_flip);
|
||||
|
||||
astc_codec_image*astc_img_from_unorm8x4_array(
|
||||
const uint8_t*imageptr,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int padding,
|
||||
int y_flip);
|
||||
|
||||
// helper functions to prepare a flat array from an ASTC image object.
|
||||
// the array is allocated with malloc(); caller needs to use free()
|
||||
// to free it.
|
||||
float* floatx4_array_from_astc_img(
|
||||
const astc_codec_image* img,
|
||||
int y_flip);
|
||||
|
||||
uint8_t* unorm8x4_array_from_astc_img(
|
||||
const astc_codec_image* img,
|
||||
int y_flip);
|
||||
|
||||
// the entries here : 0=red, 1=green, 2=blue, 3=alpha, 4=0.0, 5=1.0
|
||||
struct swizzlepattern
|
||||
struct astcenc_context
|
||||
{
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
astcenc_config config;
|
||||
block_size_descriptor* bsd;
|
||||
unsigned int thread_count;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -723,60 +649,12 @@ void compute_averages_and_variances(
|
||||
int avg_var_kernel_radius,
|
||||
int alpha_kernel_radius,
|
||||
int need_srgb_transform,
|
||||
swizzlepattern swz,
|
||||
astcenc_swizzle swz,
|
||||
int thread_count);
|
||||
|
||||
/*
|
||||
Functions to load image from file.
|
||||
If successful, return an astc_codec_image object.
|
||||
If unsuccessful, returns nullptr.
|
||||
|
||||
*result is used to return a result. In case of a successfully loaded image, bits[2:0]
|
||||
of *result indicate how many components are present, and bit[7] indicate whether
|
||||
the input image was LDR or HDR (0=LDR, 1=HDR).
|
||||
|
||||
In case of failure, *result is given a negative value.
|
||||
*/
|
||||
|
||||
astc_codec_image* astc_codec_load_image(
|
||||
const char* filename,
|
||||
int padding,
|
||||
int y_flip,
|
||||
int linearize_srgb,
|
||||
int rgb_force_use_of_hdr,
|
||||
int alpha_force_use_of_hdr,
|
||||
int* result);
|
||||
|
||||
int astc_codec_store_image(
|
||||
const astc_codec_image* output_image,
|
||||
const char* output_filename,
|
||||
const char** file_format_name,
|
||||
int y_flip);
|
||||
|
||||
int get_output_filename_enforced_bitness(
|
||||
const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Compute error metrics comparing two images.
|
||||
*
|
||||
* @param compute_hdr_metrics Non-zero if HDR metrics should be computed.
|
||||
* @param input_components The number of input color components.
|
||||
* @param img1 The original iamge.
|
||||
* @param img2 The compressed image.
|
||||
* @param fstop_lo The low exposure fstop (HDR only).
|
||||
* @param fstop_hi The high exposure fstop (HDR only).
|
||||
* @param show_psnr Non-zero if metrics should be logged to stdout.
|
||||
*/
|
||||
void compute_error_metrics(
|
||||
int compute_hdr_metrics,
|
||||
int input_components,
|
||||
const astc_codec_image* img1,
|
||||
const astc_codec_image* img2,
|
||||
int fstop_lo,
|
||||
int fstop_hi);
|
||||
|
||||
// fetch an image-block from the input file
|
||||
void fetch_imageblock(
|
||||
astcenc_profile decode_mode,
|
||||
const astc_codec_image* img,
|
||||
imageblock* pb, // picture-block to initialize with image data
|
||||
const block_size_descriptor* bsd,
|
||||
@@ -784,7 +662,7 @@ void fetch_imageblock(
|
||||
int xpos,
|
||||
int ypos,
|
||||
int zpos,
|
||||
swizzlepattern swz);
|
||||
astcenc_swizzle swz);
|
||||
|
||||
// write an image block to the output file buffer.
|
||||
// the data written are taken from orig_data.
|
||||
@@ -796,7 +674,7 @@ void write_imageblock(
|
||||
int xpos,
|
||||
int ypos,
|
||||
int zpos,
|
||||
swizzlepattern swz);
|
||||
astcenc_swizzle swz);
|
||||
|
||||
// helper function to check whether a given picture-block has alpha that is not
|
||||
// just uniformly 1.
|
||||
@@ -883,8 +761,7 @@ int pack_color_endpoints(
|
||||
|
||||
// unpack a pair of color endpoints from a series of integers.
|
||||
void unpack_color_endpoints(
|
||||
const astc_codec_image* image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
int format,
|
||||
int quantization_level,
|
||||
const int* input,
|
||||
@@ -966,9 +843,9 @@ void recompute_ideal_colors(
|
||||
const error_weight_block* ewb);
|
||||
|
||||
void expand_block_artifact_suppression(
|
||||
int xdim,
|
||||
int ydim,
|
||||
int zdim,
|
||||
unsigned int xdim,
|
||||
unsigned int ydim,
|
||||
unsigned int zdim,
|
||||
error_weighting_params* ewp);
|
||||
|
||||
// functions pertaining to weight alignment
|
||||
@@ -1001,7 +878,7 @@ void compute_angular_endpoints_2planes(
|
||||
|
||||
float compress_symbolic_block(
|
||||
const astc_codec_image* input_image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
const block_size_descriptor* bsd,
|
||||
const error_weighting_params* ewp,
|
||||
const imageblock* blk,
|
||||
@@ -1009,8 +886,7 @@ float compress_symbolic_block(
|
||||
compress_symbolic_block_buffers* tmpbuf);
|
||||
|
||||
void decompress_symbolic_block(
|
||||
const astc_codec_image* image,
|
||||
astc_decode_mode decode_mode,
|
||||
astcenc_profile decode_mode,
|
||||
const block_size_descriptor* bsd,
|
||||
int xpos,
|
||||
int ypos,
|
||||
@@ -1036,47 +912,6 @@ uint16_t lns_to_sf16(
|
||||
/* ============================================================================
|
||||
Platform-specific functions
|
||||
============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief Get the current time.
|
||||
*
|
||||
* @returns The current time in seconds since arbitrary epoch.
|
||||
*/
|
||||
double get_time();
|
||||
|
||||
/**
|
||||
* @brief Get the number of CPU cores.
|
||||
*
|
||||
* @returns The number of online or onlineable CPU cores in the system.
|
||||
*/
|
||||
int get_cpu_count();
|
||||
|
||||
/**
|
||||
* @brief Delete (unlink) a file on the filesystem.
|
||||
*
|
||||
|* @param filename The file to delete.
|
||||
*
|
||||
* @returns Zero on success, non-zero otherwise.
|
||||
*/
|
||||
int unlink_file(const char *filename);
|
||||
|
||||
/**
|
||||
* @brief Launch N worker threads and wait for them to complete.
|
||||
*
|
||||
* All threads run the same thread function, and have the same thread payload,
|
||||
* but are given a unique thread ID (0 .. N-1) as a parameter to the run
|
||||
* function to allow thread-specific behavior.
|
||||
*
|
||||
|* @param thread_count The number of threads to spawn.
|
||||
* @param func The function to execute. Must have the signature:
|
||||
* void (int thread_count, int thread_id, void* payload)
|
||||
* @param payload Pointer to an opaque thread payload object.
|
||||
*/
|
||||
void launch_threads(
|
||||
int thread_count,
|
||||
void (*func)(int, int, void*),
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* @brief Run-time detection if the host CPU supports SSE 4.2.
|
||||
* @returns Zero if not supported, positive value if it is.
|
||||
@@ -1096,15 +931,27 @@ int cpu_supports_popcnt();
|
||||
int cpu_supports_avx2();
|
||||
|
||||
/**
|
||||
* @brief The main entry point.
|
||||
* @brief Get the number of CPU cores.
|
||||
*
|
||||
* @param argc The number of arguments.
|
||||
* @param argb The array of command line arguments.
|
||||
*
|
||||
* @returns Zero on success, non-zero otherwise.
|
||||
* @returns The number of online or onlineable CPU cores in the system.
|
||||
*/
|
||||
int astc_main(
|
||||
int argc,
|
||||
char** argv);
|
||||
int get_cpu_count();
|
||||
|
||||
/**
|
||||
* @brief Launch N worker threads and wait for them to complete.
|
||||
*
|
||||
* All threads run the same thread function, and have the same thread payload,
|
||||
* but are given a unique thread ID (0 .. N-1) as a parameter to the run
|
||||
* function to allow thread-specific behavior.
|
||||
*
|
||||
|* @param thread_count The number of threads to spawn.
|
||||
* @param func The function to execute. Must have the signature:
|
||||
* void (int thread_count, int thread_id, void* payload)
|
||||
* @param payload Pointer to an opaque thread payload object.
|
||||
*/
|
||||
void launch_threads(
|
||||
int thread_count,
|
||||
void (*func)(int, int, void*),
|
||||
void *payload);
|
||||
|
||||
#endif
|
||||
@@ -27,7 +27,7 @@
|
||||
* how well the bitmaps matched.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
// for k++ means, we need pseudo-random numbers, however using random numbers
|
||||
// directly results in unreproducible encoding results. As such, we will
|
||||
@@ -15,7 +15,7 @@
|
||||
// under the License.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "astc_mathlib.h"
|
||||
#include "astcenc_mathlib.h"
|
||||
|
||||
float3 cross(float3 p, float3 q)
|
||||
{
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
|
||||
#if ASTC_SSE != 0 || ASTC_AVX != 0
|
||||
#if ASTCENC_SSE != 0 || ASTCENC_AVX != 0
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
@@ -100,7 +100,7 @@ float atan2(float y, float x);
|
||||
*/
|
||||
static inline float fabs(float val)
|
||||
{
|
||||
#if (ASTC_SSE >= 20) && USE_SCALAR_SSE
|
||||
#if (ASTCENC_SSE >= 20) && USE_SCALAR_SSE
|
||||
static const union {
|
||||
uint32_t u[4];
|
||||
__m128 v;
|
||||
@@ -125,7 +125,7 @@ static inline float fabs(float val)
|
||||
*/
|
||||
static inline float fmin(float p, float q)
|
||||
{
|
||||
#if (ASTC_SSE >= 20) && USE_SCALAR_SSE
|
||||
#if (ASTCENC_SSE >= 20) && USE_SCALAR_SSE
|
||||
return _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(p),_mm_set_ss(q)));
|
||||
#else
|
||||
return p < q ? p : q;
|
||||
@@ -146,7 +146,7 @@ static inline float fmin(float p, float q)
|
||||
*/
|
||||
static inline float fmax(float p, float q)
|
||||
{
|
||||
#if (ASTC_SSE >= 20) && USE_SCALAR_SSE
|
||||
#if (ASTCENC_SSE >= 20) && USE_SCALAR_SSE
|
||||
return _mm_cvtss_f32(_mm_max_ss(_mm_set_ss(p),_mm_set_ss(q)));
|
||||
#else
|
||||
return q < p ? p : q;
|
||||
@@ -258,7 +258,7 @@ static inline float srgb_transform(float val)
|
||||
*/
|
||||
static inline float flt_rte(float val)
|
||||
{
|
||||
#if (ASTC_SSE >= 42)
|
||||
#if (ASTCENC_SSE >= 42)
|
||||
const int flag = _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC;
|
||||
__m128 tmp = _mm_set_ss(val);
|
||||
tmp = _mm_round_ss(tmp, tmp, flag);
|
||||
@@ -277,7 +277,7 @@ static inline float flt_rte(float val)
|
||||
*/
|
||||
static inline float flt_rd(float val)
|
||||
{
|
||||
#if (ASTC_SSE >= 42)
|
||||
#if (ASTCENC_SSE >= 42)
|
||||
const int flag = _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC;
|
||||
__m128 tmp = _mm_set_ss(val);
|
||||
tmp = _mm_round_ss(tmp, tmp, flag);
|
||||
@@ -296,7 +296,7 @@ static inline float flt_rd(float val)
|
||||
*/
|
||||
static inline int flt2int_rtn(float val)
|
||||
{
|
||||
#if (ASTC_SSE >= 42) && USE_SCALAR_SSE
|
||||
#if (ASTCENC_SSE >= 42) && USE_SCALAR_SSE
|
||||
return _mm_cvt_ss2si(_mm_set_ss(val));
|
||||
#else
|
||||
return (int)(val + 0.5f);
|
||||
@@ -312,7 +312,7 @@ static inline int flt2int_rtn(float val)
|
||||
*/
|
||||
static inline int flt2int_rd(float val)
|
||||
{
|
||||
#if (ASTC_SSE >= 42) && USE_SCALAR_SSE
|
||||
#if (ASTCENC_SSE >= 42) && USE_SCALAR_SSE
|
||||
return _mm_cvt_ss2si(_mm_set_ss(val));
|
||||
#else
|
||||
return (int)(val);
|
||||
@@ -328,7 +328,7 @@ static inline int flt2int_rd(float val)
|
||||
*/
|
||||
static inline int popcount(uint64_t p)
|
||||
{
|
||||
#if ASTC_POPCNT >= 1
|
||||
#if ASTCENC_POPCNT >= 1
|
||||
return (int)_mm_popcnt_u64(p);
|
||||
#else
|
||||
uint64_t mask1 = 0x5555555555555555ULL;
|
||||
@@ -353,7 +353,7 @@ static inline int popcount(uint64_t p)
|
||||
*/
|
||||
static inline float rsqrt(float val)
|
||||
{
|
||||
#if (ASTC_SSE >= 20) && USE_SCALAR_SSE
|
||||
#if (ASTCENC_SSE >= 20) && USE_SCALAR_SSE
|
||||
// FIXME: setting val = 99 causes a crash, which it really shouldn't.
|
||||
return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(val)));
|
||||
#else
|
||||
@@ -370,7 +370,7 @@ static inline float rsqrt(float val)
|
||||
*/
|
||||
static inline float sqrt(float val)
|
||||
{
|
||||
#if (ASTC_SSE >= 20) && USE_SCALAR_SSE
|
||||
#if (ASTCENC_SSE >= 20) && USE_SCALAR_SSE
|
||||
return 1.0f * astc::rsqrt(val);
|
||||
#else
|
||||
return std::sqrt(val);
|
||||
@@ -386,7 +386,7 @@ static inline float sqrt(float val)
|
||||
*/
|
||||
static inline float recip(float val)
|
||||
{
|
||||
#if (ASTC_SSE >= 20) && USE_SCALAR_SSE
|
||||
#if (ASTCENC_SSE >= 20) && USE_SCALAR_SSE
|
||||
return _mm_cvtss_f32(_mm_rcp_ss(_mm_set_ss(val)));
|
||||
#else
|
||||
return 1.0f / val;
|
||||
@@ -19,7 +19,7 @@
|
||||
* @brief Soft-float library for IEEE-754.
|
||||
*/
|
||||
|
||||
#include "astc_mathlib.h"
|
||||
#include "astcenc_mathlib.h"
|
||||
|
||||
/******************************************
|
||||
helper functions and their lookup tables
|
||||
@@ -226,7 +226,7 @@ sf16 sf32_to_sf16(sf32 inp, roundmode rmode)
|
||||
switch (idx)
|
||||
{
|
||||
/*
|
||||
Positive number which may be Infinity or NaN.
|
||||
Positive number which may be Infinity or NaN.
|
||||
We need to check whether it is NaN; if it is, quieten it by setting the top bit of the mantissa.
|
||||
(If we don't do this quieting, then a NaN that is distinguished only by having
|
||||
its low-order bits set, would be turned into an INF. */
|
||||
@@ -19,7 +19,7 @@
|
||||
* @brief Functions for generating partition tables on demand.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/*
|
||||
Produce a canonicalized representation of a partition pattern
|
||||
@@ -22,7 +22,7 @@
|
||||
* encoding
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/**
|
||||
* @brief Structure containing packed percentile metadata.
|
||||
+7
-60
@@ -19,11 +19,7 @@
|
||||
* @brief Functions to pick best ASTC endpoint for a block.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/*
|
||||
functions to determine, for a given partitioning, which color endpoint formats are the best to use.
|
||||
@@ -73,15 +69,8 @@ static void compute_color_error_for_every_integer_count_and_quantization_level(
|
||||
float4 ep0 = ep->endpt0[partition_index];
|
||||
float4 ep1 = ep->endpt1[partition_index];
|
||||
|
||||
float ep0_max = MAX(MAX(ep0.x, ep0.y), ep0.z);
|
||||
float ep0_min = MIN(MIN(ep0.x, ep0.y), ep0.z);
|
||||
float ep1_max = MAX(MAX(ep1.x, ep1.y), ep1.z);
|
||||
float ep1_min = MIN(MIN(ep1.x, ep1.y), ep1.z);
|
||||
|
||||
ep0_min = MAX(ep0_min, 0.0f);
|
||||
ep1_min = MAX(ep1_min, 0.0f);
|
||||
ep0_max = MAX(ep0_max, 1e-10f);
|
||||
ep1_max = MAX(ep1_max, 1e-10f);
|
||||
|
||||
float4 error_weight = error_weightings[partition_index];
|
||||
|
||||
@@ -117,26 +106,14 @@ static void compute_color_error_for_every_integer_count_and_quantization_level(
|
||||
ep1_range_error_low.w = MIN(0.0f, ep1.w);
|
||||
|
||||
float4 sum_range_error =
|
||||
(ep0_range_error_low * ep0_range_error_low) + (ep1_range_error_low * ep1_range_error_low) + (ep0_range_error_high * ep0_range_error_high) + (ep1_range_error_high * ep1_range_error_high);
|
||||
float rgb_range_error = dot(float3(sum_range_error.x, sum_range_error.y, sum_range_error.z), float3(error_weight.x, error_weight.y, error_weight.z)) * 0.5f * partition_size;
|
||||
(ep0_range_error_low * ep0_range_error_low) +
|
||||
(ep1_range_error_low * ep1_range_error_low) +
|
||||
(ep0_range_error_high * ep0_range_error_high) +
|
||||
(ep1_range_error_high * ep1_range_error_high);
|
||||
float rgb_range_error = dot(float3(sum_range_error.x, sum_range_error.y, sum_range_error.z),
|
||||
float3(error_weight.x, error_weight.y, error_weight.z)) * 0.5f * partition_size;
|
||||
float alpha_range_error = sum_range_error.w * error_weight.w * 0.5f * partition_size;
|
||||
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
printf("%s : partition=%d\nrgb-error_wt=%f alpha_error_wt=%f\n", __func__, partition_index, error_weight_rgbsum, error_weight.w);
|
||||
|
||||
printf("ep0 = %f %f %f %f\n", ep0.x, ep0.y, ep0.z, ep0.w);
|
||||
printf("ep1 = %f %f %f %f\n", ep1.x, ep1.y, ep1.z, ep1.w);
|
||||
|
||||
|
||||
printf("rgb_range_error = %f, alpha_range_error = %f\n", rgb_range_error, alpha_range_error);
|
||||
|
||||
printf("rgb-luma-error: %f\n", eci->rgb_luma_error);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (encode_hdr_rgb)
|
||||
{
|
||||
|
||||
@@ -253,11 +230,6 @@ static void compute_color_error_for_every_integer_count_and_quantization_level(
|
||||
float alpha_quantization_error = error_weight.w * base_quant_error * 2.0f;
|
||||
float rgba_quantization_error = rgb_quantization_error + alpha_quantization_error;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("rgba-quant = %f can_offset_encode=%d\n", rgba_quantization_error, eci->can_offset_encode);
|
||||
#endif
|
||||
|
||||
// for 8 integers, we have two encodings: one with HDR alpha and another one
|
||||
// with LDR alpha.
|
||||
|
||||
@@ -280,16 +252,6 @@ static void compute_color_error_for_every_integer_count_and_quantization_level(
|
||||
float hdr_luminance_error = (rgb_quantization_error * mode23mult) + rgb_range_error + eci->alpha_drop_error + eci->luminance_error;
|
||||
best_error[i][0] = hdr_luminance_error;
|
||||
format_of_choice[i][0] = FMT_HDR_LUMINANCE_LARGE_RANGE;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
printf("(hdr) quant-level=%d ints=%d format=%d error=%f\n", i, j, format_of_choice[i][j], best_error[i][j]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -315,11 +277,6 @@ static void compute_color_error_for_every_integer_count_and_quantization_level(
|
||||
float alpha_quantization_error = error_weight.w * base_quant_error;
|
||||
float rgba_quantization_error = rgb_quantization_error + alpha_quantization_error;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
printf("rgba-quant = %f can_offset_encode=%d\n", rgba_quantization_error, eci->can_offset_encode);
|
||||
#endif
|
||||
|
||||
// for 8 integers, the available encodings are:
|
||||
// full LDR RGB-Alpha
|
||||
float full_ldr_rgba_error = rgba_quantization_error;
|
||||
@@ -377,16 +334,6 @@ static void compute_color_error_for_every_integer_count_and_quantization_level(
|
||||
|
||||
best_error[i][0] = luminance_error;
|
||||
format_of_choice[i][0] = FMT_LUMINANCE;
|
||||
|
||||
#ifdef DEBUG_PRINT_DIAGNOSTICS
|
||||
if (print_diagnostics)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
printf(" (ldr) quant-level=%d ints=%d format=%d error=%f\n", i, j, format_of_choice[i][j], best_error[i][j]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@
|
||||
* task has also been provided.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/* ============================================================================
|
||||
Platform code for Windows using the Win32 APIs.
|
||||
@@ -64,16 +64,6 @@ static int pthread_join(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
double get_time()
|
||||
{
|
||||
FILETIME tv;
|
||||
GetSystemTimeAsFileTime(&tv);
|
||||
unsigned long long ticks = tv.dwHighDateTime;
|
||||
ticks = (ticks << 32) | tv.dwLowDateTime;
|
||||
return ((double)ticks) / 1.0e7;
|
||||
}
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
int get_cpu_count()
|
||||
{
|
||||
@@ -82,13 +72,6 @@ int get_cpu_count()
|
||||
return sysinfo.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
int unlink_file(const char *filename)
|
||||
{
|
||||
BOOL res = DeleteFileA(filename);
|
||||
return (res ? 0 : -1);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Platform code for an platform using POSIX APIs.
|
||||
============================================================================ */
|
||||
@@ -98,26 +81,12 @@ int unlink_file(const char *filename)
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
double get_time()
|
||||
{
|
||||
timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
return (double)tv.tv_sec + (double)tv.tv_usec * 1.0e-6;
|
||||
}
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
int get_cpu_count()
|
||||
{
|
||||
return sysconf(_SC_NPROCESSORS_ONLN);
|
||||
}
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
int unlink_file(const char *filename)
|
||||
{
|
||||
return unlink(filename);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -21,7 +21,7 @@
|
||||
* This module contains functions for querying the host extended ISA support.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenccli_internal.h"
|
||||
|
||||
static int g_cpu_has_sse42 = -1;
|
||||
static int g_cpu_has_avx2 = -1;
|
||||
@@ -93,4 +93,4 @@ int cpu_supports_avx2()
|
||||
detect_cpu_isa();
|
||||
|
||||
return g_cpu_has_avx2;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
* @brief Functions and data tables for numeric quantization..
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
const uint8_t color_quantization_tables[21][256] = {
|
||||
{
|
||||
@@ -19,7 +19,7 @@
|
||||
* @brief Functions for converting between symbolic and physical encodings.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
// routine to write up to 8 bits
|
||||
static inline void write_bits(
|
||||
@@ -42,7 +42,7 @@
|
||||
* (perhaps 1/8 for low levels of quantization).
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
@@ -177,7 +177,7 @@ static void compute_lowest_and_highest_weight(
|
||||
// TODO: Add AVX2 version of this; SSE4.2 vectorizes almost perfectly in terms
|
||||
// of user-visible speedup. Might need to change the length of max_angular
|
||||
// steps to be a multiple of 8 though ...
|
||||
#if ASTC_SSE >= 42
|
||||
#if ASTCENC_SSE >= 42
|
||||
// Arrays are always multiple of 4, so this is safe even if overshoot max
|
||||
for (int sp = 0; sp < max_angular_steps; sp += 4)
|
||||
{
|
||||
@@ -349,8 +349,8 @@ void compute_angular_endpoints_for_quantization_levels(
|
||||
uint8_t cut_low_weight[40];
|
||||
for (i = 0; i < (max_quantization_steps + 4); i++)
|
||||
{
|
||||
best_errors[i] = 1e30f;
|
||||
best_scale[i] = -1; // Indicates no solution found
|
||||
best_errors[i] = 1e30f;
|
||||
cut_low_weight[i] = 0;
|
||||
}
|
||||
|
||||
@@ -410,10 +410,12 @@ void compute_angular_endpoints_for_quantization_levels(
|
||||
int bsi = best_scale[q];
|
||||
|
||||
// Did we find anything?
|
||||
// TODO: Can we do better than bsi = 0 here. We should at least
|
||||
// propagate an error (and move the printf into the CLI).
|
||||
if (bsi < 0)
|
||||
{
|
||||
printf("ERROR: Unable to find an encoding within the specified error limits\n");
|
||||
ASTC_CODEC_INTERNAL_ERROR();
|
||||
printf("WARNING: Unable to find encoding within specified error limit\n");
|
||||
bsi = 0;
|
||||
}
|
||||
|
||||
float stepsize = stepsizes[bsi];
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
* @brief Data tables for quantization transfer.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
#define _ 0 // using _ to indicate an entry that will not be used.
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
* @brief Functions for computing image error metrics.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "astcenccli_internal.h"
|
||||
|
||||
/**
|
||||
* @brief An accumulator using Kahan compensated floating-point summation.
|
||||
*
|
||||
@@ -126,8 +126,8 @@ static float mpsnr_sumdiff(
|
||||
void compute_error_metrics(
|
||||
int compute_hdr_metrics,
|
||||
int input_components,
|
||||
const astc_codec_image* img1,
|
||||
const astc_codec_image* img2,
|
||||
const astcenc_image* img1,
|
||||
const astcenc_image* img2,
|
||||
int fstop_lo,
|
||||
int fstop_hi
|
||||
) {
|
||||
@@ -139,36 +139,36 @@ void compute_error_metrics(
|
||||
kahan_accum4 log_errorsum;
|
||||
kahan_accum4 mpsnr_errorsum;
|
||||
|
||||
int xsize = MIN(img1->xsize, img2->xsize);
|
||||
int ysize = MIN(img1->ysize, img2->ysize);
|
||||
int zsize = MIN(img1->zsize, img2->zsize);
|
||||
unsigned int dim_x = MIN(img1->dim_x, img2->dim_x);
|
||||
unsigned int dim_y = MIN(img1->dim_y, img2->dim_y);
|
||||
unsigned int dim_z = MIN(img1->dim_z, img2->dim_z);
|
||||
|
||||
if (img1->xsize != img2->xsize ||
|
||||
img1->ysize != img2->ysize ||
|
||||
img1->zsize != img2->zsize)
|
||||
if (img1->dim_x != img2->dim_x ||
|
||||
img1->dim_y != img2->dim_y ||
|
||||
img1->dim_z != img2->dim_z)
|
||||
{
|
||||
printf("Warning: Only intersection of images will be compared:\n"
|
||||
printf("WARNING: Only intersection of images will be compared:\n"
|
||||
" Image 1: %dx%dx%d\n"
|
||||
" Image 2: %dx%dx%d\n",
|
||||
img1->xsize, img1->ysize, img1->zsize,
|
||||
img2->xsize, img2->ysize, img2->zsize);
|
||||
img1->dim_x, img1->dim_y, img1->dim_z,
|
||||
img2->dim_x, img2->dim_y, img2->dim_z);
|
||||
}
|
||||
|
||||
int img1pad = img1->padding;
|
||||
int img2pad = img2->padding;
|
||||
int img1pad = img1->dim_pad;
|
||||
int img2pad = img2->dim_pad;
|
||||
float rgb_peak = 0.0f;
|
||||
|
||||
for (int z = 0; z < zsize; z++)
|
||||
for (unsigned int z = 0; z < dim_z; z++)
|
||||
{
|
||||
for (int y = 0; y < ysize; y++)
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
int ze1 = (img1->zsize == 1) ? z : z + img1pad;
|
||||
int ze2 = (img2->zsize == 1) ? z : z + img2pad;
|
||||
int ze1 = (img1->dim_z == 1) ? z : z + img1pad;
|
||||
int ze2 = (img2->dim_z == 1) ? z : z + img2pad;
|
||||
|
||||
int ye1 = y + img1pad;
|
||||
int ye2 = y + img2pad;
|
||||
|
||||
for (int x = 0; x < xsize; x++)
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
float4 color1;
|
||||
float4 color2;
|
||||
@@ -255,7 +255,7 @@ void compute_error_metrics(
|
||||
}
|
||||
}
|
||||
|
||||
float pixels = (float)(xsize * ysize * zsize);
|
||||
float pixels = (float)(dim_x * dim_y * dim_z);
|
||||
float num = 0.0f;
|
||||
float alpha_num = 0.0f;
|
||||
float log_num = 0.0f;
|
||||
@@ -309,34 +309,34 @@ void compute_error_metrics(
|
||||
float rgb_psnr = psnr;
|
||||
|
||||
printf("Error metrics\n");
|
||||
printf("-------------\n");
|
||||
printf("=============\n\n");
|
||||
|
||||
if (channelmask & 8)
|
||||
{
|
||||
printf("PSNR (LDR-RGBA): %9.6f dB\n", (double)psnr);
|
||||
printf(" PSNR (LDR-RGBA): %9.6f dB\n", (double)psnr);
|
||||
|
||||
float alpha_psnr;
|
||||
if (alpha_num == 0.0f)
|
||||
alpha_psnr = 999.0f;
|
||||
else
|
||||
alpha_psnr = 10.0f * log10f(denom / alpha_num);
|
||||
printf("Alpha-weighted PSNR: %9.6f dB\n", (double)alpha_psnr);
|
||||
printf(" Alpha-weighted PSNR: %9.6f dB\n", (double)alpha_psnr);
|
||||
|
||||
float rgb_num = errorsum.sum.x + errorsum.sum.y + errorsum.sum.z;
|
||||
if (rgb_num == 0.0f)
|
||||
rgb_psnr = 999.0f;
|
||||
else
|
||||
rgb_psnr = 10.0f * log10f(pixels * 3.0f / rgb_num);
|
||||
printf("PSNR (LDR-RGB): %9.6f dB\n", (double)rgb_psnr);
|
||||
printf(" PSNR (LDR-RGB): %9.6f dB\n", (double)rgb_psnr);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("PSNR (LDR-RGB): %9.6f dB\n", (double)psnr);
|
||||
printf(" PSNR (LDR-RGB): %9.6f dB\n", (double)psnr);
|
||||
}
|
||||
|
||||
if (compute_hdr_metrics)
|
||||
{
|
||||
printf("PSNR (RGB norm to peak): %9.6f dB (peak %f)\n",
|
||||
printf(" PSNR (RGB norm to peak): %9.6f dB (peak %f)\n",
|
||||
(double)(rgb_psnr + 20.0f * log10f(rgb_peak)),
|
||||
(double)rgb_peak);
|
||||
|
||||
@@ -345,10 +345,12 @@ void compute_error_metrics(
|
||||
mpsnr = 999.0f;
|
||||
else
|
||||
mpsnr = 10.0f * log10f(mpsnr_denom / mpsnr_num);
|
||||
printf("mPSNR (RGB): %9.6f dB (fstops %+d to %+d)\n",
|
||||
printf(" mPSNR (RGB): %9.6f dB (fstops %+d to %+d)\n",
|
||||
(double)mpsnr, fstop_lo, fstop_hi);
|
||||
|
||||
float logrmse = astc::sqrt(log_num / pixels);
|
||||
printf("LogRMSE (RGB): %9.6f\n", (double)logrmse);
|
||||
printf(" LogRMSE (RGB): %9.6f\n", (double)logrmse);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2020 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Functions for creating in-memory ASTC image structures.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "astcenccli_internal.h"
|
||||
|
||||
astcenc_image *alloc_image(
|
||||
unsigned int bitness,
|
||||
unsigned int dim_x,
|
||||
unsigned int dim_y,
|
||||
unsigned int dim_z,
|
||||
unsigned int dim_pad
|
||||
) {
|
||||
astcenc_image *img = new astcenc_image;
|
||||
img->dim_x = dim_x;
|
||||
img->dim_y = dim_y;
|
||||
img->dim_z = dim_z;
|
||||
img->dim_pad = dim_pad;
|
||||
|
||||
unsigned int dim_ex = dim_x + 2 * dim_pad;
|
||||
unsigned int dim_ey = dim_y + 2 * dim_pad;
|
||||
unsigned int dim_ez = (dim_z == 1) ? 1 : dim_z + 2 * dim_pad;
|
||||
|
||||
assert(bitness == 8 || bitness == 16);
|
||||
if (bitness == 8)
|
||||
{
|
||||
img->data8 = new uint8_t **[dim_ez];
|
||||
img->data8[0] = new uint8_t *[dim_ez * dim_ey];
|
||||
img->data8[0][0] = new uint8_t[4 * dim_ez * dim_ey * dim_ex];
|
||||
memset(img->data8[0][0], 0, 4 * dim_ez * dim_ey * dim_ex);
|
||||
|
||||
for (unsigned int z = 1; z < dim_ez; z++)
|
||||
{
|
||||
img->data8[z] = img->data8[0] + z * dim_ey;
|
||||
img->data8[z][0] = img->data8[0][0] + 4 * z * dim_ex * dim_ey;
|
||||
}
|
||||
|
||||
for (unsigned int z = 0; z < dim_ez; z++)
|
||||
{
|
||||
for (unsigned int y = 1; y < dim_ey; y++)
|
||||
{
|
||||
img->data8[z][y] = img->data8[z][0] + 4 * y * dim_ex;
|
||||
}
|
||||
}
|
||||
|
||||
img->data16 = nullptr;
|
||||
}
|
||||
else if (bitness == 16)
|
||||
{
|
||||
img->data16 = new uint16_t **[dim_ez];
|
||||
img->data16[0] = new uint16_t *[dim_ez * dim_ey];
|
||||
img->data16[0][0] = new uint16_t[4 * dim_ez * dim_ey * dim_ex];
|
||||
memset(img->data16[0][0], 0, 8 * dim_ez * dim_ey * dim_ex);
|
||||
|
||||
for (unsigned int z = 1; z < dim_ez; z++)
|
||||
{
|
||||
img->data16[z] = img->data16[0] + z * dim_ey;
|
||||
img->data16[z][0] = img->data16[0][0] + 4 * z * dim_ex * dim_ey;
|
||||
}
|
||||
|
||||
for (unsigned int z = 0; z < dim_ez; z++)
|
||||
{
|
||||
for (unsigned int y = 1; y < dim_ey; y++)
|
||||
{
|
||||
img->data16[z][y] = img->data16[z][0] + 4 * y * dim_ex;
|
||||
}
|
||||
}
|
||||
|
||||
img->data8 = nullptr;
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
void free_image(astcenc_image * img)
|
||||
{
|
||||
if (img == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (img->data8)
|
||||
{
|
||||
delete[] img->data8[0][0];
|
||||
delete[] img->data8[0];
|
||||
delete[] img->data8;
|
||||
}
|
||||
|
||||
if (img->data16)
|
||||
{
|
||||
delete[] img->data16[0][0];
|
||||
delete[] img->data16[0];
|
||||
delete[] img->data16;
|
||||
}
|
||||
|
||||
delete img;
|
||||
}
|
||||
|
||||
|
||||
// fill the padding area of the input-file buffer with clamp-to-edge data
|
||||
// Done inefficiently, in that it will overwrite all the interior data at least once;
|
||||
// this is not considered a problem, since this makes up a very small part of total
|
||||
// running time.
|
||||
void fill_image_padding_area(astcenc_image * img)
|
||||
{
|
||||
if (img->dim_pad == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int dim_ex = img->dim_x + 2 * img->dim_pad;
|
||||
unsigned int dim_ey = img->dim_y + 2 * img->dim_pad;
|
||||
unsigned int dim_ez = (img->dim_z == 1) ? 1 : (img->dim_z + 2 * img->dim_pad);
|
||||
|
||||
unsigned int xmin = img->dim_pad;
|
||||
unsigned int ymin = img->dim_pad;
|
||||
unsigned int zmin = (img->dim_z == 1) ? 0 : img->dim_pad;
|
||||
unsigned int xmax = img->dim_x + img->dim_pad - 1;
|
||||
unsigned int ymax = img->dim_y + img->dim_pad - 1;
|
||||
unsigned int zmax = (img->dim_z == 1) ? 0 : img->dim_z + img->dim_pad - 1;
|
||||
|
||||
// This is a very simple implementation. Possible optimizations include:
|
||||
// * Testing if texel is outside the edge.
|
||||
// * Looping over texels that we know are outside the edge.
|
||||
if (img->data8)
|
||||
{
|
||||
for (unsigned int z = 0; z < dim_ez; z++)
|
||||
{
|
||||
int zc = MIN(MAX(z, zmin), zmax);
|
||||
for (unsigned int y = 0; y < dim_ey; y++)
|
||||
{
|
||||
int yc = MIN(MAX(y, ymin), ymax);
|
||||
for (unsigned int x = 0; x < dim_ex; x++)
|
||||
{
|
||||
int xc = MIN(MAX(x, xmin), xmax);
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
img->data8[z][y][4 * x + i] = img->data8[zc][yc][4 * xc + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (img->data16)
|
||||
{
|
||||
for (unsigned int z = 0; z < dim_ez; z++)
|
||||
{
|
||||
int zc = MIN(MAX(z, zmin), zmax);
|
||||
for (unsigned int y = 0; y < dim_ey; y++)
|
||||
{
|
||||
int yc = MIN(MAX(y, ymin), ymax);
|
||||
for (unsigned int x = 0; x < dim_ex; x++)
|
||||
{
|
||||
int xc = MIN(MAX(x, xmin), xmax);
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
img->data16[z][y][4 * x + i] = img->data16[zc][yc][4 * xc + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int determine_image_channels(const astcenc_image * img)
|
||||
{
|
||||
unsigned int dim_x = img->dim_x;
|
||||
unsigned int dim_y = img->dim_y;
|
||||
unsigned int dim_z = img->dim_z;
|
||||
|
||||
// scan through the image data
|
||||
// to determine how many color channels the image has.
|
||||
|
||||
int lum_mask;
|
||||
int alpha_mask;
|
||||
int alpha_mask_ref;
|
||||
if (img->data8)
|
||||
{
|
||||
alpha_mask_ref = 0xFF;
|
||||
alpha_mask = 0xFF;
|
||||
lum_mask = 0;
|
||||
for (unsigned int z = 0; z < dim_z; z++)
|
||||
{
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
int r = img->data8[z][y][4 * x];
|
||||
int g = img->data8[z][y][4 * x + 1];
|
||||
int b = img->data8[z][y][4 * x + 2];
|
||||
int a = img->data8[z][y][4 * x + 3];
|
||||
lum_mask |= (r ^ g) | (r ^ b);
|
||||
alpha_mask &= a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // (bitness == 16)
|
||||
{
|
||||
alpha_mask_ref = 0xFFFF;
|
||||
alpha_mask = 0xFFFF;
|
||||
lum_mask = 0;
|
||||
for (unsigned int z = 0; z < dim_z; z++)
|
||||
{
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
int r = img->data16[z][y][4 * x];
|
||||
int g = img->data16[z][y][4 * x + 1];
|
||||
int b = img->data16[z][y][4 * x + 2];
|
||||
int a = img->data16[z][y][4 * x + 3];
|
||||
lum_mask |= (r ^ g) | (r ^ b);
|
||||
alpha_mask &= (a ^ 0xC3FF); // a ^ 0xC3FF returns FFFF if and only if the input is 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int image_channels = 1 + (lum_mask == 0 ? 0 : 2) + (alpha_mask == alpha_mask_ref ? 0 : 1);
|
||||
|
||||
return image_channels;
|
||||
}
|
||||
|
||||
// initialize an astcenc_image data structure from a 2D array of RGBA float*4
|
||||
astcenc_image* astc_img_from_floatx4_array(
|
||||
const float* data,
|
||||
unsigned int dim_x,
|
||||
unsigned int dim_y,
|
||||
unsigned int dim_pad,
|
||||
bool y_flip
|
||||
) {
|
||||
astcenc_image* img = alloc_image(16, dim_x, dim_y, 1, dim_pad);
|
||||
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
unsigned int y_dst = y + dim_pad;
|
||||
unsigned int y_src = y_flip ? (dim_y - y - 1) : y;
|
||||
const float* src = data + 4 * dim_y * y_src;
|
||||
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
unsigned int x_dst = x + dim_pad;
|
||||
img->data16[0][y_dst][4 * x_dst] = float_to_sf16(src[4 * x], SF_NEARESTEVEN);
|
||||
img->data16[0][y_dst][4 * x_dst + 1] = float_to_sf16(src[4 * x + 1], SF_NEARESTEVEN);
|
||||
img->data16[0][y_dst][4 * x_dst + 2] = float_to_sf16(src[4 * x + 2], SF_NEARESTEVEN);
|
||||
img->data16[0][y_dst][4 * x_dst + 3] = float_to_sf16(src[4 * x + 3], SF_NEARESTEVEN);
|
||||
}
|
||||
}
|
||||
|
||||
fill_image_padding_area(img);
|
||||
return img;
|
||||
}
|
||||
|
||||
// initialize an astcenc_image data structure from a 2D array of UNORM8
|
||||
astcenc_image* astc_img_from_unorm8x4_array(
|
||||
const uint8_t* data,
|
||||
unsigned int dim_x,
|
||||
unsigned int dim_y,
|
||||
unsigned int dim_pad,
|
||||
bool y_flip
|
||||
) {
|
||||
astcenc_image* img = alloc_image(8, dim_x, dim_y, 1, dim_pad);
|
||||
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
unsigned int y_dst = y + dim_pad;
|
||||
unsigned int y_src = y_flip ? (dim_y - y - 1) : y;
|
||||
const uint8_t* src = data + 4 * dim_x * y_src;
|
||||
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
unsigned int x_dst = x + dim_pad;
|
||||
img->data8[0][y_dst][4 * x_dst] = src[4 * x];
|
||||
img->data8[0][y_dst][4 * x_dst + 1] = src[4 * x + 1];
|
||||
img->data8[0][y_dst][4 * x_dst + 2] = src[4 * x + 2];
|
||||
img->data8[0][y_dst][4 * x_dst + 3] = src[4 * x + 3];
|
||||
}
|
||||
}
|
||||
|
||||
fill_image_padding_area(img);
|
||||
return img;
|
||||
}
|
||||
|
||||
// initialize a flattened array of float4 values from an ASTC codec image
|
||||
// The returned array is allocated with new[] and must be deleted with delete[].
|
||||
float* floatx4_array_from_astc_img(
|
||||
const astcenc_image* img,
|
||||
bool y_flip
|
||||
) {
|
||||
unsigned int dim_x = img->dim_x;
|
||||
unsigned int dim_y = img->dim_y;
|
||||
unsigned int dim_pad = img->dim_pad;
|
||||
float *buf = new float[4 * dim_x * dim_y];
|
||||
|
||||
if (img->data8)
|
||||
{
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
unsigned int ymod = y_flip ? dim_y - y - 1 : y;
|
||||
const uint8_t* src = img->data8[0][ymod + dim_pad] + (4 * dim_pad);
|
||||
float* dst = buf + y * dim_x * 4;
|
||||
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
dst[4 * x] = src[4 * x] * (1.0f / 255.0f);
|
||||
dst[4 * x + 1] = src[4 * x + 1] * (1.0f / 255.0f);
|
||||
dst[4 * x + 2] = src[4 * x + 2] * (1.0f / 255.0f);
|
||||
dst[4 * x + 3] = src[4 * x + 3] * (1.0f / 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
unsigned int ymod = y_flip ? dim_y - y - 1 : y;
|
||||
const uint16_t *src = img->data16[0][ymod + dim_pad] + (4 * dim_pad);
|
||||
float *dst = buf + y * dim_x * 4;
|
||||
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
dst[4 * x] = sf16_to_float(src[4 * x]);
|
||||
dst[4 * x + 1] = sf16_to_float(src[4 * x + 1]);
|
||||
dst[4 * x + 2] = sf16_to_float(src[4 * x + 2]);
|
||||
dst[4 * x + 3] = sf16_to_float(src[4 * x + 3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// initialize a flattened array of unorm8x4 values from an ASTC codec image
|
||||
// The returned array is allocated with new[] and must be deleted with delete[].
|
||||
uint8_t* unorm8x4_array_from_astc_img(
|
||||
const astcenc_image* img,
|
||||
bool y_flip
|
||||
) {
|
||||
unsigned int dim_x = img->dim_x;
|
||||
unsigned int dim_y = img->dim_y;
|
||||
unsigned int dim_pad = img->dim_pad;
|
||||
uint8_t* buf = new uint8_t[4 * dim_x * dim_y];
|
||||
|
||||
if (img->data8)
|
||||
{
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
unsigned int ymod = y_flip ? dim_y - y - 1 : y;
|
||||
const uint8_t* src = img->data8[0][ymod + dim_pad] + (4 * dim_pad);
|
||||
uint8_t* dst = buf + y * dim_x * 4;
|
||||
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
dst[4 * x] = src[4 * x];
|
||||
dst[4 * x + 1] = src[4 * x + 1];
|
||||
dst[4 * x + 2] = src[4 * x + 2];
|
||||
dst[4 * x + 3] = src[4 * x + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int y = 0; y < dim_y; y++)
|
||||
{
|
||||
unsigned int ymod = y_flip ? dim_y - y - 1 : y;
|
||||
const uint16_t* src = img->data16[0][ymod + dim_pad] + (4 * dim_pad);
|
||||
uint8_t* dst = buf + y * dim_x * 4;
|
||||
|
||||
for (unsigned int x = 0; x < dim_x; x++)
|
||||
{
|
||||
dst[4 * x] = (uint8_t)astc::flt2int_rtn(astc::clamp1f(sf16_to_float(src[4*x])) * 255.0f);
|
||||
dst[4 * x + 1] = (uint8_t)astc::flt2int_rtn(astc::clamp1f(sf16_to_float(src[4*x+1])) * 255.0f);
|
||||
dst[4 * x + 2] = (uint8_t)astc::flt2int_rtn(astc::clamp1f(sf16_to_float(src[4*x+2])) * 255.0f);
|
||||
dst[4 * x + 3] = (uint8_t)astc::flt2int_rtn(astc::clamp1f(sf16_to_float(src[4*x+3])) * 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2020 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Functions and data declarations.
|
||||
*/
|
||||
|
||||
#ifndef ASTCENCCLI_INTERNAL_INCLUDED
|
||||
#define ASTCENCCLI_INTERNAL_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "astcenc.h"
|
||||
#include "astcenc_mathlib.h"
|
||||
|
||||
struct astc_compressed_image
|
||||
{
|
||||
unsigned int block_x;
|
||||
unsigned int block_y;
|
||||
unsigned int block_z;
|
||||
unsigned int dim_x;
|
||||
unsigned int dim_y;
|
||||
unsigned int dim_z;
|
||||
uint8_t* data;
|
||||
};
|
||||
|
||||
// Config options to be read from command line
|
||||
struct cli_config_options
|
||||
{
|
||||
unsigned int thread_count;
|
||||
unsigned int array_size;
|
||||
bool silentmode;
|
||||
bool y_flip;
|
||||
bool linearize_srgb;
|
||||
int low_fstop;
|
||||
int high_fstop;
|
||||
astcenc_swizzle swz_encode;
|
||||
astcenc_swizzle swz_decode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions to load image from file.
|
||||
*
|
||||
* @param filename The file path on disk.
|
||||
* @param padding The texel padding needed around the image.
|
||||
* @param y_flip Should this image be Y flipped?
|
||||
* @param[out] is_hdr Is the loaded image HDR?
|
||||
* @param[out] num_components The number of components in the loaded image.
|
||||
*
|
||||
* @return The astc image file, or nullptr on error.
|
||||
*/
|
||||
astcenc_image* load_ncimage(
|
||||
const char* filename,
|
||||
unsigned int dim_pad,
|
||||
bool y_flip,
|
||||
bool& is_hdr,
|
||||
unsigned int& num_components);
|
||||
|
||||
int store_ncimage(
|
||||
const astcenc_image* output_image,
|
||||
const char* output_filename,
|
||||
const char** file_format_name,
|
||||
int y_flip);
|
||||
|
||||
int get_output_filename_enforced_bitness(
|
||||
const char* filename);
|
||||
|
||||
|
||||
astcenc_image* alloc_image(
|
||||
unsigned int bitness,
|
||||
unsigned int dim_x,
|
||||
unsigned int dim_y,
|
||||
unsigned int dim_z,
|
||||
unsigned int dim_pad);
|
||||
|
||||
void free_image(
|
||||
astcenc_image* img);
|
||||
|
||||
void fill_image_padding_area(
|
||||
astcenc_image* img);
|
||||
|
||||
int determine_image_channels(
|
||||
const astcenc_image* img);
|
||||
|
||||
int load_cimage(
|
||||
const char* filename,
|
||||
astc_compressed_image& out_image);
|
||||
|
||||
int store_cimage(
|
||||
const astc_compressed_image& comp_img,
|
||||
const char* filename);
|
||||
|
||||
// helper functions to prepare an ASTC image object from a flat array
|
||||
// Used by the image loaders in "astc_file_load_store.cpp"
|
||||
astcenc_image* astc_img_from_floatx4_array(
|
||||
const float* data,
|
||||
unsigned int dim_x,
|
||||
unsigned int dim_y,
|
||||
unsigned int dim_pad,
|
||||
bool y_flip);
|
||||
|
||||
astcenc_image*astc_img_from_unorm8x4_array(
|
||||
const uint8_t* data,
|
||||
unsigned int dim_x,
|
||||
unsigned int dim_y,
|
||||
unsigned int dim_pad,
|
||||
bool y_flip);
|
||||
|
||||
// helper functions to prepare a flat array from an ASTC image object.
|
||||
// the array is allocated with new[], and must be freed with delete[].
|
||||
float* floatx4_array_from_astc_img(
|
||||
const astcenc_image* img,
|
||||
bool y_flip);
|
||||
|
||||
uint8_t* unorm8x4_array_from_astc_img(
|
||||
const astcenc_image* img,
|
||||
bool y_flip);
|
||||
|
||||
/* ============================================================================
|
||||
Functions for printing build info and help messages
|
||||
============================================================================ */
|
||||
void astcenc_print_header();
|
||||
|
||||
void astcenc_print_shorthelp();
|
||||
|
||||
void astcenc_print_longhelp();
|
||||
|
||||
/**
|
||||
* @brief Compute error metrics comparing two images.
|
||||
*
|
||||
* @param compute_hdr_metrics Non-zero if HDR metrics should be computed.
|
||||
* @param input_components The number of input color components.
|
||||
* @param img1 The original iamge.
|
||||
* @param img2 The compressed image.
|
||||
* @param fstop_lo The low exposure fstop (HDR only).
|
||||
* @param fstop_hi The high exposure fstop (HDR only).
|
||||
* @param show_psnr Non-zero if metrics should be logged to stdout.
|
||||
*/
|
||||
void compute_error_metrics(
|
||||
int compute_hdr_metrics,
|
||||
int input_components,
|
||||
const astcenc_image* img1,
|
||||
const astcenc_image* img2,
|
||||
int fstop_lo,
|
||||
int fstop_hi);
|
||||
|
||||
/**
|
||||
* @brief Get the current time.
|
||||
*
|
||||
* @returns The current time in seconds since arbitrary epoch.
|
||||
*/
|
||||
double get_time();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2020 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Platform-specific function implementations.
|
||||
*
|
||||
* This module contains functions with strongly OS-dependent implementations:
|
||||
*
|
||||
* * CPU count queries
|
||||
* * Threading
|
||||
* * Time
|
||||
*
|
||||
* In addition to the basic thread abstraction (which is native pthreads on
|
||||
* all platforms, except Windows where it is an emulation of pthreads), a
|
||||
* utility function to create N threads and wait for them to complete a batch
|
||||
* task has also been provided.
|
||||
*/
|
||||
|
||||
#include "astcenccli_internal.h"
|
||||
|
||||
/* ============================================================================
|
||||
Platform code for Windows using the Win32 APIs.
|
||||
============================================================================ */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
double get_time()
|
||||
{
|
||||
FILETIME tv;
|
||||
GetSystemTimeAsFileTime(&tv);
|
||||
unsigned long long ticks = tv.dwHighDateTime;
|
||||
ticks = (ticks << 32) | tv.dwLowDateTime;
|
||||
return ((double)ticks) / 1.0e7;
|
||||
}
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
int unlink_file(const char *filename)
|
||||
{
|
||||
BOOL res = DeleteFileA(filename);
|
||||
return (res ? 0 : -1);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Platform code for an platform using POSIX APIs.
|
||||
============================================================================ */
|
||||
#else
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
double get_time()
|
||||
{
|
||||
timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
return (double)tv.tv_sec + (double)tv.tv_usec * 1.0e-6;
|
||||
}
|
||||
|
||||
/* Public function, see header file for detailed documentation */
|
||||
int unlink_file(const char *filename)
|
||||
{
|
||||
return unlink(filename);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
||||
* @brief Functions for printing build info and help messages.
|
||||
*/
|
||||
|
||||
#include "astc_codec_internals.h"
|
||||
#include "astcenccli_internal.h"
|
||||
|
||||
const char *astcenc_copyright_string =
|
||||
R"(ASTC codec v2.0.alpha, %u-bit %s%s
|
||||
@@ -78,7 +78,6 @@ SYNOPSIS
|
||||
astcenc {-cl|-cs|-ch|-cH} <in> <out> <blocksize> <preset> [options]
|
||||
astcenc {-dl|-ds|-dh|-dH} <in> <out> <blocksize> <preset> [options]
|
||||
astcenc {-tl|-ts|-th|-tH} <in> <out> <blocksize> <preset> [options]
|
||||
astcenc {-compare} <in1> <in2> [options]
|
||||
|
||||
DESCRIPTION
|
||||
astcenc compresses image files into the Adaptive Scalable Texture
|
||||
@@ -136,9 +135,9 @@ COMPRESSION
|
||||
5x4x4: 1.60 bpp 6x6x6: 0.59 bpp
|
||||
|
||||
The quality preset configures the quality-performance tradeoff for
|
||||
the compressor; more complete searches of the available search
|
||||
space improve image quality at the expense of compression time.
|
||||
Available presets include:
|
||||
the compressor; more complete searches of the search space improve
|
||||
image quality at the expense of compression time. The available
|
||||
presets are:
|
||||
|
||||
-fast
|
||||
-medium
|
||||
@@ -212,11 +211,11 @@ ADVANCED COMPRESSION
|
||||
These options provide low-level control of the codec error metric
|
||||
computation, used to determine what good compression looks like.
|
||||
|
||||
-v <radius> <power> <base> <avg> <stdev> <mix>
|
||||
-v <radius> <power> <base> <mean> <stdev> <mix>
|
||||
Compute the per-texel relative error weighting for the RGB color
|
||||
channels as follows:
|
||||
|
||||
weight = 1 / (<base> + <avg> * average^2 + <stdev> * stdev^2)
|
||||
weight = 1 / (<base> + <mean> * mean^2 + <stdev> * stdev^2)
|
||||
|
||||
The <radius> argument specifies the pixel radius of the
|
||||
neighborhood over which the average and standard deviation are
|
||||
@@ -235,7 +234,7 @@ ADVANCED COMPRESSION
|
||||
e.g. a power of 0.5 causes the codec to take the square root
|
||||
of every input pixel value.
|
||||
|
||||
-va <power> <base> <avg> <stdev>
|
||||
-va <power> <base> <mean> <stdev>
|
||||
Compute the per-texel relative error weighting for the alpha
|
||||
channel, when used in conjunction with -v. See documentation for
|
||||
-v for parameter documentation.
|
||||
@@ -362,11 +361,14 @@ ADVANCED COMPRESSION
|
||||
Convert input images from sRGB to linear RGB before compression,
|
||||
and output images from linear RGB to sRGB after decompression.
|
||||
For compression, the transform is applied after any swizzle; for
|
||||
decode, the transform is applied before any swizzle.
|
||||
decode, the transform is applied before any swizzle. Note that
|
||||
using this option in a test mode (-t*) will have no obvious
|
||||
effect as the image will be converted twice, although some image
|
||||
precision loss may occur.
|
||||
|
||||
Note that this switch is only intended for diagnostic purposes;
|
||||
real use cases should directly compress/decompress sRGB data
|
||||
using the ASTC LDR sRGB format, using the -cs, -ds, and -ts
|
||||
using the LDR sRGB profile, using the -cs, -ds, and -ts
|
||||
operation modes. This preserves more perceptual image quality.
|
||||
|
||||
-yflip
|
||||
@@ -474,17 +476,17 @@ DECOMPRESSION FILE FORMATS
|
||||
// print version and basic build information
|
||||
void astcenc_print_header()
|
||||
{
|
||||
#if (ASTC_AVX == 2)
|
||||
#if (ASTCENC_AVX == 2)
|
||||
const char* simdtype = "avx2";
|
||||
#elif (ASTC_SSE == 42)
|
||||
const char* simdtype = "sse42";
|
||||
#elif (ASTC_SSE == 20)
|
||||
#elif (ASTCENC_SSE == 42)
|
||||
const char* simdtype = "sse4.2";
|
||||
#elif (ASTCENC_SSE == 20)
|
||||
const char* simdtype = "sse2";
|
||||
#else
|
||||
const char* simdtype = "unknown";
|
||||
#endif
|
||||
|
||||
#if (ASTC_POPCNT == 1)
|
||||
#if (ASTCENC_POPCNT == 1)
|
||||
const char* pcnttype = "+popcnt";
|
||||
#else
|
||||
const char* pcnttype = "";
|
||||
@@ -105,7 +105,7 @@ ASTCENC_TEST_PATTERN_HDR = {
|
||||
"BR": (0.25, 0.75, 0.00, 0.87)
|
||||
}
|
||||
|
||||
LDR_RGB_PSNR_PATTERN = re.compile(r"PSNR \(LDR-RGB\): (.*) dB")
|
||||
LDR_RGB_PSNR_PATTERN = re.compile(r"\s*PSNR \(LDR-RGB\): (.*) dB")
|
||||
|
||||
|
||||
class CLITestBase(unittest.TestCase):
|
||||
@@ -488,7 +488,10 @@ class CLIPTest(CLITestBase):
|
||||
|
||||
# Emit debug logging if needed
|
||||
if ASTCENC_CLI_ALWAYS or (error and ASTCENC_CLI_ON_ERROR):
|
||||
print(" ".join(command))
|
||||
# Format for shell replay
|
||||
print("\n" + " ".join(command))
|
||||
# Format for script command list replay
|
||||
print("\n" + ", ".join(("\"%s\"" % x for x in command)))
|
||||
|
||||
if ASTCENC_LOG_ALWAYS or (error and ASTCENC_LOG_ON_ERROR):
|
||||
print(result.stdout)
|
||||
@@ -1342,7 +1345,7 @@ class CLIPTest(CLITestBase):
|
||||
# Test time should get slower with fewer threads
|
||||
self.assertGreater(testTime, refTime)
|
||||
|
||||
def test_linearize_srgb1(self):
|
||||
def test_linearize_srgb_compress(self):
|
||||
"""
|
||||
Test linearize srgb on compression.
|
||||
|
||||
@@ -1376,7 +1379,7 @@ class CLIPTest(CLITestBase):
|
||||
self.assertColorSame(refColors[:3], srgbColors[:3], threshold=0.05)
|
||||
self.assertColorSame(refColors[3:], srgbColors[3:], threshold=0.0)
|
||||
|
||||
def test_linearize_srgb2(self):
|
||||
def test_linearize_srgb_decompress(self):
|
||||
"""
|
||||
Test linearize srgb on decompression.
|
||||
|
||||
@@ -1410,13 +1413,13 @@ class CLIPTest(CLITestBase):
|
||||
self.assertColorSame(refColors[:3], linColors[:3], threshold=0.05)
|
||||
self.assertColorSame(refColors[3:], linColors[3:], threshold=0.0)
|
||||
|
||||
def test_linearize_srgb3(self):
|
||||
def test_linearize_srgb_roundtrip(self):
|
||||
"""
|
||||
Test linearize srgb on round-trip.
|
||||
|
||||
This should behave the same as linearizing with compression only; i.e.
|
||||
we convert to linear before compression, but we do NOT sRGB encode the
|
||||
output after decompression.
|
||||
This linearizes on input, and converts back to sRGB on output, so
|
||||
overall no conversion should occur. There may be some precision
|
||||
losses however.
|
||||
"""
|
||||
inputFile = "./Test/Data/Tiles/ldr.png"
|
||||
decompFile = self.get_tmp_image_path("LDR", "decomp")
|
||||
@@ -1433,11 +1436,10 @@ class CLIPTest(CLITestBase):
|
||||
|
||||
img = tli.Image(decompFile)
|
||||
testColors = img.get_colors((7, 7))
|
||||
srgbColors = self.to_srgb_color(testColors)
|
||||
|
||||
# Test we get a match within 5% on the RGB channels, exact on alpha
|
||||
self.assertColorSame(refColors[:3], srgbColors[:3], threshold=0.05)
|
||||
self.assertColorSame(refColors[3:], srgbColors[3:], threshold=0.0)
|
||||
self.assertColorSame(refColors[:3], testColors[:3], threshold=0.0)
|
||||
self.assertColorSame(refColors[3:], testColors[3:], threshold=0.0)
|
||||
|
||||
def test_silent(self):
|
||||
"""
|
||||
@@ -1507,7 +1509,10 @@ class CLINTest(CLITestBase):
|
||||
badResult = (error == expectPass) or (rcode < 0)
|
||||
|
||||
if ASTCENC_CLI_ALWAYS or (badResult and ASTCENC_CLI_ON_ERROR_NEG):
|
||||
print(" ".join(command))
|
||||
# Format for shell replay
|
||||
print("\n" + " ".join(command))
|
||||
# Format for script command list replay
|
||||
print("\n" + ", ".join(("\"%s\"" % x for x in command)))
|
||||
|
||||
if ASTCENC_LOG_ALWAYS or (badResult and ASTCENC_LOG_ON_ERROR_NEG):
|
||||
print(result.stdout)
|
||||
@@ -1525,10 +1530,7 @@ class CLINTest(CLITestBase):
|
||||
|
||||
# Otherwise just assert that we got an error log, and some positive
|
||||
# return code value was returned
|
||||
|
||||
# TODO: Disabled until we fix GitHub issue #100
|
||||
# self.assertIn("ERROR", result.stdout)
|
||||
|
||||
self.assertIn("ERROR", result.stdout)
|
||||
self.assertGreater(rcode, 0, "Exec did not fail as expected")
|
||||
|
||||
def exec_with_omit(self, command, startOmit):
|
||||
@@ -1842,18 +1844,6 @@ class CLINTest(CLITestBase):
|
||||
|
||||
self.exec(command)
|
||||
|
||||
def test_compare_missing(self):
|
||||
"""
|
||||
Test -compare with missing arguments.
|
||||
"""
|
||||
command = [
|
||||
self.binary, "-compare",
|
||||
self.get_ref_image_path("LDR", "input", "A"),
|
||||
self.get_ref_image_path("LDR", "input", "A")]
|
||||
|
||||
# Run the command, incrementally omitting arguments
|
||||
self.exec_with_omit(command, 2)
|
||||
|
||||
def test_cl_v_missing_args(self):
|
||||
"""
|
||||
Test -cl with -v and missing arguments.
|
||||
|
||||
@@ -264,11 +264,6 @@ def get_encoder_params(encoderName, imageSet):
|
||||
name = "reference-prototype"
|
||||
outDir = "Test/Images/%s" % imageSet
|
||||
refName = None
|
||||
elif encoderName == "ref-intelispc":
|
||||
encoder = te.EncoderISPC()
|
||||
name = "reference-intelispc"
|
||||
outDir = "Test/Images/%s" % imageSet
|
||||
refName = None
|
||||
else:
|
||||
encoder = te.Encoder2x(encoderName)
|
||||
name = "develop-%s" % encoderName
|
||||
@@ -287,7 +282,7 @@ def parse_command_line():
|
||||
"""
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
refcoders = ["ref-1.7", "ref-2.0", "ref-prototype", "ref-intelispc"]
|
||||
refcoders = ["ref-1.7", "ref-2.0", "ref-prototype"]
|
||||
testcoders = ["nointrin", "sse2", "sse4.2", "avx2"]
|
||||
coders = refcoders + testcoders + ["all"]
|
||||
parser.add_argument("--encoder", dest="encoders", default="avx2",
|
||||
|
||||
+5
-129
@@ -270,18 +270,18 @@ class Encoder2x(EncoderBase):
|
||||
def get_psnr_pattern(self, image):
|
||||
if image.colorProfile != "hdr":
|
||||
if image.colorFormat != "rgba":
|
||||
patternPSNR = r"PSNR \(LDR-RGB\):\s*([0-9.]*) dB"
|
||||
patternPSNR = r"\s*PSNR \(LDR-RGB\):\s*([0-9.]*) dB"
|
||||
else:
|
||||
patternPSNR = r"PSNR \(LDR-RGBA\):\s*([0-9.]*) dB"
|
||||
patternPSNR = r"\s*PSNR \(LDR-RGBA\):\s*([0-9.]*) dB"
|
||||
else:
|
||||
patternPSNR = r"mPSNR \(RGB\)(?: \[.*?\] )?:\s*([0-9.]*) dB.*"
|
||||
patternPSNR = r"\s*mPSNR \(RGB\)(?: \[.*?\] )?:\s*([0-9.]*) dB.*"
|
||||
return patternPSNR
|
||||
|
||||
def get_total_time_pattern(self):
|
||||
return r"Total time:\s*([0-9.]*) s"
|
||||
return r"\s*Total time:\s*([0-9.]*) s"
|
||||
|
||||
def get_coding_time_pattern(self):
|
||||
return r"Coding time:\s*([0-9.]*) s"
|
||||
return r"\s*Coding time:\s*([0-9.]*) s"
|
||||
|
||||
|
||||
class Encoder1x(EncoderBase):
|
||||
@@ -379,127 +379,3 @@ class EncoderProto(Encoder1x):
|
||||
assert os.name != 'nt', "Windows builds not available"
|
||||
binary = "./Binaries/Prototype/astcenc"
|
||||
super().__init__(binary)
|
||||
|
||||
|
||||
class EncoderISPC(EncoderBase):
|
||||
"""
|
||||
This class wraps the Intel ISPC compressor, which is widely used due to its
|
||||
good performance (although with worse quality).
|
||||
|
||||
Note that the compressor does not support all features of ASTC (only a
|
||||
subset of 2D block sizes, only LDR color profile), and doesn't support
|
||||
decode at all. For round-trip analysis we use `astcenc` to provide the
|
||||
decompression and image comparisons.
|
||||
"""
|
||||
|
||||
VERSION = "IntelISPC"
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Create a new encoder instance.
|
||||
"""
|
||||
binary = "./Binaries/ispc/astcispc"
|
||||
super().__init__("intel-ispc", None, binary)
|
||||
self.decodeBinary = "./Binaries/1.7/astcenc"
|
||||
|
||||
def get_psnr_pattern(self, image):
|
||||
if image.colorFormat != "rgba":
|
||||
patternPSNR = r"PSNR \(LDR-RGB\):\s*([0-9.]*) dB"
|
||||
else:
|
||||
patternPSNR = r"PSNR \(LDR-RGBA\):\s*([0-9.]*) dB"
|
||||
|
||||
return patternPSNR
|
||||
|
||||
def get_total_time_pattern(self):
|
||||
return r"Total time:\s*([0-9.]*) s"
|
||||
|
||||
def get_coding_time_pattern(self):
|
||||
return r"Coding time:\s*([0-9.]*) s"
|
||||
|
||||
def execute(self, command):
|
||||
"""
|
||||
Run a subprocess with the specified command.
|
||||
|
||||
Args:
|
||||
command (list(str)): The list of command line arguments.
|
||||
|
||||
Returns:
|
||||
list(str): The output log (stdout) split into lines.
|
||||
"""
|
||||
command = " ".join(command)
|
||||
try:
|
||||
result = sp.run(command, stdout=sp.PIPE, stderr=sp.PIPE,
|
||||
shell=True, check=True, universal_newlines=True)
|
||||
except OSError:
|
||||
print("ERROR: Test run failed (binary not found)")
|
||||
print(" + %s" % command)
|
||||
sys.exit(1)
|
||||
except sp.CalledProcessError:
|
||||
print("ERROR: Test run failed")
|
||||
print(" + %s" % command)
|
||||
sys.exit(1)
|
||||
|
||||
return result.stdout.splitlines()
|
||||
|
||||
def run_test(self, image, blockSize, preset, testRuns):
|
||||
"""
|
||||
Run the test N times.
|
||||
|
||||
Args:
|
||||
image (TestImage): The test image to compress.
|
||||
blockSize (str): The block size to use.
|
||||
preset (str): Unused - we always use ISPC's slow preset as this
|
||||
gives acceptable image quality which is likely to be used.
|
||||
testRuns (int): The number of test repeats to run for the image.
|
||||
|
||||
Returns:
|
||||
tuple(float, float, float): Returns the best results from the N
|
||||
test runs, as PSNR (dB), total time (seconds), and coding time
|
||||
(seconds).
|
||||
"""
|
||||
dstDir = os.path.dirname(image.outFilePath)
|
||||
dstFile = os.path.basename(image.outFilePath)
|
||||
dstDir = os.path.join(dstDir, self.name, blockSize)
|
||||
dstPath = os.path.join(dstDir, dstFile)
|
||||
|
||||
compressCommand = [
|
||||
"env",
|
||||
"LD_LIBRARY_PATH=./Binaries/ispc",
|
||||
self.binary,
|
||||
image.filePath,
|
||||
dstPath + ".astc",
|
||||
blockSize
|
||||
]
|
||||
|
||||
decompressCommand = [
|
||||
self.decodeBinary,
|
||||
"-dl",
|
||||
dstPath + ".astc",
|
||||
dstPath + ".tga"
|
||||
]
|
||||
|
||||
compareCommand = [
|
||||
self.decodeBinary,
|
||||
"-compare",
|
||||
image.filePath,
|
||||
dstPath + ".tga",
|
||||
"-showpsnr"
|
||||
]
|
||||
|
||||
os.makedirs(dstDir, exist_ok=True)
|
||||
|
||||
# Execute test runs
|
||||
bestPSNR = 0
|
||||
bestTTime = sys.float_info.max
|
||||
bestCTime = sys.float_info.max
|
||||
for _ in range(0, testRuns):
|
||||
output = self.execute(compressCommand)
|
||||
self.execute(decompressCommand)
|
||||
output += self.execute(compareCommand)
|
||||
|
||||
output = self.parse_output(image, output)
|
||||
bestPSNR = max(bestPSNR, output[0])
|
||||
bestTTime = min(bestTTime, output[1])
|
||||
bestCTime = min(bestCTime, output[2])
|
||||
|
||||
return (bestPSNR, bestTTime, bestCTime)
|
||||
|
||||
Reference in New Issue
Block a user