Как правильно раскрасить изображение в градациях серого через приложение UWP?

Я работаю над приложением, и одна из его основных функций - это настройка изображения в градациях серого и применение к нему цвета.

это основная математика, которую я использую для этого:

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;
  }

Код, к счастью, работает, однако, когда изображение проходит через него, цвета кажутся намного темнее оригинала. Я знаю, что это, скорее всего, проблема с матом, но я не могу точно определить, где он находится.

Как правильно раскрасить изображение в градациях серого через приложение UWP?

Как правильно раскрасить изображение в градациях серого через приложение UWP?

Стоит отметить, что я использую цвет, хранящийся в настройках приложения:

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)));
  }

У кого-нибудь есть в этом опыт и может помочь?

🤔 А знаете ли вы, что...
C# обеспечивает возможность создания многопоточных приложений с помощью пространства имен System.Threading.


1
2 041
1

Ответ:

Проблема заключается в расчетах - вы берете «среднее» значение того, что уже является средневзвешенным. Вам скорее нужно использовать средневзвешенное значение сам для каждого из компонентов цвета. Так, например, для rb:

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

Итак, мы вычисляем, насколько интенсивным должен быть цвет replaceBlack, путем (деления количества «белого» в исходном цвете на 255, и то же самое, что мы делаем для replaceWhite. Затем мы можем безопасно суммировать эти два числа, потому что он никогда не может поднимитесь выше 255 (в худшем случае вы добавите r * 255 + ( 1 - r ) * 255 = 255), и если это произойдет из-за некоторого округления double, приведение все равно будет обрезать десятичную часть, поэтому у нас будет не более 255.

Исходный код был почти правильным, но в основном он использовал половину правильного значения, поэтому все стало темнее. Также лучше использовать для расчета значения double, так как вы избежите потенциальных ошибок округления.