2013-08-01 34 views
0

我有這個類可以用於pcb的8 bpp位圖,但是我無法使它工作在1 bpp。從一個1bpp位圖製作一個1bpp PCX的麻煩

圖像開始了這樣的:

A.bmp

但由此產生的PCX是線27黑之後,如在IrfanView中:

AOut.pcx in IrfanView

誰能幫我當場明顯的錯誤?

使用的方式是Pcx.SavePCX("AOut.pcx", new Bitmap("A.bmp"));

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 & 0xFF)); 
      stream.WriteByte((byte) ((data >> 8) & 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->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, 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); 

        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 = bmp.Width*bmp.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.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 < 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); 
      } 
     } 

     public static void SavePCX(string fileName, Bitmap bbp1Bmp) 
     { 
      using (var fstest = new FileStream(fileName, FileMode.Create, FileAccess.Write)) 
      { 
       SavePCX(fstest, bbp1Bmp); 
      } 
     } 
    } 
} 

回答

1

通過使用data.Stride爲每行的字節數,並使用步幅寬度,而不是在寬度從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); 
    } 
} 
+0

Yeesh - 你救了我!我需要將1bpp數據寫入Zebra熱敏打印機。謝謝! – jklemmack

+0

那怎麼樣,我也是用這個熱敏打印機呢! – weston