// Write a 4x5 tiled test tiff intended to have the correct sizes for a mipmap
void writeTiledTiff(const char* fileName)
{
	uint32 height = 5;
	uint32 width = 4;
	uint16 samplesPerPixel = 3;
	uint16 bitsPerSample = 8;
	uint32 tileWidth = 16;
	uint32 tileHeight = 16;

	//TIFF* outFile = TIFFStreamOpen("stream", &outStream);
	TIFF* outFile = TIFFOpen(fileName, "w");

	setTiffFields(outFile, width, height, samplesPerPixel, bitsPerSample);
	TIFFSetField(outFile, TIFFTAG_TILEWIDTH, tileWidth);
	TIFFSetField(outFile, TIFFTAG_TILELENGTH, tileHeight);

	tsize_t bufSize = TIFFTileSize(outFile);
	char* buf = reinterpret_cast<char*>(_TIFFmalloc(bufSize));
	_TIFFmemset(buf, 0x00, bufSize);

	// first directory
	TIFFWriteEncodedTile(outFile, 0, buf, bufSize);
	TIFFWriteDirectory(outFile);

	// rest of the directories
	while(width > 1 || height > 1)
	{
		width = std::max<uint32>((width+1)/2, 1);
		height = std::max<uint32>((height+1)/2, 1);
		setTiffFields(outFile, width, height, samplesPerPixel, bitsPerSample);
		TIFFSetField(outFile, TIFFTAG_TILEWIDTH, tileWidth);
		TIFFSetField(outFile, TIFFTAG_TILELENGTH, tileHeight);

		TIFFWriteEncodedTile(outFile, 0, buf, bufSize);
		TIFFWriteDirectory(outFile);
	}

	TIFFClose(outFile);
	_TIFFfree(buf);
}
Example #2
0
static
int TileBasedXform(cmsHTRANSFORM hXForm, TIFF* in, TIFF* out, int nPlanes)
{
    tsize_t BufSizeIn  = TIFFTileSize(in);
    tsize_t BufSizeOut = TIFFTileSize(out);
    unsigned char *BufferIn, *BufferOut;
    ttile_t i, TileCount = TIFFNumberOfTiles(in) / nPlanes;
    uint32 tw, tl;
    int PixelCount, j;


    TIFFGetFieldDefaulted(in, TIFFTAG_TILEWIDTH,  &tw);
    TIFFGetFieldDefaulted(in, TIFFTAG_TILELENGTH, &tl);

     PixelCount = (int) tw * tl;

     BufferIn = (unsigned char *) _TIFFmalloc(BufSizeIn * nPlanes);
    if (!BufferIn) OutOfMem(BufSizeIn * nPlanes);

    BufferOut = (unsigned char *) _TIFFmalloc(BufSizeOut * nPlanes);
    if (!BufferOut) OutOfMem(BufSizeOut * nPlanes);


    for (i = 0; i < TileCount; i++) {

        for (j=0; j < nPlanes; j++) {

            if (TIFFReadEncodedTile(in, i + (j* TileCount), 
                                    BufferIn + (j*BufSizeIn), BufSizeIn) < 0)   goto cleanup;
        }

      cmsDoTransform(hXForm, BufferIn, BufferOut, PixelCount);

      for (j=0; j < nPlanes; j++) {

             if (TIFFWriteEncodedTile(out, i + (j*TileCount),
                                    BufferOut + (j*BufSizeOut), BufSizeOut) < 0) goto cleanup;
      }

    }

    _TIFFfree(BufferIn);
    _TIFFfree(BufferOut);
    return 1;


cleanup:

    _TIFFfree(BufferIn);
   _TIFFfree(BufferOut);
   return 0;
}
Example #3
0
/*
 * Write and compress a tile of data.  The
 * tile is selected by the (x,y,z,s) coordinates.
 */
tmsize_t
TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s)
{
	if (!TIFFCheckTile(tif, x, y, z, s))
		return ((tmsize_t)(-1));
	/*
	 * NB: A tile size of -1 is used instead of tif_tilesize knowing
	 *     that TIFFWriteEncodedTile will clamp this to the tile size.
	 *     This is done because the tile size may not be defined until
	 *     after the output buffer is setup in TIFFWriteBufferSetup.
	 */
	return (TIFFWriteEncodedTile(tif,
	    TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1)));
}
Example #4
0
static int
cvt_by_tile( TIFF *in, TIFF *out )

