2016-01-20 42 views
0

我從另一個遊戲的標準自上而下的瓷磚動態創建等角拼貼。但問題是,圖像調整大小往往會導致兩側像素「缺失」。我知道他們並不是真的錯過了,代碼運行正常,但我對GDI瞭解不多,無法知道要搜索哪些設置/教程。GDI調整圖像和保證高度

我把這個:enter image description here並把它變成這個:enter image description here

它從32x32到48x24,這是正確的比例。但是,在左側和底部,草地距離圖像邊緣不到一個像素。我不想手動解決這個問題,因爲我會爲數百個tile執行此操作,所以我想找到一種方法在代碼中修復此問題。最後,問題在於瓷磚之間的微小單像素間隙。

我可以用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

你可能要考慮計算的寬度和你的旋轉物體的高度。

例如:

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))); 
    } 
+0

這將返回一個尺寸不等距比例相匹配。基於完美正方形的等距圖像應該寬50%,高25%。它基本上是將圖像在z軸上旋轉45度(向右旋轉/向左旋轉),然後沿着x軸旋轉-45度(將圖像的頂部向後傾斜)。您的方法返回39x39。我的正常旋轉實際上正常工作。我知道圖像應該是48x24,而這只是「後傾」部分的問題,我通過將高度縮小50%來完成。我不確定是否從您的解決方案中錯過了其他內容。 – sraboy

+0

你說得對。我給出了一個解決方案來獲得2D旋轉的界限。我沒有正確閱讀這個問題。也許這個線程會幫助你更進一步:http://stackoverflow.com/questions/2163829/how-do-i-rotate-a-picture-in-c-sharp –

+0

一個3D庫的例子使用四元數學的3D旋轉在GDI。 http://www.codeproject.com/Articles/36868/Quaternion-Mathematics-and-D-Library-with-C-and-G爲3D圖書館的例子。 –

相關問題