added giflib sources
This commit is contained in:
		
							
								
								
									
										1198
									
								
								src/ext/gif/dgif_lib.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1198
									
								
								src/ext/gif/dgif_lib.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1159
									
								
								src/ext/gif/egif_lib.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1159
									
								
								src/ext/gif/egif_lib.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										97
									
								
								src/ext/gif/gif_err.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/ext/gif/gif_err.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 | 
			
		||||
gif_err.c - handle error reporting for the GIF library.
 | 
			
		||||
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "gif_lib.h"
 | 
			
		||||
#include "gif_lib_private.h"
 | 
			
		||||
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 Return a string description of  the last GIF error
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
const char *
 | 
			
		||||
GifErrorString(int ErrorCode)
 | 
			
		||||
{
 | 
			
		||||
    const char *Err;
 | 
			
		||||
 | 
			
		||||
    switch (ErrorCode) {
 | 
			
		||||
      case E_GIF_ERR_OPEN_FAILED:
 | 
			
		||||
        Err = "Failed to open given file";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_WRITE_FAILED:
 | 
			
		||||
        Err = "Failed to write to given file";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_HAS_SCRN_DSCR:
 | 
			
		||||
        Err = "Screen descriptor has already been set";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_HAS_IMAG_DSCR:
 | 
			
		||||
        Err = "Image descriptor is still active";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_NO_COLOR_MAP:
 | 
			
		||||
        Err = "Neither global nor local color map";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_DATA_TOO_BIG:
 | 
			
		||||
        Err = "Number of pixels bigger than width * height";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_NOT_ENOUGH_MEM:
 | 
			
		||||
        Err = "Failed to allocate required memory";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_DISK_IS_FULL:
 | 
			
		||||
        Err = "Write failed (disk full?)";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_CLOSE_FAILED:
 | 
			
		||||
        Err = "Failed to close given file";
 | 
			
		||||
        break;
 | 
			
		||||
      case E_GIF_ERR_NOT_WRITEABLE:
 | 
			
		||||
        Err = "Given file was not opened for write";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_OPEN_FAILED:
 | 
			
		||||
        Err = "Failed to open given file";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_READ_FAILED:
 | 
			
		||||
        Err = "Failed to read from given file";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_NOT_GIF_FILE:
 | 
			
		||||
        Err = "Data is not in GIF format";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_NO_SCRN_DSCR:
 | 
			
		||||
        Err = "No screen descriptor detected";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_NO_IMAG_DSCR:
 | 
			
		||||
        Err = "No Image Descriptor detected";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_NO_COLOR_MAP:
 | 
			
		||||
        Err = "Neither global nor local color map";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_WRONG_RECORD:
 | 
			
		||||
        Err = "Wrong record type detected";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_DATA_TOO_BIG:
 | 
			
		||||
        Err = "Number of pixels bigger than width * height";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_NOT_ENOUGH_MEM:
 | 
			
		||||
        Err = "Failed to allocate required memory";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_CLOSE_FAILED:
 | 
			
		||||
        Err = "Failed to close given file";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_NOT_READABLE:
 | 
			
		||||
        Err = "Given file was not opened for read";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_IMAGE_DEFECT:
 | 
			
		||||
        Err = "Image is defective, decoding aborted";
 | 
			
		||||
        break;
 | 
			
		||||
      case D_GIF_ERR_EOF_TOO_SOON:
 | 
			
		||||
        Err = "Image EOF detected before image complete";
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        Err = NULL;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return Err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* end */
 | 
			
		||||
							
								
								
									
										259
									
								
								src/ext/gif/gif_font.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								src/ext/gif/gif_font.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,259 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 
 | 
			
		||||
gif_font.c - utility font handling and simple drawing for the GIF library
 | 
			
		||||
 
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "gif_lib.h"
 | 
			
		||||
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 Ascii 8 by 8 regular font - only first 128 characters are supported.
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Each array entry holds the bits for 8 horizontal scan lines, topmost
 | 
			
		||||
 * first.  The most significant bit of each constant is the leftmost bit of
 | 
			
		||||
 * the scan line.
 | 
			
		||||
 */
 | 
			
		||||
/*@+charint@*/
 | 
			
		||||
const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH] = {
 | 
			
		||||
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* Ascii 0 */
 | 
			
		||||
    {0x3c, 0x42, 0xa5, 0x81, 0xbd, 0x42, 0x3c, 0x00},    /* Ascii 1 */
 | 
			
		||||
    {0x3c, 0x7e, 0xdb, 0xff, 0xc3, 0x7e, 0x3c, 0x00},    /* Ascii 2 */
 | 
			
		||||
    {0x00, 0xee, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00},    /* Ascii 3 */
 | 
			
		||||
    {0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00},    /* Ascii 4 */
 | 
			
		||||
    {0x00, 0x3c, 0x18, 0xff, 0xff, 0x08, 0x18, 0x00},    /* Ascii 5 */
 | 
			
		||||
    {0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x10, 0x38, 0x00},    /* Ascii 6 */
 | 
			
		||||
    {0x00, 0x00, 0x18, 0x3c, 0x18, 0x00, 0x00, 0x00},    /* Ascii 7 */
 | 
			
		||||
    {0xff, 0xff, 0xe7, 0xc3, 0xe7, 0xff, 0xff, 0xff},    /* Ascii 8 */
 | 
			
		||||
    {0x00, 0x3c, 0x42, 0x81, 0x81, 0x42, 0x3c, 0x00},    /* Ascii 9 */
 | 
			
		||||
    {0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0xbd, 0xc3, 0xff},    /* Ascii 10 */
 | 
			
		||||
    {0x1f, 0x07, 0x0d, 0x7c, 0xc6, 0xc6, 0x7c, 0x00},    /* Ascii 11 */
 | 
			
		||||
    {0x00, 0x7e, 0xc3, 0xc3, 0x7e, 0x18, 0x7e, 0x18},    /* Ascii 12 */
 | 
			
		||||
    {0x04, 0x06, 0x07, 0x04, 0x04, 0xfc, 0xf8, 0x00},    /* Ascii 13 */
 | 
			
		||||
    {0x0c, 0x0a, 0x0d, 0x0b, 0xf9, 0xf9, 0x1f, 0x1f},    /* Ascii 14 */
 | 
			
		||||
    {0x00, 0x92, 0x7c, 0x44, 0xc6, 0x7c, 0x92, 0x00},    /* Ascii 15 */
 | 
			
		||||
    {0x00, 0x00, 0x60, 0x78, 0x7e, 0x78, 0x60, 0x00},    /* Ascii 16 */
 | 
			
		||||
    {0x00, 0x00, 0x06, 0x1e, 0x7e, 0x1e, 0x06, 0x00},    /* Ascii 17 */
 | 
			
		||||
    {0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18},    /* Ascii 18 */
 | 
			
		||||
    {0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00},    /* Ascii 19 */
 | 
			
		||||
    {0xff, 0xb6, 0x76, 0x36, 0x36, 0x36, 0x36, 0x00},    /* Ascii 20 */
 | 
			
		||||
    {0x7e, 0xc1, 0xdc, 0x22, 0x22, 0x1f, 0x83, 0x7e},    /* Ascii 21 */
 | 
			
		||||
    {0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00},    /* Ascii 22 */
 | 
			
		||||
    {0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x00, 0xff},    /* Ascii 23 */
 | 
			
		||||
    {0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00},    /* Ascii 24 */
 | 
			
		||||
    {0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x00},    /* Ascii 25 */
 | 
			
		||||
    {0x00, 0x04, 0x06, 0xff, 0x06, 0x04, 0x00, 0x00},    /* Ascii 26 */
 | 
			
		||||
    {0x00, 0x20, 0x60, 0xff, 0x60, 0x20, 0x00, 0x00},    /* Ascii 27 */
 | 
			
		||||
    {0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0x00},    /* Ascii 28 */
 | 
			
		||||
    {0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00},    /* Ascii 29 */
 | 
			
		||||
    {0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x00, 0x00},    /* Ascii 30 */
 | 
			
		||||
    {0x00, 0x00, 0x00, 0xfe, 0x7c, 0x38, 0x10, 0x00},    /* Ascii 31 */
 | 
			
		||||
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* */
 | 
			
		||||
    {0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x00},    /* ! */
 | 
			
		||||
    {0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* " */
 | 
			
		||||
    {0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00},    /* # */
 | 
			
		||||
    {0x10, 0x7c, 0xd2, 0x7c, 0x86, 0x7c, 0x10, 0x00},    /* $ */
 | 
			
		||||
    {0xf0, 0x96, 0xfc, 0x18, 0x3e, 0x72, 0xde, 0x00},    /* % */
 | 
			
		||||
    {0x30, 0x48, 0x30, 0x78, 0xce, 0xcc, 0x78, 0x00},    /* & */
 | 
			
		||||
    {0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},    /* ' */
 | 
			
		||||
    {0x10, 0x60, 0xc0, 0xc0, 0xc0, 0x60, 0x10, 0x00},    /* ( */
 | 
			
		||||
    {0x10, 0x0c, 0x06, 0x06, 0x06, 0x0c, 0x10, 0x00},    /* ) */
 | 
			
		||||
    {0x00, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x00, 0x00},    /* * */
 | 
			
		||||
    {0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00},    /* + */
 | 
			
		||||
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x70},    /* , */
 | 
			
		||||
    {0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00},    /* - */
 | 
			
		||||
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00},    /* . */
 | 
			
		||||
    {0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00},    /* / */
 | 
			
		||||
    {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00},    /* 0 */
 | 
			
		||||
    {0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00},    /* 1 */
 | 
			
		||||
    {0x7c, 0xc6, 0x06, 0x0c, 0x30, 0x60, 0xfe, 0x00},    /* 2 */
 | 
			
		||||
    {0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00},    /* 3 */
 | 
			
		||||
    {0x0e, 0x1e, 0x36, 0x66, 0xfe, 0x06, 0x06, 0x00},    /* 4 */
 | 
			
		||||
    {0xfe, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xfc, 0x00},    /* 5 */
 | 
			
		||||
    {0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00},    /* 6 */
 | 
			
		||||
    {0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x60, 0x00},    /* 7 */
 | 
			
		||||
    {0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00},    /* 8 */
 | 
			
		||||
    {0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00},    /* 9 */
 | 
			
		||||
    {0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00},    /* : */
 | 
			
		||||
    {0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x20, 0x00},    /* }, */
 | 
			
		||||
    {0x00, 0x1c, 0x30, 0x60, 0x30, 0x1c, 0x00, 0x00},    /* < */
 | 
			
		||||
    {0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00},    /* = */
 | 
			
		||||
    {0x00, 0x70, 0x18, 0x0c, 0x18, 0x70, 0x00, 0x00},    /* > */
 | 
			
		||||
    {0x7c, 0xc6, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00},    /* ? */
 | 
			
		||||
    {0x7c, 0x82, 0x9a, 0xaa, 0xaa, 0x9e, 0x7c, 0x00},    /* @ */
 | 
			
		||||
    {0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00},    /* A */
 | 
			
		||||
    {0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x00},    /* B */
 | 
			
		||||
    {0x7c, 0xc6, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00},    /* C */
 | 
			
		||||
    {0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00},    /* D */
 | 
			
		||||
    {0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xfe, 0x00},    /* E */
 | 
			
		||||
    {0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0x00},    /* F */
 | 
			
		||||
    {0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7e, 0x00},    /* G */
 | 
			
		||||
    {0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00},    /* H */
 | 
			
		||||
    {0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00},    /* I */
 | 
			
		||||
    {0x1e, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00},    /* J */
 | 
			
		||||
    {0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0x00},    /* K */
 | 
			
		||||
    {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00},    /* L */
 | 
			
		||||
    {0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00},    /* M */
 | 
			
		||||
    {0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00},    /* N */
 | 
			
		||||
    {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00},    /* O */
 | 
			
		||||
    {0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x00},    /* P */
 | 
			
		||||
    {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x06},    /* Q */
 | 
			
		||||
    {0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0x00},    /* R */
 | 
			
		||||
    {0x78, 0xcc, 0x60, 0x30, 0x18, 0xcc, 0x78, 0x00},    /* S */
 | 
			
		||||
    {0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00},    /* T */
 | 
			
		||||
    {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00},    /* U */
 | 
			
		||||
    {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00},    /* V */
 | 
			
		||||
    {0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00},    /* W */
 | 
			
		||||
    {0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x00},    /* X */
 | 
			
		||||
    {0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00},    /* Y */
 | 
			
		||||
    {0xfe, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00},    /* Z */
 | 
			
		||||
    {0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00},    /* [ */
 | 
			
		||||
    {0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x00},    /* \ */
 | 
			
		||||
    {0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00},    /* ] */
 | 
			
		||||
    {0x00, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},    /* ^ */
 | 
			
		||||
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff},    /* _ */
 | 
			
		||||
    {0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},    /* ` */
 | 
			
		||||
    {0x00, 0x00, 0x7c, 0x06, 0x7e, 0xc6, 0x7e, 0x00},    /* a */
 | 
			
		||||
    {0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0x00},    /* b */
 | 
			
		||||
    {0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0x7e, 0x00},    /* c */
 | 
			
		||||
    {0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x00},    /* d */
 | 
			
		||||
    {0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7e, 0x00},    /* e */
 | 
			
		||||
    {0x1e, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x30, 0x00},    /* f */
 | 
			
		||||
    {0x00, 0x00, 0x7e, 0xc6, 0xce, 0x76, 0x06, 0x7c},    /* g */
 | 
			
		||||
    {0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00},    /* */
 | 
			
		||||
    {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00},    /* i */
 | 
			
		||||
    {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0xf0},    /* j */
 | 
			
		||||
    {0xc0, 0xc0, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0x00},    /* k */
 | 
			
		||||
    {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00},    /* l */
 | 
			
		||||
    {0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xc6, 0xc6, 0x00},    /* m */
 | 
			
		||||
    {0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00},    /* n */
 | 
			
		||||
    {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00},    /* o */
 | 
			
		||||
    {0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0xc0},    /* p */
 | 
			
		||||
    {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x06},    /* q */
 | 
			
		||||
    {0x00, 0x00, 0x6e, 0x70, 0x60, 0x60, 0x60, 0x00},    /* r */
 | 
			
		||||
    {0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x00},    /* s */
 | 
			
		||||
    {0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00},    /* t */
 | 
			
		||||
    {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00},    /* u */
 | 
			
		||||
    {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00},    /* v */
 | 
			
		||||
    {0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x00},    /* w */
 | 
			
		||||
    {0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00},    /* x */
 | 
			
		||||
    {0x00, 0x00, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x7c},    /* y */
 | 
			
		||||
    {0x00, 0x00, 0xfc, 0x18, 0x30, 0x60, 0xfc, 0x00},    /* z */
 | 
			
		||||
    {0x0e, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0e, 0x00},    /* { */
 | 
			
		||||
    {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},    /* | */
 | 
			
		||||
    {0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00},    /* } */
 | 
			
		||||
    {0x00, 0x00, 0x70, 0x9a, 0x0e, 0x00, 0x00, 0x00},    /* ~ */
 | 
			
		||||
    {0x00, 0x00, 0x18, 0x3c, 0x66, 0xff, 0x00, 0x00}    /* Ascii 127 */
 | 
			
		||||
};
 | 
			
		||||