{
    uint32* raster;			/* retrieve RGBA image */
    uint32  width, height;		/* image width & height */
    uint32  tile_width, tile_height;
    uint32  row, col;
    uint32  *wrk_line;
    int	    ok = 1;

    TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);

    if( !TIFFGetField(in, TIFFTAG_TILEWIDTH, &tile_width)
        || !TIFFGetField(in, TIFFTAG_TILELENGTH, &tile_height) ) {
        TIFFError(TIFFFileName(in), "Source image not tiled");
        return (0);
    }
    
    TIFFSetField(out, TIFFTAG_TILEWIDTH, tile_width );
    TIFFSetField(out, TIFFTAG_TILELENGTH, tile_height );

    /*
     * Allocate tile buffer
     */
    raster = (uint32*)_TIFFmalloc(tile_width * tile_height * sizeof (uint32));
    if (raster == 0) {
        TIFFError(TIFFFileName(in), "No space for raster buffer");
        return (0);
    }

    /*
     * Allocate a scanline buffer for swapping during the vertical
     * mirroring pass.
     */
    wrk_line = (uint32*)_TIFFmalloc(tile_width * sizeof (uint32));
    if (!wrk_line) {
        TIFFError(TIFFFileName(in), "No space for raster scanline buffer");
        ok = 0;
    }
    
    /*
     * Loop over the tiles.
     */
    for( row = 0; ok && row < height; row += tile_height )
    {
        for( col = 0; ok && col < width; col += tile_width )
        {
            uint32 i_row;

            /* Read the tile into an RGBA array */
            if (!TIFFReadRGBATile(in, col, row, raster)) {
                ok = 0;
                break;
            }

            /*
             * For some reason the TIFFReadRGBATile() function chooses the
             * lower left corner as the origin.  Vertically mirror scanlines.
             */
            for( i_row = 0; i_row < tile_height / 2; i_row++ )
            {
                uint32	*top_line, *bottom_line;

                top_line = raster + tile_width * i_row;
                bottom_line = raster + tile_width * (tile_height-i_row-1);

                _TIFFmemcpy(wrk_line, top_line, 4*tile_width);
                _TIFFmemcpy(top_line, bottom_line, 4*tile_width);
                _TIFFmemcpy(bottom_line, wrk_line, 4*tile_width);
            }

            /*
             * Write out the result in a tile.
             */

            if( TIFFWriteEncodedTile( out,
                                      TIFFComputeTile( out, col, row, 0, 0),
                                      raster,
                                      4 * tile_width * tile_height ) == -1 )
            {
                ok = 0;
                break;
            }
        }
    }

    _TIFFfree( raster );
    _TIFFfree( wrk_line );

    return ok;
}
static void TIFFWriteOvrRow( TIFFOvrCache * psCache )

{
    int		nRet, iTileX, iTileY = psCache->nBlockOffset;
    unsigned char *pabyData;
    uint32	nBaseDirOffset;
    uint32 RowsInStrip;

/* -------------------------------------------------------------------- */
/*      If the output cache is multi-byte per sample, and the file      */
/*      being written to is of a different byte order than the current  */
/*      platform, we will need to byte swap the data.                   */
/* -------------------------------------------------------------------- */
    if( TIFFIsByteSwapped(psCache->hTIFF) )
    {
        if( psCache->nBitsPerPixel == 16 )
            TIFFSwabArrayOfShort( (uint16 *) psCache->pabyRow1Blocks,
                      (psCache->nBytesPerBlock * psCache->nSamples) / 2 );

        else if( psCache->nBitsPerPixel == 32 )
            TIFFSwabArrayOfLong( (uint32 *) psCache->pabyRow1Blocks,
                         (psCache->nBytesPerBlock * psCache->nSamples) / 4 );

        else if( psCache->nBitsPerPixel == 64 )
            TIFFSwabArrayOfDouble( (double *) psCache->pabyRow1Blocks,
                         (psCache->nBytesPerBlock * psCache->nSamples) / 8 );
    }

/* -------------------------------------------------------------------- */
/*      Record original directory position, so we can restore it at     */
/*      end.                                                            */
/* -------------------------------------------------------------------- */
    nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF );
    nRet = TIFFSetSubDirectory( psCache->hTIFF, psCache->nDirOffset );
    assert( nRet == 1 );

