📄 tif_dirread.c
字号:
case TIFF_SBYTE: if (!TIFFFetchByteArray(tif, dir, (uint16*) v)) return (0); if (dir->tdir_type == TIFF_BYTE) { uint16* vp = (uint16*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } else { int16* vp = (int16*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } break; case TIFF_SHORT: case TIFF_SSHORT: if (!TIFFFetchShortArray(tif, dir, (uint16*) v)) return (0); if (dir->tdir_type == TIFF_SHORT) { uint16* vp = (uint16*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } else { int16* vp = (int16*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } break; case TIFF_LONG: case TIFF_SLONG: if (!TIFFFetchLongArray(tif, dir, (uint32*) v)) return (0); if (dir->tdir_type == TIFF_LONG) { uint32* vp = (uint32*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } else { int32* vp = (int32*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } break; case TIFF_RATIONAL: case TIFF_SRATIONAL: if (!TIFFFetchRationalArray(tif, dir, (float*) v)) return (0); { float* vp = (float*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } break; case TIFF_FLOAT: if (!TIFFFetchFloatArray(tif, dir, (float*) v)) return (0); { float* vp = (float*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } break; case TIFF_DOUBLE: return (TIFFFetchDoubleArray(tif, dir, (double*) v)); default: /* TIFF_NOTYPE */ /* TIFF_ASCII */ /* TIFF_UNDEFINED */ TIFFError(tif->tif_name, "Cannot read TIFF_ANY type %d for field \"%s\"", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); return (0); } return (1);}/* * Fetch a tag that is not handled by special case code. */static intTIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp){ static const char mesg[] = "to fetch tag value"; int ok = 0; const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->tdir_tag); if (dp->tdir_count > 1) { /* array of values */ char* cp = NULL; switch (dp->tdir_type) { case TIFF_BYTE: case TIFF_SBYTE: /* NB: always expand BYTE values to shorts */ cp = CheckMalloc(tif, dp->tdir_count * sizeof (uint16), mesg); ok = cp && TIFFFetchByteArray(tif, dp, (uint16*) cp); break; case TIFF_SHORT: case TIFF_SSHORT: cp = CheckMalloc(tif, dp->tdir_count * sizeof (uint16), mesg); ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp); break; case TIFF_LONG: case TIFF_SLONG: cp = CheckMalloc(tif, dp->tdir_count * sizeof (uint32), mesg); ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp); break; case TIFF_RATIONAL: case TIFF_SRATIONAL: cp = CheckMalloc(tif, dp->tdir_count * sizeof (float), mesg); ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp); break; case TIFF_FLOAT: cp = CheckMalloc(tif, dp->tdir_count * sizeof (float), mesg); ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp); break; case TIFF_DOUBLE: cp = CheckMalloc(tif, dp->tdir_count * sizeof (double), mesg); ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp); break; case TIFF_ASCII: case TIFF_UNDEFINED: /* bit of a cheat... */ /* * Some vendors write strings w/o the trailing * NULL byte, so always append one just in case. */ cp = CheckMalloc(tif, dp->tdir_count+1, mesg); if( (ok = (cp && TIFFFetchString(tif, dp, cp))) != 0 ) cp[dp->tdir_count] = '\0'; /* XXX */ break; } if (ok) { ok = (fip->field_passcount ? TIFFSetField(tif, dp->tdir_tag, dp->tdir_count, cp) : TIFFSetField(tif, dp->tdir_tag, cp)); } if (cp != NULL) _TIFFfree(cp); } else if (CheckDirCount(tif, dp, 1)) { /* singleton value */ switch (dp->tdir_type) { case TIFF_BYTE: case TIFF_SBYTE: case TIFF_SHORT: case TIFF_SSHORT: /* * If the tag is also acceptable as a LONG or SLONG * then TIFFSetField will expect an uint32 parameter * passed to it (through varargs). Thus, for machines * where sizeof (int) != sizeof (uint32) we must do * a careful check here. It's hard to say if this * is worth optimizing. * * NB: We use TIFFFieldWithTag here knowing that * it returns us the first entry in the table * for the tag and that that entry is for the * widest potential data type the tag may have. */ { TIFFDataType type = fip->field_type; if (type != TIFF_LONG && type != TIFF_SLONG) { uint16 v = (uint16) TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); ok = (fip->field_passcount ? TIFFSetField(tif, dp->tdir_tag, 1, &v) : TIFFSetField(tif, dp->tdir_tag, v)); break; } } /* fall thru... */ case TIFF_LONG: case TIFF_SLONG: { uint32 v32 = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); ok = (fip->field_passcount ? TIFFSetField(tif, dp->tdir_tag, 1, &v32) : TIFFSetField(tif, dp->tdir_tag, v32)); } break; case TIFF_RATIONAL: case TIFF_SRATIONAL: case TIFF_FLOAT: { float v = (dp->tdir_type == TIFF_FLOAT ? TIFFFetchFloat(tif, dp) : TIFFFetchRational(tif, dp)); ok = (fip->field_passcount ? TIFFSetField(tif, dp->tdir_tag, 1, &v) : TIFFSetField(tif, dp->tdir_tag, v)); } break; case TIFF_DOUBLE: { double v; ok = (TIFFFetchDoubleArray(tif, dp, &v) && (fip->field_passcount ? TIFFSetField(tif, dp->tdir_tag, 1, &v) : TIFFSetField(tif, dp->tdir_tag, v)) ); } break; case TIFF_ASCII: case TIFF_UNDEFINED: /* bit of a cheat... */ { char c[2]; if( (ok = (TIFFFetchString(tif, dp, c) != 0)) != 0 ){ c[1] = '\0'; /* XXX paranoid */ ok = TIFFSetField(tif, dp->tdir_tag, c); } } break; } } return (ok);}#define NITEMS(x) (sizeof (x) / sizeof (x[0]))/* * Fetch samples/pixel short values for * the specified tag and verify that * all values are the same. */static intTIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, int* pl){ int samples = tif->tif_dir.td_samplesperpixel; int status = 0; if (CheckDirCount(tif, dir, (uint32) samples)) { uint16 buf[10]; uint16* v = buf; if (samples > NITEMS(buf)) v = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); if (TIFFFetchShortArray(tif, dir, v)) { int i; for (i = 1; i < samples; i++) if (v[i] != v[0]) { TIFFError(tif->tif_name, "Cannot handle different per-sample values for field \"%s\"", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); goto bad; } *pl = v[0]; status = 1; } bad: if (v != buf) _TIFFfree((char*) v); } return (status);}/* * Fetch samples/pixel ANY values for * the specified tag and verify that * all values are the same. */static intTIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl){ int samples = (int) tif->tif_dir.td_samplesperpixel; int status = 0; if (CheckDirCount(tif, dir, (uint32) samples)) { double buf[10]; double* v = buf; if (samples > NITEMS(buf)) v = (double*) _TIFFmalloc(samples * sizeof (double)); if (TIFFFetchAnyArray(tif, dir, v)) { int i; for (i = 1; i < samples; i++) if (v[i] != v[0]) { TIFFError(tif->tif_name, "Cannot handle different per-sample values for field \"%s\"", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); goto bad; } *pl = v[0]; status = 1; } bad: if (v != buf) _TIFFfree(v); } return (status);}#undef NITEMS/* * Fetch a set of offsets or lengths. * While this routine says "strips", * in fact it's also used for tiles. */static intTIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp){ register uint32* lp; int status; if (!CheckDirCount(tif, dir, (uint32) nstrips)) return (0); /* * Allocate space for strip information. */ if (*lpp == NULL && (*lpp = (uint32 *)CheckMalloc(tif, nstrips * sizeof (uint32), "for strip array")) == NULL) return (0); lp = *lpp; if (dir->tdir_type == (int)TIFF_SHORT) { /* * Handle uint16->uint32 expansion. */ uint16* dp = (uint16*) CheckMalloc(tif, dir->tdir_count* sizeof (uint16), "to fetch strip tag"); if (dp == NULL) return (0); if( (status = TIFFFetchShortArray(tif, dir, dp)) != 0 ) { register uint16* wp = dp; while (nstrips-- > 0) *lp++ = *wp++; } _TIFFfree((char*) dp); } else status = TIFFFetchLongArray(tif, dir, lp); return (status);}#define NITEMS(x) (sizeof (x) / sizeof (x[0]))/* * Fetch and set the ExtraSamples tag. */static intTIFFFetchExtraSamples(TIFF* tif, TIFFDirEntry* dir){ uint16 buf[10]; uint16* v = buf; int status; if (dir->tdir_count > NITEMS(buf)) v = (uint16*) _TIFFmalloc(dir->tdir_count * sizeof (uint16)); if (dir->tdir_type == TIFF_BYTE) status = TIFFFetchByteArray(tif, dir, v); else status = TIFFFetchShortArray(tif, dir, v); if (status) status = TIFFSetField(tif, dir->tdir_tag, dir->tdir_count, v); if (v != buf) _TIFFfree((char*) v); return (status);}#undef NITEMS#ifdef COLORIMETRY_SUPPORT/* * Fetch and set the RefBlackWhite tag. */static intTIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir){ static const char mesg[] = "for \"ReferenceBlackWhite\" array"; char* cp; int ok; if (dir->tdir_type == TIFF_RATIONAL) return (TIFFFetchNormalTag(tif, dir)); /* * Handle LONG's for backward compatibility. */ cp = CheckMalloc(tif, dir->tdir_count * sizeof (uint32), mesg); if( (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) != 0) { float* fp = (float*) CheckMalloc(tif, dir->tdir_count * sizeof (float), mesg); if( (ok = (fp != NULL)) != 0 ) { uint32 i; for (i = 0; i < dir->tdir_count; i++) fp[i] = (float)((uint32*) cp)[i]; ok = TIFFSetField(tif, dir->tdir_tag, fp); _TIFFfree((char*) fp); } } if (cp) _TIFFfree(cp); return (ok);}#endif/* * Replace a single strip (tile) of uncompressed data by * multiple strips (tiles), each approximately 8Kbytes. * This is useful for dealing with large images or * for dealing with machines with a limited amount * memory. */static voidChopUpSingleUncompressedStrip(TIFF* tif){ register TIFFDirectory *td = &tif->tif_dir; uint32 bytecount = td->td_stripbytecount[0]; uint32 offset = td->td_stripoffset[0]; tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes; tstrip_t strip, nstrips, rowsperstrip; uint32* newcounts; uint32* newoffsets; /* * Make the rows hold at least one * scanline, but fill 8k if possible. */ if (rowbytes > 8192) { stripbytes = rowbytes; rowsperstrip = 1; } else { rowsperstrip = 8192 / rowbytes; stripbytes = rowbytes * rowsperstrip; } /* never increase the number of strips in an image */ if (rowsperstrip >= td->td_rowsperstrip) return; nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes); newcounts = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32), "for chopped \"StripByteCounts\" array"); newoffsets = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32), "for chopped \"StripOffsets\" array"); if (newcounts == NULL || newoffsets == NULL) { /* * Unable to allocate new strip information, give * up and use the original one strip information. */ if (newcounts != NULL) _TIFFfree(newcounts); if (newoffsets != NULL) _TIFFfree(newoffsets); return; } /* * Fill the strip information arrays with * new bytecounts and offsets that reflect * the broken-up format. */ for (strip = 0; strip < nstrips; strip++) { if (stripbytes > (tsize_t) bytecount) stripbytes = bytecount; newcounts[strip] = stripbytes; newoffsets[strip] = offset; offset += stripbytes; bytecount -= stripbytes; } /* * Replace old single strip info with multi-strip info. */ td->td_stripsperimage = td->td_nstrips = nstrips; TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); _TIFFfree(td->td_stripbytecount); _TIFFfree(td->td_stripoffset); td->td_stripbytecount = newcounts; td->td_stripoffset = newoffsets;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -