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; }
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; }