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; }