WriteableBitmap.WritePixels显示在错误的位置

时间:2014-02-20 19:00:01

标签: c# wpf graphics

这是一段代码片段,我尝试在WPF图像控件中的图形(Bgra32 3985x3443)上放置一个蓝点图标(Bgr32; 169x169)。

string s = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\lg_dot.jpg";
BitmapImage icon = new BitmapImage(new Uri(s));
var baseLayer = img_BackgroundLayer.Source as BitmapImage;
WriteableBitmap composite = new WriteableBitmap(baseLayer);

int bytesPerPixel = (int)(icon.Format.BitsPerPixel + 7) / 8;
int stride = (int)(bytesPerPixel * icon.Width);
int size = stride * (int)icon.Height;
byte[] pixels = new byte[size];                
icon.CopyPixels(pixels, stride, 0);

composite.WritePixels(new Int32Rect(0, 0, (int)icon.Width, (int)icon.Height), pixels, stride, 1000, 1000);

请注意,我将点(图标)放在(1000,1000)图像上。但是,当观察时,点的左上角不是(1000,1000),它大约是(760,760)。如果我试图将图标放在(2000,2000),它出现在大约(1520,1520)。图标出现的位置总是大约(0.76 * X,0.76 * Y),其中X和Y是目标坐标。

我想我知道这里发生了什么......将Bgr32图像放到Bgra32背景上有什么关系...但我不够聪明,看看如何解决它。

1 个答案:

答案 0 :(得分:0)

每像素字节公式:

(bits per pixel + 7) / 8

步伐公式:

bytes per pixel * image width

注意字节并使用整数进行计算!

因此对于1024像素宽的图像:

Bgr32

  • 每像素字节数:(24 + 7) / 8 = 3
  • 步幅:3 * 1024 = 3072

Bgra32

  • 每像素字节数:(32 + 7) / 8 = 4
  • 步幅:4 * 1024 = 4096

查看您的代码:

  • 步幅应为3,而不是4:D

  • 您不必使用步幅int[],请记住sizeof(int) == 4

byte byte[]图片数组中像素的偏移量:每像素stride * y + x *字数

int int[]图像数组中像素的偏移量:y * width + x

顺便问一下,您是否检查过Image.Stretch是否设为None

最后,请注意组件顺序:

BGRA代表ARGB(如果A为0,你可能看不到任何东西,你认为你已经设置了B)

最后提示:https://writeablebitmapex.codeplex.com/最终可能对您更容易。


修改

这非常糟糕,在我的情况下它是空的,因为BitmapFrameDecode无法转换为BitmapImage,最好保留对源的引用:

var baseLayer = Image1.Source as BitmapImage;

我给你的公式是正确的,我只需改变destX和destY,因为我的背景不像你的那么大。

var icon = new BitmapImage(new Uri("..\\..\\avatar92.jpg", UriKind.Relative));
var background = new BitmapImage(new Uri("..\\..\\canary_1024_600_a_0.jpg", UriKind.Relative));
var writeableBitmap = new WriteableBitmap(background);

int bytesPerPixel = (icon.Format.BitsPerPixel + 7) / 8;
int stride = bytesPerPixel * icon.PixelWidth;
int size = stride * icon.PixelHeight;
var pixels = new byte[size];
icon.CopyPixels(pixels, stride, 0);
writeableBitmap.WritePixels(new Int32Rect(0, 0, icon.PixelWidth, icon.PixelHeight), pixels, stride, 500, 500);

Image1.Source = writeableBitmap;

enter image description here

再次

  • Image.Stretch == None
  • 图像尺寸是否正确?他们应该是我猜:D
  • 位图的格式是否相同?并非它不会失败,如果它们不同但你会得到各种有趣的惊喜,例如尝试使用.GIF和.JPEG文件。
  • 我真的建议您使用WriteableBitmapEx代替,您可以绘制像素,线条,矩形,形状等......

这与WriteableBitmapEx的结果相同,而不必处理所有细节,例如stride,array,bpp等......

var icon = new BitmapImage(new Uri("..\\..\\avatar92.jpg", UriKind.Relative));
var background = new BitmapImage(new Uri("..\\..\\canary_1024_600_a_0.jpg", UriKind.Relative));
var img1 = BitmapFactory.ConvertToPbgra32Format(icon);
var img2 = BitmapFactory.ConvertToPbgra32Format(background);
var img1Size = new Size(img1.PixelWidth, img1.PixelHeight);
img2.Blit(new Rect(new Point(500, 500), img1Size), img1, new Rect(img1Size));
Image1.Source = img2;

如果您更喜欢这种方式,请确保您的位图具有相同的格式:FormatConvertedBitmap

如果仍然无法正常使用,请发布Short, Self Contained, Correct (Compilable), Example并链接到这两个图片,以便人们可以真的帮助您。我没有在你的代码中找到任何内容,所以我猜有些东西不对,但是因为你还没有粘贴我们无法辨认的所有代码。