10
10
11
11
namespace SixLabors . ImageSharp . Formats . Webp . Lossless ;
12
12
13
- internal sealed class Vp8LHistogram : IDisposable
13
+ internal sealed unsafe class Vp8LHistogram : IDisposable
14
14
{
15
15
private const uint NonTrivialSym = 0xffffffff ;
16
- private readonly IMemoryOwner < uint > buffer ;
16
+ private readonly IMemoryOwner < uint > ? bufferOwner ;
17
+ private readonly Memory < uint > buffer ;
18
+ private readonly MemoryHandle bufferHandle ;
19
+
20
+ private readonly uint * red ;
21
+ private readonly uint * blue ;
22
+ private readonly uint * alpha ;
23
+ private readonly uint * distance ;
24
+ private readonly uint * literal ;
25
+ private readonly uint * isUsed ;
26
+
17
27
private const int RedSize = WebpConstants . NumLiteralCodes ;
18
28
private const int BlueSize = WebpConstants . NumLiteralCodes ;
19
29
private const int AlphaSize = WebpConstants . NumLiteralCodes ;
20
30
private const int DistanceSize = WebpConstants . NumDistanceCodes ;
21
31
public const int LiteralSize = WebpConstants . NumLiteralCodes + WebpConstants . NumLengthCodes + ( 1 << WebpConstants . MaxColorCacheBits ) + 1 ;
22
32
private const int UsedSize = 5 ; // 5 for literal, red, blue, alpha, distance
23
33
public const int BufferSize = RedSize + BlueSize + AlphaSize + DistanceSize + LiteralSize + UsedSize ;
24
- private readonly bool isSetMember ;
25
-
26
- /// <summary>
27
- /// Initializes a new instance of the <see cref="Vp8LHistogram"/> class.
28
- /// </summary>
29
- /// <param name="memoryAllocator">The memory allocator.</param>
30
- /// <param name="refs">The backward references to initialize the histogram with.</param>
31
- /// <param name="paletteCodeBits">The palette code bits.</param>
32
- public Vp8LHistogram ( MemoryAllocator memoryAllocator , Vp8LBackwardRefs refs , int paletteCodeBits )
33
- : this ( memoryAllocator , paletteCodeBits ) => this . StoreRefs ( refs ) ;
34
-
35
- /// <summary>
36
- /// Initializes a new instance of the <see cref="Vp8LHistogram"/> class.
37
- /// </summary>
38
- /// <param name="memoryAllocator">The memory allocator.</param>
39
- /// <param name="paletteCodeBits">The palette code bits.</param>
40
- public Vp8LHistogram ( MemoryAllocator memoryAllocator , int paletteCodeBits )
41
- {
42
- this . buffer = memoryAllocator . Allocate < uint > ( BufferSize , AllocationOptions . Clean ) ;
43
- this . PaletteCodeBits = paletteCodeBits ;
44
- }
45
34
46
35
/// <summary>
47
36
/// Initializes a new instance of the <see cref="Vp8LHistogram"/> class.
@@ -52,7 +41,7 @@ public Vp8LHistogram(MemoryAllocator memoryAllocator, int paletteCodeBits)
52
41
/// <param name="buffer">The backing buffer.</param>
53
42
/// <param name="refs">The backward references to initialize the histogram with.</param>
54
43
/// <param name="paletteCodeBits">The palette code bits.</param>
55
- public Vp8LHistogram ( IMemoryOwner < uint > buffer , Vp8LBackwardRefs refs , int paletteCodeBits )
44
+ public Vp8LHistogram ( Memory < uint > buffer , Vp8LBackwardRefs refs , int paletteCodeBits )
56
45
: this ( buffer , paletteCodeBits ) => this . StoreRefs ( refs ) ;
57
46
58
47
/// <summary>
@@ -63,11 +52,20 @@ public Vp8LHistogram(IMemoryOwner<uint> buffer, Vp8LBackwardRefs refs, int palet
63
52
/// </remarks>
64
53
/// <param name="buffer">The backing buffer.</param>
65
54
/// <param name="paletteCodeBits">The palette code bits.</param>
66
- public Vp8LHistogram ( IMemoryOwner < uint > buffer , int paletteCodeBits )
55
+ /// <param name="bufferOwner">Optional buffer owner to dispose.</param>
56
+ public Vp8LHistogram ( Memory < uint > buffer , int paletteCodeBits , IMemoryOwner < uint > ? bufferOwner = null )
67
57
{
58
+ this . bufferOwner = bufferOwner ;
68
59
this . buffer = buffer ;
60
+ this . bufferHandle = this . buffer . Pin ( ) ;
69
61
this . PaletteCodeBits = paletteCodeBits ;
70
- this . isSetMember = true ;
62
+
63
+ this . red = ( uint * ) this . bufferHandle . Pointer ;
64
+ this . blue = this . red + RedSize ;
65
+ this . alpha = this . blue + BlueSize ;
66
+ this . distance = this . alpha + AlphaSize ;
67
+ this . literal = this . distance + DistanceSize ;
68
+ this . isUsed = this . literal + LiteralSize ;
71
69
}
72
70
73
71
/// <summary>
@@ -95,22 +93,43 @@ public Vp8LHistogram(IMemoryOwner<uint> buffer, int paletteCodeBits)
95
93
/// </summary>
96
94
public double BlueCost { get ; set ; }
97
95
98
- public Span < uint > Red => this . buffer . GetSpan ( ) [ .. RedSize ] ;
96
+ public Span < uint > Red => new ( this . red , RedSize ) ;
99
97
100
- public Span < uint > Blue => this . buffer . GetSpan ( ) . Slice ( RedSize , BlueSize ) ;
98
+ public Span < uint > Blue => new ( this . blue , BlueSize ) ;
101
99
102
- public Span < uint > Alpha => this . buffer . GetSpan ( ) . Slice ( RedSize + BlueSize , AlphaSize ) ;
100
+ public Span < uint > Alpha => new ( this . alpha , AlphaSize ) ;
103
101
104
- public Span < uint > Distance => this . buffer . GetSpan ( ) . Slice ( RedSize + BlueSize + AlphaSize , DistanceSize ) ;
102
+ public Span < uint > Distance => new ( this . distance , DistanceSize ) ;
105
103
106
- public Span < uint > Literal => this . buffer . GetSpan ( ) . Slice ( RedSize + BlueSize + AlphaSize + DistanceSize , LiteralSize ) ;
104
+ public Span < uint > Literal => new ( this . literal , LiteralSize ) ;
107
105
108
106
public uint TrivialSymbol { get ; set ; }
109
107
110
- private Span < uint > IsUsedSpan => this . buffer . GetSpan ( ) . Slice ( RedSize + BlueSize + AlphaSize + DistanceSize + LiteralSize , UsedSize ) ;
108
+ private Span < uint > IsUsedSpan => new ( this . isUsed , UsedSize ) ;
109
+
110
+ private Span < uint > TotalSpan => new ( this . red , BufferSize ) ;
111
111
112
112
public bool IsDisposed { get ; set ; }
113
113
114
+ /// <summary>
115
+ /// Creates an <see cref="Vp8LHistogram"/> that is not a member of a <see cref="Vp8LHistogramSet"/>.
116
+ /// </summary>
117
+ public static Vp8LHistogram Create ( MemoryAllocator memoryAllocator , int paletteCodeBits )
118
+ {
119
+ IMemoryOwner < uint > bufferOwner = memoryAllocator . Allocate < uint > ( BufferSize , AllocationOptions . Clean ) ;
120
+ return new Vp8LHistogram ( bufferOwner . Memory , paletteCodeBits , bufferOwner ) ;
121
+ }
122
+
123
+ /// <summary>
124
+ /// Creates an <see cref="Vp8LHistogram"/> that is not a member of a <see cref="Vp8LHistogramSet"/>.
125
+ /// </summary>
126
+ public static Vp8LHistogram Create ( MemoryAllocator memoryAllocator , Vp8LBackwardRefs refs , int paletteCodeBits )
127
+ {
128
+ Vp8LHistogram histogram = Create ( memoryAllocator , paletteCodeBits ) ;
129
+ histogram . StoreRefs ( refs ) ;
130
+ return histogram ;
131
+ }
132
+
114
133
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
115
134
public bool IsUsed ( int index ) => this . IsUsedSpan [ index ] == 1u ;
116
135
@@ -140,7 +159,7 @@ public void CopyTo(Vp8LHistogram other)
140
159
141
160
public void Clear ( )
142
161
{
143
- this . buffer . Clear ( ) ;
162
+ this . TotalSpan . Clear ( ) ;
144
163
this . PaletteCodeBits = 0 ;
145
164
this . BitCost = 0 ;
146
165
this . LiteralCost = 0 ;
@@ -607,11 +626,8 @@ public void Dispose()
607
626
{
608
627
if ( ! this . IsDisposed )
609
628
{
610
- if ( ! this . isSetMember )
611
- {
612
- this . buffer . Dispose ( ) ;
613
- }
614
-
629
+ this . bufferHandle . Dispose ( ) ;
630
+ this . bufferOwner ? . Dispose ( ) ;
615
631
this . IsDisposed = true ;
616
632
}
617
633
}
0 commit comments