Ejemplo n.º 1
0
/*
 * Append the data to the specified strip.
 *
 * NB: We don't check that there's space in the
 *     file (i.e. that strips do not overlap).
 */
static int
TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
{
	TIFFDirectory *td = &tif->tif_dir;
	static const char module[] = "TIFFAppendToStrip";

	if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
		/*
		 * No current offset, set the current strip.
		 */
		if (td->td_stripoffset[strip] != 0) {
			if (!SeekOK(tif, td->td_stripoffset[strip])) {
				TIFFError(module,
				    "%s: Seek error at scanline %lu",
				    tif->tif_name, (u_long) tif->tif_row);
				return (0);
			}
		} else
			td->td_stripoffset[strip] =
			    TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
		tif->tif_curoff = td->td_stripoffset[strip];
	}
	if (!WriteOK(tif, data, cc)) {
		TIFFError(module, "%s: Write error at scanline %lu",
		    tif->tif_name, (u_long) tif->tif_row);
		return (0);
	}
	tif->tif_curoff += cc;
	td->td_stripbytecount[strip] += cc;
	return (1);
}
Ejemplo n.º 2
0
static tsize_t
TIFFReadRawStrip1(TIFF* tif,
    tstrip_t strip, tdata_t buf, tsize_t size, const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

	if (!isMapped(tif)) {
		if (!SeekOK(tif, td->td_stripoffset[strip])) {
			TIFFError(module,
			    "%s: Seek error at scanline %lu, strip %lu",
			    tif->tif_name,
			    (u_long) tif->tif_row, (u_long) strip);
			return (-1);
		}
		if (!ReadOK(tif, buf, size)) {
			TIFFError(module, "%s: Read error at scanline %lu",
			    tif->tif_name, (u_long) tif->tif_row);
			return (-1);
		}
	} else {
		if (td->td_stripoffset[strip] + size > tif->tif_size) {
			TIFFError(module,
			    "%s: Seek error at scanline %lu, strip %lu",
			    tif->tif_name,
			    (u_long) tif->tif_row, (u_long) strip);
			return (-1);
		}
		memcpy(buf, tif->tif_base + td->td_stripoffset[strip], size);
	}
	return (size);
}
Ejemplo n.º 3
0
/*
 * Append the data to the specified strip.
 */
static int
TIFFAppendToStrip(TIFF *tif, tstrip_t strip, tidata_t data, tsize_t cc)
{
    static const char module[] = "TIFFAppendToStrip";
    TIFFDirectory     *td      = &tif->tif_dir;

    if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0)
    {
        assert(td->td_nstrips > 0);

        if (td->td_stripbytecount[strip] != 0
            && td->td_stripoffset[strip] != 0
            && td->td_stripbytecount[strip] >= cc)
        {
            /*
             * There is already tile data on disk, and the new tile
             * data we have to will fit in the same space.  The only
             * aspect of this that is risky is that there could be
             * more data to append to this strip before we are done
             * depending on how we are getting called.
             */
            if (!SeekOK(tif, td->td_stripoffset[strip]))
            {
                TIFFErrorExt(tif->tif_clientdata, module,
                             "Seek error at scanline %lu",
                             (unsigned long)tif->tif_row);
                return (0);
            }
        }
        else
        {
            /*
             * Seek to end of file, and set that as our location to
             * write this strip.
             */
            td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
        }

        tif->tif_curoff = td->td_stripoffset[strip];

        /*
         * We are starting a fresh strip/tile, so set the size to zero.
         */
        td->td_stripbytecount[strip] = 0;
    }

    if (!WriteOK(tif, data, cc))
    {
        TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
                     (unsigned long) tif->tif_row);
        return (0);
    }

    tif->tif_curoff               = tif->tif_curoff + cc;
    td->td_stripbytecount[strip] += cc;
    return (1);
}
Ejemplo n.º 4
0
static tmsize_t
TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

    if (!_TIFFFillStriles( tif ))
        return ((tmsize_t)(-1));

	assert((tif->tif_flags&TIFF_NOREADRAW)==0);
	if (!isMapped(tif)) {
		tmsize_t cc;

		if (!SeekOK(tif, td->td_stripoffset[tile])) {
			TIFFErrorExt(tif->tif_clientdata, module,
			    "Seek error at row %lu, col %lu, tile %lu",
			    (unsigned long) tif->tif_row,
			    (unsigned long) tif->tif_col,
			    (unsigned long) tile);
			return ((tmsize_t)(-1));
		}
		cc = TIFFReadFile(tif, buf, size);
		if (cc != size) {
			TIFFErrorExt(tif->tif_clientdata, module,
	"Read error at row %lu, col %lu; got " TIFF_UINT64_FORMAT " bytes, expected " TIFF_UINT64_FORMAT,
				     (unsigned long) tif->tif_row,
				     (unsigned long) tif->tif_col,
				     (TIFF_UINT64_T) cc,
				     (TIFF_UINT64_T) size);
			return ((tmsize_t)(-1));
		}
	} else {
		tmsize_t ma,mb;
		tmsize_t n;
		ma=(tmsize_t)td->td_stripoffset[tile];
		mb=ma+size;
		if (((uint64)ma!=td->td_stripoffset[tile])||(ma>tif->tif_size))
			n=0;
		else if ((mb<ma)||(mb<size)||(mb>tif->tif_size))
			n=tif->tif_size-ma;
		else
			n=size;
		if (n!=size) {
			TIFFErrorExt(tif->tif_clientdata, module,
"Read error at row %lu, col %lu, tile %lu; got " TIFF_UINT64_FORMAT " bytes, expected " TIFF_UINT64_FORMAT,
				     (unsigned long) tif->tif_row,
				     (unsigned long) tif->tif_col,
				     (unsigned long) tile,
				     (TIFF_UINT64_T) n,
				     (TIFF_UINT64_T) size);
			return ((tmsize_t)(-1));
		}
		_TIFFmemcpy(buf, tif->tif_base + ma, size);
	}
	return (size);
}
Ejemplo n.º 5
0
static tsize_t
TIFFReadRawTile1(TIFF* tif,
    ttile_t tile, tdata_t buf, tsize_t size, const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

	assert((tif->tif_flags&TIFF_NOREADRAW)==0);
	if (!isMapped(tif)) {
		tsize_t cc;

		if (!SeekOK(tif, td->td_stripoffset[tile])) {
			TIFFErrorExt(tif->tif_clientdata, module,
			    "%s: Seek error at row %ld, col %ld, tile %ld",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col,
			    (long) tile);
			return ((tsize_t) -1);
		}
		cc = TIFFReadFile(tif, buf, size);
		if (cc != size) {
			TIFFErrorExt(tif->tif_clientdata, module,
	    "%s: Read error at row %ld, col %ld; got %lu bytes, expected %lu",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col,
			    (unsigned long) cc,
			    (unsigned long) size);
			return ((tsize_t) -1);
		}
	} else {
		if (td->td_stripoffset[tile] + size > tif->tif_size) {
			TIFFErrorExt(tif->tif_clientdata, module,
    "%s: Read error at row %ld, col %ld, tile %ld; got %lu bytes, expected %lu",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col,
			    (long) tile,
			    (unsigned long) tif->tif_size - td->td_stripoffset[tile],
			    (unsigned long) size);
			return ((tsize_t) -1);
		}
		_TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[tile], size);
	}
	return (size);
}
Ejemplo n.º 6
0
/*
 * Write a contiguous directory item.
 */
static int
TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp)
{
	tsize_t cc;

	if (tif->tif_flags & TIFF_SWAB) {
		switch (dir->s.tdir_type) {
		case TIFF_SHORT:
		case TIFF_SSHORT:
			TIFFSwabArrayOfShort((uint16*) cp, TDIRGetEntryCount(tif,dir));
			break;
		case TIFF_LONG:
		case TIFF_SLONG:
		case TIFF_IFD:
		case TIFF_FLOAT:
			TIFFSwabArrayOfLong((uint32*) cp, TDIRGetEntryCount(tif,dir));
			break;
		case TIFF_LONG8:
		case TIFF_SLONG8:
		case TIFF_IFD8:
			TIFFSwabArrayOfLong8((uint64*) cp, TDIRGetEntryCount(tif,dir));
			break;
		case TIFF_RATIONAL:
		case TIFF_SRATIONAL:
			TIFFSwabArrayOfLong((uint32*) cp, 2 * TDIRGetEntryCount(tif,dir));
			break;
		case TIFF_DOUBLE:
			TIFFSwabArrayOfDouble((double*) cp, TDIRGetEntryCount(tif,dir));
			break;
		}
	}
	TDIRSetEntryOff(tif,dir,tif->tif_dataoff);
	cc = TDIRGetEntryCount(tif,dir) * TIFFDataWidth((TIFFDataType) dir->s.tdir_type);
	if (SeekOK(tif, tif->tif_dataoff) &&
	    WriteOK(tif, cp, cc)) {
		tif->tif_dataoff += ((cc + 1) & ~1);
		return (1);
	}
	TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
		"Error writing data for field \"%s\" (%d)",
		_TIFFFieldWithTag(tif, dir->s.tdir_tag)->field_name, TIFFGetErrno(tif));
	return (0);
}
Ejemplo n.º 7
0
/*
 * Fetch a contiguous directory item.
 */
