mirror of https://github.com/SixLabors/ImageSharp
15 changed files with 250 additions and 638 deletions
@ -1,104 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.WebP.Filters |
|||
{ |
|||
// TODO from dsp.h
|
|||
// public enum WebPFilterType
|
|||
// {
|
|||
// None = 0,
|
|||
// Horizontal,
|
|||
// Vertical,
|
|||
// Gradient,
|
|||
// Last = Gradient + 1, // end marker
|
|||
// Best, // meta types
|
|||
// Fast
|
|||
// }
|
|||
|
|||
internal abstract class WebPFilterBase |
|||
{ |
|||
/// <summary>
|
|||
/// </summary>
|
|||
/// <param name="prevLine"></param>
|
|||
/// <param name="prevLineOffset">nullable as prevLine is nullable in the original but Span'T can't be null.</param>
|
|||
/// <param name="preds"></param>
|
|||
/// <param name="predsOffset"></param>
|
|||
/// <param name="currentLine"></param>
|
|||
/// <param name="currentLineOffset"></param>
|
|||
/// <param name="width"></param>
|
|||
public abstract void Unfilter( |
|||
Span<byte> prevLine, |
|||
int? prevLineOffset, |
|||
Span<byte> preds, |
|||
int predsOffset, |
|||
Span<byte> currentLine, |
|||
int currentLineOffset, |
|||
int width); |
|||
|
|||
public abstract void Filter( |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
int width, |
|||
int height, |
|||
int stride, |
|||
Span<byte> output, |
|||
int outputOffset); |
|||
|
|||
protected static void SanityCheck( |
|||
Span<byte> input, Span<byte> output, int width, int numRows, int height, int stride, int row) |
|||
{ |
|||
Debug.Assert(input != null); |
|||
Debug.Assert(output != null); |
|||
Debug.Assert(width > 0); |
|||
Debug.Assert(height > 0); |
|||
Debug.Assert(stride > width); |
|||
Debug.Assert(row >= 0); |
|||
Debug.Assert(height > 0); |
|||
Debug.Assert(row + numRows <= height); |
|||
} |
|||
|
|||
protected static void PredictLine( |
|||
Span<byte> src, |
|||
int srcOffset, |
|||
Span<byte> pred, |
|||
int predOffset, |
|||
Span<byte> dst, |
|||
int dstOffset, |
|||
int length, |
|||
bool inverse) |
|||
{ |
|||
if (inverse) |
|||
{ |
|||
for (int i = 0; i < length; i++) |
|||
{ |
|||
dst[i] = (byte)(src[i] + pred[i]); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int i = 0; i < length; i++) |
|||
{ |
|||
dst[i] = (byte)(src[i] - pred[i]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected void UnfilterHorizontalOrVerticalCore( |
|||
byte pred, |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
Span<byte> output, |
|||
int outputOffset, |
|||
int width) |
|||
{ |
|||
for (int i = 0; i < width; i++) |
|||
{ |
|||
output[outputOffset + i] = (byte)(pred + input[inputOffset + i]); |
|||
pred = output[i]; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,116 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.WebP.Filters |
|||
{ |
|||
class WebPFilterGradient : WebPFilterBase |
|||
{ |
|||
public override void Unfilter( |
|||
Span<byte> prevLine, |
|||
int? prevLineOffsetNullable, |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
Span<byte> output, |
|||
int outputOffset, |
|||
int width) |
|||
{ |
|||
if (prevLineOffsetNullable is int prevLineOffset) |
|||
{ |
|||
byte top = prevLine[prevLineOffset]; |
|||
byte topLeft = top; |
|||
byte left = top; |
|||
for (int i = 0; i < width; i++) |
|||
{ |
|||
top = prevLine[prevLineOffset + i]; // need to read this first in case prev==out
|
|||
left = (byte)(input[inputOffset + i] + GradientPredictor(left, top, topLeft)); |
|||
topLeft = top; |
|||
output[outputOffset + i] = left; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
this.UnfilterHorizontalOrVerticalCore(0, input, inputOffset, output, outputOffset, width); |
|||
} |
|||
} |
|||
|
|||
public override void Filter( |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
int width, |
|||
int height, |
|||
int stride, |
|||
Span<byte> output, |
|||
int outputOffset) |
|||
{ |
|||
// calling (input, width, height, stride, 0, height, 0, output
|
|||
int row = 0; |
|||
int numRows = height; |
|||
bool inverse = false; |
|||
|
|||
int startOffset = row * stride; |
|||
int lastRow = row + numRows; |
|||
SanityCheck(input, output, width, numRows, height, stride, row); |
|||
inputOffset += startOffset; |
|||
outputOffset += startOffset; |
|||
Span<byte> preds; |
|||
int predsOffset; |
|||
if (inverse) |
|||
{ |
|||
preds = output; |
|||
predsOffset = outputOffset; |
|||
} |
|||
else |
|||
{ |
|||
preds = input; |
|||
predsOffset = inputOffset; |
|||
} |
|||
|
|||
if (row == 0) |
|||
{ |
|||
output[outputOffset] = input[inputOffset]; |
|||
PredictLine( |
|||
input, |
|||
inputOffset + 1, |
|||
preds, |
|||
predsOffset, |
|||
output, |
|||
outputOffset + 1, |
|||
width - 1, |
|||
inverse); |
|||
} |
|||
|
|||
while (row < lastRow) |
|||
{ |
|||
PredictLine( |
|||
input, |
|||
inputOffset, |
|||
preds, |
|||
predsOffset - stride, |
|||
output, |
|||
outputOffset, |
|||
1, |
|||
inverse); |
|||
|
|||
for (int w = 1; w < width; w++) |
|||
{ |
|||
int pred = GradientPredictor(preds[w - 1], preds[w - stride], preds[w - stride - 1]); |
|||
int signedPred = inverse ? pred : -pred; |
|||
output[outputOffset + w] = (byte)(input[inputOffset + w] + signedPred); |
|||
} |
|||
|
|||
row++; |
|||
predsOffset += stride; |
|||
inputOffset += stride; |
|||
outputOffset += stride; |
|||
} |
|||
} |
|||
|
|||
private static int GradientPredictor(byte a, byte b, byte c) |
|||
{ |
|||
int g = a + b + c; |
|||
return (g & ~0xff) == 0 ? g : (g < 0) ? 0 : 255; |
|||
} |
|||
} |
|||
} |
|||
@ -1,115 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.WebP.Filters |
|||
{ |
|||
internal class WebPFilterHorizontal : WebPFilterBase |
|||
{ |
|||
public override void Unfilter( |
|||
Span<byte> prevLine, |
|||
int? prevLineOffsetNullable, |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
Span<byte> output, |
|||
int outputOffset, |
|||
int width) |
|||
{ |
|||
byte pred = prevLineOffsetNullable is int prevLineOffset |
|||
? prevLine[prevLineOffset] |
|||
: (byte)0; |
|||
|
|||
this.UnfilterHorizontalOrVerticalCore( |
|||
pred, |
|||
input, |
|||
inputOffset, |
|||
output, |
|||
outputOffset, |
|||
width); |
|||
} |
|||
|
|||
public override void Filter( |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
int width, |
|||
int height, |
|||
int stride, |
|||
Span<byte> output, |
|||
int outputOffset) |
|||
{ |
|||
int numRows = height; |
|||
int row = 0; |
|||
|
|||
const bool inverse = false; |
|||
|
|||
int startOffset = row * stride; |
|||
int lastRow = row + height; |
|||
SanityCheck(input, output, width, height, numRows, stride, row); |
|||
inputOffset += startOffset; |
|||
outputOffset += startOffset; |
|||
|
|||
Span<byte> preds; |
|||
int predsOffset; |
|||
|
|||
if (inverse) |
|||
{ |
|||
preds = output; |
|||
predsOffset = outputOffset; |
|||
} |
|||
else |
|||
{ |
|||
preds = input; |
|||
predsOffset = inputOffset; |
|||
} |
|||
|
|||
if (row is 0) |
|||
{ |
|||
// leftmost pixel is the same as Input for topmost scanline
|
|||
output[0] = input[0]; |
|||
PredictLine( |
|||
input, |
|||
inputOffset + 1, |
|||
preds, |
|||
predsOffset, |
|||
output, |
|||
outputOffset + 1, |
|||
width - 1, |
|||
inverse); |
|||
|
|||
row = 1; |
|||
predsOffset += stride; |
|||
inputOffset += stride; |
|||
outputOffset += stride; |
|||
} |
|||
|
|||
// Filter line by line.
|
|||
while (row < lastRow) |
|||
{ |
|||
PredictLine( |
|||
input, |
|||
inputOffset, |
|||
preds, |
|||
predsOffset - stride, |
|||
output, |
|||
0, |
|||
1, |
|||
inverse); |
|||
PredictLine( |
|||
input, |
|||
inputOffset, |
|||
preds, |
|||
predsOffset, |
|||
output, |
|||
outputOffset + 1, |
|||
width - 1, |
|||
inverse); |
|||
|
|||
row++; |
|||
predsOffset += stride; |
|||
inputOffset += stride; |
|||
outputOffset += stride; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,33 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.WebP.Filters |
|||
{ |
|||
// TODO: check if this is a filter or just a placeholder from the C implementation details
|
|||
class WebPFilterNone : WebPFilterBase |
|||
{ |
|||
public override void Unfilter( |
|||
Span<byte> prevLine, |
|||
int? prevLineOffset, |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
Span<byte> output, |
|||
int outputOffset, |
|||
int width) |
|||
{ |
|||
} |
|||
|
|||
public override void Filter( |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
int width, |
|||
int height, |
|||
int stride, |
|||
Span<byte> output, |
|||
int outputOffset) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.WebP.Filters |
|||
{ |
|||
internal enum WebPFilterType |
|||
{ |
|||
None = 0, |
|||
|
|||
Horizontal = 1, |
|||
|
|||
Vertical = 2, |
|||
|
|||
Gradient = 3, |
|||
} |
|||
} |
|||
@ -1,100 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.WebP.Filters |
|||
{ |
|||
class WebPFilterVertical : WebPFilterBase |
|||
{ |
|||
public override void Unfilter(Span<byte> prevLine, int? prevLineOffsetNullable, Span<byte> input, int inputOffset, Span<byte> output, int outputOffset, int width) |
|||
{ |
|||
if (prevLineOffsetNullable is int prevLineOffset) |
|||
{ |
|||
for (int i = 0; i < width; i++) |
|||
{ |
|||
output[outputOffset + i] = (byte)(prevLine[prevLineOffset + i] + input[inputOffset + i]); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
this.UnfilterHorizontalOrVerticalCore(0, input, inputOffset, output, outputOffset, width); |
|||
} |
|||
} |
|||
|
|||
public override void Filter( |
|||
Span<byte> input, |
|||
int inputOffset, |
|||
int width, |
|||
int height, |
|||
int stride, |
|||
Span<byte> output, |
|||
int outputOffset) |
|||
{ |
|||
int row = 0; |
|||
bool inverse = false; |
|||
|
|||
// TODO: DoVerticalFilter_C with parameters after stride and after height set to 0
|
|||
int startOffset = row * stride; |
|||
int lastRow = row + height; |
|||
SanityCheck(input, output, width, height, height, stride, row); |
|||
inputOffset += startOffset; |
|||
outputOffset += startOffset; |
|||
Span<byte> preds; |
|||
int predsOffset; |
|||
|
|||
if (inverse) |
|||
{ |
|||
preds = output; |
|||
predsOffset = outputOffset; |
|||
} |
|||
else |
|||
{ |
|||
preds = input; |
|||
predsOffset = inputOffset; |
|||
} |
|||
|
|||
if (row == 0) |
|||
{ |
|||
// Very first top-left pixel is copied.
|
|||
output[0] = input[0]; |
|||
|
|||
// Rest of top scan-line is left-predicted:
|
|||
PredictLine( |
|||
input, |
|||
inputOffset + 1, |
|||
preds, |
|||
predsOffset, |
|||
output, |
|||
outputOffset + 1, |
|||
width - 1, |
|||
inverse); |
|||
row = 1; |
|||
inputOffset += stride; |
|||
outputOffset += stride; |
|||
} |
|||
else |
|||
{ |
|||
predsOffset -= stride; |
|||
} |
|||
|
|||
// Filter line-by-line.
|
|||
while (row < lastRow) |
|||
{ |
|||
PredictLine( |
|||
input, |
|||
inputOffset, |
|||
preds, |
|||
predsOffset, |
|||
output, |
|||
outputOffset, |
|||
width, |
|||
inverse); |
|||
row++; |
|||
predsOffset += stride; |
|||
inputOffset += stride; |
|||
outputOffset += stride; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.WebP |
|||
{ |
|||
/// <summary>
|
|||
/// Enum for the different alpha filter types.
|
|||
/// </summary>
|
|||
internal enum WebPAlphaFilterType |
|||
{ |
|||
/// <summary>
|
|||
/// No filtering.
|
|||
/// </summary>
|
|||
None = 0, |
|||
|
|||
/// <summary>
|
|||
/// Horizontal filter.
|
|||
/// </summary>
|
|||
Horizontal = 1, |
|||
|
|||
/// <summary>
|
|||
/// Vertical filter.
|
|||
/// </summary>
|
|||
Vertical = 2, |
|||
|
|||
/// <summary>
|
|||
/// Gradient filter.
|
|||
/// </summary>
|
|||
Gradient = 3, |
|||
} |
|||
} |
|||
Loading…
Reference in new issue