14

私はgifをアニメーション化しており、クラスを使用してそこから画像(フレーム)を解析しています。クラスは次のとおりです。

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.IO;

public class AnimatedGif
{
    private List<AnimatedGifFrame> mImages = new List<AnimatedGifFrame>();
    public AnimatedGif(string path)
    {
        Image img = Image.FromFile(path);
        int frames = img.GetFrameCount(FrameDimension.Time);
        if (frames <= 1) throw new ArgumentException("Image not animated");
        byte[] times = img.GetPropertyItem(0x5100).Value;
        int frame = 0;
        for (; ; )
        {
            int dur = BitConverter.ToInt32(times, 4 * frame);
            mImages.Add(new AnimatedGifFrame(new Bitmap(img), dur));
            if (++frame >= frames) break;
            img.SelectActiveFrame(FrameDimension.Time, frame);
        }
        img.Dispose();
    }
    public List<AnimatedGifFrame> Images { get { return mImages; } }
}

public class AnimatedGifFrame
{
    private int mDuration;
    private Image mImage;
    internal AnimatedGifFrame(Image img, int duration)
    {
        mImage = img; mDuration = duration;
    }
    public Image Image { get { return mImage; } }
    public int Duration { get { return mDuration; } }
}

form1 では、このケースでは 4 のフレームをループし、アニメーションを任意の角度で回転させたいと考えています。これで、45 度または 90 度ずつ回転します。アニメーションにフレーム (画像) を追加したいので、回転を 31 度または 10 度に設定すると、アニメーションが 10 度回転するのがわかります。

