博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PNG格式图片常见转换方法
阅读量:7180 次
发布时间:2019-06-29

本文共 7223 字,大约阅读时间需要 24 分钟。

前言

最近碰到一个需要将图片由原始的PNG转化为JPG的需求,由于PNG图片本身质量等原因,导致转化为JPG之后,存在失真的问题,后来一个同事分享了下述的HighQualityPNGToJPG方法解决PNG转JPG失真的问题。

1、准备

using System.Drawing;using System.Net;using System.Drawing.Imaging;/// /// 常见图片格式枚举/// public enum ImageFormatenmu{    jpg,    gif,    bmp,    png}

2、给透明PNG图片添加白色底图

/// /// 透明PNG图片添加白色底图/// /// Png文件路径/// 新Png文件保存路径/// 
public static void AddBlankBaseMap(string pngFilePath, string savePngFilePath){ Bitmap bitmap = new Bitmap(pngFilePath); int w = bitmap.Width; int h = bitmap.Height; Bitmap dstBitmap = new Bitmap(bitmap.Width, bitmap.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); System.Drawing.Imaging.BitmapData srcData = bitmap.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); System.Drawing.Imaging.BitmapData dstData = dstBitmap.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); //不安全代码,编译时需将项目生成操作中添加【允许不安全代码】 unsafe { byte* pIn = (byte*)srcData.Scan0.ToPointer(); byte* pOut = (byte*)dstData.Scan0.ToPointer(); byte* p; int stride = srcData.Stride; int r, g, b, a; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { p = pIn; b = pIn[0]; g = pIn[1]; r = pIn[2]; a = pIn[3]; if (a == 0) { pOut[1] = (byte)255; pOut[2] = (byte)255; pOut[3] = (byte)255; pOut[0] = (byte)255; } else { pOut[1] = (byte)g; pOut[2] = (byte)r; pOut[3] = (byte)a; pOut[0] = (byte)b; } pIn += 4; pOut += 4; } pIn += srcData.Stride - w * 4; pOut += srcData.Stride - w * 4; } bitmap.UnlockBits(srcData); dstBitmap.UnlockBits(dstData); //也可以再这里讲dstBitmap转化为其他类型,如转gif:bitmap.Save(saveFilePath, ImageFormat.Gif) dstBitmap.Save(savePngFilePath); }}

3、根据图片url保存图片

/// /// 根据图片url保存图片/// /// url地址/// 保存本地路径【含文件名,注意扩展名要和url对应文件本身一样,否则可能出错】public static void GetImageByURL(String url, String savePath){    WebClient webClient = new WebClient();    webClient.DownloadFile(url, savePath);}

4、普通PNG格式转换

/// /// 普通PNG格式转换/// /// png文件路径/// 保存文件路径/// 转化格式public static void GeneralPngChange(String pngFilePath,String saveFilePath,ImageFormatenmu imageFromat){    Bitmap bitmap = new Bitmap(pngFilePath);    switch (imageFromat)    {        case ImageFormatenmu.bmp:             {                 bitmap.Save(saveFilePath, ImageFormat.Bmp);            };            break;        case ImageFormatenmu.gif:            {                bitmap.Save(saveFilePath, ImageFormat.Gif);            };            break;        case ImageFormatenmu.jpg:            {                bitmap.Save(saveFilePath, ImageFormat.Jpeg);            };            break;    }}

5、PNG转JPG一般操作方法,可设置图片质量

/// /// PNG转JPG一般操作方法,可设置图片质量/// /// png文件路径/// jpg文件路径/// 图片质量>0public static void GeneralPngToJpg(String pngFilePath, String saveFilePath, long percentage){    Bitmap bmp1 = new Bitmap(pngFilePath);    ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);    System.Drawing.Imaging.Encoder myEncoder =System.Drawing.Imaging.Encoder.Quality;    EncoderParameters myEncoderParameters = new EncoderParameters(1);    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, percentage);    myEncoderParameters.Param[0] = myEncoderParameter;    bmp1.Save(saveFilePath, jgpEncoder, myEncoderParameters);}/// /// 获取图片编码信息/// /// 图片格式MIME类型/// 
private static ImageCodecInfo GetEncoder(ImageFormat format){ ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); foreach (ImageCodecInfo codec in codecs) { if (codec.FormatID == format.Guid) { return codec; } } return null;}

6、高保真PNG转JPG,解决部分PNG转JPG过程中图像失真的问题

/// /// 高保真PNG转JPG,解决部分PNG转JPG过程中图像失真的问题/// 例如:本人将一张透明的PNG转JPG后,JEP图片失真/// /// png文件路径/// jpg文件路径public static void HighQualityPNGToJPG(String pngFilePath, String jpgFilePath){    Image pngImg = Image.FromFile(pngFilePath);    var width = pngImg.Width;    var height = pngImg.Height;    Image bitmap = new System.Drawing.Bitmap(width, height);    Graphics g = System.Drawing.Graphics.FromImage(bitmap);    //设置高质量插值法    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;    g.Clear(Color.White);    //在指定位置并且按指定大小绘制原图片的指定部分    g.DrawImage(pngImg, new Rectangle(0, 0, width, height), new Rectangle(0, 0, width, height), GraphicsUnit.Pixel);    bitmap.Save(jpgFilePath, System.Drawing.Imaging.ImageFormat.Jpeg);    bitmap.Dispose();    g.Dispose();}}

