Beispiel #1
0
bool
OpenEXRInput::read_native_tile (int x, int y, int z, void *data)
{
    return read_native_tiles (x, x+m_spec.tile_width, y, y+m_spec.tile_height,
                              z, z+m_spec.tile_depth,
                              0, m_spec.nchannels, data);
}
Beispiel #2
0
bool
OpenEXRInput::read_native_tiles (int xbegin, int xend, int ybegin, int yend,
                                 int zbegin, int zend, void *data)
{
    return read_native_tiles (xbegin, xend, ybegin, yend, zbegin, zend,
                              0, m_spec.nchannels, data);
}
Beispiel #3
0
bool
ImageInput::read_native_tiles (int xbegin, int xend, int ybegin, int yend,
                               int zbegin, int zend, 
                               int chbegin, int chend, void *data)
{
    chend = clamp (chend, chbegin+1, m_spec.nchannels);
    int nchans = chend - chbegin;

    // All-channel case just reduces to the simpler read_native_scanlines.
    if (chbegin == 0 && chend >= m_spec.nchannels)
        return read_native_tiles (xbegin, xend, ybegin, yend,
                                  zbegin, zend, data);

    if (! m_spec.valid_tile_range (xbegin, xend, ybegin, yend, zbegin, zend))
        return false;

    // Base class implementation of read_native_tiles just repeatedly
    // calls read_native_tile, which is supplied by every plugin that
    // supports tiles.  Only the hardcore ones will overload
    // read_native_tiles with their own implementation.

    stride_t native_pixel_bytes = (stride_t) m_spec.pixel_bytes (true);
    stride_t native_tileystride = native_pixel_bytes * m_spec.tile_width;
    stride_t native_tilezstride = native_tileystride * m_spec.tile_height;

    size_t prefix_bytes = m_spec.pixel_bytes (0,chbegin,true);
    size_t subset_bytes = m_spec.pixel_bytes (chbegin,chend,true);
    stride_t subset_ystride = (xend-xbegin) * subset_bytes;
    stride_t subset_zstride = (yend-ybegin) * subset_ystride;

    boost::scoped_array<char> pels (new char [m_spec.tile_bytes(true)]);
    for (int z = zbegin;  z < zend;  z += m_spec.tile_depth) {
        for (int y = ybegin;  y < yend;  y += m_spec.tile_height) {
            for (int x = xbegin;  x < xend;  x += m_spec.tile_width) {
                bool ok = read_native_tile (x, y, z, &pels[0]);
                if (! ok)
                    return false;
                copy_image (nchans, m_spec.tile_width,
                            m_spec.tile_height, m_spec.tile_depth,
                            &pels[prefix_bytes], subset_bytes,
                            native_pixel_bytes, native_tileystride,
                            native_tilezstride,
                            (char *)data+ (z-zbegin)*subset_zstride + 
                                (y-ybegin)*subset_ystride +
                                (x-xbegin)*subset_bytes,
                            subset_bytes, subset_ystride, subset_zstride);
            }
        }
    }
    return true;
}
Beispiel #4
0
bool 
ImageInput::read_tiles (int xbegin, int xend, int ybegin, int yend,
                        int zbegin, int zend, 
                        int firstchan, int nchans,
                        TypeDesc format, void *data,
                        stride_t xstride, stride_t ystride, stride_t zstride)
{
    if (! m_spec.valid_tile_range (xbegin, xend, ybegin, yend, zbegin, zend))
        return false;

    nchans = std::min (nchans, m_spec.nchannels-firstchan);
    // native_pixel_bytes is the size of a pixel in the FILE, including
    // the per-channel format.
    stride_t native_pixel_bytes = (stride_t) m_spec.pixel_bytes (firstchan, nchans, true);
    // perchanfile is true if the file has different per-channel formats
    bool perchanfile = m_spec.channelformats.size();
    // native_data is true if the user asking for data in the native format
    bool native_data = (format == TypeDesc::UNKNOWN ||
                        (format == m_spec.format && !perchanfile));
    if (format == TypeDesc::UNKNOWN && xstride == AutoStride)
        xstride = native_pixel_bytes;
    m_spec.auto_stride (xstride, ystride, zstride, format, nchans,
                        xend-xbegin, yend-ybegin);
    // Do the strides indicate that the data area is contiguous?
    bool contiguous = (native_data && xstride == native_pixel_bytes) ||
        (!native_data && xstride == (stride_t)m_spec.pixel_bytes(false));
    contiguous &= (ystride == xstride*(xend-xbegin) &&
                   (zstride == ystride*(yend-ybegin) || (zend-zbegin) <= 1));

    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;
    int nztiles = (zend - zbegin + m_spec.tile_depth - 1) / m_spec.tile_depth;

    // If user's format and strides are set up to accept the native data
    // layout, and we're asking for a whole number of tiles (no partial
    // tiles at the edges), then read the tile directly into the user's
    // buffer.
    if (native_data && contiguous &&
        (xend-xbegin) == nxtiles*m_spec.tile_width &&
        (yend-ybegin) == nytiles*m_spec.tile_height &&
        (zend-zbegin) == nztiles*m_spec.tile_depth) {
        if (firstchan == 0 && nchans == m_spec.nchannels)
            return read_native_tiles (xbegin, xend, ybegin, yend, zbegin, zend,
                                      data);  // Simple case
        else
            return read_native_tiles (xbegin, xend, ybegin, yend, zbegin, zend,
                                      firstchan, nchans, data);
    }

    // No such luck.  Just punt and read tiles individually.
    bool ok = true;
    stride_t pixelsize = native_data ? native_pixel_bytes 
                                     : (format.size() * nchans);
    stride_t full_pixelsize = native_data ? m_spec.pixel_bytes(true)
                                          : (format.size() * m_spec.nchannels);
    size_t prefix_bytes = m_spec.pixel_bytes (0,firstchan,true);
    std::vector<char> buf;
    for (int z = zbegin;  z < zend;  z += std::max(1,m_spec.tile_depth)) {
        int zd = std::min (zend-z, m_spec.tile_depth);
        for (int y = ybegin;  y < yend;  y += m_spec.tile_height) {
            char *tilestart = ((char *)data + (z-zbegin)*zstride
                               + (y-ybegin)*ystride);
            int yh = std::min (yend-y, m_spec.tile_height);
            for (int x = xbegin;  ok && x < xend;  x += m_spec.tile_width) {
                int xw = std::min (xend-x, m_spec.tile_width);
                // Full tiles are read directly into the user buffer,
                // but partial tiles (such as at the image edge) or
                // partial channel subsets are read into a buffer and
                // then copied.
                if (xw == m_spec.tile_width && yh == m_spec.tile_height &&
                      zd == m_spec.tile_depth &&
                      firstchan == 0 && nchans == m_spec.nchannels) {
                    ok &= read_tile (x, y, z, format, tilestart,
                                     xstride, ystride, zstride);
                } else {
                    buf.resize (m_spec.tile_bytes());
                    ok &= read_tile (x, y, z, format, &buf[0],
                                     full_pixelsize,
                                     full_pixelsize*m_spec.tile_width,
                                     full_pixelsize*m_spec.tile_pixels());
                    if (ok)
                        copy_image (nchans, xw, yh, zd, &buf[prefix_bytes],
                                    pixelsize, full_pixelsize,
                                    full_pixelsize*m_spec.tile_width,
                                    full_pixelsize*m_spec.tile_pixels(),
                                    tilestart, xstride, ystride, zstride);
                }
                tilestart += m_spec.tile_width * xstride;
            }
        }
    }

    if (! ok)
        error ("ImageInput::read_tiles : no support for format %s",
               m_spec.format.c_str());
    return ok;
}