C#中圖片與BASE64碼互相轉換


 //保存目錄
            string dir = "/upload/user/head";
            //站點文件目錄
            string fileDir = HttpContext.Current.Server.MapPath("~" + dir);
            //文件名稱
            string fileName = "headdemo" + DateTime.Now.ToString("yyyyMMddHHmmssff");
            //保存文件所在站點位置
            string filePath = Path.Combine(fileDir, fileName);

            if (!System.IO.Directory.Exists(fileDir))
                System.IO.Directory.CreateDirectory(fileDir);

            //讀圖片轉為Base64String
            System.Drawing.Bitmap bmp1 = new System.Drawing.Bitmap(Path.Combine(fileDir, "default.jpg"));
            using (MemoryStream ms1 = new MemoryStream())
            {
                bmp1.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg);
                byte[] arr1 = new byte[ms1.Length];
                ms1.Position = 0;
                ms1.Read(arr1, 0, (int)ms1.Length);
                ms1.Close();
                UserPhoto = Convert.ToBase64String(arr1);
            }

            //將Base64String轉為圖片並保存
            byte[] arr2 = Convert.FromBase64String(UserPhoto);
            using (MemoryStream ms2 = new MemoryStream(arr2))
            {
                System.Drawing.Bitmap bmp2 = new System.Drawing.Bitmap(ms2);
                bmp2.Save(filePath + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                //bmp2.Save(filePath + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
                //bmp2.Save(filePath + ".gif", System.Drawing.Imaging.ImageFormat.Gif);
                //bmp2.Save(filePath + ".png", System.Drawing.Imaging.ImageFormat.Png);
            }

 

//將Base64String轉為圖片並保存
                        byte[] arr2 = Convert.FromBase64String(UserPhoto);
                        using (MemoryStream ms2 = new MemoryStream(arr2))
                        {
                            System.Drawing.Bitmap bmp2 = new System.Drawing.Bitmap(ms2);
                            ////只有把當前的圖像復制一份,然后把舊的Dispose掉,那個文件就不被鎖住了,
                            ////這樣就可以放心覆蓋原始文件,否則GDI+一般性錯誤(A generic error occurred in GDI+)
                            //System.Drawing.Bitmap bmpNew = new System.Drawing.Bitmap(bmp2);
                            //bmp2.Dispose();
                            //bmp2 = null;
                            bmp2.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
                            //bmp2.Save(filePath + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                            //bmp2.Save(filePath + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
                            //bmp2.Save(filePath + ".gif", System.Drawing.Imaging.ImageFormat.Gif);
                            //bmp2.Save(filePath + ".png", System.Drawing.Imaging.ImageFormat.Png);
                            bmp2.Dispose();
                        }

GDI+一般性錯誤(A generic error occurred in GDI+)

 

1.GDI+的前世今生

GDI+全稱圖形設備接口,Graphics Device Interface (GDI) ,他的爸爸叫做GDI, 用C寫的。Windows XP出來以后用C++重新寫了一下,變成了GDI+。從.NET Framework 1.0開始,GDI+就被正式封裝在了.NET Framework里面,並被廣泛地應用到了所有和圖形圖像相關的程序中。不幸的是,這個GDI+引入了微軟有史以來最大的2個patch,造成了Microsoft IT, Support, Developer, Tester的無數麻煩。[1][2]

GDI+沒有用顯卡加速,所以Windows Vista推薦用Windows Display Driver Model (WDDM)了,支持渲染,3D加速。不過普通的應用程序,用GDI/GDI+其實是完全足夠了,所以GDI+是在微軟平台上開發圖形圖像程序的最好選擇了。至少現在沒有聽說微軟准備重新寫GDI

GDI+ 可以用來做圖形處理,也可以做圖像處理。這里只分析幾個使用.NET Framework容易出錯的地方。 

2. GDI+一般性錯誤(A generic error occurred in GDI+)

這是使用GDI+的時候最滑稽的一個Exception,里面啥信息都沒有。對於剛剛開始使用.NET Framework開發者來說,很難發現這個問題到底是為什么。

我們先來看看下面一段代碼 

 

string fileName = "sample.jpg";
Bitmap bmp = new Bitmap(fileName);
bmp.Save(fileName, ImageFormat.Jpeg);

這段代碼的目的是要打開一個Bitmap,然后保存。可惜這段代碼一定會給你一個GDI+一般性錯誤:

System.Runtime.InteropServices.ExternalException

其中的Error Code是0x80004005, innerException是空。如果你查Windows的Error Code表,會發現這個錯誤原因是“Unspecified Error”,還是什么都不知道。這其實是.NET Framework封裝不好的問題,我們可以調用

Marshal.GetLastWin32Error()

拿到Win32的Error, 32。這個錯誤代碼就有點信息量了,在winerror.h里面,我們可以找到下面的定義:

復制代碼
//
// MessageId: ERROR_SHARING_VIOLATION
//
// MessageText:
//
//  The process cannot access the file because it is being used by another process.
//
#define ERROR_SHARING_VIOLATION          32L
復制代碼

  

原來是文件不能寫。其實MSDN里面有一句話,The file remains locked until the Bitmap is disposed。所以文件讀取以后是鎖着的,沒有辦法寫。那如果我想做點改動然后再保存原來的文件怎么辦呢?

這里有個土辦法可以搞定這個問題 

Bitmap bmpTemp = new Bitmap(image);
Bitmap bmp = new Bitmap(bmpTemp);
bmpTemp.Dispose();
bmp.Save(image, ImageFormat.Jpeg);

 

只要把當前的圖像復制一份,然后把舊的Dispose掉,那個文件就不被鎖住了,這樣就可以放心覆蓋原始文件了。

想想如果你要用GDI+寫一個Painter,很容易你就會遇到這個問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM