📄 gifdecoderapi.c
字号:
///////////////////////////////////////////////////////////////////////////////
//
// gifdecoderapi.h
//
// DESCRIPTION
// Define functions that implements the GIF Decoder API.
//
//
///////////////////////////////////////////////////////////////////////////////
#include "gifdecoderapi.h"
#include "gifcommon.h"
// global variable
static Image *currentImage;
// external
extern Image *ReadGIFFrame
(
const Image *image,
unsigned char *outbuf,
ImageSaveMethod saveimage,
unsigned char skipdecoding,
OP_BOOLEAN only_info,
OP_BOOLEAN func(OP_UINT16 x, OP_UINT16 y)
);
extern Image *ReadGIFHeader
(
const Image *image_info
);
#define RGB565(r, g, b) ((r >> 3) << 11)| ((g >> 2) << 5)| ((b >> 3) << 0)
// function pointer type definition
typedef void* (*GetMemoryFunction)(OP_UINT32 size);
typedef void (*FreeMemoryFunction)(void *x);
// Global variables
// input buffer pointer
static OP_UINT8 *gifInputBuffer;
// output buffer pointer;
static OP_UINT8 *gifOutputBuffer;
// input buffer size
static OP_UINT32 gifInputBufferSize;
// image information
static GIF_IMAGE_INFO gifImageInfo;
// memory allocation function pointer
static GetMemoryFunction gifDynMemAllocate;
// memory deallocate function pointer
static FreeMemoryFunction gifDynMemDeallocate;
// decoder state
static GIF_DECODER_STATE gifDecoderState = GIF_DECODER_STATE_UNINITIALIZED;
// GIF Decoder API Functions
/////////////////////////////////////////////////////////////////////////////
// NAME
// gifDecoderInitialize
//
// DESCRIPTION
// This function initializes the GIF Decoder and sets the image
// decoding configurations to default values.
//
// INPUTS
// none.
//
// OUTPUTS
// none.
//
// RETURN VALUE
// none.
//
/////////////////////////////////////////////////////////////////////////////
void gifDecoderInitialize
(
void
)
{
// clear input and output buffer pointers
gifInputBuffer = 0;
gifOutputBuffer = 0;
gifInputBufferSize = 0;
// clear image info structure
gifImageInfo.imageWidth = 0;
gifImageInfo.imageHeight = 0;
gifImageInfo.logicalScreenWidth = 0;
gifImageInfo.logicalScreenHeight = 0;
gifImageInfo.imageLeftPos = 0;
gifImageInfo.imageTopPos = 0;
gifImageInfo.imageDelay = 0;
gifImageInfo.imageIterations = 0;
gifImageInfo.backgroundColor = 0;
gifImageInfo.disposal = 0;
gifImageInfo.trans_flag = OP_FALSE;
gifImageInfo.comments[0] = 0;
// clear image pointer
currentImage = OP_NULL;
// update decoder state
gifDecoderState = GIF_DECODER_STATE_INITIALIZED;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// gifSetInputBuffer
//
// DESCRIPTION
// This function allows the Decoder Controller to pass the decoder
// the input buffer pointer and the input buffer size
//
// INPUTS
// inputBuffer - input buffer pointer
// bufferSize - input buffer size
//
// OUTPUTS
// none.
//
// RETURN VALUE
// none.
//
/////////////////////////////////////////////////////////////////////////////
void gifSetInputBuffer
(
OP_UINT8 *inputBuffer,
OP_UINT32 bufferSize
)
{
OP_UINT16 i;
Image image0;
Image *image1;
Image *image2;
// store input buffer info
gifInputBuffer = inputBuffer;
gifInputBufferSize = bufferSize;
// get GIF image size information
for(i = 0; i < sizeof(Image); i++)
{
((OP_UINT8 *)&image0)[i] = 0;
}
image0.getmemory = gifDynMemAllocate;
image0.freememory = gifDynMemDeallocate;
image1 = AllocateImage(&image0);
image1->blob->data = gifInputBuffer;
image1->blob->offset = 0;
image1->blob->length = gifInputBufferSize;
currentImage = ReadGIFHeader(image1);
DestroyImage(image1);
if(currentImage == OP_NULL)
{
return;
}
// get GIF image info
image1 = AllocateImage(currentImage);
if(image1 == OP_NULL)
{
return;
}
image2 = ReadGIFFrame(image1, OP_NULL, OP_NULL, OP_TRUE, OP_FALSE, OP_NULL);
if(image2 == OP_NULL)
{
DestroyImage(image1);
return;
}
// copy image size, location and logical screen size
gifImageInfo.imageWidth = image2->columns;
gifImageInfo.imageHeight = image2->rows;
gifImageInfo.logicalScreenWidth = image2->page.width;
gifImageInfo.logicalScreenHeight = image2->page.height;
gifImageInfo.imageLeftPos = image2->page.x;
gifImageInfo.imageTopPos = image2->page.y;
gifImageInfo.imageDelay = image2->delay * 10;
gifImageInfo.imageIterations = image2->iterations;
gifImageInfo.backgroundColor = RGB565(image2->background_color.red,
image2->background_color.green,
image2->background_color.blue);
gifImageInfo.disposal = image2->dispose;
gifImageInfo.trans_flag = image2->trans_flag;
// free memory
if(image2 != image1)
{
DestroyImage(image2);
}
DestroyImage(image1);
// update decoder state
gifDecoderState = GIF_DECODER_STATE_READY;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// gifGetImageInfo
//
// DESCRIPTION
// This function returns image information to Image Decoder
// Controller
//
// INPUTS
// info - pointer to GIF image info structure
//
// OUTPUTS
// info - update value in this structure.
//
// RETURN VALUE
// GIF_DECODER_ERR_NONE if successful, an error code otherwise.
//
/////////////////////////////////////////////////////////////////////////////
GIF_DECODER_ERR gifGetImageInfo
(
GIF_IMAGE_INFO *info
)
{
// check if we are in the right state
if(gifDecoderState == GIF_DECODER_STATE_READY)
{
// copy image info
info->imageWidth = gifImageInfo.imageWidth;
info->imageHeight = gifImageInfo.imageHeight;
info->logicalScreenWidth = gifImageInfo.logicalScreenWidth;
info->logicalScreenHeight = gifImageInfo.logicalScreenHeight;
info->imageLeftPos = gifImageInfo.imageLeftPos;
info->imageTopPos = gifImageInfo.imageTopPos;
info->imageDelay = gifImageInfo.imageDelay;
info->imageIterations = gifImageInfo.imageIterations;
info->backgroundColor = gifImageInfo.backgroundColor;
info->disposal = gifImageInfo.disposal;
info->trans_flag = gifImageInfo.trans_flag;
return GIF_DECODER_ERR_NONE;
}
else
{
return GIF_DECODER_ERR_INVALID_STATE;
}
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// gifDecodeImage
//
// DESCRIPTION
// This function decodes a frame in the GIF image
//
// INPUTS
// outputBuffer - output buffer pointer
// func - callback function
// lastFrame - indicates whether this is the last frame in image
//
// OUTPUTS
// outputBuffer - store result to output buffer
//
// RETURN VALUE
// GIF_DECODER_ERR_NONE if successful, an error code otherwise.
//
/////////////////////////////////////////////////////////////////////////////
GIF_DECODER_ERR gifDecodeImage
(
OP_UINT8 *outputBuffer,
OP_BOOLEAN func(OP_UINT16 x, OP_UINT16 y),
OP_BOOLEAN *lastFrame,
OP_BOOLEAN only_info
)
{
// check if we are in the right state
if(gifDecoderState == GIF_DECODER_STATE_READY)
{
Image *image1;
Image *image2;
// save output buffer pointer
gifOutputBuffer = outputBuffer;
// update decoder state
gifDecoderState = GIF_DECODER_STATE_ACTIVE;
// start GIF decoding
image1 = ReadGIFFrame(currentImage, outputBuffer, OP_NULL, only_info, only_info, func);
if(image1 != OP_NULL)
{
// free memory if necessary
if(image1 != currentImage)
{
DestroyImage(currentImage);
}
currentImage = image1;
// check if there is more frame
image1 = AllocateImage(currentImage);
if(image1 == OP_NULL)
{
return GIF_DECODER_ERR_OPERATION_FAILED;
}
image2 = ReadGIFFrame(image1, OP_NULL, OP_NULL, OP_TRUE, OP_FALSE, OP_NULL);
if(image2 == OP_NULL)
{
// if no more frame, return
*lastFrame = OP_TRUE;
DestroyImage(image1);
return GIF_DECODER_ERR_NONE;
}
// otherwise update image info
*lastFrame = OP_FALSE;
// copy image size, location and logical screen size
gifImageInfo.imageWidth = image2->columns;
gifImageInfo.imageHeight = image2->rows;
gifImageInfo.logicalScreenWidth = image2->page.width;
gifImageInfo.logicalScreenHeight = image2->page.height;
gifImageInfo.imageLeftPos = image2->page.x;
gifImageInfo.imageTopPos = image2->page.y;
gifImageInfo.imageDelay = image2->delay * 10;
gifImageInfo.imageIterations = image2->iterations;
gifImageInfo.backgroundColor = RGB565(image2->background_color.red,
image2->background_color.green,
image2->background_color.blue);
gifImageInfo.disposal = image2->dispose;
// free memory
if(image2 != image1)
{
DestroyImage(image2);
}
DestroyImage(image1);
// update decoder state
gifDecoderState = GIF_DECODER_STATE_READY;
return GIF_DECODER_ERR_NONE;
}
else
{
/*
* Remove DestroyImage() because of duplicated free memory in ReadGIFFrame()
* // free memory if necessary
* if(currentImage->next != OP_NULL)
* {
* DestroyImage(currentImage->next);
* }
*/
*lastFrame = OP_TRUE;
// update decoder state
gifDecoderState = GIF_DECODER_STATE_READY;
return GIF_DECODER_ERR_OPERATION_FAILED;
}
}
else
{
return GIF_DECODER_ERR_INVALID_STATE;
}
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// gifSetDynMemAllocFuncs
//
// DESCRIPTION
// This function allows the Decoder Controller to pass the dynamic
// memory allocation function pointers to the decoder
//
// INPUTS
// allocate - memory allocation function pointer
// deallocate - memory deallocation function pointer
//
// OUTPUTS
// none.
//
// RETURN VALUE
// none.
//
/////////////////////////////////////////////////////////////////////////////
void gifSetDynMemAllocFuncs
(
void *allocate(OP_UINT32 size),
void deallocate(void *x)
)
{
gifDynMemAllocate = allocate;
gifDynMemDeallocate = deallocate;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// gifDecoderCleanup
//
// DESCRIPTION
// This function releases all dynamic memory resources allocated
// during decoding
//
// INPUTS
// none.
//
// OUTPUTS
// none.
//
// RETURN VALUE
// none.
//
/////////////////////////////////////////////////////////////////////////////
void gifDecoderCleanup
(
void
)
{
if(currentImage != OP_NULL)
{
DestroyImage(currentImage);
}
currentImage = OP_NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -