home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / images / image.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  26.0 KB  |  1,201 lines

  1. /*
  2.  *    Don't use capstdio and ?capalloc since will really be external from
  3.  *        doslynx (TurboVision) code.  Every allocation is clean,
  4.  *        and display is erased once doslynx will start back up.
  5.  */
  6. #include"capalloc.h"
  7. #include<string.h>
  8.  
  9. #include <graphics.h>
  10. #include <stdlib.h>
  11. #include <conio.h>
  12. #include <stdio.h>
  13. #include <math.h>
  14. #ifdef SVGA
  15. #include "svga256.h"
  16. #endif /* SVGA */
  17. #include "image.h"
  18.  
  19. #define FALSE 0
  20. #define TRUE 1
  21.  
  22. #define pm_message printf
  23. #define pm_error printf
  24.  
  25. char *image_mode_names[] = {
  26.     "CGA (640x200x2)",
  27.   "EGA (640x350x16)",
  28.   "Hercules (720x348x2)",
  29.   "VGA (640x480x16)",
  30.   "VGA (320x200x256)"
  31. #ifdef SVGA
  32.   ,
  33.   "SVGA (640x480x256)",
  34.   "SVGA (800x600x256)",
  35.   "SVGA (1024x768x256)"
  36. #endif /* SVGA */
  37. };
  38.  
  39. static int gif_setup(image_modes mode);
  40. static void gif_shutdown(void);
  41. static int colorsavail;
  42. static float gif_aspect;
  43. static float mode_aspect;
  44. static int *xvector;
  45. static int *yvector;
  46. #ifdef SVGA
  47. static int svga_mode_choice;
  48. #endif /* SVGA */
  49.  
  50. #ifdef SVGA
  51. int huge DetectVGA256();
  52. static DacPalette256 pal256;
  53. #endif /* SVGA */
  54.  
  55. typedef struct {
  56.     int r, g, b;
  57. } rgb;
  58.  
  59. #define MYMAXCOLORS 256
  60.  
  61. static rgb *ctable;
  62.  
  63. static int psettable = 0;
  64. static void setp(int id, rgb v);
  65. static int ctotal = 0;
  66. static int *vtoc;
  67. #ifdef SVGA
  68. static int svga_flag = 0;
  69. #endif /* SVGA */
  70. typedef struct {
  71.     unsigned int    Width;
  72.     unsigned int    Height;
  73.     unsigned char    ColorMap[3][MYMAXCOLORS];
  74.     unsigned int    BitPixel;
  75.     unsigned int    ColorResolution;
  76.     unsigned int    Background;
  77.     unsigned int    AspectRatio;
  78. } GifScreenType;
  79.  
  80. /* We'll have to malloc this sucker to keep DOS memory schemes happy */
  81. static GifScreenType *GifScreen_p;
  82.  
  83. /* Alias to make the GIF code happy */
  84. #define GifScreen (*GifScreen_p)
  85.  
  86. static long *hist;
  87. static int *foundcolors;
  88. static int foundtotal = 0;
  89. static char *bgi_path = 0;
  90. static char *bgi_default = "";
  91.  
  92. static int gif_setup(image_modes mode) {
  93.   int gdriver, gmode, errorcode;
  94.   int xasp, yasp;
  95.   struct palettetype pal;
  96.   int i;
  97.  
  98. #ifdef SVGA
  99.   svga_flag = 0;
  100. #endif /* SVGA */
  101.     registerfarbgidriver(EGAVGA_driver_far);
  102.     registerfarbgidriver(Herc_driver_far);
  103.     registerfarbgidriver(CGA_driver_far);
  104.  
  105.     ctable = (rgb*) malloc(sizeof(rgb) * (size_t)MYMAXCOLORS);
  106.     if(ctable == NULL)    {
  107.         pm_error("Out of memory.\n");
  108.         return(-1);
  109.     }
  110.  
  111.     vtoc = (int*) malloc(sizeof(int) * (size_t)MYMAXCOLORS);
  112.     if(vtoc == NULL)    {
  113.         free(ctable);
  114.         ctable = NULL;
  115.         pm_error("Out of memory.\n");
  116.         return(-1);
  117.     }
  118.  
  119.     hist = (long*) malloc(sizeof(long) * (size_t)MYMAXCOLORS);
  120.     if(hist == NULL)    {
  121.         free(ctable);
  122.         ctable = NULL;
  123.         free(vtoc);
  124.         vtoc = NULL;
  125.         pm_error("Out of memory.\n");
  126.         return(-1);
  127.     }
  128.  
  129.     foundcolors = (int*) malloc(sizeof(int) * (size_t)MYMAXCOLORS);
  130.     if(foundcolors == NULL)    {
  131.         free(ctable);
  132.         ctable = NULL;
  133.         free(vtoc);
  134.         vtoc = NULL;
  135.         free(hist);
  136.         hist = NULL;
  137.         pm_error("Out of memory.\n");
  138.         return(-1);
  139.     }
  140.  
  141.     GifScreen_p = (GifScreenType*) malloc(sizeof(GifScreenType));
  142.  
  143.     foundcolors = (int*) malloc(sizeof(int) * (size_t)MYMAXCOLORS);
  144.     if(foundcolors == NULL)    {
  145.         free(ctable);
  146.         ctable = NULL;
  147.         free(vtoc);
  148.         vtoc = NULL;
  149.         free(hist);
  150.         hist = NULL;
  151.         free(foundcolors);
  152.         foundcolors = NULL;
  153.         pm_error("Out of memory.\n");
  154.         return(-1);
  155.     }
  156.  
  157.   switch(mode) {
  158.         case image_mode_cga:
  159.     gdriver = CGA;
  160.       gmode = CGAHI;
  161.       break;
  162.     case image_mode_herc:
  163.       detectgraph(&gdriver, &gmode);
  164.       if (gdriver != HERCMONO) {
  165.     printf("You do not have a Hercules graphics card installed\n");
  166.     printf("(or that is not the preferred mode of your graphics card).\n");
  167.     printf("Try CGA, EGA or VGA.\n");
  168.         free(ctable);
  169.         ctable = NULL;
  170.         free(vtoc);
  171.         vtoc = NULL;
  172.         free(hist);
  173.         hist = NULL;
  174.         free(foundcolors);
  175.         foundcolors = NULL;
  176.         free(GifScreen_p);
  177.         GifScreen_p = NULL;
  178.     return -1;
  179.       }
  180.     gdriver = HERCMONO;
  181.       gmode = HERCMONOHI;
  182.       break;
  183.     case image_mode_ega:
  184.     gdriver = EGA;
  185.       gmode = EGAHI;
  186.       break;
  187.     case image_mode_vga_640x480x16:
  188.     gdriver = VGA;
  189.       gmode = VGAHI;
  190.       break;
  191. #ifdef SVGA
  192.     case image_mode_vga_320x200x256:
  193.     svga_flag = 1;
  194.       gdriver = DETECT;
  195.       gmode = SVGA320x200x256;
  196.       break;
  197.     case image_mode_svga_640x480x256:
  198.     svga_flag = 1;
  199.       gdriver = DETECT;
  200.       gmode = SVGA640x480x256;
  201.       break;
  202.     case image_mode_svga_800x600x256:
  203.     svga_flag = 1;
  204.       gdriver = DETECT;
  205.       gmode = SVGA800x600x256;
  206.       break;
  207.     case image_mode_svga_1024x768x256:
  208.     svga_flag = 1;
  209.       gdriver = DETECT;
  210.       gmode = SVGA1024x768x256;
  211.       break;
  212. #endif /* SVGA */
  213.         default:
  214.     gdriver = DETECT;
  215.       break;
  216.   }
  217. #ifdef SVGA
  218.   if (svga_flag) {
  219.         installuserdriver("Svga256",DetectVGA256);
  220.     registerfarbgidriver(Svga256_fdriver);
  221.     svga_mode_choice = gmode;
  222.   }
  223. #endif /* SVGA */
  224.   if (!bgi_path) {
  225.         bgi_path = getenv("BGI_PATH");
  226.   }
  227.   if (!bgi_path) {
  228.     bgi_path = bgi_default;
  229.   }
  230.   initgraph(&gdriver, &gmode, bgi_path);
  231.   errorcode = graphresult();
  232.     /* an error occurred */
  233.     if (errorcode != grOk)
  234.   {
  235.     printf("Graphics error: %s\n", grapherrormsg(errorcode));
  236.     printf("(Perhaps the .BGI drivers are not in the current directory\n");
  237.     printf("and you have not set BGI_PATH to point to them.)\n");
  238.         free(ctable);
  239.         ctable = NULL;
  240.         free(vtoc);
  241.         vtoc = NULL;
  242.         free(hist);
  243.         hist = NULL;
  244.         free(foundcolors);
  245.         foundcolors = NULL;
  246.         free(GifScreen_p);
  247.         GifScreen_p = NULL;
  248.     return -1;
  249.     }
  250.   getaspectratio(&xasp, &yasp);
  251.   colorsavail = getmaxcolor() + 1;
  252.   if (colorsavail == 2) {
  253.     ctable[0].r = 0x0;
  254.     ctable[0].g = 0x0;
  255.     ctable[0].b = 0x0;
  256.     ctable[1].r = 0xFF;
  257.     ctable[1].g = 0xFF;
  258.     ctable[1].b = 0xFF;
  259.     setp(0, ctable[0]);
  260.     setp(1, ctable[1]);
  261.   } else {
  262.     psettable = 1;
  263.   }
  264.     ctotal = 0;
  265.   for (i=0; (i<MYMAXCOLORS); i++) {
  266.     vtoc[i] = -1;
  267.   }
  268.   mode_aspect = (float)yasp / (float)xasp;
  269.   pal.size = colorsavail;
  270.   for (i=0; (i<colorsavail); i++) {
  271.     pal.colors[i] = i;
  272.   }
  273.   setallpalette(&pal);
  274.     return 0;
  275. }
  276.  
  277. static void gif_shutdown(void) {
  278.     closegraph();
  279.     free(ctable);
  280.     free(vtoc);
  281.     free(hist);
  282.     free(foundcolors);
  283.     free(GifScreen_p);
  284. }
  285.  
  286. static int ReadGIF ( FILE    *fd, int imageNumber );
  287.  
  288. /*
  289.  *    To get rid of the static memory hog this code has!
  290.  */
  291. #define    MAX_LWZ_BITS        12
  292. int *ip_table0 = NULL;
  293. int *ip_table1 = NULL;
  294. int *ip_stack = NULL;
  295.  
  296. signed short int image_viewer(const char *fname, image_modes mode) {
  297.     FILE *in;
  298.     if (gif_setup(mode) != 0) {
  299.     fprintf(stderr, "Graphics mode %s not available.\n", image_mode_names[mode]);
  300.     fprintf(stderr, "Press any key:\n");
  301.     getch();
  302.     return -1;
  303.   }
  304.  
  305.   in = fopen(fname, "rb");
  306.   if (!in) {
  307.     fprintf(stderr, "File %s not found\n", fname);
  308.     fprintf(stderr, "Press any key:\n");
  309.     getch();
  310.     gif_shutdown();
  311.     return -1;
  312.   }
  313.  
  314.     /*
  315.      *    Allocate the static memory the code used to have off of the
  316.      *    heap.  If unable, return an error, -1.
  317.      *    The memory allocated here will be realeased at the return
  318.      *    of this function.
  319.      */
  320.     if(ip_table0 == NULL || ip_table1 == NULL || ip_stack == NULL)    {
  321.         ip_table0 = (int *)calloc((size_t)2, (size_t)((size_t)1 <<
  322.             (size_t)MAX_LWZ_BITS) * sizeof(int));
  323.         ip_table1 = ip_table0 + (size_t)((size_t)1 <<
  324.             (size_t)MAX_LWZ_BITS);
  325.  
  326.         ip_stack = (int *)calloc((size_t)2, (size_t)((size_t)1 <<
  327.             (size_t)MAX_LWZ_BITS) * sizeof(int));
  328.  
  329.         if(ip_table0 == NULL || ip_table1 == NULL || ip_stack == NULL)
  330.         {
  331.             pm_error("Out of memory.\n");
  332.             gif_shutdown();
  333.             return(-1);
  334.         }
  335.     }
  336.  
  337.   if (ReadGIF(in, 1) != 0) {
  338.     fprintf(stderr, "\n");
  339.     fprintf(stderr, "Press any key:\n");
  340.     getch();
  341.     gif_shutdown();
  342.     free(ip_table0);
  343.     free(ip_stack);
  344.     ip_table0 = ip_table1 = ip_stack = NULL;
  345.     return -1;
  346.   }
  347.  
  348.   getch();
  349.   gif_shutdown();
  350.     free(ip_table0);
  351.     free(ip_stack);
  352.     ip_table0 = ip_table1 = ip_stack = NULL;
  353.     return 0;
  354. }
  355.  
  356. static void setp(int id, rgb v) {
  357. #ifdef SVGA
  358.   if (svga_flag) {
  359.     pal256[id][0] = v.r >> 2;
  360.     pal256[id][1] = v.g >> 2;
  361.     pal256[id][2] = v.b >> 2;
  362.   } else {
  363. #endif /* SVGA */
  364.         setrgbpalette(id, v.r >> 2, v.g >> 2, v.b >> 2);
  365. #ifdef SVGA
  366.   }
  367. #endif /* SVGA */
  368. }
  369.  
  370. /* +-------------------------------------------------------------------+ */
  371. /* | Copyright 1990, David Koblas.                                     | */
  372. /* |   Permission to use, copy, modify, and distribute this software   | */
  373. /* |   and its documentation for any purpose and without fee is hereby | */
  374. /* |   granted, provided that the above copyright notice appear in all | */
  375. /* |   copies and that both that copyright notice and this permission  | */
  376. /* |   notice appear in supporting documentation.  This software is    | */
  377. /* |   provided "as is" without express or implied warranty.           | */
  378. /* +-------------------------------------------------------------------+ */
  379.  
  380.  
  381. #define CM_RED        0
  382. #define CM_GREEN    1
  383. #define CM_BLUE        2
  384.  
  385.  
  386. #define INTERLACE        0x40
  387. #define LOCALCOLORMAP    0x80
  388. #define BitSet(byte, bit)    (((byte) & (bit)) == (bit))
  389.  
  390. #define    ReadOK(file,buffer,len)    (fread(buffer, len, 1, file) != 0)
  391.  
  392. #define LM_to_uint(a,b)            (((b)<<8)|(a))
  393.  
  394. struct {
  395.     int    transparent;
  396.     int    delayTime;
  397.     int    inputFlag;
  398.     int    disposal;
  399. } Gif89 = { -1, -1, -1, 0 };
  400.  
  401. int    verbose;
  402. int    showComment;
  403.  
  404. static int ReadColorMap ( FILE *fd, int number, unsigned char buffer[3][MYMAXCOLORS] );
  405. static int DoExtension ( FILE *fd, int label );
  406. static int GetDataBlock ( FILE *fd, unsigned char  *buf );
  407. static int GetCode ( FILE *fd, int code_size, int flag );
  408. static int LWZReadByte ( FILE *fd, int flag, int input_code_size );
  409. static int DisplayImage ( FILE *fd, int len, int height, int maxcolors, unsigned char cmap[3][MYMAXCOLORS], int interlace, int ignore );
  410. static int HistImage ( FILE *fd, int len, int height, unsigned char cmap[3][MYMAXCOLORS], int interlace, int ignore, long hist[MYMAXCOLORS], int *mc_color);
  411.  
  412. static int    verbose = FALSE;
  413. static int    showComment = FALSE;
  414.  
  415. int mc_color;
  416.  
  417. static int
  418. ReadGIF(fd, imageNumber)
  419. FILE    *fd;
  420. int    imageNumber;
  421. {
  422.   int maxcolors;
  423.     unsigned char    buf[16];
  424.     unsigned char    c;
  425.     unsigned char    localColorMap[3][MYMAXCOLORS];
  426.     int        useGlobalColormap;
  427.     int        bitPixel;
  428.     int        imageCount = 0;
  429.     char        version[4];
  430.  
  431.     if (! ReadOK(fd,buf,6)) {
  432.         pm_error("error reading magic number" );
  433.     return -1;
  434.   }
  435.     if (strncmp(buf,"GIF",3) != 0) {
  436.         pm_error("not a GIF file" );
  437.     return -1;
  438.   }
  439.     strncpy(version, buf + 3, 3);
  440.     version[3] = '\0';
  441.  
  442.     if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
  443.         pm_error("bad version number, not '87a' or '89a'" );
  444.     return -1;
  445.   }
  446.     if (! ReadOK(fd,buf,7)) {
  447.         pm_error("failed to read screen descriptor" );
  448.     return -1;
  449.   }
  450.     GifScreen.Width           = LM_to_uint(buf[0],buf[1]);
  451.     GifScreen.Height          = LM_to_uint(buf[2],buf[3]);
  452.     GifScreen.BitPixel        = 2<<(buf[4]&0x07);
  453.     GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
  454.     GifScreen.Background      = buf[5];
  455.     GifScreen.AspectRatio     = buf[6];
  456.   maxcolors = GifScreen.BitPixel;
  457.     if (BitSet(buf[4], LOCALCOLORMAP)) {    /* Global Colormap */
  458.         if (ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap)) {
  459.             pm_error("error reading global colormap" );
  460.         return -1;
  461.     }
  462.     }
  463.  
  464.     if (GifScreen.AspectRatio != 0 && GifScreen.AspectRatio != 49) {
  465.         float    r;
  466.         r = ( (float) GifScreen.AspectRatio + 15.0 ) / 64.0;
  467.     gif_aspect = r;
  468.     }
  469.  
  470.     for (;;) {
  471.         if (! ReadOK(fd,&c,1)) {
  472.             pm_error("EOF / read error on image data" );
  473.       return -1;
  474.     }
  475.         if (c == ';') {        /* GIF terminator */
  476.             if (imageCount < imageNumber) {
  477.                 pm_error("only %d image%s found in file",
  478.                      imageCount, imageCount>1?"s":"" );
  479.     return -1;
  480.       }
  481.             return 0;
  482.         }
  483.  
  484.         if (c == '!') {     /* Extension */
  485.             if (! ReadOK(fd,&c,1)) {
  486.                 pm_error("OF / read error on extension function code");
  487.     return -1;
  488.       }
  489.             DoExtension(fd, c);
  490.             continue;
  491.         }
  492.  
  493.         if (c != ',') {        /* Not a valid start character */
  494.             pm_message("bogus character 0x%02x, ignoring", (int) c );
  495.             continue;
  496.         }
  497.  
  498.         ++imageCount;
  499.  
  500.         if (! ReadOK(fd,buf,9)) {
  501.             pm_error("couldn't read left/top/width/height");
  502.       return -1;
  503.     }
  504.         useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
  505.  
  506.         bitPixel = 1<<((buf[8]&0x07)+1);
  507.  
  508.         if (! useGlobalColormap) {
  509.             if (ReadColorMap(fd, bitPixel, localColorMap)) {
  510.                 pm_error("error reading local colormap" );
  511.     return -1;
  512.       }
  513.       maxcolors = bitPixel;
  514.             DisplayImage(fd, LM_to_uint(buf[4],buf[5]),
  515.                   LM_to_uint(buf[6],buf[7]), maxcolors, localColorMap,
  516.                   BitSet(buf[8], INTERLACE), imageCount != imageNumber);
  517.         } else {
  518.             DisplayImage(fd, LM_to_uint(buf[4],buf[5]),
  519.                   LM_to_uint(buf[6],buf[7]), maxcolors, GifScreen.ColorMap,
  520.                   BitSet(buf[8], INTERLACE), imageCount != imageNumber);
  521.         }
  522.     }
  523.     return 0;
  524. }
  525.  
  526. static int
  527. ReadColorMap(fd,number,buffer)
  528. FILE        *fd;
  529. int        number;
  530. unsigned char    buffer[3][MYMAXCOLORS];
  531. {
  532.     int        i;
  533.     unsigned char    rgb[3];
  534.  
  535.     for (i = 0; i < number; ++i) {
  536.         if (! ReadOK(fd, rgb, sizeof(rgb))) {
  537.             pm_error("bad colormap" );
  538.       return -1;
  539.     }
  540.  
  541.         buffer[CM_RED][i] = rgb[0] ;
  542.         buffer[CM_GREEN][i] = rgb[1] ;
  543.         buffer[CM_BLUE][i] = rgb[2] ;
  544.     }
  545.     return 0;
  546. }
  547.  
  548. static int
  549. DoExtension(fd, label)
  550. FILE    *fd;
  551. int    label;
  552. {
  553.     static char    buf[256];
  554.     char        *str;
  555.  
  556.     switch (label) {
  557.     case 0x01:        /* Plain Text Extension */
  558.         str = "Plain Text Extension";
  559. #ifdef notdef
  560.         if (GetDataBlock(fd, (unsigned char*) buf) == 0)
  561.             ;
  562.  
  563.         lpos   = LM_to_uint(buf[0], buf[1]);
  564.         tpos   = LM_to_uint(buf[2], buf[3]);
  565.         width  = LM_to_uint(buf[4], buf[5]);
  566.         height = LM_to_uint(buf[6], buf[7]);
  567.         cellw  = buf[8];
  568.         cellh  = buf[9];
  569.         foreground = buf[10];
  570.         background = buf[11];
  571.  
  572.         while (GetDataBlock(fd, (unsigned char*) buf) != 0) {
  573.             PPM_ASSIGN(image[ypos][xpos],
  574.                     cmap[CM_RED][v],
  575.                     cmap[CM_GREEN][v],
  576.                     cmap[CM_BLUE][v]);
  577.             ++index;
  578.         }
  579.  
  580.         return FALSE;
  581. #else
  582.         break;
  583. #endif
  584.     case 0xff:
  585.         /* Application Extension */
  586.         str = "Application Extension";
  587.         break;
  588.     case 0xfe:        /* Comment Extension */
  589.         str = "Comment Extension";
  590.         while (GetDataBlock(fd, (unsigned char*) buf) != 0) {
  591.             if (showComment)
  592.                 pm_message("gif comment: %s", buf );
  593.         }
  594.         return FALSE;
  595.     case 0xf9:        /* Graphic Control Extension */
  596.         str = "Graphic Control Extension";
  597.         (void) GetDataBlock(fd, (unsigned char*) buf);
  598.         Gif89.disposal    = (buf[0] >> 2) & 0x7;
  599.         Gif89.inputFlag   = (buf[0] >> 1) & 0x1;
  600.         Gif89.delayTime   = LM_to_uint(buf[1],buf[2]);
  601.         if ((buf[0] & 0x1) != 0)
  602.             Gif89.transparent = buf[3];
  603.  
  604.         while (GetDataBlock(fd, (unsigned char*) buf) != 0)
  605.             ;
  606.         return FALSE;
  607.     default:
  608.         str = buf;
  609.         sprintf(buf, "UNKNOWN (0x%02x)", label);
  610.         break;
  611.     }
  612.  
  613.     pm_message("got a '%s' extension", str );
  614.  
  615.     while (GetDataBlock(fd, (unsigned char*) buf) != 0)
  616.         ;
  617.  
  618.     return FALSE;
  619. }
  620.  
  621. int    ZeroDataBlock = FALSE;
  622.  
  623. static int
  624. GetDataBlock(fd, buf)
  625. FILE        *fd;
  626. unsigned char     *buf;
  627. {
  628.     unsigned char    count;
  629.  
  630.     if (! ReadOK(fd,&count,1)) {
  631.         pm_message("error in getting DataBlock size" );
  632.         return -1;
  633.     }
  634.  
  635.     ZeroDataBlock = count == 0;
  636.     if ((count != 0) && (! ReadOK(fd, buf, count))) {
  637.         pm_message("error in reading DataBlock" );
  638.         return -1;
  639.     }
  640.  
  641.     return count;
  642. }
  643.  
  644. static int
  645. GetCode(fd, code_size, flag)
  646. FILE    *fd;
  647. int    code_size;
  648. int    flag;
  649. {
  650.     static unsigned char    buf[280];
  651.     static int        curbit, lastbit, done, last_byte;
  652.     int            i, j, ret;
  653.     unsigned char        count;
  654.  
  655.     if (flag) {
  656.         curbit = 0;
  657.         lastbit = 0;
  658.         done = FALSE;
  659.         return 0;
  660.     }
  661.  
  662.     if ( (curbit+code_size) >= lastbit) {
  663.         if (done) {
  664.             if (curbit >= lastbit)
  665.                 pm_error("ran off the end of my bits" );
  666.             return -1;
  667.         }
  668.         buf[0] = buf[last_byte-2];
  669.         buf[1] = buf[last_byte-1];
  670.  
  671.         if ((count = GetDataBlock(fd, &buf[2])) == 0)
  672.             done = TRUE;
  673.  
  674.         last_byte = 2 + count;
  675.         curbit = (curbit - lastbit) + 16;
  676.         lastbit = (2+count)*8 ;
  677.     }
  678.  
  679.     ret = 0;
  680.     for (i = curbit, j = 0; j < code_size; ++i, ++j)
  681.         ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
  682.  
  683.     curbit += code_size;
  684.  
  685.     return ret;
  686. }
  687.  
  688. static int
  689. LWZReadByte(fd, flag, input_code_size)
  690. FILE    *fd;
  691. int    flag;
  692. int    input_code_size;
  693. {
  694.     static int    fresh = FALSE;
  695.     int        code, incode;
  696.     static int    code_size, set_code_size;
  697.     static int    max_code, max_code_size;
  698.     static int    firstcode, oldcode;
  699.     static int    clear_code, end_code;
  700.     static int *table[2];
  701.     static int *stack, *sp;
  702.     register int    i;
  703.  
  704.     /*
  705.      *    Assign in the used to be static area as now pointers.
  706.      */
  707.     table[0] = ip_table1;
  708.     table[1] = ip_table0;
  709.     stack = ip_stack;
  710.  
  711.     if (flag) {
  712.         set_code_size = input_code_size;
  713.         code_size = set_code_size+1;
  714.         clear_code = 1 << set_code_size ;
  715.         end_code = clear_code + 1;
  716.         max_code_size = 2*clear_code;
  717.         max_code = clear_code+2;
  718.  
  719.         GetCode(fd, 0, TRUE);
  720.  
  721.         fresh = TRUE;
  722.  
  723.         for (i = 0; i < clear_code; ++i) {
  724.             table[0][i] = 0;
  725.             table[1][i] = i;
  726.         }
  727.  
  728.         table[1][0] = 0;
  729.         for (; i < (1<<MAX_LWZ_BITS); ++i)    {
  730.             table[0][i] = 0;
  731.         }
  732.  
  733.         sp = stack;
  734.  
  735.         return 0;
  736.     } else if (fresh) {
  737.         fresh = FALSE;
  738.  
  739.         do {
  740.             firstcode = oldcode =
  741.                 GetCode(fd, code_size, FALSE);
  742.         } while (firstcode == clear_code);
  743.  
  744.         return firstcode;
  745.     }
  746.  
  747.     if (sp > stack)    {
  748.         return *--sp;
  749.     }
  750.  
  751.     while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
  752.         if (code == clear_code) {
  753.             for (i = 0; i < clear_code; ++i) {
  754.                 table[0][i] = 0;
  755.                 table[1][i] = i;
  756.             }
  757.  
  758.             for (; i < (1<<MAX_LWZ_BITS); ++i)
  759.                 table[0][i] = table[1][i] = 0;
  760.             code_size = set_code_size+1;
  761.             max_code_size = 2*clear_code;
  762.             max_code = clear_code+2;
  763.             sp = stack;
  764.             firstcode = oldcode =
  765.                     GetCode(fd, code_size, FALSE);
  766.             return firstcode;
  767.         } else if (code == end_code) {
  768.             int        count;
  769.             unsigned char    buf[260];
  770.  
  771.             if (ZeroDataBlock)    {
  772.  
  773.                 return -2;
  774.             }
  775.  
  776.             while ((count = GetDataBlock(fd, buf)) > 0)
  777.                 ;
  778.  
  779.             if (count != 0)
  780.                 pm_message("missing EOD in data stream (common occurence)");
  781.             return -2;
  782.         }
  783.  
  784.         incode = code;
  785.  
  786.         if (code >= max_code) {
  787.             *sp++ = firstcode;
  788.             code = oldcode;
  789.         }
  790.  
  791.         while (code >= clear_code) {
  792.             *sp++ = table[1][code];
  793.             if (code == table[0][code])
  794.                 pm_error("circular table entry BIG ERROR");
  795.             code = table[0][code];
  796.         }
  797.  
  798.         *sp++ = firstcode = table[1][code];
  799.  
  800.         if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
  801.             table[0][code] = oldcode;
  802.             table[1][code] = firstcode;
  803.             ++max_code;
  804.  
  805.             if ((max_code >= max_code_size) &&
  806.                 (max_code_size < (1<<MAX_LWZ_BITS))) {
  807.                 max_code_size *= 2;
  808.                 ++code_size;
  809.             }
  810.         }
  811.  
  812.         oldcode = incode;
  813.  
  814.         if (sp > stack)    {
  815.             return *--sp;
  816.         }
  817.  
  818.     }
  819.  
  820.     return code;
  821. }
  822.  
  823. int cmpcolors(const void *v1, const void *v2) {
  824.     int cid1 = *(int*)v1;
  825.   int cid2 = *(int*)v2;
  826.   return (hist[cid1] < hist[cid2]);
  827. }
  828.  
  829. int color_d = 0;
  830. int *pflags;
  831.  
  832. static int
  833. DisplayImage(fd, len, height, maxcolors, cmap, interlace, ignore)
  834. FILE    *fd;
  835. int    len, height;
  836. int maxcolors;
  837. unsigned char    cmap[3][MYMAXCOLORS];
  838. int    interlace, ignore;
  839. {
  840.     unsigned char    c;
  841.   int r, g, b;
  842.   int all_colors = 0;
  843.   int dither_colors = 0;
  844.   int ra, ga, ba;
  845.     int        v;
  846.     int        xpos = 0, ypos = 0, pass = 0;
  847.   int vxpos = 0, vypos = 0;
  848.   long fpos;
  849.   int i;
  850.   float lastacc;
  851.   float xacc = 0.0;
  852.   float yacc = 0.0;
  853.   float sf = 1.0;
  854.   int xs;
  855.   int ys;
  856.   int vydup = 1;
  857.  
  858.     fpos = ftell(fd);
  859.   foundtotal = 0;
  860.   if (maxcolors <= colorsavail) {
  861.     for (i=0; (i<maxcolors); i++) {
  862.     foundcolors[i] = i;
  863.     }
  864.     foundtotal = maxcolors;
  865.   } else {
  866.     printf("Counting colors...\n");
  867.       HistImage(fd, len, height, cmap, interlace, ignore, hist, &mc_color);
  868.     cleardevice();
  869.   }
  870.   if (foundtotal <= colorsavail) {
  871.     all_colors = 1;
  872.     for (i=0; (i<foundtotal); i++) {
  873.             vtoc[foundcolors[i]] = i;
  874.     ctable[i].r = cmap[0][foundcolors[i]];
  875.     ctable[i].g = cmap[1][foundcolors[i]];
  876.     ctable[i].b = cmap[2][foundcolors[i]];
  877.     setp(i, ctable[i]);
  878.     }
  879.   } else if (colorsavail >= 8) {
  880.     i = 0;
  881.     dither_colors = 1;
  882.         for (r = 0; (r < 2); r++) {
  883.         for (g = 0; (g < 2); g++) {
  884.         for (b = 0; (b < 2); b++) {
  885.         ctable[i].r = r * 0xff;
  886.         ctable[i].g = g * 0xff;
  887.         ctable[i].b = b * 0xff;
  888.                     setp(i, ctable[i]);
  889.         i++;
  890.             }
  891.         }
  892.     }
  893.     if (colorsavail >= 16) {
  894.     /* Half-intensity colors */
  895.     dither_colors = 2;
  896.             for (r = 0; (r < 2); r++) {
  897.             for (g = 0; (g < 2); g++) {
  898.             for (b = 0; (b < 2); b++) {
  899.             ctable[i].r = r * 0x80;
  900.             ctable[i].g = g * 0x80;
  901.             ctable[i].b = b * 0x80;
  902.                         setp(i, ctable[i]);
  903.             i++;
  904.                 }
  905.         }
  906.       }
  907.     }
  908.  
  909.   }
  910.   if (!all_colors) {
  911.     /* Blow it up to give the dithering a better chance;
  912.     it'll be knocked down below if this makes it too big */
  913.     sf *= 3;
  914.   }
  915.   if (mode_aspect > 1.0) {
  916.     /* Blow it up to avoid loss of pixels on y axis; again,
  917.     code below will knock this back down if necessary */
  918.     sf *= mode_aspect;
  919.   }
  920.   xs = getmaxx()+1;
  921.   ys = getmaxy()+1;
  922.  
  923.   xvector = (int *) malloc(sizeof(int) * (size_t)((size_t)len+(size_t)2));
  924.   if (!xvector) {
  925.     pm_error("Out of memory\n");
  926.     return -1;
  927.   }
  928.   yvector = (int *) malloc(sizeof(int) * (size_t)((size_t)height+(size_t)2));
  929.   if(!yvector)    {
  930.     pm_error("Out of memory\n");
  931.     return(-1);
  932.   }
  933.  
  934.   pflags = (int *) malloc(sizeof(int) * (size_t)ys);
  935.   if(!pflags)    {
  936.     pm_error("Out of memory\n");
  937.     return(-1);
  938.   }
  939.  
  940.   for (i=0; (i<ys); i++) {
  941.     pflags[i] = 0;
  942.   }
  943.   if (len*sf > xs) {
  944.     sf = (float)xs / len;
  945.   }
  946.   if (height*sf > ys * mode_aspect) {
  947.     sf = (float)ys * mode_aspect / height;
  948.   }
  949.   lastacc = 0;
  950.     for (i=0; (i<len); i++) {
  951.     float diff;
  952.     xacc = sf*(i+1);
  953.     diff = floor(xacc)-floor(lastacc);
  954.     xvector[i] = (int) diff;
  955.     lastacc = xacc;
  956.   }
  957.   lastacc = 0;
  958.     for (i=0; (i<height); i++) {
  959.     float diff;
  960.     yacc = sf*(i+1)/mode_aspect;
  961.     diff = floor(yacc)-floor(lastacc);
  962.     yvector[i] = (int) diff;
  963.     lastacc = yacc;
  964.   }
  965. #ifdef SVGA
  966.   if (svga_flag) {
  967.     setvgapalette256(&pal256);
  968.   }
  969. #endif /* SVGA */
  970.   fseek(fd, fpos, SEEK_SET);
  971.     /*
  972.     **  Initialize the Compression routines
  973.     */
  974.     if (! ReadOK(fd,&c,1)) {
  975.         pm_error("EOF / read error on image data" );
  976.     return -1;
  977.   }
  978.     if (LWZReadByte(fd, TRUE, c) < 0) {
  979.         pm_error("error reading image" );
  980.     return -1;
  981.   }
  982.  
  983.     /*
  984.     **  If this is an "uninteresting picture" ignore it.
  985.     */
  986.     if (ignore) {
  987.         if (verbose)
  988.             pm_message("skipping image..." );
  989.  
  990.         while (LWZReadByte(fd, FALSE, c) >= 0)
  991.             ;
  992.         return 0;
  993.     }
  994.     if (verbose)
  995.         pm_message("reading %d by %d%s GIF image",
  996.             len, height, interlace ? " interlaced" : "" );
  997.   ra = random(256);
  998.   ga = random(256);
  999.   ba = random(256);
  1000.   vydup = 1;
  1001.     while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
  1002.     int y;
  1003.     if (yvector[ypos] && (!pflags[vypos])) {
  1004.       for (i=0; (i<xvector[xpos]); i++) {
  1005.                 if (all_colors) {
  1006.       int y;
  1007.       for (y=vypos; (y < vypos+vydup); y++) {
  1008.                    putpixel(vxpos, y, vtoc[v]);
  1009.       }
  1010.         vxpos++;
  1011.             } else if (dither_colors) {
  1012.         int high;
  1013.       int shift = 0;
  1014.       int rf, gf, bf;
  1015.       rf = cmap[CM_RED][v];
  1016.       gf = cmap[CM_GREEN][v];
  1017.       bf = cmap[CM_BLUE][v];
  1018.                 ra += rf;
  1019.                 ga += gf;
  1020.                 ba += bf;
  1021.       high = max(max(rf, gf), bf);
  1022.       if ((dither_colors == 2) && (high <= 0x80)) {
  1023.         shift = 8;
  1024.                     if (ra >= 128) {
  1025.                             ra -= 128;
  1026.                     r = 4;
  1027.                     } else {
  1028.                         r = 0;
  1029.                     }
  1030.                     if (ga >= 128) {
  1031.                         ga -= 128;
  1032.                     g = 2;
  1033.                     } else {
  1034.                         g = 0;
  1035.                     }
  1036.                     if (ba >= 128) {
  1037.                         ba -= 128;
  1038.                     b = 1;
  1039.                     } else {
  1040.                         b = 0;
  1041.                     }
  1042.       } else {
  1043.                     if (ra >= 255) {
  1044.                             ra -= 255;
  1045.                     r = 4;
  1046.                     } else {
  1047.                         r = 0;
  1048.                     }
  1049.                     if (ga >= 255) {
  1050.                         ga -= 255;
  1051.                     g = 2;
  1052.                     } else {
  1053.                         g = 0;
  1054.                     }
  1055.                     if (ba >= 255) {
  1056.                         ba -= 255;
  1057.                     b = 1;
  1058.                     } else {
  1059.                         b = 0;
  1060.                     }
  1061.       }
  1062.       for (y=vypos; (y < vypos+vydup); y++) {
  1063.                 putpixel(vxpos, y, color_d+r+g+b+shift);
  1064.       }
  1065.         vxpos++;
  1066.             } else {
  1067.         /* Dither black and white */
  1068.       int l = cmap[CM_RED][v] + cmap[CM_GREEN][v] + cmap[CM_BLUE][v];
  1069.       l /= 3;
  1070.       ra += l;
  1071.       if (ra >= 255) {
  1072.         ra -= 255;
  1073.         r = 1;
  1074.       } else {
  1075.         r = 0;
  1076.       }
  1077.       for (y=vypos; (y < vypos+vydup); y++) {
  1078.                 putpixel(vxpos, y, r);
  1079.       }
  1080.       vxpos++;
  1081.     }
  1082.       }
  1083.     }
  1084.         ++xpos;
  1085.         if (xpos == len) {
  1086.     vxpos = 0;
  1087.             xpos = 0;
  1088.       if (yvector[ypos]) {
  1089.     pflags[vypos] = 1;
  1090.       }
  1091.           ra = random(256);
  1092.           ga = random(256);
  1093.           ba = random(256);
  1094.             if (interlace) {
  1095.                 switch (pass) {
  1096.                 case 0:
  1097.                 case 1:
  1098.                     ypos += 8; break;
  1099.                 case 2:
  1100.                     ypos += 4; break;
  1101.                 case 3:
  1102.                     ypos += 2; break;
  1103.                 }
  1104.  
  1105.                 if (ypos >= height) {
  1106.                     ++pass;
  1107.                     switch (pass) {
  1108.                     case 1:
  1109.                         ypos = 4; break;
  1110.                     case 2:
  1111.                         ypos = 2; break;
  1112.                     case 3:
  1113.                         ypos = 1; break;
  1114.                     default:
  1115.                         goto fini;
  1116.                     }
  1117.                 }
  1118.             } else {
  1119.                 ++ypos;
  1120.             }
  1121.       vypos = ypos * sf / mode_aspect;
  1122.       /* Fudge to avoid inevitable streaks */
  1123.             vydup = yvector[ypos]+1;
  1124.         }
  1125.         if (ypos >= height)
  1126.             break;
  1127.     }
  1128.  
  1129. fini:
  1130.     if (LWZReadByte(fd,FALSE,c)>=0)
  1131.         pm_message("too much input data, ignoring extra...");
  1132.     free(xvector);
  1133.   free(yvector);
  1134.   free(pflags);
  1135.     return 0;
  1136. }
  1137.  
  1138. static int
  1139. HistImage(fd, len, height, cmap, interlace, ignore, hist, mc_color)
  1140. FILE    *fd;
  1141. int    len, height;
  1142. unsigned char    cmap[3][MYMAXCOLORS];
  1143. int    interlace, ignore;
  1144. long hist[MYMAXCOLORS];
  1145. int *mc_color;
  1146. {
  1147.     unsigned char    c;
  1148.     int        v;
  1149.     int i;
  1150.  
  1151.     for (i=0; (i<MYMAXCOLORS); i++) {
  1152.         hist[i] = 0;
  1153.     }
  1154.  
  1155.     /*
  1156.     **  Initialize the Compression routines
  1157.     */
  1158.     if (! ReadOK(fd,&c,1)) {
  1159.         pm_error("EOF / read error on image data" );
  1160.         return -1;
  1161.     }
  1162.  
  1163.     if (LWZReadByte(fd, TRUE, c) < 0) {
  1164.         pm_error("error reading image" );
  1165.         return -1;
  1166.     }
  1167.  
  1168.     /*
  1169.     **  If this is an "uninteresting picture" ignore it.
  1170.     */
  1171.     if (ignore) {
  1172.         if (verbose)
  1173.             pm_message("skipping image..." );
  1174.  
  1175.         while (LWZReadByte(fd, FALSE, c) >= 0)
  1176.             ;
  1177.         return 0;
  1178.     }
  1179.     if (verbose)
  1180.         pm_message("reading %d by %d%s GIF image",
  1181.             len, height, interlace ? " interlaced" : "" );
  1182.  
  1183.     while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
  1184.         if (!hist[v]) {
  1185.             foundcolors[foundtotal++] = v;
  1186.         }
  1187.         hist[v]++;
  1188.         if (hist[v] > hist[*mc_color]) {
  1189.             *mc_color = v;
  1190.         }
  1191.     }
  1192.     return 0;
  1193. }
  1194.  
  1195. #ifdef SVGA
  1196. int huge DetectVGA256()
  1197. {
  1198.   return svga_mode_choice;
  1199. }
  1200. #endif /* SVGA */
  1201.