嗨我有一个bmp
加载到BMP
对象,我需要将像素作为上面的图像从(1,1)
像素到(100,100)
px。使用getpixel()
方法。我使用的是 ONE 循环但是没有成功。
如果我使用多维数组的概念应该是什么变量值?
答案 0 :(得分:47)
当您想要进行图像处理时 在巨大的图像上GetPixel()方法需要很长时间 但我认为我的算法需要更少 例如,时间比其他答案 你可以在800 * 600上测试这段代码 像素图像。
Bitmap bmp = new Bitmap("SomeImage");
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = bmpData.Stride * bmp.Height;
byte[] rgbValues = new byte[bytes];
byte[] r = new byte[bytes / 3];
byte[] g = new byte[bytes / 3];
byte[] b = new byte[bytes / 3];
// Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, bytes);
int count = 0;
int stride = bmpData.Stride;
for (int column = 0; column < bmpData.Height; column++)
{
for (int row = 0; row < bmpData.Width; row++)
{
b[count] = (byte)(rgbValues[(column * stride) + (row * 3)]);
g[count] = (byte)(rgbValues[(column * stride) + (row * 3) + 1]);
r[count++] = (byte)(rgbValues[(column * stride) + (row * 3) + 2]);
}
}
答案 1 :(得分:8)
如果你想在一个循环中右移,左移,右移......,这样就可以了:
for (int i = 0 ; i < bmp.Height * bmp.Width; ++i) {
int row = i / bmp.Height;
int col = i % bmp.Width;
if (row%2 != 0) col = bmp.Width - col-1;
var pixel = bmp.GetPixel(col, row);
}
答案 2 :(得分:7)
您需要使用两个循环:
for (int ii = 0; ii < 100; ii++)
{
for (int jj = 0; jj < 100; jj++)
{
Color pixelColor = bitmap.GetPixel(ii, jj);
// do stuff with pixelColor
}
}
答案 3 :(得分:6)
您使用Linq选择来获取IEnumerable对象:
var pixelColors =
from x in Enumerable.Range(0, bmp.Width - 1)
from y in Enumerable.Range(0, bmp.Height - 1)
select bmp.GetPixel(x, y);
...然后迭代IEnumerable(使用隐式类型):
foreach(var color in pixelColors)
{
//do stuff on RGB values, etc...
}
答案 4 :(得分:5)
您可以将其转换为易于访问的多维颜色数组,如下所示:
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
// ...
Color[,] GetSection(Image img, Rectangle r) {
Color[,] r = new Color[r.Width, r.Height]; // Create an array of colors to return
using (Bitmap b = new Bitmap(img)) { // Turn the Image into a Bitmap
BitmapData bd = b.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format32BppArgb); // Lock the bitmap data
int[] arr = new int[b.Width * b.Height - 1]; // Create an array to hold the bitmap's data
Marshal.Copy(b.Scan0, arr, 0, arr.Length); // Copy over the data
b.UnlockBits(bd); // Unlock the bitmap
for (int i = 0; i < arr.Length; i++) {
r[i % r.Width, i / r.Width] = Color.FromArgb(arr[i]); // Copy over into a Color structure
}
}
return r; // Return the result
}
你会这样称呼它:
Color[,] c = GetSection(myImage, new Rectangle(0, 0, 100, 100)); // Get the upper-left 100x100 pixel block in the image myImage
for (int x = 0; x < c.GetUpperBound(0); x++) {
for (int y = 0; y < c.GetUpperBound(1); y++) {
Color thePixel = c[x, y];
// do something with the color
}
}
你可以在你想要的任何方向上快速遍历返回的阵列。
答案 5 :(得分:4)
虽然两个嵌套循环方法通常“更好”或更具可读性,但您可以在1循环中执行此操作:
for(int i = 0; i < bmp.Height * bmp.Width; i++)
{
int row = i / bmp.Width;
int col = i % bmp.Width;
var pixel = bmp.GetPixel(col, row);
}
或稍好一点,将第一行更改为:
var numberOfPixels = bmp.Height * bmp.Width;
for(int i = 0; i < numberOfPixels; i++)
答案 6 :(得分:4)
您可以尝试这样的事情
for(int y = 0; y < bmp.Height; y++)
{
var even = y % 2 == 0;
var startX = even ? 0 : bmp.Width - 1;
var endX = even ? bmp.Width : -1;
var delta = even ? 1 : -1;
for(int x = startX; x != endX; x += delta)
{
var pixel = bmp.GetPixel(x,y);
}
}
或者您可以将内部循环拆分为:从左到右和从右到左
for(int y = 0; y < bmp.Height; y += 2)
{
for(int x = 0; x < bmp.Width; x++)
{
var pixel = bmp.GetPixel(x,y);
}
var line = y + 1;
if(line < bmp.Height)
{
for(int x = bmp.Width; x >= 0; --x)
{
var pixel = bmp.GetPixel(x,line);
}
}
}