88
99namespace PlateauResoniteLink . Application . Importing ;
1010
11- public enum RawTexturePayloadFormat
11+ public abstract class RawTexturePayload
1212{
13- Rgba32 = 0 ,
14- RgbaFloat32 = 1 ,
13+ private protected RawTexturePayload (
14+ int width ,
15+ int height ,
16+ string ? colorProfile ,
17+ byte [ ] bytes )
18+ {
19+ ArgumentOutOfRangeException . ThrowIfNegativeOrZero ( width ) ;
20+ ArgumentOutOfRangeException . ThrowIfNegativeOrZero ( height ) ;
21+ ArgumentNullException . ThrowIfNull ( bytes ) ;
22+
23+ Width = width ;
24+ Height = height ;
25+ ColorProfile = colorProfile ;
26+ Bytes = bytes ;
27+ }
28+
29+ public int Width { get ; }
30+
31+ public int Height { get ; }
32+
33+ public string ? ColorProfile { get ; }
34+
35+ public byte [ ] Bytes { get ; }
36+
37+ public abstract TResult Match < TResult > (
38+ Func < Rgba32RawTexturePayload , TResult > rgba32 ,
39+ Func < RgbaFloat32RawTexturePayload , TResult > rgbaFloat32 ) ;
1540}
1641
17- public sealed record RawTexturePayload (
18- int Width ,
19- int Height ,
20- string ? ColorProfile ,
21- byte [ ] Bytes ,
22- RawTexturePayloadFormat Format = RawTexturePayloadFormat . Rgba32 ) ;
42+ public sealed class Rgba32RawTexturePayload : RawTexturePayload
43+ {
44+ private const int BytesPerPixel = 4 ;
45+
46+ public Rgba32RawTexturePayload (
47+ int width ,
48+ int height ,
49+ string ? colorProfile ,
50+ byte [ ] bytes )
51+ : base ( width , height , colorProfile , bytes )
52+ {
53+ ValidateByteLength ( width , height , bytes ) ;
54+ }
55+
56+ internal static void ValidateByteLength (
57+ int width ,
58+ int height ,
59+ byte [ ] bytes )
60+ {
61+ ArgumentOutOfRangeException . ThrowIfNegativeOrZero ( width ) ;
62+ ArgumentOutOfRangeException . ThrowIfNegativeOrZero ( height ) ;
63+ ArgumentNullException . ThrowIfNull ( bytes ) ;
64+
65+ int expectedByteLength = checked ( width * height * BytesPerPixel ) ;
66+ if ( bytes . Length != expectedByteLength )
67+ {
68+ throw new ArgumentException (
69+ $ "RGBA32 texture payload length must be width * height * { BytesPerPixel } bytes ({ expectedByteLength } ), but was { bytes . Length } .",
70+ nameof ( bytes ) ) ;
71+ }
72+ }
73+
74+ public override TResult Match < TResult > (
75+ Func < Rgba32RawTexturePayload , TResult > rgba32 ,
76+ Func < RgbaFloat32RawTexturePayload , TResult > rgbaFloat32 )
77+ {
78+ ArgumentNullException . ThrowIfNull ( rgba32 ) ;
79+ ArgumentNullException . ThrowIfNull ( rgbaFloat32 ) ;
80+ return rgba32 ( this ) ;
81+ }
82+ }
83+
84+ public sealed class RgbaFloat32RawTexturePayload : RawTexturePayload
85+ {
86+ public RgbaFloat32RawTexturePayload (
87+ int width ,
88+ int height ,
89+ string ? colorProfile ,
90+ byte [ ] bytes )
91+ : base ( width , height , colorProfile , bytes )
92+ {
93+ }
94+
95+ public override TResult Match < TResult > (
96+ Func < Rgba32RawTexturePayload , TResult > rgba32 ,
97+ Func < RgbaFloat32RawTexturePayload , TResult > rgbaFloat32 )
98+ {
99+ ArgumentNullException . ThrowIfNull ( rgba32 ) ;
100+ ArgumentNullException . ThrowIfNull ( rgbaFloat32 ) ;
101+ return rgbaFloat32 ( this ) ;
102+ }
103+ }
23104
24105public interface ITextureImportSource
25106{
@@ -32,9 +113,14 @@ public interface ITextureImportSource
32113 long ? EstimatedByteLength { get ; }
33114}
34115
35- internal interface IRawTexturePayloadSource : ITextureImportSource
116+ internal interface IRgba32RawTexturePayloadSource : ITextureImportSource
36117{
37- ValueTask < RawTexturePayload > MaterializeRawAsync ( CancellationToken cancellationToken ) ;
118+ ValueTask < Rgba32RawTexturePayload > MaterializeRgba32Async ( CancellationToken cancellationToken ) ;
119+ }
120+
121+ internal interface IRgbaFloat32RawTexturePayloadSource : ITextureImportSource
122+ {
123+ ValueTask < RgbaFloat32RawTexturePayload > MaterializeRgbaFloat32Async ( CancellationToken cancellationToken ) ;
38124}
39125
40126internal static class TextureImportSourceMaterializer
@@ -44,17 +130,50 @@ public static ValueTask<RawTexturePayload> MaterializeRawAsync(
44130 CancellationToken cancellationToken )
45131 {
46132 ArgumentNullException . ThrowIfNull ( source ) ;
47- if ( source is not IRawTexturePayloadSource rawSource )
133+ if ( source is IRgba32RawTexturePayloadSource rgba32Source )
134+ {
135+ return new ValueTask < RawTexturePayload > ( MaterializeRgba32AsRawAsync ( rgba32Source , cancellationToken ) ) ;
136+ }
137+
138+ if ( source is IRgbaFloat32RawTexturePayloadSource rgbaFloat32Source )
139+ {
140+ return new ValueTask < RawTexturePayload > ( MaterializeRgbaFloat32AsRawAsync ( rgbaFloat32Source , cancellationToken ) ) ;
141+ }
142+
143+ throw new InvalidOperationException (
144+ $ "Texture import source '{ source . GetType ( ) . Name } ' cannot materialize a raw texture payload.") ;
145+
146+ static async Task < RawTexturePayload > MaterializeRgba32AsRawAsync (
147+ IRgba32RawTexturePayloadSource source ,
148+ CancellationToken cancellationToken )
149+ {
150+ return await source . MaterializeRgba32Async ( cancellationToken ) ;
151+ }
152+
153+ static async Task < RawTexturePayload > MaterializeRgbaFloat32AsRawAsync (
154+ IRgbaFloat32RawTexturePayloadSource source ,
155+ CancellationToken cancellationToken )
156+ {
157+ return await source . MaterializeRgbaFloat32Async ( cancellationToken ) ;
158+ }
159+ }
160+
161+ public static ValueTask < Rgba32RawTexturePayload > MaterializeRgba32Async (
162+ ITextureImportSource source ,
163+ CancellationToken cancellationToken )
164+ {
165+ ArgumentNullException . ThrowIfNull ( source ) ;
166+ if ( source is not IRgba32RawTexturePayloadSource rgba32Source )
48167 {
49168 throw new InvalidOperationException (
50- $ "Texture import source '{ source . GetType ( ) . Name } ' cannot materialize a raw texture payload.") ;
169+ $ "Texture import source '{ source . GetType ( ) . Name } ' cannot materialize an RGBA32 texture payload.") ;
51170 }
52171
53- return rawSource . MaterializeRawAsync ( cancellationToken ) ;
172+ return rgba32Source . MaterializeRgba32Async ( cancellationToken ) ;
54173 }
55174}
56175
57- internal sealed class InMemoryRawTextureImportSource : IRawTexturePayloadSource
176+ internal sealed class InMemoryRawTextureImportSource : IRgba32RawTexturePayloadSource
58177{
59178 private readonly byte [ ] bytes ;
60179
@@ -69,6 +188,7 @@ public InMemoryRawTextureImportSource(
69188 ArgumentOutOfRangeException . ThrowIfNegativeOrZero ( height ) ;
70189 ArgumentNullException . ThrowIfNull ( bytes ) ;
71190 ArgumentException . ThrowIfNullOrWhiteSpace ( identity ) ;
191+ Rgba32RawTexturePayload . ValidateByteLength ( width , height , bytes ) ;
72192 Width = width ;
73193 Height = height ;
74194 ColorProfile = colorProfile ;
@@ -88,18 +208,18 @@ public InMemoryRawTextureImportSource(
88208
89209 public long ? EstimatedByteLength => bytes . Length ;
90210
91- public ValueTask < RawTexturePayload > MaterializeRawAsync ( CancellationToken cancellationToken )
211+ public ValueTask < Rgba32RawTexturePayload > MaterializeRgba32Async ( CancellationToken cancellationToken )
92212 {
93213 cancellationToken . ThrowIfCancellationRequested ( ) ;
94- return ValueTask . FromResult ( new RawTexturePayload (
214+ return ValueTask . FromResult ( new Rgba32RawTexturePayload (
95215 Width ,
96216 Height ,
97217 ColorProfile ,
98218 ( byte [ ] ) bytes . Clone ( ) ) ) ;
99219 }
100220}
101221
102- internal sealed class InMemoryEncodedTextureImportSource : IRawTexturePayloadSource
222+ internal sealed class InMemoryEncodedTextureImportSource : IRgba32RawTexturePayloadSource
103223{
104224 private readonly byte [ ] bytes ;
105225
@@ -123,7 +243,7 @@ public InMemoryEncodedTextureImportSource(
123243
124244 public long ? EstimatedByteLength => bytes . Length ;
125245
126- public async ValueTask < RawTexturePayload > MaterializeRawAsync ( CancellationToken cancellationToken )
246+ public async ValueTask < Rgba32RawTexturePayload > MaterializeRgba32Async ( CancellationToken cancellationToken )
127247 {
128248 cancellationToken . ThrowIfCancellationRequested ( ) ;
129249 using MemoryStream stream = new ( bytes , writable : false ) ;
@@ -138,7 +258,7 @@ internal sealed class DatasetTextureImportSource(
138258 IPlateauDatasetContentSource datasetSource ,
139259 string relativePath ,
140260 string ? colorProfile ,
141- string identity ) : IRawTexturePayloadSource
261+ string identity ) : IRgba32RawTexturePayloadSource
142262{
143263 public string Identity { get ; } = identity ;
144264
@@ -150,7 +270,7 @@ internal sealed class DatasetTextureImportSource(
150270 ? lengthSource . TryGetFileLength ( relativePath )
151271 : null ;
152272
153- public async ValueTask < RawTexturePayload > MaterializeRawAsync ( CancellationToken cancellationToken )
273+ public async ValueTask < Rgba32RawTexturePayload > MaterializeRgba32Async ( CancellationToken cancellationToken )
154274 {
155275 await using Stream stream = await datasetSource . OpenReadAsync ( relativePath , cancellationToken ) ;
156276 using Image < Rgba32 > image = await Image . LoadAsync < Rgba32 > ( stream , cancellationToken ) ;
@@ -161,7 +281,7 @@ public async ValueTask<RawTexturePayload> MaterializeRawAsync(CancellationToken
161281internal sealed class FileTextureImportSource (
162282 string absolutePath ,
163283 string colorProfile ,
164- string identity ) : IRawTexturePayloadSource
284+ string identity ) : IRgba32RawTexturePayloadSource
165285{
166286 public string Identity { get ; } = identity ;
167287
@@ -188,19 +308,40 @@ public long? EstimatedByteLength
188308 }
189309 }
190310
191- public async ValueTask < RawTexturePayload > MaterializeRawAsync ( CancellationToken cancellationToken )
311+ public async ValueTask < Rgba32RawTexturePayload > MaterializeRgba32Async ( CancellationToken cancellationToken )
192312 {
193313 using Image < Rgba32 > image = await Image . LoadAsync < Rgba32 > ( absolutePath , cancellationToken ) ;
194314 return TextureImportSourceFactory . CreateRawPayloadFromImage ( image , ColorProfile ) ;
195315 }
196316}
197317
198- internal sealed class GeneratedTextureImportSource (
199- Func < CancellationToken , ValueTask < RawTexturePayload > > materializeRawAsync ,
318+ internal sealed class GeneratedRgba32TextureImportSource (
319+ Func < CancellationToken , ValueTask < Rgba32RawTexturePayload > > materializeRgba32Async ,
320+ string identity ,
321+ string description ,
322+ string ? colorProfile ,
323+ long ? estimatedByteLength = null ) : IRgba32RawTexturePayloadSource
324+ {
325+ public string Identity { get ; } = identity ;
326+
327+ public string Description { get ; } = description ;
328+
329+ public string ? ColorProfile { get ; } = colorProfile ;
330+
331+ public long ? EstimatedByteLength { get ; } = estimatedByteLength ;
332+
333+ public ValueTask < Rgba32RawTexturePayload > MaterializeRgba32Async ( CancellationToken cancellationToken )
334+ {
335+ return materializeRgba32Async ( cancellationToken ) ;
336+ }
337+ }
338+
339+ internal sealed class GeneratedRgbaFloat32TextureImportSource (
340+ Func < CancellationToken , ValueTask < RgbaFloat32RawTexturePayload > > materializeRgbaFloat32Async ,
200341 string identity ,
201342 string description ,
202343 string ? colorProfile ,
203- long ? estimatedByteLength = null ) : IRawTexturePayloadSource
344+ long ? estimatedByteLength = null ) : IRgbaFloat32RawTexturePayloadSource
204345{
205346 public string Identity { get ; } = identity ;
206347
@@ -210,9 +351,9 @@ internal sealed class GeneratedTextureImportSource(
210351
211352 public long ? EstimatedByteLength { get ; } = estimatedByteLength ;
212353
213- public ValueTask < RawTexturePayload > MaterializeRawAsync ( CancellationToken cancellationToken )
354+ public ValueTask < RgbaFloat32RawTexturePayload > MaterializeRgbaFloat32Async ( CancellationToken cancellationToken )
214355 {
215- return materializeRawAsync ( cancellationToken ) ;
356+ return materializeRgbaFloat32Async ( cancellationToken ) ;
216357 }
217358}
218359
@@ -266,15 +407,30 @@ public static ITextureImportSource CreateFileImage(
266407 identity ?? $ "file:{ Path . GetFullPath ( absolutePath ) } :{ colorProfile } ") ;
267408 }
268409
269- public static ITextureImportSource CreateGeneratedImage (
270- Func < CancellationToken , ValueTask < RawTexturePayload > > materializeRawAsync ,
410+ public static ITextureImportSource CreateGeneratedRgba32Image (
411+ Func < CancellationToken , ValueTask < Rgba32RawTexturePayload > > materializeRgba32Async ,
412+ string identity ,
413+ string description ,
414+ string ? colorProfile ,
415+ long ? estimatedByteLength = null )
416+ {
417+ return new GeneratedRgba32TextureImportSource (
418+ materializeRgba32Async ,
419+ identity ,
420+ description ,
421+ colorProfile ,
422+ estimatedByteLength ) ;
423+ }
424+
425+ public static ITextureImportSource CreateGeneratedRgbaFloat32Image (
426+ Func < CancellationToken , ValueTask < RgbaFloat32RawTexturePayload > > materializeRgbaFloat32Async ,
271427 string identity ,
272428 string description ,
273429 string ? colorProfile ,
274430 long ? estimatedByteLength = null )
275431 {
276- return new GeneratedTextureImportSource (
277- materializeRawAsync ,
432+ return new GeneratedRgbaFloat32TextureImportSource (
433+ materializeRgbaFloat32Async ,
278434 identity ,
279435 description ,
280436 colorProfile ,
@@ -290,7 +446,7 @@ public static ITextureImportSource CreateGeneratedImageFromClone(
290446 ArgumentNullException . ThrowIfNull ( image ) ;
291447 Image < Rgba32 > retainedImage = image . Clone ( ) ;
292448 object gate = new ( ) ;
293- return CreateGeneratedImage (
449+ return CreateGeneratedRgba32Image (
294450 cancellationToken =>
295451 {
296452 cancellationToken . ThrowIfCancellationRequested ( ) ;
@@ -305,14 +461,14 @@ public static ITextureImportSource CreateGeneratedImageFromClone(
305461 ( long ) image . Width * image . Height * 4 ) ;
306462 }
307463
308- public static RawTexturePayload CreateRawPayloadFromImage (
464+ public static Rgba32RawTexturePayload CreateRawPayloadFromImage (
309465 Image < Rgba32 > image ,
310466 string ? colorProfile )
311467 {
312468 ArgumentNullException . ThrowIfNull ( image ) ;
313469 byte [ ] rawBytes = new byte [ image . Width * image . Height * 4 ] ;
314470 image . CopyPixelDataTo ( rawBytes ) ;
315- return new RawTexturePayload (
471+ return new Rgba32RawTexturePayload (
316472 image . Width ,
317473 image . Height ,
318474 colorProfile ,
0 commit comments