mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-19 00:15:30 +00:00
IMAGE: added GIFDecoder using libgif
This commit is contained in:
parent
78c48fd9df
commit
bb34721dd4
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@ -15,21 +15,21 @@ jobs:
|
||||
arch: x86
|
||||
# fribidi is disabled due to timeouts when installing the package
|
||||
configFlags: --enable-faad --enable-mpeg2 --enable-discord --disable-fribidi
|
||||
vcpkgPackages: 'curl discord-rpc faad2 fluidsynth freetype glew libflac libjpeg-turbo libmad libmpeg2 libogg libpng libtheora libvorbis sdl2 sdl2-net zlib'
|
||||
vcpkgPackages: 'curl discord-rpc faad2 fluidsynth freetype glew libflac libjpeg-turbo libmad libmpeg2 libogg libpng libtheora libvorbis sdl2 sdl2-net zlib giflib'
|
||||
useNasm: 'true'
|
||||
- platform: x64
|
||||
arch: x64
|
||||
triplet: x64-windows
|
||||
# fribidi is disabled due to timeouts when installing the package
|
||||
configFlags: --enable-faad --enable-mpeg2 --enable-discord --disable-fribidi
|
||||
vcpkgPackages: 'curl discord-rpc faad2 fluidsynth freetype glew libflac libjpeg-turbo libmad libmpeg2 libogg libpng libtheora libvorbis sdl2 sdl2-net zlib'
|
||||
vcpkgPackages: 'curl discord-rpc faad2 fluidsynth freetype glew libflac libjpeg-turbo libmad libmpeg2 libogg libpng libtheora libvorbis sdl2 sdl2-net zlib giflib'
|
||||
- platform: arm64
|
||||
arch: arm64
|
||||
triplet: arm64-windows
|
||||
# fribidi is disabled due to https://github.com/microsoft/vcpkg/issues/11248 [fribidi] Fribidi doesn't cross-compile on x86-64 to target arm/arm64
|
||||
# Note that fribidi is also disabled on arm64 in devtools/create_project/msvc.cpp
|
||||
configFlags: --enable-faad --enable-mpeg2 --enable-discord --disable-fribidi --disable-opengl
|
||||
vcpkgPackages: 'curl discord-rpc faad2 fluidsynth freetype libflac libjpeg-turbo libmad libmpeg2 libogg libpng libtheora libvorbis sdl2 sdl2-net zlib'
|
||||
vcpkgPackages: 'curl discord-rpc faad2 fluidsynth freetype libflac libjpeg-turbo libmad libmpeg2 libogg libpng libtheora libvorbis sdl2 sdl2-net zlib giflib'
|
||||
env:
|
||||
CONFIGURATION: Release
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
@ -103,7 +103,7 @@ jobs:
|
||||
- platform: macosx
|
||||
buildFlags: -scheme ScummVM-macOS
|
||||
configFlags: --disable-nasm --enable-faad --enable-mpeg2
|
||||
brewPackages: a52dec faad2 flac fluid-synth freetype fribidi glew mad libmpeg2 libogg libpng libvorbis sdl2 sdl2_net theora
|
||||
brewPackages: a52dec faad2 flac fluid-synth freetype fribidi glew mad libmpeg2 libogg libpng libvorbis sdl2 sdl2_net theora giflib
|
||||
- platform: ios7
|
||||
buildFlags: -scheme ScummVM-iOS CODE_SIGN_IDENTITY="" CODE_SIGNING_ALLOWED=NO
|
||||
configFlags: --disable-nasm --disable-opengl --disable-theora --disable-taskbar --disable-tts --disable-fribidi
|
||||
|
@ -32,6 +32,7 @@ addons:
|
||||
- libsndio-dev
|
||||
- libreadline-dev
|
||||
- libglew-dev
|
||||
- libgif-dev
|
||||
|
||||
branches:
|
||||
only:
|
||||
|
35
configure
vendored
35
configure
vendored
@ -154,6 +154,7 @@ _sparkle=auto
|
||||
_osxdockplugin=auto
|
||||
_jpeg=auto
|
||||
_png=auto
|
||||
_gif=auto
|
||||
_theoradec=auto
|
||||
_faad=auto
|
||||
_fluidsynth=auto
|
||||
@ -272,6 +273,7 @@ add_feature jpeg "JPEG" "_jpeg"
|
||||
add_feature mpeg2 "mpeg2" "_mpeg2"
|
||||
add_feature opengl_game_shaders "OpenGL with shaders" "_opengl_game_shaders"
|
||||
add_feature png "PNG" "_png"
|
||||
add_feature png "GIF" "_gif"
|
||||
add_feature theoradec "libtheoradec" "_theoradec"
|
||||
add_feature tinygl "TinyGL" "_tinygl"
|
||||
add_feature vorbis "Vorbis file support" "_vorbis _tremor"
|
||||
@ -1111,6 +1113,8 @@ for ac_option in $@; do
|
||||
--enable-jpeg) _jpeg=yes ;;
|
||||
--disable-png) _png=no ;;
|
||||
--enable-png) _png=yes ;;
|
||||
--disable-gif) _gif=no ;;
|
||||
--enable-gif) _gif=yes ;;
|
||||
--disable-theoradec) _theoradec=no ;;
|
||||
--enable-theoradec) _theoradec=yes ;;
|
||||
--disable-faad) _faad=no ;;
|
||||
@ -4477,6 +4481,37 @@ fi
|
||||
define_in_config_if_yes "$_png" 'USE_PNG'
|
||||
echo "$_png"
|
||||
|
||||
#
|
||||
# Check for GIF
|
||||
#
|
||||
echocheck "GIF >= 5.0.0"
|
||||
if test "$_pkg_config" = "yes" && $_pkgconfig --exists libgif; then
|
||||
append_var GIF_LIBS "`$_pkgconfig --libs libgif`"
|
||||
append_var GIF_CFLAGS "`$_pkgconfig --cflags libgif`"
|
||||
else
|
||||
append_var GIF_LIBS "-lgif"
|
||||
fi
|
||||
if test "$_gif" = auto ; then
|
||||
_gif=no
|
||||
cat > $TMPC << EOF
|
||||
#include <gif_lib.h>
|
||||
int main(void) {
|
||||
#if GIFLIB_MAJOR >= 5
|
||||
#else
|
||||
syntax error
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
cc_check $GIF_CFLAGS $GIF_LIBS && _gif=yes
|
||||
fi
|
||||
if test "$_gif" = yes ; then
|
||||
append_var LIBS "$GIF_LIBS"
|
||||
append_var INCLUDES "$GIF_CFLAGS"
|
||||
fi
|
||||
define_in_config_if_yes "$_gif" 'USE_GIF'
|
||||
echo "$_gif"
|
||||
|
||||
#
|
||||
# Check for Theora Decoder
|
||||
#
|
||||
|
@ -1043,6 +1043,7 @@ const Feature s_features[] = {
|
||||
{ "tremor", "USE_TREMOR", true, false, "Tremor support" },
|
||||
{ "flac", "USE_FLAC", true, true, "FLAC support" },
|
||||
{ "png", "USE_PNG", true, true, "libpng support" },
|
||||
{ "gif", "USE_GIF", true, false, "libgif support" },
|
||||
{ "faad", "USE_FAAD", true, false, "AAC support" },
|
||||
{ "mpeg2", "USE_MPEG2", true, false, "MPEG-2 support" },
|
||||
{ "theora", "USE_THEORADEC", true, true, "Theora decoding support" },
|
||||
|
145
image/gif.cpp
Normal file
145
image/gif.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "image/gif.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "common/util.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
|
||||
#ifdef USE_GIF
|
||||
#include <gif_lib.h>
|
||||
#endif
|
||||
|
||||
namespace Image {
|
||||
|
||||
GIFDecoder::GIFDecoder() : _outputSurface(0), _palette(0), _colorCount(0) {
|
||||
}
|
||||
|
||||
GIFDecoder::~GIFDecoder() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
#ifdef USE_GIF
|
||||
static int gifReadFromStream(GifFileType *gif, GifByteType *bytes, int size) {
|
||||
Common::SeekableReadStream *stream = (Common::SeekableReadStream *)gif->UserData;
|
||||
return stream->read(bytes, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool GIFDecoder::loadStream(Common::SeekableReadStream &stream) {
|
||||
destroy();
|
||||
|
||||
#ifdef USE_GIF
|
||||
int error = 0;
|
||||
GifFileType *gif = DGifOpen(&stream, gifReadFromStream, &error);
|
||||
if (!gif) {
|
||||
warning("GIF open failed with error %s", GifErrorString(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
const int errcode = DGifSlurp(gif);
|
||||
if (errcode != GIF_OK) {
|
||||
warning("GIF failed to load");
|
||||
DGifCloseFile(gif, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gif->ImageCount <= 0) {
|
||||
warning("GIF doesn't contain valid image data");
|
||||
DGifCloseFile(gif, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gif->ImageCount > 1) {
|
||||
warning("GIF contains more than one frame - only loading the first one");
|
||||
}
|
||||
|
||||
const SavedImage *gifImage = gif->SavedImages;
|
||||
|
||||
const int width = gif->SWidth;
|
||||
const int height = gif->SHeight;
|
||||
|
||||
const ColorMapObject *colorMap = gif->SColorMap;
|
||||
_transparentColor = NO_TRANSPARENT_COLOR;
|
||||
for (int i = 0; i < gif->ExtensionBlockCount; ++i) {
|
||||
const ExtensionBlock &eb = gif->ExtensionBlocks[i];
|
||||
GraphicsControlBlock gcb;
|
||||
DGifExtensionToGCB(eb.ByteCount, eb.Bytes, &gcb);
|
||||
if (gcb.TransparentColor != NO_TRANSPARENT_COLOR) {
|
||||
_transparentColor = gcb.TransparentColor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_colorCount = colorMap->ColorCount;
|
||||
_outputSurface = new Graphics::Surface();
|
||||
_palette = new uint8[_colorCount * 3];
|
||||
|
||||
const Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
|
||||
for (int i = 0; i < _colorCount; ++i) {
|
||||
_palette[(i * 3) + 0] = colorMap->Colors[i].Red;
|
||||
_palette[(i * 3) + 1] = colorMap->Colors[i].Green;
|
||||
_palette[(i * 3) + 2] = colorMap->Colors[i].Blue;
|
||||
}
|
||||
|
||||
// TODO: support transparency
|
||||
|
||||
_outputSurface->create(width, height, format);
|
||||
const uint8 *in = (const uint8 *)gifImage->RasterBits;
|
||||
uint8 *pixelPtr = (uint8 *)_outputSurface->getBasePtr(0, 0);
|
||||
if (gif->Image.Interlace) {
|
||||
const int interlacedOffset[] = {0, 4, 2, 1};
|
||||
const int interlacedJumps[] = {8, 8, 4, 2};
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int row = interlacedOffset[i]; row < height; row += interlacedJumps[i]) {
|
||||
memcpy(pixelPtr + width * row, in, width);
|
||||
in += width;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(pixelPtr, in, width * height);
|
||||
}
|
||||
|
||||
DGifCloseFile(gif, 0);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GIFDecoder::destroy() {
|
||||
if (_outputSurface) {
|
||||
_outputSurface->free();
|
||||
delete _outputSurface;
|
||||
_outputSurface = 0;
|
||||
}
|
||||
if (_palette) {
|
||||
delete[] _palette;
|
||||
_palette = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Image
|
71
image/gif.h
Normal file
71
image/gif.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_GIF_H
|
||||
#define IMAGE_GIF_H
|
||||
|
||||
#include "image/image_decoder.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace Image {
|
||||
|
||||
/**
|
||||
* @defgroup image_gif GIF decoder
|
||||
* @ingroup image
|
||||
*
|
||||
* @brief Decoder for images encoded as Graphics Interchange Format (GIF).
|
||||
*
|
||||
* This decoder has a dependency on the libgif library.
|
||||
*
|
||||
* Used in engines:
|
||||
* - TwinE
|
||||
* @{
|
||||
*/
|
||||
class GIFDecoder : public ImageDecoder {
|
||||
public:
|
||||
GIFDecoder();
|
||||
~GIFDecoder();
|
||||
|
||||
bool loadStream(Common::SeekableReadStream &stream) override;
|
||||
void destroy() override;
|
||||
const byte *getPalette() const override { return _palette; }
|
||||
uint16 getPaletteColorCount() const override { return _colorCount; }
|
||||
const Graphics::Surface *getSurface() const override { return _outputSurface; }
|
||||
int getTransparentColor() const { return _transparentColor; }
|
||||
private:
|
||||
Graphics::Surface *_outputSurface;
|
||||
uint8 *_palette;
|
||||
uint16 _colorCount;
|
||||
int _transparentColor;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
} // End of namespace Image
|
||||
|
||||
#endif
|
@ -3,6 +3,7 @@ MODULE := image
|
||||
MODULE_OBJS := \
|
||||
bmp.o \
|
||||
cel_3do.o \
|
||||
gif.o \
|
||||
iff.o \
|
||||
jpeg.o \
|
||||
pcx.o \
|
||||
|
1
test/.gitignore
vendored
Normal file
1
test/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/engine-data
|
41
test/image/gif.h
Normal file
41
test/image/gif.h
Normal file
@ -0,0 +1,41 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "common/memstream.h"
|
||||
#include "image/gif.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
class GIFDecoderTestSuite : public CxxTest::TestSuite {
|
||||
public:
|
||||
void test_load_gif_2x2() {
|
||||
#ifdef USE_GIF
|
||||
const uint8 gifBuf[63] = {
|
||||
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x02, 0x00, 0x02, 0x00, 0xa1,
|
||||
0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x14, 0x82, 0x31,
|
||||
0xff, 0xff, 0xff, 0x21, 0xfe, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d,
|
||||
0x50, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
|
||||
0x00, 0x02, 0x03, 0x54, 0x06, 0x05, 0x00, 0x3b
|
||||
};
|
||||
|
||||
Image::GIFDecoder decoder;
|
||||
Common::MemoryReadStream stream(gifBuf, sizeof(gifBuf));
|
||||
const bool status = decoder.loadStream(stream);
|
||||
TS_ASSERT(status);
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
const Graphics::Surface *surface = decoder.getSurface();
|
||||
TS_ASSERT(surface != 0);
|
||||
if (surface == 0) {
|
||||
return;
|
||||
}
|
||||
TS_ASSERT_EQUALS(surface->w, 2);
|
||||
TS_ASSERT_EQUALS(surface->h, 2);
|
||||
TS_ASSERT_EQUALS(surface->format.bytesPerPixel, 1);
|
||||
#endif
|
||||
}
|
||||
};
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
######################################################################
|
||||
|
||||
TESTS := $(srcdir)/test/common/*.h $(srcdir)/test/audio/*.h $(srcdir)/test/math/*.h
|
||||
TESTS := $(srcdir)/test/common/*.h $(srcdir)/test/audio/*.h $(srcdir)/test/math/*.h $(srcdir)/test/image/*.h
|
||||
TEST_LIBS :=
|
||||
|
||||
ifdef POSIX
|
||||
@ -27,7 +27,7 @@ TEST_LIBS += test/null_osystem.o \
|
||||
backends/modular-backend.o
|
||||
endif
|
||||
|
||||
TEST_LIBS += audio/libaudio.a math/libmath.a common/libcommon.a
|
||||
TEST_LIBS += audio/libaudio.a math/libmath.a common/libcommon.a image/libimage.a graphics/libgraphics.a
|
||||
|
||||
ifeq ($(ENABLE_WINTERMUTE), STATIC_PLUGIN)
|
||||
TESTS += $(srcdir)/test/engines/wintermute/*.h
|
||||
|
Loading…
x
Reference in New Issue
Block a user