2020年8月5日 星期三

[ ASP.NET MVC ] Image 原始圖片方向屬性與圖檔轉向


今天同事向我反映,直式照片上傳後會變成橫式的,經過一番測試後終於找到原因,這邊紀錄一下查詢到的資料與解法。


此次的問題為,若圖檔經由 Windows 內建的功能轉向,上傳後圖檔會保持原有方向,並不會改變,但若經由轉向後在另存新檔則不會有此問題。



因此,若知道原本圖檔的方向,就可以針對原方向做轉換,想獲取這些資訊可以經由 Exif ( Exchangeable image file format )。

      
private byte[] ImageToBuffer(Image Image)
{
    if (Image == null) { return null; }
    byte[] data = null;

    foreach (var prop in Image.PropertyItems)
    {
        if (prop.Id == 0x0112) //value of EXIF
        {
            int orientationValue = Image.GetPropertyItem(prop.Id).Value[0];
            RotateFlipType rotateFlipType = GetOrientationToFlipType(orientationValue);//取得轉的度數
            Image.RotateFlip(rotateFlipType);//依度數轉成正的
            break;
        }
    }
    using (MemoryStream oMemoryStream = new MemoryStream())
    {
        //建立副本
        using (Bitmap oBitmap = new Bitmap(Image))
        {
            //儲存圖片到 MemoryStream 物件,並且指定儲存影像之格式為 Jpeg
            oBitmap.Save(oMemoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
            //設定資料流位置
            oMemoryStream.Position = 0;
            //設定 buffer 長度
            data = new byte[oMemoryStream.Length];
            //將資料寫入 buffer
            oMemoryStream.Read(data, 0, Convert.ToInt32(oMemoryStream.Length));
            //將所有緩衝區的資料寫入資料流
            oMemoryStream.Flush();
        }
    }
    return data;
}

private RotateFlipType GetOrientationToFlipType(int orientationValue)
{
    RotateFlipType rotateFlipType = RotateFlipType.RotateNoneFlipNone;

    switch (orientationValue)
    {
        case 1:
            rotateFlipType = RotateFlipType.RotateNoneFlipNone;
            break;
        case 2:
            rotateFlipType = RotateFlipType.RotateNoneFlipX;
            break;
        case 3:
            rotateFlipType = RotateFlipType.Rotate180FlipNone;
            break;
        case 4:
            rotateFlipType = RotateFlipType.Rotate180FlipX;
            break;
        case 5:
            rotateFlipType = RotateFlipType.Rotate90FlipX;
            break;
        case 6:
            rotateFlipType = RotateFlipType.Rotate90FlipNone;
            break;
        case 7:
            rotateFlipType = RotateFlipType.Rotate270FlipX;
            break;
        case 8:
            rotateFlipType = RotateFlipType.Rotate270FlipNone;
            break;
        default:
            rotateFlipType = RotateFlipType.RotateNoneFlipNone;
            break;
    }

    return rotateFlipType;
}