home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / formats / gif / gen_code / gifasm.arc / CLIPGIF.C next >
Encoding:
C/C++ Source or Header  |  1988-10-22  |  10.1 KB  |  462 lines

  1. /* CLIPGIF.c - Clip and re-encode GIF files
  2.  
  3.    Written by Steve Becquer (74155,767)
  4.  
  5.    Version 1.01 last revised 10/22/88
  6.  
  7.    GIF and 'Graphics Interchange Format' are trademarks (tm) of
  8.    CompuServe Incorporated, an H&R Block Company  */
  9.  
  10. #include <stdio.h>
  11. #include <conio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include <malloc.h>
  16.  
  17. #define MAXSTRLEN    255
  18. #define EOS           0
  19. #define TRUE          -1
  20. #define FALSE           0
  21.  
  22. extern int Decompress(unsigned int,int (*)(),void (*)(unsigned int));
  23. extern int Compress(unsigned int,int (*)(),void (*)(unsigned int));
  24.  
  25. unsigned char InFile[MAXSTRLEN];
  26. FILE *InGIF;
  27. unsigned char OutFile[MAXSTRLEN];
  28. FILE *OutGIF;
  29.  
  30. unsigned int width, height, left, top, iwidth, iheight;
  31. unsigned int newwidth, newheight, newleft, newtop, newiwidth, newiheight;
  32. unsigned int interlaced, relace, image;
  33.  
  34. int block_count, block_offset;
  35. unsigned char buffer[256];
  36.  
  37. unsigned char far **GIF_buf;
  38. unsigned char far *rsv_buf;
  39.  
  40. unsigned int pass, line, line_offset, last_line, eom;
  41. unsigned line_inc[5] = {8,8,4,2,0};
  42. unsigned line_start[5] = {0,4,2,1,0};
  43.  
  44. long pTimer()
  45. {
  46.    long far *clock_count = (long far *) 0x046C;
  47.  
  48.    return(*clock_count);
  49. }
  50.  
  51. void Upper(string)
  52. char *string;
  53. {
  54.  
  55.    while (*string != EOS) {
  56.       *string = islower(*string) ? toupper(*string) : *string;
  57.       string++;
  58.    }
  59. }
  60.  
  61. unsigned int Aski(string,deflt)
  62. unsigned char *string;
  63. unsigned int deflt;
  64. {
  65.    unsigned char avalue[MAXSTRLEN];
  66.    int temp;
  67.  
  68.    printf(string);
  69.    gets(avalue);
  70.    if (avalue[0] == EOS)
  71.       return(deflt);
  72.    temp = atoi(avalue);
  73.    if (temp < 0)
  74.       return(deflt);
  75.    else
  76.       return(temp);
  77. }
  78.  
  79. unsigned int Askyn(string,deflt)
  80. unsigned char *string;
  81. unsigned int deflt;
  82. {
  83.    unsigned char avalue[MAXSTRLEN];
  84.    int temp;
  85.  
  86.    printf(string);
  87.    gets(avalue);
  88.    if (avalue[0] == EOS)
  89.       return(deflt);
  90.    if (avalue[0] == 'Y' || avalue[0] == 'y')
  91.       return(TRUE);
  92.    if (avalue[0] == 'N' || avalue[0] == 'n')
  93.       return(FALSE);
  94.    return(deflt);
  95. }
  96.  
  97. unsigned int Getword()
  98. {
  99.  
  100.    return(fgetc(InGIF) | (fgetc(InGIF) << 8));
  101. }
  102.  
  103. void Putword(wvalue)
  104. unsigned int wvalue;
  105. {
  106.    int temp;
  107.  
  108.    temp = fputc(wvalue,OutGIF);
  109.    temp = fputc((wvalue >> 8),OutGIF);
  110. }
  111.  
  112. unsigned char Getbyte()
  113. {
  114.  
  115.    return(fgetc(InGIF));
  116. }
  117.  
  118. void Putbyte(bvalue)
  119. unsigned char bvalue;
  120. {
  121.    int temp;
  122.  
  123.    temp = fputc(bvalue,OutGIF);
  124. }
  125.  
  126. void Get_buf(y)
  127. int y;
  128. {
  129.    if (GIF_buf[y] == NULL) {
  130.       GIF_buf[y] = (unsigned char far *) _fmalloc(newwidth);
  131.       if (GIF_buf[y] == NULL) {
  132.      GIF_buf[y] = GIF_buf[last_line];
  133.      eom = TRUE;
  134.       }
  135.       else
  136.      last_line = y;
  137.    }
  138. }
  139.  
  140. int Get_raster_byte()
  141. {
  142.    int byte, temp;
  143.  
  144.    if (block_count == 0) {
  145.       block_count = fgetc(InGIF);
  146.       if (block_count == 0)
  147.      return(-1);
  148.       temp = fread(buffer,1,block_count,InGIF);
  149.       block_offset = 0;
  150.    }
  151.    byte = buffer[block_offset++];
  152.    block_count--;
  153.    return(byte);
  154. }
  155.  
  156. void Put_raster_byte(byte)
  157. unsigned int byte;
  158. {
  159.    int temp;
  160.  
  161.    if (block_count == 255) {
  162.       buffer[0] = block_count;
  163.       temp = fwrite(buffer,1,256,OutGIF);
  164.       block_count = 0;
  165.    }
  166.    buffer[++block_count] = byte;
  167. }
  168.  
  169. int Get_pixel()
  170. {
  171.  
  172.    if (line_offset >= newiwidth) {
  173.       line_offset = 0;
  174.       if (relace) {
  175.      line += line_inc[pass];
  176.      if (line >= newiheight)
  177.         if (++pass > 3)
  178.            return(-1);
  179.         else
  180.            line = line_start[pass];
  181.       }
  182.       else
  183.      if (++line >= newiheight)
  184.         return(-1);
  185.    }
  186.    return(GIF_buf[line][line_offset++]);
  187. }
  188.  
  189. void Put_pixel(pixel)
  190. unsigned int pixel;
  191. {
  192.  
  193.    if (pass > 3)
  194.       return;
  195.    if (line_offset >= iwidth) {
  196.       line_offset = 0;
  197.       if (interlaced) {
  198.      line += line_inc[pass];
  199.      if (line >= iheight) {
  200.         line = line_start[++pass];
  201.         if (pass > 3)
  202.            return;
  203.      }
  204.       }
  205.       else
  206.      if (++line >= iheight) {
  207.         pass = 4;
  208.         return;
  209.      }
  210.       if (line < newiheight)
  211.      Get_buf(line);
  212.    }
  213.    if (line < newiheight && line_offset < newiwidth)
  214.       GIF_buf[line][line_offset] = pixel;
  215.    line_offset++;
  216. }
  217.  
  218. void Flush()
  219. {
  220.    int i, temp;
  221.  
  222.    if (block_count != 0) {
  223.       buffer[0] = block_count;
  224.       temp = fwrite(buffer,1,block_count+1,OutGIF);
  225.    }
  226. }
  227.  
  228. void PrintHelp()
  229. {
  230.  
  231.    puts("\nThis program can be used to clip and re-encode GIF files.");
  232.    puts("You will be prompted for new GIF parameter values.  Enter");
  233.    puts("new value or hit enter to maintain old value.");
  234.    puts("\nUsage:  CLIPGIF [drive:][path][infile] [drive:][path][outfile]");
  235.    puts("      infile ........ Input GIF file (extension defaults to .GIF)");
  236.    puts("      outfile ....... Output GIF file (extension defaults to .GIF)");
  237. }
  238.  
  239. void Signature()
  240. {
  241.    int i, temp;
  242.    unsigned char signature[6];
  243.  
  244.    for (i=0; i<6; i++)
  245.       signature[i] = fgetc(InGIF);
  246.    signature[i] = '\0';
  247.    if (strncmp(signature,"GIF87a",6)) {
  248.       printf("\n%s is not a valid GIF file\n",InFile);
  249.       exit(1);
  250.    }
  251.    temp = fputs(signature,OutGIF);
  252. }
  253.  
  254. void ScreenDescriptor()
  255. {
  256.    unsigned char avalue[MAXSTRLEN], byte;
  257.    int i, gcm, colors;
  258.  
  259.    width = Getword();
  260.    printf("\nScreen width: %d\n",width);
  261.    height = Getword();
  262.    printf("Screen height: %d\n",height);
  263.    newwidth = Aski("\nEnter new screen width: ",width);
  264.    while (newwidth > width)
  265.       newwidth = Aski("New screen width to large, renter: ",width);
  266.    Putword(newwidth);
  267.    newheight = Aski("Enter new screen height: ",height);
  268.    while (newheight > height)
  269.       newheight = Aski("New screen height to large, renter: ",height);
  270.    Putword(newheight);
  271.    byte = Getbyte();
  272.    gcm = byte & 0x80;
  273.    colors = 1 << ((byte & 0x07) + 1);
  274.    Putbyte(byte);
  275.    Putbyte(Getbyte());
  276.    Putbyte(Getbyte());
  277.    if (gcm)
  278.       for (i=0; i<colors; i++) {
  279.      Putbyte(Getbyte());
  280.      Putbyte(Getbyte());
  281.      Putbyte(Getbyte());
  282.       }
  283. }
  284.  
  285. void SkipImage()
  286. {
  287.    int i, lcm, colors;
  288.    unsigned char byte;
  289.  
  290.    for (i=0; i<8; i++)
  291.       byte = Getbyte();
  292.    colors = 1 << ((byte & 0x07) + 1);
  293.    byte = Getbyte();
  294.    lcm = byte & 0x80;
  295.    colors = 1 << ((byte & 0x07) + 1);
  296.    if (lcm)
  297.       for (i=0; i<colors; i++) {
  298.      byte = Getbyte();
  299.      byte = Getbyte();
  300.      byte = Getbyte();
  301.       }
  302.    byte = Getbyte();
  303.    while ((i = Get_raster_byte()) >= 0);
  304. }
  305.  
  306. void ImageDescriptor()
  307. {
  308.    unsigned char avalue[MAXSTRLEN], byte;
  309.    int i, lcm, colors, codesize, status;
  310.  
  311.    printf("\nImage descriptor %d found\n",++image);
  312.    i = Askyn("\nDiscard this image? ",FALSE);
  313.    if (i) {
  314.       SkipImage();
  315.       return;
  316.    }
  317.    Putbyte(',');
  318.    left = Getword();
  319.    printf("\nImage left: %d\n",left);
  320.    top = Getword();
  321.    printf("\Image top: %d\n",top);
  322.    iwidth = Getword();
  323.    printf("\Image width: %d\n",width);
  324.    iheight = Getword();
  325.    printf("\Image height: %d\n",height);
  326.    newleft = Aski("\nEnter new image left: ",left);
  327.    Putword(newleft);
  328.    newtop = Aski("Enter new image top: ",top);
  329.    Putword(newtop);
  330.    newiwidth = Aski("Enter new image width: ",iwidth);
  331.    while (newiwidth > newwidth)
  332.       newiwidth = Aski("New image width to large, renter: ",iwidth);
  333.    Putword(newiwidth);
  334.    newiheight = Aski("Enter new image height: ",iheight);
  335.    while (newiheight > newheight)
  336.       newiwidth = Aski("New image height to large, renter: ",iheight);
  337.    Putword(newiheight);
  338.    byte = Getbyte();
  339.    lcm = byte & 0x80;
  340.    interlaced = byte & 0x40;
  341.    if (interlaced)
  342.       relace = !Askyn("\nImage is interlaced, make it sequential? ",FALSE);
  343.    else
  344.       relace = Askyn("\nImage is sequential, make it interlaced? ",FALSE);
  345.    if (relace)
  346.       byte |= 0x40;
  347.    else
  348.       byte &= 0xBF;
  349.    Putbyte(byte);
  350.    colors = 1 << ((byte & 0x07) + 1);
  351.    if (lcm)
  352.       for (i=0; i<colors; i++) {
  353.      Putbyte(Getbyte());
  354.      Putbyte(Getbyte());
  355.      Putbyte(Getbyte());
  356.       }
  357.    codesize = Getbyte();
  358.    Putbyte(codesize);
  359.    block_count = 0;
  360.    line = 0;
  361.    line_offset = 0;
  362.    pass = 0;
  363.    eom = FALSE;
  364.    Get_buf(0);
  365.    status = Decompress(codesize,Get_raster_byte,Put_pixel);
  366.    if (status) {
  367.       puts("\nError in Decompress routine");
  368.       exit(1);
  369.    }
  370.    if (eom)
  371.       puts("\nMemory was exhausted, possible incomplete image");
  372.    block_count = 0;
  373.    line = 0;
  374.    line_offset = 0;
  375.    pass = 0;
  376.    status = Compress(codesize,Get_pixel,Put_raster_byte);
  377.    if (status) {
  378.       puts("\nError in Compress routine");
  379.       exit(1);
  380.    }
  381.    Flush();
  382.    Putbyte(0x00);
  383. }
  384.  
  385. void ExtensionBlock()
  386. {
  387.    int i, j;
  388.  
  389.    Putbyte('!');
  390.    Putbyte(Getbyte());
  391.    while (i = Getbyte()) {
  392.       Putbyte(i);
  393.       for (j=0; j<i; j++)
  394.      Putbyte(Getbyte());
  395.    }
  396.    Putbyte(0x00);
  397. }
  398.  
  399. main(argc,argv)
  400. int argc;
  401. char *argv[];
  402. {
  403.    int i, done = FALSE, separator;
  404.  
  405.    puts("\nCLIPGIF Version 1.01 - Clip and re-encode GIF files");
  406.    if (argc < 3)
  407.       PrintHelp();
  408.    puts("\nGIF and 'Graphics Interchange Format' are trademarks (tm)");
  409.    puts("of CompuServe Incorporated, an H&R Block Company");
  410.    if (argc < 3)
  411.       exit(0);
  412.  
  413.    strcpy(InFile,argv[1]);
  414.    Upper(InFile);
  415.    if (strchr(InFile,'.') == NULL)
  416.       strcat(InFile,".GIF");
  417.    strcpy(OutFile,argv[2]);
  418.    Upper(OutFile);
  419.    if (strchr(OutFile,'.') == NULL)
  420.       strcat(OutFile,".GIF");
  421.    if ((InGIF = fopen(InFile,"rb")) == NULL) {
  422.       printf("\nCan't open input file %s\n",InFile);
  423.       exit(1);
  424.    }
  425.    if ((OutGIF = fopen(OutFile,"wb")) == NULL) {
  426.       printf("\nCan't open output file %s\n",InFile);
  427.       exit(1);
  428.    }
  429.  
  430.    Signature();
  431.    ScreenDescriptor();
  432.    GIF_buf = (unsigned char far **) malloc(newheight*sizeof(char far *));
  433.    if (GIF_buf == NULL) {
  434.       puts("\nNot enough memory to run CLIPGIF");
  435.       exit(1);
  436.    }
  437.    for (i=0; i<newheight; i++)
  438.       GIF_buf[i] = NULL;
  439.    while (!done && ((separator = fgetc(InGIF)) != EOF)) {
  440.       switch (separator) {
  441.      case ',': {
  442.         ImageDescriptor();
  443.         break;
  444.      }
  445.  
  446.      case '!': {
  447.         ExtensionBlock();
  448.         break;
  449.      }
  450.  
  451.      case ';': {
  452.         Putbyte(';');
  453.         done = TRUE;
  454.         break;
  455.      }
  456.       }
  457.    }
  458.  
  459.    fclose(InGIF);
  460.    fclose(OutGIF);
  461. }
  462.