我遇到将一个透明的PNG或一个质量较低的PNG用上述方法转JPG出现失真的问题。

例如:

使用GeneralPngToJpg方法将png图转jpg,透明底图PNG转换情况如下:

图表 1 透明底图PNG

图表 2透明底图PNG转化后的JPG图片【较严重失真】

非透明底图PNG转换情况如下:

图表 3非透明底图PNG

图表 4 非透明底图PNG转JPG【较严重失真】

HighQualityPNGToJPG分别转化透明及非透明低图的PNG,结果如下:

图表 5 非透明底图的PNG格式转化后的JPG

图表 6 透明底图的PNG格式转化后的JPG

7、测试代码

String imageDirectory = string.Format("{0}image/",AppDomain.CurrentDomain.BaseDirectory);//透明PNG图片添加白色底图String transparentPng = Path.Combine(imageDirectory, "transparent.png");String noTransparentPng = Path.Combine(imageDirectory, "noTransparent.png");PngHelp.AddBlankBaseMap(transparentPng, noTransparentPng);//根据图片url保存图片String urlPng=Path.Combine(imageDirectory, "url.png");PngHelp.GetImageByURL("http://image.bitauto.com/dealer/brandgroup/m/389.png", urlPng);//PNG转JPG一般操作方法【存在失真的情况,原因决定于原始PNG图片的质量】String changeJpg=Path.Combine(imageDirectory, "changeJpg.jpg");PngHelp.GeneralPngChange(noTransparentPng, changeJpg,ImageFormatenmu.jpg);String changeBmp = Path.Combine(imageDirectory, "changeBmp.bmp");PngHelp.GeneralPngChange(noTransparentPng, changeBmp, ImageFormatenmu.bmp);String changeGif = Path.Combine(imageDirectory, "changeGif.gif");PngHelp.GeneralPngChange(noTransparentPng, changeBmp, ImageFormatenmu.gif);            //【透明图失真更多】String changeNewJpg = Path.Combine(imageDirectory, "changeNewJpg.jpg");PngHelp.GeneralPngChange(transparentPng, changeNewJpg, ImageFormatenmu.jpg);//PNG转JPG一般操作方法,可设置图片质量String changeJpg0=Path.Combine(imageDirectory, "changeJpg0.jpg");PngHelp.GeneralPngToJpg(noTransparentPng, changeJpg0,0L);String changeJpg50 = Path.Combine(imageDirectory, "changeJpg50.jpg");PngHelp.GeneralPngToJpg(noTransparentPng, changeJpg50, 50L);String changeJpg100 = Path.Combine(imageDirectory, "changeJpg100.jpg");PngHelp.GeneralPngToJpg(noTransparentPng, changeJpg100, 50L);//高保真PNG转JPG,解决部分PNG转JPG过程中图像失真的问题String highqualityJpgFromTrasparent = Path.Combine(imageDirectory, "highqualityJpgFromTrasparent.jpg");String highqualityJpgFromNoTrasparent = Path.Combine(imageDirectory, "highqualityJpgFromNoTrasparent.jpg");PngHelp.HighQualityPNGToJPG(transparentPng, highqualityJpgFromTrasparent);PngHelp.HighQualityPNGToJPG(noTransparentPng, highqualityJpgFromNoTrasparent);

8、完整示例代码

版权说明

作者:

欢迎转载,请注明版权及来源。

 
 
你可能感兴趣的文章
【死磕Java并发】-----J.U.C之AQS:CLH同步队列
查看>>
maven仓库中有jar包pom还报错
查看>>
scp -r拷贝目录不会拷贝软连接
查看>>
WordPress版微信小程序3.1.5版的新功能
查看>>
sqlserver2008导出架构+数据到2005
查看>>
管理 SharePoint Server 2010 的爬网删除策略
查看>>
jQuery-图片上传裁剪插件--imgAreaSelect(分析二) 同步显示图像位置信息
查看>>
TextBox获取焦点清空文本,失去焦点回复文本
查看>>
Qt窗口屏幕居中显示
查看>>
海量小文件存储
查看>>
iOS开发工具——网络封包分析工具Charles
查看>>
MediaWiki隐藏index
查看>>
I2C总线信号时序总结
查看>>
WPF绘制矢量图形模糊的问题
查看>>
jquery checkbox相关 prop方法
查看>>
简析 .NET Core 构成体系
查看>>
Bootstrap IIFE
查看>>
静态链接与动态链接的区别(转载)
查看>>
qt实现头像上传功能
查看>>
第二十三章 springboot + 全局异常处理
查看>>