1 module sbylib.wrapper.freeimage.image; 2 3 import derelict.freeimage.freeimage; 4 import sbylib.wrapper.freeimage.freeimage; 5 6 public import sbylib.wrapper.freeimage.constants; 7 8 import std.format : format; 9 10 /** 11 Class represented FIBITMAP. 12 */ 13 class Image { 14 15 private FIBITMAP* bitmap; 16 17 /** 18 Constructor by image size and image type. 19 20 Params: 21 width = image width 22 height = image height 23 type = flag used to specify the bitmap type 24 */ 25 this(int width, int height, ImageType type) { 26 this(FreeImage().allocate(width, height, type)); 27 } 28 29 /** 30 Constructor by image size and bpp. 31 32 Params: 33 width = image width 34 height = image height 35 bpp = number to specify the bit depth of the image 36 */ 37 this(int width, int height, int bpp) { 38 this(FreeImage().allocate(width, height, bpp)); 39 } 40 41 package this(FIBITMAP* bitmap) 42 in(bitmap !is null) 43 { 44 this.bitmap = bitmap; 45 } 46 47 ~this() { 48 FreeImage().unload(this.bitmap); 49 } 50 51 /** 52 Load image. 53 This function is same as ImageLoader.load. 54 55 Params: 56 path = image file path 57 58 Returns: loaded image 59 60 See_Also: ImageLoader.load 61 */ 62 static Image load(string path) { 63 import sbylib.wrapper.freeimage.imageloader : ImageLoader; 64 65 return ImageLoader.load(path); 66 } 67 68 /** 69 Converts a bitmap to 32 bits. A clone of the input bitmap is returned for 32-bit bitmaps. 70 For 48-bit RGB images, conversion is done by dividing each 16-bit channel by 256 and by setting the alpha channel to an opaque value (0xFF). For 64-bit RGBA images, conversion is done by dividing each 16-bit channel by 256. A NULL value is returned for other nonstandard bitmap types. 71 72 Returns: conveted image 73 */ 74 Image to32bit() { 75 return new Image(FreeImage().convertTo32Bits(bitmap)); 76 } 77 78 /** 79 Returns the width of the bitmap in pixel units. 80 81 Returns: the width of the bitmap in pixel units 82 */ 83 int width() { 84 return FreeImage().getWidth(bitmap); 85 } 86 87 /** 88 Returns the height of the bitmap in pixel units. 89 90 Returns: the height of the bitmap in pixel units 91 */ 92 int height() { 93 return FreeImage().getHeight(bitmap); 94 } 95 96 /** 97 Returns the size of one pixel in the bitmap in bits. For example when each pixel takes 32-bits of space in the bitmap, this function returns 32. Possible bit depths are 1, 4, 8, 16, 24, 32 for standard bitmaps and 16-, 32-, 48-, 64-, 96- and 128-bit for non standard bitmaps. 98 99 Returns: the bit depth of the bitmap 100 */ 101 uint bpp() { 102 return FreeImage().getBPP(bitmap); 103 } 104 105 /** 106 Returns how many channels the image has. 107 This is calculated by (bpp) / (1 channel bits). 108 1 channel bits is estimated by image type. 109 110 Returns: the channels of the image 111 */ 112 uint channels() { 113 return bpp / getTypeBits(imageType); 114 } 115 116 /** 117 Returns the raw pointer to the image data for low level API. 118 119 Returns: the pointer to the raw image data. 120 */ 121 void* rawPointer() { 122 return FreeImage().getBits(bitmap); 123 } 124 125 RGBQUAD* palette() { 126 return FreeImage().getPalette(bitmap); 127 } 128 129 /** 130 Returns the raw image data as T[]. 131 132 Returns: an array pointing to the raw data. 133 */ 134 T[] dataArray(T=ubyte)() { 135 return (cast(T*)rawPointer)[0..width * height * bpp / (8*T.sizeof)]; 136 } 137 138 /** 139 Returns the type of the image. 140 141 Returns: the type of the image 142 */ 143 ImageType imageType() { 144 import std.conv : to; 145 return FreeImage_GetImageType(bitmap).to!ImageType; 146 } 147 148 /** 149 Save the image. 150 The extension is estimated by the output path. 151 152 Params: 153 path = where the image is saved 154 */ 155 void save(string path) { 156 import std.path : extension; 157 158 switch(path.extension) { 159 case ".bmp": 160 saveAsBmp(path); 161 break; 162 case ".exr": 163 saveAsExr(path); 164 break; 165 case ".jpeg": 166 case ".jpg": 167 saveAsJpeg(path); 168 break; 169 case ".png": 170 saveAsPng(path); 171 break; 172 case ".tiff": 173 saveAsTiff(path); 174 break; 175 default: 176 assert(false, "Unrecognized format '" ~ path.extension ~ "'"); 177 } 178 } 179 180 /** 181 Save the image as bmp. 182 183 Params: 184 path = where the image is saved 185 rle = compress the bitmap using RLE when saving 186 */ 187 void saveAsBmp(string path, bool rle = false) { 188 save(ImageFormat.Bmp, path, (rle ? BMP_SAVE_RLE : BMP_DEFAULT)); 189 } 190 191 /** 192 Save the image as exr. 193 194 Params: 195 path = where the image is saved 196 saveAs32Bit = save data as float instead of as half (not recommended) 197 compress = compression method 198 199 See_Also: ExrCompressOption 200 */ 201 void saveAsExr(string path, bool saveAs32Bit = false, ExrCompressOption compress = ExrCompressOption.None) { 202 save(ImageFormat.Exr, path, 203 (saveAs32Bit ? EXR_FLOAT : EXR_DEFAULT) 204 | (compress)); 205 } 206 207 /** 208 Save the image as j2k. 209 210 Params: 211 path = where the image is saved 212 rate = Save with a rate:1 213 */ 214 void saveAsJ2k(string path, int rate = J2K_DEFAULT) 215 in(1 <= rate && rate <= 512) 216 { 217 save(ImageFormat.J2k, path, rate); 218 } 219 220 /** 221 Save the image as jp2. 222 223 Params: 224 path = where the image is saved 225 rate = Save with a rate:1 226 */ 227 void saveAsJp2(string path, int rate = JP2_DEFAULT) 228 in(1 <= rate && rate <= 512) 229 { 230 save(ImageFormat.Jp2, path, rate); 231 } 232 233 /** 234 Save the image as jpeg. 235 236 Params: 237 path = where the image is saved 238 quality = save quality(%) 239 progressive = save as a progressive JPEG file 240 subsampling = for SubSampling4ab, save with 4:a:b 241 optimize = On saving, compute optimal Huffman coding tables (can reduce a few percent of file size) 242 baseline = Save basic JPEG, without metadata or any markers 243 */ 244 void saveAsJpeg(string path, int quality = 75, bool progressive = false, 245 JpegSaveSubsamplingOption subsampling = JpegSaveSubsamplingOption.Subsampling420, 246 bool optimize = false, bool baseline = false) 247 in(0 <= quality && quality <= 100) 248 { 249 save(ImageFormat.Jpeg, path, 250 quality 251 | (progressive & JPEG_PROGRESSIVE) 252 | (subsampling) 253 | (optimize & JPEG_OPTIMIZE) 254 | (baseline & JPEG_BASELINE)); 255 } 256 257 /** 258 Save the image as png. 259 260 Params: 261 path = where the image is saved 262 compress = compression level 263 interlace = Save using Adam7 interlacing 264 */ 265 void saveAsPng(string path, 266 PngCompressOption compress = PngCompressOption.DefaultCompression, bool interlace = false) { 267 save(ImageFormat.Png, path, 268 (compress) 269 | (interlace & PNG_INTERLACED)); 270 } 271 272 /** 273 Save the image as pbm. 274 275 Params: 276 path = where the image is saved 277 option = Saves the bitmap as a binary file or an ascii file 278 */ 279 void saveAsPbm(string path, PnmSaveOption option = PnmSaveOption.Raw) { 280 save(ImageFormat.Pbm, path, option); 281 } 282 283 /** 284 Save the image as pgm. 285 286 Params: 287 path = where the image is saved 288 option = Saves the bitmap as a binary file or an ascii file 289 */ 290 void saveAsPgm(string path, PnmSaveOption option = PnmSaveOption.Raw) { 291 save(ImageFormat.Pgm, path, option); 292 } 293 294 /** 295 Save the image as ppm. 296 297 Params: 298 path = where the image is saved 299 option = Saves the bitmap as a binary file or an ascii file 300 */ 301 void saveAsPpm(string path, PnmSaveOption option = PnmSaveOption.Raw) { 302 save(ImageFormat.Ppm, path, option); 303 } 304 305 /** 306 Save the image as tiff. 307 308 Params: 309 path = where the image is saved 310 cmyk = Stores tags for separated CMYK (use | to combine with 311 TIFF compression flags) 312 compress = compression level 313 */ 314 void saveAsTiff(string path, bool cmyk = false, TiffCompressOption compress = TiffCompressOption.LZW) { 315 save(ImageFormat.Tiff, path, 316 (cmyk & TIFF_CMYK) 317 | (compress)); 318 } 319 320 private void save(ImageFormat fmt, string path, int option = 0) { 321 import std..string : toStringz; 322 323 const saveResult = FreeImage_Save(fmt, bitmap, path.toStringz, option); 324 325 assert(saveResult, format!"Failed to Save '%s'"(path)); 326 } 327 328 private static int getTypeBits(ImageType type) { 329 final switch(type) { 330 case ImageType.Unknown: assert(false, format!"Invalid Enum: %s"(type)); 331 case ImageType.Bitmap: return 8; 332 case ImageType.Rgb16: return 16; 333 case ImageType.Rgba16: return 16; 334 case ImageType.Rgbf: return 32; 335 case ImageType.Rgbaf: return 32; 336 case ImageType.Uint16: return 16; 337 case ImageType.Int16: return 16; 338 case ImageType.Uint32: return 32; 339 case ImageType.Int32: return 32; 340 case ImageType.Float: return 32; 341 case ImageType.Double: return 64; 342 case ImageType.Complex: return 128; 343 } 344 } 345 346 bool flipVertical() { 347 return FreeImage_FlipVertical(bitmap) > 0; 348 } 349 350 bool flipHorizontal() { 351 return FreeImage_FlipHorizontal(bitmap) > 0; 352 } 353 }