对图片进行切片处理,对BitBlt()方法的研究心得--c#

bitblt方法用于快速截取设备上图片的一部分在内存中,然后进行显示。

 

bitblt是api的方法,首先引用此方法。

  1. [DllImport("gdi32.dll   ")]
  2.         private static extern bool BitBlt(
  3.         IntPtr hdcDest,   //   handle   to   destination   DC   
  4.         int nXDest,   //   x-coord   of   destination   upper-left   corner   
  5.         int nYDest,   //   y-coord   of   destination   upper-left   corner   
  6.         int nWidth,   //   width   of   destination   rectangle   
  7.         int nHeight,   //   height   of   destination   rectangle   
  8.         IntPtr hdcSrc,   //   handle   to   source   DC   
  9.         int nXSrc,   //   x-coordinate   of   source   upper-left   corner   
  10.         int nYSrc,   //   y-coordinate   of   source   upper-left   corner   
  11.         System.Int32 dwRop   //   raster   operation   code   
  12.         );

在vb中此方法的解释是:

BitBlt 目标hDC, 目标X, 目标Y, 图像高, 图像宽, 源hDC, 源X, 源Y, 光栅运算常数

【函数】
BitBlt

【操作系统】
Win9X:Yes
WinNT:Yes

【声明】
BitBlt Lib "gdi32" Alias "BitBlt" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

【说明】

将一幅位图从一个设备场景复制到另一个。源和目标DC相互间必须兼容

【返回值】

Long,非零表示成功,零表示失败。会设置GetLastError

【其它】

在NT环境下,如在一次世界传输中要求在源设备场景中进行剪切或旋转处理,这个函数的执行会失败
如目标和源DC的映射关系要求矩形中像素的大小必须在传输过程中改变,那么这个函数会根据需要自动伸缩、旋转、折叠、或切断,以便完成最终的传输过程

【参数表】
hDestDC -------- Long,目标设备场景

x,y ------------ Long,对目标DC中目标矩形左上角位置进行描述的那个点。用目标DC的逻辑坐标表示

nWidth,nHeight - Long,欲传输图象的宽度和高度

hSrcDC --------- Long,源设备场景。如光栅运算未指定源,则应设为0

xSrc,ySrc ------ Long,对源DC中源矩形左上角位置进行描述的那个点。用源DC的逻辑坐标表示

dwRop ---------- Long,传输过程要执行的光栅运算

 

然后使用下面的方法进行截取:

  1. private Bitmap copyRect(PictureBox pic, Rectangle rect)
  2.         {
  3.             const int SRCCOPY = 0x00CC0020;
  4.             //Get a Graphics Object from the form
  5.             Graphics g1 = pic.CreateGraphics();
  6.             //Create a EMPTY bitmap from that graphics
  7.             Bitmap bit2 = new Bitmap(100, 100, g1);
  8.             //Create a Graphics object in memory from that bitmap
  9.             Graphics g2 = Graphics.FromImage(bit2);
  10.             //get the IntPtr's of the graphics
  11.             IntPtr hdc1 = g1.GetHdc();
  12.             //get the IntPtr's of the graphics
  13.             IntPtr hdc2 = g2.GetHdc();
  14.             //get the picture 
  15.             BitBlt(hdc2, p1.Location.X, p1.Location.Y, rect.Width, rect.Height, hdc1, rect.X, rect.Y, SRCCOPY);
  16.             Bitmap b = (Bitmap)bit2.Clone();
  17.             //clear all
  18.             g1.ReleaseHdc(hdc1);
  19.             g2.ReleaseHdc(hdc2);
  20.             g1.Dispose();
  21.             g2.Dispose();
  22.             return b;
  23.         }

但是,正如大家所看到的,copyRect方法有一个参数是picturebox类型的。而且此picturebox控件,必须是显示在设备(譬如form)上的。如果不这样我们就得不到截取的图片。也就是说它只能截取已经显示到设备上的控件上的图片。

如果我们将上述代码改为:

  1. private Bitmap copyRect(Bitmap bit1, Rectangle rect)
  2.         {
  3.             const   int   SRCCOPY   =   0x00CC0020;
  4.             Graphics g1 = Graphics.FromImage(bit1);
  5.             Bitmap bit2 = new Bitmap(100, 100, g1);
  6.             Graphics g2 = Graphics.FromImage(bit2);
  7.             IntPtr hdc1 = g1.GetHdc();
  8.             IntPtr hdc2 = g2.GetHdc();
  9.             BitBlt(hdc2, p1.Location.X, p1.Location.Y, rect.Width, rect.Height, hdc1, rect.X, rect.Y, 13369376);
  10.             Bitmap b =(Bitmap) bit2.Clone();
  11.             g1.ReleaseHdc(hdc1);
  12.             g2.ReleaseHdc(hdc2);
  13.             g1.Dispose();
  14.             g2.Dispose();
  15.             return b;
  16.         }

那么我们将得不到任何的内容,只是一张透明的图片。

或者我们可以考虑声明一个picturebox并且将原图赋给它,然后以此picturebox作为截取图片的设备。

如下的代码:

  1. private Bitmap copyRect(Bitmap bit1, Rectangle rect)
  2.         {
  3.             const   int   SRCCOPY   =   0x00CC0020;
  4.             PictureBox p1 = new PictureBox();
  5.             p1.Image = bit1;
  6.             
  7.             Graphics g1 = p1.CreateGraphics();
  8.             Bitmap bit2 = new Bitmap(100, 100, g1);
  9.             Graphics g2 = Graphics.FromImage(bit2);
  10.             IntPtr hdc1 = g1.GetHdc();
  11.             IntPtr hdc2 = g2.GetHdc();
  12.             BitBlt(hdc2, p1.Location.X, p1.Location.Y, rect.Width, rect.Height, hdc1, rect.X, rect.Y, 13369376);
  13.             Bitmap b =(Bitmap) bit2.Clone();
  14.             g1.ReleaseHdc(hdc1);
  15.             g2.ReleaseHdc(hdc2);
  16.             g1.Dispose();
  17.             g2.Dispose();
  18.             return b;
  19.         }

但是我们还是错了,不过这次得到的不是一个透明的图片,而是你截取的屏幕上的从左上开始的rect大小的截屏图片。

 

由上我们可以看出来,bitblt方法只能截取已经显示在控件上的图片。而不能截取内存中的图片。

我们可以从一个PICTUREBOX框里取出一部分图片填充到另一个PICTUREBOX框。

你可能感兴趣的:(api,vb)