2011-01-20 3 views
8

В настоящее время я пишу реализацию C# небольшой программы, которую я написал на Java.Получение массива RGB из изображения в C#

Я использовал BufferedImage.getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) функцию в своем приложении Java. Но я не мог точно найти версию этого в C#, и я не уверен, как писать его вручную.

ответ

16

Там не прямой эквивалент в .NET Framework с помощью этого метода. Однако, если ваше изображение является System.Drawing.Bitmap, вы можете вызвать метод LockBits, и это вернет структуру BitmapData, содержащую адрес первой строки сканирования. Затем вы можете использовать его для создания того, что должно быть совместимой с API оберткой. Я предполагаю, что вы используете C# 3.5 или выше, поэтому я использую метод расширения - если вы используете более старый вкус, измените это на обычный метод, сбросив «this» из аргумента битмапа:

public static void getRGB(this Bitmap image, int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) 
    { 
     const int PixelWidth = 3; 
     const PixelFormat PixelFormat = PixelFormat.Format24bppRgb; 

     // En garde! 
     if (image == null) throw new ArgumentNullException("image"); 
     if (rgbArray == null) throw new ArgumentNullException("rgbArray"); 
     if (startX < 0 || startX + w > image.Width) throw new ArgumentOutOfRangeException("startX"); 
     if (startY < 0 || startY + h > image.Height) throw new ArgumentOutOfRangeException("startY"); 
     if (w < 0 || w > scansize || w > image.Width) throw new ArgumentOutOfRangeException("w"); 
     if (h < 0 || (rgbArray.Length < offset + h * scansize) || h > image.Height) throw new ArgumentOutOfRangeException("h"); 

     BitmapData data = image.LockBits(new Rectangle(startX, startY, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat); 
     try 
     { 
      byte[] pixelData = new Byte[data.Stride]; 
      for (int scanline = 0; scanline < data.Height; scanline++) 
      { 
       Marshal.Copy(data.Scan0 + (scanline * data.Stride), pixelData, 0, data.Stride); 
       for (int pixeloffset = 0; pixeloffset < data.Width; pixeloffset++) 
       { 
        // PixelFormat.Format32bppRgb means the data is stored 
        // in memory as BGR. We want RGB, so we must do some 
        // bit-shuffling. 
        rgbArray[offset + (scanline * scansize) + pixeloffset] = 
         (pixelData[pixeloffset * PixelWidth + 2] << 16) + // R 
         (pixelData[pixeloffset * PixelWidth + 1] << 8) + // G 
         pixelData[pixeloffset * PixelWidth];    // B 
       } 
      } 
     } 
     finally 
     { 
      image.UnlockBits(data); 
     } 
    } 

Эта обертку теперь можно назвать так:

 Bitmap foo = Bitmap.FromFile(@"somefile.jpg") as Bitmap; 
     int[] rgbArray = new int[100]; 
     foo.getRGB(1, 1, 10, 10, rgbArray, 0, 10); 

Надеется, что это помогает, и добру пожаловать в .NET!

2

Я думаю, что ближайший из них - Bitmap.GetPixel(x,y), которые возвращают один пиксельный цвет в точке. Чтобы имитировать функцию java, вам нужно будет написать некоторую помощницу.

1

Это зависит от того, как быстро вам это нужно.

Bitmap имеет GetPixel() метод, который отлично подходит для пикселя.

Если вам нужно выполнить быструю обработку изображений, вам нужно использовать LockBits, который вы можете найти здесь.

Bitmap img = (Bitmap) Image.FromFile(imageFileName); 
BitmapData data = img.LockBits(new Rectangle(0,0,img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat); 
byte* ptr = (byte*) data.Scan0; 
for (int j = 0; j < data.Height; j++) 
{ 
    byte* scanPtr = ptr + (j * data.Stride); 
    for (int i = 0; i < data.width; i++, scanPtr+=NO_OF_CHANNELS) 
    { 
     for (int m = 0; m < NO_OF_CHANNELS; m++) 
      Console.WriteLine(*scanPtr); // value of each channel 
    } 
} 

img.UnlockBits(data); 
+0

@Lazarus Почему вы отредактировали мой отзыв? – Aliostad

+0

«Это зависит от того, как ** жиры ** вам нужно это сделать». Если вы предпочтете оставить свои орфографические ошибки, тогда вам просто нужно сказать. – Lazarus

+0

@Lazarus Нет проблем. По какой-то причине это также удалило мой код, который я вставил. Спасибо, что убрали мою орфографическую ошибку - я перепробовал мой код. – Aliostad

6

Вы должны использовать Bitmap.LockBits, чтобы получить прямой доступ к пикселям в растровом изображении. Вот пример реализации, она возвращает один ScanLine из переданного растрового изображения в качестве ИНТ []:

int[] getRGB(Bitmap bmp, int line) { 
     var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), 
      System.Drawing.Imaging.ImageLockMode.ReadOnly, 
      System.Drawing.Imaging.PixelFormat.Format32bppRgb); 
     try { 
      var ptr = (IntPtr)((long)data.Scan0 + data.Stride * (bmp.Height - line - 1)); 
      var ret = new int[bmp.Width]; 
      System.Runtime.InteropServices.Marshal.Copy(ptr, ret, 0, ret.Length * 4); 
      return ret; 
     } 
     finally { 
      bmp.UnlockBits(data); 
     } 
    } 
Смежные вопросы