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

C# 圖片檔案與位元組陣列/資料流雙向轉換完整範例

     編輯:關於C#

在資料庫儲存圖片(`varbinary`/`BLOB`)、網路傳輸、快取等場景,常需在 Image、byte[]、Stream、檔案之間轉換。本文提供三個核心方法:檔案→位元組陣列、位元組陣列→Image、位元組陣列→檔案,並說明記憶體流管理與常見坑點。

核心轉換方法

using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

public class ImageConverter
{
    private byte[] _buffer; // 內部快取

    public string SourcePath { get; set; }
    public string TargetPath { get; set; }

    // 1. 檔案 → byte[] (儲存至 _buffer)
    public void FileToBuffer()
    {
        using (Image img = Image.FromFile(SourcePath))
        using (MemoryStream ms = new MemoryStream())
        {
            img.Save(ms, ImageFormat.Bmp); // 或 Png/Jpeg 依需求
            _buffer = ms.ToArray();
        }
    }

    // 2. byte[] → Image (供 PictureBox 顯示)
    public Image BufferToImage()
    {
        if (_buffer == null || _buffer.Length == 0) return null;
        using (MemoryStream ms = new MemoryStream(_buffer))
        {
            // 重要:FromStream 要求 stream 保持開啟直到 Image 不再使用
            // 若需立即關閉 stream,請先複製像素資料:
            Image img = Image.FromStream(ms);
            // 強制載入像素資料,脫離 stream 依賴
            var bmp = new Bitmap(img);
            return bmp;
        }
    }

    // 3. byte[] → 檔案
    public void BufferToFile()
    {
        if (_buffer == null) return;
        using (FileStream fs = new FileStream(TargetPath, FileMode.Create, FileAccess.Write))
        {
            fs.Write(_buffer, 0, _buffer.Length);
            fs.Flush();
        }
    }
}

關鍵細節與避坑指南

問題原因解決
Image.FromStream 關閉 stream 後報錯GDI+ 延遲載入,stream 必須保持開啟在 `using` 區塊內 `new Bitmap(img)` 強制複製像素,或不關閉 stream(由外部管理生命週期)
大圖記憶體暴增一次 `ToArray()` 載入完整像素分塊處理、使用 `Image.FromStream` 串流式處理、或改用 `Bitmap.LockBits`
儲存格式與原檔不符範例固定用 `ImageFormat.Bmp`根據副檔名或 `Image.RawFormat` 動態決定格式
`Image.FromFile` 鎖定檔案檔案流未釋放改用 `FileStream` + `Image.FromStream`,或複製檔案到暫存目錄

進階:資料庫儲存與讀取範例

// 存入 SQL Server varbinary(max)
public void SaveToDb(int id, byte[] imgData)
{
    using (var conn = new SqlConnection(connStr))
    using (var cmd = new SqlCommand("UPDATE Users SET Photo=@p WHERE Id=@id", conn))
    {
        cmd.Parameters.Add("@p", SqlDbType.VarBinary, -1).Value = imgData;
        cmd.Parameters.AddWithValue("@id", id);
        conn.Open(); cmd.ExecuteNonQuery();
    }
}

// 讀出並顯示
public Image LoadFromDb(int id)
{
    using (var conn = new SqlConnection(connStr))
    using (var cmd = new SqlCommand("SELECT Photo FROM Users WHERE Id=@id", conn))
    {
        cmd.Parameters.AddWithValue("@id", id);
        conn.Open();
        byte[] data = (byte[])cmd.ExecuteScalar();
        if (data == null) return null;
        using (var ms = new MemoryStream(data))
        {
            Image img = Image.FromStream(ms);
            return new Bitmap(img); // 脫離 stream
        }
    }
}

總結

  • File → byte[]:`Image.FromFile` → `MemoryStream` → `ToArray()`。
  • byte[] → Image:`MemoryStream` → `Image.FromStream` → `new Bitmap()` 脫離流。
  • byte[] → File:`FileStream.Write`。
  • 統一使用 `using` 確保非受控資源釋放。
  • 大量圖片處理考慮 `ImageSharp`、`SkiaSharp` 等跨平台高效能庫。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved