C#绘制图像实现
我试图用不安全的代码和指针来实现Grahpics.DrawImage 在这种情况下,我试图在更大的宽度上绘制一个小位图(都是32bppArgb) 这是我的密码C#绘制图像实现,c#,image-processing,graphics,C#,Image Processing,Graphics,我试图用不安全的代码和指针来实现Grahpics.DrawImage 在这种情况下,我试图在更大的宽度上绘制一个小位图(都是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.Hei
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);
}
private静态绘制(位图bmp、位图bmp2、int-xPoint、int-yPoint)
{
BitmapData bmData=bmp.LockBits(新矩形(0,0,bmp.Width,bmp.Height),System.Drawing.ImageLockMode.WriteOnly,bmp.PixelFormat);
BitmapData bmData2=bmp2.LockBits(新矩形(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-stripe2=bmData2.stripe;
int nWidth=bmp2.宽度;
int nHeight=bmp2.高度;
int sourceX=0;
int sourceY=0;
字节*p=(字节*)scan0.ToPointer();
p+=yPoint*stride+xPoint*4;
字节*p2=(字节*)scan02.ToPointer();
p2+=sourceY*2+sourceX*4;
int字节=nWidth*4;
对于(int y=0;y 对于(int x=0;x我做了一些更改以使其工作:
- 使用
LockBits
中的ImageLockMode.WriteOnly
调用要写入的图像
- 不要根据
xPoint
和yPoint
移动p2
我看到您将指针设置在外循环内,因此不需要移动循环末尾的指针。我建议您计算外循环外的起点,然后将指针移动到外循环内
我还建议进行以下更改:
- 添加对图像边界的检查,以避免意外尝试在图像外部绘制
- 使方法
无效
。返回位图表明它创建了一个新位图,而不是更改传递给它的位图之一
我添加了一个pixelBytes
参数,使其可用于不同的像素格式(主要是因为我碰巧使用了JPEG,而不是PNG进行测试)
代码:
private静态绘制(位图bmp、位图bmp2、int-xPoint、int-yPoint、int-pixelBytes){
BitmapData bmData=bmp.LockBits(新矩形(0,0,bmp.Width,bmp.Height),System.Drawing.ImageLockMode.WriteOnly,bmp.PixelFormat);
BitmapData bmData2=bmp2.LockBits(新矩形(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-stripe2=bmData2.stripe;
int nWidth=bmp2.宽度;
int nHeight=bmp2.高度;
int sourceX=0;
int sourceY=0;
if(xPoint<0){
sourceX=-xPoint;
nWidth-=sourceX;
xPoint=0;
}
如果(yPoint<0){
sourceY=-yPoint;
nHeight-=源代码;
yPoint=0;
}
if(xPoint+nWidth>bmp.Width){
nWidth=bmp.Width-xPoint;
}
如果(yPoint+nHeight>bmp.Height){
nHeight=bmp.Height-yPoint;
}
如果(nWidth>0&&n宽度>0){
字节*p=(字节*)scan0.ToPointer();
p+=yPoint*stride+xPoint*pixelBytes;
字节*p2=(字节*)scan02.ToPointer();
p2+=sourceY*strip2+sourceX*pixelBytes;
int字节=nWidth*像素字节;
对于(int y=0;y
您正在将图像复制到自身。对于b2
您应该使用scan02
而不是scan0
。对于b2
,您还应该使用stride
和stride2
将b
和b2
移动到下一行,而不是假设下一行在当前行之后立即开始。行之间可能有填充,当图像在内存中颠倒存储时,步幅甚至可能为负值。@Guffa ohh..没有看到它…谢谢!Guffa等等..现在我在这里遇到一个异常`p[0]=p2[0];**试图读取或写入受保护的内存**我刚刚在上面的评论中添加了更多内容。@Guffa首先是它的p
哈哈。关于移动p
元素而不是p+=4
来只使用`p+=(yPoint*stride)+(xPoint*4)
?谢谢你,伙计,你太棒了!你的代码直截了当了!+1最后一件事是,这个方法的执行时间比我的慢多了(我知道它不起作用,但仍然有效).我认为主要的瓶颈是内部循环正在运行字节
时间..难道它不能运行得更快吗?你能更新我的代码中的一些东西使其工作吗?非常感谢兄弟!你的答案非常棒,但有点慢..提前感谢!@Slashy:如果你删除像素字节
参数并使其循环pixels而不是字节,你应该恢复性能。删除了参数。现在我应该改为写4
,对吗?什么意思?让它循环像素@Guffa@Slashy:是。在循环中使用x
,将所有p[0]
复制到p[3]
,并使用+=4
增加指针。
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);
}