title: Trouble making a 1bpp PCX from a 1bpp bitmap
body: <p>I have this class that worked for 8 bpp bitmaps to pcx, but I am having trouble making it work for 1 bpp.</p>
  
  <p>The image starts off like this:</p>
  
  <p><img src="https://i.stack.imgur.com/HXoo0.png" alt="A.bmp"></p>
  
  <p>But the resulting PCX is black after line 27, as seen in IrfanView:</p>
  
  <p><img src="https://i.stack.imgur.com/l5RYu.png" alt="AOut.pcx in IrfanView"></p>
  
  <p>Can anyone help me spot the glaring error?</p>
  
  <p>Usage by the way is <code>Pcx.SavePCX("AOut.pcx", new Bitmap("A.bmp"));</code></p>
  
  <pre><code>using System;
  using System.Diagnostics;
  using System.Drawing;
  using System.Drawing.Imaging;
  using System.IO;
  using System.Runtime.InteropServices;
  
  namespace Imaging
  {
      public sealed class Pcx
      {
          private static void WriteWord(Stream stream, int data)
          {
              stream.WriteByte((byte) (data &amp; 0xFF));
              stream.WriteByte((byte) ((data &gt;&gt; 8) &amp; 0xFF));
          }
  
          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-&gt;hdpi, 72);
                      WriteWord(pcxStream, 72); // word(pcx-&gt;vdpi, 72);
                      for (var i = 0; i &lt; 16*3; i++) //4bpp palette
                      {
                          pcxStream.WriteByte(0);
                      }
                      pcxStream.WriteByte(0); // pcx-&gt;res = 0;
                      pcxStream.WriteByte(1); // pcx-&gt;nplanes = 1;
                      WriteWord(pcxStream, bmp.Width); // word(pcx-&gt;bytesperline, width / 2);
                      WriteWord(pcxStream, 0); //word(pcx-&gt;palletteinfo, 0);
                      WriteWord(pcxStream, 0); //word(pcx-&gt;hscrn, 0);
                      WriteWord(pcxStream, 0); //word(pcx-&gt;vscrn, 0);
  
                      for (var i = 0; i &lt; 54; i++) //memset(pcx-&gt;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 = bmp.Width*bmp.Height;
                      var bytes = new byte[byteLength];
  
                      // Copy the RGB values into the array.
                      for (var y = 0; y &lt; data.Height; y++)
                      {
                          var lineOffset = y*data.Stride;
                          Debug.WriteLine("Y={0}, Offset={1}", y, lineOffset);
                          for (var x = 0; x &lt; data.Width; x++)
                          {
                              bytes[y*bmp.Width + x] = Marshal.ReadByte(baseLine, lineOffset + x);
                          }
                      }
  
                      var baseIdx = 0;
                      var end = byteLength;
                      var run = 0;
                      var ldata = -1;
                      byte ld;
  
                      while (baseIdx &lt; end)
                      {
                          //if it matches, increase the run by 1 up to max of 63
                          if ((bytes[baseIdx] == ldata) &amp;&amp; (run &lt; 63)) run++;
                          else
                          {
                              //write data
                              if (run != 0) //not first run
                              {
                                  ld = (byte) ldata;
                                  if ((run &gt; 1) || (ld &gt;= 0xC0)) pcxStream.WriteByte((byte) (0xC0 | run));
                                  pcxStream.WriteByte(ld);
                              }
                              run = 1;
                          }
                          ldata = bytes[baseIdx];
                          baseIdx++;
                      }
                      ld = (byte) ((ldata &gt;&gt; 4) | (ldata &lt;&lt; 4));
                      if ((run &gt; 1) || (ld &gt;= 0xC0)) pcxStream.WriteByte((byte) (0xC0 | run));
                      pcxStream.WriteByte(ld);
                  }
              }
              finally
              {
                  bmp.UnlockBits(data);
              }
          }
  
          public static void SavePCX(string fileName, Bitmap bbp1Bmp)
          {
              using (var fstest = new FileStream(fileName, FileMode.Create, FileAccess.Write))
              {
                  SavePCX(fstest, bbp1Bmp);
              }
          }
      }
  }
  </code></pre>