C# 从1bpp位图生成1bpp PCX时出现问题

C# 从1bpp位图生成1bpp PCX时出现问题,c#,bmp,pcx,C#,Bmp,Pcx,我有一个类,它可以工作8个bpp到pcx的位图,但是我很难让它工作1个bpp 图像开始时如下所示: 但在第27行之后生成的PCX为黑色,如IrfanView中所示: 有人能帮我找出那个明显的错误吗 顺便说一下,用法是Pcx.SavePCX(“AOut.Pcx”,新位图(“A.bmp”) 使用系统; 使用系统诊断; 使用系统图; 使用系统、绘图、成像; 使用System.IO; 使用System.Runtime.InteropServices; 名称空间映像 { 公共密封类Pcx { 私有静态

我有一个类,它可以工作8个bpp到pcx的位图,但是我很难让它工作1个bpp

图像开始时如下所示:

但在第27行之后生成的PCX为黑色,如IrfanView中所示:

有人能帮我找出那个明显的错误吗

顺便说一下,用法是
Pcx.SavePCX(“AOut.Pcx”,新位图(“A.bmp”)

使用系统;
使用系统诊断;
使用系统图;
使用系统、绘图、成像;
使用System.IO;
使用System.Runtime.InteropServices;
名称空间映像
{
公共密封类Pcx
{
私有静态void WriteWord(流、整型数据)
{
stream.WriteByte((字节)(data&0xFF));
stream.WriteByte((字节)((数据>>8)和0xFF));
}
公共静态void SavePCX(流pcxStream、位图bmp)
{
如果(bmp.PixelFormat!=PixelFormat.format1bppingdexed)
{
抛出新异常(“只能创建1bpp索引的PCX位图”);
}
var data=bmp.LockBits(新矩形(0,0,bmp.Width,bmp.Height),ImageLockMode.ReadOnly,bmp.PixelFormat);
尝试
{
{
//标题
pcxStream.WriteByte(10);//字符制造商;
pcxStream.WriteByte(5);//字符版本;
pcxStream.WriteByte(1);//字符编码;
pcxStream.WriteByte(1);//字符bpp;
pcxStream.WriteByte(0);
pcxStream.WriteByte(0);//字符xmin[2];
pcxStream.WriteByte(0);
pcxStream.WriteByte(0);//字符ymin[2];
WriteWord(pcxStream,bmp.Width-1);//字符xmax[2];
WriteWord(pcxStream,bmp.Height-1);//char-ymax[2];
WriteWord(pcxStream,72);//word(pcx->hdpi,72);
WriteWord(pcxStream,72);//word(pcx->vdpi,72);
对于(var i=0;i<16*3;i++)//4bpp调色板
{
pcxStream.WriteByte(0);
}
pcxStream.WriteByte(0);//pcx->res=0;
pcxStream.WriteByte(1);//pcx->nplanes=1;
WriteWord(pcxStream,bmp.Width);//word(pcx->bytesperline,Width/2);
WriteWord(pcxStream,0);//word(pcx->palletteinfo,0);
WriteWord(pcxStream,0);//word(pcx->hscrn,0);
WriteWord(pcxStream,0);//word(pcx->vscrn,0);
对于(vari=0;i<54;i++)//memset(pcx->filler,0,54);
{
pcxStream.WriteByte(0);
}
}//头的末尾
{
//将所有字节读取到数组
var基线=data.Scan0;
//声明一个数组以保存位图的字节。
var bytellength=bmp.Width*bmp.Height;
var字节=新字节[字节长度];
//将RGB值复制到数组中。
对于(变量y=0;y1)| |(ld>=0xC0))pcxStream.WriteByte((byte)(0xC0 | run));
pcxStream.WriteByte(ld);
}
run=1;
}
ldata=字节[baseIdx];
baseIdx++;
}
ld=(字节)((ldata>>4)|(ldata 1)|(ld>=0xC0))pcxStream.WriteByte((字节)(0xC0 | run));
pcxStream.WriteByte(ld);
}
}
最后
{
解锁位(数据);
}
}
公共静态void SavePCX(字符串文件名,位图bbp1Bmp)
{
使用(var fstest=newfilestream(文件名,FileMode.Create,FileAccess.Write))
{
SavePCX(fstest,bbp1Bmp);
}
}
}
}