static tsize_t
TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp)
{
	int w = tiffDataWidth[dir->tdir_type];
	tsize_t cc = dir->tdir_count * w;

	if (!isMapped(tif)) {
		if (!SeekOK(tif, dir->tdir_offset))
			goto bad;
		if (!ReadOK(tif, cp, cc))
			goto bad;
	} else {
		if (dir->tdir_offset + cc > tif->tif_size)
			goto bad;
		_TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc);
	}
	if (tif->tif_flags & TIFF_SWAB) {
		switch (dir->tdir_type) {
		case TIFF_SHORT:
		case TIFF_SSHORT:
			TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
			break;
		case TIFF_LONG:
		case TIFF_SLONG:
		case TIFF_FLOAT:
			TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
			break;
		case TIFF_RATIONAL:
		case TIFF_SRATIONAL:
			TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
			break;
		case TIFF_DOUBLE:
			TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
			break;
		}
	}
	return (cc);
bad:
	TIFFError(tif->tif_name, "Error fetching data for field \"%s\"",
	    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
	return ((tsize_t) 0);
}
Ejemplo n.º 8
0
static tsize_t
TIFFReadRawStrip1(TIFF* tif,
    tstrip_t strip, tdata_t buf, tsize_t size, const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

	if (!isMapped(tif)) {
		tsize_t cc;

		if (!SeekOK(tif, td->td_stripoffset[strip])) {
			TIFFError(module,
			    "%s: Seek error at scanline %lu, strip %lu",
			    tif->tif_name,
			    (unsigned long) tif->tif_row, (unsigned long) strip);
			return (-1);
		}
		cc = TIFFReadFile(tif, buf, size);
		if (cc != size) {
			TIFFError(module,
		"%s: Read error at scanline %lu; got %lu bytes, expected %lu",
			    tif->tif_name,
			    (unsigned long) tif->tif_row,
			    (unsigned long) cc,
			    (unsigned long) size);
			return (-1);
		}
	} else {
		if (td->td_stripoffset[strip] + size > tif->tif_size) {
			TIFFError(module,
    "%s: Read error at scanline %lu, strip %lu; got %lu bytes, expected %lu",
			    tif->tif_name,
			    (unsigned long) tif->tif_row,
			    (unsigned long) strip,
			    (unsigned long) tif->tif_size - td->td_stripoffset[strip],
			    (unsigned long) size);
			return (-1);
		}
		_TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[strip],
                            size);
	}
	return (size);
}
Ejemplo n.º 9
0
static tsize_t
TIFFReadRawTile1(TIFF* tif,
    ttile_t tile, tdata_t buf, tsize_t size, const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

	if (!isMapped(tif)) {
		if (!SeekOK(tif, td->td_stripoffset[tile])) {
			TIFFError(module,
			    "%s: Seek error at row %ld, col %ld, tile %ld",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col,
			    (long) tile);
			return ((tsize_t) -1);
		}
		if (!ReadOK(tif, buf, size)) {
			TIFFError(module, "%s: Read error at row %ld, col %ld",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col);
			return ((tsize_t) -1);
		}
	} else {
		if (td->td_stripoffset[tile] + size > tif->tif_size) {
			TIFFError(module,
			    "%s: Seek error at row %ld, col %ld, tile %ld",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col,
			    (long) tile);
			return ((tsize_t) -1);
		}
		memcpy(buf, tif->tif_base + td->td_stripoffset[tile], size);
	}
	return (size);
}
Ejemplo n.º 10
0
/*
 * Write a contiguous directory item.
 */
static int
TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp)
{
    tsize_t cc;

    if (tif->tif_flags & TIFF_SWAB) {
        switch (dir->tdir_type) {
        case TIFF_SHORT:
        case TIFF_SSHORT:
            TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
            break;
        case TIFF_LONG:
        case TIFF_SLONG:
        case TIFF_FLOAT:
            TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
            break;
        case TIFF_RATIONAL:
        case TIFF_SRATIONAL:
            TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
            break;
        case TIFF_DOUBLE:
            TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
            break;
        }
    }
    dir->tdir_offset = tif->tif_dataoff;
    cc = dir->tdir_count * TIFFDataWidth((TIFFDataType) dir->tdir_type);
    if (SeekOK(tif, dir->tdir_offset) &&
            WriteOK(tif, cp, cc)) {
        tif->tif_dataoff += (cc + 1) & ~1;
        return (1);
    }
    TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
                 "Error writing data for field \"%s\"",
                 _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
    return (0);
}
Ejemplo n.º 11
0
static tmsize_t
TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip,
                        tmsize_t size, const char* module)
{
        TIFFDirectory *td = &tif->tif_dir;

        assert( !isMapped(tif) );
        assert((tif->tif_flags&TIFF_NOREADRAW)==0);

        if (!SeekOK(tif, td->td_stripoffset[strip_or_tile])) {
            if( is_strip )
            {
                TIFFErrorExt(tif->tif_clientdata, module,
                    "Seek error at scanline %lu, strip %lu",
                    (unsigned long) tif->tif_row,
                    (unsigned long) strip_or_tile);
            }
            else
            {
                TIFFErrorExt(tif->tif_clientdata, module,
                    "Seek error at row %lu, col %lu, tile %lu",
                    (unsigned long) tif->tif_row,
                    (unsigned long) tif->tif_col,
                    (unsigned long) strip_or_tile);
            }
            return ((tmsize_t)(-1));
        }

        if( !TIFFReadAndRealloc( tif, size, 0, is_strip,
                                 strip_or_tile, module ) )
        {
            return ((tmsize_t)(-1));
        }

        return (size);
}
Ejemplo n.º 12
0
/*
 * Append the data to the specified strip.
 */
static int
TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
{
	static const char module[] = "TIFFAppendToStrip";
	TIFFDirectory *td = &tif->tif_dir;
	uint64 m;
        int64 old_byte_count = -1;

	if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
            assert(td->td_nstrips > 0);

            if( td->td_stripbytecount[strip] != 0 
                && td->td_stripoffset[strip] != 0 
                && td->td_stripbytecount[strip] >= (uint64) cc )
            {
                /* 
                 * There is already tile data on disk, and the new tile
                 * data we have will fit in the same space.  The only 
                 * aspect of this that is risky is that there could be
                 * more data to append to this strip before we are done
                 * depending on how we are getting called.
                 */
                if (!SeekOK(tif, td->td_stripoffset[strip])) {
                    TIFFErrorExt(tif->tif_clientdata, module,
                                 "Seek error at scanline %lu",
                                 (unsigned long)tif->tif_row);
                    return (0);
                }
            }
            else
            {
                /* 
                 * Seek to end of file, and set that as our location to 
                 * write this strip.
                 */
                td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
                tif->tif_flags |= TIFF_DIRTYSTRIP;
            }

            tif->tif_curoff = td->td_stripoffset[strip];

            /*
             * We are starting a fresh strip/tile, so set the size to zero.
             */
            old_byte_count = td->td_stripbytecount[strip];
            td->td_stripbytecount[strip] = 0;
	}

	m = tif->tif_curoff+cc;
	if (!(tif->tif_flags&TIFF_BIGTIFF))
		m = (uint32)m;
	if ((m<tif->tif_curoff)||(m<(uint64)cc))
	{
		TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded");
		return (0);
	}
	if (!WriteOK(tif, data, cc)) {
		TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
		    (unsigned long) tif->tif_row);
		    return (0);
	}
	tif->tif_curoff = m;
	td->td_stripbytecount[strip] += cc;

        if( (int64) td->td_stripbytecount[strip] != old_byte_count )
            tif->tif_flags |= TIFF_DIRTYSTRIP;
            
	return (1);
}
Ejemplo n.º 13
0
/*
 * Similar to TIFFWriteDirectory(), but if the directory has already
 * been written once, it is relocated to the end of the file, in case it
 * has changed in size.  Note that this will result in the loss of the 
 * previously used directory space. 
 */ 
