home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / RandomDot 1.1.0 / source / pgm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-19  |  6.6 KB  |  295 lines  |  [TEXT/KAHL]

  1. /* pgm.c - read Portable Graymap Files
  2.     by David Phillip Oster October 1994 oster@netcom.com
  3.     for:
  4.     Stuart Inglis singlis@waikato.ac.nz
  5.     Department of Computer Science
  6.     University of Waikato, Hamilton, New Zealand
  7.  */
  8. #include "RandomDotMain.h"
  9. #include "RandomDotRes.h"
  10. #include "pgm.h"
  11. #include "Error.h"
  12. #include "RandomDotWin.h"
  13. #include "Progress.h"
  14. #include "Utils.h"
  15.  
  16. /* IsPGMFile - return TRUE if this is a pgm File.
  17.     for now, a pgm file ends in ".pgm" (any case) and starts with
  18.     "P2" or "P5"
  19.  */
  20. Boolean IsPGMFile(ParmBlkPtr io){
  21.     Str255    s;
  22. #if 0
  23.     OSErr    errCode;
  24.     Str255    buf;
  25.     FSSpec    fs;
  26.     Integer    ref;
  27.     LongInt    len;
  28. #endif
  29.  
  30.     if(Length(io->fileParam.ioNamePtr) < 5){
  31.         return FALSE;
  32.     }
  33.     s[0] = 4;
  34.     BlockMove(&io->fileParam.ioNamePtr[Length(io->fileParam.ioNamePtr) - 3], &s[1], 4);
  35.     if(EqualString(s, "\p.pgm", FALSE, TRUE)){
  36.         return TRUE;
  37.     }
  38. #if 0
  39.     buf[0] = 2;
  40.     len = 2;
  41.     ref = -1;
  42.     /* this line always fails */
  43.     errCode = FSMakeFSSpec(io->fileParam.ioVRefNum, io->fileParam.ioFlNum, io->fileParam.ioNamePtr, &fs);
  44.     if(noErr == errCode){ errCode = FSpOpenDF(&fs, fsCurPerm, &ref); }
  45.     if(noErr == errCode){ errCode = FSRead(ref, &len, &buf[1]); }
  46.     if(noErr == errCode &&
  47.         'P' == buf[1] &&
  48.         ('2' == buf[2] || '5' == buf[2])){
  49.  
  50.         FSClose(ref);
  51.         return TRUE;
  52.     }
  53.     if(ref != -1){
  54.         FSClose(ref);
  55.     }
  56. #endif
  57.     return FALSE;
  58. }
  59.  
  60. /* GetInt - read an int into *np, return io error code.
  61.  */
  62. static OSErr GetInt(Integer ref, LongInt *np){
  63.     OSErr    errCode;
  64.     LongInt    len;
  65.     LongInt    n;
  66.     char    ch;
  67.  
  68.     n = 0;
  69.     len = 1;
  70.     do{
  71.         if(noErr != (errCode = FSRead(ref, &len, &ch))){
  72.             return errCode;
  73.         }
  74.     }while(NOT ('0' <= ch && ch <= '9'));
  75.  
  76.     do{
  77.         n = n * 10 + ch - '0';
  78.         if(noErr != (errCode = FSRead(ref, &len, &ch))){
  79.             return errCode;
  80.         }
  81.     }while('0' <= ch && ch <= '9');
  82.     *np = n;
  83.     return errCode;
  84. }
  85.  
  86. typedef struct BufferedIO{
  87.     Ptr    pStart;
  88.     Ptr    p;
  89.     Ptr    pEnd;
  90.     Integer    ref;
  91. }BufferedIO, *BufferedIOPtr;
  92.  
  93. /* OpenBuffer - open ref for buffered reads.
  94.  */
  95. static OSErr OpenBuffer(Integer ref, Ptr *tempp){
  96.     OSErr            errCode;
  97.     BufferedIOPtr    bp;
  98.  
  99.     bp = (BufferedIOPtr) NewPtr(sizeof(BufferedIO));
  100.     if(noErr == (errCode = MemError())){
  101.         bp->pStart = NewPtr(10000L);
  102.     }
  103.     if(noErr == (errCode = MemError())){
  104.         bp->p =
  105.         bp->pEnd = bp->pStart;
  106.         bp->ref = ref;
  107.         *tempp = (Ptr) bp;
  108.     }
  109.     return errCode;
  110. }
  111.  
  112. /* BufferedGetChar - 
  113.  */
  114. static OSErr BufferedGetChar(Ptr temp, char *cp){
  115.     OSErr            errCode;
  116.     BufferedIOPtr    bp;
  117.     LongInt            len;
  118.  
  119.     bp = (BufferedIOPtr) temp;
  120.     if(bp->p < bp->pEnd){
  121.         *cp = *bp->p++;
  122.         return noErr;
  123.     }
  124.     len = 10000L;
  125.     errCode = FSRead(bp->ref, &len, bp->pStart);
  126.     if(eofErr == errCode && len > 0){
  127.         errCode = noErr;
  128.     }
  129.     bp->pEnd = bp->pStart + len;
  130.     bp->p = bp->pStart;
  131.     return noErr == errCode ? BufferedGetChar(temp, cp) : errCode;
  132. }
  133.  
  134. /* BufferedGetInt - read an int into *np, return io error code.
  135.  */
  136. static OSErr BufferedGetInt(Ptr temp, LongInt *np){
  137.     OSErr    errCode;
  138.     LongInt    len;
  139.     LongInt    n;
  140.     char    ch;
  141.  
  142.     n = 0;
  143.     len = 1;
  144.     do{
  145.         if(noErr != (errCode = BufferedGetChar(temp, &ch))){
  146.             return errCode;
  147.         }
  148.     }while(NOT ('0' <= ch && ch <= '9'));
  149.  
  150.     do{
  151.         n = n * 10 + ch - '0';
  152.         if(noErr != (errCode = BufferedGetChar(temp, &ch))){
  153.             return errCode;
  154.         }
  155.     }while('0' <= ch && ch <= '9');
  156.     *np = n;
  157.     return errCode;
  158. }
  159.  
  160.  
  161. /* CloseBuffer - 
  162.  */
  163. static OSErr CloseBuffer(Ptr temp){
  164.     BufferedIOPtr    bp;
  165.  
  166.     bp = (BufferedIOPtr) temp;
  167.     DisposePtr(bp->pStart);
  168.     DisposePtr((Ptr) bp);
  169.     return noErr;
  170. }
  171.  
  172. /* PGMFileToGWorld - read a pgm file into a gray scale gworld
  173.  
  174.     Note: there is a bug in System 7.1 with the LaserWriter driver such that if
  175.         you CopyBits() to the printer, with an 8-bit indexed offscreen gworld
  176.         as the source, the first and last entries of the color table of the
  177.         offscreen gworld get set so the first is white and the last is black.
  178.         So, we follow that scheme in this program: for an 8-bit pixmap index,
  179.         the gray scale value is the complement of the index.
  180.         Watch out, expressions evaluate to ints in C, so ~(unsigned char) 1
  181.         if 0xFFFE not 0xFE
  182.  */
  183. OSErr PGMFileToGWorld(FSSpecPtr fs, ScriptCode code, GWorldPtr *gworld){
  184.     OSErr            errCode;
  185.     CGrafPtr        savePort;
  186.     GDHandle        saveGD;
  187.     Integer            ref;
  188.     LongInt            len;
  189.     Str255            buf, buf2;
  190.     char            magic;
  191.     LongInt            width;
  192.     LongInt            height;
  193.     LongInt            maxval;
  194.     LongInt            x, y;
  195.     Rect            frame;
  196.     unsigned char    ch;
  197.     GWorldPtr        grayImage;
  198.     PixMapHandle    pm;
  199.     Ptr                p;
  200.     unsigned char *pp, *pEnd;
  201.     Ptr                temp;
  202.  
  203.     GetIndString(buf, kMainStrs, kOpening1S);
  204.     Concat(buf, fs->name);
  205.     GetIndString(buf2, kMainStrs, kOpening2S);
  206.     Concat(buf, buf2);
  207.     SetProgressLabelText(buf);
  208.     grayImage = NIL;
  209.     ref = -1;
  210.     errCode = FSpOpenDF(fs, fsCurPerm, &ref);
  211.     len = 2;
  212.     temp = NIL;
  213.     if(noErr == errCode){ errCode = FSRead(ref, &len, &buf[1]); }
  214.     if(noErr == errCode && 'P' != buf[1]){ errCode = eBadPGMMagicNumber; }
  215.     if(noErr == errCode){ errCode = GetInt(ref, &width); }
  216.     if(noErr == errCode){ errCode = GetInt(ref, &height); }
  217.     if(noErr == errCode){ errCode = GetInt(ref, &maxval); }
  218.     if(noErr == errCode){ 
  219.         magic = buf[2];
  220.         frame.left = 0;
  221.         frame.top = 0;
  222.         frame.right = width;
  223.         frame.bottom = height;
  224.     }
  225.     GetGWorld(&savePort, &saveGD);
  226.     if(noErr == errCode){ errCode = NewGWorld(&grayImage, 8, &frame, grayCTab, NIL, 0); }
  227.     if(noErr == errCode){
  228.         SetGWorld(grayImage, NIL);
  229.         ClipRect(&qd.thePort->portRect);
  230.         pm = GetGWorldPixMap(grayImage);
  231.         LockPixels(pm);
  232.         switch (magic){
  233.         case '2' :
  234.             if(noErr != (errCode = OpenBuffer(ref, &temp))){ goto afterSwitch; }
  235.             for (y = 0; y < height; y++ ){
  236.                 if(0 == (y & 15)){
  237.                     SetGWorld(savePort, saveGD);
  238.                     if(noErr != (errCode = ShowProgress(y, height))){
  239.                         goto afterSwitch;
  240.                     }
  241.                     SetGWorld(grayImage, NIL);
  242.                 }
  243.                 p = GetPixBaseAddr(pm) + y * ((**pm).rowBytes & 0x7FFF);
  244.                 for(x = 0; x < width; x++, p++)    {
  245.                     if(noErr != (errCode = BufferedGetInt(temp, &len))){
  246.                         goto afterSwitch;
  247.                     }
  248.                     ch = len;
  249.                     *p = ~ch;
  250.                 }
  251.             }
  252.             break;
  253.         case '5' :
  254.             len = width;
  255.             for (y = 0; y < height; y++ ){
  256.                 if(0 == (y & 15)){
  257.                     SetGWorld(savePort, saveGD);
  258.                     if(noErr != (errCode = ShowProgress(y, height))){
  259.                         goto afterSwitch;
  260.                     }
  261.                     SetGWorld(grayImage, NIL);
  262.                 }
  263.                 p = GetPixBaseAddr(pm) + y * ((**pm).rowBytes & 0x7FFF);
  264.                 if(noErr != (errCode = FSRead(ref, &len, p))){
  265.                     goto afterSwitch;
  266.                 }
  267.                 pEnd = (unsigned char *)  (p + len);
  268.                 for(pp = (unsigned char *) p ; pp < pEnd ; pp++){
  269.                     *pp = ~*pp;
  270.                 }
  271.             }
  272.             break;
  273.         default : errCode = eBadPGMMagicNumber;
  274.             break; 
  275.         }
  276. afterSwitch:
  277.         SetGWorld(savePort, saveGD);
  278.         ShowProgress(height, height);
  279.         UnlockPixels(pm);
  280.     }
  281.     if(-1 != ref){
  282.         FSClose(ref);
  283.     }
  284.     if(NIL != temp){
  285.         CloseBuffer(temp);
  286.         temp = NIL;
  287.     }
  288.     SetGWorld(savePort, saveGD);
  289.     if(noErr == errCode){
  290.         *gworld = grayImage;
  291.     }else if(NIL != grayImage){
  292.         DisposeGWorld(grayImage);
  293.     }
  294.     return errCode;
  295. }