C# - 图片操作和Base64处理
旋转
(1)按角度旋转
/// <summary>
/// 根据角度旋转图标
/// </summary>
/// <param name="img"></param>
public Image RotateImg(Image img, float angle)
{
//通过Png图片设置图片透明,修改旋转图片变黑问题。
int width = img.Width;
int height = img.Height;
//角度
Matrix mtrx = new Matrix();
mtrx.RotateAt(angle, new PointF((width / 2), (height / 2)), MatrixOrder.Append);
//得到旋转后的矩形
GraphicsPath path = new GraphicsPath();
path.AddRectangle(new RectangleF(0f, 0f, width, height));
RectangleF rct = path.GetBounds(mtrx);
//生成目标位图
Bitmap devImage = new Bitmap((int)(rct.Width), (int)(rct.Height));
Graphics g = Graphics.FromImage(devImage);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//计算偏移量
Point Offset = new Point((int)(rct.Width - width) / 2, (int)(rct.Height - height) / 2);
//构造图像显示区域:让图像的中心与窗口的中心点一致
Rectangle rect = new Rectangle(Offset.X, Offset.Y, (int)width, (int)height);
Point center = new Point((int)(rect.X + rect.Width / 2), (int)(rect.Y + rect.Height / 2));
g.TranslateTransform(center.X, center.Y);
g.RotateTransform(angle);
//恢复图像在水平和垂直方向的平移
g.TranslateTransform(-center.X, -center.Y);
g.DrawImage(img, rect);
//重至绘图的所有变换
g.ResetTransform();
g.Save();
g.Dispose();
path.Dispose();
return devImage;
}
(2)按弧度旋转
/// <summary>
/// 第二种方法
/// </summary>
/// <param name="b"></param>
/// <param name="angle"></param>
/// <returns></returns>
public Image RotateImg2(Image b, float angle)
{
angle = angle % 360; //弧度转换
double radian = angle * Math.PI / 180.0;
double cos = Math.Cos(radian);
double sin = Math.Sin(radian);
//原图的宽和高
int w = b.Width;
int h = b.Height;
int W = (int)(Math.Max(Math.Abs(w * cos - h * sin), Math.Abs(w * cos + h * sin)));
int H = (int)(Math.Max(Math.Abs(w * sin - h * cos), Math.Abs(w * sin + h * cos)));
//目标位图
Image dsImage = new Bitmap(W, H);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(dsImage);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//计算偏移量
Point Offset = new Point((W - w) / 2, (H - h) / 2);
//构造图像显示区域:让图像的中心与窗口的中心点一致
Rectangle rect = new Rectangle(Offset.X, Offset.Y, w, h);
Point center = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
g.TranslateTransform(center.X, center.Y);
g.RotateTransform(360-angle);
//恢复图像在水平和垂直方向的平移
g.TranslateTransform(-center.X, -center.Y);
g.DrawImage(b, rect);
//重至绘图的所有变换
g.ResetTransform();
g.Save();
g.Dispose();
//dsImage.Save("yuancd.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
return dsImage;
}
以上参考:基于C#的两种图片旋转方法
此外,可以直接使用已封装的方法:
/// <summary>
/// 旋转(利用已封装的方法)
/// </summary>
/// <param name="path">图片路径</param>
/// <param name="rotateFlipType">旋转方式</param>
/// <returns></returns>
public bool KiRotate(string path, RotateFlipType rotateFlipType)
{
try
{
using (Bitmap bitmap = new Bitmap(path))
{
// 顺时针旋转90度 RotateFlipType.Rotate90FlipNone
// 逆时针旋转90度 RotateFlipType.Rotate270FlipNone
// 水平翻转 RotateFlipType.Rotate180FlipY
// 垂直翻转 RotateFlipType.Rotate180FlipX
bitmap.RotateFlip(rotateFlipType);
bitmap.Save(path);
}
return true;
}
catch(Exception ex)
{
return false;
}
}
转换
(1)Bitmap & BitmapImage
// 程序集
System.Xaml.dll
System.Drawing.dll
WindowsBase.dll
PresentationCore.dll
// 命名空间
using System.Drawing;
using System.IO;
using System.Windows.Media.Imaging;
using System.Windows.Interop;
using System.Windows; /// <summary>
/// 创建一个Bitmap对象
/// </summary>
/// <param name="_uri">"../Images/test.png"</param>
public Bitmap CreatBitmapObject(string _uri)
{
Bitmap bitmap = new Bitmap(_uri);
return bitmap;
} /// <summary>
/// 创建一个BitmapImage对象
/// </summary>
/// <param name="_uri">"../Images/test.png"</param>
public BitmapImage CreatBitmapImageObject(string _uri)
{
BitmapImage bitmapImage = new BitmapImage(
new Uri(_uri, UriKind.Relative));
return bitmapImage;
} /// <summary>
/// BitmapImage to Bitmap
/// </summary>
public Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapImage));
enc.Save(outStream);
Bitmap bitmap = new Bitmap(outStream);
return new Bitmap(bitmap);
}
} /// <summary>
/// Bitmap to BitmapImage
/// </summary>
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
public BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
{
IntPtr hBitmap = bitmap.GetHbitmap();
BitmapImage retval; try
{
retval = (BitmapImage)Imaging.CreateBitmapSourceFromHBitmap(
hBitmap, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
finally
{
DeleteObject(hBitmap);
} return retval;
}
若是将Bitmap转换成BitmapSource,只需将返回值类型更改为BitmapSource即可。
具体参考:Converting BitmapImage to Bitmap and vice versa;
(2)Bitmap/BitmapImage & byte[]
/// <summary>
/// Bitmap to 字节数组
/// </summary>
public byte[] Bitmap2Bytes(Bitmap bitmap)
{
ImageFormat format = bitmap.RawFormat;
using (MemoryStream ms = new MemoryStream())
{
bitmap.Save(ms, format);
byte[] data = new byte[ms.Length];
//Save()会改变MemoryStream的Position,需要重新Seek到Begin也就是开始的0位置
ms.Seek(0, SeekOrigin.Begin);
ms.Read(data, 0, Convert.ToInt32(ms.Length));
return data;
}
}
/// <summary>
/// 字节数组 to Bitmap
/// </summary>
public Bitmap Bytes2Bitmap(byte[] data)
{
MemoryStream ms = null;
try
{
ms = new MemoryStream(data);
return new Bitmap((Image)new Bitmap(ms));
}
catch (Exception ex)
{
throw ex;
}
finally
{
ms.Close();
}
} /// <summary>
/// BitmapImage to 字节数组
/// </summary>
public byte[] BitmapImage2Bytes(BitmapImage bitmapImage)
{
byte[] bytes = null;
try
{
Stream ms = bitmapImage.StreamSource;
if (ms != null && ms.Length > 0)
{
//很重要,因为Position经常位于stream的末尾,导致下面读取到的长度为0
ms.Position = 0;
using (BinaryReader br = new BinaryReader(ms))
{
bytes = br.ReadBytes((int)ms.Length);
}
}
}
catch(Exception ex)
{
bytes = null;
throw ex;
}
return bytes;
}
/// <summary>
/// 字节数组 to BitmapImage
/// </summary>
public BitmapImage Bytes2BitmapImage(byte[] data)
{
BitmapImage bitmapImage = null;
try
{
bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(data);
bitmapImage.EndInit();
}
catch(Exception ex)
{
bitmapImage = null;
throw ex;
}
return bitmapImage;
}
此时,可以总结下Bitmap、BitmapImage、Image和BitmapSource、ImageSource之间的关系
// Image抽象类,Bitmap密封类
public abstract class Image: xxx
public sealed class Bitmap : Image
// ImageSource和BitmapSource抽象类,BitmapImage密封类
public abstract class ImageSource: xxx
public abstract class BitmapSource : ImageSource
public sealed class BitmapImage : BitmapSource
压缩
图片大小 > 1M 时,可以对图片进行压缩,有效减小图片大小、占用内存空间等。
/// <summary>
/// 生成缩略图
/// </summary>
/// <param name="sourceFile">原始图片文件</param>
/// <param name="quality">质量压缩比:0-100,越大质量越好</param>
/// <param name="multiple">压缩倍数</param>
/// <param name="outputFile">输出文件名</param>
/// <returns>成功返回true,失败返回false</returns>
/// 调用格式:GetThumImage("", 85L, 3, "");
public static bool GetThumImage(string sourceFile, long quality, int multiple, string outputFile)
{
try
{
// 获取图片信息
Bitmap sourceImage = new Bitmap(sourceFile);
ImageCodecInfo myImageCodecInfo = GetEncoderInfo(sourceImage.RawFormat);
if (null == myImageCodecInfo) {
return false;
} // 压缩质量
System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, quality);
myEncoderParameters.Param[0] = myEncoderParameter; // 按比例压缩
float _xWidth = sourceImage.Width;
float _yWidth = sourceImage.Height;
Bitmap newImage = new Bitmap((int)(_xWidth / multiple), (int)(_yWidth / multiple));
Graphics g = Graphics.FromImage(newImage);
/// 可按需配置属性
//g.CompositingQuality = CompositingQuality.HighQuality;
//g.CompositingMode = CompositingMode.SourceCopy;
//g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(sourceImage, 0, 0, (_xWidth / multiple), (_yWidth / multiple));
g.Dispose(); // 保存图片
newImage.Save(outputFile, myImageCodecInfo, myEncoderParameters);
return true;
}
catch
{
return false;
}
} /// <summary>
/// 获取图片编码信息
/// </summary>
private static ImageCodecInfo GetEncoderInfo(ImageFormat format)
{
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (encoders[j].FormatID == format.Guid) {
return encoders[j];
}
}
return null;
}
提供一个在工作中压缩图片的方法
public string CompressImageString(string str) {
string convertedImageString = string.Empty;
byte[] b = Convert.FromBase64String(str);
MemoryStream ms = new MemoryStream(b);
Bitmap bitMap = new Bitmap(ms);
bitMap = CompressImage(bitMap);
byte[] byteArray = null;
using (MemoryStream stream = new MemoryStream()) {
bitMap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
byteArray = new byte[stream.Length];
stream.Seek(0, SeekOrigin.Begin);
if (stream.Read(byteArray, 0, Convert.ToInt32(stream.Length)) <= 0)
{
return "";
}
}
convertedImageString = Convert.ToBase64String(byteArray);
return convertedImageString;
}
private Bitmap CompressImage(Bitmap bitmap, double compressRatio) {
int width = (int)(bitmap.Width * compressRatio);
int height = (int)(bitmap.Height * compressRatio);
System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image myThumbnail = bitmap.GetThumbnailImage(width, height, myCallback, IntPtr.Zero);
Bitmap compressBitmap = new Bitmap(myThumbnail);
return compressBitmap;
}
public bool ThumbnailCallback() { return false; }
Base64处理
最常见的用于传输8Bit字节码的编码方式之一,可以将任意一组字节转换为较长的常见文本字符序列,从而可以合法地作为首部字段值
- Base64:一种基于64个可打印字符以及用作后缀的等号来表示二进制数据的方法
- Base64编码:从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息
- 编码规则:每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3个字符变成4个字符,每76个字符加一个换行符,最后的结束符也要处理
其中,64个可打印字符包括:大小写字母、数字、 + 和 / 。相关特点:
- 把含有不可见字符串的信息用可见字符串表示出来、降低出错率,但具有不可读性、需解码
- 二进制序列的长度必须是24的倍数(6和8的最小公倍数)
- 等号一定用作后缀,且数目一定是0个、1个或2个
- 因为将3个字节转化成4个字节,因此编码后的文本,会比原文本大出三分之一左右
['A', 'B', 'C', 'D', ... 'a', 'b', 'c', 'd', ... '0', '1', '2', ... '+', '/']
注意,标准的Base64编码存在 '+'和 '/',针对URL,通过"url safe"的base64编码,将 '+'和 '/' 分别变成 '-'和 '_',同时会删除结果最后的 '='
>>> base64.b64encode('i\xb7\x1d\xfb\xef\xff')
'abcd++//'
>>> base64.urlsafe_b64encode('i\xb7\x1d\xfb\xef\xff')
'abcd--__'
对于二进制序列长度必须是24倍数的解释:正常情况下,只要长度是6的倍数即可。但是,当连接两段Base64编码过的字符串后再解码,这个时候就需要6和8的公倍数,即长度必须是24的倍数。
现在浏览器已有内置的自动生成base64的方法 atob()
和 btoa()
// 编码
window.btoa()
// 解码
window.atob()
具体参见:window.btoa()
;window.atob()
;
注意,待编码字符串若包含中文,直接编码会出现问题,应采用如下方式
function utf8_to_b64( str ) {
return window.btoa(
unescape(
encodeURIComponent( str )));
}
function b64_to_utf8( str ) {
return decodeURIComponent(
escape(
window.atob( str )));
}
参考:
C# - 图片操作和Base64处理的更多相关文章
- bootstrap-wysiwyg 结合 base64 解码 .net bbs 图片操作类
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Dr ...
- EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象
EF+LINQ事物处理 在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...
- JS将图片转换成Base64码
直接上代码 html页面代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- C#——图片操作类简单封装
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Dr ...
- ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave由于鼠标移动速度过快导致问题解决办法
记录两个项目开发中遇到的问题,一个是ECharts外部调用保存为图片操作,一个是workflow工作流连接曲线onmouseenter和onmouseleave事件由于鼠标移动过快触发问题. 一.外部 ...
- 【php学习】图片操作
前两天要对一张图片进行处理,其实很简单,就是在图片上加上字符串,一个图片而已,但是自己如同得了短暂性失忆似的,图片操作的函数一个都想不起来.所以就抽空整理了一下图片操作函数. 图片处理三步走: 创建画 ...
- Android应用程序开发之图片操作(一)——Bitmap,surfaceview,imageview,Canvas
Android应用程序开发之图片操作(一)——Bitmap,surfaceview,imageview,Canvas 1,Bitmap对象的获取 首先说一下Bitmap,Bitmap是Androi ...
- ASP图片格式与base64数据互转方法
ASP图片格式与base64数据相互转换的方法,经常用于处理表单中存储有base64字符串格式的图片. 获取到base64数据,转换成图片 <% Subfolder=year(now)& ...
- 图片转换成Base64编码集成到html文件
首先为什么要这么做? 原因很简单这样可以减少与服务器的请求,当然对于一些浏览器并不支持,如IE8.通常用在手机版网站中,具体转化方法如下: 1.在线打开Base64的编码器将图片编码成Base64 ...
随机推荐
- Nginx源码完全注释(2)ngx_array.h / ngx_array.c
数组头文件 ngx_array.h #include <ngx_config.h> #include <ngx_core.h> struct ngx_array_s { voi ...
- AJAX(XMLHttpRequest)进行跨域请求方法详解
AJAX(XMLHttpRequest)进行跨域请求方法详解(三) 2010年01月11日 08:48:00 阅读数:24213 注意:以下代码请在Firefox 3.5.Chrome 3.0.Saf ...
- JNDI数据源
孤傲苍狼 只为成功找方法,不为失败找借口! JNDI学习总结(一)——JNDI数据源的配置 一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下: ①加载数据库驱动程序(Cla ...
- shiro 集成spring 配置 学习记录(一)
首先当然是项目中需要增加shiro的架包依赖: <!-- shiro --> <dependency> <groupId>org.apache.shiro</ ...
- 原型设计工具Mockplus新年送福利,见者有份
为感谢大家对Mockplus的喜爱与支持,给大家送福利了! 送送送,见者有份! 参与活动,三分钟时间,均可最高获赠专业版1个月使用时间.见者有份! 领福利步骤: 1. 扫码关注微信公众号:Mockpl ...
- 手把手教你看KEGG通路图!
手把手教你看KEGG通路图! 亲爱的小伙伴们,是不是正关注代谢通路研究?或者你正面对数据,绞尽脑汁?小编当然不能让亲们这么辛苦,今天就跟大家分享KEGG代谢通路图的正确解读方法,还在迷糊中的小伙伴赶紧 ...
- js教程系列32 :javascript-DOM节点操作
1 DOM节点操作 1.1 创建节点 createElement() var createDiv = document.createElement("div"); 1.2 插入子节 ...
- HDU 3361 ASCII (水题)
题意: 析:不说话. #include <cstdio> #include <string> #include <cstdlib> #include <cma ...
- 设计模式17:Iterator 迭代器模式(行为型模式)
Iterator 迭代器模式(行为型模式) 动机(Motivation) 在软件构建过程中,集合对象内部结构常常变化各异.但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码可以透 ...
- APUE(4)---文件和目录 (2)
七.函数umask umask函数为进程设置文件模式创建屏蔽字,并返回之前的值,这是少数几个没有出错返回函数中的一个.其中cmask是9个常量(S_IR/W/XUSR.S_IR/W/XGRP.S_IR ...