Skip to content

Commit b33209c

Browse files
committed
Merge branch 'riff-helper' into animated-webp-encoder
2 parents b4e1b7f + 4beafcf commit b33209c

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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 static class RiffHelper
10+
{
11+
/// <summary>
12+
/// The header bytes identifying RIFF file.
13+
/// </summary>
14+
private const 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.WriteUInt32BigEndian(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+
38+
uint dataSize = (uint)(position - sizePosition - 4);
39+
40+
// padding
41+
if (dataSize % 2 == 1)
42+
{
43+
stream.WriteByte(0);
44+
position++;
45+
}
46+
47+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, dataSize);
48+
stream.Position = sizePosition;
49+
stream.Write(buffer);
50+
stream.Position = position;
51+
}
52+
53+
public static void WriteChunk(Stream stream, uint fourCc, ReadOnlySpan<byte> data)
54+
{
55+
Span<byte> buffer = stackalloc byte[4];
56+
57+
// write the fourCC
58+
BinaryPrimitives.WriteUInt32BigEndian(buffer, fourCc);
59+
stream.Write(buffer);
60+
uint size = (uint)data.Length;
61+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, size);
62+
stream.Write(buffer);
63+
stream.Write(data);
64+
65+
// padding
66+
if (size % 2 is 1)
67+
{
68+
stream.WriteByte(0);
69+
}
70+
}
71+
72+
public static unsafe void WriteChunk<TStruct>(Stream stream, uint fourCc, in TStruct chunk)
73+
where TStruct : unmanaged
74+
{
75+
fixed (TStruct* ptr = &chunk)
76+
{
77+
WriteChunk(stream, fourCc, new Span<byte>(ptr, sizeof(TStruct)));
78+
}
79+
}
80+
81+
public static long BeginWriteChunk(Stream stream, uint fourCc)
82+
{
83+
Span<byte> buffer = stackalloc byte[4];
84+
85+
// write the fourCC
86+
BinaryPrimitives.WriteUInt32BigEndian(buffer, fourCc);
87+
stream.Write(buffer);
88+
89+
long sizePosition = stream.Position;
90+
stream.Position += 4;
91+
92+
return sizePosition;
93+
}
94+
95+
public static void EndWriteChunk(Stream stream, long sizePosition)
96+
{
97+
Span<byte> buffer = stackalloc byte[4];
98+
99+
long position = stream.Position;
100+
101+
uint dataSize = (uint)(position - sizePosition - 4);
102+
103+
// padding
104+
if (dataSize % 2 is 1)
105+
{
106+
stream.WriteByte(0);
107+
position++;
108+
}
109+
110+
BinaryPrimitives.WriteUInt32LittleEndian(buffer, dataSize);
111+
stream.Position = sizePosition;
112+
stream.Write(buffer);
113+
stream.Position = position;
114+
}
115+
116+
public static long BeginWriteRiffFile(Stream stream, string formType)
117+
{
118+
long sizePosition = BeginWriteChunk(stream, RiffFourCc);
119+
stream.Write(Encoding.ASCII.GetBytes(formType));
120+
return sizePosition;
121+
}
122+
123+
public static void EndWriteRiffFile(Stream stream, long sizePosition) => EndWriteChunk(stream, sizePosition);
124+
}

0 commit comments

Comments
 (0)