C# 图像处理#
我有下面的代码,它获取我生成的字节数组,并将它们写到这个位图中。如果我将像素格式设置为Format4bppIndexed,则会得到一个可读图像,按宽度重复4次,如果我将其设置为Format1bppIndexed(这是正确的设置),则会得到一个大的不可读图像 该图像是一个解码的Jbig2图像,我知道字节是正确的,我似乎不知道如何将其转换为1bpp可读格式 有人对这件事有什么建议吗C# 图像处理#,c#,image-processing,C#,Image Processing,我有下面的代码,它获取我生成的字节数组,并将它们写到这个位图中。如果我将像素格式设置为Format4bppIndexed,则会得到一个可读图像,按宽度重复4次,如果我将其设置为Format1bppIndexed(这是正确的设置),则会得到一个大的不可读图像 该图像是一个解码的Jbig2图像,我知道字节是正确的,我似乎不知道如何将其转换为1bpp可读格式 有人对这件事有什么建议吗 Bitmap bitmap = new Bitmap(width, height, PixelForm
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format1bppIndexed);
//Create a BitmapData and Lock all pixels to be written
BitmapData bmpData = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, bitmap.PixelFormat);
//Copy the data from the byte array into BitmapData.Scan0
Marshal.Copy(newarray, 0, bmpData.Scan0, newarray.Length);
//Unlock the pixels
bitmap.UnlockBits(bmpData);
如果我没记错的话,下面的方法可能有效,
Stride
有时会有效果,简单的块拷贝是不够的(必须使用逐行拷贝)
要处理您想要的步幅,请执行以下操作:
BitmapData^ data = bitmap->LockBits(oSize,
ImageLockMode::ReadOnly, bitmap->PixelFormat);
try {
unsigned char *pData = (unsigned char *)data->Scan0.ToPointer();
for( int x = 0; x < bmpImage->Width; ++x )
{
for( int y = 0; y < bmpImage->Height; ++y )
{
// Note: Stride is data width of scan line rounded up
// to 4 byte boundary.
// Requires use of Stride, not (width * pixelWidth)
int ps = y*bmpImage->Width*(nBitsPerPixel / 8)
+ x * (nBitsPerPixel / 8);
int p = y * data->Stride + x * (nBitsPerPixel / 8);
Byte lo = newarray[ps + 1];
Byte hi = newarray[ps + 0];
pData[p + 1] = lo;
pData[p + 0] = hi;
}
}
} finally {
bmpImage->UnlockBits(data);
}
BitmapData^data=bitmap->LockBits(oSize、,
ImageLockMode::只读,位图->像素格式);
试一试{
unsigned char*pData=(unsigned char*)data->Scan0.ToPointer();
对于(int x=0;x宽度;++x)
{
对于(int y=0;y高度;++y)
{
//注:步长是向上舍入扫描线的数据宽度
//到4字节边界。
//需要使用步幅,而不是(宽度*像素宽度)
int ps=y*bmp图像->宽度*(n像素/8)
+x*(每像素n比特/8);
int p=y*数据->步幅+x*(n比特/像素/8);
字节lo=新数组[ps+1];
字节hi=新数组[ps+0];
pData[p+1]=lo;
pData[p+0]=hi;
}
}
}最后{
bmp图像->解锁位(数据);
}
注意:这是用C++/CLI编写的。如果这里的任何操作需要C#等价物,请告诉我。(另外,我是从位图读取而不是从位图写入来的,所以它可能有点粗糙,但希望能给你一个想法……我明白了这一点,尽管我仍然不知道为什么它会起作用 基于此堆栈溢出过帐 我使用了WPF类而不是GDI,并编写了如下代码
var bitmap = new WriteableBitmap(width, height, 96, 96, System.Windows.Media.PixelFormats.BlackWhite, null);
bitmap.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), newarray, stride, 0);
MemoryStream stream3 = new MemoryStream();
var encoder = new TiffBitmapEncoder ();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream3);
这将正确创建图像
如果有人对这种情况有任何见解,请在下面进行评论
现在主要工作的端口(大量清理代码)基于JPedal Big2解码器到.NET的java实现。如果有人认识感兴趣的人,就把他们送到这里来
基于“4次重复”,听起来应该是每像素16位。不知道为什么你认为你的数据只有1位黑/白。。。注意:如果不是1bpp,则转换为1bpp将在解码后进行。是每像素位还是每像素字节?@Stefan我想不出还有多少事情会以每像素4字节的速度重复4次(alpha是什么32位?@ebyrob:你说得对。是的,每像素32位是A(lpha)RGB格式。对于位图,它通常是XRGB(也是32位,但第一个字节被忽略)。后者只是针对32位系统的优化。为什么您认为1bpp是“正确的设置”?只是问一下,因为我在查看专有图像格式时很少遇到1bpp图像。虽然考虑到它是一种非常有效的文本图像存储方式,但1bpp还是很不错的。我必须通过WPF名称空间实现16bpp,因为GDI不支持保存它。但当我这样做的时候,它看起来都是扭曲的,不可读。代码看起来像这个var bitmap=newwriteablebitmap(宽度,高度,96,96,System.Windows.Media.PixelFormats.Gray16,null);Lock();Marshal.Copy(newarray,0,bitmap.BackBuffer,newarray.Length);bitmap.Unlock()@DevTeamExpress我打赌这就是大步,问题很抱歉反应太慢,我会看看是否能找到我的代码示例。。。说得清楚一点,你看到了图像,但它被扭曲了,对吧@DevTeamExpress最简单的事情可能是首先将步幅与(宽度*像素宽度)进行比较。PS-知道这里的宽度可能会有很大帮助。我会尝试一下,让你知道会发生什么。听起来这可能就是问题所在。感谢宽度是2550px,步幅是320,高度是3299假设1bpp,我仍然很确定它一定是。当运行你的代码时,我收到一个内存超出界限的错误。
var bitmap = new WriteableBitmap(width, height, 96, 96, System.Windows.Media.PixelFormats.BlackWhite, null);
bitmap.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), newarray, stride, 0);
MemoryStream stream3 = new MemoryStream();
var encoder = new TiffBitmapEncoder ();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream3);