Browse Source

Remove redundant floor. Float to int conversion will already truncate toward zero

pull/3137/head
Erik White 2 months ago
parent
commit
3b37d5552d
  1. 36
      src/ImageSharp/Formats/Png/PngCgbiProcessor.cs

36
src/ImageSharp/Formats/Png/PngCgbiProcessor.cs

@ -129,20 +129,20 @@ internal static class PngCgbiProcessor
Vector512<int> halfAlpha = Vector512.ShiftRightLogical(safeAlpha, 1); Vector512<int> halfAlpha = Vector512.ShiftRightLogical(safeAlpha, 1);
Vector512<float> safeAlphaF = Vector512.ConvertToSingle(safeAlpha); Vector512<float> safeAlphaF = Vector512.ConvertToSingle(safeAlpha);
// The scalar path computes ((c * 255) + (a >> 1)) / a with integer // ConvertToInt32 truncates toward zero (cvttps2dq / fcvtzs); since
// division. Floor the positive quotient before converting so SIMD does // every quotient here is non-negative, that matches the scalar
// not use the default round-to-nearest conversion and drift by one. // ((c * 255) + (a >> 1)) / a integer-division floor.
Vector512<int> unpremultipliedR = Vector512.Min( Vector512<int> unpremultipliedR = Vector512.Min(
byteMax, byteMax,
Vector512.ConvertToInt32(Vector512.Floor(Vector512.ConvertToSingle((r * byteMax) + halfAlpha) / safeAlphaF))); Vector512.ConvertToInt32(Vector512.ConvertToSingle((r * byteMax) + halfAlpha) / safeAlphaF));
Vector512<int> unpremultipliedG = Vector512.Min( Vector512<int> unpremultipliedG = Vector512.Min(
byteMax, byteMax,
Vector512.ConvertToInt32(Vector512.Floor(Vector512.ConvertToSingle((g * byteMax) + halfAlpha) / safeAlphaF))); Vector512.ConvertToInt32(Vector512.ConvertToSingle((g * byteMax) + halfAlpha) / safeAlphaF));
Vector512<int> unpremultipliedB = Vector512.Min( Vector512<int> unpremultipliedB = Vector512.Min(
byteMax, byteMax,
Vector512.ConvertToInt32(Vector512.Floor(Vector512.ConvertToSingle((b * byteMax) + halfAlpha) / safeAlphaF))); Vector512.ConvertToInt32(Vector512.ConvertToSingle((b * byteMax) + halfAlpha) / safeAlphaF));
// ConditionalSelect applies the expensive unpremultiply only to pixels // ConditionalSelect applies the expensive unpremultiply only to pixels
// where alpha is between 1 and 254; alpha 0 and 255 lanes keep the // where alpha is between 1 and 254; alpha 0 and 255 lanes keep the
@ -201,20 +201,20 @@ internal static class PngCgbiProcessor
Vector256<int> halfAlpha = Vector256.ShiftRightLogical(safeAlpha, 1); Vector256<int> halfAlpha = Vector256.ShiftRightLogical(safeAlpha, 1);
Vector256<float> safeAlphaF = Vector256.ConvertToSingle(safeAlpha); Vector256<float> safeAlphaF = Vector256.ConvertToSingle(safeAlpha);
// The scalar path computes ((c * 255) + (a >> 1)) / a with integer // ConvertToInt32 truncates toward zero (cvttps2dq / fcvtzs); since
// division. Floor the positive quotient before converting so SIMD does // every quotient here is non-negative, that matches the scalar
// not use the default round-to-nearest conversion and drift by one. // ((c * 255) + (a >> 1)) / a integer-division floor.
Vector256<int> unpremultipliedR = Vector256.Min( Vector256<int> unpremultipliedR = Vector256.Min(
byteMax, byteMax,
Vector256.ConvertToInt32(Vector256.Floor(Vector256.ConvertToSingle((r * byteMax) + halfAlpha) / safeAlphaF))); Vector256.ConvertToInt32(Vector256.ConvertToSingle((r * byteMax) + halfAlpha) / safeAlphaF));
Vector256<int> unpremultipliedG = Vector256.Min( Vector256<int> unpremultipliedG = Vector256.Min(
byteMax, byteMax,
Vector256.ConvertToInt32(Vector256.Floor(Vector256.ConvertToSingle((g * byteMax) + halfAlpha) / safeAlphaF))); Vector256.ConvertToInt32(Vector256.ConvertToSingle((g * byteMax) + halfAlpha) / safeAlphaF));
Vector256<int> unpremultipliedB = Vector256.Min( Vector256<int> unpremultipliedB = Vector256.Min(
byteMax, byteMax,
Vector256.ConvertToInt32(Vector256.Floor(Vector256.ConvertToSingle((b * byteMax) + halfAlpha) / safeAlphaF))); Vector256.ConvertToInt32(Vector256.ConvertToSingle((b * byteMax) + halfAlpha) / safeAlphaF));
// ConditionalSelect applies the expensive unpremultiply only to pixels // ConditionalSelect applies the expensive unpremultiply only to pixels
// where alpha is between 1 and 254; alpha 0 and 255 lanes keep the // where alpha is between 1 and 254; alpha 0 and 255 lanes keep the
@ -270,20 +270,20 @@ internal static class PngCgbiProcessor
Vector128<int> halfAlpha = Vector128.ShiftRightLogical(safeAlpha, 1); Vector128<int> halfAlpha = Vector128.ShiftRightLogical(safeAlpha, 1);
Vector128<float> safeAlphaF = Vector128.ConvertToSingle(safeAlpha); Vector128<float> safeAlphaF = Vector128.ConvertToSingle(safeAlpha);
// The scalar path computes ((c * 255) + (a >> 1)) / a with integer // ConvertToInt32 truncates toward zero (cvttps2dq / fcvtzs); since
// division. Floor the positive quotient before converting so SIMD does // every quotient here is non-negative, that matches the scalar
// not use the default round-to-nearest conversion and drift by one. // ((c * 255) + (a >> 1)) / a integer-division floor.
Vector128<int> unpremultipliedR = Vector128.Min( Vector128<int> unpremultipliedR = Vector128.Min(
byteMax, byteMax,
Vector128.ConvertToInt32(Vector128.Floor(Vector128.ConvertToSingle((r * byteMax) + halfAlpha) / safeAlphaF))); Vector128.ConvertToInt32(Vector128.ConvertToSingle((r * byteMax) + halfAlpha) / safeAlphaF));
Vector128<int> unpremultipliedG = Vector128.Min( Vector128<int> unpremultipliedG = Vector128.Min(
byteMax, byteMax,
Vector128.ConvertToInt32(Vector128.Floor(Vector128.ConvertToSingle((g * byteMax) + halfAlpha) / safeAlphaF))); Vector128.ConvertToInt32(Vector128.ConvertToSingle((g * byteMax) + halfAlpha) / safeAlphaF));
Vector128<int> unpremultipliedB = Vector128.Min( Vector128<int> unpremultipliedB = Vector128.Min(
byteMax, byteMax,
Vector128.ConvertToInt32(Vector128.Floor(Vector128.ConvertToSingle((b * byteMax) + halfAlpha) / safeAlphaF))); Vector128.ConvertToInt32(Vector128.ConvertToSingle((b * byteMax) + halfAlpha) / safeAlphaF));
// ConditionalSelect applies the expensive unpremultiply only to pixels // ConditionalSelect applies the expensive unpremultiply only to pixels
// where alpha is between 1 and 254; alpha 0 and 255 lanes keep the // where alpha is between 1 and 254; alpha 0 and 255 lanes keep the

Loading…
Cancel
Save