Category : C Source Code
Archive   : TIFTOOL.ZIP
Filename : TIFF.C
*
* Created 88-10-31, out of rev 3.8.
*/
#include "aldtypes.h"
#include "aldmem.h"
#include "aldutils.h"
#include "imtypes.h"
#include "swap.h"
#include "immem.h"
#include "vio.h"
#include "imag.h"
#include "imtiff.h"
#include "tiff.h"
#include "ImErr.h"
#include "ImErr2.h" /* application-dependent! for WarningAlert proto and IA_PLACE_IMAGE */
#include "tiffrout.h"
extern char *ErrorMessages;
#define min(x,y) (((y)<(x)) ? (y) : (x))
#define MAXBYTE 255
/************************ mostly local procedures *************************/
/* get data -- handles file/table and byte-order problems
* 64K max
*/
RC GtData (pDloc, order, pos, n, dtype, lpData)
PDLOC pDloc; /* data location - open file or locked-down table */
WORD order; /* byte order -- INTELTIFF or MOTOROLATIFF */
DWORD pos; /* file/table position, with respect to its beginning */
WORD n; /* number of data elements to read */
WORD dtype; /* data type: TIFFSHORT, etc */
LPSTR lpData; /* where to put the data */
{
RC err;
WORD tsize;
WORD BytesToRead;
if (n == 0)
goto done;
/* read the data
*/
if (err = GtTiffSizeof (dtype, &tsize)) {
DBMSG(("GtData: bad dtype\n"));
return err;
}
BytesToRead = tsize * n;
if (err = VRead (pDloc, pos, BytesToRead, lpData)) {
DBMSG(("GtData: VRead\n"));
DBMSG((" err=%u pos=%lu BytesToRead=%u\n",
err,pos,BytesToRead));
return err;
}
/* change the byte order, if necessary
*/
if (order != MOTOROLATIFF && order != INTELTIFF) {
DBMSG(("GtData: bad byte order: %u\n", order));
return IM_BUG; /* should have been caught earlier */
}
#ifdef WINDOWS
if (order == MOTOROLATIFF) {
#endif
#ifdef MACINTOSH
if (order == INTELTIFF) {
#endif
if (dtype == TIFFSHORT)
swab (lpData, lpData, BytesToRead);
else if (dtype == TIFFLONG)
swaw (lpData, lpData, BytesToRead);
else if (dtype == TIFFRATIONAL)
swaw (lpData, lpData, BytesToRead);
else if (dtype == TIFFSIGNED)
swab (lpData, lpData, BytesToRead);
}
/* return
*/
done: return SUCCESS;
}
#define CHUNKSIZE 32768L
/* get a possibly >64K chunk of data, by calling GtData repeatedly
*/
RC GtHugeData (pDloc, order, pos, dwN, dtype, lpData)
PDLOC pDloc; /* data location - open file or locked-down table */
WORD order; /* INTELTIFF or MOTOROLATIFF */
DWORD pos; /* file/table position, with respect to its beginning */
DWORD dwN; /* number of data elements to read */
WORD dtype; /* data type: TIFFSHORT, etc */
LPSTR lpData; /* where to put the data */
{
RC err = SUCCESS;
WORD tsize;
DWORD ElementsLeft;
DWORD ElementsToRead;
LPSTR lpOut = lpData;
DWORD ElementsPerChunk;
/* DBMSG(("GtHugeData: top\n")); */
/* get size of elements
*/
if (err = GtTiffSizeof (dtype, &tsize)) {
DBMSG(("GtHugeData: bad dtype\n"));
return err;
}
/* calculate number of elements per chunk
*/
ElementsPerChunk = CHUNKSIZE / tsize;
/* DBMSG((" ElementsPerChunk=%lu\n",ElementsPerChunk)); */
/* read repeatedly
*/
ElementsLeft = dwN;
while (ElementsLeft > 0L) {
ElementsToRead = min (ElementsPerChunk, ElementsLeft);
/* DBMSG((" ElementsToRead=%lu\n",ElementsToRead)); */
if (err = GtData (pDloc, order, pos, (WORD)ElementsToRead,
dtype, lpOut)) {
DBMSG(("GtHugeData: GtData\n"));
goto cu;
}
lpOut += ElementsToRead * tsize;
ElementsLeft -= ElementsToRead;
/* DBMSG((" ElementsLeft=%lu\n",ElementsLeft)); */
}
/* DBMSG(("GtHugeData: bottom\n")); */
cu: return err;
}
/* get TIFF 8-byte header
* currently only probably portable. depends somewhat on compiler's
* structure organization.
*/
RC GtTiffHdr (pDloc, pHdr)
PDLOC pDloc;
register TIFFHDR *pHdr;
{
RC err;
/* get the first word -- the byte order.
* first, set dlOrder to either valid value, since we will immediately
* change it. sort of a chicken and egg situation.
*/
/* pDloc->dlOrder = INTELTIFF; */
if (err = GtData (pDloc, INTELTIFF, (DWORD) 0, 1, TIFFSHORT,
(LPSTR)&pHdr->thByteOrder)) {
DBMSG(("GtTiffHdr: A\n"));
return err;
}
/* *pOrder = pHdr->thByteOrder; */
/* get the version
*/
if (err = GtData (pDloc, pHdr->thByteOrder, (DWORD) 2, 1, TIFFSHORT,
(LPSTR)&pHdr->thVersion)) {
DBMSG(("GtTiffHdr: AA\n"));
return err;
}
/* get the double word (IFD offset)
*/
if (err = GtData (pDloc, pHdr->thByteOrder, (DWORD)4, 1, TIFFLONG,
(LPSTR)&pHdr->thIfdOffset)) {
DBMSG(("GtTiffHdr: B\n"));
return err;
}
#if 0
DBMSG(("GtTiffHdr: ByteOrder=%x Version=%u IfdOffset=%lu\n",
pHdr->thByteOrder, pHdr->thVersion, pHdr->thIfdOffset));
#endif /* 0 */
/* return
*/
return SUCCESS;
}
/* get TIFF directory entry
*/
RC GtTiffEntry (pDloc, order, EntryOffset, pDe)
PDLOC pDloc;
WORD order;
DWORD EntryOffset;
register DIRENTRY *pDe;
{
RC err;
DWORD BytesToRead;
WORD tsize;
WORD wTmp;
/* get the 2 words beginning with deTag
*/
if (err = GtData (pDloc, order, EntryOffset, 2, TIFFSHORT,
(LPSTR)&pDe->deTag)) {
DBMSG(("GtTiffEntry: A\n"));
return err;
}
/* get the 2 dwords, beginning with deLength
*/
if (err = GtData (pDloc, order, EntryOffset + 4L, 2, TIFFLONG,
(LPSTR)&pDe->deLength)) {
DBMSG(("GtTiffEntry: B\n"));
return err;
}
/* fix up deVal, if it's not really a LONG
*/
#ifdef WINDOWS
if (order == MOTOROLATIFF) {
#endif
#ifdef MACINTOSH
if (order == INTELTIFF) {
#endif
if (err = GtTiffSizeof (pDe->deType, &tsize)) {
DBMSG(("GtTiffEntry: GtTiffSizeof\n"));
WARN ((HWND)NULL, IM_WARNING, IM_BAD_TTYPE);
return err;
}
BytesToRead = (DWORD)tsize * pDe->deLength;
if (BytesToRead <= 4) {
if (tsize == 2) { /* swap words */
wTmp = * (WORD *) &pDe->deVal;
* (WORD *) &pDe->deVal = * ((WORD *) &pDe->deVal + 1);
* ((WORD *) &pDe->deVal + 1) = wTmp;
}
else if (tsize == 1) { /* swap bytes */
swaw ((LPSTR)&pDe->deVal, (LPSTR)&pDe->deVal, 4);
}
}
}
/* return
*/
return SUCCESS;
}
/* Fill a Tiff Field structure
* Note: the caller should probably not totally die upon getting an error.
* Private data types are possible, for one thing. Just don't set the
* existence flag for the field.
*/
RC FillTField ARGS((PDLOC,WORD,DIRENTRY *,DWORD,TFIELD *));
LOCAL RC FillTField (pDloc, order, pDe, EntryOffset, pTF)
PDLOC pDloc;
WORD order;
register DIRENTRY *pDe;
DWORD EntryOffset;
register TFIELD *pTF;
{
RC err = SUCCESS;
HANDLE h;
LPSTR lp;
WORD TypeSize;
DWORD BytesToRead;
/* copy tag, type, and length from DIRENTRY structure
*/
pTF->Texists = TRUE;
pTF->Ttag = pDe->deTag;
pTF->Ttype = pDe->deType;
pTF->Tlength = pDe->deLength;
/* record the offset, for possible later modify-in-place action
*/
pTF->Tentryoffset = EntryOffset;
/* calculate needed space
*/
if (err = GtTiffSizeof (pTF->Ttype, &TypeSize)) {
DBMSG(("FillTField: unknown type\n"));
goto cu0;
}
BytesToRead = (DWORD)TypeSize * pTF->Tlength;
/* if <= 4 bytes, we're almost done. else we have to do some
* work.
*/
pTF->Talloc = FALSE; /* just to be safe */
if (BytesToRead <= 4) {
pTF->val.Tdword = pDe->deVal;
}
else {
/* allocate and lock a buffer
*/
if (!(h = MMAlloc (BytesToRead))) {
DBMSG(("FillTField: h\n"));
err = IM_MEM_FULL;
goto cu0;
}
if (!(lp = MMLock (h))) {
DBMSG(("FillTField: lp\n"));
err = IM_MEM_FAIL;
MMFree (h);
goto cu0;
}
/* read the data
*/
if (err = GtHugeData (pDloc, order, pDe->deVal, pDe->deLength,
pDe->deType, lp)) {
DBMSG(("FillTField: GtHugeData\n"));
MMUnlock (h);
MMFree (h);
goto cu0;
}
/* make sure that the val union contains the first N values from
* the memory buffer, so that we can use things like p->iBitsPerSample
* constructs even if there are 3 BitsPerSample values.
*/
lmemcpy ((LPSTR) &pTF->val.Tchar[0], lp, 4);
/* unlock the buffer
*/
MMUnlock (h);
/* stuff the handle into the TFIELD structure
*/
pTF->Thandle = h;
pTF->Talloc = TRUE;
} /* end of greater-than-4-byte case */
/* return
*/
cu0: return err;
}
RC TypeConvert ARGS((TFIELD *, WORD));
LOCAL RC TypeConvert (pTF, totype)
register TFIELD *pTF;
WORD totype; /* TIFFBYTE, etc */
{
RC err = SUCCESS;
WORD fromtype;
DWORD dwLength;
WORD SrcSize;
DWORD SrcBytes;
DWORD SrcVal;
LPSTR lpSrc;
WORD DstSize;
DWORD DstBytes;
DWORD DstVal;
LPSTR lpDst;
HANDLE hDst = (HANDLE)NULL;
/* DBMSG(("TypeConvert: top\n")); */
/* shorthands:
*/
fromtype = pTF->Ttype;
dwLength = pTF->Tlength;
/* DBMSG(("tfield:\n"));
* DBMSG((" Talloc=%u Ttag=%u Ttype=%u Tlength=%lu val=%lx\n",
* pTF->Talloc,pTF->Ttag,pTF->Ttype,pTF->Tlength,pTF->val.Tdword));
*/
/* if the same type, do nothing
*/
if (totype == fromtype) {
goto done;
}
/* calculate number of source bytes
*/
if (err = GtTiffSizeof (fromtype, &SrcSize)) {
DBMSG(("TypeConvert: bad dtype src\n"));
goto done;
}
SrcBytes = (DWORD)SrcSize * dwLength;
/* point to source data
*/
if (SrcBytes <= (DWORD)4) {
if (pTF->Talloc) {
DBMSG(("TypeConvert: size error A\n"));
err = IM_BUG; /* programming error */
goto done;
}
SrcVal = pTF->val.Tdword;
lpSrc = (LPSTR)&SrcVal;
} else {
if (!pTF->Talloc) {
DBMSG(("TypeConvert: size error B\n"));
err = IM_BUG; /* programming error */
goto done;
}
if (pTF->Thandle == (HANDLE)NULL) {
DBMSG(("TypeConvert: null handle\n"));
err = IM_BUG; /* programming error */
goto done;
}
if ((lpSrc = MMLock (pTF->Thandle)) == (LPSTR)NULL) {
DBMSG(("TypeConvert: Thandle\n"));
err = IM_MEM_FAIL;
goto done;
}
}
/* calculate number of destination bytes
*
* In the case of ASCII source and integer or
* floating point destination, we are going to
* allocate too much space, and quite possibly
* allocate when the result would fit into 4
* bytes, so make sure we take that into consideration
* below.
*/
if (err = GtTiffSizeof (totype, &DstSize)) {
DBMSG(("TypeConvert: bad dtype dst\n"));
if (pTF->Talloc) MMUnlock (pTF->Thandle);
goto done;
}
DstBytes = (DWORD)DstSize * dwLength;
/* point to destination data
*/
if (DstBytes <= (DWORD)4)
lpDst = (LPSTR)&DstVal;
else {
if (err = GetItLockIt (DstBytes, &hDst,
(LPBYTE *)&lpDst)) {
DBMSG(("TypeConvert: hDst\n"));
if (pTF->Talloc) MMUnlock (pTF->Thandle);
goto done;
}
}
/* convert depending on source and destination type
*/
{
/* if TIFFRATIONAL, convert to floating point or
* integer. Note that I am relaxing the definition
* of RATIONAL to include negative numbers.
*/
if (fromtype == TIFFRATIONAL &&
(totype == TIFFFLOAT || totype == TIFFSIGNED ||
totype == TIFFSHORT)) {
register long FAR *lpSrcPtr; /* assumption: long & DWORD are same length */
register LPSTR lpDstPtr;
register DWORD dwCnt;
float FloatVal;
short ShortVal;
/* set up
*/
lpSrcPtr = (long FAR *)lpSrc;
lpDstPtr = lpDst;
/* for each rational...
*/
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
/* calculate a float equivalent
*/
if (*(lpSrcPtr +1) == (DWORD)0) {
FloatVal = (float)0.0;
} else {
FloatVal = (float)*lpSrcPtr / (float)*(lpSrcPtr+1);
}
/* translate if necessary, and store
* into the destination array
*/
if (totype == TIFFFLOAT) {
*((float FAR *)lpDstPtr) = FloatVal;
} else {
if (FloatVal >= (float)0.0) {
ShortVal = (short)(FloatVal + .5);
} else {
/* is this right? */
ShortVal = (short)(FloatVal - .5);
}
}
if (totype == TIFFSHORT) {
*((LPWORD)lpDstPtr) = (WORD)ShortVal;
} else if (totype == TIFFSIGNED) {
*((short FAR *)lpDstPtr) = ShortVal;
}
/* increment the pointers
*/
lpSrcPtr++;
lpDstPtr += DstSize;
}
/* make sure that the val section contains the first N values from
* the destination array
*/
if (DstBytes > (DWORD)4) {
lmemcpy ((LPSTR) &pTF->val.Tdword, (LPSTR)lpDst, 4);
}
/* set the new type
*/
pTF->Ttype = totype;
} /* end of rational to float/short/WORD section */
/* else if an unsigned integer (TIFFBYTE, TIFFSHORT, or TIFFLONG),
* do the appropriate conversion. I probably should check for
* problems when converting to something smaller. TODO.
*/
else if ((fromtype == TIFFBYTE || fromtype == TIFFSHORT ||
fromtype == TIFFLONG) &&
(totype == TIFFBYTE || totype == TIFFSHORT ||
totype == TIFFLONG)) {
register LPSTR lpSrcPtr = lpSrc;
register LPSTR lpDstPtr = lpDst;
register DWORD dwCnt;
register WORD TiffShort;
register DWORD TiffLong;
if (fromtype == TIFFBYTE && totype == TIFFSHORT) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
*((LPWORD)lpDstPtr) = (WORD)*((LPBYTE)lpSrcPtr);
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFBYTE && totype == TIFFLONG) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
*((LPDWORD)lpDstPtr) = (DWORD)*((LPBYTE)lpSrcPtr);
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFSHORT && totype == TIFFBYTE) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
TiffShort = *((LPWORD)lpSrcPtr);
if (TiffShort > MAXBYTE) {
TiffShort = MAXBYTE;
}
*((LPBYTE)lpDstPtr) = (BYTE)TiffShort;
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFSHORT && totype == TIFFLONG) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
*((LPDWORD)lpDstPtr) = (DWORD)*((LPWORD)lpSrcPtr);
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFLONG && totype == TIFFBYTE) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
TiffLong = *((LPDWORD)lpSrcPtr);
if (TiffLong > MAXWORD) {
TiffLong = MAXWORD;
}
*((LPBYTE)lpDstPtr) = (BYTE)TiffLong;
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFLONG && totype == TIFFSHORT) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
TiffLong = *((LPDWORD)lpSrcPtr);
if (TiffLong > MAXWORD) {
TiffLong = MAXWORD;
}
*((LPWORD)lpDstPtr) = (WORD)TiffLong;
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
}
/* make sure that the val section contains the first N values from
* the destination array, so that I can have a 3-valued BitsPerSample
* (forced to be the same) but still get "the" BitsPerSample value
* by using the p->iBitsPerSample contruct
*/
if (DstBytes > (DWORD)4) {
lmemcpy ((LPSTR) &pTF->val.Tdword, (LPSTR)lpDst, 4);
}
/* set the new type
*/
pTF->Ttype = totype;
} /* end of unsigned section */
/* else if none of the above cases, give up.
*/
else {
DBMSG(("TypeConvert: type problem. fromtype=%d totype=%d\n",
fromtype, totype));
if (pTF->Talloc) MMUnlock (pTF->Thandle);
if (hDst) {
UnlockItFreeIt (hDst);
hDst = (HANDLE) NULL;
}
err = IM_BUG; /* programming error */
goto done;
}
} /* end of conversion section */
/* if neither the source nor destination is allocated,
* just copy into the 4-byte value
*/
if (!pTF->Talloc && !hDst) {
pTF->val.Tdword = DstVal;
}
/* else if source and destination are both allocated,
* free the old buffer, and store the new destination handle
*/
else if (pTF->Talloc && hDst) {
UnlockItFreeIt (pTF->Thandle);
pTF->Thandle = hDst;
MMUnlock (hDst);
}
/* else if destination is allocated, but not the source,
* just store the new destination handle
*/
else if (!pTF->Talloc && hDst) {
pTF->Thandle = hDst;
MMUnlock (pTF->Thandle);
pTF->Talloc = TRUE;
}
/* else if source is allocated, but not the destination,
* unlock and free the buffer, and copy the value.
*/
else if (pTF->Talloc && !hDst) {
UnlockItFreeIt (pTF->Thandle);
pTF->Talloc = FALSE;
pTF->val.Tdword = DstVal;
}
/* return
*/
done: return err;
}
/* check for bad values, convert from one format to another
* if necessary, and store the information in the appropriate
* TFIELD structure in the IMAG structure
*/
RC NicefyTField ARGS((TFIELD *, IMAG *));
RC NicefyTField (pTF, x)
register TFIELD *pTF;
register IMAG *x;
{
RC err = SUCCESS;
register WORD Tag;
Tag = pTF->Ttag;
/* DBMSG(("Nicefy: unsigned tag=%u signed tag=%d\n",
* pTF->Ttag, pTF->Ttag));
*/
if (Tag == TGNEWSUBFILETYPE) {
if (err = TypeConvert (pTF, TIFFLONG))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_NEWSUBFILETYPE] = *pTF; /* structure copy */
} else if (Tag == TGIMAGEWIDTH) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_IMAGEWIDTH] = *pTF; /* structure copy */
} else if (Tag == TGIMAGELENGTH) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_IMAGELENGTH] = *pTF; /* structure copy */
} else if (Tag == TGBITSPERSAMPLE) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_BITSPERSAMPLE] = *pTF; /* structure copy */
} else if (Tag == TGCOMPRESSION) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_COMPRESSION] = *pTF; /* structure copy */
} else if (Tag == TGPHOTOMETRICINTERPRETATION) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_PHOTOMETRICINTERP] = *pTF; /* structure copy */
} else if (Tag == TGSTRIPOFFSETS) {
if (err = TypeConvert (pTF, TIFFLONG))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_STRIPOFFSETS] = *pTF; /* structure copy */
} else if (Tag == TGSAMPLESPERPIXEL) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_SAMPLES] = *pTF; /* structure copy */
} else if (Tag == TGSTRIPBYTECOUNTS) {
if (err = TypeConvert (pTF, TIFFLONG))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_STRIPBYTECOUNTS] = *pTF; /* structure copy */
} else if (Tag == TGROWSPERSTRIP) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_ROWSPERSTRIP] = *pTF; /* structure copy */
} else if (Tag == TGXRESOLUTION) {
if (err = TypeConvert (pTF, TIFFFLOAT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_XRESOLUTION] = *pTF; /* structure copy */
if (x->fXResolution == (float)0.0)
x->fXResolution = (float)300.0;
} else if (Tag == TGYRESOLUTION) {
if (err = TypeConvert (pTF, TIFFFLOAT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_YRESOLUTION] = *pTF; /* structure copy */
if (x->fYResolution == (float)0.0)
x->fYResolution = (float)300.0;
} else if (Tag == TGPLANARCONFIGURATION) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
#if 0
pTF->Texists = TRUE;
x->tf[X_PLANAR] = *pTF; /* structure copy */
#endif
} else if (Tag == TGGRAYUNIT) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_GRAYUNIT] = *pTF; /* structure copy */
} else if (Tag == TGGRAYCURVE) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_GRAYCURVE] = *pTF; /* structure copy */
} else if (Tag == TGRESOLUTIONUNIT) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_RESOLUTIONUNIT] = *pTF; /* structure copy */
} else if (Tag == TGPREDICTOR) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_PREDICTOR] = *pTF; /* structure copy */
} else {
/* DBMSG(("GtTiffInfo: unrecognized tag %d\n",de.deTag)); */
/*
* no big deal, probably.
*/
}
cu0: return err;
}
/************************ exported procedures **********************/
/* read all the TIFF fields that we care about.
* if from file, it should be open for read.
* currently, subsequent IFD's are ignored.
*
* make sure you fill out the DLOC structure before calling this routine.
*/
RC GtTiffInfo (pDloc, x)
PDLOC pDloc; /* table/file input structure */
register IMAG *x; /* this is where the field information will be put */
{
RC err = SUCCESS;
TIFFHDR th;
DIRENTRY de;
TFIELD tf;
WORD IfdEntries;
DWORD NextIfd;
DWORD EntryOffset;
WORD ii;
DWORD location;
/* DBMSG(("GtTiffInfo: top\n")); */
/* initialize the structure
*/
InitImag (x);
/* get the 8-byte header
*/
if (err = GtTiffHdr (pDloc, &th)) {
DBMSG(("GtTiffInfo(): can't read header.\n"));
goto cu0;
}
x->iFileType = th.thByteOrder;
/* pDloc->dlOrder = th.thByteOrder; */
/* check version
*/
if (th.thVersion != VERSION42) {
DBMSG(("GtTiffInfo: wrong version\n"));
err = IM_BUG; /* should have been caught earlier */
goto cu0;
}
x->iVersion = th.thVersion;
/* read the number of directory entries
*/
if (err = GtData (pDloc, th.thByteOrder, th.thIfdOffset, 1, TIFFSHORT,
(LPSTR)&IfdEntries)) {
DBMSG(("GtTiffInfo: can't read # of dir entries\n"));
goto cu0;
}
/* loop through the entries
*/
EntryOffset = th.thIfdOffset + sizeof(IfdEntries);
for (ii = 0; ii < IfdEntries; ii++, EntryOffset += sizeof(de)) {
/* read the entry
*/
if (err = GtTiffEntry (pDloc, th.thByteOrder, EntryOffset, &de)) {
DBMSG(("GtTiffInfo: can't read entry.\n"));
err = SUCCESS;
continue;
}
/* convert to a TFIELD structure, reading big fields as necessary
*/
if (err = FillTField (pDloc, th.thByteOrder, &de, EntryOffset, &tf)) {
DBMSG(("GtTiffInfo: FillTField\n"));
err = SUCCESS;
continue;
}
/* check for bad values, convert from one format to another
* if necessary, and store the information in the appropriate
* TFIELD structure in the IMAG structure
*/
if (err = NicefyTField (&tf, x)) {
DBMSG(("GtTiffInfo: NicefyTField\n"));
err = SUCCESS;
continue;
}
} /* end of direntry loop */
/* check the offset of the next IFD
*/
{
DWORD NextIFD;
WORD Dummy;
if (err = GtData (pDloc, th.thByteOrder, EntryOffset, 1, TIFFLONG,
(LPSTR)&NextIFD)) {
DBMSG(("GtTiffInfo: can't read next-IFD-offset\n"));
err = IM_BAD_NEXT_IFD;
goto cu0;
}
if (err = GtData (pDloc, th.thByteOrder, NextIFD, 1, TIFFSHORT,
(LPSTR)&Dummy)) {
DBMSG(("GtTiffInfo: can't read next IFD\n"));
err = IM_BAD_NEXT_IFD;
goto cu0;
}
}
/* miscellaneous correctness checks
*/
if (err = CheckTiff (x)) {
/* DBMSG((" CheckTiff\n")); */
goto cu0;
}
/* return
*/
cu0: return err;
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/