int 
TIFFRewriteDirectory( TIFF *tif )
{
    static const char module[] = "TIFFRewriteDirectory";

    /* We don't need to do anything special if it hasn't been written. */
    if( tif->tif_diroff == 0 )
        return TIFFWriteDirectory( tif );

    /*
    ** Find and zero the pointer to this directory, so that TIFFLinkDirectory
    ** will cause it to be added after this directories current pre-link.
    */
    
    /* Is it the first directory in the file? */
    if (TIFFGetHdrDirOff(tif,tif->tif_header) == tif->tif_diroff) 
    {
        TIFFSetHdrDirOff(tif,tif->tif_header,0);
        tif->tif_diroff = 0;

        if (!SeekOK(tif, 0) ||
	    !WriteOK(tif, &tif->tif_header, sizeof(TIFFHeader))) {
	    TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
		"Error updating TIFF header (%d)", TIFFGetErrno(tif));
            return (0);
        }
    }
    else
    {
        toff_t	nextdir, off;
	toff_t	nextdiroff;		/* 32-bit or 64-bit directory offset */

	nextdir = TIFFGetHdrDirOff(tif,tif->tif_header);
	do {
		uint16 dircount;

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
			TIFFErrorExt(tif->tif_clientdata, module, 
				"Error fetching directory count (%d)", TIFFGetErrno(tif));
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		(void) TIFFSeekFile(tif, TIFFGetDirCnt(tif,dircount) * TDIREntryLen(tif), SEEK_CUR);
		if (!ReadOK(tif, &nextdiroff, TIFFDirOffLen(tif))) {
			TIFFErrorExt(tif->tif_clientdata, module, 
				"Error fetching directory link (%d)", TIFFGetErrno(tif));
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabDirOff(tif,&nextdiroff);
		nextdir = TIFFGetDirOff(tif,nextdiroff);
	} while (nextdir != tif->tif_diroff && nextdir != 0);

        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
        (void) TIFFSeekFile(tif, off - TIFFDirOffLen(tif), SEEK_SET);
        tif->tif_diroff = 0;
	if (!WriteOK(tif, &(tif->tif_diroff), TIFFDirOffLen(tif))) {
		TIFFErrorExt(tif->tif_clientdata, module, 
			"Error writing directory link (%d)", TIFFGetErrno(tif));
		return (0);
	}
    }

    /*
    ** Now use TIFFWriteDirectory() normally.
    */
    return TIFFWriteDirectory( tif );
}
Ejemplo n.º 14
0
static tmsize_t
TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
    const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

    if (!_TIFFFillStriles( tif ))
        return ((tmsize_t)(-1));
        
	assert((tif->tif_flags&TIFF_NOREADRAW)==0);
	if (!isMapped(tif)) {
		tmsize_t cc;

		if (!SeekOK(tif, td->td_stripoffset[strip])) {
			TIFFErrorExt(tif->tif_clientdata, module,
			    "Seek error at scanline %lu, strip %lu",
			    (unsigned long) tif->tif_row, (unsigned long) strip);
			return ((tmsize_t)(-1));
		}
		cc = TIFFReadFile(tif, buf, size);
		if (cc != size) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
			TIFFErrorExt(tif->tif_clientdata, module,
		"Read error at scanline %lu; got %I64u bytes, expected %I64u",
				     (unsigned long) tif->tif_row,
				     (unsigned __int64) cc,
				     (unsigned __int64) size);
#else
			TIFFErrorExt(tif->tif_clientdata, module,
		"Read error at scanline %lu; got %llu bytes, expected %llu",
				     (unsigned long) tif->tif_row,
				     (unsigned long long) cc,
				     (unsigned long long) size);
#endif
			return ((tmsize_t)(-1));
		}
	} else {
		tmsize_t ma = 0;
		tmsize_t n;
		if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)||
                    ((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size))
                {
                    n=0;
                }
                else if( ma > TIFF_TMSIZE_T_MAX - size )
                {
                    n=0;
                }
                else
                {
                    tmsize_t mb=ma+size;
                    if (mb>tif->tif_size)
                            n=tif->tif_size-ma;
                    else
                            n=size;
                }
		if (n!=size) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
			TIFFErrorExt(tif->tif_clientdata, module,
	"Read error at scanline %lu, strip %lu; got %I64u bytes, expected %I64u",
				     (unsigned long) tif->tif_row,
				     (unsigned long) strip,
				     (unsigned __int64) n,
				     (unsigned __int64) size);
#else
			TIFFErrorExt(tif->tif_clientdata, module,
	"Read error at scanline %lu, strip %lu; got %llu bytes, expected %llu",
				     (unsigned long) tif->tif_row,
				     (unsigned long) strip,
				     (unsigned long long) n,
				     (unsigned long long) size);
#endif
			return ((tmsize_t)(-1));
		}
		_TIFFmemcpy(buf, tif->tif_base + ma,
			    size);
	}
	return (size);
}
Ejemplo n.º 15
0
/*
 * Append the data to the specified strip.
 */
static int
TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc) {
    TIFFDirectory* td = &tif->tif_dir;
    static const char module[] = "TIFFAppendToStrip";

    if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
        /*
         * No current offset, set the current strip.
         */
        assert(td->td_nstrips > 0);
        if (td->td_stripoffset[strip] != 0) {
            /*
             * Prevent overlapping of the data chunks. We need
                         * this to enable in place updating of the compressed
                         * images. Larger blocks will be moved at the end of
                         * the file without any optimization of the spare
                         * space, so such scheme is not too much effective.
             */
            if (td->td_stripbytecountsorted) {
                if (strip == td->td_nstrips - 1
                        || td->td_stripoffset[strip + 1] <
                        td->td_stripoffset[strip] + cc) {
                    td->td_stripoffset[strip] =
                        TIFFSeekFile(tif, (toff_t)0,
                                     SEEK_END);
                }
            } else {
                tstrip_t i;
                for (i = 0; i < td->td_nstrips; i++) {
                    if (td->td_stripoffset[i] >
                            td->td_stripoffset[strip]
                            && td->td_stripoffset[i] <
                            td->td_stripoffset[strip] + cc) {
                        td->td_stripoffset[strip] =
                            TIFFSeekFile(tif,
                                         (toff_t)0,
                                         SEEK_END);
                    }
                }
            }

            if (!SeekOK(tif, td->td_stripoffset[strip])) {
                TIFFError(module,
                          "%s: Seek error at scanline %lu",
                          tif->tif_name,
                          (unsigned long)tif->tif_row);
                return (0);
            }
        } else
            td->td_stripoffset[strip] =
                TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
        tif->tif_curoff = td->td_stripoffset[strip];
    }

    if (!WriteOK(tif, data, cc)) {
        TIFFError(module, "%s: Write error at scanline %lu",
                  tif->tif_name, (unsigned long) tif->tif_row);
        return (0);
    }
    tif->tif_curoff += cc;
    td->td_stripbytecount[strip] += cc;
    return (1);
}
Ejemplo n.º 16
0
/*
 * Link the current directory into the
 * directory chain for the file.
 */
static int
TIFFLinkDirectory(TIFF* tif)
{
	static const char module[] = "TIFFLinkDirectory";
	toff_t currdir, nextdir;
	toff_t diroff, nextdiroff;	/* 32-bit or 64-bit dir offsets */

	/*
	 * New directory will go at end of file; if file not BigTIFF and
	 * size is beyond 2^32, convert to BigTIFF now.
	 */
	tif->tif_diroff = ((TIFFSeekFile(tif, 0, SEEK_END) + 1) & ~(toff_t) 1);
	if (!isBigTIFF(tif) && isBigOff(tif->tif_diroff)) {
		if (!TIFFMakeBigTIFF(tif))
			return (0);
		tif->tif_diroff = ((TIFFSeekFile(tif, 0, SEEK_END) + 1) & ~(toff_t) 1);
	}

	TIFFSetDirOff(tif,diroff,tif->tif_diroff);
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabDirOff(tif,&diroff);

	/*
	 * Handle SubIFDs
	 */
        if (tif->tif_flags & TIFF_INSUBIFD) {
		(void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
		if (!WriteOK(tif, &diroff, TIFFDirOffLen(tif))) {
			TIFFErrorExt(tif->tif_clientdata, module,
			    "%s: Error writing SubIFD directory link (%d)",
			    tif->tif_name, TIFFGetErrno(tif));
			return (0);
		}
		/*
		 * Advance to the next SubIFD or, if this is
		 * the last one configured, revert back to the
		 * normal directory linkage.
		 */
		if (--tif->tif_nsubifd)
			tif->tif_subifdoff += TIFFDirOffLen(tif);
		else
			tif->tif_flags &= ~TIFF_INSUBIFD;
		return (1);
	}

	/*
	 * First directory, overwrite offset in header.
	 */
	nextdir = TIFFGetHdrDirOff(tif,tif->tif_header);
	if (nextdir == 0) {
		TIFFSetHdrDirOff(tif,tif->tif_header, tif->tif_diroff);
		if (!SeekOK(tif, 0) ||
		    !WriteOK(tif, &tif->tif_header, sizeof(TIFFHeader)) ) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error writing TIFF header (%d)", TIFFGetErrno(tif));
			return (0);
		}
		return (1);
	}
	/*
	 * Not the first directory, search to the last and append.
	 */
	do {
		uint64 dircount;	/* 16-bit or 64-bit directory count */

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, TIFFDirCntLen(tif))) {
			TIFFErrorExt(tif->tif_clientdata, module, 
				"Error fetching directory count (%d)", TIFFGetErrno(tif));
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabDirCnt(tif,&dircount);
		currdir = nextdir + TIFFDirCntLen(tif) + TIFFGetDirCnt(tif,dircount) * TDIREntryLen(tif);
		TIFFSeekFile(tif, currdir, SEEK_SET);
		if (!ReadOK(tif, &nextdiroff, TIFFDirOffLen(tif)) ) {
			TIFFErrorExt(tif->tif_clientdata, module, 
				"Error fetching directory link (%d)", TIFFGetErrno(tif));
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabDirOff(tif,&nextdiroff);
		nextdir = TIFFGetDirOff(tif,nextdiroff);
	} while (nextdir != 0);

        TIFFSeekFile(tif, currdir, SEEK_SET);
	if (!WriteOK(tif, &diroff, TIFFDirOffLen(tif)) ) {
		TIFFErrorExt(tif->tif_clientdata, module, 
			"Error writing directory link (%d)", TIFFGetErrno(tif));
		return (0);
	}
	return (1);
}
Ejemplo n.º 17
0
static int
TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
{
	static const char module[] = "TIFFFillStripPartial";
	register TIFFDirectory *td = &tif->tif_dir;
        tmsize_t unused_data;
        uint64 read_offset;
        tmsize_t cc, to_read;
        /* tmsize_t bytecountm; */
        
        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
            return 0;
        
        /*
         * Expand raw data buffer, if needed, to hold data
         * strip coming from file (perhaps should set upper
         * bound on the size of a buffer we'll use?).
         */

        /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */
        if (read_ahead*2 > tif->tif_rawdatasize) {
                assert( restart );
                
                tif->tif_curstrip = NOSTRIP;
                if ((tif->tif_flags & TIFF_MYBUFFER) == 0) {
                        TIFFErrorExt(tif->tif_clientdata, module,
                                     "Data buffer too small to hold part of strip %lu",
                                     (unsigned long) strip);
                        return (0);
                }
                if (!TIFFReadBufferSetup(tif, 0, read_ahead*2))
                        return (0);
        }

        if( restart )
        {
                tif->tif_rawdataloaded = 0;
                tif->tif_rawdataoff = 0;
        }

        /*
        ** If we are reading more data, move any unused data to the
        ** start of the buffer.
        */
        if( tif->tif_rawdataloaded > 0 )
                unused_data = tif->tif_rawdataloaded - (tif->tif_rawcp - tif->tif_rawdata);
        else
                unused_data = 0;
        
        if( unused_data > 0 )
        {
		assert((tif->tif_flags&TIFF_BUFFERMMAP)==0);
                memmove( tif->tif_rawdata, tif->tif_rawcp, unused_data );
        }

        /*
        ** Seek to the point in the file where more data should be read.
        */
        read_offset = td->td_stripoffset[strip]
                + tif->tif_rawdataoff + tif->tif_rawdataloaded;

        if (!SeekOK(tif, read_offset)) {
                TIFFErrorExt(tif->tif_clientdata, module,
                             "Seek error at scanline %lu, strip %lu",
                             (unsigned long) tif->tif_row, (unsigned long) strip);
                return 0;
        }

        /*
        ** How much do we want to read?
        */
        to_read = tif->tif_rawdatasize - unused_data;
        if( (uint64) to_read > td->td_stripbytecount[strip] 
            - tif->tif_rawdataoff - tif->tif_rawdataloaded )
        {
                to_read = (tmsize_t) td->td_stripbytecount[strip]
                        - tif->tif_rawdataoff - tif->tif_rawdataloaded;
        }

	assert((tif->tif_flags&TIFF_BUFFERMMAP)==0);
        cc = TIFFReadFile(tif, tif->tif_rawdata + unused_data, to_read);

        if (cc != to_read) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
                TIFFErrorExt(tif->tif_clientdata, module,
                             "Read error at scanline %lu; got %I64u bytes, expected %I64u",
                             (unsigned long) tif->tif_row,
                             (unsigned __int64) cc,
                             (unsigned __int64) to_read);
#else
                TIFFErrorExt(tif->tif_clientdata, module,
                             "Read error at scanline %lu; got %llu bytes, expected %llu",
                             (unsigned long) tif->tif_row,
                             (unsigned long long) cc,
                             (unsigned long long) to_read);
#endif
                return 0;
        }
        
        tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ;
        tif->tif_rawdataloaded = unused_data + to_read;

        tif->tif_rawcp = tif->tif_rawdata;
                        
        if (!isFillOrder(tif, td->td_fillorder) &&
            (tif->tif_flags & TIFF_NOBITREV) == 0) {
		assert((tif->tif_flags&TIFF_BUFFERMMAP)==0);
                TIFFReverseBits(tif->tif_rawdata + unused_data, to_read );
	}

        /*
        ** When starting a strip from the beginning we need to
        ** restart the decoder.
        */
        if( restart )
                return TIFFStartStrip(tif, strip);
        else
                return 1;
}
Ejemplo n.º 18
0
/*
 * Read the next TIFF directory from a file
 * and convert it to the internal format.
 * We read directories sequentially.
 */
