From f741453b94b8ce76aa9a6dda4730d8745d40e4ea Mon Sep 17 00:00:00 2001 From: poire-z Date: Sun, 22 Apr 2018 12:47:00 +0200 Subject: [PATCH] Adds Pic.openGIFDocumentFromData() (#657) This will allow using giflib to render GIF images, which is better than MuPDF for rendering the first frame of an animated GIF, and will allow getting all its frames. Also fix alpha value when combining animated GIF frames. --- ffi/giflib_h.lua | 2 ++ ffi/pic.lua | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ffi/giflib_h.lua b/ffi/giflib_h.lua index 0e27a620a..8cb6a406b 100644 --- a/ffi/giflib_h.lua +++ b/ffi/giflib_h.lua @@ -75,4 +75,6 @@ static const int DISPOSE_DO_NOT = 1; static const int DISPOSE_BACKGROUND = 2; static const int DISPOSE_PREVIOUS = 3; static const int NO_TRANSPARENT_COLOR = -1; +typedef int (*GifInputFunc) (GifFileType *, GifByteType *, int); +GifFileType *DGifOpen(void *, GifInputFunc, int *); ]] diff --git a/ffi/pic.lua b/ffi/pic.lua index 4da407e9a..7ef73d00b 100644 --- a/ffi/pic.lua +++ b/ffi/pic.lua @@ -166,7 +166,7 @@ function GifDocument:openPage(number) local palette={} for c=0, cmap.ColorCount-1 do local color = cmap.Colors[c] - palette[c] = BB.ColorRGB32(color.Red, color.Green, color.Blue, 0) + palette[c] = BB.ColorRGB32(color.Red, color.Green, color.Blue, 0xFF) end -- Draw current frame on our bb @@ -221,6 +221,37 @@ function Pic.openGIFDocument(filename) return GifDocument:new{giffile = giffile} end +function Pic.openGIFDocumentFromData(data, size) + -- Create GIF from data pointer (from https://github.com/luapower/giflib) + local function data_reader(r_data, r_size) + r_data = ffi.cast('unsigned char*', r_data) + return function(_, buf, sz) + if sz < 1 or r_size < 1 then error('eof') end + sz = math.min(r_size, sz) + ffi.copy(buf, r_data, sz) + r_data = r_data + sz + r_size = r_size - sz + return sz + end + end + local read_cb = ffi.cast('GifInputFunc', data_reader(data, size)) + local err = ffi.new("int[1]") + local giffile = giflib.DGifOpen(nil, read_cb, err) + if giffile == nil then + read_cb:free() + error(string.format("Cannot read GIF file: %s", + ffi.string(giflib.GifErrorString(err[0])))) + end + if giflib.DGifSlurp(giffile) ~= giflib.GIF_OK then + giflib.DGifCloseFile(giffile, err) + read_cb:free() + error(string.format("Cannot parse GIF file: %s", + ffi.string(giflib.GifErrorString(giffile.Error)))) + end + read_cb:free() + return GifDocument:new{giffile = giffile} +end + function Pic.openPNGDocument(filename) local ok, re = Png.decodeFromFile(filename) if not ok then error(re) end