核心 API:Image.Save 方法
public void Save(string filename, ImageFormat format);
public void Save(Stream stream, ImageFormat format);
ImageFormat 靜態屬性對照表
| 屬性 | 副檔名 | MIME | 特性 |
| ImageFormat.Bmp | .bmp | image/bmp | 無損、無壓縮、檔案大 |
| ImageFormat.Gif | .gif | image/gif | 256 色、支援動畫、透明 |
| ImageFormat.Jpeg | .jpg/.jpeg | image/jpeg | 有損壓縮、相片適用、不支援透明 |
| ImageFormat.Png | .png | image/png | 無損、支援 Alpha 透明、網頁首選 |
| ImageFormat.Tiff | .tif/.tiff | image/tiff | 多頁、無損/有損、列印業標準 |
| ImageFormat.Wmf | .wmf | image/wmf | Windows 向量圖元檔 |
| ImageFormat.Emf | .emf | image/emf | 增強型向量圖元檔 |
| ImageFormat.Exif | .jpg | image/jpeg | JPEG + EXIF 中繼資料 |
| ImageFormat.Icon | .ico | image/x-icon | 圖示檔,含多尺寸 |
完整轉換程式碼
private void ConvertImage(Bitmap sourceImage, string targetPath, ImageFormat format)
{
if (sourceImage == null)
{
MessageBox.Show("請先載入圖片");
return;
}
try
{
// 確保目錄存在
string dir = Path.GetDirectoryName(targetPath);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
sourceImage.Save(targetPath, format);
MessageBox.Show($"轉換成功:{targetPath}");
}
catch (Exception ex)
{
MessageBox.Show($"轉換失敗:{ex.Message}");
}
}
// 使用範例
private void btnConvert_Click(object sender, EventArgs e)
{
using (var saveDlg = new SaveFileDialog())
{
saveDlg.Filter = "PNG|*.png|JPEG|*.jpg|BMP|*.bmp|GIF|*.gif|TIFF|*.tif";
if (saveDlg.ShowDialog() == DialogResult.OK)
{
ImageFormat format = saveDlg.FilterIndex switch
{
1 => ImageFormat.Png,
2 => ImageFormat.Jpeg,
3 => ImageFormat.Bmp,
4 => ImageFormat.Gif,
5 => ImageFormat.Tiff,
_ => ImageFormat.Png
};
ConvertImage(_myBitmap, saveDlg.FileName, format);
}
}
}
進階:JPEG 品質控制
using System.Drawing.Imaging;
public void SaveJpegWithQuality(Image image, string path, long quality)
{
// quality: 0-100
var encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality);
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
image.Save(path, jpegCodec, encoderParams);
}
private ImageCodecInfo GetEncoderInfo(string mimeType)
{
foreach (var codec in ImageCodecInfo.GetImageEncoders())
if (codec.MimeType == mimeType) return codec;
return null;
}
進階:PNG 壓縮等級
public void SavePngWithCompression(Image image, string path, long compressionLevel)
{
// compressionLevel: 0-9 (0=無壓縮, 9=最大壓縮)
var encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(Encoder.Compression, compressionLevel);
ImageCodecInfo pngCodec = GetEncoderInfo("image/png");
image.Save(path, pngCodec, encoderParams);
}
常見錯誤與注意事項
- 原始碼 Bug:範例中
SelectedIndex == 1 存成 GIF 卻用 ImageFormat.Gif,但副檔名寫 .jpg — **副檔名應與格式一致**
- GIF 限制:只支援 256 色,真彩色圖片轉 GIF 會減色
- JPEG 不支援透明:透明背景會變黑或白
- 記憶體釋放:
Bitmap 實作 IDisposable,用完呼叫 Dispose() 或 using
- 大圖處理:大尺寸圖片轉換易發生 OOM,考慮分塊或使用
Image.GetThumbnailImage
現代替代方案
- ImageSharp:跨平台、無原生相依、支援 .NET Core/5+
- SkiaSharp:Google Skia 繪圖引擎封裝、高效能
- Magick.NET:ImageMagick 封裝、格式支援最全