int
TIFFReadDirectory(TIFF* tif)
{
	register TIFFDirEntry* dp;
	register int n;
	register TIFFDirectory* td;
	TIFFDirEntry* dir;
	int iv;
	long v;
	double dv;
	const TIFFFieldInfo* fip;
	int fix;
	uint16 dircount;
	toff_t nextdiroff;
	char* cp;
	int diroutoforderwarning = 0;

	tif->tif_diroff = tif->tif_nextdiroff;
	if (tif->tif_diroff == 0)		/* no more directories */
		return (0);
	/*
	 * Cleanup any previous compression state.
	 */
	(*tif->tif_cleanup)(tif);
	tif->tif_curdir++;
	nextdiroff = 0;
	if (!isMapped(tif)) {
		if (!SeekOK(tif, tif->tif_diroff)) {
			TIFFError(tif->tif_name,
			    "Seek error accessing TIFF directory");
			return (0);
		}
		if (!ReadOK(tif, &dircount, sizeof (uint16))) {
			TIFFError(tif->tif_name,
			    "Can not read TIFF directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		dir = (TIFFDirEntry *)CheckMalloc(tif,
		    dircount * sizeof (TIFFDirEntry), "to read TIFF directory");
		if (dir == NULL)
			return (0);
		if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) {
			TIFFError(tif->tif_name, "Can not read TIFF directory");
			goto bad;
		}
		/*
		 * Read offset to next directory for sequential scans.
		 */
		(void) ReadOK(tif, &nextdiroff, sizeof (uint32));
	} else {
		toff_t off = tif->tif_diroff;

		if (off + sizeof (uint16) > tif->tif_size) {
			TIFFError(tif->tif_name,
			    "Can not read TIFF directory count");
			return (0);
		} else
			_TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16));
		off += sizeof (uint16);
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		dir = (TIFFDirEntry *)CheckMalloc(tif,
		    dircount * sizeof (TIFFDirEntry), "to read TIFF directory");
		if (dir == NULL)
			return (0);
		if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) {
			TIFFError(tif->tif_name, "Can not read TIFF directory");
			goto bad;
		} else
			_TIFFmemcpy(dir, tif->tif_base + off,
			    dircount*sizeof (TIFFDirEntry));
		off += dircount* sizeof (TIFFDirEntry);
		if (off + sizeof (uint32) <= tif->tif_size)
			_TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32));
	}
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabLong(&nextdiroff);
	tif->tif_nextdiroff = nextdiroff;

	tif->tif_flags &= ~TIFF_BEENWRITING;	/* reset before new dir */
	/*
	 * Setup default value and then make a pass over
	 * the fields to check type and tag information,
	 * and to extract info required to size data
	 * structures.  A second pass is made afterwards
	 * to read in everthing not taken in the first pass.
	 */
	td = &tif->tif_dir;
	/* free any old stuff and reinit */
	TIFFFreeDirectory(tif);
	TIFFDefaultDirectory(tif);
	/*
	 * Electronic Arts writes gray-scale TIFF files
	 * without a PlanarConfiguration directory entry.
	 * Thus we setup a default value here, even though
	 * the TIFF spec says there is no default value.
	 */
	TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);

	/*
	 * Sigh, we must make a separate pass through the
	 * directory for the following reason:
	 *
	 * We must process the Compression tag in the first pass
	 * in order to merge in codec-private tag definitions (otherwise
	 * we may get complaints about unknown tags).  However, the
	 * Compression tag may be dependent on the SamplesPerPixel
	 * tag value because older TIFF specs permited Compression
	 * to be written as a SamplesPerPixel-count tag entry.
	 * Thus if we don't first figure out the correct SamplesPerPixel
	 * tag value then we may end up ignoring the Compression tag
	 * value because it has an incorrect count value (if the
	 * true value of SamplesPerPixel is not 1).
	 *
	 * It sure would have been nice if Aldus had really thought
	 * this stuff through carefully.
	 */ 
	for (dp = dir, n = dircount; n > 0; n--, dp++) {
		if (tif->tif_flags & TIFF_SWAB) {
			TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
			TIFFSwabArrayOfLong(&dp->tdir_count, 2);
		}
		if (dp->tdir_tag == TIFFTAG_SAMPLESPERPIXEL) {
			if (!TIFFFetchNormalTag(tif, dp))
				goto bad;
			dp->tdir_tag = IGNORE;
		}
	}
	/*
	 * First real pass over the directory.
	 */
	fix = 0;
	for (dp = dir, n = dircount; n > 0; n--, dp++) {

                /*
                 * Find the field information entry for this tag.
		 * Added check for tags to ignore ... [BFC]
                 */
		if( TIFFReassignTagToIgnore(TIS_EXTRACT, dp->tdir_tag) )
                    dp->tdir_tag = IGNORE;

		if (dp->tdir_tag == IGNORE)
                    continue;
                
		/*
		 * Silicon Beach (at least) writes unordered
		 * directory tags (violating the spec).  Handle
		 * it here, but be obnoxious (maybe they'll fix it?).
		 */
		if (dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) {
			if (!diroutoforderwarning) {
				TIFFWarning(tif->tif_name,
	"invalid TIFF directory; tags are not sorted in ascending order");
				diroutoforderwarning = 1;
			}
			fix = 0;			/* O(n^2) */
		}
		while (fix < tif->tif_nfields &&
		    tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
			fix++;
		if (fix == tif->tif_nfields ||
		    tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) {
			TIFFWarning(tif->tif_name,
			    "unknown field with tag %d (0x%x) ignored",
			    dp->tdir_tag,  dp->tdir_tag);
			dp->tdir_tag = IGNORE;
			fix = 0;			/* restart search */
			continue;
		}
		/*
		 * Null out old tags that we ignore.
		 */
		if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) {
	ignore:
			dp->tdir_tag = IGNORE;
			continue;
		}
		/*
		 * Check data type.
		 */
		fip = tif->tif_fieldinfo[fix];
		while (dp->tdir_type != (u_short) fip->field_type) {
			if (fip->field_type == TIFF_ANY)	/* wildcard */
				break;
			fip++, fix++;
			if (fix == tif->tif_nfields ||
			    fip->field_tag != dp->tdir_tag) {
				TIFFWarning(tif->tif_name,
				   "wrong data type %d for \"%s\"; tag ignored",
				    dp->tdir_type, fip[-1].field_name);
				goto ignore;
			}
		}
		/*
		 * Check count if known in advance.
		 */
		if (fip->field_readcount != TIFF_VARIABLE) {
			uint32 expected = (fip->field_readcount == TIFF_SPP) ?
			    (uint32) td->td_samplesperpixel :
			    (uint32) fip->field_readcount;
			if (!CheckDirCount(tif, dp, expected))
				goto ignore;
		}

		switch (dp->tdir_tag) {
		case TIFFTAG_COMPRESSION:
			/*
			 * The 5.0 spec says the Compression tag has
			 * one value, while earlier specs say it has
			 * one value per sample.  Because of this, we
			 * accept the tag if one value is supplied.
			 */
			if (dp->tdir_count == 1) {
				v = TIFFExtractData(tif,
				    dp->tdir_type, dp->tdir_offset);
				if (!TIFFSetField(tif, dp->tdir_tag, (int)v))
					goto bad;
				break;
			}
			if (!TIFFFetchPerSampleShorts(tif, dp, &iv) ||
			    !TIFFSetField(tif, dp->tdir_tag, iv))
				goto bad;
			dp->tdir_tag = IGNORE;
			break;
		case TIFFTAG_STRIPOFFSETS:
		case TIFFTAG_STRIPBYTECOUNTS:
		case TIFFTAG_TILEOFFSETS:
		case TIFFTAG_TILEBYTECOUNTS:
			TIFFSetFieldBit(tif, fip->field_bit);
			break;
		case TIFFTAG_IMAGEWIDTH:
		case TIFFTAG_IMAGELENGTH:
		case TIFFTAG_IMAGEDEPTH:
		case TIFFTAG_TILELENGTH:
		case TIFFTAG_TILEWIDTH:
		case TIFFTAG_TILEDEPTH:
		case TIFFTAG_PLANARCONFIG:
		case TIFFTAG_ROWSPERSTRIP:
			if (!TIFFFetchNormalTag(tif, dp))
				goto bad;
			dp->tdir_tag = IGNORE;
			break;
		case TIFFTAG_EXTRASAMPLES:
			(void) TIFFFetchExtraSamples(tif, dp);
			dp->tdir_tag = IGNORE;
			break;
		}
	}

	/*
	 * Allocate directory structure and setup defaults.
	 */
	if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
		MissingRequired(tif, "ImageLength");
		goto bad;
	}
	if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
		MissingRequired(tif, "PlanarConfiguration");
		goto bad;
	}
	/* 
 	 * Setup appropriate structures (by strip or by tile)
	 */
	if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
		td->td_nstrips = TIFFNumberOfStrips(tif);
		td->td_tilewidth = td->td_imagewidth;
		td->td_tilelength = td->td_rowsperstrip;
		td->td_tiledepth = td->td_imagedepth;
		tif->tif_flags &= ~TIFF_ISTILED;
	} else {
		td->td_nstrips = TIFFNumberOfTiles(tif);
		tif->tif_flags |= TIFF_ISTILED;
	}
	td->td_stripsperimage = td->td_nstrips;
	if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
		td->td_stripsperimage /= td->td_samplesperpixel;
	if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
		MissingRequired(tif,
		    isTiled(tif) ? "TileOffsets" : "StripOffsets");
		goto bad;
	}

	/*
	 * Second pass: extract other information.
	 */
	for (dp = dir, n = dircount; n > 0; n--, dp++) {
		if (dp->tdir_tag == IGNORE)
			continue;
		switch (dp->tdir_tag) {
		case TIFFTAG_MINSAMPLEVALUE:
		case TIFFTAG_MAXSAMPLEVALUE:
		case TIFFTAG_BITSPERSAMPLE:
			/*
			 * The 5.0 spec says the Compression tag has
			 * one value, while earlier specs say it has
			 * one value per sample.  Because of this, we
			 * accept the tag if one value is supplied.
			 *
			 * The MinSampleValue, MaxSampleValue and
			 * BitsPerSample tags are supposed to be written
			 * as one value/sample, but some vendors incorrectly
			 * write one value only -- so we accept that
			 * as well (yech).
			 */
			if (dp->tdir_count == 1) {
				v = TIFFExtractData(tif,
				    dp->tdir_type, dp->tdir_offset);
				if (!TIFFSetField(tif, dp->tdir_tag, (int)v))
					goto bad;
				break;
			}
			/* fall thru... */
		case TIFFTAG_DATATYPE:
		case TIFFTAG_SAMPLEFORMAT:
			if (!TIFFFetchPerSampleShorts(tif, dp, &iv) ||
			    !TIFFSetField(tif, dp->tdir_tag, iv))
				goto bad;
			break;
		case TIFFTAG_SMINSAMPLEVALUE:
		case TIFFTAG_SMAXSAMPLEVALUE:
			if (!TIFFFetchPerSampleAnys(tif, dp, &dv) ||
			    !TIFFSetField(tif, dp->tdir_tag, dv))
				goto bad;
			break;
		case TIFFTAG_STRIPOFFSETS:
		case TIFFTAG_TILEOFFSETS:
			if (!TIFFFetchStripThing(tif, dp,
			    td->td_nstrips, &td->td_stripoffset))
				goto bad;
			break;
		case TIFFTAG_STRIPBYTECOUNTS:
		case TIFFTAG_TILEBYTECOUNTS:
			if (!TIFFFetchStripThing(tif, dp,
			    td->td_nstrips, &td->td_stripbytecount))
				goto bad;
			break;
		case TIFFTAG_COLORMAP:
		case TIFFTAG_TRANSFERFUNCTION:
			/*
			 * TransferFunction can have either 1x or 3x data
			 * values; Colormap can have only 3x items.
			 */
			v = 1L<<td->td_bitspersample;
			if (dp->tdir_tag == TIFFTAG_COLORMAP ||
			    dp->tdir_count != (uint32) v) {
				if (!CheckDirCount(tif, dp, (uint32)(3*v)))
					break;
			}
			v *= sizeof (uint16);
			cp = CheckMalloc(tif, dp->tdir_count * sizeof (uint16),
			    "to read \"TransferFunction\" tag");
			if (cp != NULL) {
				if (TIFFFetchData(tif, dp, cp)) {
					/*
					 * This deals with there being only
					 * one array to apply to all samples.
					 */
					uint32 c =
					    (uint32)1 << td->td_bitspersample;
					if (dp->tdir_count == c)
						v = 0;
					TIFFSetField(tif, dp->tdir_tag,
					    cp, cp+v, cp+2*v);
				}
				_TIFFfree(cp);
			}
			break;
		case TIFFTAG_PAGENUMBER:
		case TIFFTAG_HALFTONEHINTS:
		case TIFFTAG_YCBCRSUBSAMPLING:
		case TIFFTAG_DOTRANGE:
			(void) TIFFFetchShortPair(tif, dp);
			break;
#ifdef COLORIMETRY_SUPPORT
		case TIFFTAG_REFERENCEBLACKWHITE:
			(void) TIFFFetchRefBlackWhite(tif, dp);
			break;
#endif
/* BEGIN REV 4.0 COMPATIBILITY */
		case TIFFTAG_OSUBFILETYPE:
			v = 0;
			switch (TIFFExtractData(tif, dp->tdir_type,
			    dp->tdir_offset)) {
			case OFILETYPE_REDUCEDIMAGE:
				v = FILETYPE_REDUCEDIMAGE;
				break;
			case OFILETYPE_PAGE:
				v = FILETYPE_PAGE;
				break;
			}
			if (v)
				(void) TIFFSetField(tif,
				    TIFFTAG_SUBFILETYPE, (int)v);
			break;
/* END REV 4.0 COMPATIBILITY */
		default:
			(void) TIFFFetchNormalTag(tif, dp);
			break;
		}
	}
	/*
	 * Verify Palette image has a Colormap.
	 */
	if (td->td_photometric == PHOTOMETRIC_PALETTE &&
	    !TIFFFieldSet(tif, FIELD_COLORMAP)) {
		MissingRequired(tif, "Colormap");
		goto bad;
	}
	/*
	 * Attempt to deal with a missing StripByteCounts tag.
	 */
	if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) {
		/*
		 * Some manufacturers violate the spec by not giving
		 * the size of the strips.  In this case, assume there
		 * is one uncompressed strip of data.
		 */
		if ((td->td_planarconfig == PLANARCONFIG_CONTIG &&
		    td->td_nstrips > 1) ||
		    (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
		     td->td_nstrips != td->td_samplesperpixel)) {
		    MissingRequired(tif, "StripByteCounts");
		    goto bad;
		}
		TIFFWarning(tif->tif_name,
			"TIFF directory is missing required \"%s\" field, calculating from imagelength",
		    _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
		EstimateStripByteCounts(tif, dir, dircount);
#define	BYTECOUNTLOOKSBAD \
    ((td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \
    (td->td_compression == COMPRESSION_NONE && \
     td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0]))
	} else if (td->td_nstrips == 1 && BYTECOUNTLOOKSBAD) {
		/*
		 * Plexus (and others) sometimes give a value
		 * of zero for a tag when they don't know what
		 * the correct value is!  Try and handle the
		 * simple case of estimating the size of a one
		 * strip image.
		 */
		TIFFWarning(tif->tif_name,
	    "Bogus \"%s\" field, ignoring and calculating from imagelength",
		    _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
		EstimateStripByteCounts(tif, dir, dircount);
	}
	if (dir)
		_TIFFfree((char *)dir);
	if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))
		td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1);
	/*
	 * Setup default compression scheme.
	 */
	if (!TIFFFieldSet(tif, FIELD_COMPRESSION))
		TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
        /*
         * Some manufacturers make life difficult by writing
	 * large amounts of uncompressed data as a single strip.
	 * This is contrary to the recommendations of the spec.
         * The following makes an attempt at breaking such images
	 * into strips closer to the recommended 8k bytes.  A
	 * side effect, however, is that the RowsPerStrip tag
	 * value may be changed.
         */
	if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE &&
	    (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP)
		ChopUpSingleUncompressedStrip(tif);
	/*
	 * Reinitialize i/o since we are starting on a new directory.
	 */
	tif->tif_row = (uint32) -1;
	tif->tif_curstrip = (tstrip_t) -1;
	tif->tif_col = (uint32) -1;
	tif->tif_curtile = (ttile_t) -1;
	tif->tif_tilesize = TIFFTileSize(tif);
	tif->tif_scanlinesize = TIFFScanlineSize(tif);
	return (1);
