@ -33,18 +33,6 @@
# include <libexif/exif-data.h>
# include <libexif/exif-data.h>
# endif
# endif
# if HAVE_LIBGIF && !HAVE_IMLIB2_MULTI_FRAME
# include <gif_lib.h>
enum { DEF_GIF_DELAY = 75 } ;
# endif
# if HAVE_LIBWEBP && !HAVE_IMLIB2_MULTI_FRAME
# include <stdio.h>
# include <webp/decode.h>
# include <webp/demux.h>
enum { DEF_WEBP_DELAY = 75 } ;
# endif
# if HAVE_IMLIB2_MULTI_FRAME
# if HAVE_IMLIB2_MULTI_FRAME
enum { DEF_ANIM_DELAY = 75 } ;
enum { DEF_ANIM_DELAY = 75 } ;
# endif
# endif
@ -144,7 +132,7 @@ void exif_auto_orientate(const fileinfo_t *file)
}
}
# endif
# endif
# if HAVE_ LIBGIF || HAVE_LIBWEBP || HAVE_ IMLIB2_MULTI_FRAME
# if HAVE_ IMLIB2_MULTI_FRAME
static void img_multiframe_context_set ( img_t * img )
static void img_multiframe_context_set ( img_t * img )
{
{
if ( img - > multi . cnt > 1 ) {
if ( img - > multi . cnt > 1 ) {
@ -157,283 +145,7 @@ static void img_multiframe_context_set(img_t *img)
imlib_context_set_image ( img - > im ) ;
imlib_context_set_image ( img - > im ) ;
}
}
# endif
# if (HAVE_LIBGIF || HAVE_LIBWEBP) && !HAVE_IMLIB2_MULTI_FRAME
static void img_multiframe_deprecation_notice ( void )
{
static bool warned ;
if ( ! warned ) {
error ( 0 , 0 , " \n "
" ################################################################ \n "
" # DEPRECATION NOTICE # \n "
" ################################################################ \n "
" # Internal multi-frame gif and webp loaders are deprecated and # \n "
" # will be removed soon. Please upgrade to Imlib2 v1.8.0 for # \n "
" # multi-frame/animated image support. # \n "
" ################################################################ " ) ;
warned = true ;
}
}
# endif
# if HAVE_LIBGIF && !HAVE_IMLIB2_MULTI_FRAME
static bool img_load_gif ( img_t * img , const fileinfo_t * file )
{
GifFileType * gif ;
GifRowType * rows = NULL ;
GifRecordType rec ;
ColorMapObject * cmap ;
uint32_t bgpixel = 0 , * data , * ptr ;
uint32_t * prev_frame = NULL ;
Imlib_Image im ;
int i , j , bg , r , g , b ;
int x , y , w , h , sw , sh ;
int px , py , pw , ph ;
int intoffset [ ] = { 0 , 4 , 2 , 1 } ;
int intjump [ ] = { 8 , 8 , 4 , 2 } ;
int transp = - 1 ;
unsigned int disposal = 0 , prev_disposal = 0 ;
unsigned int delay = 0 ;
bool err = false ;
multi_img_t * m = & img - > multi ;
img_multiframe_deprecation_notice ( ) ;
# if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
gif = DGifOpenFileName ( file - > path , NULL ) ;
# else
gif = DGifOpenFileName ( file - > path ) ;
# endif
if ( gif = = NULL ) {
error ( 0 , 0 , " %s: Error opening gif image " , file - > name ) ;
return false ;
}
bg = gif - > SBackGroundColor ;
sw = gif - > SWidth ;
sh = gif - > SHeight ;
px = py = pw = ph = 0 ;
m - > length = m - > cnt = m - > sel = 0 ;
do {
if ( DGifGetRecordType ( gif , & rec ) = = GIF_ERROR ) {
err = true ;
break ;
}
if ( rec = = EXTENSION_RECORD_TYPE ) {
int ext_code ;
GifByteType * ext = NULL ;
DGifGetExtension ( gif , & ext_code , & ext ) ;
while ( ext ) {
if ( ext_code = = GRAPHICS_EXT_FUNC_CODE ) {
if ( ext [ 1 ] & 1 )
transp = ( int ) ext [ 4 ] ;
else
transp = - 1 ;
delay = 10 * ( ( unsigned int ) ext [ 3 ] < < 8 | ( unsigned int ) ext [ 2 ] ) ;
disposal = ( unsigned int ) ext [ 1 ] > > 2 & 0x7 ;
}
ext = NULL ;
DGifGetExtensionNext ( gif , & ext ) ;
}
} else if ( rec = = IMAGE_DESC_RECORD_TYPE ) {
if ( DGifGetImageDesc ( gif ) = = GIF_ERROR ) {
err = true ;
break ;
}
x = gif - > Image . Left ;
y = gif - > Image . Top ;
w = gif - > Image . Width ;
h = gif - > Image . Height ;
rows = emalloc ( h * sizeof ( * rows ) ) ;
for ( i = 0 ; i < h ; i + + )
rows [ i ] = emalloc ( w * sizeof ( * rows [ i ] ) ) ;
if ( gif - > Image . Interlace ) {
for ( i = 0 ; i < 4 ; i + + ) {
for ( j = intoffset [ i ] ; j < h ; j + = intjump [ i ] )
DGifGetLine ( gif , rows [ j ] , w ) ;
}
} else {
for ( i = 0 ; i < h ; i + + )
DGifGetLine ( gif , rows [ i ] , w ) ;
}
ptr = data = emalloc ( sw * sh * sizeof ( * data ) ) ;
cmap = gif - > Image . ColorMap ? gif - > Image . ColorMap : gif - > SColorMap ;
/* if bg > cmap->ColorCount, it is transparent black already */
if ( cmap & & bg > = 0 & & bg < cmap - > ColorCount ) {
r = cmap - > Colors [ bg ] . Red ;
g = cmap - > Colors [ bg ] . Green ;
b = cmap - > Colors [ bg ] . Blue ;
bgpixel = 0x00ffffff & ( r < < 16 | g < < 8 | b ) ;
}
for ( i = 0 ; i < sh ; i + + ) {
for ( j = 0 ; j < sw ; j + + ) {
if ( i < y | | i > = y + h | | j < x | | j > = x + w | |
rows [ i - y ] [ j - x ] = = transp )
{
if ( prev_frame ! = NULL & &
( prev_disposal ! = 2 | | i < py | | i > = py + ph | |
j < px | | j > = px + pw ) )
{
* ptr = prev_frame [ i * sw + j ] ;
} else {
* ptr = bgpixel ;
}
} else {
assert ( cmap ! = NULL ) ;
r = cmap - > Colors [ rows [ i - y ] [ j - x ] ] . Red ;
g = cmap - > Colors [ rows [ i - y ] [ j - x ] ] . Green ;
b = cmap - > Colors [ rows [ i - y ] [ j - x ] ] . Blue ;
* ptr = 0xffu < < 24 | r < < 16 | g < < 8 | b ;
}
ptr + + ;
}
}
im = imlib_create_image_using_copied_data ( sw , sh , data ) ;
for ( i = 0 ; i < h ; i + + )
free ( rows [ i ] ) ;
free ( rows ) ;
free ( data ) ;
if ( im = = NULL ) {
err = true ;
break ;
}
imlib_context_set_image ( im ) ;
imlib_image_set_format ( " gif " ) ;
if ( transp > = 0 )
imlib_image_set_has_alpha ( 1 ) ;
if ( disposal ! = 3 )
prev_frame = imlib_image_get_data_for_reading_only ( ) ;
prev_disposal = disposal ;
px = x , py = y , pw = w , ph = h ;
assert ( m - > cnt < = m - > cap ) ;
if ( m - > cnt = = m - > cap ) {
m - > cap = m - > cap = = 0 ? 16 : ( m - > cap * 2 ) ;
m - > frames = erealloc ( m - > frames , m - > cap * sizeof ( * m - > frames ) ) ;
}
m - > frames [ m - > cnt ] . im = im ;
delay = m - > framedelay > 0 ? m - > framedelay : delay ;
m - > frames [ m - > cnt ] . delay = delay > 0 ? delay : DEF_GIF_DELAY ;
m - > length + = m - > frames [ m - > cnt ] . delay ;
m - > cnt + + ;
}
} while ( rec ! = TERMINATE_RECORD_TYPE ) ;
# if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1
DGifCloseFile ( gif , NULL ) ;
# else
DGifCloseFile ( gif ) ;
# endif
if ( err & & ( file - > flags & FF_WARN ) )
error ( 0 , 0 , " %s: Corrupted gif file " , file - > name ) ;
img_multiframe_context_set ( img ) ;
return ! err ;
}
# endif /* HAVE_LIBGIF */
# if HAVE_LIBWEBP && !HAVE_IMLIB2_MULTI_FRAME
static bool img_load_webp ( img_t * img , const fileinfo_t * file )
{
FILE * webp_file ;
WebPData data ;
Imlib_Image im = NULL ;
struct WebPAnimDecoderOptions opts ;
WebPAnimDecoder * dec = NULL ;
struct WebPAnimInfo info ;
unsigned char * buf = NULL , * bytes = NULL ;
int ts ;
const WebPDemuxer * demux ;
WebPIterator iter ;
unsigned long flags ;
unsigned int delay ;
bool err = false ;
multi_img_t * m = & img - > multi ;
img_multiframe_deprecation_notice ( ) ;
if ( ( webp_file = fopen ( file - > path , " rb " ) ) = = NULL ) {
error ( 0 , errno , " %s: Error opening webp image " , file - > name ) ;
return false ;
}
fseek ( webp_file , 0L , SEEK_END ) ;
data . size = ftell ( webp_file ) ;
rewind ( webp_file ) ;
bytes = emalloc ( data . size ) ;
if ( ( err = fread ( bytes , 1 , data . size , webp_file ) ! = data . size ) ) {
error ( 0 , 0 , " %s: Error reading webp image " , file - > name ) ;
goto fail ;
}
data . bytes = bytes ;
/* Setup the WebP Animation Decoder */
if ( ( err = ! WebPAnimDecoderOptionsInit ( & opts ) ) ) {
error ( 0 , 0 , " %s: WebP library version mismatch " , file - > name ) ;
goto fail ;
}
opts . color_mode = MODE_BGRA ;
/* NOTE: Multi-threaded decoding may cause problems on some system */
opts . use_threads = true ;
dec = WebPAnimDecoderNew ( & data , & opts ) ;
if ( ( err = ( dec = = NULL ) | | ! WebPAnimDecoderGetInfo ( dec , & info ) ) ) {
error ( 0 , 0 , " %s: WebP parsing or memory error (file is corrupt?) " , file - > name ) ;
goto fail ;
}
demux = WebPAnimDecoderGetDemuxer ( dec ) ;
/* Get global information for the image */
flags = WebPDemuxGetI ( demux , WEBP_FF_FORMAT_FLAGS ) ;
img - > w = WebPDemuxGetI ( demux , WEBP_FF_CANVAS_WIDTH ) ;
img - > h = WebPDemuxGetI ( demux , WEBP_FF_CANVAS_HEIGHT ) ;
if ( info . frame_count > m - > cap ) {
m - > cap = info . frame_count ;
m - > frames = erealloc ( m - > frames , m - > cap * sizeof ( * m - > frames ) ) ;
}
/* Load and decode frames (also works on images with only 1 frame) */
m - > length = m - > cnt = m - > sel = 0 ;
while ( WebPAnimDecoderGetNext ( dec , & buf , & ts ) ) {
im = imlib_create_image_using_copied_data ( info . canvas_width , info . canvas_height ,
( uint32_t * ) buf ) ;
imlib_context_set_image ( im ) ;
imlib_image_set_format ( " webp " ) ;
/* Get an iterator of this frame - used for frame info (duration, etc.) */
WebPDemuxGetFrame ( demux , m - > cnt + 1 , & iter ) ;
imlib_image_set_has_alpha ( ( flags & ALPHA_FLAG ) = = ALPHA_FLAG ) ;
/* Store info for this frame */
m - > frames [ m - > cnt ] . im = im ;
delay = iter . duration > 0 ? iter . duration : DEF_WEBP_DELAY ;
m - > frames [ m - > cnt ] . delay = delay ;
m - > length + = m - > frames [ m - > cnt ] . delay ;
m - > cnt + + ;
}
WebPDemuxReleaseIterator ( & iter ) ;
img_multiframe_context_set ( img ) ;
fail :
if ( dec ! = NULL )
WebPAnimDecoderDelete ( dec ) ;
free ( bytes ) ;
fclose ( webp_file ) ;
return ! err ;
}
# endif /* HAVE_LIBWEBP */
# if HAVE_IMLIB2_MULTI_FRAME
static void img_area_clear ( int x , int y , int w , int h )
static void img_area_clear ( int x , int y , int w , int h )
{
{
assert ( x > = 0 & & y > = 0 ) ;
assert ( x > = 0 & & y > = 0 ) ;
@ -596,14 +308,6 @@ bool img_load(img_t *img, const fileinfo_t *file)
# endif
# endif
if ( ( fmt = imlib_image_format ( ) ) ! = NULL ) { /* NOLINT: fmt might be unused, not worth fixing */
if ( ( fmt = imlib_image_format ( ) ) ! = NULL ) { /* NOLINT: fmt might be unused, not worth fixing */
# if HAVE_LIBGIF && !HAVE_IMLIB2_MULTI_FRAME
if ( STREQ ( fmt , " gif " ) )
img_load_gif ( img , file ) ;
# endif
# if HAVE_LIBWEBP && !HAVE_IMLIB2_MULTI_FRAME
if ( STREQ ( fmt , " webp " ) )
img_load_webp ( img , file ) ;
# endif
# if HAVE_LIBEXIF && defined(IMLIB2_VERSION)
# if HAVE_LIBEXIF && defined(IMLIB2_VERSION)
if ( ! STREQ ( fmt , " jpeg " ) & & ! STREQ ( fmt , " jpg " ) )
if ( ! STREQ ( fmt , " jpeg " ) & & ! STREQ ( fmt , " jpg " ) )
exif_auto_orientate ( file ) ;
exif_auto_orientate ( file ) ;