GIFLoader.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "GIFLoader.h"
  2. #include "api__gif.h"
  3. #include <wchar.h>
  4. #include <bfc/platform/strcmp.h>
  5. extern "C" {
  6. #include "../giflib/gif_lib.h"
  7. };
  8. static bool StringEnds(const wchar_t *a, const wchar_t *b)
  9. {
  10. size_t aLen = wcslen(a);
  11. size_t bLen = wcslen(b);
  12. if (aLen < bLen) return false; // too short
  13. return !_wcsicmp(a + aLen - bLen, b);
  14. }
  15. int GIFLoader::isMine(const wchar_t *filename)
  16. {
  17. return (filename && StringEnds(filename, L".GIF"));
  18. }
  19. int GIFLoader::getHeaderSize()
  20. {
  21. return 3;
  22. }
  23. const wchar_t *GIFLoader::mimeType()
  24. {
  25. return L"image/gif";
  26. }
  27. int GIFLoader::testData(const void *data, int datalen)
  28. {
  29. if(datalen >= 3 && strncmp((const char*)data,"GIF",3)==0) return 1;
  30. return 0;
  31. }
  32. typedef struct {
  33. BYTE * data;
  34. int len;
  35. } readStruct;
  36. extern "C" int myreader(GifFileType *gif, GifByteType *data, int len) {
  37. readStruct* r = (readStruct*)gif->UserData;
  38. int l = min(len,r->len);
  39. if(l == 0) return 0;
  40. memcpy(data,r->data,l);
  41. r->len -= l;
  42. r->data += l;
  43. return l;
  44. }
  45. ARGB32 *GIFLoader::loadImage(const void *datain, int datalen, int *w, int *h, ifc_xmlreaderparams *params)
  46. {
  47. readStruct read = {(BYTE*)datain,datalen};
  48. int* l_error = NULL;
  49. GifFileType * gif = DGifOpen(&read, myreader, l_error);
  50. if(!gif) return 0;
  51. if(!DGifSlurp(gif) || !gif->ImageCount) { DGifCloseFile(gif, l_error); return 0; }
  52. ColorMapObject *map = gif->SColorMap;
  53. if(!map) map = gif->SavedImages[0].ImageDesc.ColorMap;
  54. if(!map) { DGifCloseFile(gif, l_error); return 0; }
  55. int iw = gif->SavedImages[0].ImageDesc.Width;
  56. int ih = gif->SavedImages[0].ImageDesc.Height;
  57. if(w) *w = iw;
  58. if(h) *h = ih;
  59. ARGB32 * data = (ARGB32 *)WASABI_API_MEMMGR->sysMalloc(iw * ih * sizeof(ARGB32));
  60. ARGB32 * p = data;
  61. ARGB32 * end = data + (iw * ih);
  62. GifPixelType *line = gif->SavedImages[0].RasterBits;
  63. if(gif->SavedImages[0].ImageDesc.Interlace)
  64. {
  65. // The way Interlaced image should be read - offsets and jumps...
  66. const int InterlacedOffset[] = { 0, 4, 2, 1 };
  67. const int InterlacedJumps[] = { 8, 8, 4, 2 };
  68. for(int i = 0; i < 4; i++)
  69. {
  70. for(int j = InterlacedOffset[i]; j < ih; j += InterlacedJumps[i])
  71. {
  72. p = &data[j*iw];
  73. for(int k = 0; k<iw; k++)
  74. {
  75. int px = *(line++);
  76. if(px < map->ColorCount && (px != gif->SBackGroundColor || px == 0)) {
  77. GifColorType& color = map->Colors[px];
  78. *(p++) = 0xff000000 | color.Blue | (color.Green << 8) | (color.Red << 16);
  79. } else
  80. *(p++) = 0;
  81. }
  82. }
  83. }
  84. }
  85. else
  86. {
  87. while(p < end) {
  88. int px = *(line++);
  89. if(px < map->ColorCount && (px != gif->SBackGroundColor || px == 0)) {
  90. GifColorType& color = map->Colors[px];
  91. *(p++) = 0xff000000 | color.Blue | (color.Green << 8) | (color.Red << 16);
  92. } else
  93. *(p++) = 0;
  94. }
  95. }
  96. DGifCloseFile(gif, l_error);
  97. return data;
  98. }
  99. #define CBCLASS GIFLoader
  100. START_DISPATCH;
  101. CB(ISMINE, isMine);
  102. CB(MIMETYPE, mimeType);
  103. CB(TESTDATA, testData);
  104. CB(GETHEADERSIZE, getHeaderSize);
  105. CB(GETDIMENSIONS, getDimensions);
  106. CB(LOADIMAGE, loadImage);
  107. CB(LOADIMAGEDATA, loadImageData);
  108. END_DISPATCH;
  109. #undef CBCLASS