通过使用
数据解决了这个问题。对于每行的字节,使用跨步
读取1bpp中的字节,使用跨步作为宽度,而不是宽度

public static void SavePCX(Stream pcxStream, Bitmap bmp)
{
    if (bmp.PixelFormat != PixelFormat.Format1bppIndexed)
    {
        throw new Exception("Can only PCX bitmaps that are 1bpp indexed");
    }

    var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
    try
    {
        {
            //header
            pcxStream.WriteByte(10); //    char manufacturer;
            pcxStream.WriteByte(5); //char version;
            pcxStream.WriteByte(1); //char encoding;
            pcxStream.WriteByte(1); // char bpp;
            pcxStream.WriteByte(0);
            pcxStream.WriteByte(0); //char xmin[2];
            pcxStream.WriteByte(0);
            pcxStream.WriteByte(0); //char ymin[2];
            WriteWord(pcxStream, bmp.Width - 1); // char xmax[2];
            WriteWord(pcxStream, bmp.Height - 1); //char ymax[2];

            WriteWord(pcxStream, 72); //word(pcx->hdpi, 72);
            WriteWord(pcxStream, 72); // word(pcx->vdpi, 72);
            for (var i = 0; i < 16*3; i++) //4bpp palette
            {
                pcxStream.WriteByte(0);
            }
            pcxStream.WriteByte(0); // pcx->res = 0;
            pcxStream.WriteByte(1); // pcx->nplanes = 1;
            WriteWord(pcxStream, data.Stride); // word(pcx->bytesperline, width / 2);
            WriteWord(pcxStream, 0); //word(pcx->palletteinfo, 0);
            WriteWord(pcxStream, 0); //word(pcx->hscrn, 0);
            WriteWord(pcxStream, 0); //word(pcx->vscrn, 0);

            for (var i = 0; i < 54; i++) //memset(pcx->filler, 0, 54);
            {
                pcxStream.WriteByte(0);
            }
        } //end of header

        {
            //read all bytes to an array
            var baseLine = data.Scan0;
            // Declare an array to hold the bytes of the bitmap.
            var byteLength = data.Stride*data.Height;
            var bytes = new byte[byteLength];

            // Copy the RGB values into the array.
            for (var y = 0; y < data.Height; y++)
            {
                var lineOffset = y*data.Stride;
                Debug.WriteLine("Y={0}, Offset={1}", y, lineOffset);
                for (var x = 0; x < data.Stride; x++)
                {
                    bytes[y*data.Stride + x] = Marshal.ReadByte(baseLine, lineOffset + x);
                }
            }

            var baseIdx = 0;
            var end = byteLength;
            var run = 0;
            var ldata = -1;
            byte ld;

            while (baseIdx < end)
            {
                //if it matches, increase the run by 1 up to max of 63
                if ((bytes[baseIdx] == ldata) && (run < 63)) run++;
                else
                {
                    //write data
                    if (run != 0) //not first run
                    {
                        ld = (byte) ldata;
                        if ((run > 1) || (ld >= 0xC0)) pcxStream.WriteByte((byte) (0xC0 | run));
                        pcxStream.WriteByte(ld);
                    }
                    run = 1;
                }
                ldata = bytes[baseIdx];
                baseIdx++;
            }
            ld = (byte) ((ldata >> 4) | (ldata << 4));
            if ((run > 1) || (ld >= 0xC0)) pcxStream.WriteByte((byte) (0xC0 | run));
            pcxStream.WriteByte(ld);
        }
    }
    finally
    {
        bmp.UnlockBits(data);
    }
}
publicstaticvoidsavepcx(流pcxStream,位图bmp)
{
如果(bmp.PixelFormat!=PixelFormat.format1bppingdexed)
{
抛出新异常(“只能创建1bpp索引的PCX位图”);
}
var data=bmp.LockBits(新矩形(0,0,bmp.Width,bmp.Height),ImageLockMode.ReadOnly,bmp.PixelFormat);
尝试
{
{
//标题
pcxStream.WriteByte(10);//字符制造商;
pcxStream.WriteByte(5);//字符版本;
pcxStream.WriteByte(1);//字符编码;
pcxStream.WriteByte(1);//字符bpp;
pcxStream.WriteByte(0);
pcxStream.WriteByte(0);//字符xmin[2];
public static void SavePCX(Stream pcxStream, Bitmap bmp)
{
    if (bmp.PixelFormat != PixelFormat.Format1bppIndexed)
    {
        throw new Exception("Can only PCX bitmaps that are 1bpp indexed");
    }

    var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
    try
    {
        {
            //header
            pcxStream.WriteByte(10); //    char manufacturer;
            pcxStream.WriteByte(5); //char version;
            pcxStream.WriteByte(1); //char encoding;
            pcxStream.WriteByte(1); // char bpp;
            pcxStream.WriteByte(0);
            pcxStream.WriteByte(0); //char xmin[2];
            pcxStream.WriteByte(0);
            pcxStream.WriteByte(0); //char ymin[2];
            WriteWord(pcxStream, bmp.Width - 1); // char xmax[2];
            WriteWord(pcxStream, bmp.Height - 1); //char ymax[2];

            WriteWord(pcxStream, 72); //word(pcx->hdpi, 72);
            WriteWord(pcxStream, 72); // word(pcx->vdpi, 72);
            for (var i = 0; i < 16*3; i++) //4bpp palette
            {
                pcxStream.WriteByte(0);
            }
            pcxStream.WriteByte(0); // pcx->res = 0;
            pcxStream.WriteByte(1); // pcx->nplanes = 1;
            WriteWord(pcxStream, data.Stride); // word(pcx->bytesperline, width / 2);
            WriteWord(pcxStream, 0); //word(pcx->palletteinfo, 0);
            WriteWord(pcxStream, 0); //word(pcx->hscrn, 0);
            WriteWord(pcxStream, 0); //word(pcx->vscrn, 0);

            for (var i = 0; i < 54; i++) //memset(pcx->filler, 0, 54);
            {
                pcxStream.WriteByte(0);
            }
        } //end of header

        {
            //read all bytes to an array
            var baseLine = data.Scan0;
            // Declare an array to hold the bytes of the bitmap.
            var byteLength = data.Stride*data.Height;
            var bytes = new byte[byteLength];

            // Copy the RGB values into the array.
            for (var y = 0; y < data.Height; y++)
            {
                var lineOffset = y*data.Stride;
                Debug.WriteLine("Y={0}, Offset={1}", y, lineOffset);
                for (var x = 0; x < data.Stride; x++)
                {
                    bytes[y*data.Stride + x] = Marshal.ReadByte(baseLine, lineOffset + x);
                }
            }

            var baseIdx = 0;
            var end = byteLength;
            var run = 0;
            var ldata = -1;
            byte ld;

            while (baseIdx < end)
            {
                //if it matches, increase the run by 1 up to max of 63
                if ((bytes[baseIdx] == ldata) && (run < 63)) run++;
                else
                {
                    //write data
                    if (run != 0) //not first run
                    {
                        ld = (byte) ldata;
                        if ((run > 1) || (ld >= 0xC0)) pcxStream.WriteByte((byte) (0xC0 | run));
                        pcxStream.WriteByte(ld);
                    }
                    run = 1;
                }
                ldata = bytes[baseIdx];
                baseIdx++;
            }
            ld = (byte) ((ldata >> 4) | (ldata << 4));
            if ((run > 1) || (ld >= 0xC0)) pcxStream.WriteByte((byte) (0xC0 | run));
            pcxStream.WriteByte(ld);
        }
    }
    finally
    {
        bmp.UnlockBits(data);
    }
}