[release] version bump to 13.0 beta1
[vuplus_xbmc] / lib / cximage-6.0 / CxImage / DllInterface.cpp
1 #ifdef _DLL
2 #include "ximage.h"
3 #include "ximajpg.h"
4
5 #if defined(_LINUX) || defined(__APPLE__)
6 #include <unistd.h>
7 #include <sys/stat.h>
8 #include <errno.h>
9 #define strcmpi strcasecmp
10 #else //win32
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
14 #define strcmpi _strcmpi
15 #endif
16
17 #define RESAMPLE_QUALITY 0
18 #undef USE_EXIF_THUMBS
19
20 extern "C" struct ImageInfo
21 {
22   unsigned int width;
23   unsigned int height;
24   unsigned int originalwidth;
25   unsigned int originalheight;
26   EXIFINFO exifInfo;
27   BYTE *texture;
28   void *context;
29   BYTE *alpha;
30 };
31
32 // helper functions
33
34 // determines based on file extension the type of file
35 DWORD GetImageType(const char *file)
36
37   if ( !file || ( 0 == *file ) ) // ensure file is not NULL and has non-zero length
38     return CXIMAGE_FORMAT_UNKNOWN;
39
40   // try to determine extension using '.' or use entire filename
41   // if '.' is absent.
42   const char *ext = strrchr(file, '.');
43   if (ext == NULL)
44     ext = (char*)file;
45   else
46     ext++;
47
48   if ( 0 == *ext ) // if filename ends in '.', we can't identify based on extension
49     return CXIMAGE_FORMAT_UNKNOWN;
50
51   if ( 0 == strcmpi(ext, "bmp") ) return CXIMAGE_FORMAT_BMP;
52   else if ( 0 == strcmpi(ext, "bitmap") ) return CXIMAGE_FORMAT_BMP;
53   else if ( 0 == strcmpi(ext, "gif") )    return CXIMAGE_FORMAT_GIF;
54   else if ( 0 == strcmpi(ext, "jpg") )    return CXIMAGE_FORMAT_JPG;
55   else if ( 0 == strcmpi(ext, "tbn") )    return CXIMAGE_FORMAT_JPG;
56   else if ( 0 == strcmpi(ext, "jpeg") )   return CXIMAGE_FORMAT_JPG;
57   else if ( 0 == strcmpi(ext, "png") )    return CXIMAGE_FORMAT_PNG;
58   else if ( 0 == strcmpi(ext, "ico") )    return CXIMAGE_FORMAT_ICO;
59   else if ( 0 == strcmpi(ext, "tif") )    return CXIMAGE_FORMAT_TIF;
60   else if ( 0 == strcmpi(ext, "tiff") )   return CXIMAGE_FORMAT_TIF;
61   else if ( 0 == strcmpi(ext, "tga") )    return CXIMAGE_FORMAT_TGA;
62   else if ( 0 == strcmpi(ext, "pcx") )    return CXIMAGE_FORMAT_PCX;
63
64   // RAW camera formats
65   else if ( 0 == strcmpi(ext, "cr2") ) return CXIMAGE_FORMAT_RAW;  
66   else if ( 0 == strcmpi(ext, "nef") ) return CXIMAGE_FORMAT_RAW;
67   else if ( 0 == strcmpi(ext, "dng") ) return CXIMAGE_FORMAT_RAW;
68   else if ( 0 == strcmpi(ext, "crw") ) return CXIMAGE_FORMAT_RAW;
69   else if ( 0 == strcmpi(ext, "orf") ) return CXIMAGE_FORMAT_RAW;
70   else if ( 0 == strcmpi(ext, "arw") ) return CXIMAGE_FORMAT_RAW;
71   else if ( 0 == strcmpi(ext, "erf") ) return CXIMAGE_FORMAT_RAW;
72   else if ( 0 == strcmpi(ext, "3fr") ) return CXIMAGE_FORMAT_RAW;
73   else if ( 0 == strcmpi(ext, "dcr") ) return CXIMAGE_FORMAT_RAW;
74   else if ( 0 == strcmpi(ext, "x3f") ) return CXIMAGE_FORMAT_RAW;
75   else if ( 0 == strcmpi(ext, "mef") ) return CXIMAGE_FORMAT_RAW;
76   else if ( 0 == strcmpi(ext, "raf") ) return CXIMAGE_FORMAT_RAW;
77   else if ( 0 == strcmpi(ext, "mrw") ) return CXIMAGE_FORMAT_RAW;
78   else if ( 0 == strcmpi(ext, "pef") ) return CXIMAGE_FORMAT_RAW;
79   else if ( 0 == strcmpi(ext, "sr2") ) return CXIMAGE_FORMAT_RAW;
80
81   // fallback to unknown
82   return CXIMAGE_FORMAT_UNKNOWN;
83 }
84
85 int DetectFileType(const BYTE* pBuffer, int nBufSize)
86 {
87   if (nBufSize <= 5)
88     return CXIMAGE_FORMAT_UNKNOWN;
89   if (pBuffer[1] == 'P' && pBuffer[2] == 'N' && pBuffer[3] == 'G')
90     return CXIMAGE_FORMAT_PNG;
91   if (pBuffer[0] == 'B' && pBuffer[1] == 'M')
92     return CXIMAGE_FORMAT_BMP;
93   if (pBuffer[0] == 0xFF && pBuffer[1] == 0xD8 && pBuffer[2] == 0xFF)
94     // don't include the last APP0 byte (0xE0), as some (non-conforming) JPEG/JFIF files might have some other
95     // APPn-specific data here, and we should skip over this.
96     return CXIMAGE_FORMAT_JPG;
97   return CXIMAGE_FORMAT_UNKNOWN;
98 }
99
100 int ResampleKeepAspect(CxImage &image, unsigned int width, unsigned int height)
101 {
102   bool bResize = false;
103   float fAspect = ((float)image.GetWidth()) / ((float)image.GetHeight());
104   unsigned int newwidth = image.GetWidth();
105   unsigned int newheight = image.GetHeight();
106   if (newwidth > width)
107   {
108     bResize = true;
109     newwidth = width;
110     newheight = (DWORD)( ( (float)newwidth) / fAspect);
111   }
112   if (newheight > height)
113   {
114     bResize = true;
115     newheight = height;
116     newwidth = (DWORD)( fAspect * ( (float)newheight) );
117   }
118   if (bResize)
119   {
120     if (!image.Resample(newwidth, newheight, RESAMPLE_QUALITY) || !image.IsValid())
121     {
122       printf("PICTURE::SaveThumb: Unable to resample picture: Error:%s\n", image.GetLastError());
123       return -1;
124     }
125   }
126   return bResize ? 1 : 0;
127 }
128
129 #ifdef LoadImage
130 #undef LoadImage
131 #endif
132
133 #if defined(_LINUX) || defined(__APPLE__)
134 #define __declspec(x) 
135 #endif
136
137 extern "C"
138 {
139   bool IsDir(const char* file)
140   {
141     struct stat holder;
142     if (stat(file, &holder) == -1)
143       return false;
144     if (S_ISDIR(holder.st_mode))
145       return true;
146
147     return false;
148   }
149
150   __declspec(dllexport) bool ReleaseImage(ImageInfo *info) 
151   {
152     if (info && info->context)
153     {
154       delete ((CxImage *)info->context);
155       return true;
156     }
157
158           return false;
159   }
160
161   __declspec(dllexport) bool LoadImage(const char *file, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
162   {
163     if (!file || !info) return false;
164
165         if (IsDir(file))
166                 return false;
167
168           // load the image
169     DWORD dwImageType = GetImageType(file);
170     CxImage *image = new CxImage(dwImageType);
171     if (!image) return false;
172
173     int actualwidth = maxwidth;
174     int actualheight = maxheight;
175     try
176     {
177       if (!image->Load(file, dwImageType, actualwidth, actualheight) || !image->IsValid())
178       {
179 #if !defined(_LINUX) && !defined(__APPLE__)
180             int nErr = GetLastError();
181 #else
182             int nErr = errno;
183 #endif
184         printf("PICTURE::LoadImage: Unable to open image: %s Error:%s (%d)\n", file, image->GetLastError(),nErr);
185         delete image;
186         return false;
187       }
188     }
189     catch (...)
190     {
191       printf("PICTURE::LoadImage: Unable to open image: %s\n", file);
192       delete image;
193       return false;
194     }
195     // ok, now resample the image down if necessary
196     if (ResampleKeepAspect(*image, maxwidth, maxheight) < 0)
197     {
198       printf("PICTURE::LoadImage: Unable to resample picture: %s\n", file);
199       delete image;
200       return false;
201     }
202
203     // make sure our image is 24bit minimum
204     image->IncreaseBpp(24);
205
206     // fill in our struct
207     info->width = image->GetWidth();
208     info->height = image->GetHeight();
209     info->originalwidth = actualwidth;
210     info->originalheight = actualheight;
211     memcpy(&info->exifInfo, image->GetExifInfo(), sizeof(EXIFINFO));
212
213     // create our texture
214     info->context = image;
215     info->texture = image->GetBits();
216     info->alpha = image->AlphaGetBits();
217     return (info->texture != NULL);
218   };
219
220   __declspec(dllexport) bool LoadImageFromMemory(const BYTE *buffer, unsigned int size, const char *mime, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
221   {
222     if (!buffer || !size || !mime || !info) return false;
223
224     // load the image
225     DWORD dwImageType = CXIMAGE_FORMAT_UNKNOWN;
226     if (strlen(mime))
227       dwImageType = GetImageType(mime);
228     if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
229       dwImageType = DetectFileType(buffer, size);
230     if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
231     {
232       printf("PICTURE::LoadImageFromMemory: Unable to determine image type.");
233       return false;
234     }
235
236     CxImage *image = new CxImage(dwImageType);
237     if (!image)
238       return false;
239
240     int actualwidth = maxwidth;
241     int actualheight = maxheight;
242
243     try
244     {
245       bool success = image->Decode((BYTE*)buffer, size, dwImageType, actualwidth, actualheight);
246       if (!success && dwImageType != CXIMAGE_FORMAT_UNKNOWN)
247       { // try to decode with unknown imagetype
248         success = image->Decode((BYTE*)buffer, size, CXIMAGE_FORMAT_UNKNOWN);
249       }
250       if (!success || !image->IsValid())
251       {
252         printf("PICTURE::LoadImageFromMemory: Unable to decode image. Error:%s\n", image->GetLastError());
253         delete image;
254         return false;
255       }
256     }
257     catch (...)
258     {
259       printf("PICTURE::LoadImageFromMemory: Unable to decode image.");
260       delete image;
261       return false;
262     }
263
264     // ok, now resample the image down if necessary
265     if (ResampleKeepAspect(*image, maxwidth, maxheight) < 0)
266     {
267       printf("PICTURE::LoadImage: Unable to resample picture\n");
268       delete image;
269       return false;
270     }
271
272     // make sure our image is 24bit minimum
273     image->IncreaseBpp(24);
274
275     // fill in our struct
276     info->width = image->GetWidth();
277     info->height = image->GetHeight();
278     info->originalwidth = actualwidth;
279     info->originalheight = actualheight;
280     memcpy(&info->exifInfo, image->GetExifInfo(), sizeof(EXIFINFO));
281
282     // create our texture
283     info->context = image;
284     info->texture = image->GetBits();
285     info->alpha = image->AlphaGetBits();
286     return (info->texture != NULL);
287   };
288
289   __declspec(dllexport) bool CreateThumbnailFromSurface(BYTE *buffer, unsigned int width, unsigned int height, unsigned int stride, const char *thumb)
290   {
291     if (!buffer || !thumb) return false;
292     // creates an image, and copies the surface data into it.
293     CxImage image(width, height, 24, CXIMAGE_FORMAT_PNG);
294     if (!image.IsValid()) return false;
295     image.AlphaCreate();
296     if (!image.AlphaIsValid()) return false;
297     bool fullyTransparent(true);
298     bool fullyOpaque(true);
299     for (unsigned int y = 0; y < height; y++)
300     {
301       BYTE *ptr = buffer + (y * stride);
302       for (unsigned int x = 0; x < width; x++)
303       {
304         BYTE b = *ptr++;
305         BYTE g = *ptr++;
306         BYTE r = *ptr++;
307         BYTE a = *ptr++;  // alpha
308         if (a)
309           fullyTransparent = false;
310         if (a != 0xff)
311           fullyOpaque = false;
312         image.SetPixelColor(x, height - 1 - y, RGB(r, g, b));
313         image.AlphaSet(x, height - 1 - y, a);
314       }
315     }
316     if (fullyTransparent || fullyOpaque)
317       image.AlphaDelete();
318     image.SetJpegQuality(90);
319
320     DWORD type;
321     if (image.AlphaIsValid() || GetImageType(thumb) == CXIMAGE_FORMAT_PNG)
322       type = CXIMAGE_FORMAT_PNG;
323     else
324       type = CXIMAGE_FORMAT_JPG;
325
326     if (!image.Save(thumb, type))
327     {
328       printf("PICTURE::CreateThumbnailFromSurface: Unable to save thumb to %s", thumb);
329       return false;
330     }
331     return true;
332   };
333
334   __declspec(dllexport) bool CreateThumbnailFromSurface2(BYTE * bufferin, unsigned int width, unsigned int height, unsigned int stride, const char *thumb, 
335                                                          BYTE * &bufferout, unsigned int &bufferoutSize)
336   {
337     if (!bufferin) return false;
338     // creates an image, and copies the surface data into it.
339     CxImage image(width, height, 24, CXIMAGE_FORMAT_PNG);
340     if (!image.IsValid()) return false;
341     image.AlphaCreate();
342     if (!image.AlphaIsValid()) return false;
343     bool fullyTransparent(true);
344     bool fullyOpaque(true);
345     for (unsigned int y = 0; y < height; y++)
346     {
347       BYTE *ptr = bufferin + (y * stride);
348       for (unsigned int x = 0; x < width; x++)
349       {
350         BYTE b = *ptr++;
351         BYTE g = *ptr++;
352         BYTE r = *ptr++;
353         BYTE a = *ptr++;  // alpha
354         if (a)
355           fullyTransparent = false;
356         if (a != 0xff)
357           fullyOpaque = false;
358         image.SetPixelColor(x, height - 1 - y, RGB(r, g, b));
359         image.AlphaSet(x, height - 1 - y, a);
360       }
361     }
362     if (fullyTransparent || fullyOpaque)
363       image.AlphaDelete();
364     image.SetJpegQuality(90);
365
366     DWORD type;
367     if (image.AlphaIsValid() || GetImageType(thumb) == CXIMAGE_FORMAT_PNG)
368       type = CXIMAGE_FORMAT_PNG;
369     else
370       type = CXIMAGE_FORMAT_JPG;
371
372     long buffout=0;
373
374     if (!image.Encode(bufferout, buffout, type))
375     {
376       printf("PICTURE::CreateThumbnailFromSurface: Unable to save thumb to %s", thumb);
377       return false;
378     }
379     bufferoutSize = buffout;
380     return true;
381   };
382
383   __declspec(dllexport) void    FreeMemory(void* memblock)
384   {
385     if (memblock)
386                   free(memblock);
387   };
388 }
389
390 #endif