Skip to content

Commit 296da73

Browse files
committed
add riif helper
1 parent b4e9805 commit 296da73

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using System.Buffers.Binary;
5+
using System.Text;
6+
7+
namespace SixLabors.ImageSharp.Common.Helpers;
8+
9+
internal class RiffHelper
10+
{
11+
/// <summary>
12+
/// The header bytes identifying RIFF file.
13+
/// </summary>
14+
public static readonly uint RiffFourCc = 0x52_49_46_46;
15+
16+
public static void WriteRiffFile(Stream stream, string formType, Action<Stream> func) =>
17+
WriteChunk(stream, RiffFourCc, s =>
18+
{
19+
s.Write(Encoding.ASCII.GetBytes(formType));
20+
func(s);
21+
});
22+
23+
public static void WriteChunk(Stream stream, uint fourCc, Action<Stream> func)
24+
{
25+
Span<byte> buffer = stackalloc byte[4];
26+
27+
// write the fourCC
28+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, fourCc);
29+
stream.Write(buffer);
30+
31+
long sizePosition = stream.Position;
32+
stream.Position += 4;
33+
34+
func(stream);
35+
36+
long position = stream.Position;
37+
stream.Position = sizePosition;
38+
39+
uint dataSize = (uint)(position - sizePosition - 4);
40+
41+
// padding
42+
if (dataSize % 2 == 1)
43+
{
44+
stream.WriteByte(0);
45+
position++;
46+
}
47+
48+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, dataSize);
49+
stream.Write(buffer);
50+
51+
stream.Position = position;
52+
}
53+
54+
public static void WriteChunk(Stream stream, uint fourCc, ReadOnlySpan<byte> data)
55+
{
56+
Span<byte> buffer = stackalloc byte[4];
57+
58+
// write the fourCC
59+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, fourCc);
60+
stream.Write(buffer);
61+
uint size = (uint)data.Length;
62+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, size);
63+
stream.Write(buffer);
64+
stream.Write(data);
65+
66+
// padding
67+
if (size % 2 == 1)
68+
{
69+
stream.WriteByte(0);
70+
}
71+
}
72+
73+
public static unsafe void WriteChunk<TStruct>(Stream stream, uint fourCc, in TStruct chunk)
74+
where TStruct : unmanaged
75+
{
76+
fixed (TStruct* ptr = &chunk)
77+
{
78+
WriteChunk(stream, fourCc, new Span<byte>(ptr, sizeof(TStruct)));
79+
}
80+
}
81+
82+
public static long BeginWriteChunk(Stream stream, uint fourCc)
83+
{
84+
Span<byte> buffer = stackalloc byte[4];
85+
86+
// write the fourCC
87+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, fourCc);
88+
stream.Write(buffer);
89+
90+
long sizePosition = stream.Position;
91+
stream.Position += 4;
92+
93+
return sizePosition;
94+
}
95+
96+
public static void EndWriteChunk(Stream stream, long sizePosition)
97+
{
98+
Span<byte> buffer = stackalloc byte[4];
99+
100+
long position = stream.Position;
101+
stream.Position = sizePosition;
102+
103+
uint dataSize = (uint)(position - sizePosition - 4);
104+
105+
// padding
106+
if (dataSize % 2 == 1)
107+
{
108+
stream.WriteByte(0);
109+
position++;
110+
}
111+
112+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, dataSize);
113+
stream.Write(buffer);
114+
115+
stream.Position = position;
116+
}
117+
}

0 commit comments

Comments
 (0)