Как я могу вращать растровое изображение, сохраняя его масштаб - PullRequest
0 голосов
/ 11 апреля 2020

Я пытаюсь повернуть растровое изображение, в котором я сохраняю все пиксели, а целевой размер растрового изображения установлен таким образом, чтобы получить его в том же масштабе. Другими словами, каждый пиксель в источнике является отдельным пикселем на выходе, и размер растрового изображения на выходе корректируется в соответствии.

Я пробовал кучу вещей ( ниже кода здесь в zip-файле) с растровыми файлами ). Но то, что я получаю, это частичные изображения в выводе, а в некоторых случаях уменьшенные.

Примечание: здесь есть несколько решений для этого, но все они имеют ту же проблему, которую демонстрирует этот код .

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

Также опубликовано в MSDN.

1 Ответ

0 голосов
/ 11 апреля 2020

Ответил на MSDN:

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 );
            }
        }
    }
}
...