我如何将rgbvalues 0和255的位图数组转换为0和1的2d int数组
本文关键字:数组 转换 int 2d rgbvalues 位图 | 更新日期: 2023-09-27 18:17:44
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace ConvertBitmapToArray
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Bitmap bitmap = new Bitmap(@"C:'Temp'Gimp Maps'Bitmaps'test1.bmp");
CreateArray(bitmap);
File.Create(@"C:'Temp'Gimp Maps'Maps.cs");
}
private void CreateArray(Bitmap bmp)
{
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bmp.UnlockBits(bmpData);
for (int i = 0; i < rgbValues.Count(); i++)
{
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
我有一个黑白位图,大小为8x8或800x800,我得到rgbValues数组。现在在循环中:
for (int i = 0; i < rgbValues.Count(); i++)
{
}
我想创建一个2d的int数组,由0和1组成。例如:
int[,] map = new int[,]
{
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{1,1,1,1,0,0,0,0,},
{0,0,0,1,0,0,0,0,},
{0,0,1,1,0,0,0,0,},
{0,0,0,0,1,1,1,0,},
{0,0,0,0,0,0,0,1,},
};
255等于0 0等于1。在int数组的例子中,1是黑色,0是白色。
我试过了:
private void CreateArray(Bitmap bmp)
{
int[] pix = new int[bmp.Width*bmp.Height];
int x, y, rgb, val;
for (y = 0; y < bmp.Height; y++)
{
for (x = 0; x < bmp.Width; x++)
{
Color c = bmp.GetPixel(x, y);
rgb = c.ToArgb();
if (rgb == 0xff000000) // if black
{
val = 0;
}
else
val = 1;
pix[y * bmp.Width + x] = val;
}
}
}
但它不是很好,我不确定颜色c和rgb = c. toargb ();
在if条件下,我得到了绿行:
警告1与积分常数的比较是无用的;该常量在类型'int'
的范围之外。我怎么能做到这一点与LockBits或与GetPixel ?我想知道使用每种方法有什么不同。
这是我目前所做的:
private void CreateArray(Bitmap bmp)
{
int[,] array = new int[,]
{
};
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[bytes];
int x, y, rgb, val;
for (y = 0; y < bmp.Height; y++)
{
for (x = 0; x < bmp.Width; x++)
{
var row = ptr + (y * bmpData.Stride);
var pixel = row + x * ; // bpp will be 4 in your case
// A bit=0
// R bit=1
// G bit=2
// B bit=3
// (depending on your image pixel format)
for (var bit = 0; bit < bpp; bit++)
{
var pixelComponent = pixel[bit];
}
}
}
}
要以更合乎逻辑的方式循环图像的字节,请将unsafe
关键字添加到函数签名(private unsafe void ...
)中,并确保通过项目属性启用unsafe
代码。
var pt = (byte*)bmpData.Scan0;
现在可以很容易地遍历x和y:
var row = pt + (y * bmpData.Stride);
var pixel = row + x * bpp; // bpp will be 4 in your case
// A bit=0
// R bit=1
// G bit=2
// B bit=3
// (depending on your image pixel format)
for (var bit = 0; bit < bpp; bit++)
{
var pixelComponent = pixel[bit];
}
如果您真的希望最终结果为二维数组,您应该使用[,]
或[][]
而不是[]
(单维数组)
LockBits
方法与GetPixel
方法之间的巨大差异是性能。GetPixel
实际上锁定了比特,检索单个像素并再次解锁比特-这意味着在多次重复执行时性能很差。
编辑
下面是一个完整的代码:
private unsafe void CreateArray(Bitmap bmp)
{
// Note that is it somewhat a standard
// to define 2d array access by [y,x] (not [x,y])
bool[,] bwValues = new bool[bmp.Height, bmp.Width];
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat);
// Get the address of the first line.
byte* ptr = (byte*)bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
for (int y = 0; y < bmp.Height; y++)
{
var row = ptr + (y * bmpData.Stride);
for (int x = 0; x < bmp.Width; x++)
{
var pixel = row + x * 4; // ARGB has 4 bytes per pixel
// A bit=0
// R bit=1
// G bit=2
// B bit=3
// (depending on your image pixel format)
// Check if A = R = G = B = 255 (meaning the pixel is white)
bool isWhite = (pixel[0] == 255 &&
pixel[1] == 255 &&
pixel[2] == 255 &&
pixel[3] == 255);
// Assume that anything that isn't white is black
bwValues[y, x] = isWhite;
}
}
// Do whatever you want with vwValues here
}