/* -------------------------------------------------------------------- */
/*      Write blocks to TIFF file.                                      */
/* -------------------------------------------------------------------- */
	for( iTileX = 0; iTileX < psCache->nBlocksPerRow; iTileX++ )
	{
		int nTileID;

		if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
		{
			int iSample;

			for( iSample = 0; iSample < psCache->nSamples; iSample++ )
			{
				pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, iSample );

				if( psCache->bTiled )
				{
					nTileID = TIFFComputeTile( psCache->hTIFF,
					    iTileX * psCache->nBlockXSize,
					    iTileY * psCache->nBlockYSize,
					    0, (tsample_t) iSample );
					TIFFWriteEncodedTile( psCache->hTIFF, nTileID,
					    pabyData,
					    TIFFTileSize(psCache->hTIFF) );
				}
				else
				{
					nTileID = TIFFComputeStrip( psCache->hTIFF,
					    iTileY * psCache->nBlockYSize,
					    (tsample_t) iSample );
					RowsInStrip=psCache->nBlockYSize;
					if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize)
						RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize;
					TIFFWriteEncodedStrip( psCache->hTIFF, nTileID,
					    pabyData,
					    TIFFVStripSize(psCache->hTIFF,RowsInStrip) );
				}
			}

		}
		else
		{
			pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, 0 );

			if( psCache->bTiled )
			{
				nTileID = TIFFComputeTile( psCache->hTIFF,
				    iTileX * psCache->nBlockXSize,
				    iTileY * psCache->nBlockYSize,
				    0, 0 );
				TIFFWriteEncodedTile( psCache->hTIFF, nTileID,
				    pabyData,
				    TIFFTileSize(psCache->hTIFF) );
			}
			else
			{
				nTileID = TIFFComputeStrip( psCache->hTIFF,
				    iTileY * psCache->nBlockYSize,
				    0 );
				RowsInStrip=psCache->nBlockYSize;
				if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize)
					RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize;
				TIFFWriteEncodedStrip( psCache->hTIFF, nTileID,
				    pabyData,
				    TIFFVStripSize(psCache->hTIFF,RowsInStrip) );
			}
		}
	}
	/* TODO: add checks on error status return of TIFFWriteEncodedTile and TIFFWriteEncodedStrip */

/* -------------------------------------------------------------------- */
/*      Rotate buffers.                                                 */
/* -------------------------------------------------------------------- */
    pabyData = psCache->pabyRow1Blocks;
    psCache->pabyRow1Blocks = psCache->pabyRow2Blocks;
    psCache->pabyRow2Blocks = pabyData;

    _TIFFmemset( pabyData, 0, psCache->nBytesPerRow );

    psCache->nBlockOffset++;

/* -------------------------------------------------------------------- */
/*      Restore access to original directory.                           */
/* -------------------------------------------------------------------- */
    TIFFFlush( psCache->hTIFF );
    /* TODO: add checks on error status return of TIFFFlush */
    TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset );
    /* TODO: add checks on error status return of TIFFSetSubDirectory */
}
Example #6
0
/* Copy a TIFF file ... we know we wrote it, so just copy the tags we know 
 * we might have set.
 */
