Re: Decoding GIF file in C? [Source code here]

Discussion in 'C++' started by kirannd1989@gmail.com, Jan 9, 2014.

  1. Guest

    Hi..
    i tried compiling this code but there are few undefined Macro/functions like MK_FP().
    I am trying it on WIN32, VS2012.. i have made changes accordingly.
    Is this solution dependent on any library.
    Thanks in advance


    On Monday, August 1, 1994 1:02:48 PM UTC+5:30, Cyborg wrote:
    > In article <> (Muhammad Salman Mughal) writes:
    > >
    > >Hi there,
    > >
    > > I am desperately looking for a C code that could decode a GIF file
    > > in DOS. Anybody out there who knows how to do it? I will really
    > > appreciate any help.
    > >

    >
    >
    > The following code is based on a LZW decoder originally coded by Steven A.
    > Bennett. All I did is write the code for parsing the GIF format, passing
    > the approptiate data to the LZW decoder and writing the code for displaying
    > the data on the screen. Both 87a and 89a formats are accepted.
    >
    > Video BIOS must support VESA functions - the code selects a video mode
    > whith a resolution just high enough to display the given GIF file. Max
    > resolution is 1280x1024, pictures larger than this will be partially
    > displayed. Interlaced GIFs are supported. Program was only tested on my
    > video card (Cirrus 5428 VESA Local Bus). It was not intended for public
    > release but since I've already written it and the guy i desperate...
    >
    > Compiles with Borland C++ v3.1
    >
    > ----------------------- chop here --------------------------
    >
    > /* Various error codes used by decoder
    > * and my own routines... It's okay
    > * for you to define whatever you want,
    > * as long as it's negative... It will be
    > * returned intact up the various subroutine
    > * levels...
    > */
    > #define READ_ERROR -1
    > #define WRITE_ERROR -2
    > #define OPEN_ERROR -3
    > #define CREATE_ERROR -4
    > #define OUT_OF_MEMORY -5
    > #define BAD_CODE_SIZE -6
    >
    > #define ISIZE 2048 // image line size
    > #define BSIZE 256 // buffer size
    > #define PSIZE 768 // pallette size
    > #define NULL 0L
    > #define MAX_CODES 4095
    >
    > #include <dos.h>
    > #include <conio.h>
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > /* Static variables */
    > short curr_size; /* The current code size */
    > short clear; /* Value for a clear code */
    > short ending; /* Value for a ending code */
    > short newcodes; /* First available code */
    > short top_slot; /* Highest code for current size */
    > short slot; /* Last read code */
    >
    > /* The following static variables are used
    > * for seperating out codes
    > */
    > short navail_bytes = 0; /* # bytes left in block */
    > short nbits_left = 0; /* # bits left in current byte */
    > unsigned char b1; /* Current byte */
    > unsigned char byte_buff[257]; /* Current block */
    > unsigned char *pbytes; /* Pointer to next byte in block */
    >
    > /* The reason we have these separated like this instead of using
    > * a structure like the original Wilhite code did, is because this
    > * stuff generally produces significantly faster code when compiled...
    > * This code is full of similar speedups... (For a good book on writing
    > * C for speed or for space optimisation, see Efficient C by Tom Plum,
    > * published by Plum-Hall Associates...)
    > */
    > unsigned char stack[MAX_CODES + 1]; /* Stack for storing pixels */
    > unsigned char suffix[MAX_CODES + 1]; /* Suffix table */
    > unsigned short prefix[MAX_CODES + 1]; /* Prefix linked list */
    >
    > long code_mask[13] = {
    > 0x0000,
    > 0x0001, 0x0003, 0x0007, 0x000F,
    > 0x001F, 0x003F, 0x007F, 0x00FF,
    > 0x01FF, 0x03FF, 0x07FF, 0x0FFF
    > };
    >
    > // incremented each time an out of range code is read by the decoder
    > int bad_code_count;
    >
    > unsigned char far *buffer=NULL; // file buffer
    > unsigned char far *grgb=NULL; // global rgb table
    > unsigned char far *lrgb=NULL; // local rgb table
    > unsigned char far *pixels=NULL; // line of pixels to be displayed
    > unsigned char far *vid=NULL; // ptr to start of graphics window
    > unsigned char background=0; // background color index
    > unsigned long offset=0; // offset into graphics window
    > unsigned long piclen; // total screen size in pixels
    > unsigned int realx; // real picture width
    > unsigned int realy; // real picture height
    > unsigned int xsize=0; // graphic width
    > unsigned int ysize=0; // graphic height
    > unsigned int win=0; // window number
    > unsigned int granularity=0; // granularity of video window
    > unsigned int group=0; // picture group (interlaced or not)
    > FILE *fp; // file pointer
    >
    > /* int get_byte()
    > * - This function is expected to return the next byte from
    > * the GIF file or a negative number defined in ERRS.H
    > */
    > int get_byte(){
    > unsigned char c;
    >
    > if(fscanf(fp, "%c", &c)==1)
    > return((int)c);
    > else
    > return(READ_ERROR);
    > }
    >
    > /* int out_line(unsigned char pixels[], int linelen)
    > * - This function takes a full line of pixels (one byte per pixel) and
    > * displays them (or does whatever your program wants with them...). It
    > * should return zero, or negative if an error or some other event occurs
    > * which would require aborting the decode process... Note that the length
    > * passed will almost always be equal to the line length passed to the
    > * decoder function, with the sole exception occurring when an ending code
    > * occurs in an odd place in the GIF file... In any case, linelen will be
    > * equal to the number of pixels passed...
    > */
    > int out_line(unsigned char *pixels, int linelen){
    > unsigned long segment;
    >
    > segment=offset&(unsigned long)(granularity-1);
    >
    > // put pixels on screen
    > memmove(vid+segment, pixels, linelen);
    > memset(vid+segment+linelen, background, xsize-linelen);
    > switch (group) {
    > case 0:
    > offset+=xsize;
    > break;
    > case 1:
    > offset+=xsize*8;
    > if(offset>=piclen){
    > group++;
    > offset=xsize*4;
    > }
    > break;
    > case 2:
    > offset+=xsize*8;
    > if(offset>=piclen){
    > group++;
    > offset=xsize*2;
    > }
    > break;
    > case 3:
    > offset+=xsize*4;
    > if(offset>=piclen){
    > group++;
    > offset=xsize;
    > }
    > break;
    > case 4:
    > offset+=xsize*2;
    > break;
    > default:
    > break;
    > }
    >
    > // if we've run over a window granularity border, move window position
    > if((offset>>12)!=win){
    > win=offset>>12;
    > asm pusha
    > asm mov ax, 0x4f05
    > asm mov bx, 0x0000
    > asm mov dx, win
    > asm int 0x10
    > asm popa
    > }
    > return(1);
    > }
    >
    >
    > /* This function initializes the decoder for reading a new image.
    > */
    > static short init_exp(short size)
    > {
    > curr_size = size + 1;
    > top_slot = 1 << curr_size;
    > clear = 1 << size;
    > ending = clear + 1;
    > slot = newcodes = ending + 1;
    > navail_bytes = nbits_left = 0;
    > return(0);
    > }
    >
    > /* get_next_code()
    > * - gets the next code from the GIF file. Returns the code, or else
    > * a negative number in case of file errors...
    > */
    > static short get_next_code()
    > {
    > short i, x;
    > unsigned long ret;
    >
    > if (nbits_left == 0)
    > {
    > if (navail_bytes <= 0)
    > {
    >
    > /* Out of bytes in current block, so read next block
    > */
    > pbytes = byte_buff;
    > if ((navail_bytes = get_byte()) < 0)
    > return(navail_bytes);
    > else if (navail_bytes)
    > {
    > for (i = 0; i < navail_bytes; ++i)
    > {
    > if ((x = get_byte()) < 0)
    > return(x);
    > byte_buff = x;
    > }
    > }
    > }
    > b1 = *pbytes++;
    > nbits_left = 8;
    > --navail_bytes;
    > }
    >
    > ret = b1 >> (8 - nbits_left);
    > while (curr_size > nbits_left)
    > {
    > if (navail_bytes <= 0)
    > {
    >
    > /* Out of bytes in current block, so read next block
    > */
    > pbytes = byte_buff;
    > if ((navail_bytes = get_byte()) < 0)
    > return(navail_bytes);
    > else if (navail_bytes)
    > {
    > for (i = 0; i < navail_bytes; ++i)
    > {
    > if ((x = get_byte()) < 0)
    > return(x);
    > byte_buff = x;
    > }
    > }
    > }
    > b1 = *pbytes++;
    > ret |= b1 << nbits_left;
    > nbits_left += 8;
    > --navail_bytes;
    > }
    > nbits_left -= curr_size;
    > ret &= code_mask[curr_size];
    > return((short)(ret));
    > }
    >
    > /* DECODE.C - An LZW decoder for GIF
    > *
    > * Copyright (C) 1987, by Steven A. Bennett
    > *
    > * Permission is given by the author to freely redistribute and include
    > * this code in any program as long as this credit is given where due.
    > *
    > * In accordance with the above, I want to credit Steve Wilhite who wrote
    > * the code which this is heavily inspired by...
    > *
    > * GIF and 'Graphics Interchange Format' are trademarks (tm) of
    > * Compuserve, Incorporated, an H&R Block Company.
    > *
    > * Release Notes: This file contains a decoder routine for GIF images
    > * which is similar, structurally, to the original routine by Steve Wilhite.
    > * It is, however, somewhat noticably faster in most cases.
    > *
    > * short decode(linewidth)
    > * short linewidth; * Pixels per line of image *
    > *
    > * - This function decodes an LZW image, according to the method used
    > * in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
    > * will generate a call to out_line(), which is a user specific function
    > * to display a line of pixels. The function gets it's codes from
    > * get_next_code() which is responsible for reading blocks of data and
    > * seperating them into the proper size codes. Finally, get_byte() is
    > * the global routine to read the next byte from the GIF file.
    > *
    > * It is generally a good idea to have linewidth correspond to the actual
    > * width of a line (as specified in the Image header) to make your own
    > * code a bit simpler, but it isn't absolutely necessary.
    > *
    > * Returns: 0 if successful, else negative. (See ERRS.H)
    > *
    > */
    >
    > short decode(short linewidth)
    > {
    > register unsigned char *sp, *bufptr;
    > unsigned char *buf;
    > register short code, fc, oc, bufcnt;
    > short c, size, ret;
    >
    > /* Initialize for decoding a new image...
    > */
    > if ((size = get_byte()) < 0)
    > return(size);
    > if (size < 2 || 9 < size)
    > return(BAD_CODE_SIZE);
    > init_exp(size);
    >
    > /* Initialize in case they forgot to put in a clear code.
    > * (This shouldn't happen, but we'll try and decode it anyway...)
    > */
    > oc = fc = 0;
    >
    > /* Allocate space for the decode buffer
    > */
    > if ((buf = (unsigned char *)malloc(linewidth + 1)) == NULL)
    > return(OUT_OF_MEMORY);
    >
    > /* Set up the stack pointer and decode buffer pointer
    > */
    > sp = stack;
    > bufptr = buf;
    > bufcnt = linewidth;
    >
    > /* This is the main loop. For each code we get we pass through the
    > * linked list of prefix codes, pushing the corresponding "character" for
    > * each code onto the stack. When the list reaches a single "character"
    > * we push that on the stack too, and then start unstacking each
    > * character for output in the correct order. Special handling is
    > * included for the clear code, and the whole thing ends when we get
    > * an ending code.
    > */
    > while ((c = get_next_code()) != ending)
    > {
    >
    > /* If we had a file error, return without completing the decode
    > */
    > if (c < 0)
    > {
    > free(buf);
    > return(0);
    > }
    >
    > /* If the code is a clear code, reinitialize all necessary items.
    > */
    > if (c == clear)
    > {
    > curr_size = size + 1;
    > slot = newcodes;
    > top_slot = 1 << curr_size;
    >
    > /* Continue reading codes until we get a non-clear code
    > * (Another unlikely, but possible case...)
    > */
    > while ((c = get_next_code()) == clear)
    > ;
    >
    > /* If we get an ending code immediately after a clear code
    > * (Yet another unlikely case), then break out of the loop.
    > */
    > if (c == ending)
    > break;
    >
    > /* Finally, if the code is beyond the range of already set codes,
    > * (This one had better NOT happen... I have no idea what will
    > * result from this, but I doubt it will look good...) then set it
    > * to color zero.
    > */
    > if (c >= slot)
    > c = 0;
    >
    > oc = fc = c;
    >
    > /* And let us not forget to put the char into the buffer... And
    > * if, on the off chance, we were exactly one pixel from the end
    > * of the line, we have to send the buffer to the out_line()
    > * routine...
    > */
    > *bufptr++ = c;
    > if (--bufcnt == 0)
    > {
    > if ((ret = out_line(buf, linewidth)) < 0)
    > {
    > free(buf);
    > return(ret);
    > }
    > bufptr = buf;
    > bufcnt = linewidth;
    > }
    > }
    > else
    > {
    >
    > /* In this case, it's not a clear code or an ending code, so
    > * it must be a code code... So we can now decode the code into
    > * a stack of character codes. (Clear as mud, right?)
    > */
    > code = c;
    >
    > /* Here we go again with one of those off chances... If, on the
    > * off chance, the code we got is beyond the range of those already
    > * set up (Another thing which had better NOT happen...) we trick
    > * the decoder into thinking it actually got the last code read.
    > * (Hmmn... I'm not sure why this works... But it does...)
    > */
    > if (code >= slot)
    > {
    > if (code > slot)
    > ++bad_code_count;
    > code = oc;
    > *sp++ = fc;
    > }
    >
    > /* Here we scan back along the linked list of prefixes, pushing
    > * helpless characters (ie. suffixes) onto the stack as we do so.
    > */
    > while (code >= newcodes)
    > {
    > *sp++ = suffix
    Code:
    ;
    > 	    code = prefix[code];
    > 	    }
    >
    >          /* Push the last character on the stack, and set up the new
    > 	  * prefix and suffix, and if the required slot number is greater
    >           * than that allowed by the current bit size, increase the bit
    > 	  * size.  (NOTE - If we are all full, we *don't* save the new
    > 	  * suffix and prefix...  I'm not certain if this is correct...
    > 	  * it might be more proper to overwrite the last code...
    > 	  */
    > 	 *sp++ = code;
    > 	 if (slot < top_slot)
    > 	    {
    > 	    suffix[slot] = fc = code;
    > 	    prefix[slot++] = oc;
    > 	    oc = c;
    > 	    }
    > 	 if (slot >= top_slot)
    > 	    if (curr_size < 12)
    > 	       {
    > 	       top_slot <<= 1;
    > 	       ++curr_size;
    > 	       }
    >
    > 	 /* Now that we've pushed the decoded string (in reverse order)
    >           * onto the stack, lets pop it off and put it into our decode
    > 	  * buffer...  And when the decode buffer is full, write another
    > 	  * line...
    > 	  */
    > 	 while (sp > stack)
    > 	    {
    > 	    *bufptr++ = *(--sp);
    > 	    if (--bufcnt == 0)
    > 	       {
    > 	       if ((ret = out_line(buf, linewidth)) < 0)
    > 		  {
    > 		  free(buf);
    > 		  return(ret);
    > 		  }
    > 	       bufptr = buf;
    > 	       bufcnt = linewidth;
    > 	       }
    > 	    }
    >          }
    >       }
    >    ret = 0;
    >    if (bufcnt != linewidth)
    >       ret = out_line(buf, (linewidth - bufcnt));
    >    free(buf);
    >    return(ret);
    >    }
    >
    >
    > // this function is called just before program exits
    > void cleanup(void){
    >   // free any allocated resources
    >   if(fp!=NULL)
    >     fclose(fp);
    >   if(buffer!=NULL)
    >     free(buffer);
    >   if(grgb!=NULL)
    >     free(grgb);
    >   if(lrgb!=NULL)
    >     free(lrgb);
    >   if(pixels!=NULL)
    >     free(pixels);
    > }
    >
    > void main(int argc, char **argv){
    >   unsigned int gctsize=0, lctsize=0, mode;
    >   int i;
    >
    >   // set bad codes encountered to zero
    >   bad_code_count=0;
    >
    >   // set function to be called on exit
    >   if(atexit(cleanup))
    >     exit(0);
    >
    >   // exit if no file given
    >   if (argc<2){
    >     printf("Usage: %s gif_file\n", argv[0]);
    >     exit(0);
    >   }
    >
    >   // try to open file
    >   if((fp=fopen(argv[1], "rb"))==NULL){
    >     printf("Failed to open file.\n");
    >     exit(0);
    >   }
    >
    >   // allocate buffers
    >   buffer=(unsigned char *)malloc(BSIZE);
    >   pixels=(unsigned char *)malloc(ISIZE);
    >   grgb  =(unsigned char *)malloc(PSIZE);
    >   lrgb  =(unsigned char *)malloc(PSIZE);
    >   if((grgb==NULL) || (lrgb==NULL) || (pixels==NULL) || (buffer==NULL)){
    >     printf("Not enough memory.\n");
    >     exit(0);
    >   }
    >
    >   fread(buffer, 1, 6, fp);
    >   // test file for valid GIF signature
    >   if(memcmp(buffer, "GIF", 3)!=0){
    >     printf("Not a GIF file.\n");
    >     exit(0);
    >   }
    >   // test file for version number
    >   if((memcmp(buffer+3, "87a", 3)!=0) && (memcmp(buffer+3, "89a", 3)!=0)){
    >     printf("Unsuported GIF version. Hit a key to decode anyway.\n");
    >     getch();
    >   }
    >
    >   // read logical screen descriptor
    >   fread(buffer, 1, 7, fp);
    >
    >   // test for global color table presence
    >   if(*(buffer+4)&0x80){
    >     // compute global color table size
    >     gctsize=1<<((*(buffer+4)&0x07) + 1);
    >     // read global color table into buffer
    >     fread(grgb, 1, gctsize*3, fp);
    >     // adjust colors to crappy 6-bit PC-DAC values
    >     for(i=0; i<gctsize*3; i++)
    >       *(grgb+i)>>=2;
    >   }
    >   // get background color index
    >   background=*(buffer+5);
    >
    >
    >   // scan file for data blocks
    >   while((i=get_byte())>0) {
    >     // in end of GIF marker encountered then exit
    >     if(i==0x3b)
    >       exit(0);
    >     // test for extentions
    >     if(i==0x21){
    >       if( (i=get_byte()) < 0 )
    > 	exit(0);
    >       // if graphic color extention present or
    >       // coment extention present or
    >       // plain text extention present or
    >       // application extention present then skip it
    >       if( (i==0x01) || (i==0xf9) || (i==0xfe) || (i==0xff)){
    > 	while((i=get_byte())!=0){
    > 	  if(fread(buffer, 1, i, fp)!=i)
    > 	    exit(0);
    > 	}
    >       }
    >     }
    >
    >     // test for presence of image descriptor
    >     if(i==0x2c){
    >       // get image descriptor
    >       fread(buffer, 1, 9, fp);
    >       // interlaced flag is set or cleared accordingly
    >       if(*(buffer+8)&0x40)
    > 	group=1;
    >       realx=xsize=*(buffer+4) | (*(buffer+5)<<8);
    >       realy=ysize=*(buffer+6) | (*(buffer+7)<<8);
    >       // test for presence of local color table
    >       if(*(buffer+8)&0x80){
    > 	// compute local color table size
    > 	lctsize=1<<((*(buffer+8)&0x07) + 1);
    > 	// read local color table into buffer
    > 	fread(lrgb, 1, lctsize*3, fp);
    > 	// adjust colors to crappy 6-bit PC-DAC values
    > 	for(i=0; i<gctsize*3; i++)
    > 	  *(lrgb+i)>>=2;
    >       }
    >
    >       // choose a video mode that will just fit the image
    >       if((xsize<=640) && (ysize<=480)){
    > 	mode=0x101;		//  VESA 640 x  480 x 256
    > 	xsize=640;
    > 	ysize=480;
    >       } else if ((xsize<=800) && (ysize<=600)){
    > 	mode=0x103;		//  VESA 800 x  600 x 256
    > 	xsize=800;
    > 	ysize=600;
    >       } else if ((xsize<=1024) && (ysize<=768)){
    > 	mode=0x105;		// VESA 1024 x  768 x 256
    > 	xsize=1024;
    > 	ysize=768;
    >       } else {
    > 	mode=0x107;		// VESA 1280 x 1024 x 256
    > 	xsize=1280;
    > 	ysize=1024;
    >       }
    >
    >       piclen=(unsigned long)xsize*(unsigned long)ysize;
    >       // get video mode info through VESA call
    >       asm pusha
    >       asm mov ax, 0x4f01
    >       asm mov cx, mode
    >       asm les di, buffer
    >       asm int 0x10
    >       asm mov i, ax
    >       asm popa
    >
    >       if(i!=0x004f){
    > 	printf("VESA video functions not available.\n");
    > 	exit(0);
    >       }
    >       // if mode not supported, or not color, or not graphics then exit
    >       if((*buffer&0x19)!=0x19){
    > 	printf("Required graphics mode is not available.\n");
    > 	exit(0);
    >       }
    >
    >       // if window does not exist or is not writable exit
    >       if((*(buffer+2)&0x05)!=0x05) {
    > 	printf("Cannot access video RAM.\n");
    > 	exit(0);
    >       }
    >
    >       // calculate window granularity
    >       granularity=(*(buffer+4) | (*(buffer+5)<<8))<<10;
    >       // calculate pointer to video RAM start
    >       vid=(unsigned char *)MK_FP((*(buffer+8) | (*(buffer+9)<<8)), 0);
    >
    >       // set VESA video mode
    >       asm pusha
    >       asm mov ax, 0x4f02
    >       asm mov bx, mode
    >       asm int 0x10
    >       asm popa
    >
    >       // set color table if present
    >       if(lctsize){
    > 	// scope of local color table is local so once used it's gone
    > 	lctsize=0;
    > 	asm pusha
    > 	asm mov ax, 0x1012
    > 	asm mov bx, 0x0000
    > 	asm mov cx, 0x0100
    > 	asm les dx, lrgb
    > 	asm int 0x10
    > 	asm popa
    >       } else if(gctsize){
    > 	// if no local color table then set global color table if present
    > 	asm pusha
    > 	asm mov ax, 0x1012
    > 	asm mov bx, 0x0000
    > 	asm mov cx, 0x0100
    > 	asm les dx, grgb
    > 	asm int 0x10
    > 	asm pop es
    > 	asm popa
    >       }
    >
    >       // decode and display graphic
    >       decode(realx);
    >       // wait for key press
    >       getch();
    >
    >       // set default text mode
    >       asm mov ax, 0x0003
    >       asm int 0x10
    >     }
    >   }
    >
    >   // exit to dos
    >   exit(0);
    > }
    >
    > -------------- chop here -------------------
    >
    > --
    > +-----------------------------+-----------------------------------------------+
    > | Alex Ivopol                 |  If you  love  something set it free.  If it  |
    > |  |  doesn't come back, hunt it down and kill it. |
    > +-----------------------------+-----------------------------------------------+[/color]
     
    , Jan 9, 2014
    #1
    1. Advertising

  2. Ian Collins Guest

    wrote:
    > Hi..
    > i tried compiling this code but there are few undefined Macro/functions like MK_FP().
    > I am trying it on WIN32, VS2012.. i have made changes accordingly.
    > Is this solution dependent on any library.
    > Thanks in advance
    >
    >
    > On Monday, August 1, 1994 1:02:48 PM UTC+5:30, Cyborg wrote:


    Are you going for the record for the oldest post to reply to?

    --
    Ian Collins
     
    Ian Collins, Jan 9, 2014
    #2
    1. Advertising

  3. wrote:
    > Hi..
    > i tried compiling this code but there are few undefined Macro/functions like MK_FP().
    > I am trying it on WIN32, VS2012.. i have made changes accordingly.
    > Is this solution dependent on any library.
    > Thanks in advance
    >
    >
    > On Monday, August 1, 1994 1:02:48 PM UTC+5:30, Cyborg wrote:
    >> In article<> (Muhammad Salman Mughal) writes:
    >>>
    >>> Hi there,
    >>>
    >>> I am desperately looking for a C code that could decode a GIF file
    >>> in DOS. Anybody out there who knows how to do it? I will really
    >>> appreciate any help.
    >>>

    >>
    >>
    >> The following code is based on a LZW decoder originally coded by Steven A.
    >> Bennett. All I did is write the code for parsing the GIF format, passing
    >> the approptiate data to the LZW decoder and writing the code for displaying
    >> the data on the screen. Both 87a and 89a formats are accepted.
    >>
    >> Video BIOS must support VESA functions - the code selects a video mode
    >> whith a resolution just high enough to display the given GIF file. Max
    >> resolution is 1280x1024, pictures larger than this will be partially
    >> displayed. Interlaced GIFs are supported. Program was only tested on my
    >> video card (Cirrus 5428 VESA Local Bus). It was not intended for public
    >> release but since I've already written it and the guy i desperate...
    >>
    >> Compiles with Borland C++ v3.1
    >>
    >> ----------------------- chop here --------------------------
    >>
    >> /* Various error codes used by decoder
    >> * and my own routines... It's okay
    >> * for you to define whatever you want,
    >> * as long as it's negative... It will be
    >> * returned intact up the various subroutine
    >> * levels...
    >> */
    >> #define READ_ERROR -1
    >> #define WRITE_ERROR -2
    >> #define OPEN_ERROR -3
    >> #define CREATE_ERROR -4
    >> #define OUT_OF_MEMORY -5
    >> #define BAD_CODE_SIZE -6
    >>
    >> #define ISIZE 2048 // image line size
    >> #define BSIZE 256 // buffer size
    >> #define PSIZE 768 // pallette size
    >> #define NULL 0L
    >> #define MAX_CODES 4095
    >>
    >> #include<dos.h>
    >> #include<conio.h>
    >> #include<stdio.h>
    >> #include<stdlib.h>
    >> #include<string.h>
    >>
    >> /* Static variables */
    >> short curr_size; /* The current code size */
    >> short clear; /* Value for a clear code */
    >> short ending; /* Value for a ending code */
    >> short newcodes; /* First available code */
    >> short top_slot; /* Highest code for current size */
    >> short slot; /* Last read code */
    >>
    >> /* The following static variables are used
    >> * for seperating out codes
    >> */
    >> short navail_bytes = 0; /* # bytes left in block */
    >> short nbits_left = 0; /* # bits left in current byte */
    >> unsigned char b1; /* Current byte */
    >> unsigned char byte_buff[257]; /* Current block */
    >> unsigned char *pbytes; /* Pointer to next byte in block */
    >>
    >> /* The reason we have these separated like this instead of using
    >> * a structure like the original Wilhite code did, is because this
    >> * stuff generally produces significantly faster code when compiled...
    >> * This code is full of similar speedups... (For a good book on writing
    >> * C for speed or for space optimisation, see Efficient C by Tom Plum,
    >> * published by Plum-Hall Associates...)
    >> */
    >> unsigned char stack[MAX_CODES + 1]; /* Stack for storing pixels */
    >> unsigned char suffix[MAX_CODES + 1]; /* Suffix table */
    >> unsigned short prefix[MAX_CODES + 1]; /* Prefix linked list */
    >>
    >> long code_mask[13] = {
    >> 0x0000,
    >> 0x0001, 0x0003, 0x0007, 0x000F,
    >> 0x001F, 0x003F, 0x007F, 0x00FF,
    >> 0x01FF, 0x03FF, 0x07FF, 0x0FFF
    >> };
    >>
    >> // incremented each time an out of range code is read by the decoder
    >> int bad_code_count;
    >>
    >> unsigned char far *buffer=NULL; // file buffer
    >> unsigned char far *grgb=NULL; // global rgb table
    >> unsigned char far *lrgb=NULL; // local rgb table
    >> unsigned char far *pixels=NULL; // line of pixels to be displayed
    >> unsigned char far *vid=NULL; // ptr to start of graphics window
    >> unsigned char background=0; // background color index
    >> unsigned long offset=0; // offset into graphics window
    >> unsigned long piclen; // total screen size in pixels
    >> unsigned int realx; // real picture width
    >> unsigned int realy; // real picture height
    >> unsigned int xsize=0; // graphic width
    >> unsigned int ysize=0; // graphic height
    >> unsigned int win=0; // window number
    >> unsigned int granularity=0; // granularity of video window
    >> unsigned int group=0; // picture group (interlaced or not)
    >> FILE *fp; // file pointer
    >>
    >> /* int get_byte()
    >> * - This function is expected to return the next byte from
    >> * the GIF file or a negative number defined in ERRS.H
    >> */
    >> int get_byte(){
    >> unsigned char c;
    >>
    >> if(fscanf(fp, "%c",&c)==1)
    >> return((int)c);
    >> else
    >> return(READ_ERROR);
    >> }
    >>
    >> /* int out_line(unsigned char pixels[], int linelen)
    >> * - This function takes a full line of pixels (one byte per pixel) and
    >> * displays them (or does whatever your program wants with them...). It
    >> * should return zero, or negative if an error or some other event occurs
    >> * which would require aborting the decode process... Note that the length
    >> * passed will almost always be equal to the line length passed to the
    >> * decoder function, with the sole exception occurring when an ending code
    >> * occurs in an odd place in the GIF file... In any case, linelen will be
    >> * equal to the number of pixels passed...
    >> */
    >> int out_line(unsigned char *pixels, int linelen){
    >> unsigned long segment;
    >>
    >> segment=offset&(unsigned long)(granularity-1);
    >>
    >> // put pixels on screen
    >> memmove(vid+segment, pixels, linelen);
    >> memset(vid+segment+linelen, background, xsize-linelen);
    >> switch (group) {
    >> case 0:
    >> offset+=xsize;
    >> break;
    >> case 1:
    >> offset+=xsize*8;
    >> if(offset>=piclen){
    >> group++;
    >> offset=xsize*4;
    >> }
    >> break;
    >> case 2:
    >> offset+=xsize*8;
    >> if(offset>=piclen){
    >> group++;
    >> offset=xsize*2;
    >> }
    >> break;
    >> case 3:
    >> offset+=xsize*4;
    >> if(offset>=piclen){
    >> group++;
    >> offset=xsize;
    >> }
    >> break;
    >> case 4:
    >> offset+=xsize*2;
    >> break;
    >> default:
    >> break;
    >> }
    >>
    >> // if we've run over a window granularity border, move window position
    >> if((offset>>12)!=win){
    >> win=offset>>12;
    >> asm pusha
    >> asm mov ax, 0x4f05
    >> asm mov bx, 0x0000
    >> asm mov dx, win
    >> asm int 0x10
    >> asm popa
    >> }
    >> return(1);
    >> }
    >>
    >>
    >> /* This function initializes the decoder for reading a new image.
    >> */
    >> static short init_exp(short size)
    >> {
    >> curr_size = size + 1;
    >> top_slot = 1<< curr_size;
    >> clear = 1<< size;
    >> ending = clear + 1;
    >> slot = newcodes = ending + 1;
    >> navail_bytes = nbits_left = 0;
    >> return(0);
    >> }
    >>
    >> /* get_next_code()
    >> * - gets the next code from the GIF file. Returns the code, or else
    >> * a negative number in case of file errors...
    >> */
    >> static short get_next_code()
    >> {
    >> short i, x;
    >> unsigned long ret;
    >>
    >> if (nbits_left == 0)
    >> {
    >> if (navail_bytes<= 0)
    >> {
    >>
    >> /* Out of bytes in current block, so read next block
    >> */
    >> pbytes = byte_buff;
    >> if ((navail_bytes = get_byte())< 0)
    >> return(navail_bytes);
    >> else if (navail_bytes)
    >> {
    >> for (i = 0; i< navail_bytes; ++i)
    >> {
    >> if ((x = get_byte())< 0)
    >> return(x);
    >> byte_buff = x;
    >> }
    >> }
    >> }
    >> b1 = *pbytes++;
    >> nbits_left = 8;
    >> --navail_bytes;
    >> }
    >>
    >> ret = b1>> (8 - nbits_left);
    >> while (curr_size> nbits_left)
    >> {
    >> if (navail_bytes<= 0)
    >> {
    >>
    >> /* Out of bytes in current block, so read next block
    >> */
    >> pbytes = byte_buff;
    >> if ((navail_bytes = get_byte())< 0)
    >> return(navail_bytes);
    >> else if (navail_bytes)
    >> {
    >> for (i = 0; i< navail_bytes; ++i)
    >> {
    >> if ((x = get_byte())< 0)
    >> return(x);
    >> byte_buff = x;
    >> }
    >> }
    >> }
    >> b1 = *pbytes++;
    >> ret |= b1<< nbits_left;
    >> nbits_left += 8;
    >> --navail_bytes;
    >> }
    >> nbits_left -= curr_size;
    >> ret&= code_mask[curr_size];
    >> return((short)(ret));
    >> }
    >>
    >> /* DECODE.C - An LZW decoder for GIF
    >> *
    >> * Copyright (C) 1987, by Steven A. Bennett
    >> *
    >> * Permission is given by the author to freely redistribute and include
    >> * this code in any program as long as this credit is given where due.
    >> *
    >> * In accordance with the above, I want to credit Steve Wilhite who wrote
    >> * the code which this is heavily inspired by...
    >> *
    >> * GIF and 'Graphics Interchange Format' are trademarks (tm) of
    >> * Compuserve, Incorporated, an H&R Block Company.
    >> *
    >> * Release Notes: This file contains a decoder routine for GIF images
    >> * which is similar, structurally, to the original routine by Steve Wilhite.
    >> * It is, however, somewhat noticably faster in most cases.
    >> *
    >> * short decode(linewidth)
    >> * short linewidth; * Pixels per line of image *
    >> *
    >> * - This function decodes an LZW image, according to the method used
    >> * in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
    >> * will generate a call to out_line(), which is a user specific function
    >> * to display a line of pixels. The function gets it's codes from
    >> * get_next_code() which is responsible for reading blocks of data and
    >> * seperating them into the proper size codes. Finally, get_byte() is
    >> * the global routine to read the next byte from the GIF file.
    >> *
    >> * It is generally a good idea to have linewidth correspond to the actual
    >> * width of a line (as specified in the Image header) to make your own
    >> * code a bit simpler, but it isn't absolutely necessary.
    >> *
    >> * Returns: 0 if successful, else negative. (See ERRS.H)
    >> *
    >> */
    >>
    >> short decode(short linewidth)
    >> {
    >> register unsigned char *sp, *bufptr;
    >> unsigned char *buf;
    >> register short code, fc, oc, bufcnt;
    >> short c, size, ret;
    >>
    >> /* Initialize for decoding a new image...
    >> */
    >> if ((size = get_byte())< 0)
    >> return(size);
    >> if (size< 2 || 9< size)
    >> return(BAD_CODE_SIZE);
    >> init_exp(size);
    >>
    >> /* Initialize in case they forgot to put in a clear code.
    >> * (This shouldn't happen, but we'll try and decode it anyway...)
    >> */
    >> oc = fc = 0;
    >>
    >> /* Allocate space for the decode buffer
    >> */
    >> if ((buf = (unsigned char *)malloc(linewidth + 1)) == NULL)
    >> return(OUT_OF_MEMORY);
    >>
    >> /* Set up the stack pointer and decode buffer pointer
    >> */
    >> sp = stack;
    >> bufptr = buf;
    >> bufcnt = linewidth;
    >>
    >> /* This is the main loop. For each code we get we pass through the
    >> * linked list of prefix codes, pushing the corresponding "character" for
    >> * each code onto the stack. When the list reaches a single "character"
    >> * we push that on the stack too, and then start unstacking each
    >> * character for output in the correct order. Special handling is
    >> * included for the clear code, and the whole thing ends when we get
    >> * an ending code.
    >> */
    >> while ((c = get_next_code()) != ending)
    >> {
    >>
    >> /* If we had a file error, return without completing the decode
    >> */
    >> if (c< 0)
    >> {
    >> free(buf);
    >> return(0);
    >> }
    >>
    >> /* If the code is a clear code, reinitialize all necessary items.
    >> */
    >> if (c == clear)
    >> {
    >> curr_size = size + 1;
    >> slot = newcodes;
    >> top_slot = 1<< curr_size;
    >>
    >> /* Continue reading codes until we get a non-clear code
    >> * (Another unlikely, but possible case...)
    >> */
    >> while ((c = get_next_code()) == clear)
    >> ;
    >>
    >> /* If we get an ending code immediately after a clear code
    >> * (Yet another unlikely case), then break out of the loop.
    >> */
    >> if (c == ending)
    >> break;
    >>
    >> /* Finally, if the code is beyond the range of already set codes,
    >> * (This one had better NOT happen... I have no idea what will
    >> * result from this, but I doubt it will look good...) then set it
    >> * to color zero.
    >> */
    >> if (c>= slot)
    >> c = 0;
    >>
    >> oc = fc = c;
    >>
    >> /* And let us not forget to put the char into the buffer... And
    >> * if, on the off chance, we were exactly one pixel from the end
    >> * of the line, we have to send the buffer to the out_line()
    >> * routine...
    >> */
    >> *bufptr++ = c;
    >> if (--bufcnt == 0)
    >> {
    >> if ((ret = out_line(buf, linewidth))< 0)
    >> {
    >> free(buf);
    >> return(ret);
    >> }
    >> bufptr = buf;
    >> bufcnt = linewidth;
    >> }
    >> }
    >> else
    >> {
    >>
    >> /* In this case, it's not a clear code or an ending code, so
    >> * it must be a code code... So we can now decode the code into
    >> * a stack of character codes. (Clear as mud, right?)
    >> */
    >> code = c;
    >>
    >> /* Here we go again with one of those off chances... If, on the
    >> * off chance, the code we got is beyond the range of those already
    >> * set up (Another thing which had better NOT happen...) we trick
    >> * the decoder into thinking it actually got the last code read.
    >> * (Hmmn... I'm not sure why this works... But it does...)
    >> */
    >> if (code>= slot)
    >> {
    >> if (code> slot)
    >> ++bad_code_count;
    >> code = oc;
    >> *sp++ = fc;
    >> }
    >>
    >> /* Here we scan back along the linked list of prefixes, pushing
    >> * helpless characters (ie. suffixes) onto the stack as we do so.
    >> */
    >> while (code>= newcodes)
    >> {
    >> *sp++ = suffix
    Code:
    ;
    >> 	    code = prefix[code];
    >> 	    }
    >>
    >>           /* Push the last character on the stack, and set up the new
    >> 	  * prefix and suffix, and if the required slot number is greater
    >>            * than that allowed by the current bit size, increase the bit
    >> 	  * size.  (NOTE - If we are all full, we *don't* save the new
    >> 	  * suffix and prefix...  I'm not certain if this is correct...
    >> 	  * it might be more proper to overwrite the last code...
    >> 	  */
    >> 	 *sp++ = code;
    >> 	 if (slot<  top_slot)
    >> 	    {
    >> 	    suffix[slot] = fc = code;
    >> 	    prefix[slot++] = oc;
    >> 	    oc = c;
    >> 	    }
    >> 	 if (slot>= top_slot)
    >> 	    if (curr_size<  12)
    >> 	       {
    >> 	       top_slot<<= 1;
    >> 	       ++curr_size;
    >> 	       }
    >>
    >> 	 /* Now that we've pushed the decoded string (in reverse order)
    >>            * onto the stack, lets pop it off and put it into our decode
    >> 	  * buffer...  And when the decode buffer is full, write another
    >> 	  * line...
    >> 	  */
    >> 	 while (sp>  stack)
    >> 	    {
    >> 	    *bufptr++ = *(--sp);
    >> 	    if (--bufcnt == 0)
    >> 	       {
    >> 	       if ((ret = out_line(buf, linewidth))<  0)
    >> 		  {
    >> 		  free(buf);
    >> 		  return(ret);
    >> 		  }
    >> 	       bufptr = buf;
    >> 	       bufcnt = linewidth;
    >> 	       }
    >> 	    }
    >>           }
    >>        }
    >>     ret = 0;
    >>     if (bufcnt != linewidth)
    >>        ret = out_line(buf, (linewidth - bufcnt));
    >>     free(buf);
    >>     return(ret);
    >>     }
    >>
    >>
    >> // this function is called just before program exits
    >> void cleanup(void){
    >>    // free any allocated resources
    >>    if(fp!=NULL)
    >>      fclose(fp);
    >>    if(buffer!=NULL)
    >>      free(buffer);
    >>    if(grgb!=NULL)
    >>      free(grgb);
    >>    if(lrgb!=NULL)
    >>      free(lrgb);
    >>    if(pixels!=NULL)
    >>      free(pixels);
    >> }
    >>
    >> void main(int argc, char **argv){
    >>    unsigned int gctsize=0, lctsize=0, mode;
    >>    int i;
    >>
    >>    // set bad codes encountered to zero
    >>    bad_code_count=0;
    >>
    >>    // set function to be called on exit
    >>    if(atexit(cleanup))
    >>      exit(0);
    >>
    >>    // exit if no file given
    >>    if (argc<2){
    >>      printf("Usage: %s gif_file\n", argv[0]);
    >>      exit(0);
    >>    }
    >>
    >>    // try to open file
    >>    if((fp=fopen(argv[1], "rb"))==NULL){
    >>      printf("Failed to open file.\n");
    >>      exit(0);
    >>    }
    >>
    >>    // allocate buffers
    >>    buffer=(unsigned char *)malloc(BSIZE);
    >>    pixels=(unsigned char *)malloc(ISIZE);
    >>    grgb  =(unsigned char *)malloc(PSIZE);
    >>    lrgb  =(unsigned char *)malloc(PSIZE);
    >>    if((grgb==NULL) || (lrgb==NULL) || (pixels==NULL) || (buffer==NULL)){
    >>      printf("Not enough memory.\n");
    >>      exit(0);
    >>    }
    >>
    >>    fread(buffer, 1, 6, fp);
    >>    // test file for valid GIF signature
    >>    if(memcmp(buffer, "GIF", 3)!=0){
    >>      printf("Not a GIF file.\n");
    >>      exit(0);
    >>    }
    >>    // test file for version number
    >>    if((memcmp(buffer+3, "87a", 3)!=0)&&  (memcmp(buffer+3, "89a", 3)!=0)){
    >>      printf("Unsuported GIF version. Hit a key to decode anyway.\n");
    >>      getch();
    >>    }
    >>
    >>    // read logical screen descriptor
    >>    fread(buffer, 1, 7, fp);
    >>
    >>    // test for global color table presence
    >>    if(*(buffer+4)&0x80){
    >>      // compute global color table size
    >>      gctsize=1<<((*(buffer+4)&0x07) + 1);
    >>      // read global color table into buffer
    >>      fread(grgb, 1, gctsize*3, fp);
    >>      // adjust colors to crappy 6-bit PC-DAC values
    >>      for(i=0; i<gctsize*3; i++)
    >>        *(grgb+i)>>=2;
    >>    }
    >>    // get background color index
    >>    background=*(buffer+5);
    >>
    >>
    >>    // scan file for data blocks
    >>    while((i=get_byte())>0) {
    >>      // in end of GIF marker encountered then exit
    >>      if(i==0x3b)
    >>        exit(0);
    >>      // test for extentions
    >>      if(i==0x21){
    >>        if( (i=get_byte())<  0 )
    >> 	exit(0);
    >>        // if graphic color extention present or
    >>        // coment extention present or
    >>        // plain text extention present or
    >>        // application extention present then skip it
    >>        if( (i==0x01) || (i==0xf9) || (i==0xfe) || (i==0xff)){
    >> 	while((i=get_byte())!=0){
    >> 	  if(fread(buffer, 1, i, fp)!=i)
    >> 	    exit(0);
    >> 	}
    >>        }
    >>      }
    >>
    >>      // test for presence of image descriptor
    >>      if(i==0x2c){
    >>        // get image descriptor
    >>        fread(buffer, 1, 9, fp);
    >>        // interlaced flag is set or cleared accordingly
    >>        if(*(buffer+8)&0x40)
    >> 	group=1;
    >>        realx=xsize=*(buffer+4) | (*(buffer+5)<<8);
    >>        realy=ysize=*(buffer+6) | (*(buffer+7)<<8);
    >>        // test for presence of local color table
    >>        if(*(buffer+8)&0x80){
    >> 	// compute local color table size
    >> 	lctsize=1<<((*(buffer+8)&0x07) + 1);
    >> 	// read local color table into buffer
    >> 	fread(lrgb, 1, lctsize*3, fp);
    >> 	// adjust colors to crappy 6-bit PC-DAC values
    >> 	for(i=0; i<gctsize*3; i++)
    >> 	  *(lrgb+i)>>=2;
    >>        }
    >>
    >>        // choose a video mode that will just fit the image
    >>        if((xsize<=640)&&  (ysize<=480)){
    >> 	mode=0x101;		//  VESA 640 x  480 x 256
    >> 	xsize=640;
    >> 	ysize=480;
    >>        } else if ((xsize<=800)&&  (ysize<=600)){
    >> 	mode=0x103;		//  VESA 800 x  600 x 256
    >> 	xsize=800;
    >> 	ysize=600;
    >>        } else if ((xsize<=1024)&&  (ysize<=768)){
    >> 	mode=0x105;		// VESA 1024 x  768 x 256
    >> 	xsize=1024;
    >> 	ysize=768;
    >>        } else {
    >> 	mode=0x107;		// VESA 1280 x 1024 x 256
    >> 	xsize=1280;
    >> 	ysize=1024;
    >>        }
    >>
    >>        piclen=(unsigned long)xsize*(unsigned long)ysize;
    >>        // get video mode info through VESA call
    >>        asm pusha
    >>        asm mov ax, 0x4f01
    >>        asm mov cx, mode
    >>        asm les di, buffer
    >>        asm int 0x10
    >>        asm mov i, ax
    >>        asm popa
    >>
    >>        if(i!=0x004f){
    >> 	printf("VESA video functions not available.\n");
    >> 	exit(0);
    >>        }
    >>        // if mode not supported, or not color, or not graphics then exit
    >>        if((*buffer&0x19)!=0x19){
    >> 	printf("Required graphics mode is not available.\n");
    >> 	exit(0);
    >>        }
    >>
    >>        // if window does not exist or is not writable exit
    >>        if((*(buffer+2)&0x05)!=0x05) {
    >> 	printf("Cannot access video RAM.\n");
    >> 	exit(0);
    >>        }
    >>
    >>        // calculate window granularity
    >>        granularity=(*(buffer+4) | (*(buffer+5)<<8))<<10;
    >>        // calculate pointer to video RAM start
    >>        vid=(unsigned char *)MK_FP((*(buffer+8) | (*(buffer+9)<<8)), 0);
    >>
    >>        // set VESA video mode
    >>        asm pusha
    >>        asm mov ax, 0x4f02
    >>        asm mov bx, mode
    >>        asm int 0x10
    >>        asm popa
    >>
    >>        // set color table if present
    >>        if(lctsize){
    >> 	// scope of local color table is local so once used it's gone
    >> 	lctsize=0;
    >> 	asm pusha
    >> 	asm mov ax, 0x1012
    >> 	asm mov bx, 0x0000
    >> 	asm mov cx, 0x0100
    >> 	asm les dx, lrgb
    >> 	asm int 0x10
    >> 	asm popa
    >>        } else if(gctsize){
    >> 	// if no local color table then set global color table if present
    >> 	asm pusha
    >> 	asm mov ax, 0x1012
    >> 	asm mov bx, 0x0000
    >> 	asm mov cx, 0x0100
    >> 	asm les dx, grgb
    >> 	asm int 0x10
    >> 	asm pop es
    >> 	asm popa
    >>        }
    >>
    >>        // decode and display graphic
    >>        decode(realx);
    >>        // wait for key press
    >>        getch();
    >>
    >>        // set default text mode
    >>        asm mov ax, 0x0003
    >>        asm int 0x10
    >>      }
    >>    }
    >>
    >>    // exit to dos
    >>    exit(0);
    >> }
    >>
    >> -------------- chop here -------------------
    >>
    >> --
    >> +-----------------------------+-----------------------------------------------+
    >> | Alex Ivopol                 |  If you  love  something set it free.  If it  |
    >> |  |  doesn't come back, hunt it down and kill it. |
    >> +-----------------------------+-----------------------------------------------+[/color][/color]
    
    Dear people from the future,
    
    The code does direct hardware access to gfx card(VESA for mode-setting
    and output). The MK_FP is problematic, too(16 bit dos program). The
    output is pallettized and 6 bits per components(r,g,b). You'll most
    likely want 8. Aside from those details it might work alright. You will
    need another way to actually display the decoded data. there have been
    help files floating around the net documenting M$ win32 API. try those.
    Also...
    http://www.winprog.org/tutorial/
     
    Johann Klammer, Jan 9, 2014
    #3
  4. On 09.01.2014 04:23, wrote:
    > Hi..
    > i tried compiling this code but there are few undefined Macro/functions like MK_FP().
    > I am trying it on WIN32, VS2012.. i have made changes accordingly.
    > Is this solution dependent on any library.


    [snip early 1990's code]

    No, the code is just very DOS-specific. It contains inline assembly for
    a PC, with the program running with the processor in 8086 mode. In this
    mode a logical address consists of a 16-bit offset and a 16-bit segment
    selector. The segment selector could be implied, then taken from a
    processor register. This (a 16-bit logical address specified as only
    offset) was called a NEAR address. Alternatively the segment selector
    could be explicitly specified, and this (a 32-bit logical address
    specified as offset and selector) was called a FAR address.

    Worth noting that a FAR address only specified 21 bits, because a
    selector S always selected the logical segment starting at address 16*S.

    MK_FP created a C language representation of a "far pointer".

    There is nothing corresponding to that[1] in modern C or C++.

    * * *

    You may still be able to use the code, either directly in a DOS box (the
    DOS emulator, not a Windows command interpreter instance) or by
    replacing the DOS presentation with whatever you want.


    Cheers & hth.,

    - Alf

    Notes:
    [1] In still much used 32-bit C and C++ programming on the PC there is a
    corresponding issue, namely that all addresses handled by C or C++
    pointers are really just 32-bit offsets into a segment. The implied
    segment selector can come from any relevant selector register because
    the operating places the same selector value in all these registers (a
    neat little trick). In order to access some Windows thread information
    it's necessary to specify a different segment than the usual, namely the
    one denoted by the FS register, if I recall correctly. To do this one
    must delve down to the assembly language level.
     
    Alf P. Steinbach, Jan 9, 2014
    #4
  5. Guest

    Thanks for the nominations :).
    Fortunately i was able to find only this to start up.
    Hope u understand how a startup person would feel, when he comes across a source file all of a sudden.

    Please can u direct me to the place where i can find something useful.


    On Thursday, January 9, 2014 9:03:33 AM UTC+5:30, Ian Collins wrote:
    > wrote:
    >
    > > Hi..

    >
    > > i tried compiling this code but there are few undefined Macro/functions like MK_FP().

    >
    > > I am trying it on WIN32, VS2012.. i have made changes accordingly.

    >
    > > Is this solution dependent on any library.

    >
    > > Thanks in advance

    >
    > >

    >
    > >

    >
    > > On Monday, August 1, 1994 1:02:48 PM UTC+5:30, Cyborg wrote:

    >
    >
    >
    > Are you going for the record for the oldest post to reply to?
    >
    >
    >
    > --
    >
    > Ian Collins
     
    , Jan 13, 2014
    #5
  6. Jorgen Grahn Guest

    On Mon, 2014-01-13, wrote:
    > Thanks for the nominations :).
    > Fortunately i was able to find only this to start up.
    > Hope u understand how a startup person would feel,
    > when he comes across a source file all of a sudden.
    >
    > Please can u direct me to the place where i can find something useful.


    What do you want to do? Decoding GIFs was useful back in 1994, but
    since then a few other image formats have become more popular. There
    are widely used libraries for decoding all of them.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Jan 13, 2014
    #6
  7. Guest

    On Monday, January 13, 2014 6:28:12 PM UTC+5:30, Jorgen Grahn wrote:
    > On Mon, 2014-01-13, wrote:
    >
    > > Thanks for the nominations :).

    >
    > > Fortunately i was able to find only this to start up.

    >
    > > Hope u understand how a startup person would feel,

    >
    > > when he comes across a source file all of a sudden.

    >
    > >

    >
    > > Please can u direct me to the place where i can find something useful.

    >
    >
    >
    > What do you want to do? Decoding GIFs was useful back in 1994, but
    >
    > since then a few other image formats have become more popular. There
    >
    > are widely used libraries for decoding all of them.
    >
    >
    >
    > /Jorgen
    >
    >
    >
    > --
    >
    > // Jorgen Grahn <grahn@ Oo o. . .
    >
    > \X/ snipabacken.se> O o .


    I want to decode a GIF encoded image.
    Ideally a GIF decoder(open source code).
     
    , Jan 15, 2014
    #7
  8. Geoff Guest

    On Tue, 14 Jan 2014 19:23:15 -0800 (PST), wrote:

    >On Monday, January 13, 2014 6:28:12 PM UTC+5:30, Jorgen Grahn wrote:
    >> On Mon, 2014-01-13, wrote:
    >>
    >> > Thanks for the nominations :).

    >>
    >> > Fortunately i was able to find only this to start up.

    >>
    >> > Hope u understand how a startup person would feel,

    >>
    >> > when he comes across a source file all of a sudden.

    >>
    >> >

    >>
    >> > Please can u direct me to the place where i can find something useful.

    >>
    >>
    >>
    >> What do you want to do? Decoding GIFs was useful back in 1994, but
    >>
    >> since then a few other image formats have become more popular. There
    >>
    >> are widely used libraries for decoding all of them.
    >>
    >>
    >>
    >> /Jorgen
    >>
    >>
    >>
    >> --
    >>
    >> // Jorgen Grahn <grahn@ Oo o. . .
    >>
    >> \X/ snipabacken.se> O o .

    >
    >I want to decode a GIF encoded image.
    >Ideally a GIF decoder(open source code).


    Your OP contains Borland C for DOS code which has problems as cited by
    others with inline asm and obsolete things like far pointers.

    Since you seem to be doing your project on Windows, here's how you use
    the Microsoft image library functions:

    http://msdn.microsoft.com/en-us/library/aa970565(v=vs.110).aspx

    Since you seem to be unfamiliar with the tool known as Google, here is
    a sample search that yields some excellent resources about the GIF
    file format and some excellent code samples.

    https://www.google.com/#q=gif decoder
     
    Geoff, Jan 15, 2014
    #8
  9. Jorgen Grahn Guest

    On Wed, 2014-01-15, wrote:
    > On Monday, January 13, 2014 6:28:12 PM UTC+5:30, Jorgen Grahn wrote:
    >> On Mon, 2014-01-13, wrote:
    >>
    >> > Thanks for the nominations :).
    >> > Fortunately i was able to find only this to start up.
    >> > Hope u understand how a startup person would feel,
    >> > when he comes across a source file all of a sudden.
    >> >
    >> > Please can u direct me to the place where i can find something useful.

    >>
    >> What do you want to do? Decoding GIFs was useful back in 1994, but
    >> since then a few other image formats have become more popular. There
    >> are widely used libraries for decoding all of them.


    > I want to decode a GIF encoded image.


    I meant "/why/ do you want to decode GIF?" I'm not saying /noone/ uses
    GIF any more, but I see it very rarely compared to PNG and JPEG.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Jan 15, 2014
    #9
  10. Guest

    For the images being encoded by someone with GIF encoder needs to be decoded by GIF decoder only (Am i wrong in this assumption?) :)
    And thanks for the info of GIF usage :)


    On Thursday, January 16, 2014 3:16:13 AM UTC+5:30, Jorgen Grahn wrote:
    > On Wed, 2014-01-15, wrote:
    >
    > > On Monday, January 13, 2014 6:28:12 PM UTC+5:30, Jorgen Grahn wrote:

    >
    > >> On Mon, 2014-01-13, wrote:

    >
    > >>

    >
    > >> > Thanks for the nominations :).

    >
    > >> > Fortunately i was able to find only this to start up.

    >
    > >> > Hope u understand how a startup person would feel,

    >
    > >> > when he comes across a source file all of a sudden.

    >
    > >> >

    >
    > >> > Please can u direct me to the place where i can find something useful.

    >
    > >>

    >
    > >> What do you want to do? Decoding GIFs was useful back in 1994, but

    >
    > >> since then a few other image formats have become more popular. There

    >
    > >> are widely used libraries for decoding all of them.

    >
    >
    >
    > > I want to decode a GIF encoded image.

    >
    >
    >
    > I meant "/why/ do you want to decode GIF?" I'm not saying /noone/ uses
    >
    > GIF any more, but I see it very rarely compared to PNG and JPEG.
    >
    >
    >
    > /Jorgen
    >
    >
    >
    > --
    >
    > // Jorgen Grahn <grahn@ Oo o. . .
    >
    > \X/ snipabacken.se> O o .
     
    , Jan 16, 2014
    #10
  11. seeplus Guest

    On Thursday, January 16, 2014 7:44:12 PM UTC+11, wrote:
    > For the images being encoded by someone with GIF encoder needs to be decoded by GIF decoder only (Am i wrong in this assumption?) :)
    >
    > And thanks for the info of GIF usage :)
    >


    Do you mean >> can some OTHER decoder, which is designed to decode something else and is not specifically a GIF decoder, decode GIF images?
     
    seeplus, Jan 17, 2014
    #11
  12. Guest

    Hey..
    Just as a reply for why i was in need of GIF decoder which is rarely used compared to PNG and GPEG.
    I had to mention it.
    Hope you understand.

    Thanks for all inputs.

    On Friday, January 17, 2014 1:28:36 PM UTC+5:30, seeplus wrote:
    > On Thursday, January 16, 2014 7:44:12 PM UTC+11, wrote:
    >
    > > For the images being encoded by someone with GIF encoder needs to be decoded by GIF decoder only (Am i wrong in this assumption?) :)

    >
    > >

    >
    > > And thanks for the info of GIF usage :)

    >
    > >

    >
    >
    >
    > Do you mean >> can some OTHER decoder, which is designed to decode something else and is not specifically a GIF decoder, decode GIF images?
     
    , Jan 17, 2014
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. hb
    Replies:
    6
    Views:
    9,187
  2. b83503104
    Replies:
    2
    Views:
    334
    Rolf Magnus
    Nov 28, 2003
  3. b83503104
    Replies:
    2
    Views:
    552
    Rolf Magnus
    Nov 28, 2003
  4. Beauregard T. Shagnasty

    Re: filename.gif or filename.gif.jpg?

    Beauregard T. Shagnasty, May 30, 2008, in forum: HTML
    Replies:
    1
    Views:
    793
    Jonathan N. Little
    May 30, 2008
  5. Bergamot
    Replies:
    0
    Views:
    474
    Bergamot
    May 30, 2008
Loading...

Share This Page