我有一个这样的位图:
var map = new WriteableBitmap(800,800,800,800, PixelFormats.Bgr32,null);
然后我有一个50x50的png图片,我想合并到这个位图(包含透明度)位于偏移顶部100左边150(从位图的左上角)
var img = new BitmapImage(new Uri(@"D:\test.png", UriKind.Absolute));
我尝试了map.WritePixels(img);
之类的东西,但这只会引发错误。
如何将此图像合并到位图中?
答案 0 :(得分:3)
只需将颜色值复制到缓冲区,然后将其复制回WriteableBitmap
public void Chubs_BitBltMerge(ref WriteableBitmap dest, int nXDest, int nYDest, ref BitmapImage src)
{
// copy the source image into a byte buffer
int src_stride = src.PixelWidth * (src.Format.BitsPerPixel >> 3);
byte[] src_buffer = new byte[src_stride * src.PixelHeight];
src.CopyPixels(src_buffer, src_stride, 0);
// copy the dest image into a byte buffer
int dest_stride = src.PixelWidth * (dest.Format.BitsPerPixel >> 3);
byte[] dest_buffer = new byte[(src.PixelWidth * src.PixelHeight) << 2];
dest.CopyPixels(new Int32Rect(nXDest, nYDest, src.PixelWidth, src.PixelHeight), dest_buffer, dest_stride, 0);
// do merge (could be made faster through parallelization)
for (int i = 0; i < src_buffer.Length; i = i + 4)
{
float src_alpha = ((float)src_buffer[i + 3] / 255);
dest_buffer[i + 0] = (byte)((src_buffer[i + 0] * src_alpha) + dest_buffer[i + 0] * (1.0 - src_alpha));
dest_buffer[i + 1] = (byte)((src_buffer[i + 1] * src_alpha) + dest_buffer[i + 1] * (1.0 - src_alpha));
dest_buffer[i + 2] = (byte)((src_buffer[i + 2] * src_alpha) + dest_buffer[i + 2] * (1.0 - src_alpha));
}
// copy dest buffer back to the dest WriteableBitmap
dest.WritePixels(new Int32Rect(nXDest, nYDest, src.PixelWidth, src.PixelHeight), dest_buffer, dest_stride, 0);
}
public MainWindow()
{
InitializeComponent();
BitmapImage texture = new BitmapImage(new Uri("50x50.png", UriKind.Relative));
Image background = new Image();
background.Source = new BitmapImage(new Uri("backdrop.png", UriKind.Relative));
WriteableBitmap wb = new WriteableBitmap((BitmapSource)background.Source);
// bit the 50x50 onto the backdrop
Chubs_BitBltMerge(ref wb, 150, 100, ref texture);
// set the result to an Image in XAML to see the result
//this.myImage.Source = wb;
//this.myImage.Width = wb.PixelWidth;
//this.myImage.Height = wb.PixelHeight;
}
答案 1 :(得分:0)
在计算Alpha通道的值时,请确保要除以浮点值,例如通过使用255.0而不是255,否则当alpha = 255时,您只会得到src_alpha = 1,否则,您将得到src_alpha = 0。进行小透明处理时,变化很小,但影响很大。 所以我的解决方案看起来像这样:
public void Chubs_BitBltMerge(ref WriteableBitmap dest, int nXDest, int nYDest, ref BitmapImage src)
{
// copy the source image into a byte buffer
int src_stride = src.PixelWidth * (src.Format.BitsPerPixel >> 3);
byte[] src_buffer = new byte[src_stride * src.PixelHeight];
src.CopyPixels(src_buffer, src_stride, 0);
// copy the dest image into a byte buffer
int dest_stride = src.PixelWidth * (dest.Format.BitsPerPixel >> 3);
byte[] dest_buffer = new byte[(src.PixelWidth * src.PixelHeight) << 2];
dest.CopyPixels(new Int32Rect(nXDest, nYDest, src.PixelWidth, src.PixelHeight), dest_buffer, dest_stride, 0);
// do merge (could be made faster through parallelization)
for (int i = 0; i < src_buffer.Length; i = i + 4)
{
float src_alpha = (float)(src_buffer[i + 3] / 255.0);
dest_buffer[i + 0] = (byte)((src_buffer[i + 0] * src_alpha) + dest_buffer[i + 0] * (1.0 - src_alpha));
dest_buffer[i + 1] = (byte)((src_buffer[i + 1] * src_alpha) + dest_buffer[i + 1] * (1.0 - src_alpha));
dest_buffer[i + 2] = (byte)((src_buffer[i + 2] * src_alpha) + dest_buffer[i + 2] * (1.0 - src_alpha));
}
// copy dest buffer back to the dest WriteableBitmap
dest.WritePixels(new Int32Rect(nXDest, nYDest, src.PixelWidth, src.PixelHeight), dest_buffer, dest_stride, 0);
}