📄 gif_lzw.c
字号:
/* First time, just eat the expected Clear code(s) and return next code, */
/* which is expected to be a raw byte. */
if (*first_time)
{
*first_time = FALSE;
code = *clear_code; /* enables sharing code with Clear case */
}
else
{
/* If any codes are stacked from a previously read symbol, return them */
if (sp > symbol_stack)
{
return (int) *(--sp);
}
/* Time to read a new symbol */
code = GetCode(cinfo);
}
if(code == *clear_code)
{
/* Reinit static state, swallow any extra Clear codes, and */
/* return next code, which is expected to be a raw byte. */
ReInitLZW();
do {
code = GetCode(cinfo);
} while (code == *clear_code);
if (code > *clear_code)
{ /* make sure it is a raw byte */
#ifdef PCVER
WriteToErrorFile("LZWReadByte",ERROR_FILE_DATA_ERROR,FileError);
#endif
InsertError(ERROR_FILE_DATA_ERROR);
code = 0; /* use something valid */
}
firstcode = oldcode = code; /* make firstcode, oldcode valid! */
return code;
}
if (code == *end_code)
{
/* Skip the rest of the image, unless GetCode already read terminator */
if (! *out_of_blocks)
{
SkipDataBlocks();
*out_of_blocks = TRUE;
}
/* Complain that there's not enough data */
#ifdef PCVER
WriteToErrorFile("LZWReadByte",ERROR_FILE_ACCESS_ERROR,FileError);
#endif
InsertError(ERROR_FILE_ACCESS_ERROR);
/* Pad data with 0's */
return 0; /* fake something usable */
}
/* Got normal raw byte or LZW symbol */
incode = code; /* save for a moment */
if (code >= *max_code)
{ /* special case for not-yet-defined symbol */
/* code == max_code is OK; anything bigger is bad data */
if (code > *max_code)
{
#ifdef PCVER
WriteToErrorFile("LZWReadByte",ERROR_FILE_DATA_ERROR,FileError);
#endif
InsertError(ERROR_FILE_DATA_ERROR);
incode = 0; /* prevent creation of loops in symbol table */
}
*sp++ = (UINT8) firstcode; /* it will be defined as oldcode/firstcode */
code = oldcode;
}
/* If it's a symbol, expand it into the stack */
while (code >= *clear_code)
{
*sp++ = symbol_tail[code]; /* tail of symbol: a simple byte value */
code = symbol_head[code]; /* head of symbol: another LZW symbol */
}
/* At this point code just represents a raw byte */
firstcode = code; /* save for possible future use */
/* If there's room in table, */
if ((code = *max_code) < LZW_TABLE_SIZE)
{
/* Define a new symbol = prev sym + head of this sym's expansion */
symbol_head[code] = oldcode;
symbol_tail[code] = (UINT8) firstcode;
(*max_code)++;
/* Is it time to increase code_size? */
if ((*max_code >= *limit_code) && (*code_size < MAX_LZW_BITS))
{
(*code_size)++;
*limit_code <<= 1; /* keep equal to 2^code_size */
}
}
oldcode = incode; /* save last input symbol for future use */
return firstcode; /* return first byte of symbol's expansion */
}
//====================================================================================
// Function Name: LOCAL void ReInitLZW (void)
// Purpose : (Re)initialize LZW state; shared code for startup and Clear processing
// Parameter :
// Return : none
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
LOCAL void ReInitLZW (void)
{
*code_size = *input_code_size+1;
*limit_code = *clear_code << 1; /* 2^code_size */
*max_code = *clear_code + 2; /* first unused code value */
sp = symbol_stack; /* init stack to empty */
}
//====================================================================================
// Function Name: static Bool ReadColorMap (decompress_info_ptr cinfo, int cmaplen, uchar* cmap)
// Purpose : read coclor map from gif data buffer not only local colormap but also
// global color map data reading can call this function to read data
// Parameter :
// Return : none
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
static Bool ReadColorMap (decompress_info_ptr cinfo, int cmaplen, uchar* cmap)
{
int i;
if(!SetBufferCur(GetDataBufferCur() + cmaplen * 3))
{
return FALSE;
}
SetBufferCur(GetDataBufferCur() - cmaplen * 3);
for (i = 0; i < cmaplen; i++)
{
cmap[3*i] = (JSAMPLE) ReadByte();
cmap[3*i + CM_GREEN] = (JSAMPLE) ReadByte();
cmap[3*i + CM_BLUE] = (JSAMPLE) ReadByte();
}
return TRUE;
}
//====================================================================================
// Function Name: void get_input_row (decompress_info_ptr cinfo, char* pixel_row,int cur_col)
// Purpose : Read one row of pixels. This version is used for noninterlaced GIF
// images: we read directly from the GIF file.
// Parameter :
// Return : none
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
void get_input_row (decompress_info_ptr cinfo, char* pixel_row,int cur_col)
{
register JSAMPROW ptr0;
register long col;
register int c;
ptr0 = pixel_row + cur_col * 3 * cinfo->image_width;
for (col = 0; col < *width; col++)
{
if(*zoomflag == TRUE)
{
if(!half_find(width_record,(int) (cinfo->image_width -1),col))
{
c = LZWReadByte(cinfo);
}
else
{
c = LZWReadByte(cinfo);
*ptr0++ = colormap[3*c +CM_BLUE];
*ptr0++ = colormap[3*c +CM_GREEN];
*ptr0++ = colormap[3*c +CM_RED];
}
}
else
{
c = LZWReadByte(cinfo);
*ptr0++ = colormap[3*c +CM_BLUE];
*ptr0++ = colormap[3*c +CM_GREEN];
*ptr0++ = colormap[3*c +CM_RED];
}
}
}
//====================================================================================
// Function Name: void load_interlaced_image (decompress_info_ptr cinfo, char* pixel_row)
// Purpose : Read one row of pixels. This version is used for the first call on
// get_input_row when reading an interlaced GIF file: we read the whole
// image into memory.
// Parameter :
// Return : none
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
void load_interlaced_image (decompress_info_ptr cinfo, char* pixel_row)
{
uchar* image_ptr;
register int col;
int row;
int index;
long irow;
uchar data;
int count;
int record[MAXPELHEIGHT];
*cur_row_number = 0;
*pass2_offset = (*height + 7L) / 8L;
*pass3_offset = *pass2_offset + (*height + 3L) / 8L;
*pass4_offset = *pass3_offset + (*height + 1L) / 4L;
memset(record, 0, sizeof(record));
for(;*cur_row_number < *height;)
{
switch ((int) (*cur_row_number & 7L))
{
case 0: /* first-pass row */
irow = *cur_row_number >> 3;
break;
case 4: /* second-pass row */
irow = (*cur_row_number >> 3) + *pass2_offset;
break;
case 2: /* third-pass row */
case 6:
irow = (*cur_row_number >> 2) + *pass3_offset;
break;
default: /* fourth-pass row */
irow = (*cur_row_number >> 1) + *pass4_offset;
break;
}
record[*cur_row_number] = irow;
(*cur_row_number)++;
}
//now get all the information to image buffer//
count = 0;
if(*zoomflag == TRUE)
{
for (row = 0; row < *height; row++)
{
for(index = 0; index < *height; index++)
{
if(row == record[index])
{
break;
}
}
if(half_find(height_record, (cinfo->image_height -1 ),index))
{
*cur_row_number = get_real_height_index((int) (cinfo->image_height -1),index,height_record);
image_ptr = (uchar*) (pixel_row + *cur_row_number * 3 * cinfo->image_width);
count = 0;
for (col = 0; col <*width; col++)
{
if(half_find(width_record, (cinfo->image_width-1),col))
{
count++;
data = (JSAMPLE) LZWReadByte(cinfo);
*image_ptr++ = colormap[3*data + CM_BLUE];
*image_ptr++ = colormap[3*data + CM_GREEN];
*image_ptr++ = colormap[3*data + CM_RED];
}
else
{
data = LZWReadByte(cinfo);
}
}//end for
}
else
{
for (col = 0; col <*width; col++)
{
LZWReadByte(cinfo);
}
}//end if
}//end for
}//end if
else
{
for (row = 0; row < *height; row++)
{
for(index = 0; index < *height; index++)
{
if(row == record[index])
{
break;
}
}
image_ptr = (uchar*) (pixel_row + index * 3 * cinfo->image_width);
for (col = *width ; col > 0; col--)
{
index = (JSAMPLE) LZWReadByte(cinfo);
*image_ptr++ = colormap[3*index + CM_BLUE];
*image_ptr++ = colormap[3*index + CM_GREEN];
*image_ptr++ = colormap[3*index + CM_RED];
}
}
}//end else
}
//====================================================================================
// Function Name: Bool input_init (GIFParameter *ucGifParameter)
// Purpose : Read the file header; return image size and component count.
// Parameter :
// Return : none
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
Bool input_init (GIFParameter *ucGifParameter)
{
char hdrbuf[10]; /* workspace for reading control blocks */
/* image dimensions */
int colormaplen, aspectRatio;
int c,playback,PictureCount = 0;
uint ZoomSize;
uchar colorResolution;
uchar CommentCount;
#ifdef FLOAT_SURPORT
float scale;
#else
int scale_width,scale_height;
#endif
CommentCount = 0;
*BgIndex = -1;
/* Read and verify GIF Header */
if( !readFromBuffer( 6 ,hdrbuf))
{
#ifdef PCVER
WriteToErrorFile("input_init",ERROR_NOT_GIF_FILE,FileError);
#endif
InsertError(ERROR_NOT_GIF_FILE);
return FALSE;
}
if (hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F')
{
#ifdef PCVER
WriteToErrorFile("input_init",ERROR_NOT_GIF_FILE,FileError);
#endif
InsertError(ERROR_NOT_GIF_FILE);
return FALSE;
}
/* Check for expected version numbers.
* If unknown version, give warning and try to process anyway;
* this is per recommendation in GIF89a standard.
*/
if ((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') &&
(hdrbuf[3] != '8' || hdrbuf[4] != '9' || hdrbuf[5] != 'a'))
{
InsertError(ERROR_VERSION_ERROR);
return FALSE;
}
if(hdrbuf[4] =='7')
{
ucGifParameter->uReInfor->ucVersion = VERSION87;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -