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