/*@=charint@*/
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
GifDrawText8x8(SavedImage *Image, 
 | 
			
		||||
	    const int x, const int y,
 | 
			
		||||
	    const char *legend,
 | 
			
		||||
	    const int color)
 | 
			
		||||
{
 | 
			
		||||
    int i, j;
 | 
			
		||||
    int base;
 | 
			
		||||
    const char *cp;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < GIF_FONT_HEIGHT; i++) {
 | 
			
		||||
        base = Image->ImageDesc.Width * (y + i) + x;
 | 
			
		||||
 | 
			
		||||
        for (cp = legend; *cp; cp++)
 | 
			
		||||
            for (j = 0; j < GIF_FONT_WIDTH; j++) {
 | 
			
		||||
                if (GifAsciiTable8x8[(short)(*cp)][i] & (1 << (GIF_FONT_WIDTH - j)))
 | 
			
		||||
                    Image->RasterBits[base] = color;
 | 
			
		||||
                base++;
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
GifDrawBox(SavedImage *Image,
 | 
			
		||||
	   const int x, const int y,
 | 
			
		||||
	   const int w, const int d,
 | 
			
		||||
	   const int color)
 | 
			
		||||
{
 | 
			
		||||
    int j, base = Image->ImageDesc.Width * y + x;
 | 
			
		||||
 | 
			
		||||
    for (j = 0; j < w; j++)
 | 
			
		||||
        Image->RasterBits[base + j] =
 | 
			
		||||
            Image->RasterBits[base + (d * Image->ImageDesc.Width) + j] = color;
 | 
			
		||||
 | 
			
		||||
    for (j = 0; j < d; j++)
 | 
			
		||||
        Image->RasterBits[base + j * Image->ImageDesc.Width] =
 | 
			
		||||
            Image->RasterBits[base + j * Image->ImageDesc.Width + w] = color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
GifDrawRectangle(SavedImage *Image,
 | 
			
		||||
              const int x, const int y,
 | 
			
		||||
              const int w, const int d,
 | 
			
		||||
              const int color)
 | 
			
		||||
{
 | 
			
		||||
    unsigned char *bp = Image->RasterBits + Image->ImageDesc.Width * y + x;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < d; i++)
 | 
			
		||||
        memset(bp + (i * Image->ImageDesc.Width), color, (size_t)w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
GifDrawBoxedText8x8(SavedImage *Image,
 | 
			
		||||
              const int x, const int y,
 | 
			
		||||
              const char *legend,
 | 
			
		||||
              const int border,
 | 
			
		||||
              const int bg, const int fg)
 | 
			
		||||
{
 | 
			
		||||
    int j = 0, LineCount = 0, TextWidth = 0;
 | 
			
		||||
    const char *cp;
 | 
			
		||||
    char *dup;
 | 
			
		||||
 | 
			
		||||
    /* compute size of text to box */
 | 
			
		||||
    for (cp = legend; *cp; cp++)
 | 
			
		||||
        if (*cp == '\r') {
 | 
			
		||||
            if (j > TextWidth)
 | 
			
		||||
                TextWidth = j;
 | 
			
		||||
            j = 0;
 | 
			
		||||
            LineCount++;
 | 
			
		||||
        } else if (*cp != '\t')
 | 
			
		||||
            ++j;
 | 
			
		||||
    LineCount++;    /* count last line */
 | 
			
		||||
    if (j > TextWidth)    /* last line might be longer than any previous */
 | 
			
		||||
        TextWidth = j;
 | 
			
		||||
 | 
			
		||||
    /* draw the text */
 | 
			
		||||
    dup = malloc(strlen(legend)+1);
 | 
			
		||||
    /* FIXME: should return bad status, but that would require API change */
 | 
			
		||||
    if (dup != NULL) {
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	/* fill the box */
 | 
			
		||||
	GifDrawRectangle(Image, x + 1, y + 1,
 | 
			
		||||
		      border + TextWidth * GIF_FONT_WIDTH + border - 1,
 | 
			
		||||
		      border + LineCount * GIF_FONT_HEIGHT + border - 1, bg);
 | 
			
		||||
	(void)strcpy(dup, (char *)legend);
 | 
			
		||||
	cp = strtok((char *)dup, "\r\n");
 | 
			
		||||
	do {
 | 
			
		||||
	    int leadspace = 0;
 | 
			
		||||
 | 
			
		||||
	    if (cp[0] == '\t')
 | 
			
		||||
		leadspace = (TextWidth - strlen(++cp)) / 2;
 | 
			
		||||
 | 
			
		||||
	    GifDrawText8x8(Image, x + border + (leadspace * GIF_FONT_WIDTH),
 | 
			
		||||
			   y + border + (GIF_FONT_HEIGHT * i++), cp, fg);
 | 
			
		||||
	    cp = strtok((char *)NULL, "\r\n");
 | 
			
		||||
	} while (cp);
 | 
			
		||||
	(void)free((void *)dup);
 | 
			
		||||
 | 
			
		||||
	/* outline the box */
 | 
			
		||||
	GifDrawBox(Image, x, y, border + TextWidth * GIF_FONT_WIDTH + border,
 | 
			
		||||
		   border + LineCount * GIF_FONT_HEIGHT + border, fg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* end */
 | 
			
		||||
							
								
								
									
										131
									
								
								src/ext/gif/gif_hash.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								src/ext/gif/gif_hash.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 | 
			
		||||
gif_hash.c -- module to support the following operations:
 | 
			
		||||
 | 
			
		||||
1. InitHashTable - initialize hash table.
 | 
			
		||||
2. ClearHashTable - clear the hash table to an empty state.
 | 
			
		||||
2. InsertHashTable - insert one item into data structure.
 | 
			
		||||
3. ExistsHashTable - test if item exists in data structure.
 | 
			
		||||
 | 
			
		||||
This module is used to hash the GIF codes during encoding.
 | 
			
		||||
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "gif_lib.h"
 | 
			
		||||
#include "gif_hash.h"
 | 
			
		||||
#include "gif_lib_private.h"
 | 
			
		||||
 | 
			
		||||
/* #define  DEBUG_HIT_RATE    Debug number of misses per hash Insert/Exists. */
 | 
			
		||||
 | 
			
		||||
#ifdef	DEBUG_HIT_RATE
 | 
			
		||||
static long NumberOfTests = 0,
 | 
			
		||||
	    NumberOfMisses = 0;
 | 
			
		||||
#endif	/* DEBUG_HIT_RATE */
 | 
			
		||||
 | 
			
		||||
static int KeyItem(uint32_t Item);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Initialize HashTable - allocate the memory needed and clear it.	      *
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
GifHashTableType *_InitHashTable(void)
 | 
			
		||||
{
 | 
			
		||||
    GifHashTableType *HashTable;
 | 
			
		||||
 | 
			
		||||
    if ((HashTable = (GifHashTableType *) malloc(sizeof(GifHashTableType)))
 | 
			
		||||
	== NULL)
 | 
			
		||||
	return NULL;
 | 
			
		||||
 | 
			
		||||
    _ClearHashTable(HashTable);
 | 
			
		||||
 | 
			
		||||
    return HashTable;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Routine to clear the HashTable to an empty state.			      *
 | 
			
		||||
 This part is a little machine depended. Use the commented part otherwise.   *
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
void _ClearHashTable(GifHashTableType *HashTable)
 | 
			
		||||
{
 | 
			
		||||
    memset(HashTable -> HTable, 0xFF, HT_SIZE * sizeof(uint32_t));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Routine to insert a new Item into the HashTable. The data is assumed to be  *
 | 
			
		||||
 new one.								      *
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
void _InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code)
 | 
			
		||||
{
 | 
			
		||||
    int HKey = KeyItem(Key);
 | 
			
		||||
    uint32_t *HTable = HashTable -> HTable;
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_HIT_RATE
 | 
			
		||||
	NumberOfTests++;
 | 
			
		||||
	NumberOfMisses++;
 | 
			
		||||
#endif /* DEBUG_HIT_RATE */
 | 
			
		||||
 | 
			
		||||
    while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) {
 | 
			
		||||
#ifdef DEBUG_HIT_RATE
 | 
			
		||||
	    NumberOfMisses++;
 | 
			
		||||
#endif /* DEBUG_HIT_RATE */
 | 
			
		||||
	HKey = (HKey + 1) & HT_KEY_MASK;
 | 
			
		||||
    }
 | 
			
		||||
    HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Routine to test if given Key exists in HashTable and if so returns its code *
 | 
			
		||||
 Returns the Code if key was found, -1 if not.				      *
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
int _ExistsHashTable(GifHashTableType *HashTable, uint32_t Key)
 | 
			
		||||
{
 | 
			
		||||
    int HKey = KeyItem(Key);
 | 
			
		||||
    uint32_t *HTable = HashTable -> HTable, HTKey;
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_HIT_RATE
 | 
			
		||||
	NumberOfTests++;
 | 
			
		||||
	NumberOfMisses++;
 | 
			
		||||
#endif /* DEBUG_HIT_RATE */
 | 
			
		||||
 | 
			
		||||
    while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) {
 | 
			
		||||
#ifdef DEBUG_HIT_RATE
 | 
			
		||||
	    NumberOfMisses++;
 | 
			
		||||
#endif /* DEBUG_HIT_RATE */
 | 
			
		||||
	if (Key == HTKey) return HT_GET_CODE(HTable[HKey]);
 | 
			
		||||
	HKey = (HKey + 1) & HT_KEY_MASK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Routine to generate an HKey for the hashtable out of the given unique key.  *
 | 
			
		||||
 The given Key is assumed to be 20 bits as follows: lower 8 bits are the     *
 | 
			
		||||
 new postfix character, while the upper 12 bits are the prefix code.	      *
 | 
			
		||||
 Because the average hit ratio is only 2 (2 hash references per entry),      *
 | 
			
		||||
 evaluating more complex keys (such as twin prime keys) does not worth it!   *
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
static int KeyItem(uint32_t Item)
 | 
			
		||||
{
 | 
			
		||||
    return ((Item >> 12) ^ Item) & HT_KEY_MASK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef	DEBUG_HIT_RATE
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Debugging routine to print the hit ratio - number of times the hash table   *
 | 
			
		||||
 was tested per operation. This routine was used to test the KeyItem routine *
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
void HashTablePrintHitRatio(void)
 | 
			
		||||
{
 | 
			
		||||
    printf("Hash Table Hit Ratio is %ld/%ld = %ld%%.\n",
 | 
			
		||||
	NumberOfMisses, NumberOfTests,
 | 
			
		||||
	NumberOfMisses * 100 / NumberOfTests);
 | 
			
		||||
}
 | 
			
		||||
#endif	/* DEBUG_HIT_RATE */
 | 
			
		||||
 | 
			
		||||
/* end */
 | 
			
		||||
							
								
								
									
										39
									
								
								src/ext/gif/gif_hash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/ext/gif/gif_hash.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 | 
			
		||||
gif_hash.h - magfic constants and declarations for GIF LZW
 | 
			
		||||
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef _GIF_HASH_H_
 | 
			
		||||
#define _GIF_HASH_H_
 | 
			
		||||
 | 
			
		||||
//#include <unistd.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#define HT_SIZE			8192	   /* 12bits = 4096 or twice as big! */
 | 
			
		||||
#define HT_KEY_MASK		0x1FFF			      /* 13bits keys */
 | 
			
		||||
#define HT_KEY_NUM_BITS		13			      /* 13bits keys */
 | 
			
		||||
#define HT_MAX_KEY		8191	/* 13bits - 1, maximal code possible */
 | 
			
		||||
#define HT_MAX_CODE		4095	/* Biggest code possible in 12 bits. */
 | 
			
		||||
 | 
			
		||||
/* The 32 bits of the long are divided into two parts for the key & code:   */
 | 
			
		||||
/* 1. The code is 12 bits as our compression algorithm is limited to 12bits */
 | 
			
		||||
/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits.	    */
 | 
			
		||||
/* The key is the upper 20 bits.  The code is the lower 12. */
 | 
			
		||||
#define HT_GET_KEY(l)	(l >> 12)
 | 
			
		||||
#define HT_GET_CODE(l)	(l & 0x0FFF)
 | 
			
		||||
#define HT_PUT_KEY(l)	(l << 12)
 | 
			
		||||
#define HT_PUT_CODE(l)	(l & 0x0FFF)
 | 
			
		||||
 | 
			
		||||
typedef struct GifHashTableType {
 | 
			
		||||
    uint32_t HTable[HT_SIZE];
 | 
			
		||||
} GifHashTableType;
 | 
			
		||||
 | 
			
		||||
GifHashTableType *_InitHashTable(void);
 | 
			
		||||
void _ClearHashTable(GifHashTableType *HashTable);
 | 
			
		||||
void _InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code);
 | 
			
		||||
int _ExistsHashTable(GifHashTableType *HashTable, uint32_t Key);
 | 
			
		||||
 | 
			
		||||
#endif /* _GIF_HASH_H_ */
 | 
			
		||||
 | 
			
		||||
/* end */
 | 
			
		||||
							
								
								
									
										312
									
								
								src/ext/gif/gif_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								src/ext/gif/gif_lib.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,312 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 
 | 
			
		||||
gif_lib.h - service library for decoding and encoding GIF images
 | 
			
		||||
                                                                             
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef _GIF_LIB_H_
 | 
			
		||||
#define _GIF_LIB_H_ 1
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif /* __cplusplus */
 | 
			
		||||
 | 
			
		||||
#define GIFLIB_MAJOR 5
 | 
			
		||||
#define GIFLIB_MINOR 1
 | 
			
		||||
#define GIFLIB_RELEASE 4
 | 
			
		||||
 | 
			
		||||
#define GIF_ERROR   0
 | 
			
		||||
#define GIF_OK      1
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#define GIF_STAMP "GIFVER"          /* First chars in file - GIF stamp.  */
 | 
			
		||||
#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
 | 
			
		||||
#define GIF_VERSION_POS 3           /* Version first character in stamp. */
 | 
			
		||||
#define GIF87_STAMP "GIF87a"        /* First chars in file - GIF stamp.  */
 | 
			
		||||
#define GIF89_STAMP "GIF89a"        /* First chars in file - GIF stamp.  */
 | 
			
		||||
 | 
			
		||||
typedef unsigned char GifPixelType;
 | 
			
		||||
typedef unsigned char *GifRowType;
 | 
			
		||||
typedef unsigned char GifByteType;
 | 
			
		||||
typedef unsigned int GifPrefixType;
 | 
			
		||||
typedef int GifWord;
 | 
			
		||||
 | 
			
		||||
typedef struct GifColorType {
 | 
			
		||||
    GifByteType Red, Green, Blue;
 | 
			
		||||
} GifColorType;
 | 
			
		||||
 | 
			
		||||
typedef struct ColorMapObject {
 | 
			
		||||
    int ColorCount;
 | 
			
		||||
    int BitsPerPixel;
 | 
			
		||||
    bool SortFlag;
 | 
			
		||||
    GifColorType *Colors;    /* on malloc(3) heap */
 | 
			
		||||
} ColorMapObject;
 | 
			
		||||
 | 
			
		||||
typedef struct GifImageDesc {
 | 
			
		||||
    GifWord Left, Top, Width, Height;   /* Current image dimensions. */
 | 
			
		||||
    bool Interlace;                     /* Sequential/Interlaced lines. */
 | 
			
		||||
    ColorMapObject *ColorMap;           /* The local color map */
 | 
			
		||||
} GifImageDesc;
 | 
			
		||||
 | 
			
		||||
typedef struct ExtensionBlock {
 | 
			
		||||
    int ByteCount;
 | 
			
		||||
    GifByteType *Bytes; /* on malloc(3) heap */
 | 
			
		||||
    int Function;       /* The block function code */
 | 
			
		||||
#define CONTINUE_EXT_FUNC_CODE    0x00    /* continuation subblock */
 | 
			
		||||
#define COMMENT_EXT_FUNC_CODE     0xfe    /* comment */
 | 
			
		||||
#define GRAPHICS_EXT_FUNC_CODE    0xf9    /* graphics control (GIF89) */
 | 
			
		||||
#define PLAINTEXT_EXT_FUNC_CODE   0x01    /* plaintext */
 | 
			
		||||
#define APPLICATION_EXT_FUNC_CODE 0xff    /* application block */
 | 
			
		||||
} ExtensionBlock;
 | 
			
		||||
 | 
			
		||||
typedef struct SavedImage {
 | 
			
		||||
    GifImageDesc ImageDesc;
 | 
			
		||||
    GifByteType *RasterBits;         /* on malloc(3) heap */
 | 
			
		||||
    int ExtensionBlockCount;         /* Count of extensions before image */    
 | 
			
		||||
    ExtensionBlock *ExtensionBlocks; /* Extensions before image */    
 | 
			
		||||
} SavedImage;
 | 
			
		||||
 | 
			
		||||
typedef struct GifFileType {
 | 
			
		||||
    GifWord SWidth, SHeight;         /* Size of virtual canvas */
 | 
			
		||||
    GifWord SColorResolution;        /* How many colors can we generate? */
 | 
			
		||||
    GifWord SBackGroundColor;        /* Background color for virtual canvas */
 | 
			
		||||
    GifByteType AspectByte;	     /* Used to compute pixel aspect ratio */
 | 
			
		||||
    ColorMapObject *SColorMap;       /* Global colormap, NULL if nonexistent. */
 | 
			
		||||
    int ImageCount;                  /* Number of current image (both APIs) */
 | 
			
		||||
    GifImageDesc Image;              /* Current image (low-level API) */
 | 
			
		||||
    SavedImage *SavedImages;         /* Image sequence (high-level API) */
 | 
			
		||||
    int ExtensionBlockCount;         /* Count extensions past last image */
 | 
			
		||||
    ExtensionBlock *ExtensionBlocks; /* Extensions past last image */    
 | 
			
		||||
    int Error;			     /* Last error condition reported */
 | 
			
		||||
    void *UserData;                  /* hook to attach user data (TVT) */
 | 
			
		||||
    void *Private;                   /* Don't mess with this! */
 | 
			
		||||
} GifFileType;
 | 
			
		||||
 | 
			
		||||
#define GIF_ASPECT_RATIO(n)	((n)+15.0/64.0)
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    UNDEFINED_RECORD_TYPE,
 | 
			
		||||
    SCREEN_DESC_RECORD_TYPE,
 | 
			
		||||
    IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */
 | 
			
		||||
    EXTENSION_RECORD_TYPE,  /* Begin with '!' */
 | 
			
		||||
    TERMINATE_RECORD_TYPE   /* Begin with ';' */
 | 
			
		||||
} GifRecordType;
 | 
			
		||||
 | 
			
		||||
/* func type to read gif data from arbitrary sources (TVT) */
 | 
			
		||||
typedef int (*InputFunc) (GifFileType *, GifByteType *, int);
 | 
			
		||||
 | 
			
		||||
/* func type to write gif data to arbitrary targets.
 | 
			
		||||
 * Returns count of bytes written. (MRB)
 | 
			
		||||
 */
 | 
			
		||||
typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 GIF89 structures
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
typedef struct GraphicsControlBlock {
 | 
			
		||||
    int DisposalMode;
 | 
			
		||||
#define DISPOSAL_UNSPECIFIED      0       /* No disposal specified. */
 | 
			
		||||
#define DISPOSE_DO_NOT            1       /* Leave image in place */
 | 
			
		||||
#define DISPOSE_BACKGROUND        2       /* Set area too background color */
 | 
			
		||||
#define DISPOSE_PREVIOUS          3       /* Restore to previous content */
 | 
			
		||||
    bool UserInputFlag;      /* User confirmation required before disposal */
 | 
			
		||||
    int DelayTime;           /* pre-display delay in 0.01sec units */
 | 
			
		||||
    int TransparentColor;    /* Palette index for transparency, -1 if none */
 | 
			
		||||
#define NO_TRANSPARENT_COLOR	-1
 | 
			
		||||
} GraphicsControlBlock;
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 GIF encoding routines
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* Main entry points */
 | 
			
		||||
GifFileType *EGifOpenFileName(const char *GifFileName,
 | 
			
		||||
                              const bool GifTestExistence, int *Error);
 | 
			
		||||
GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error);
 | 
			
		||||
GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error);
 | 
			
		||||
int EGifSpew(GifFileType * GifFile);
 | 
			
		||||
const char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */
 | 
			
		||||
int EGifCloseFile(GifFileType *GifFile, int *ErrorCode);
 | 
			
		||||
 | 
			
		||||
#define E_GIF_SUCCEEDED          0
 | 
			
		||||
#define E_GIF_ERR_OPEN_FAILED    1    /* And EGif possible errors. */
 | 
			
		||||
#define E_GIF_ERR_WRITE_FAILED   2
 | 
			
		||||
#define E_GIF_ERR_HAS_SCRN_DSCR  3
 | 
			
		||||
#define E_GIF_ERR_HAS_IMAG_DSCR  4
 | 
			
		||||
#define E_GIF_ERR_NO_COLOR_MAP   5
 | 
			
		||||
#define E_GIF_ERR_DATA_TOO_BIG   6
 | 
			
		||||
#define E_GIF_ERR_NOT_ENOUGH_MEM 7
 | 
			
		||||
#define E_GIF_ERR_DISK_IS_FULL   8
 | 
			
		||||
#define E_GIF_ERR_CLOSE_FAILED   9
 | 
			
		||||
#define E_GIF_ERR_NOT_WRITEABLE  10
 | 
			
		||||
 | 
			
		||||
/* These are legacy.  You probably do not want to call them directly */
 | 
			
		||||
int EGifPutScreenDesc(GifFileType *GifFile,
 | 
			
		||||
                      const int GifWidth, const int GifHeight, 
 | 
			
		||||
		      const int GifColorRes,
 | 
			
		||||
                      const int GifBackGround,
 | 
			
		||||
                      const ColorMapObject *GifColorMap);
 | 
			
		||||
int EGifPutImageDesc(GifFileType *GifFile, 
 | 
			
		||||
		     const int GifLeft, const int GifTop,
 | 
			
		||||
                     const int GifWidth, const int GifHeight, 
 | 
			
		||||
		     const bool GifInterlace,
 | 
			
		||||
                     const ColorMapObject *GifColorMap);
 | 
			
		||||
void EGifSetGifVersion(GifFileType *GifFile, const bool gif89);
 | 
			
		||||
int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine,
 | 
			
		||||
                int GifLineLen);
 | 
			
		||||
int EGifPutPixel(GifFileType *GifFile, const GifPixelType GifPixel);
 | 
			
		||||
int EGifPutComment(GifFileType *GifFile, const char *GifComment);
 | 
			
		||||
int EGifPutExtensionLeader(GifFileType *GifFile, const int GifExtCode);
 | 
			
		||||
int EGifPutExtensionBlock(GifFileType *GifFile,
 | 
			
		||||
                         const int GifExtLen, const void *GifExtension);
 | 
			
		||||
int EGifPutExtensionTrailer(GifFileType *GifFile);
 | 
			
		||||
int EGifPutExtension(GifFileType *GifFile, const int GifExtCode, 
 | 
			
		||||
		     const int GifExtLen,
 | 
			
		||||
                     const void *GifExtension);
 | 
			
		||||
int EGifPutCode(GifFileType *GifFile, int GifCodeSize,
 | 
			
		||||
                const GifByteType *GifCodeBlock);
 | 
			
		||||
int EGifPutCodeNext(GifFileType *GifFile,
 | 
			
		||||
                    const GifByteType *GifCodeBlock);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 GIF decoding routines
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* Main entry points */
 | 
			
		||||
GifFileType *DGifOpenFileName(const char *GifFileName, int *Error);
 | 
			
		||||
GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error);
 | 
			
		||||
int DGifSlurp(GifFileType * GifFile);
 | 
			
		||||
GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error);    /* new one (TVT) */
 | 
			
		||||
    int DGifCloseFile(GifFileType * GifFile, int *ErrorCode);
 | 
			
		||||
 | 
			
		||||
#define D_GIF_SUCCEEDED          0
 | 
			
		||||
#define D_GIF_ERR_OPEN_FAILED    101    /* And DGif possible errors. */
 | 
			
		||||
#define D_GIF_ERR_READ_FAILED    102
 | 
			
		||||
#define D_GIF_ERR_NOT_GIF_FILE   103
 | 
			
		||||
#define D_GIF_ERR_NO_SCRN_DSCR   104
 | 
			
		||||
#define D_GIF_ERR_NO_IMAG_DSCR   105
 | 
			
		||||
#define D_GIF_ERR_NO_COLOR_MAP   106
 | 
			
		||||
#define D_GIF_ERR_WRONG_RECORD   107
 | 
			
		||||
#define D_GIF_ERR_DATA_TOO_BIG   108
 | 
			
		||||
#define D_GIF_ERR_NOT_ENOUGH_MEM 109
 | 
			
		||||
#define D_GIF_ERR_CLOSE_FAILED   110
 | 
			
		||||
#define D_GIF_ERR_NOT_READABLE   111
 | 
			
		||||
#define D_GIF_ERR_IMAGE_DEFECT   112
 | 
			
		||||
#define D_GIF_ERR_EOF_TOO_SOON   113
 | 
			
		||||
 | 
			
		||||
/* These are legacy.  You probably do not want to call them directly */
 | 
			
		||||
int DGifGetScreenDesc(GifFileType *GifFile);
 | 
			
		||||
int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType);
 | 
			
		||||
int DGifGetImageDesc(GifFileType *GifFile);
 | 
			
		||||
int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen);
 | 
			
		||||
int DGifGetPixel(GifFileType *GifFile, GifPixelType GifPixel);
 | 
			
		||||
int DGifGetComment(GifFileType *GifFile, char *GifComment);
 | 
			
		||||
int DGifGetExtension(GifFileType *GifFile, int *GifExtCode,
 | 
			
		||||
                     GifByteType **GifExtension);
 | 
			
		||||
int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension);
 | 
			
		||||
