5 #if defined(_LINUX) || defined(__APPLE__)
9 #define strcmpi strcasecmp
11 #include <sys/types.h>
13 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
14 #define strcmpi _strcmpi
17 #define RESAMPLE_QUALITY 0
18 #undef USE_EXIF_THUMBS
20 extern "C" struct ImageInfo
24 unsigned int originalwidth;
25 unsigned int originalheight;
34 // determines based on file extension the type of file
35 DWORD GetImageType(const char *file)
37 if ( !file || ( 0 == *file ) ) // ensure file is not NULL and has non-zero length
38 return CXIMAGE_FORMAT_UNKNOWN;
40 // try to determine extension using '.' or use entire filename
42 const char *ext = strrchr(file, '.');
48 if ( 0 == *ext ) // if filename ends in '.', we can't identify based on extension
49 return CXIMAGE_FORMAT_UNKNOWN;
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;
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;
81 // fallback to unknown
82 return CXIMAGE_FORMAT_UNKNOWN;
85 int DetectFileType(const BYTE* pBuffer, int nBufSize)
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 if (pBuffer[0] == 'G' && pBuffer[1] == 'I' && pBuffer[2] == 'F')
98 return CXIMAGE_FORMAT_GIF;
99 return CXIMAGE_FORMAT_UNKNOWN;
102 int ResampleKeepAspect(CxImage &image, unsigned int width, unsigned int height)
104 bool bResize = false;
105 float fAspect = ((float)image.GetWidth()) / ((float)image.GetHeight());
106 unsigned int newwidth = image.GetWidth();
107 unsigned int newheight = image.GetHeight();
108 if (newwidth > width)
112 newheight = (DWORD)( ( (float)newwidth) / fAspect);
114 if (newheight > height)
118 newwidth = (DWORD)( fAspect * ( (float)newheight) );
122 if (!image.Resample(newwidth, newheight, RESAMPLE_QUALITY) || !image.IsValid())
124 printf("PICTURE::SaveThumb: Unable to resample picture: Error:%s\n", image.GetLastError());
128 return bResize ? 1 : 0;
135 #if defined(_LINUX) || defined(__APPLE__)
136 #define __declspec(x)
141 bool IsDir(const char* file)
144 if (stat(file, &holder) == -1)
146 if (S_ISDIR(holder.st_mode))
152 __declspec(dllexport) bool ReleaseImage(ImageInfo *info)
154 if (info && info->context)
156 delete ((CxImage *)info->context);
163 __declspec(dllexport) bool LoadImage(const char *file, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
165 if (!file || !info) return false;
171 DWORD dwImageType = GetImageType(file);
172 CxImage *image = new CxImage(dwImageType);
173 if (!image) return false;
175 int actualwidth = maxwidth;
176 int actualheight = maxheight;
179 if (!image->Load(file, dwImageType, actualwidth, actualheight) || !image->IsValid())
181 #if !defined(_LINUX) && !defined(__APPLE__)
182 int nErr = GetLastError();
186 printf("PICTURE::LoadImage: Unable to open image: %s Error:%s (%d)\n", file, image->GetLastError(),nErr);
193 printf("PICTURE::LoadImage: Unable to open image: %s\n", file);
197 // ok, now resample the image down if necessary
198 if (ResampleKeepAspect(*image, maxwidth, maxheight) < 0)
200 printf("PICTURE::LoadImage: Unable to resample picture: %s\n", file);
205 // make sure our image is 24bit minimum
206 image->IncreaseBpp(24);
208 // fill in our struct
209 info->width = image->GetWidth();
210 info->height = image->GetHeight();
211 info->originalwidth = actualwidth;
212 info->originalheight = actualheight;
213 memcpy(&info->exifInfo, image->GetExifInfo(), sizeof(EXIFINFO));
215 // create our texture
216 info->context = image;
217 info->texture = image->GetBits();
218 info->alpha = image->AlphaGetBits();
219 return (info->texture != NULL);
222 __declspec(dllexport) bool LoadImageFromMemory(const BYTE *buffer, unsigned int size, const char *mime, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
224 if (!buffer || !size || !mime || !info) return false;
227 DWORD dwImageType = CXIMAGE_FORMAT_UNKNOWN;
229 dwImageType = GetImageType(mime);
230 if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
231 dwImageType = DetectFileType(buffer, size);
232 if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
234 printf("PICTURE::LoadImageFromMemory: Unable to determine image type.");
238 CxImage *image = new CxImage(dwImageType);
242 int actualwidth = maxwidth;
243 int actualheight = maxheight;
247 bool success = image->Decode((BYTE*)buffer, size, dwImageType, actualwidth, actualheight);
248 if (!success && dwImageType != CXIMAGE_FORMAT_UNKNOWN)
249 { // try to decode with unknown imagetype
250 success = image->Decode((BYTE*)buffer, size, CXIMAGE_FORMAT_UNKNOWN);
252 if (!success || !image->IsValid())
254 printf("PICTURE::LoadImageFromMemory: Unable to decode image. Error:%s\n", image->GetLastError());
261 printf("PICTURE::LoadImageFromMemory: Unable to decode image.");
266 // ok, now resample the image down if necessary
267 if (ResampleKeepAspect(*image, maxwidth, maxheight) < 0)
269 printf("PICTURE::LoadImage: Unable to resample picture\n");
274 // make sure our image is 24bit minimum
275 image->IncreaseBpp(24);
277 // fill in our struct
278 info->width = image->GetWidth();
279 info->height = image->GetHeight();
280 info->originalwidth = actualwidth;
281 info->originalheight = actualheight;
282 memcpy(&info->exifInfo, image->GetExifInfo(), sizeof(EXIFINFO));
284 // create our texture
285 info->context = image;
286 info->texture = image->GetBits();
287 info->alpha = image->AlphaGetBits();
288 return (info->texture != NULL);
291 __declspec(dllexport) bool CreateThumbnailFromSurface(BYTE *buffer, unsigned int width, unsigned int height, unsigned int stride, const char *thumb)
293 if (!buffer || !thumb) return false;
294 // creates an image, and copies the surface data into it.
295 CxImage image(width, height, 24, CXIMAGE_FORMAT_PNG);
296 if (!image.IsValid()) return false;
298 if (!image.AlphaIsValid()) return false;
299 bool fullyTransparent(true);
300 bool fullyOpaque(true);
301 for (unsigned int y = 0; y < height; y++)
303 BYTE *ptr = buffer + (y * stride);
304 for (unsigned int x = 0; x < width; x++)
309 BYTE a = *ptr++; // alpha
311 fullyTransparent = false;
314 image.SetPixelColor(x, height - 1 - y, RGB(r, g, b));
315 image.AlphaSet(x, height - 1 - y, a);
318 if (fullyTransparent || fullyOpaque)
320 image.SetJpegQuality(90);
323 if (image.AlphaIsValid() || GetImageType(thumb) == CXIMAGE_FORMAT_PNG)
324 type = CXIMAGE_FORMAT_PNG;
326 type = CXIMAGE_FORMAT_JPG;
328 if (!image.Save(thumb, type))
330 printf("PICTURE::CreateThumbnailFromSurface: Unable to save thumb to %s", thumb);
336 __declspec(dllexport) bool CreateThumbnailFromSurface2(BYTE * bufferin, unsigned int width, unsigned int height, unsigned int stride, const char *thumb,
337 BYTE * &bufferout, unsigned int &bufferoutSize)
339 if (!bufferin) return false;
340 // creates an image, and copies the surface data into it.
341 CxImage image(width, height, 24, CXIMAGE_FORMAT_PNG);
342 if (!image.IsValid()) return false;
344 if (!image.AlphaIsValid()) return false;
345 bool fullyTransparent(true);
346 bool fullyOpaque(true);
347 for (unsigned int y = 0; y < height; y++)
349 BYTE *ptr = bufferin + (y * stride);
350 for (unsigned int x = 0; x < width; x++)
355 BYTE a = *ptr++; // alpha
357 fullyTransparent = false;
360 image.SetPixelColor(x, height - 1 - y, RGB(r, g, b));
361 image.AlphaSet(x, height - 1 - y, a);
364 if (fullyTransparent || fullyOpaque)
366 image.SetJpegQuality(90);
369 if (image.AlphaIsValid() || GetImageType(thumb) == CXIMAGE_FORMAT_PNG)
370 type = CXIMAGE_FORMAT_PNG;
372 type = CXIMAGE_FORMAT_JPG;
376 if (!image.Encode(bufferout, buffout, type))
378 printf("PICTURE::CreateThumbnailFromSurface: Unable to save thumb to %s", thumb);
381 bufferoutSize = buffout;
385 __declspec(dllexport) void FreeMemory(void* memblock)