static int
write_copy_tiff( Write *write, TIFF *out, TIFF *in )
{
	uint32 i32;
	uint16 i16;
	float f;
	tdata_t buf;
	ttile_t tile;
	ttile_t n;

	/* All the fields we might have set.
	 */
	CopyField( TIFFTAG_IMAGEWIDTH, i32 );
	CopyField( TIFFTAG_IMAGELENGTH, i32 );
	CopyField( TIFFTAG_PLANARCONFIG, i16 );
	CopyField( TIFFTAG_ORIENTATION, i16 );
	CopyField( TIFFTAG_XRESOLUTION, f );
	CopyField( TIFFTAG_YRESOLUTION, f );
	CopyField( TIFFTAG_RESOLUTIONUNIT, i16 );
	CopyField( TIFFTAG_COMPRESSION, i16 );
	CopyField( TIFFTAG_SAMPLESPERPIXEL, i16 );
	CopyField( TIFFTAG_BITSPERSAMPLE, i16 );
	CopyField( TIFFTAG_PHOTOMETRIC, i16 );
	CopyField( TIFFTAG_ORIENTATION, i16 );
	CopyField( TIFFTAG_TILEWIDTH, i32 );
	CopyField( TIFFTAG_TILELENGTH, i32 );
	CopyField( TIFFTAG_ROWSPERSTRIP, i32 );
	CopyField( TIFFTAG_SUBFILETYPE, i32 );

	if( write->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE ) 
		TIFFSetField( out, TIFFTAG_PREDICTOR, write->predictor );

	/* TIFFTAG_JPEGQUALITY is a pesudo-tag, so we can't copy it.
	 * Set explicitly from Write.
	 */
	if( write->compression == COMPRESSION_JPEG ) {
		TIFFSetField( out, TIFFTAG_JPEGQUALITY, write->jpqual );

		/* Only for three-band, 8-bit images.
		 */
		if( write->im->Bands == 3 &&
			write->im->BandFmt == VIPS_FORMAT_UCHAR ) { 
			/* Enable rgb->ycbcr conversion in the jpeg write. 
			 */
			if( !write->rgbjpeg &&
				write->jpqual < 90 ) 
				TIFFSetField( out, 
					TIFFTAG_JPEGCOLORMODE, 
						JPEGCOLORMODE_RGB );

			/* And we want ycbcr expanded to rgb on read. Otherwise
			 * TIFFTileSize() will give us the size of a chrominance
			 * subsampled tile.
			 */
			TIFFSetField( in, 
				TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
		}
	}

	/* We can't copy profiles or xmp :( Set again from Write.
	 */
	if( !write->strip ) 
		if( write_embed_profile( write, out ) ||
			write_embed_xmp( write, out ) ||
			write_embed_ipct( write, out ) ||
			write_embed_photoshop( write, out ) ||
			write_embed_imagedescription( write, out ) )
			return( -1 );

	buf = vips_malloc( NULL, TIFFTileSize( in ) );
	n = TIFFNumberOfTiles( in );
	for( tile = 0; tile < n; tile++ ) {
		tsize_t len;

		/* It'd be good to use TIFFReadRawTile()/TIFFWriteRawTile() 
		 * here to save compression/decompression, but sadly it seems
		 * not to work :-( investigate at some point.
		 */
		len = TIFFReadEncodedTile( in, tile, buf, -1 );
		if( len < 0 ||
			TIFFWriteEncodedTile( out, tile, buf, len ) < 0 ) {
			vips_free( buf );
			return( -1 );
		}
	}
	vips_free( buf );

	return( 0 );
}
static int
cvt_by_tile( TIFF *in, TIFF *out )

{
    uint32* raster;			/* retrieve RGBA image */
    uint32  width, height;		/* image width & height */
    uint32  tile_width, tile_height;
    uint32  row, col;
    uint32  *wrk_line;
    tsize_t raster_size;
    int	    ok = 1;

    TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);

    if( !TIFFGetField(in, TIFFTAG_TILEWIDTH, &tile_width)
        || !TIFFGetField(in, TIFFTAG_TILELENGTH, &tile_height) ) {
        TIFFError(TIFFFileName(in), "Source image not tiled");
        return (0);
    }
    
    TIFFSetField(out, TIFFTAG_TILEWIDTH, tile_width );
    TIFFSetField(out, TIFFTAG_TILELENGTH, tile_height );

    /*
     * Allocate tile buffer
     */
    raster_size = multiply(multiply(tile_width, tile_height), sizeof (uint32));
    if (!raster_size) {
	TIFFError(TIFFFileName(in),
		  "Can't allocate buffer for raster of size %lux%lu",
		  (unsigned long) tile_width, (unsigned long) tile_height);
	return (0);
    }
    raster = (uint32*)_TIFFmalloc(raster_size);
    if (raster == 0) {
        TIFFError(TIFFFileName(in), "No space for raster buffer");
        return (0);
    }

    /*
     * Allocate a scanline buffer for swapping during the vertical
     * mirroring pass.  (Request can't overflow given prior checks.)
     */
    wrk_line = (uint32*)_TIFFmalloc(tile_width * sizeof (uint32));
    if (!wrk_line) {
        TIFFError(TIFFFileName(in), "No space for raster scanline buffer");
        ok = 0;
    }
    
    /*
     * Loop over the tiles.
     */
    for( row = 0; ok && row < height; row += tile_height )
    {
        for( col = 0; ok && col < width; col += tile_width )
        {
            uint32 i_row;

            /* Read the tile into an RGBA array */
            if (!TIFFReadRGBATile(in, col, row, raster)) {
                ok = 0;
                break;
            }


	    /*
	     * XXX: raster array has 4-byte unsigned integer type, that is why
	     * we should rearrange it here.
	     */
#if HOST_BIGENDIAN
	    TIFFSwabArrayOfLong(raster, tile_width * tile_height);
#endif

            /*
             * For some reason the TIFFReadRGBATile() function chooses the
             * lower left corner as the origin.  Vertically mirror scanlines.
             */
            for( i_row = 0; i_row < tile_height / 2; i_row++ )
            {
                uint32	*top_line, *bottom_line;

                top_line = raster + tile_width * i_row;
                bottom_line = raster + tile_width * (tile_height-i_row-1);

                _TIFFmemcpy(wrk_line, top_line, 4*tile_width);
                _TIFFmemcpy(top_line, bottom_line, 4*tile_width);
                _TIFFmemcpy(bottom_line, wrk_line, 4*tile_width);
            }

            /*
             * Write out the result in a tile.
             */

            if( TIFFWriteEncodedTile( out,
                                      TIFFComputeTile( out, col, row, 0, 0),
                                      raster,
                                      4 * tile_width * tile_height ) == -1 )
            {
                ok = 0;
                break;
            }
        }
    }

    _TIFFfree( raster );
    _TIFFfree( wrk_line );

    return ok;
}
Example #8
0
static
void TIFF_WriteOverview( TIFF *hTIFF, int nSamples, RawBlockedImage **papoRBI,
                         int bTiled, int nCompressFlag, int nPhotometric,
                         unsigned short *panRed,
                         unsigned short *panGreen,
                         unsigned short *panBlue,
                         int bUseSubIFDs )

