home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / 3DTOSHI2.ZIP / mpgfx / source / gfxflic.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-20  |  27.8 KB  |  1,070 lines

  1.  
  2. // gfxflic.cpp
  3. //
  4. // Copyright (c) 1995 by Toshiaki Tsuji, all rights reserved.
  5.  
  6. #include "stdgfx.h"
  7. #include "gfxflic.h"
  8.  
  9. #define ID_PREFIX 0xF100
  10. #define ID_FRAME  0xF1FA
  11. #define ID_FRAME_NODATA  0x00A1
  12.  
  13. FLICFILE::FLICFILE () : MYOBJECT ()
  14.   {
  15.     FLICHeader.FLI.NumFrames = 0;
  16.     FLICHeader.FLI.Width = 0;
  17.     FLICHeader.FLI.Height = 0;
  18.     FrameData = NULL;
  19.     f = NULL;
  20.     CurrentFrame = 0;
  21.     Image = NULL;
  22.     Pal = new RGBPALETTE ();
  23.     PalChange = FALSE;
  24.     hDisplay = NULL;
  25.     Speed = FLIC_SPEED_DEFAULT;
  26.     Loop = FLIC_LOOP_INFINITE;
  27.     DefaultSpeed = 0;
  28.   } // End of Constructor for FLICFILE
  29.  
  30. FLICFILE::~FLICFILE ()
  31.   {
  32.     DestroyFrames ();
  33.     
  34.     if (Image!=NULL)
  35.       delete Image;
  36.     Image = NULL;
  37.     
  38.     if (Pal!=NULL)
  39.       delete Pal;
  40.     Pal = NULL;  
  41.   } // End of Destructor for FLICFILE
  42.  
  43. BOOLEAN FLICFILE::ReadHeader ()
  44.   {
  45.     if (File.Read ( f, &FLICHeader, 128 )==FAILURE)
  46.       return FAILURE;
  47.  
  48.     #if defined (__MSBFIRST__)
  49.       SwapDWord ( (DWORD*)&FLICHeader.FLI.Size );
  50.       SwapWord ( (WORD*)&FLICHeader.FLI.ID );
  51.       SwapWord ( (WORD*)&FLICHeader.FLI.NumFrames );
  52.       SwapWord ( (WORD*)&FLICHeader.FLI.Width );
  53.       SwapWord ( (WORD*)&FLICHeader.FLI.Height );
  54.       SwapWord ( (WORD*)&FLICHeader.FLI.Reserved1 );
  55.       SwapWord ( (WORD*)&FLICHeader.FLI.Flag );
  56.       SwapDWord ( (DWORD*)&FLICHeader.FLC.Speed );
  57.       SwapWord ( (WORD*)&FLICHeader.FLC.Unused );
  58.       SwapDWord ( (DWORD*)&FLICHeader.FLC.Created );
  59.       SwapDWord ( (DWORD*)&FLICHeader.FLC.Creator );
  60.       SwapDWord ( (DWORD*)&FLICHeader.FLC.Updated );
  61.       SwapDWord ( (DWORD*)&FLICHeader.FLC.Updator );
  62.       SwapWord ( (WORD*)&FLICHeader.FLC.AspectX );
  63.       SwapWord ( (WORD*)&FLICHeader.FLC.AspectY );
  64.       SwapDWord ( (DWORD*)&FLICHeader.FLC.Offset1 );
  65.       SwapDWord ( (DWORD*)&FLICHeader.FLC.Offset2 );
  66.     #endif
  67.  
  68.     if (FLICHeader.FLI.ID==(SHORT)ID_FLI)
  69.       IsFLC = FALSE;
  70.     else if (FLICHeader.FLI.ID==(SHORT)ID_FLC)
  71.       IsFLC = TRUE;
  72.     else
  73.       return FAILURE;
  74.     return SUCCESS;
  75.   } // End of ReadHeader for FLICFILE
  76.  
  77. BOOLEAN FLICFILE::ReadChunk ( CHUNK_DATA *Chunk )
  78.   {
  79.     BOOLEAN Ok;
  80.     DWORD Size;
  81.  
  82.     if (File.Read ( f, &(Chunk->Header), 6 )==FAILURE)
  83.       return FAILURE;
  84.  
  85.     #if defined (__MSBFIRST__)
  86.       SwapDWord ( (DWORD*)&(Chunk->Header.Size) );
  87.       SwapWord ( (DWORD*)&(Chunk->Header.Type) );
  88.     #endif
  89.  
  90.     Size = Chunk->Header.Size - 6;
  91.  
  92.     Chunk->Data = new BYTE [Size];
  93.     if (Chunk->Data==NULL)
  94.       return FAILURE;
  95.  
  96.     if (File.Read ( f, Chunk->Data, Size )==FAILURE)
  97.       return FAILURE;
  98.  
  99.     return Ok;
  100.   } // End of ReadChunk for FLICFILE
  101.  
  102. BOOLEAN FLICFILE::ReadFrame ( LONG WhichFrame )
  103.   {
  104.     FRAMEHEADER FrameHeader;
  105.     // Read Frame Header
  106.     if (File.Read ( f, &FrameHeader, 16 )==FAILURE)
  107.       return FAILURE;
  108.  
  109.     #if defined (__MSBFIRST__)
  110.       SwapDWord ( (DWORD*)&(FrameHeader.Size) );
  111.       SwapWord ( (WORD*)&(FrameHeader.ID) );
  112.       SwapWord ( (WORD*)&(FrameHeader.NumChunks) );
  113.     #endif
  114.  
  115.     if (FrameHeader.ID==(SHORT)ID_PREFIX) // If prefix header, read next one
  116.       {
  117.         File.Seek ( f, FrameHeader.Size-16, FROM_CURRENT );
  118.         if (File.Read ( f, &FrameHeader, 16 )==FAILURE)
  119.           return FAILURE;
  120.       } // End if
  121.     else if (FrameHeader.ID==(SHORT)ID_FRAME_NODATA) // If no pixel data, skip
  122.       {
  123.         File.Seek ( f, FrameHeader.Size-16, FROM_CURRENT );
  124.         if (File.Read ( f, &FrameHeader, 16 )==FAILURE)
  125.           return FAILURE;
  126.       } // End if
  127.     else if (FrameHeader.ID!=(SHORT)ID_FRAME)
  128.       return FAILURE;
  129.  
  130.     FrameData[WhichFrame].NumChunks = FrameHeader.NumChunks;
  131.     FrameData[WhichFrame].Chunks = new CHUNK_DATA [FrameHeader.NumChunks];
  132.     if (FrameData[WhichFrame].Chunks==NULL)
  133.       return FAILURE;
  134.  
  135.     LONG i;
  136.     for (i=0;i<FrameHeader.NumChunks;i++)
  137.       {
  138.         FrameData[WhichFrame].Chunks[i].Data = NULL;
  139.       } // End for
  140.  
  141.     BOOLEAN Ok;
  142.  
  143.     for (i=0;i<FrameHeader.NumChunks;i++)
  144.       {
  145.         Ok = ReadChunk ( &(FrameData[WhichFrame].Chunks[i]) );
  146.         if (!Ok)
  147.           return FAILURE;
  148.       } // End for
  149.  
  150.     return TRUE;
  151.   } // End of ReadFrame for FLICFILE
  152.  
  153. VOID FLICFILE::DestroyFrames ()
  154.   {
  155.     INT i,j;
  156.  
  157.     if (FrameData!=NULL)
  158.       {
  159.         for (i=0;i<FLICHeader.FLI.NumFrames;i++)
  160.           {
  161.             for (j=0;j<FrameData[i].NumChunks;j++)
  162.               {
  163.                 if (FrameData[i].Chunks[j].Data!=NULL)
  164.                   delete FrameData[i].Chunks[j].Data;
  165.                 FrameData[i].Chunks[j].Data=NULL;
  166.               } // End for
  167.             if (FrameData[i].Chunks!=NULL)
  168.               delete FrameData[i].Chunks;
  169.             FrameData[i].Chunks=NULL;
  170.           } // End for
  171.  
  172.         delete FrameData;
  173.       } // End if
  174.     FrameData = NULL;
  175.   } // End of DestroyFrames for FLICFILE
  176.  
  177. BOOLEAN FLICFILE::SetDisplay ( HDISPLAY Display )
  178.   {
  179.     if (Image!=NULL)
  180.       delete Image;
  181.     Image = NULL;  
  182.     hDisplay = Display;  
  183.     if (FLICHeader.FLI.NumFrames)
  184.       {
  185.         #if defined (__FORWIN32__)
  186.           GetFirstPalette ();
  187.           LOGPALETTE *LogPal;
  188.           RGBCOLOR *Entry;
  189.           HPALETTE hPal,OldPal;      
  190.  
  191.           Entry = Pal->GetEntry ();
  192.  
  193.           LogPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE)+
  194.                                         sizeof(RGBQUAD)*256);
  195.           if (LogPal==NULL)
  196.             return FAILURE;
  197.  
  198.           INT i;
  199.           LogPal->palVersion = 0x300;
  200.           LogPal->palNumEntries = 256;
  201.           for (i=0;i<256;i++)
  202.             {
  203.               LogPal->palPalEntry[i].peRed = Entry[i].Red;  
  204.               LogPal->palPalEntry[i].peGreen = Entry[i].Green;  
  205.               LogPal->palPalEntry[i].peBlue = Entry[i].Blue;
  206.               LogPal->palPalEntry[i].peFlags = 0;              
  207.             } // End for
  208.             
  209.           hPal = CreatePalette ( (LOGPALETTE*)LogPal );     
  210.           OldPal = SelectPalette ( hDisplay, hPal, FALSE );
  211.           RealizePalette ( hDisplay );
  212.           Image = new IMAGE ( IMAGE_BOTTOMUP );
  213.           if (Image->Create ( hDisplay, IMAGE_8BIT, FLICHeader.FLI.Width, FLICHeader.FLI.Height )==FAILURE)
  214.             return FAILURE;
  215.             
  216.           SelectPalette ( hDisplay, OldPal, FALSE );
  217.           RealizePalette ( hDisplay );
  218.           DeleteObject ( hPal );        
  219.           free ( LogPal );
  220.         #elif defined (__FORWINDOWS__)
  221.           Image = new IMAGE ( IMAGE_BOTTOMUP );
  222.           if (Image->Create ( IMAGE_8BIT, FLICHeader.FLI.Width, FLICHeader.FLI.Height )==FAILURE)
  223.             return FAILURE;
  224.         #else  
  225.           Image = new IMAGE ( IMAGE_TOPDOWN );
  226.           if (Image->Create ( IMAGE_8BIT, FLICHeader.FLI.Width, FLICHeader.FLI.Height )==FAILURE)
  227.             return FAILURE;
  228.         #endif
  229.         
  230.         LONG Frame=CurrentFrame;
  231.         CurrentFrame = 0;
  232.         SetFrame ( Frame );
  233.       } // End if
  234.     return SUCCESS;  
  235.   } // End of SetDisplay for FLICFILE
  236.  
  237. BOOLEAN FLICFILE::CreateImage ()
  238.   {
  239.     if (FLICHeader.FLI.NumFrames==0)
  240.       return FAILURE;
  241.       
  242.     Image = new IMAGE ( IMAGE_TOPDOWN );
  243.     if (Image->Create ( IMAGE_8BIT, FLICHeader.FLI.Width, FLICHeader.FLI.Height )==FAILURE)
  244.       return FAILURE;
  245.       
  246.     SetFrame ( 0 );
  247.     return SUCCESS;
  248.   } // End of CreateImage for FLICFILE
  249.  
  250. BOOLEAN FLICFILE::Load ( STRING FileName )
  251.   {
  252.     BOOLEAN Ok;
  253.  
  254.     if (Image!=NULL)
  255.       delete Image;
  256.     Image = NULL;
  257.       
  258.     if (f!=NULL)
  259.       File.Close ( f );
  260.       
  261.     f = File.Open ( FileName, OPEN_READ | OPEN_BINARY );
  262.     if (f==NULL)
  263.       return FAILURE;
  264.       
  265.     Ok = ReadHeader ();
  266.     if (!Ok)
  267.       {
  268.         File.Close ( f );
  269.         return FAILURE;
  270.       } // End if  
  271.  
  272.     if (FrameData!=NULL)
  273.       delete FrameData;
  274.  
  275.     FrameData = new FRAME_DATA [FLICHeader.FLI.NumFrames];
  276.     if (FrameData==NULL)
  277.       {
  278.         File.Close ( f );
  279.         return FAILURE;
  280.       } // End if  
  281.  
  282.     LONG i,NumFrames;
  283.  
  284.     NumFrames = FLICHeader.FLI.NumFrames;
  285.  
  286.     for (i=0;i<NumFrames;i++)
  287.       {
  288.         FrameData[i].Chunks = NULL;
  289.       } // End for
  290.  
  291.     for (i=0;i<NumFrames;i++)
  292.       {
  293.         Ok = ReadFrame ( i );
  294.         if (!Ok)
  295.           {
  296.             File.Close ( f );
  297.             return FAILURE;
  298.           } // End if  
  299.       } // End for
  300.  
  301.     DefaultSpeed = FLICHeader.FLI.Speed;
  302.     File.Close ( f );
  303.  
  304.     CreateImage ();    
  305.     return SUCCESS;
  306.   } // End of Load for FLICFILE
  307.  
  308. BOOLEAN FLICFILE::DoColor ( RGBPALETTE *Pal, CHUNK_DATA* Chunk, BOOLEAN Is256 )
  309.   {
  310.     INT i,j,Index;
  311.     SHORT NumChanges;
  312.     BYTE *Data;
  313.     DWORD Offset;
  314.     RGBCOLOR *Entry;
  315.  
  316.     if (Pal==NULL)
  317.       return FAILURE;
  318.  
  319.     Entry = Pal->GetEntry ();
  320.       
  321.     Index = 0;
  322.     Offset = 0;
  323.     Data = Chunk->Data;
  324.     NumChanges = (*(SHORT*)(Data+Offset));
  325.  
  326.     #if defined (__MSBFIRST__)
  327.       SwapWord ( (WORD*)&NumChanges );
  328.     #endif
  329.  
  330.     Offset+=2;
  331.  
  332.     INT Count;
  333.  
  334.     for (i=0;i<NumChanges;i++)
  335.       {
  336.         Index += Data[Offset++];
  337.         Count = Data[Offset++];
  338.  
  339.         if (Count==0)
  340.           Count = 256;
  341.  
  342.         for (j=0;j<Count;j++)
  343.           {
  344.             if (Is256)
  345.               {
  346.                 Entry[Index].Red = Data[Offset++];
  347.                 Entry[Index].Green = Data[Offset++];
  348.                 Entry[Index].Blue = Data[Offset++];
  349.               } // End if
  350.             else
  351.               {
  352.                 Entry[Index].Red = (BYTE)(Data[Offset++]<<2);
  353.                 Entry[Index].Green = (BYTE)(Data[Offset++]<<2);
  354.                 Entry[Index].Blue = (BYTE)(Data[Offset++]<<2);
  355.               } // End else
  356.  
  357.             Index++;
  358.           } // End for
  359.         if (Count&0x01)
  360.           Offset++; // Padding byte
  361.       } // End for
  362.  
  363.     PalChange = TRUE;
  364.     return SUCCESS;
  365.   } // End of DoColor for FLICFILE
  366.  
  367. BOOLEAN FLICFILE::DoLine ( IMAGE *Image, CHUNK_DATA* Chunk )
  368.   {
  369.     SHORT SkipLines,ChangeLines;
  370.     DWORD Offset;
  371.     BYTE *Data;
  372.  
  373.     Data = Chunk->Data;
  374.     Offset = 0;
  375.  
  376.     SkipLines = (*(SHORT*)(Data+Offset));
  377.     Offset += 2;
  378.     ChangeLines = (*(SHORT*)(Data+Offset));
  379.     Offset += 2;
  380.  
  381.     #if defined (__MSBFIRST__)
  382.       SwapWord ( (WORD*)&SkipLines );
  383.       SwapWord ( (WORD*)&ChangeLines );
  384.     #endif
  385.  
  386.     INT i,j,k;
  387.     BYTE *Buffer;
  388.     LONG BuffOffset;
  389.     INT Count;
  390.     INT SkipPixel;
  391.  
  392.     Buffer = Image->GetBuffer ();
  393.     
  394.     for (i=0;i<SkipLines;i++)
  395.       Buffer = Image->GetNextRow ( ROW_DOWN );
  396.  
  397.     for (i=0;i<ChangeLines;i++)
  398.       {
  399.         BuffOffset = 0;
  400.         INT NumPackets;
  401.  
  402.         NumPackets = Data[Offset++];
  403.  
  404.  
  405.         for (j=0;j<NumPackets;j++)
  406.           {
  407.             SkipPixel = Data[Offset++];
  408.             BuffOffset += SkipPixel;
  409.  
  410.             Count = Data[Offset++];
  411.             if (Count<128)
  412.               {
  413.                 for (k=0;k<Count;k++)
  414.                   Buffer[BuffOffset++] = Data[Offset++];
  415.               } // End if
  416.             else
  417.               {
  418.                 Count = 256 - Count;
  419.                 BYTE Color;
  420.                 Color = Data[Offset++];
  421.                 for (k=0;k<Count;k++)
  422.                   Buffer[BuffOffset++] = Color;
  423.               } // End Count
  424.           } // End for
  425.  
  426.         Buffer = Image->GetNextRow ( ROW_DOWN );
  427.       } // End for
  428.  
  429.     return SUCCESS;
  430.   } // End of DoLine for FLICFILE
  431.  
  432. BOOLEAN FLICFILE::DoLineWord ( IMAGE *Image, CHUNK_DATA* Chunk )
  433.   {
  434.     SHORT LineCount,Content;
  435.     DWORD Offset;
  436.     BYTE *Data;
  437.  
  438.     Data = Chunk->Data;
  439.     Offset = 0;
  440.  
  441.     LineCount = (*(SHORT*)(Data+Offset));
  442.  
  443.     #if defined (__MSBFIRST__)
  444.       SwapWord ( (WORD*)&LineCount );
  445.     #endif
  446.  
  447.     Offset += 2;
  448.  
  449.     INT i,j,k;
  450.     BYTE *Buffer;
  451.     LONG BuffOffset;
  452.     INT Count;
  453.     INT SkipPixel;
  454.     SHORT SkipLine;
  455.  
  456.     Buffer =Image->GetBuffer ();
  457.  
  458.     BOOLEAN Done;
  459.     INT NumPackets;
  460.  
  461.     for (i=0;i<LineCount;i++)
  462.       {
  463.         BuffOffset = 0;
  464.  
  465.         Content = (*(SHORT*)(Data+Offset));
  466.         #if defined (__MSBFIRST__)
  467.           SwapWord ( (WORD*)&Content );
  468.         #endif
  469.  
  470.         Offset += 2;
  471.  
  472.         Done = FALSE;
  473.         while (!Done)
  474.           {
  475.             if ((Content&0xC000)==0xC000) // If Top 2 bits are 11
  476.               {
  477.                 SkipLine = (SHORT)(-Content);
  478.                 for (j=0;j<SkipLine;j++)
  479.                   Buffer = Image->GetNextRow ( ROW_DOWN );
  480.  
  481.                 Content = (*(SHORT*)(Data+Offset));
  482.                 #if defined (__MSBFIRST__)
  483.                   SwapWord ( (WORD*)&Content );
  484.                 #endif
  485.  
  486.                 Offset += 2;
  487.               } // End if
  488.             else if ((Content&0xC000)==0x00) // If Top 2 bits are 00
  489.               {
  490.                 NumPackets = Content;
  491.                 Done = TRUE;
  492.               } // End else if
  493.             else if ((Content&0x8000)==0x8000) //  If Top 2 bits are 10
  494.               {
  495.                 Content &= 0xFFFF;
  496.                 Done = TRUE;
  497.                 NumPackets = 0;
  498.               } // End else if
  499.             else // Unknown type
  500.               {
  501.                 return FAILURE;
  502.               } // End else
  503.           } // End while
  504.  
  505.         for (j=0;j<NumPackets;j++)
  506.           {
  507.             SkipPixel = Data[Offset++];
  508.             BuffOffset += SkipPixel;
  509.  
  510.             Count = Data[Offset++];
  511.             if (Count<128)
  512.               {
  513.                 for (k=0;k<Count;k++)
  514.                   {
  515.                     Buffer[BuffOffset++] = Data[Offset++];
  516.                     Buffer[BuffOffset++] = Data[Offset++];
  517.                   } // End for
  518.               } // End if
  519.             else
  520.               {
  521.                 Count = 256 - Count;
  522.                 BYTE Color1,Color2;
  523.                 Color1 = Data[Offset++];
  524.                 Color2 = Data[Offset++];
  525.                 for (k=0;k<Count;k++)
  526.                   {
  527.                     Buffer[BuffOffset++] = Color1;
  528.                     Buffer[BuffOffset++] = Color2;
  529.                   } // End for
  530.               } // End Count
  531.           } // End for
  532.  
  533.         Buffer = Image->GetNextRow ( ROW_DOWN );
  534.       } // End for
  535.     return SUCCESS;
  536.   } // End of DoLineWord for FLICFILE
  537.  
  538. BOOLEAN FLICFILE::DoBRun ( IMAGE *Image, CHUNK_DATA* Chunk )
  539.   {
  540.     DWORD Offset;
  541.     BYTE *Data;
  542.  
  543.     Data = Chunk->Data;
  544.     Offset = 0;
  545.  
  546.     INT i,j,k;
  547.     BYTE *Buffer;
  548.     LONG BuffOffset;
  549.     INT Count;
  550.  
  551.     Buffer = Image->SetOffset ( 0, 0 );
  552.  
  553.     for (i=0;i<Image->GetHeight();i++)
  554.       {
  555.         INT NumPackets;
  556.  
  557.         BuffOffset = 0;
  558.  
  559.         NumPackets = Data[Offset++];
  560.  
  561.         for (j=0;j<NumPackets;j++)
  562.           {
  563.             Count = Data[Offset++];
  564.             BYTE Color;
  565.             if (Count<128)
  566.               {
  567.                 Color = Data[Offset++];
  568.                 for (k=0;k<Count;k++)
  569.                   Buffer[BuffOffset++] = Color;
  570.               } // End if
  571.             else
  572.               {
  573.                 Count = 256 - Count;
  574.                 for (k=0;k<Count;k++)
  575.                   Buffer[BuffOffset++] = Data[Offset++];
  576.               } // End Count
  577.           } // End for
  578.  
  579.         Buffer = Image->GetNextRow ( ROW_DOWN );
  580.       } // End for
  581.  
  582.     return SUCCESS;
  583.   } // End of DoBRun for FLICFILE
  584.  
  585. BOOLEAN FLICFILE::DoCopy ( IMAGE *Image, CHUNK_DATA* Chunk )
  586.   {
  587.     BYTE *Buffer;
  588.  
  589.     Buffer = Image->SetOffset ( 0, 0 );
  590.     memcpy ( Buffer, Chunk->Data, Image->GetWidth()*Image->GetHeight() );
  591.     
  592.     return SUCCESS;
  593.   } // End of DoCopy for FLICFILE
  594.  
  595. BOOLEAN FLICFILE::DoBlack ( IMAGE *Image, CHUNK_DATA* Chunk )
  596.   {
  597.     Image->Clear ( 0 );
  598.     
  599.     if (Chunk)
  600.       {}
  601.     return SUCCESS;
  602.   } // End of DoCopy for FLICFILE
  603.  
  604. BOOLEAN FLICFILE::DoPreview ( IMAGE *Image, CHUNK_DATA* Chunk )
  605.   {
  606.     if ((Image)&&(Chunk))
  607.       {}
  608.     return SUCCESS;
  609.   } // End of DoPreview for FLICFILE
  610.  
  611. VOID FLICFILE::GetFirstPalette ()
  612.   {
  613.     LONG i;  
  614.     for (i=0;i<FrameData[0].NumChunks;i++)
  615.       {
  616.         LONG ChunkType = FrameData[0].Chunks[i].Header.Type;
  617.         switch (ChunkType)
  618.           {
  619.             case FLI_COLOR :
  620.               DoColor ( Pal, &(FrameData[0].Chunks[i]), FALSE );
  621.               break;
  622.  
  623.             case FLI_COLOR_256 :
  624.               DoColor ( Pal, &(FrameData[0].Chunks[i]), TRUE );
  625.               break;
  626.           } // End switch
  627.       } // End for              
  628.   } // End of GetFirstPalette for FLICFILE
  629.  
  630. VOID FLICFILE::SetFrame ( LONG FrameNumber )
  631.   {
  632.     if (FrameNumber>=FLICHeader.FLI.NumFrames)
  633.       FrameNumber=FLICHeader.FLI.NumFrames-1;
  634.     if (FrameNumber<0)
  635.       FrameNumber = 0;
  636.  
  637.     if (FrameNumber>CurrentFrame)
  638.       {
  639.         while (CurrentFrame<FrameNumber)
  640.           PlayFrame ( TRUE );
  641.       } // End if
  642.     else if (FrameNumber<CurrentFrame)
  643.       {
  644.         CurrentFrame = 0;  
  645.         while (CurrentFrame<FrameNumber)  
  646.           PlayFrame ( TRUE );
  647.       } // End else
  648.   } // End of SetFrame for FLICFILE
  649.  
  650. BOOLEAN FLICFILE::PlayFrame ( BOOLEAN Advance )
  651.   {
  652.     LONG i;
  653.     BOOLEAN Ok;
  654.     SHORT ChunkType;
  655.  
  656.     if (FLICHeader.FLI.NumFrames==0)
  657.       return FAILURE;
  658.  
  659.     if (Image==NULL)
  660.       {
  661.         if (SetDisplay ( hDisplay )==FAILURE)
  662.           return FAILURE;
  663.       } // End if  
  664.         
  665.     if (CurrentFrame>=FLICHeader.FLI.NumFrames)
  666.       CurrentFrame = 0;
  667.       
  668.     Image->SetOffset ( 0, 0 );
  669.  
  670.     for (i=0;i<FrameData[CurrentFrame].NumChunks;i++)
  671.       {
  672.         ChunkType = FrameData[CurrentFrame].Chunks[i].Header.Type;
  673.         switch (ChunkType)
  674.           {
  675.             case FLI_COLOR :
  676.               Ok = DoColor ( Pal, &(FrameData[CurrentFrame].Chunks[i]), FALSE );
  677.               break;
  678.  
  679.             case FLI_COLOR_256 :
  680.               Ok = DoColor ( Pal, &(FrameData[CurrentFrame].Chunks[i]), TRUE );
  681.               break;
  682.               
  683.             case FLI_LC :
  684.               Ok = DoLine ( Image, &(FrameData[CurrentFrame].Chunks[i]) );
  685.               break;
  686.  
  687.             case FLI_WORD_LC :
  688.               Ok = DoLineWord ( Image, &(FrameData[CurrentFrame].Chunks[i]) );
  689.               break;
  690.  
  691.             case FLI_BRUN :
  692.               Ok = DoBRun ( Image, &(FrameData[CurrentFrame].Chunks[i]) );
  693.               break;
  694.  
  695.             case FLI_COPY :
  696.               Ok = DoCopy ( Image, &(FrameData[CurrentFrame].Chunks[i]) );
  697.               break;
  698.  
  699.             case FLI_BLACK :
  700.               Ok = DoBlack ( Image, &(FrameData[CurrentFrame].Chunks[i]) );
  701.               break;
  702.  
  703.             case FLI_PREVIEW :
  704.               Ok = DoPreview ( Image, &(FrameData[CurrentFrame].Chunks[i]) );
  705.               break;
  706.  
  707.             default :
  708.               Ok = FAILURE;
  709.               break;
  710.           } // End switch
  711.         if (!Ok)
  712.           return FAILURE;
  713.       } // End for
  714.  
  715.     if (Advance)   
  716.       CurrentFrame++;
  717.     return SUCCESS;
  718.   } // End of PlayFrame for FLICFILE
  719.  
  720. VOID FLICFILE::ConvertColor ( CHUNK_DATA* Chunk, BOOLEAN Is256, COLORTABLE *Table )
  721.   {
  722.     INT i,j,Index;
  723.     SHORT NumChanges;
  724.     BYTE *Data;
  725.     DWORD Offset;
  726.     RGBCOLOR *Entry;
  727.  
  728.     if (Pal==NULL)
  729.       return;
  730.  
  731.     Entry = (Table->GetPalette())->GetEntry();
  732.       
  733.     Index = 0;
  734.     Offset = 0;
  735.     Data = Chunk->Data;
  736.     NumChanges = (*(SHORT*)(Data+Offset));
  737.  
  738.     #if defined (__MSBFIRST__)
  739.       SwapWord ( (WORD*)&NumChanges );
  740.     #endif
  741.  
  742.     Offset+=2;
  743.  
  744.     INT Count;
  745.  
  746.     for (i=0;i<NumChanges;i++)
  747.       {
  748.         Index += Data[Offset++];
  749.         Count = Data[Offset++];
  750.  
  751.         if (Count==0)
  752.           Count = 256;
  753.  
  754.         for (j=0;j<Count;j++)
  755.           {
  756.             if (Is256)
  757.               {
  758.                 Data[Offset++] = Entry[Index].Red;
  759.                 Data[Offset++] = Entry[Index].Green;
  760.                 Data[Offset++] = Entry[Index].Blue;
  761.               } // End if
  762.             else
  763.               {
  764.                 Data[Offset++] = (BYTE)((Entry[Index].Red)>>2);
  765.                 Data[Offset++] = (BYTE)((Entry[Index].Green)>>2);
  766.                 Data[Offset++] = (BYTE)((Entry[Index].Blue)>>2);
  767.               } // End else
  768.  
  769.             Index++;
  770.           } // End for
  771.         if (Count&0x01)
  772.           Offset++; // Padding byte
  773.       } // End for
  774.   } // End of ConvertColor for FLICFILE
  775.  
  776. VOID FLICFILE::ConvertLine ( CHUNK_DATA* Chunk, COLORTABLE *Table )
  777.   {
  778.     SHORT SkipLines,ChangeLines;
  779.     DWORD Offset;
  780.     BYTE *Data;
  781.  
  782.     Data = Chunk->Data;
  783.     Offset = 0;
  784.  
  785.     SkipLines = (*(SHORT*)(Data+Offset));
  786.     Offset += 2;
  787.     ChangeLines = (*(SHORT*)(Data+Offset));
  788.     Offset += 2;
  789.  
  790.     #if defined (__MSBFIRST__)
  791.       SwapWord ( (WORD*)&SkipLines );
  792.       SwapWord ( (WORD*)&ChangeLines );
  793.     #endif
  794.  
  795.     INT i,j,k;
  796.     INT Count;
  797.     INT SkipPixel;
  798.     BYTE Color;
  799.     BYTE *TableEntry = Table->GetTable ();
  800.  
  801.     for (i=0;i<SkipLines;i++)
  802.       {}
  803.  
  804.     for (i=0;i<ChangeLines;i++)
  805.       {
  806.         INT NumPackets;
  807.  
  808.         NumPackets = Data[Offset++];
  809.  
  810.  
  811.         for (j=0;j<NumPackets;j++)
  812.           {
  813.             SkipPixel = Data[Offset++];
  814.  
  815.             Count = Data[Offset++];
  816.             if (Count<128)
  817.               {
  818.                 for (k=0;k<Count;k++)
  819.                   {
  820.                     Color = Data[Offset];
  821.                     Data[Offset] = TableEntry[Color];
  822.                     Offset++;  
  823.                   } // End for
  824.               } // End if
  825.             else
  826.               {
  827.                 Count = 256 - Count;
  828.                 Color = Data[Offset];
  829.                 Data[Offset] = TableEntry[Color];
  830.                 Offset++;  
  831.               } // End Count
  832.           } // End for
  833.       } // End for
  834.   } // End of ConvertLine for FLICFILE
  835.  
  836. VOID FLICFILE::ConvertLineWord ( CHUNK_DATA* Chunk, COLORTABLE *Table )
  837.   {
  838.     SHORT LineCount,Content;
  839.     DWORD Offset;
  840.     BYTE *Data;
  841.  
  842.     Data = Chunk->Data;
  843.     Offset = 0;
  844.  
  845.     LineCount = (*(SHORT*)(Data+Offset));
  846.  
  847.     #if defined (__MSBFIRST__)
  848.       SwapWord ( (WORD*)&LineCount );
  849.     #endif
  850.  
  851.     Offset += 2;
  852.  
  853.     INT i,j,k;
  854.     INT Count;
  855.     INT SkipPixel;
  856.     SHORT SkipLine;
  857.  
  858.     BOOLEAN Done;
  859.     INT NumPackets;
  860.     BYTE Color;
  861.     BYTE *TableEntry = Table->GetTable ();
  862.  
  863.     for (i=0;i<LineCount;i++)
  864.       {
  865.         Content = (*(SHORT*)(Data+Offset));
  866.         #if defined (__MSBFIRST__)
  867.           SwapWord ( (WORD*)&Content );
  868.         #endif
  869.  
  870.         Offset += 2;
  871.  
  872.         Done = FALSE;
  873.         while (!Done)
  874.           {
  875.             if ((Content&0xC000)==0xC000) // If Top 2 bits are 11
  876.               {
  877.                 SkipLine = (SHORT)(-Content);
  878.                 for (j=0;j<SkipLine;j++)
  879.                   {}
  880.  
  881.                 Content = (*(SHORT*)(Data+Offset));
  882.                 #if defined (__MSBFIRST__)
  883.                   SwapWord ( (WORD*)&Content );
  884.                 #endif
  885.  
  886.                 Offset += 2;
  887.               } // End if
  888.             else if ((Content&0xC000)==0x00) // If Top 2 bits are 00
  889.               {
  890.                 NumPackets = Content;
  891.                 Done = TRUE;
  892.               } // End else if
  893.             else if ((Content&0x8000)==0x8000) //  If Top 2 bits are 10
  894.               {
  895.                 Content &= 0xFFFF;
  896.                 Done = TRUE;
  897.                 NumPackets = 0;
  898.               } // End else if
  899.             else // Unknown type
  900.               {
  901.                 return;
  902.               } // End else
  903.           } // End while
  904.  
  905.         for (j=0;j<NumPackets;j++)
  906.           {
  907.             SkipPixel = Data[Offset++];
  908.  
  909.             Count = Data[Offset++];
  910.             if (Count<128)
  911.               {
  912.                 for (k=0;k<Count;k++)
  913.                   {
  914.                     Color = Data[Offset];
  915.                     Data[Offset] = TableEntry[Color];
  916.                     Offset++;
  917.                     
  918.                     Color = Data[Offset];
  919.                     Data[Offset] = TableEntry[Color];
  920.                     Offset++;
  921.                   } // End for
  922.               } // End if
  923.             else
  924.               {
  925.                 Count = 256 - Count;
  926.                 Color = Data[Offset];
  927.                 Data[Offset] = TableEntry[Color];
  928.                 Offset++;
  929.                     
  930.                 Color = Data[Offset];
  931.                 Data[Offset] = TableEntry[Color];
  932.                 Offset++;
  933.               } // End Count
  934.           } // End for
  935.       } // End for
  936.   } // End of ConvertLineWord for FLICFILE
  937.  
  938. VOID FLICFILE::ConvertBRun ( CHUNK_DATA* Chunk, COLORTABLE *Table )
  939.   {
  940.     LONG i,j,k;
  941.     BYTE *Data = Chunk->Data;
  942.     LONG Offset = 0;
  943.     INT Count;
  944.     BYTE *TableEntry = Table->GetTable ();
  945.       
  946.     for (i=0;i<GetImageHeight();i++)
  947.       {
  948.         INT NumPackets;
  949.  
  950.         NumPackets = Data[Offset++];
  951.  
  952.         for (j=0;j<NumPackets;j++)
  953.           {
  954.             Count = Data[Offset++];
  955.             BYTE Color;
  956.             if (Count<128)
  957.               {
  958.                 Color = Data[Offset];
  959.                 Data[Offset] = TableEntry[Color];
  960.                 Offset++;
  961.               } // End if
  962.             else
  963.               {
  964.                 Count = 256 - Count;
  965.                 for (k=0;k<Count;k++)
  966.                   {
  967.                     Color = Data[Offset];  
  968.                     Data[Offset] = TableEntry[Color];
  969.                     Offset++;
  970.                   } // End for  
  971.               } // End else
  972.           } // End for
  973.       } // End for
  974.   } // End of ConvertBRun for FLICFILE
  975.  
  976. VOID FLICFILE::ConvertCopy ( CHUNK_DATA* Chunk, COLORTABLE *Table )
  977.   {
  978.     LONG i;
  979.     BYTE *TableEntry = Table->GetTable ();
  980.     BYTE *ChunkData;
  981.     BYTE Color;
  982.  
  983.     ChunkData = Chunk->Data;
  984.     
  985.     for (i=0;i<GetImageWidth()*GetImageHeight();i++)
  986.       {
  987.         Color = *ChunkData;
  988.         *ChunkData = TableEntry[Color];
  989.         ChunkData++;
  990.       } // End for  
  991.   } // End of ConvertCopy for FLICFILE
  992.  
  993. VOID FLICFILE::ConvertBlack ( CHUNK_DATA* Chunk, COLORTABLE *Table )
  994.   {
  995.     if (Chunk)
  996.       {}
  997.     if (Table)
  998.       {}    
  999.   } // End of ConvertBlack for FLICFILE
  1000.  
  1001. VOID FLICFILE::ConvertPreview ( CHUNK_DATA* Chunk, COLORTABLE *Table )
  1002.   {
  1003.     if (Chunk)
  1004.       {}
  1005.     if (Table)
  1006.       {}    
  1007.   } // End of ConvertPreview for FLICFILE
  1008.  
  1009. VOID FLICFILE::Convert ( RGBPALETTE *NewPal )
  1010.   {
  1011.     if (FLICHeader.FLI.NumFrames==0)
  1012.       return;
  1013.  
  1014.     GetFirstPalette ();
  1015.     
  1016.     COLORTABLE *MatchTable = new COLORTABLE ();
  1017.     MatchTable->CopyPalette ( NewPal );
  1018.     MatchTable->CreateMatchTable ( Pal );
  1019.  
  1020.     LONG i,j;
  1021.     LONG ChunkType;
  1022.     
  1023.     for (i=0;i<FLICHeader.FLI.NumFrames;i++)
  1024.       {
  1025.         for (j=0;j<FrameData[i].NumChunks;j++)
  1026.           {
  1027.             ChunkType = FrameData[i].Chunks[j].Header.Type;
  1028.             switch (ChunkType)
  1029.               {
  1030.                 case FLI_COLOR :
  1031.                   ConvertColor ( &(FrameData[i].Chunks[j]), FALSE, MatchTable );
  1032.                   break;
  1033.  
  1034.                 case FLI_COLOR_256 :
  1035.                   ConvertColor ( &(FrameData[i].Chunks[j]), TRUE, MatchTable );
  1036.                   break;
  1037.               
  1038.                 case FLI_LC :
  1039.                   ConvertLine ( &(FrameData[i].Chunks[j]), MatchTable );
  1040.                   break;
  1041.  
  1042.                 case FLI_WORD_LC :
  1043.                   ConvertLineWord ( &(FrameData[i].Chunks[j]), MatchTable );
  1044.                   break;
  1045.  
  1046.                 case FLI_BRUN :
  1047.                   ConvertBRun ( &(FrameData[i].Chunks[j]), MatchTable );
  1048.                   break;
  1049.  
  1050.                 case FLI_COPY :
  1051.                   ConvertCopy ( &(FrameData[i].Chunks[j]), MatchTable );
  1052.                   break;
  1053.  
  1054.                 case FLI_BLACK :
  1055.                   ConvertBlack ( &(FrameData[i].Chunks[j]), MatchTable );
  1056.                   break;
  1057.  
  1058.                 case FLI_PREVIEW :
  1059.                   ConvertPreview ( &(FrameData[i].Chunks[j]), MatchTable );
  1060.                   break;
  1061.                   
  1062.               } // End switch
  1063.           } // End for
  1064.       } // End for
  1065.  
  1066.     GetFirstPalette ();
  1067.     delete MatchTable;  
  1068.   } // End of Convert for FLICFILE 
  1069.  
  1070.