Browse Source

Remove index bounds checks from Png encoder

af/merge-core
James Jackson-South 8 years ago
parent
commit
edcb2ec52f
  1. 41
      src/ImageSharp/Formats/Png/PngEncoderCore.cs

41
src/ImageSharp/Formats/Png/PngEncoderCore.cs

@ -316,7 +316,10 @@ namespace SixLabors.ImageSharp.Formats.Png
const float RX = .2126F; const float RX = .2126F;
const float GX = .7152F; const float GX = .7152F;
const float BX = .0722F; const float BX = .0722F;
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
Span<byte> rawScanlineSpan = this.rawScanline.GetSpan(); Span<byte> rawScanlineSpan = this.rawScanline.GetSpan();
ref byte rawScanlineSpanRef = ref MemoryMarshal.GetReference(rawScanlineSpan);
if (this.pngColorType.Equals(PngColorType.Grayscale)) if (this.pngColorType.Equals(PngColorType.Grayscale))
{ {
@ -327,7 +330,7 @@ namespace SixLabors.ImageSharp.Formats.Png
Rgb48 rgb = default; Rgb48 rgb = default;
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2) for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2)
{ {
rowSpan[x].ToRgb48(ref rgb); Unsafe.Add(ref rowSpanRef, x).ToRgb48(ref rgb);
ushort luminance = (ushort)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B)); ushort luminance = (ushort)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B));
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
} }
@ -340,8 +343,8 @@ namespace SixLabors.ImageSharp.Formats.Png
Rgb24 rgb = default; Rgb24 rgb = default;
for (int x = 0; x < rowSpan.Length; x++) for (int x = 0; x < rowSpan.Length; x++)
{ {
rowSpan[x].ToRgb24(ref rgb); Unsafe.Add(ref rowSpanRef, x).ToRgb24(ref rgb);
rawScanlineSpan[x] = (byte)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B)); Unsafe.Add(ref rawScanlineSpanRef, x) = (byte)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B));
} }
} }
else else
@ -351,12 +354,14 @@ namespace SixLabors.ImageSharp.Formats.Png
{ {
int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(this.bitDepth) - 1); int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(this.bitDepth) - 1);
Span<byte> tempSpan = temp.GetSpan(); Span<byte> tempSpan = temp.GetSpan();
ref byte tempSpanRef = ref MemoryMarshal.GetReference(tempSpan);
Rgb24 rgb = default; Rgb24 rgb = default;
for (int x = 0; x < rowSpan.Length; x++) for (int x = 0; x < rowSpan.Length; x++)
{ {
rowSpan[x].ToRgb24(ref rgb); Unsafe.Add(ref rowSpanRef, x).ToRgb24(ref rgb);
float luminance = ((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B)) / scaleFactor; float luminance = ((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B)) / scaleFactor;
tempSpan[x] = (byte)luminance; Unsafe.Add(ref tempSpanRef, x) = (byte)luminance;
this.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth); this.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth);
} }
} }
@ -371,7 +376,7 @@ namespace SixLabors.ImageSharp.Formats.Png
Rgba64 rgba = default; Rgba64 rgba = default;
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 4) for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 4)
{ {
rowSpan[x].ToRgba64(ref rgba); Unsafe.Add(ref rowSpanRef, x).ToRgba64(ref rgba);
ushort luminance = (ushort)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B)); ushort luminance = (ushort)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B));
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A);
@ -383,9 +388,9 @@ namespace SixLabors.ImageSharp.Formats.Png
Rgba32 rgba = default; Rgba32 rgba = default;
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2) for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2)
{ {
rowSpan[x].ToRgba32(ref rgba); Unsafe.Add(ref rowSpanRef, x).ToRgba32(ref rgba);
rawScanlineSpan[o] = (byte)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B)); Unsafe.Add(ref rawScanlineSpanRef, o) = (byte)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B));
rawScanlineSpan[o + 1] = rgba.A; Unsafe.Add(ref rawScanlineSpanRef, o + 1) = rgba.A;
} }
} }
} }
@ -421,9 +426,10 @@ namespace SixLabors.ImageSharp.Formats.Png
{ {
// 16 bit Rgba // 16 bit Rgba
Rgba64 rgba = default; Rgba64 rgba = default;
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 8) for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 8)
{ {
rowSpan[x].ToRgba64(ref rgba); Unsafe.Add(ref rowSpanRef, x).ToRgba64(ref rgba);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgba.R); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgba.R);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.G); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.G);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgba.B); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgba.B);
@ -437,9 +443,10 @@ namespace SixLabors.ImageSharp.Formats.Png
{ {
// 16 bit Rgb // 16 bit Rgb
Rgb48 rgb = default; Rgb48 rgb = default;
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 6) for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 6)
{ {
rowSpan[x].ToRgb48(ref rgb); Unsafe.Add(ref rowSpanRef, x).ToRgb48(ref rgb);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgb.R); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgb.R);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgb.G); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgb.G);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgb.B); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgb.B);
@ -630,8 +637,8 @@ namespace SixLabors.ImageSharp.Formats.Png
using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength)) using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength))
using (IManagedByteBuffer alphaTable = this.memoryAllocator.AllocateManagedByteBuffer(paletteLength)) using (IManagedByteBuffer alphaTable = this.memoryAllocator.AllocateManagedByteBuffer(paletteLength))
{ {
Span<byte> colorTableSpan = colorTable.GetSpan(); ref byte colorTableRef = ref MemoryMarshal.GetReference(colorTable.GetSpan());
Span<byte> alphaTableSpan = alphaTable.GetSpan(); ref byte alphaTableRef = ref MemoryMarshal.GetReference(alphaTable.GetSpan());
Span<byte> quantizedSpan = quantized.GetPixelSpan(); Span<byte> quantizedSpan = quantized.GetPixelSpan();
for (int i = 0; i < paletteLength; i++) for (int i = 0; i < paletteLength; i++)
@ -643,9 +650,9 @@ namespace SixLabors.ImageSharp.Formats.Png
byte alpha = rgba.A; byte alpha = rgba.A;
colorTableSpan[offset] = rgba.R; Unsafe.Add(ref colorTableRef, offset) = rgba.R;
colorTableSpan[offset + 1] = rgba.G; Unsafe.Add(ref colorTableRef, offset + 1) = rgba.G;
colorTableSpan[offset + 2] = rgba.B; Unsafe.Add(ref colorTableRef, offset + 2) = rgba.B;
if (alpha > this.threshold) if (alpha > this.threshold)
{ {
@ -653,7 +660,7 @@ namespace SixLabors.ImageSharp.Formats.Png
} }
anyAlpha = anyAlpha || alpha < byte.MaxValue; anyAlpha = anyAlpha || alpha < byte.MaxValue;
alphaTableSpan[i] = alpha; Unsafe.Add(ref alphaTableRef, i) = alpha;
} }
} }

Loading…
Cancel
Save