C# WinForm 使用多种方法实现 图片的切割和拼接
1、通过拷贝像素 实现图片的切割和拼接
来自:百度空间http://hi.baidu.com/%B2%E8%B6%E0%B7%D3%BB%BC%D5%DF/blog/item/051081c7df4c5c069c163da6.html
这种方法我不想试了,效率太低了
try
{
int count = myarray.Count;//动态数据,保存所有图片的Top和Left,以及最大点的坐标
int width = (((int)myarray[count - 2])/256+1)*256;//使动态生成的图片长和宽式256的整数倍
int height = (((int)myarray[count - 1])/256+1)*256;
Bitmap newBitmap = new Bitmap(width,height);
Color pixel;
int width1 = 0, height1 = 0;
for (int j = 0; j <(count-2)/2; j++)
{
Bitmap oldBitmap=(Bitmap)((PictureBox)this.Controls.Find("newpicturebox"+j, true)[0]).Image;
width1 = ((PictureBox)this.Controls.Find("newpicturebox"+j, true)[0]).Image.Width;
height1 = ((PictureBox)this.Controls.Find("newpicturebox"+j, true)[0]).Image.Height;
int px =Convert.ToInt16(myarray[j*2]);// ((PictureBox)this.Controls.Find("newpicturebox" + j, true)[0]).Location.X;
int py=Convert.ToInt16(myarray[j*2+1]);//((PictureBox)this.Controls.Find("newpicturebox"+j, true)[0]).Location.Y;
for(int p=0;p<width1;p++)
for (int q=0; q<height1; q++)
{
pixel = oldBitmap.GetPixel(p,q);
newBitmap.SetPixel(px+p,py+q, pixel);
}
}
Clear();
this.pictureBox1.Size = new Size(width,height);
this.pictureBox1.Image = newBitmap;
newBitmap.Save(DirectoryInfoPath+"00.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "信息提示");
}
图片切割:
int width2 = this.pictureBox1.Width;
int height2 = this.pictureBox1.Height;
Bitmap newBitmap = new Bitmap(256, 256);
Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image;
Color pixel;
for (int i = 0; i <width2 / 256; i++)
for (int j = 0; j < height2 / 256; j++)
{
for (int p =i * 256; p < i * 256 + 256; p++)
for (int q = i * 256; q < j * 256 + 256; q++)
{
pixel = oldBitmap.GetPixel(p, q);
newBitmap.SetPixel(p%256,q%256, pixel);
}
newBitmap.Save(DirectoryInfoPath +"新"+i+j+ ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
2、使用Graphics类中的DrawImage方法,实现图片的拼接Graphics draw;
来自:博客园http://www.cnblogs.com/youwang/archive/2011/12/22/2298594.html
private Image JoinImage(List imageList, JoinMode jm) { //图片列表 if (imageList.Count <= 0) return null; if (jm == JoinMode.Horizontal) { //横向拼接 int width = 0; //计算总长度 foreach (Image i in imageList) { width += i.Width; } //高度不变 int height = imageList.Max(x => x.Height); //构造最终的图片白板 Bitmap tableChartImage = new Bitmap(width, height); Graphics graph = Graphics.FromImage(tableChartImage); //初始化这个大图 graph.DrawImage(tableChartImage, width, height); //初始化当前宽 int currentWidth = 0; foreach (Image i in imageList) { //拼图 graph.DrawImage(i, currentWidth, 0); //拼接改图后,当前宽度 currentWidth += i.Width; } return tableChartImage; } else if (jm == JoinMode.Vertical) { //纵向拼接 int height = 0; //计算总长度 foreach (Image i in imageList) { height += i.Height; } //宽度不变 int width = imageList.Max(x => x.Width); //构造最终的图片白板 Bitmap tableChartImage = new Bitmap(width, height); Graphics graph = Graphics.FromImage(tableChartImage); //初始化这个大图 graph.DrawImage(tableChartImage, width, height); //初始化当前宽 int currentHeight = 0; foreach (Image i in imageList) { //拼图 graph.DrawImage(i, 0, currentHeight); //拼接改图后,当前宽度 currentHeight += i.Height; } return tableChartImage; } else { return null; } }也做了一个很简陋的图像界面,如下图所示:
3、使用[API-BitBlt]
(1)、声明API
#region Win32API [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] private static extern bool BitBlt( IntPtr hdcDest, // 目标 DC的句柄 int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, // 源DC的句柄 int nXSrc, int nYSrc, System.Int32 dwRop // 光栅的处理数值 ); [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] private static extern bool DeleteObject(IntPtr hdc); [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject); #endregion
(2)、函数
const int SRCCOPY = 0x00CC0020; public bool CutPictrueToStream(Bitmap BmpSource) { Graphics grSource = Graphics.FromImage(BmpSource); Bitmap Bitmap_cutted = new Bitmap(SizeX, SizeY, grSource); IntPtr hdcTarget = IntPtr.Zero; IntPtr hdcSource = IntPtr.Zero; IntPtr hBitmapSource = IntPtr.Zero; IntPtr hOldObject = IntPtr.Zero; hBitmapSource = BmpSource.GetHbitmap(); MemorySource = new MemoryStream[ClassCount][][]; for (int i = 0; i < ClassCount; i++) { MemorySource[i] = new MemoryStream[DirectionCount][]; for (int j = 0; j < DirectionCount; j++) { MemorySource[i][j] = new MemoryStream[Frames[i]]; for (int k = 0; k < Frames[i]; k++) { Graphics grTarget = Graphics.FromImage(Bitmap_cutted); hdcTarget = grTarget.GetHdc(); hdcSource = grSource.GetHdc(); hOldObject = SelectObject(hdcSource, hBitmapSource); BitBlt(hdcTarget, 0, 0, SizeX, SizeY, hdcSource, (i * Frames[i] + k) * SizeX, j * SizeY, SRCCOPY); //必须释放DC,否则保存为黑图 if (hdcTarget != IntPtr.Zero) { grTarget.ReleaseHdc(hdcTarget); } if (hdcSource != IntPtr.Zero) { grSource.ReleaseHdc(hdcSource); } Bitmap_cutted.MakeTransparent();//保存为透明背景 Bitmap_cutted.Save(@"F:\Project\VS 2008\C#\(十一)地图遮罩层的实现\(十一)地图遮罩层的实现\Player\" + i.ToString() + "_" + j.ToString() + "_" + k.ToString() + ".Png",ImageFormat.Png); // MemorySource[i][j][k] = new MemoryStream(); // Bitmap_cutted.Save(MemorySource[i][j][k], ImageFormat.Png); grTarget.Dispose(); } } } if (hOldObject != IntPtr.Zero) SelectObject(hdcSource, hOldObject); if (hBitmapSource != IntPtr.Zero) DeleteObject(hBitmapSource); grSource.Dispose(); Bitmap_cutted.Dispose(); return true; }
(3)效果