我的问题是何时拍摄8位灰度图像并将其转换为24位rgb24bpp我的图像会放大并且色阶会混淆(请参阅3)。 我的计划是通过客户端 - 服务器实现在我的程序中显示GigE-Cam。因此,由于日期问题,我需要将图片变得灰度化,但我只能得到这个错误尺寸和相应的图片。只有当我将它们转换为myImage / myImageFormat时才会发生这种情况。我的问题是我之后需要测量图片。
我用来转换图像的代码如下:
public myImage(Bitmap bmp, myImageFormat format)
{
if (bmp == null)
{
throw new ArgumentNullException("bmp");
}
this.Height = bmp.Height;
this.Width = bmp.Width;
this.Format = format;
// copy bmp matrix without padding to rgb or grey array
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
//if (format == myImageFormat.Grey8)
//{ return; }
//else
//{
int factor = 3;
if (format == myImageFormat.Grey8)
{
factor = 1;
// save grey scale palette
m_colorPaletteColorData = new Color[bmp.Palette.Entries.Length];
for (int i = 0; i < bmp.Palette.Entries.Length; i++)
{
m_colorPaletteColorData[i] = bmp.Palette.Entries[i];
}
//return;
}
else if (format == myImageFormat.Rgb888
&& bmp.PixelFormat == PixelFormat.Format8bppIndexed)
{
// convert all type of bitmaps to 24-Bit bitmaps by using GDI+
Bitmap bmp24 = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format24bppRgb);
bmp24.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution); // prevent resolution conversion
using (Graphics g = Graphics.FromImage(bmp24))
{
g.PageUnit = GraphicsUnit.Pixel; // prevent DPI conversion
g.DrawImageUnscaled(bmp, 0, 0, bmp.Width, bmp.Height);
}
bmp = bmp24;
}
BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat); // LOCKED
int bytes = bmp.Height * bmp.Width * factor;
int byteIndex = 0;
m_imageData = new byte[bytes];
unsafe
{
for (int y = 0; y < bmpData.Height; y++)
{
byte* row = (byte*)bmpData.Scan0 + (y * bmpData.Stride);
for (int x = 0; x < bmpData.Width; x++)
{
m_imageData[byteIndex] = row[x * factor];
byteIndex++;
if (format == myImageFormat.Rgb888)
{
m_imageData[byteIndex] = row[x * factor + 1];
byteIndex++;
m_imageData[byteIndex] = row[x * factor + 2];
byteIndex++;
}
}
}
}
bmp.UnlockBits(bmpData); // UNLOCKED
//}
}
/// <summary>
/// returns a 8bppGrey or 24bppRgb Bitmap
/// </summary>
public Bitmap ToBitmap()
{
if (m_imageData == null)
{
throw new InvalidOperationException("Internal image data does not exist!");
}
PixelFormat pixelFormat;
int factor = 3;
if (this.Format == myImageFormat.Grey8)
{
pixelFormat = PixelFormat.Format8bppIndexed;
factor = 1;
}
else
{
pixelFormat = PixelFormat.Format24bppRgb;
}
m_bmp = new Bitmap(this.Width, this.Height, pixelFormat);
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
BitmapData bmpData = m_bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat); // LOCKED
int counter = 0;
unsafe
{
for (int y = 0; y < bmpData.Height; y++)
{
byte* row = (byte*)bmpData.Scan0 + (y * bmpData.Stride);
for (int x = 0; x < bmpData.Width; x++)
{
byte color = m_imageData[counter];
row[x * factor] = color;
counter++;
if (this.Format == myImageFormat.Rgb888)
{
row[x * factor + 1] = m_imageData[counter];
counter++;
row[x * factor + 2] = m_imageData[counter];
counter++;
}
}
}
}
// copy original grayscale color palette, otherwise it will be a 8bit RGB bitmap
if (this.Format == myImageFormat.Grey8)
{
ColorPalette palette = m_bmp.Palette;
Color[] entries = palette.Entries;
if (m_colorPaletteColorData.Length >= entries.Length)
{
for (int i = 0; i < entries.Length; i++)
{
entries[i] = m_colorPaletteColorData[i];
}
}
m_bmp.Palette = palette;
}
m_bmp.UnlockBits(bmpData); // UNLOCKED
return m_bmp;
}
任何人都可以帮我解决这个问题吗?
答案 0 :(得分:0)
如果传入24位位图以转换为8位灰色,则无法复制有效的源调色板,因为24位格式未编入索引。因此,当您将调色板从24位源图像(在构造函数中)保存到m_colorPaletteColorData[]
然后将其设置在8位灰度图像(在ToBitmap()中)时,该调色板实际包含什么?在构造函数中,当源是24位(因此没有有效的调色板)时,您需要创建一个新的灰度调色板,而不是尝试将其从非索引图像中复制出来。
另一个小点,当在两个方向(8到24,24到8)进行转换时,您可以直接将一个图像的字节分配给另一个图像;因此,如果一个是打算调色的8位图像,另一个是24位图像,则指定一个调色板索引作为颜色分量的每个R,G和B值,或指定一个color component作为索引。
如果调色板保证是线性渐变,其中每个索引与灰度阴影相匹配,但是基于调色板的图像很少使用完美组织的调色板,所以这是一个危险的假设。为了使其正常工作,您应该在分配到24位图像之前将8位索引值转换为调色板中的颜色值,并在分配时从24位值中查找调色板中最接近的匹配项到8位灰度图像。