我正在从另一款游戏的标准自顶向下瓷砖动态创建等距瓷砖。但问题是,图像调整大小通常会导致两侧的某些像素“丢失”。我知道他们并没有真正丢失并且代码工作正常但我对GDI知之甚少,无法知道要搜索的设置/教程。
从32x32到48x24,这是正确的比例。然而,在左侧和底部,草是到达图像边缘的一个像素。我不想手动修复此问题,因为我将为数百个磁贴执行此操作,因此我想在代码中找到解决此问题的方法。最后,问题是瓷砖最终会在它们之间留下微小的一个像素间隙。
除了仅检查每个图像的边缘颜色并手动添加它们(如果它们缺失/透明)之外,我能用GDI做些什么吗?
以下是我用来执行此操作的代码。注释掉的部分是我一直在搞乱的各种设置:
Bitmap bmp = RotateImage(new Bitmap(fileName), 45);
bmp = ResizeImage(bmp, bmp.Width, bmp.Height / 2);
private static Bitmap RotateImage(Bitmap rotateMe, float angle)
{
//First, re-center the image in a larger image that has a margin/frame
//to compensate for the rotated image's increased size
var bmp = new Bitmap(rotateMe.Width + (rotateMe.Width / 2), rotateMe.Height + (rotateMe.Height / 2));
using (Graphics g = Graphics.FromImage(bmp))
g.DrawImageUnscaled(rotateMe, (rotateMe.Width / 4), (rotateMe.Height / 4), bmp.Width, bmp.Height);
rotateMe = bmp;
//Now, actually rotate the image
Bitmap rotatedImage = new Bitmap(rotateMe.Width, rotateMe.Height);
using (Graphics g = Graphics.FromImage(rotatedImage))
{
g.TranslateTransform(rotateMe.Width / 2, rotateMe.Height / 2); //set the rotation point as the center into the matrix
g.RotateTransform(angle); //rotate
g.TranslateTransform(-rotateMe.Width / 2, -rotateMe.Height / 2); //restore rotation point into the matrix
g.DrawImage(rotateMe, new Point(0, 0)); //draw the image on the new bitmap
}
return rotatedImage;
}
private static Bitmap ResizeImage(System.Drawing.Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
//graphics.CompositingMode = CompositingMode.SourceCopy;
//graphics.CompositingQuality = CompositingQuality.HighQuality;
//graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
//graphics.SmoothingMode = SmoothingMode.HighQuality;
//graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
答案 0 :(得分:0)
您可能需要考虑计算旋转对象的宽度和高度。
例如:
private void button1_Click(object sender, EventArgs e)
{
var width = (int) numericUpDown2.Value;
var height = (int) numericUpDown3.Value;
var angle = (float) numericUpDown1.Value;
var size = new Size(width, height);
var result = RotatedSettings(angle, size);
textBox1.Text = String.Format("{0} x {1}", result.Width, result.Height);
}
private static Size RotatedSettings(float angle, Size size)
{
// setup corner values in array
var corners = new[]
{ new PointF(0, 0),
new PointF(size.Width, 0),
new PointF(0, size.Height),
new PointF(size.Width, size.Height)};
// rotate corners
var xc = corners.Select(p => Rotate(p, (float)angle).X);
var yc = corners.Select(p => Rotate(p, (float)angle).Y);
// find the new sizes by subtracting highest from lowest result.
var widths = xc as IList<float> ?? xc.ToList();
var newWidth = (int)Math.Abs(widths.Max() - widths.Min());
var heights = yc as IList<float> ?? yc.ToList();
var newHeight = (int)Math.Abs(heights.Max() - heights.Min());
// as we rotate the mid point we need to middle midpoint section and add the outcome to size.
var midX = ((size.Width / 2) - ((double)newWidth / 2));
var midY = ((size.Height / 2) - ((double)newHeight / 2));
return new Size(newWidth + (int)midX, newHeight + (int)midY);
}
/// <summary>
/// Rotates a point around the origin (0,0)
/// </summary>
private static PointF Rotate(PointF p, float angle)
{
// convert from angle to radians
var theta = Math.PI * angle / 180;
return new PointF(
(float)(Math.Cos(theta) * (p.X) - Math.Sin(theta) * (p.Y)),
(float)(Math.Sin(theta) * (p.X) + Math.Cos(theta) * (p.Y)));
}