GIFWriter.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "GIFWriter.h"
  2. #include "api__gif.h"
  3. #include <wchar.h>
  4. #include <bfc/platform/strcmp.h>
  5. extern "C" {
  6. #include "gif_lib.h"
  7. };
  8. // valid items include "quality" for jpeg files with value "0" to "100"
  9. // return value is 1 if the config item is supported, 0 if it is not.
  10. int GIFWriter::setConfig(const wchar_t * item, const wchar_t * value) {
  11. return 0; // no config yet
  12. }
  13. // valid items include "quality" for jpeg files with value "0" to "100", "lossless" returns "1" if it is "0" otherwise
  14. // return value is 1 if the config item is supported, 0 if it is not.
  15. int GIFWriter::getConfig(const wchar_t * item, wchar_t * value, int valuelen) {
  16. if(!_wcsicmp(item,L"lossless")) lstrcpynW(value,L"0",valuelen);
  17. else return 0;
  18. return 1;
  19. }
  20. // returns 1 if the bit depth is supported (eg 32 for ARGB32, 24 for RGB24)
  21. // ARGB32 MUST be supported
  22. int GIFWriter::bitDepthSupported(int depth) {
  23. if(depth == 32 || depth == 24) return 1;
  24. return 0;
  25. }
  26. typedef struct {
  27. BYTE * data;
  28. unsigned int len;
  29. unsigned int alloc;
  30. } writeStruct;
  31. extern "C" int MyOutputFunc(GifFileType * gif, const GifByteType * data, int len) {
  32. writeStruct * p = (writeStruct *)gif->UserData;
  33. while (len + p->len > p->alloc) { // allocate more memory
  34. int d = ((p->alloc / 4) & 0xffffff00) + 0x100;
  35. if(d < 4096) d = 4096;
  36. p->alloc+=d;
  37. p->data = (BYTE*)WASABI_API_MEMMGR->sysRealloc(p->data,p->alloc);
  38. }
  39. memcpy(p->data+p->len,data,len);
  40. p->len += len;
  41. return len;
  42. }
  43. // returns the image in our format, free the returned buffer with api_memmgr::sysFree()
  44. void * GIFWriter::convert(const void *pixels, int bitDepth, int w, int h, int *length) {
  45. // split into planes
  46. BYTE *redplane, *blueplane, *greenplane;
  47. redplane = (BYTE *)malloc(w*h*sizeof(BYTE));
  48. greenplane = (BYTE *)malloc(w*h*sizeof(BYTE));
  49. blueplane = (BYTE *)malloc(w*h*sizeof(BYTE));
  50. BYTE * px = (BYTE *)pixels;
  51. BYTE * end = px + (w * h * (bitDepth/8));
  52. int i=0;
  53. if(bitDepth == 24) {
  54. while(px < end) {
  55. blueplane[i] = *(px++);
  56. greenplane[i] = *(px++);
  57. redplane[i] = *(px++);
  58. i++;
  59. }
  60. } else if(bitDepth == 32) {
  61. while(px < end) {
  62. blueplane[i] = *(px++);
  63. greenplane[i] = *(px++);
  64. redplane[i] = *(px++);
  65. px++;
  66. i++;
  67. }
  68. }
  69. // make a color map
  70. int colormapsize = 256;
  71. ColorMapObject * OutputColorMap = GifMakeMapObject(colormapsize, NULL);
  72. BYTE* OutputBuffer = (GifByteType *) malloc(w * h * sizeof(GifByteType));
  73. // this is actually kinda crappy
  74. GifQuantizeBuffer(w,h,&colormapsize,redplane,greenplane,blueplane,OutputBuffer,OutputColorMap->Colors);
  75. unsigned int alloc = ((w*h / 3) & 0xffffff00) + 0x100; // guess at output file size
  76. if(alloc < 4096) alloc = 4096;
  77. writeStruct write = {(BYTE*)WASABI_API_MEMMGR->sysMalloc(alloc),0,alloc};
  78. bool succeeded=false;
  79. // write the file out
  80. int* l_error = NULL;
  81. GifFileType *gif = EGifOpen(&write,MyOutputFunc, l_error);
  82. if(gif) {
  83. if(EGifPutScreenDesc(gif,w, h, 8, 0, OutputColorMap)) {
  84. if(EGifPutImageDesc(gif, 0, 0, w, h, FALSE, NULL)) {
  85. BYTE * p = OutputBuffer;
  86. succeeded=true;
  87. for (int i = 0; i < h; i++) {
  88. if(!EGifPutLine(gif, p, w)) {succeeded=false; break;}
  89. p+=w;
  90. }
  91. }
  92. }
  93. EGifCloseFile(gif, l_error);
  94. }
  95. // done!
  96. free(OutputBuffer);
  97. free(redplane);
  98. free(greenplane);
  99. free(blueplane);
  100. if(succeeded) {
  101. *length = write.len;
  102. return write.data;
  103. } else return 0;
  104. }
  105. #define CBCLASS GIFWriter
  106. START_DISPATCH;
  107. CB(GETIMAGETYPENAME, getImageTypeName);
  108. CB(GETEXTENSIONS, getExtensions);
  109. CB(SETCONFIG, setConfig);
  110. CB(GETCONFIG, getConfig);
  111. CB(BITDEPTHSUPPORTED, bitDepthSupported);
  112. CB(CONVERT, convert);
  113. END_DISPATCH;
  114. #undef CBCLASS