ANI loader: Multiframe suport

This commit is contained in:
Kim Woelders 2022-12-06 16:24:02 +01:00
parent 7e7eae168a
commit 03e4460c17
1 changed files with 92 additions and 0 deletions

View File

@ -23,6 +23,9 @@
#define RIFF_TYPE_INAM T('I', 'N', 'A', 'M')
#define RIFF_TYPE_IART T('I', 'A', 'R', 'T')
#define RIFF_TYPE_icon T('i', 'c', 'o', 'n')
#define RIFF_TYPE_anih T('a', 'n', 'i', 'h')
#define RIFF_TYPE_rate T('r', 'a', 't', 'e')
#define RIFF_TYPE_seq T('s', 'e', 'q', ' ')
#define RIFF_NAME_ACON T('A', 'C', 'O', 'N')
@ -30,8 +33,25 @@ static const char *const _formats[] = { "ani" };
typedef struct {
unsigned char nest;
int nframes, nfsteps;
uint32_t *rates, *seq;
} riff_ctx_t;
typedef struct {
uint32_t size; // Size of chunk data (=36)
uint32_t frames; // Number of frames in file
uint32_t steps; // Number of steps in animation sequence
uint32_t width; // Image width (raw data only?)
uint32_t height; // Image height (raw data only?)
uint32_t bpp; // Bits per pixel (raw data only?)
uint32_t planes; // N. planes (raw data only?)
uint32_t rate; // Default rate in 1/60s
uint32_t flags; // Flags: ANIH_FLAG_...
} anih_data_t;
#define ANIH_FLAG_ICO 0x01 // Frames are icons or cursors (otherwiwe raw - bmp?)
#define ANIH_FLAG_SEQ 0x02 // Image contains seq chunk
static int
_load_embedded(ImlibImage * im, int load_data, const char *data,
unsigned int size)
@ -72,10 +92,15 @@ _riff_parse(ImlibImage * im, riff_ctx_t * ctx, const char *fdata,
int rc;
unsigned int type;
int size, avail;
int fcount, i;
ImlibImageFrame *pf;
rc = LOAD_FAIL;
ctx->nest += 1;
pf = NULL;
fcount = 0;
for (; rc == 0; fptr += 8 + size)
{
avail = fdata + fsize - fptr; /* Bytes left in chunk */
@ -128,8 +153,75 @@ _riff_parse(ImlibImage * im, riff_ctx_t * ctx, const char *fdata,
break;
case RIFF_TYPE_icon:
Dx("\n");
fcount++;
if (im->frame > 0)
{
i = (ctx->seq) ?
(int)SWAP_LE_32(ctx->seq[im->frame - 1]) + 1 : im->frame;
if (i != fcount)
break;
}
if (pf && ctx->rates)
pf->frame_delay =
(1000 * SWAP_LE_32(ctx->rates[im->frame - 1])) / 60;
rc = _load_embedded(im, 1, fptr + 8, size);
break;
case RIFF_TYPE_anih:
#define AH ((const anih_data_t*)(fptr + 8))
/**INDENT-OFF**/
Dx("sz=%u nf=%u/%u WxH=%ux%u bc=%u np=%u dr=%u fl=%u\n",
SWAP_LE_32(AH->size), SWAP_LE_32(AH->frames), SWAP_LE_32(AH->steps),
SWAP_LE_32(AH->width), SWAP_LE_32(AH->height),
SWAP_LE_32(AH->bpp), SWAP_LE_32(AH->planes),
SWAP_LE_32(AH->rate), SWAP_LE_32(AH->flags));
/**INDENT-ON**/
ctx->nframes = SWAP_LE_32(AH->frames);
ctx->nfsteps = SWAP_LE_32(AH->steps);
if (im->frame <= 0)
break;
if (ctx->nfsteps < ctx->nframes)
ctx->nfsteps = ctx->nframes;
if (im->frame > ctx->nfsteps)
return LOAD_BADFRAME;
pf = __imlib_GetFrame(im);
if (!pf)
{
rc = LOAD_OOM;
break;
}
pf->frame_count = ctx->nfsteps;
if (ctx->nframes > 1)
pf->frame_flags = FF_IMAGE_ANIMATED;
pf->frame_delay = (1000 * SWAP_LE_32(AH->rate)) / 60;
break;
case RIFF_TYPE_rate:
ctx->rates = (uint32_t *) (fptr + 8);
if ((int)size != 4 * ctx->nfsteps)
{
D("rate chunk size mismatch: %d != %d\n", size,
4 * ctx->nfsteps);
break;
}
#if IMLIB2_DEBUG
for (i = 0; i < ctx->nfsteps; i++)
Dx(" %d", SWAP_LE_32(ctx->rates[i]));
#endif
Dx("\n");
break;
case RIFF_TYPE_seq:
ctx->seq = (uint32_t *) (fptr + 8);
if ((int)size != 4 * ctx->nfsteps)
{
D("seq chunk size mismatch: %d != %d\n", size,
4 * ctx->nfsteps);
break;
}
#if IMLIB2_DEBUG
for (i = 0; i < ctx->nfsteps; i++)
Dx(" %d", SWAP_LE_32(ctx->seq[i]));
#endif
Dx("\n");
break;
}
size = (size + 1) & ~1;
}