const void * pvt::parallel_convert_from_float (const float *src, void *dst, size_t nvals, TypeDesc format, int nthreads) { if (format.basetype == TypeDesc::FLOAT) return src; const size_t quanta = 30000; if (nvals < quanta) nthreads = 1; if (nthreads <= 0) nthreads = oiio_threads; int quant_min, quant_max; get_default_quantize (format, quant_min, quant_max); if (nthreads <= 1) return convert_from_float (src, dst, nvals, quant_min, quant_max, format); boost::thread_group threads; size_t blocksize = std::max (quanta, size_t((nvals + nthreads - 1) / nthreads)); for (size_t i = 0; i < size_t(nthreads); i++) { size_t begin = i * blocksize; if (begin >= nvals) break; // no more work to divvy up size_t end = std::min (begin + blocksize, nvals); threads.add_thread (new boost::thread ( boost::bind (convert_from_float, src+begin, (char *)dst+begin*format.size(), end-begin, quant_min, quant_max, format))); } threads.join_all (); return dst; }
// DEPRECATED (1.4) const void * pvt::convert_from_float (const float *src, void *dst, size_t nvals, int quant_black, int quant_white, int quant_min, int quant_max, TypeDesc format) { return convert_from_float (src, dst, nvals, quant_min, quant_max, format); }
/* {{{ ps_fetch_double */ static void ps_fetch_double(MYSQL_BIND *r_param, const MYSQL_FIELD * field , unsigned char **row) { switch (r_param->buffer_type) { case MYSQL_TYPE_DOUBLE: { double *value= (double *)r_param->buffer; float8get(*value, *row); r_param->buffer_length= 8; } break; default: { double value; float8get(value, *row); convert_from_float(r_param, field, value, sizeof(double)); } break; } (*row)+= 8; }
/* {{{ ps_fetch_float */ static void ps_fetch_float(MYSQL_BIND *r_param, const MYSQL_FIELD * field, unsigned char **row) { switch(r_param->buffer_type) { case MYSQL_TYPE_FLOAT: { float *value= (float *)r_param->buffer; float4get(*value, *row); r_param->buffer_length= 4; *r_param->error= 0; } break; default: { float value; memcpy(&value, *row, sizeof(float)); float4get(value, (char *)*row); convert_from_float(r_param, field, value, sizeof(float)); } break; } (*row)+= 4; }
const void * ImageOutput::to_native_rectangle (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::vector<unsigned char> &scratch) { // native_pixel_bytes is the size of a pixel in the FILE, including // the per-channel format, if specified when the file was opened. stride_t native_pixel_bytes = (stride_t) m_spec.pixel_bytes (true); // perchanfile is true if the file has different per-channel formats bool perchanfile = m_spec.channelformats.size() && supports("channelformats"); // It's an error to pass per-channel data formats to a writer that // doesn't support it. if (m_spec.channelformats.size() && !perchanfile) return NULL; // native_data is true if the user is passing data in the native format bool native_data = (format == TypeDesc::UNKNOWN || (format == m_spec.format && !perchanfile)); // If the user is passing native data and they've left xstride set // to Auto, then we know it's the native pixel size. if (native_data && xstride == AutoStride) xstride = native_pixel_bytes; // Fill in the rest of the strides that haven't been set. m_spec.auto_stride (xstride, ystride, zstride, format, m_spec.nchannels, xend-xbegin, yend-ybegin); // Compute width and height from the rectangle extents int width = xend - xbegin; int height = yend - ybegin; int depth = zend - zbegin; // Do the strides indicate that the data area is contiguous? bool contiguous = (xstride == (stride_t)m_spec.pixel_bytes(native_data)); contiguous &= ((ystride == xstride*width || height == 1) && (zstride == ystride*height || depth == 1)); if (native_data && contiguous) { // Data are already in the native format and contiguous // just return a ptr to the original data. return data; } imagesize_t rectangle_pixels = width * height * depth; imagesize_t rectangle_values = rectangle_pixels * m_spec.nchannels; imagesize_t rectangle_bytes = rectangle_pixels * native_pixel_bytes; // Cases to handle: // 1. File has per-channel data, user passes native data -- this has // already returned above, since the data didn't need munging. // 2. File has per-channel data, user passes some other data type // 3. File has uniform data, user passes some other data type // 4. File has uniform data, user passes the right data -- note that // this case already returned if the user data was contiguous // Handle the per-channel format case (#2) where the user is passing // a non-native buffer. if (perchanfile) { if (native_data) { ASSERT (contiguous && "Per-channel native output requires contiguous strides"); } ASSERT (format != TypeDesc::UNKNOWN); ASSERT (m_spec.channelformats.size() == (size_t)m_spec.nchannels); scratch.resize (rectangle_bytes); size_t offset = 0; for (int c = 0; c < m_spec.nchannels; ++c) { TypeDesc chanformat = m_spec.channelformats[c]; convert_image (1 /* channels */, width, height, depth, (char *)data + c*format.size(), format, xstride, ystride, zstride, &scratch[offset], chanformat, native_pixel_bytes, AutoStride, AutoStride, NULL, c == m_spec.alpha_channel ? 0 : -1, c == m_spec.z_channel ? 0 : -1); offset += chanformat.size (); } return &scratch[0]; } // The remaining code is where all channels in the file have the // same data type, which may or may not be what the user passed in // (cases #3 and #4 above). imagesize_t contiguoussize = contiguous ? 0 : rectangle_values * native_pixel_bytes; contiguoussize = (contiguoussize+3) & (~3); // Round up to 4-byte boundary DASSERT ((contiguoussize & 3) == 0); imagesize_t floatsize = rectangle_values * sizeof(float); scratch.resize (contiguoussize + floatsize + rectangle_bytes); // Force contiguity if not already present if (! contiguous) { data = contiguize (data, m_spec.nchannels, xstride, ystride, zstride, (void *)&scratch[0], width, height, depth, format); } // Rather than implement the entire cross-product of possible // conversions, use float as an intermediate format, which generally // will always preserve enough precision. const float *buf; if (format == TypeDesc::FLOAT) { // Already in float format -- leave it as-is. buf = (float *)data; } else { // Convert to from 'format' to float. buf = convert_to_float (data, (float *)&scratch[contiguoussize], rectangle_values, format); } // Convert from float to native format. return convert_from_float (buf, &scratch[contiguoussize+floatsize], rectangle_values, m_spec.quant_black, m_spec.quant_white, m_spec.quant_min, m_spec.quant_max, m_spec.format); }
const void * ImageOutput::to_native_rectangle (int xmin, int xmax, int ymin, int ymax, int zmin, int zmax, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride, std::vector<unsigned char> &scratch) { stride_t native_pixel_bytes = (stride_t) m_spec.pixel_bytes (true); if (format == TypeDesc::UNKNOWN && xstride == AutoStride) xstride = native_pixel_bytes; m_spec.auto_stride (xstride, ystride, zstride, format, m_spec.nchannels, xmax-xmin+1, ymax-ymin+1); // Compute width and height from the rectangle extents int width = xmax - xmin + 1; int height = ymax - ymin + 1; int depth = zmax - zmin + 1; // Do the strides indicate that the data are already contiguous? bool contiguous = (xstride == native_pixel_bytes && (ystride == xstride*width || height == 1) && (zstride == ystride*height || depth == 1)); // Does the user already have the data in the right format? bool rightformat = (format == TypeDesc::UNKNOWN) || (format == m_spec.format && m_spec.channelformats.empty()); if (rightformat && contiguous) { // Data are already in the native format and contiguous // just return a ptr to the original data. return data; } imagesize_t rectangle_pixels = width * height * depth; imagesize_t rectangle_values = rectangle_pixels * m_spec.nchannels; imagesize_t rectangle_bytes = rectangle_pixels * native_pixel_bytes; // Handle the per-channel format case if (m_spec.channelformats.size() && supports("channelformats")) { ASSERT (contiguous && "Per-channel output requires contiguous strides"); ASSERT (format != TypeDesc::UNKNOWN); scratch.resize (rectangle_bytes); size_t offset = 0; for (int c = 0; c < (int)m_spec.channelformats.size(); ++c) { TypeDesc chanformat = m_spec.channelformats[c]; convert_image (1 /* channels */, width, height, depth, (char *)data + c*m_spec.format.size(), format, xstride, ystride, zstride, &scratch[offset], chanformat, native_pixel_bytes, AutoStride, AutoStride, NULL, c == m_spec.alpha_channel ? 0 : -1, c == m_spec.z_channel ? 0 : -1); offset = chanformat.size (); } return &scratch[0]; } imagesize_t contiguoussize = contiguous ? 0 : rectangle_values * native_pixel_bytes; contiguoussize = (contiguoussize+3) & (~3); // Round up to 4-byte boundary DASSERT ((contiguoussize & 3) == 0); imagesize_t floatsize = rectangle_values * sizeof(float); scratch.resize (contiguoussize + floatsize + rectangle_bytes); // Force contiguity if not already present if (! contiguous) { data = contiguize (data, m_spec.nchannels, xstride, ystride, zstride, (void *)&scratch[0], width, height, depth, format); } // Rather than implement the entire cross-product of possible // conversions, use float as an intermediate format, which generally // will always preserve enough precision. const float *buf; if (format == TypeDesc::FLOAT) { // Already in float format -- leave it as-is. buf = (float *)data; } else { // Convert to from 'format' to float. buf = convert_to_float (data, (float *)&scratch[contiguoussize], rectangle_values, format); } // Convert from float to native format. return convert_from_float (buf, &scratch[contiguoussize+floatsize], rectangle_values, m_spec.quant_black, m_spec.quant_white, m_spec.quant_min, m_spec.quant_max, m_spec.format); }