feat(texconv): add texture format decoders and sRGB fixes#17
Merged
thesprockee merged 1 commit intomainfrom Mar 14, 2026
Merged
feat(texconv): add texture format decoders and sRGB fixes#17thesprockee merged 1 commit intomainfrom
thesprockee merged 1 commit intomainfrom
Conversation
…RGBA output Add decoders for R8_UNORM (grayscale), R8G8B8A8, B8G8R8A8 (sRGB and Typeless), and R11G11B10_FLOAT packed format with IEEE partial-precision float conversion. Fix RGB565 bit expansion to use proper bit-replication instead of the lossy multiply-divide method. Add sRGB linear-space interpolation for BC1/BC3 decompression (correct per DDS spec). Change output image type from image.RGBA (premultiplied) to image.NRGBA (non-premultiplied), which is correct for texture data with alpha channels. Based on work by heisthecat31 in PR #5, cleaned up and tested. Co-Authored-By: he_is_the_cat <heisthecat31@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR extends texconv’s DDS decoding capabilities by adding support for additional uncompressed DXGI formats and improving correctness for sRGB handling and channel/alpha representation during decompression.
Changes:
- Added decoders for R8_UNORM, RGBA/BGRA uncompressed formats (including sRGB/typeless variants), and R11G11B10_FLOAT.
- Fixed RGB565 expansion via bit replication and added linear-space interpolation for BC1/BC3 sRGB decompression paths.
- Switched decode output image type from
image.RGBAtoimage.NRGBAand added helper conversions/tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| cmd/texconv/main.go | Adds new format constants, mip sizing for new formats, decoders (R8/RGBA/BGRA/R11G11B10Float), sRGB helpers, and updates BC1/BC3 to optionally interpolate in linear space; changes decode output to NRGBA. |
| cmd/texconv/decode_test.go | Introduces unit tests for new decoders and float helpers, plus some basic BC1 and sRGB round-trip coverage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+607
to
+615
| if isSRGB { | ||
| // sRGB linear-space interpolation | ||
| lr0, lg0, lb0 := srgbToLinear(r0_8), srgbToLinear(g0_8), srgbToLinear(b0_8) | ||
| lr1, lg1, lb1 := srgbToLinear(r1_8), srgbToLinear(g1_8), srgbToLinear(b1_8) | ||
| colors[2] = [4]uint8{ | ||
| linearToSrgb((2*lr0 + lr1) / 3), | ||
| linearToSrgb((2*lg0 + lg1) / 3), | ||
| linearToSrgb((2*lb0 + lb1) / 3), | ||
| 255, |
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| got := f10ToF32(tt.in) | ||
| if math.Abs(float64(got-tt.want)) > 0.001 { |
Comment on lines
+216
to
+225
| func TestDecompressBC1_NRGBA(t *testing.T) { | ||
| // Verify return type is NRGBA, not RGBA | ||
| block := make([]byte, 8) | ||
| img, err := decompressBC1(block, 4, 4, false) | ||
| if err != nil { | ||
| t.Fatal(err) | ||
| } | ||
| // Type assertion — img should be *image.NRGBA | ||
| _ = img.Stride // only NRGBA has Stride; compilation proves the type | ||
| } |
|
|
||
| // decompressBC decompresses BC-compressed data to RGBA | ||
| func decompressBC(data []byte, info *TextureInfo) (*image.RGBA, error) { | ||
| // decompressBC decompresses BC-compressed data to NRGBA |
Comment on lines
+881
to
+884
| if v <= 0.0031308 { | ||
| return uint8(min(255, max(0, float64(v)*12.92*255.0))) | ||
| } | ||
| srgb := 1.055*math.Pow(float64(v), 1.0/2.4) - 0.055 |
Comment on lines
+957
to
+967
| // Clamp to [0,1] and convert to uint8 | ||
| dstOff := nrgba.PixOffset(x, y) | ||
| nrgba.Pix[dstOff+0] = uint8(min(255, max(0, float64(r)*255.0))) | ||
| nrgba.Pix[dstOff+1] = uint8(min(255, max(0, float64(g)*255.0))) | ||
| nrgba.Pix[dstOff+2] = uint8(min(255, max(0, float64(b)*255.0))) | ||
| nrgba.Pix[dstOff+3] = 255 | ||
| } | ||
| } | ||
| return nrgba, nil | ||
| } | ||
|
|
| return nrgba, nil | ||
| } | ||
|
|
||
| // decompressBC5 decompresses BC5 (normal maps) to RGBA |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Based on work by @heisthecat31 in PR #5, extracted and cleaned up with tests.
Test plan
🤖 Generated with Claude Code