Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用位图中的锁定位扫描白色像素,然后将所有非白色像素写入新位图?_C#_.net_Winforms - Fatal编程技术网

C# 如何使用位图中的锁定位扫描白色像素,然后将所有非白色像素写入新位图?

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

这是我在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 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");
}