bad:
	if (dir)
		_TIFFfree(dir);
	return (0);
}
Ejemplo n.º 19
0
/*
 * Function to convert standard TIFF file to BigTIFF file.  Loop through all directories in
 * current file (including subdirectories linked via SubIFD arrays) and create corresponding
 * new directories with 64-bit arrays.  The old 32-bit directories are left in the file as
 * dead space.  The data for directory entries are reused by default.  Some directory entries
 * require new data with 64-bit offsets (e.g. stripe/tile offsets and SubIFD arrays).
 *
 * Returns 1 if successful, 0 if cannot convert to BigTIFF (TIFF_NOBIGTIFF set 
 * or 32-bit API called).
 */
static int 
TIFFMakeBigTIFF(TIFF *tif)
{
	uint32	dirlink = TIFF_HEADER_DIROFF_S,
		diroff = tif->tif_header.s.tiff_diroff;
	toff_t	dirlinkB = TIFF_HEADER_DIROFF_B,
		diroffB;
	uint16	dircount, dirindex;
	uint64	dircountB;
	tsize_t	dirsize, dirsizeB;
	int	issubifd = 0;
	uint32	subifdcnt = 0;
	uint32	subifdlink;
	toff_t	subifdlinkB;
	char	*data, *dataB;
	TIFFDirEntry *dir, *dirB;

	/*
	 * Update flags and file header
	 */
	if (noBigTIFF(tif)) {
		TIFFErrorExt((tif)->tif_clientdata, 
			"TIFFCheckBigTIFF", "File > 2^32 and NO BigTIFF specified");
		return (0);
	}
	tif->tif_flags |= TIFF_ISBIGTIFF;
	tif->tif_header.b.tiff_version = TIFF_BIGTIFF_VERSION;
	tif->tif_header.b.tiff_offsize = 8;
	tif->tif_header.b.tiff_fill = 0;
	tif->tif_header.b.tiff_diroff = 0;
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.b.tiff_version);
		TIFFSwabShort(&tif->tif_header.b.tiff_offsize);
	}
	if (!SeekOK(tif, 0) ||
	    !WriteOK(tif, &tif->tif_header, sizeof(TIFFHeader))) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
			"Error updating TIFF header (%d)", TIFFGetErrno(tif));
		return (0);
	}
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.b.tiff_version);
		TIFFSwabShort(&tif->tif_header.b.tiff_offsize);
	}

	/*
	 * Loop through all directories and rewrite as BigTIFF with 64-bit offsets.  This
	 * begins with main IFD chain but may divert to SubIFD arrays as needed.
	 */
	while (diroff != 0 && diroff != tif->tif_diroff) {
		if (!SeekOK(tif, diroff) ||
		    !ReadOK(tif, &dircount, sizeof(dircount))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error reading TIFF directory (%d)", TIFFGetErrno(tif));
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		dircountB = dircount;
		if (!(data = _TIFFmalloc(dirsize = dircount * TIFFDirEntryLenS)) ||
		    !(dataB = _TIFFmalloc(dirsizeB = dircount * TIFFDirEntryLenB))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error allocating space for directory");
			return (0);
		}
		if (!SeekOK(tif, diroff + sizeof(dircount)) ||
		    !ReadOK(tif, data, dirsize)) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error reading TIFF directory (%d)", TIFFGetErrno(tif));
			goto error;
		}
		diroffB = tif->tif_dataoff;
		tif->tif_dataoff += sizeof(dircountB) + dirsizeB + sizeof(toff_t);

		for (dirindex = 0; dirindex < dircount; dirindex++) {
			dir = (TIFFDirEntry*) (data + dirindex * TIFFDirEntryLenS);
			dirB = (TIFFDirEntry*) (dataB + dirindex * TIFFDirEntryLenB);
			if (tif->tif_flags & TIFF_SWAB) {
				TIFFSwabShort(&dir->s.tdir_tag);
				TIFFSwabShort(&dir->s.tdir_type);
				TIFFSwabLong(&dir->s.tdir_count);
				TIFFSwabLong(&dir->s.tdir_offset);
			}
			dirB->b.tdir_tag = dir->s.tdir_tag;
			dirB->b.tdir_type = dir->s.tdir_type;
			dirB->b.tdir_count = dir->s.tdir_count;
			dirB->b.tdir_offset = 0;
			/*
			 * If data are in directory entry itself, copy data, else (data are pointed
			 * to by directory entry) copy pointer.  This is complicated by the fact that
			 * the old entry had 32-bits of space, and the new has 64-bits, so may have
			 * to read data pointed at by the old entry directly into the new entry.
			 */
			switch (dir->s.tdir_type) {
			case TIFF_UNDEFINED:
			case TIFF_BYTE:
			case TIFF_SBYTE:
			case TIFF_ASCII:
				if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset))
					_TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count);
				else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count)) {
					TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET);
					TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count);
				} else
					dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			case TIFF_SHORT:
			case TIFF_SSHORT:
				if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset) / sizeof(uint16))
					_TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count * sizeof(uint16));
				else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count) / sizeof(uint16)) {
					TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET);
					TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * sizeof(uint16));
					if (tif->tif_flags & TIFF_SWAB)
						TIFFSwabArrayOfShort((uint16*) &dirB->b.tdir_offset, dir->s.tdir_count);
				} else
					dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			case TIFF_LONG:
			case TIFF_FLOAT:
			case TIFF_IFD:
				if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset) / sizeof(uint32))
					_TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count * sizeof(uint32));
				else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count) / sizeof(uint32)) {
					TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET);
					TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * sizeof(uint32));
					if (tif->tif_flags & TIFF_SWAB)
						TIFFSwabArrayOfLong((uint32*) &dirB->b.tdir_offset, dir->s.tdir_count);
				} else
					dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			case TIFF_RATIONAL:
			case TIFF_SRATIONAL:
				if (dir->s.tdir_count * 2 <= sizeof(dirB->b.tdir_offset) / sizeof(uint32)) {
					TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET);
					TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * 2 * sizeof(uint32));
					if (tif->tif_flags & TIFF_SWAB)
						TIFFSwabArrayOfLong((uint32*) &dirB->b.tdir_offset, dir->s.tdir_count * 2);
				} else
					dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			default:
				dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			}
			/*
			 * Process special case of SUBIFD; must change data from 32-bit to 64-bit in 
			 * case new 64-bit directory offsets need to be added.
			 */
			switch (dirB->b.tdir_tag) {
			case TIFFTAG_SUBIFD:
				dirB->b.tdir_type = TIFF_IFD8;
				subifdcnt = dir->s.tdir_count;
				/*
				 * Set pointer to existing SubIFD array
				 */
				if (subifdcnt <= sizeof(dir->s.tdir_offset) / sizeof(uint32))
					subifdlink = diroff + sizeof(dircount) +
						(char*) &dir->s.tdir_offset - (char*) dir;
				else
					subifdlink = dir->s.tdir_offset;
				/*
				 * Initialize new SubIFD array, set pointer to it
				 */
				if (subifdcnt <= sizeof(dir->b.tdir_offset) / sizeof(toff_t)) {
					dir->b.tdir_offset = 0;
					subifdlinkB = diroffB + sizeof(dircountB) +
						(char*) &dir->b.tdir_offset - (char*) dirB;
				} else {
					toff_t *offB;

					if (!(offB = _TIFFmalloc(subifdcnt * sizeof(toff_t)))) {
						TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
							"Error allocating space for 64-bit SubIFDs");
						goto error;
					}
					_TIFFmemset(offB, 0, subifdcnt * sizeof(toff_t));
					TIFFWriteLong8Array(tif, dirB, offB);
					_TIFFfree(offB);
					subifdlinkB = dirB->b.tdir_offset;
					}
				break;
			}
			if (tif->tif_flags & TIFF_SWAB) {
				TIFFSwabShort(&dirB->b.tdir_tag);
				TIFFSwabShort(&dirB->b.tdir_type);
				TIFFSwabLong8(&dirB->b.tdir_count);
				TIFFSwabLong8(&dirB->b.tdir_offset);
			}
		}
		
		/*
		 * Write out new directory and chain to previous
		 */
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong8(&dircountB);
		if (!SeekOK(tif, diroffB) ||
		    !WriteOK(tif, &dircountB, sizeof(dircountB)) ||
		    !SeekOK(tif, diroffB + sizeof(dircountB)) ||
		    !WriteOK(tif, dataB, dirsizeB)) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error writing TIFF directory (%d)", TIFFGetErrno(tif));
			goto error;
		}

		/*
		 * If directory is SubIFD update array in host directory, else add to
		 * main directory chain
		 */
		if (tif->tif_nsubifd &&
			tif->tif_subifdoff == subifdlink)
			tif->tif_subifdoff = subifdlinkB;

		if (!issubifd && 
			dirlinkB == TIFF_HEADER_DIROFF_B)
			tif->tif_header.b.tiff_diroff = diroffB;
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong8(&diroffB);
		if (!SeekOK(tif, (issubifd ? subifdlinkB++ : dirlinkB)) ||
		    !WriteOK(tif, &diroffB, sizeof(diroffB))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error writing directory link (%d)", TIFFGetErrno(tif));
			goto error;
		}

		if (issubifd)
			subifdcnt--;
		else {
			dirlink = diroff + sizeof(dircount) + dirsize;
			dirlinkB = diroffB + sizeof(dircountB) + dirsizeB;
		}
		issubifd = (subifdcnt > 0);

		if (!SeekOK(tif, (issubifd ? subifdlink++ : dirlink)) ||
		    !ReadOK(tif, &diroff, sizeof(diroff))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error reading directory link (%d)", TIFFGetErrno(tif));
			goto error;
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&diroff);
		_TIFFfree(dataB);
		_TIFFfree(data);
	}

	/*
	 * Mark end of directory chain
	 */
	diroffB = 0;
	if (dirlinkB == TIFF_HEADER_DIROFF_B)
		tif->tif_header.b.tiff_diroff = diroffB;
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabLong8(&diroffB);
	if (!SeekOK(tif, dirlinkB) ||
	    !WriteOK(tif, &diroffB, sizeof(diroffB))) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
			"Error writing directory link (%d)", TIFFGetErrno(tif));
		goto error;
	}

	return (1);

