1 module gfm.sdl2.sdlimage;
2 
3 import std..string;
4 
5 import bindbc.sdl,
6        bindbc.sdl.image;
7 
8 import std.experimental.logger;
9 
10 import gfm.sdl2.sdl,
11        gfm.sdl2.surface;
12 
13 /// Load images using SDL_image, a SDL companion library able to load various image formats.
14 final class SDLImage
15 {
16     public
17     {
18         /// Loads the SDL_image library.
19         /// SDL must be already initialized.
20         /// Throws: $(D SDL2Exception) on error.
21         this(SDL2 sdl2, int flags = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF | IMG_INIT_WEBP)
22         {
23             _sdl2 = sdl2; // force loading of SDL first
24             _logger = sdl2._logger;
25             _SDLImageInitialized = false;
26 
27             const ret = loadSDLImage();
28             if(ret < sdlImageSupport)
29             {
30                 if(ret == SDLImageSupport.noLibrary)
31                     throwSDL2ImageException("SDL Image shared library failed to load");
32                 else if(SDLImageSupport.badLibrary)
33                     // One or more symbols failed to load. The likely cause is that the
34                     // shared library is for a lower version than bindbc-sdl was configured
35                     // to load (via SDL_201, SDL_202, etc.)
36                     throwSDL2ImageException("One or more symbols of SDL Image shared library failed to load");
37                 throwSDL2ImageException("The version of the SDL Image library on your system is too low. Please upgrade.");
38             }
39 
40             int inited = IMG_Init(flags);
41             _SDLImageInitialized = true;
42         }
43 
44         /// Releases the SDL resource.
45         ~this()
46         {
47             if (_SDLImageInitialized)
48             {
49                 debug ensureNotInGC("SDLImage");
50                 _SDLImageInitialized = false;
51                 IMG_Quit();
52             }
53         }
54 
55         /// Load an image.
56         /// Returns: A SDL surface with loaded content.
57         /// Throws: $(D SDL2Exception) on error.
58         SDL2Surface load(string path)
59         {
60             immutable(char)* pathz = toStringz(path);
61             SDL_Surface* surface = IMG_Load(pathz);
62             if (surface is null)
63                 throwSDL2ImageException("IMG_Load");
64 
65             return new SDL2Surface(_sdl2, surface, SDL2Surface.Owned.YES);
66         }
67     }
68 
69     private
70     {
71         Logger _logger;
72         SDL2 _sdl2;
73         bool _SDLImageInitialized;
74 
75         void throwSDL2ImageException(string callThatFailed)
76         {
77             string message = format("%s failed: %s", callThatFailed, getErrorString());
78             throw new SDL2Exception(message);
79         }
80 
81         const(char)[] getErrorString()
82         {
83             return fromStringz(IMG_GetError());
84         }
85     }
86 }