/// <inheritdoc />
        public Bitmap Transform(Bitmap bitmap, IDistribution distribution)
        {
            if (bitmap is null)
            {
                throw new ArgumentNullException(nameof(bitmap));
            }
            if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new NotSupportedException(Errors.NotSupported);
            }

            var cdf = GetCDF(bitmap);

            //get the new pixel values, according to a selected distribution
            var newPixels = _service.TransformToByte(cdf, distribution);

            var bitmapData = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite, bitmap.PixelFormat);

            var options = new ParallelOptions()
            {
                MaxDegreeOfParallelism = Environment.ProcessorCount
            };

            var step   = Image.GetPixelFormatSize(PixelFormat.Format32bppArgb) / 8;
            var size   = bitmap.Size;
            var stride = bitmapData.Stride;

            var(dstWidth, dstHeight) = (size.Width, size.Height);

            unsafe
            {
                var startPtr = (byte *)bitmapData.Scan0.ToPointer();

                Parallel.For(0, dstHeight, options, y =>
                {
                    //get a start address
                    var ptr = startPtr + y * stride;

                    for (int x = 0; x < dstWidth; ++x, ptr += step)
                    {
                        //get a new pixel value, transofrming by a quantile
                        ptr[0] = ptr[1] = ptr[2] = newPixels[ptr[0]];
                    }
                });
            }

            bitmap.UnlockBits(bitmapData);

            return(bitmap);
        }
 public byte[] TransformToByte(decimal[] cdf, IDistribution distribution)
 => _service.TransformToByte(cdf, distribution);