我想在ColorPalette.Entries中更改大小。如果我喜欢下面,我得到错误。如何以正确的方式更改条目的大小?
Bitmap bm = new Bitmap(Width, Height,PixelFormat.Format8bppIndexed);
var palette = bm.Palette;
var colr = palette.Entries;
Array.Resize(ref colr, 4);
错误:
'ColorPalette.Entries'无法分配 - 它是只读的
答案 0 :(得分:0)
为什么要将8bppIndex的大小从256更改为4?图像中的颜色指示取决于256个索引。你不希望图像中的索引超出范围。如果像素应该是索引5怎么办?太糟糕了,没有Format2bppIndexed
格式。
答案 1 :(得分:0)
我实际上找到了一种方法来做到这一点; png可以有可变大小的调色板,.Net框架在加载文件时不会填充它们。
而且,constructing a png file in a byte array with customised chunks is fairly easy.
使用那里链接的代码(主要是WritePngChunk),这将构造一个包含所需颜色的png,加载它并提取其调色板对象:
private static Byte[] PNG_IDENTIFIER = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
private static Byte[] PNG_BLANK = { 0x08, 0xD7, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01};
/// <summary>
/// Creates a custom-sized color palette by creating an empty png with a limited palette and extracting its palette.
/// </summary>
/// <param name="colors">The colors to convert into a palette.</param>
/// <returns>A color palette containing the given colors.</returns>
public static ColorPalette GetPalette(Color[] colors)
{
// Silliest idea ever, but it works.
const Int32 chunkExtraLen = 0x0C;
Int32 lenPng = PNG_IDENTIFIER.Length;
const Int32 lenHdr = 0x0D;
Int32 lenPal = Math.Min(colors.Length, 0x100) * 3;
Int32 lenData = PNG_BLANK.Length;
Int32 fullLen = lenPng + lenHdr + chunkExtraLen + lenPal + chunkExtraLen + lenData + chunkExtraLen + chunkExtraLen;
Int32 offset = 0;
Byte[] emptyPng = new Byte[fullLen];
Array.Copy(PNG_IDENTIFIER, 0, emptyPng, 0, PNG_IDENTIFIER.Length);
offset += lenPng;
Byte[] header = new Byte[lenHdr];
// Width: 1
header[3] = 1;
// Heigth: 1
header[7] = 1;
// Color depth: 8
header[8] = 8;
// Color type: paletted
header[9] = 3;
WritePngChunk(emptyPng, offset, "IHDR", header);
offset += lenHdr + chunkExtraLen;
// Don't even need to fill this in. We just need the size.
Byte[] palette = new Byte[lenPal];
WritePngChunk(emptyPng, offset, "PLTE", palette);
offset += lenPal + chunkExtraLen;
WritePngChunk(emptyPng, offset, "IDAT", PNG_BLANK);
offset += lenData + chunkExtraLen;
WritePngChunk(emptyPng, offset, "IEND", new Byte[0]);
using (MemoryStream ms = new MemoryStream(emptyPng))
// By doing this afterwards we can ensure the alpha is correct too; the PLTE chunk
// is RGB without alpha, and if there's a tRNS chunk to add alpha, the framework will
// convert the image to 32 bit for some bizarre reason.
using (Bitmap loadedImage = new Bitmap(ms))
{
ColorPalette pal = loadedImage.Palette;
for (Int32 i = 0; i < pal.Entries.Length; i++)
pal.Entries[i] = colors[i];
return pal;
}
}
尽管如此,我不太确定您计划用这张图片实际做。我在Nintendo 64 ROM图像格式上需要此功能以实现转换准确性,但除非您有太多可怕的空间问题,否则调色板大小通常无法发挥作用。
如果您实际编辑图像(可以使用LockBits
和Marshal.Copy
直接操作支持数组),您需要非常小心不要