1 module nudsfml.graphics.image;
2 
3 import bindbc.sfml.graphics;
4 
5 import nudsfml.graphics.color;
6 import nudsfml.graphics.rect;
7 import nudsfml.system.vector2;
8 import nudsfml.system.inputstream;
9 
10 class Image {
11     sfImage* sfPtr = null;
12     /// Default constructor.
13     this() {
14         sfPtr = sfImage_create(0,0);
15     }
16 
17     package this(sfImage* image){
18         sfPtr = image;
19     }
20 
21     /// Destructor.
22     ~this() {
23         if(sfPtr != null){
24             sfImage_destroy(sfPtr);
25         }
26     }
27 
28     /**
29      * Create the image and fill it with a unique color.
30      *
31      * Params:
32      * 		width	= Width of the image
33      * 		height	= Height of the image
34      * 		color	= Fill color
35      *
36      */
37     void create(uint width, uint height, Color color) {
38         sfColor c = fromColor(color);
39         if(sfPtr !is null) {
40             sfImage_destroy(sfPtr);
41         }
42         sfPtr = sfImage_createFromColor(width, height,c);
43     }
44 
45     /**
46      * Create the image from an array of pixels.
47      *
48      * The pixel array is assumed to contain 32-bits RGBA pixels, and have the
49      * given width and height. If not, this is an undefined behaviour. If pixels
50      * is null, an empty image is created.
51      *
52      * Params:
53      * 		width	= Width of the image
54      * 		height	= Height of the image
55      * 		pixels	= Array of pixels to copy to the image
56      *
57      */
58     void create(uint width, uint height, const(ubyte)[] pixels) {
59         if (sfPtr !is null)
60             sfImage_destroy(sfPtr);
61         sfPtr = sfImage_createFromPixels(width, height,pixels.ptr);
62     }
63 
64     /**
65      * Load the image from a file on disk.
66      *
67      * The supported image formats are bmp, png, tga, jpg, gif, psd, hdr and
68      * pic. Some format options are not supported, like progressive jpeg. If
69      * this function fails, the image is left unchanged.
70      *
71      * Params:
72      * 		filename	= Path of the image file to load
73      *
74      * Returns: true if loading succeeded, false if it failed
75      */
76     bool loadFromFile(const(char)[] filename) {
77         import std.string;
78         if(sfPtr !is null){
79             sfImage_destroy(sfPtr);
80         }
81         sfPtr = sfImage_createFromFile(filename.toStringz);
82         return sfPtr !is null;
83     }
84 
85     /**
86      * Load the image from a file in memory.
87      *
88      * The supported image formats are bmp, png, tga, jpg, gif, psd, hdr and
89      * pic. Some format options are not supported, like progressive jpeg. If
90      * this function fails, the image is left unchanged.
91      *
92      * Params:
93      * 		data	= Data file in memory to load
94      *
95      * Returns: true if loading succeeded, false if it failed
96      */
97     bool loadFromMemory(const(void)[] data) {
98         if(sfPtr !is null){
99             sfImage_destroy(sfPtr);
100         }
101         sfPtr = sfImage_createFromMemory(data.ptr, data.length);
102         return sfPtr !is null;
103     }
104 
105     /**
106      * Get the color of a pixel
107      *
108      * This function doesn't check the validity of the pixel coordinates; using
109      * out-of-range values will result in an undefined behaviour.
110      *
111      * Params:
112      * 		x	= X coordinate of the pixel to get
113      * 		y	= Y coordinate of the pixel to get
114      *
115      * Returns: Color of the pixel at coordinates (x, y)
116      */
117     Color getPixel(uint x, uint y) const {
118         import std.conv;
119         sfColor c = sfImage_getPixel(sfPtr, x,y);
120         Color temp;
121         temp.r = c.r.to!ubyte;
122         temp.g = c.g.to!ubyte;
123         temp.b = c.b.to!ubyte;
124         temp.a = c.a.to!ubyte;
125         return temp;
126     }
127 
128     /**
129      * Get the read-only array of pixels that make up the image.
130      *
131      * The returned value points to an array of RGBA pixels made of 8 bits
132      * integers components. The size of the array is:
133      * `width * height * 4 (getSize().x * getSize().y * 4)`.
134      *
135      * Warning: the returned slice may become invalid if you modify the image,
136      * so you should never store it for too long.
137      *
138      * Returns: Read-only array of pixels that make up the image.
139      */
140     const(ubyte)[] getPixelArray() const {
141         import std.stdio;
142         Vector2u size = getSize();
143         int length = size.x * size.y * 4;
144 
145         if(length!=0) {
146             return sfImage_getPixelsPtr(sfPtr)[0..length];
147         } else {
148             writeln("Trying to access the pixels of an empty image");
149             return [];
150         }
151     }
152 
153     /**
154      * Return the size (width and height) of the image.
155      *
156      * Returns: Size of the image, in pixels.
157      */
158     Vector2u getSize() const {
159        auto v = sfImage_getSize(sfPtr);
160         Vector2u temp = Vector2u(v.x,v.y);
161         return temp;
162     }
163 
164     /**
165      * Return the size (width and height) of the image.
166      *
167      * Returns: Size of the image, in pixels.
168      */
169     Vector2u size() const {
170        auto v = sfImage_getSize(sfPtr);
171         Vector2u temp = Vector2u(v.x,v.y);
172         return temp;
173     }
174 
175 
176     /**
177      * Change the color of a pixel.
178      *
179      * This function doesn't check the validity of the pixel coordinates, using
180      * out-of-range values will result in an undefined behaviour.
181      *
182      * Params:
183      * 		x		= X coordinate of pixel to change
184      * 		y		= Y coordinate of pixel to change
185      * 		color	= New color of the pixel
186      */
187     void setPixel(uint x, uint y, Color color) {
188         sfColor c = fromColor(color);
189         sfImage_setPixel(sfPtr, x,y,c);
190     }
191 
192     /**
193      * Copy pixels from another image onto this one.
194      *
195      * This function does a slow pixel copy and should not be used intensively.
196      * It can be used to prepare a complex static image from several others, but
197      * if you need this kind of feature in real-time you'd better use
198      * RenderTexture.
199      *
200      * If sourceRect is empty, the whole image is copied. If applyAlpha is set
201      * to true, the transparency of source pixels is applied. If it is false,
202      * the pixels are copied unchanged with their alpha value.
203      *
204      * Params:
205      * 	source		= Source image to copy
206      * 	destX		= X coordinate of the destination position
207      * 	destY		= Y coordinate of the destination position
208      * 	sourceRect	= Sub-rectangle of the source image to copy
209      * 	applyAlpha	= Should the copy take the source transparency into account?
210      */
211     void copyImage(const(Image) source, uint destX, uint destY, IntRect sourceRect = IntRect(0,0,0,0), bool applyAlpha = false){
212         sfIntRect sourcerect;
213         
214         sourcerect.left = sourceRect.left;
215         sourcerect.top = sourceRect.top;
216         sourcerect.width = sourceRect.width;
217         sourcerect.height = sourceRect.height;
218 
219         sfImage_copyImage(sfPtr, source.sfPtr, destX, destY,sourcerect, applyAlpha);
220     }
221 
222     /**
223      * Create a transparency mask from a specified color-key.
224      *
225      * This function sets the alpha value of every pixel matching the given
226      * color to alpha (0 by default) so that they become transparent.
227      *
228      * Params:
229      * 		maskColor   = Color to make transparent
230      * 		alpha	    = Alpha value to assign to transparent pixels
231      */
232     void createMaskFromColor(Color maskColor, ubyte alpha = 0) {
233         sfColor c = fromColor(maskColor);
234         sfImage_createMaskFromColor(sfPtr,c, alpha);
235     }
236 
237     /// Create a copy of the Image.
238     @property Image dup() const {
239         return new Image(sfImage_copy(sfPtr));
240     }
241 
242     /// Flip the image horizontally (left <-> right)
243     void flipHorizontally(){
244         sfImage_flipHorizontally(sfPtr);
245     }
246 
247     /// Flip the image vertically (top <-> bottom)
248     void flipVertically() {
249         sfImage_flipVertically(sfPtr);
250     }
251 
252     /**
253      * Save the image to a file on disk.
254      *
255      * The format of the image is automatically deduced from the extension. The
256      * supported image formats are bmp, png, tga and jpg. The destination file
257      * is overwritten if it already exists. This function fails if the image is
258      * empty.
259      *
260      * Params:
261      * 		filename	= Path of the file to save
262      *
263      * Returns: true if saving was successful
264      */
265     bool saveToFile(const(char)[] filename) const{
266         import std.string;
267         auto f  = filename.toStringz;
268         return sfImage_saveToFile(sfPtr, f)!=0;
269     }
270 }