mirror of https://github.com/vitalif/phantomjs
Remove GIF format for screen capture export (render).
This is to reduce maintenance burden. A GIF representation of a web page can be produced by converting its PNG capture. There are numerous third-party tools which can do the job better (optimized palette, minimized loss, etc). https://github.com/ariya/phantomjs/issues/124802.0
parent
51c8c9cc62
commit
8cabfed4b3
|
@ -1 +0,0 @@
|
||||||
#define UINT32 uint32_t
|
|
1111
src/gif/egif_lib.c
1111
src/gif/egif_lib.c
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +0,0 @@
|
||||||
VPATH += $$PWD
|
|
||||||
INCLUDEPATH += $$PWD
|
|
||||||
|
|
||||||
DEFINES += HAVE_CONFIG_H
|
|
||||||
DEFINES += HAVE_FCNTL_H
|
|
||||||
DEFINES += HAVE_STDARG_H
|
|
||||||
!win32-msvc* {
|
|
||||||
DEFINES += HAVE_STDINT_H
|
|
||||||
DEFINES += HAVE_UNISTD_H
|
|
||||||
}
|
|
||||||
|
|
||||||
SOURCES += gif_err.c
|
|
||||||
SOURCES += gifalloc.c
|
|
||||||
SOURCES += egif_lib.c
|
|
||||||
SOURCES += gif_hash.c
|
|
||||||
SOURCES += quantize.c
|
|
||||||
SOURCES += gifwriter.cpp
|
|
||||||
|
|
||||||
HEADERS += gif_hash.h
|
|
||||||
HEADERS += gif_lib_private.h
|
|
||||||
HEADERS += gif_lib.h
|
|
||||||
HEADERS += gifwriter.h
|
|
|
@ -1,120 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
* "Gif-Lib" - Yet another gif library.
|
|
||||||
*
|
|
||||||
* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989
|
|
||||||
*****************************************************************************
|
|
||||||
* Handle error reporting for the GIF library.
|
|
||||||
*****************************************************************************
|
|
||||||
* History:
|
|
||||||
* 17 Jun 89 - Version 1.0 by Gershon Elber.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "gif_lib.h"
|
|
||||||
|
|
||||||
int _GifError = 0;
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* Return the last GIF error (0 if none) and reset the error.
|
|
||||||
****************************************************************************/
|
|
||||||
int
|
|
||||||
GifLastError(void) {
|
|
||||||
int i = _GifError;
|
|
||||||
|
|
||||||
_GifError = 0;
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
#ifndef _GBA_NO_FILEIO
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* Print the last GIF error to stderr.
|
|
||||||
****************************************************************************/
|
|
||||||
void
|
|
||||||
PrintGifError(void) {
|
|
||||||
char *Err;
|
|
||||||
|
|
||||||
switch (_GifError) {
|
|
||||||
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 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 = "#Pixels bigger than Width * Height";
|
|
||||||
break;
|
|
||||||
case E_GIF_ERR_NOT_ENOUGH_MEM:
|
|
||||||
Err = "Fail 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 = "Given file is NOT GIF file";
|
|
||||||
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 = "#Pixels bigger than Width * Height";
|
|
||||||
break;
|
|
||||||
case D_GIF_ERR_NOT_ENOUGH_MEM:
|
|
||||||
Err = "Fail 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;
|
|
||||||
}
|
|
||||||
if (Err != NULL)
|
|
||||||
fprintf(stderr, "\nGIF-LIB error: %s.\n", Err);
|
|
||||||
else
|
|
||||||
fprintf(stderr, "\nGIF-LIB undefined error %d.\n", _GifError);
|
|
||||||
}
|
|
||||||
#endif /* _GBA_NO_FILEIO */
|
|
|
@ -1,160 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
* "Gif-Lib" - Yet another gif library. *
|
|
||||||
* *
|
|
||||||
* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 *
|
|
||||||
******************************************************************************
|
|
||||||
* 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. *
|
|
||||||
******************************************************************************
|
|
||||||
* History: *
|
|
||||||
* 14 Jun 89 - Version 1.0 by Gershon Elber. *
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Find a thirty-two bit int type */
|
|
||||||
#ifdef HAVE_STDINT_H
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __MSDOS__
|
|
||||||
#include <io.h>
|
|
||||||
#include <alloc.h>
|
|
||||||
#include <sys\stat.h>
|
|
||||||
#else
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif /* __MSDOS__ */
|
|
||||||
|
|
||||||
#ifdef HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif /* HAVE_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 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Routine to insert a new Item into the HashTable. The data is assumed to be *
|
|
||||||
* new one. *
|
|
||||||
******************************************************************************/
|
|
||||||
void _InsertHashTable(GifHashTableType *HashTable, UINT32 Key, int Code)
|
|
||||||
{
|
|
||||||
int HKey = KeyItem(Key);
|
|
||||||
UINT32 *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 Key)
|
|
||||||
{
|
|
||||||
int HKey = KeyItem(Key);
|
|
||||||
UINT32 *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 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 */
|
|
|
@ -1,61 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* Declarations, global to other of the GIF-HASH.C module. *
|
|
||||||
* *
|
|
||||||
* Written by Gershon Elber, Jun 1989 *
|
|
||||||
*******************************************************************************
|
|
||||||
* History: *
|
|
||||||
* 14 Jun 89 - Version 1.0 by Gershon Elber. *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _GIF_HASH_H_
|
|
||||||
#define _GIF_HASH_H_
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Find a thirty-two bit int type */
|
|
||||||
#ifdef HAVE_STDINT_H
|
|
||||||
#include <stdint.h>
|
|
||||||
#else if defined(Q_CC_MSVC)
|
|
||||||
typedef unsigned __int32 uint32_t;
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_BASETSD_H
|
|
||||||
#include <basetsd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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 HTable[HT_SIZE];
|
|
||||||
} GifHashTableType;
|
|
||||||
|
|
||||||
GifHashTableType *_InitHashTable(void);
|
|
||||||
void _ClearHashTable(GifHashTableType *HashTable);
|
|
||||||
void _InsertHashTable(GifHashTableType *HashTable, UINT32 Key, int Code);
|
|
||||||
int _ExistsHashTable(GifHashTableType *HashTable, UINT32 Key);
|
|
||||||
|
|
||||||
#endif /* _GIF_HASH_H_ */
|
|
|
@ -1,336 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* In order to make life a little bit easier when using the GIF file format,
|
|
||||||
* this library was written, and which does all the dirty work...
|
|
||||||
*
|
|
||||||
* Written by Gershon Elber, Jun. 1989
|
|
||||||
* Hacks by Eric S. Raymond, Sep. 1992
|
|
||||||
******************************************************************************
|
|
||||||
* History:
|
|
||||||
* 14 Jun 89 - Version 1.0 by Gershon Elber.
|
|
||||||
* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names)
|
|
||||||
* 15 Sep 90 - Version 2.0 by Eric S. Raymond (Changes to suoport GIF slurp)
|
|
||||||
* 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support)
|
|
||||||
* 17 Dec 98 - Version 4.0 by Toshio Kuratomi (Fix extension writing code)
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _GIF_LIB_H_
|
|
||||||
#define _GIF_LIB_H_ 1
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#define GIF_LIB_VERSION " Version 4.1, "
|
|
||||||
|
|
||||||
#define GIF_ERROR 0
|
|
||||||
#define GIF_OK 1
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE 1
|
|
||||||
#endif /* TRUE */
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE 0
|
|
||||||
#endif /* FALSE */
|
|
||||||
|
|
||||||
#ifndef NULL
|
|
||||||
#define NULL 0
|
|
||||||
#endif /* NULL */
|
|
||||||
|
|
||||||
#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. */
|
|
||||||
|
|
||||||
#define GIF_FILE_BUFFER_SIZE 16384 /* Files uses bigger buffers than usual. */
|
|
||||||
|
|
||||||
typedef int GifBooleanType;
|
|
||||||
typedef unsigned char GifPixelType;
|
|
||||||
typedef unsigned char *GifRowType;
|
|
||||||
typedef unsigned char GifByteType;
|
|
||||||
#ifdef _GBA_OPTMEM
|
|
||||||
typedef unsigned short GifPrefixType;
|
|
||||||
typedef short GifWord;
|
|
||||||
#else
|
|
||||||
typedef unsigned int GifPrefixType;
|
|
||||||
typedef int GifWord;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GIF_MESSAGE(Msg) fprintf(stderr, "\n%s: %s\n", PROGRAM_NAME, Msg)
|
|
||||||
#define GIF_EXIT(Msg) { GIF_MESSAGE(Msg); exit(-3); }
|
|
||||||
|
|
||||||
#ifdef SYSV
|
|
||||||
#define VoidPtr char *
|
|
||||||
#else
|
|
||||||
#define VoidPtr void *
|
|
||||||
#endif /* SYSV */
|
|
||||||
|
|
||||||
typedef struct GifColorType {
|
|
||||||
GifByteType Red, Green, Blue;
|
|
||||||
} GifColorType;
|
|
||||||
|
|
||||||
typedef struct ColorMapObject {
|
|
||||||
int ColorCount;
|
|
||||||
int BitsPerPixel;
|
|
||||||
GifColorType *Colors; /* on malloc(3) heap */
|
|
||||||
} ColorMapObject;
|
|
||||||
|
|
||||||
typedef struct GifImageDesc {
|
|
||||||
GifWord Left, Top, Width, Height, /* Current image dimensions. */
|
|
||||||
Interlace; /* Sequential/Interlaced lines. */
|
|
||||||
ColorMapObject *ColorMap; /* The local color map */
|
|
||||||
} GifImageDesc;
|
|
||||||
|
|
||||||
typedef struct GifFileType {
|
|
||||||
GifWord SWidth, SHeight, /* Screen dimensions. */
|
|
||||||
SColorResolution, /* How many colors can we generate? */
|
|
||||||
SBackGroundColor; /* I hope you understand this one... */
|
|
||||||
ColorMapObject *SColorMap; /* NULL if not exists. */
|
|
||||||
int ImageCount; /* Number of current image */
|
|
||||||
GifImageDesc Image; /* Block describing current image */
|
|
||||||
struct SavedImage *SavedImages; /* Use this to accumulate file state */
|
|
||||||
VoidPtr UserData; /* hook to attach user data (TVT) */
|
|
||||||
VoidPtr Private; /* Don't mess with this! */
|
|
||||||
} GifFileType;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* DumpScreen2Gif routine constants identify type of window/screen to dump.
|
|
||||||
* Note all values below 1000 are reserved for the IBMPC different display
|
|
||||||
* devices (it has many!) and are compatible with the numbering TC2.0
|
|
||||||
* (Turbo C 2.0 compiler for IBM PC) gives to these devices.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
GIF_DUMP_SGI_WINDOW = 1000,
|
|
||||||
GIF_DUMP_X_WINDOW = 1001
|
|
||||||
} GifScreenDumpType;
|
|
||||||
|
|
||||||
/* func type to read gif data from arbitrary sources (TVT) */
|
|
||||||
typedef int (*InputFunc) (GifFileType *, GifByteType *, int);
|
|
||||||
|
|
||||||
/* func type to write gif data ro arbitrary targets.
|
|
||||||
* Returns count of bytes written. (MRB)
|
|
||||||
*/
|
|
||||||
typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* GIF89 extension function codes
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */
|
|
||||||
#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control */
|
|
||||||
#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */
|
|
||||||
#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* O.K., here are the routines one can access in order to encode GIF file:
|
|
||||||
* (GIF_LIB file EGIF_LIB.C).
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
GifFileType *EGifOpenFileName(const char *GifFileName,
|
|
||||||
int GifTestExistance);
|
|
||||||
GifFileType *EGifOpenFileHandle(int GifFileHandle);
|
|
||||||
GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc);
|
|
||||||
|
|
||||||
int EGifSpew(GifFileType * GifFile);
|
|
||||||
void EGifSetGifVersion(const char *Version);
|
|
||||||
int EGifPutScreenDesc(GifFileType * GifFile,
|
|
||||||
int GifWidth, int GifHeight, int GifColorRes,
|
|
||||||
int GifBackGround,
|
|
||||||
const ColorMapObject * GifColorMap);
|
|
||||||
int EGifPutImageDesc(GifFileType * GifFile, int GifLeft, int GifTop,
|
|
||||||
int Width, int GifHeight, int GifInterlace,
|
|
||||||
const ColorMapObject * GifColorMap);
|
|
||||||
int EGifPutLine(GifFileType * GifFile, GifPixelType * GifLine,
|
|
||||||
int GifLineLen);
|
|
||||||
int EGifPutPixel(GifFileType * GifFile, GifPixelType GifPixel);
|
|
||||||
int EGifPutComment(GifFileType * GifFile, const char *GifComment);
|
|
||||||
int EGifPutExtensionFirst(GifFileType * GifFile, int GifExtCode,
|
|
||||||
int GifExtLen, const VoidPtr GifExtension);
|
|
||||||
int EGifPutExtensionNext(GifFileType * GifFile, int GifExtCode,
|
|
||||||
int GifExtLen, const VoidPtr GifExtension);
|
|
||||||
int EGifPutExtensionLast(GifFileType * GifFile, int GifExtCode,
|
|
||||||
int GifExtLen, const VoidPtr GifExtension);
|
|
||||||
int EGifPutExtension(GifFileType * GifFile, int GifExtCode, int GifExtLen,
|
|
||||||
const VoidPtr GifExtension);
|
|
||||||
int EGifPutCode(GifFileType * GifFile, int GifCodeSize,
|
|
||||||
const GifByteType * GifCodeBlock);
|
|
||||||
int EGifPutCodeNext(GifFileType * GifFile,
|
|
||||||
const GifByteType * GifCodeBlock);
|
|
||||||
int EGifCloseFile(GifFileType * GifFile);
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* O.K., here are the routines one can access in order to decode GIF file:
|
|
||||||
* (GIF_LIB file DGIF_LIB.C).
|
|
||||||
*****************************************************************************/
|
|
||||||
#ifndef _GBA_NO_FILEIO
|
|
||||||
GifFileType *DGifOpenFileName(const char *GifFileName);
|
|
||||||
GifFileType *DGifOpenFileHandle(int GifFileHandle);
|
|
||||||
int DGifSlurp(GifFileType * GifFile);
|
|
||||||
#endif /* _GBA_NO_FILEIO */
|
|
||||||
GifFileType *DGifOpen(void *userPtr, InputFunc readFunc); /* new one
|
|
||||||
* (TVT) */
|
|
||||||
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);
|
|
||||||
int DGifCloseFile(GifFileType * GifFile);
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* O.K., here are the routines from GIF_LIB file QUANTIZE.C.
|
|
||||||
******************************************************************************/
|
|
||||||
int QuantizeBuffer(unsigned int Width, unsigned int Height,
|
|
||||||
int *ColorMapSize, GifByteType * RedInput,
|
|
||||||
GifByteType * GreenInput, GifByteType * BlueInput,
|
|
||||||
GifByteType * OutputBuffer,
|
|
||||||
GifColorType * OutputColorMap);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* O.K., here are the routines from GIF_LIB file QPRINTF.C.
|
|
||||||
******************************************************************************/
|
|
||||||
extern int GifQuietPrint;
|
|
||||||
|
|
||||||
#ifdef HAVE_STDARG_H
|
|
||||||
extern void GifQprintf(char *Format, ...);
|
|
||||||
#elif defined (HAVE_VARARGS_H)
|
|
||||||
extern void GifQprintf();
|
|
||||||
#endif /* HAVE_STDARG_H */
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* O.K., here are the routines from GIF_LIB file GIF_ERR.C.
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef _GBA_NO_FILEIO
|
|
||||||
extern void PrintGifError(void);
|
|
||||||
#endif /* _GBA_NO_FILEIO */
|
|
||||||
extern int GifLastError(void);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* O.K., here are the routines from GIF_LIB file DEV2GIF.C.
|
|
||||||
******************************************************************************/
|
|
||||||
extern int DumpScreen2Gif(const char *FileName,
|
|
||||||
int ReqGraphDriver,
|
|
||||||
long ReqGraphMode1,
|
|
||||||
long ReqGraphMode2,
|
|
||||||
long ReqGraphMode3);
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* 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 ALLOCGIF.C
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
extern ColorMapObject *MakeMapObject(int ColorCount,
|
|
||||||
const GifColorType * ColorMap);
|
|
||||||
extern void FreeMapObject(ColorMapObject * Object);
|
|
||||||
extern ColorMapObject *UnionColorMap(const ColorMapObject * ColorIn1,
|
|
||||||
const ColorMapObject * ColorIn2,
|
|
||||||
GifPixelType ColorTransIn2[]);
|
|
||||||
extern int BitSize(int n);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Support for the in-core structures allocation (slurp mode).
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/* This is the in-core version of an extension record */
|
|
||||||
typedef struct {
|
|
||||||
int ByteCount;
|
|
||||||
char *Bytes; /* on malloc(3) heap */
|
|
||||||
int Function; /* Holds the type of the Extension block. */
|
|
||||||
} ExtensionBlock;
|
|
||||||
|
|
||||||
/* This holds an image header, its unpacked raster bits, and extensions */
|
|
||||||
typedef struct SavedImage {
|
|
||||||
GifImageDesc ImageDesc;
|
|
||||||
unsigned char *RasterBits; /* on malloc(3) heap */
|
|
||||||
int Function; /* DEPRECATED: Use ExtensionBlocks[x].Function instead */
|
|
||||||
int ExtensionBlockCount;
|
|
||||||
ExtensionBlock *ExtensionBlocks; /* on malloc(3) heap */
|
|
||||||
} SavedImage;
|
|
||||||
|
|
||||||
extern void ApplyTranslation(SavedImage * Image, GifPixelType Translation[]);
|
|
||||||
extern void MakeExtension(SavedImage * New, int Function);
|
|
||||||
extern int AddExtensionBlock(SavedImage * New, int Len,
|
|
||||||
unsigned char ExtData[]);
|
|
||||||
extern void FreeExtension(SavedImage * Image);
|
|
||||||
extern SavedImage *MakeSavedImage(GifFileType * GifFile,
|
|
||||||
const SavedImage * CopyFrom);
|
|
||||||
extern void FreeSavedImages(GifFileType * GifFile);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* The library's internal utility font
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#define GIF_FONT_WIDTH 8
|
|
||||||
#define GIF_FONT_HEIGHT 8
|
|
||||||
extern unsigned char AsciiTable[][GIF_FONT_WIDTH];
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
extern void DrawGifText(SavedImage * Image,
|
|
||||||
#else
|
|
||||||
extern void DrawText(SavedImage * Image,
|
|
||||||
#endif
|
|
||||||
const int x, const int y,
|
|
||||||
const char *legend, const int color);
|
|
||||||
|
|
||||||
extern void DrawBox(SavedImage * Image,
|
|
||||||
const int x, const int y,
|
|
||||||
const int w, const int d, const int color);
|
|
||||||
|
|
||||||
void DrawRectangle(SavedImage * Image,
|
|
||||||
const int x, const int y,
|
|
||||||
const int w, const int d, const int color);
|
|
||||||
|
|
||||||
extern void DrawBoxedText(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 */
|
|
|
@ -1,59 +0,0 @@
|
||||||
#ifndef _GIF_LIB_PRIVATE_H
|
|
||||||
#define _GIF_LIB_PRIVATE_H
|
|
||||||
|
|
||||||
#include "gif_lib.h"
|
|
||||||
#include "gif_hash.h"
|
|
||||||
|
|
||||||
#define PROGRAM_NAME "GIFLIB"
|
|
||||||
|
|
||||||
#ifdef SYSV
|
|
||||||
#define VersionStr "Gif library module,\t\tEric S. Raymond\n\
|
|
||||||
(C) Copyright 1997 Eric S. Raymond\n"
|
|
||||||
#else
|
|
||||||
#define VersionStr PROGRAM_NAME " IBMPC " GIF_LIB_VERSION \
|
|
||||||
" Eric S. Raymond, " __DATE__ ", " \
|
|
||||||
__TIME__ "\n" "(C) Copyright 1997 Eric S. Raymond\n"
|
|
||||||
#endif /* SYSV */
|
|
||||||
|
|
||||||
#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;
|
|
||||||
} GifFilePrivateType;
|
|
||||||
|
|
||||||
extern int _GifError;
|
|
||||||
|
|
||||||
#endif /* _GIF_LIB_PRIVATE_H */
|
|
|
@ -1,443 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
* "Gif-Lib" - Yet another gif library.
|
|
||||||
*
|
|
||||||
* Written by: Gershon Elber Ver 0.1, Jun. 1989
|
|
||||||
* Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992
|
|
||||||
*****************************************************************************
|
|
||||||
* GIF construction tools
|
|
||||||
*****************************************************************************
|
|
||||||
* History:
|
|
||||||
* 15 Sep 92 - Version 1.0 by Eric Raymond.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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
|
|
||||||
BitSize(int n) {
|
|
||||||
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
for (i = 1; i <= 8; i++)
|
|
||||||
if ((1 << i) >= n)
|
|
||||||
break;
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Color map object functions
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a color map of given size; initialize with contents of
|
|
||||||
* ColorMap if that pointer is non-NULL.
|
|
||||||
*/
|
|
||||||
ColorMapObject *
|
|
||||||
MakeMapObject(int ColorCount,
|
|
||||||
const GifColorType * ColorMap) {
|
|
||||||
|
|
||||||
ColorMapObject *Object;
|
|
||||||
|
|
||||||
/*** FIXME: Our ColorCount has to be a power of two. Is it necessary to
|
|
||||||
* make the user know that or should we automatically round up instead? */
|
|
||||||
if (ColorCount != (1 << BitSize(ColorCount))) {
|
|
||||||
return ((ColorMapObject *) NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
|
|
||||||
if (Object == (ColorMapObject *) NULL) {
|
|
||||||
return ((ColorMapObject *) NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
|
|
||||||
if (Object->Colors == (GifColorType *) NULL) {
|
|
||||||
return ((ColorMapObject *) NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object->ColorCount = ColorCount;
|
|
||||||
Object->BitsPerPixel = BitSize(ColorCount);
|
|
||||||
|
|
||||||
if (ColorMap) {
|
|
||||||
memcpy((char *)Object->Colors,
|
|
||||||
(char *)ColorMap, ColorCount * sizeof(GifColorType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Free a color map object
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
FreeMapObject(ColorMapObject * Object) {
|
|
||||||
|
|
||||||
if (Object != NULL) {
|
|
||||||
free(Object->Colors);
|
|
||||||
free(Object);
|
|
||||||
/*** FIXME:
|
|
||||||
* When we are willing to break API we need to make this function
|
|
||||||
* FreeMapObject(ColorMapObject **Object)
|
|
||||||
* and do this assignment to NULL here:
|
|
||||||
* *Object = NULL;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void
|
|
||||||
DumpColorMap(ColorMapObject * Object,
|
|
||||||
FILE * fp) {
|
|
||||||
|
|
||||||
if (Object) {
|
|
||||||
int i, j, Len = Object->ColorCount;
|
|
||||||
|
|
||||||
for (i = 0; i < Len; i += 4) {
|
|
||||||
for (j = 0; j < 4 && j < Len; j++) {
|
|
||||||
fprintf(fp, "%3d: %02x %02x %02x ", i + j,
|
|
||||||
Object->Colors[i + j].Red,
|
|
||||||
Object->Colors[i + j].Green,
|
|
||||||
Object->Colors[i + j].Blue);
|
|
||||||
}
|
|
||||||
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 ColorUnion color map table.
|
|
||||||
*/
|
|
||||||
ColorMapObject *
|
|
||||||
UnionColorMap(const ColorMapObject * ColorIn1,
|
|
||||||
const ColorMapObject * ColorIn2,
|
|
||||||
GifPixelType ColorTransIn2[]) {
|
|
||||||
|
|
||||||
int i, j, CrntSlot, RoundUpTo, NewBitSize;
|
|
||||||
ColorMapObject *ColorUnion;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate table which will hold the result for sure.
|
|
||||||
*/
|
|
||||||
ColorUnion = MakeMapObject(MAX(ColorIn1->ColorCount,
|
|
||||||
ColorIn2->ColorCount) * 2, NULL);
|
|
||||||
|
|
||||||
if (ColorUnion == NULL)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
/* Copy ColorIn1 to ColorUnionSize; */
|
|
||||||
/*** FIXME: What if there are duplicate entries into the colormap to begin
|
|
||||||
* with? */
|
|
||||||
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 ColorUnionSize (use old colors if they exist): */
|
|
||||||
for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
|
|
||||||
/* Let's see if this color already exists: */
|
|
||||||
/*** FIXME: Will it ever occur that ColorIn2 will contain duplicate
|
|
||||||
* entries? So we should search from 0 to CrntSlot rather than
|
|
||||||
* ColorIn1->ColorCount?
|
|
||||||
*/
|
|
||||||
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) {
|
|
||||||
FreeMapObject(ColorUnion);
|
|
||||||
return ((ColorMapObject *) NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
NewBitSize = BitSize(CrntSlot);
|
|
||||||
RoundUpTo = (1 << NewBitSize);
|
|
||||||
|
|
||||||
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)
|
|
||||||
ColorUnion->Colors = (GifColorType *)realloc(Map,
|
|
||||||
sizeof(GifColorType) * RoundUpTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorUnion->ColorCount = RoundUpTo;
|
|
||||||
ColorUnion->BitsPerPixel = NewBitSize;
|
|
||||||
|
|
||||||
return (ColorUnion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Apply a given color translation to the raster bits of an image
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ApplyTranslation(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
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
MakeExtension(SavedImage * New,
|
|
||||||
int Function) {
|
|
||||||
|
|
||||||
New->Function = Function;
|
|
||||||
/*** FIXME:
|
|
||||||
* Someday we might have to deal with multiple extensions.
|
|
||||||
* ??? Was this a note from Gershon or from me? Does the multiple
|
|
||||||
* extension blocks solve this or do we need multiple Functions? Or is
|
|
||||||
* this an obsolete function? (People should use AddExtensionBlock
|
|
||||||
* instead?)
|
|
||||||
* Looks like AddExtensionBlock needs to take the int Function argument
|
|
||||||
* then it can take the place of this function. Right now people have to
|
|
||||||
* use both. Fix AddExtensionBlock and add this to the deprecation list.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
AddExtensionBlock(SavedImage * New,
|
|
||||||
int Len,
|
|
||||||
unsigned char ExtData[]) {
|
|
||||||
|
|
||||||
ExtensionBlock *ep;
|
|
||||||
|
|
||||||
if (New->ExtensionBlocks == NULL)
|
|
||||||
New->ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
|
|
||||||
else
|
|
||||||
New->ExtensionBlocks = (ExtensionBlock *)realloc(New->ExtensionBlocks,
|
|
||||||
sizeof(ExtensionBlock) *
|
|
||||||
(New->ExtensionBlockCount + 1));
|
|
||||||
|
|
||||||
if (New->ExtensionBlocks == NULL)
|
|
||||||
return (GIF_ERROR);
|
|
||||||
|
|
||||||
ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
|
|
||||||
|
|
||||||
ep->ByteCount=Len;
|
|
||||||
ep->Bytes = (char *)malloc(ep->ByteCount);
|
|
||||||
if (ep->Bytes == NULL)
|
|
||||||
return (GIF_ERROR);
|
|
||||||
|
|
||||||
if (ExtData) {
|
|
||||||
memcpy(ep->Bytes, ExtData, Len);
|
|
||||||
ep->Function = New->Function;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (GIF_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FreeExtension(SavedImage * Image)
|
|
||||||
{
|
|
||||||
ExtensionBlock *ep;
|
|
||||||
|
|
||||||
if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (ep = Image->ExtensionBlocks;
|
|
||||||
ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++)
|
|
||||||
(void)free((char *)ep->Bytes);
|
|
||||||
free((char *)Image->ExtensionBlocks);
|
|
||||||
Image->ExtensionBlocks = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* 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) {
|
|
||||||
FreeMapObject(sp->ImageDesc.ColorMap);
|
|
||||||
sp->ImageDesc.ColorMap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Deallocate the image data */
|
|
||||||
if (sp->RasterBits)
|
|
||||||
free((char *)sp->RasterBits);
|
|
||||||
|
|
||||||
/* Deallocate any extensions */
|
|
||||||
if (sp->ExtensionBlocks)
|
|
||||||
FreeExtension(sp);
|
|
||||||
|
|
||||||
/*** 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 FreeSavedImages 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 *
|
|
||||||
MakeSavedImage(GifFileType * GifFile,
|
|
||||||
const SavedImage * CopyFrom) {
|
|
||||||
|
|
||||||
SavedImage *sp;
|
|
||||||
|
|
||||||
if (GifFile->SavedImages == NULL)
|
|
||||||
GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
|
|
||||||
else
|
|
||||||
GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
|
|
||||||
sizeof(SavedImage) * (GifFile->ImageCount + 1));
|
|
||||||
|
|
||||||
if (GifFile->SavedImages == NULL)
|
|
||||||
return ((SavedImage *)NULL);
|
|
||||||
else {
|
|
||||||
sp = &GifFile->SavedImages[GifFile->ImageCount++];
|
|
||||||
memset((char *)sp, '\0', sizeof(SavedImage));
|
|
||||||
|
|
||||||
if (CopyFrom) {
|
|
||||||
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) {
|
|
||||||
sp->ImageDesc.ColorMap = MakeMapObject(
|
|
||||||
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 *)malloc(sizeof(GifPixelType) *
|
|
||||||
CopyFrom->ImageDesc.Height *
|
|
||||||
CopyFrom->ImageDesc.Width);
|
|
||||||
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) {
|
|
||||||
sp->ExtensionBlocks = (ExtensionBlock *)malloc(
|
|
||||||
sizeof(ExtensionBlock) *
|
|
||||||
CopyFrom->ExtensionBlockCount);
|
|
||||||
if (sp->ExtensionBlocks == NULL) {
|
|
||||||
FreeLastSavedImage(GifFile);
|
|
||||||
return (SavedImage *)(NULL);
|
|
||||||
}
|
|
||||||
memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,
|
|
||||||
sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For the moment, the actual blocks can take their
|
|
||||||
* chances with free(). We'll fix this later.
|
|
||||||
*** FIXME: [Better check this out... Toshio]
|
|
||||||
* 2004 May 27: Looks like this was an ESR note.
|
|
||||||
* It means the blocks are shallow copied from InFile to
|
|
||||||
* OutFile. However, I don't see that in this code....
|
|
||||||
* Did ESR fix it but never remove this note (And other notes
|
|
||||||
* in gifspnge?)
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (sp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FreeSavedImages(GifFileType * GifFile) {
|
|
||||||
|
|
||||||
SavedImage *sp;
|
|
||||||
|
|
||||||
if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (sp = GifFile->SavedImages;
|
|
||||||
sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
|
|
||||||
if (sp->ImageDesc.ColorMap) {
|
|
||||||
FreeMapObject(sp->ImageDesc.ColorMap);
|
|
||||||
sp->ImageDesc.ColorMap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sp->RasterBits)
|
|
||||||
free((char *)sp->RasterBits);
|
|
||||||
|
|
||||||
if (sp->ExtensionBlocks)
|
|
||||||
FreeExtension(sp);
|
|
||||||
}
|
|
||||||
free((char *)GifFile->SavedImages);
|
|
||||||
GifFile->SavedImages=NULL;
|
|
||||||
}
|
|
|
@ -1,126 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of the PhantomJS project from Ofi Labs.
|
|
||||||
|
|
||||||
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the <organization> nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gifwriter.h"
|
|
||||||
|
|
||||||
#include "gif_lib.h"
|
|
||||||
|
|
||||||
#include <QImage>
|
|
||||||
#include <QFile>
|
|
||||||
|
|
||||||
static int saveGifBlock(GifFileType *gif, const GifByteType *data, int i)
|
|
||||||
{
|
|
||||||
QFile *file = (QFile*)(gif->UserData);
|
|
||||||
return file->write((const char*)data, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool exportGif(const QImage &img, const QString &fileName)
|
|
||||||
{
|
|
||||||
QFile file;
|
|
||||||
file.setFileName(fileName);
|
|
||||||
if (!file.open(QFile::WriteOnly)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage image = img;
|
|
||||||
|
|
||||||
int dim = image.width() * image.height();
|
|
||||||
GifByteType *rBuffer = new GifByteType[dim];
|
|
||||||
GifByteType *gBuffer = new GifByteType[dim];
|
|
||||||
GifByteType *bBuffer = new GifByteType[dim];
|
|
||||||
for (int i = 0; i < image.width(); ++i) {
|
|
||||||
for (int j = 0; j < image.height(); ++j) {
|
|
||||||
QRgb color = image.pixel(i, j);
|
|
||||||
rBuffer[i + j * image.width()] = qRed(color);
|
|
||||||
gBuffer[i + j * image.width()] = qGreen(color);
|
|
||||||
bBuffer[i + j * image.width()] = qBlue(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ColorMapSize = 255;
|
|
||||||
ColorMapObject cmap;
|
|
||||||
cmap.ColorCount = ColorMapSize;
|
|
||||||
cmap.BitsPerPixel = 8;
|
|
||||||
cmap.Colors = new GifColorType[ColorMapSize];
|
|
||||||
GifByteType *outputBuffer = new GifByteType[dim];
|
|
||||||
QuantizeBuffer(image.width(), image.height(), &ColorMapSize,
|
|
||||||
rBuffer, gBuffer, bBuffer, outputBuffer, cmap.Colors);
|
|
||||||
|
|
||||||
QVector<QRgb> colorTable;
|
|
||||||
colorTable.reserve(256);
|
|
||||||
for (int i = 0; i < ColorMapSize; ++i) {
|
|
||||||
GifColorType color = cmap.Colors[i];
|
|
||||||
colorTable += qRgb(color.Red, color.Green, color.Blue);
|
|
||||||
}
|
|
||||||
colorTable += qRgba(0, 0, 0, 0);
|
|
||||||
while (colorTable.count() < 256)
|
|
||||||
colorTable += qRgb(0, 0, 0);
|
|
||||||
|
|
||||||
delete [] outputBuffer;
|
|
||||||
delete [] rBuffer;
|
|
||||||
delete [] gBuffer;
|
|
||||||
delete [] bBuffer;
|
|
||||||
|
|
||||||
image = image.convertToFormat(QImage::Format_Indexed8, colorTable);
|
|
||||||
|
|
||||||
colorTable = image.colorTable();
|
|
||||||
cmap.ColorCount = 256;
|
|
||||||
cmap.BitsPerPixel = 8;
|
|
||||||
int bgcolor = -1;
|
|
||||||
for (int c = 0; c < 256; ++c) {
|
|
||||||
cmap.Colors[c].Red = qRed(colorTable[c]);
|
|
||||||
cmap.Colors[c].Green = qGreen(colorTable[c]);
|
|
||||||
cmap.Colors[c].Blue = qBlue(colorTable[c]);
|
|
||||||
if (qAlpha(colorTable[c]) == 0)
|
|
||||||
bgcolor = c;
|
|
||||||
}
|
|
||||||
EGifSetGifVersion("87a");
|
|
||||||
|
|
||||||
GifFileType *gif = EGifOpen(&file, saveGifBlock);
|
|
||||||
gif->ImageCount = 1;
|
|
||||||
EGifPutScreenDesc(gif, image.width(), image.height(), 256, 0, &cmap);
|
|
||||||
if (bgcolor >= 0) {
|
|
||||||
char extension[] = { 1, 0, 0, bgcolor };
|
|
||||||
EGifPutExtension(gif, GRAPHICS_EXT_FUNC_CODE, 4, extension);
|
|
||||||
}
|
|
||||||
EGifPutImageDesc(gif, 0, 0, image.width(), image.height(), 0, &cmap);
|
|
||||||
|
|
||||||
for (int y = 0; y < image.height(); ++y) {
|
|
||||||
if (EGifPutLine(gif, (GifPixelType*)(image.scanLine(y)), img.width()) == GIF_ERROR) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EGifCloseFile(gif);
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
delete [] cmap.Colors;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of the PhantomJS project from Ofi Labs.
|
|
||||||
|
|
||||||
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the <organization> nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GIFWRITER_H
|
|
||||||
#define GIFWRITER_H
|
|
||||||
|
|
||||||
#include <QImage>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
bool exportGif(const QImage &image, const QString &fileName);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,330 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
* "Gif-Lib" - Yet another gif library.
|
|
||||||
*
|
|
||||||
* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989
|
|
||||||
******************************************************************************
|
|
||||||
* Module to quatize high resolution image into lower one. You may want to
|
|
||||||
* peek into the following article this code is based on:
|
|
||||||
* "Color Image Quantization for frame buffer Display", by Paul Heckbert
|
|
||||||
* SIGGRAPH 1982 page 297-307.
|
|
||||||
******************************************************************************
|
|
||||||
* History:
|
|
||||||
* 5 Jan 90 - Version 1.0 by Gershon Elber.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __MSDOS__
|
|
||||||
#include <dos.h>
|
|
||||||
#include <alloc.h>
|
|
||||||
#include <graphics.h>
|
|
||||||
#endif /* __MSDOS__ */
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "gif_lib.h"
|
|
||||||
#include "gif_lib_private.h"
|
|
||||||
|
|
||||||
#define ABS(x) ((x) > 0 ? (x) : (-(x)))
|
|
||||||
|
|
||||||
/* The colors are stripped to 5 bits per primary color if non MSDOS system
|
|
||||||
* or to 4 (not enough memory...) if MSDOS as first step.
|
|
||||||
*/
|
|
||||||
#ifdef __MSDOS__
|
|
||||||
#define COLOR_ARRAY_SIZE 4096
|
|
||||||
#define BITS_PER_PRIM_COLOR 4
|
|
||||||
#define MAX_PRIM_COLOR 0x0f
|
|
||||||
#else
|
|
||||||
#define COLOR_ARRAY_SIZE 2097152
|
|
||||||
#define BITS_PER_PRIM_COLOR 7
|
|
||||||
#define MAX_PRIM_COLOR 0x7f
|
|
||||||
#endif /* __MSDOS__ */
|
|
||||||
|
|
||||||
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 VoidPtr Entry1, const VoidPtr 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 succesfull, GIF_ERROR otherwise.
|
|
||||||
******************************************************************************/
|
|
||||||
int
|
|
||||||
QuantizeBuffer(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) {
|
|
||||||
_GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
|
|
||||||
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;
|
|
||||||
} else
|
|
||||||
fprintf(stderr,
|
|
||||||
"\n%s: Null entry in quantized color map - that's weird.\n",
|
|
||||||
PROGRAM_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
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 ((Sum -= QuantizedColor->Pnext->Count) >= 0 &&
|
|
||||||
QuantizedColor->Pnext != NULL &&
|
|
||||||
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 */
|
|
||||||
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 to entries.
|
|
||||||
****************************************************************************/
|
|
||||||
static int
|
|
||||||
SortCmpRtn(const VoidPtr Entry1,
|
|
||||||
const VoidPtr Entry2) {
|
|
||||||
|
|
||||||
return (*((QuantizedColorType **) Entry1))->RGB[SortRGBAxis] -
|
|
||||||
(*((QuantizedColorType **) Entry2))->RGB[SortRGBAxis];
|
|
||||||
}
|
|
|
@ -62,7 +62,6 @@ OTHER_FILES += \
|
||||||
modules/cookiejar.js \
|
modules/cookiejar.js \
|
||||||
repl.js
|
repl.js
|
||||||
|
|
||||||
include(gif/gif.pri)
|
|
||||||
include(mongoose/mongoose.pri)
|
include(mongoose/mongoose.pri)
|
||||||
include(linenoise/linenoise.pri)
|
include(linenoise/linenoise.pri)
|
||||||
include(qcommandline/qcommandline.pri)
|
include(qcommandline/qcommandline.pri)
|
||||||
|
|
|
@ -56,8 +56,6 @@
|
||||||
#include <QImageWriter>
|
#include <QImageWriter>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include <gifwriter.h>
|
|
||||||
|
|
||||||
#include "phantom.h"
|
#include "phantom.h"
|
||||||
#include "networkaccessmanager.h"
|
#include "networkaccessmanager.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -922,9 +920,6 @@ bool WebPage::render(const QString &fileName, const QVariantMap &option)
|
||||||
else if (fileName.endsWith(".pdf", Qt::CaseInsensitive) ){
|
else if (fileName.endsWith(".pdf", Qt::CaseInsensitive) ){
|
||||||
format = "pdf";
|
format = "pdf";
|
||||||
}
|
}
|
||||||
else if (fileName.endsWith(".gif", Qt::CaseInsensitive) ){
|
|
||||||
format = "gif";
|
|
||||||
}
|
|
||||||
|
|
||||||
if( option.contains("quality") ){
|
if( option.contains("quality") ){
|
||||||
quality = option.value("quality").toInt();
|
quality = option.value("quality").toInt();
|
||||||
|
@ -934,10 +929,6 @@ bool WebPage::render(const QString &fileName, const QVariantMap &option)
|
||||||
if ( format == "pdf" ){
|
if ( format == "pdf" ){
|
||||||
retval = renderPdf(outFileName);
|
retval = renderPdf(outFileName);
|
||||||
}
|
}
|
||||||
else if ( format == "gif" ) {
|
|
||||||
QImage rawPageRendering = renderImage();
|
|
||||||
retval = exportGif(rawPageRendering, outFileName);
|
|
||||||
}
|
|
||||||
else{
|
else{
|
||||||
QImage rawPageRendering = renderImage();
|
QImage rawPageRendering = renderImage();
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 23 KiB |
|
@ -2210,14 +2210,6 @@ xdescribe("WebPage render image", function(){
|
||||||
render_test("pdf", { format: "pdf" });
|
render_test("pdf", { format: "pdf" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render GIF file", function(){
|
|
||||||
render_test("gif");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should render GIF file with format option", function(){
|
|
||||||
render_test("gif", { format: "gif" });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should render PNG file", function(){
|
it("should render PNG file", function(){
|
||||||
render_test("png");
|
render_test("png");
|
||||||
});
|
});
|
||||||
|
|
|
@ -35,10 +35,6 @@ QCommandLine - http://xf.iksaif.net/dev/qcommandline.html
|
||||||
License: GNU Lesser General Public License (LGPL) version 2.1.
|
License: GNU Lesser General Public License (LGPL) version 2.1.
|
||||||
Reference: http://dev.iksaif.net/projects/qcommandline/repository/revisions/master/entry/COPYING
|
Reference: http://dev.iksaif.net/projects/qcommandline/repository/revisions/master/entry/COPYING
|
||||||
|
|
||||||
GIFLIB - http://giflib.sourceforge.net/
|
|
||||||
License: MIT
|
|
||||||
Reference: http://giflib.cvs.sourceforge.net/viewvc/giflib/giflib/COPYING
|
|
||||||
|
|
||||||
wkhtmlpdf - http://code.google.com/p/wkhtmltopdf/
|
wkhtmlpdf - http://code.google.com/p/wkhtmltopdf/
|
||||||
License: GNU Lesser General Public License (LGPL)
|
License: GNU Lesser General Public License (LGPL)
|
||||||
Reference: http://code.google.com/p/wkhtmltopdf/
|
Reference: http://code.google.com/p/wkhtmltopdf/
|
||||||
|
|
Loading…
Reference in New Issue