Esempio n. 1
0
bool 
ImageInput::read_scanline (int y, int z, TypeDesc format, void *data,
                           stride_t xstride)
{
    // 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 (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 (native_data && xstride == AutoStride)
        xstride = native_pixel_bytes;
    else
        m_spec.auto_stride (xstride, format, m_spec.nchannels);
    // 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));

    // If user's format and strides are set up to accept the native data
    // layout, read the scanline directly into the user's buffer.
    if (native_data && contiguous)
        return read_native_scanline (y, z, data);

    // Complex case -- either changing data type or stride
    int scanline_values = m_spec.width * m_spec.nchannels;
    unsigned char *buf = (unsigned char *) alloca (m_spec.scanline_bytes(true));
    bool ok = read_native_scanline (y, z, buf);
    if (! ok)
        return false;
    if (! perchanfile) {
        // No per-channel formats -- do the conversion in one shot
        ok = contiguous 
            ? convert_types (m_spec.format, buf, format, data, scanline_values)
            : convert_image (m_spec.nchannels, m_spec.width, 1, 1, 
                             buf, m_spec.format, AutoStride, AutoStride, AutoStride,
                             data, format, xstride, AutoStride, AutoStride);
    } else {
        // Per-channel formats -- have to convert/copy channels individually
        ASSERT (m_spec.channelformats.size() == (size_t)m_spec.nchannels);
        size_t offset = 0;
        for (int c = 0;  ok && c < m_spec.nchannels;  ++c) {
            TypeDesc chanformat = m_spec.channelformats[c];
            ok = convert_image (1 /* channels */, m_spec.width, 1, 1, 
                                buf+offset, chanformat, 
                                native_pixel_bytes, AutoStride, AutoStride,
                                (char *)data + c*format.size(),
                                format, xstride, AutoStride, AutoStride);
            offset += chanformat.size ();
        }
    }

    if (! ok)
        error ("ImageInput::read_scanline : no support for format %s",
               m_spec.format.c_str());
    return ok;
}
Esempio n. 2
0
bool
ImageInput::read_native_scanlines (int ybegin, int yend, int z,
                                   int firstchan, int nchans, void *data)
{
    // All-channel case just reduces to the simpler read_native_scanlines.
    if (firstchan == 0 && nchans >= m_spec.nchannels)
        return read_native_scanlines (ybegin, yend, z, data);

    // Base class implementation of read_native_scanlines (with channel
    // subset) just calls read_native_scanlines (all channels), and
    // copies the appropriate subset.
    size_t prefix_bytes = m_spec.pixel_bytes (0,firstchan,true);
    size_t subset_bytes = m_spec.pixel_bytes (firstchan,nchans,true);
    size_t subset_ystride = m_spec.width * subset_bytes;

    size_t native_pixel_bytes = m_spec.pixel_bytes (true);
    size_t native_ystride = m_spec.width * native_pixel_bytes;
    std::vector<char> buf (native_ystride);
    yend = std::min (yend, spec().y+spec().height);
    for (int y = ybegin;  y < yend;  ++y) {
        bool ok = read_native_scanline (y, z, &buf[0]);
        if (! ok)
            return false;
        for (int x = 0;  x < m_spec.width;  ++x)
            memcpy ((char *)data + subset_bytes*x,
                    &buf[prefix_bytes+native_pixel_bytes*x], subset_bytes);
        data = (char *)data + subset_ystride;
    }
    return true;
}
Esempio n. 3
0
bool
ImageInput::read_native_scanlines (int ybegin, int yend, int z, void *data)
{
    // Base class implementation of read_native_scanlines just repeatedly
    // calls read_native_scanline, which is supplied by every plugin.
    // Only the hardcore ones will overload read_native_scanlines with
    // their own implementation.
    size_t ystride = m_spec.scanline_bytes (true);
    yend = std::min (yend, spec().y+spec().height);
    for (int y = ybegin;  y < yend;  ++y) {
        bool ok = read_native_scanline (y, z, data);
        if (! ok)
            return false;
        data = (char *)data + ystride;
    }
    return true;
}