使用C#将颜色合并到位图中(通用Windows应用程序)

Embergleam

我有一个.png资源,其中包括需要按下表所述进行“着色”的区域(这些是我自己的定义,如果有更好的用语,我可以随时使用它来教育我)。我需要基于ColorBrush(例如BGRA =#6572D8FF)对图像进行“着色”,以便...

//                        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>

我希望将控件放置在红色背景上并指定蓝色ColorBrush,希望获得底部图像(我是通过在原始图像后面简单地放置一个蓝色椭圆来创建的)

在此处输入图片说明

不幸的是我得到了最高的形象。我的透明度丢失了,我希望达到的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));
}
皮埃尔·阿诺(Pierre Arnaud)

在我看来,这似乎是一个预乘的alpha问题,但这只是一个疯狂的猜测。

一些图形库要求alpha <1.0的像素将其RGB分量存储为:

R' := R x A
G' := G x A
B' := B x A
A' := A

因此0xFFFFFF,alpha值为零的RGB→将无效。

当其RGB值超过其alpha值时,预期将与预乘alpha像素一起馈送的混合算法会产生意外结果

因此0x000000,在预乘alpha情况下,始终将完全透明的像素编码为0 alpha。

看一下有关Alpha合成的Wikipedia文章

假设像素颜色是使用直的(未预乘)RGBA元组表示的,则像素值(0.0,0.5,0.0,0.5)表示最大绿色强度为50%,不透明度为50%的像素。如果颜色是完全绿色,则其RGBA将为(0,1,0,0.5)。

但是,如果此像素使用预乘alpha,则将所有RGB值(0,1,0)乘以0.5,然后将alpha附加到末尾以产生(0,0.5,0,0.5)。在这种情况下,G通道的0.5值实际上表示100%的绿色强度(不透明度为50%)。出于这个原因,知道文件是使用预乘还是直接Alpha是正确处理或合成该文件的关键。

它还说明了各种颜色合并运算符的工作方式。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将多个单独的通用应用程序合并到一个主应用程序

将SQLite Windows窗体应用程序迁移到通用Windows应用程序(C#)

如何使用WinForms C#应用程序通过电子邮件将数据合并到中央SQL Server数据库中?

如何在Windows 10 C#通用应用程序中使用C ++类?

C#:如何将RAW图像(格式:rgb565)加载到位图中?

如何使用C#在通用Windows应用程序中包含计时器

使用C#在Windows应用程序的数据网格视图中随机显示数据

使用毕加索将图像加载到位图中

如何使用套接字将文件从 android java 应用程序传输到 C# windows 应用程序?

通用Windows平台(UWP)C#应用程序-如何在应用程序中运行独立的python

使用Windows应用程序C#将文本文件上传到mysql中

在Windows Store应用程序中使用C#将FadeOut添加到图像中

将 Redis/Spring Session 合并到我的应用程序中会阻止我部署应用程序

压缩或压缩文件-Windows Phone通用应用程序-C#

c# windows 窗体应用程序中将通用列表的项绑定到不同的网格

C#通用应用程序:将github存储库添加为依赖项

仅使用Windows窗体应用程序的C#游戏

尝试将 ML onnx 模型合并到 Android 应用程序中

无法将Unity 5合并到我们的iOS应用程序中

将YUI3合并到Java Web应用程序中的有效方法?

将国家标志合并到Rails 4应用程序中,我有哪些选择?

将几个管道作业的结果合并到Azure Web应用程序包中

将库中的专用 ELF 部分合并到应用程序专用 ELF 部分

我如何开始将 reactJs 合并到现有的 Laravel 应用程序中

如何使用通用Windows应用程序将串行数据写入COM端口?

将 c# 控制台应用程序转换为 c# windows 窗体应用程序

合并到位排序

裁剪图像通用应用程序C#

通用应用程序:从JavaScript调用C#方法