2016-08-16 89 views
1

我試圖用另一張圖像替換圖像塊,但我在Marshal.Copy(rgbValues, startIndx, desPtr, bytes)上得到System.ArgumentOutOfRangeException,就在我進入第二行時。我不明白爲什麼,因爲我是這個圖像處理的新手。這裏是我的代碼:如何用另一個圖像替換圖像中的塊?

public static void ReplaceImageBlock(Bitmap src, Bitmap des, int x, int y, int xParts, int yParts) 
    { 
     var srcRec = new Rectangle(0, 0, src.Width, src.Height); 
     BitmapData srcData = src.LockBits(srcRec, 
             ImageLockMode.ReadOnly,              src.PixelFormat); 

     var desRec = new Rectangle(x, y, src.Width, src.Height); 
     BitmapData desData = des.LockBits(desRec, ImageLockMode.WriteOnly, des.PixelFormat); 

     int srcStride = srcData.Stride; 
     IntPtr srcPtr = srcData.Scan0; 

     int desStride = desData.Stride; 
     IntPtr desPtr = desData.Scan0; 



     int bytes = 3 * xParts; 
     var rgbIndex = 0; 

     //actual pixel values 
     int width = 3 * xParts; //3 bytes by xParts 
     int height = yParts; 

     var rgbValues = new byte[bytes]; 

     // Populate rgbValues with src image 
     unsafe 
     { 
      byte* p = (byte*)(void*)srcPtr; 

      for (int i = 0; i < height; i++) 
      { 
       for (int j = 0; j < width; j++) 
       { 
        int index = (i * srcStride) + j; 
        rgbValues[rgbIndex++] = p[index]; 
       } 
       rgbIndex = 0; // reset index 
       var startIndx = (i * desStride) + x; 


       Marshal.Copy(rgbValues, startIndx, desPtr, bytes);//copy to destination block 
      } 
     } 
    } 
+0

'startIndx'可以被計算錯了要簡單得多? – TW80000

+0

你使用3個字節的像素,但你確定位圖格式是RGB而不是RGBA? – Aybe

+0

@Aybe,我該如何檢查格式?我的圖像屬性說比特深度是24. @TW我在'startIndex'上會做錯什麼? –

回答

1

下面是一些接受任何格式代碼:

using System; 
using System.Drawing; 
using System.Drawing.Imaging; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      var bitmap1 = new Bitmap(@"..\..\untitled.png"); 
      var bitmap2 = new Bitmap(256, 256, bitmap1.PixelFormat); 
      CopyRegion(bitmap1, new Rectangle(0, 0, 100, 100), bitmap2, new Point(99, 99)); 
      bitmap2.Save("result.png"); 
     } 

     private unsafe void CopyRegion(Bitmap src, Rectangle srcRect, Bitmap tgt, Point tgtPoint) 
     { 
      // TODO extra checks etc ... 

      if (src == null) throw new ArgumentNullException(nameof(src)); 
      if (tgt == null) throw new ArgumentNullException(nameof(tgt)); 

      if (tgt.PixelFormat != src.PixelFormat) 
       throw new ArgumentOutOfRangeException(nameof(tgt)); 

      var tgtRect = new Rectangle(Point.Empty, tgt.Size); 
      var rect = new Rectangle(tgtPoint, srcRect.Size); 
      if (!tgtRect.Contains(rect)) 
       throw new ArgumentOutOfRangeException(nameof(tgtPoint)); 

      var d1 = src.LockBits(srcRect, ImageLockMode.ReadOnly, src.PixelFormat); 
      var d2 = tgt.LockBits(tgtRect, ImageLockMode.WriteOnly, tgt.PixelFormat); 

      int bitsPerPixel; 
      switch (src.PixelFormat) 
      { 
       case PixelFormat.Format24bppRgb: 
        bitsPerPixel = 24; 
        break; 
       case PixelFormat.Format32bppPArgb: 
        bitsPerPixel = 32; 
        break; 
       case PixelFormat.Format32bppRgb: 
        bitsPerPixel = 32; 
        break; 
       default: 
        throw new ArgumentOutOfRangeException(); 
      } 

      var cols = srcRect.Width; 
      var rows = srcRect.Height; 
      var bytesPerPixel = (bitsPerPixel + 7)/8; 
      var bytes = cols*bytesPerPixel; 
      var p1 = d1.Scan0; 
      var p2 = d2.Scan0; 
      var s1 = d1.Stride; 
      var s2 = d2.Stride; 
      var x1 = srcRect.X; 
      var x2 = tgtPoint.X; 
      var y1 = srcRect.Y; 
      var y2 = tgtPoint.Y; 
      for (var y = 0; y < rows; y++) 
      { 
       var b1 = (byte*) (p1 + (s1*(y1 + y) + x1*bytesPerPixel)); 
       var b2 = (byte*) (p2 + (s2*(y2 + y) + x2*bytesPerPixel)); 
       for (var x = 0; x < bytes; x++) 
       { 
        *b2 = *b1; 
        b1++; 
        b2++; 
       } 
      } 

      src.UnlockBits(d1); 
      tgt.UnlockBits(d2); 
     } 
    } 
} 

結果:

enter image description here

enter image description here

編輯

這原來是到底:)

How to crop an image using C#?

+0

運行你的方法我可以看到我調整大小的圖像現在有32bpp。我正在使用此http://stackoverflow.com/a/24199315/852243進行調整大小。 –

相關問題