これは、正常に機能していない Form1 のコードです。機能するかどうかまだテストしていない回転用の関数を使用しています。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AnimatedGifEditor
{
    public partial class Form1 : Form
    {
        Image myImage;
        AnimatedGif myGif;
        Bitmap bitmap;

        public Form1()
        {
            InitializeComponent();

            myImage = Image.FromFile(@"D:\fananimation.gif");
            myGif = new AnimatedGif(@"D:\fananimation.gif");
            for (int i = 0; i < myGif.Images.Count; i++)
            {
                pictureBox1.Image = myGif.Images[3].Image;
                bitmap = new Bitmap(pictureBox1.Image);
                rotateImage(bitmap, 76);
                pictureBox1.Image = bitmap;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

private Bitmap RotateImg(Bitmap bmp, float angle, Color bkColor)
    {
        int w = bmp.Width;
        int h = bmp.Height;
        bmp.PixelFormat pf = default(bmp.PixelFormat);
        if (bkColor == Color.Transparent)
        {
            pf = bmp.Format32bppArgb;
        }
        else
        {
            pf = bmp.PixelFormat;
        }

        Bitmap tempImg = new Bitmap(w, h, pf);
        Graphics g = Graphics.FromImage(tempImg);
        g.Clear(bkColor);
        g.DrawImageUnscaled(bmp, 1, 1);
        g.Dispose();

        GraphicsPath path = new GraphicsPath();
        path.AddRectangle(new RectangleF(0f, 0f, w, h));
        Matrix mtrx = new Matrix();
        //Using System.Drawing.Drawing2D.Matrix class 
        mtrx.Rotate(angle);
        RectangleF rct = path.GetBounds(mtrx);
        Bitmap newImg = new Bitmap(Convert.ToInt32(rct.Width), Convert.ToInt32(rct.Height), pf);
        g = Graphics.FromImage(newImg);
        g.Clear(bkColor);
        g.TranslateTransform(-rct.X, -rct.Y);
        g.RotateTransform(angle);
        g.InterpolationMode = InterpolationMode.HighQualityBilinear;
        g.DrawImageUnscaled(tempImg, 0, 0);
        g.Dispose();
        tempImg.Dispose();
        return newImg;
    }
    }
}

テストに使用しているアニメーション gif は次の場所にあります。

ここに画像の説明を入力

4

7 に答える 7

28

何が問題なのかわかりませんでしたが、コードを改善できると思います。Matrixクラスを直接使用する必要はないと思います。これを行う関数がいくつかあります。実際、必要なのは、回転のポイントを中心に設定し、グラフィックを回転させ、Graphicsクラスの関数を使用して描画することだけです。したがって、画像を回転するには、次の単純なコードを使用できます。

private Bitmap RotateImage(Bitmap bmp, float angle) {
     Bitmap rotatedImage = new Bitmap(bmp.Width, bmp.Height);
     rotatedImage.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);

     using (Graphics g = Graphics.FromImage(rotatedImage)) {
        // Set the rotation point to the center in the matrix
        g.TranslateTransform(bmp.Width / 2, bmp.Height / 2);
        // Rotate
        g.RotateTransform(angle);
        // Restore rotation point in the matrix
        g.TranslateTransform(- bmp.Width / 2, - bmp.Height / 2);
        // Draw the image on the bitmap
        g.DrawImage(bmp, new Point(0, 0));
     }

     return rotatedImage;
}
于 2012-08-19T10:47:40.283 に答える
6

RotateFlipを試しましたか?

public partial class Form1 : Form
{
    Image myImage;
    AnimatedGif myGif;
    Bitmap bitmap;
    public Form1()
    {
        InitializeComponent();
        myImage = Image.FromFile(@"D:\fananimation.gif");
        bitmap = new Bitmap(myImage);
        bitmap.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
        this.pictureBox1.Image = bitmap;
    }

}

ソース

于 2012-08-19T06:37:15.447 に答える
1

私はVBでこの関数を使用していました:

    Public Function RotateImage(ByRef image As Image, ByVal angle As Single) As Drawing.Bitmap
    If image Is Nothing Then
        Throw New ArgumentNullException("image")
    End If

    Dim pi2 As Single = Math.PI / 2.0
    Dim oldWidth As Single = image.Width
    Dim oldHeight As Single = image.Height

    Dim theta As Single = angle * Math.PI / 180.0
    Dim locked_theta As Single = theta

    If locked_theta < 0.0 Then locked_theta += 2 * Math.PI

    Dim newWidth, newHeight As Single
    Dim nWidth, nHeight As Integer

    Dim adjacentTop, oppositeTop As Single
    Dim adjacentBottom, oppositeBottom As Single

    If (locked_theta >= 0.0 And locked_theta < pi2) Or _
    (locked_theta >= Math.PI And locked_theta < (Math.PI + pi2)) Then
        adjacentTop = Math.Abs(Math.Cos(locked_theta)) * oldWidth
        oppositeTop = Math.Abs(Math.Sin(locked_theta)) * oldWidth

        adjacentBottom = Math.Abs(Math.Cos(locked_theta)) * oldHeight
        oppositeBottom = Math.Abs(Math.Sin(locked_theta)) * oldHeight
    Else
        adjacentTop = Math.Abs(Math.Sin(locked_theta)) * oldHeight
        oppositeTop = Math.Abs(Math.Cos(locked_theta)) * oldHeight

        adjacentBottom = Math.Abs(Math.Sin(locked_theta)) * oldWidth
        oppositeBottom = Math.Abs(Math.Cos(locked_theta)) * oldWidth
    End If



    newWidth = adjacentTop + oppositeBottom
    newHeight = adjacentBottom + oppositeTop

    nWidth = Int(Math.Ceiling(newWidth))
    nHeight = Int(Math.Ceiling(newHeight))

    Dim rotatedBmp As New Drawing.Bitmap(nWidth, nHeight)

    Dim g As Graphics = Graphics.FromImage(rotatedBmp)

    Dim points(2) As Point

    If (locked_theta >= 0.0 And locked_theta < pi2) Then

        points(0) = New Point(Int(oppositeBottom), 0)
        points(1) = New Point(nWidth, Int(oppositeTop))
        points(2) = New Point(0, Int(adjacentBottom))

    ElseIf locked_theta >= pi2 And locked_theta < Math.PI Then

        points(0) = New Point(nWidth, Int(oppositeTop))
        points(1) = New Point(Int(adjacentTop), nHeight)
        points(2) = New Point(Int(oppositeBottom), 0)

    ElseIf locked_theta >= Math.PI And locked_theta < (Math.PI + pi2) Then

        points(0) = New Point(Int(adjacentTop), nHeight)
        points(1) = New Point(0, Int(adjacentBottom))
        points(2) = New Point(nWidth, Int(oppositeTop))

    Else

        points(0) = New Point(0, Int(adjacentBottom))
        points(1) = New Point(Int(oppositeBottom), 0)
        points(2) = New Point(Int(adjacentTop), nHeight)
    End If

    g.DrawImage(image, points)

    g.Dispose()
    image.Dispose()

    Return rotatedBmp

End Function
于 2012-08-19T11:15:57.850 に答える
0

回答を確認したところ、次のいずれかの問題が少なくとも 1 つありました。

  • クロッピング/不適切なセンタリング
  • 不要なマージン
  • 一部の角度範囲でのエラー
  • 不必要に複雑な計算/コード

このソリューションは、あらゆる角度 (正、負、360° 以上など) を処理できます。トリミングや余分な余白はありません。メモリリークもありません。

public Bitmap RotateBitmap(Bitmap bmp, float angle)
{
    double radianAngle = angle / 180.0 * Math.PI;
    double cosA = Math.Abs(Math.Cos(radianAngle));
    double sinA = Math.Abs(Math.Sin(radianAngle));

    int newWidth = (int)(cosA * bmp.Width + sinA * bmp.Height);
    int newHeight = (int)(cosA * bmp.Height + sinA * bmp.Width);

    var rotatedBitmap = new Bitmap(newWidth, newHeight);
    rotatedBitmap.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
    
    using (Graphics g = Graphics.FromImage(rotatedBitmap))
    {
        g.TranslateTransform(rotatedBitmap.Width / 2, rotatedBitmap.Height / 2);
        g.RotateTransform(angle);
        g.TranslateTransform(-bmp.Width / 2, -bmp.Height / 2);
        g.DrawImage(bmp, new Point(0, 0));
    }

    bmp.Dispose();//Remove if you want to keep oryginal bitmap

    return rotatedBitmap;
}
于 2022-01-09T00:41:52.270 に答える