-
-
Notifications
You must be signed in to change notification settings - Fork 894
Expand file tree
/
Copy pathRiffHelper.cs
More file actions
139 lines (110 loc) · 3.75 KB
/
Copy pathRiffHelper.cs
File metadata and controls
139 lines (110 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Buffers.Binary;
using System.Text;
using SixLabors.ImageSharp.Formats.Webp.Chunks;
namespace SixLabors.ImageSharp.Common.Helpers;
internal static class RiffHelper
{
/// <summary>
/// The header bytes identifying RIFF file.
/// </summary>
private const uint RiffFourCc = 0x52_49_46_46;
public static void WriteRiffFile(Stream stream, string formType, Action<Stream> func) =>
WriteChunk(stream, RiffFourCc, s =>
{
s.Write(Encoding.ASCII.GetBytes(formType));
func(s);
});
public static void WriteChunk(Stream stream, uint fourCc, Action<Stream> func)
{
Span<byte> buffer = stackalloc byte[4];
// write the fourCC
BinaryPrimitives.WriteUInt32BigEndian(buffer, fourCc);
stream.Write(buffer);
long sizePosition = stream.Position;
stream.Position += 4;
func(stream);
long position = stream.Position;
uint dataSize = (uint)(position - sizePosition - 4);
// padding
if (dataSize % 2 == 1)
{
stream.WriteByte(0);
position++;
}
BinaryPrimitives.WriteUInt32LittleEndian(buffer, dataSize);
stream.Position = sizePosition;
stream.Write(buffer);
stream.Position = position;
}
public static void WriteChunk(Stream stream, uint fourCc, ReadOnlySpan<byte> data)
{
Span<byte> buffer = stackalloc byte[4];
// write the fourCC
BinaryPrimitives.WriteUInt32BigEndian(buffer, fourCc);
stream.Write(buffer);
uint size = (uint)data.Length;
BinaryPrimitives.WriteUInt32LittleEndian(buffer, size);
stream.Write(buffer);
stream.Write(data);
// padding
if (size % 2 is 1)
{
stream.WriteByte(0);
}
}
public static unsafe void WriteChunk<TStruct>(Stream stream, uint fourCc, in TStruct chunk)
where TStruct : unmanaged
{
fixed (TStruct* ptr = &chunk)
{
WriteChunk(stream, fourCc, new Span<byte>(ptr, sizeof(TStruct)));
}
}
public static long BeginWriteChunk(Stream stream, uint fourCc)
{
Span<byte> buffer = stackalloc byte[4];
// write the fourCC
BinaryPrimitives.WriteUInt32BigEndian(buffer, fourCc);
stream.Write(buffer);
long sizePosition = stream.Position;
stream.Position += 4;
return sizePosition;
}
public static void EndWriteChunk(Stream stream, long sizePosition)
{
Span<byte> buffer = stackalloc byte[4];
long position = stream.Position;
uint dataSize = (uint)(position - sizePosition - 4);
// padding
if (dataSize % 2 is 1)
{
stream.WriteByte(0);
position++;
}
// Add the size of the encoded file to the Riff header.
BinaryPrimitives.WriteUInt32LittleEndian(buffer, dataSize);
stream.Position = sizePosition;
stream.Write(buffer);
stream.Position = position;
}
public static long BeginWriteRiffFile(Stream stream, string formType)
{
long sizePosition = BeginWriteChunk(stream, RiffFourCc);
stream.Write(Encoding.ASCII.GetBytes(formType));
return sizePosition;
}
public static void EndWriteRiffFile(Stream stream, in WebpVp8X vp8x, bool updateVp8x, long sizePosition)
{
EndWriteChunk(stream, sizePosition + 4);
// Write the VP8X chunk if necessary.
if (updateVp8x)
{
long position = stream.Position;
stream.Position = sizePosition + 12;
vp8x.WriteTo(stream);
stream.Position = position;
}
}
}