Работа с изображениями: поворот растрового изображения (C++/GDI+)

Я трачу много времени, пытаясь найти решение, но не могу. Я надеюсь, что вы можете мне помочь. Код немного длиннее, поэтому я привожу здесь только ту часть, где у меня возникла проблема. Мой код захватывает растровое изображение из окна и сохраняет его в HBitmap. Мне нужно сделать поворот растрового изображения. Поэтому я запускаю GDI+ и создаю растровое изображение pBitmap из HBitmap:

// INIT GDI
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if (!gdiplusToken) return 3;

// Gdip_GetRotatedDimensions:
GpBitmap* pBitmap;
int result = Gdiplus::DllExports::GdipCreateBitmapFromHBITMAP(HBitmap, 0, &pBitmap);

Затем я вычисляю переменные, необходимые для вращения. Затем я создаю графический объект и пытаюсь повернуть изображение:

GpGraphics * pG;
result = Gdiplus::DllExports::GdipGetImageGraphicsContext(pBitmap, &pG);
Gdiplus::SmoothingMode smooth = SmoothingModeHighQuality;
result = Gdiplus::DllExports::GdipSetSmoothingMode(pG, smooth);
Gdiplus::InterpolationMode interpolation = InterpolationModeNearestNeighbor;
result = Gdiplus::DllExports::GdipSetInterpolationMode(pG, interpolation);
MatrixOrder MatrixOrder_ = MatrixOrderPrepend;
result = Gdiplus::DllExports::GdipTranslateWorldTransform(pG, xTranslation, yTranslation, MatrixOrder_);
MatrixOrder_ = MatrixOrderPrepend;
result = Gdiplus::DllExports::GdipRotateWorldTransform(pG, ROTATION_ANGLE, MatrixOrder_);
GpImageAttributes * ImgAttributes;
result = Gdiplus::DllExports::GdipCreateImageAttributes(&ImgAttributes); // create an ImageAttribute object
result = Gdiplus::DllExports::GdipDrawImageRectRect(pG,pBitmap,0,0,w,h,0,0,w,h,UnitPixel,ImgAttributes,0,0);  // Draw the original image onto the new bitmap
result = Gdiplus::DllExports::GdipDisposeImageAttributes(ImgAttributes);

Наконец, я хотел проверить изображение, поэтому я добавил:

CLSID pngClsid; 
GetEncoderClsid(L"image/png", &pngClsid);
result = Gdiplus::DllExports::GdipCreateBitmapFromGraphics(w, h, pG, &pBitmap);
result = Gdiplus::DllExports::GdipSaveImageToFile(pBitmap, L"justest.png", &pngClsid, NULL);  // last voluntary? GDIPCONST EncoderParameters* encoderParams

Но мое изображение пусто. Я обнаружил, что GdipCreateBitmapFromGraphics создает пустое изображение, но как мне закончить его, чтобы проверить, какие рисунки я сделал? Являются ли эти шаги правильными (не только здесь, но и выше, рядом с GdipCreateBitmapFromHBITMAP() и GdipGetImageGraphicsContext() или мне нужно что-то добавить? Как заставить это работать?

PS: я уверен, что HBitmap содержит изображение окна, я уже проверял это.

1 ответ

На мой взгляд, у вас есть некоторые вещи назад в вашем подходе. Что вам нужно сделать, это следующее:

  1. Читайте в вашем изображении (SRC)
  2. Найдите минимальный ограничивающий прямоугольник, который будет содержать повернутое изображение (т. Е. Поверните углы, а расстояние между min и max x и y являются размерами.
  3. Создайте новый объект Image с этими размерами и желаемым форматом пикселей (вероятно, такой же, как у src, но, возможно, вам нужен альфа-канал) и нужным цветом фона (dst).
  4. Создать графику на основе dst (new Graphics(dst))
  5. Установите соответствующее преобразование на графике
  6. Draw Src на DST
  7. Экспорт DST

Хорошей новостью является то, что чтобы убедиться, что вы все делаете правильно, вы можете изолировать шаги. Например, вы можете просто сделать изображение и графику и нарисовать на нем линию без преобразования (или лучше с полем X) и сохранить это. Если у вас есть то, что вы ожидаете, то вы на правильном пути. Затем добавьте преобразование в поле. В вашем случае вам понадобится как ротация, так и перевод. Затем получите размеры изображения dest для этого поворота (подсказка: не используйте квадрат для проверки). Наконец, сделайте это с вашим реальным изображением.

Это поможет вам шаг за шагом к правильному выводу вместо того, чтобы пытаться получить все это за один выстрел.

Другие вопросы по тегам