📄 gui_gif.c
字号:
}
}
return Code;
}
/*********************************************************************
*
* _ReadExtension
*
* Purpose:
* Reads an extension block. One extension block can consist of several data blocks.
* If an unknown extension block occures, the routine failes.
*/
static int _ReadExtension(int * pTransIndex, GUI_GIF_IMAGE_INFO * pInfo, U8 * pDisposal) {
U8 Label;
Label = _ReadU8();
switch (Label) {
case GIF_PLAINTEXT:
case GIF_APPLICATION:
case GIF_COMMENT:
while (_GetDataBlock(_aBuffer) > 0);
return 0;
case GIF_GRAPHICCTL:
if (_GetDataBlock(_aBuffer) != 4) { /* Length of a graphic control block must be 4 */
return 1;
}
if (pInfo) {
pInfo->Delay = (_aBuffer[2] << 8) | _aBuffer[1];
}
if (pDisposal) {
*pDisposal = (_aBuffer[0] >> 2) & 0x7;
}
if (pTransIndex) {
if ((_aBuffer[0] & 0x1) != 0) {
*pTransIndex = _aBuffer[3];
}
}
if (_ReadU8() != 0) { /* Read block terminator */
return 1;
}
return 0;
}
return 1; /* Error */
}
/*********************************************************************
*
* _ReadComment
*
* Purpose:
* Reads a comment from the extension block if available and returns the number
* of comment bytes.
*/
static int _ReadComment(U8 * pBuffer, int MaxSize, int * pSize) {
U8 Label;
int Size;
Label = _ReadU8();
switch (Label) {
case GIF_PLAINTEXT:
case GIF_APPLICATION:
while (_GetDataBlock(_aBuffer) > 0);
return 0;
case GIF_COMMENT:
Size = _GetDataBlock(_aBuffer);
if (Size > MaxSize) {
Size = MaxSize;
}
if (pBuffer) {
*pSize = Size;
memcpy(pBuffer, _aBuffer, Size);
}
return 0;
case GIF_GRAPHICCTL:
if (_GetDataBlock(_aBuffer) != 4) { /* Length of a graphic control block must be 4 */
return 1;
}
if (_ReadU8() != 0) { /* Read block terminator, must be 0 */
return 1;
}
return 0;
}
return 1; /* Error */
}
/*********************************************************************
*
* _DispGIFImage
*
* Purpose:
* This routine draws a GIF image from the current pointer which should point to a
* valid GIF data block. The size of the desired image is given in the image descriptor.
*
* Return value:
* 0 if succeed
* 1 if not succeed
*
* Parameters:
* pDescriptor - Points to a IMAGE_DESCRIPTOR structure, which contains infos about size, colors and interlacing.
* x0, y0 - Obvious.
* Transparency - Color index which should be treated as transparent.
* Disposal - Contains the disposal method of the previous image. If Disposal == 2, the transparent pixels
* of the image are rendered with the background color.
*/
static int _DispGIFImage(IMAGE_DESCRIPTOR * pDescriptor, int x0, int y0, int Transparency, int Disposal) {
int Codesize, Index, OldIndex, XPos, YPos, YCnt, Pass, Interlace, XEnd;
int Width, Height, NumColors, Cnt, BkColorIndex, ColorIndex;
LCD_LOGPALETTE LogPalette;
const LCD_PIXELINDEX * pTrans;
Width = pDescriptor->XSize;
Height = pDescriptor->YSize;
NumColors = pDescriptor->NumColors;
XEnd = Width + x0 - 1;
BkColorIndex = LCD_GetBkColorIndex();
/* Get color translation table */
LogPalette.NumEntries = NumColors;
LogPalette.HasTrans = 0;
LogPalette.pPalEntries = _aColorTable;
if ((pTrans = LCD_GetpPalConvTable((const LCD_LOGPALETTE *)&LogPalette)) == NULL) {
return 1; /* Error */
}
Codesize = _ReadU8(); /* Read the LZW codesize */
_InitLZW(Codesize); /* Initialize the LZW stack with the LZW codesize */
Interlace = pDescriptor->Flags & 0x40; /* Evaluate if image is interlaced */
for (YCnt = 0, YPos = y0, Pass = 0; YCnt < Height; YCnt++) {
Cnt = 0;
OldIndex = -1;
for (XPos = x0; XPos <= XEnd; XPos++) {
if (_LZWContext.sp > _LZWContext.aDecompBuffer) {
Index = *--(_LZWContext.sp);
} else {
Index = _GetNextByte();
}
if (Index == -2) {
return 0; /* End code */
}
if ((Index < 0) || (Index >= NumColors)) {
/* If Index out of legal range stop decompressing */
return 1; /* Error */
}
/* If current index equals old index increment counter */
if ((Index == OldIndex) && (XPos <= XEnd)) {
Cnt++;
} else {
if (Cnt) {
if (OldIndex != Transparency) {
LCD_SetColorIndex(*(pTrans + OldIndex));
LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1);
} else if (Disposal == 2) {
LCD_SetColorIndex(BkColorIndex);
LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1);
}
Cnt = 0;
} else {
if (OldIndex >= 0) {
if (OldIndex != Transparency) {
LCD_SetPixelIndex(XPos - 1, YPos, *(pTrans + OldIndex));
} else if (Disposal == 2) {
LCD_SetPixelIndex(XPos - 1, YPos, BkColorIndex);
}
}
}
}
OldIndex = Index;
}
if ((OldIndex != Transparency) || (Disposal == 2)) {
if (OldIndex != Transparency) {
ColorIndex = *(pTrans + OldIndex);
} else {
ColorIndex = BkColorIndex;
}
if (Cnt) {
LCD_SetColorIndex(ColorIndex);
LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1);
} else {
LCD_SetPixelIndex(XEnd, YPos, ColorIndex);
}
}
/* Adjust YPos if image is interlaced */
if (Interlace) {
YPos += _aInterlaceOffset[Pass];
if ((YPos - y0) >= Height) {
++Pass;
YPos = _aInterlaceYPos[Pass] + y0;
}
} else {
YPos++;
}
}
return 0;
}
/*********************************************************************
*
* _ReadColorMap
*/
static int _ReadColorMap(int NumColors) {
int i;
for (i = 0; i < NumColors; i++) {
U8 r, g, b;
r = _ReadU8 ();
g = _ReadU8 ();
b = _ReadU8 ();
if (_Source.RemBytes < 0) {
return 1; /* Error */
}
_aColorTable[i] = r | ((U16)g << 8) | ((U32)b << 16);
}
return 0;
}
/*********************************************************************
*
* _InitGIFDecoding
*
* Purpose:
* The routine initializes the static SOURCE structure and checks
* if the file is a legal GIF file.
*
* Return value:
* 0 on success, 1 on error
*/
static int _InitGIFDecoding(const U8 * pData, U32 NumBytes) {
U8 acVersion[7] = {0};
_Source.pSrc = pData;
_Source.RemBytes = NumBytes;
/* Check if the file is a legal GIF file by checking the 6 byte file header */
_ReadBytes(acVersion, 6); if (!_Source.RemBytes) { return 0; }
if ( (acVersion[0] != 'G') ||
(acVersion[1] != 'I') ||
(acVersion[2] != 'F') ||
(acVersion[3] != '8') ||
((acVersion[4] != '7') && (acVersion[4] != '9')) ||
(acVersion[5] != 'a')) {
return 1;
}
return 0;
}
/*********************************************************************
*
* _GetImageDimension
*
* Purpose:
* Reads the image dimension from the logical screen descriptor
*
* Return value:
* 0 on success, 1 on error
*/
static int _GetImageDimension(int * pxSize, int * pySize) {
int XSize, YSize;
/* Read image size */
XSize = _ReadU16();
YSize = _ReadU16();
if ((XSize > 2000) || (YSize > 2000)) {
return 1; /* Error if image is too large */
}
if (pxSize) {
*pxSize = XSize;
}
if (pySize) {
*pySize = YSize;
}
return 0;
}
/*********************************************************************
*
* _GetGlobalColorTable
*
* Purpose:
* Reads the global color table if there is one. Returns the number of
* available colors over the pointer pNumColors (can be NULL).
*
* Return value:
* 0 on success, 1 on error
*/
static int _GetGlobalColorTable(int * pNumColors) {
U8 Flags;
int NumColors;
/* Read flags from logical screen descriptor */
Flags = _ReadU8 ();
_ReadU8 ();
_ReadU8 ();
if (_Source.RemBytes < 0) {
return 1; /* Error */
}
NumColors = 2 << (Flags & 0x7);
if (Flags & 0x80) {
/* Read global color table */
if (_ReadColorMap(NumColors)) {
return 1; /* Error */
}
}
if (pNumColors) {
*pNumColors = NumColors;
}
return 0;
}
/*********************************************************************
*
* _GetSizeAndColorTable
*/
static int _GetSizeAndColorTable(const U8 * pData, U32 NumBytes, int * pxSize, int * pySize, int * pNumColors) {
/* Initialize decoding */
if (_InitGIFDecoding(pData, NumBytes)) {
return 1; /* Error */
}
/* Get image size */
if (_GetImageDimension(pxSize, pySize)) {
return 1; /* Error */
}
/* Get global color table (if available) */
if (_GetGlobalColorTable(pNumColors)) {
return 1; /* Error */
}
return 0;
}
/*********************************************************************
*
* _GetGIFInfo
*/
static int _GetGIFInfo(const U8 * pData, U32 NumBytes, GUI_GIF_INFO * pInfo) {
U8 Flags, Introducer;
int NumColors, ImageCnt;
/* Initialize decoding and get size and global color table */
if (_GetSizeAndColorTable(pData, NumBytes, &pInfo->xSize, &pInfo->ySize, &NumColors)) {
return 1; /* Error */
}
ImageCnt = 0;
/* Iterate over the blocks */
do {
Introducer = _ReadU8();
switch (Introducer) {
case GIF_INTRO_IMAGE:
_SkipBytes(8); /* Skip the first 8 bytes of the image descriptor */
Flags = _ReadU8(); /* Only 'Flags' are intresting */
if (Flags & 0x80) {
_SkipBytes(NumColors * 3); /* Skip local color table */
}
_SkipBytes(1); /* Skip codesize */
while (_GetDataBlock(0) > 0); /* Skip data blocks */
ImageCnt++;
break;
case GIF_INTRO_TERMINATOR:
break;
case GIF_INTRO_EXTENSION:
if (_ReadExtension(NULL, NULL, NULL)) { /* Skip image extension */
return 1;
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -