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 return CXIMAGE_FORMAT_UNKNOWN;
100 int ResampleKeepAspect(CxImage &image, unsigned int width, unsigned int height)
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)
110 newheight = (DWORD)( ( (float)newwidth) / fAspect);
112 if (newheight > height)
116 newwidth = (DWORD)( fAspect * ( (float)newheight) );
120 if (!image.Resample(newwidth, newheight, RESAMPLE_QUALITY) || !image.IsValid())
122 printf("PICTURE::SaveThumb: Unable to resample picture: Error:%s\n", image.GetLastError());
126 return bResize ? 1 : 0;
133 #if defined(_LINUX) || defined(__APPLE__)
134 #define __declspec(x)
139 bool IsDir(const char* file)
142 if (stat(file, &holder) == -1)
144 if (S_ISDIR(holder.st_mode))
150 __declspec(dllexport) bool ReleaseImage(ImageInfo *info)
152 if (info && info->context)
154 delete ((CxImage *)info->context);
161 __declspec(dllexport) bool LoadImage(const char *file, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
163 if (!file || !info) return false;
169 DWORD dwImageType = GetImageType(file);
170 CxImage *image = new CxImage(dwImageType);
171 if (!image) return false;
173 int actualwidth = maxwidth;
174 int actualheight = maxheight;
177 if (!image->Load(file, dwImageType, actualwidth, actualheight) || !image->IsValid())
179 #if !defined(_LINUX) && !defined(__APPLE__)
180 int nErr = GetLastError();
184 printf("PICTURE::LoadImage: Unable to open image: %s Error:%s (%d)\n", file, image->GetLastError(),nErr);
191 printf("PICTURE::LoadImage: Unable to open image: %s\n", file);
195 // ok, now resample the image down if necessary
196 if (ResampleKeepAspect(*image, maxwidth, maxheight) < 0)
198 printf("PICTURE::LoadImage: Unable to resample picture: %s\n", file);
203 // make sure our image is 24bit minimum
204 image->IncreaseBpp(24);
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));
213 // create our texture
214 info->context = image;
215 info->texture = image->GetBits();
216 info->alpha = image->AlphaGetBits();
217 return (info->texture != NULL);
220 __declspec(dllexport) bool LoadImageFromMemory(const BYTE *buffer, unsigned int size, const char *mime, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
222 if (!buffer || !size || !mime || !info) return false;
225 DWORD dwImageType = CXIMAGE_FORMAT_UNKNOWN;
227 dwImageType = GetImageType(mime);
228 if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
229 dwImageType = DetectFileType(buffer, size);
230 if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
232 printf("PICTURE::LoadImageFromMemory: Unable to determine image type.");
236 CxImage *image = new CxImage(dwImageType);
240 int actualwidth = maxwidth;
241 int actualheight = maxheight;
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);
250 if (!success || !image->IsValid())
252 printf("PICTURE::LoadImageFromMemory: Unable to decode image. Error:%s\n", image->GetLastError());
259 printf("PICTURE::LoadImageFromMemory: Unable to decode image.");
264 // ok, now resample the image down if necessary
265 if (ResampleKeepAspect(*image, maxwidth, maxheight) < 0)
267 printf("PICTURE::LoadImage: Unable to resample picture\n");
272 // make sure our image is 24bit minimum
273 image->IncreaseBpp(24);
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));
282 // create our texture
283 info->context = image;
284 info->texture = image->GetBits();
285 info->alpha = image->AlphaGetBits();
286 return (info->texture != NULL);
289 __declspec(dllexport) bool CreateThumbnailFromSurface(BYTE *buffer, unsigned int width, unsigned int height, unsigned int stride, const char *thumb)
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;
296 if (!image.AlphaIsValid()) return false;
297 bool fullyTransparent(true);
298 bool fullyOpaque(true);
299 for (unsigned int y = 0; y < height; y++)
301 BYTE *ptr = buffer + (y * stride);
302 for (unsigned int x = 0; x < width; x++)
307 BYTE a = *ptr++; // alpha
309 fullyTransparent = false;
312 image.SetPixelColor(x, height - 1 - y, RGB(r, g, b));
313 image.AlphaSet(x, height - 1 - y, a);
316 if (fullyTransparent || fullyOpaque)
318 image.SetJpegQuality(90);
321 if (image.AlphaIsValid() || GetImageType(thumb) == CXIMAGE_FORMAT_PNG)
322 type = CXIMAGE_FORMAT_PNG;
324 type = CXIMAGE_FORMAT_JPG;
326 if (!image.Save(thumb, type))
328 printf("PICTURE::CreateThumbnailFromSurface: Unable to save thumb to %s", thumb);
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)
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;
342 if (!image.AlphaIsValid()) return false;
343 bool fullyTransparent(true);
344 bool fullyOpaque(true);
345 for (unsigned int y = 0; y < height; y++)
347 BYTE *ptr = bufferin + (y * stride);
348 for (unsigned int x = 0; x < width; x++)
353 BYTE a = *ptr++; // alpha
355 fullyTransparent = false;
358 image.SetPixelColor(x, height - 1 - y, RGB(r, g, b));
359 image.AlphaSet(x, height - 1 - y, a);
362 if (fullyTransparent || fullyOpaque)
364 image.SetJpegQuality(90);
367 if (image.AlphaIsValid() || GetImageType(thumb) == CXIMAGE_FORMAT_PNG)
368 type = CXIMAGE_FORMAT_PNG;
370 type = CXIMAGE_FORMAT_JPG;
374 if (!image.Encode(bufferout, buffout, type))
376 printf("PICTURE::CreateThumbnailFromSurface: Unable to save thumb to %s", thumb);
379 bufferoutSize = buffout;
383 __declspec(dllexport) void FreeMemory(void* memblock)