⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gui_gif.c

📁 ucgui的3.98版本的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    }
  }
  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 + -