mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-23 14:59:47 +03:00
[project @ 2004-03-19 18:14:50 by rjw]
Animated GIF support. svn path=/import/netsurf/; revision=635
This commit is contained in:
parent
5df9d191e8
commit
c28b257d9d
501
riscos/gif.c
501
riscos/gif.c
@ -1,12 +1,12 @@
|
||||
/*
|
||||
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
||||
* Licensed under the GNU General Public License,
|
||||
* http://www.opensource.org/licenses/gpl-license
|
||||
* http://www.opensource.org/licenses/gpl-license
|
||||
* Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
|
||||
* Copyright 2004 Richard Wilson <not_ginger_matt@sourceforge.net>
|
||||
*
|
||||
* Parts modified from IGviewer source by Peter Hartley
|
||||
* http://utter.chaos.org/~pdh/software/intergif.htm
|
||||
* http://utter.chaos.org/~pdh/software/intergif.htm
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -17,6 +17,7 @@
|
||||
#include "animlib/animlib.h"
|
||||
#include "oslib/colourtrans.h"
|
||||
#include "oslib/os.h"
|
||||
#include "oslib/osfile.h"
|
||||
#include "oslib/osspriteop.h"
|
||||
#include "netsurf/utils/config.h"
|
||||
#include "netsurf/content/content.h"
|
||||
@ -37,9 +38,9 @@
|
||||
32bpp sprite.
|
||||
|
||||
To overcome the problem of memory wastage, each frame of the GIF is held as
|
||||
an 8bpp sprite with a 256 colour entry palette and is converted into a 32bpp
|
||||
sprite suitable for plotting following a frame transition. This conversion is
|
||||
performed by using Tinct_ConvertSprite.
|
||||
a Nbpp paletted sprite and is converted into a 32bpp sprite suitable for
|
||||
plotting following a frame transition. This conversion is performed by using
|
||||
Tinct_ConvertSprite.
|
||||
|
||||
By using this technique rather than dynamically decompressing the current
|
||||
GIF frame we can skip over frames that we can't display and always keep
|
||||
@ -47,18 +48,15 @@
|
||||
GIF then it would be necessary to also decompress any intermediate frames as
|
||||
the GIF format dictates that each successive frame is plotted on top of any
|
||||
previous one.
|
||||
|
||||
N.B. Future implementations may of store each frame at the lowest possible
|
||||
colour depth to reduce memory usage. To ensure this forwards compatibility
|
||||
nsgif_get_sprite_address should always be used to obtain the sprite for the
|
||||
various animation frames.
|
||||
|
||||
[rjw] - Wed 17th March 2004
|
||||
[rjw] - Thu 18th March 2004
|
||||
*/
|
||||
|
||||
#ifdef WITH_GIF
|
||||
|
||||
static osspriteop_area *create_buffer_sprite(struct content *c, anim a);
|
||||
|
||||
static void CompressSpriteLine( pixel *dest, const pixel *src, int n, int bpp );
|
||||
static void CompressMaskLine( pixel *dest, const pixel *src, int n, int bpp );
|
||||
|
||||
void nsgif_init(void) {
|
||||
}
|
||||
@ -67,93 +65,297 @@ void nsgif_create(struct content *c, const char *params[]) {
|
||||
c->data.gif.sprite_area = 0;
|
||||
c->data.gif.buffer_pos = 0;
|
||||
c->data.gif.total_frames = 0; // Paranoid
|
||||
|
||||
c->data.gif.current_frame = 0;
|
||||
c->data.gif.expanded_frame = 0xffffffff; // ie invalid value
|
||||
c->data.gif.remainder_time = 0;
|
||||
}
|
||||
|
||||
|
||||
int nsgif_convert(struct content *c, unsigned int iwidth, unsigned int iheight)
|
||||
{
|
||||
anim a;
|
||||
frame f;
|
||||
pixel *img, *mask;
|
||||
struct osspriteop_header *header;
|
||||
struct osspriteop_area *area;
|
||||
int nsgif_convert(struct content *c, unsigned int iwidth, unsigned int iheight) {
|
||||
struct osspriteop_area *sprite_area;
|
||||
|
||||
unsigned int sprite_area_size;
|
||||
unsigned int frame_count;
|
||||
unsigned int cur_frame;
|
||||
unsigned int frame_colours;
|
||||
unsigned int frame_bpp;
|
||||
unsigned int frame_size;
|
||||
unsigned int *frame_delays;
|
||||
|
||||
anim gif_animation;
|
||||
frame gif_frame;
|
||||
|
||||
|
||||
a = Anim_FromData(c->source_data, c->source_size, NULL, false, false, false);
|
||||
if (!a) {
|
||||
|
||||
LOG(("Error creating anim object"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!Anim_CommonPalette(a)) {
|
||||
|
||||
LOG(("bad palette"));
|
||||
Anim_Destroy(&a);
|
||||
return 1;
|
||||
}
|
||||
/* Claim a buffer [temporary code]
|
||||
/* Get an anim object from our data
|
||||
*/
|
||||
struct osspriteop_header *temp_buf = xcalloc(1, a->nWidth * a->nHeight * 4 + 44);
|
||||
gif_animation = Anim_FromData(c->source_data, c->source_size, NULL, false, false, false);
|
||||
if (!gif_animation) {
|
||||
LOG(("Error creating anim object"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check we have some frames
|
||||
*/
|
||||
if (gif_animation->nFrames < 1) {
|
||||
LOG(("No frames found"));
|
||||
Anim_Destroy(&gif_animation);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Store the animation details
|
||||
*/
|
||||
c->width = gif_animation->nWidth;
|
||||
c->height = gif_animation->nHeight;
|
||||
c->data.gif.current_frame = 0;
|
||||
c->data.gif.expanded_frame = 0xffffffff; // ie invalid value
|
||||
c->data.gif.remainder_time = 0;
|
||||
c->data.gif.total_frames = frame_count = gif_animation->nFrames;
|
||||
c->data.gif.animate_gif = (frame_count > 1);
|
||||
c->data.gif.loop_gif = true;
|
||||
|
||||
/* Claim a buffer for the cached 32bpp version of the current frame. By
|
||||
doing this now we can use the same memory area as the temporary buffer
|
||||
for decoding all the subsequent frames later.
|
||||
*/
|
||||
struct osspriteop_header *temp_buf = xcalloc(gif_animation->nWidth *
|
||||
gif_animation->nHeight + 11, 4);
|
||||
c->data.gif.buffer_header = (osspriteop_header*)(temp_buf);
|
||||
|
||||
area = create_buffer_sprite(c, a);
|
||||
if(!area) {
|
||||
/* We can store our frame transitions now too
|
||||
*/
|
||||
if (frame_count > 1) {
|
||||
frame_delays = xcalloc(frame_count, sizeof(int));
|
||||
c->data.gif.frame_transitions = frame_delays;
|
||||
}
|
||||
|
||||
LOG(("Failed to create sprite"));
|
||||
Anim_Destroy(&a);
|
||||
return 1;
|
||||
}
|
||||
c->data.gif.sprite_area = area;
|
||||
/* Now we need to work out the total size of the sprite area. If we are
|
||||
doing dynamic decompression then this can simply be an 8bpp paletted
|
||||
sprite of the required dimensions as all frames will fit.
|
||||
For dynamic decompression, the frame delay buffer must still be filled
|
||||
in a similar manner.
|
||||
*/
|
||||
sprite_area_size = sizeof(osspriteop_area);
|
||||
for (cur_frame = 0; cur_frame < frame_count; cur_frame++) {
|
||||
|
||||
header = (osspriteop_header*)((char*)c->data.gif.sprite_area +
|
||||
c->data.gif.sprite_area->first);
|
||||
f = a->pFrames + 0;
|
||||
img = (pixel*)header + header->image;
|
||||
mask = (pixel*)header + header->mask;
|
||||
/* Increment by the header size
|
||||
*/
|
||||
sprite_area_size += sizeof(osspriteop_header);
|
||||
|
||||
if (!Anim_DecompressAligned(f->pImageData, f->nImageSize,
|
||||
a->nWidth, a->nHeight, img)) {
|
||||
LOG(("Anim_DecompressAligned image failed"));
|
||||
Anim_Destroy(&a);
|
||||
xfree(area);
|
||||
return 1;
|
||||
}
|
||||
/* Get the frame details
|
||||
*/
|
||||
gif_frame = gif_animation->pFrames + cur_frame;
|
||||
frame_colours = gif_frame->pal->nColours;
|
||||
|
||||
if(f->pMaskData) {
|
||||
/* Store our transition time
|
||||
*/
|
||||
if (frame_count > 1) {
|
||||
frame_delays[cur_frame] = gif_frame->csDelay;
|
||||
}
|
||||
|
||||
int i,n = header->mask - header->image;
|
||||
/* Get the minimum number of bpp for this frame
|
||||
*/
|
||||
frame_bpp = 8;
|
||||
if (frame_colours <=16) frame_bpp = 4;
|
||||
if (frame_colours <=4) frame_bpp = 2;
|
||||
if (frame_colours <=2) frame_bpp = 1;
|
||||
|
||||
if (!Anim_DecompressAligned(f->pMaskData, f->nMaskSize,
|
||||
a->nWidth, a->nHeight, mask)) {
|
||||
LOG(("Anim_DecompressAligned mask failed"));
|
||||
Anim_Destroy(&a);
|
||||
xfree(area);
|
||||
return 1;
|
||||
}
|
||||
/* Increase our area by our palette size. Due to legacy flashing
|
||||
colour support, RISC OS lumbers all sprites with two words of
|
||||
palette data per colour.
|
||||
*/
|
||||
sprite_area_size += (8 << frame_bpp);
|
||||
|
||||
for(i=0; i<n; i++)
|
||||
if(!mask[i]) {
|
||||
/* Now we need to calculate how big each sprite is given the
|
||||
current number of bits per pixel.
|
||||
*/
|
||||
frame_size = (((((gif_animation->nWidth * frame_bpp) + 31) & ~31) >> 3) *
|
||||
gif_animation->nHeight);
|
||||
|
||||
img[i] = 255;
|
||||
mask[i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
memset(mask, 255, (unsigned int)(header->mask - header->image));
|
||||
/* Finally we add in our frame size, and add it again if we have
|
||||
some mask data.
|
||||
*/
|
||||
if (gif_frame->pMaskData) frame_size *= 2;
|
||||
sprite_area_size += frame_size;
|
||||
}
|
||||
|
||||
c->title = xcalloc(100, sizeof(char));
|
||||
sprintf(c->title, messages_get("GIFTitle"), c->width, c->height);
|
||||
c->status = CONTENT_STATUS_DONE;
|
||||
/* So, we now have the size needed so we can create our sprite area and
|
||||
fill in some data for it.
|
||||
*/
|
||||
sprite_area = xcalloc(sprite_area_size, 1);
|
||||
sprite_area->size = sprite_area_size;
|
||||
sprite_area->sprite_count = frame_count;
|
||||
sprite_area->first = sizeof(osspriteop_area);
|
||||
sprite_area->used = sprite_area_size;
|
||||
c->data.gif.sprite_area = sprite_area;
|
||||
|
||||
/* xosspriteop_save_sprite_file(osspriteop_USER_AREA,
|
||||
c->data.gif.sprite_area, "gif"); */
|
||||
/* Now we need to decompress all our frames. This is handled by a
|
||||
sub-routine so we can easily modify this object to do dynamic
|
||||
decompression if desired.
|
||||
*/
|
||||
for (cur_frame = 0; cur_frame < frame_count; cur_frame++) {
|
||||
|
||||
return 0;
|
||||
/* Decompress the frame. We don't worry if we failed as
|
||||
we'll have an empty sprite that'll just make the animation
|
||||
look wrong rather than having no animation at all.
|
||||
If we wanted we could stop at this frame and set the maximum
|
||||
number of frames as our current frame.
|
||||
*/
|
||||
nsgif_decompress_frame(c, &gif_animation, cur_frame);
|
||||
|
||||
}
|
||||
|
||||
/* Destroy our animation data. If things are being done dynamically
|
||||
then this needs to be done in nsgif_destroy or things will go
|
||||
horribly wrong.
|
||||
*/
|
||||
Anim_Destroy(&gif_animation);
|
||||
|
||||
/* Finish things off
|
||||
*/
|
||||
c->title = xcalloc(100, sizeof(char));
|
||||
sprintf(c->title, messages_get("GIFTitle"), c->width, c->height);
|
||||
c->status = CONTENT_STATUS_DONE;
|
||||
|
||||
/* Debugging helpers
|
||||
*/
|
||||
/* xosspriteop_save_sprite_file(osspriteop_USER_AREA,
|
||||
c->data.gif.sprite_area, "gif");
|
||||
if (frame_count > 1) {
|
||||
xosfile_save_stamped("gif_frames", 0xffd,
|
||||
frame_delays, (unsigned int*)(frame_delays + frame_count));
|
||||
}
|
||||
*/
|
||||
|
||||
/* Exit as a success
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Decompresses a GIF frame.
|
||||
NB: This call uses the current decompressed image as a temporary buffer.
|
||||
|
||||
@param c The content store the data back to
|
||||
@param p_gif_animation A pointer to the GIF animation to read from
|
||||
@param cur_frame The desired frame [0...(max-1)]
|
||||
@return <code>true</code> on success, <code>false</code> otherwise
|
||||
*/
|
||||
bool nsgif_decompress_frame(struct content *c, anim *p_gif_animation, unsigned int cur_frame) {
|
||||
|
||||
struct osspriteop_header *sprite_header;
|
||||
anim gif_animation = *p_gif_animation;
|
||||
frame gif_frame;
|
||||
palette frame_palette;
|
||||
const unsigned int *palette_entries;
|
||||
unsigned int frame_colours;
|
||||
unsigned int frame_bpp;
|
||||
unsigned int scanline_size;
|
||||
unsigned int frame_size;
|
||||
unsigned int *sprite_palette;
|
||||
unsigned int loop;
|
||||
pixel *src;
|
||||
pixel *dest;
|
||||
|
||||
/* Get the frame details
|
||||
*/
|
||||
gif_frame = gif_animation->pFrames + cur_frame;
|
||||
frame_palette = gif_frame->pal;
|
||||
palette_entries = frame_palette->pColours;
|
||||
frame_colours = frame_palette->nColours;
|
||||
|
||||
/* Get the minimum number of bpp for this frame
|
||||
*/
|
||||
frame_bpp = 8;
|
||||
if (frame_colours <=16) frame_bpp = 4;
|
||||
if (frame_colours <=4) frame_bpp = 2;
|
||||
if (frame_colours <=2) frame_bpp = 1;
|
||||
|
||||
/* Now we need to calculate how big each sprite is given the
|
||||
current number of bits per pixel.
|
||||
*/
|
||||
scanline_size = ((((gif_animation->nWidth * frame_bpp) + 31) & ~31) >> 3);
|
||||
frame_size = scanline_size * gif_animation->nHeight;
|
||||
|
||||
/* Get our current sprite. For dynamic decompression we should always use 0.
|
||||
*/
|
||||
sprite_header = nsgif_get_sprite_address(c, cur_frame);
|
||||
|
||||
/* Set up the sprite header details
|
||||
*/
|
||||
sprite_header->size = frame_size + (8 << frame_bpp) + sizeof(osspriteop_header);
|
||||
sprite_header->width = (scanline_size >> 2) - 1;
|
||||
sprite_header->height = gif_animation->nHeight - 1;
|
||||
sprite_header->left_bit = 0;
|
||||
sprite_header->right_bit = (gif_animation->nWidth * frame_bpp - 1 ) & 31;
|
||||
sprite_header->image = (8 << frame_bpp) + sizeof(osspriteop_header);
|
||||
strcpy(sprite_header->name, "gif");
|
||||
|
||||
/* Do the mask stuff if we have one
|
||||
*/
|
||||
if (gif_frame->pMaskData) {
|
||||
sprite_header->size += frame_size;
|
||||
sprite_header->mask = sprite_header->image + frame_size;
|
||||
} else {
|
||||
sprite_header->mask = sprite_header->image;
|
||||
}
|
||||
|
||||
/* Set the mode using old skool values
|
||||
*/
|
||||
switch (frame_bpp) {
|
||||
case 1: sprite_header->mode = 18; break;
|
||||
case 2: sprite_header->mode = 19; break;
|
||||
case 4: sprite_header->mode = 20; break;
|
||||
case 8: sprite_header->mode = 21; break;
|
||||
}
|
||||
|
||||
/* Set up the palette - 2 words per entry.
|
||||
*/
|
||||
sprite_palette = (unsigned int*)(sprite_header + 1);
|
||||
memset(sprite_palette, 0, frame_colours);
|
||||
for (loop = 0; loop < frame_colours; loop++) {
|
||||
*sprite_palette++ = palette_entries[loop];
|
||||
*sprite_palette++ = palette_entries[loop];
|
||||
}
|
||||
|
||||
/* Get the intermediate result place (src) and where it ends up after
|
||||
we've changed it to the correct bpp (dest).
|
||||
We use our 32bpp sprite buffer as temporary workspace.
|
||||
*/
|
||||
dest = ((pixel*)sprite_header) + sprite_header->image;
|
||||
src = (pixel*)c->data.gif.buffer_header;
|
||||
|
||||
if (!Anim_Decompress(gif_frame->pImageData, gif_frame->nImageSize,
|
||||
gif_animation->nWidth * gif_animation->nHeight, src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Now we compress each line to the minimum bpp
|
||||
*/
|
||||
for (loop=0; loop < gif_animation->nHeight; loop++) {
|
||||
CompressSpriteLine(dest, src, gif_animation->nWidth, frame_bpp );
|
||||
dest += scanline_size;
|
||||
src += gif_animation->nWidth;
|
||||
}
|
||||
|
||||
/* As before, but for the mask this time
|
||||
*/
|
||||
if (gif_frame->pMaskData) {
|
||||
dest = ((pixel*)sprite_header) + sprite_header->mask;
|
||||
src = (pixel*)c->data.gif.buffer_header;
|
||||
|
||||
if (!Anim_Decompress(gif_frame->pMaskData, gif_frame->nMaskSize,
|
||||
gif_animation->nWidth * gif_animation->nHeight, src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Now we compress each line to the minimum bpp
|
||||
*/
|
||||
for (loop=0; loop < gif_animation->nHeight; loop++) {
|
||||
CompressMaskLine(dest, src, gif_animation->nWidth, frame_bpp);
|
||||
dest += scanline_size;
|
||||
src += gif_animation->nWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return success
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -162,21 +364,23 @@ void nsgif_redraw(struct content *c, long x, long y,
|
||||
long clip_x0, long clip_y0, long clip_x1, long clip_y1,
|
||||
float scale) {
|
||||
|
||||
/* Hack - animate as if 4cs have passed every redraw
|
||||
*/
|
||||
nsgif_animate(c, 4);
|
||||
|
||||
/* Check if we need to expand the current frame to 32bpp
|
||||
*/
|
||||
if (c->data.gif.current_frame != c->data.gif.expanded_frame) {
|
||||
|
||||
/* Convert the sprite
|
||||
*/
|
||||
/* Convert the sprite
|
||||
*/
|
||||
_swix(Tinct_ConvertSprite, _IN(2) | _IN(3),
|
||||
((char *) nsgif_get_sprite_address(c, c->data.gif.current_frame)),
|
||||
((char *) c->data.gif.buffer_header));
|
||||
|
||||
LOG(("Converted GIF frame %i.", c->data.gif.current_frame));
|
||||
|
||||
/* Remember we are expanded for future calls
|
||||
*/
|
||||
c->data.gif.current_frame = c->data.gif.expanded_frame;
|
||||
/* Remember we are expanded for future calls
|
||||
*/
|
||||
c->data.gif.expanded_frame = c->data.gif.current_frame;
|
||||
}
|
||||
|
||||
/* Tinct currently only handles 32bpp sprites that have an embedded alpha mask. Any
|
||||
@ -230,7 +434,8 @@ int nsgif_animate(struct content *c, unsigned int advance_time) {
|
||||
|
||||
/* Get our frame information locally
|
||||
*/
|
||||
cur_frame = old_frame = c->data.gif.current_frame;
|
||||
cur_frame = c->data.gif.current_frame;
|
||||
old_frame = cur_frame;
|
||||
delay_values = c->data.gif.frame_transitions;
|
||||
|
||||
/* Move through the frames
|
||||
@ -239,16 +444,15 @@ int nsgif_animate(struct content *c, unsigned int advance_time) {
|
||||
|
||||
/* Advance a frame
|
||||
*/
|
||||
advance_time -= delay_values[cur_frame];
|
||||
cur_frame++;
|
||||
advance_time -= delay_values[cur_frame++];
|
||||
|
||||
/* Handle looping
|
||||
*/
|
||||
if (cur_frame >= max_frame) {
|
||||
if (!c->data.gif.loop_gif) {
|
||||
if (!c->data.gif.loop_gif) {
|
||||
c->data.gif.current_frame = max_frame - 1;
|
||||
c->data.gif.animate_gif = false;
|
||||
|
||||
|
||||
/* We can't return 0 as it indicates no animation
|
||||
has occured, so we return a small value so we
|
||||
can be called back and then say that we're done.
|
||||
@ -280,9 +484,10 @@ int nsgif_animate(struct content *c, unsigned int advance_time) {
|
||||
|
||||
@param c The content to find the frame from
|
||||
@param frame The desired frame [0...(max-1)]
|
||||
@return The address of the sprite header
|
||||
@return The address of the sprite header
|
||||
*/
|
||||
osspriteop_header *nsgif_get_sprite_address(struct content *c, unsigned int frame) {
|
||||
|
||||
struct osspriteop_header *header;
|
||||
|
||||
/* Get the header for the first sprite
|
||||
@ -292,54 +497,86 @@ osspriteop_header *nsgif_get_sprite_address(struct content *c, unsigned int fram
|
||||
|
||||
/* Keep advancing until we get our sprite
|
||||
*/
|
||||
while (frame-- > 0) header += header->size;
|
||||
while (frame-- > 0) {
|
||||
header = (osspriteop_header*)(((char *)header) + header->size);
|
||||
}
|
||||
|
||||
/* Return our value
|
||||
*/
|
||||
return header;
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
static osspriteop_area *create_buffer_sprite( struct content *c, anim a )
|
||||
|
||||
|
||||
/* Shamelessly stolen from AnimLib.savesprite.c
|
||||
*/
|
||||
static void CompressSpriteLine( pixel *dest, const pixel *src, int n, int bpp )
|
||||
{
|
||||
unsigned int abw = ((a->nWidth + 3 ) & ~3u) * a->nHeight;
|
||||
unsigned int nBytes = abw*2 + 44 + 16 + 256*8;
|
||||
struct osspriteop_area *result = xcalloc(1, nBytes);
|
||||
struct osspriteop_header *spr = (osspriteop_header*)(result+1);
|
||||
int i,n;
|
||||
unsigned int *pPalDest = (unsigned int*)(spr+1);
|
||||
unsigned int *pPalSrc;
|
||||
int i;
|
||||
pixel j;
|
||||
|
||||
if ( !result )
|
||||
return NULL;
|
||||
|
||||
result->size = nBytes;
|
||||
result->sprite_count = 1;
|
||||
result->first = sizeof(*result);
|
||||
result->used = nBytes;
|
||||
|
||||
spr->size = nBytes-sizeof(*result);
|
||||
strncpy( spr->name, "gif", 12 );
|
||||
spr->width = ((a->nWidth+3)>>2)-1;
|
||||
spr->height = a->nHeight-1;
|
||||
spr->left_bit = 0;
|
||||
spr->right_bit = ((a->nWidth & 3) * 8 - 1) & 31;
|
||||
spr->image = sizeof(*spr) + 256*8;
|
||||
spr->mask = sizeof(*spr) + 256*8 + abw;
|
||||
spr->mode = os_MODE8BPP90X90; /* 28 */
|
||||
|
||||
c->data.gif.sprite_image = ((char*)spr) + spr->image;
|
||||
c->width = a->nWidth;
|
||||
c->height = a->nHeight;
|
||||
|
||||
n = a->pFrames->pal->nColours;
|
||||
pPalSrc = a->pFrames->pal->pColours;
|
||||
for ( i=0; i<n; i++ )
|
||||
switch ( bpp )
|
||||
{
|
||||
*pPalDest++ = *pPalSrc;
|
||||
*pPalDest++ = *pPalSrc++;
|
||||
}
|
||||
case 8:
|
||||
if ( src != dest )
|
||||
memmove( dest, src, n );
|
||||
break;
|
||||
|
||||
return result;
|
||||
case 4:
|
||||
for ( i=0; i< (n+1)/2; i++ )
|
||||
dest[i] = (src[i<<1] & 0xF) + ( src[(i<<1)+1] << 4 ) ;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for ( i=0; i < (n+3)/4; i++ )
|
||||
dest[i] = ( ( src[i<<2 ] ) & 3 )
|
||||
| ( ( src[(i<<2)+1] << 2 ) & 0xC )
|
||||
| ( ( src[(i<<2)+2] << 4 ) & 0x30 )
|
||||
| ( src[(i<<2)+3] << 6 );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
j = 0;
|
||||
for ( i=0; i < (n|7)+1; i++ )
|
||||
{
|
||||
j += (src[i] & 1) << (i&7);
|
||||
if ( (i&7) == 7 )
|
||||
{
|
||||
dest[i>>3] = j;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void CompressMaskLine( pixel *dest, const pixel *src, int n, int bpp )
|
||||
{
|
||||
int i;
|
||||
|
||||
switch ( bpp )
|
||||
{
|
||||
case 8:
|
||||
for ( i=0; i<n; i++ )
|
||||
dest[i] = ( src[i] ) ? 0xFF : 0;
|
||||
break;
|
||||
case 4:
|
||||
for ( i=0; i< (n+1)/2; i++ )
|
||||
dest[i] = ( src[i<<1] ? 0xF : 0 )
|
||||
+ ( ( src[(i<<1)+1] ? 0xF : 0 ) << 4 );
|
||||
break;
|
||||
case 2:
|
||||
for ( i=0; i < (n+3)/4; i++ )
|
||||
dest[i] = ( src[i<<2 ] ? 0x3 : 0 )
|
||||
+ ( src[(i<<2)+1] ? 0xC : 0 )
|
||||
+ ( src[(i<<2)+2] ? 0x30 : 0 )
|
||||
+ ( src[(i<<2)+3] ? 0xC0 : 0 );
|
||||
break;
|
||||
case 1:
|
||||
CompressSpriteLine( dest, src, n, 1 ); /* It's the same! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -20,10 +20,6 @@ struct content_gif_data {
|
||||
*/
|
||||
osspriteop_area *sprite_area;
|
||||
|
||||
/* The sprite image of the current 8bpp frame
|
||||
*/
|
||||
char *sprite_image;
|
||||
|
||||
/* The sprite header of the current 32bpp image.
|
||||
*/
|
||||
osspriteop_header *buffer_header;
|
||||
@ -69,4 +65,6 @@ void nsgif_redraw(struct content *c, long x, long y,
|
||||
long clip_x0, long clip_y0, long clip_x1, long clip_y1,
|
||||
float scale);
|
||||
osspriteop_header *nsgif_get_sprite_address(struct content *c, unsigned int frame);
|
||||
bool nsgif_decompress_frame(struct content *c, anim *p_gif_animation, unsigned int cur_frame);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user