2010-04-07 85 views
3

我试图编辑8bpp的像素。由于这PixelFormat索引,我知道它使用颜色表来映射像素值。尽管我可以通过将位图转换为24bpp来编辑位图,但8bpp编辑速度更快(13ms vs 3ms)。但是,访问8bpp位图时更改每个值会导致一些随机的rgb颜色,即使PixelFormat保持8bpp。编辑8bpp索引位图

我目前正在开发在C#和算法如下:

(C#)在8bpp的

2-

1-加载原始位图与和8bpp的创建空临时位图与原始大小相同

这两个位图的3-LockBits以及使用P/Invoke调用每个BitmapData对象的Scan0的C++方法。 (I使用C++方法通过位图的像素迭代时,因为它提供更好的性能)

(C++)

4-创建INT根据一些参数[256]调色板和通过使编辑临时位图字节原始像素值通过调色板。

(C#)

5- UnlockBits。

我的问题是如何编辑像素值,而不会有奇怪的RGB颜色,甚至更好,编辑8bpp位图的颜色表?

回答

1

您是否试过加载System.Drawing.Image?该课程可让您访问调色板。一旦设置了调色板,您就可以将System.Drawing.Image作为System.Drawing.Bitmap包装起来。

我不确定System.Drawing.BitMap.SetPixel()如何与索引的彩色图像一起使用。它可能会尝试将其映射到调色板中最接近的颜色。

+0

感谢您的回答。我知道我可以通过更改位图的调色板属性来修改位图的调色板。但是这样做太慢了。我希望有人能告诉我如何访问颜色表指针,以便我可以直接修改它。 SetPixel不起作用,也非常缓慢。 我不明白为什么像素被分配了rgb颜色,当我将其值从0(黑色)更改为100(应该是灰色,但是是红色)。 – 2010-04-07 15:20:15

+0

嗯。 'Bitmap'从'Image'继承,因此具有相同的调色板。你可以简单地用'bm2.Palette = bm1.Palette'复制调色板。 – Nyerguds 2018-01-22 21:48:04

10

有没有必要进入C++土地或使用P/Invoke; C#支持指针和不安全的代码完美无瑕;我甚至可能会猜测这是造成你的问题。

颜色可能来自默认的调色板。你会发现改变调色板应该不会很慢。这是我做的,以创建一个灰度调色板:

image = new Bitmap(_size.Width, _size.Height, PixelFormat.Format8bppIndexed); 
ColorPalette pal = image.Palette; 
for(int i=0;i<=255;i++) { 
    // create greyscale color table 
    pal.Entries[i] = Color.FromArgb(i, i, i); 
} 
image.Palette = pal; // you need to re-set this property to force the new ColorPalette 
+0

如何将新调色板应用于旧图像?如何改变旧图像的大小? – Leon 2012-07-18 10:55:35

+1

只需设置“调色板”属性。调整图像大小是不同的,在右边的dumensions的新图像上使用'Graphics.DrawImage'。 – Dai 2013-05-28 06:59:55

+0

Graphics.DrawImage在索引的像素格式上不受支持,并且转换为非索引会否定使用索引格式的速度优势。 – Nuzzolilo 2016-02-17 00:44:21

2

试想一下,你的索引8ppp graysacle存储的线性阵列在数据B(速度)

试试这个代码:

//Create 8bpp bitmap and look bitmap data 
bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed); 
bmp.SetResolution(horizontalResolution, verticalResolution); 
bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 

//Create grayscale color table 
ColorPalette palette = bmp.Palette; 
for (int i = 0; i < 256; i++) 
    palette.Entries[i] = Color.FromArgb(i, i, i); 
bmp.Palette = palette; 

//write data to bitmap 
int dataCount = 0; 
int stride = bmpData.Stride < 0 ? -bmpData.Stride : bmpData.Stride; 
unsafe 
{ 
    byte* row = (byte*)bmpData.Scan0; 
    for (int f = 0; f < height; f++) 
    { 
     for (int w = 0; w < width; w++) 
     { 
      row[w] = (byte)Math.Min(255, Math.Max(0, dataB[dataCount])); 
      dataCount++; 
     } 
     row += stride; 
    } 
} 

//Unlock bitmap data 
bmp.UnlockBits(bmpData); 
0

我没有足够的声望评论Paul Ruane的帖子,但不得不说他将文件加载到System.Drawing.Image的方法,改变调色板并将生成的图像发送到System.Drawing.Bitmap以保存实际的作品。

>如果我直接通过Image进行保存,则更改将被丢弃。

>如果通过Bitmap保存,则更改将保留。