首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 打造圖片查看器:目錄輪播、旋轉翻轉、任意角度旋轉與關閉自動保存

     編輯:關於C語言

功能清單與架構設計

  • 目錄輪播:載入資料夾所有圖片 (jpg/png/bmp),上一張/下一張循環切換。
  • 90° 旋轉/翻轉:呼叫 Image.RotateFlip,無損操作 EXIF 方向標籤。
  • 任意角度旋轉:Graphics.TranslateTransform/RotateTransform 繪製新 Bitmap。
  • 關閉時自動保存:參考 Windows 照片檢視器行為,旋轉後不即時寫入,關閉視窗時統一覆蓋原檔。

核心模組實作

1. 目錄掃描與索引管理

// 掃描支援格式
public static List GetImages(string folder)
{
    var exts = new[] { ".jpg", ".jpeg", ".png", ".bmp" };
    return Directory.GetFiles(folder)
        .Where(f => exts.Contains(Path.GetExtension(f).ToLower()))
        .ToList();
}

// 循環索引邏輯
private int CurrentIndex { get; set; }
private List ImageFiles { get; set; }

private void ShowImage(int index)
{
    if (index < 0) index = ImageFiles.Count - 1;
    if (index >= ImageFiles.Count) index = 0;

    CurrentImage?.Dispose(); // 釋放舊圖,避免 GDI+ 通用錯誤
    CurrentImage = Image.FromFile(ImageFiles[index]);
    picBox.Image = CurrentImage;
    CurrentIndex = index;
    Text = $"圖片查看器 - {Path.GetFileName(ImageFiles[index])} ({CurrentIndex + 1}/{ImageFiles.Count})";
}

private void BtnPrev_Click(object s, EventArgs e) => ShowImage(CurrentIndex - 1);
private void BtnNext_Click(object s, EventArgs e) => ShowImage(CurrentIndex + 1);

2. 90° 級旋轉 — RotateFlip 無損操作

RotateFlip 直接操作像素資料並更新 EXIF Orientation 標籤,速度極快且無畫質損耗。

// 順時針 90°
private void BtnRotateCw_Click(object s, EventArgs e)
{
    CurrentImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
    picBox.Image = CurrentImage;
    IsModified = true; // 標記需保存
}

// 逆時針 90° (相當於 270°)
private void BtnRotateCcw_Click(object s, EventArgs e)
{
    CurrentImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
    picBox.Image = CurrentImage;
    IsModified = true;
}

// 水平/垂直翻轉
CurrentImage.RotateFlip(RotateFlipType.RotateNoneFlipX); // 水平鏡像
CurrentImage.RotateFlip(RotateFlipType.RotateNoneFlipY); // 垂直鏡像

3. 任意角度旋轉 — 矩陣變換繪製新 Bitmap

需計算旋轉後外接矩形尺寸,避免圖片被裁切。

public static Bitmap RotateImage(Image src, float angleDeg, Color backColor)
{
    double rad = angleDeg * Math.PI / 180;
    double cos = Math.Abs(Math.Cos(rad));
    double sin = Math.Abs(Math.Sin(rad));
    int newW = (int)(src.Width * cos + src.Height * sin);
    int newH = (int)(src.Width * sin + src.Height * cos);

    var dest = new Bitmap(newW, newH);
    dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);

    using (Graphics g = Graphics.FromImage(dest))
    {
        g.Clear(backColor);
        g.TranslateTransform(newW / 2f, newH / 2f); // 移至中心
        g.RotateTransform(angleDeg);
        g.TranslateTransform(-src.Width / 2f, -src.Height / 2f); // 移回左上
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(src, 0, 0, src.Width, src.Height);
    }
    return dest;
}

// 使用範例
private void BtnRotateFree_Click(object s, EventArgs e)
{
    var newImg = RotateImage(CurrentImage, 45f, Color.White);
    CurrentImage.Dispose();
    CurrentImage = newImg;
    picBox.Image = CurrentImage;
    IsModified = true;
}

4. 關閉視窗統一保存 — 依副檔名選擇編碼器

private void Form_FormClosed(object s, FormClosedEventArgs e)
{
    if (!IsModified || string.IsNullOrEmpty(CurrentPath)) return;

    try
    {
        var ext = Path.GetExtension(CurrentPath).ToLower();
        ImageFormat fmt = ext switch
        {
            ".png" => ImageFormat.Png,
            ".jpg" or ".jpeg" => ImageFormat.Jpeg,
            _ => ImageFormat.Bmp
        };
        CurrentImage.Save(CurrentPath, fmt);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"保存失敗:{ex.Message}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    finally
    {
        CurrentImage?.Dispose();
    }
}

進階優化建議

  1. 縮放模式:picBox.SizeMode = PictureBoxSizeMode.Zoom 保持比例適應;提供 Actual Size 切換至 100%。
  2. 非同步載入:大圖載入時 UI 會卡頓,可用 Task.Run(() => Image.FromFile(path)) 配合 await 載入縮圖先顯示。
  3. EXIF 方向自動修正:讀取 PropertyItem.Id == 0x0112 (Orientation),載入時自動 RotateFlip 校正。
  4. 快捷鍵支援:←/→ 切換、R 旋轉、Esc 關閉,覆寫 ProcessCmdKey。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved