1 module gfm.freeimage.freeimage;
2 
3 import std.conv,
4        std.string;
5 
6 import derelict.freeimage.freeimage,
7        derelict.util.exception;
8 
9 /// The one exception type thrown in this wrapper.
10 /// A failing FreeImage function should <b>always</b> throw an FreeImageException.
11 class FreeImageException : Exception
12 {
13     public
14     {
15         @safe pure nothrow this(string message, string file =__FILE__, size_t line = __LINE__, Throwable next = null)
16         {
17             super(message, file, line, next);
18         }
19     }
20 }
21 
22 /// FreeImage library wrapper.
23 final class FreeImage
24 {
25     public
26     {
27         /// Loads the FreeImage library and logs some information.
28         /// Throws: FreeImageException on error.
29         this(bool useExternalPlugins = false)
30         {
31             try
32             {
33                 DerelictFI.load();
34             }
35             catch(DerelictException e)
36             {
37                 throw new FreeImageException(e.msg);
38             }
39 
40             //FreeImage_Initialise(useExternalPlugins ? TRUE : FALSE); // documentation says it's useless
41             _libInitialized = true;
42         }
43 
44         ~this()
45         {
46             if (_libInitialized)
47             {
48                 debug ensureNotInGC("FreeImage");
49                 //FreeImage_DeInitialise(); // documentation says it's useless
50                 _libInitialized = false;
51             }
52         }
53 
54         const(char)[] getVersion()
55         {
56             const(char)* versionZ = FreeImage_GetVersion();
57             return fromStringz(versionZ);
58         }
59 
60         const(char)[] getCopyrightMessage()
61         {
62             const(char)* copyrightZ = FreeImage_GetCopyrightMessage();
63             return fromStringz(copyrightZ);
64         }
65     }
66 
67     private
68     {
69         bool _libInitialized;
70     }
71 }
72 
73 /// Crash if the GC is running.
74 /// Useful in destructors to avoid reliance GC resource release.
75 package void ensureNotInGC(string resourceName) nothrow
76 {
77     import core.exception;
78     try
79     {
80         import core.memory;
81         cast(void) GC.malloc(1); // not ideal since it allocates
82         return;
83     }
84     catch(InvalidMemoryOperationError e)
85     {
86 
87         import core.stdc.stdio;
88         fprintf(stderr, "Error: clean-up of %s incorrectly depends on destructors called by the GC.\n", resourceName.ptr);
89         assert(false);
90     }
91 }