bool ImageOutput::copy_to_image_buffer (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, void *image_buffer, TypeDesc buf_format) { const ImageSpec &spec (this->spec()); if (buf_format == TypeDesc::UNKNOWN) buf_format = spec.format; spec.auto_stride (xstride, ystride, zstride, format, spec.nchannels, spec.width, spec.height); stride_t buf_xstride = spec.nchannels * buf_format.size(); stride_t buf_ystride = buf_xstride * spec.width; stride_t buf_zstride = buf_ystride * spec.height; stride_t offset = (xbegin-spec.x)*buf_xstride + (ybegin-spec.y)*buf_ystride + (zbegin-spec.z)*buf_zstride; int width = xend-xbegin, height = yend-ybegin, depth = zend-zbegin; imagesize_t npixels = imagesize_t(width) * imagesize_t(height) * imagesize_t(depth); // Add dither if requested -- requires making a temporary staging area boost::scoped_array<float> ditherarea; unsigned int dither = spec.get_int_attribute ("oiio:dither", 0); if (dither && format.is_floating_point() && buf_format.basetype == TypeDesc::UINT8) { stride_t pixelsize = spec.nchannels * sizeof(float); ditherarea.reset (new float [pixelsize * npixels]); OIIO::convert_image (spec.nchannels, width, height, depth, data, format, xstride, ystride, zstride, ditherarea.get(), TypeDesc::FLOAT, pixelsize, pixelsize*width, pixelsize*width*height); data = ditherarea.get(); format = TypeDesc::FLOAT; xstride = pixelsize; ystride = xstride * width; zstride = ystride * height; float ditheramp = spec.get_float_attribute ("oiio:ditheramplitude", 1.0f/255.0f); OIIO::add_dither (spec.nchannels, width, height, depth, (float *)data, pixelsize, pixelsize*width, pixelsize*width*height, ditheramp, spec.alpha_channel, spec.z_channel, dither, 0, xbegin, ybegin, zbegin); } return OIIO::convert_image (spec.nchannels, width, height, depth, data, format, xstride, ystride, zstride, (char *)image_buffer + offset, buf_format, buf_xstride, buf_ystride, buf_zstride); }