gpt4 book ai didi

c# - 绘制 8bpp 位图时如何使调色板中的颜色透明

转载 作者:行者123 更新时间:2023-12-04 01:08:46 24 4
gpt4 key购买 nike

我有一个 8bpp 索引位图,带有自定义的 256 色调色板,其中调色板中的特定颜色( Color.PinkColor.Green )表示透明度。
我可以使用 MakeTransparent(color)位图上的方法(每种颜色两次),但它将其转换为 32bpp。所以我使用:

using var imageAttr = new ImageAttributes();
imageAttr.SetColorKey(pink, pink, ColorAdjustType.Default);
进而
g.DrawImage(bitmap, destRect, X, Y, Width, Height, GraphicsUnit.Pixel, imageAttr);
它按原样绘制位图,但仅进行更改 Color.Pink到透明的颜色。对于第二种颜色( Color.Green ),我该如何做到这一点?

最佳答案

两者 ImageAttributes.SetColorKey()Bitmap.MakeTransparent不是您需要时的首选重新映射 位图调色板的索引颜色:前者一次只能设置一种颜色,后者将原始图像转换为 32bpp 图像。
您需要更改索引图像 ColorPalette或使用 ImageAttributes.SetRemapTable() 绘制新的位图方法。此方法接受一个数组 ColorMap对象。 ColorMap 用于指定在绘制位图时替换旧颜色的新颜色。

让我们制作一个示例 8bpp 图像并应用部分调色板,然后使用 Image.LockBits解析 BitmapData并将这些颜色应用于一组 3x3 矩形:

var image = new Bitmap(12, 12, PixelFormat.Format8bppIndexed);
var palette = image.Palette; // Copy the Palette entries
palette.Entries[0] = Color.SteelBlue;
palette.Entries[1] = Color.Pink;
palette.Entries[2] = Color.Red;
palette.Entries[3] = Color.Orange;
palette.Entries[4] = Color.YellowGreen;
palette.Entries[5] = Color.Khaki;
palette.Entries[6] = Color.Green;
palette.Entries[7] = Color.LightCoral;
palette.Entries[8] = Color.Maroon;
image.Palette = palette; // Sets back the modified palette

var data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.WriteOnly, image.PixelFormat);

int rectsCount = 3; // Generate 3 Rectangles per line...
int step = data.Stride / rectsCount; // ...of this size (single dimension, since w=h here)
int colorIdx = 0, col = 0; // Color and Column positions

byte[] buffer = new byte[data.Stride * image.Height];

for (int i = 1; i <= rectsCount; i++) {
for (int y = 0; y < data.Height; y++) {
for (int x = col; x < (step * i); x++) {
buffer[x + y * data.Stride] = (byte)colorIdx;
}
colorIdx += (y + 1) % step == 0 ? 1 : 0;
}
col += step;
}

Marshal.Copy(buffer, 0, data.Scan0, buffer.Length);
image.UnlockBits(data);
这会生成这个有趣的图像(缩放 x25):
ImageAttributes SetColorMap Original Colors
现在,您要使调色板中的两种颜色透明: Color.PinkColor.Green .
您可以构建一个数组 ColorMap指定哪些新颜色替换现有颜色的对象:
var mapPink = new ColorMap() { OldColor = Color.Pink, NewColor = Color.Transparent };
var mapGreen = new ColorMap() { OldColor = Color.Green, NewColor = Color.Transparent };
var colorMap = new ColorMap[] { mapPink, mapGreen };
然后:
  • 或者用新的映射颜色替换图像调色板中的每个颜色:
    (请注意,我没有直接传递 [Image].Palette 对象,我使用的是之前创建的调色板副本( var palette = image.Palette; ):如果直接传递图像调色板,则不会注册更改)
  • private ColorPalette RemapImagePalette(ColorPalette palette, ColorMap[] colorMaps)
    {
    for (int i = 0; i < palette.Entries.Length; i++) {
    foreach (ColorMap map in colorMaps) {
    if (palette.Entries[i] == map.OldColor) {
    palette.Entries[i] = map.NewColor;
    }
    }
    }
    return palette;
    }

    // [...]

    var palette = image.Palette;
    image.Palette = RemapImagePalette(palette, colorMap);
  • 或者生成一个新的位图,使用 ImageAttributes.SetRemapTable()方法并使用 使用新的颜色图绘制索引图像Graphics.DrawImage() 接受 ImageAttributes 的方法参数:
  • private Bitmap ImageRemapColors(Image image, Size newSize, ColorMap[] map)
    {
    var bitmap = new Bitmap(newSize.Width, newSize.Height);

    using (var g = Graphics.FromImage(bitmap))
    using (var attributes = new ImageAttributes()) {
    if (map != null) attributes.SetRemapTable(map);

    g.InterpolationMode = InterpolationMode.NearestNeighbor;
    g.PixelOffsetMode = PixelOffsetMode.Half;
    g.DrawImage(image, new Rectangle(Point.Empty, newSize),
    0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
    }
    return bitmap;
    }

    // [...]

    // Draws the 12x12 indexed 8bpp Image to a new 300x300 32bpp Bitmap
    Bitmap remappedImage = ImageRemapColors(image, new Size(300, 300), colorMap);
    这些方法生成相同的输出。
  • 一个可用于更改索引图像格式的调色板。
  • 另一种是在设备上下文中显示具有重新映射颜色的图像(例如,将位图分配给控件的图像属性)。
  • [额外] 另一种选择是使用 TextureBrush,如下所示:
    How to draw a transparent shape over an Image

  • ImageAttributes SetColorMap Remapped Colors

    关于c# - 绘制 8bpp 位图时如何使调色板中的颜色透明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65489188/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com