error:
	_TIFFfree(dataB);
	_TIFFfree(data);
	return (0);
}
Ejemplo n.º 20
0
/*
 * Append the data to the specified strip.
 */
static int
TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
{
	TIFFDirectory *td = &tif->tif_dir;
	static const char module[] = "TIFFAppendToStrip";

	if (_TIFFGetOffset(tif, strip) == 0 || tif->tif_curoff == 0) {
		/*
		 * No current offset, set the current strip.
		 */
		assert(td->td_nstrips > 0);
		if (_TIFFGetOffset(tif, strip) != 0) {
			/*
			 * Prevent overlapping of the data chunks. We need
                         * this to enable in place updating of the compressed
                         * images. Larger blocks will be moved at the end of
                         * the file without any optimization of the spare
                         * space, so such scheme is not too much effective.
			 */
			if (td->td_stripbytecountsorted) {
				if (strip == td->td_nstrips - 1 || 
					_TIFFGetOffset(tif, strip + 1) < _TIFFGetOffset(tif, strip) + cc) {
					_TIFFSetOffset(tif, strip, TIFFSeekFile(tif, (toff_t)0, SEEK_END));
				}
			} else {
				tstrip_t i;
				for (i = 0; i < td->td_nstrips; i++) {
					if (_TIFFGetOffset(tif, i) > _TIFFGetOffset(tif, strip) && 
						_TIFFGetOffset(tif, i) < _TIFFGetOffset(tif, strip) + cc) {
						_TIFFSetOffset(tif, strip, TIFFSeekFile(tif, (toff_t)0, SEEK_END));
						break;
					}
				}
			}
			/* check if block will overlap offsets or bytes counts arrays */
			if ((td->td_stripoffsoff &&
				_TIFFGetOffset(tif, strip) < td->td_stripoffsoff &&
				_TIFFGetOffset(tif, strip) + cc > td->td_stripoffsoff) ||
			    (td->td_stripbcsoff &&
				_TIFFGetOffset(tif, strip) < td->td_stripbcsoff &&
				_TIFFGetOffset(tif, strip) + cc > td->td_stripbcsoff))
				_TIFFSetOffset(tif, strip, TIFFSeekFile(tif, (toff_t)0, SEEK_END));

			if (!SeekOK(tif, _TIFFGetOffset(tif, strip))) {
				TIFFErrorExt(tif->tif_clientdata, module,
					  "%s: Seek error at scanline %lu",
					  tif->tif_name,
					  (unsigned long)tif->tif_row);
				return (0);
			}
		} else
			_TIFFSetOffset(tif, strip,
				TIFFSeekFile(tif, (toff_t) 0, SEEK_END));
		tif->tif_curoff = _TIFFGetOffset(tif, strip);
	}

	if (!WriteOK(tif, data, cc)) {
		TIFFErrorExt(tif->tif_clientdata, module, 
			"%s: Write error at scanline %lu (%d)",
			tif->tif_name, (unsigned long) tif->tif_row, TIFFGetErrno(tif));
		return (0);
	}
	tif->tif_curoff += cc;
	_TIFFSetByteCount(tif, strip, _TIFFGetByteCount(tif, strip) + cc);
	return (1);
}
Ejemplo n.º 21
0
static tmsize_t
TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

	assert((tif->tif_flags&TIFF_NOREADRAW)==0);
	if (!isMapped(tif)) {
		tmsize_t cc;

		if (!SeekOK(tif, td->td_stripoffset[tile])) {
			TIFFErrorExt(tif->tif_clientdata, module,
			    "Seek error at row %lu, col %lu, tile %lu",
			    (unsigned long) tif->tif_row,
			    (unsigned long) tif->tif_col,
			    (unsigned long) tile);
			return ((tmsize_t)(-1));
		}
		cc = TIFFReadFile(tif, buf, size);
		if (cc != size) {
#if defined(__WIN32__) && defined(_MSC_VER)
			TIFFErrorExt(tif->tif_clientdata, module,
	"Read error at row %lu, col %lu; got %I64u bytes, expected %I64u",
				     (unsigned long) tif->tif_row,
				     (unsigned long) tif->tif_col,
				     (unsigned __int64) cc,
				     (unsigned __int64) size);
#else
			TIFFErrorExt(tif->tif_clientdata, module,
	"Read error at row %lu, col %lu; got %llu bytes, expected %llu",
				     (unsigned long) tif->tif_row,
				     (unsigned long) tif->tif_col,
				     (unsigned long long) cc,
				     (unsigned long long) size);
#endif
			return ((tmsize_t)(-1));
		}
	} else {
		tmsize_t ma,mb;
		tmsize_t n;
		ma=(tmsize_t)td->td_stripoffset[tile];
		mb=ma+size;
		if (((uint64)ma!=td->td_stripoffset[tile])||(ma>tif->tif_size))
			n=0;
		else if ((mb<ma)||(mb<size)||(mb>tif->tif_size))
			n=tif->tif_size-ma;
		else
			n=size;
		if (n!=size) {
#if defined(__WIN32__) && defined(_MSC_VER)
			TIFFErrorExt(tif->tif_clientdata, module,
"Read error at row %lu, col %lu, tile %lu; got %I64u bytes, expected %I64u",
				     (unsigned long) tif->tif_row,
				     (unsigned long) tif->tif_col,
				     (unsigned long) tile,
				     (unsigned __int64) n,
				     (unsigned __int64) size);
#else
			TIFFErrorExt(tif->tif_clientdata, module,
"Read error at row %lu, col %lu, tile %lu; got %llu bytes, expected %llu",
				     (unsigned long) tif->tif_row,
				     (unsigned long) tif->tif_col,
				     (unsigned long) tile,
				     (unsigned long long) n,
				     (unsigned long long) size);
#endif
			return ((tmsize_t)(-1));
		}
		_TIFFmemcpy(buf, tif->tif_base + ma, size);
	}
	return (size);
}
Ejemplo n.º 22
0
int 
TIFFRewriteDirectory( TIFF *tif )
{
    static const char module[] = "TIFFRewriteDirectory";

    /* We don't need to do anything special if it hasn't been written. */
    if( tif->tif_diroff == 0 )
        return TIFFWriteDirectory( tif );

    /*
    ** Find and zero the pointer to this directory, so that TIFFLinkDirectory
    ** will cause it to be added after this directories current pre-link.
    */
    
    /* Is it the first directory in the file? */
    if (tif->tif_header.tiff_diroff == tif->tif_diroff) 
    {
        tif->tif_header.tiff_diroff = 0;
        tif->tif_diroff = 0;

#if defined(__hpux) && defined(__LP64__)
#define HDROFF(f) ((toff_t)(unsigned long) &(((TIFFHeader*) 0)->f))
#else
#define	HDROFF(f)	((toff_t) &(((TIFFHeader*) 0)->f))
#endif
        TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET);
        if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), 
                     sizeof (tif->tif_diroff))) 
        {
            TIFFError(tif->tif_name, "Error updating TIFF header");
            return (0);
        }
    }
    else
    {
        toff_t  nextdir, off;

	nextdir = tif->tif_header.tiff_diroff;
	do {
		uint16 dircount;

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
			TIFFError(module, "Error fetching directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		(void) TIFFSeekFile(tif,
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
			TIFFError(module, "Error fetching directory link");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&nextdir);
	} while (nextdir != tif->tif_diroff && nextdir != 0);
        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
        tif->tif_diroff = 0;
	if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) {
		TIFFError(module, "Error writing directory link");
		return (0);
	}
    }

    /*
    ** Now use TIFFWriteDirectory() normally.
    */

    return TIFFWriteDirectory( tif );
}
Ejemplo n.º 23
0
static int
TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
{
	static const char module[] = "TIFFFillStripPartial";
	register TIFFDirectory *td = &tif->tif_dir;
        tmsize_t unused_data;
        uint64 read_offset;
        tmsize_t to_read;
        tmsize_t read_ahead_mod;
        /* tmsize_t bytecountm; */
        
        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
            return 0;
        
        /*
         * Expand raw data buffer, if needed, to hold data
         * strip coming from file (perhaps should set upper
         * bound on the size of a buffer we'll use?).
         */

        /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */

        /* Not completely sure where the * 2 comes from, but probably for */
        /* an exponentional growth strategy of tif_rawdatasize */
        if( read_ahead < TIFF_TMSIZE_T_MAX / 2 )
                read_ahead_mod = read_ahead * 2;
        else
                read_ahead_mod = read_ahead;
        if (read_ahead_mod > tif->tif_rawdatasize) {
                assert( restart );
                
                tif->tif_curstrip = NOSTRIP;
                if ((tif->tif_flags & TIFF_MYBUFFER) == 0) {
                        TIFFErrorExt(tif->tif_clientdata, module,
                                     "Data buffer too small to hold part of strip %lu",
                                     (unsigned long) strip);
                        return (0);
                }
        }

        if( restart )
        {
                tif->tif_rawdataloaded = 0;
                tif->tif_rawdataoff = 0;
        }

        /*
        ** If we are reading more data, move any unused data to the
        ** start of the buffer.
        */
        if( tif->tif_rawdataloaded > 0 )
                unused_data = tif->tif_rawdataloaded - (tif->tif_rawcp - tif->tif_rawdata);
        else
                unused_data = 0;
        
        if( unused_data > 0 )
        {
		assert((tif->tif_flags&TIFF_BUFFERMMAP)==0);
                memmove( tif->tif_rawdata, tif->tif_rawcp, unused_data );
        }

        /*
        ** Seek to the point in the file where more data should be read.
        */
        read_offset = td->td_stripoffset[strip]
                + tif->tif_rawdataoff + tif->tif_rawdataloaded;

        if (!SeekOK(tif, read_offset)) {
                TIFFErrorExt(tif->tif_clientdata, module,
                             "Seek error at scanline %lu, strip %lu",
                             (unsigned long) tif->tif_row, (unsigned long) strip);
                return 0;
        }

        /*
        ** How much do we want to read?
        */
        if( read_ahead_mod > tif->tif_rawdatasize )
                to_read = read_ahead_mod - unused_data;
        else
                to_read = tif->tif_rawdatasize - unused_data;
        if( (uint64) to_read > td->td_stripbytecount[strip] 
            - tif->tif_rawdataoff - tif->tif_rawdataloaded )
        {
                to_read = (tmsize_t) td->td_stripbytecount[strip]
                        - tif->tif_rawdataoff - tif->tif_rawdataloaded;
        }

	assert((tif->tif_flags&TIFF_BUFFERMMAP)==0);
        if( !TIFFReadAndRealloc( tif, to_read, unused_data,
                                 1, /* is_strip */
                                 0, /* strip_or_tile */
                                 module) )
        {
                return 0;
        }

        tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ;
        tif->tif_rawdataloaded = unused_data + to_read;

        tif->tif_rawcc = tif->tif_rawdataloaded;
        tif->tif_rawcp = tif->tif_rawdata;
                        
        if (!isFillOrder(tif, td->td_fillorder) &&
            (tif->tif_flags & TIFF_NOBITREV) == 0) {
		assert((tif->tif_flags&TIFF_BUFFERMMAP)==0);
                TIFFReverseBits(tif->tif_rawdata + unused_data, to_read );
	}

        /*
        ** When starting a strip from the beginning we need to
        ** restart the decoder.
        */
        if( restart )
        {

#ifdef JPEG_SUPPORT
            /* A bit messy since breaks the codec abstraction. Ultimately */
            /* there should be a function pointer for that, but it seems */
            /* only JPEG is affected. */
            /* For JPEG, if there are multiple scans (can generally be known */
            /* with the  read_ahead used), we need to read the whole strip */
            if( tif->tif_dir.td_compression==COMPRESSION_JPEG &&
                (uint64)tif->tif_rawcc < td->td_stripbytecount[strip] )
            {
                if( TIFFJPEGIsFullStripRequired(tif) )
                {
                    return TIFFFillStrip(tif, strip);
                }
            }
#endif

            return TIFFStartStrip(tif, strip);
        }
        else
        {
                return 1;
        }
}
Ejemplo n.º 24
0
/*
 * Link the current directory into the
 * directory chain for the file.
 */
