1 module gfm.freeimage.fibitmap;
2 
3 import std.string;
4 
5 import derelict.freeimage.freeimage;
6 
7 import gfm.freeimage.freeimage;
8 
9 /// FreeImage bitmap wrapper.
10 final class FIBitmap
11 {
12     public
13     {
14         /// Load an image from file.
15         /// Throws: FreeImage on error.
16         this(FreeImage lib, string filename, int flags = 0)
17         {
18             _lib = lib;
19             _bitmap = null;
20             const(char)* filenameZ = toStringz(filename);
21 
22             FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
23 
24             fif = FreeImage_GetFileType(filenameZ, 0);
25             if(fif == FIF_UNKNOWN)
26             {
27                 fif = FreeImage_GetFIFFromFilename(filenameZ);
28             }
29 
30             if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif))
31             {
32                 _bitmap = FreeImage_Load(fif, filenameZ, flags);
33             }
34             if (_bitmap is null)
35                 throw new FreeImageException(format("Coudln't load image %s", filename));
36         }
37 
38         /// Loads from existing bitmap handle.
39         /// Throws: FreeImage on error.
40         this(FreeImage lib, FIBITMAP* bitmap)
41         {
42             _lib = lib;
43 
44             if (bitmap is null)
45                 throw new FreeImageException("Cannot make FIBitmap from null handle");
46 
47             _bitmap = bitmap;
48         }
49 
50         /// Creates an image from from existing memory data.
51         /// Throws: FreeImage on error.
52         this(FreeImage lib, ubyte* data, int width, int height, int pitch, uint bpp,
53              uint redMask, uint blueMask, uint greenMask, bool topDown = false)
54         {
55             _lib = lib;
56             _bitmap = FreeImage_ConvertFromRawBits(data, width, height, pitch, bpp,
57                                                    redMask, greenMask, blueMask, FALSE);
58 
59             if (_bitmap is null)
60                 throw new FreeImageException("Cannot make FIBitmap from raw data");
61         }
62 
63         ~this()
64         {
65             close();
66         }
67 
68         /// Releases the FreeImage bitmap resource.
69         void close()
70         {
71             if (_bitmap !is null)
72             {
73                 FreeImage_Unload(_bitmap);
74                 _bitmap = null;
75             }
76         }
77 
78         /// Saves an image to a file.
79         /// Throws: FreeImage on error.
80         void save(string filename, int flags = 0)
81         {
82             const(char)* filenameZ = toStringz(filename);
83             FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(filenameZ);
84             if (fif == FIF_UNKNOWN)
85                 throw new FreeImageException(format("Coudln't guess format for filename %s", filename));
86             FreeImage_Save(fif, _bitmap, filenameZ, flags);
87         }
88 
89         /// Returns: Width of the image.
90         uint width()
91         {
92             return FreeImage_GetWidth(_bitmap);
93         }
94 
95         /// Returns: Height of the image.
96         uint height()
97         {
98             return FreeImage_GetHeight(_bitmap);
99         }
100 
101         FREE_IMAGE_TYPE getImageType()
102         {
103             return FreeImage_GetImageType(_bitmap);
104         }
105 
106         uint dotsPerMeterX()
107         {
108             return FreeImage_GetDotsPerMeterX(_bitmap);
109         }
110 
111         uint dotsPerMeterY()
112         {
113             return FreeImage_GetDotsPerMeterY(_bitmap);
114         }
115 
116         FREE_IMAGE_COLOR_TYPE colorType()
117         {
118             return FreeImage_GetColorType(_bitmap);
119         }
120 
121         // pixels access
122 
123         /// Returns: Red channel bit mask.
124         uint redMask()
125         {
126             return FreeImage_GetRedMask(_bitmap);
127         }
128 
129         /// Returns: Green channel bit mask.
130         uint greenMask()
131         {
132             return FreeImage_GetGreenMask(_bitmap);
133         }
134 
135         /// Returns: Blue channel bit mask.
136         uint blueMask()
137         {
138             return FreeImage_GetBlueMask(_bitmap);
139         }
140 
141         /// Returns: Bits per pixels.
142         uint BPP()
143         {
144             return FreeImage_GetBPP(_bitmap);
145         }
146 
147         /// Returns: A pointer to pixels data.
148         void* data()
149         {
150             return FreeImage_GetBits(_bitmap);
151         }
152 
153         /// Returns: Pitch between scanlines in bytes.
154         uint pitch()
155         {
156             return FreeImage_GetPitch(_bitmap);
157         }
158 
159         /// Returns: A pointer to scanline y.
160         void* scanLine(int y)
161         {
162             return FreeImage_GetScanLine(_bitmap, y);
163         }
164 
165         /// Converts an image to 4-bits.
166         /// Returns: Converted image.
167         FIBitmap convertTo4Bits()
168         {
169             return new FIBitmap(_lib, FreeImage_ConvertTo4Bits(_bitmap));
170         }
171 
172         /// Converts an image to 8-bits.
173         /// Returns: Converted image.
174         FIBitmap convertTo8Bits()
175         {
176             return new FIBitmap(_lib, FreeImage_ConvertTo8Bits(_bitmap));
177         }
178 
179         /// Converts an image to greyscale.
180         /// Returns: Converted image.
181         FIBitmap convertToGreyscale()
182         {
183             return new FIBitmap(_lib, FreeImage_ConvertToGreyscale(_bitmap));
184         }
185 
186         /// Converts an image to 16-bits 555.
187         /// Returns: Converted image.
188         FIBitmap convertTo16Bits555()
189         {
190             return new FIBitmap(_lib, FreeImage_ConvertTo16Bits555(_bitmap));
191         }
192 
193         /// Converts an image to 16-bits 565.
194         /// Returns: Converted image.
195         FIBitmap convertTo16Bits565()
196         {
197             return new FIBitmap(_lib, FreeImage_ConvertTo16Bits565(_bitmap));
198         }
199 
200         /// Converts an image to 24-bits.
201         /// Returns: Converted image.
202         FIBitmap convertTo24Bits()
203         {
204             return new FIBitmap(_lib, FreeImage_ConvertTo24Bits(_bitmap));
205         }
206 
207         /// Converts an image to 32-bits.
208         /// Throws: FreeImageException on error.
209         /// Returns: Converted image.
210         FIBitmap convertTo32Bits()
211         {
212             return new FIBitmap(_lib, FreeImage_ConvertTo32Bits(_bitmap));
213         }
214 
215         /// Converts an image to another format.
216         /// Throws: FreeImageException on error.
217         /// Returns: Converted image.
218         FIBitmap convertToType(FREE_IMAGE_TYPE dstType, bool scaleLinear = true)
219         {
220             FIBITMAP* converted = FreeImage_ConvertToType(_bitmap, dstType, scaleLinear);
221             if (converted is null)
222                 throw new FreeImageException("disallowed conversion");
223             return new FIBitmap(_lib, converted);
224         }
225 
226         /// Converts an image to float format.
227         /// Returns: Converted image.
228         FIBitmap convertToFloat()
229         {
230             return new FIBitmap(_lib, FreeImage_ConvertToFloat(_bitmap));
231         }
232 
233         /// Converts an image to RGBF format.
234         /// Returns: Converted image.
235         FIBitmap convertToRGBF()
236         {
237             return new FIBitmap(_lib, FreeImage_ConvertToRGBF(_bitmap));
238         }
239 
240         /// Converts an image to UINT16 format.
241         /// Returns: Converted image.
242         FIBitmap convertToUINT16()
243         {
244             return new FIBitmap(_lib, FreeImage_ConvertToUINT16(_bitmap));
245         }
246 
247         /// Converts an image to RGB16 format.
248         /// Returns: Converted image.
249         FIBitmap convertToRGB16()
250         {
251             return new FIBitmap(_lib, FreeImage_ConvertToRGB16(_bitmap));
252         }
253 
254         /// Clones an image.
255         /// Returns: Cloned image.
256         FIBitmap clone()
257         {
258             return new FIBitmap(_lib, FreeImage_Clone(_bitmap));
259         }
260 
261         /// Applies color quantization.
262         FIBitmap colorQuantize(FREE_IMAGE_QUANTIZE quantize)
263         {
264             return new FIBitmap(_lib, FreeImage_ColorQuantize(_bitmap, quantize));
265         }
266 
267         /// Applies tone-mapping operator.
268         FIBitmap toneMapDrago03(double gamma = 2.2, double exposure = 0.0)
269         {
270             return new FIBitmap(_lib, FreeImage_TmoDrago03(_bitmap, gamma, exposure));
271         }
272 
273         /// Rescales the image.
274         FIBitmap rescale(int dstWidth, int dstHeight, FREE_IMAGE_FILTER filter)
275         {
276             return new FIBitmap(_lib, FreeImage_Rescale(_bitmap, dstWidth, dstHeight, filter));
277         }
278 
279         /// Flips the image vertically.
280         /// Throws: FreeImageException on error.
281         void horizontalFlip()
282         {
283             BOOL res = FreeImage_FlipHorizontal(_bitmap);
284             if (res == FALSE)
285                 throw new FreeImageException("cannot flip image horizontally");
286         }
287 
288         /// Flips the image horizontally.
289         /// Throws: FreeImageException on error.
290         void verticalFlip()
291         {
292             BOOL res = FreeImage_FlipVertical(_bitmap);
293             if (res == FALSE)
294                 throw new FreeImageException("cannot flip image horizontally");
295         }
296 
297         /// Rotates the image.
298         /// Returns: Rotated image.
299         FIBitmap rotate(double angle, void* bkColor = null)
300         {
301             return new FIBitmap(_lib, FreeImage_Rotate(_bitmap, angle, bkColor));
302         }
303     }
304 
305     private
306     {
307         FreeImage _lib;
308         FIBITMAP* _bitmap;
309     }
310 }