Я работаю над приложением, и одна из его основных функций - это настройка изображения в градациях серого и применение к нему цвета.
это основная математика, которую я использую для этого:
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;
}
Код, к счастью, работает, однако, когда изображение проходит через него, цвета кажутся намного темнее оригинала. Я знаю, что это, скорее всего, проблема с матом, но я не могу точно определить, где он находится.
Стоит отметить, что я использую цвет, хранящийся в настройках приложения:
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.
Проблема заключается в расчетах - вы берете «среднее» значение того, что уже является средневзвешенным. Вам скорее нужно использовать средневзвешенное значение сам для каждого из компонентов цвета. Так, например, для 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
, так как вы избежите потенциальных ошибок округления.