/dmagick/ColorYUV.d

http://github.com/MikeWey/DMagick · D · 154 lines · 82 code · 20 blank · 52 comment · 3 complexity · ac3cbdb269c64d36882fd97723b212c9 MD5 · raw file

  1. /**
  2. * Copyright: Mike Wey 2011
  3. * License: zlib (See accompanying LICENSE file)
  4. * Authors: Mike Wey
  5. */
  6. module dmagick.ColorYUV;
  7. import dmagick.Color;
  8. import dmagick.c.magickType;
  9. import dmagick.c.quantum;
  10. /**
  11. * The YUV color format describes a color by using the color components
  12. * luminance and chrominance. The luminance component (Y) represents the
  13. * brightness information of a color, the chrominance components (U and V)
  14. * contain the color differences.
  15. *
  16. * The YUV color format was developed for analog TV transmissions to provide
  17. * compatibility between black-and-white television and color television:
  18. * The luminance component is sufficient for black-and-white TV sets,
  19. * whereas color TV sets need the additional chrominance information.
  20. */
  21. class ColorYUV : Color
  22. {
  23. /** */
  24. this()
  25. {
  26. super();
  27. }
  28. /**
  29. * Create a YUV Color from the specified doubles.
  30. *
  31. * Params:
  32. * y = The luminance as a value between 0.0 and 1.0
  33. * u = The U chrominance component as a value between -0.5 and 0.5
  34. * v = The V chrominance component as a value between -0.5 and 0.5
  35. */
  36. this(double y, double u, double v, double opacity = 0)
  37. {
  38. Quantum red, green, blue;
  39. convertYUVToRGB(y, u, v, red, green, blue);
  40. super(red, green, blue, scaleDoubleToQuantum(opacity));
  41. }
  42. /**
  43. * Create a Color from a X11 color specification string
  44. */
  45. this(string color)
  46. {
  47. super(color);
  48. }
  49. /**
  50. * The value for the luminance in the range [0.0 .. 1.0]
  51. */
  52. void y(double y)
  53. {
  54. double oldY, u, v;
  55. convertRGBToYUV(packet.red, packet.green, packet.blue, oldY, u, v);
  56. convertYUVToRGB(y, u, v, packet.red, packet.green, packet.blue);
  57. }
  58. ///ditto
  59. double y()
  60. {
  61. return 0.299 * scaleQuantumToDouble(packet.red) +
  62. 0.587 * scaleQuantumToDouble(packet.green) +
  63. 0.114 * scaleQuantumToDouble(packet.blue);
  64. }
  65. /**
  66. * The value for U chrominance component in the range [-0.5 .. 0.5]
  67. */
  68. void u(double u)
  69. {
  70. double y, oldU, v;
  71. convertRGBToYUV(packet.red, packet.green, packet.blue, y, oldU, v);
  72. convertYUVToRGB(y, u, v, packet.red, packet.green, packet.blue);
  73. }
  74. ///ditto
  75. double u()
  76. {
  77. return -0.147 * scaleQuantumToDouble(packet.red) +
  78. -0.289 * scaleQuantumToDouble(packet.green) +
  79. 0.436 * scaleQuantumToDouble(packet.blue);
  80. }
  81. /**
  82. * The value for V chrominance component in the range [-0.5 .. 0.5]
  83. */
  84. void v(double v)
  85. {
  86. double y, u, oldV;
  87. convertRGBToYUV(packet.red, packet.green, packet.blue, y, u, oldV);
  88. convertYUVToRGB(y, u, v, packet.red, packet.green, packet.blue);
  89. }
  90. ///ditto
  91. double v()
  92. {
  93. return 0.615 * scaleQuantumToDouble(packet.red) +
  94. -0.515 * scaleQuantumToDouble(packet.green) +
  95. -0.100 * scaleQuantumToDouble(packet.blue);
  96. }
  97. /**
  98. * Convert an RGB value to a YUV value.
  99. */
  100. private void convertRGBToYUV(Quantum red, Quantum green, Quantum blue, ref double y, ref double u, ref double v)
  101. {
  102. // ⌈Y⌉ ⌈ 0.299 0.587 0.114⌉ ⌈R⌉
  103. // |U|=|-0.147 -0.289 0.436|·|G|
  104. // ⌊V⌋ ⌊ 0.615 -0.515 -0.100⌋ ⌊B⌋
  105. double r = scaleQuantumToDouble(red);
  106. double g = scaleQuantumToDouble(green);
  107. double b = scaleQuantumToDouble(blue);
  108. y = 0.299*r + 0.587*g + 0.114*b;
  109. u = -0.147*r + -0.289*g + 0.436*b;
  110. v = 0.615*r + -0.515*g + -0.100*b;
  111. }
  112. /**
  113. * Convert an YUV value to a RGB value.
  114. */
  115. private void convertYUVToRGB(double y, double u, double v, ref Quantum red, ref Quantum green, ref Quantum blue)
  116. in
  117. {
  118. assert(y <= 1 && y >= 0 );
  119. assert(u <= -0.5 && u >= 0.5);
  120. assert(v <= -0.5 && v >= 0.5);
  121. }
  122. body
  123. {
  124. // ⌈R⌉ ⌈ 1.000 0.000 1.140⌉ ⌈Y⌉
  125. // |G|=| 1.000 -0.395 -0.581|·|U|
  126. // ⌊B⌋ ⌊ 1.000 2.032 0.000⌋ ⌊V⌋
  127. double r = 1.000*y + 0.000*u + 1.140*v;
  128. double g = 1.000*y + -0.395*u + -0.581*v;
  129. double b = 1.000*y + 2.032*u + 0.000*v;
  130. red = scaleDoubleToQuantum(r);
  131. green = scaleDoubleToQuantum(g);
  132. blue = scaleDoubleToQuantum(b);
  133. }
  134. }