C# 从一种像素格式转换为另一种WPF
我知道这听起来很琐碎,但我现在已经卡住了 我有各种格式的图像作为输入。灰色16、灰色8、索引8等等。我需要的是将它们转换为RGB24格式,到目前为止我已经完成了这项工作C# 从一种像素格式转换为另一种WPF,c#,bitmap,pixelformat,C#,Bitmap,Pixelformat,我知道这听起来很琐碎,但我现在已经卡住了 我有各种格式的图像作为输入。灰色16、灰色8、索引8等等。我需要的是将它们转换为RGB24格式,到目前为止我已经完成了这项工作 public WriteableBitmap ConvertToRgb(WriteableBitmap source) { <-- create the new bitmap of the same width/height as the source with specific R
public WriteableBitmap ConvertToRgb(WriteableBitmap source)
{
<-- create the new bitmap of the same width/height as the source with specific RGB24 format-->
var newBitmap = new WriteableBitmap(source.PixelWidth, source.PixelHeight, source.DpiX, source.DpiY, PixelFormats.Rgb24, source.Palette);
<-- create my pixel array -->
byte[] pixels = new byte[
source.PixelHeight * source.PixelWidth *
source.Format.BitsPerPixel / 8];
<-- copy my original pixels into the array) -->
source.CopyPixels(pixels, source.PixelWidth * source.Format.BitsPerPixel / 8, 0);
<-- write the pixels into the new image -->
newBitmap.WritePixels(
new Int32Rect(0, 0, newBitmap.PixelWidth, newBitmap.PixelHeight),
pixels,
newBitmap.PixelWidth * newBitmap.Format.BitsPerPixel/8,
0);
return newBitmap;
}
public WriteableBitmap转换器GB(WriteableBitmap源)
{
var newBitmap=new WriteableBitmap(source.PixelWidth、source.PixelHeight、source.DpiX、source.DpiY、PixelFormats.Rgb24、source.palete);
字节[]像素=新字节[
source.PixelHeight*source.PixelWidth*
source.Format.BitsPerPixel/8];
source.CopyPixels(像素,source.PixelWidth*source.Format.BitsPerPixel/8,0);
newBitmap.WritePixels(
新的Int32Rect(0,0,newBitmap.PixelWidth,newBitmap.PixelHeight),
像素,
newBitmap.PixelWidth*newBitmap.Format.BitsPerPixel/8,
0);
返回newBitmap;
}
此方法引发异常“缓冲区大小不足”
我想这和我的WritePixels参数有关。但我不知道缓冲区的正确大小。我找不到太多的文档。任何帮助都很好
我用于转换的方法不是确定的,如果您知道更好的转换方法,请告诉我。首先:RGB图像的默认格式是(与直觉相反)BGR24或BGRA32,用于ARGB。这是因为系统() 第二:使用这种方法时,根本不会转换像素格式。您只需获取所有像素,将它们转换为字节数组,并将这些字节用于新的像素格式-这将以完全不同的方式解释字节。因此,如果源图像位于BGRA中,并转换为RGB24,则第一个源像素的蓝色分量将被解释为第一个目标像素的红色分量,依此类推-第一个源alpha字节将被解释为第二个像素的第一个红色字节(不完全正确,但更容易理解。正确的映射是a>b,r>g,g>r,r>b2…因为颜色如何映射到与其命名方式正好相反的字节)。这也是缓冲区大小不匹配的原因,因为不同的像素格式需要不同的字节数 WriteableBitmap的CopyPixels和WritePixels完全不知道底层的PixelFormat,并完全忽略它。只有在源和目标具有完全相同的PixelFormat和调色板,或者您手动重新计算和重新排列缓冲区中的所有字节时,这才有效 您要查找的内容更简单:它被称为。这是一个位图源,特别用于更改图像的像素格式。下面这行应该可以将所有内容转换为正确的RGBA32图像(仅对RGB使用Bgr24)
所以经过多次尝试,我找到了答案
public WriteableBitmap ConvertToRgb(WriteableBitmap source)
{
var newBitmap = new WriteableBitmap(source.PixelWidth, source.PixelHeight, source.DpiX, source.DpiY, PixelFormats.Rgb24, null);
byte[] pixels = new byte[
source.PixelHeight * source.PixelWidth *
source.Format.BitsPerPixel / 8];
source.CopyPixels(pixels, source.PixelWidth * source.Format.BitsPerPixel / 8, 0);
byte[] newPixels = new byte[newBitmap.PixelWidth * newBitmap.PixelHeight * newBitmap.Format.BitsPerPixel / 8];
var pixelCounter = 0;
var colorArray = source.Palette != null ? source.Palette.Colors.ToArray() : BitmapPalettes.Gray256.Colors.ToArray();
foreach (var pixel in pixels)
{
newPixels[pixelCounter] = colorArray[pixel].R;
pixelCounter++;
newPixels[pixelCounter] = colorArray[pixel].G;
pixelCounter++;
newPixels[pixelCounter] = colorArray[pixel].B;
pixelCounter++;
}
newBitmap.WritePixels(
new Int32Rect(0, 0, newBitmap.PixelWidth, newBitmap.PixelHeight),
newPixels,
newBitmap.PixelWidth * newBitmap.Format.BitsPerPixel / 8,
0);
return newBitmap;
}
基本上,问题在于步幅和新像素阵列的尺寸。这是一个完全可以工作的转换功能。如果您不需要/不想自己做图像的低级工作,有几个选项可以处理几乎所有的图像处理任务。我将尝试,主要是我将使用Gray16、Gray8和索引8格式作为我的源。我必须将它们转换为RGB,因为以后我必须重叠图像。
public WriteableBitmap ConvertToRgb(WriteableBitmap source)
{
var newBitmap = new WriteableBitmap(source.PixelWidth, source.PixelHeight, source.DpiX, source.DpiY, PixelFormats.Rgb24, null);
byte[] pixels = new byte[
source.PixelHeight * source.PixelWidth *
source.Format.BitsPerPixel / 8];
source.CopyPixels(pixels, source.PixelWidth * source.Format.BitsPerPixel / 8, 0);
byte[] newPixels = new byte[newBitmap.PixelWidth * newBitmap.PixelHeight * newBitmap.Format.BitsPerPixel / 8];
var pixelCounter = 0;
var colorArray = source.Palette != null ? source.Palette.Colors.ToArray() : BitmapPalettes.Gray256.Colors.ToArray();
foreach (var pixel in pixels)
{
newPixels[pixelCounter] = colorArray[pixel].R;
pixelCounter++;
newPixels[pixelCounter] = colorArray[pixel].G;
pixelCounter++;
newPixels[pixelCounter] = colorArray[pixel].B;
pixelCounter++;
}
newBitmap.WritePixels(
new Int32Rect(0, 0, newBitmap.PixelWidth, newBitmap.PixelHeight),
newPixels,
newBitmap.PixelWidth * newBitmap.Format.BitsPerPixel / 8,
0);
return newBitmap;
}