static int
TIFFLinkDirectory(TIFF* tif)
{
	static const char module[] = "TIFFLinkDirectory";
	toff_t nextdir;
	toff_t diroff, off;

	tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
	diroff = tif->tif_diroff;
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabLong(&diroff);
#if SUBIFD_SUPPORT
	if (tif->tif_flags & TIFF_INSUBIFD) {
		(void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
			TIFFError(module,
			    "%s: Error writing SubIFD directory link",
			    tif->tif_name);
			return (0);
		}
		/*
		 * Advance to the next SubIFD or, if this is
		 * the last one configured, revert back to the
		 * normal directory linkage.
		 */
		if (--tif->tif_nsubifd)
			tif->tif_subifdoff += sizeof (diroff);
		else
			tif->tif_flags &= ~TIFF_INSUBIFD;
		return (1);
	}
#endif
	if (tif->tif_header.tiff_diroff == 0) {
		/*
		 * First directory, overwrite offset in header.
		 */
		tif->tif_header.tiff_diroff = tif->tif_diroff;
#define	HDROFF(f)	((toff_t) &(((TIFFHeader*) 0)->f))
		(void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET);
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
			TIFFError(tif->tif_name, "Error writing TIFF header");
			return (0);
		}
		return (1);
	}
	/*
	 * Not the first directory, search to the last and append.
	 */
	nextdir = tif->tif_header.tiff_diroff;
	do {
		uint16 dircount;

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
			TIFFError(module, "Error fetching directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		(void) TIFFSeekFile(tif,
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
			TIFFError(module, "Error fetching directory link");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&nextdir);
	} while (nextdir != 0);
        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
	if (!WriteOK(tif, &diroff, sizeof (diroff))) {
		TIFFError(module, "Error writing directory link");
		return (0);
	}
	return (1);
}
Ejemplo n.º 25
0
/*
 * Link the current directory into the
 * directory chain for the file.
 */
