home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / printimage_394.lzh / PrintImage / PrintImage.c < prev    next >
C/C++ Source or Header  |  1990-10-28  |  19KB  |  991 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by MXM
  4.  *
  5.  *    Name .....: PrintImage.c
  6.  *    Created ..: Saturday 15-Sep-90 14:16
  7.  *    Revision .: 1
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    15-Sep-90       Olsen           Created this file!
  12.  *
  13.  * $Revision Header ********************************************************/
  14.  
  15.     /* Remove this definition if you don't need it (see below). */
  16.  
  17. /*#define CITIZEN_SWIFT_24 1*/
  18.  
  19.     /* Prototypes for this module. */
  20.  
  21. VOID            CloseAll(BYTE ReturnCode);
  22. VOID            OpenAll(VOID);
  23. VOID            FreeImage(VOID);
  24. BYTE            LoadImage(char *Name);
  25. ULONG            FindChunk(ULONG ChunkName,FILE *FilePointer);
  26. LONG            LoadHeader(char *FileName,BitMapHeader *BMHeader);
  27. BYTE            LoadCMAP(char *FileName,BYTE Colours[32][3],LONG MaxCol,BitMapHeader *BMHeader);
  28. BYTE            LoadRaster(char *FileName,PLANEPTR *BitPlanes,BitMapHeader *BMHeader);
  29. VOID            main(VOID);
  30.  
  31.     /* Global and shared library identifiers. */
  32.  
  33. extern struct ExecBase    *SysBase;
  34. struct IntuitionBase    *IntuitionBase;
  35. struct GfxBase        *GfxBase;
  36. struct ReqLib        *ReqBase;
  37.  
  38.     /* Window and process data. */
  39.  
  40. struct Window        *Window;
  41. struct Process        *ThisProcess;
  42.  
  43.     /* Printer IO. */
  44.  
  45. struct MsgPort        *PrintPort;
  46. struct IODRPReq        *PrintRequest;
  47. struct IOStdReq        *PrintStdReq;
  48.  
  49.     /* File requester and associated data. */
  50.  
  51. struct FileRequester     LoadFileReq;
  52. char             FileName[FCHARS],DirectoryName[DSIZE],Buffer[FCHARS + DSIZE + 2];
  53.  
  54.     /* Image data. */
  55.  
  56. struct BitMap         ImageBitMap;
  57. struct RastPort         ImageRastPort;
  58. struct ColorMap        *ImageColourMap;
  59. BitMapHeader         ImageBitMapHeader;
  60. LONG             ImageModes;
  61. BYTE             HasImage;
  62.  
  63.     /* Window data. */
  64.  
  65. struct IntuiMessage    *Massage;
  66. ULONG             Class;
  67. USHORT             Code;
  68. BYTE             GadgetID,i;
  69.  
  70.     /* The four gadgets. */
  71.  
  72. char *GadgetTexts[] =
  73. {
  74.     "Load new image",
  75.     "Print current image",
  76.     "Stop printing",
  77.     "Exit program"
  78. };
  79.  
  80.     /* Define the number of gadgets. */
  81.  
  82. #define NUMGADS    (sizeof(GadgetTexts) / sizeof(char *))
  83.  
  84.     /* Present a fitting number of gadget blocks. */
  85.  
  86. struct GadgetBlock GadgetBlocks[NUMGADS];
  87.  
  88.     /* A window definition. */
  89.  
  90. struct NewWindow NewWindow =
  91. {
  92.     0,0,
  93.     0,0,
  94.     0,1,
  95.     CLOSEWINDOW | GADGETUP,
  96.     WINDOWDEPTH | WINDOWDRAG | WINDOWCLOSE | RMBTRAP | ACTIVATE,
  97.     (struct Gadget *)NULL,
  98.     (struct Image *)NULL,
  99.     (STRPTR)"PrintImage",
  100.     (struct Screen *)NULL,
  101.     (struct BitMap *)NULL,
  102.     ~0,~0,
  103.     ~0,~0,
  104.     WBENCHSCREEN
  105. };
  106.  
  107.     /* A Zz... mouse pointer. */
  108.  
  109. USHORT ElecArtsWaitPointer[(22 + 2) * 2] =
  110. {
  111.     0x0000,0x0000,
  112.  
  113.     0x6700,0xC000,
  114.     0xCFA0,0xC700,
  115.     0xBFF0,0x0FA0,
  116.     0x70F8,0x3FF0,
  117.     0x7DFC,0x3FF8,
  118.     0xFBFC,0x7FF8,
  119.     0x70FC,0x3FF8,
  120.     0x7FFE,0x3FFC,
  121.     0x7F0E,0x3FFC,
  122.     0x3FDF,0x1FFE,
  123.     0x7FBE,0x3FFC,
  124.     0x3F0E,0x1FFC,
  125.     0x1FFC,0x07F8,
  126.     0x07F8,0x01E0,
  127.     0x01E0,0x0080,
  128.     0x07C0,0x0340,
  129.     0x0FE0,0x07C0,
  130.     0x0740,0x0200,
  131.     0x0000,0x0000,
  132.     0x0070,0x0020,
  133.     0x0078,0x0038,
  134.     0x0038,0x0010,
  135.  
  136.     0x0000,0x0000
  137. };
  138.  
  139.     /* A macro to attach the mouse pointer to a window. */
  140.  
  141. #define SetWait(Window) SetPointer(Window,ElecArtsWaitPointer,22,16,0,0)
  142.  
  143.     /* CloseAll():
  144.      *
  145.      *    Closes all resources and returns to the shell.
  146.      */
  147.  
  148. VOID
  149. CloseAll(BYTE ReturnCode)
  150. {
  151.     ThisProcess -> pr_WindowPtr = NULL;
  152.  
  153.     PurgeFiles(&LoadFileReq);
  154.  
  155.     FreeImage();
  156.  
  157.     if(Window)
  158.         CloseWindow(Window);
  159.  
  160.     if(PrintRequest)
  161.     {
  162.         if(PrintRequest -> io_Device)
  163.         {
  164.             /* The following code puts the Citicen Swift 24
  165.              * printer back into Epson emulation mode.
  166.              */
  167.  
  168. #ifdef    CITIZEN_SWIFT_24
  169.  
  170.             PrintStdReq -> io_Command    = PRD_RAWWRITE;
  171.             PrintStdReq -> io_Data        = (APTR)"\33~5\0";
  172.             PrintStdReq -> io_Length    = 4;
  173.     
  174.             DoIO(PrintStdReq);
  175.  
  176. #endif    /* CITIZEN_SWIFT_24 */
  177.  
  178.             CloseDevice(PrintRequest);
  179.         }
  180.  
  181.         DeleteExtIO(PrintRequest);
  182.     }
  183.  
  184.     if(PrintPort)
  185.         DeletePort(PrintPort);
  186.  
  187.     if(ReqBase)
  188.         CloseLibrary(ReqBase);
  189.  
  190.     exit(ReturnCode);
  191. }
  192.  
  193.     /* OpenAll():
  194.      *
  195.      *    Open all resources to start the program.
  196.      */
  197.  
  198. VOID
  199. OpenAll()
  200. {
  201.     SHORT    MaxWidth = 0,TempWidth;
  202.     BYTE    i;
  203.  
  204.     ThisProcess = (struct Process *)SysBase -> ThisTask;
  205.  
  206.     if(!(ReqBase = (struct ReqLib *)OpenLibrary("req.library",0)))
  207.         CloseAll(RETURN_FAIL + 1);
  208.  
  209.     IntuitionBase    = ReqBase -> IntuiLib;
  210.     GfxBase        = ReqBase -> GfxLib;
  211.  
  212.     if(!(PrintPort = (struct MsgPort *)CreatePort(NULL,0)))
  213.         CloseAll(RETURN_FAIL + 2);
  214.  
  215.     if(!(PrintRequest = (struct IODRPReq *)CreateExtIO(PrintPort,sizeof(struct IODRPReq))))
  216.         CloseAll(RETURN_FAIL + 3);
  217.  
  218.     PrintStdReq = (struct IOStdReq *)PrintRequest;
  219.  
  220.     if(OpenDevice("printer.device",0,PrintRequest,NULL))
  221.         CloseAll(RETURN_FAIL + 4);
  222.  
  223.         /* The following lines will put the Citizen Swift 24
  224.          * printer into NEC P6+ emulation mode. Since the
  225.          * Workbench EpsonQ printer driver only permits
  226.          * to print with a maximum resolution of 360×180 dpi
  227.          * this provides a convenient way to work with the
  228.          * Nec_Pinwriter driver without having to reselect
  229.          * the emulation manually.
  230.          */
  231.  
  232. #ifdef    CITIZEN_SWIFT_24
  233.  
  234.     PrintStdReq -> io_Command    = PRD_RAWWRITE;
  235.     PrintStdReq -> io_Data        = (APTR)"\33~5\2";
  236.     PrintStdReq -> io_Length    = 4;
  237.  
  238.     if(DoIO(PrintStdReq))
  239.         CloseAll(RETURN_FAIL + 4);
  240.  
  241. #endif    /* CITIZEN_SWIFT_24 */
  242.  
  243.         /* The following piece of code adapts the
  244.          * window to the number and the dimensions of
  245.          * the gadgets.
  246.          */
  247.  
  248.     for(i = 0 ; i < NUMGADS ; i++)
  249.     {
  250.         if((TempWidth = 8 * strlen(GadgetTexts[i]) + 4) > MaxWidth)
  251.             MaxWidth = TempWidth;
  252.     }
  253.  
  254.     NewWindow . Width = MaxWidth + 8;
  255.  
  256.     for(i = 0 ; i < NUMGADS ; i++)
  257.     {
  258.         LinkGadget(&GadgetBlocks[i],GadgetTexts[i],&NewWindow,((NewWindow . Width - (8 * strlen(GadgetTexts[i]) + 4)) >> 1) + 2,13 + (5 + 8) * i);
  259.  
  260.         GadgetBlocks[i] . Gadget . GadgetID = i;
  261.     }
  262.  
  263.     NewWindow . Height = 11 + ((5 + 8) * NUMGADS + 1);
  264.  
  265.     Center(&NewWindow,GadgetBlocks[0] . Gadget . LeftEdge + (GadgetBlocks[0] . Gadget . Width >> 1),GadgetBlocks[0] . Gadget . TopEdge + (GadgetBlocks[0] . Gadget . Height >> 1));
  266.  
  267.     if(!(Window = (struct Window *)OpenWindow(&NewWindow)))
  268.         CloseAll(RETURN_FAIL + 5);
  269.  
  270.     for(i = 1 ; i < NUMGADS - 1 ; i++)
  271.         OffGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
  272.  
  273.     LoadFileReq . PathName        = Buffer;
  274.     LoadFileReq . Title        = GadgetTexts[0];
  275.     LoadFileReq . dirnamescolor    = 3;
  276.     LoadFileReq . devicenamescolor    = 3;
  277.     LoadFileReq . Window        = Window;
  278.  
  279.     LoadFileReq . Dir        = DirectoryName;
  280.     LoadFileReq . File        = FileName;
  281.     LoadFileReq . Flags        = FRQCACHINGM | FRQINFOGADGETM | FRQNOHALFCACHEM | FRQLOADINGM;
  282.     LoadFileReq . blockcolor    = 1;
  283.  
  284.     ThisProcess -> pr_WindowPtr = (APTR)Window;
  285. }
  286.  
  287.     /* FreeImage():
  288.      *
  289.      *    Free the data associated with the image in memory.
  290.      */
  291.  
  292. VOID
  293. FreeImage()
  294. {
  295.     if(ImageColourMap)
  296.         FreeColorMap(ImageColourMap);
  297.  
  298.     if(ImageBitMap . Planes[0])
  299.         FreeMem(ImageBitMap . Planes[0],ImageBitMap . Depth * ImageBitMap . BytesPerRow * ImageBitMap . Rows);
  300.  
  301.     HasImage = FALSE;
  302. }
  303.  
  304.     /* PrintImage():
  305.      *
  306.      *    Print the image in memory according to the current
  307.      *    Preferences settings.
  308.      */
  309.  
  310. VOID
  311. PrintImage()
  312. {
  313.     ULONG    SignalSet;
  314.     SHORT    i;
  315.  
  316.         /* Standard system hardcopy. */
  317.  
  318.     PrintRequest -> io_Command    = PRD_DUMPRPORT;
  319.     PrintRequest -> io_RastPort    = &ImageRastPort;
  320.     PrintRequest -> io_ColorMap    = ImageColourMap;
  321.     PrintRequest -> io_Modes    = ImageModes;
  322.     PrintRequest -> io_SrcWidth    = ImageBitMapHeader . w;
  323.     PrintRequest -> io_SrcHeight    = ImageBitMapHeader . h;
  324.     PrintRequest -> io_SrcX        = 0;
  325.     PrintRequest -> io_SrcY        = 0;
  326.     PrintRequest -> io_DestCols    = ImageBitMapHeader . w;
  327.     PrintRequest -> io_DestRows    = ImageBitMapHeader . h;
  328.     PrintRequest -> io_Special    = SPECIAL_ASPECT | SPECIAL_TRUSTME;
  329.  
  330.         /* Block all gadgets save one. */
  331.  
  332.     for(i = 0 ; i < NUMGADS ; i++)
  333.     {
  334.         if(i != 2)
  335.             OffGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
  336.         else
  337.             OnGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
  338.     }
  339.  
  340.         /* Sleep... */
  341.  
  342.     SetWait(Window);
  343.  
  344.         /* ...and fire off the printer dump. */
  345.  
  346.     BeginIO(PrintRequest);
  347.  
  348.     FOREVER
  349.     {
  350.             /* Wait for 'stop' or printer to finish. */
  351.  
  352.         SignalSet = Wait((1 << PrintPort -> mp_SigBit) | (1 << Window -> UserPort -> mp_SigBit));
  353.  
  354.         if(SignalSet & (1 << PrintPort -> mp_SigBit))
  355.         {
  356.             while(GetMsg(PrintPort));
  357.  
  358.             break;
  359.         }
  360.  
  361.         if(SignalSet & (1 << Window -> UserPort -> mp_SigBit))
  362.         {
  363.             while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  364.             {
  365.                 Class        = Massage -> Class;
  366.                 Code        = Massage -> Code;
  367.                 GadgetID    = ((struct Gadget *)Massage -> IAddress) -> GadgetID;
  368.  
  369.                 ReplyMsg((struct Message *)Massage);
  370.  
  371.                 if(Class == GADGETUP && GadgetID == 2)
  372.                 {
  373.                     AbortIO(PrintRequest);
  374.                     WaitIO(PrintRequest);
  375.  
  376.                     goto Quit;
  377.                 }
  378.             }
  379.         }
  380.     }
  381.  
  382. Quit:    ClearPointer(Window);
  383.  
  384.     for(i = 0 ; i < NUMGADS ; i++)
  385.     {
  386.         if(i != 2)
  387.             OnGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
  388.         else
  389.             OffGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
  390.     }
  391. }
  392.  
  393.     /* LoadImage():
  394.      *
  395.      *    Loads an IFF-ILBM file and prepares it for the graphic
  396.      *    dump.
  397.      */
  398.  
  399. BYTE
  400. LoadImage(char *Name)
  401. {
  402.     BYTE    Colours[32][3];
  403.     ULONG    PageSize;
  404.     BYTE    i,MaxCol;
  405.  
  406.         /* Load the view modes. */
  407.  
  408.     if((ImageModes = LoadHeader(Name,&ImageBitMapHeader)) != -1)
  409.     {
  410.             /* Load the colour table. */
  411.  
  412.         if(MaxCol = LoadCMAP(Name,Colours,32,&ImageBitMapHeader))
  413.         {
  414.                 /* Initialize the bitmap. */
  415.  
  416.             InitBitMap(&ImageBitMap,ImageBitMapHeader . nPlanes,ImageBitMapHeader . w,ImageBitMapHeader . h);
  417.  
  418.                 /* Don't forget the rastport. */
  419.  
  420.             InitRastPort(&ImageRastPort);
  421.  
  422.                 /* Put the bitmap into the rastport. */
  423.  
  424.             ImageRastPort . BitMap = &ImageBitMap;
  425.  
  426.                 /* Calculate the size of a single bitplane. */
  427.  
  428.             PageSize = ImageBitMap . BytesPerRow * ImageBitMap . Rows;
  429.  
  430.                 /* Allocate space for the bitmap. */
  431.  
  432.             if(ImageBitMap . Planes[0] = AllocMem(PageSize * ImageBitMap . Depth,MEMF_CHIP | MEMF_CLEAR))
  433.             {
  434.                     /* Set the bitplane pointers accordingly. */
  435.  
  436.                 for(i = 1 ; i < ImageBitMapHeader . nPlanes ; i++)
  437.                     ImageBitMap . Planes[i] = (PLANEPTR)((ULONG)ImageBitMap . Planes[0] + PageSize * i);
  438.  
  439.                     /* Allocate a colour map. */
  440.  
  441.                 if(ImageColourMap = (struct ColorMap *)GetColorMap(MaxCol))
  442.                 {
  443.                         /* Set the image colours. */
  444.  
  445.                     for(i = 0 ; i < MaxCol ; i++)
  446.                         SetRGB4CM(ImageColourMap,i,Colours[i][0],Colours[i][1],Colours[i][2]);
  447.  
  448.                         /* Finally, load the bitmap itself. */
  449.  
  450.                     if(LoadRaster(Name,ImageBitMap . Planes,&ImageBitMapHeader))
  451.                     {
  452.                         HasImage = TRUE;
  453.  
  454.                         return(TRUE);
  455.                     }
  456.                 }
  457.             }
  458.         }
  459.     }
  460.  
  461.     FreeImage();
  462.  
  463.     return(FALSE);
  464. }
  465.  
  466.     /* FindChunk():
  467.      *
  468.      *    Find a chunk in a file and return its length.
  469.      */
  470.  
  471. ULONG
  472. FindChunk(ULONG ChunkName,FILE *FilePointer)
  473. {
  474.     ULONG        OldPosition,FormType;
  475.     IFF_Chunk    Chunk;
  476.  
  477.         /* Remember the initial file position. */
  478.  
  479.     OldPosition = ftell(FilePointer);
  480.  
  481.         /* Reset the form type. */
  482.  
  483.     FormType = 0;
  484.  
  485.     for(;;)
  486.     {
  487.             /* Try to read the chunk. */
  488.  
  489.         if(fread(&Chunk,sizeof(Chunk),1,FilePointer) != 1)
  490.         {
  491.                 /* If it went wrong, reset the
  492.                  * file position.
  493.                  */
  494.  
  495.             fseek(FilePointer,OldPosition,0);
  496.             return(0);
  497.         }
  498.  
  499.             /* If this is supposed to be a FORM chunk,
  500.              * try to figure out the form type.
  501.              */
  502.  
  503.         if(OldPosition == 0 && FormType == 0 && Chunk . IFF_Type == 'FORM')
  504.         {
  505.             fread(&FormType,sizeof(LONG),1,FilePointer);
  506.  
  507.                 /* Is it the type we want? */
  508.  
  509.             if(FormType == ChunkName)
  510.                 return(Chunk . IFF_Length);
  511.  
  512.             continue;
  513.         }
  514.  
  515.             /* Is this what we want? */
  516.  
  517.         if(Chunk . IFF_Type == ChunkName)
  518.             return(Chunk . IFF_Length);
  519.  
  520.             /* Else, skip the length information. */
  521.  
  522.         fseek(FilePointer,Chunk . IFF_Length,1);
  523.     }
  524. }
  525.  
  526.     /* LoadHeader():
  527.      *
  528.      *    Try to load a BitMapHeader from a file and return
  529.      *    the proper ViewModes.
  530.      */
  531.  
  532. LONG
  533. LoadHeader(char *FileName,BitMapHeader *BMHeader)
  534. {
  535.     LONG     ViewModes = -1;
  536.     FILE    *ImageFile;
  537.  
  538.         /* No such file? */
  539.  
  540.     if(ImageFile = fopen(FileName,"rb"))
  541.     {
  542.             /* No BMHD-Chunk? */
  543.  
  544.         if(FindChunk('BMHD',ImageFile))
  545.         {
  546.                 /* Read the header. */
  547.  
  548.             if(fread(BMHeader,sizeof(BitMapHeader),1,ImageFile))
  549.             {
  550.  
  551.                 /* Strange values, probably not a picture but a
  552.                  * "mistake", or even a CMAP.
  553.                  */
  554.  
  555.                 if(BMHeader -> nPlanes && BMHeader -> nPlanes <= 8)
  556.                 {
  557.                     ViewModes = NULL;
  558.  
  559.                     /* If we don't find a CAMG chunk in the file
  560.                      * we will have to guess the right
  561.                      * ViewModes. This line takes care of the
  562.                      * interlaced display mode.
  563.                      */
  564.  
  565.                     if(BMHeader -> pageHeight > GfxBase -> NormalDisplayRows)
  566.                         ViewModes |= LACE;
  567.  
  568.                     /* Could it be HIRES? */
  569.  
  570.                     if(BMHeader -> pageWidth >= 640)
  571.                         ViewModes |= HIRES;
  572.  
  573.                     /* It is still much more likely to encounter a
  574.                      * HAM picture than an EHB picture. If we are
  575.                      * wrong with this assumption, the CAMG chunk
  576.                      * will tell us (hope so).
  577.                      */
  578.  
  579.                     if(BMHeader -> nPlanes == 6)
  580.                         ViewModes |= HAM;
  581.  
  582.                     /* Hello out there, got any CAMG chunk? */
  583.  
  584.                     if(FindChunk('CAMG',ImageFile))
  585.                     {
  586.                         /* Read it then. */
  587.  
  588.                         if(fread(&ViewModes,sizeof(LONG),1,ImageFile) == 1)
  589.                         {
  590.                             /* Mask out all unwanted bits (thanks, Carolyn!). */
  591.  
  592.                             ViewModes &= (~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO) | 0xFFFF);
  593.                         }
  594.                         else
  595.                             ViewModes = -1;
  596.                     }
  597.                 }
  598.             }
  599.         }
  600.  
  601.         fclose(ImageFile);
  602.     }
  603.  
  604.         /* Finish it. */
  605.  
  606.     return(ViewModes);
  607. }
  608.  
  609.     /* LoadCMAP():
  610.      *
  611.      *    Load a colour table from a file and return the number
  612.      *    of colours.
  613.      */
  614.  
  615. BYTE
  616. LoadCMAP(char *FileName,BYTE Colours[32][3],LONG MaxCol,BitMapHeader *BMHeader)
  617. {
  618.     BYTE     NumCols = 0;
  619.     FILE    *ColFile;
  620.     BYTE     i;
  621.  
  622.         /* Are you there? */
  623.  
  624.     if(ColFile = fopen(FileName,"rb"))
  625.     {
  626.             /* Black 'n white or colour TV? */
  627.  
  628.         if(FindChunk('CMAP',ColFile))
  629.         {
  630.                 /* Correct it before the reader believes it! */
  631.  
  632.             if(MaxCol < 2)
  633.                 MaxCol = 1 << BMHeader -> nPlanes;
  634.  
  635.                 /* A bit too large, innit? */
  636.  
  637.             if(MaxCol > 32)
  638.                 MaxCol = 32;
  639.  
  640.                 /* Read those colours. */
  641.  
  642.             if(fread(Colours,32 * 3,1,ColFile) == 1)
  643.             {
  644.                 for(i = 0 ; i < MaxCol ; i++)
  645.                 {
  646.                     Colours[i][0] >>= 4;
  647.                     Colours[i][1] >>= 4;
  648.                     Colours[i][2] >>= 4;
  649.                 }
  650.  
  651.                 NumCols = MaxCol;
  652.             }
  653.         }
  654.  
  655.             /* Finish it. */
  656.  
  657.         fclose(ColFile);
  658.     }
  659.  
  660.     return(NumCols);
  661. }
  662.  
  663.     /* LoadRaster():
  664.      *
  665.      *    Load the bitmap from a file and decompress it into the
  666.      *    supplied planes.
  667.      */
  668.  
  669. BYTE
  670. LoadRaster(char *FileName,PLANEPTR *BitPlanes,BitMapHeader *BMHeader)
  671. {
  672.     UBYTE         Value,SoFar,Compr,Depth;
  673.     LONG         Height,Width;
  674.     PLANEPTR     Planes[9];    /* 9 for possible bitmask. */
  675.     FILE        *PicFile;
  676.     BYTE         ChkVal;
  677.     LONG         i,j,k;
  678.  
  679.     LONG         AuxLength;
  680.     BYTE        *AuxBuff2;
  681.     BYTE        *AuxBuff;    /* Decompress in memory buffer. */
  682.  
  683.         /* Clear the planes. */
  684.  
  685.     for(i = 0 ; i < 9 ; i++)
  686.         Planes[i] = NULL;
  687.  
  688.         /* Set up the working copies. */
  689.  
  690.     Width    = byte(BMHeader -> w);
  691.     Height    = BMHeader -> h;
  692.     Depth    = BMHeader -> nPlanes;
  693.     Compr    = BMHeader -> compression;
  694.  
  695.         /* Is there something wrong in paradise? */
  696.  
  697.     if(Compr > 1 || !BitPlanes)
  698.         return(FALSE);
  699.  
  700.         /* Can we read it, please? */
  701.  
  702.     if(!(PicFile = fopen(FileName,"rb")))
  703.         return(FALSE);
  704.  
  705.         /* No BODY? What is this? */
  706.  
  707.     if(!(AuxLength = FindChunk('BODY',PicFile)))
  708.     {
  709.         fclose(PicFile);
  710.         return(FALSE);
  711.     }
  712.  
  713.         /* Copy the bitmap pointers since their
  714.          * contents will get changed.
  715.          */
  716.  
  717.     for(i = 0 ; i < Depth ; i++)
  718.         Planes[i] = BitPlanes[i];
  719.  
  720.         /* Very well, nobody told me that DPaint and Aegis Images
  721.          * are allowed to save their own home-brewn BODY chunks
  722.          * if the transparent colour is nonzero or the
  723.          * stencil/behind function is used. In this case the
  724.          * interleaved plane data is immediately followed by
  725.          * a bitmask which is to clear all unwanted pixels
  726.          * after the image is drawn. To support this feature
  727.          * we increment the depth of the image to give the
  728.          * reader access to a blank pointer the bitmask will
  729.          * be sent to.
  730.          */
  731.  
  732.     if(BMHeader -> masking == 1)
  733.         Depth++;
  734.  
  735.         /* If we can allocate the memory buffer, we will
  736.          * decompress the image in memory rather than
  737.          * while reading it from disk.
  738.          */
  739.  
  740.     if(AuxBuff = (BYTE *)AllocMem(AuxLength,MEMF_PUBLIC))
  741.     {
  742.             /* Read the data. */
  743.  
  744.         fread(AuxBuff,AuxLength,1,PicFile);
  745.  
  746.             /* Remember the buffer address. */
  747.  
  748.         AuxBuff2 = AuxBuff;
  749.  
  750.             /* No compression? */
  751.  
  752.         if(Compr == 0)
  753.         {
  754.             for(k = 0 ; k < Height ; k++)
  755.             {
  756.                 for(j = 0 ; j < Depth ; j++)
  757.                 {
  758.                     if(Planes[j])
  759.                     {
  760.                         CopyMem(AuxBuff,Planes[j],Width);
  761.                         Planes[j] += Width;
  762.                     }
  763.  
  764.                     AuxBuff += Width;
  765.                 }
  766.             }
  767.         }
  768.  
  769.             /* ByteRun compression? */
  770.  
  771.         if(Compr == 1)
  772.         {
  773.             for(k = 0 ; k < Height ; k++)
  774.             {
  775.                 for(j = 0 ; j < Depth ; j++)
  776.                 {
  777.                     for(SoFar = 0 ; SoFar < Width ; )
  778.                     {
  779.                         ChkVal = *AuxBuff;
  780.                         AuxBuff++;
  781.  
  782.                         if(ChkVal > 0)
  783.                         {
  784.                             if(Planes[j])
  785.                             {
  786.                                 CopyMem(AuxBuff,Planes[j],ChkVal + 1);
  787.  
  788.                                 Planes[j] += ChkVal + 1;
  789.                             }
  790.  
  791.                             AuxBuff += ChkVal + 1;
  792.  
  793.                             SoFar += ChkVal + 1;
  794.                         }
  795.                         else
  796.                         {
  797.                             if(ChkVal != -128)
  798.                             {
  799.                                 Value = *AuxBuff;
  800.                                 AuxBuff++;
  801.  
  802.                                 for(i = 0 ; i <= -ChkVal ; i++)
  803.                                 {
  804.                                     if(Planes[j])
  805.                                         *Planes[j]++ = Value;
  806.  
  807.                                     SoFar++;
  808.                                 }
  809.                             }
  810.                         }
  811.                     }
  812.                 }
  813.             }
  814.         }
  815.  
  816.             /* Free the auxilary buffer. */
  817.  
  818.         FreeMem(AuxBuff2,AuxLength);
  819.  
  820.         goto Quit;
  821.     }
  822.         /* No compression, take the data as is. */
  823.  
  824.     if(Compr == 0)
  825.     {
  826.         for(k = 0 ; k < Height ; k++)
  827.         {
  828.             for(j = 0 ; j < Depth ; j++)
  829.             {
  830.                 if(Planes[j])
  831.                 {
  832.                     fread(Planes[j],Width,1,PicFile);
  833.                     Planes[j] += Width;
  834.                 }
  835.                 else
  836.                     fseek(PicFile,Width,1);
  837.             }
  838.         }
  839.     }
  840.  
  841.         /* ByteRun1 compression. */
  842.  
  843.     if(Compr == 1)
  844.     {
  845.         for(k = 0 ; k < Height ; k++)
  846.         {
  847.             for(j = 0 ; j < Depth ; j++)
  848.             {
  849.                 for(SoFar = 0 ; SoFar < Width ; )
  850.                 {
  851.                     ChkVal = fgetc(PicFile);
  852.  
  853.                         /* Read the next bytes. */
  854.  
  855.                     if(ChkVal > 0)
  856.                     {
  857.                         if(Planes[j])
  858.                         {
  859.                             fread(Planes[j],ChkVal + 1,1,PicFile);
  860.  
  861.                             Planes[j] += ChkVal + 1;
  862.                         }
  863.                         else
  864.                             fseek(PicFile,ChkVal + 1,1);
  865.  
  866.                         SoFar += ChkVal + 1;
  867.                     }
  868.                     else
  869.                     {
  870.                             /* Set the memory to this
  871.                              * value.
  872.                              */
  873.  
  874.                         if(ChkVal != -128)
  875.                         {
  876.                             Value = fgetc(PicFile);
  877.  
  878.                             for(i = 0 ; i <= -ChkVal ; i++)
  879.                             {
  880.                                 if(Planes[j])
  881.                                     *Planes[j]++ = Value;
  882.  
  883.                                 SoFar++;
  884.                             }
  885.                         }
  886.                     }
  887.                 }
  888.             }
  889.         }
  890.     }
  891.  
  892.         /* Finish it up. */
  893.  
  894. Quit:    fclose(PicFile);
  895.  
  896.     return(TRUE);
  897. }
  898.  
  899.     /* Stub routines. */
  900.  
  901. VOID _cli_parse() {}
  902. VOID _wb_parse() {}
  903.  
  904.     /* main():
  905.      *
  906.      *    The real main program.
  907.      */
  908.  
  909. VOID
  910. main()
  911. {
  912.     BYTE i;
  913.  
  914.         /* Open all resources. */
  915.  
  916.     OpenAll();
  917.  
  918.         /* Go into neverending loop. */
  919.  
  920.     FOREVER
  921.     {
  922.         WaitPort(Window -> UserPort);
  923.  
  924.             /* Pick up all the messages. */
  925.  
  926.         while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  927.         {
  928.             Class        = Massage -> Class;
  929.             Code        = Massage -> Code;
  930.             GadgetID    = ((struct Gadget *)Massage -> IAddress) -> GadgetID;
  931.  
  932.             ReplyMsg((struct Message *)Massage);
  933.  
  934.                 /* Close the window? */
  935.  
  936.             if(Class == CLOSEWINDOW)
  937.                 CloseAll(RETURN_OK);
  938.  
  939.                 /* Hit a gadget. */
  940.  
  941.             if(Class == GADGETUP)
  942.             {
  943.                 switch(GadgetID)
  944.                 {
  945.                         /* Load a new image? */
  946.  
  947.                     case 0:    if(HasImage)
  948.                             FreeImage();
  949.  
  950.                         if(FileRequester(&LoadFileReq))
  951.                         {
  952.                             SetWait(Window);
  953.  
  954.                             if(LoadImage(Buffer))
  955.                             {
  956.                                 for(i = 1 ; i < NUMGADS - 1 ; i++)
  957.                                 {
  958.                                     if(i != 2)
  959.                                         OnGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
  960.                                     else
  961.                                         OffGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
  962.                                 }
  963.                             }
  964.                             else
  965.                                 SimpleRequest("Couldn't load file \"%s\"!",Buffer);
  966.  
  967.                             ClearPointer(Window);
  968.                         }
  969.  
  970.                         break;
  971.  
  972.                         /* Print the image? */
  973.  
  974.                     case 1:    if(HasImage)
  975.                             PrintImage();
  976.  
  977.                         break;
  978.  
  979.                         /* Stop printing (ignore)? */
  980.  
  981.                     case 2:    break;
  982.  
  983.                         /* Exit the program? */
  984.  
  985.                     case 3:    CloseAll(RETURN_OK);
  986.                 }
  987.             }
  988.         }
  989.     }
  990. }
  991.