{
    int		iSample;
    RawBlockedImage	*poRBI = papoRBI[0];

    /* -------------------------------------------------------------------- */
    /*      Setup TIFF fields.                                              */
    /* -------------------------------------------------------------------- */
    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, poRBI->GetXSize() );
    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, poRBI->GetYSize() );
    TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG,
                  PLANARCONFIG_SEPARATE );

    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, poRBI->GetBitsPerPixel() );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
    TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );

    if( bTiled )
    {
        TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, poRBI->GetBlockXSize() );
        TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, poRBI->GetBlockYSize() );
    }
    else
        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, poRBI->GetBlockYSize() );

    TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );

    /* -------------------------------------------------------------------- */
    /*	Write color table if one is present.				*/
    /* -------------------------------------------------------------------- */
    if( panRed != NULL )
    {
        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
    }

    /* -------------------------------------------------------------------- */
    /*      Write blocks to TIFF file.                                      */
    /* -------------------------------------------------------------------- */
    for( iSample = 0; iSample < nSamples; iSample++ )
    {
        int		iTileX, iTileY;

        poRBI = papoRBI[iSample];

        for( iTileY = 0;
                iTileY*poRBI->GetBlockYSize() < poRBI->GetYSize();
                iTileY++ )
        {
            for( iTileX = 0;
                    iTileX*poRBI->GetBlockXSize() < poRBI->GetXSize();
                    iTileX++ )
            {
                unsigned char	*pabyData = poRBI->GetTile( iTileX, iTileY );
                int	nTileID;

                if( bTiled )
                {
                    nTileID =
                        TIFFComputeTile(hTIFF,
                                        iTileX * poRBI->GetBlockXSize(),
                                        iTileY * poRBI->GetBlockYSize(),
                                        0, iSample );
                    TIFFWriteEncodedTile( hTIFF, nTileID,
                                          pabyData, TIFFTileSize(hTIFF) );
                }
                else
                {
                    nTileID =
                        TIFFComputeStrip(hTIFF, iTileY*poRBI->GetBlockYSize(),
                                         iSample);

                    TIFFWriteEncodedStrip( hTIFF, nTileID,
                                           pabyData, TIFFStripSize( hTIFF ) );
                }
            }
        }
    }

    TIFFWriteDirectory( hTIFF );
}