C# StretchBlt для копирования между двумя растровыми изображениями ничего не рисуетC#

Место общения программистов C#
Anonymous
C# StretchBlt для копирования между двумя растровыми изображениями ничего не рисует

Сообщение Anonymous »

tl;dr;
Я пытаюсь использовать следующий код, чтобы скопировать и растянуть часть моего растрового изображения srcBmp в мой destBmp с помощью StretchBlt - он возвращает 1, что указывает на успех, но в целевом растровом изображении ничего не нарисовано...

Код: Выделить всё

    public static void StretchBltImage()
{
// create the source bitmap
var srcBmp = new Bitmap(500, 500, PixelFormat.Format32bppArgb);
var srcGfx = Graphics.FromImage(srcBmp);
srcGfx.Clear(Color.Green);
var srcHdc = srcGfx.GetHdc();

// create the target image
var destBmp = new Bitmap(200, 200, PixelFormat.Format32bppArgb);
using var destGfx = Graphics.FromImage(destBmp);
destGfx.Clear(Color.Gray);
var destHdc = destGfx.GetHdc();

var res1 = SetStretchBltMode(destHdc, STRETCH_HALFTONE);
var res2 = StretchBlt(destHdc, 75, 75, 50, 50, srcHdc, 0, 0, 100, 100, SRCCOPY);

srcGfx.ReleaseHdc(srcHdc);
destGfx.ReleaseHdc(destHdc);
destBmp.Save(".\\image.png");
}
Длинная версия
Я пишу приложение на C#, которое успешно использует StretchBlt для захвата (и сжатия) части рабочего стола в растровое изображение с помощью следующего (упрощенного) кода.
ConsoleApp1.csproj

Код: Выделить всё



Exe
net7.0-windows
enable
enable
true







Capture.cs

Код: Выделить всё

public static partial class Capture
{
[LibraryImport("user32")]
internal static partial nint GetDesktopWindow();

[LibraryImport("user32")]
internal static partial nint GetWindowDC(nint hWnd);

[LibraryImport("gdi32")]
internal static partial int SetStretchBltMode(
nint hdc,
int mode);

[LibraryImport("gdi32")]
internal static partial int StretchBlt(nint hdcDest, int xDest, int yDest, int  , int hDest, nint hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, int rop);

private const int BLACKNESS = 0x00000042;
private const int SRCCOPY = 0x00CC0020;
private const int STRETCH_HALFTONE = 4;

public static void StretchBltScreen()
{
// open the desktop handles
var srcHwnd = GetDesktopWindow();
var srcHdc = GetWindowDC(srcHwnd);

// create the target image
var destBmp = new Bitmap(200, 200, PixelFormat.Format32bppArgb);
using var destGfx = Graphics.FromImage(destBmp);
destGfx.Clear(Color.Gray);
var destHdc = destGfx.GetHdc();

var res1 = SetStretchBltMode(destHdc, STRETCH_HALFTONE);
var res2 = StretchBlt(destHdc, 75, 75, 50, 50, srcHdc, 0, 0, 100, 100, SRCCOPY);

destGfx.ReleaseHdc(destHdc);
destBmp.Save(".\\screen.png");
}
}
Кроме того: Причина, по которой я использую StretchBlt, заключается в том, что я копирую большую часть сверхширокого монитора (5120 x 1440) в маленькую миниатюру, поэтому я не хочу использовать Graphics.CopyFromScreen для копирования полноразмерного изображения и затем масштабирования его - я бы предпочел сделать это в один шаг с StretchBlt, так как это намного быстрее по сравнению с тем временем, которое я взял.

Итак, если я вызываю свой StretchBltScreen в основной программе, он работает и сохраняет изображение следующим образом:
Изображение

Однако сейчас я пытаюсь написать несколько модульных тестов, и мне бы хотелось выполнить StretchBlt со статическим растровым изображением в памяти, а не использовать текущий рабочий стол в качестве источника, но есть что-то не совсем правильно: StretchBlt возвращает 1, указывая на успех, но на целевом эскизе ничего не нарисовано.
Моя версия модульного теста выглядит как код вверху этого примера вопрос и в результате дает это изображение, ничего не взятое из исходного растрового изображения:
Изображение

Я почти уверен, что это как-то связано с контекстами устройств, совместимыми растровыми изображениями, DIB и т. д., и пробовал различные комбинации вызовов GDI, чтобы попытаться обойти эту проблему, но на данный момент Я немного застрял в том, куда идти дальше.
Если у кого-нибудь есть какие-либо идеи, я был бы очень благодарен...

Вернуться в «C#»