2013-06-04 3 views
0

Я пытаюсь использовать BitBlt, чтобы получить области графики и сохранить их в растровых изображениях. Но здесь, я что-то легче понять мою проблему:C# gdi32 bitblt ничего не делает

 Bitmap sourceBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb); 
     Graphics sourceGraphics = Graphics.FromImage(sourceBitmap); 

     Bitmap destBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb); 
     Graphics destGraphics = Graphics.FromImage(destBitmap); 

     sourceGraphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(0, 0, 30, 30)); 
     sourceGraphics.FillRectangle(new SolidBrush(Color.Green), new Rectangle(30, 30, 30, 30)); 

     destGraphics.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(0, 0, 30, 30)); 
     destGraphics.FillRectangle(new SolidBrush(Color.Yellow), new Rectangle(30, 30, 30, 30)); 

     IntPtr destDC = destGraphics.GetHdc(); 
     IntPtr destHB = destBitmap.GetHbitmap(); 
     IntPtr old = SelectObject(destDC, destHB); 

     IntPtr sourceDC = sourceGraphics.GetHdc(); 
     IntPtr sourceHB = sourceBitmap.GetHbitmap(); 
     old = SelectObject(sourceDC, sourceHB); 

     int success = BitBlt(
      destDC, 0, 0, 64, 64, sourceDC, 0, 0, 0x00CC0020 
     ); 

Почему после того, как BitBlt моего destBitmap содержит синий/желтый прямоугольник (начальный точечный рисунок в пункте назначения) вместо красного/зеленого прямоугольники, которые должны были быть выведены из исходное растровое изображение?

Импорта делается так:

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] 
    private static extern int BitBlt(
     IntPtr hdcDest,  // handle to destination DC (device context) 
     int nXDest,   // x-coord of destination upper-left corner 
     int nYDest,   // y-coord of destination upper-left corner 
     int nWidth,   // width of destination rectangle 
     int nHeight,  // height of destination rectangle 
     IntPtr hdcSrc,  // handle to source DC 
     int nXSrc,   // x-coordinate of source upper-left corner 
     int nYSrc,   // y-coordinate of source upper-left corner 
     System.Int32 dwRop // raster operation code 
    ); 

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] 
    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj); 

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] 
    public static extern void DeleteObject(IntPtr obj); 

И, наконец, очистки коды и растровые потоковые видеть содержимое растрового:

 DeleteObject(destHB); 
     DeleteObject(sourceHB); 
     destGraphics.ReleaseHdc(); 
     sourceGraphics.ReleaseHdc(); 

     string path = "c:/tmp/dest.png"; 
     destBitmap.Save(path); 
+0

Поскольку вы, очевидно, используете WinForms и пишете код на C#, почему вам нужно p/вызвать функции GDI? Что не так с использованием функций GDI +, завершенных классом 'Graphics'? Намного легче, труднее ошибиться. –

+0

@CodyGray Также медленнее. – Rotem

+0

Вот только пример, который можно сделать в чистом C#, но как я могу извлечь область графики в растровое изображение? И BTW теперь я хотел бы понять, почему это не работает :) – mat

ответ

0

Нашел комбинацию, которая работает ... но я не понять, почему (определенно не эксперт GDI):

BitBlt() across Managed Bitmaps

Я добавил в вызовы для создания совместимых контроллеров домена с помощью CreateCompatibleDC().

Но отметить, что в фактическом вызове BitBlt(), я до сих пор использую оригинальный DC «destDC» для назначения постоянного тока (не новый «destCDC»), но новая совместимый DC «sourceCDC» для источника DC. Казалось, что никакой другой комбо не работал. Я до сих пор, однако , пришлось создать совместимый DC для назначения, даже если я не использовал его в (вызов BitBlt):

private const int SRCCOPY = 0xCC0020; 

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] 
    private static extern int BitBlt(
     IntPtr hdcDest,  // handle to destination DC (device context) 
     int nXDest,   // x-coord of destination upper-left corner 
     int nYDest,   // y-coord of destination upper-left corner 
     int nWidth,   // width of destination rectangle 
     int nHeight,  // height of destination rectangle 
     IntPtr hdcSrc,  // handle to source DC 
     int nXSrc,   // x-coordinate of source upper-left corner 
     int nYSrc,   // y-coordinate of source upper-left corner 
     int dwRop // raster operation code 
    ); 

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] 
    public static extern IntPtr CreateCompatibleDC(IntPtr hdc); 

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] 
    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj); 

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] 
    public static extern void DeleteObject(IntPtr obj); 

    private void button1_Click(object sender, EventArgs e) 
    { 
     Bitmap sourceBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb); 
     Graphics sourceGraphics = Graphics.FromImage(sourceBitmap); 

     Bitmap destBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb); 
     Graphics destGraphics = Graphics.FromImage(destBitmap); 

     sourceGraphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(0, 0, 30, 30)); 
     sourceGraphics.FillRectangle(new SolidBrush(Color.Green), new Rectangle(30, 30, 30, 30)); 

     destGraphics.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(0, 0, 30, 30)); 
     destGraphics.FillRectangle(new SolidBrush(Color.Yellow), new Rectangle(30, 30, 30, 30)); 

     IntPtr destDC = destGraphics.GetHdc(); 
     IntPtr destCDC = CreateCompatibleDC(destDC); 
     IntPtr destHB = destBitmap.GetHbitmap(); 
     IntPtr oldDest = SelectObject(destCDC, destHB); 

     IntPtr sourceDC = sourceGraphics.GetHdc(); 
     IntPtr sourceCDC = CreateCompatibleDC(sourceDC); 
     IntPtr sourceHB = sourceBitmap.GetHbitmap(); 
     IntPtr oldSource = SelectObject(sourceCDC, sourceHB); 

     int success = BitBlt(
      destDC, 0, 0, 64, 64, sourceCDC, 0, 0, SRCCOPY 
     ); 

     SelectObject(destCDC, oldDest); 
     SelectObject(sourceCDC, oldSource); 

     DeleteObject(destCDC); 
     DeleteObject(sourceCDC); 

     DeleteObject(destHB); 
     DeleteObject(sourceHB); 

     destGraphics.ReleaseHdc(); 
     sourceGraphics.ReleaseHdc(); 

     pictureBox1.Image = sourceBitmap; 
     pictureBox2.Image = destBitmap; 
    } 

Кто-нибудь есть какие-либо понять, почему это комбо работает ?. ..

+0

Большое спасибо, немного волшебства здесь:) Ожидание информации. Я думал, что Graphics.FromImage уже создает совместимый dc. – mat

Смежные вопросы