C# 如何使用位图中的锁定位扫描白色像素,然后将所有非白色像素写入新位图?
这是我在form1构造函数中所做的:C# 如何使用位图中的锁定位扫描白色像素,然后将所有非白色像素写入新位图?,c#,.net,winforms,C#,.net,Winforms,这是我在form1构造函数中所做的: Bitmap bmp2 = new Bitmap(@"e:\result1001.jpg"); CropImageWhiteAreas.ImageTrim(bmp2); bmp2.Save(@"e:\result1002.jpg"); bmp2.Dispose(); CropImageWhiteAreas类: using System; using System.Collections.Generic; using System.Linq; using S
Bitmap bmp2 = new Bitmap(@"e:\result1001.jpg");
CropImageWhiteAreas.ImageTrim(bmp2);
bmp2.Save(@"e:\result1002.jpg");
bmp2.Dispose();
CropImageWhiteAreas类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace Test
{
class CropImageWhiteAreas
{
public static Bitmap ImageTrim(Bitmap img)
{
//get image data
BitmapData bd = img.LockBits(new Rectangle(Point.Empty, img.Size),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int[] rgbValues = new int[img.Height * img.Width];
Marshal.Copy(bd.Scan0, rgbValues, 0, rgbValues.Length);
img.UnlockBits(bd);
#region determine bounds
int left = bd.Width;
int top = bd.Height;
int right = 0;
int bottom = 0;
//determine top
for (int i = 0; i < rgbValues.Length; i++)
{
int color = rgbValues[i] & 0xffffff;
if (color != 0xffffff)
{
int r = i / bd.Width;
int c = i % bd.Width;
if (left > c)
{
left = c;
}
if (right < c)
{
right = c;
}
bottom = r;
top = r;
break;
}
}
//determine bottom
for (int i = rgbValues.Length - 1; i >= 0; i--)
{
int color = rgbValues[i] & 0xffffff;
if (color != 0xffffff)
{
int r = i / bd.Width;
int c = i % bd.Width;
if (left > c)
{
left = c;
}
if (right < c)
{
right = c;
}
bottom = r;
break;
}
}
if (bottom > top)
{
for (int r = top + 1; r < bottom; r++)
{
//determine left
for (int c = 0; c < left; c++)
{
int color = rgbValues[r * bd.Width + c] & 0xffffff;
if (color != 0xffffff)
{
if (left > c)
{
left = c;
break;
}
}
}
//determine right
for (int c = bd.Width - 1; c > right; c--)
{
int color = rgbValues[r * bd.Width + c] & 0xffffff;
if (color != 0xffffff)
{
if (right < c)
{
right = c;
break;
}
}
}
}
}
int width = right - left + 1;
int height = bottom - top + 1;
#endregion
//copy image data
int[] imgData = new int[width * height];
for (int r = top; r <= bottom; r++)
{
Array.Copy(rgbValues, r * bd.Width + left, imgData, (r - top) * width, width);
}
//create new image
Bitmap newImage = new Bitmap(width, height, PixelFormat.Format32bppArgb);
BitmapData nbd
= newImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(imgData, 0, nbd.Scan0, imgData.Length);
newImage.UnlockBits(nbd);
return newImage;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用系统图;
使用系统、绘图、成像;
使用System.Runtime.InteropServices;
名称空间测试
{
CropImageWhiteAreas类
{
公共静态位图ImageTrim(位图img)
{
//获取图像数据
BitmapData bd=img.LockBits(新矩形(Point.Empty,img.Size),
ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
int[]rgbValues=新int[img.Height*img.Width];
Marshal.Copy(bd.Scan0,rgbvalue,0,rgbvalue.Length);
img.解锁位(bd);
#区域确定边界
int left=bd.宽度;
int top=bd.高度;
int right=0;
int-bottom=0;
//确定顶部
for(int i=0;ic)
{
左=c;
}
如果(右=0;i--)
{
int color=RGB值[i]&0xffffff;
如果(颜色!=0xffffff)
{
int r=i/bd.宽度;
int c=i%bd.宽度;
如果(左>c)
{
左=c;
}
如果(右顶部)
{
对于(int r=top+1;rc)
{
左=c;
打破
}
}
}
//确定权利
对于(int c=bd.Width-1;c>right;c--)
{
int color=rgb值[r*bd.Width+c]&0xffffff;
如果(颜色!=0xffffff)
{
如果(右 对于(int r=top;r,如果我理解正确,您已经找到了一个使用LockBits()
的示例代码段,但是您不确定它是如何工作的,或者如何修改它以满足您的特定需要。因此,我将尝试从这个角度回答
首先,一个粗略的猜测(因为在第一个示例中没有包含所使用的LockBitmap
类的实现)LockBitmap
类是一种助手类,它应该封装调用LockBits()
并使用结果的工作,包括提供GetPixel()的版本
和SetPixel()
这两种方法大概比直接在位图
对象上调用这些方法要快得多(即,通过调用LockBits()
访问缓冲区)
如果是这样,那么修改第一个示例以满足您的需要可能是最好的:
public void Change(Bitmap bmp)
{
Bitmap newBitmap = new Bitmap(bmp.Width, bmp.Height, bmp.PixelFormat);
LockBitmap source = new LockBitmap(bmp),
target = new LockBitmap(newBitmap);
source.LockBits();
target.LockBits();
Color white = Color.FromArgb(255, 255, 255, 255);
for (int y = 0; y < source.Height; y++)
{
for (int x = 0; x < source.Width; x++)
{
Color old = source.GetPixel(x, y);
if (old != white)
{
target.SetPixel(x, y, old);
}
}
}
source.UnlockBits();
target.UnlockBits();
newBitmap.Save("d:\\result.png");
}
上述内容将完全替换内部x
循环的主体
一个警告:请注意,当使用LockBits()时
approach,了解位图的像素格式至关重要。您所展示的示例假设位图为24 bpp格式。如果您自己的位图是这种格式,则无需更改任何内容。但如果位图的格式不同,则需要调整代码以适应这种格式。例如,如果您的位图为32 bpp格式,您需要将正确的PixelFormat
值传递给LockBits()
方法调用,然后将pixelSize
设置为4
,而不是像代码现在那样设置为3
编辑:
您已表示要裁剪新图像,使其成为包含所有非白色像素所需的最小尺寸。以下是上述第一个示例的一个版本,可以实现这一点:
public void Change(Bitmap bmp)
{
LockBitmap source = new LockBitmap(bmp);
source.LockBits();
Color white = Color.FromArgb(255, 255, 255, 255);
int minX = int.MaxValue, maxX = int.MinValue,
minY = int.MaxValue, maxY = int.MinValue;
// Brute-force scan of the bitmap to find image boundary
for (int y = 0; y < source.Height; y++)
{
for (int x = 0; x < source.Width; x++)
{
if (source.GetPixel(x, y) != white)
{
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
}
}
Bitmap newBitmap = new Bitmap(maxX - minx + 1, maxY - minY + 1, bmp.PixelFormat);
LockBitmap target = new LockBitmap(newBitmap);
target.LockBits();
for (int y = 0; y < target.Height; y++)
{
for (int x = 0; x < target.Width; x++)
{
target.SetPixel(x, y, source.GetPixel(x + minX, y + minY));
}
}
source.UnlockBits();
target.UnlockBits();
newBitmap.Save("d:\\result.png");
}
公共作废更改(位图bmp)
{
锁位图源=新的锁位图(bmp);
source.LockBits();
颜色白色=颜色。来自argb(255,255,255,255);
int minX=int.MaxValue,maxX=int.MinValue,
minY=int.MaxValue,maxY=int.MinValue;
//对位图进行暴力扫描以查找图像边界
对于(int y=0;ypublic void Change(Bitmap bmp)
{
LockBitmap source = new LockBitmap(bmp);
source.LockBits();
Color white = Color.FromArgb(255, 255, 255, 255);
int minX = int.MaxValue, maxX = int.MinValue,
minY = int.MaxValue, maxY = int.MinValue;
// Brute-force scan of the bitmap to find image boundary
for (int y = 0; y < source.Height; y++)
{
for (int x = 0; x < source.Width; x++)
{
if (source.GetPixel(x, y) != white)
{
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
}
}
Bitmap newBitmap = new Bitmap(maxX - minx + 1, maxY - minY + 1, bmp.PixelFormat);
LockBitmap target = new LockBitmap(newBitmap);
target.LockBits();
for (int y = 0; y < target.Height; y++)
{
for (int x = 0; x < target.Width; x++)
{
target.SetPixel(x, y, source.GetPixel(x + minX, y + minY));
}
}
source.UnlockBits();
target.UnlockBits();
newBitmap.Save("d:\\result.png");
}