Skip to content

Commit 44599c8

Browse files
committed
Add HDR support
1 parent 0aba876 commit 44599c8

File tree

59 files changed

+1331
-99
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1331
-99
lines changed

src/ImageSharp.Textures/Common/Helpers/FloatHelper.cs

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4+
using System;
45
using System.Runtime.CompilerServices;
56

67
namespace SixLabors.ImageSharp.Textures.Common.Helpers
@@ -14,32 +15,31 @@ internal static class FloatHelper
1415
public static uint PackFloatToFloat32(float value) => Unsafe.As<float, uint>(ref value);
1516

1617
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17-
public static float UnpackFloat16ToFloat(uint value)
18-
{
19-
uint result =
20-
((value >> 15) << 31) |
21-
((((value >> 10) & 0x1f) - 15 + 127) << 23) |
22-
((value & 0x3ff) << 13);
23-
return Unsafe.As<uint, float>(ref result);
24-
}
18+
public static float UnpackFloat16ToFloat(uint value) => (float)BitConverter.UInt16BitsToHalf((ushort)value);
2519

2620
[MethodImpl(MethodImplOptions.AggressiveInlining)]
27-
public static uint PackFloatToFloat16(float value)
28-
{
29-
uint temp = Unsafe.As<float, uint>(ref value);
30-
return
31-
((temp >> 31) << 15) |
32-
((((temp >> 23) & 0xff) - 127 + 15) << 10) |
33-
((temp & 0x7fffff) >> 13);
34-
}
21+
public static uint PackFloatToFloat16(float value) => BitConverter.HalfToUInt16Bits((Half)value);
3522

3623
[MethodImpl(MethodImplOptions.AggressiveInlining)]
37-
public static float UnpackFloat10ToFloat(uint value)
24+
public static float UnpackFloat10ToFloat(uint value, uint bias = 10)
3825
{
39-
uint result =
40-
((((value >> 5) & 0x1f) - 10 + 127) << 23) |
41-
((value & 0x1f) << 18);
42-
return Unsafe.As<uint, float>(ref result);
26+
uint e = (value >> 5) & 0x1Fu;
27+
uint m = value & 0x1Fu;
28+
29+
return e switch
30+
{
31+
// Zero
32+
0 when m == 0 => 0f,
33+
34+
// Denormalized
35+
0 => m * BitConverter.UInt32BitsToSingle((128u - bias - 5u) << 23),
36+
37+
// Inf/NaN
38+
31 => BitConverter.UInt32BitsToSingle((0xFFu << 23) | (m << 18)),
39+
40+
// Normalized
41+
_ => BitConverter.UInt32BitsToSingle(((e + 127u - bias) << 23) | (m << 18)),
42+
};
4343
}
4444

4545
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -52,12 +52,29 @@ public static uint PackFloatToFloat10(float value)
5252
}
5353

5454
[MethodImpl(MethodImplOptions.AggressiveInlining)]
55-
public static float UnpackFloat11ToFloat(uint value)
55+
public static float UnpackFloat11ToFloat(uint value, uint bias = 11)
5656
{
57-
uint result =
58-
((((value >> 6) & 0x1f) - 11 + 127) << 23) |
59-
((value & 0x3f) << 17);
60-
return Unsafe.As<uint, float>(ref result);
57+
uint e = (value >> 6) & 0x1Fu;
58+
uint m = value & 0x3Fu;
59+
60+
if (e == 0)
61+
{
62+
if (m == 0)
63+
{
64+
return 0f;
65+
}
66+
67+
// Denormalized: m * 2^(1 - bias - 6)
68+
return m * BitConverter.UInt32BitsToSingle((128u - bias - 6u) << 23);
69+
}
70+
71+
if (e == 31)
72+
{
73+
uint ieee = (0xFFu << 23) | (m << 17);
74+
return BitConverter.UInt32BitsToSingle(ieee);
75+
}
76+
77+
return BitConverter.UInt32BitsToSingle(((e + 127u - bias) << 23) | (m << 17));
6178
}
6279

6380
[MethodImpl(MethodImplOptions.AggressiveInlining)]

