bool TIFFOutput::write_tile (int x, int y, int z, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride) { if (! m_spec.valid_tile_range (x, x, y, y, z, z)) return false; m_spec.auto_stride (xstride, ystride, zstride, format, spec().nchannels, spec().tile_width, spec().tile_height); x -= m_spec.x; // Account for offset, so x,y are file relative, not y -= m_spec.y; // image relative const void *origdata = data; // Stash original pointer data = to_native_tile (format, data, xstride, ystride, zstride, m_scratch); if (m_planarconfig == PLANARCONFIG_SEPARATE && m_spec.nchannels > 1) { // Convert from contiguous (RGBRGBRGB) to separate (RRRGGGBBB) imagesize_t tile_pixels = m_spec.tile_pixels(); imagesize_t plane_bytes = tile_pixels * m_spec.format.size(); DASSERT (plane_bytes*m_spec.nchannels == m_spec.tile_bytes()); m_scratch.resize (m_spec.tile_bytes()); boost::scoped_array<char> separate_heap; char *separate = NULL; imagesize_t separate_size = plane_bytes * m_spec.nchannels; if (separate_size <= (1<<16)) separate = ALLOCA (char, separate_size); // <=64k ? stack else { // >64k ? heap
bool TIFFOutput::write_tile (int x, int y, int z, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride) { if (! m_spec.valid_tile_range (x, x, y, y, z, z)) return false; m_spec.auto_stride (xstride, ystride, zstride, format, spec().nchannels, spec().tile_width, spec().tile_height); x -= m_spec.x; // Account for offset, so x,y are file relative, not y -= m_spec.y; // image relative z -= m_spec.z; const void *origdata = data; // Stash original pointer data = to_native_tile (format, data, xstride, ystride, zstride, m_scratch, m_dither, x, y, z); // Handle weird photometric/color spaces if (m_photometric == PHOTOMETRIC_SEPARATED) data = convert_to_cmyk (spec().tile_pixels(), data); // Handle weird bit depths if (spec().format.size()*8 != m_bitspersample) { // Move to scratch area if not already there imagesize_t nbytes = spec().scanline_bytes(); int nvals = int (spec().tile_pixels()) * spec().nchannels; if (data == origdata) { m_scratch.assign ((unsigned char *)data, (unsigned char *)data+nbytes); data = &m_scratch[0]; } if (spec().format == TypeDesc::UINT16 && m_bitspersample == 10) { convert_pack_bits<unsigned short, 10> ((unsigned short *)data, nvals); } else if (spec().format == TypeDesc::UINT16 && m_bitspersample == 12) { convert_pack_bits<unsigned short, 12> ((unsigned short *)data, nvals); } else if (spec().format == TypeDesc::UINT8 && m_bitspersample == 4) { convert_pack_bits<unsigned char, 4> ((unsigned char *)data, nvals); } else if (spec().format == TypeDesc::UINT8 && m_bitspersample == 2) { convert_pack_bits<unsigned char, 2> ((unsigned char *)data, nvals); } else { ASSERT (0 && "unsupported bit conversion -- shouldn't reach here"); } } if (m_planarconfig == PLANARCONFIG_SEPARATE && m_spec.nchannels > 1) { // Convert from contiguous (RGBRGBRGB) to separate (RRRGGGBBB) imagesize_t tile_pixels = m_spec.tile_pixels(); imagesize_t plane_bytes = tile_pixels * m_spec.format.size(); DASSERT (plane_bytes*m_spec.nchannels == m_spec.tile_bytes()); m_scratch.resize (m_spec.tile_bytes()); boost::scoped_array<char> separate_heap; char *separate = NULL; imagesize_t separate_size = plane_bytes * m_spec.nchannels; if (separate_size <= (1<<16)) separate = ALLOCA (char, separate_size); // <=64k ? stack else { // >64k ? heap
bool TIFFOutput::write_tile (int x, int y, int z, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride) { if (! m_spec.valid_tile_range (x, x, y, y, z, z)) return false; m_spec.auto_stride (xstride, ystride, zstride, format, spec().nchannels, spec().tile_width, spec().tile_height); x -= m_spec.x; // Account for offset, so x,y are file relative, not y -= m_spec.y; // image relative const void *origdata = data; // Stash original pointer data = to_native_tile (format, data, xstride, ystride, zstride, m_scratch); if (m_planarconfig == PLANARCONFIG_SEPARATE && m_spec.nchannels > 1) { // Convert from contiguous (RGBRGBRGB) to separate (RRRGGGBBB) imagesize_t tile_pixels = m_spec.tile_pixels(); imagesize_t plane_bytes = tile_pixels * m_spec.format.size(); DASSERT (plane_bytes*m_spec.nchannels == m_spec.tile_bytes()); m_scratch.resize (m_spec.tile_bytes()); contig_to_separate (tile_pixels, (const unsigned char *)data, &m_scratch[0]); for (int c = 0; c < m_spec.nchannels; ++c) { if (TIFFWriteTile (m_tif, (tdata_t)&m_scratch[plane_bytes*c], x, y, z, c) < 0) { error ("TIFFWriteTile failed"); return false; } } } else { // No contig->separate is necessary. But we still use scratch // space since TIFFWriteTile is destructive when // TIFFTAG_PREDICTOR is used. if (data == origdata) { m_scratch.assign ((unsigned char *)data, (unsigned char *)data + m_spec.tile_bytes()); data = &m_scratch[0]; } if (TIFFWriteTile (m_tif, (tdata_t)data, x, y, z, 0) < 0) { error ("TIFFWriteTile failed"); return false; } } // Should we checkpoint? Only if we have enough tiles and enough time has passed if (m_checkpointTimer() > DEFAULT_CHECKPOINT_INTERVAL_SECONDS && m_checkpointItems >= MIN_SCANLINES_OR_TILES_PER_CHECKPOINT) { TIFFCheckpointDirectory (m_tif); m_checkpointTimer.lap(); m_checkpointItems = 0; } else { ++m_checkpointItems; } return true; }
bool SocketOutput::write_tile (int x, int y, int z, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride) { data = to_native_tile (format, data, xstride, ystride, zstride, m_scratch); try { socket_pvt::socket_write (socket, format, data, m_spec.tile_bytes ()); } catch (boost::system::system_error &err) { error ("Error while writing: %s", err.what ()); return false; } catch (...) { error ("Error while writing: unknown exception"); return false; } return true; }