home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TIFF / TACS40.ZIP / CUTIL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-27  |  8.1 KB  |  443 lines

  1. /*
  2.  * C utilities for the Tag Image File Format routines
  3.  */
  4.  
  5. #include <tiff.h>
  6. #define NODEBUG 1        /* VJ 11/10 */
  7. #define SHORT_TYPE 3        /* BGM 11/12/87 */
  8.  
  9. #ifndef NULL
  10. #define NULL 0L
  11. #endif /* NULL */
  12.  
  13. typedef char *va_list;
  14.  
  15. #define va_start(ap,v) ap = (va_list)&v + sizeof(v)
  16. #define va_arg(ap,t) ((t*)(ap += sizeof(t)))[-1]
  17. #define va_end(ap) ap = NULL
  18.  
  19. static char temp[160];
  20. extern int vsprintf();
  21.  
  22. #ifdef NOWINDOWS    /* Windows-specific stuff */
  23.  
  24. extern void write();
  25.  
  26. #else
  27.  
  28. #define GMEM_LOCKCOUNT 0x00ff
  29. extern SHORT pascal GlobalFlags();
  30. extern char far * far pascal GlobalLock();
  31. extern BOOL far pascal GlobalUnlock();
  32. extern SHORT far pascal GlobalAlloc();
  33. extern void far pascal GlobalFree();
  34. extern void far pascal TextOut();
  35. extern unsigned short far pascal GetDC();
  36. extern void far pascal ReleaseDC();
  37. extern unsigned short MainWindow;
  38.  
  39. #define GHND    0x0040        /* fixed + zeroinit */
  40.  
  41. #endif /* NOWINDOWS */
  42.  
  43. extern unsigned short tlRead();
  44. extern LONG bigRead();
  45. extern SHORT tdosAlloc();
  46. extern void tdosFree();
  47.  
  48. extern BOOL _TIFF_reorder_bytes;
  49. extern BOOL _TIFF_debug_flag;
  50.  
  51. /* allocate up to one megabyte of data */
  52. LONGPTR
  53. bigalloc(size)
  54. LONG size;
  55. {
  56. #ifdef NOWINDOWS    /* non-Windows allocator */
  57.  
  58.     /* convert to paragraphs */
  59.     LONG temp = (size + 15) >> 4;    /* convert to paragraphs */
  60.     SHORT segment;
  61.  
  62.     /* must be < 1 megabyte */
  63.     if(HIWORD(temp))
  64.     {
  65.         return((LONGPTR)0L);
  66.     }
  67.  
  68.     if(!(segment = tdosAlloc(LOWORD(temp))))
  69.     {
  70.         return((LONGPTR)0L);
  71.     }
  72.     temp = (LONG)segment;
  73.     temp <<= 16;
  74.     return((LONGPTR)temp);
  75.  
  76. #else        /* Windows allocator */
  77.  
  78.     LONGPTR temp;
  79.     SHORT handle;
  80.  
  81.     /* get the space and make room for the handle */
  82.     handle = GlobalAlloc((SHORT)GHND, (LONG)(size + (LONG)SHORT_SIZE));
  83.     if(!handle)
  84.     {
  85.         return((LONGPTR)0L);
  86.     }
  87.  
  88.     /* lock the memory */
  89.     temp = GlobalLock(handle);
  90.     if(!temp)
  91.     {
  92.         GlobalFree(handle);
  93.         return((LONGPTR)0L);
  94.     }
  95.  
  96.     /* store the handle, adjust the pointer, and then return */
  97.     *((SHORT far *)temp) = handle;
  98.     return((LONGPTR)(temp + SHORT_SIZE));
  99.  
  100. #endif /* NOWINDOWS */
  101. }
  102.  
  103. /* free data allocated by bigalloc() */
  104. void
  105. bigfree(memptr)
  106. LONGPTR memptr;
  107. {
  108. #ifdef NOWINDOWS    /* non-Windows */
  109.  
  110.     LONG temp = (LONG)memptr;
  111.  
  112.     if(!memptr)
  113.     {
  114.         return;
  115.     }
  116.  
  117.     /* must be of form SEG:0 if it was returned from bigalloc() */
  118.     if(LOWORD(temp))
  119.     {
  120.         return;
  121.     }
  122.     tdosFree(HIWORD(temp));
  123.  
  124. #else        /* Windows */
  125.  
  126.     SHORT handle;
  127.  
  128.     /* mustn't be a null pointer */
  129.     if(!memptr)
  130.     {
  131.         return;
  132.     }
  133.  
  134.     /* get the handle */
  135.     memptr -= SHORT_SIZE;
  136.     handle = *((SHORT far *)memptr);
  137.  
  138.     /* free the memory */
  139.     /* this is kind of kludgie, but ... */
  140.     while( GlobalFlags(handle) & GMEM_LOCKCOUNT > 0 ) {
  141.         GlobalUnlock(handle);
  142.     }
  143.     GlobalFree(handle);
  144.     return;
  145.  
  146. #endif /* NOWINDOWS */
  147. }
  148.  
  149. /* reorder bytes if necessary */
  150. void
  151. reorder(data, size)
  152. LONGPTR data;
  153. SHORT size;
  154. {
  155.     if(_TIFF_reorder_bytes)
  156.     {
  157.         LONGPTR end = (data + size) - 1;
  158.         char temp;
  159.         while(data < end)
  160.         {
  161.             temp = *data;
  162.             *data++ = *end;
  163.             *end-- = temp;
  164.         }
  165.     }
  166. }
  167.  
  168. /* check if supplied value is correct version number */
  169. BOOL
  170. correct_version(value)
  171. SHORT value;
  172. {
  173.     /*
  174.      * For now, just compare to legal version number.  But this
  175.      * might get more complex as time goes on.
  176.      */
  177.     if(value == LEGAL_VERSION)
  178.     {
  179.         return(TRUE);
  180.     }
  181.     else
  182.     {
  183.         return(FALSE);
  184.     }
  185. }
  186.  
  187. /* return the length of a given type */
  188. SHORT
  189. type_length(type)
  190. SHORT type;
  191. {
  192.     static SHORT length_array[] =
  193.     {
  194.         BYTE_SIZE,
  195.         ASCII_SIZE,
  196.         SHORT_SIZE,
  197.         LONG_SIZE,
  198.         RATIONAL_SIZE,
  199.     };
  200.  
  201.     if(type < 1 || type > ELEMENTS(length_array))
  202.     {
  203.         return(0);
  204.     }
  205.     else
  206.     {
  207.         return(length_array[--type]);
  208.     }
  209. }
  210.  
  211. /* get value of tag */
  212. SHORT
  213. value_of(dirent, value)
  214. TIFF_DIR_ENTRY far *dirent;
  215. LONGPTR value;
  216. {
  217.     SHORT tlen = type_length(dirent->type);
  218.     SHORT code = DIRECT_VALUE;
  219.     LONG len;
  220.     long x;
  221.     LONGPTR cp;
  222.  
  223.     if(tlen < 1)
  224.     {
  225.         return(ERROR_VALUE);
  226.     }
  227.  
  228.     /* calculate real length */
  229.     len = (LONG)tlen;
  230.     len *= dirent->length;
  231.  
  232.     /* if longer than a LONG, only return the pointer to the data */
  233.     if(len >= LONG_SIZE)
  234.     {
  235.         len = LONG_SIZE;
  236.         code = INDIRECT_VALUE;
  237.     }
  238.  
  239.     /* move the value */
  240.     cp = (LONGPTR)&(dirent->value_offset);
  241.     x = (long)len;
  242.     while(x-- > 0)
  243.     {
  244.         *value++ = *cp++;
  245.     }
  246.  
  247.     return(code);
  248. }
  249.  
  250. /* read pertinent data from currently-pointed-to directory entry */
  251. BOOL
  252. read_dir(fhandle, dirent)
  253. SHORT fhandle;
  254. TIFF_DIR_ENTRY far *dirent;
  255. {
  256.     LONG littleRead();
  257.  
  258.     if(littleRead(fhandle, dirent, (LONG)TIFF_DIR_ENTRY_SIZE) <
  259.       TIFF_DIR_ENTRY_SIZE)
  260.     {
  261.         return(TRUE);
  262.     }
  263.  
  264.     /* reorder bytes if necessary */
  265.     reorder((SHORT far *)&(dirent->tag), SHORT_SIZE);
  266.     reorder((SHORT far *)&(dirent->type), SHORT_SIZE);
  267.     reorder((LONG far *)&(dirent->length), LONG_SIZE);
  268.     if(dirent->type == SHORT_TYPE  && dirent->length == 1) {
  269.         reorder((SHORT far *)&(dirent->value_offset), SHORT_SIZE);
  270.     } else {
  271.         reorder((LONG far *)&(dirent->value_offset), LONG_SIZE);
  272.     }
  273.  
  274.     return(FALSE);
  275. }
  276.  
  277. /* return entry count and subfile type of referenced IFD */
  278. BOOL
  279. access_ifd(fhandle, offset, dirent, entry_count, subfile_type,
  280.   next_dir_offset)
  281. SHORT fhandle;
  282. LONG offset;
  283. TIFF_DIR_ENTRY far *dirent;
  284. SHORT *entry_count;
  285. SHORT *subfile_type;
  286. LONG *next_dir_offset;
  287. {
  288.     BOOL retcode = FALSE;
  289.     LONG next_offset;
  290.     LONG lseek();
  291.  
  292.     /* seek to appropriate file position and exit if seek fails */
  293.     if(lseek(fhandle, offset, 0) != offset)
  294.     {
  295.         return(TRUE);
  296.     }
  297.  
  298.     /* attempt to read entry count */
  299.     if(littleRead(fhandle, (SHORT far *)entry_count, (LONG)SHORT_SIZE) <
  300.       SHORT_SIZE)
  301.     {
  302.         return(TRUE);
  303.     }
  304.     offset += SHORT_SIZE;
  305.  
  306.     /* reorder bytes if necessary */
  307.     reorder((SHORT far *)entry_count, SHORT_SIZE);
  308.  
  309.     /* entry count must be >= 1 (for now and maybe forever) */
  310.     if(*entry_count < 1)
  311.     {
  312.         return(TRUE);
  313.     }
  314.  
  315.     /* read directory entry at current file offset and return info */
  316.     if(read_dir(fhandle, dirent))
  317.     {
  318.         return(TRUE);
  319.     }
  320.     offset += TIFF_DIR_ENTRY_SIZE;
  321.  
  322.     /* first entry must be "SubfileType" or else it's an error */
  323.     if(dirent->tag != SUBFILE_TYPE_TAG)
  324.     {
  325.         return(TRUE);
  326.     }
  327.  
  328.     /* retrieve value (subfile type in this case) */
  329.     if(value_of(dirent, (LONGPTR)subfile_type) != DIRECT_VALUE)
  330.     {
  331.         return(TRUE);
  332.     }
  333.  
  334.     /* seek (relative) to end of IFD and read offset of next IFD */
  335.     next_offset = (LONG)*entry_count - 1;
  336.     next_offset *= TIFF_DIR_ENTRY_SIZE;
  337.     if(lseek(fhandle, next_offset, 1) == (LONG)(-1))
  338.     {
  339.         retcode = TRUE;
  340.     }
  341.     else if(littleRead(fhandle, (LONG far *)next_dir_offset, (LONG)LONG_SIZE)
  342.       != LONG_SIZE)
  343.     {
  344.         retcode = TRUE;
  345.     }
  346.  
  347.     /* seek back to where we were before seek to end of IFD */
  348.     if(lseek(fhandle, offset, 0) != offset)
  349.     {
  350.         retcode = TRUE;
  351.     }
  352.     return(retcode);
  353. }
  354.  
  355. LONG
  356. bigRead(fhandle, buffer, size)
  357. SHORT fhandle;
  358. LONGPTR buffer;
  359. LONG size;
  360. {
  361.     SHORT pages = HIWORD(size);
  362.     unsigned short rest = (unsigned short)LOWORD(size);
  363.     unsigned short bytes;
  364.     unsigned long total = 0;
  365.  
  366.     while(pages-- > 0)
  367.     {
  368.         int repeat = 2;
  369.         while(repeat-- > 0)
  370.         {
  371.             bytes = tlRead(fhandle, buffer, 0x8000);
  372.             total += (unsigned long)bytes;
  373.             if(bytes != 0x8000)
  374.             {
  375.                 return((LONG)total);
  376.             }
  377.             buffer += bytes;
  378.         }
  379.     }
  380.     bytes = tlRead(fhandle, buffer, rest);
  381.     total += (unsigned long)bytes;
  382.     return((LONG)total);
  383. }
  384.  
  385. LONG littleRead(fhandle,buffer,size)
  386. SHORT fhandle;
  387. LONGPTR buffer;
  388. LONG size;
  389. {
  390.     long bytes;
  391.  
  392.     bytes = tlRead(fhandle,buffer,size);
  393.     
  394.     return(bytes);
  395. }
  396.  
  397. void
  398. copybytes(to, from, amount)
  399. LONGPTR to;
  400. LONGPTR from;
  401. LONG amount;
  402. {
  403.     if(!to || !from)
  404.     {
  405.         return;
  406.     }
  407.     while(amount-- > 0)
  408.     {
  409.         *to++ = *from++;
  410.     }
  411. }
  412.  
  413. void
  414. debug(fmt)
  415. char *fmt;
  416.  
  417. {
  418. #ifndef  NODEBUG            /* vj, 11/10 */
  419.     va_list arg_ptr;
  420.     if(_TIFF_debug_flag)
  421.     {
  422. #ifndef NOWINDOWS
  423.         unsigned short hdc;
  424. #endif /* not NOWINDOWS */
  425.         int len;
  426.         va_start(arg_ptr, fmt);
  427.         len = vsprintf(temp, fmt, arg_ptr);
  428. #ifdef NOWINDOWS
  429.         write(1, temp, len);
  430. #else
  431.         if(temp[len - 1] == '\n')
  432.         {
  433.             temp[--len] = '\0';
  434.         }
  435.         hdc = GetDC(MainWindow);
  436.         TextOut(hdc, 40, 40, (LONGPTR)temp, len);
  437.         ReleaseDC(MainWindow, hdc);
  438. #endif /* NOWINDOWS */
  439.         va_end(arg_ptr);
  440.     }
  441. #endif     /* no debug */
  442. }
  443.