diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcFillPredictor.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcFillPredictor.cs
new file mode 100644
index 0000000000..d0bc59f1c0
--- /dev/null
+++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcFillPredictor.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+
+namespace SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
+
+internal class Av1DcFillPredictor : IAv1Predictor
+{
+ private readonly uint blockWidth;
+ private readonly uint blockHeight;
+
+ public Av1DcFillPredictor(Size blockSize)
+ {
+ this.blockWidth = (uint)blockSize.Width;
+ this.blockHeight = (uint)blockSize.Height;
+ }
+
+ public void PredictScalar(ref byte destination, nuint stride, ref byte above, ref byte left)
+ {
+ const byte expectedDc = 0x80;
+ for (uint r = 0; r < this.blockHeight; r++)
+ {
+ Unsafe.InitBlock(ref destination, expectedDc, this.blockWidth);
+ destination = ref Unsafe.Add(ref destination, stride);
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcLeftPredictor.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcLeftPredictor.cs
new file mode 100644
index 0000000000..4aea10bdf4
--- /dev/null
+++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcLeftPredictor.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+
+namespace SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
+
+internal class Av1DcLeftPredictor : IAv1Predictor
+{
+ private readonly uint blockWidth;
+ private readonly uint blockHeight;
+
+ public Av1DcLeftPredictor(Size blockSize)
+ {
+ this.blockWidth = (uint)blockSize.Width;
+ this.blockHeight = (uint)blockSize.Height;
+ }
+
+ public void PredictScalar(ref byte destination, nuint stride, ref byte above, ref byte left)
+ {
+ int sum = 0;
+ for (uint i = 0; i < this.blockHeight; i++)
+ {
+ sum += Unsafe.Add(ref left, i);
+ }
+
+ byte expectedDc = (byte)((sum + (this.blockHeight >> 1)) / this.blockHeight);
+ for (uint r = 0; r < this.blockHeight; r++)
+ {
+ Unsafe.InitBlock(ref destination, expectedDc, this.blockWidth);
+ destination = ref Unsafe.Add(ref destination, stride);
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcPredictor.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcPredictor.cs
new file mode 100644
index 0000000000..f3a3cf4ae6
--- /dev/null
+++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcPredictor.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+
+namespace SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
+
+internal class Av1DcPredictor : IAv1Predictor
+{
+ private readonly uint blockWidth;
+ private readonly uint blockHeight;
+
+ public Av1DcPredictor(Size blockSize)
+ {
+ this.blockWidth = (uint)blockSize.Width;
+ this.blockHeight = (uint)blockSize.Height;
+ }
+
+ public void PredictScalar(ref byte destination, nuint stride, ref byte above, ref byte left)
+ {
+ int sum = 0;
+ uint count = this.blockWidth + this.blockHeight;
+ for (uint i = 0; i < this.blockWidth; i++)
+ {
+ sum += Unsafe.Add(ref above, i);
+ }
+
+ for (uint i = 0; i < this.blockHeight; i++)
+ {
+ sum += Unsafe.Add(ref left, i);
+ }
+
+ byte expectedDc = (byte)((sum + (count >> 1)) / count);
+ for (uint r = 0; r < this.blockHeight; r++)
+ {
+ Unsafe.InitBlock(ref destination, expectedDc, this.blockWidth);
+ destination = ref Unsafe.Add(ref destination, stride);
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcTopPredictor.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcTopPredictor.cs
new file mode 100644
index 0000000000..a79a473938
--- /dev/null
+++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DcTopPredictor.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+
+namespace SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
+
+internal class Av1DcTopPredictor : IAv1Predictor
+{
+ private readonly uint blockWidth;
+ private readonly uint blockHeight;
+
+ public Av1DcTopPredictor(Size blockSize)
+ {
+ this.blockWidth = (uint)blockSize.Width;
+ this.blockHeight = (uint)blockSize.Height;
+ }
+
+ public void PredictScalar(ref byte destination, nuint stride, ref byte above, ref byte left)
+ {
+ int sum = 0;
+ for (uint i = 0; i < this.blockWidth; i++)
+ {
+ sum += Unsafe.Add(ref above, i);
+ }
+
+ byte expectedDc = (byte)((sum + (this.blockWidth >> 1)) / this.blockWidth);
+ for (uint r = 0; r < this.blockHeight; r++)
+ {
+ Unsafe.InitBlock(ref destination, expectedDc, this.blockWidth);
+ destination = ref Unsafe.Add(ref destination, stride);
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/IAv1Predictor.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/IAv1Predictor.cs
new file mode 100644
index 0000000000..3bf8907789
--- /dev/null
+++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/IAv1Predictor.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
+
+///
+/// Interface for predictor implementations.
+///
+internal interface IAv1Predictor
+{
+ ///
+ /// Predict using scalar logic within the 8-bit pipeline.
+ ///
+ /// The destination to write to.
+ /// The stride of the destination buffer.
+ /// Pointer to the first element of the block above.
+ /// Pointer to the first element of the block to the left.
+ public void PredictScalar(ref byte destination, nuint stride, ref byte above, ref byte left);
+}
diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/PredictorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/PredictorTests.cs
new file mode 100644
index 0000000000..42dfaa568a
--- /dev/null
+++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/PredictorTests.cs
@@ -0,0 +1,123 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
+using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
+
+namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
+
+[Trait("Format", "Avif")]
+public class PredictorTests
+{
+ [Theory]
+ [MemberData(nameof(GetTransformSizes))]
+ public void VerifyDcFill(int width, int height)
+ {
+ // Assign
+ byte[] destination = new byte[width * height];
+ byte[] left = new byte[1];
+ byte[] above = new byte[1];
+ byte expected = 0x80;
+
+ // Act
+ Av1DcFillPredictor predictor = new(new Size(width, height));
+ predictor.PredictScalar(ref destination[0], (nuint)width, ref above[0], ref left[0]);
+
+ // Assert
+ Assert.All(destination, (b) => AssertValue(expected, b));
+ }
+
+ [Theory]
+ [MemberData(nameof(GetTransformSizes))]
+ public void VerifyDc(int width, int height)
+ {
+ // Assign
+ byte[] destination = new byte[width * height];
+ byte[] left = new byte[width * height];
+ byte[] above = new byte[width * height];
+ Array.Fill(left, (byte)5);
+ Array.Fill(above, (byte)28);
+ int count = width + height;
+ int sum = Sum(left, height) + Sum(above, width);
+ byte expected = (byte)((sum + (count >> 1)) / count);
+
+ // Act
+ Av1DcPredictor predictor = new(new Size(width, height));
+ predictor.PredictScalar(ref destination[0], (nuint)width, ref above[0], ref left[0]);
+
+ // Assert
+ Assert.Equal((5 * height) + (28 * width), sum);
+ Assert.All(destination, (b) => AssertValue(expected, b));
+ }
+
+ [Theory]
+ [MemberData(nameof(GetTransformSizes))]
+ public void VerifyDcLeft(int width, int height)
+ {
+ // Assign
+ byte[] destination = new byte[width * height];
+ byte[] left = new byte[width * height];
+ byte[] above = new byte[width * height];
+ Array.Fill(left, (byte)5);
+ Array.Fill(above, (byte)28);
+ byte expected = left[0];
+
+ // Act
+ Av1DcLeftPredictor predictor = new(new Size(width, height));
+ predictor.PredictScalar(ref destination[0], (nuint)width, ref above[0], ref left[0]);
+
+ // Assert
+ Assert.All(destination, (b) => AssertValue(expected, b));
+ }
+
+ [Theory]
+ [MemberData(nameof(GetTransformSizes))]
+ public void VerifyDcTop(int width, int height)
+ {
+ // Assign
+ byte[] destination = new byte[width * height];
+ byte[] left = new byte[width * height];
+ byte[] above = new byte[width * height];
+ Array.Fill(left, (byte)5);
+ Array.Fill(above, (byte)28);
+ byte expected = above[0];
+
+ // Act
+ Av1DcTopPredictor predictor = new(new Size(width, height));
+ predictor.PredictScalar(ref destination[0], (nuint)width, ref above[0], ref left[0]);
+
+ // Assert
+ Assert.All(destination, (b) => AssertValue(expected, b));
+ }
+
+ private static void AssertValue(byte expected, byte actual)
+ {
+ Assert.NotEqual(0, actual);
+ Assert.Equal(expected, actual);
+ }
+
+ private static int Sum(Span values, int length)
+ {
+ int sum = 0;
+ for (int i = 0; i < length; i++)
+ {
+ sum += values[i];
+ }
+
+ return sum;
+ }
+
+ public static TheoryData GetTransformSizes()
+ {
+ TheoryData combinations = [];
+ for (int s = 0; s < (int)Av1TransformSize.AllSizes; s++)
+ {
+ Av1TransformSize size = (Av1TransformSize)s;
+ int width = size.GetWidth();
+ int height = size.GetHeight();
+ combinations.Add(width, height);
+ }
+
+ return combinations;
+ }
+}
diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/SymbolTest.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/SymbolTests.cs
similarity index 99%
rename from tests/ImageSharp.Tests/Formats/Heif/Av1/SymbolTest.cs
rename to tests/ImageSharp.Tests/Formats/Heif/Av1/SymbolTests.cs
index 33a47cd807..756319adaf 100644
--- a/tests/ImageSharp.Tests/Formats/Heif/Av1/SymbolTest.cs
+++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/SymbolTests.cs
@@ -9,7 +9,7 @@ using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
[Trait("Format", "Avif")]
-public class SymbolTest
+public class SymbolTests
{
[Fact]
public void ReadRandomLiteral()