📄 ungif.c
字号:
/*
* Gif extracting routines - derived from libungif
*
* Portions Copyright 2006 Mike McCormack
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* Original copyright notice:
*
* The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
/******************************************************************************
* "Gif-Lib" - Yet another gif library.
*
* Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990
******************************************************************************
* The kernel of the GIF Decoding process can be found here.
******************************************************************************
* History:
* 16 Jun 89 - Version 1.0 by Gershon Elber.
* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names).
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "ungif.h"
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
static void *ungif_alloc( size_t sz )
{
return HeapAlloc( GetProcessHeap(), 0, sz );
}
static void *ungif_calloc( size_t num, size_t sz )
{
return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, num*sz );
}
static void ungif_free( void *ptr )
{
HeapFree( GetProcessHeap(), 0, ptr );
}
#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
#define LZ_BITS 12
#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
typedef struct GifFilePrivateType {
GifWord BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */
ClearCode, /* The CLEAR LZ code. */
EOFCode, /* The EOF LZ code. */
RunningCode, /* The next code algorithm can generate. */
RunningBits, /* The number of bits required to represent RunningCode. */
MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
LastCode, /* The code before the current code. */
CrntCode, /* Current algorithm code. */
StackPtr, /* For character stack (see below). */
CrntShiftState; /* Number of bits in CrntShiftDWord. */
unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */
unsigned long PixelCount; /* Number of pixels in image. */
InputFunc Read; /* function to read gif input (TVT) */
GifByteType Buf[256]; /* Compressed input is buffered here. */
GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */
GifPrefixType Prefix[LZ_MAX_CODE + 1];
} GifFilePrivateType;
/* avoid extra function call in case we use fread (TVT) */
#define READ(_gif,_buf,_len) \
((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len)
static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
static int DGifSetupDecompress(GifFileType *GifFile);
static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen);
static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
static int DGifDecompressInput(GifFileType *GifFile, int *Code);
static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
GifByteType *NextByte);
static int DGifGetExtensionNext(GifFileType * GifFile, GifByteType ** GifExtension);
static int DGifGetCodeNext(GifFileType * GifFile, GifByteType ** GifCodeBlock);
/******************************************************************************
* Miscellaneous utility functions
*****************************************************************************/
/* return smallest bitfield size n will fit in */
static int
BitSize(int n) {
register int i;
for (i = 1; i <= 8; i++)
if ((1 << i) >= n)
break;
return (i);
}
/******************************************************************************
* Color map object functions
*****************************************************************************/
/*
* Allocate a color map of given size; initialize with contents of
* ColorMap if that pointer is non-NULL.
*/
static ColorMapObject *
MakeMapObject(int ColorCount,
const GifColorType * ColorMap) {
ColorMapObject *Object;
/*** FIXME: Our ColorCount has to be a power of two. Is it necessary to
* make the user know that or should we automatically round up instead? */
if (ColorCount != (1 << BitSize(ColorCount))) {
return ((ColorMapObject *) NULL);
}
Object = ungif_alloc(sizeof(ColorMapObject));
if (Object == (ColorMapObject *) NULL) {
return ((ColorMapObject *) NULL);
}
Object->Colors = ungif_calloc(ColorCount, sizeof(GifColorType));
if (Object->Colors == (GifColorType *) NULL) {
return NULL;
}
Object->ColorCount = ColorCount;
Object->BitsPerPixel = BitSize(ColorCount);
if (ColorMap) {
memcpy(Object->Colors, ColorMap, ColorCount * sizeof(GifColorType));
}
return (Object);
}
/*
* Free a color map object
*/
static void
FreeMapObject(ColorMapObject * Object) {
if (Object != NULL) {
ungif_free(Object->Colors);
ungif_free(Object);
/*** FIXME:
* When we are willing to break API we need to make this function
* FreeMapObject(ColorMapObject **Object)
* and do this assignment to NULL here:
* *Object = NULL;
*/
}
}
static int
AddExtensionBlock(SavedImage * New,
int Len,
unsigned char ExtData[]) {
ExtensionBlock *ep;
if (New->ExtensionBlocks == NULL)
New->ExtensionBlocks = ungif_alloc(sizeof(ExtensionBlock));
else
New->ExtensionBlocks = realloc(New->ExtensionBlocks,
sizeof(ExtensionBlock) *
(New->ExtensionBlockCount + 1));
if (New->ExtensionBlocks == NULL)
return (GIF_ERROR);
ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
ep->ByteCount=Len;
ep->Bytes = ungif_alloc(ep->ByteCount);
if (ep->Bytes == NULL)
return (GIF_ERROR);
if (ExtData) {
memcpy(ep->Bytes, ExtData, Len);
ep->Function = New->Function;
}
return (GIF_OK);
}
static void
FreeExtension(SavedImage * Image)
{
ExtensionBlock *ep;
if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) {
return;
}
for (ep = Image->ExtensionBlocks;
ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++)
ungif_free(ep->Bytes);
ungif_free(Image->ExtensionBlocks);
Image->ExtensionBlocks = NULL;
}
/******************************************************************************
* Image block allocation functions
******************************************************************************/
static void
FreeSavedImages(GifFileType * GifFile) {
SavedImage *sp;
if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
return;
}
for (sp = GifFile->SavedImages;
sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
if (sp->ImageDesc.ColorMap) {
FreeMapObject(sp->ImageDesc.ColorMap);
sp->ImageDesc.ColorMap = NULL;
}
ungif_free(sp->RasterBits);
if (sp->ExtensionBlocks)
FreeExtension(sp);
}
ungif_free(GifFile->SavedImages);
GifFile->SavedImages=NULL;
}
/******************************************************************************
* This routine should be called before any other DGif calls. Note that
* this routine is called automatically from DGif file open routines.
*****************************************************************************/
static int
DGifGetScreenDesc(GifFileType * GifFile) {
int i, BitsPerPixel;
GifByteType Buf[3];
/* Put the screen descriptor into the file: */
if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
return GIF_ERROR;
if (READ(GifFile, Buf, 3) != 3) {
return GIF_ERROR;
}
GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
BitsPerPixel = (Buf[0] & 0x07) + 1;
GifFile->SBackGroundColor = Buf[1];
if (Buf[0] & 0x80) { /* Do we have global color map? */
GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
if (GifFile->SColorMap == NULL) {
return GIF_ERROR;
}
/* Get the global color map: */
for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
if (READ(GifFile, Buf, 3) != 3) {
FreeMapObject(GifFile->SColorMap);
GifFile->SColorMap = NULL;
return GIF_ERROR;
}
GifFile->SColorMap->Colors[i].Red = Buf[0];
GifFile->SColorMap->Colors[i].Green = Buf[1];
GifFile->SColorMap->Colors[i].Blue = Buf[2];
}
} else {
GifFile->SColorMap = NULL;
}
return GIF_OK;
}
/******************************************************************************
* This routine should be called before any attempt to read an image.
*****************************************************************************/
static int
DGifGetRecordType(GifFileType * GifFile,
GifRecordType * Type) {
GifByteType Buf;
if (READ(GifFile, &Buf, 1) != 1) {
return GIF_ERROR;
}
switch (Buf) {
case ',':
*Type = IMAGE_DESC_RECORD_TYPE;
break;
case '!':
*Type = EXTENSION_RECORD_TYPE;
break;
case ';':
*Type = TERMINATE_RECORD_TYPE;
break;
default:
*Type = UNDEFINED_RECORD_TYPE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -