利用 ImageAttributes.SetColorMatrix 設定 5x5 色彩轉換矩陣,調整矩陣對角線元素(M33 對應 Alpha 通道)從 0→1(淡入)或 1→0(淡出),搭配 Graphics.DrawImage 繪製每一幀,即可實現淡入淡出動畫。
[ R 0 0 0 0 ] // Red
[ 0 G 0 0 0 ] // Green
[ 0 0 B 0 0 ] // Blue
[ 0 0 0 A 0 ] // Alpha (M33)
[ 0 0 0 0 1 ] // W (M44, 固定 1)
淡入:A 從 0 遞增至 1
淡出:A 從 1 遞減至 0
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
public partial class Form1 : Form
{
private Bitmap _sourceImage;
public Form1()
{
InitializeComponent();
_sourceImage = new Bitmap("sample.jpg"); // 載入測試圖片
}
// === 淡入動畫 ===
private async void btnFadeIn_Click(object sender, EventArgs e)
{
await FadeAnimation(0f, 1f, 0.02f, 20); // 從 0 到 1,步進 0.02,延遲 20ms
}
// === 淡出動畫 ===
private async void btnFadeOut_Click(object sender, EventArgs e)
{
await FadeAnimation(1f, 0f, -0.02f, 20);
}
// === 通用淡入淡出核心邏輯 ===
private Task FadeAnimation(float startAlpha, float endAlpha, float step, int delayMs)
{
return Task.Run(() =>
{
using (Graphics g = panel1.CreateGraphics())
{
g.Clear(Color.Gray); // 背景色
var attributes = new ImageAttributes();
var matrix = new ColorMatrix
{
Matrix33 = startAlpha, // 初始 Alpha
Matrix44 = 1f
};
float alpha = startAlpha;
bool increasing = step > 0;
while (increasing ? alpha <= endAlpha : alpha >= endAlpha)
{
matrix.Matrix33 = alpha;
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
// 在 UI 執行緒繪圖
this.Invoke((Action)(() =>
{
g.DrawImage(_sourceImage,
new Rectangle(0, 0, _sourceImage.Width, _sourceImage.Height),
0, 0, _sourceImage.Width, _sourceImage.Height,
GraphicsUnit.Pixel, attributes);
}));
alpha += step;
Thread.Sleep(delayMs);
}
}
});
}
}
| 類別/方法 | 用途 |
|---|---|
ColorMatrix | 5x5 仿射轉換矩陣,控制 RGBA 縮放與平移 |
ImageAttributes.SetColorMatrix | 將矩陣套用至後續 DrawImage 操作 |
Graphics.DrawImage(..., ImageAttributes) | 依指定屬性繪製影像 |
ColorMatrixFlag.Default | 套用至整個影像(含灰階調整) |
ColorAdjustType.Bitmap | 指定調整目標為點陣圖 |
panel1.DoubleBuffered = true 減少閃爍Bitmap 再一次 DrawImage 至螢幕Task.Run + InvokeOpacity 動畫或 Effect,效能遠優於 GDI+| 問題 | 原因與解決 |
|---|---|
| 動畫卡頓 | UI 執行緒被 Sleep 阻塞 → 改用 Task/Timer/async-await |
| 影像邊緣鋸齒 | g.InterpolationMode = InterpolationMode.HighQualityBicubic |
| 背景殘影 | 每幀先 g.Clear 或繪製背景圖 |
| 透明背景變黑 | 來源影像需為 32bppArgb,或矩陣 M44=1, M33 控制 Alpha |
修改矩陣其他元素可實現:
參考:MSDN ColorMatrix 文件、GDI+ 影像處理教學