/****************************************************************************** Get 2 bytes (word) from the given file: ******************************************************************************/ static int DGifGetWord(GifFileType *GifFile, GifWord *Word) { unsigned char c[2]; if (READ(GifFile, c, 2) != 2) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]); return GIF_OK; }
bool Gif::GcbToFrame(GifFrame &frame, unsigned int imgIdx) { int transparent = -1; frame.m_delay = 0; frame.m_disposal = 0; if (m_gif->ImageCount > 0) { #if GIFLIB_MAJOR == 5 GraphicsControlBlock gcb; if (!m_dll.DGifSavedExtensionToGCB(m_gif, imgIdx, &gcb)) { PrettyPrintError(StringUtils::Format("Gif::GcbToFrame(): Could not read GraphicsControlBlock of frame %d in file %s", imgIdx, memOrFile().c_str()), m_gif->Error); return false; } // delay in ms frame.m_delay = gcb.DelayTime * 10; frame.m_disposal = gcb.DisposalMode; transparent = gcb.TransparentColor; #else ExtensionBlock* extb = m_gif->SavedImages[imgIdx].ExtensionBlocks; while (extb && extb->Function != GRAPHICS_EXT_FUNC_CODE) extb++; if (!extb || extb->ByteCount != 4) { CLog::Log(LOGERROR, "Gif::GcbToFrame() : Could not read GraphicsControlBlock of frame %d in file %s", imgIdx, memOrFile().c_str()); return false; } else { frame.m_delay = UNSIGNED_LITTLE_ENDIAN(extb->Bytes[1], extb->Bytes[2]) * 10; frame.m_disposal = (extb->Bytes[0] >> 2) & 0x07; if (extb->Bytes[0] & 0x01) { transparent = static_cast<int>(extb->Bytes[3]); if (transparent < 0) transparent += 256; } else transparent = -1; } #endif }
int DGifExtensionToGCB(const size_t GifExtensionLength, const GifByteType *GifExtension, GraphicsControlBlock *GCB) { if (GifExtensionLength != 4) { return GIF_ERROR; } GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07; GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0; GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]); if (GifExtension[0] & 0x01) GCB->TransparentColor = (int)GifExtension[3]; else GCB->TransparentColor = NO_TRANSPARENT_COLOR; return GIF_OK; }
bool Gif::LoadGifMetaData(GifFileType* gif) { if (!m_dll.IsLoaded() || !Slurp(gif)) return false; m_height = gif->SHeight; m_width = gif->SWidth; if (!m_height || !m_width) { CLog::Log(LOGERROR, "Gif::LoadGif(): Zero sized image. File %s", memOrFile().c_str()); return false; } m_numFrames = gif->ImageCount; if (m_numFrames > 0) { ExtensionBlock* extb = gif->SavedImages[0].ExtensionBlocks; if (extb && extb->Function == APPLICATION_EXT_FUNC_CODE) { // Read number of loops if (++extb && extb->Function == CONTINUE_EXT_FUNC_CODE) { m_loops = UNSIGNED_LITTLE_ENDIAN(extb->Bytes[1], extb->Bytes[2]); } } } else { CLog::Log(LOGERROR, "Gif::LoadGif(): No images found in file %s", memOrFile().c_str()); return false; } m_pitch = m_width * sizeof(GifColor); m_imageSize = m_pitch * m_height; unsigned long memoryUsage = m_numFrames * m_imageSize; if (memoryUsage > GIF_MAX_MEMORY) { // at least 1 image m_numFrames = std::max(1U, GIF_MAX_MEMORY / m_imageSize); CLog::Log(LOGERROR, "Gif::LoadGif(): Memory consumption too high: %lu bytes. Restricting animation to %u. File %s", memoryUsage, m_numFrames, memOrFile().c_str()); } return true; }