在Viewbox的ContentPresenter中的Image上的BitmapImage上半透明地绘制

时间:2013-05-26 12:28:22

标签: c# wpf draw bitmapimage viewbox

似乎之前已经问过这个问题的变体,但没有具体说明。此外,BitmapImages似乎与直Bitmaps不同。所以我们走了:

我有BitmapImage x:Name="HeightMapImage"指向位于x:Name="image" ContentPresenter x:Name="contentPresenter"Viewbox x:Name="viewBox"内的图片HeightMapImage。我想在BitmapImage的特定X,Y坐标上半透明地和非透明地绘制。

这种设置的原因是BitmapImage正在滚动和缩放。当我在X上的XAML上画画时,我希望它也能自动滚动和缩放。

多年来,我是一位非常古怪的极客,为许多不同的GDI编写了许多机器。这似乎是对某些图形设备上下文问题的“处理”,一旦我得到它,我就可以愉快地离开。

非常感谢您的帮助。

有人想看看代码。这是<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>

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

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

image.Source = bitmap;

这是一个有人想要的屏幕截图:

enter image description here

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

Writeable Bitmap

这是否需要为{{1}}重写?

1 个答案:

答案 0 :(得分:4)

您可以使用WriteableBitmap而不是(或实际上除了)BitmapImage。首先像往常一样创建BitmapImage(但代码较少):

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

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

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

现在您可以修改WriteableBitmap以绘制叠加数据。以下代码段显示了如何获取和修改位图中的像素:

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。

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值,然后立即将它们全部写回。