如何通过UWP应用正确为灰度图像着色?

时间:2018-08-16 12:50:16

标签: c# uwp bitmapimage grayscale argb

我正在开发一个应用程序,其主要功能之一是它可以调整灰度图像并为其应用颜色。

这是我用来计算的主要数学公式:

Color replaceWhite = Color.FromArgb(255, byte.Parse(acent.Substring(0, 2), 
    System.Globalization.NumberStyles.HexNumber), byte.Parse(acent.Substring(2, 2),
    System.Globalization.NumberStyles.HexNumber), byte.Parse(acent.Substring(4, 2),
    System.Globalization.NumberStyles.HexNumber));
WriteableBitmap source = await GetImageFile(sourceImage);
byte[] byteArray = null;
using (Stream stream = source.PixelBuffer.AsStream())
  {
    long streamLength = stream.Length;
    byteArray = new byte[streamLength];
    await stream.ReadAsync(byteArray, 0, byteArray.Length);
    if (streamLength > 0)
      {
        for (int i = 0; i < streamLength; i += 4)
          {
            if (byteArray[i + 3] != 0)
              {
                int b = Convert.ToInt32(byteArray[i]);
                int g = Convert.ToInt32(byteArray[i + 1]);
                int r = Convert.ToInt32(byteArray[i + 2]);

                int rB = ((((b * replaceBlack.B) / 255) + (((255 - b) * replaceWhite.B) / 255)) / 2);
                int rG = ((((g * replaceBlack.G) / 255) + (((255 - g) * replaceWhite.G) / 255)) / 2);
                int rR = ((((r * replaceBlack.R) / 255) + (((255 - r) * replaceWhite.R) / 255)) / 2);

                byte blue = Convert.ToByte(rB);
                byte green = Convert.ToByte(rG);
                byte red = Convert.ToByte(rR);

                byteArray[i] = blue; // Blue
                byteArray[i + 1] = green;  // Green
                byteArray[i + 2] = red; // Red
              }
          }
      }
  }
if (byteArray != null)
  {
    WriteableBitmap result = await PixelBufferToWritableBitmap(byteArray, source.PixelWidth, source.PixelHeight);
    StorageFile image = await WriteableBitmapToStorageFile(result, fileName, folderName);
    BitmapImage imageSource = await StorageFileToBitmapImage(image);
    return imageSource;
  }

该代码很幸运,但是当图像通过时,颜色看起来比原始颜色要暗得多。我知道这很可能是数学上的问题,但我无法查明问题所在。

This is the image I am putting through the code. it is a png image

And this is the result. as you can see, the colors in the color picker are much different than the final result

值得一提的是,我正在使用存储在应用程序设置中的颜色:

settings.Values["FlatWallpaperColor"] = theme.ColorCode;
string color = theme.ColorCode.Replace("#", "");
if (color.Length == 6)
  {
    SelectFlatWallpaperColorButton.Background = new SolidColorBrush (ColorHelper.FromArgb(255,
      byte.Parse(color.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
      byte.Parse(color.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
      byte.Parse(color.Substring(4, 2), System.Globalization.NumberStyles.HexNumber)));
  }

有人在这方面有经验并可以提供帮助吗?

1 个答案:

答案 0 :(得分:3)

问题出在计算中-您正在获取已经是加权平均值的“均值”值。您宁愿对每种颜色成分使用加权平均值 。例如rb

int rb = (byte)((b/255.0)*replaceBlack.B + ((255-b)/255.0)*replaceWhite.B));

因此,我们通过将原始颜色中的“白色”量除以255,然后对replaceBlack做同样的事情来计算replaceWhite颜色应具有的强度。可以安全地将这两个数字相加,因为它永远都不能超过255(在最坏的情况下,您将累加r * 255 + ( 1 - r ) * 255 = 255),并且如果因为某些double舍入而这样做,则转换仍将舍去小数因此我们最多只能有255个。

原始代码几乎是正确的,但是它基本上使用了正确值的一半-因此所有内容都会变得更暗。此外,使用double值进行计算会更好,因为这样可以避免潜在的舍入误差。