home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / 3DTOSHI2.ZIP / mpgfx / source / gfxpcx.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-18  |  12.1 KB  |  519 lines

  1.  
  2. // gfxpcx.cpp
  3. //
  4. // Copyright (c) 1995 by Toshiaki Tsuji, all rights reserved.
  5.  
  6. #include "stdgfx.h"
  7. #include "gfxpcx.h"
  8.  
  9. PCXFILETOOL::PCXFILETOOL ( FILEHANDLE f ) : IMAGEFILETOOL ( f )
  10.   {
  11.     DataBuffer = NULL;
  12.   } // End of Constructor for PCXFILETOOL
  13.  
  14. PCXFILETOOL::~PCXFILETOOL ()
  15.   {
  16.     if (DataBuffer!=NULL)
  17.       delete DataBuffer;
  18.     DataBuffer = NULL;
  19.   } // End of Destructor for PCXFILETOOL
  20.  
  21. BOOLEAN PCXFILETOOL::ReadHeader ()
  22.   {
  23.     BOOLEAN Ok;
  24.  
  25.     File.Seek ( fp, 0, FROM_BEGIN );
  26.  
  27.     Ok = File.Read ( fp, &PCXHeader, 128 );
  28.     if (!Ok)
  29.       return FAILURE;
  30.  
  31.     // Check for valid PCX
  32.     if (PCXHeader.ID!=0x0A)
  33.       return FALSE;
  34.  
  35.     #if defined (__MSBFIRST__)
  36.       SwapWord ( (WORD*)&(PCXHeader.XMin) );
  37.       SwapWord ( (WORD*)&(PCXHeader.YMin) );
  38.       SwapWord ( (WORD*)&(PCXHeader.XMax) );
  39.       SwapWord ( (WORD*)&(PCXHeader.YMax) );
  40.       SwapWord ( (WORD*)&(PCXHeader.XResolution) );
  41.       SwapWord ( (WORD*)&(PCXHeader.YResolution) );
  42.       SwapWord ( (WORD*)&(PCXHeader.BytesPerRow) );
  43.       SwapWord ( (WORD*)&(PCXHeader.PalType) );
  44.       SwapWord ( (WORD*)&(PCXHeader.XScreen) );
  45.       SwapWord ( (WORD*)&(PCXHeader.YScreen) ); 
  46.     #endif
  47.  
  48.     return TRUE;
  49.   } // End of ReadHeader for PCXFILETOOL
  50.  
  51. BOOLEAN PCXFILETOOL::ReadImageRow2 ( IMAGE *Image, INT Row )
  52.   {
  53.     INT Count;
  54.     INT RepCount;
  55.     INT Ch;
  56.     INT i;
  57.     BYTE *Buffer;
  58.     INT Size;
  59.  
  60.     Size = PCXHeader.BytesPerRow;
  61.     Count = 0;
  62.     Buffer = Image->SetOffset ( 0, Row );
  63.  
  64.     while (Count<Size)
  65.       {
  66.         Ch = File.GetCh ( fp );
  67.         if (Ch==EOF)
  68.           return FAILURE;
  69.         if (Ch<192)
  70.           RepCount = 1;
  71.         else
  72.           {
  73.             RepCount = Ch - 192;
  74.             Ch = File.GetCh ( fp );
  75.             if (Ch==EOF)
  76.               return FAILURE;
  77.           } // End else
  78.         for (i=0;i<RepCount;i++)
  79.           {
  80.             DataBuffer[Count] = (BYTE)Ch;
  81.             Count++;
  82.           } // End for
  83.       } // End while
  84.  
  85.     INT Bit1;
  86.     INT Off1;
  87.     INT Mask;
  88.     INT Byte;
  89.  
  90.     Off1 = 0;
  91.  
  92.     Mask = (LONG)1<<7;
  93.     for (i=0;i<Image->GetWidth();i++)
  94.       {
  95.         Bit1 = (DataBuffer[Off1+(i)/8]&Mask)&&1;
  96.         Byte = (Bit1<<0);
  97.         Buffer[i] = (BYTE)Byte;
  98.  
  99.         if (Mask==1)
  100.           Mask = (LONG)1<<7;
  101.         else
  102.           Mask >>= 1;
  103.       } // End for
  104.  
  105.     return SUCCESS;
  106.   } // End of ReadImageRow2 for PCXFILETOOL
  107.  
  108. BOOLEAN PCXFILETOOL::ReadImageRow4 ( IMAGE *Image, INT Row )
  109.   {
  110.     INT Count;
  111.     INT RepCount;
  112.     INT Ch;
  113.     INT i;
  114.     BYTE *Buffer;
  115.     INT Size;
  116.  
  117.     Size = PCXHeader.BytesPerRow*2;
  118.     Count = 0;
  119.     Buffer = Image->SetOffset ( 0, Row );
  120.  
  121.     while (Count<Size)
  122.       {
  123.         Ch = File.GetCh ( fp );
  124.         if (Ch==EOF)
  125.           return FAILURE;
  126.         if (Ch<192)
  127.           RepCount = 1;
  128.         else
  129.           {
  130.             RepCount = Ch - 192;
  131.             Ch = File.GetCh ( fp );
  132.             if (Ch==EOF)
  133.               return FAILURE;
  134.           } // End else
  135.         for (i=0;i<RepCount;i++)
  136.           {
  137.             DataBuffer[Count] = (BYTE)Ch;
  138.             Count++;
  139.           } // End for
  140.       } // End while
  141.  
  142.     INT Bit1,Bit2;
  143.     INT Off1,Off2;
  144.     INT Mask;
  145.     INT Byte;
  146.  
  147.     Off1 = 0;
  148.     Off2 = PCXHeader.BytesPerRow;
  149.  
  150.     Mask = (LONG)1<<7;
  151.     for (i=0;i<Image->GetWidth();i++)
  152.       {
  153.         Bit1 = (DataBuffer[Off1+(i)/8]&Mask)&&1;
  154.         Bit2 = (DataBuffer[Off2+(i)/8]&Mask)&&1;
  155.         Byte = (Bit1<<0)+(Bit2<<1);
  156.         Buffer[i] = (BYTE)Byte;
  157.  
  158.         if (Mask==1)
  159.           Mask = (LONG)1<<7;
  160.         else
  161.           Mask >>= 1;
  162.       } // End for
  163.  
  164.     return SUCCESS;
  165.   } // End of ReadImageRow4 for PCXFILETOOL
  166.  
  167. BOOLEAN PCXFILETOOL::ReadImageRow16 ( IMAGE *Image, INT Row )
  168.   {
  169.     INT Count;
  170.     INT RepCount;
  171.     INT Ch;
  172.     INT i;
  173.     BYTE *Buffer;
  174.     INT Size;
  175.  
  176.     Size = PCXHeader.BytesPerRow*4;
  177.     Count = 0;
  178.     Buffer = Image->SetOffset ( 0, Row );
  179.  
  180.     while (Count<Size)
  181.       {
  182.         Ch = File.GetCh ( fp );
  183.         if (Ch==EOF)
  184.           return FAILURE;
  185.         if (Ch<192)
  186.           RepCount = 1;
  187.         else
  188.           {
  189.             RepCount = Ch - 192;
  190.             Ch = File.GetCh ( fp );
  191.             if (Ch==EOF)
  192.               return FAILURE;
  193.           } // End else
  194.         for (i=0;i<RepCount;i++)
  195.           {
  196.             DataBuffer[Count] = (BYTE)Ch;
  197.             Count++;
  198.           } // End for
  199.       } // End while
  200.  
  201.     INT Bit1,Bit2,Bit3,Bit4;
  202.     INT Off1,Off2,Off3,Off4;
  203.     INT Mask;
  204.     INT Byte;
  205.  
  206.     Off1 = 0;
  207.     Off2 = PCXHeader.BytesPerRow;
  208.     Off3 = PCXHeader.BytesPerRow*2;
  209.     Off4 = PCXHeader.BytesPerRow*3;
  210.  
  211.     Mask = (LONG)1<<7;
  212.     for (i=0;i<Image->GetWidth();i++)
  213.       {
  214.         Bit1 = (DataBuffer[Off1+(i)/8]&Mask)&&1;
  215.         Bit2 = (DataBuffer[Off2+(i)/8]&Mask)&&1;
  216.         Bit3 = (DataBuffer[Off3+(i)/8]&Mask)&&1;
  217.         Bit4 = (DataBuffer[Off4+(i)/8]&Mask)&&1;
  218.         Byte = (Bit1<<0)+(Bit2<<1)+(Bit3<<2)+(Bit4<<3);
  219.         Buffer[i] = (BYTE)Byte;
  220.  
  221.         if (Mask==1)
  222.           Mask = (LONG)1<<7;
  223.         else
  224.           Mask >>= 1;
  225.       } // End for
  226.  
  227.     return SUCCESS;
  228.   } // End of ReadImageRow16 for PCXFILETOOL
  229.  
  230. BOOLEAN PCXFILETOOL::ReadImageRow256 ( IMAGE *Image, INT Row )
  231.   {
  232.     INT Count;
  233.     INT RepCount;
  234.     INT Ch;
  235.     INT i;
  236.     BYTE *Buffer;
  237.  
  238.     Count = 0;
  239.     Buffer = Image->SetOffset ( 0, Row );
  240.  
  241.     while (Count<PCXHeader.BytesPerRow)
  242.       {
  243.         Ch = File.GetCh ( fp );
  244.         if (Ch==EOF)
  245.           return FAILURE;
  246.         if (Ch<192)
  247.           RepCount = 1;
  248.         else
  249.           {
  250.             RepCount = Ch - 192;
  251.             Ch = File.GetCh ( fp );
  252.             if (Ch==EOF)
  253.               return FAILURE;
  254.           } // End else
  255.         if (Count<Image->GetWidth())
  256.           {
  257.             for (i=0;i<RepCount;i++)
  258.               {
  259.                 Buffer[Count] = (BYTE)Ch;
  260.                 Count++;
  261.               } // End for
  262.           } // End for
  263.         else
  264.           {
  265.             for (i=0;i<RepCount;i++)
  266.               {
  267.                 Count++;
  268.               } // End for
  269.           } // End for
  270.       } // End while
  271.  
  272.     return SUCCESS;
  273.   } // End of ReadImageRow256 for PCXFILETOOL
  274.  
  275. BOOLEAN PCXFILETOOL::ReadImage ( IMAGE *Image)
  276.   {
  277.     INT i;
  278.     BOOLEAN Ok;
  279.  
  280.     File.Seek ( fp, 128, FROM_BEGIN );
  281.  
  282.     DataBuffer = NULL;
  283.     DataBuffer = new BYTE[(PCXHeader.BytesPerRow+1)*PCXHeader.NumPlanes];
  284.  
  285.     for (i=0;i<Image->GetHeight();i++)
  286.       {
  287.         if (PCXHeader.BitsPerPixel==8)
  288.           Ok = ReadImageRow256 ( Image, i );
  289.         else if (PCXHeader.NumPlanes==4)
  290.           Ok = ReadImageRow16 ( Image, i );
  291.         else if (PCXHeader.NumPlanes==2)
  292.           Ok = ReadImageRow4 ( Image, i );
  293.         else if (PCXHeader.NumPlanes==1)
  294.           Ok = ReadImageRow2 ( Image, i );
  295.         if (!Ok)
  296.           return FAILURE;
  297.       } // End for
  298.  
  299.     if (DataBuffer!=NULL)  
  300.       delete DataBuffer;
  301.     DataBuffer = NULL;  
  302.  
  303.     return SUCCESS;
  304.   } // End of ReadImage for PCXFILETOOL
  305.  
  306. BOOLEAN PCXFILETOOL::ReadPalette ( RGBPALETTE *Pal )
  307.   {
  308.     INT i;
  309.     if (Pal==NULL)
  310.       return SUCCESS;
  311.  
  312.     RGBCOLOR *Entry;
  313.  
  314.     Entry = Pal->GetEntry ();
  315.  
  316.     if (PCXHeader.BitsPerPixel>=8)
  317.       {
  318.         File.Seek ( fp, -768, FROM_END );
  319.         for (i=0;i<256;i++)
  320.           {
  321.             Entry[i].Red = (BYTE)File.GetCh ( fp );
  322.             Entry[i].Green = (BYTE)File.GetCh ( fp );
  323.             Entry[i].Blue = (BYTE)File.GetCh ( fp );
  324.           } // End for
  325.       } // End if
  326.     else
  327.       {
  328.         for (i=0;i<16;i++)
  329.           {
  330.             Entry[i].Red = (BYTE)PCXHeader.Palette[i].Red;
  331.             Entry[i].Red = (BYTE)PCXHeader.Palette[i].Green;
  332.             Entry[i].Red = (BYTE)PCXHeader.Palette[i].Blue;
  333.           } // End for
  334.       } // End else
  335.       
  336.     return SUCCESS;
  337.   } // End of ReadPalette for PCXFILETOOL
  338.  
  339. BOOLEAN PCXFILETOOL::LoadImage ( IMAGE *Image, RGBPALETTE *Pal  )
  340.   {
  341.     BOOLEAN Ok;
  342.  
  343.     if (Image==NULL)
  344.       return FAILURE;
  345.  
  346.     Ok = ReadHeader ();
  347.     if (!Ok)
  348.       return FAILURE;
  349.  
  350.     INT Wd,Ht;
  351.  
  352.     Wd = PCXHeader.XMax - PCXHeader.XMin + 1;
  353.     Ht = PCXHeader.YMax - PCXHeader.YMin + 1;
  354.  
  355.     Ok = Image->Create ( IMAGE_8BIT, Wd, Ht );
  356.     if (!Ok)
  357.       return FAILURE;
  358.  
  359.     Ok = ReadImage ( Image );
  360.     if (!Ok)
  361.       return FAILURE;
  362.  
  363.     Ok = ReadPalette ( Pal );
  364.     if (!Ok)
  365.       return FAILURE;
  366.  
  367.     return SUCCESS;
  368.   } // End of LoadImage for PCXFILETOOL
  369.  
  370. BOOLEAN PCXFILETOOL::WriteHeader ( INT Wd, INT Ht )
  371.   {
  372.     PCXHeader.ID = 0x0A;
  373.     PCXHeader.Version = 5;
  374.     PCXHeader.Encoding = 1;
  375.     PCXHeader.BitsPerPixel = 8;
  376.     PCXHeader.XMin = 0;
  377.     PCXHeader.YMin = 0;
  378.     PCXHeader.XMax = (SHORT)(Wd-1);
  379.     PCXHeader.YMax = (SHORT)(Ht-1);
  380.     PCXHeader.XResolution = 0;
  381.     PCXHeader.YResolution = 0;
  382.     PCXHeader.Reserved = 0;
  383.     PCXHeader.NumPlanes = 1;
  384.     if (Wd&0x01)
  385.       PCXHeader.BytesPerRow = (SHORT)(Wd+1);
  386.     else
  387.       PCXHeader.BytesPerRow = (SHORT)(Wd);
  388.  
  389.     PCXHeader.PalType = 1;
  390.     PCXHeader.XScreen = 0;
  391.     PCXHeader.YScreen = 0;
  392.  
  393.     #if defined (__MSBFIRST__)
  394.       SwapWord ( (WORD*)&(PCXHeader.XMin) );
  395.       SwapWord ( (WORD*)&(PCXHeader.YMin) );
  396.       SwapWord ( (WORD*)&(PCXHeader.XMax) );
  397.       SwapWord ( (WORD*)&(PCXHeader.YMax) );
  398.       SwapWord ( (WORD*)&(PCXHeader.XResolution) );
  399.       SwapWord ( (WORD*)&(PCXHeader.YResolution) );
  400.       SwapWord ( (WORD*)&(PCXHeader.BytesPerRow) );
  401.       SwapWord ( (WORD*)&(PCXHeader.PalType) );
  402.       SwapWord ( (WORD*)&(PCXHeader.XScreen) );
  403.       SwapWord ( (WORD*)&(PCXHeader.YScreen) ); 
  404.     #endif
  405.  
  406.     BOOLEAN Ok;
  407.  
  408.     File.Seek ( fp, 0, FROM_BEGIN );
  409.     Ok = File.Write ( fp, &PCXHeader, 128 );
  410.     if (!Ok)
  411.       return FAILURE;
  412.     return SUCCESS;
  413.   } // End of WriteHeader for PCXGILETOOL
  414.  
  415. BOOLEAN PCXFILETOOL::WriteImageRow256 ( IMAGE *Image, INT Sx, INT Wd, INT WhichRow )
  416.   {
  417.     BYTE *Buffer;
  418.     INT Ch;
  419.     INT Count;
  420.     INT RepCount;
  421.     INT Size;
  422.  
  423.     Size = Wd;
  424.     Buffer = Image->SetOffset ( Sx, WhichRow );
  425.     Count = 0;
  426.  
  427.     while (Count<Size)
  428.       {
  429.         RepCount = 1;
  430.         Ch = Buffer[Count];
  431.         Count++;
  432.         while ((Ch==Buffer[Count])&&(RepCount<63)&&(Count<Size))
  433.           {
  434.             Count++;
  435.             RepCount++;
  436.           } // End if
  437.         if ((Ch<192)&&(RepCount==1))
  438.           {
  439.             File.PutCh ( fp, (CHAR)Ch );
  440.           } // End if
  441.         else
  442.           {
  443.             RepCount += 192;
  444.             File.PutCh ( fp, (CHAR)RepCount );
  445.             File.PutCh ( fp, (CHAR)Ch );
  446.           } // End if
  447.       } // End while
  448.  
  449.     if (Wd<PCXHeader.BytesPerRow)
  450.       File.PutCh ( fp, 0 );
  451.  
  452.     return SUCCESS;
  453.   } // End of WriteImageRow256 for PCXFILETOOL
  454.  
  455. BOOLEAN PCXFILETOOL::WriteImage ( IMAGE *Image, INT Sx, INT Sy, INT Wd, INT Ht  )
  456.   {
  457.     INT i;
  458.     BOOLEAN Ok;
  459.  
  460.     for (i=0;i<Ht;i++)
  461.       {
  462.         Ok = WriteImageRow256 ( Image, Sx, Wd, Sy+i );
  463.         if (!Ok)
  464.           return FAILURE;
  465.       } // End for
  466.     return SUCCESS;
  467.   } // End of WriteImage for PCXFILETOOL
  468.  
  469. BOOLEAN PCXFILETOOL::WritePalette ( RGBPALETTE *Pal )
  470.   {
  471.     RGBCOLOR *Entry;
  472.  
  473.     File.PutCh ( fp, 0x0C );
  474.  
  475.     if (Pal==NULL)
  476.       {
  477.         return FAILURE;
  478.       } // End if
  479.     else
  480.       {
  481.         Entry = Pal->GetEntry ();
  482.  
  483.         INT i;
  484.         for (i=0;i<256;i++)
  485.           {
  486.             File.PutCh ( fp, Entry[i].Red );
  487.             File.PutCh ( fp, Entry[i].Green );
  488.             File.PutCh ( fp, Entry[i].Blue );
  489.           } // End for
  490.       } // End else
  491.     return SUCCESS;
  492.   } // End of WritePalette for PCXGILETOOL
  493.  
  494. BOOLEAN PCXFILETOOL::SaveImage ( IMAGE *Image, LONG Sx, LONG Sy,
  495.                                  LONG Wd, LONG Ht, RGBPALETTE *Pal  )
  496.   {
  497.     if (Image==NULL)
  498.       {
  499.         return FAILURE;
  500.       } // End if
  501.  
  502.     BOOLEAN Ok;
  503.  
  504.     Ok = WriteHeader ( Wd, Ht );
  505.     if (!Ok)
  506.       return FAILURE;
  507.  
  508.     Ok = WriteImage ( Image, Sx, Sy, Wd, Ht );
  509.     if (!Ok)
  510.       return FAILURE;
  511.  
  512.     Ok = WritePalette ( Pal );
  513.     if (!Ok)
  514.       return FAILURE;
  515.  
  516.     return SUCCESS;
  517.   } // End of SaveImage for PCXFILETOOL
  518.  
  519.