Dear Thomas, Bill, Russ, Dane, ...

After weekend I have time to try to explain a bit how it works. 
(I wasn't working with GIF format never before, just read
GIF specification last Thursday :-).

If I'll have some time, I wanna try to write more complex
script for making arbitrary GIFs. But it take some time,
because implementation of LZW compression is needed... 

Regards,
Jan

Well, here is the script with minor changes but with huge comment:
(I'll also send it to rebol.org soon)

REBOL [
        Title:    "GIF number generator"
        Author:   "Jan Strejcek"
        File:     %gif-number.r
        Email:    [EMAIL PROTECTED]
        Date:     15-Nov-1999
        Category: [cgi web]
        Purpose:  {Returns gif with given number and given length (number of digits)}
        Usage:    {
                Place on net as cgi-bin. Then you can call it in <IMG> tag
                in common manner:
                http://your.domain.com/path/to/cgi/gif-number.r?number=5&digits=4      
                   
                        number - content of gif
                        digits - number of digits in gif (supported 1-10)  
        }
]

gif: func [
        number [integer!] ;content of gif
        digits [integer!] ;number of digits (supported 1-10)
        /local header lsd gct sep ilp id lcts imcs pics bt trailer n i
][
        ; all strings here are in hexadecimal code, i.e. 8 Bits = 1 Byte = 2 chars
        ; Unsigned = 2 Bytes unsigned

; Header
        header: "474946383961"  ; = GIF89a, also can be "474946383761"= GIF87a

; Logical Screen Descriptor
        ; Logical Screen Width          Unsigned
                ;this is count by (skip tail to-string to-hex (21 * digits) -2)
                ;here is used only 1 Byte tj. max size of gif can be 255
                ;and this is the reason of constrained argument digits <= 10 
        ; Logical Screen Height         Unsigned
                ;here 27 = "1b00"

        ; Global Color Table Flag       1 Bit
                ;Flag indicating the presence of a Global Color Table.
        ; Color Resolution              3 Bits
                ;Number of bits per primary color available
                ;to the original image, minus 1.
        ; Sort Flag                     1 Bit
                ;Indicates whether the Global Color Table is sorted.
        ; Size of Global Color Table    3 Bits
                ;the value in this field is used to calculate the
                ;number of bytes contained in the Global Color Table
                ;size of Global Color Table = 3 x 2^(Size of Global Color Table+1)
                ;this means RGB values for 8 colors 
        ;all these flags are set to 11000010 = "c2"
                ;I don't know why, but without global color table it
                ;didn't work (athough in GIF specification is written 
                ;it should work

        ; Background Color Index        Byte
                ;Index into the Global Color Table for background color
                ;"00" here
        ; Pixel Aspect Ratio            Byte    
                ;for no-square pixels (e.g. on printers)
                ;"00" = 0 here (No aspect ratio information given 

        ;well, here is the whole Local Screen Descriptor value 
        lsd: head insert/part {001b00c20000} (skip tail to-string to-hex (21 * digits) 
-2) 2  
                
; Global Color Table
        ;as usual, here are colors in RGB format: ffffff=white...
        gct: {ffffffe1e1e1999999686868000000c0c0c0000000000000} 

; Image Descriptor
        ;GIF can contain more pictures, each one has own Image Descriptor
        ;In this script, each digit is another picure...

        ; Separator                     Byte
                ;is "2c"
        ; Image Left Position           Unsigned
                ;holds x position of relative position in Logocal Screen of GIF
                ;is count for every digit
        ; Image Top Position            Unsigned
                ;analogous, always "0000" here
        ; Image Width                   Unsigned
                ;width of each digit here is 21 = "1500" 
        ; Image Height                  Unsigned    
                ;here 27 = "1b00"      

        ; Local Color Table Flag        1 Bit
                ;here 1 because each digit has different palette
        ; Interlace Flag                1 Bit
                ;Indicates if the image is interlaced, here 0
        ; Sort Flag                     1 Bit
                ;same as in Logical Screen Descriptor
        ; Reserved                      2 Bits
        ; Size of Local Color Table     3 Bits    
                ;analogous as in Logical Screen Descriptor
        ;flags here are 10000010 = "82"

        ;here are values of sep(arator), counting of ilp (image left position)
        ;and id (the rest) 
        sep: {2c}    
        ilp: func [n][
                return skip tail to-string to-hex (21 * n) -2
        ]
        id: {00000015001b0082}
        

; Local Color Table
        ;color tables for digits 0..9
        lcts: [
                {FFFFFFC0C0C0E1E1E1000000686868999999000000000000}
                {FFFFFF999999686868C0C0C0E1E1E1000000000000000000}
                {FFFFFFC0C0C0000000686868E1E1E1999999000000000000}
                {FFFFFFC0C0C0686868999999E1E1E1000000000000000000}
                {FFFFFFE1E1E1999999686868000000C0C0C0000000000000}
                {FFFFFFC0C0C0000000686868999999E1E1E1000000000000}
                {FFFFFFC0C0C0686868000000E1E1E1999999000000000000}
                {FFFFFFE1E1E1000000686868999999C0C0C0000000000000}
                {FFFFFF686868000000999999C0C0C0E1E1E1000000000000}
                {FFFFFFE1E1E1999999000000686868C0C0C0000000000000}
        ]

; Image Data
        ; LZW Minimum Code Size         Byte (3-12)   
        imcs: "03"   

        ;LZW packed data of digits 0..9 
        pics: [
                
{4D08BADCFE30CA49ABBD358020701820A851C24008426156E20252DFD0291F31A90353E612F132BF88CF06E409578C02F168A4351FB1027024096904BE0A2E848471979554818A299BCFE8B43A01}
                
{3E08BADCFE30CA49AB75418C710129601174425608DD22A64A41B040C1B12E5CD36FFAE5DD6EF315C2202003CC28A1E48892C9084028161046AD5AAF584002}
                
{4C08BADCFE30CA49AB7D4188112C195AD8515AA16402958D4A21B050D664E6A580F5050A84B7BF15824BC30986063D8B0B6903940281C2603A98FC42A1DC638815350181E4774C2E9BCFE84602}
                
{4B08BADCFE30CA4967106190A16BF9E057010141045F302E1FB10284F8A205E656713D08353E30A8DB0B20100C15B26172C553BD3EC6158157780D404ECA15249C507B2B54E7482E9BCFC304}
                
{4908BADCFE30CA496B10D50D92DBEECC30808B8091C01028C46AB5AC4B091C5B64C409E415CDC0930061A428F02684E45099BC453649A8D29931523B425DC7A8ED10AE5894784C2E6712}
                
{4908BADCFE30CA49ABBD3388CD47DD44480CC457608B100045B05A5C5C52DB7016844A0DEF92A3A9194623BC1025815363A08BD45E054E2616534AA2546B2540286881E0B0784C862400}
                
{4B08BADCFE30CA496B0BB68981331960061420216E8508049C0AB4EA260869060E335EC9CB275083DA82658A7C1E30C8D19184042FCDC7A608F80C2AA0D9E689BD45278440C7452E9BCF9604}
                
{4208BADCFE30CA4965108364C2C32442288A1451149C1656CD20B0CC55C08B4B2B8540DC807D5F03DE4A18FCE978B9DD0DA4A4B93CB71094169ADD0A459E76CBEDC212}
                
{4F08BADCFE30CA49ABBD35881DAEDEDB501182080C4247690C4BA1C5B2550537A0E6548361850A855F69422230488289EB08942C17456793698CFC628ADD8AF3115427C2CDD752C062CEE8B47AAD4800}
                
{5008BADCFE30CA49AB0A9689C189B004270E0515924071521C76715F14A04C3110D28C33FAC435B3584454026C06AE886D24AA044EC44C2070CCBC6896D9CD7ADA558E0321458B75DE92D6B47ACD6E3312}
    
        ]
        ;block terminator - terminates Image Data block
        bt: "00" 

;Trailer (end of GIF)
        trailer: "3b"        

;and here is all this used to compose one GIF:  
;for theorists here is structure of GIF (very simplified for this script !!)
; <GIF Data Stream> ::=     Header <Logical Screen> <Data>* Trailer
; <Logical Screen> ::=      Logical Screen Descriptor [Global Color Table]
; <Data> ::=   Image Descriptor [Local Color Table] Image Data

        result: ""
        n: digits
        loop digits [
                i: (number // 10) + 1
                number: to-integer number / 10
                result: append result reduce [sep ilp n: (n - 1) id lcts/:i imcs 
pics/:i bt]
        ]
        return load rejoin [ "#{"header lsd gct result trailer "}"]
]

;here goes the cgi-communication and calling of above defined gif function    

tmp!: make object! [number: "" digits: ""]
data: make tmp! decode-cgi system/options/cgi/query-string   
number: load data/number
digits: load data/digits

either all [
        integer? number 
        integer? digits 
        (1 <= digits) 
        (digits <= 10)
][      
        print "Content-Type: image/gif^/"
        t: gif number digits   
        write-io system/ports/output t length? t
][
        print "Content-Type: text/plain^/"
        print " Usage:  number - content of gif"
        print "         digits - number of digits in gif (supported 1-10)"
        print " e.g. http://your.domain.com/path/to/cgi/gif-number.r?number=5&digits=4"
]

Reply via email to