1 module dimage.types; 2 3 import std.bitmanip : bitfields; 4 //import std.conv : roundTo; 5 6 ///Sets the byteorder of 7 enum Endianness { 8 Little, 9 Big 10 } 11 12 alias ARGB8888 = ARGB8888Templ!(Endianness.Little); 13 alias ARGB8888BE = ARGB8888Templ!(Endianness.Big); 14 15 /** 16 * 4 * 32 bit floating point pixel representation. 17 * Used for RGBA conversion and other things. 18 */ 19 struct RGBA_f32 { 20 float fR; 21 float fG; 22 float fB; 23 float fA; 24 ///Standard CTOR 25 this(float fR, float fG, float fB, float fA) @safe @nogc pure nothrow { 26 this.fR = fR; 27 this.fG = fG; 28 this.fB = fB; 29 this.fA = fA; 30 } 31 ///Conversion CTOR 32 this(ColorType)(ColorType orig) @safe @nogc pure nothrow { 33 this.fR = orig.fR; 34 this.fG = orig.fG; 35 this.fB = orig.fB; 36 this.fA = orig.fA; 37 } 38 ///Conversion CTOR from monochrome 39 this(float fY, float fA = 1.0) @safe @nogc pure nothrow { 40 this.fR = fY; 41 this.fG = fY; 42 this.fB = fY; 43 this.fA = fA; 44 } 45 } 46 /** 47 * Standard 32 bit pixel representation. 48 */ 49 struct ARGB8888Templ (Endianness byteOrder = Endianness.Little) { 50 union{ 51 ubyte[4] bytes; /// BGRA 52 uint base; /// Direct address 53 } 54 static if (byteOrder == Endianness.Big) { 55 ///Red 56 @safe @nogc @property nothrow pure ref auto r() inout { return bytes[1]; } 57 ///Green 58 @safe @nogc @property nothrow pure ref auto g() inout { return bytes[2]; } 59 ///Blue 60 @safe @nogc @property nothrow pure ref auto b() inout { return bytes[3]; } 61 ///Alpha 62 @safe @nogc @property nothrow pure ref auto a() inout { return bytes[0]; } 63 } else { 64 ///Red 65 @safe @nogc @property nothrow pure ref auto r() inout { return bytes[2]; } 66 ///Green 67 @safe @nogc @property nothrow pure ref auto g() inout { return bytes[1]; } 68 ///Blue 69 @safe @nogc @property nothrow pure ref auto b() inout { return bytes[0]; } 70 ///Alpha 71 @safe @nogc @property nothrow pure ref auto a() inout { return bytes[3]; } 72 } 73 static immutable double fRStepping = 1.0 / 255; ///Floating-point red stepping 74 static immutable double fGStepping = 1.0 / 255; ///Floating-point green stepping 75 static immutable double fBStepping = 1.0 / 255; ///Floating-point blue stepping 76 static immutable double fAStepping = 1.0 / 255; ///Floating-point alpha stepping 77 ///Returns the red channel as a normalized floating-point value 78 @property float fR() @safe @nogc pure nothrow const { 79 return r * fRStepping; 80 } 81 ///Returns the green channel as a normalized floating-point value 82 @property float fG() @safe @nogc pure nothrow const { 83 return g * fGStepping; 84 } 85 ///Returns the blue channel as a normalized floating-point value 86 @property float fB() @safe @nogc pure nothrow const { 87 return b * fBStepping; 88 } 89 ///Returns the alpha channel as a normalized floating-point value 90 @property float fA() @safe @nogc pure nothrow const { 91 return a * fAStepping; 92 } 93 ///Sets the red value channel a normalized floating-point value 94 ///Returns the new requantized value 95 @property float fR(float val) @safe @nogc pure nothrow { 96 //if(val >= 1) r = 255; 97 //else 98 r = cast(ubyte)(val / fRStepping); 99 return fR; 100 } 101 ///Sets the green value channel a normalized floating-point value 102 ///Returns the new requantized value 103 @property float fG(float val) @safe @nogc pure nothrow { 104 g = cast(ubyte)(val / fGStepping); 105 return fG; 106 } 107 ///Sets the blue value channel a normalized floating-point value 108 ///Returns the new requantized value 109 @property float fB(float val) @safe @nogc pure nothrow { 110 b = cast(ubyte)(val / fBStepping); 111 return fB; 112 } 113 ///Sets the alpha value channel a normalized floating-point value 114 ///Returns the new requantized value 115 @property float fA(float val) @safe @nogc pure nothrow { 116 a = cast(ubyte)(val / fAStepping); 117 return fA; 118 } 119 ///Creates a standard pixel representation out from a 4 element array 120 this(ubyte[4] bytes) @safe @nogc pure nothrow { 121 this.bytes = bytes; 122 } 123 ///Creates a standard pixel representation out from 4 separate values 124 this(ubyte r, ubyte g, ubyte b, ubyte a) @safe @nogc pure nothrow { 125 this.b = b; 126 this.g = g; 127 this.r = r; 128 this.a = a; 129 } 130 ///Standard CTOR 131 this(float fR, float fG, float fB, float fA) @safe @nogc pure nothrow { 132 this.fR = fR; 133 this.fG = fG; 134 this.fB = fB; 135 this.fA = fA; 136 } 137 ///Template for pixel conversion 138 this(ColorType)(ColorType orig) @safe @nogc pure nothrow { 139 this.fB = orig.fB; 140 this.fG = orig.fG; 141 this.fR = orig.fR; 142 this.fA = orig.fA; 143 } 144 ///Conversion CTOR from monochrome 145 this(float fY, float fA = 1.0) @safe @nogc pure nothrow { 146 this.fR = fY; 147 this.fG = fY; 148 this.fB = fY; 149 this.fA = fA; 150 } 151 ///Conversion from 8bit monochrome 152 this(ubyte p) @safe @nogc pure nothrow { 153 this.b = p; 154 this.g = p; 155 this.r = p; 156 this.a = 0xFF; 157 } 158 ///String representation of this struct 159 string toString() const { 160 import std.conv : to; 161 return to!string(r) ~ "," ~ to!string(g) ~ "," ~ to!string(b) ~ "," ~ to!string(a); 162 } 163 ///Returns true if type has alpha channel support 164 static bool hasAlphaChannelSupport() { 165 return true; 166 } 167 168 } 169 170 alias RGBA8888BE = RGBA8888Templ!(Endianness.Big); 171 alias RGBA8888 = RGBA8888Templ!(Endianness.Little); 172 /** 173 * Standard 32 bit pixel representation. 174 */ 175 struct RGBA8888Templ (Endianness byteOrder = Endianness.Little) { 176 union{ 177 ubyte[4] bytes; /// RGBA 178 uint base; /// Direct address 179 } 180 static if (byteOrder == Endianness.Big) { 181 ///Red 182 @safe @nogc @property pure ref auto r() inout { return bytes[0]; } 183 ///Green 184 @safe @nogc @property pure ref auto g() inout { return bytes[1]; } 185 ///Blue 186 @safe @nogc @property pure ref auto b() inout { return bytes[2]; } 187 ///Alpha 188 @safe @nogc @property pure ref auto a() inout { return bytes[3]; } 189 } else { 190 ///Red 191 @safe @nogc @property pure ref auto r() inout { return bytes[3]; } 192 ///Green 193 @safe @nogc @property pure ref auto g() inout { return bytes[2]; } 194 ///Blue 195 @safe @nogc @property pure ref auto b() inout { return bytes[1]; } 196 ///Alpha 197 @safe @nogc @property pure ref auto a() inout { return bytes[0]; } 198 } 199 static immutable double fRStepping = 1.0 / 255; ///Floating-point red stepping 200 static immutable double fGStepping = 1.0 / 255; ///Floating-point green stepping 201 static immutable double fBStepping = 1.0 / 255; ///Floating-point blue stepping 202 static immutable double fAStepping = 1.0 / 255; ///Floating-point alpha stepping 203 ///Returns the red channel as a normalized floating-point value 204 @property float fR() @safe @nogc pure nothrow const { 205 return r * fRStepping; 206 } 207 ///Returns the green channel as a normalized floating-point value 208 @property float fG() @safe @nogc pure nothrow const { 209 return g * fGStepping; 210 } 211 ///Returns the blue channel as a normalized floating-point value 212 @property float fB() @safe @nogc pure nothrow const { 213 return b * fBStepping; 214 } 215 ///Returns the alpha channel as a normalized floating-point value 216 @property float fA() @safe @nogc pure nothrow const { 217 return a * fAStepping; 218 } 219 ///Sets the red value channel a normalized floating-point value 220 ///Returns the new requantized value 221 @property float fR(float val) @safe @nogc pure nothrow { 222 r = cast(ubyte)(val / fRStepping); 223 return fR; 224 } 225 ///Sets the green value channel a normalized floating-point value 226 ///Returns the new requantized value 227 @property float fG(float val) @safe @nogc pure nothrow { 228 g = cast(ubyte)(val / fGStepping); 229 return fG; 230 } 231 ///Sets the blue value channel a normalized floating-point value 232 ///Returns the new requantized value 233 @property float fB(float val) @safe @nogc pure nothrow { 234 b = cast(ubyte)(val / fBStepping); 235 return fB; 236 } 237 ///Sets the alpha value channel a normalized floating-point value 238 ///Returns the new requantized value 239 @property float fA(float val) @safe @nogc pure nothrow { 240 a = cast(ubyte)(val / fAStepping); 241 return fA; 242 } 243 ///Creates a standard pixel representation out from a 4 element array 244 this(ubyte[4] bytes) @safe @nogc pure nothrow { 245 this.bytes = bytes; 246 } 247 ///Creates a standard pixel representation out from 4 separate values 248 this(ubyte r, ubyte g, ubyte b, ubyte a) @safe @nogc pure nothrow { 249 bytes[0] = r; 250 bytes[1] = g; 251 bytes[2] = b; 252 bytes[3] = a; 253 } 254 ///Standard CTOR 255 this(float fR, float fG, float fB, float fA) @safe @nogc pure nothrow { 256 this.fR = fR; 257 this.fG = fG; 258 this.fB = fB; 259 this.fA = fA; 260 } 261 ///Conversion CTOR from monochrome 262 this(float fY, float fA = 1.0) @safe @nogc pure nothrow { 263 this.fR = fY; 264 this.fG = fY; 265 this.fB = fY; 266 this.fA = fA; 267 } 268 ///Template for pixel conversion 269 this(ColorType)(ColorType orig) @safe @nogc pure nothrow { 270 this.fB = orig.fB; 271 this.fG = orig.fG; 272 this.fR = orig.fR; 273 this.fA = orig.fA; 274 } 275 ///Conversion from 8bit monochrome 276 this(ubyte p) @safe @nogc pure nothrow { 277 this.b = p; 278 this.g = p; 279 this.r = p; 280 this.a = 0xFF; 281 } 282 ///Returns true if type has alpha channel support 283 static bool hasAlphaChannelSupport() { 284 return true; 285 } 286 } 287 alias YA88 = YA88Templ!(Endianness.Little); 288 alias YA88BE = YA88Templ!(Endianness.Big); 289 /** 290 * For monochrome images with a single channel 291 */ 292 struct YA88Templ (Endianness byteOrder = Endianness.Little) { 293 union{ 294 ushort base; /// direct access 295 ubyte[2] channels; /// individual access 296 } 297 static immutable double fRStepping = 1.0 / 255; ///Floating-point red stepping 298 static immutable double fGStepping = 1.0 / 255; ///Floating-point green stepping 299 static immutable double fBStepping = 1.0 / 255; ///Floating-point blue stepping 300 static immutable double fAStepping = 1.0 / 255; ///Floating-point alpha stepping 301 ///Returns the red channel as a normalized floating-point value 302 @property float fR() @safe @nogc pure nothrow const { 303 return y * fRStepping; 304 } 305 ///Returns the green channel as a normalized floating-point value 306 @property float fG() @safe @nogc pure nothrow const { 307 return y * fGStepping; 308 } 309 ///Returns the blue channel as a normalized floating-point value 310 @property float fB() @safe @nogc pure nothrow const { 311 return y * fBStepping; 312 } 313 ///Returns the alpha channel as a normalized floating-point value 314 @property float fA() @safe @nogc pure nothrow const { 315 return a * fAStepping; 316 } 317 ///Sets the red value channel a normalized floating-point value 318 ///Returns the new requantized value 319 @property float fR(float val) @safe @nogc pure nothrow { 320 y = cast(ubyte)(val / fRStepping); 321 return fR; 322 } 323 ///Sets the green value channel a normalized floating-point value 324 ///Returns the new requantized value 325 @property float fG(float val) @safe @nogc pure nothrow { 326 y = cast(ubyte)(val / fGStepping); 327 return fG; 328 } 329 ///Sets the blue value channel a normalized floating-point value 330 ///Returns the new requantized value 331 @property float fB(float val) @safe @nogc pure nothrow { 332 y = cast(ubyte)(val / fBStepping); 333 return fB; 334 } 335 ///Sets the alpha value channel a normalized floating-point value 336 ///Returns the new requantized value 337 @property float fA(float val) @safe @nogc pure nothrow { 338 a = cast(ubyte)(val / fAStepping); 339 return fA; 340 } 341 ///Standard CTOR 342 this(ubyte y, ubyte a) @safe @nogc pure nothrow { 343 this.y = y; 344 this.a = a; 345 } 346 ///Standard CTOR 347 this(float fR, float fG, float fB, float fA) @safe @nogc pure nothrow { 348 this.fB = 0.2125 * fR + 0.7154 * fG + 0.0721 * fB; 349 this.fA = fA; 350 } 351 ///Template for pixel conversion 352 ///Uses mathematical average to calculate the new values 353 this(ColorType)(ColorType orig) @safe @nogc pure nothrow { 354 this.fB = 0.2125 * orig.fR + 0.7154 * orig.fG + 0.0721 * orig.fB; 355 this.fA = orig.fA; 356 } 357 ///Conversion CTOR from monochrome 358 this(float fY, float fA = 1.0) @safe @nogc pure nothrow { 359 this.fR = fY; 360 this.fA = fA; 361 } 362 ///Conversion from 8bit monochrome 363 this(ubyte p) @safe @nogc pure nothrow { 364 this.y = p; 365 this.a = 0xFF; 366 } 367 /// luminance 368 nothrow @safe @nogc @property pure ref auto y() inout { 369 static if(byteOrder == Endianness.Big) { 370 return channels[1]; 371 } else { 372 return channels[0]; 373 } 374 } 375 /// alpha 376 nothrow @safe @nogc @property pure ref auto a() inout { 377 static if(byteOrder == Endianness.Big) { 378 return channels[0]; 379 } else { 380 return channels[1]; 381 } 382 } 383 /// pseudo-red (output only) 384 nothrow @safe @nogc @property pure ubyte r() const { return y; } 385 /// pseudo-green (output only) 386 nothrow @safe @nogc @property pure ubyte g() const { return y; } 387 /// pseudo-blue (output only) 388 nothrow @safe @nogc @property pure ubyte b() const { return y; } 389 ///Returns true if type has alpha channel support 390 static bool hasAlphaChannelSupport() { 391 return true; 392 } 393 } 394 alias YA16_16 = YA16_16Templ!(Endianness.Little); 395 alias YA16_16BE = YA16_16Templ!(Endianness.Big); 396 /** 397 * For monochrome images with a single channel 398 */ 399 struct YA16_16Templ (Endianness byteOrder = Endianness.Little) { 400 union{ 401 uint base; /// direct access 402 ushort[2] channels; /// individual access 403 } 404 static immutable double fRStepping = 1.0 / 65_535; ///Floating-point red stepping 405 static immutable double fGStepping = 1.0 / 65_535; ///Floating-point green stepping 406 static immutable double fBStepping = 1.0 / 65_535; ///Floating-point blue stepping 407 static immutable double fAStepping = 1.0 / 65_535; ///Floating-point alpha stepping 408 ///Returns the red channel as a normalized floating-point value 409 @property float fR() @safe @nogc pure nothrow const { 410 return y * fRStepping; 411 } 412 ///Returns the green channel as a normalized floating-point value 413 @property float fG() @safe @nogc pure nothrow const { 414 return y * fGStepping; 415 } 416 ///Returns the blue channel as a normalized floating-point value 417 @property float fB() @safe @nogc pure nothrow const { 418 return y * fBStepping; 419 } 420 ///Returns the alpha channel as a normalized floating-point value 421 @property float fA() @safe @nogc pure nothrow const { 422 return a * fAStepping; 423 } 424 ///Sets the red value channel a normalized floating-point value 425 ///Returns the new requantized value 426 @property float fR(float val) @safe @nogc pure nothrow { 427 y = cast(ubyte)(val / fRStepping); 428 return fR; 429 } 430 ///Sets the green value channel a normalized floating-point value 431 ///Returns the new requantized value 432 @property float fG(float val) @safe @nogc pure nothrow { 433 y = cast(ubyte)(val / fGStepping); 434 return fG; 435 } 436 ///Sets the blue value channel a normalized floating-point value 437 ///Returns the new requantized value 438 @property float fB(float val) @safe @nogc pure nothrow { 439 y = cast(ubyte)(val / fBStepping); 440 return fB; 441 } 442 ///Sets the alpha value channel a normalized floating-point value 443 ///Returns the new requantized value 444 @property float fA(float val) @safe @nogc pure nothrow { 445 a = cast(ubyte)(val / fAStepping); 446 return fA; 447 } 448 ///Standard CTOR 449 this(ushort y, ushort a) @safe @nogc pure nothrow { 450 this.y = y; 451 this.a = a; 452 } 453 ///Standard CTOR 454 this(float fR, float fG, float fB, float fA) @safe @nogc pure nothrow { 455 this.fB = 0.2125 * fR + 0.7154 * fG + 0.0721 * fB; 456 this.fA = fA; 457 } 458 ///Template for pixel conversion 459 ///Uses mathematical average to calculate the new values 460 this(ColorType)(ColorType orig) @safe @nogc pure nothrow { 461 this.fB = 0.2125 * orig.fR + 0.7154 * orig.fG + 0.0721 * orig.fB; 462 this.fA = orig.fA; 463 } 464 ///Conversion CTOR from monochrome 465 this(float fY, float fA = 1.0) @safe @nogc pure nothrow { 466 this.fR = fY; 467 this.fA = fA; 468 } 469 ///Conversion from 8bit monochrome 470 this(ubyte p) @safe @nogc pure nothrow { 471 this.y = p; 472 this.a = 0xFF; 473 } 474 /// luminance 475 nothrow @safe @nogc @property pure ref auto y() inout { 476 static if(byteOrder == Endianness.Big) { 477 return channels[1]; 478 } else { 479 return channels[0]; 480 } 481 } 482 /// alpha 483 nothrow @safe @nogc @property pure ref auto a() inout { 484 static if(byteOrder == Endianness.Big) { 485 return channels[0]; 486 } else { 487 return channels[1]; 488 } 489 } 490 /// pseudo-red (output only) 491 nothrow @safe @nogc @property pure ushort r() const { return y; } 492 /// pseudo-green (output only) 493 nothrow @safe @nogc @property pure ushort g() const { return y; } 494 /// pseudo-blue (output only) 495 nothrow @safe @nogc @property pure ushort b() const { return y; } 496 ///Returns true if type has alpha channel support 497 static bool hasAlphaChannelSupport() { 498 return true; 499 } 500 } 501 /** 502 * 16 Bit colorspace with a single bit alpha. This is should be used with RGBX5551 with channel `a` ignored 503 */ 504 struct RGBA5551 { 505 union{ 506 ushort base; /// direct access 507 mixin(bitfields!( 508 ubyte, "_b", 5, 509 ubyte, "_g", 5, 510 ubyte, "_r", 5, 511 bool, "_a", 1, 512 )); 513 } 514 static immutable double fRStepping = 1.0 / 31; ///Floating-point red stepping 515 static immutable double fGStepping = 1.0 / 31; ///Floating-point green stepping 516 static immutable double fBStepping = 1.0 / 31; ///Floating-point blue stepping 517 static immutable double fAStepping = 1.0; ///Floating-point alpha stepping 518 ///Returns the red channel as a normalized floating-point value 519 @property float fR() @safe @nogc pure nothrow const { 520 return _r * fRStepping; 521 } 522 ///Returns the green channel as a normalized floating-point value 523 @property float fG() @safe @nogc pure nothrow const { 524 return _g * fGStepping; 525 } 526 ///Returns the blue channel as a normalized floating-point value 527 @property float fB() @safe @nogc pure nothrow const { 528 return _b * fBStepping; 529 } 530 ///Returns the alpha channel as a normalized floating-point value 531 @property float fA() @safe @nogc pure nothrow const { 532 return _a ? 1.0 : 0.0; 533 } 534 ///Sets the red value channel a normalized floating-point value 535 ///Returns the new requantized value 536 @property float fR(float val) @safe @nogc pure nothrow { 537 _r = cast(ubyte)(val / fRStepping); 538 return fR; 539 } 540 ///Sets the green value channel a normalized floating-point value 541 ///Returns the new requantized value 542 @property float fG(float val) @safe @nogc pure nothrow { 543 _g = cast(ubyte)(val / fGStepping); 544 return fG; 545 } 546 ///Sets the blue value channel a normalized floating-point value 547 ///Returns the new requantized value 548 @property float fB(float val) @safe @nogc pure nothrow { 549 _b = cast(ubyte)(val / fBStepping); 550 return fB; 551 } 552 ///Sets the alpha value channel a normalized floating-point value 553 ///Returns the new requantized value 554 @property float fA(float val) @safe @nogc pure nothrow { 555 _a = val == 0.0; 556 return fA; 557 } 558 /// Standard CTOR with 8bit normalized inputs 559 this(ubyte r, ubyte g, ubyte b, ubyte a) @safe @nogc pure nothrow { 560 _r = r>>3; 561 _g = g>>3; 562 _b = b>>3; 563 _a = a != 0; 564 } 565 ///Standard CTOR 566 this(float fR, float fG, float fB, float fA) @safe @nogc pure nothrow { 567 this.fR = fR; 568 this.fG = fG; 569 this.fB = fB; 570 this.fA = fA; 571 } 572 ///Conversion CTOR from monochrome 573 this(float fY, float fA = 1.0) @safe @nogc pure nothrow { 574 this.fR = fY; 575 this.fG = fY; 576 this.fB = fY; 577 this.fA = fA; 578 } 579 ///Template for pixel conversion 580 this(ColorType)(ColorType orig) @safe @nogc pure { 581 this.fB = orig.fB; 582 this.fG = orig.fG; 583 this.fR = orig.fR; 584 this.fA = orig.fA; 585 } 586 ///Conversion from 8bit monochrome 587 this(ubyte p) @safe @nogc pure nothrow { 588 _b = p>>3; 589 _g = p>>3; 590 _r = p>>3; 591 _a = true; 592 } 593 /// upconverted-red (output only) 594 nothrow @safe @nogc @property pure ubyte r() const { return cast(ubyte)(_r << 3 | _r >>> 2); } 595 /// upconverted-green (output only) 596 nothrow @safe @nogc @property pure ubyte g() const { return cast(ubyte)(_g << 3 | _g >>> 2); } 597 /// upconverted-blue (output only) 598 nothrow @safe @nogc @property pure ubyte b() const { return cast(ubyte)(_b << 3 | _b >>> 2); } 599 /// upconverted-alpha 600 nothrow @safe @nogc @property pure ubyte a() const { return _a ? 0xFF : 0x00; } 601 ///Returns true if type has alpha channel support 602 static bool hasAlphaChannelSupport() { 603 return true; 604 } 605 } 606 /** 607 * 16 Bit RGB565 colorspace with no alpha. 608 */ 609 struct RGB565 { 610 union{ 611 ushort base; /// direct access 612 mixin(bitfields!( 613 ubyte, "_b", 5, 614 ubyte, "_g", 6, 615 ubyte, "_r", 5, 616 )); 617 } 618 static immutable double fRStepping = 1.0 / 31; ///Floating-point red stepping 619 static immutable double fGStepping = 1.0 / 63; ///Floating-point green stepping 620 static immutable double fBStepping = 1.0 / 31; ///Floating-point blue stepping 621 static immutable double fAStepping = 1.0; ///Floating-point alpha stepping 622 ///Returns the red channel as a normalized floating-point value 623 @property float fR() @safe @nogc pure nothrow const { 624 return _r * fRStepping; 625 } 626 ///Returns the green channel as a normalized floating-point value 627 @property float fG() @safe @nogc pure nothrow const { 628 return _g * fGStepping; 629 } 630 ///Returns the blue channel as a normalized floating-point value 631 @property float fB() @safe @nogc pure nothrow const { 632 return _b * fBStepping; 633 } 634 ///Returns the alpha channel as a normalized floating-point value 635 @property float fA() @safe @nogc pure nothrow const { 636 return 1.0; 637 } 638 ///Sets the red value channel a normalized floating-point value 639 ///Returns the new requantized value 640 @property float fR(float val) @safe @nogc pure nothrow { 641 _r = cast(ubyte)(val / fRStepping); 642 return fR; 643 } 644 ///Sets the green value channel a normalized floating-point value 645 ///Returns the new requantized value 646 @property float fG(float val) @safe @nogc pure nothrow { 647 _g = cast(ubyte)(val / fGStepping); 648 return fG; 649 } 650 ///Sets the blue value channel a normalized floating-point value 651 ///Returns the new requantized value 652 @property float fB(float val) @safe @nogc pure nothrow { 653 _b = cast(ubyte)(val / fBStepping); 654 return fB; 655 } 656 ///Sets the alpha value channel a normalized floating-point value 657 ///Returns the new requantized value 658 @property float fA(float val) @safe @nogc pure nothrow { 659 return 1.0; 660 } 661 /// Standard CTOR with 8bit normalized inputs 662 this(ubyte r, ubyte g, ubyte b) @safe @nogc pure nothrow { 663 _r = r>>3; 664 _g = g>>2; 665 _b = b>>3; 666 } 667 ///Standard CTOR 668 this(float fR, float fG, float fB, float fA) @safe @nogc pure nothrow { 669 this.fR = fR; 670 this.fG = fG; 671 this.fB = fB; 672 this.fA = fA; 673 } 674 ///Template for pixel conversion 675 this(ColorType)(ColorType orig) @safe @nogc pure nothrow { 676 this.fB = orig.fB; 677 this.fG = orig.fG; 678 this.fR = orig.fR; 679 this.fA = orig.fA; 680 } 681 ///Conversion CTOR from monochrome 682 this(float fY, float fA = 1.0) @safe @nogc pure nothrow { 683 this.fR = fY; 684 this.fG = fY; 685 this.fB = fY; 686 this.fA = fA; 687 } 688 ///Conversion from 8bit monochrome 689 this(ubyte p) @safe @nogc pure nothrow { 690 _b = p>>3; 691 _g = p>>2; 692 _r = p>>3; 693 } 694 /// upconverted-red (output only) 695 nothrow @safe @nogc @property pure ubyte r() const { return cast(ubyte)(_r << 3 | _r >>> 2); } 696 /// upconverted-green (output only) 697 nothrow @safe @nogc @property pure ubyte g() const { return cast(ubyte)(_g << 2 | _g >>> 4); } 698 /// upconverted-blue (output only) 699 nothrow @safe @nogc @property pure ubyte b() const { return cast(ubyte)(_b << 3 | _b >>> 2); } 700 //pseudo-alpha (output only) 701 nothrow @safe @nogc @property pure ubyte a() const { return 0xFF; } 702 ///Returns true if type has alpha channel support 703 static bool hasAlphaChannelSupport() { 704 return false; 705 } 706 } 707 alias RGB888 = RGB888Templ!(Endianness.Little); 708 alias RGB888BE = RGB888Templ!(Endianness.Big); 709 /** 710 * 24 Bit colorspace 711 */ 712 align(1) struct RGB888Templ (Endianness byteOrder = Endianness.Little) { 713 ubyte[3] bytes; ///individual access 714 static if (byteOrder == Endianness.Big) { 715 ///red 716 nothrow @safe @nogc @property pure ref auto r() inout { return bytes[0]; } 717 ///green 718 nothrow @safe @nogc @property pure ref auto g() inout { return bytes[1]; } 719 ///blue 720 nothrow @safe @nogc @property pure ref auto b() inout { return bytes[2]; } 721 } else { 722 ///red 723 nothrow @safe @nogc @property pure ref auto r() inout { return bytes[2]; } 724 ///green 725 nothrow @safe @nogc @property pure ref auto g() inout { return bytes[1]; } 726 ///blue 727 nothrow @safe @nogc @property pure ref auto b() inout { return bytes[0]; } 728 } 729 static immutable double fRStepping = 1.0 / 255; ///Floating-point red stepping 730 static immutable double fGStepping = 1.0 / 255; ///Floating-point green stepping 731 static immutable double fBStepping = 1.0 / 255; ///Floating-point blue stepping 732 static immutable double fAStepping = 1.0; ///Floating-point alpha stepping 733 ///Returns the red channel as a normalized floating-point value 734 @property float fR() @safe @nogc pure nothrow const { 735 return r * fRStepping; 736 } 737 ///Returns the green channel as a normalized floating-point value 738 @property float fG() @safe @nogc pure nothrow const { 739 return g * fGStepping; 740 } 741 ///Returns the blue channel as a normalized floating-point value 742 @property float fB() @safe @nogc pure nothrow const { 743 return b * fBStepping; 744 } 745 ///Returns the alpha channel as a normalized floating-point value 746 @property float fA() @safe @nogc pure nothrow const { 747 return 1.0; 748 } 749 ///Sets the red value channel a normalized floating-point value 750 ///Returns the new requantized value 751 @property float fR(float val) @safe @nogc pure nothrow { 752 r = cast(ubyte)(val / fRStepping); 753 return fR; 754 } 755 ///Sets the green value channel a normalized floating-point value 756 ///Returns the new requantized value 757 @property float fG(float val) @safe @nogc pure nothrow { 758 g = cast(ubyte)(val / fGStepping); 759 return fG; 760 } 761 ///Sets the blue value channel a normalized floating-point value 762 ///Returns the new requantized value 763 @property float fB(float val) @safe @nogc pure nothrow { 764 b = cast(ubyte)(val / fBStepping); 765 return fB; 766 } 767 ///Sets the alpha value channel a normalized floating-point value 768 ///Returns the new requantized value 769 @property float fA(float val) @safe @nogc pure nothrow { 770 return 1.0; 771 } 772 ///Standard CTOR 773 this(ubyte r, ubyte g, ubyte b) pure nothrow @safe @nogc { 774 this.r = r; 775 this.g = g; 776 this.b = b; 777 } 778 ///Standard CTOR 779 this(float fR, float fG, float fB, float fA) { 780 this.fR = fR; 781 this.fG = fG; 782 this.fB = fB; 783 this.fA = fA; 784 } 785 ///Conversion CTOR from monochrome 786 this(float fY, float fA = 1.0) { 787 this.fR = fY; 788 this.fG = fY; 789 this.fB = fY; 790 this.fA = fA; 791 } 792 ///Template for pixel conversion 793 this(ColorType)(ColorType orig) @safe @nogc pure { 794 this.fB = orig.fB; 795 this.fG = orig.fG; 796 this.fR = orig.fR; 797 this.fA = orig.fA; 798 } 799 ///Conversion from 8bit monochrome 800 this(ubyte p) @safe @nogc pure { 801 this.b = p; 802 this.g = p; 803 this.r = p; 804 } 805 //pseudo-alpha (output only) 806 nothrow @safe @nogc @property pure ubyte a() const { return 0xFF; } 807 ///direct access read 808 nothrow @safe @nogc @property pure uint base(){ return 0xff_00_00_00 | r << 16 | g << 8 | b; } 809 ///Returns true if type has alpha channel support 810 static bool hasAlphaChannelSupport() { 811 return false; 812 } 813 } 814 alias RGB16_16_16 = RGB16_16_16Templ!(Endianness.Little); 815 alias RGB16_16_16BE = RGB16_16_16Templ!(Endianness.Big); 816 /** 817 * 48 bit RGB colorspace with 16 bit per channel. 818 */ 819 align(2) public struct RGB16_16_16Templ (Endianness byteOrder = Endianness.Little) { 820 ushort[3] bytes; ///individual access 821 static if (byteOrder == Endianness.Big) { 822 ///red 823 nothrow @safe @nogc @property pure ref auto r() inout { return bytes[0]; } 824 ///green 825 nothrow @safe @nogc @property pure ref auto g() inout { return bytes[1]; } 826 ///blue 827 nothrow @safe @nogc @property pure ref auto b() inout { return bytes[2]; } 828 } else { 829 ///red 830 nothrow @safe @nogc @property pure ref auto r() inout { return bytes[2]; } 831 ///green 832 nothrow @safe @nogc @property pure ref auto g() inout { return bytes[1]; } 833 ///blue 834 nothrow @safe @nogc @property pure ref auto b() inout { return bytes[0]; } 835 } 836 static immutable double fRStepping = 1.0 / 65_535;///Floating-point red stepping 837 static immutable double fGStepping = 1.0 / 65_535;///Floating-point green stepping 838 static immutable double fBStepping = 1.0 / 65_535;///Floating-point blue stepping 839 static immutable double fAStepping = 1.0; ///Floating-point alpha stepping 840 ///Returns the red channel as a normalized floating-point value 841 @property float fR() @safe @nogc pure nothrow const { 842 return r * fRStepping; 843 } 844 ///Returns the green channel as a normalized floating-point value 845 @property float fG() @safe @nogc pure nothrow const { 846 return g * fGStepping; 847 } 848 ///Returns the blue channel as a normalized floating-point value 849 @property float fB() @safe @nogc pure nothrow const { 850 return b * fBStepping; 851 } 852 ///Returns the alpha channel as a normalized floating-point value 853 @property float fA() @safe @nogc pure nothrow const { 854 return 1.0; 855 } 856 ///Sets the red value channel a normalized floating-point value 857 ///Returns the new requantized value 858 @property float fR(float val) @safe @nogc pure nothrow { 859 r = cast(ushort)(val / fRStepping); 860 return fR; 861 } 862 ///Sets the green value channel a normalized floating-point value 863 ///Returns the new requantized value 864 @property float fG(float val) @safe @nogc pure nothrow { 865 g = cast(ushort)(val / fGStepping); 866 return fG; 867 } 868 ///Sets the blue value channel a normalized floating-point value 869 ///Returns the new requantized value 870 @property float fB(float val) @safe @nogc pure nothrow { 871 b = cast(ushort)(val / fBStepping); 872 return fB; 873 } 874 ///Sets the alpha value channel a normalized floating-point value 875 ///Returns the new requantized value 876 @property float fA(float val) @safe @nogc pure nothrow { 877 return 1.0; 878 } 879 ///Standard CTOR 880 this(ushort r, ushort g, ushort b) pure nothrow @safe @nogc { 881 this.r = r; 882 this.g = g; 883 this.b = b; 884 } 885 ///Standard CTOR 886 this(float fR, float fG, float fB, float fA) { 887 this.fR = fR; 888 this.fG = fG; 889 this.fB = fB; 890 this.fA = fA; 891 } 892 ///Conversion CTOR from monochrome 893 this(float fY, float fA = 1.0) { 894 this.fR = fY; 895 this.fG = fY; 896 this.fB = fY; 897 this.fA = fA; 898 } 899 ///Template for pixel conversion 900 this(ColorType)(ColorType orig) @safe @nogc pure { 901 this.fB = orig.fB; 902 this.fG = orig.fG; 903 this.fR = orig.fR; 904 this.fA = orig.fA; 905 } 906 ///Returns true if type has alpha channel support 907 static bool hasAlphaChannelSupport() { 908 return false; 909 } 910 } 911 alias RGBA16_16_16_16 = RGBA16_16_16_16Templ!(Endianness.Little); 912 alias RGBA16_16_16_16BE = RGBA16_16_16_16Templ!(Endianness.Big); 913 /** 914 * 48 bit RGB colorspace with 16 bit per channel. 915 */ 916 align(2) public struct RGBA16_16_16_16Templ (Endianness byteOrder = Endianness.Little) { 917 ushort[4] bytes; ///individual access 918 static if (byteOrder == Endianness.Big) { 919 ///red 920 nothrow @safe @nogc @property pure ref auto r() inout { return bytes[0]; } 921 ///green 922 nothrow @safe @nogc @property pure ref auto g() inout { return bytes[1]; } 923 ///blue 924 nothrow @safe @nogc @property pure ref auto b() inout { return bytes[2]; } 925 ///alpha 926 nothrow @safe @nogc @property pure ref auto a() inout { return bytes[3]; } 927 } else { 928 ///red 929 nothrow @safe @nogc @property pure ref auto r() inout { return bytes[3]; } 930 ///green 931 nothrow @safe @nogc @property pure ref auto g() inout { return bytes[2]; } 932 ///blue 933 nothrow @safe @nogc @property pure ref auto b() inout { return bytes[1]; } 934 ///alpha 935 nothrow @safe @nogc @property pure ref auto a() inout { return bytes[0]; } 936 } 937 static immutable double fRStepping = 1.0 / 65_535;///Floating-point red stepping 938 static immutable double fGStepping = 1.0 / 65_535;///Floating-point green stepping 939 static immutable double fBStepping = 1.0 / 65_535;///Floating-point blue stepping 940 static immutable double fAStepping = 1.0 / 65_535;///Floating-point alpha stepping 941 ///Returns the red channel as a normalized floating-point value 942 @property float fR() @safe @nogc pure nothrow const { 943 return r * fRStepping; 944 } 945 ///Returns the green channel as a normalized floating-point value 946 @property float fG() @safe @nogc pure nothrow const { 947 return g * fGStepping; 948 } 949 ///Returns the blue channel as a normalized floating-point value 950 @property float fB() @safe @nogc pure nothrow const { 951 return b * fBStepping; 952 } 953 ///Returns the alpha channel as a normalized floating-point value 954 @property float fA() @safe @nogc pure nothrow const { 955 return a * fAStepping; 956 } 957 ///Sets the red value channel a normalized floating-point value 958 ///Returns the new requantized value 959 @property float fR(float val) @safe @nogc pure nothrow { 960 r = cast(ushort)(val / fRStepping); 961 return fR; 962 } 963 ///Sets the green value channel a normalized floating-point value 964 ///Returns the new requantized value 965 @property float fG(float val) @safe @nogc pure nothrow { 966 g = cast(ushort)(val / fGStepping); 967 return fG; 968 } 969 ///Sets the blue value channel a normalized floating-point value 970 ///Returns the new requantized value 971 @property float fB(float val) @safe @nogc pure nothrow { 972 b = cast(ushort)(val / fBStepping); 973 return fB; 974 } 975 ///Sets the alpha value channel a normalized floating-point value 976 ///Returns the new requantized value 977 @property float fA(float val) @safe @nogc pure nothrow { 978 a = cast(ushort)(val / fAStepping); 979 return fB; 980 } 981 ///Standard CTOR 982 this(ushort r, ushort g, ushort b, ushort a) pure nothrow @safe @nogc { 983 this.r = r; 984 this.g = g; 985 this.b = b; 986 this.a = a; 987 } 988 ///Standard CTOR 989 this(float fR, float fG, float fB, float fA) { 990 this.fR = fR; 991 this.fG = fG; 992 this.fB = fB; 993 this.fA = fA; 994 } 995 ///Conversion CTOR from monochrome 996 this(float fY, float fA = 1.0) { 997 this.fR = fY; 998 this.fG = fY; 999 this.fB = fY; 1000 this.fA = fA; 1001 } 1002 ///Template for pixel conversion 1003 this(ColorType)(ColorType orig) @safe @nogc pure { 1004 this.fB = orig.fB; 1005 this.fG = orig.fG; 1006 this.fR = orig.fR; 1007 this.fA = orig.fA; 1008 } 1009 ///Returns true if type has alpha channel support 1010 static bool hasAlphaChannelSupport() { 1011 return false; 1012 } 1013 } 1014 /** 1015 * Pixel format flags. 1016 * Undefined should be used for all indexed bitmaps, except 16 bit big endian ones, in which case a single BigEndian bit should be set high. 1017 * Lower 16 bits should be used for general identification, upper 16 bits are general identificators (endianness, valid alpha channel, etc). 1018 * 0x01 - 0x1F are reserved for 16 bit truecolor, 0x20 - 0x2F are reserved for 24 bit truecolor, 0x30 - 3F are reserved for integer grayscale, 1019 * 0x40 - 0x5F are reserved for 32 bit truecolor, 0xF00-0xF0F are reserved for "chunky" indexed images, 0xF10-0xF1F are reserved for planar 1020 * indexed images. 1021 */ 1022 enum PixelFormat : uint { 1023 BigEndian = 0x00_01_00_00, ///Always little endian if bit not set 1024 ValidAlpha = 0x00_02_00_00, ///If set, alpha is used 1025 SeparateAlphaField = 0x00_04_00_00, ///If set, then there's a separate alpha field 1026 RGBX5551 = 0x1, 1027 RGBA5551 = RGBX5551 | ValidAlpha, 1028 RGB565 = 0x2, 1029 RGB888 = 0x20, 1030 Grayscale1Bit = 0x30, 1031 Grayscale2Bit = 0x31, 1032 Grayscale4Bit = 0x32, 1033 Grayscale8Bit = 0x33, 1034 Grayscale16Bit = 0x34, 1035 YX88 = 0x3A, 1036 YA88 = YX88 | ValidAlpha, 1037 YX16_16 = 0x3B, 1038 YA16_16 = YX16_16 | ValidAlpha, 1039 RGBX8888 = 0x40, 1040 RGBA8888 = RGBX8888 | ValidAlpha, 1041 XRGB8888 = 0x41, 1042 ARGB8888 = XRGB8888 | ValidAlpha, 1043 RGB16_16_16 = 0x60, 1044 RGBX16_16_16_16 = 0x61, 1045 RGBA16_16_16_16 = RGBX16_16_16_16 | ValidAlpha, 1046 RGBX_f32 = 0x101, 1047 RGBA_f32 = RGBX_f32 | ValidAlpha, 1048 Indexed1Bit = 0xF00, 1049 Indexed2Bit = 0xF01, 1050 Indexed4Bit = 0xF02, 1051 Indexed8Bit = 0xF03, 1052 Indexed16Bit = 0xF04, 1053 Planar2Color = 0xF10, 1054 Planar4Color = 0xF11, 1055 Planar8Color = 0xF12, 1056 Planar16Color = 0xF13, 1057 Planar32Color = 0xF14, 1058 Planar64Color = 0xF15, 1059 Planar128Color = 0xF16, 1060 Planar256Color = 0xF17, 1061 Planar512Color = 0xF18, 1062 Planar1024Color = 0xF19, 1063 Planar2048Color = 0xF1A, 1064 Planar4096Color = 0xF1B, 1065 Planar8192Color = 0xF1C, 1066 Planar16384Color= 0xF1D, 1067 Planar32768Color= 0xF1E, 1068 Planar65536Color= 0xF1F, 1069 1070 Undefined = 0, 1071 } 1072 /** 1073 * Returns the bitdepth of a format. 1074 */ 1075 public ubyte getBitDepth(uint format) @nogc @safe pure nothrow { 1076 format &= 0xFF_FF; 1077 switch (format) { 1078 case 0x00_01: .. case 0x00_1F: case 0x0F_04, 0x00_3A: 1079 return 16; 1080 case 0x00_20: .. case 0x00_2F: 1081 return 24; 1082 case 0x00_40: .. case 0x00_5F: 1083 return 32; 1084 case 0x00_60: 1085 return 48; 1086 case 0x0F_00: 1087 return 1; 1088 case 0x0F_01: 1089 return 2; 1090 case 0x0F_02, 0x00_31: 1091 return 4; 1092 case 0x0F_03, 0x00_30: 1093 return 8; 1094 case 0x0F_10: .. case 0x0F_1F: 1095 return cast(ubyte)(format & 0x0F); 1096 default: 1097 return 0; 1098 } 1099 } 1100 1101 @safe unittest { 1102 import std.conv : to; 1103 assert(ARGB8888.sizeof == 4); 1104 ARGB8888 test0 = ARGB8888(1.0,1.0,1.0,1.0); 1105 assert(test0.base == 0xFF_FF_FF_FF, to!string(test0.base)); 1106 test0.fR = test0.fR - ARGB8888.fRStepping; 1107 assert(test0.r == 0xFE, to!string(test0.r)); 1108 test0.r = 0xFF; 1109 assert(test0.fR == 1.0, to!string(test0.fR)); 1110 RGB16_16_16 test1 = RGB16_16_16(test0); 1111 assert(test1.r == 0xFF_FF, to!string(test1.r)); 1112 assert(test1.g == 0xFF_FF, to!string(test1.g)); 1113 assert(test1.b == 0xFF_FF, to!string(test1.b)); 1114 }