Ответ 1
Если я правильно понял ваш вопрос, вы, по сути, хотите выработать новый размер изображения, когда он повернут, и как поместить повернутое изображение в него новым растровым изображением.
Диаграмма, надеюсь, поможет прояснить решение. Вот несколько псевдокодов:
sinVal = abs(sin(angle))
cosVal = abs(cos(angle))
newImgWidth = sinVal * oldImgHeight + cosVal * oldImgWidth
newImgHeight = sinVal * oldImgWidth + cosVal * oldImgHeight
originX = 0
originY = sinVal * oldImgWidth
Вы хотите сделать новое изображение из newImgWidth и newImgHeight, а затем выполнить поворот вокруг начала координат (originX, originY), а затем визуализировать изображение до этой точки. Это будет падать, если угол (в градусах) не находится между -90 и 0 градусов (изображен). Если он находится между 0 и 90 градусами, вы просто меняете начало координат:
originX = sinVal * oldImgHeight
originY = 0
Если он находится в диапазоне от 90 до 270 градусов (-90 градусов), он немного обманут (см. пример кода ниже).
Ваш код переписан (кратко проверен) - он немного изволен, но, похоже, работает:
public static Bitmap RotateImg(Bitmap bmp, float angle, Color bkColor)
{
angle = angle % 360;
if (angle > 180)
angle -= 360;
System.Drawing.Imaging.PixelFormat pf = default(System.Drawing.Imaging.PixelFormat);
if (bkColor == Color.Transparent)
{
pf = System.Drawing.Imaging.PixelFormat.Format32bppArgb;
}
else
{
pf = bmp.PixelFormat;
}
float sin = (float)Math.Abs(Math.Sin(angle * Math.PI / 180.0)); // this function takes radians
float cos = (float)Math.Abs(Math.Cos(angle * Math.PI / 180.0)); // this one too
float newImgWidth = sin * bmp.Height + cos * bmp.Width;
float newImgHeight = sin * bmp.Width + cos * bmp.Height;
float originX = 0f;
float originY = 0f;
if (angle > 0)
{
if (angle <= 90)
originX = sin * bmp.Height;
else
{
originX = newImgWidth;
originY = newImgHeight - sin * bmp.Width;
}
}
else
{
if (angle >= -90)
originY = sin * bmp.Width;
else
{
originX = newImgWidth - sin * bmp.Height;
originY = newImgHeight;
}
}
Bitmap newImg = new Bitmap((int)newImgWidth, (int)newImgHeight, pf);
Graphics g = Graphics.FromImage(newImg);
g.Clear(bkColor);
g.TranslateTransform(originX, originY); // offset the origin to our calculated values
g.RotateTransform(angle); // set up rotate
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.DrawImageUnscaled(bmp, 0, 0); // draw the image at 0, 0
g.Dispose();
return newImg;
}
Обратите внимание на степень конверсии радианов (180 градусов == Pi Radians) для функций триггера
Изменить: большой проблемой были отрицательные значения sin, и я получаю ширину/высоту путаницы при вычислении начала x/y - теперь это должно работать нормально (проверено)
Изменить: измененный код для обработки любого угла