void CqTiffOutputFile::writeTiledPixels(const CqMixedImageBuffer& buffer)
{
	SqTileInfo tileInfo = m_header.find<Attr::TileInfo>();
	// Check that the buffer has a height that is a multiple of the tile height.
	if( buffer.height() % tileInfo.height != 0
		&& m_currentLine + buffer.height() != m_header.height() )
	{
		AQSIS_THROW_XQERROR(XqInternal, EqE_Bug,
				"pixel buffer with height = " << buffer.height() << " must be a multiple "
				"of requested tile height (= " << tileInfo.height << ") or run exactly to "
				"the full image height (= " << m_header.height() << ").");
	}

	CqTiffDirHandle dirHandle(m_fileHandle);
	const TqUint8* rawBuf = buffer.rawData();
	const TqInt bytesPerPixel = buffer.channelList().bytesPerPixel();
	boost::scoped_array<TqUint8> tileBuf(
			new TqUint8[bytesPerPixel*tileInfo.width*tileInfo.height]);
	const TqInt rowStride = bytesPerPixel*buffer.width();
	const TqInt tileRowStride = bytesPerPixel*tileInfo.width;
	const TqInt endLine = m_currentLine + buffer.height();
	const TqInt numTileCols = (buffer.width()-1)/tileInfo.width + 1;
	for(TqInt line = m_currentLine; line < endLine; line += tileInfo.height)
	{
		// srcBuf will point to the beginning of the memory region which will
		// become the tile.
		const TqUint8* srcBuf = rawBuf;
		for(TqInt tileCol = 0; tileCol < numTileCols; ++tileCol)
		{
			const TqInt tileDataLen = min(tileRowStride,
					rowStride - tileCol*tileRowStride);
			const TqInt tileDataHeight = min(tileInfo.height, buffer.height() - line);
			// Copy parts of the scanlines into the tile buffer.
			stridedCopy(tileBuf.get(), tileRowStride, srcBuf, rowStride,
					tileDataHeight, tileDataLen);

			TIFFWriteTile(dirHandle.tiffPtr(),
					reinterpret_cast<tdata_t>(const_cast<TqUint8*>(tileBuf.get())),
					tileCol*tileInfo.width, line, 0, 0);
			srcBuf += tileRowStride;
		}
		rawBuf += rowStride*tileInfo.height;
	}
	m_currentLine = endLine;
}
void CqTiffOutputFile::writeScanlinePixels(const CqMixedImageBuffer& buffer)
{
	CqTiffDirHandle dirHandle(m_fileHandle);
	// Simplest possible implementation using scanline TIFF I/O.  Could use
	// Strip-based IO if performance is ever a problem here.
	const TqUint8* rawBuf = buffer.rawData();
	const TqInt rowStride = buffer.channelList().bytesPerPixel()*buffer.width();
	const TqInt endLine = m_currentLine + buffer.height();
	// Temporary buffer for scanlines.  We need to copy the data into here
	// since libtiff trashes the buffer when encoding is turned on.  (The TIFF
	// docs don't seem to mention this though, ugh.)
	boost::scoped_array<TqUint8> lineBuf(new TqUint8[rowStride]);
	for(TqInt line = m_currentLine; line < endLine; ++line)
	{
		// copy the data into temp buffer.
		std::memcpy(lineBuf.get(), rawBuf, rowStride);
		// write data
		TIFFWriteScanline( dirHandle.tiffPtr(), reinterpret_cast<tdata_t>(lineBuf.get()),
				static_cast<uint32>(line) );
		rawBuf += rowStride;
	}
	m_currentLine = endLine;
}