在Viewbox的ContentPresenter中的图像上的BitmapImage上半透明地绘制 [英] Drawing semi-transparently on a BitmapImage on an Image in a ContentPresenter in a Viewbox

查看:102
本文介绍了在Viewbox的ContentPresenter中的图像上的BitmapImage上半透明地绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎已经有人问过这个问题的变体,但没有具体问过.另外,似乎 BitmapImages 与普通的 Bitmaps 不同.所以我们开始:

It seems like variations of this question have been asked before, but not this specifically. Also, it seems that BitmapImages are different from straight Bitmaps. So here we go:

我有一个 BitmapImage x:Name ="HeightMapImage" 指向一个位于 ContentPresenter内部的图像 x:Name ="image" 位于 Viewbox x:Name ="viewBox" 中的x:Name ="contentPresenter" .我想在 HeightMapImage 上的特定X,Y坐标处半透明和不透明地绘制.

I've got a BitmapImage x:Name="HeightMapImage" that is pointing to an Image x:Name="image" that is inside ContentPresenter x:Name="contentPresenter" that is in Viewbox x:Name="viewBox". I want to draw both semi-transparently and non-transparently at specific X,Y coordinates on the HeightMapImage.

进行此设置的原因是 BitmapImage 正在滚动和缩放.当我在X,Y上绘制 BitmapImage 时,我也希望它也自动滚动和缩放.

The reason for this set-up is that the BitmapImage is being scrolled and zoomed. When I draw on the BitmapImage at X,Y I want that to automatically scroll and zoom, too.

这些年来,我是一位非常老的怪胎,曾为许多不同的GDI中的许多机器编写过软件.这似乎是一些图形设备上下文问题的解决方法",一旦我掌握了它,我就可以轻松地将其撤走.

I'm a very old geek having written for many machines in many different GDIs over the years. This seems like a 'get the handle' to some graphic device context problem and once I've got it I can merrily draw away.

非常感谢您的帮助.

有人想看代码.这是 XAML :

<Viewbox x:Name="viewBox" Margin="0,0,0,0">
    <ContentPresenter x:Name="contentPresenter" Width="350" Height="350" >
        <ContentPresenter.Content>
            <Image x:Name="image" Width="350" Height="350">
                <Image.Source>
                    <BitmapImage x:Name="HeightMapImage" UriSource="DinoIslandLogo.bmp" />
                </Image.Source>
            </Image>
        </ContentPresenter.Content>
    </ContentPresenter>
</Viewbox>

这是某人想要的屏幕截图:

And here's a screen capture that somebody wanted:

这是获取用户所选位图并加载并显示它的代码:

And here's the code that gets the user's selected bitmap and loads and displays it:

string selectedFileName = dlg.FileName;
BitmapImage bitmap = new BitmapImage();

bitmap.BeginInit();
bitmap.UriSource = new Uri(selectedFileName);
bitmap.EndInit();

image.Source = bitmap;

是否需要为可写位图重写此内容?

Does this need to be rewritten for a Writeable Bitmap?

推荐答案

您可以使用WriteableBitmap代替BitmapImage(或实际上除了BitmapImage之外).首先像往常一样创建BitmapImage(但使用更少的代码):

You may use a WriteableBitmap instead of (or actually in addition to) a BitmapImage. First create your BitmapImage as usual (but with less code):

var selectedFileName = dlg.FileName;
var bitmap = new BitmapImage(new Uri(selectedFileName));

然后从BitmapImage创建一个WritableBitmap并将其分配给Image控件:

Then create a WritableBitmap from the BitmapImage and assign that to the Image control:

var writeableBitmap = new WriteableBitmap(bitmap);
image.Source = writeableBitmap;

现在,您可以修改WriteableBitmap以便绘制覆盖数据.以下代码段显示了如何获取和修改位图中的像素:

Now you may modify the WriteableBitmap in order to draw your overlay data. The following code snippet shows how to get and modify a pixel in the bitmap:

if (writeableBitmap.Format.BitsPerPixel == 32)
{
    var x = 10;
    var y = 20;
    var pixelRect = new Int32Rect(x, y, 1, 1);
    var pixelBuffer = new byte[4];
    writeableBitmap.CopyPixels(pixelRect, pixelBuffer, 4, 0);
    // modify pixelBuffer and write it back
    writeableBitmap.WritePixels(pixelRect, pixelBuffer, 4, 0);
}

建议使用SetPixel方法,该方法将覆盖色的alpha值考虑在内.请注意,此方法假定位图的像素格式为Bgr32.

A suggestion for a SetPixel method that takes the overlay color alpha value into account. Please note that this method assumes that the bitmap's pixel format is Bgr32.

public void SetPixel(WriteableBitmap wb, int x, int y, Color color)
{
    var pixelRect = new Int32Rect(x, y, 1, 1);
    var pixelBuffer = new byte[4];
    wb.CopyPixels(pixelRect, pixelBuffer, 4, 0);
    pixelBuffer[0] = (byte)(pixelBuffer[0] * (1F - color.ScA) + color.B * color.ScA);
    pixelBuffer[1] = (byte)(pixelBuffer[1] * (1F - color.ScA) + color.G * color.ScA);
    pixelBuffer[2] = (byte)(pixelBuffer[2] * (1F - color.ScA) + color.R * color.ScA);
    wb.WritePixels(pixelRect, pixelBuffer, 4, 0);
}

另请注意,一次性设置更多像素的效率要高得多.理想情况下,您应该一次设置所有重叠像素.您需要将所有像素值复制到一个大数组中,如上所示计算其新的RGB值,然后立即将它们全部写回.

Please note also that it is a lot more efficient to set a larger number of pixels in one go. Ideally you would set all overlay pixels at once. You would copy all pixel values into one large array, calculate their new RGB values as shown above, and then write them all back at once.

这篇关于在Viewbox的ContentPresenter中的图像上的BitmapImage上半透明地绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