You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WPF使用SharpAvi转图片为AVI时视频画面旋转问题

图片转AVI视频画面旋转问题解决

将图片转为AVI视频后,生成的视频画面出现旋转,与原图方向不符:

原图:
Original Image

生成视频中的画面:
Image from video generated

问题原因

这种情况几乎都是因为图片的EXIF旋转信息未被处理。很多手机拍摄的图片会在EXIF元数据中记录旋转角度(比如竖拍图片会标记需旋转90度),但直接将图片转为System.Drawing.Bitmap时,BMP格式不支持保存EXIF信息,且现有代码未主动读取并应用该旋转角度,导致视频帧使用了原始像素数据——而视频播放器不会自动解析EXIF旋转,最终画面显示为旋转状态。

你的代码片段

var croppedImage = GetCroppedImageVideo(vidSize);
System.Drawing.Bitmap bmp;
bmp = BitmapFromSource(croppedImage);
byte[] byteArray = BitmapToByteArray(bmp);
stream.WriteFrame(true, byteArray, 0, byteArray.Length);
public static System.Drawing.Bitmap BitmapFromSource(CroppedBitmap bmp)
{
    System.Drawing.Bitmap bitmap;
    using (var outStream = new MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bmp));
        enc.Save(outStream);
        bitmap = new System.Drawing.Bitmap(outStream);
    }
    return bitmap;
}
public static byte[] BitmapToByteArray(System.Drawing.Bitmap bitmap)
{
    BitmapData bmpdata = null;

    try
    {
        bmpdata = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
        int numbytes = bmpdata.Stride * bitmap.Height;
        byte[] bytedata = new byte[numbytes];
        IntPtr ptr = bmpdata.Scan0;

        Marshal.Copy(ptr, bytedata, 0, numbytes);
        
        return bytedata;
    }
    finally
    {
        if (bmpdata != null)
        {
            bitmap.UnlockBits(bmpdata);
        }
    }
}

解决方法

需要先读取原图的EXIF旋转角度,再将Bitmap旋转到正确方向后写入视频帧。

  1. 添加读取EXIF旋转角度的方法:
private static int GetExifRotationAngle(Image image)
{
    // 274是EXIF标准中标记旋转角度的属性ID
    if (image.PropertyIdList.Contains(274))
    {
        var rotationProp = image.GetPropertyItem(274);
        return rotationProp.Value[0];
    }
    return 0; // 默认无旋转
}
  1. 添加Bitmap旋转方法:
private static System.Drawing.Bitmap RotateBitmap(System.Drawing.Bitmap bitmap, int rotationAngle)
{
    switch (rotationAngle)
    {
        case 90:
            bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
            break;
        case 180:
            bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
            break;
        case 270:
            bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
            break;
    }
    return new System.Drawing.Bitmap(bitmap);
}
  1. 修改调用代码,加入旋转处理:
var croppedImage = GetCroppedImageVideo(vidSize);
System.Drawing.Bitmap bmp;
bmp = BitmapFromSource(croppedImage);

// 读取并应用EXIF旋转
int rotationAngle = GetExifRotationAngle(bmp);
if (rotationAngle != 0)
{
    using (var tempBmp = bmp)
    {
        bmp = RotateBitmap(tempBmp, rotationAngle);
    }
}

byte[] byteArray = BitmapToByteArray(bmp);
stream.WriteFrame(true, byteArray, 0, byteArray.Length);
// 记得最后释放bmp资源
bmp.Dispose();

额外说明

如果GetCroppedImageVideo方法处理的是带EXIF信息的原图,也可以在生成CroppedBitmap前先处理旋转,避免后续转Bitmap时丢失信息。另外,视频的分辨率需要和旋转后的Bitmap尺寸匹配,否则可能出现拉伸或黑边问题。

内容的提问来源于stack exchange,提问作者Muhammad Arshad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:48:22