📄 gifsave.c
字号:
Byte tmp;
if (WriteWord(sd->LocalScreenWidth) != GIF_OK)
return GIF_ERRWRITE;
if (WriteWord(sd->LocalScreenHeight) != GIF_OK)
return GIF_ERRWRITE;
tmp = (sd->GlobalColorTableFlag << 7)
| (sd->ColorResolution << 4)
| (sd->SortFlag << 3)
| sd->GlobalColorTableSize;
if (WriteByte(tmp) != GIF_OK)
return GIF_ERRWRITE;
if (WriteByte(sd->BackgroundColorIndex) != GIF_OK)
return GIF_ERRWRITE;
if (WriteByte(sd->PixelAspectRatio) != GIF_OK)
return GIF_ERRWRITE;
return GIF_OK;
}
/*-------------------------------------------------------------------------
*
* NAME WriteTransparentColorIndex (added by j.forkosh)
*
* DESCRIPTION Output a graphic extension block setting transparent
* colormap index
*
* INPUT colornum colormap index of color to be transparent
*
* RETURNS GIF_OK - OK
* GIF_ERRWRITE - Error writing to the file
*/
static int
WriteTransparentColorIndex(int colornum)
{
if ( colornum < 0 ) return GIF_OK; /*no transparent color set*/
if (WriteByte((Byte)(0x21)) != GIF_OK) /*magic:Extension Introducer*/
return GIF_ERRWRITE;
if (WriteByte((Byte)(0xf9)) != GIF_OK) /*magic:Graphic Control Label*/
return GIF_ERRWRITE;
if (WriteByte((Byte)(4)) != GIF_OK) /* #bytes in block */
return GIF_ERRWRITE;
if (WriteByte((Byte)(1)) != GIF_OK) /*transparent index indicator*/
return GIF_ERRWRITE;
if (WriteWord((Word)(0)) != GIF_OK) /* delay time */
return GIF_ERRWRITE;
if (WriteByte((Byte)(colornum)) != GIF_OK) /* transparent color index */
return GIF_ERRWRITE;
if (WriteByte((Byte)(0)) != GIF_OK) /* terminator */
return GIF_ERRWRITE;
return GIF_OK;
}
/*-------------------------------------------------------------------------
*
* NAME WriteImageDescriptor
*
* DESCRIPTION Output an image descriptor to the current GIF-file
*
* INPUT id pointer to image descriptor to output
*
* RETURNS GIF_OK - OK
* GIF_ERRWRITE - Error writing to the file
*/
static int
WriteImageDescriptor(ImageDescriptor *id)
{
Byte tmp;
if (WriteByte(id->Separator) != GIF_OK)
return GIF_ERRWRITE;
if (WriteWord(id->LeftPosition) != GIF_OK)
return GIF_ERRWRITE;
if (WriteWord(id->TopPosition) != GIF_OK)
return GIF_ERRWRITE;
if (WriteWord(id->Width) != GIF_OK)
return GIF_ERRWRITE;
if (WriteWord(id->Height) != GIF_OK)
return GIF_ERRWRITE;
tmp = (id->LocalColorTableFlag << 7)
| (id->InterlaceFlag << 6)
| (id->SortFlag << 5)
| (id->Reserved << 3)
| id->LocalColorTableSize;
if (WriteByte(tmp) != GIF_OK)
return GIF_ERRWRITE;
return GIF_OK;
}
/**************************************************************************
* *
* P U B L I C F U N C T I O N S *
* *
**************************************************************************/
/*-------------------------------------------------------------------------
*
* NAME GIF_Create
*
* DESCRIPTION Create a GIF-file, and write headers for both screen
* and image.
*
* INPUT filename
* name of file to create (including extension)
* width number of horisontal pixels on screen
* height number of vertical pixels on screen
* numcolors
* number of colors in the colormaps
* colorres
* color resolution. Number of bits for each
* primary color
*
* RETURNS GIF_OK - OK
* GIF_ERRCREATE - Couldn't create file
* GIF_ERRWRITE - Error writing to the file
* GIF_OUTMEM - Out of memory allocating color table
*/
int
GIF_Create(const char *filename, int width, int height,
int numcolors, int colorres)
{
int q, tabsize;
Byte *bp;
ScreenDescriptor SD;
/* initiate variables for new GIF-file */
NumColors = numcolors ? (1 << BitsNeeded(numcolors)) : 0;
BitsPrPrimColor = colorres;
ScreenHeight = height;
ScreenWidth = width;
/* create file specified */
if (Create(filename) != GIF_OK)
return GIF_ERRCREATE;
/* write GIF signature */
if ((Write("GIF87a", 6)) != GIF_OK)
return GIF_ERRWRITE;
/* initiate and write screen descriptor */
SD.LocalScreenWidth = width;
SD.LocalScreenHeight = height;
if (NumColors) {
SD.GlobalColorTableSize = BitsNeeded(NumColors) - 1;
SD.GlobalColorTableFlag = 1;
} else {
SD.GlobalColorTableSize = 0;
SD.GlobalColorTableFlag = 0;
}
SD.SortFlag = 0;
SD.ColorResolution = colorres - 1;
SD.BackgroundColorIndex = 0;
SD.PixelAspectRatio = 0;
if (WriteScreenDescriptor(&SD) != GIF_OK)
return GIF_ERRWRITE;
/* allocate color table */
if (ColorTable) {
free(ColorTable);
ColorTable = NULL;
}
if (NumColors) {
tabsize = NumColors * 3;
if ((ColorTable = (Byte *) malloc(tabsize * sizeof(Byte))) == NULL)
return GIF_OUTMEM;
else {
bp = ColorTable;
for (q = 0; q < tabsize; q++)
*bp++ = 0;
}
}
return 0;
}
/*-------------------------------------------------------------------------
*
* NAME GIF_SetColor
*
* DESCRIPTION Set red, green and blue components of one of the
* colors. The color components are all in the range
* [0, (1 << BitsPrPrimColor) - 1]
*
* INPUT colornum
* color number to set. [0, NumColors - 1]
* red red component of color
* green green component of color
* blue blue component of color
*/
void
GIF_SetColor(int colornum, int red, int green, int blue)
{
long maxcolor;
Byte *p;
maxcolor = (1L << BitsPrPrimColor) - 1L;
p = ColorTable + colornum * 3;
*p++ = (Byte) ((red * 255L) / maxcolor);
*p++ = (Byte) ((green * 255L) / maxcolor);
*p++ = (Byte) ((blue * 255L) / maxcolor);
}
/*-------------------------------------------------------------------------
*
* NAME GIF_SetTransparent (added by j.forkosh)
*
* DESCRIPTION Set colormap index of color to be transparent
*
* INPUT colornum
* color number to set transparent. [0, NumColors - 1]
*/
void
GIF_SetTransparent(int colornum)
{
TransparentColorIndex = colornum;
}
/*-------------------------------------------------------------------------
*
* NAME GIF_CompressImage
*
* DESCRIPTION Compress an image into the GIF-file previousely
* created using GIF_Create(). All color values should
* have been specified before this function is called.
*
* The pixels are retrieved using a user defined callback
* function. This function should accept two parameters,
* x and y, specifying which pixel to retrieve. The pixel
* values sent to this function are as follows:
*
* x : [ImageLeft, ImageLeft + ImageWidth - 1]
* y : [ImageTop, ImageTop + ImageHeight - 1]
*
* The function should return the pixel value for the
* point given, in the interval [0, NumColors - 1]
*
* INPUT left screen-relative leftmost pixel x-coordinate
* of the image
* top screen-relative uppermost pixel y-coordinate
* of the image
* width width of the image, or -1 if as wide as
* the screen
* height height of the image, or -1 if as high as
* the screen
* getpixel
* address of user defined callback function.
* (see above)
*
* RETURNS GIF_OK - OK
* GIF_OUTMEM - Out of memory
* GIF_ERRWRITE - Error writing to the file
*/
int
GIF_CompressImage(int left, int top, int width, int height,
int (*getpixel)(int x, int y))
{
int codesize, errcode;
ImageDescriptor ID;
if (width < 0) {
width = ScreenWidth;
left = 0;
}
if (height < 0) {
height = ScreenHeight;
top = 0;
}
if (left < 0)
left = 0;
if (top < 0)
top = 0;
/* write global colortable if any */
if (NumColors)
if ((Write(ColorTable, NumColors * 3)) != GIF_OK)
return GIF_ERRWRITE;
/* write graphic extension block with transparent color index */
if ( TransparentColorIndex >= 0 ) /* (added by j.forkosh) */
if ( WriteTransparentColorIndex(TransparentColorIndex)
!= GIF_OK ) return GIF_ERRWRITE;
/* initiate and write image descriptor */
ID.Separator = ',';
ID.LeftPosition = ImageLeft = left;
ID.TopPosition = ImageTop = top;
ID.Width = ImageWidth = width;
ID.Height = ImageHeight = height;
ID.LocalColorTableSize = 0;
ID.Reserved = 0;
ID.SortFlag = 0;
ID.InterlaceFlag = 0;
ID.LocalColorTableFlag = 0;
if (WriteImageDescriptor(&ID) != GIF_OK)
return GIF_ERRWRITE;
/* write code size */
codesize = BitsNeeded(NumColors);
if (codesize == 1)
++codesize;
if (WriteByte(codesize) != GIF_OK)
return GIF_ERRWRITE;
/* perform compression */
RelPixX = RelPixY = 0;
GetPixel = getpixel;
if ((errcode = LZW_Compress(codesize, InputByte)) != GIF_OK)
return errcode;
/* write terminating 0-byte */
if (WriteByte(0) != GIF_OK)
return GIF_ERRWRITE;
return GIF_OK;
}
/*-------------------------------------------------------------------------
*
* NAME GIF_Close
*
* DESCRIPTION Close the GIF-file
*
* RETURNS GIF_OK - OK
* GIF_ERRWRITE - Error writing to file
*/
int
GIF_Close(void)
{
ImageDescriptor ID;
/* initiate and write ending image descriptor */
ID.Separator = ';';
ID.LeftPosition = 0; /* (added by j.forkosh) */
ID.TopPosition = 0; /* " initialize entire ID structure */
ID.Width = 0; /* " and ditto for other ID.x=0; below */
ID.Height = 0;
ID.LocalColorTableSize = 0;
ID.Reserved = 0;
ID.SortFlag = 0;
ID.InterlaceFlag = 0;
ID.LocalColorTableFlag = 0;
if (WriteImageDescriptor(&ID) != GIF_OK)
return GIF_ERRWRITE;
/* close file */
Close();
/* release color table */
if (ColorTable) {
free(ColorTable);
ColorTable = NULL;
}
return GIF_OK;
}
/* --- end-of-file gifsave.c --- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -