如何为 Windows-10 Metro 应用程序的图像着色?
How to Colorize Image @ Windows-10 Metro app?
我制作了灰度图像,我想对其进行着色(例如更改 HSL)。
在我在 Internet 上找到的示例中,我需要位图 class,但在 Windows-10 通用应用程序中不存在。
WriteableBitmap class可用于获取图像的像素缓冲区,并使用语言指定的方法修改像素内容。查看 "Remarks" 和 "Examples" 会话以更好地理解。
并且我想推荐你WriteableBitmapEx which includes many extension methods to WriteableBitmap. You can get install the NuGet package在你的项目中使用它。
在出现许多错误后,这里是工作代码:
它可能看起来很糟糕,但它正在运行,我很高兴 :)
private static async void changeImage(Molecule molecule)
{
Molecule.Reaction++; // Used as Working/Loading status here
var atoms = molecule.Atoms;
if (atoms > 5) atoms = 5;
var stream = await GetStream("Assets/Images/" + atoms + ".png");
var decoder = await BitmapDecoder.CreateAsync(stream);
var pixelData = await decoder.GetPixelDataAsync();
var data = pixelData.DetachPixelData(); // Finally something where I can get my pixels
var wb = new WriteableBitmap(16, 16);
//wb.SetSource(stream); // Get pixel not working so I dont need this
for(int y = 0; y < decoder.PixelHeight; y++)
{
for(int x = 0; x < decoder.PixelWidth; x++)
{
// var rgba = wb.GetPixel(x, y); // This is not working, only returnning empty pixels (A:0, R:0, G:0, B:0)
// Get RGBA value of pixel
var rgba = new Color {
R = data[x * 4 + y * decoder.PixelWidth * 4 + 0],
G = data[x * 4 + y * decoder.PixelWidth * 4 + 1],
B = data[x * 4 + y * decoder.PixelWidth * 4 + 2],
A = data[x * 4 + y * decoder.PixelWidth * 4 + 3]
};
// Array can't have index -1 and -1 is for gray what is default
if (molecule.Owner != -1)
{
// Colorize pixel
var z = ((rgba.R + rgba.G + rgba.B) / 3.0) / 256;
rgba.R = Convert.ToByte(z * Settings.Colors[molecule.Owner].Item1.Color.R);
rgba.G = Convert.ToByte(z * Settings.Colors[molecule.Owner].Item1.Color.G);
rgba.B = Convert.ToByte(z * Settings.Colors[molecule.Owner].Item1.Color.B);
data[x * 4 + y * decoder.PixelWidth * 4 + 0] = rgba.R;
data[x * 4 + y * decoder.PixelWidth * 4 + 1] = rgba.G;
data[x * 4 + y * decoder.PixelWidth * 4 + 2] = rgba.B;
}
wb.SetPixel(x, y, rgba); // I tried to connect byte[] and WriteAbleBitmap via stream but Failed so I'm using this
}
}
if (atoms == molecule.Atoms) // Because it's async method so If value is already different don't change it to old picture
{
molecule.parent.Content = new Image();
(molecule.parent.Content as Image).Source = wb;
(molecule.parent.Content as Image).Width = 24;
(molecule.parent.Content as Image).Height = 24;
}
Molecule.Reaction--; // done changing picture
}
internal static async Task<IRandomAccessStream> GetStream(string relativePath)
{
var storageFile = await Package.Current.InstalledLocation.GetFileAsync(relativePath.Replace('/', '\'));
var stream = await storageFile.OpenReadAsync();
return stream;
}
我制作了灰度图像,我想对其进行着色(例如更改 HSL)。
在我在 Internet 上找到的示例中,我需要位图 class,但在 Windows-10 通用应用程序中不存在。
WriteableBitmap class可用于获取图像的像素缓冲区,并使用语言指定的方法修改像素内容。查看 "Remarks" 和 "Examples" 会话以更好地理解。
并且我想推荐你WriteableBitmapEx which includes many extension methods to WriteableBitmap. You can get install the NuGet package在你的项目中使用它。
在出现许多错误后,这里是工作代码:
它可能看起来很糟糕,但它正在运行,我很高兴 :)
private static async void changeImage(Molecule molecule)
{
Molecule.Reaction++; // Used as Working/Loading status here
var atoms = molecule.Atoms;
if (atoms > 5) atoms = 5;
var stream = await GetStream("Assets/Images/" + atoms + ".png");
var decoder = await BitmapDecoder.CreateAsync(stream);
var pixelData = await decoder.GetPixelDataAsync();
var data = pixelData.DetachPixelData(); // Finally something where I can get my pixels
var wb = new WriteableBitmap(16, 16);
//wb.SetSource(stream); // Get pixel not working so I dont need this
for(int y = 0; y < decoder.PixelHeight; y++)
{
for(int x = 0; x < decoder.PixelWidth; x++)
{
// var rgba = wb.GetPixel(x, y); // This is not working, only returnning empty pixels (A:0, R:0, G:0, B:0)
// Get RGBA value of pixel
var rgba = new Color {
R = data[x * 4 + y * decoder.PixelWidth * 4 + 0],
G = data[x * 4 + y * decoder.PixelWidth * 4 + 1],
B = data[x * 4 + y * decoder.PixelWidth * 4 + 2],
A = data[x * 4 + y * decoder.PixelWidth * 4 + 3]
};
// Array can't have index -1 and -1 is for gray what is default
if (molecule.Owner != -1)
{
// Colorize pixel
var z = ((rgba.R + rgba.G + rgba.B) / 3.0) / 256;
rgba.R = Convert.ToByte(z * Settings.Colors[molecule.Owner].Item1.Color.R);
rgba.G = Convert.ToByte(z * Settings.Colors[molecule.Owner].Item1.Color.G);
rgba.B = Convert.ToByte(z * Settings.Colors[molecule.Owner].Item1.Color.B);
data[x * 4 + y * decoder.PixelWidth * 4 + 0] = rgba.R;
data[x * 4 + y * decoder.PixelWidth * 4 + 1] = rgba.G;
data[x * 4 + y * decoder.PixelWidth * 4 + 2] = rgba.B;
}
wb.SetPixel(x, y, rgba); // I tried to connect byte[] and WriteAbleBitmap via stream but Failed so I'm using this
}
}
if (atoms == molecule.Atoms) // Because it's async method so If value is already different don't change it to old picture
{
molecule.parent.Content = new Image();
(molecule.parent.Content as Image).Source = wb;
(molecule.parent.Content as Image).Width = 24;
(molecule.parent.Content as Image).Height = 24;
}
Molecule.Reaction--; // done changing picture
}
internal static async Task<IRandomAccessStream> GetStream(string relativePath)
{
var storageFile = await Package.Current.InstalledLocation.GetFileAsync(relativePath.Replace('/', '\'));
var stream = await storageFile.OpenReadAsync();
return stream;
}