如何旋转位图,保持其比例
How can I rotate a bitmap, keeping its scale
我正在尝试旋转保留所有像素的位图,并设置了目标位图大小,以便我以相同的比例获得它。换句话说,源中的每个像素都是输出中的不同像素,输出位图大小会调整以匹配。
我已经尝试了很多东西 (below code here in a zip with bitmap files)。但我得到的是输出中的部分图像,在某些情况下,按比例缩小。
注意:此处列出了很多解决方案,但它们都存在此代码演示的相同问题。
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace RotateBitmap
{
class Program
{
static void Main(string[] args)
{
RotateBitmap("cows.png", "cows_rotated.png", 90);
RotateBitmap("zoey.jpeg", "zoey_rotated.png", 45);
}
static void RotateBitmap(string srcFilename, string destFilename, double degrees)
{
srcFilename = Path.GetFullPath(Path.Combine("../..", srcFilename));
destFilename = Path.GetFullPath(Path.Combine("../..", destFilename));
byte[] data = File.ReadAllBytes(srcFilename);
MemoryStream stream = new MemoryStream(data);
Bitmap srcBitmap = new Bitmap(stream);
double radians = Math.PI * degrees / 180;
double sin = Math.Abs(Math.Sin(radians)), cos = Math.Abs(Math.Cos(radians));
int srcWidth = srcBitmap.Width;
int srcHeight = srcBitmap.Height;
int rotatedWidth = (int)Math.Floor(srcWidth * cos + srcHeight * sin);
int rotatedHeight = (int)Math.Floor(srcHeight * cos + srcWidth * sin);
Bitmap rotatedImage = new Bitmap(rotatedWidth, rotatedHeight);
Graphics g = Graphics.FromImage(rotatedImage);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
// Set the rotation point to the center in the matrix
g.TranslateTransform(rotatedWidth / 2, rotatedHeight / 2);
// Rotate
g.RotateTransform((float)degrees);
// Restore rotation point in the matrix
g.TranslateTransform(-srcWidth / 2, -rotatedHeight / 2);
// Draw the image on the bitmap
g.DrawImage(srcBitmap, 0, 0);
srcBitmap.Dispose();
g.Dispose();
stream.Close();
stream = new MemoryStream();
rotatedImage.Save(stream, ImageFormat.Png);
data = stream.ToArray();
File.WriteAllBytes(destFilename, data);
}
}
}
static void RotateBitmap2( string srcFilename, string destFilename, double degrees )
{
using( var srcBitmap = Bitmap.FromFile( srcFilename ) )
{
using( var g1 = Graphics.FromImage( srcBitmap ) )
{
var w = srcBitmap.Width;
var h = srcBitmap.Height;
g1.TranslateTransform( w / 2, h / 2 );
g1.RotateTransform( checked((float)degrees) );
g1.TranslateTransform( -w / 2, -h / 2 );
var a = new[] { new Point( 0, 0 ), new Point( w, 0 ), new Point( w, h ), new Point( 0, h ) };
g1.TransformPoints( CoordinateSpace.Device, CoordinateSpace.World, a );
int new_w = a.Max( p => p.X ) - a.Min( p => p.X );
int new_h = a.Max( p => p.Y ) - a.Min( p => p.Y );
using( var rotatedImage = new Bitmap( new_w, new_h, g1 ) )
{
using(var g2 = Graphics.FromImage(rotatedImage))
{
g2.TranslateTransform( new_w / 2, new_h / 2 );
g2.RotateTransform( checked((float)degrees) );
g2.DrawImageUnscaled( srcBitmap, -w / 2, -h / 2 );
}
rotatedImage.Save( destFilename, ImageFormat.Png );
}
}
}
}
我正在尝试旋转保留所有像素的位图,并设置了目标位图大小,以便我以相同的比例获得它。换句话说,源中的每个像素都是输出中的不同像素,输出位图大小会调整以匹配。
我已经尝试了很多东西 (below code here in a zip with bitmap files)。但我得到的是输出中的部分图像,在某些情况下,按比例缩小。
注意:此处列出了很多解决方案,但它们都存在此代码演示的相同问题。
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace RotateBitmap
{
class Program
{
static void Main(string[] args)
{
RotateBitmap("cows.png", "cows_rotated.png", 90);
RotateBitmap("zoey.jpeg", "zoey_rotated.png", 45);
}
static void RotateBitmap(string srcFilename, string destFilename, double degrees)
{
srcFilename = Path.GetFullPath(Path.Combine("../..", srcFilename));
destFilename = Path.GetFullPath(Path.Combine("../..", destFilename));
byte[] data = File.ReadAllBytes(srcFilename);
MemoryStream stream = new MemoryStream(data);
Bitmap srcBitmap = new Bitmap(stream);
double radians = Math.PI * degrees / 180;
double sin = Math.Abs(Math.Sin(radians)), cos = Math.Abs(Math.Cos(radians));
int srcWidth = srcBitmap.Width;
int srcHeight = srcBitmap.Height;
int rotatedWidth = (int)Math.Floor(srcWidth * cos + srcHeight * sin);
int rotatedHeight = (int)Math.Floor(srcHeight * cos + srcWidth * sin);
Bitmap rotatedImage = new Bitmap(rotatedWidth, rotatedHeight);
Graphics g = Graphics.FromImage(rotatedImage);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
// Set the rotation point to the center in the matrix
g.TranslateTransform(rotatedWidth / 2, rotatedHeight / 2);
// Rotate
g.RotateTransform((float)degrees);
// Restore rotation point in the matrix
g.TranslateTransform(-srcWidth / 2, -rotatedHeight / 2);
// Draw the image on the bitmap
g.DrawImage(srcBitmap, 0, 0);
srcBitmap.Dispose();
g.Dispose();
stream.Close();
stream = new MemoryStream();
rotatedImage.Save(stream, ImageFormat.Png);
data = stream.ToArray();
File.WriteAllBytes(destFilename, data);
}
}
}
static void RotateBitmap2( string srcFilename, string destFilename, double degrees )
{
using( var srcBitmap = Bitmap.FromFile( srcFilename ) )
{
using( var g1 = Graphics.FromImage( srcBitmap ) )
{
var w = srcBitmap.Width;
var h = srcBitmap.Height;
g1.TranslateTransform( w / 2, h / 2 );
g1.RotateTransform( checked((float)degrees) );
g1.TranslateTransform( -w / 2, -h / 2 );
var a = new[] { new Point( 0, 0 ), new Point( w, 0 ), new Point( w, h ), new Point( 0, h ) };
g1.TransformPoints( CoordinateSpace.Device, CoordinateSpace.World, a );
int new_w = a.Max( p => p.X ) - a.Min( p => p.X );
int new_h = a.Max( p => p.Y ) - a.Min( p => p.Y );
using( var rotatedImage = new Bitmap( new_w, new_h, g1 ) )
{
using(var g2 = Graphics.FromImage(rotatedImage))
{
g2.TranslateTransform( new_w / 2, new_h / 2 );
g2.RotateTransform( checked((float)degrees) );
g2.DrawImageUnscaled( srcBitmap, -w / 2, -h / 2 );
}
rotatedImage.Save( destFilename, ImageFormat.Png );
}
}
}
}