src/ImageSharp.Textures/Formats/Ktx/Enums/GlInternalPixelFormat.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ internal enum GlInternalPixelFormat : uint
4545

4646
Rgba16 = 0x805B,
4747

48+
R16F = 0x822D,
49+
50+
Rg16F = 0x822F,
51+
52+
R32F = 0x822E,
53+
54+
Rg32F = 0x8230,
55+
56+
Rgb16F = 0x881B,
57+
58+
Rgba16F = 0x881A,
59+
60+
Rgb32F = 0x8815,
61+
62+
Rgba32F = 0x8814,
63+
4864
R8 = 0x8229,
4965

5066
R8UnsignedInt = 0x8232,
@@ -131,6 +147,11 @@ internal enum GlInternalPixelFormat : uint
131147

132148
CompressedSrgb8Alpha8Etc2Eac = 0x9279,
133149

150+
/// <summary>
151+
/// ASTC 4x4 block compression. Supports both LDR and HDR content.
152+
/// HDR is determined by block encoding, not a separate format constant.
153+
/// Note: Current decoder may not fully support HDR endpoint modes (2, 3, 7, 11, 14, 15).
154+
/// </summary>
134155
CompressedRgbaAstc4x4Khr = 0x93B0,
135156

136157
CompressedRgbaAstc5x4Khr = 0x93B1,
@@ -158,5 +179,37 @@ internal enum GlInternalPixelFormat : uint
158179
CompressedRgbaAstc12x10Khr = 0x93BC,
159180

160181
CompressedRgbaAstc12x12Khr = 0x93BD,
182+
183+
/// <summary>
184+
/// ASTC 4x4 block compression with sRGB color space.
185+
/// HDR blocks in sRGB formats will decode incorrectly.
186+
/// </summary>
187+
CompressedSrgb8Alpha8Astc4x4Khr = 0x93D0,
188+
189+
CompressedSrgb8Alpha8Astc5x4Khr = 0x93D1,
190+
191+
CompressedSrgb8Alpha8Astc5x5Khr = 0x93D2,
192+
193+
CompressedSrgb8Alpha8Astc6x5Khr = 0x93D3,
194+
195+
CompressedSrgb8Alpha8Astc6x6Khr = 0x93D4,
196+
197+
CompressedSrgb8Alpha8Astc8x5Khr = 0x93D5,
198+
199+
CompressedSrgb8Alpha8Astc8x6Khr = 0x93D6,
200+
201+
CompressedSrgb8Alpha8Astc8x8Khr = 0x93D7,
202+
203+
CompressedSrgb8Alpha8Astc10x5Khr = 0x93D8,
204+
205+
CompressedSrgb8Alpha8Astc10x6Khr = 0x93D9,
206+
207+
CompressedSrgb8Alpha8Astc10x8Khr = 0x93DA,
208+
209+
CompressedSrgb8Alpha8Astc10x10Khr = 0x93DB,
210+
211+
CompressedSrgb8Alpha8Astc12x10Khr = 0x93DC,
212+
213+
CompressedSrgb8Alpha8Astc12x12Khr = 0x93DD,
161214
}
162215
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using System;
5+
6+
namespace SixLabors.ImageSharp.Textures.Formats.Ktx
7+
{
8+
/// <summary>
9+
/// Handles endianness conversions for KTX texture data.
10+
/// </summary>
11+
internal interface IEndianHandler
12+
{
13+
/// <summary>
14+
/// Reads a UInt32 value from a buffer with appropriate endianness.
15+
/// </summary>
16+
/// <param name="buffer">The buffer containing the UInt32 data.</param>
17+
/// <returns>The UInt32 value.</returns>
18+
uint ReadUInt32(ReadOnlySpan<byte> buffer);
19+
20+
/// <summary>
21+
/// Converts pixel data endianness if needed based on the type size.
22+
/// </summary>
23+
/// <param name="data">The pixel data to convert.</param>
24+
/// <param name="typeSize">The size of each data element (2 for half-float, 4 for float).</param>
25+
void ConvertPixelData(Span<byte> data, uint typeSize);
26+
}
27+
}

0 commit comments

Comments
 (0)