C# 图像处理#

C# 图像处理#,c#,image-processing,C#,Image Processing,我有下面的代码,它获取我生成的字节数组,并将它们写到这个位图中。如果我将像素格式设置为Format4bppIndexed,则会得到一个可读图像,按宽度重复4次,如果我将其设置为Format1bppIndexed(这是正确的设置),则会得到一个大的不可读图像 该图像是一个解码的Jbig2图像,我知道字节是正确的,我似乎不知道如何将其转换为1bpp可读格式 有人对这件事有什么建议吗 Bitmap bitmap = new Bitmap(width, height, PixelForm

我有下面的代码,它获取我生成的字节数组,并将它们写到这个位图中。如果我将像素格式设置为Format4bppIndexed,则会得到一个可读图像,按宽度重复4次,如果我将其设置为Format1bppIndexed(这是正确的设置),则会得到一个大的不可读图像

该图像是一个解码的Jbig2图像,我知道字节是正确的,我似乎不知道如何将其转换为1bpp可读格式

有人对这件事有什么建议吗

        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);