1 /**
2  * Copyright:       Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved
3  * Authors:         $(Gabriel Gheorghe)
4  * License:         $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007)
5  * Source
6  * Documentation:
7  * Coverage:
8  */
9 module liberty.core.imaging.bitmap;
10 import std.string;
11 import derelict.freeimage.freeimage;
12 import liberty.core.imaging.image;
13 /// Image bitmap wrapper.
14 final class Bitmap {
15     private {
16         Image _lib;
17         FIBITMAP* _bitmap;
18     }
19     /// Load an image from file.
20     /// Throws: Image on error.
21     this(Image lib, string filename, int flags = 0) {
22         _lib = lib;
23         _bitmap = null;
24         const(char)* filenameZ = toStringz(filename);
25         FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
26         fif = FreeImage_GetFileType(filenameZ, 0);
27         if(fif == FIF_UNKNOWN) {
28             fif = FreeImage_GetFIFFromFilename(filenameZ);
29         }
30         if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
31             _bitmap = FreeImage_Load(fif, filenameZ, flags);
32         }
33         if (_bitmap is null)
34             throw new ImageException(format("Coudln't load image %s", filename));
35     }
36     /// Loads from existing bitmap handle.
37     /// Throws: Image on error.
38     this(Image lib, FIBITMAP* bitmap) {
39         _lib = lib;
40         if (bitmap is null)
41             throw new ImageException("Cannot make FIBitmap from null handle");
42         _bitmap = bitmap;
43     }
44     /// Creates an image from from existing memory data.
45     /// Throws: Image on error.
46     this(Image lib, ubyte* data, int width, int height, int pitch, uint bpp, uint redMask, uint blueMask, uint greenMask, bool topDown = false) {
47         _lib = lib;
48         _bitmap = FreeImage_ConvertFromRawBits(data, width, height, pitch, bpp, redMask, greenMask, blueMask, FALSE);
49         if (_bitmap is null)
50             throw new ImageException("Cannot make FIBitmap from raw data");
51     }
52     /// Releases the Image bitmap resource.
53     ~this() {
54         if (_bitmap !is null) {
55             debug import liberty.core.memory : ensureNotInGC;
56             debug ensureNotInGC("FIBitmap");
57             FreeImage_Unload(_bitmap);
58             _bitmap = null;
59         }
60     }
61     /// Saves an image to a file.
62     /// Throws: Image on error.
63     void save(string filename, int flags = 0) {
64         const(char)* filenameZ = toStringz(filename);
65         FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(filenameZ);
66         if (fif == FIF_UNKNOWN)
67             throw new ImageException(format("Coudln't guess format for filename %s", filename));
68         FreeImage_Save(fif, _bitmap, filenameZ, flags);
69     }
70     /// Returns: Width of the image.
71     uint width() {
72         return FreeImage_GetWidth(_bitmap);
73     }
74     /// Returns: Height of the image.
75     uint height() {
76         return FreeImage_GetHeight(_bitmap);
77     }
78     ///
79     FREE_IMAGE_TYPE imageType() {
80         return FreeImage_GetImageType(_bitmap);
81     }
82     ///
83     uint dotsPerMeterX() {
84         return FreeImage_GetDotsPerMeterX(_bitmap);
85     }
86     ///
87     uint dotsPerMeterY() {
88         return FreeImage_GetDotsPerMeterY(_bitmap);
89     }
90     ///
91     FREE_IMAGE_COLOR_TYPE colorType() {
92         return FreeImage_GetColorType(_bitmap);
93     }
94     /// Returns: Red channel bit mask.
95     uint redMask() {
96         return FreeImage_GetRedMask(_bitmap);
97     }
98     /// Returns: Green channel bit mask.
99     uint greenMask() {
100         return FreeImage_GetGreenMask(_bitmap);
101     }
102     /// Returns: Blue channel bit mask.
103     uint blueMask() {
104         return FreeImage_GetBlueMask(_bitmap);
105     }
106     /// Returns: Bits per pixels.
107     uint BPP() {
108         return FreeImage_GetBPP(_bitmap);
109     }
110     /// Returns: A pointer to pixels data.
111     void* data() {
112         return FreeImage_GetBits(_bitmap);
113     }
114     /// Returns: Pitch between scanlines in bytes.
115     uint pitch() {
116         return FreeImage_GetPitch(_bitmap);
117     }
118     /// Returns: A pointer to scanline y.
119     void* scanLine(int y) {
120         return FreeImage_GetScanLine(_bitmap, y);
121     }
122     /// Converts an image to 4-bits.
123     /// Returns: Converted image.
124     Bitmap convertTo4Bits() {
125         return new Bitmap(_lib, FreeImage_ConvertTo4Bits(_bitmap));
126     }
127     /// Converts an image to 8-bits.
128     /// Returns: Converted image.
129     Bitmap convertTo8Bits() {
130         return new Bitmap(_lib, FreeImage_ConvertTo8Bits(_bitmap));
131     }
132     /// Converts an image to greyscale.
133     /// Returns: Converted image.
134     Bitmap convertToGreyscale() {
135         return new Bitmap(_lib, FreeImage_ConvertToGreyscale(_bitmap));
136     }
137     /// Converts an image to 16-bits 555.
138     /// Returns: Converted image.
139     Bitmap convertTo16Bits555() {
140         return new Bitmap(_lib, FreeImage_ConvertTo16Bits555(_bitmap));
141     }
142     /// Converts an image to 16-bits 565.
143     /// Returns: Converted image.
144     Bitmap convertTo16Bits565() {
145         return new Bitmap(_lib, FreeImage_ConvertTo16Bits565(_bitmap));
146     }
147     /// Converts an image to 24-bits.
148     /// Returns: Converted image.
149     Bitmap convertTo24Bits() {
150         return new Bitmap(_lib, FreeImage_ConvertTo24Bits(_bitmap));
151     }
152     /// Converts an image to 32-bits.
153     /// Throws: ImageException on error.
154     /// Returns: Converted image.
155     Bitmap convertTo32Bits() {
156         return new Bitmap(_lib, FreeImage_ConvertTo32Bits(_bitmap));
157     }
158     /// Converts an image to another format.
159     /// Throws: ImageException on error.
160     /// Returns: Converted image.
161     Bitmap convertToType(FREE_IMAGE_TYPE dstType, bool scaleLinear = true) {
162         FIBITMAP* converted = FreeImage_ConvertToType(_bitmap, dstType, scaleLinear);
163         if (converted is null)
164             throw new ImageException("disallowed conversion");
165         return new Bitmap(_lib, converted);
166     }
167     /// Converts an image to float format.
168     /// Returns: Converted image.
169     Bitmap convertToFloat() {
170         return new Bitmap(_lib, FreeImage_ConvertToFloat(_bitmap));
171     }
172     /// Converts an image to RGBF format.
173     /// Returns: Converted image.
174     Bitmap convertToRGBF() {
175         return new Bitmap(_lib, FreeImage_ConvertToRGBF(_bitmap));
176     }
177     /// Converts an image to UINT16 format.
178     /// Returns: Converted image.
179     Bitmap convertToUINT16() {
180         return new Bitmap(_lib, FreeImage_ConvertToUINT16(_bitmap));
181     }
182     /// Converts an image to RGB16 format.
183     /// Returns: Converted image.
184     Bitmap convertToRGB16() {
185         return new Bitmap(_lib, FreeImage_ConvertToRGB16(_bitmap));
186     }
187     /// Clones an image.
188     /// Returns: Cloned image.
189     Bitmap clone() {
190         return new Bitmap(_lib, FreeImage_Clone(_bitmap));
191     }
192     /// Applies color quantization.
193     Bitmap colorQuantize(FREE_IMAGE_QUANTIZE quantize) {
194         return new Bitmap(_lib, FreeImage_ColorQuantize(_bitmap, quantize));
195     }
196     /// Applies tone-mapping operator.
197     Bitmap toneMapDrago03(double gamma = 2.2, double exposure = 0.0) {
198         return new Bitmap(_lib, FreeImage_TmoDrago03(_bitmap, gamma, exposure));
199     }
200     /// Rescales the image.
201     Bitmap rescale(int dstWidth, int dstHeight, FREE_IMAGE_FILTER filter) {
202         return new Bitmap(_lib, FreeImage_Rescale(_bitmap, dstWidth, dstHeight, filter));
203     }
204     /// Flips the image vertically.
205     /// Throws: ImageException on error.
206     void horizontalFlip() {
207         BOOL res = FreeImage_FlipHorizontal(_bitmap);
208         if (res == FALSE)
209             throw new ImageException("cannot flip image horizontally");
210     }
211     /// Flips the image horizontally.
212     /// Throws: FreeImageException on error.
213     void verticalFlip() {
214         BOOL res = FreeImage_FlipVertical(_bitmap);
215         if (res == FALSE)
216             throw new ImageException("cannot flip image horizontally");
217     }
218     /// Rotates the image.
219     /// Returns: Rotated image.
220     Bitmap rotate(double angle, void* bkColor = null) {
221         return new Bitmap(_lib, FreeImage_Rotate(_bitmap, angle, bkColor));
222     }
223     ///
224     uint numberOfChannels() {
225         uint bytespp = FreeImage_GetLine(_bitmap) / FreeImage_GetWidth(_bitmap);
226         uint samples = bytespp / imageType.sizeof;
227         return samples;
228     }
229 }