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