aboutsummaryrefslogtreecommitdiff
path: root/Src/gif/GIFWriter.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/gif/GIFWriter.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/gif/GIFWriter.cpp')
-rw-r--r--Src/gif/GIFWriter.cpp127
1 files changed, 127 insertions, 0 deletions
diff --git a/Src/gif/GIFWriter.cpp b/Src/gif/GIFWriter.cpp
new file mode 100644
index 00000000..e1387c4d
--- /dev/null
+++ b/Src/gif/GIFWriter.cpp
@@ -0,0 +1,127 @@
+#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 \ No newline at end of file