home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / grafik / gif / tpgif / scr2gifu.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1992-03-09  |  15.4 KB  |  442 lines

  1. UNIT SCR2GIFU;
  2.  
  3. (* *************************************************************************
  4.    Turbo 5.0 unit to send any screen to a gif file. Includes the
  5.    LZW compression routines in CMPRSS.INC.  User need only call
  6.    the function 'ScreenToGif(FileName: String):Integer;' and provide a valid
  7.    file name.  Detecting the screen dimensions, color map, etc is all
  8.    automatically handled.  Example usage:
  9.  
  10.    Program Sample;
  11.    Uses SCR2GIFU,GRAPH;
  12.    Var
  13.      GifCompressError: Integer;
  14.    Begin
  15.      OpenGraphics;                  {your procedure to open a graphics mode}
  16.      DrawGraphics;                  {your procedure to draw graphics}
  17.      GifCompressError:=ScreenToGif('TEST.GIF');
  18.      CloseGraphics;                 {your procedure to exit graphics mode}
  19.      ClrScr;
  20.      If GifCompressError=0
  21.        Then Writeln('GIF save successful.')
  22.        Else
  23.          If GifCompressError=-2
  24.            Then Writeln('Not enough memory available.')  {needs about 25k}
  25.            Else Writeln('GIF save unsuccessful.');       {other problem}
  26.      Readln;                        {pause for <RETURN>}
  27.    End.
  28.  
  29.    If you are planning to write your own graphics driver (or unit to
  30.    replace GRAPH.TPU), you may want to know that this SCR2GIFU unit uses
  31.    the following from the GRAPH.TPU:
  32.  
  33.          Const
  34.            Maxcolors=15;
  35.          Type
  36.            PaletteType=Record
  37.              Size: Byte;
  38.              Colors:Array[0..maxcolors] of shortint;
  39.            End;
  40.  
  41.          Function GetMaxColor:Word;
  42.          Procedure GetPalette(Palette:PaletteType);
  43.          Function GetGraphMode:Integer;
  44.          Function GetMaxY: Integer;
  45.          Function GetMaxX: Integer;
  46.          Function GetPixel(X,Y: Integer):Word;
  47.  
  48.    This unit does not work for the IBM8451 driver modes because I have no
  49.    idea how to get the palette values in this mode.  This unit
  50.    does not work for the EGAMonoHi mode only because
  51.    GetMaxColor returns 3 (4 colors) in this two color mode (should
  52.    return 1).  I have tested this unit using SVGA 256 color modes with a
  53.    substituted super vga GRAPH unit and it works great.
  54.  
  55.    Written by Rob Crockett [76167,1561] April 1992.  The include file
  56.    CMPRSS.INC written by Bob Berry [76555,167] 1988.
  57.  
  58.    ********************************************************************** *)
  59.  
  60.  
  61.  
  62. INTERFACE
  63.  
  64.   Uses DOS ,GRAPH;
  65.  
  66.   Function ScreenToGif(FileName: String):Integer;
  67.  
  68. IMPLEMENTATION
  69.   Type
  70.     ByteFile = File of Byte;
  71.  
  72.   Var
  73.     Signature    : Array[0..5] of Byte;            {GIF signature}
  74.     SDescriptor  : Array[1..7] of byte;            {screen descriptor}
  75.     ColorMap     : Array[0..2,0..255] of byte;     {RGB color map}
  76.     IDescriptor  : Array[1..10] of byte;           {image descriptor}
  77.     GifFile      : ByteFile;                       {output file}
  78.     Debugger     : Boolean;
  79.     X,Y          : Integer;
  80.     GifTerminator: Byte;                           {';' GIF terminator}
  81.  
  82.   {$I CMPRSS.INC}     {Include Bob Berry's LZW GIF compression routines}
  83.  
  84.   Procedure OpenGifFile(FileName:String;Var GifFile: ByteFile);
  85.      Begin
  86.        Assign(GifFile,FileName);
  87.        ReWrite(GifFile);
  88.      End;
  89.  
  90.   Procedure CloseGifFile(Var GifFile: ByteFile);
  91.      Begin
  92.        Close(GifFile);
  93.      End;
  94.  
  95.   Procedure SaveDescriptor(Var GifFile:ByteFile);
  96.      Var
  97.        I,J                 :Integer;
  98.        Pixel,MaxColor      :Byte;
  99.      Begin
  100.        For I:=0 to 5 do Write(GifFile,Signature[I]);
  101.        For I:=1 to 7 do Write(Giffile,SDescriptor[I]);
  102.        For J:=0 to GetMaxColor {MaxColor} do
  103.          For I:=0 to 2 do Write(GifFile,ColorMap[I,J]);
  104.        For I:=1 to 10 do Write(GifFile,IDescriptor[I]);
  105.      End;
  106.  
  107.   Procedure GetAllRGBPalette(ColorNum:Integer; Var RedNum,GreenNum,BlueNum: Byte);
  108.        {Procedure to return the color componant values of each color number.
  109.         Uses the TP 'GetPalette' procedure.  Each componant normalized to
  110.         a 0..255 range, eg (0,0,0) is black, (255,255,255) is white.
  111.  
  112.         TP 'GetPalette' returns a color with the following bit plane coding
  113.         when in 640x350 or 640x480 EGA/VGA modes:
  114.              bit   76543210
  115.              gives 00rgbRGB
  116.        ..where small letters mean low intensity and large letters mean high.
  117.        In the lower resolution EGA/VGA modes, the 'GetPalette' returns a byte
  118.        with the following coding:
  119.              bit   76543210
  120.              gives 000I0RGB
  121.        ...where the I is the intensity bit.
  122.  
  123.        Palette values for the 4 color modes are internal to this procedure.
  124.  
  125.        This procedure does not work for the IBM8451 driver modes.  I have no
  126.        idea where the palette values would be stored in this mode.  This
  127.        procedure does not work for the EGAMonoHi mode only because
  128.        GetMaxColor returns 3 (4 colors) in this two color mode (should
  129.        return 1).
  130.  
  131.        Since virgin TP does not support 256 color modes, I have included an
  132.        EGA/VGA BIOS routine to return the DAC palette values, should you be
  133.        inclined to experiment with SVGA.}
  134.  
  135.     Type
  136.       {PaletteType=Record      ...turbo preset type...
  137.           Size: Byte;
  138.           Colors: Array[0..maxcolors] of ShortInt;
  139.         End;       }
  140.       CGAColors = Array[0..11] of byte;
  141.  
  142.     Const                     {the four CGA palettes}
  143.       C0:CGAColors = (  0,  0,  0, 85,255, 85,255, 85, 85,255,255, 85);
  144.       C1:CGAColors = (  0,  0,  0, 85,255,255,255, 85,255,255,255,255);
  145.       C2:CGAColors = (  0,  0,  0,  0,170,  0,170,  0,  0,170, 85,  0);
  146.       C3:CGAColors = (  0,  0,  0,  0,170,170,170,  0,170,170,170,170);
  147.  
  148.     Var
  149.       Palette:PaletteType;
  150.       ColorValue: ShortInt;
  151.       ColorIndex: Integer;
  152.       Regs: Registers;
  153.       CGAPalette: CGAColors;
  154.  
  155.     Begin
  156.       Case GetMaxColor of
  157.         1: Begin                                     {2 color}
  158.              Case ColorNum of
  159.                0: Begin RedNum:=0; GreenNum:=0; BlueNum:=0; End;
  160.                1: Begin RedNum:=255; GreenNum:=255; BlueNum:=255;  End;
  161.              End;
  162.            End;
  163.         3: Begin                                     {4 color}
  164.              Case GetGraphMode of
  165.                0: CGAPalette:=C0;
  166.                1: CGAPalette:=C1;
  167.                2: CGAPalette:=C2;
  168.                3: CGAPalette:=C3;
  169.              End;
  170.              RedNum:=  CGAPalette[ColorNum*3+0];
  171.              GreenNum:=CGAPalette[ColorNum*3+1];
  172.              BlueNum:= CGAPalette[ColorNum*3+2];
  173.            End;
  174.        15: Begin                                     {16 color modes}
  175.              GetPalette(Palette);
  176.              If (GetMaxY<349)
  177.                Then                 {EGA palette byte code: 765I3RGB}
  178.                  Begin
  179.                    ColorValue:=Palette.Colors[ColorNum] SHR 4;
  180.                    If Odd(ColorValue)
  181.                      Then
  182.                        Begin
  183.                          RedNum:=1; GreenNum:=1; BlueNum:=1;
  184.                        End
  185.                      Else
  186.                        Begin
  187.                          RedNum:=0; GreenNum:=0; BlueNum:=0;
  188.                        End;
  189.                  End
  190.                Else                 {VGA palette byte code: 76rgbRGB}
  191.                  Begin
  192.                    ColorValue:=Palette.Colors[ColorNum] SHR 3;
  193.                    If Odd(ColorValue) then BlueNum:=1 else BlueNum:=0;
  194.                    ColorValue:=ColorValue shr 1;
  195.                    If Odd(ColorValue) then GreenNum:=1 else GreenNum:=0;
  196.                    ColorValue:=ColorValue shr 1;
  197.                    If Odd(ColorValue) then RedNum:=1 else RedNum:=0;
  198.                  End;
  199.  
  200.              ColorValue:=Palette.Colors[ColorNum];
  201.              If Odd(ColorValue) then BlueNum:=BlueNum+2;
  202.              ColorValue:=ColorValue shr 1;
  203.              If Odd(ColorValue) then GreenNum:=GreenNum+2;
  204.              ColorValue:=ColorValue shr 1;
  205.              If Odd(ColorValue) then RedNum:=RedNum+2;
  206.  
  207.              RedNum:=RedNum*85;        {85=255/3...brings 0-3value to}
  208.              GreenNum:=GreenNum*85;    {0-255 range}
  209.              BlueNum:=BlueNum*85;
  210.            End;
  211.       255: Begin                        {256 Colors}
  212.              Regs.AH:=$10;              {Read contents of multiple DAC registers}
  213.              Regs.AL:=$15;
  214.              Regs.BX:=ColorNum;         {The DAC color register of interest}
  215.              Intr($10,Regs);
  216.              RedNum:=Regs.DH*4;         {DAC is 18 bit, 6 bits each R,G,and B}
  217.              GreenNum:=Regs.CH*4;       {thus DAC.R ranges 0-63}
  218.              BlueNum:=Regs.CL*4;        {so multiply by 4 to range 0-255}
  219.            End;   { 255}
  220.      End;  {case GetMaxColor of}
  221.   End;    {getRGBPalette}
  222.  
  223.   Procedure SetGifDescriptor;
  224.     {sets the gif signature 'Signature[0..5]', screen
  225.      descriptor array 'SDescriptor[1..7]', and global color
  226.      map as follows:
  227.        Signature = GIF87a as six bytes
  228.        Screen Descriptor as seven bytes:
  229.  
  230.              bits
  231.          7 6 5 4 3 2 1 0  Byte #
  232.         +---------------+
  233.         |               |  1
  234.         +-Screen Width -+      Raster width in pixels (LSB first)
  235.         |               |  2
  236.         +---------------+
  237.         |               |  3
  238.         +-Screen Height-+      Raster height in pixels (LSB first)
  239.         |               |  4
  240.         +-+-----+-+-----+      M = 1, Global color map follows Descriptor
  241.         |M|  cr |0|pixel|  5   cr+1 = # bits of color resolution
  242.         +-+-----+-+-----+      pixel+1 = # bits/pixel in image (bit 3 of word 5 reserved)
  243.         |   background  |  6   background=Color index of screen background
  244.         +---------------+          (color is defined from the Global color
  245.         |0 0 0 0 0 0 0 0|  7        map or default map if none specified)
  246.         +---------------+
  247.  
  248.        Global Color Map has 3*GetMaxColor bytes.
  249.  
  250.     }
  251.  
  252.     Const
  253.       X = 1;
  254.       Y = 1;
  255.       X1 = 40;
  256.       Y1 = 1;
  257.       GIF87a: Array[0..5] of Byte = (71,73,70,56,55,97);
  258.  
  259.  
  260.     Var
  261.       I,J                       :Integer;
  262.       CR,Pixel                  :Byte;
  263.       Regs: Registers;
  264.     Begin
  265.       {*** SCREEN DESCRIPTOR ******************************}
  266.  
  267.       {Signature}
  268.       For I:=0 to 5 do
  269.         Signature[I]:=GIF87a[I];
  270.  
  271.       {Screen Width}
  272.       SDescriptor[1]:=(GetMaxX+1) Mod 256;
  273.       SDescriptor[2]:=(GetMaxX+1) Div 256;
  274.  
  275.       {Screen Height}
  276.       SDescriptor[3]:=(GetMaxY+1) Mod 256;
  277.       SDescriptor[4]:=(GetMaxY+1) Div 256;
  278.  
  279.  
  280.       SDescriptor[5]:=0;
  281.  
  282.       {M=1}
  283.       SDescriptor[5]:=SDescriptor[5] OR 128; {1000000}
  284.  
  285.       {CR+1=bits color resolution}
  286.       CR:=1;
  287.       Case GetMaxColor of    {CR+1=color resolution=bits per RGB color componant}
  288.          1: CR:=0;
  289.          3: CR:=0;
  290.         15: CR:=1;
  291.        255: CR:=7;
  292.       End;
  293.       SDescriptor[5]:=SDescriptor[5] OR (CR shl 4);
  294.  
  295.       {Pixel+1=bits per pixel in image}
  296.       Pixel:=3;
  297.       Case GetMaxColor of
  298.          1: Pixel:=0;
  299.          3: Pixel:=1;
  300.         15: Pixel:=3;
  301.        255: pixel:=7;
  302.       End;
  303.       SDescriptor[5]:=SDescriptor[5] OR Pixel;
  304.  
  305.       {Background color}
  306.       SDescriptor[6]:=0;         {set as black}
  307.  
  308.       {Reserved}
  309.       SDescriptor[7]:=0;
  310.  
  311.  
  312.       {****** Global Color Map *********************}
  313.  
  314.       For I:=0 to GetMaxColor do
  315.          GetAllRGBPalette(I,ColorMap[0,I],ColorMap[1,I],ColorMap[2,I]);
  316.  
  317.       {*** IMAGE DESCRIPTOR *****************************}
  318.  
  319.       {ImageSepChar ',' }
  320.       IDescriptor[1]:=Ord(',');
  321.  
  322.       {Image Left}
  323.       IDescriptor[2]:=0 mod 256;
  324.       IDescriptor[3]:=0 div 256;
  325.  
  326.       {Image Top}
  327.       IDescriptor[4]:=0 mod 256;
  328.       IDescriptor[5]:=0 div 256;
  329.  
  330.       {Image Width}
  331.       IDescriptor[6]:=(GetMaxX+1) mod 256;
  332.       IDescriptor[7]:=(GetMaxX+1) div 256;
  333.  
  334.       {Image Height}
  335.       IDescriptor[8]:=(GetMaxY+1) mod 256;
  336.       IDescriptor[9]:=(GetMaxY+1) div 256;
  337.  
  338.       {ImageSpecByte}
  339.         IDescriptor[10]:=0;
  340.       {M=1 local color map follows, use 'pixel'}
  341.       {M=0 use global color map, ignore 'pixel'}
  342.         {IDescriptor[10]:=IDescriptor[10] OR 128;} {10000000}
  343.       {I=0 formatted in sequential order}
  344.       {I=1 formatted in interlaced order}
  345.         {IDescriptor[10]:=IDescriptor[10] OR 64;}  {01000000}
  346.       {Pixel+1=bits per pixel for this image}
  347.         Case GetMaxColor of
  348.           1: Pixel:=0;
  349.           3: Pixel:=1;
  350.          15: Pixel:=3;
  351.         255: pixel:=7;
  352.         End;
  353.         IDescriptor[10]:=IDescriptor[10] OR Pixel;
  354.     End;
  355.  
  356.     Function GetByte:Integer;
  357.       {Called by the LZW compression routines, GetByte produces
  358.        a byte representing the color value of a pixel on the screen.
  359.        The byte is packaged as the low byte of a word (integer).
  360.        GetByte uses the global variables X and Y to keep track of
  361.        its position on the screen.}
  362.  
  363.       Begin
  364.         If X<GetMaxX
  365.           Then
  366.             Begin
  367.               X:=X+1;
  368.               GetByte:=GetPixel(X,Y);
  369.             End
  370.           Else
  371.             Begin
  372.               If Y<GetMaxY
  373.                 Then
  374.                   Begin
  375.                     Y:=Y+1;
  376.                     X:=0;
  377.                     GetByte:=GetPixel(X,Y);
  378.                   End
  379.                 Else
  380.                   Begin
  381.                     GetByte:=(-1);
  382.                   End;
  383.             End;
  384.       End;
  385.  
  386.   Procedure PutByte(B:Integer);
  387.     {Called by the LZW compression routines, PutByte sends a byte
  388.      of data to the forming GIF file.  The first byte sent by the LZW
  389.      compression routings is the 'Minimum Code Size', next byte is
  390.      the block size, then the bytes forming the data block, the next
  391.      block size byte, next block data bytes, etc.  The byte is accepted
  392.      from the compression routines as the low byte of an integer.}
  393.  
  394.     Var
  395.       ByteNum: Byte;
  396.     Begin
  397.       ByteNum:=Lo(B);
  398.       Write(GifFile,ByteNum);
  399.     End;
  400.  
  401. Function GetMinCodeSize: Byte;
  402.     {Produces the minimum number of bits required to represent
  403.      the actual pixel value (the color number).  This would be the same
  404.      as the bits per pixel except that because of algorithmic constraints
  405.      of the LZW compression routines, black and white images with a
  406.      bits-per-pixel of 1 have a minimum code size of 2.  Thus the
  407.      mincodesize can be from 2 (black and white) to 8 (256 colors).}
  408.   Var
  409.     Code: Byte;
  410.   Begin
  411.     Case GetMaxColor of
  412.        1: Code:=2;
  413.        3: Code:=2;
  414.       15: Code:=4;
  415.      255: Code:=8;
  416.     End;
  417.     GetMinCodeSize:=Code;
  418.   End;
  419.  
  420.   Function ScreenToGif(FileName: String):Integer;
  421.     {Master function to create a GIF file 'FileName' from the graphics screen.
  422.      Returns ScreenToGif=0 if no errors, ScreenToGif<>0 if some error
  423.      encountered.}
  424.     Var
  425.       GifResult,I                   :Integer;
  426.       {global var  X,Y : Integer}
  427.     Begin
  428.       GifTerminator:=$3B;                   {';'}
  429.       X:=-1;                                {set (X,Y) for screen location...}
  430.       Y:=0;                                 {...used in GetByte function.}
  431.       OpenGifFile(FileName,GifFile);        {open the file for output}
  432.       SetGifDescriptor;                     {set up GIF file info header}
  433.       SaveDescriptor(GifFile);              {send info header to GIF file}
  434.       GifResult:= CompressGif(GetMinCodeSize);  {send screen data to GIF file}
  435.       Write(GifFile,GifTerminator);         {send ';' to end GIF mode}
  436.       CloseGifFile(GifFile);                {close the file}
  437.       ScreenToGif:=GifResult;               {pass along error codes}
  438.     End;
  439.  
  440. END.
  441.  
  442.