c# - 为什么保存位图后颜色数量会发生变化?
问题描述
我正在创建一个单一用途的应用程序,它将拍摄一张图像并通过一些 Alpha 通道调整来保存它。调整是使用颜色矩阵进行的,旨在仅更改 Alpha 通道。我希望 otput 在 RGB 值方面与原始值相同。
我正在处理使用 Photoshop 或 After Effects 创建的 32 位 PNG 图像。我在没有任何压缩的情况下保存/渲染文件(至少这是我被告知的)。
这是两个颜色矩阵,可以帮助我说明问题。
ColorMatrix harmlessCm = new ColorMatrix(new float[][]{
new float[]{1, 0, 0, 0, 0},
new float[]{0, 1, 0, 0, 0},
new float[]{0, 0, 1, 0, 0},
new float[]{0, 0, 0, 1, 0},
new float[]{0, 0, 0, 0, 0}});
ColorMatrix luminanceToAlphaCm = new ColorMatrix(new float[][]{
new float[]{1, 0, 0, .2125f, 0},
new float[]{0, 1, 0, .7154f, 0},
new float[]{0, 0, 1, .0721f, 0},
new float[]{0, 0, 0, 0, 0},
new float[]{0, 0, 0, 0, 0}});
情景#1。文件:没有透明区域的 32 位 PNG,颜色数5707。
应用harmlessCm
对颜色数量没有任何影响。
应用 LEDluminanceToAlphaCm
减少颜色数量:1052。
情景#2。文件:具有多个半透明区域(相同图像但没有背景)的 32 位 PNG,颜色数6244。
应用harmlessCm
led减少颜色数量:5990。
应用luminanceToAlphaCm
led减少颜色数量:1470。
全班:
using Microsoft.WindowsAPICodePack.Dialogs;
using Prism.Commands;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace RGBA_Playground.ViewModels
{
class MainViewModel : BaseViewModel
{
public string Before { get; private set; }
public Image After { get; private set; }
public DelegateCommand UploadCommand { get; }
public DelegateCommand SaveCommand { get; }
public MainViewModel()
{
UploadCommand = new DelegateCommand(() =>
{
using (var dialog = new CommonOpenFileDialog())
{
dialog.Multiselect = false;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
var image = dialog.FileName;
Before = image;
After = GetChangedImage(image);
RaisePropertyChanged("Before");
RaisePropertyChanged("After");
}
}
});
SaveCommand = new DelegateCommand(() =>
{
var changedImage = GetChangedImage(Before);
using (Bitmap bm = new Bitmap(changedImage))
{
bm.Save(Path.GetDirectoryName(Before) + "\\" + Path.GetRandomFileName() + ".png", ImageFormat.Png);
}
});
private static Bitmap GetChangedImage(string path)
{
Bitmap original = new Bitmap(path, false);
Bitmap result = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
result.SetResolution(original.HorizontalResolution, original.VerticalResolution);
ColorMatrix cm = new ColorMatrix(new float[][]{
new float[]{1, 0, 0, .2125f, 0},
new float[]{0, 1, 0, .7154f, 0},
new float[]{0, 0, 1, .0721f, 0},
new float[]{0, 0, 0, 0, 0},
new float[]{0, 0, 0, 0, 0}});
using (ImageAttributes ia = new ImageAttributes())
{
ia.SetColorMatrix(cm);
using (Graphics g = Graphics.FromImage(result))
{
g.DrawImage(original,
new Rectangle(0, 0, original.Width, original.Height),
0, 0,
original.Width,
original.Height,
GraphicsUnit.Pixel,
ia);
}
}
return result;
}
}
}
我需要输出在两种情况下具有相同数量的颜色。任何帮助将不胜感激。谢谢!
如果我最初的帖子令人困惑,我很抱歉。另一个编辑:在此处发布之前,我忘记回滚一些编辑。我现在正在使用另一个位图构造函数。
Bitmap result = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
场景和结果也被编辑。
解决方案
回答我自己的问题。那么为什么保存半透明位图后颜色的数量会发生变化呢?
看起来像类Graphics
虽然快速且易于使用,但在处理半透明图像时实际上并不那么精确。我设法通过使用GetPixel()
和SetPixel()
方法获得了预期的结果。由于性能低下、缺乏灵活性等明显的原因,我避免使用它们。但它们完成了工作。
private static Image GetNewImage(string path)
{
Bitmap original = new Bitmap(path);
Bitmap result = new Bitmap(original.Width, original.Height);
for (int x = 0; x < original.Width; x++)
{
for (int y = 0; y < original.Height; y++)
{
var px = original.GetPixel(x, y);
result.SetPixel(x, y, Color.FromArgb((int)GetColorLuminance(px), px.R, px.G, px.B));
}
}
return result;
}
private static float GetColorLuminance(Color color)
{
var R = color.R * .2125f;
var G = color.G * .7154f;
var B = color.B * .0721f;
return R + G + B;
}
推荐阅读
- reactjs - 如何为中心选项卡栏项创建自定义操作
- flutter - Flutter 中的 Markdown 用法
- android - 应用程序终止后保持活动 SMS BroadcastReceiver 类
- c - 为什么在单链表中使用这样的免费?
- linux - 用于用户输入的 Bash 脚本无法正常工作
- database - Qt 与 SQLite 连接错误 QSqlQuery::prepare: database not open with SQLite
- python - sudo权限和python中的运行脚本
- python - dash_html_components 包已弃用。请替换`import dash_html_components as html
- c# - 为什么在依赖解析期间不考虑可选的构造函数参数
- html - 我可以在同一个标签中组合元名称“描述”和属性“og:描述”吗?