- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用 BitmapSource 和 PngBitmapEncoder/Decoder 保存和加载 PNG 时遇到问题。基本上,我希望能够保存源自字节数组的图像,并且当 PNG 加载到我的程序中时,重新加载完全相同的字节。原始数据保存很重要。
同时,我希望 PNG 使用自定义调色板(256 种颜色的索引数组)。
我正在尝试使用自定义索引调色板保存我的 8 位数据。原始数据的范围可以是 0-255。调色板可以是“阈值”调色板(例如 0-20 是颜色 #1,21-50 是颜色 #2,等等)。
我发现,当我保存数据、重新加载并执行 CopyPixels 以检索“原始”数据时,数据值是基于调色板设置的,而不是原始字节数组值。
有没有办法在 PNG 中保留原始字节数组,不会丢失自定义调色板?或者是否有不同的方法从 BitmapSource 中检索字节数组?
以下是我的保存例程:
// This gets me a custom palette that is an array of 256 colors
List<System.Windows.Media.Color> colors = PaletteToolsWPF.TranslatePalette(this, false, true);
BitmapPalette myPalette = new BitmapPalette(colors);
// This retrieves my byte data as an array of dimensions _stride * sizeY
byte[] ldata = GetData();
BitmapSource image = BitmapSource.Create(
sizeX,
sizeY,
96,
96,
PixelFormats.Indexed8,
myPalette,
ldata,
_stride);
PngBitmapEncoder enc = new PngBitmapEncoder();
enc.Interlace = PngInterlaceOption.On;
enc.Frames.Add(BitmapFrame.Create(image));
// save the data via FileStream
enc.Save(fs);
这是我的加载例程:
// Create an array to hold the raw data
localData = new byte[_stride * sizeY];
// Load the data via a FileStream
PngBitmapDecoder pd = new PngBitmapDecoder(Fs, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = pd.Frames[0];
// When I look at the byte data, it is *not* the same as my original data
bitmapSource.CopyPixels(localData, _stride, 0);
如有任何建议,我们将不胜感激。谢谢。
附录 #1:我发现问题的一部分是 PNG 被保存为 32 位颜色,尽管我将它设置为 Indexed8 并使用 256 项调色板。这似乎也取决于设置的调色板。知道为什么吗?
最佳答案
我知道为什么您的 PNG 文件以高颜色保存。事实上,它们不是“保存为高色的 8 位图像”;问题是,从它们包含透明度的那一刻起,它们就被 .Net 框架加载为高色。图像本身非常好,只是框架把它们弄乱了。
这里发布了解决方法:
A: Loading an indexed color image file correctly
As wip said但是,如果您想保留原始字节,调色板的实际更改应该使用 block 来完成,而不是通过 .Net 图形类,因为 .Net 重新编码将不可避免地更改字节。而且,有趣的是,我刚刚提供的调色板问题修复程序已经包含了您为此所需的一半代码,即 block 读取代码。
block 编写代码将是这样的:
/// <summary>
/// Writes a png data chunk.
/// </summary>
/// <param name="target">Target array to write into.</param>
/// <param name="offset">Offset in the array to write the data to.</param>
/// <param name="chunkName">4-character chunk name.</param>
/// <param name="chunkData">Data to write into the new chunk.</param>
/// <returns>The new offset after writing the new chunk. Always equal to the offset plus the length of chunk data plus 12.</returns>
private static Int32 WritePngChunk(Byte[] target, Int32 offset, String chunkName, Byte[] chunkData)
{
if (offset + chunkData.Length + 12 > target.Length)
throw new ArgumentException("Data does not fit in target array!", "chunkData");
if (chunkName.Length != 4)
throw new ArgumentException("Chunk must be 4 characters!", "chunkName");
Byte[] chunkNamebytes = Encoding.ASCII.GetBytes(chunkName);
if (chunkNamebytes.Length != 4)
throw new ArgumentException("Chunk must be 4 bytes!", "chunkName");
Int32 curLength;
ArrayUtils.WriteIntToByteArray(target, offset, curLength = 4, false, (UInt32)chunkData.Length);
offset += curLength;
Int32 nameOffset = offset;
Array.Copy(chunkNamebytes, 0, target, offset, curLength = 4);
offset += curLength;
Array.Copy(chunkData, 0, target, offset, curLength = chunkData.Length);
offset += curLength;
UInt32 crcval = Crc32.ComputeChecksum(target, nameOffset, chunkData.Length + 4);
ArrayUtils.WriteIntToByteArray(target, offset, curLength = 4, false, crcval);
offset += curLength;
return offset;
}
我使用的Crc32.ComputeChecksum
函数是the Sanity Free Coding CRC implementation 的数组内改编。 .使其适应给定数组内的可变开始和长度应该不难。
字节写入类 ArrayUtils
是我制作的一个工具集,用于从具有指定字节序的数组读取值和写入值。它在 this answer 末尾发布在 SO 上.
关于c# - 使用 BitmapSource、PngBitmapEncoder/Decoder 时,在 PNG 中保存 8 位索引数据会改变原始字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12306114/
我正在使用此代码将 jpg 图像转换为 png 8。代码有效,但图像看起来有颗粒感。我在 Photoshop 中导出为 png 8,它看起来更平滑且没有颗粒。 注意:8位png 有没有图像专家可以提供
我们的 .NET 应用程序能够生成 .png 文件,这些文件是 WPF Canvas 的屏幕截图。 这可以从客户端触发并由我们的另一个应用程序处理(本质上是将作业外包给它排队和处理的东西)可以在另一台
我在使用 BitmapSource 和 PngBitmapEncoder/Decoder 保存和加载 PNG 时遇到问题。基本上,我希望能够保存源自字节数组的图像,并且当 PNG 加载到我的程序中时,
我是一名优秀的程序员,十分优秀!