diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs index df7686c31..0ce6e3c9f 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.Runtime.CompilerServices; @@ -42,9 +42,11 @@ internal sealed class CieXyzToCieLabConverter float xr = input.X / wx, yr = input.Y / wy, zr = input.Z / wz; - float fx = xr > CieConstants.Epsilon ? MathF.Pow(xr, 0.3333333F) : ((CieConstants.Kappa * xr) + 16F) / 116F; - float fy = yr > CieConstants.Epsilon ? MathF.Pow(yr, 0.3333333F) : ((CieConstants.Kappa * yr) + 16F) / 116F; - float fz = zr > CieConstants.Epsilon ? MathF.Pow(zr, 0.3333333F) : ((CieConstants.Kappa * zr) + 16F) / 116F; + const float inv116 = 1 / 116F; + + float fx = xr > CieConstants.Epsilon ? MathF.Pow(xr, 0.3333333F) : ((CieConstants.Kappa * xr) + 16F) * inv116; + float fy = yr > CieConstants.Epsilon ? MathF.Pow(yr, 0.3333333F) : ((CieConstants.Kappa * yr) + 16F) * inv116; + float fz = zr > CieConstants.Epsilon ? MathF.Pow(zr, 0.3333333F) : ((CieConstants.Kappa * zr) + 16F) * inv116; float l = (116F * fy) - 16F; float a = 500F * (fx - fy); diff --git a/src/ImageSharp/Common/Helpers/HexConverter.cs b/src/ImageSharp/Common/Helpers/HexConverter.cs index 7ec0ca625..3c863cc37 100644 --- a/src/ImageSharp/Common/Helpers/HexConverter.cs +++ b/src/ImageSharp/Common/Helpers/HexConverter.cs @@ -16,21 +16,19 @@ internal static class HexConverter /// The number of bytes written to . public static int HexStringToBytes(ReadOnlySpan chars, Span bytes) { - if ((chars.Length % 2) != 0) + if ((chars.Length & 1) != 0) // bit-hack for % 2 { throw new ArgumentException("Input string length must be a multiple of 2", nameof(chars)); } - if ((bytes.Length * 2) < chars.Length) + if ((bytes.Length << 1) < chars.Length) // bit-hack for * 2 { throw new ArgumentException("Output span must be at least half the length of the input string"); } - else - { - // Slightly better performance in the loop below, allows us to skip a bounds check - // while still supporting output buffers that are larger than necessary - bytes = bytes[..(chars.Length / 2)]; - } + + // Slightly better performance in the loop below, allows us to skip a bounds check + // while still supporting output buffers that are larger than necessary + bytes = bytes[..(chars.Length >> 1)]; // bit-hack for / 2 [MethodImpl(MethodImplOptions.AggressiveInlining)] static int FromChar(int c) diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs index 18daaed48..f2135b764 100644 --- a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs +++ b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs @@ -84,7 +84,7 @@ internal readonly struct WXYZShuffle4 : IShuffle4 { ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); - int n = source.Length / 4; + int n = (int)((uint)source.Length / 4); for (nint i = 0; i < (uint)n; i++) { @@ -108,7 +108,7 @@ internal readonly struct WZYXShuffle4 : IShuffle4 { ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); - int n = source.Length / 4; + int n = (int)((uint)source.Length / 4); for (nint i = 0; i < (uint)n; i++) { @@ -132,7 +132,7 @@ internal readonly struct YZWXShuffle4 : IShuffle4 { ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); - int n = source.Length / 4; + int n = (int)((uint)source.Length / 4); for (nint i = 0; i < (uint)n; i++) { @@ -156,7 +156,7 @@ internal readonly struct ZYXWShuffle4 : IShuffle4 { ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); - int n = source.Length / 4; + int n = (int)((uint)source.Length / 4); for (nint i = 0; i < (uint)n; i++) { @@ -187,7 +187,7 @@ internal readonly struct XWZYShuffle4 : IShuffle4 { ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); - int n = source.Length / 4; + int n = (int)((uint)source.Length / 4); for (nint i = 0; i < (uint)n; i++) { diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs index 8c79b181c..6fc36cd70 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs @@ -71,7 +71,7 @@ internal static partial class SimdUtils { VerifySpanInput(source, dest, 4); - int count = dest.Length / 4; + int count = (int)((uint)dest.Length / 4); if (count == 0) { return; @@ -105,7 +105,7 @@ internal static partial class SimdUtils { VerifySpanInput(source, dest, 4); - int count = source.Length / 4; + int count = (int)((uint)source.Length / 4); if (count == 0) { return; diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index 654ae3810..06b61443f 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -159,7 +159,7 @@ internal static partial class SimdUtils int remainder = source.Length % (Vector128.Count * 3); int sourceCount = source.Length - remainder; - int destCount = sourceCount * 4 / 3; + int destCount = (int)((uint)sourceCount * 4 / 3); if (sourceCount > 0) { @@ -192,7 +192,7 @@ internal static partial class SimdUtils int remainder = source.Length % (Vector128.Count * 4); int sourceCount = source.Length - remainder; - int destCount = sourceCount * 3 / 4; + int destCount = (int)((uint)sourceCount * 3 / 4); if (sourceCount > 0) { diff --git a/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs b/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs index d507d88c5..ebc43f882 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs @@ -206,8 +206,8 @@ internal sealed unsafe class DeflaterHuffman : IDisposable int lc = Lcode(litlen); this.literalTree.WriteSymbol(pendingBuffer, lc); - int bits = (lc - 261) / 4; - if (bits > 0 && bits <= 5) + int bits = (int)(((uint)lc - 261) / 4); + if (bits is > 0 and <= 5) { this.Pending.WriteBits(litlen & ((1 << bits) - 1), bits); } @@ -364,7 +364,7 @@ internal sealed unsafe class DeflaterHuffman : IDisposable this.literalTree.Frequencies[lc]++; if (lc >= 265 && lc < 285) { - this.extraBits += (lc - 261) / 4; + this.extraBits += (int)(((uint)lc - 261) / 4); } int dc = Dcode(distance - 1); diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index dfc6bb961..4a71dc8b8 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -489,7 +489,7 @@ internal sealed class BmpDecoderCore : IImageDecoderInternals // If the second byte > 2, we are in 'absolute mode'. // The second byte contains the number of color indexes that follow. int max = cmd[1]; - int bytesToRead = (max + 1) / 2; + int bytesToRead = (int)(((uint)max + 1) / 2); byte[] run = new byte[bytesToRead]; diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index f30369d19..a2c705823 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -124,7 +124,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals this.bitsPerPixel ??= bmpMetadata.BitsPerPixel; short bpp = (short)this.bitsPerPixel; - int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32); + int bytesPerLine = (int)(4 * ((((uint)image.Width * (ushort)bpp) + 31) / 32)); this.padding = bytesPerLine - (int)(image.Width * (bpp / 8F)); int colorPaletteSize = this.bitsPerPixel switch diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index d1cb3559b..e5d252f43 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -16,7 +16,7 @@ internal partial struct Block8x8F { var CMin4 = new Vector4(0F); var CMax4 = new Vector4(maximum); - var COff4 = new Vector4(MathF.Ceiling(maximum / 2)); + var COff4 = new Vector4(MathF.Ceiling(maximum * 0.5F)); // /2 this.V0L = Numerics.Clamp(this.V0L + COff4, CMin4, CMax4); this.V0R = Numerics.Clamp(this.V0R + COff4, CMin4, CMax4); @@ -42,7 +42,7 @@ internal partial struct Block8x8F [MethodImpl(InliningOptions.ShortMethod)] public void NormalizeColorsAndRoundInPlaceVector8(float maximum) { - var off = new Vector(MathF.Ceiling(maximum / 2)); + var off = new Vector(MathF.Ceiling(maximum * 0.5F)); // /2 var max = new Vector(maximum); ref Vector row0 = ref Unsafe.As>(ref this.V0L); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index aa211ea22..7350edd38 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -29,7 +29,7 @@ internal partial struct Block8x8F { var CMin4 = new Vector4(0F); var CMax4 = new Vector4(maximum); - var COff4 = new Vector4(MathF.Ceiling(maximum / 2)); + var COff4 = new Vector4(MathF.Ceiling(maximum * 0.5F)); // /2 <# @@ -53,7 +53,7 @@ internal partial struct Block8x8F [MethodImpl(InliningOptions.ShortMethod)] public void NormalizeColorsAndRoundInPlaceVector8(float maximum) { - var off = new Vector(MathF.Ceiling(maximum / 2)); + var off = new Vector(MathF.Ceiling(maximum * 0.5F)); // /2 var max = new Vector(maximum); <# diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs index 62f48af16..1291beb47 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs @@ -26,7 +26,7 @@ internal abstract partial class JpegColorConverterBase this.ColorSpace = colorSpace; this.Precision = precision; this.MaximumValue = MathF.Pow(2, precision) - 1; - this.HalfValue = MathF.Ceiling(this.MaximumValue / 2); + this.HalfValue = MathF.Ceiling(this.MaximumValue * 0.5F); // /2 } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor2.cs index 51d8d0359..8b4256e3b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor2.cs @@ -25,7 +25,7 @@ internal sealed class DownScalingComponentProcessor2 : ComponentProcessor Buffer2D spectralBuffer = this.Component.SpectralBlocks; float maximumValue = this.Frame.MaxColorChannelValue; - float normalizationValue = MathF.Ceiling(maximumValue / 2); + float normalizationValue = MathF.Ceiling(maximumValue * 0.5F); // /2 int destAreaStride = this.ColorBuffer.Width; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor4.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor4.cs index b8a40f53b..170cdbb3c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor4.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor4.cs @@ -25,7 +25,7 @@ internal sealed class DownScalingComponentProcessor4 : ComponentProcessor Buffer2D spectralBuffer = this.Component.SpectralBlocks; float maximumValue = this.Frame.MaxColorChannelValue; - float normalizationValue = MathF.Ceiling(maximumValue / 2); + float normalizationValue = MathF.Ceiling(maximumValue * 0.5F); // /2 int destAreaStride = this.ColorBuffer.Width; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor8.cs index 121b74546..81104d2f3 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor8.cs @@ -22,7 +22,7 @@ internal sealed class DownScalingComponentProcessor8 : ComponentProcessor Buffer2D spectralBuffer = this.Component.SpectralBlocks; float maximumValue = this.Frame.MaxColorChannelValue; - float normalizationValue = MathF.Ceiling(maximumValue / 2); + float normalizationValue = MathF.Ceiling(maximumValue * 0.5F); // /2 int destAreaStride = this.ColorBuffer.Width; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs index f479df7e2..1453b0a56 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs @@ -123,7 +123,7 @@ internal class HuffmanScanEncoder private bool IsStreamFlushNeeded { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => this.emitWriteIndex < (uint)this.emitBuffer.Length / 2; + get => this.emitWriteIndex < (int)((uint)this.emitBuffer.Length / 2); } public void BuildHuffmanTable(JpegHuffmanTableConfig tableConfig) diff --git a/src/ImageSharp/Formats/Jpeg/Components/ScaledFloatingPointDCT.cs b/src/ImageSharp/Formats/Jpeg/Components/ScaledFloatingPointDCT.cs index 369626a96..4f67b7dfe 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ScaledFloatingPointDCT.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ScaledFloatingPointDCT.cs @@ -103,10 +103,10 @@ internal static class ScaledFloatingPointDCT // temporal result is saved to +4 shifted indices // because result is saved into the top left 2x2 region of the // input block - block[(ctr * 8) + 0 + 4] = (tmp10 + tmp2) / 2; - block[(ctr * 8) + 3 + 4] = (tmp10 - tmp2) / 2; - block[(ctr * 8) + 1 + 4] = (tmp12 + tmp0) / 2; - block[(ctr * 8) + 2 + 4] = (tmp12 - tmp0) / 2; + block[(ctr * 8) + 0 + 4] = (tmp10 + tmp2) * 0.5F; + block[(ctr * 8) + 3 + 4] = (tmp10 - tmp2) * 0.5F; + block[(ctr * 8) + 1 + 4] = (tmp12 + tmp0) * 0.5F; + block[(ctr * 8) + 2 + 4] = (tmp12 - tmp0) * 0.5F; } for (int ctr = 0; ctr < 4; ctr++) @@ -136,10 +136,10 @@ internal static class ScaledFloatingPointDCT (z4 * FP32_2_562915447); // Save results to the top left 4x4 subregion - block[(ctr * 8) + 0] = MathF.Round(Numerics.Clamp(((tmp10 + tmp2) / 2) + normalizationValue, 0, maxValue)); - block[(ctr * 8) + 3] = MathF.Round(Numerics.Clamp(((tmp10 - tmp2) / 2) + normalizationValue, 0, maxValue)); - block[(ctr * 8) + 1] = MathF.Round(Numerics.Clamp(((tmp12 + tmp0) / 2) + normalizationValue, 0, maxValue)); - block[(ctr * 8) + 2] = MathF.Round(Numerics.Clamp(((tmp12 - tmp0) / 2) + normalizationValue, 0, maxValue)); + block[(ctr * 8) + 0] = MathF.Round(Numerics.Clamp(((tmp10 + tmp2) * 0.5F) + normalizationValue, 0, maxValue)); + block[(ctr * 8) + 3] = MathF.Round(Numerics.Clamp(((tmp10 - tmp2) * 0.5F) + normalizationValue, 0, maxValue)); + block[(ctr * 8) + 1] = MathF.Round(Numerics.Clamp(((tmp12 + tmp0) * 0.5F) + normalizationValue, 0, maxValue)); + block[(ctr * 8) + 2] = MathF.Round(Numerics.Clamp(((tmp12 - tmp0) * 0.5F) + normalizationValue, 0, maxValue)); } } @@ -183,8 +183,8 @@ internal static class ScaledFloatingPointDCT // temporal result is saved to +2 shifted indices // because result is saved into the top left 2x2 region of the // input block - block[(ctr * 8) + 2] = (tmp10 + tmp0) / 4; - block[(ctr * 8) + 3] = (tmp10 - tmp0) / 4; + block[(ctr * 8) + 2] = (tmp10 + tmp0) * 0.25F; // /4 + block[(ctr * 8) + 3] = (tmp10 - tmp0) * 0.25F; // /4 } for (int ctr = 0; ctr < 2; ctr++) @@ -199,8 +199,8 @@ internal static class ScaledFloatingPointDCT (block[ctr + (8 * 1) + 2] * FP32_3_624509785); // Save results to the top left 2x2 subregion - block[(ctr * 8) + 0] = MathF.Round(Numerics.Clamp(((tmp10 + tmp0) / 4) + normalizationValue, 0, maxValue)); - block[(ctr * 8) + 1] = MathF.Round(Numerics.Clamp(((tmp10 - tmp0) / 4) + normalizationValue, 0, maxValue)); + block[(ctr * 8) + 0] = MathF.Round(Numerics.Clamp(((tmp10 + tmp0) * 0.25F) + normalizationValue, 0, maxValue)); + block[(ctr * 8) + 1] = MathF.Round(Numerics.Clamp(((tmp10 - tmp0) * 0.25F) + normalizationValue, 0, maxValue)); } } diff --git a/src/ImageSharp/Formats/Png/Adam7.cs b/src/ImageSharp/Formats/Png/Adam7.cs index f52a66c26..8310ca64c 100644 --- a/src/ImageSharp/Formats/Png/Adam7.cs +++ b/src/ImageSharp/Formats/Png/Adam7.cs @@ -67,16 +67,22 @@ internal static class Adam7 [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ComputeColumns(int width, int passIndex) { - switch (passIndex) + uint w = (uint)width; + + uint result = passIndex switch { - case 0: return (width + 7) / 8; - case 1: return (width + 3) / 8; - case 2: return (width + 3) / 4; - case 3: return (width + 1) / 4; - case 4: return (width + 1) / 2; - case 5: return width / 2; - case 6: return width; - default: throw new ArgumentException($"Not a valid pass index: {passIndex}"); - } + 0 => (w + 7) / 8, + 1 => (w + 3) / 8, + 2 => (w + 3) / 4, + 3 => (w + 1) / 4, + 4 => (w + 1) / 2, + 5 => w / 2, + 6 => w, + _ => Throw(passIndex) + }; + + return (int)result; + + static uint Throw(int passIndex) => throw new ArgumentException($"Not a valid pass index: {passIndex}"); } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs index 36f8c20d7..d57dea994 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs @@ -16,7 +16,7 @@ internal abstract class TiffBaseCompression : IDisposable this.Width = width; this.BitsPerPixel = bitsPerPixel; this.Predictor = predictor; - this.BytesPerRow = ((width * bitsPerPixel) + 7) / 8; + this.BytesPerRow = (int)(((uint)(width * bitsPerPixel) + 7) / 8); } /// diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index 45bbed12d..4499c5583 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -793,7 +793,7 @@ internal class TiffDecoderCore : IImageDecoderInternals } } - int bytesPerRow = ((width * bitsPerPixel) + 7) / 8; + int bytesPerRow = (int)(((uint)(width * bitsPerPixel) + 7) / 8); return bytesPerRow * height; } diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter{TPixel}.cs index 189c8fd6a..c4a749255 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter{TPixel}.cs @@ -29,7 +29,7 @@ internal abstract class TiffBaseColorWriter : IDisposable /// /// Gets the bytes per row. /// - public int BytesPerRow => ((this.Image.Width * this.BitsPerPixel) + 7) / 8; + public int BytesPerRow => (int)(((uint)(this.Image.Width * this.BitsPerPixel) + 7) / 8); protected ImageFrame Image { get; } diff --git a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs index b83b44fa1..5b4eab64a 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs @@ -457,7 +457,7 @@ internal class Vp8BitWriter : BitWriterBase this.Finish(); uint numBytes = (uint)this.NumBytes(); int mbSize = this.enc.Mbw * this.enc.Mbh; - int expectedSize = mbSize * 7 / 8; + int expectedSize = (int)((uint)mbSize * 7 / 8); Vp8BitWriter bitWriterPartZero = new(expectedSize, this.enc); diff --git a/src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs index 139518163..5eec2a2ca 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs @@ -316,7 +316,7 @@ internal class HistogramEncoder int triesWithNoSuccess = 0; int numUsed = histograms.Count(h => h != null); int outerIters = numUsed; - int numTriesNoSuccess = outerIters / 2; + int numTriesNoSuccess = (int)((uint)outerIters / 2); var stats = new Vp8LStreaks(); var bitsEntropy = new Vp8LBitEntropy(); @@ -346,7 +346,7 @@ internal class HistogramEncoder for (int iter = 0; iter < outerIters && numUsed >= minClusterSize && ++triesWithNoSuccess < numTriesNoSuccess; iter++) { double bestCost = histoPriorityList.Count == 0 ? 0.0d : histoPriorityList[0].CostDiff; - int numTries = numUsed / 2; + int numTries = (int)((uint)numUsed / 2); uint randRange = (uint)((numUsed - 1) * numUsed); // Pick random samples. diff --git a/src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs index 5cee6bc39..18104331c 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs @@ -100,7 +100,7 @@ internal static class HuffmanUtils uint k; // The stride must end, collapse what we have, if we have enough (4). - uint count = (uint)((sum + (stride / 2)) / stride); + uint count = (sum + ((uint)stride / 2)) / (uint)stride; if (count < 1) { count = 1; @@ -144,7 +144,7 @@ internal static class HuffmanUtils sum += counts[i]; if (stride >= 4) { - limit = (uint)((sum + (stride / 2)) / stride); + limit = (sum + ((uint)stride / 2)) / (uint)stride; } } } diff --git a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs index d4db3db53..8a5ec162f 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs @@ -1440,7 +1440,12 @@ internal static unsafe class LosslessUtils } [MethodImpl(InliningOptions.ShortMethod)] - private static int AddSubtractComponentHalf(int a, int b) => (int)Clip255((uint)(a + ((a - b) / 2))); + private static int AddSubtractComponentHalf(int a, int b) + { + uint ua = (uint)a; + uint ub = (uint)b; + return (int)Clip255(ua + ((ua - ub) / 2)); + } [MethodImpl(InliningOptions.ShortMethod)] private static int AddSubtractComponentFull(int a, int b, int c) => (int)Clip255((uint)(a + b - c)); diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs index e714a7725..7be0e69f7 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs @@ -963,7 +963,7 @@ internal class Vp8LEncoder : IDisposable else { int nBits = BitOperations.Log2((uint)trimmedLength - 2); - int nBitPairs = (nBits / 2) + 1; + int nBitPairs = (int)(((uint)nBits / 2) + 1); this.bitWriter.PutBits((uint)nBitPairs - 1, 3); this.bitWriter.PutBits((uint)trimmedLength - 2, nBitPairs * 2); } @@ -1820,7 +1820,7 @@ internal class Vp8LEncoder : IDisposable { // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra // pixel in each, plus 2 regular scanlines of bytes. - int bgraScratchSize = this.UsePredictorTransform ? ((width + 1) * 2) + (((width * 2) + 4 - 1) / 4) : 0; + int bgraScratchSize = this.UsePredictorTransform ? (int)((((uint)width + 1) * 2) + ((((uint)width * 2) + 4 - 1) / 4)) : 0; int transformDataSize = this.UsePredictorTransform || this.UseCrossColorTransform ? LosslessUtils.SubSampleSize(width, this.TransformBits) * LosslessUtils.SubSampleSize(height, this.TransformBits) : 0; this.BgraScratch = this.memoryAllocator.Allocate(bgraScratchSize); diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LHashChain.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LHashChain.cs index 527242906..32d4fcbb6 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LHashChain.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LHashChain.cs @@ -59,7 +59,7 @@ internal sealed class Vp8LHashChain : IDisposable public void Fill(ReadOnlySpan bgra, int quality, int xSize, int ySize, bool lowEffort) { int size = xSize * ySize; - int iterMax = GetMaxItersForQuality(quality); + int iterMax = GetMaxItersForQuality((uint)quality); int windowSize = GetWindowSizeForHashChain(quality, xSize); int pos; @@ -272,7 +272,7 @@ internal sealed class Vp8LHashChain : IDisposable /// The quality. /// Number of hash chain lookups. [MethodImpl(InliningOptions.ShortMethod)] - private static int GetMaxItersForQuality(int quality) => 8 + (quality * quality / 128); + private static int GetMaxItersForQuality(uint quality) => (int)(8 + (quality * quality / 128)); [MethodImpl(InliningOptions.ShortMethod)] private static int GetWindowSizeForHashChain(int quality, int xSize) diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs index 16b4c827e..186aa6c21 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs @@ -683,7 +683,7 @@ internal class Vp8Encoder : IDisposable { if (accum[n] != 0) { - int newCenter = (distAccum[n] + (accum[n] / 2)) / accum[n]; + int newCenter = (distAccum[n] + (accum[n] >> 1)) / accum[n]; // >> 1 is bit-hack for / 2 displaced += Math.Abs(centers[n] - newCenter); centers[n] = newCenter; weightedAverage += newCenter * accum[n]; @@ -691,7 +691,7 @@ internal class Vp8Encoder : IDisposable } } - weightedAverage = (weightedAverage + (totalWeight / 2)) / totalWeight; + weightedAverage = (weightedAverage + (totalWeight >> 1)) / totalWeight; // >> 1 is bit-hack for / 2 if (displaced < 5) { break; // no need to keep on looping... @@ -1177,6 +1177,6 @@ internal class Vp8Encoder : IDisposable { int total = a + b; return total == 0 ? 255 // that's the default probability. - : ((255 * a) + (total / 2)) / total; // rounded proba + : ((255 * a) + (int)((uint)total / 2)) / total; // rounded proba } } diff --git a/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs b/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs index e63a7ef74..36f3abcd9 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs @@ -731,7 +731,7 @@ internal sealed class WebpLossyDecoder Span dst = buf[dstStartIdx..]; int yEnd = io.MbY + io.MbH; int mbw = io.MbW; - int uvw = (mbw + 1) / 2; + int uvw = (int)(((uint)mbw + 1) / 2); int y = io.MbY; byte[] uvBuffer = new byte[(14 * 32) + 15]; diff --git a/src/ImageSharp/IO/ChunkedMemoryStream.cs b/src/ImageSharp/IO/ChunkedMemoryStream.cs index da52f7ca8..253454814 100644 --- a/src/ImageSharp/IO/ChunkedMemoryStream.cs +++ b/src/ImageSharp/IO/ChunkedMemoryStream.cs @@ -547,7 +547,7 @@ internal sealed class ChunkedMemoryStream : Stream #pragma warning disable IDE1006 // Naming Styles const int _128K = 1 << 17; const int _4M = 1 << 22; - return i < 16 ? _128K * (1 << (i / 4)) : _4M; + return i < 16 ? _128K * (1 << (int)((uint)i / 4)) : _4M; #pragma warning restore IDE1006 // Naming Styles } diff --git a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs index 2cb4421d5..798edf9b2 100644 --- a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs +++ b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs @@ -156,7 +156,7 @@ internal sealed class UniformUnmanagedMemoryPoolMemoryAllocator : MemoryAllocato // Workaround for https://github.com/dotnet/runtime/issues/65466 if (total > 0) { - return total / 8; + return (long)((ulong)total / 8); } } diff --git a/src/ImageSharp/Primitives/Rectangle.cs b/src/ImageSharp/Primitives/Rectangle.cs index baffbc7f4..2f0df3574 100644 --- a/src/ImageSharp/Primitives/Rectangle.cs +++ b/src/ImageSharp/Primitives/Rectangle.cs @@ -195,7 +195,7 @@ public struct Rectangle : IEquatable /// The rectangle. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Center(Rectangle rectangle) => new(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); + public static Point Center(Rectangle rectangle) => new(rectangle.Left + (rectangle.Width & 1), rectangle.Top + (rectangle.Height & 1)); // & 1 is bit-hack for / 2 /// /// Creates a rectangle that represents the intersection between and diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs index b710243a5..1c76ea6a4 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs @@ -132,7 +132,7 @@ internal class BinaryThresholdProcessor : ImageProcessor case BinaryThresholdMode.MaxChroma: { - float threshold = this.threshold / 2F; + float threshold = this.threshold * 0.5F; // /2 for (int x = 0; x < rowSpan.Length; x++) { float chroma = GetMaxChroma(span[x]); @@ -149,9 +149,10 @@ internal class BinaryThresholdProcessor : ImageProcessor private static float GetSaturation(Rgb24 rgb) { // Slimmed down RGB => HSL formula. See HslAndRgbConverter. - float r = rgb.R / 255F; - float g = rgb.G / 255F; - float b = rgb.B / 255F; + const float inv255 = 1 / 255F; + float r = rgb.R * inv255; + float g = rgb.G * inv255; + float b = rgb.B * inv255; float max = MathF.Max(r, MathF.Max(g, b)); float min = MathF.Min(r, MathF.Min(g, b)); @@ -162,7 +163,7 @@ internal class BinaryThresholdProcessor : ImageProcessor return 0F; } - float l = (max + min) / 2F; + float l = (max + min) * 0.5F; // /2 if (l <= .5F) { diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs index e2272db03..0baa87a61 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs @@ -59,8 +59,8 @@ internal class AdaptiveHistogramEqualizationProcessor : HistogramEqualiz int tileWidth = (int)MathF.Ceiling(sourceWidth / (float)this.Tiles); int tileHeight = (int)MathF.Ceiling(sourceHeight / (float)this.Tiles); int tileCount = this.Tiles; - int halfTileWidth = tileWidth / 2; - int halfTileHeight = tileHeight / 2; + int halfTileWidth = (int)((uint)tileWidth / 2); + int halfTileHeight = (int)((uint)tileHeight / 2); int luminanceLevels = this.LuminanceLevels; // The image is split up into tiles. For each tile the cumulative distribution function will be calculated. @@ -176,7 +176,7 @@ internal class AdaptiveHistogramEqualizationProcessor : HistogramEqualiz int xEnd, int luminanceLevels) { - int halfTileHeight = tileHeight / 2; + int halfTileHeight = (int)((uint)tileHeight / 2); int cdfY = 0; int y = halfTileHeight; @@ -228,7 +228,7 @@ internal class AdaptiveHistogramEqualizationProcessor : HistogramEqualiz int yEnd, int luminanceLevels) { - int halfTileWidth = tileWidth / 2; + int halfTileWidth = (int)((uint)tileWidth / 2); int cdfX = 0; int x = halfTileWidth; diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs index f25db12c2..bbac9b9d8 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs @@ -59,7 +59,7 @@ internal class AdaptiveHistogramEqualizationSlidingWindowProcessor : His int tileWidth = source.Width / this.Tiles; int tileHeight = tileWidth; int pixelInTile = tileWidth * tileHeight; - int halfTileHeight = tileHeight / 2; + int halfTileHeight = (int)((uint)tileHeight / 2); int halfTileWidth = halfTileHeight; SlidingWindowInfos slidingWindowInfos = new(tileWidth, tileHeight, halfTileWidth, halfTileHeight, pixelInTile); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs index 11befd5da..14da3ac89 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs @@ -54,7 +54,7 @@ internal class FlipProcessor : ImageProcessor using IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(source.Width); Span temp = tempBuffer.Memory.Span; - for (int yTop = 0; yTop < height / 2; yTop++) + for (int yTop = 0; yTop < (int)((uint)height / 2); yTop++) { int yBottom = height - yTop - 1; Span topRow = source.DangerousGetRowSpan(yBottom); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs index d03a694ba..d90f948b6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs @@ -105,11 +105,11 @@ internal static class ResizeHelper switch (options.Position) { case AnchorPositionMode.Left: - targetY = (height - sourceHeight) / 2; + targetY = (int)((uint)(height - sourceHeight) / 2); targetX = 0; break; case AnchorPositionMode.Right: - targetY = (height - sourceHeight) / 2; + targetY = (int)((uint)(height - sourceHeight) / 2); targetX = width - sourceWidth; break; case AnchorPositionMode.TopRight: @@ -118,7 +118,7 @@ internal static class ResizeHelper break; case AnchorPositionMode.Top: targetY = 0; - targetX = (width - sourceWidth) / 2; + targetX = (int)((uint)(width - sourceWidth) / 2); break; case AnchorPositionMode.TopLeft: targetY = 0; @@ -130,15 +130,15 @@ internal static class ResizeHelper break; case AnchorPositionMode.Bottom: targetY = height - sourceHeight; - targetX = (width - sourceWidth) / 2; + targetX = (int)((uint)(width - sourceWidth) / 2); break; case AnchorPositionMode.BottomLeft: targetY = height - sourceHeight; targetX = 0; break; default: - targetY = (height - sourceHeight) / 2; - targetX = (width - sourceWidth) / 2; + targetY = (int)((uint)(height - sourceHeight) / 2); + targetX = (int)((uint)(width - sourceWidth) / 2); break; }