2011-10-08 110 views
2

什么是从位图获取像素列的最快方法? 我不考虑两个循环,因为它可能需要很长时间。任何想法我都会很感激。谢谢!什么是获取像素的位图列的最佳和快速的方法?

+0

你只想得到一个像素阵列在图中单个列? –

+0

@ChrisTaylor无论如何,但它必须是与像素的像素列,像上面:)哇,如此之快 – deadfish

回答

3

我会建议您的位图转换成使用下面的代码的字节数组:

Bitmpa myImage=new Bitmap("myImage.bmp");  

BitmapData bmpData1=myImage.LockBits(new Rectangle(0,0,myImage.Width,myImage.Height), 
       System.Drawing.Imaging.ImageLockMode.ReadWrite, myImage.PixelFormat); 
byte[] myImageData = new byte[bmpData1.Stride * bmpData1.Height]; 
System.Runtime.InteropServices.Marshal.Copy(bmpData1.Scan0,myImageData,0 
         ,myImageData.Length); 
myImgage.UnlockBits(bmpData1); 

然后就很容易获取你想要的列的像素。只需循环遍历矢量myImageData,其步长等于每行像素数*每像素的字节数。

只要注意每个像素的字节数就可以用来表示位图。 这取决于PixelFormat

+0

当我列出所有像素的值是否可以改变它们并保存到新的位图?我研究了你的代码,我明白marshal.copy将值保存到字节数组中,对吗? – deadfish

+0

我发现它是可能的,只是改变字节数组中的元素,然后再次使用marschall副本。检查[库ms](http://msdn.microsoft.com/en-us/library/ms146625.aspx) – deadfish

+0

小提示:在第一行,“Bitmpa”应该是“位图” – Nic

2

假设你只需要一个列,以下例程应该可以帮到你。

首先这里是标准的解决方案采用可验证的C#代码

static Color[] GetPixelColumn(Bitmap bmp, int x) 
{ 
    Color[] pixelColumn = new Color[bmp.Height]; 
    for (int i = 0; i < bmp.Height; ++i) 
    { 
    pixelColumn[i] = bmp.GetPixel(x, i); 
    } 
    return pixelColumn; 
} 

这里是一个更快的替代方案,但是这需要您启用的C#编译器

static Color[] GetPixelColumnFast(Bitmap bmp, int x) 
{ 
    Color[] pixelColumn = new Color[bmp.Height]; 
    BitmapData pixelData = bmp.LockBits(
    new Rectangle(0, 0, bmp.Width, bmp.Height), 
    ImageLockMode.ReadOnly, 
    PixelFormat.Format32bppArgb); 
    unsafe 
    { 
    int* pData = (int*)pixelData.Scan0.ToPointer(); 
    pData += x; 
    for (int i = 0; i < bmp.Height; ++i) 
    { 
     pixelColumn[i] = Color.FromArgb(*pData); 
     pData += bmp.Width; 
    } 
    } 
    bmp.UnlockBits(pixelData); 

    return pixelColumn; 
} 

这两个函数将返回unsafe支持一个Color数组,其中包含位图中特定列的像素的颜色。

1

将其转换为字节数组

private static byte[, ,] BitmapToBytes(Bitmap bitmap) 
    { 
     BitmapData bitmapData = 
      bitmap.LockBits(new Rectangle(new Point(), bitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 
     byte[] bitmapBytes; 
     var stride = bitmapData.Stride; 
     try 
     { 
      int byteCount = bitmapData.Stride * bitmap.Height; 
      bitmapBytes = new byte[byteCount]; 
      Marshal.Copy(bitmapData.Scan0, bitmapBytes, 0, byteCount); 
     } 
     finally 
     { 
      bitmap.UnlockBits(bitmapData);     
     } 
     byte[, ,] result = new byte[3, bitmap.Width, bitmap.Height]; 
     for (int k = 0; k < 3; k++) 
     { 
      for (int i = 0; i < bitmap.Width; i++) 
      { 
       for (int j = 0; j < bitmap.Height; j++) 
       { 
        result[k, i, j] = bitmapBytes[j * stride + i * 3 + k]; 
       } 
      } 
     } 
     return result; 
    } 
+0

为什么我必须使用跨度?如果我想在图像上制作两个循环,其长度不会是100 .. – deadfish

+0

当我得到BitmapData时,我使用了PixelFormat.Format24bppRgb集,因此每个像素使用24位(每个像素使用8位,绿色和蓝色组件),但是行的大小可能不是像素大小的精确倍数,因为为了提高效率,系统将其打包在从四字节边界开始的行中,并且步幅是单行像素,四舍五入到四个字节的边界 – MishaU

+0

我在我的代码中发现错误:(我必须使用bitmapData.Stride而不是bitmap.Width * 3当我得到像素:result [k,i,j] = bitmapBytes [j * bitmapData.Stride + i * 3 + k]; – MishaU

相关问题