bool OpenEXROutput::write_tile (int x, int y, int z, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride) { bool native = (format == TypeDesc::UNKNOWN); size_t pixel_bytes = m_spec.pixel_bytes (native); if (native && xstride == AutoStride) xstride = (stride_t) pixel_bytes; m_spec.auto_stride (xstride, ystride, zstride, format, spec().nchannels, spec().tile_width, spec().tile_height); data = to_native_tile (format, data, xstride, ystride, zstride, m_scratch); // Compute where OpenEXR needs to think the full buffers starts. // OpenImageIO requires that 'data' points to where the client wants // to put the pixels being read, but OpenEXR's frameBuffer.insert() // wants where the address of the "virtual framebuffer" for the // whole image. char *buf = (char *)data - x * pixel_bytes - y * pixel_bytes * m_spec.tile_width; try { Imf::FrameBuffer frameBuffer; size_t chanoffset = 0; for (int c = 0; c < m_spec.nchannels; ++c) { size_t chanbytes = m_spec.channelformats.size() ? m_spec.channelformats[c].size() : m_spec.format.size(); frameBuffer.insert (m_spec.channelnames[c].c_str(), Imf::Slice (m_pixeltype[c], buf + chanoffset, pixel_bytes, pixel_bytes*m_spec.tile_width)); chanoffset += chanbytes; } m_output_tiled->setFrameBuffer (frameBuffer); m_output_tiled->writeTile ((x - m_spec.x) / m_spec.tile_width, (y - m_spec.y) / m_spec.tile_height, m_miplevel, m_miplevel); } catch (const std::exception &e) { error ("Failed OpenEXR write: %s", e.what()); return false; } return true; }
bool OpenEXROutput::write_tiles (int xbegin, int xend, int ybegin, int yend, int zbegin, int zend, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride) { // std::cerr << "exr::write_tiles " << xbegin << ' ' << xend // << ' ' << ybegin << ' ' << yend << "\n"; if (! m_output_tiled || ! m_spec.valid_tile_range (xbegin, xend, ybegin, yend, zbegin, zend)) return false; // Compute where OpenEXR needs to think the full buffers starts. // OpenImageIO requires that 'data' points to where the client wants // to put the pixels being read, but OpenEXR's frameBuffer.insert() // wants where the address of the "virtual framebuffer" for the // whole image. bool native = (format == TypeDesc::UNKNOWN); size_t user_pixelbytes = m_spec.pixel_bytes (native); size_t pixelbytes = m_spec.pixel_bytes (true); if (native && xstride == AutoStride) xstride = (stride_t) user_pixelbytes; m_spec.auto_stride (xstride, ystride, zstride, format, spec().nchannels, (xend-xbegin), (yend-ybegin)); data = to_native_rectangle (xbegin, xend, ybegin, yend, zbegin, zend, format, data, xstride, ystride, zstride, m_scratch); // clamp to the image edge xend = std::min (xend, m_spec.x+m_spec.width); yend = std::min (yend, m_spec.y+m_spec.height); zend = std::min (zend, m_spec.z+m_spec.depth); int firstxtile = (xbegin-m_spec.x) / m_spec.tile_width; int firstytile = (ybegin-m_spec.y) / m_spec.tile_height; int nxtiles = (xend - xbegin + m_spec.tile_width - 1) / m_spec.tile_width; int nytiles = (yend - ybegin + m_spec.tile_height - 1) / m_spec.tile_height; std::vector<char> padded; int width = nxtiles*m_spec.tile_width; int height = nytiles*m_spec.tile_height; stride_t widthbytes = width * pixelbytes; if (width != (xend-xbegin) || height != (yend-ybegin)) { // If the image region is not an even multiple of the tile size, // we need to copy and add padding. padded.resize (pixelbytes * width * height, 0); OIIO::copy_image (m_spec.nchannels, xend-xbegin, yend-ybegin, 1, data, pixelbytes, pixelbytes, (xend-xbegin)*pixelbytes, (xend-xbegin)*(yend-ybegin)*pixelbytes, &padded[0], pixelbytes, widthbytes, height*widthbytes); data = &padded[0]; } char *buf = (char *)data - xbegin * pixelbytes - ybegin * widthbytes; try { Imf::FrameBuffer frameBuffer; size_t chanoffset = 0; for (int c = 0; c < m_spec.nchannels; ++c) { size_t chanbytes = m_spec.channelformats.size() ? m_spec.channelformats[c].size() : m_spec.format.size(); frameBuffer.insert (m_spec.channelnames[c].c_str(), Imf::Slice (m_pixeltype[c], buf + chanoffset, pixelbytes, widthbytes)); chanoffset += chanbytes; } m_output_tiled->setFrameBuffer (frameBuffer); m_output_tiled->writeTiles (firstxtile, firstxtile+nxtiles-1, firstytile, firstytile+nytiles-1, m_miplevel, m_miplevel); } catch (const std::exception &e) { error ("Failed OpenEXR write: %s", e.what()); return false; } return true; }