Ejemplo n.º 1
0
bool
ImageInput::read_native_tiles (int xbegin, int xend, int ybegin, int yend,
                               int zbegin, int zend, void *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 pixel_bytes = (stride_t) m_spec.pixel_bytes (true);
    stride_t tileystride = pixel_bytes * m_spec.tile_width;
    stride_t tilezstride = tileystride * m_spec.tile_height;
    stride_t ystride = (xend-xbegin) * pixel_bytes;
    stride_t zstride = (yend-ybegin) * ystride;
    std::vector<char> pels (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 (m_spec.nchannels, m_spec.tile_width,
                            m_spec.tile_height, m_spec.tile_depth,
                            &pels[0], size_t(pixel_bytes),
                            pixel_bytes, tileystride, tilezstride,
                            (char *)data+ (z-zbegin)*zstride + 
                                (y-ybegin)*ystride + (x-xbegin)*pixel_bytes,
                            pixel_bytes, ystride, zstride);
            }
        }
    }
    return true;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
bool
ImageInput::read_image (TypeDesc format, void *data,
                        stride_t xstride, stride_t ystride, stride_t zstride,
                        ProgressCallback progress_callback,
                        void *progress_callback_data)
{
    bool native = (format == TypeDesc::UNKNOWN);
    stride_t pixel_bytes = native ? (stride_t) m_spec.pixel_bytes (native)
                                  : (stride_t) (format.size()*m_spec.nchannels);
    if (native && xstride == AutoStride)
        xstride = pixel_bytes;
    m_spec.auto_stride (xstride, ystride, zstride, format, m_spec.nchannels,
                        m_spec.width, m_spec.height);
    bool ok = true;
    if (progress_callback)
        if (progress_callback (progress_callback_data, 0.0f))
            return ok;
    if (m_spec.tile_width) {
        // Tiled image

        // Locally allocate a single tile to gracefully deal with image
        // dimensions smaller than a tile, or if one of the tiles runs
        // past the right or bottom edge.  Then we copy from our tile to
        // the user data, only copying valid pixel ranges.
        stride_t tilexstride = pixel_bytes;
        stride_t tileystride = tilexstride * m_spec.tile_width;
        stride_t tilezstride = tileystride * m_spec.tile_height;
        imagesize_t tile_pixels = m_spec.tile_pixels();
        std::vector<char> pels (tile_pixels * pixel_bytes);
        for (int z = 0;  z < m_spec.depth;  z += m_spec.tile_depth)
            for (int y = 0;  y < m_spec.height;  y += m_spec.tile_height) {
                for (int x = 0;  x < m_spec.width && ok;  x += m_spec.tile_width) {
                    ok &= read_tile (x+m_spec.x, y+m_spec.y, z+m_spec.z,
                                     format, &pels[0]);
                    // Now copy out the scanlines
                    int ntz = std::min (z+m_spec.tile_depth, m_spec.depth) - z;
                    int nty = std::min (y+m_spec.tile_height, m_spec.height) - y;
                    int ntx = std::min (x+m_spec.tile_width, m_spec.width) - x;
                    for (int tz = 0;  tz < ntz;  ++tz) {
                        for (int ty = 0;  ty < nty;  ++ty) {
                            // FIXME -- doesn't work for non-contiguous scanlines
                            memcpy ((char *)data + x*xstride + (y+ty)*ystride + (z+tz)*zstride,
                                    &pels[ty*tileystride+tz*tilezstride],
                                    ntx*tilexstride);
                        }
                    }
//                    return ok; // DEBUG -- just try very first tile
                }
                if (progress_callback)
                    if (progress_callback (progress_callback_data, (float)y/m_spec.height))
                        return ok;
            }
    } else {
        // Scanline image
        for (int z = 0;  z < m_spec.depth;  ++z)
            for (int y = 0;  y < m_spec.height && ok;  ++y) {
                ok &= read_scanline (y+m_spec.y, z+m_spec.z, format,
                                     (char *)data + z*zstride + y*ystride,
                                     xstride);
                if (progress_callback && !(y & 0x0f))
                    if (progress_callback (progress_callback_data, (float)y/m_spec.height))
                        return ok;
            }
    }
    if (progress_callback)
        progress_callback (progress_callback_data, 1.0f);
    return ok;
}
Ejemplo n.º 4
0
bool
ImageOutput::write_image (TypeDesc format, const void *data,
                          stride_t xstride, stride_t ystride, stride_t zstride,
                          ProgressCallback progress_callback,
                          void *progress_callback_data)
{
    bool native = (format == TypeDesc::UNKNOWN);
    stride_t pixel_bytes = (stride_t) m_spec.pixel_bytes (native);
    if (native && xstride == AutoStride)
        xstride = pixel_bytes;
    m_spec.auto_stride (xstride, ystride, zstride, format,
                        m_spec.nchannels, m_spec.width, m_spec.height);
    if (supports ("rectangles")) {
        // Use a rectangle if we can
        return write_rectangle (0, m_spec.width-1, 0, m_spec.height-1, 0, m_spec.depth-1,
                                format, data, xstride, ystride, zstride);
    }

    bool ok = true;
    if (progress_callback)
        if (progress_callback (progress_callback_data, 0.0f))
            return ok;
    if (m_spec.tile_width && supports ("tiles")) {
        // Tiled image

        // FIXME: what happens if the image dimensions are smaller than
        // the tile dimensions?  Or if one of the tiles runs past the
        // right or bottom edge?  Do we need to allocate a full tile and
        // copy into it before calling write_tile?  That's probably the
        // safe thing to do.  Or should that handling be pushed all the
        // way into write_tile itself?

        // Locally allocate a single tile to gracefully deal with image
        // dimensions smaller than a tile, or if one of the tiles runs
        // past the right or bottom edge.  Then we copy from our tile to
        // the user data, only copying valid pixel ranges.
        size_t tilexstride = pixel_bytes;
        size_t tileystride = tilexstride * m_spec.tile_width;
        size_t tilezstride = tileystride * m_spec.tile_height;
        size_t tile_pixels = (size_t)m_spec.tile_width * (size_t)m_spec.tile_height *
            (size_t)std::max(1,m_spec.tile_depth);
        std::vector<char> pels (tile_pixels * pixel_bytes);
        for (int z = 0;  z < m_spec.depth;  z += m_spec.tile_depth)
            for (int y = 0;  y < m_spec.height;  y += m_spec.tile_height) {
                for (int x = 0;  x < m_spec.width && ok;  x += m_spec.tile_width) {
                    // Now copy out the scanlines
                    // FIXME -- can we do less work for the tiles that
                    // don't overlap image boundaries?
                    int ntz = std::min (z+m_spec.tile_depth, m_spec.depth) - z;
                    int nty = std::min (y+m_spec.tile_height, m_spec.height) - y;
                    int ntx = std::min (x+m_spec.tile_width, m_spec.width) - x;
                    for (int tz = 0;  tz < ntz;  ++tz) {
                        for (int ty = 0;  ty < nty;  ++ty) {
                            // FIXME -- doesn't work for non-contiguous scanlines
                            memcpy (&pels[ty*tileystride+tz*tilezstride],
                                    (char *)data + x*xstride + (y+ty)*ystride + (z+tz)*zstride,
                                    ntx*tilexstride);
                        }
                    }

                    ok &= write_tile (x+m_spec.x, y+m_spec.y, z+m_spec.z,
                                      format, &pels[0]);
                }
                if (progress_callback)
                    if (progress_callback (progress_callback_data, (float)y/m_spec.height))
                        return ok;
            }
    } else {
        // Scanline image
        for (int z = 0;  z < m_spec.depth;  ++z)
            for (int y = 0;  y < m_spec.height && ok;  ++y) {
                ok &= write_scanline (y+m_spec.y, z+m_spec.z, format,
                                      (const char *)data + z*zstride + y*ystride,
                                      xstride);
                if (progress_callback && !(y & 0x0f))
                    if (progress_callback (progress_callback_data, (float)y/m_spec.height))
                        return ok;
            }
    }
    if (progress_callback)
        progress_callback (progress_callback_data, 1.0f);

    return ok;
}