【C#】PNG 和 JPG、JPEG的应用以及三种格式的区别?
PNG(Portable Network Graphics)、JPG(也称为JPEG,Joint Photographic Experts Group)是两种常用的图像文件格式,它们各有特点,适用于不同的场景。
三种格式的区别
-
压缩方式:
- PNG:采用无损压缩算法。这意味着无论你保存、编辑多少次,图像质量都不会下降。
- JPG/JPEG:使用有损压缩算法。在保存为JPG时,你可以选择压缩比例,更高的压缩率意味着更小的文件大小,但同时也会导致图像质量下降。
-
透明度支持:
- PNG:支持透明度。PNG有两种主要形式:PNG-8(支持256色和一个透明通道)和PNG-24(支持全彩色和一个alpha通道,允许不同程度的透明)。这使得它非常适合用于需要背景透明效果的图像,如网站图标、标志等。
- JPG/JPEG:不支持透明度。所有JPG图像都必须有一个背景颜色(通常为白色或其它纯色),因此不适合需要透明背景的应用场景。
-
用途:
- PNG:由于其无损质量和对透明度的支持,常用于保存图形设计、文本较多的图像、需要高质量输出的设计稿以及任何需要透明背景的场合。
- JPG/JPEG:因其高效的压缩比,适合用来存储色彩丰富的照片或复杂的图像,特别是在网络上传输或展示时,因为这些场景往往更看重文件大小而非绝对的图像质量。
在处理图像时关于透明度的区别
当你处理包含透明区域的图像时,PNG格式通常是首选,因为它可以准确地保存透明度信息。而JPG格式则无法保存透明度信息,如果你将一个具有透明背景的PNG图像另存为JPG格式,软件通常会要求你指定一种背景颜色来填充原本透明的部分。
综上所述,在需要保持最佳图像质量和/或透明背景的情况下,PNG是一个更好的选择;而在追求较小文件尺寸且不需要透明背景的照片存储中,JPG更为合适。
在C#中PNG 和 JPG、JPEG的应用
在C#中处理PNG和JPG/JPEG图像时,通常会使用到System.Drawing
命名空间(或较新的System.Drawing.Common
),以及可能的第三方库如ImageSharp等。从.NET Core 3.0开始,System.Drawing.Common
成为了跨平台处理图像的标准方式,但需要注意的是自.NET 6起,微软建议在非Windows平台上使用其他库,因为System.Drawing.Common
在Linux和macOS上的实现依赖于GDI+,这可能会带来兼容性问题。
使用System.Drawing.Common
处理图像
以下是使用System.Drawing.Common
库加载、保存PNG和JPEG图像的基本示例:
加载和保存图像
using System;
using System.Drawing;
using System.Drawing.Imaging;class Program
{static void Main(){// 加载一个PNG或JPG图像using (Image image = Image.FromFile("example.png")){// 保存为PNG格式image.Save("output.png", ImageFormat.Png);// 保存为JPG格式,并设置质量var encoderParams = new EncoderParameters(1);encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 90L); // 设置JPEG质量为90ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);image.Save("output.jpg", jpgEncoder, encoderParams);}}private static ImageCodecInfo GetEncoder(ImageFormat format)
{ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();foreach (ImageCodecInfo codec in codecs){if (codec.FormatID == format.Guid){return codec;}}return null;
}
}
处理透明度
- PNG:当你处理需要保留透明背景的图像时,可以无损地保存为PNG格式。使用
ImageFormat.Png
作为保存格式即可。 - JPEG:由于JPEG不支持透明度,所有透明区域将会被填充为某种颜色(通常是白色)。如果你尝试将具有透明度的PNG图像保存为JPEG格式,必须决定如何处理这些透明部分。
编码器 | 像素格式 | 透明通道 | 背景色 |
---|---|---|---|
JpegBitmapEncoder | 不支持透明(Alpha=1) | 强制不透明 | 未初始化的像素为 黑色 (0,0,0) |
PngBitmapEncoder | 支持透明 | 使用 Pbgra32 等格式 | 未绘制区域 Alpha=0(透明),但显示时背景为白色(取决于查看器) |
总之,在C#中处理PNG和JPG/JPEG图像主要涉及到正确使用System.Drawing.Common
中的类和方法来加载、修改和保存图像文件。对于更高级的需求,比如复杂的图像处理或在非Windows平台上更好的兼容性,考虑使用如ImageSharp这样的第三方库可能是明智的选择。
在C#中处理PNG图像的透明部分,通常涉及到使用System.Drawing
或System.Drawing.Common
命名空间中的类。以下是一些基本的操作方法,包括如何创建带有透明度的图像、如何设置图像区域为透明以及如何保存包含透明度的PNG文件。
创建带有透明背景的图像
当你创建一个新的图像时,可以通过指定像素格式来包含透明度支持:
using System.Drawing;
using System.Drawing.Imaging;// 创建一个32位带有Alpha通道(透明度)的新Bitmap对象
Bitmap bitmap = new Bitmap(100, 100, PixelFormat.Format32bppArgb);// 获取图形上下文
Graphics g = Graphics.FromImage(bitmap);// 设置背景颜色为完全透明
g.Clear(Color.Transparent);
处理现有图像的透明部分
对于已经存在的PNG图像,如果你想要修改其透明度或者将某个颜色替换为透明,可以这样做:
using (Bitmap bitmap = new Bitmap("input.png"))
{for (int x = 0; x < bitmap.Width; x++){for (int y = 0; y < bitmap.Height; y++){Color pixelColor = bitmap.GetPixel(x, y);// 假设我们想将纯绿色变为透明if (pixelColor.R == 0 && pixelColor.G == 255 && pixelColor.B == 0){bitmap.SetPixel(x, y, Color.FromArgb(0)); // 完全透明}}}// 保存结果,注意要保存为PNG以保留透明度bitmap.Save("output.png", ImageFormat.Png);
}
背景默认填充色
JPEG 格式本身并不支持透明度,因此在将包含透明区域的图像保存为 JPEG 时,这些透明区域需要被某种颜色填充。默认情况下,不同的软件和库可能会以黑色或白色来填充这些透明区域,但这并不是由 JPEG 标准本身决定的,而是具体实现的选择。
黑色或白色作为默认填充色
-
默认行为:当使用某些工具或库(例如你提到的
JpegBitmapEncoder
)将具有透明度的图像转换为 JPEG 格式时,透明部分通常会被填充为黑色或者白色。这种选择通常是库或工具开发者所做的一个设计决策,并不是固定的规则。 -
为什么是黑色或白色?
- 黑色:一些实现可能选择黑色作为默认填充色,因为这可以避免与浅色背景混合时产生强烈的对比,尤其是在图像编辑和视频处理中。
- 白色:另一方面,白色有时也被用作默认填充色,特别是在网页设计或其他需要明亮背景的应用场景中。
自定义填充色
对于想要自定义这个填充色(例如设定为黑色或白色,甚至是其他颜色),你需要在将图像编码为 JPEG 之前手动填充透明区域。以下是大致步骤:
- 创建一个新的位图,其大小与原图相同,并且背景色为你希望的填充色(比如黑色或白色)。
- 将原始图像绘制到这个新的位图上。这样做会覆盖掉新的位图中的相应部分,而任何未被覆盖的部分(即原图中的透明区域)将保留你所选的颜色。
- 使用
JpegBitmapEncoder
或类似的工具将这个新生成的位图保存为 JPEG 文件。
这种方法允许你在保存 JPEG 文件之前控制如何处理图像的透明区域,包括选择任何你希望的填充颜色。
想将透明区域填充为黑色,然后保存为 JPEG:
// 假设 originalBitmap 是你的原始 BitmapSource
var blackBackgroundBitmap = new RenderTargetBitmap(originalBitmap.PixelWidth, originalBitmap.PixelHeight, 96, 96, PixelFormats.Pbgra32);
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext dc = drawingVisual.RenderOpen())
{// 先画一个黑色背景dc.DrawRectangle(Brushes.Black, null, new Rect(0, 0, originalBitmap.Width, originalBitmap.Height));// 然后绘制你的原始图像dc.DrawImage(originalBitmap, new Rect(0, 0, originalBitmap.Width, originalBitmap.Height));
}
blackBackgroundBitmap.Render(drawingVisual);// 接下来使用 JpegBitmapEncoder 保存 blackBackgroundBitmap
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(blackBackgroundBitmap));
using (var fileStream = new FileStream("output.jpg", FileMode.Create))
{encoder.Save(fileStream);
}
使用白色填充透明区域
如果你想要使用白色来填充透明区域,只需将上面代码中的 Brushes.Black
替换为 Brushes.White
:
// 绘制一个白色背景代替黑色背景 dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, originalBitmap.Width, originalBitmap.Height));
通过这种方式,你可以根据需要选择任何颜色作为背景色来填充透明区域。只需要更改DrawRectangle
方法中使用的画刷(Brush)即可。这样,在最终保存为JPEG格式时,原本透明的部分就会被你选择的颜色所替代。
注意事项
- PixelFormat:确保使用支持透明度的像素格式(如
Format32bppArgb
),以便正确处理透明度。 - 保存格式:由于JPEG不支持透明度,因此当处理需要透明背景的图像时,请使用PNG格式进行保存。
- 性能考虑:
GetPixel
和SetPixel
方法对于大量操作来说效率较低。对于性能敏感的应用,可以考虑使用LockBits
方法直接访问图像数据,但这要求更复杂的代码处理。
jpg、bmp、png图像的位深度分别有多少种?分别表示什么意思?如果操作时需要注意什么?_png 位深度-CSDN博客文章浏览阅读8.5k次,点赞30次,收藏22次。C#语言操作 jpg、bmp、png图像的位深度分别有多少种?分别表示什么意思?如果操作时需要注意什么?_png 位深度https://blog.csdn.net/wangnaisheng/article/details/137332692C# Bitmap转换为jpg、bmp、png、gif图片_c# bitmap 保存图片jpg-CSDN博客文章浏览阅读4.7k次。该代码示例展示了如何使用C#将Bitmap对象转换为不同格式的图片,包括JPG、BMP、PNG和GIF。通过检查文件后缀并使用ImageFormat和ImageCodecInfo类,程序能保存图片到指定格式,并支持设置JPEG的质量参数。
https://blog.csdn.net/wangnaisheng/article/details/129838880?spm=1011.2415.3001.5331