zoukankan      html  css  js  c++  java
  • 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,很容易你就会遇到这个问题。

  • 相关阅读:
    迭代器和生成器
    案例:复制大文件
    案例:使用seek倒查获取日志文件的最后一行
    Leetcode165. Compare Version Numbers比较版本号
    Leetcode137. Single Number II只出现一次的数字2
    Leetcode129. Sum Root to Leaf Numbers求根到叶子节点数字之和
    Leetcode116. Populating Next Right Pointers in Each Node填充同一层的兄弟节点
    Leetcode114. Flatten Binary Tree to Linked List二叉树展开为链表
    Leetcode113. Path Sum II路径总和2
    C++stl中vector的几种常用构造方法
  • 原文地址:https://www.cnblogs.com/efreer/p/11362601.html
Copyright © 2011-2022 走看看