int DGifGetCode(GifFileType *GifFile, int *GifCodeSize,
 | 
			
		||||
                GifByteType **GifCodeBlock);
 | 
			
		||||
int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock);
 | 
			
		||||
int DGifGetLZCodes(GifFileType *GifFile, int *GifCode);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Color table quantization (deprecated)
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
int GifQuantizeBuffer(unsigned int Width, unsigned int Height,
 | 
			
		||||
                   int *ColorMapSize, GifByteType * RedInput,
 | 
			
		||||
                   GifByteType * GreenInput, GifByteType * BlueInput,
 | 
			
		||||
                   GifByteType * OutputBuffer,
 | 
			
		||||
                   GifColorType * OutputColorMap);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Error handling and reporting.
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
extern const char *GifErrorString(int ErrorCode);     /* new in 2012 - ESR */
 | 
			
		||||
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 Everything below this point is new after version 1.2, supporting `slurp
 | 
			
		||||
 mode' for doing I/O in two big belts with all the image-bashing in core.
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Color map handling from gif_alloc.c
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
extern ColorMapObject *GifMakeMapObject(int ColorCount,
 | 
			
		||||
                                     const GifColorType *ColorMap);
 | 
			
		||||
extern void GifFreeMapObject(ColorMapObject *Object);
 | 
			
		||||
extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1,
 | 
			
		||||
                                     const ColorMapObject *ColorIn2,
 | 
			
		||||
                                     GifPixelType ColorTransIn2[]);
 | 
			
		||||
extern int GifBitSize(int n);
 | 
			
		||||
 | 
			
		||||
extern void *
 | 
			
		||||
reallocarray(void *optr, size_t nmemb, size_t size);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Support for the in-core structures allocation (slurp mode).              
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
extern void GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]);
 | 
			
		||||
extern int GifAddExtensionBlock(int *ExtensionBlock_Count,
 | 
			
		||||
				ExtensionBlock **ExtensionBlocks, 
 | 
			
		||||
				int Function, 
 | 
			
		||||
				unsigned int Len, unsigned char ExtData[]);
 | 
			
		||||
extern void GifFreeExtensions(int *ExtensionBlock_Count,
 | 
			
		||||
			      ExtensionBlock **ExtensionBlocks);
 | 
			
		||||
extern SavedImage *GifMakeSavedImage(GifFileType *GifFile,
 | 
			
		||||
                                  const SavedImage *CopyFrom);
 | 
			
		||||
extern void GifFreeSavedImages(GifFileType *GifFile);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 5.x functions for GIF89 graphics control blocks
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
int DGifExtensionToGCB(const size_t GifExtensionLength,
 | 
			
		||||
		       const GifByteType *GifExtension,
 | 
			
		||||
		       GraphicsControlBlock *GCB);
 | 
			
		||||
size_t EGifGCBToExtension(const GraphicsControlBlock *GCB,
 | 
			
		||||
		       GifByteType *GifExtension);
 | 
			
		||||
 | 
			
		||||
int DGifSavedExtensionToGCB(GifFileType *GifFile, 
 | 
			
		||||
			    int ImageIndex, 
 | 
			
		||||
			    GraphicsControlBlock *GCB);
 | 
			
		||||
int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB, 
 | 
			
		||||
			    GifFileType *GifFile, 
 | 
			
		||||
			    int ImageIndex);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 The library's internal utility font                          
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#define GIF_FONT_WIDTH  8
 | 
			
		||||
#define GIF_FONT_HEIGHT 8
 | 
			
		||||
extern const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH];
 | 
			
		||||
 | 
			
		||||
extern void GifDrawText8x8(SavedImage *Image,
 | 
			
		||||
                     const int x, const int y,
 | 
			
		||||
                     const char *legend, const int color);
 | 
			
		||||
 | 
			
		||||
extern void GifDrawBox(SavedImage *Image,
 | 
			
		||||
                    const int x, const int y,
 | 
			
		||||
                    const int w, const int d, const int color);
 | 
			
		||||
 | 
			
		||||
extern void GifDrawRectangle(SavedImage *Image,
 | 
			
		||||
                   const int x, const int y,
 | 
			
		||||
                   const int w, const int d, const int color);
 | 
			
		||||
 | 
			
		||||
extern void GifDrawBoxedText8x8(SavedImage *Image,
 | 
			
		||||
                          const int x, const int y,
 | 
			
		||||
                          const char *legend,
 | 
			
		||||
                          const int border, const int bg, const int fg);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif /* __cplusplus */
 | 
			
		||||
#endif /* _GIF_LIB_H */
 | 
			
		||||
 | 
			
		||||
/* end */
 | 
			
		||||
							
								
								
									
										59
									
								
								src/ext/gif/gif_lib_private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/ext/gif/gif_lib_private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
 | 
			
		||||
gif_lib_private.h - internal giflib routines and structures
 | 
			
		||||
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef _GIF_LIB_PRIVATE_H
 | 
			
		||||
#define _GIF_LIB_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "gif_lib.h"
 | 
			
		||||
#include "gif_hash.h"
 | 
			
		||||
 | 
			
		||||
#define EXTENSION_INTRODUCER      0x21
 | 
			
		||||
#define DESCRIPTOR_INTRODUCER     0x2c
 | 
			
		||||
#define TERMINATOR_INTRODUCER     0x3b
 | 
			
		||||
 | 
			
		||||
#define LZ_MAX_CODE         4095    /* Biggest code possible in 12 bits. */
 | 
			
		||||
#define LZ_BITS             12
 | 
			
		||||
 | 
			
		||||
#define FLUSH_OUTPUT        4096    /* Impossible code, to signal flush. */
 | 
			
		||||
#define FIRST_CODE          4097    /* Impossible code, to signal first. */
 | 
			
		||||
#define NO_SUCH_CODE        4098    /* Impossible code, to signal empty. */
 | 
			
		||||
 | 
			
		||||
#define FILE_STATE_WRITE    0x01
 | 
			
		||||
#define FILE_STATE_SCREEN   0x02
 | 
			
		||||
#define FILE_STATE_IMAGE    0x04
 | 
			
		||||
#define FILE_STATE_READ     0x08
 | 
			
		||||
 | 
			
		||||
#define IS_READABLE(Private)    (Private->FileState & FILE_STATE_READ)
 | 
			
		||||
#define IS_WRITEABLE(Private)   (Private->FileState & FILE_STATE_WRITE)
 | 
			
		||||
 | 
			
		||||
typedef struct GifFilePrivateType {
 | 
			
		||||
    GifWord FileState, FileHandle,  /* Where all this data goes to! */
 | 
			
		||||
      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. */
 | 
			
		||||
    FILE *File;    /* File as stream. */
 | 
			
		||||
    InputFunc Read;     /* function to read gif input (TVT) */
 | 
			
		||||
    OutputFunc Write;   /* function to write gif output (MRB) */
 | 
			
		||||
    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];
 | 
			
		||||
    GifHashTableType *HashTable;
 | 
			
		||||
    bool gif89;
 | 
			
		||||
} GifFilePrivateType;
 | 
			
		||||
 | 
			
		||||
#endif /* _GIF_LIB_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/* end */
 | 
			
		||||
							
								
								
									
										412
									
								
								src/ext/gif/gifalloc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										412
									
								
								src/ext/gif/gifalloc.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,412 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 | 
			
		||||
 GIF construction tools
 | 
			
		||||
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "gif_lib.h"
 | 
			
		||||
 | 
			
		||||
#define MAX(x, y)    (((x) > (y)) ? (x) : (y))
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Miscellaneous utility functions                          
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* return smallest bitfield size n will fit in */
 | 
			
		||||
int
 | 
			
		||||
GifBitSize(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.
 | 
			
		||||
 */
 | 
			
		||||
ColorMapObject *
 | 
			
		||||
GifMakeMapObject(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 << GifBitSize(ColorCount))) {
 | 
			
		||||
        return ((ColorMapObject *) NULL);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
 | 
			
		||||
    if (Object == (ColorMapObject *) NULL) {
 | 
			
		||||
        return ((ColorMapObject *) NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
 | 
			
		||||
    if (Object->Colors == (GifColorType *) NULL) {
 | 
			
		||||
	free(Object);
 | 
			
		||||
        return ((ColorMapObject *) NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Object->ColorCount = ColorCount;
 | 
			
		||||
    Object->BitsPerPixel = GifBitSize(ColorCount);
 | 
			
		||||
    Object->SortFlag = false;
 | 
			
		||||
 | 
			
		||||
    if (ColorMap != NULL) {
 | 
			
		||||
        memcpy((char *)Object->Colors,
 | 
			
		||||
               (char *)ColorMap, ColorCount * sizeof(GifColorType));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (Object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
Free a color map object
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
void
 | 
			
		||||
GifFreeMapObject(ColorMapObject *Object)
 | 
			
		||||
{
 | 
			
		||||
    if (Object != NULL) {
 | 
			
		||||
        (void)free(Object->Colors);
 | 
			
		||||
        (void)free(Object);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
void
 | 
			
		||||
DumpColorMap(ColorMapObject *Object,
 | 
			
		||||
             FILE * fp)
 | 
			
		||||
{
 | 
			
		||||
    if (Object != NULL) {
 | 
			
		||||
        int i, j, Len = Object->ColorCount;
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < Len; i += 4) {
 | 
			
		||||
            for (j = 0; j < 4 && j < Len; j++) {
 | 
			
		||||
                (void)fprintf(fp, "%3d: %02x %02x %02x   ", i + j,
 | 
			
		||||
			      Object->Colors[i + j].Red,
 | 
			
		||||
			      Object->Colors[i + j].Green,
 | 
			
		||||
			      Object->Colors[i + j].Blue);
 | 
			
		||||
            }
 | 
			
		||||
            (void)fprintf(fp, "\n");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif /* DEBUG */
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 Compute the union of two given color maps and return it.  If result can't 
 | 
			
		||||
 fit into 256 colors, NULL is returned, the allocated union otherwise.
 | 
			
		||||
 ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
 | 
			
		||||
 copied iff they didn't exist before.  ColorTransIn2 maps the old
 | 
			
		||||
 ColorIn2 into the ColorUnion color map table./
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
ColorMapObject *
 | 
			
		||||
GifUnionColorMap(const ColorMapObject *ColorIn1,
 | 
			
		||||
              const ColorMapObject *ColorIn2,
 | 
			
		||||
              GifPixelType ColorTransIn2[])
 | 
			
		||||
{
 | 
			
		||||
    int i, j, CrntSlot, RoundUpTo, NewGifBitSize;
 | 
			
		||||
    ColorMapObject *ColorUnion;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * We don't worry about duplicates within either color map; if
 | 
			
		||||
     * the caller wants to resolve those, he can perform unions
 | 
			
		||||
     * with an empty color map.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /* Allocate table which will hold the result for sure. */
 | 
			
		||||
    ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount,
 | 
			
		||||
                               ColorIn2->ColorCount) * 2, NULL);
 | 
			
		||||
 | 
			
		||||
    if (ColorUnion == NULL)
 | 
			
		||||
        return (NULL);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Copy ColorIn1 to ColorUnion.
 | 
			
		||||
     */
 | 
			
		||||
    for (i = 0; i < ColorIn1->ColorCount; i++)
 | 
			
		||||
        ColorUnion->Colors[i] = ColorIn1->Colors[i];
 | 
			
		||||
    CrntSlot = ColorIn1->ColorCount;
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Potentially obnoxious hack:
 | 
			
		||||
     *
 | 
			
		||||
     * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
 | 
			
		||||
     * of table 1.  This is very useful if your display is limited to
 | 
			
		||||
     * 16 colors.
 | 
			
		||||
     */
 | 
			
		||||
    while (ColorIn1->Colors[CrntSlot - 1].Red == 0
 | 
			
		||||
           && ColorIn1->Colors[CrntSlot - 1].Green == 0
 | 
			
		||||
           && ColorIn1->Colors[CrntSlot - 1].Blue == 0)
 | 
			
		||||
        CrntSlot--;
 | 
			
		||||
 | 
			
		||||
    /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */
 | 
			
		||||
    for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
 | 
			
		||||
        /* Let's see if this color already exists: */
 | 
			
		||||
        for (j = 0; j < ColorIn1->ColorCount; j++)
 | 
			
		||||
            if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], 
 | 
			
		||||
                        sizeof(GifColorType)) == 0)
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
        if (j < ColorIn1->ColorCount)
 | 
			
		||||
            ColorTransIn2[i] = j;    /* color exists in Color1 */
 | 
			
		||||
        else {
 | 
			
		||||
            /* Color is new - copy it to a new slot: */
 | 
			
		||||
            ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
 | 
			
		||||
            ColorTransIn2[i] = CrntSlot++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (CrntSlot > 256) {
 | 
			
		||||
        GifFreeMapObject(ColorUnion);
 | 
			
		||||
        return ((ColorMapObject *) NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    NewGifBitSize = GifBitSize(CrntSlot);
 | 
			
		||||
    RoundUpTo = (1 << NewGifBitSize);
 | 
			
		||||
 | 
			
		||||
    if (RoundUpTo != ColorUnion->ColorCount) {
 | 
			
		||||
        register GifColorType *Map = ColorUnion->Colors;
 | 
			
		||||
 | 
			
		||||
        /* 
 | 
			
		||||
         * Zero out slots up to next power of 2.
 | 
			
		||||
         * We know these slots exist because of the way ColorUnion's
 | 
			
		||||
         * start dimension was computed.
 | 
			
		||||
         */
 | 
			
		||||
        for (j = CrntSlot; j < RoundUpTo; j++)
 | 
			
		||||
            Map[j].Red = Map[j].Green = Map[j].Blue = 0;
 | 
			
		||||
 | 
			
		||||
        /* perhaps we can shrink the map? */
 | 
			
		||||
        if (RoundUpTo < ColorUnion->ColorCount) {
 | 
			
		||||
            GifColorType *new_map = (GifColorType *)reallocarray(Map,
 | 
			
		||||
                                 RoundUpTo, sizeof(GifColorType));
 | 
			
		||||
            if( new_map == NULL ) {
 | 
			
		||||
                GifFreeMapObject(ColorUnion);
 | 
			
		||||
                return ((ColorMapObject *) NULL);
 | 
			
		||||
            }
 | 
			
		||||
            ColorUnion->Colors = new_map;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ColorUnion->ColorCount = RoundUpTo;
 | 
			
		||||
    ColorUnion->BitsPerPixel = NewGifBitSize;
 | 
			
		||||
 | 
			
		||||
    return (ColorUnion);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 Apply a given color translation to the raster bits of an image
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
void
 | 
			
		||||
GifApplyTranslation(SavedImage *Image, GifPixelType Translation[])
 | 
			
		||||
{
 | 
			
		||||
    register int i;
 | 
			
		||||
    register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < RasterSize; i++)
 | 
			
		||||
        Image->RasterBits[i] = Translation[Image->RasterBits[i]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Extension record functions                              
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
int
 | 
			
		||||
GifAddExtensionBlock(int *ExtensionBlockCount,
 | 
			
		||||
		     ExtensionBlock **ExtensionBlocks,
 | 
			
		||||
		     int Function,
 | 
			
		||||
		     unsigned int Len,
 | 
			
		||||
		     unsigned char ExtData[])
 | 
			
		||||
{
 | 
			
		||||
    ExtensionBlock *ep;
 | 
			
		||||
 | 
			
		||||
    if (*ExtensionBlocks == NULL)
 | 
			
		||||
        *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
 | 
			
		||||
    else {
 | 
			
		||||
        ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray
 | 
			
		||||
				 (*ExtensionBlocks, (*ExtensionBlockCount + 1),
 | 
			
		||||
                                      sizeof(ExtensionBlock));
 | 
			
		||||
        if( ep_new == NULL )
 | 
			
		||||
            return (GIF_ERROR);
 | 
			
		||||
        *ExtensionBlocks = ep_new;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (*ExtensionBlocks == NULL)
 | 
			
		||||
        return (GIF_ERROR);
 | 
			
		||||
 | 
			
		||||
    ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++];
 | 
			
		||||
 | 
			
		||||
    ep->Function = Function;
 | 
			
		||||
    ep->ByteCount=Len;
 | 
			
		||||
    ep->Bytes = (GifByteType *)malloc(ep->ByteCount);
 | 
			
		||||
    if (ep->Bytes == NULL)
 | 
			
		||||
        return (GIF_ERROR);
 | 
			
		||||
 | 
			
		||||
    if (ExtData != NULL) {
 | 
			
		||||
        memcpy(ep->Bytes, ExtData, Len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (GIF_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
GifFreeExtensions(int *ExtensionBlockCount,
 | 
			
		||||
		  ExtensionBlock **ExtensionBlocks)
 | 
			
		||||
{
 | 
			
		||||
    ExtensionBlock *ep;
 | 
			
		||||
 | 
			
		||||
    if (*ExtensionBlocks == NULL)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    for (ep = *ExtensionBlocks;
 | 
			
		||||
	 ep < (*ExtensionBlocks + *ExtensionBlockCount); 
 | 
			
		||||
	 ep++)
 | 
			
		||||
        (void)free((char *)ep->Bytes);
 | 
			
		||||
    (void)free((char *)*ExtensionBlocks);
 | 
			
		||||
    *ExtensionBlocks = NULL;
 | 
			
		||||
    *ExtensionBlockCount = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Image block allocation functions                          
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* Private Function:
 | 
			
		||||
 * Frees the last image in the GifFile->SavedImages array
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
FreeLastSavedImage(GifFileType *GifFile)
 | 
			
		||||
{
 | 
			
		||||
    SavedImage *sp;
 | 
			
		||||
    
 | 
			
		||||
    if ((GifFile == NULL) || (GifFile->SavedImages == NULL))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* Remove one SavedImage from the GifFile */
 | 
			
		||||
    GifFile->ImageCount--;
 | 
			
		||||
    sp = &GifFile->SavedImages[GifFile->ImageCount];
 | 
			
		||||
 | 
			
		||||
    /* Deallocate its Colormap */
 | 
			
		||||
    if (sp->ImageDesc.ColorMap != NULL) {
 | 
			
		||||
        GifFreeMapObject(sp->ImageDesc.ColorMap);
 | 
			
		||||
        sp->ImageDesc.ColorMap = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Deallocate the image data */
 | 
			
		||||
    if (sp->RasterBits != NULL)
 | 
			
		||||
        free((char *)sp->RasterBits);
 | 
			
		||||
 | 
			
		||||
    /* Deallocate any extensions */
 | 
			
		||||
    GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
 | 
			
		||||
 | 
			
		||||
    /*** FIXME: We could realloc the GifFile->SavedImages structure but is
 | 
			
		||||
     * there a point to it? Saves some memory but we'd have to do it every
 | 
			
		||||
     * time.  If this is used in GifFreeSavedImages then it would be inefficient
 | 
			
		||||
     * (The whole array is going to be deallocated.)  If we just use it when
 | 
			
		||||
     * we want to free the last Image it's convenient to do it here.
 | 
			
		||||
     */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Append an image block to the SavedImages array  
 | 
			
		||||
 */
 | 
			
		||||
SavedImage *
 | 
			
		||||
GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
 | 
			
		||||
{
 | 
			
		||||
    if (GifFile->SavedImages == NULL)
 | 
			
		||||
        GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
 | 
			
		||||
    else
 | 
			
		||||
        GifFile->SavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,
 | 
			
		||||
                               (GifFile->ImageCount + 1), sizeof(SavedImage));
 | 
			
		||||
 | 
			
		||||
    if (GifFile->SavedImages == NULL)
 | 
			
		||||
        return ((SavedImage *)NULL);
 | 
			
		||||
    else {
 | 
			
		||||
        SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++];
 | 
			
		||||
        memset((char *)sp, '\0', sizeof(SavedImage));
 | 
			
		||||
 | 
			
		||||
        if (CopyFrom != NULL) {
 | 
			
		||||
            memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
 | 
			
		||||
 | 
			
		||||
            /* 
 | 
			
		||||
             * Make our own allocated copies of the heap fields in the
 | 
			
		||||
             * copied record.  This guards against potential aliasing
 | 
			
		||||
             * problems.
 | 
			
		||||
             */
 | 
			
		||||
 | 
			
		||||
            /* first, the local color map */
 | 
			
		||||
            if (sp->ImageDesc.ColorMap != NULL) {
 | 
			
		||||
                sp->ImageDesc.ColorMap = GifMakeMapObject(
 | 
			
		||||
                                         CopyFrom->ImageDesc.ColorMap->ColorCount,
 | 
			
		||||
                                         CopyFrom->ImageDesc.ColorMap->Colors);
 | 
			
		||||
                if (sp->ImageDesc.ColorMap == NULL) {
 | 
			
		||||
                    FreeLastSavedImage(GifFile);
 | 
			
		||||
                    return (SavedImage *)(NULL);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* next, the raster */
 | 
			
		||||
            sp->RasterBits = (unsigned char *)reallocarray(NULL,
 | 
			
		||||
                                                  (CopyFrom->ImageDesc.Height *
 | 
			
		||||
                                                  CopyFrom->ImageDesc.Width),
 | 
			
		||||
						  sizeof(GifPixelType));
 | 
			
		||||
            if (sp->RasterBits == NULL) {
 | 
			
		||||
                FreeLastSavedImage(GifFile);
 | 
			
		||||
                return (SavedImage *)(NULL);
 | 
			
		||||
            }
 | 
			
		||||
            memcpy(sp->RasterBits, CopyFrom->RasterBits,
 | 
			
		||||
                   sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *
 | 
			
		||||
                   CopyFrom->ImageDesc.Width);
 | 
			
		||||
 | 
			
		||||
            /* finally, the extension blocks */
 | 
			
		||||
            if (sp->ExtensionBlocks != NULL) {
 | 
			
		||||
                sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL,
 | 
			
		||||
                                      CopyFrom->ExtensionBlockCount,
 | 
			
		||||
				      sizeof(ExtensionBlock));
 | 
			
		||||
                if (sp->ExtensionBlocks == NULL) {
 | 
			
		||||
                    FreeLastSavedImage(GifFile);
 | 
			
		||||
                    return (SavedImage *)(NULL);
 | 
			
		||||
                }
 | 
			
		||||
                memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,
 | 
			
		||||
                       sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return (sp);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
GifFreeSavedImages(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 != NULL) {
 | 
			
		||||
            GifFreeMapObject(sp->ImageDesc.ColorMap);
 | 
			
		||||
            sp->ImageDesc.ColorMap = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (sp->RasterBits != NULL)
 | 
			
		||||
            free((char *)sp->RasterBits);
 | 
			
		||||
	
 | 
			
		||||
	GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
 | 
			
		||||
    }
 | 
			
		||||
    free((char *)GifFile->SavedImages);
 | 
			
		||||
    GifFile->SavedImages = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* end */
 | 
			
		||||
							
								
								
									
										42
									
								
								src/ext/gif/openbsd-reallocarray.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/ext/gif/openbsd-reallocarray.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
/*	$OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $	*/
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 * copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#ifndef SIZE_MAX
 | 
			
		||||
#define SIZE_MAX ((size_t) - 1)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
 | 
			
		||||
 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
 | 
			
		||||
 */
 | 
			
		||||
#define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
 | 
			
		||||
 | 
			
		||||
void *
 | 
			
		||||
reallocarray(void *optr, size_t nmemb, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
 | 
			
		||||
	    nmemb > 0 && SIZE_MAX / nmemb < size) {
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	return realloc(optr, size * nmemb);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										330
									
								
								src/ext/gif/quantize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								src/ext/gif/quantize.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,330 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 | 
			
		||||
 quantize.c - quantize a high resolution image into lower one
 | 
			
		||||
 | 
			
		||||
 Based on: "Color Image Quantization for frame buffer Display", by
 | 
			
		||||
 Paul Heckbert SIGGRAPH 1982 page 297-307.
 | 
			
		||||
 | 
			
		||||
 This doesn't really belong in the core library, was undocumented,
 | 
			
		||||
 and was removed in 4.2.  Then it turned out some client apps were
 | 
			
		||||
 actually using it, so it was restored in 5.0.
 | 
			
		||||
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "gif_lib.h"
 | 
			
		||||
#include "gif_lib_private.h"
 | 
			
		||||
 | 
			
		||||
#define ABS(x)    ((x) > 0 ? (x) : (-(x)))
 | 
			
		||||
 | 
			
		||||
#define COLOR_ARRAY_SIZE 32768
 | 
			
		||||
#define BITS_PER_PRIM_COLOR 5
 | 
			
		||||
#define MAX_PRIM_COLOR      0x1f
 | 
			
		||||
 | 
			
		||||
static int SortRGBAxis;
 | 
			
		||||
 | 
			
		||||
typedef struct QuantizedColorType {
 | 
			
		||||
    GifByteType RGB[3];
 | 
			
		||||
    GifByteType NewColorIndex;
 | 
			
		||||
    long Count;
 | 
			
		||||
    struct QuantizedColorType *Pnext;
 | 
			
		||||
} QuantizedColorType;
 | 
			
		||||
 | 
			
		||||
typedef struct NewColorMapType {
 | 
			
		||||
    GifByteType RGBMin[3], RGBWidth[3];
 | 
			
		||||
    unsigned int NumEntries; /* # of QuantizedColorType in linked list below */
 | 
			
		||||
    unsigned long Count; /* Total number of pixels in all the entries */
 | 
			
		||||
    QuantizedColorType *QuantizedColors;
 | 
			
		||||
} NewColorMapType;
 | 
			
		||||
 | 
			
		||||
static int SubdivColorMap(NewColorMapType * NewColorSubdiv,
 | 
			
		||||
                          unsigned int ColorMapSize,
 | 
			
		||||
                          unsigned int *NewColorMapSize);
 | 
			
		||||
static int SortCmpRtn(const void *Entry1, const void *Entry2);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Quantize high resolution image into lower one. Input image consists of a
 | 
			
		||||
 2D array for each of the RGB colors with size Width by Height. There is no
 | 
			
		||||
 Color map for the input. Output is a quantized image with 2D array of
 | 
			
		||||
 indexes into the output color map.
 | 
			
		||||
   Note input image can be 24 bits at the most (8 for red/green/blue) and
 | 
			
		||||
 the output has 256 colors at the most (256 entries in the color map.).
 | 
			
		||||
 ColorMapSize specifies size of color map up to 256 and will be updated to
 | 
			
		||||
 real size before returning.
 | 
			
		||||
   Also non of the parameter are allocated by this routine.
 | 
			
		||||
   This function returns GIF_OK if successful, GIF_ERROR otherwise.
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
int
 | 
			
		||||
GifQuantizeBuffer(unsigned int Width,
 | 
			
		||||
               unsigned int Height,
 | 
			
		||||
               int *ColorMapSize,
 | 
			
		||||
               GifByteType * RedInput,
 | 
			
		||||
               GifByteType * GreenInput,
 | 
			
		||||
               GifByteType * BlueInput,
 | 
			
		||||
               GifByteType * OutputBuffer,
 | 
			
		||||
               GifColorType * OutputColorMap) {
 | 
			
		||||
 | 
			
		||||
    unsigned int Index, NumOfEntries;
 | 
			
		||||
    int i, j, MaxRGBError[3];
 | 
			
		||||
    unsigned int NewColorMapSize;
 | 
			
		||||
    long Red, Green, Blue;
 | 
			
		||||
    NewColorMapType NewColorSubdiv[256];
 | 
			
		||||
    QuantizedColorType *ColorArrayEntries, *QuantizedColor;
 | 
			
		||||
 | 
			
		||||
    ColorArrayEntries = (QuantizedColorType *)malloc(
 | 
			
		||||
                           sizeof(QuantizedColorType) * COLOR_ARRAY_SIZE);
 | 
			
		||||
    if (ColorArrayEntries == NULL) {
 | 
			
		||||
        return GIF_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < COLOR_ARRAY_SIZE; i++) {
 | 
			
		||||
        ColorArrayEntries[i].RGB[0] = i >> (2 * BITS_PER_PRIM_COLOR);
 | 
			
		||||
        ColorArrayEntries[i].RGB[1] = (i >> BITS_PER_PRIM_COLOR) &
 | 
			
		||||
           MAX_PRIM_COLOR;
 | 
			
		||||
        ColorArrayEntries[i].RGB[2] = i & MAX_PRIM_COLOR;
 | 
			
		||||
        ColorArrayEntries[i].Count = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Sample the colors and their distribution: */
 | 
			
		||||
    for (i = 0; i < (int)(Width * Height); i++) {
 | 
			
		||||
        Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
 | 
			
		||||
                  (2 * BITS_PER_PRIM_COLOR)) +
 | 
			
		||||
                ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
 | 
			
		||||
                  BITS_PER_PRIM_COLOR) +
 | 
			
		||||
                (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
 | 
			
		||||
        ColorArrayEntries[Index].Count++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Put all the colors in the first entry of the color map, and call the
 | 
			
		||||
     * recursive subdivision process.  */
 | 
			
		||||
    for (i = 0; i < 256; i++) {
 | 
			
		||||
        NewColorSubdiv[i].QuantizedColors = NULL;
 | 
			
		||||
        NewColorSubdiv[i].Count = NewColorSubdiv[i].NumEntries = 0;
 | 
			
		||||
        for (j = 0; j < 3; j++) {
 | 
			
		||||
            NewColorSubdiv[i].RGBMin[j] = 0;
 | 
			
		||||
            NewColorSubdiv[i].RGBWidth[j] = 255;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Find the non empty entries in the color table and chain them: */
 | 
			
		||||
    for (i = 0; i < COLOR_ARRAY_SIZE; i++)
 | 
			
		||||
        if (ColorArrayEntries[i].Count > 0)
 | 
			
		||||
            break;
 | 
			
		||||
    QuantizedColor = NewColorSubdiv[0].QuantizedColors = &ColorArrayEntries[i];
 | 
			
		||||
    NumOfEntries = 1;
 | 
			
		||||
    while (++i < COLOR_ARRAY_SIZE)
 | 
			
		||||
        if (ColorArrayEntries[i].Count > 0) {
 | 
			
		||||
            QuantizedColor->Pnext = &ColorArrayEntries[i];
 | 
			
		||||
            QuantizedColor = &ColorArrayEntries[i];
 | 
			
		||||
            NumOfEntries++;
 | 
			
		||||
        }
 | 
			
		||||
    QuantizedColor->Pnext = NULL;
 | 
			
		||||
 | 
			
		||||
    NewColorSubdiv[0].NumEntries = NumOfEntries; /* Different sampled colors */
 | 
			
		||||
    NewColorSubdiv[0].Count = ((long)Width) * Height; /* Pixels */
 | 
			
		||||
    NewColorMapSize = 1;
 | 
			
		||||
    if (SubdivColorMap(NewColorSubdiv, *ColorMapSize, &NewColorMapSize) !=
 | 
			
		||||
       GIF_OK) {
 | 
			
		||||
        free((char *)ColorArrayEntries);
 | 
			
		||||
        return GIF_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    if (NewColorMapSize < *ColorMapSize) {
 | 
			
		||||
        /* And clear rest of color map: */
 | 
			
		||||
        for (i = NewColorMapSize; i < *ColorMapSize; i++)
 | 
			
		||||
            OutputColorMap[i].Red = OutputColorMap[i].Green =
 | 
			
		||||
                OutputColorMap[i].Blue = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Average the colors in each entry to be the color to be used in the
 | 
			
		||||
     * output color map, and plug it into the output color map itself. */
 | 
			
		||||
    for (i = 0; i < NewColorMapSize; i++) {
 | 
			
		||||
        if ((j = NewColorSubdiv[i].NumEntries) > 0) {
 | 
			
		||||
            QuantizedColor = NewColorSubdiv[i].QuantizedColors;
 | 
			
		||||
            Red = Green = Blue = 0;
 | 
			
		||||
            while (QuantizedColor) {
 | 
			
		||||
                QuantizedColor->NewColorIndex = i;
 | 
			
		||||
                Red += QuantizedColor->RGB[0];
 | 
			
		||||
                Green += QuantizedColor->RGB[1];
 | 
			
		||||
                Blue += QuantizedColor->RGB[2];
 | 
			
		||||
                QuantizedColor = QuantizedColor->Pnext;
 | 
			
		||||
            }
 | 
			
		||||
            OutputColorMap[i].Red = (Red << (8 - BITS_PER_PRIM_COLOR)) / j;
 | 
			
		||||
            OutputColorMap[i].Green = (Green << (8 - BITS_PER_PRIM_COLOR)) / j;
 | 
			
		||||
            OutputColorMap[i].Blue = (Blue << (8 - BITS_PER_PRIM_COLOR)) / j;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Finally scan the input buffer again and put the mapped index in the
 | 
			
		||||
     * output buffer.  */
 | 
			
		||||
    MaxRGBError[0] = MaxRGBError[1] = MaxRGBError[2] = 0;
 | 
			
		||||
    for (i = 0; i < (int)(Width * Height); i++) {
 | 
			
		||||
        Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
 | 
			
		||||
                 (2 * BITS_PER_PRIM_COLOR)) +
 | 
			
		||||
                ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
 | 
			
		||||
                 BITS_PER_PRIM_COLOR) +
 | 
			
		||||
                (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
 | 
			
		||||
        Index = ColorArrayEntries[Index].NewColorIndex;
 | 
			
		||||
        OutputBuffer[i] = Index;
 | 
			
		||||
        if (MaxRGBError[0] < ABS(OutputColorMap[Index].Red - RedInput[i]))
 | 
			
		||||
            MaxRGBError[0] = ABS(OutputColorMap[Index].Red - RedInput[i]);
 | 
			
		||||
        if (MaxRGBError[1] < ABS(OutputColorMap[Index].Green - GreenInput[i]))
 | 
			
		||||
            MaxRGBError[1] = ABS(OutputColorMap[Index].Green - GreenInput[i]);
 | 
			
		||||
        if (MaxRGBError[2] < ABS(OutputColorMap[Index].Blue - BlueInput[i]))
 | 
			
		||||
            MaxRGBError[2] = ABS(OutputColorMap[Index].Blue - BlueInput[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
    fprintf(stderr,
 | 
			
		||||
            "Quantization L(0) errors: Red = %d, Green = %d, Blue = %d.\n",
 | 
			
		||||
            MaxRGBError[0], MaxRGBError[1], MaxRGBError[2]);
 | 
			
		||||
#endif /* DEBUG */
 | 
			
		||||
 | 
			
		||||
    free((char *)ColorArrayEntries);
 | 
			
		||||
 | 
			
		||||
    *ColorMapSize = NewColorMapSize;
 | 
			
		||||
 | 
			
		||||
    return GIF_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 Routine to subdivide the RGB space recursively using median cut in each
 | 
			
		||||
 axes alternatingly until ColorMapSize different cubes exists.
 | 
			
		||||
 The biggest cube in one dimension is subdivide unless it has only one entry.
 | 
			
		||||
 Returns GIF_ERROR if failed, otherwise GIF_OK.
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
static int
 | 
			
		||||
SubdivColorMap(NewColorMapType * NewColorSubdiv,
 | 
			
		||||
               unsigned int ColorMapSize,
 | 
			
		||||
               unsigned int *NewColorMapSize) {
 | 
			
		||||
 | 
			
		||||
    int MaxSize;
 | 
			
		||||
    unsigned int i, j, Index = 0, NumEntries, MinColor, MaxColor;
 | 
			
		||||
    long Sum, Count;
 | 
			
		||||
    QuantizedColorType *QuantizedColor, **SortArray;
 | 
			
		||||
 | 
			
		||||
    while (ColorMapSize > *NewColorMapSize) {
 | 
			
		||||
        /* Find candidate for subdivision: */
 | 
			
		||||
        MaxSize = -1;
 | 
			
		||||
        for (i = 0; i < *NewColorMapSize; i++) {
 | 
			
		||||
            for (j = 0; j < 3; j++) {
 | 
			
		||||
                if ((((int)NewColorSubdiv[i].RGBWidth[j]) > MaxSize) &&
 | 
			
		||||
                      (NewColorSubdiv[i].NumEntries > 1)) {
 | 
			
		||||
                    MaxSize = NewColorSubdiv[i].RGBWidth[j];
 | 
			
		||||
                    Index = i;
 | 
			
		||||
                    SortRGBAxis = j;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (MaxSize == -1)
 | 
			
		||||
            return GIF_OK;
 | 
			
		||||
 | 
			
		||||
        /* Split the entry Index into two along the axis SortRGBAxis: */
 | 
			
		||||
 | 
			
		||||
        /* Sort all elements in that entry along the given axis and split at
 | 
			
		||||
         * the median.  */
 | 
			
		||||
        SortArray = (QuantizedColorType **)malloc(
 | 
			
		||||
                      sizeof(QuantizedColorType *) * 
 | 
			
		||||
                      NewColorSubdiv[Index].NumEntries);
 | 
			
		||||
        if (SortArray == NULL)
 | 
			
		||||
            return GIF_ERROR;
 | 
			
		||||
        for (j = 0, QuantizedColor = NewColorSubdiv[Index].QuantizedColors;
 | 
			
		||||
             j < NewColorSubdiv[Index].NumEntries && QuantizedColor != NULL;
 | 
			
		||||
             j++, QuantizedColor = QuantizedColor->Pnext)
 | 
			
		||||
            SortArray[j] = QuantizedColor;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Because qsort isn't stable, this can produce differing 
 | 
			
		||||
	 * results for the order of tuples depending on platform
 | 
			
		||||
	 * details of how qsort() is implemented.
 | 
			
		||||
	 *
 | 
			
		||||
	 * We mitigate this problem by sorting on all three axes rather
 | 
			
		||||
	 * than only the one specied by SortRGBAxis; that way the instability
 | 
			
		||||
	 * can only become an issue if there are multiple color indices
 | 
			
		||||
	 * referring to identical RGB tuples.  Older versions of this 
 | 
			
		||||
	 * sorted on only the one axis.
 | 
			
		||||
	 */
 | 
			
		||||
        qsort(SortArray, NewColorSubdiv[Index].NumEntries,
 | 
			
		||||
              sizeof(QuantizedColorType *), SortCmpRtn);
 | 
			
		||||
 | 
			
		||||
        /* Relink the sorted list into one: */
 | 
			
		||||
        for (j = 0; j < NewColorSubdiv[Index].NumEntries - 1; j++)
 | 
			
		||||
            SortArray[j]->Pnext = SortArray[j + 1];
 | 
			
		||||
        SortArray[NewColorSubdiv[Index].NumEntries - 1]->Pnext = NULL;
 | 
			
		||||
        NewColorSubdiv[Index].QuantizedColors = QuantizedColor = SortArray[0];
 | 
			
		||||
        free((char *)SortArray);
 | 
			
		||||
 | 
			
		||||
        /* Now simply add the Counts until we have half of the Count: */
 | 
			
		||||
        Sum = NewColorSubdiv[Index].Count / 2 - QuantizedColor->Count;
 | 
			
		||||
        NumEntries = 1;
 | 
			
		||||
        Count = QuantizedColor->Count;
 | 
			
		||||
        while (QuantizedColor->Pnext != NULL &&
 | 
			
		||||
	       (Sum -= QuantizedColor->Pnext->Count) >= 0 &&
 | 
			
		||||
               QuantizedColor->Pnext->Pnext != NULL) {
 | 
			
		||||
            QuantizedColor = QuantizedColor->Pnext;
 | 
			
		||||
            NumEntries++;
 | 
			
		||||
            Count += QuantizedColor->Count;
 | 
			
		||||
        }
 | 
			
		||||
        /* Save the values of the last color of the first half, and first
 | 
			
		||||
         * of the second half so we can update the Bounding Boxes later.
 | 
			
		||||
         * Also as the colors are quantized and the BBoxes are full 0..255,
 | 
			
		||||
         * they need to be rescaled.
 | 
			
		||||
         */
 | 
			
		||||
        MaxColor = QuantizedColor->RGB[SortRGBAxis]; /* Max. of first half */
 | 
			
		||||
	/* coverity[var_deref_op] */
 | 
			
		||||
        MinColor = QuantizedColor->Pnext->RGB[SortRGBAxis]; /* of second */
 | 
			
		||||
        MaxColor <<= (8 - BITS_PER_PRIM_COLOR);
 | 
			
		||||
        MinColor <<= (8 - BITS_PER_PRIM_COLOR);
 | 
			
		||||
 | 
			
		||||
        /* Partition right here: */
 | 
			
		||||
        NewColorSubdiv[*NewColorMapSize].QuantizedColors =
 | 
			
		||||
           QuantizedColor->Pnext;
 | 
			
		||||
        QuantizedColor->Pnext = NULL;
 | 
			
		||||
        NewColorSubdiv[*NewColorMapSize].Count = Count;
 | 
			
		||||
        NewColorSubdiv[Index].Count -= Count;
 | 
			
		||||
        NewColorSubdiv[*NewColorMapSize].NumEntries =
 | 
			
		||||
           NewColorSubdiv[Index].NumEntries - NumEntries;
 | 
			
		||||
        NewColorSubdiv[Index].NumEntries = NumEntries;
 | 
			
		||||
        for (j = 0; j < 3; j++) {
 | 
			
		||||
            NewColorSubdiv[*NewColorMapSize].RGBMin[j] =
 | 
			
		||||
               NewColorSubdiv[Index].RGBMin[j];
 | 
			
		||||
            NewColorSubdiv[*NewColorMapSize].RGBWidth[j] =
 | 
			
		||||
               NewColorSubdiv[Index].RGBWidth[j];
 | 
			
		||||
        }
 | 
			
		||||
        NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] =
 | 
			
		||||
           NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] +
 | 
			
		||||
           NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] - MinColor;
 | 
			
		||||
        NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] = MinColor;
 | 
			
		||||
 | 
			
		||||
        NewColorSubdiv[Index].RGBWidth[SortRGBAxis] =
 | 
			
		||||
           MaxColor - NewColorSubdiv[Index].RGBMin[SortRGBAxis];
 | 
			
		||||
 | 
			
		||||
        (*NewColorMapSize)++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return GIF_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
 Routine called by qsort to compare two entries.
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
SortCmpRtn(const void *Entry1,
 | 
			
		||||
           const void *Entry2) {
 | 
			
		||||
	   QuantizedColorType *entry1 = (*((QuantizedColorType **) Entry1));
 | 
			
		||||
	   QuantizedColorType *entry2 = (*((QuantizedColorType **) Entry2));
 | 
			
		||||
 | 
			
		||||
	   /* sort on all axes of the color space! */
 | 
			
		||||
	   int hash1 = entry1->RGB[SortRGBAxis] * 256 * 256
 | 
			
		||||
	   			+ entry1->RGB[(SortRGBAxis+1) % 3] * 256
 | 
			
		||||
				+ entry1->RGB[(SortRGBAxis+2) % 3];
 | 
			
		||||
	   int hash2 = entry2->RGB[SortRGBAxis] * 256 * 256
 | 
			
		||||
	   			+ entry2->RGB[(SortRGBAxis+1) % 3] * 256
 | 
			
		||||
				+ entry2->RGB[(SortRGBAxis+2) % 3];
 | 
			
		||||
 | 
			
		||||
    return hash1 - hash2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* end */
 | 
			
		||||
		Reference in New Issue
	
	Block a user