C#绘制图像实现 [英] C# Draw image implemention
问题描述
我正在尝试使用不安全的代码和指针来实现Grahpics.DrawImage
实施.
Im trying to make kind of Grahpics.DrawImage
implemention using unsafe code and pointers of course.
在这种情况下,我试图在较大的宽度(均为32bppArgb)上绘制小的位图.
In this case im trying to draw a small bitmap on a bigger width(both 32bppArgb).
这是我的代码
private static unsafe void Draw(Bitmap bmp, Bitmap bmp2, int xPoint, int yPoint)
{
BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp.PixelFormat);
BitmapData bmData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp2.PixelFormat);
IntPtr scan0 = bmData.Scan0;
IntPtr scan02 = bmData2.Scan0;
int stride = bmData.Stride;
int stride2 = bmData2.Stride;
int nWidth = bmp2.Width;
int nHeight = bmp2.Height;
int sourceX = 0;
int sourceY = 0;
byte* p = (byte*)scan0.ToPointer();
p += yPoint * stride + xPoint * 4;
byte* p2 = (byte*)scan02.ToPointer();
p2 += sourceY * stride2 + sourceX * 4;
int bytes = nWidth * 4;
for (int y = 0; y < nHeight; y++)
{
for (int x = 0; x <nWidth; x++)
{
p[0] = p2[0];
p[1] = p2[1];
p[2] = p2[2];
p[3] = p2[3];
}
p += 4;
p2 += 4;
}
bmp.UnlockBits(bmData);
bmp2.UnlockBits(bmData2);
}
这是更新的代码
推荐答案
我进行了一些更改以使其起作用:
I made some changes to make it work:
- 在
LockBits
调用中使用ImageLockMode.WriteOnly
来写入要写入的图像. - 不要按照
xPoint
和yPoint
移动p2
.
- Use
ImageLockMode.WriteOnly
in theLockBits
call for the image that you want to write to. - Don't move
p2
according toxPoint
andyPoint
.
我看到您在外部循环中设置了指针,因此您无需在循环的末尾移动指针.我建议您在外循环外计算起点,然后将指针移到外循环内.
I saw that you set the pointers inside the outer loop, so then you would not need to move the pointers at the end of the loop. I recommend that you calculcate the starting points outside the outer loop, and move the pointers inside it.
我还建议我进行以下更改:
I also recommend these changes that I did:
-
添加检查图像边界的方法,这样您就不会意外地在图像外部进行绘制.
Add checks for the bounds of the images, so that you don't accidentally try to draw outside the image.
使方法为void
.返回位图表明它会创建一个新的位图,而不是更改传递给它的位图之一.
Make the method void
. Returning a bitmap suggests that it creates a new bitmap rather than changing one of the bitmap that you pass into it.
我添加了一个pixelBytes
参数以使其可用于不同的像素格式. (主要是因为我碰巧有JPEG,而不是要测试的PNG.)
I added a pixelBytes
parameter to make it usable for different pixel formats. (Mostly because I happened to have JPEGs, not PNGs to test with.)
代码:
private static unsafe void Draw(Bitmap bmp, Bitmap bmp2, int xPoint, int yPoint, int pixelBytes) {
BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp.PixelFormat);
BitmapData bmData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp2.PixelFormat);
IntPtr scan0 = bmData.Scan0;
IntPtr scan02 = bmData2.Scan0;
int stride = bmData.Stride;
int stride2 = bmData2.Stride;
int nWidth = bmp2.Width;
int nHeight = bmp2.Height;
int sourceX = 0;
int sourceY = 0;
if (xPoint < 0) {
sourceX = -xPoint;
nWidth -= sourceX;
xPoint = 0;
}
if (yPoint < 0) {
sourceY = -yPoint;
nHeight -= sourceY;
yPoint = 0;
}
if (xPoint + nWidth > bmp.Width) {
nWidth = bmp.Width - xPoint;
}
if (yPoint + nHeight > bmp.Height) {
nHeight = bmp.Height - yPoint;
}
if (nWidth > 0 && nHeight > 0) {
byte* p = (byte*)scan0.ToPointer();
p += yPoint * stride + xPoint * pixelBytes;
byte* p2 = (byte*)scan02.ToPointer();
p2 += sourceY * stride2 + sourceX * pixelBytes;
int bytes = nWidth * pixelBytes;
for (int y = 0; y < nHeight; y++) {
for (int x = 0; x < bytes; x++) {
p[0] = p2[0];
p++;
p2++;
}
p += stride - nWidth * pixelBytes;
p2 += stride2 - nWidth * pixelBytes;
}
}
bmp.UnlockBits(bmData);
bmp2.UnlockBits(bmData2);
}
这篇关于C#绘制图像实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!