1 // =====================================================================
2 // FreeImage Plugin Interface
3 //
4 // Design and implementation by
5 // - Floris van den Berg (floris@geekhq.nl)
6 // - Rui Lopes (ruiglopes@yahoo.com)
7 // - Detlev Vendt (detlev.vendt@brillit.de)
8 // - Petr Pytelka (pyta@lightcomp.com)
9 //
10 // This file is part of FreeImage 3
11 //
12 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
13 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
14 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
15 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
16 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
17 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
18 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
19 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
20 // THIS DISCLAIMER.
21 //
22 // Use at your own risk!
23 // =====================================================================
24
25 #ifdef _MSC_VER
26 #pragma warning (disable : 4786) // identifier was truncated to 'number' characters
27 #endif
28
29 #ifdef _WIN32
30 #include <windows.h>
31 #include <io.h>
32 #else
33 #include <ctype.h>
34 #endif // _WIN32
35
36 #include "FreeImage.h"
37 #include "Utilities.h"
38 #include "FreeImageIO.h"
39 #include "Plugin.h"
40
41 #include "../Metadata/FreeImageTag.h"
42
43 // =====================================================================
44
45 using namespace std;
46
47 // =====================================================================
48 // Plugin search list
49 // =====================================================================
50
51 const char *
52 s_search_list[] = {
53 "",
54 "plugins\\",
55 };
56
57 static int s_search_list_size = sizeof(s_search_list) / sizeof(char *);
58 static PluginList *s_plugins = NULL;
59 static int s_plugin_reference_count = 0;
60
61
62 // =====================================================================
63 // Reimplementation of stricmp (it is not supported on some systems)
64 // =====================================================================
65
66 int
FreeImage_stricmp(const char * s1,const char * s2)67 FreeImage_stricmp(const char *s1, const char *s2) {
68 int c1, c2;
69
70 do {
71 c1 = tolower(*s1++);
72 c2 = tolower(*s2++);
73 } while (c1 && c1 == c2);
74
75 return c1 - c2;
76 }
77
78 // =====================================================================
79 // Implementation of PluginList
80 // =====================================================================
81
PluginList()82 PluginList::PluginList() :
83 m_plugin_map(),
84 m_node_count(0) {
85 }
86
87 FREE_IMAGE_FORMAT
AddNode(FI_InitProc init_proc,void * instance,const char * format,const char * description,const char * extension,const char * regexpr)88 PluginList::AddNode(FI_InitProc init_proc, void *instance, const char *format, const char *description, const char *extension, const char *regexpr) {
89 if (init_proc != NULL) {
90 PluginNode *node = new(std::nothrow) PluginNode;
91 Plugin *plugin = new(std::nothrow) Plugin;
92 if(!node || !plugin) {
93 if(node) delete node;
94 if(plugin) delete plugin;
95 FreeImage_OutputMessageProc(FIF_UNKNOWN, FI_MSG_ERROR_MEMORY);
96 return FIF_UNKNOWN;
97 }
98
99 memset(plugin, 0, sizeof(Plugin));
100
101 // fill-in the plugin structure
102 // note we have memset to 0, so all unset pointers should be NULL)
103
104 init_proc(plugin, (int)m_plugin_map.size());
105
106 // get the format string (two possible ways)
107
108 const char *the_format = NULL;
109
110 if (format != NULL) {
111 the_format = format;
112 } else if (plugin->format_proc != NULL) {
113 the_format = plugin->format_proc();
114 }
115
116 // add the node if it wasn't there already
117
118 if (the_format != NULL) {
119 node->m_id = (int)m_plugin_map.size();
120 node->m_instance = instance;
121 node->m_plugin = plugin;
122 node->m_format = format;
123 node->m_description = description;
124 node->m_extension = extension;
125 node->m_regexpr = regexpr;
126 node->m_enabled = TRUE;
127
128 m_plugin_map[(const int)m_plugin_map.size()] = node;
129
130 return (FREE_IMAGE_FORMAT)node->m_id;
131 }
132
133 // something went wrong while allocating the plugin... cleanup
134
135 delete plugin;
136 delete node;
137 }
138
139 return FIF_UNKNOWN;
140 }
141
142 PluginNode *
FindNodeFromFormat(const char * format)143 PluginList::FindNodeFromFormat(const char *format) {
144 for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) {
145 const char *the_format = ((*i).second->m_format != NULL) ? (*i).second->m_format : (*i).second->m_plugin->format_proc();
146
147 if ((*i).second->m_enabled) {
148 if (FreeImage_stricmp(the_format, format) == 0) {
149 return (*i).second;
150 }
151 }
152 }
153
154 return NULL;
155 }
156
157 PluginNode *
FindNodeFromMime(const char * mime)158 PluginList::FindNodeFromMime(const char *mime) {
159 for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) {
160 const char *the_mime = ((*i).second->m_plugin->mime_proc != NULL) ? (*i).second->m_plugin->mime_proc() : "";
161
162 if ((*i).second->m_enabled) {
163 if ((the_mime != NULL) && (strcmp(the_mime, mime) == 0)) {
164 return (*i).second;
165 }
166 }
167 }
168
169 return NULL;
170 }
171
172 PluginNode *
FindNodeFromFIF(int node_id)173 PluginList::FindNodeFromFIF(int node_id) {
174 map<int, PluginNode *>::iterator i = m_plugin_map.find(node_id);
175
176 if (i != m_plugin_map.end()) {
177 return (*i).second;
178 }
179
180 return NULL;
181 }
182
183 int
Size() const184 PluginList::Size() const {
185 return (int)m_plugin_map.size();
186 }
187
188 BOOL
IsEmpty() const189 PluginList::IsEmpty() const {
190 return m_plugin_map.empty();
191 }
192
~PluginList()193 PluginList::~PluginList() {
194 for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) {
195 #ifdef _WIN32
196 if ((*i).second->m_instance != NULL) {
197 FreeLibrary((HINSTANCE)(*i).second->m_instance);
198 }
199 #endif
200 delete (*i).second->m_plugin;
201 delete ((*i).second);
202 }
203 }
204
205 // =====================================================================
206 // Retrieve a pointer to the plugin list container
207 // =====================================================================
208
209 PluginList * DLL_CALLCONV
FreeImage_GetPluginList()210 FreeImage_GetPluginList() {
211 return s_plugins;
212 }
213
214 // =====================================================================
215 // Plugin System Initialization
216 // =====================================================================
217
218 void DLL_CALLCONV
FreeImage_Initialise(BOOL load_local_plugins_only)219 FreeImage_Initialise(BOOL load_local_plugins_only) {
220 if (s_plugin_reference_count++ == 0) {
221
222 /*
223 Note: initialize all singletons here
224 in order to avoid race conditions with multi-threading
225 */
226
227 // initialise the TagLib singleton
228 TagLib& s = TagLib::instance();
229
230 // internal plugin initialization
231
232 s_plugins = new(std::nothrow) PluginList;
233
234 if (s_plugins) {
235 /* NOTE :
236 The order used to initialize internal plugins below MUST BE the same order
237 as the one used to define the FREE_IMAGE_FORMAT enum.
238 */
239 s_plugins->AddNode(InitBMP);
240 s_plugins->AddNode(InitICO);
241 s_plugins->AddNode(InitJPEG);
242 s_plugins->AddNode(InitJNG);
243 s_plugins->AddNode(InitKOALA);
244 s_plugins->AddNode(InitIFF);
245 s_plugins->AddNode(InitMNG);
246 s_plugins->AddNode(InitPNM, NULL, "PBM", "Portable Bitmap (ASCII)", "pbm", "^P1");
247 s_plugins->AddNode(InitPNM, NULL, "PBMRAW", "Portable Bitmap (RAW)", "pbm", "^P4");
248 s_plugins->AddNode(InitPCD);
249 s_plugins->AddNode(InitPCX);
250 s_plugins->AddNode(InitPNM, NULL, "PGM", "Portable Greymap (ASCII)", "pgm", "^P2");
251 s_plugins->AddNode(InitPNM, NULL, "PGMRAW", "Portable Greymap (RAW)", "pgm", "^P5");
252 s_plugins->AddNode(InitPNG);
253 s_plugins->AddNode(InitPNM, NULL, "PPM", "Portable Pixelmap (ASCII)", "ppm", "^P3");
254 s_plugins->AddNode(InitPNM, NULL, "PPMRAW", "Portable Pixelmap (RAW)", "ppm", "^P6");
255 s_plugins->AddNode(InitRAS);
256 s_plugins->AddNode(InitTARGA);
257 s_plugins->AddNode(InitTIFF);
258 s_plugins->AddNode(InitWBMP);
259 s_plugins->AddNode(InitPSD);
260 s_plugins->AddNode(InitCUT);
261 s_plugins->AddNode(InitXBM);
262 s_plugins->AddNode(InitXPM);
263 s_plugins->AddNode(InitDDS);
264 s_plugins->AddNode(InitGIF);
265 s_plugins->AddNode(InitHDR);
266 s_plugins->AddNode(InitG3);
267 s_plugins->AddNode(InitSGI);
268 s_plugins->AddNode(InitEXR);
269 s_plugins->AddNode(InitJ2K);
270 s_plugins->AddNode(InitJP2);
271 s_plugins->AddNode(InitPFM);
272 s_plugins->AddNode(InitPICT);
273 s_plugins->AddNode(InitRAW);
274 s_plugins->AddNode(InitWEBP);
275 #if !(defined(_MSC_VER) && (_MSC_VER <= 1310))
276 s_plugins->AddNode(InitJXR);
277 #endif // unsupported by MS Visual Studio 2003 !!!
278
279 // external plugin initialization
280
281 #ifdef _WIN32
282 if (!load_local_plugins_only) {
283 int count = 0;
284 char buffer[MAX_PATH + 200];
285 wchar_t current_dir[2 * _MAX_PATH], module[2 * _MAX_PATH];
286 BOOL bOk = FALSE;
287
288 // store the current directory. then set the directory to the application location
289
290 if (GetCurrentDirectoryW(2 * _MAX_PATH, current_dir) != 0) {
291 if (GetModuleFileNameW(NULL, module, 2 * _MAX_PATH) != 0) {
292 wchar_t *last_point = wcsrchr(module, L'\\');
293
294 if (last_point) {
295 *last_point = L'\0';
296
297 bOk = SetCurrentDirectoryW(module);
298 }
299 }
300 }
301
302 // search for plugins
303
304 while (count < s_search_list_size) {
305 _finddata_t find_data;
306 long find_handle;
307
308 strcpy(buffer, s_search_list[count]);
309 strcat(buffer, "*.fip");
310
311 if ((find_handle = (long)_findfirst(buffer, &find_data)) != -1L) {
312 do {
313 strcpy(buffer, s_search_list[count]);
314 strncat(buffer, find_data.name, MAX_PATH + 200);
315
316 HINSTANCE instance = LoadLibrary(buffer);
317
318 if (instance != NULL) {
319 FARPROC proc_address = GetProcAddress(instance, "_Init@8");
320
321 if (proc_address != NULL) {
322 s_plugins->AddNode((FI_InitProc)proc_address, (void *)instance);
323 } else {
324 FreeLibrary(instance);
325 }
326 }
327 } while (_findnext(find_handle, &find_data) != -1L);
328
329 _findclose(find_handle);
330 }
331
332 count++;
333 }
334
335 // restore the current directory
336
337 if (bOk) {
338 SetCurrentDirectoryW(current_dir);
339 }
340 }
341 #endif // _WIN32
342 }
343 }
344 }
345
346 void DLL_CALLCONV
FreeImage_DeInitialise()347 FreeImage_DeInitialise() {
348 --s_plugin_reference_count;
349
350 if (s_plugin_reference_count == 0) {
351 delete s_plugins;
352 }
353 }
354
355 // =====================================================================
356 // Open and close a bitmap
357 // =====================================================================
358
359 void * DLL_CALLCONV
FreeImage_Open(PluginNode * node,FreeImageIO * io,fi_handle handle,BOOL open_for_reading)360 FreeImage_Open(PluginNode *node, FreeImageIO *io, fi_handle handle, BOOL open_for_reading) {
361 if (node->m_plugin->open_proc != NULL) {
362 return node->m_plugin->open_proc(io, handle, open_for_reading);
363 }
364
365 return NULL;
366 }
367
368 void DLL_CALLCONV
FreeImage_Close(PluginNode * node,FreeImageIO * io,fi_handle handle,void * data)369 FreeImage_Close(PluginNode *node, FreeImageIO *io, fi_handle handle, void *data) {
370 if (node->m_plugin->close_proc != NULL) {
371 node->m_plugin->close_proc(io, handle, data);
372 }
373 }
374
375 // =====================================================================
376 // Plugin System Load/Save Functions
377 // =====================================================================
378
379 FIBITMAP * DLL_CALLCONV
FreeImage_LoadFromHandle(FREE_IMAGE_FORMAT fif,FreeImageIO * io,fi_handle handle,int flags)380 FreeImage_LoadFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags) {
381 if ((fif >= 0) && (fif < FreeImage_GetFIFCount())) {
382 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
383
384 if (node != NULL) {
385 if(node->m_plugin->load_proc != NULL) {
386 void *data = FreeImage_Open(node, io, handle, TRUE);
387
388 FIBITMAP *bitmap = node->m_plugin->load_proc(io, handle, -1, flags, data);
389
390 FreeImage_Close(node, io, handle, data);
391
392 return bitmap;
393 }
394 }
395 }
396
397 return NULL;
398 }
399
400 FIBITMAP * DLL_CALLCONV
FreeImage_Load(FREE_IMAGE_FORMAT fif,const char * filename,int flags)401 FreeImage_Load(FREE_IMAGE_FORMAT fif, const char *filename, int flags) {
402 FreeImageIO io;
403 SetDefaultIO(&io);
404
405 FILE *handle = fopen(filename, "rb");
406
407 if (handle) {
408 FIBITMAP *bitmap = FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags);
409
410 fclose(handle);
411
412 return bitmap;
413 } else {
414 FreeImage_OutputMessageProc((int)fif, "FreeImage_Load: failed to open file %s", filename);
415 }
416
417 return NULL;
418 }
419
420 FIBITMAP * DLL_CALLCONV
FreeImage_LoadU(FREE_IMAGE_FORMAT fif,const wchar_t * filename,int flags)421 FreeImage_LoadU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, int flags) {
422 FreeImageIO io;
423 SetDefaultIO(&io);
424 #ifdef _WIN32
425 FILE *handle = _wfopen(filename, L"rb");
426
427 if (handle) {
428 FIBITMAP *bitmap = FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags);
429
430 fclose(handle);
431
432 return bitmap;
433 } else {
434 FreeImage_OutputMessageProc((int)fif, "FreeImage_LoadU: failed to open input file");
435 }
436 #endif
437 return NULL;
438 }
439
440 BOOL DLL_CALLCONV
FreeImage_SaveToHandle(FREE_IMAGE_FORMAT fif,FIBITMAP * dib,FreeImageIO * io,fi_handle handle,int flags)441 FreeImage_SaveToHandle(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FreeImageIO *io, fi_handle handle, int flags) {
442 // cannot save "header only" formats
443 if(FreeImage_HasPixels(dib) == FALSE) {
444 FreeImage_OutputMessageProc((int)fif, "FreeImage_SaveToHandle: cannot save \"header only\" formats");
445 return FALSE;
446 }
447
448 if ((fif >= 0) && (fif < FreeImage_GetFIFCount())) {
449 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
450
451 if (node) {
452 if(node->m_plugin->save_proc != NULL) {
453 void *data = FreeImage_Open(node, io, handle, FALSE);
454
455 BOOL result = node->m_plugin->save_proc(io, dib, handle, -1, flags, data);
456
457 FreeImage_Close(node, io, handle, data);
458
459 return result;
460 }
461 }
462 }
463
464 return FALSE;
465 }
466
467
468 BOOL DLL_CALLCONV
FreeImage_Save(FREE_IMAGE_FORMAT fif,FIBITMAP * dib,const char * filename,int flags)469 FreeImage_Save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags) {
470 FreeImageIO io;
471 SetDefaultIO(&io);
472
473 FILE *handle = fopen(filename, "w+b");
474
475 if (handle) {
476 BOOL success = FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags);
477
478 fclose(handle);
479
480 return success;
481 } else {
482 FreeImage_OutputMessageProc((int)fif, "FreeImage_Save: failed to open file %s", filename);
483 }
484
485 return FALSE;
486 }
487
488 BOOL DLL_CALLCONV
FreeImage_SaveU(FREE_IMAGE_FORMAT fif,FIBITMAP * dib,const wchar_t * filename,int flags)489 FreeImage_SaveU(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const wchar_t *filename, int flags) {
490 FreeImageIO io;
491 SetDefaultIO(&io);
492 #ifdef _WIN32
493 FILE *handle = _wfopen(filename, L"w+b");
494
495 if (handle) {
496 BOOL success = FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags);
497
498 fclose(handle);
499
500 return success;
501 } else {
502 FreeImage_OutputMessageProc((int)fif, "FreeImage_SaveU: failed to open output file");
503 }
504 #endif
505 return FALSE;
506 }
507
508 // =====================================================================
509 // Plugin construction + enable/disable functions
510 // =====================================================================
511
512 FREE_IMAGE_FORMAT DLL_CALLCONV
FreeImage_RegisterLocalPlugin(FI_InitProc proc_address,const char * format,const char * description,const char * extension,const char * regexpr)513 FreeImage_RegisterLocalPlugin(FI_InitProc proc_address, const char *format, const char *description, const char *extension, const char *regexpr) {
514 return s_plugins->AddNode(proc_address, NULL, format, description, extension, regexpr);
515 }
516
517 #ifdef _WIN32
518 FREE_IMAGE_FORMAT DLL_CALLCONV
FreeImage_RegisterExternalPlugin(const char * path,const char * format,const char * description,const char * extension,const char * regexpr)519 FreeImage_RegisterExternalPlugin(const char *path, const char *format, const char *description, const char *extension, const char *regexpr) {
520 if (path != NULL) {
521 HINSTANCE instance = LoadLibrary(path);
522
523 if (instance != NULL) {
524 FARPROC proc_address = GetProcAddress(instance, "_Init@8");
525
526 FREE_IMAGE_FORMAT result = s_plugins->AddNode((FI_InitProc)proc_address, (void *)instance, format, description, extension, regexpr);
527
528 if (result == FIF_UNKNOWN)
529 FreeLibrary(instance);
530
531 return result;
532 }
533 }
534
535 return FIF_UNKNOWN;
536 }
537 #endif // _WIN32
538
539 int DLL_CALLCONV
FreeImage_SetPluginEnabled(FREE_IMAGE_FORMAT fif,BOOL enable)540 FreeImage_SetPluginEnabled(FREE_IMAGE_FORMAT fif, BOOL enable) {
541 if (s_plugins != NULL) {
542 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
543
544 if (node != NULL) {
545 BOOL previous_state = node->m_enabled;
546
547 node->m_enabled = enable;
548
549 return previous_state;
550 }
551 }
552
553 return -1;
554 }
555
556 int DLL_CALLCONV
FreeImage_IsPluginEnabled(FREE_IMAGE_FORMAT fif)557 FreeImage_IsPluginEnabled(FREE_IMAGE_FORMAT fif) {
558 if (s_plugins != NULL) {
559 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
560
561 return (node != NULL) ? node->m_enabled : FALSE;
562 }
563
564 return -1;
565 }
566
567 // =====================================================================
568 // Plugin Access Functions
569 // =====================================================================
570
571 int DLL_CALLCONV
FreeImage_GetFIFCount()572 FreeImage_GetFIFCount() {
573 return (s_plugins != NULL) ? s_plugins->Size() : 0;
574 }
575
576 FREE_IMAGE_FORMAT DLL_CALLCONV
FreeImage_GetFIFFromFormat(const char * format)577 FreeImage_GetFIFFromFormat(const char *format) {
578 if (s_plugins != NULL) {
579 PluginNode *node = s_plugins->FindNodeFromFormat(format);
580
581 return (node != NULL) ? (FREE_IMAGE_FORMAT)node->m_id : FIF_UNKNOWN;
582 }
583
584 return FIF_UNKNOWN;
585 }
586
587 FREE_IMAGE_FORMAT DLL_CALLCONV
FreeImage_GetFIFFromMime(const char * mime)588 FreeImage_GetFIFFromMime(const char *mime) {
589 if (s_plugins != NULL) {
590 PluginNode *node = s_plugins->FindNodeFromMime(mime);
591
592 return (node != NULL) ? (FREE_IMAGE_FORMAT)node->m_id : FIF_UNKNOWN;
593 }
594
595 return FIF_UNKNOWN;
596 }
597
598 const char * DLL_CALLCONV
FreeImage_GetFormatFromFIF(FREE_IMAGE_FORMAT fif)599 FreeImage_GetFormatFromFIF(FREE_IMAGE_FORMAT fif) {
600 if (s_plugins != NULL) {
601 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
602
603 return (node != NULL) ? (node->m_format != NULL) ? node->m_format : node->m_plugin->format_proc() : NULL;
604 }
605
606 return NULL;
607 }
608
609 const char * DLL_CALLCONV
FreeImage_GetFIFMimeType(FREE_IMAGE_FORMAT fif)610 FreeImage_GetFIFMimeType(FREE_IMAGE_FORMAT fif) {
611 if (s_plugins != NULL) {
612 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
613
614 return (node != NULL) ? (node->m_plugin != NULL) ? ( node->m_plugin->mime_proc != NULL )? node->m_plugin->mime_proc() : NULL : NULL : NULL;
615 }
616
617 return NULL;
618 }
619
620 const char * DLL_CALLCONV
FreeImage_GetFIFExtensionList(FREE_IMAGE_FORMAT fif)621 FreeImage_GetFIFExtensionList(FREE_IMAGE_FORMAT fif) {
622 if (s_plugins != NULL) {
623 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
624
625 return (node != NULL) ? (node->m_extension != NULL) ? node->m_extension : (node->m_plugin->extension_proc != NULL) ? node->m_plugin->extension_proc() : NULL : NULL;
626 }
627
628 return NULL;
629 }
630
631 const char * DLL_CALLCONV
FreeImage_GetFIFDescription(FREE_IMAGE_FORMAT fif)632 FreeImage_GetFIFDescription(FREE_IMAGE_FORMAT fif) {
633 if (s_plugins != NULL) {
634 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
635
636 return (node != NULL) ? (node->m_description != NULL) ? node->m_description : (node->m_plugin->description_proc != NULL) ? node->m_plugin->description_proc() : NULL : NULL;
637 }
638
639 return NULL;
640 }
641
642 const char * DLL_CALLCONV
FreeImage_GetFIFRegExpr(FREE_IMAGE_FORMAT fif)643 FreeImage_GetFIFRegExpr(FREE_IMAGE_FORMAT fif) {
644 if (s_plugins != NULL) {
645 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
646
647 return (node != NULL) ? (node->m_regexpr != NULL) ? node->m_regexpr : (node->m_plugin->regexpr_proc != NULL) ? node->m_plugin->regexpr_proc() : NULL : NULL;
648 }
649
650 return NULL;
651 }
652
653 BOOL DLL_CALLCONV
FreeImage_FIFSupportsReading(FREE_IMAGE_FORMAT fif)654 FreeImage_FIFSupportsReading(FREE_IMAGE_FORMAT fif) {
655 if (s_plugins != NULL) {
656 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
657
658 return (node != NULL) ? node->m_plugin->load_proc != NULL : FALSE;
659 }
660
661 return FALSE;
662 }
663
664 BOOL DLL_CALLCONV
FreeImage_FIFSupportsWriting(FREE_IMAGE_FORMAT fif)665 FreeImage_FIFSupportsWriting(FREE_IMAGE_FORMAT fif) {
666 if (s_plugins != NULL) {
667 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
668
669 return (node != NULL) ? node->m_plugin->save_proc != NULL : FALSE ;
670 }
671
672 return FALSE;
673 }
674
675 BOOL DLL_CALLCONV
FreeImage_FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif,int depth)676 FreeImage_FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif, int depth) {
677 if (s_plugins != NULL) {
678 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
679
680 return (node != NULL) ?
681 (node->m_plugin->supports_export_bpp_proc != NULL) ?
682 node->m_plugin->supports_export_bpp_proc(depth) : FALSE : FALSE;
683 }
684
685 return FALSE;
686 }
687
688 BOOL DLL_CALLCONV
FreeImage_FIFSupportsExportType(FREE_IMAGE_FORMAT fif,FREE_IMAGE_TYPE type)689 FreeImage_FIFSupportsExportType(FREE_IMAGE_FORMAT fif, FREE_IMAGE_TYPE type) {
690 if (s_plugins != NULL) {
691 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
692
693 return (node != NULL) ?
694 (node->m_plugin->supports_export_type_proc != NULL) ?
695 node->m_plugin->supports_export_type_proc(type) : FALSE : FALSE;
696 }
697
698 return FALSE;
699 }
700
701 BOOL DLL_CALLCONV
FreeImage_FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif)702 FreeImage_FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif) {
703 if (s_plugins != NULL) {
704 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
705
706 return (node != NULL) ?
707 (node->m_plugin->supports_icc_profiles_proc != NULL) ?
708 node->m_plugin->supports_icc_profiles_proc() : FALSE : FALSE;
709 }
710
711 return FALSE;
712 }
713
714 BOOL DLL_CALLCONV
FreeImage_FIFSupportsNoPixels(FREE_IMAGE_FORMAT fif)715 FreeImage_FIFSupportsNoPixels(FREE_IMAGE_FORMAT fif) {
716 if (s_plugins != NULL) {
717 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
718
719 return (node != NULL) ?
720 (node->m_plugin->supports_no_pixels_proc != NULL) ?
721 node->m_plugin->supports_no_pixels_proc() : FALSE : FALSE;
722 }
723
724 return FALSE;
725 }
726
727 FREE_IMAGE_FORMAT DLL_CALLCONV
FreeImage_GetFIFFromFilename(const char * filename)728 FreeImage_GetFIFFromFilename(const char *filename) {
729 if (filename != NULL) {
730 const char *extension;
731
732 // get the proper extension if we received a filename
733
734 char *place = strrchr((char *)filename, '.');
735 extension = (place != NULL) ? ++place : filename;
736
737 // look for the extension in the plugin table
738
739 for (int i = 0; i < FreeImage_GetFIFCount(); ++i) {
740
741 if (s_plugins->FindNodeFromFIF(i)->m_enabled) {
742
743 // compare the format id with the extension
744
745 if (FreeImage_stricmp(FreeImage_GetFormatFromFIF((FREE_IMAGE_FORMAT)i), extension) == 0) {
746 return (FREE_IMAGE_FORMAT)i;
747 } else {
748 // make a copy of the extension list and split it
749
750 char *copy = (char *)malloc(strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i)) + 1);
751 memset(copy, 0, strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i)) + 1);
752 memcpy(copy, FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i), strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i)));
753
754 // get the first token
755
756 char *token = strtok(copy, ",");
757
758 while (token != NULL) {
759 if (FreeImage_stricmp(token, extension) == 0) {
760 free(copy);
761
762 return (FREE_IMAGE_FORMAT)i;
763 }
764
765 token = strtok(NULL, ",");
766 }
767
768 // free the copy of the extension list
769
770 free(copy);
771 }
772 }
773 }
774 }
775
776 return FIF_UNKNOWN;
777 }
778
779 FREE_IMAGE_FORMAT DLL_CALLCONV
FreeImage_GetFIFFromFilenameU(const wchar_t * filename)780 FreeImage_GetFIFFromFilenameU(const wchar_t *filename) {
781 #ifdef _WIN32
782 if (filename == NULL) return FIF_UNKNOWN;
783
784 // get the proper extension if we received a filename
785 wchar_t *place = wcsrchr((wchar_t *)filename, '.');
786 if (place == NULL) return FIF_UNKNOWN;
787 // convert to single character - no national chars in extensions
788 char *extension = (char *)malloc(wcslen(place)+1);
789 unsigned int i=0;
790 for(; i < wcslen(place); i++) // convert 16-bit to 8-bit
791 extension[i] = (char)(place[i] & 0x00FF);
792 // set terminating 0
793 extension[i]=0;
794 FREE_IMAGE_FORMAT fRet = FreeImage_GetFIFFromFilename(extension);
795 free(extension);
796
797 return fRet;
798 #else
799 return FIF_UNKNOWN;
800 #endif // _WIN32
801 }
802
803 BOOL DLL_CALLCONV
FreeImage_ValidateFIF(FREE_IMAGE_FORMAT fif,FreeImageIO * io,fi_handle handle)804 FreeImage_ValidateFIF(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle) {
805 if (s_plugins != NULL) {
806 BOOL validated = FALSE;
807
808 PluginNode *node = s_plugins->FindNodeFromFIF(fif);
809
810 if (node) {
811 long tell = io->tell_proc(handle);
812
813 validated = (node != NULL) ? (node->m_enabled) ? (node->m_plugin->validate_proc != NULL) ? node->m_plugin->validate_proc(io, handle) : FALSE : FALSE : FALSE;
814
815 io->seek_proc(handle, tell, SEEK_SET);
816 }
817
818 return validated;
819 }
820
821 return FALSE;
822 }
823