123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- #include "GIFWriter.h"
- #include "api__gif.h"
- #include <wchar.h>
- #include <bfc/platform/strcmp.h>
- extern "C" {
- #include "gif_lib.h"
- };
- // valid items include "quality" for jpeg files with value "0" to "100"
- // return value is 1 if the config item is supported, 0 if it is not.
- int GIFWriter::setConfig(const wchar_t * item, const wchar_t * value) {
- return 0; // no config yet
- }
- // valid items include "quality" for jpeg files with value "0" to "100", "lossless" returns "1" if it is "0" otherwise
- // return value is 1 if the config item is supported, 0 if it is not.
- int GIFWriter::getConfig(const wchar_t * item, wchar_t * value, int valuelen) {
- if(!_wcsicmp(item,L"lossless")) lstrcpynW(value,L"0",valuelen);
- else return 0;
- return 1;
- }
- // returns 1 if the bit depth is supported (eg 32 for ARGB32, 24 for RGB24)
- // ARGB32 MUST be supported
- int GIFWriter::bitDepthSupported(int depth) {
- if(depth == 32 || depth == 24) return 1;
- return 0;
- }
- typedef struct {
- BYTE * data;
- unsigned int len;
- unsigned int alloc;
- } writeStruct;
- extern "C" int MyOutputFunc(GifFileType * gif, const GifByteType * data, int len) {
- writeStruct * p = (writeStruct *)gif->UserData;
- while (len + p->len > p->alloc) { // allocate more memory
- int d = ((p->alloc / 4) & 0xffffff00) + 0x100;
- if(d < 4096) d = 4096;
- p->alloc+=d;
- p->data = (BYTE*)WASABI_API_MEMMGR->sysRealloc(p->data,p->alloc);
- }
- memcpy(p->data+p->len,data,len);
- p->len += len;
- return len;
- }
- // returns the image in our format, free the returned buffer with api_memmgr::sysFree()
- void * GIFWriter::convert(const void *pixels, int bitDepth, int w, int h, int *length) {
- // split into planes
- BYTE *redplane, *blueplane, *greenplane;
- redplane = (BYTE *)malloc(w*h*sizeof(BYTE));
- greenplane = (BYTE *)malloc(w*h*sizeof(BYTE));
- blueplane = (BYTE *)malloc(w*h*sizeof(BYTE));
-
- BYTE * px = (BYTE *)pixels;
- BYTE * end = px + (w * h * (bitDepth/8));
- int i=0;
- if(bitDepth == 24) {
- while(px < end) {
- blueplane[i] = *(px++);
- greenplane[i] = *(px++);
- redplane[i] = *(px++);
- i++;
- }
- } else if(bitDepth == 32) {
- while(px < end) {
- blueplane[i] = *(px++);
- greenplane[i] = *(px++);
- redplane[i] = *(px++);
- px++;
- i++;
- }
- }
- // make a color map
- int colormapsize = 256;
- ColorMapObject * OutputColorMap = GifMakeMapObject(colormapsize, NULL);
- BYTE* OutputBuffer = (GifByteType *) malloc(w * h * sizeof(GifByteType));
- // this is actually kinda crappy
- GifQuantizeBuffer(w,h,&colormapsize,redplane,greenplane,blueplane,OutputBuffer,OutputColorMap->Colors);
- unsigned int alloc = ((w*h / 3) & 0xffffff00) + 0x100; // guess at output file size
- if(alloc < 4096) alloc = 4096;
- writeStruct write = {(BYTE*)WASABI_API_MEMMGR->sysMalloc(alloc),0,alloc};
- bool succeeded=false;
- // write the file out
- int* l_error = NULL;
- GifFileType *gif = EGifOpen(&write,MyOutputFunc, l_error);
- if(gif) {
- if(EGifPutScreenDesc(gif,w, h, 8, 0, OutputColorMap)) {
- if(EGifPutImageDesc(gif, 0, 0, w, h, FALSE, NULL)) {
- BYTE * p = OutputBuffer;
- succeeded=true;
- for (int i = 0; i < h; i++) {
- if(!EGifPutLine(gif, p, w)) {succeeded=false; break;}
- p+=w;
- }
- }
- }
- EGifCloseFile(gif, l_error);
- }
- // done!
- free(OutputBuffer);
- free(redplane);
- free(greenplane);
- free(blueplane);
- if(succeeded) {
- *length = write.len;
- return write.data;
- } else return 0;
- }
- #define CBCLASS GIFWriter
- START_DISPATCH;
- CB(GETIMAGETYPENAME, getImageTypeName);
- CB(GETEXTENSIONS, getExtensions);
- CB(SETCONFIG, setConfig);
- CB(GETCONFIG, getConfig);
- CB(BITDEPTHSUPPORTED, bitDepthSupported);
- CB(CONVERT, convert);
- END_DISPATCH;
- #undef CBCLASS
|