Работа с изображениями: поворот растрового изображения (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 ответ
На мой взгляд, у вас есть некоторые вещи назад в вашем подходе. Что вам нужно сделать, это следующее:
- Читайте в вашем изображении (SRC)
- Найдите минимальный ограничивающий прямоугольник, который будет содержать повернутое изображение (т. Е. Поверните углы, а расстояние между min и max x и y являются размерами.
- Создайте новый объект Image с этими размерами и желаемым форматом пикселей (вероятно, такой же, как у src, но, возможно, вам нужен альфа-канал) и нужным цветом фона (dst).
- Создать графику на основе dst (
new Graphics(dst)
) - Установите соответствующее преобразование на графике
- Draw Src на DST
- Экспорт DST
Хорошей новостью является то, что чтобы убедиться, что вы все делаете правильно, вы можете изолировать шаги. Например, вы можете просто сделать изображение и графику и нарисовать на нем линию без преобразования (или лучше с полем X) и сохранить это. Если у вас есть то, что вы ожидаете, то вы на правильном пути. Затем добавьте преобразование в поле. В вашем случае вам понадобится как ротация, так и перевод. Затем получите размеры изображения dest для этого поворота (подсказка: не используйте квадрат для проверки). Наконец, сделайте это с вашим реальным изображением.
Это поможет вам шаг за шагом к правильному выводу вместо того, чтобы пытаться получить все это за один выстрел.