static int
TIFFLinkDirectory(TIFF* tif)
{
	static const char module[] = "TIFFLinkDirectory";
	uint32 nextdir;
	uint32 diroff;

	tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
	diroff = (uint32) tif->tif_diroff;
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabLong(&diroff);
#if SUBIFD_SUPPORT
	if (tif->tif_flags & TIFF_INSUBIFD) {
		(void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
			TIFFErrorExt(tif->tif_clientdata, module,
			    "%s: Error writing SubIFD directory link",
			    tif->tif_name);
			return (0);
		}
		/*
		 * Advance to the next SubIFD or, if this is
		 * the last one configured, revert back to the
		 * normal directory linkage.
		 */
		if (--tif->tif_nsubifd)
			tif->tif_subifdoff += sizeof (diroff);
		else
			tif->tif_flags &= ~TIFF_INSUBIFD;
		return (1);
	}
#endif
	if (tif->tif_header.tiff_diroff == 0) {
		/*
		 * First directory, overwrite offset in header.
		 */
		tif->tif_header.tiff_diroff = (uint32) tif->tif_diroff;
#define	HDROFF(f)	((toff_t) &(((TIFFHeader*) 0)->f))
		(void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET);
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing TIFF header");
			return (0);
		}
		return (1);
	}
	/*
	 * Not the first directory, search to the last and append.
	 */
	nextdir = tif->tif_header.tiff_diroff;
#if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */
#   pragma ivdep
#   pragma swp
#   pragma unroll
#   pragma prefetch
#   if 0
#       pragma simd noassert
#   endif
#endif /* VDM auto patch */
	do {
		uint16 dircount;

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
			TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		(void) TIFFSeekFile(tif,
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
			TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&nextdir);
	} while (nextdir != 0);
	(void) TIFFSeekFile(tif, -(toff_t) sizeof (nextdir), SEEK_CUR);
	if (!WriteOK(tif, &diroff, sizeof (diroff))) {
		TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
		return (0);
	}
	return (1);
}