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      * Change the color of a pixel.
166      *
167      * This function doesn't check the validity of the pixel coordinates, using
168      * out-of-range values will result in an undefined behaviour.
169      *
170      * Params:
171      * 		x		= X coordinate of pixel to change
172      * 		y		= Y coordinate of pixel to change
173      * 		color	= New color of the pixel
174      */
175     void setPixel(uint x, uint y, Color color) {
176         sfColor c = fromColor(color);
177         sfImage_setPixel(sfPtr, x,y,c);
178     }
179 
180     /**
181      * Copy pixels from another image onto this one.
182      *
183      * This function does a slow pixel copy and should not be used intensively.
184      * It can be used to prepare a complex static image from several others, but
185      * if you need this kind of feature in real-time you'd better use
186      * RenderTexture.
187      *
188      * If sourceRect is empty, the whole image is copied. If applyAlpha is set
189      * to true, the transparency of source pixels is applied. If it is false,
190      * the pixels are copied unchanged with their alpha value.
191      *
192      * Params:
193      * 	source		= Source image to copy
194      * 	destX		= X coordinate of the destination position
195      * 	destY		= Y coordinate of the destination position
196      * 	sourceRect	= Sub-rectangle of the source image to copy
197      * 	applyAlpha	= Should the copy take the source transparency into account?
198      */
199     void copyImage(const(Image) source, uint destX, uint destY, IntRect sourceRect = IntRect(0,0,0,0), bool applyAlpha = false){
200         sfIntRect sourcerect;
201         
202         sourcerect.left = sourceRect.left;
203         sourcerect.top = sourceRect.top;
204         sourcerect.width = sourceRect.width;
205         sourcerect.height = sourceRect.height;
206 
207         sfImage_copyImage(sfPtr, source.sfPtr, destX, destY,sourcerect, applyAlpha);
208     }
209 
210     /**
211      * Create a transparency mask from a specified color-key.
212      *
213      * This function sets the alpha value of every pixel matching the given
214      * color to alpha (0 by default) so that they become transparent.
215      *
216      * Params:
217      * 		maskColor   = Color to make transparent
218      * 		alpha	    = Alpha value to assign to transparent pixels
219      */
220     void createMaskFromColor(Color maskColor, ubyte alpha = 0) {
221         sfColor c = fromColor(maskColor);
222         sfImage_createMaskFromColor(sfPtr,c, alpha);
223     }
224 
225     /// Create a copy of the Image.
226     @property Image dup() const {
227         return new Image(sfImage_copy(sfPtr));
228     }
229 
230     /// Flip the image horizontally (left <-> right)
231     void flipHorizontally(){
232         sfImage_flipHorizontally(sfPtr);
233     }
234 
235     /// Flip the image vertically (top <-> bottom)
236     void flipVertically() {
237         sfImage_flipVertically(sfPtr);
238     }
239 
240     /**
241      * Save the image to a file on disk.
242      *
243      * The format of the image is automatically deduced from the extension. The
244      * supported image formats are bmp, png, tga and jpg. The destination file
245      * is overwritten if it already exists. This function fails if the image is
246      * empty.
247      *
248      * Params:
249      * 		filename	= Path of the file to save
250      *
251      * Returns: true if saving was successful
252      */
253     bool saveToFile(const(char)[] filename) const{
254         import std.string;
255         auto f  = filename.toStringz;
256         return sfImage_saveToFile(sfPtr, f)!=0;
257     }
258 }