home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2005 June (DVD) / DPPRO0605DVD.iso / Install / program files / Borland / BDS / 3.0 / Demos / CSharp / Graphics / PCX / PCXClass.cs < prev    next >
Encoding:
Text File  |  2004-10-22  |  24.3 KB  |  626 lines

  1. using System;
  2. using System.Drawing;
  3. using System.IO;
  4.  
  5. ///
  6. /// <summary>
  7. /// PCXClass.cs contain a moreless useful PCX-viewer class
  8. /// It will work with the most widely distributed 256 or 24bit color
  9. /// pictures and the older 16 bit ones.
  10. /// Known issues are the possibly problems with true CGA pictures
  11. /// and the packed 16 bit ones (with 4 planes).
  12. /// Some coding solution surely will be like a stone-age way
  13. /// for professionals, but probably not for starter ones in the C#-world.
  14.  
  15. /// Example submitted by Endre I Simay based on Turbo Pascal viewer,
  16. ///
  17. /// </summary>
  18.  
  19. public class VideoModes {
  20.     public byte CGA4; // { video modes }
  21.     public byte CGA2;
  22.     public byte EGA ;
  23.     public byte VGA ;
  24.     public byte MCGA;
  25.     public byte MCGA2;
  26.     public VideoModes() {
  27.         CGA4 = 0x04; // { video modes }
  28.         CGA2 = 0x06;
  29.         EGA = 0x10;
  30.         VGA = 0x12;
  31.         MCGA = 0x13;
  32.         MCGA2 = 0x15;
  33.     }
  34. }
  35. public class ByteBitWise {
  36.     byte [] ext;
  37.     public ByteBitWise () {
  38.         ext =new byte [8];
  39.         ext[0]=1;
  40.         for (int i=1; i<8; i++) // {1, 2, 4, 8, 16, 32, 64, 128};
  41.         {
  42.             ext[i]=(byte)(ext[i-1]*2);
  43.         }
  44.     }
  45.     public byte shr (byte basic, byte n) {
  46.         return (byte)(basic/ext[n & (8-1)]);
  47.     }
  48.     public byte shl (byte basic, byte n) {
  49.         return (byte)(basic*ext[n & (8-1)]);
  50.     }
  51. }
  52. public struct BITMAPFILEHEADER {
  53.     public UInt16 bfType;
  54.     public UInt32 bfSize;
  55.     public UInt16 bfReserved1;
  56.     public UInt16 bfReserved2;
  57.     public UInt32 bfOffBits;
  58. } // Size=14
  59.  
  60. public struct BITMAPINFOHEADER {
  61.     public UInt32 biSize;
  62.     public Int32 biWidth;
  63.     public Int32 biHeight;
  64.     public UInt16 biPlanes;
  65.     public UInt16 biBitCount;
  66.     public UInt32 biCompression;
  67.     public UInt32 biSizeImage;
  68.     public Int32 biXPelsPerMeter;
  69.     public Int32 biYPelsPerMeter;
  70.     public UInt32 biClrUsed;
  71.     public UInt32 biClrImportant;
  72. } // Size=40
  73.  
  74. public class PCX_Header {
  75.     public byte Manufacturer; // Always 10 for PCX file
  76.     public byte Version;
  77.       /* 2 - old PCX - no palette (NOT used anymore),
  78.          3 - no palette,
  79.          4 - Microsoft Windows - no palette (only in
  80.          old files, New Windows version USES 3),
  81.          5 - WITH palette */
  82.     public byte Encoding;
  83.       /* 1 is PCX, it is possible that we may add
  84.          additional encoding methods IN the future */
  85.     public byte Bits_per_pixel;
  86.       /* Number of bits to represent a pixel
  87.          (per plane) - 1, 2, 4, or 8 */
  88.     public Int16 Xmin; // Image window dimensions (inclusive)
  89.     public Int16 Ymin; // Xmin, Ymin are usually zero (not always)
  90.     public Int16 Xmax;
  91.     public Int16 Ymax;
  92.     public Int16 Hdpi; // Resolution of image (dots per inch)
  93.     public Int16 Vdpi; // Set to scanner resolution - 300 is default
  94.     public byte [,] ColorMap;
  95.       /* RGB palette data (16 colors or less)
  96.          256 color palette is appended to END OF FILE */
  97.     public byte Reserved;
  98.       /* (used to contain video mode)
  99.          now it is ignored - just set to zero */
  100.     public byte Nplanes; // Number of planes
  101.     public UInt16 Bytes_per_line_per_plane;
  102.       /* Number of bytes to allocate
  103.          for a scanline plane.
  104.          MUST be an an EVEN number!
  105.          DO NOT calculate from Xmax-Xmin! */
  106.     public UInt16 PaletteInfo;
  107.       /* 1 = black & white or color image,
  108.          2 = grayscale image - ignored IN PB4, PB4+
  109.          palette must also be set to shades of gray! }*/
  110.     public Int16 HscreenSize; // added for PC Paintbrush IV Plus ver 1.0,
  111.     public Int16 VscreenSize; // PC Paintbrush IV ver 1.02 (and later)
  112.     public byte [] Filler; // Set to zeros but mainly indifferent paddings to 128 byte
  113.  
  114.     public PCX_Header() {
  115.         ColorMap = new byte [16,3];
  116.         Filler = new byte [54];
  117.     }
  118. }
  119.  
  120. public class PCX_Reader {
  121.     private Int16 PictureMode=0;
  122.     private int Error=0;
  123.     private int Index = 0;
  124.     private byte data=0;
  125.     private UInt16 bytes_per_line = 0;
  126.     private VideoModes video = new VideoModes();
  127.  
  128.     private PCX_Header PCXheader;
  129.     private int RealWidth, RealHeight =0;
  130.     private System.IO.StreamReader PCXStream;
  131.     private System.IO.BinaryReader breader;
  132.     private BITMAPFILEHEADER bitmapfileheader;
  133.     private BITMAPINFOHEADER bitmapinfoheader;
  134.     private System.IO.BinaryWriter bwrite = new BinaryWriter(new MemoryStream());
  135.     private string [] errors = new string []
  136.             {
  137.             "No problems.",
  138.             "Problem with opening the sourcefile.",
  139.             "Problem to read the PCX-header.",
  140.             "Problem with initializing the BinaryReader.",
  141.             "Not a valid PCX-file for this decoder.",
  142.             "Problem with reading the palette.",
  143.             "Any problem with reading from or writing to a stream of the image."
  144.             };
  145.  
  146.     private void PCX_Reader_Init() {
  147.         video = new VideoModes();
  148.         PCXheader = new PCX_Header();
  149.     }
  150.  
  151.     public PCX_Reader() {
  152.         PCX_Reader_Init();
  153.     }
  154.  
  155.     protected void Dispose (bool disposing) {
  156.         if (disposing) {
  157.             if (bwrite !=null) {
  158.                 bwrite.Close();
  159.             }
  160.         }
  161.     }
  162.  
  163.     public string PCX_ErrorString() {
  164.         return errors[Error];
  165.     }
  166.  
  167.     public int PCX_ErrorNumber() {
  168.         return Error;
  169.     }
  170.  
  171.     public Stream FromStream (Stream source) {
  172.         MemoryStream stream = new MemoryStream();
  173.         PCXStream = new StreamReader(source);
  174.         FromStreamToStream(stream);
  175.         if (Error == 0)
  176.         {
  177.           return stream;
  178.         } else
  179.         {
  180.          return null;
  181.         }
  182.     }
  183.  
  184.     public Stream FromFile (string FilePath) {
  185.         MemoryStream stream = new MemoryStream();
  186.         PCXStream = new StreamReader(FilePath);
  187.         FromStreamToStream(stream);
  188.         if (Error == 0)
  189.         {
  190.           return stream;
  191.         } else
  192.         {
  193.          return null;
  194.         }
  195.     }
  196.  
  197.     private void FromFileToStream (string FilePath, Stream stream) {
  198.         try {
  199.             PCXStream = new StreamReader(FilePath);
  200.             FromStreamToStream(stream);
  201.         } catch (Exception) {
  202.             Error = 1; //Problem with opening the sourcefile
  203.         }
  204.     }
  205.  
  206.     private void FromStreamToStream (Stream stream) {
  207.         PCX_Reader_Init();
  208.         try {
  209.             breader = new BinaryReader(PCXStream.BaseStream);
  210.             try {
  211.                 PCXheader.Manufacturer = breader.ReadByte();
  212.                 PCXheader.Version = breader.ReadByte();
  213.                 PCXheader.Encoding = breader.ReadByte();
  214.                 PCXheader.Bits_per_pixel = breader.ReadByte();
  215.                 PCXheader.Xmin = breader.ReadInt16();
  216.                 PCXheader.Ymin = breader.ReadInt16();
  217.                 PCXheader.Xmax = breader.ReadInt16();
  218.                 PCXheader.Ymax = breader.ReadInt16();
  219.                 PCXheader.Hdpi = breader.ReadInt16();
  220.                 PCXheader.Vdpi = breader.ReadInt16();
  221.                 for (int j = 0; j < 16; j++) {
  222.                     for (int i = 0; i < 3; i++) {
  223.                         PCXheader.ColorMap[j,i] = breader.ReadByte();
  224.                     }
  225.                 }
  226.                 PCXheader.Reserved = breader.ReadByte();
  227.                 PCXheader.Nplanes = breader.ReadByte();
  228.                 PCXheader.Bytes_per_line_per_plane = breader.ReadUInt16();
  229.                 PCXheader.PaletteInfo = breader.ReadUInt16();
  230.                 PCXheader.HscreenSize = breader.ReadInt16();
  231.                 PCXheader.VscreenSize = breader.ReadInt16();
  232.                 PCXheader.Filler = breader.ReadBytes(55);
  233.             } catch (Exception) {
  234.                 Error=2; //Problem to read the PCX-header
  235.             }
  236.         } catch (Exception) {
  237.             Error = 3; //Problem with initializing the BinaryReader
  238.         }
  239.         if (Error == 0) {
  240.             if ((PCXheader.Manufacturer != 10) || (PCXheader.Encoding != 1)) {
  241.                 Error =4; //Not a valid PCX-file
  242.             }
  243.             if ((PCXheader.Nplanes == 3) && (PCXheader.Bits_per_pixel == 8)) {
  244.                 PictureMode = video.MCGA2;
  245.             }
  246.             if ((PCXheader.Nplanes == 4) && (PCXheader.Bits_per_pixel == 1)) {
  247.                 PictureMode =video.VGA;
  248.             }
  249.  
  250.             if ((PCXheader.Nplanes == 1) &&(PCXheader.Bits_per_pixel == 4)) {
  251.                  Error=4; //Not a valid PCX-file for this class
  252.                  /* Not implemented yet */
  253.             }
  254.  
  255.             if (PCXheader.Nplanes == 1) {
  256.                 if (PCXheader.Bits_per_pixel == 1) {
  257.                     PictureMode =video.VGA;
  258.                     /* b/w PCX saved on Windows (e.g. from Paint Shop Pro)
  259.                        working with VGA-decoding, while true CGA2
  260.                        images may cause problem
  261.                     */
  262.                     //   Error=4; //Not a valid PCX-file for this class
  263.                 } else {
  264.                     if (PCXheader.Bits_per_pixel == 2) {
  265.                         PictureMode =video.CGA4;
  266.                         Error=4; //Not a valid PCX-file for this class
  267.                     } else {
  268.                         if (PCXheader.Bits_per_pixel == 8) {
  269.                             PictureMode = video.MCGA;
  270.                             if (PCXheader.Version != 5) {
  271.                                 Error = 4; //Not a valid PCX-file
  272.                             }
  273.                         }
  274.                     }
  275.                 }
  276.             }
  277.         }
  278.         if (Error==0) {
  279.             bytes_per_line = (UInt16)(PCXheader.Bytes_per_line_per_plane * PCXheader.Nplanes);
  280.             RealWidth=PCXheader.Xmax-PCXheader.Xmin+1;
  281.             RealHeight=PCXheader.Ymax-PCXheader.Ymin+1;
  282.             FillBitmapStructs();
  283.             ReadPalettes(PCXStream.BaseStream);
  284.         }
  285.         if (breader!=null) {
  286.             breader.Close();
  287.         }
  288.         if (PCXStream!=null) {
  289.             PCXStream.Close();
  290.         }
  291.         if (Error==0) {
  292.             ((MemoryStream) bwrite.BaseStream).WriteTo(stream);
  293.         } else {
  294.             stream.Close();
  295.         }
  296.     }
  297.  
  298.     private void FillBitmapStructs() {
  299.         bitmapfileheader.bfType =(UInt16)0x4D42;
  300.         bitmapfileheader.bfSize = (UInt32)((3*255) + 14 /*Sizeof(BitmapFileHeader)*/
  301.                                            + 40 /* Sizeof(TBitmapInfoHeader) */
  302.                                            + ((RealHeight)*(RealWidth)));
  303.         bitmapfileheader.bfReserved1 = 0;
  304.         bitmapfileheader.bfReserved2 = 0;
  305.         bitmapfileheader.bfOffBits = (4*256)+ 14 /*Sizeof(BitmapFileHeader)*/
  306.                                      +  40 /* Sizeof(TBitmapInfoHeader) */;
  307.         bitmapinfoheader.biSize =(UInt32)40;
  308.         bitmapinfoheader.biWidth =(Int32)RealWidth;
  309.         bitmapinfoheader.biHeight =(Int32)RealHeight;
  310.         bitmapinfoheader.biPlanes=(UInt16)1;// biPlanes = 1; Arcane and rarely used
  311.         bitmapinfoheader.biBitCount=(UInt16)8; //biBitCount = 8; Most widely occurring for PCX format
  312.         bitmapinfoheader.biCompression= (UInt32)0; // biCompression = BI_RGB; Not needed compressing for the laters
  313.         bitmapinfoheader.biSizeImage=(UInt32)0; //biSizeImage = 0; Valid since we are not compressing the image
  314.         bitmapinfoheader.biXPelsPerMeter =(Int32)143; //biXPelsPerMeter = 143; Rarely used (Windows not use) very arcane field
  315.         bitmapinfoheader.biYPelsPerMeter=(Int32)143; //biYPelsPerMeter = 143; Ditto
  316.         bitmapinfoheader.biClrUsed=(UInt32)0; //biClrUsed = 0; all colors are used
  317.         bitmapinfoheader.biClrImportant=(UInt32)0; //biClrImportant = 0; all colors are important
  318.     }
  319.  
  320.     private void ReadPalettes(Stream stream) {
  321.         Error =0;
  322.         if ((PictureMode == video.MCGA) && (PCXheader.Version == 5)) {
  323.             Read256palette(stream);
  324.         }
  325.         if (PictureMode == video.MCGA2) {
  326.             ReadMCGA2palette(stream);
  327.         }
  328.         if (PictureMode == video.VGA) {
  329.             ReadVGA16palette(stream);
  330.         }
  331.     }
  332.  
  333.     private void Read256palette(Stream stream) // Read in a 256 color palette at end of PCX file
  334.     {
  335.         int bytes_in_line,dY;
  336.         UInt16 count;
  337.  
  338.         byte[,] Palette256 = new byte[256, 3];
  339.         stream.Seek( (stream.Length) - 769,0);
  340.         // read indicator byte
  341.         try {
  342.         if (stream.ReadByte() == 12) {
  343.             // read palette if there is one
  344.             for (int j = 0; j < 256; j++) {
  345.                 for (int i = 0; i < 3; i++) {
  346.                     Palette256[j,i] = (byte)stream.ReadByte();
  347.                 }
  348.             }
  349.             stream.Seek(128,0); /// go back to start of PCX data
  350.             Error = 0;
  351.         } else {
  352.             Error=5; // no palette here...
  353.         }
  354.         } catch (Exception)
  355.          {
  356.             Error=5; //Problem with reading the palette
  357.          }
  358.  
  359.         if (Error==0) {
  360.           try {
  361.             bwrite.Write (bitmapfileheader.bfType);
  362.             bwrite.Write (bitmapfileheader.bfSize);
  363.             bwrite.Write (bitmapfileheader.bfReserved1);
  364.             bwrite.Write (bitmapfileheader.bfReserved2);
  365.             bwrite.Write (bitmapfileheader.bfOffBits);
  366.             bwrite.Write (bitmapinfoheader.biSize);
  367.             bwrite.Write (bitmapinfoheader.biWidth);
  368.             bwrite.Write (bitmapinfoheader.biHeight);
  369.             bwrite.Write (bitmapinfoheader.biPlanes);
  370.             bwrite.Write (bitmapinfoheader.biBitCount);
  371.             bwrite.Write (bitmapinfoheader.biCompression);
  372.             bwrite.Write (bitmapinfoheader.biSizeImage);
  373.             bwrite.Write (bitmapinfoheader.biXPelsPerMeter);
  374.             bwrite.Write (bitmapinfoheader.biYPelsPerMeter);
  375.             bwrite.Write (bitmapinfoheader.biClrUsed);
  376.             bwrite.Write (bitmapinfoheader.biClrImportant);
  377.             for (int i = 0; i< 256; i++) {// R, G, and B must be 0..63
  378.                 bwrite.Write((byte) Palette256 [i, 2]);
  379.                 bwrite.Write((byte) Palette256 [i, 1]);
  380.                 bwrite.Write((byte) Palette256 [i, 0]);
  381.                 bwrite.Write((byte)0);
  382.             }
  383.             Index = 0;
  384.             bytes_in_line = RealWidth;
  385.             dY = 4-(bytes_in_line-(bytes_in_line / 4)*4);
  386.             if (dY==4) {
  387.                 dY=0;
  388.             }
  389.             bytes_in_line = bytes_in_line+dY;
  390.             byte [,] lines = new byte [RealHeight,bytes_in_line];
  391.             for (int i=0; i<(RealHeight); i++) {
  392.                 if (Index != 0) {
  393.                     for (int j=0; j<Index;j++) {
  394.                         lines[i,j]= data; // fills a contiguous block
  395.                     }
  396.                 }
  397.                 while (Index < bytes_per_line) // read 1 line of data (all planes)
  398.                 {
  399.                     data = (byte)stream.ReadByte();
  400.                     if ((byte)(data & (byte)(0xC0)) == (byte)(0xC0)) {
  401.                         count = (UInt16)((byte)(data & (byte)(0x3F)));
  402.                         data = (byte)stream.ReadByte();
  403.                         for (int j=0; j<count;j++) //(int i=Index; i<count;i++)
  404.                         {
  405.                             lines[i,Index+j]= data; // fills a contiguous block
  406.                         }
  407.                         Index += count;
  408.                     } else {
  409.                         lines [i,Index] = data;
  410.                         Index++;
  411.                     }
  412.                 }
  413.                 Index = Index - bytes_per_line;
  414.             }
  415.             for (int k = RealHeight-1; k>= 0; k--) {
  416.                 for (int i = 0; i<(bytes_in_line); i++) {
  417.                     bwrite.Write((byte)lines[k,i]);
  418.                 }
  419.             }
  420.          }catch  (Exception){
  421.             Error=6; // Any problem with reading from or writing to a stream of the image
  422.          }
  423.  
  424.       }
  425.    }
  426.  
  427.     private void ReadMCGA2palette(Stream stream) // Read in a 24b color PCX file
  428.     {
  429.         int bytes_in_line,dY;
  430.         UInt16 count;
  431.         stream.Seek(128,0); ///  guaranted go to start of PCX data
  432.         bytes_in_line=3*(RealWidth);
  433.  
  434.         dY=4-(bytes_in_line-(bytes_in_line / 4)*4);
  435.         if (dY==4) {
  436.             dY=0;
  437.         }
  438.         bytes_in_line=bytes_in_line+dY;
  439.  
  440.         if (Error==0) {
  441.           try {
  442.             bitmapfileheader.bfSize = (UInt32)((3*15) + 14 /*Sizeof(BitmapFileHeader)*/
  443.                                                + 40 /* Sizeof(TBitmapInfoHeader) */
  444.                                                + ((RealHeight)*(RealWidth)*3));
  445.             bitmapfileheader.bfOffBits = 14 /*Sizeof(BitmapFileHeader)*/
  446.                                          +  40 /* Sizeof(TBitmapInfoHeader) */;
  447.             bitmapinfoheader.biBitCount=(UInt16)24;
  448.             bwrite.Write (bitmapfileheader.bfType);
  449.             bwrite.Write (bitmapfileheader.bfSize);
  450.             bwrite.Write (bitmapfileheader.bfReserved1);
  451.             bwrite.Write (bitmapfileheader.bfReserved2);
  452.             bwrite.Write (bitmapfileheader.bfOffBits);
  453.             bwrite.Write (bitmapinfoheader.biSize);
  454.             bwrite.Write (bitmapinfoheader.biWidth);
  455.             bwrite.Write (bitmapinfoheader.biHeight);
  456.             bwrite.Write (bitmapinfoheader.biPlanes);
  457.             bwrite.Write (bitmapinfoheader.biBitCount);
  458.             bwrite.Write (bitmapinfoheader.biCompression);
  459.             bwrite.Write (bitmapinfoheader.biSizeImage);
  460.             bwrite.Write (bitmapinfoheader.biXPelsPerMeter);
  461.             bwrite.Write (bitmapinfoheader.biYPelsPerMeter);
  462.             bwrite.Write (bitmapinfoheader.biClrUsed);
  463.             bwrite.Write (bitmapinfoheader.biClrImportant);
  464.             int x =0;
  465.             Index = 0;
  466.             byte [,] lines = new byte [RealHeight,bytes_in_line];
  467.             byte [] line = new byte [bytes_in_line];
  468.             for (int i=0; i<(RealHeight); i++) {
  469.                 if (Index != 0) {
  470.                     for (int j=0; j<Index;j++)
  471.                     {
  472.                         line[j]= data; // fills a contiguous block
  473.                     }
  474.                 }
  475.                 while (Index < bytes_per_line) // read 1 line of data (all planes)
  476.                 {
  477.                     data = (byte)stream.ReadByte();
  478.                     if ((byte)(data & (byte)(0xC0)) == (byte)(0xC0)) {
  479.                         count = (UInt16)((byte)(data & (byte)(0x3F)));
  480.                         data = (byte)stream.ReadByte();
  481.                         for (int j=0; j<count;j++)
  482.                         {
  483.                             line[Index+j]= data; // fills a contiguous block
  484.                         }
  485.                         Index += count;
  486.                     } else {
  487.                         line [Index] = data;
  488.                         Index++;
  489.                     }
  490.                 }
  491.                 Index = Index - bytes_per_line;
  492.                 x=0;
  493.                 for (int L=0; L<PCXheader.Bytes_per_line_per_plane; L++) {
  494.                     lines[i,x+2]=line[L];
  495.                     lines[i,x+1]=line[L+PCXheader.Bytes_per_line_per_plane];
  496.                     lines[i,x]=line[L+2*PCXheader.Bytes_per_line_per_plane];
  497.                     lines[i,x+3]=0;
  498.                     x=x+3;
  499.                 }
  500.             }
  501.             for (int k = RealHeight-1; k>= 0; k--) {
  502.                 for (int i = 0; i<(bytes_in_line); i++) {
  503.                     bwrite.Write((byte)lines[k,i]);
  504.                 }
  505.             }
  506.          }catch  (Exception){
  507.             Error=6; // Any problem with reading from or writing to a stream of the image
  508.          }
  509.  
  510.         }
  511.     }
  512.  
  513.     private void ReadVGA16palette(Stream stream) // Read in a 16 color PCX file
  514.     {
  515.         ByteBitWise bitwise =new ByteBitWise();
  516.         int bytes_in_line,dY;
  517.         byte c;
  518.  
  519.         stream.Seek(128,0); /// guaranted go to start of PCX data
  520.         if (Error==0) {
  521.           try {
  522.             bitmapfileheader.bfSize = (UInt32)((3*15) + 14 /*Sizeof(BitmapFileHeader)*/
  523.                                                + 40 /* Sizeof(TBitmapInfoHeader) */
  524.                                                + ((RealHeight)*(RealWidth)));
  525.             bitmapfileheader.bfOffBits = (4*16)+ 14 /*Sizeof(BitmapFileHeader)*/
  526.                                          +  40 /* Sizeof(TBitmapInfoHeader) */;
  527.             bitmapinfoheader.biBitCount=(UInt16)4; //biBitCount = 24;
  528.             bwrite.Write (bitmapfileheader.bfType);
  529.             bwrite.Write (bitmapfileheader.bfSize);
  530.             bwrite.Write (bitmapfileheader.bfReserved1);
  531.             bwrite.Write (bitmapfileheader.bfReserved2);
  532.             bwrite.Write (bitmapfileheader.bfOffBits);
  533.             bwrite.Write (bitmapinfoheader.biSize);
  534.             bwrite.Write (bitmapinfoheader.biWidth);
  535.             bwrite.Write (bitmapinfoheader.biHeight);
  536.             bwrite.Write (bitmapinfoheader.biPlanes);
  537.             bwrite.Write (bitmapinfoheader.biBitCount);
  538.             bwrite.Write (bitmapinfoheader.biCompression);
  539.             bwrite.Write (bitmapinfoheader.biSizeImage);
  540.             bwrite.Write (bitmapinfoheader.biXPelsPerMeter);
  541.             bwrite.Write (bitmapinfoheader.biYPelsPerMeter);
  542.             bwrite.Write (bitmapinfoheader.biClrUsed);
  543.             bwrite.Write (bitmapinfoheader.biClrImportant);
  544.             for (int L= 0;L<16;L++) {// R, G, and B must be 0..63
  545.                 bwrite.Write((byte) PCXheader.ColorMap [L, 2]);
  546.                 bwrite.Write((byte) PCXheader.ColorMap [L, 1]);
  547.                 bwrite.Write((byte) PCXheader.ColorMap [L, 0]);
  548.                 bwrite.Write((byte) 0);
  549.             }
  550.             int kmax = PCXheader.Ymin +PCXheader.Ymax;
  551.             int x =0;
  552.             UInt16 count;
  553.             Index = 0;
  554.             bytes_in_line=(RealWidth)/2;
  555.             dY = 4-(bytes_in_line-(bytes_in_line / 4)*4);
  556.             if (dY==4) {
  557.                 dY = 0;
  558.             }
  559.             bytes_in_line=bytes_in_line+dY;
  560.             byte [,] lines = new byte [RealHeight,bytes_in_line*2];
  561.             byte [] line = new byte [bytes_in_line*2];
  562.             for (int i=0; i<(RealHeight); i++) {
  563.                 if (Index != 0) {
  564.                     for (int j=0; j<Index;j++) {
  565.                         line[j]= data; // fills a contiguous block
  566.                     }
  567.                 }
  568.                 while (Index < bytes_per_line) // read 1 line of data (all planes)
  569.                 {
  570.                     data = (byte)stream.ReadByte();
  571.                     if ((byte)(data & (byte)(0xC0)) == (byte)(0xC0)) {
  572.                         count = (UInt16)((byte)(data & (byte)(0x3F)));
  573.                         data = (byte)stream.ReadByte();
  574.                         for (int j=0; j<count;j++) {
  575.                             line[Index+j]= data; // fills a contiguous block
  576.                         }
  577.                         Index += count;
  578.                     } else {
  579.                         line [Index] = data;
  580.                         Index++;
  581.                     }
  582.                 }
  583.                 Index = Index - bytes_per_line;
  584.  
  585.                 for (dY = 0; dY<bytes_in_line*2; dY++) {
  586.                     lines[i,dY]=0;
  587.                 }
  588.                 x=0;
  589.                 for (dY=0; dY<PCXheader.Nplanes; dY++) {
  590.                     for (int j=0; j<PCXheader.Bytes_per_line_per_plane; j++) {
  591.                         c = line[x];
  592.                         x++;
  593.                         for (int k=0; k<8; k++) {
  594.                             if (((byte)c & bitwise.shr(128,(byte)k)) > 0) {
  595.                                 lines[i,(j*8)+k]= (byte)(lines[i,(j*8)+k] | bitwise.shl(1,(byte)dY));
  596.                             }
  597.                         }
  598.                     }
  599.                 }
  600.                 for (dY=0; dY<bytes_in_line*2; dY++) {
  601.                     line[dY]=lines[i,dY];
  602.                 }
  603.                 dY=(-1);
  604.                 x=(-1);
  605.                 while (x<(PCXheader.Xmax - PCXheader.Xmin)) {
  606.                     dY++;
  607.                     x++;
  608.                     lines[i,dY]=(byte)(bitwise.shl(line[x],4) ^ line[x+1] & 0x0F);
  609.                     x++;
  610.                 }
  611.             }
  612.  
  613.             for ( int k = RealHeight-1; k>= 0; k--) {
  614.                 for ( int i = 0; i<(bytes_in_line); i++) {
  615.                     bwrite.Write((byte)lines[k,i]);
  616.                 }
  617.             }
  618.          }catch  (Exception){
  619.             Error=6; // Any problem with reading from or writing to a stream of the image
  620.          }
  621.         }
  622.     }
  623.  
  624. }
  625.  
  626.