bool test (int height)
{
    bool ok = true;
    std::set<int> encoded, decoded;
    for (int l = 0; l < height; l++) {
        int d = decode_line_number (l, height);
        ok &= 0 <= d && d < height;
        decoded.insert (d);

        int e = encode_line_number (l, height);
        ok &= 0 <= e && e < height;
        encoded.insert (e);

        ok &= (l == encode_line_number(decode_line_number(l, height), height));
        ok &= (l == decode_line_number(encode_line_number(l, height), height));
    }

    ok &= decoded.size() == height;
    ok &= encoded.size() == height;

    return ok;
}
Esempio n. 2
0
bool
GIFInput::read_native_scanline (int _y, int z, void *data)
{
    if (_y < 0 || _y > m_spec.height)
        return false;

    bool interlacing = m_spec.get_int_attribute ("gif:Interlacing") != 0;

    // decode scanline index if image is interlaced
    int gif_y = interlacing ? decode_line_number (_y) : _y;

    if (interlacing) { // gif is interlaced so cache the scanlines
        int scanlines_cached = m_cached_data.size() / m_spec.width;
        if (gif_y >= scanlines_cached) {
            // scanline is not cached yet, read the scanline and preceding ones
            m_cached_data.resize (m_spec.width * (gif_y + 1));
            int delta_size = m_spec.width * (gif_y - scanlines_cached + 1);
            if (DGifGetLine (m_gif_file,
                             &m_cached_data[scanlines_cached * m_spec.width],
                             delta_size) == GIF_ERROR) {
                report_last_error ();
                return false;
            }
        }

        translate_scanline (&m_cached_data[gif_y * m_spec.width], data);

    } else { // no interlacing, thus no scanlines caching
        if (m_next_scanline > gif_y) {
            // requested scanline is located before the one to read next
            // random access is not supported, so reopen the file, find
            // current subimage and skip preceding image data
            ImageSpec dummyspec;
            if (! close () ||
                    ! open (m_filename, dummyspec) ||
                    ! seek_subimage (m_subimage, 0, dummyspec)) {
                return false;
            }

            int remaining_size = m_spec.width * gif_y;
            boost::scoped_array<unsigned char> buffer
            (new unsigned char[remaining_size]);
            if (DGifGetLine (m_gif_file, buffer.get(), remaining_size)
                    == GIF_ERROR) {
                report_last_error ();
                return false;
            }

        } else if (m_next_scanline < gif_y) {
            // requested scanline is located after the one to read next
            // skip the lines in between
            int delta_size = m_spec.width * (gif_y - m_next_scanline);
            boost::scoped_array<unsigned char> buffer
            (new unsigned char[delta_size]);
            if (DGifGetLine (m_gif_file,
                             buffer.get(),
                             delta_size) == GIF_ERROR) {
                report_last_error ();
                return false;
            }
        }

        // read the requested scanline
        boost::scoped_array<unsigned char> fscanline
        (new unsigned char[m_spec.width]);
        if (DGifGetLine (m_gif_file,
                         fscanline.get(),
                         m_spec.width) == GIF_ERROR) {
            report_last_error ();
            return false;
        }
        translate_scanline (fscanline.get(), data);
    }

    m_next_scanline = gif_y + 1;

    return true;
}