使用c#(通用windows应用程序)将颜色合并到位图中
我有一个.png资源,其中包括下表中所述的需要“着色”的区域(这些是我自己的定义,如果有更好的术语,我应该使用,请随意教我)。我需要根据彩色画笔(例如BGRA=#6572D8FF)为这张图像“上色”,以便使用c#(通用windows应用程序)将颜色合并到位图中,c#,C#,我有一个.png资源,其中包括下表中所述的需要“着色”的区域(这些是我自己的定义,如果有更好的术语,我应该使用,请随意教我)。我需要根据彩色画笔(例如BGRA=#6572D8FF)为这张图像“上色”,以便 // Input Output // Transparent BGRA=#FFFFFF00 --> #FFFFFF00 // AlphaOnly BGRA=#00000000 --> #6572
// Input Output
// Transparent BGRA=#FFFFFF00 --> #FFFFFF00
// AlphaOnly BGRA=#00000000 --> #6572D800 // Colored area
// Alpha-Shaded BGRA=#000000aa --> #6572D8aa // Colored area
// Solid colors BGRA=#bbggrrFF --> #rrggbbFF
结果图像需要使用以下XAML显示
<Viewbox Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">
<Grid Height="100" Width="100">
<Image x:Name="currentImage" />
</Grid>
</Viewbox>
将控件放置在红色背景上并指定蓝色画笔,我希望得到底部图像(我只需在原始图像后面放置一个蓝色椭圆即可创建)
不幸的是,我得到了最高的形象。我的透明度丢失了,我希望实现的alpha着色是错误的。任何帮助(包括你这个“白痴”,你应该这样做)都将不胜感激
public sealed class MyImage : Control {
public MyImage() {
this.DefaultStyleKey = typeof(MyImage);
Loaded += MyImage_Loaded;
}
private async void MyImage_Loaded(object sender, RoutedEventArgs e) {
((Image)this.GetTemplateChild("currentImage")).Source = await ColorImage();
}
private async Task<WriteableBitmap> ColorImage() {
// Get the image as a byte array
StorageFile fileImage = await StorageFile.GetFileFromApplicationUriAsync(new Uri(BaseImageUri, UriKind.Absolute));
ImageProperties propsImage = await fileImage.Properties.GetImagePropertiesAsync();
int height = (int)propsImage.Height;
int width = (int)propsImage.Width;
byte[] baseImagePixels = await ReadPixels(fileImage);
// Modify the mask by adding the accent color
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
byte B = baseImagePixels[4 * (y * height + x) + 0];
byte G = baseImagePixels[4 * (y * height + x) + 1];
byte R = baseImagePixels[4 * (y * height + x) + 2];
byte A = baseImagePixels[4 * (y * height + x) + 3];
if (R == 0x00 && G == 0x00 && B == 0x00 && A != 0xFF) {
baseImagePixels[4 * (y * height + x) + 0] = ColorBrush.Color.B;
baseImagePixels[4 * (y * height + x) + 1] = ColorBrush.Color.G;
baseImagePixels[4 * (y * height + x) + 2] = ColorBrush.Color.R;
}
}
}
WriteableBitmap coloredImage = new WriteableBitmap((int)propsImage.Width, (int)propsImage.Height);
using (Stream stream = coloredImage.PixelBuffer.AsStream()) {
await stream.WriteAsync(baseImagePixels, 0, baseImagePixels.Length);
}
return coloredImage;
}
private async Task<byte[]> ReadPixels(StorageFile file) {
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(await file.OpenAsync(FileAccessMode.Read));
BitmapTransform transform = new BitmapTransform();
PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
new BitmapTransform(),
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage);
return pixelData.DetachPixelData();
}
public String BaseImageUri {
get { return (String)GetValue(BaseImageUriProperty); }
set {
if (value.StartsWith("ms-appx:///")) {
SetValue(BaseImageUriProperty, value);
} else {
SetValue(BaseImageUriProperty, "ms-appx:///" + value);
}
}
}
public static readonly DependencyProperty BaseImageUriProperty =
DependencyProperty.Register("BaseImageUri", typeof(String), typeof(MyImage), new PropertyMetadata(0));
public SolidColorBrush ColorBrush {
get { return (SolidColorBrush)GetValue(ColorBrushProperty); }
set { SetValue(ColorBrushProperty, value); }
}
public static readonly DependencyProperty ColorBrushProperty =
DependencyProperty.Register("ColorBrush", typeof(SolidColorBrush), typeof(MyImage), new PropertyMetadata(0));
}
公共密封类MyImage:控件{
公共MyImage(){
this.DefaultStyleKey=typeof(MyImage);
已加载+=已加载的MyImage\u;
}
已加载私有异步void MyImage_(对象发送方,RoutedEventArgs e){
((Image)this.GetTemplateChild(“currentImage”)).Source=await ColorImage();
}
专用异步任务ColorImage(){
//以字节数组的形式获取图像
StorageFile fileImage=等待StorageFile.GetFileFromApplicationUrisync(新Uri(BaseImageUri,UriKind.Absolute));
ImageProperties propsImage=await fileImage.Properties.GetImagePropertiesAsync();
int height=(int)propsImage.height;
int width=(int)propsImage.width;
字节[]baseImagePixels=等待读取像素(fileImage);
//通过添加强调色修改遮罩
对于(int y=0;y
我找到了一个解决办法。我不知道为什么它会起作用。。。如果有人知道原因,我会很乐意接受这方面的教育。我为for循环添加了第二个更改
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixelIndex = 4 * (y * width + x);
byte B = baseImagePixels[pixelIndex];
byte G = baseImagePixels[pixelIndex + 1];
byte R = baseImagePixels[pixelIndex + 2];
byte A = baseImagePixels[pixelIndex + 3];
if (!(B == 0xFF && G == 0xFF && R == 0xFF && A == 0x00)) {
baseImagePixels[pixelIndex] = colorBrush.Color.B;
baseImagePixels[pixelIndex + 1] = colorBrush.Color.G;
baseImagePixels[pixelIndex + 2] = colorBrush.Color.R;
baseImagePixels[pixelIndex + 3] = colorBrush.Color.A;
} else if (B == 0xFF && G == 0xFF && R == 0xFF && A == 0x00) {
baseImagePixels[pixelIndex] = 0x00;
baseImagePixels[pixelIndex + 1] = 0x00;
baseImagePixels[pixelIndex + 2] = 0x00;
baseImagePixels[pixelIndex + 3] = 0x00;
}
}
}
for(int y=0;y
这对我来说似乎是个问题,但这只是一个猜测
某些图形库要求alpha<1.0的像素将其RGB组件存储为:
R' := R x A
G' := G x A
B' := B x A
A' := A
因此RGB→ <字母为零的代码>0xFFFFFF无效
当RGB值超过其alpha值时,预期使用预乘alpha像素的混合算法会产生意外的结果
因此,在预乘alpha的情况下,完全透明的像素始终以0 alpha编码为0x000000