home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / graphics / utilities / gifmachine_458 / sources / main.c < prev    next >
C/C++ Source or Header  |  1991-02-15  |  11KB  |  492 lines

  1. /* Copyright 1990 by Christopher A. Wichura.
  2.    See file GIFMachine.doc for full description of rights.
  3. */
  4.  
  5. #include "GIFMachine.h"
  6. #include <dos/rdargs.h>
  7. #include <dos/dosasl.h>
  8. #include <dos/stdio.h>
  9. #include <workbench/startup.h>
  10.  
  11. struct GIFdescriptor gdesc;
  12.  
  13. struct RGB **BitPlane;
  14. struct RGB GlobalColourTable[256];
  15.  
  16. extern UWORD *SHAMmem;
  17.  
  18. extern BYTE *PlaneBuf;
  19.  
  20. extern BOOL Laced;
  21.  
  22. extern UBYTE *Planes[24];
  23.  
  24. ULONG ImageNumber;
  25.  
  26. extern struct MinList CommentList;
  27.  
  28. /* indicates which memory list to allocate from */
  29. extern UWORD CurrentMem;
  30.  
  31. /* the current GIF file handle */
  32. BPTR GIFfh = NULL;
  33.  
  34. /* here we have some defines relating to our GADS call */
  35. #define ESC "\x9B"
  36. #define GIFMACH ESC "33;42mGIFMachine" ESC "32;40m"
  37.  
  38. #define ARG_TEMPLATE "GIFfiles/M/A,TO/K,ALL/S,NOBORDER/K/N,XCOMP/S,DITHER/S,XFLIP/s,YFLIP/s,DEEP/S,BUFSIZE/K/N"
  39. #define ARG_FILES  0
  40. #define ARG_TO     1
  41. #define ARG_ALL    2
  42. #define ARG_NOBORD 3
  43. #define ARG_XCOMP  4
  44. #define ARG_DITHER 5
  45. #define ARG_FLIPX  6
  46. #define ARG_FLIPY  7
  47. #define ARG_DEEP   8
  48. #define ARG_BUFSIZ 9
  49. #define ARG_sizeof 10
  50.  
  51. /* we will make the argument array global so that other modules can get at
  52.    the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
  53. struct RDArgs *ArgsPtr;
  54. char *ArgArray[ARG_sizeof];
  55. BOOL ArgToIsDir;
  56.  
  57. /* size of the read buffered i/o space */
  58. static ULONG BufSize = 2048;    /* default size is 2k */
  59.  
  60. int NoBorderLineThresh = 0;
  61.  
  62. /* some mem pointers used when we do dithering */
  63. BYTE *CurrentLineErr[3];
  64. BYTE *LastLineErr[3];
  65.  
  66. /* this flag says if we scaled the image */
  67. BOOL DidXComp;
  68.  
  69. /* we print this when the user hits the break key */
  70. char *AbortMsg = "*** User Interruption!\n";
  71.  
  72. /* storage for our library bases */
  73. struct Library *MathIeeeDoubBasBase = NULL;
  74. struct Library *IFFParseBase = NULL;
  75.  
  76. /* storage for our anchor when looking for pattern matches */
  77. struct Anchor {
  78.         struct AnchorPath APath;
  79.         char              Path[256];
  80.     } *anchor = NULL;
  81.  
  82. /* here we have our main routine */
  83. int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
  84. {
  85.     register char **FilesPtr;
  86.     struct RDArgs MyArgs;
  87.     extern UBYTE __far arg_help[];
  88.     extern UBYTE __far VersionID[];
  89.  
  90.     InitMemory();
  91.  
  92.     if (WBMsg) {
  93.         WarnMustUseCLI();
  94.         MyExit(5);
  95.     }
  96.  
  97.     if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 0))) {
  98.         MyPrintf("Unable to access %s!\n", "mathieeedoubbas.library");
  99.         MyExit(5);
  100.     }
  101.  
  102.     if (!(IFFParseBase = OpenLibrary("iffparse.library", 0))) {
  103.         MyPrintf("Unable to access %s!\n", "iffparse.library");
  104.         MyExit(5);
  105.     }
  106.  
  107.     memset ((char *)&MyArgs, 0, sizeof(struct RDArgs));
  108.  
  109.     if (!(MyArgs.RDA_ExtHelp = (UBYTE *)MyAlloc(strlen(arg_help) + (2 * strlen(GIFMACH)) + strlen(VersionID) + 1))) {
  110.         PutStr("Out of memory!\n");
  111.         MyExit(5);
  112.     }
  113.  
  114.     MySPrintf((char *)MyArgs.RDA_ExtHelp, arg_help, GIFMACH, VersionID, GIFMACH);
  115.  
  116.     if (!(ArgsPtr = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, &MyArgs))) {
  117.         PrintFault(IoErr(), NULL);
  118.         MyExit(5);
  119.     }
  120.  
  121.     MyFree((char *)MyArgs.RDA_ExtHelp);
  122.  
  123.     if (ArgArray[ARG_TO])
  124.         ArgToIsDir = IsDir(ArgArray[ARG_TO]);
  125.  
  126.     if (ArgArray[ARG_NOBORD]) {
  127.         NoBorderLineThresh = *((LONG *)ArgArray[ARG_NOBORD]);
  128.         if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
  129.             PutStr("Invalid NOBORDER line threshhold specified.\n");
  130.             MyExit(3);
  131.         }
  132.     }
  133.  
  134.     if (ArgArray[ARG_BUFSIZ])
  135.         BufSize = *((LONG *)ArgArray[ARG_BUFSIZ]) * 1024;
  136.  
  137.     if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
  138.         PutStr("No GIF files selected.\n");
  139.         MyExit(3);
  140.     }
  141.  
  142.     InitDiff();    /* one time init for the RGBdiff function */
  143.  
  144.     while (*FilesPtr)
  145.         DoPattern(*FilesPtr++);
  146.  
  147.     MyExit(0);
  148. }
  149.  
  150. void MyExit(ULONG result)
  151. {
  152.     if (GIFfh)
  153.         Close(GIFfh);
  154.  
  155.     if (IFFParseBase)
  156.         CloseLibrary(IFFParseBase);
  157.  
  158.     if (MathIeeeDoubBasBase)
  159.         CloseLibrary(MathIeeeDoubBasBase);
  160.  
  161.     if (anchor)
  162.         MatchEnd(&anchor->APath);
  163.  
  164.     if (ArgsPtr)
  165.         FreeArgs(ArgsPtr);
  166.  
  167.     FreeAll(1);
  168.     FreeAll(0);
  169.  
  170.     XCEXIT(result);
  171. }
  172.  
  173.  
  174. /* this will walk through a pattern doing conversions */
  175. void DoPattern(char *pat)
  176. {
  177.     register int error;
  178.  
  179.     if (!(anchor = (struct Anchor *)MyAlloc(sizeof(struct Anchor)))) {
  180.         PutStr("Out of memory!\n");
  181.         MyExit(10);
  182.     }
  183.  
  184.     anchor->APath.ap_Strlen = sizeof(anchor->Path);
  185.     anchor->APath.ap_Flags = APF_DOWILD;
  186.     anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
  187.  
  188.     error = MatchFirst(pat, &anchor->APath);
  189.  
  190.     while (!error) {
  191.         if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
  192.             if (ArgArray[ARG_ALL]) {
  193.                 if (!(anchor->APath.ap_Flags & APF_DIDDIR))
  194.                     anchor->APath.ap_Flags |= APF_DODIR;
  195.                 anchor->APath.ap_Flags &= ~APF_DIDDIR;
  196.             }
  197.         } else
  198.             Convert(anchor->APath.ap_Buf);
  199.  
  200.         error = MatchNext(&anchor->APath);
  201.     }
  202.  
  203.     MatchEnd(&anchor->APath);
  204.     MyFree((char *)anchor);
  205.     anchor = NULL;
  206.  
  207.     switch(error) {
  208.         case ERROR_BREAK:
  209.             PutStr(AbortMsg);
  210.             MyExit(ABORTEXITVAL);
  211.             break;
  212.  
  213.         case ERROR_OBJECT_NOT_FOUND:
  214.             PutStr("File not found.\n");
  215.             break;
  216.  
  217.         case ERROR_BUFFER_OVERFLOW:
  218.             PutStr("Path too long!\n");
  219.             break;
  220.  
  221.         case ERROR_NO_MORE_ENTRIES:    /* normal termination */
  222.             break;
  223.  
  224.         default:
  225.             MyPrintf("I/O Error #%ld!\n", error);
  226.             break;
  227.     }
  228. }
  229.  
  230. /* here we have the routine that gets ready to do the conversion */
  231. void Convert(char *name)
  232. {
  233.     register int index;
  234.     char *basename;
  235.     char *ptr;
  236.     char sig[7];
  237.     int size;
  238.     int error;
  239.     int colours;
  240.     LONG cmdcode;
  241.     
  242.     struct DateStamp StartTime, EndTime;
  243.  
  244.     CurrentMem++;
  245.  
  246.     if (!(GIFfh = Open(name, MODE_OLDFILE))) {
  247.         MyPrintf("Error #%ld trying to open %s...\n", IoErr(), name);
  248.         goto LeaveConvert;
  249.     }
  250.  
  251.     SetVBuf(GIFfh, BUF_FULL, BufSize);
  252.  
  253.     sig[6] = NULL;
  254.  
  255.     if (FRead(GIFfh, sig, 1, 6) != 6 || strncmp("GIF", sig, 3)) {
  256.         MyPrintf("%s is not a GIF file...\n", name);
  257.         goto LeaveConvert;
  258.     }
  259.  
  260.     MyPrintf("Converting %s ", name);
  261.  
  262.     basename = FilePart(name);
  263.     ptr = basename + strlen(basename) - 4;
  264.  
  265.     if (!strnicmp(".gif", ptr, 4))
  266.         *ptr = NULL;
  267.  
  268.     size = strlen(basename) + 6;
  269.  
  270.     if (ArgArray[ARG_TO]) {
  271.         if (ArgToIsDir)
  272.             size += strlen(ArgArray[ARG_TO]) + 1;
  273.         else
  274.             size = strlen(ArgArray[ARG_TO]) + 1;
  275.     }
  276.  
  277.     if (!(ptr = MyAlloc(size))) {
  278.         PutStr("... Out of memory!\n");
  279.         goto LeaveConvert;
  280.     }
  281.  
  282.     if (ArgArray[ARG_TO]) {
  283.         strcpy(ptr, ArgArray[ARG_TO]);
  284.  
  285.         if (ArgToIsDir) {
  286.             AddPart(ptr, basename, size);
  287.             strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
  288.         }
  289.     } else {
  290.         strcpy(ptr, basename);
  291.         strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
  292.     }
  293.  
  294.     MyPrintf("to %s...\n", ptr);
  295.  
  296.     DateStamp(&StartTime);
  297.  
  298.     if (FRead(GIFfh, (char *)&gdesc, 1, 7) != 7) {
  299.         PutStr("Error reading screen descriptor.\n");
  300.         goto LeaveConvert;
  301.     }
  302.  
  303.     FlipWord(&gdesc.gd_Width);
  304.     FlipWord(&gdesc.gd_Height);
  305.  
  306.     MyPrintf("Signature = \"%s\", Width = %ld, Height = %ld\n",
  307.         sig, gdesc.gd_Width, gdesc.gd_Height);
  308.  
  309.     NewList((struct List *)&CommentList);
  310.  
  311.     DidXComp = 0;
  312.     colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
  313.  
  314.     if (!(gdesc.gd_ColInfo & 1L << 7)) {
  315.         PutStr("No global colour map supplied, using internal.\n");
  316.  
  317.         for (index = 0; index < colours; index++) {
  318.             GlobalColourTable[index].rgb_Red   =
  319.             GlobalColourTable[index].rgb_Green =
  320.             GlobalColourTable[index].rgb_Blue  = index;
  321.         }
  322.     } else {
  323.         MyPrintf("Global colour map contains %ld entries.\n", colours);
  324.  
  325.         for (index = 0; index < colours; index++) {
  326.             if (FRead(GIFfh, &GlobalColourTable[index], 1, 3) != 3) {
  327.                 MyPrintf("Error reading global colour #%ld.\n",
  328.                     index);
  329.                 goto LeaveConvert;
  330.             }
  331.         }
  332.     }
  333.  
  334.     size = ((gdesc.gd_Width + 7) / 8) + 1;
  335.     size += (size + 127) >> 7;
  336.  
  337.     if (!(BitPlane = (struct RGB **)MyAlloc(gdesc.gd_Height * sizeof(struct RGB *))) ||
  338.         !(SHAMmem  = (UWORD *)MyAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
  339.         !(PlaneBuf = (BYTE *)MyAlloc(size))) {
  340.         PutStr("Out of memory trying to allocate picture.\n");
  341.         goto LeaveConvert;
  342.     }
  343.  
  344.     size = (gdesc.gd_Width + 1) * sizeof(struct RGB);
  345.  
  346.     for (index = 0; index < gdesc.gd_Height; index++)
  347.         if (!(BitPlane[index] = (struct RGB *)MyAlloc(size))) {
  348.             PutStr("Out of memory trying to allocate picture.\n");
  349.             goto LeaveConvert;
  350.         }
  351.  
  352.     size = ((gdesc.gd_Width + 7) / 8) + 1;
  353.     for (index = 0; index < (ArgArray[ARG_DEEP] ? 24 : 6); index++)
  354.         if (!(Planes[index] = (UBYTE *)MyAlloc(size))) {
  355.             PutStr("Out of memory trying to allocate picture.\n");
  356.             goto LeaveConvert;
  357.         }
  358.  
  359.     if (ArgArray[ARG_DITHER]) {
  360.         size = gdesc.gd_Width * sizeof(BYTE);
  361.  
  362.         for (index = 0; index < 3; index++)
  363.             if (!(CurrentLineErr[index] = (BYTE *)MyAlloc(size)) ||
  364.                 !(LastLineErr[index] = (BYTE *)MyAlloc(size))) {
  365.                 PutStr("Out of memory trying to allocate picture.\n");
  366.                 goto LeaveConvert;
  367.             }
  368.     }
  369.  
  370.     ImageNumber = 1;
  371.  
  372.     /* at this point we start looking for images, extensions or the gif
  373.        terminator.  we call the appropriate routine as we find each. */
  374.  
  375.     for (error = FALSE; error == FALSE;) {
  376.         if ((cmdcode = FGetC(GIFfh)) == -1) {
  377.             PutStr("...I/O error reading GIF file.\n");
  378.             goto LeaveConvert;
  379.         }
  380.  
  381.         switch(cmdcode) {
  382.             case GIF_IMAGE:
  383.                 error = DoImage(GIFfh);
  384.                 break;
  385.  
  386.             case GIF_EXTENSION:
  387.                 error = DoExtension(GIFfh);
  388.                 break;
  389.  
  390.             case GIF_TERMINATOR:
  391.                 if (ArgArray[ARG_NOBORD])
  392.                     StripBorder();
  393.  
  394.                 if (ArgArray[ARG_FLIPX])
  395.                     DoXFlip();
  396.  
  397.                 if (ArgArray[ARG_FLIPY])
  398.                     DoYFlip();
  399.  
  400.                 if (ArgArray[ARG_XCOMP]) {
  401.                     DoXComp();
  402.                     DidXComp = 1;
  403.                 }
  404.  
  405.                 if (gdesc.gd_Height > 200 && DidXComp)
  406.                     Laced = TRUE;
  407.                 else
  408.                     Laced = FALSE;
  409.  
  410.                 if (!ArgArray[ARG_DEEP]) {
  411.                     if (ArgArray[ARG_DITHER])
  412.                         DitherTo12();
  413.                     else
  414.                         ReduceTo12();
  415.  
  416.                     GIFtoSHAM();
  417.                 }
  418.  
  419.                 error = WriteIFF(ptr, (BOOL)ArgArray[ARG_DEEP]);
  420.                 break;
  421.  
  422.             default:
  423.                 MyPrintf("...Unknown directive #%ld encountered.\n",
  424.                     cmdcode);
  425.                 error = TRUE;
  426.         }
  427.     }
  428.  
  429.     DateStamp(&EndTime);
  430.  
  431.     {
  432.         register ULONG Hours;
  433.         register ULONG Minutes;
  434.         register ULONG Seconds;
  435.         register ULONG Seconds2;
  436.     
  437.         Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
  438.         Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
  439.  
  440.         Seconds -= Seconds2;
  441.  
  442.         Hours = Seconds / 3600;
  443.         Seconds -= Hours * 3600;
  444.  
  445.         Minutes = Seconds / 60;
  446.         Seconds -= Minutes * 60;
  447.  
  448.         MyPrintf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
  449.             Hours, (Hours != 1 ? "s" : ""),
  450.             Minutes, (Minutes != 1 ? "s" : ""),
  451.             Seconds, (Seconds != 1 ? "s" : ""));
  452.     }
  453.  
  454. LeaveConvert:
  455.     FreeAll(CurrentMem--);
  456.  
  457.     if (GIFfh) {
  458.         Close(GIFfh);
  459.         GIFfh = NULL;
  460.     }
  461. }
  462.  
  463. /* this will check to see if we have a directory or not */
  464. BOOL IsDir(char *name)
  465. {
  466.     register BPTR lock;
  467.     register BOOL result = FALSE;
  468.  
  469.     struct FileInfoBlock __aligned fib;
  470.  
  471.     if (lock = Lock(name, ACCESS_READ)) {
  472.         if (Examine(lock, &fib)) {
  473.             if (fib.fib_DirEntryType > 0)
  474.                 result = TRUE;
  475.         }
  476.         UnLock(lock);
  477.     }
  478.  
  479.     return result;
  480. }
  481.  
  482. /* this will convert a word from LSB/MSB to MSB/LSB */
  483. void FlipWord(UWORD *word)
  484. {
  485.     register UBYTE swap1;
  486.     register UBYTE swap2;
  487.  
  488.     swap1 = *word & 0xFF;
  489.     swap2 = (*word & 0xFF00) >> 8;
  490.     *word = swap1 << 8 | swap2;
  491. }
  492.