ある表色系(色空間・カラースペース)から別の表色系に変換する式とサンプルなど。
代表的な表色系の種類
- RGB
- 加法混色の表色系、R(赤)、G(緑)、B(青)の三原色の強さによって色を表す
- CMY
- 減法混色の表色系、C(シアン)、M(マゼンタ)、Y(黄)の三原色の濃度によって色を表す
- CMYK
- 黒の発色をよくするためにCMYを拡張してK(Key plate)の濃度を加えた表色系
印刷物などの表色に用いられ、シアン・マゼンタ・黄・黒のインクの濃度を表す - HSV (HSB)
- H(hue,色相)、S(saturation,彩度),V(value,明度)の三要素によって色を表す
色相は環状の値で、通常0度から360度で表す
彩度0%が無彩色、彩度100%が純色を表す - HSL (HLS, HSI)
- HSV同様、H(hue,色相)、S(saturation,彩度),L(lightness/luminance,輝度)の三要素によって色を表す
HSVと異なり、彩度に関わらず輝度0%が黒、輝度100%が白を表し、50%の場合純色を表す - YCbCr
- Y(luma,輝度成分)とCb(blue-difference chroma,青の色差成分)、Cr(red-difference chroma,赤の色差成分)の三要素によって色を表す
動画処理などの映像技術に用いられる
表色系の変換スクリプト
色 | 表色系 | 値 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
カラーコード | |||||||||
カラーネーム | ||||||||||
RGB | ||||||||||
CMY | ||||||||||
CMYK | ||||||||||
HSV | ||||||||||
HSL |
- 使い方
- カラーコードもしくは各表色系での値を入力してsetをクリックすると、対応する色と他の表色系での表現を得られます
- RGB, CMY, CMYK
- それぞれ16進で00~ffの範囲の数値を入力してください
- HSV, HSL
- S, V, Lは0.0~1.0の範囲の数値を入力してください
Hは0~359の範囲の数値を入力してください (360を超える値は自動的に0~359の範囲に正規化します) - 近似色
- 名前(カラーネーム)が定義されている147色のうち、現在の色に最も近い色を表示します
- 階調の反転
- 現在の色をネガポジ反転した色を表示します
- 補色
- 現在の色の彩度・明度を維持したまま色相だけを反転した色を表示します
- 純色
- 現在の色の彩度・明度を最大(1.0)にした色を表示します
- 無彩色
- 現在の色の彩度を最小(0.0)にした色を表示します
変換式
RGB⇄CMY
R, G, B, C, M, Yの値域が0〜255(8ビット)の場合。
C = 255 - R
M = 255 - G
Y = 255 - B
R = 255 - C
G = 255 - M
B = 255 - Y
RGB⇄CMYK
R, G, B, C, M, Y, Kの値域が0〜255(8ビット)の場合。
RGB→CMYK
K = min(255 - R, 255 - G, 255 - B)
C = 255 - R - K
M = 255 - G - K
Y = 255 - B - K
CMYK→RGB
R' = 255 - C - K
G' = 255 - M - K
B' = 255 - Y - K
R = max(0, R') // R' < 0のときは0、そうでないときはR'
G = max(0, G')
B = max(0, B')
RGB⇄HSV
R, G, B, S, Vの値域が0〜255(8ビット)、Hの値域が0〜359の場合。
RGB→HSV
max = Max(R, G, B)
min = Min(R, G, B)
max - min
S = ---------
max
V = max
Rが最大のとき
G - B
H = 60 * --------- + 0
max - min
Gが最大のとき
B - R
H = 60 * --------- + 120
max - min
Bが最大のとき
R - G
H = 60 * --------- + 240
max - min
ここでH < 0のとき
H += 360
HSV→RGB
省略。 後述する実装例もしくはHSV色空間 - Wikipediaを参照。
RGB⇄YCbCr
スケーリングされていないYCbCrの場合
(Y ) = (+0.299 +0.587 +0.114) (R )
(Cb) = (-0.299 -0.587 +0.866) (G )
(Cr) = (+0.701 -0.587 -0.114) (B )
(R ) = (+1 0 +1 ) (Y )
(G ) = (+1 -0.19421 -0.50937) (Cb)
(B ) = (+1 +1 0 ) (Cr)
スケーリングされたYCbCrの場合
R, G, Bの値域が0〜255(8ビット)、Yの値域が16〜235(8ビット)、Cb, Crの値域が16〜240(8ビット、128=色差なし)の場合。
(Y ) = (+0.257 +0.504 +0.098) (R ) ( 16)
(Cb) = (-0.148 -0.291 +0.439) (G ) + (128)
(Cr) = (+0.439 -0.368 -0.071) (B ) (128)
(R ) = (+1.164 0 +1.596) (Y - 16)
(G ) = (+1.164 -0.391 -0.813) (Cb - 128)
(B ) = (+1.164 +2.018 0 ) (Cr - 128)
実装例
.NET FrameworkでのRGB→HSL変換
.NET FrameworkのColor構造体に用意されているメソッドGetHue(), GetSaturation(), GetBrightness()を用いることでRGBからHSLへの変換ができる。 なお、ドキュメントではこれらのメソッドはHSB表色系の値を返すように記述されているが、実際に返される値はHSL表色系になっている模様。
using System;
using System.Drawing;
class Sample {
static void Main()
{
foreach (var col in new[] {
Color.Red,
Color.Yellow,
Color.Lime,
Color.Cyan,
Color.Blue,
Color.Magenta,
Color.Black,
Color.Gray,
Color.White,
Color.FromArgb(0xff, 0xa0, 0xa0),
Color.FromArgb(0xff, 0x80, 0x80),
Color.FromArgb(0xc0, 0x60, 0x60),
Color.FromArgb(0x80, 0x40, 0x40),
}) {
Console.Write("RGB({0:D3}, {1:D3}, {2:D3}) => ", col.R, col.G, col.B);
Console.WriteLine("HSL({0,6:N2}, {1,7:P2}, {2,7:P2})", col.GetHue(), col.GetSaturation(), col.GetBrightness());
}
}
}
Imports System
Imports System.Drawing
Class Sample
Public Shared Sub Main()
For Each col As Color In New Color() { _
Color.Red, _
Color.Yellow, _
Color.Lime, _
Color.Cyan, _
Color.Blue, _
Color.Magenta, _
Color.Black, _
Color.Gray, _
Color.White, _
Color.FromArgb(&hFF, &hA0, &hA0), _
Color.FromArgb(&hFF, &h80, &h80), _
Color.FromArgb(&hC0, &h60, &h60), _
Color.FromArgb(&h80, &h40, &h40) _
}
Console.Write("RGB({0:D3}, {1:D3}, {2:D3}) => ", col.R, col.G, col.B)
Console.WriteLine("HSL({0,6:N2}, {1,7:P2}, {2,7:P2})", col.GetHue(), col.GetSaturation(), col.GetBrightness())
Next
End Sub
End Class
実行結果
RGB(255, 000, 000) => HSL(360.00, 100.00%, 50.00%) RGB(255, 255, 000) => HSL( 60.00, 100.00%, 50.00%) RGB(000, 255, 000) => HSL(120.00, 100.00%, 50.00%) RGB(000, 255, 255) => HSL(180.00, 100.00%, 50.00%) RGB(000, 000, 255) => HSL(240.00, 100.00%, 50.00%) RGB(255, 000, 255) => HSL(300.00, 100.00%, 50.00%) RGB(000, 000, 000) => HSL( 0.00, 0.00%, 0.00%) RGB(128, 128, 128) => HSL( 0.00, 0.00%, 50.20%) RGB(255, 255, 255) => HSL( 0.00, 0.00%, 100.00%) RGB(255, 160, 160) => HSL(360.00, 100.00%, 81.37%) RGB(255, 128, 128) => HSL(360.00, 100.00%, 75.10%) RGB(192, 096, 096) => HSL(360.00, 43.24%, 56.47%) RGB(128, 064, 064) => HSL(360.00, 33.33%, 37.65%)
VB.NETでのRGB, CMYK, HSV相互変換の実装例
構造体宣言
それぞれのカラースペースでの色データを表す構造体を作成。
RGB
''' <summary>
''' RGB
''' </summary>
<StructLayout(LayoutKind.Explicit)> _
Public Structure Rgb
Public Const IntensityMax As Byte = 255
Public Const IntensityMin As Byte = 0
Public Shared ReadOnly White As RGB
Public Shared ReadOnly Black As RGB
Shared Sub New()
White = New RGB(IntensityMax, IntensityMax, IntensityMax)
Black = New RGB(IntensityMin, IntensityMin, IntensityMin)
End Sub
<FieldOffset(0)> Public B As Byte
<FieldOffset(1)> Public G As Byte
<FieldOffset(2)> Public R As Byte
Public ReadOnly Property RGB() As Integer
Get
Return CInt(R) * &H10000 + CInt(G) * &H100 + CInt(B)
End Get
End Property
Public ReadOnly Property IsBlack() As Boolean
Get
Return (Me.R = IntensityMin AndAlso Me.G = IntensityMin AndAlso Me.B = IntensityMin)
End Get
End Property
Public ReadOnly Property IsWhite() As Boolean
Get
Return (Me.R = IntensityMax AndAlso Me.G = IntensityMax AndAlso Me.B = IntensityMax)
End Get
End Property
Public ReadOnly Property L() As Byte
Get
Return CByte(0.299F * R + 0.587F * G + 0.114F * B)
End Get
End Property
Public Overloads Function Equals(ByVal rgb As RGB) As Boolean
Return (rgb.R = Me.R AndAlso rgb.G = Me.G AndAlso rgb.B = Me.B)
End Function
Public Sub SetRGB(ByVal value As Integer)
R = CByte(value And &HFF0000 \ &H10000)
G = CByte(value And &HFF00 \ &H100)
B = CByte(value And &HFF)
End Sub
Public Function ToInt32() As Int32
Return R * &H10000 Or G * &H100 Or B
End Function
Public Function ToColor() As System.Drawing.Color
Return System.Drawing.Color.FromArgb(R, G, B)
End Function
Private Sub New(ByVal r As Byte, ByVal g As Byte, ByVal b As Byte)
Me.R = r
Me.G = g
Me.B = b
End Sub
End Structure
CMYK
''' <summary>
''' CMYK
''' </summary>
<StructLayout(LayoutKind.Explicit)> _
Public Structure Cmyk
Public Shared ReadOnly White As Cmyk
Public Shared ReadOnly Black As Cmyk
Public Const DensityMin As Byte = 0
Public Const DensityMax As Byte = 255
Shared Sub New()
White = New Cmyk(0, 0, 0, DensityMin)
Black = New Cmyk(0, 0, 0, DensityMax)
End Sub
<FieldOffset(0)> Public C As Byte
<FieldOffset(1)> Public M As Byte
<FieldOffset(2)> Public Y As Byte
<FieldOffset(3)> Public K As Byte
Public Overloads Function Equals(ByVal cmyk As Cmyk) As Boolean
Return (cmyk.C = Me.C AndAlso cmyk.M = Me.M AndAlso cmyk.Y = Me.Y AndAlso cmyk.K = Me.K)
End Function
Private Sub New(ByVal c As Byte, ByVal m As Byte, ByVal y As Byte, ByVal k As Byte)
Me.C = c
Me.M = m
Me.Y = y
Me.K = k
End Sub
End Structure
HSV
''' <summary>
''' HSV
''' </summary>
<StructLayout(LayoutKind.Explicit)> _
Public Structure Hsv
Public Shared ReadOnly White As Hsv
Public Shared ReadOnly Black As Hsv
Public Const HueMin As Short = 0
Public Const HueMax As Short = 359
Public Const SaturationMin As Byte = 0
Public Const SaturationMax As Byte = 255
Public Const ValueMin As Byte = 0
Public Const ValueMax As Byte = 255
Shared Sub New()
White = New Hsv(0, 0, ValueMax)
Black = New Hsv(0, 0, ValueMin)
End Sub
<FieldOffset(0)> Public H As Short
<FieldOffset(2)> Public S As Byte
<FieldOffset(3)> Public V As Byte
Public Overloads Function Equals(ByVal hsv As Hsv) As Boolean
Return (hsv.H = Me.H AndAlso hsv.S = Me.S AndAlso hsv.V = Me.V)
End Function
Private Sub New(ByVal h As Short, ByVal s As Byte, ByVal v As Byte)
Me.H = h
Me.S = s
Me.V = v
End Sub
End Structure
ColorConverter
変換メソッドとその他のユーティリティメソッドをもったクラスを作成。
''' <summary>
''' 色空間の変換
''' </summary>
Public Class ColorConverter
''' <summary>
''' 三つの要素の内、もっとも大きいものを取得する。
''' </summary>
Private Shared Function GetGreatestValue(ByVal x As Byte, ByVal y As Byte, ByVal z As Byte) As Byte
If x < y Then
If y < z Then
Return z
Else
Return y
End If
ElseIf x < z Then
If z < y Then
Return y
Else
Return z
End If
Else
Return x
End If
End Function
''' <summary>
''' 三つの要素の内、もっとも小さいものを取得する。
''' </summary>
Private Shared Function GetSmallestValue(ByVal x As Byte, ByVal y As Byte, ByVal z As Byte) As Byte
If y < x Then
If z < y Then
Return z
Else
Return y
End If
ElseIf z < x Then
If y < z Then
Return y
Else
Return z
End If
Else
Return x
End If
End Function
''' <summary>
''' HSVからRGBへの変換
''' </summary>
Public Shared Function ToRgb(ByVal hsv As Hsv) As Rgb
Dim rgb As New rgb()
If hsv.S = 0 Then
rgb.R = hsv.V
rgb.G = hsv.V
rgb.B = hsv.V
Else
Const hueMax As Single = CSng(hsv.HueMax)
Const saturationMax As Single = CSng(hsv.SaturationMax)
Dim ht As Integer = hsv.H * 6
Dim d As Single = CSng(ht Mod hsv.HueMax)
Dim t1 As Byte = CByte(hsv.V * (saturationMax - hsv.S) / saturationMax)
Dim t2 As Byte = CByte(hsv.V * (saturationMax - hsv.S * d / hueMax) / saturationMax)
Dim t3 As Byte = CByte(hsv.V * (saturationMax - hsv.S * (hueMax - d) / hueMax) / saturationMax)
Select Case ht \ hsv.HueMax
Case 0
rgb.R = hsv.V : rgb.G = t3 : rgb.B = t1
Case 1
rgb.R = t2 : rgb.G = hsv.V : rgb.B = t1
Case 2
rgb.R = t1 : rgb.G = hsv.V : rgb.B = t3
Case 3
rgb.R = t1 : rgb.G = t2 : rgb.B = hsv.V
Case 4
rgb.R = t3 : rgb.G = t1 : rgb.B = hsv.V
Case Else
rgb.R = hsv.V : rgb.G = t1 : rgb.B = t2
End Select
End If
Return rgb
End Function
''' <summary>
''' CMYKからRGBへの変換
''' </summary>
Public Shared Function ToRgb(ByVal cmyk As Cmyk) As Rgb
Dim rgb As New rgb()
Dim r As Integer = cmyk.DensityMax - (cmyk.C + cmyk.K)
Dim g As Integer = cmyk.DensityMax - (cmyk.M + cmyk.K)
Dim b As Integer = cmyk.DensityMax - (cmyk.Y + cmyk.K)
If r < 0 Then rgb.R = 0 Else rgb.R = CByte(r)
If g < 0 Then rgb.G = 0 Else rgb.G = CByte(g)
If b < 0 Then rgb.B = 0 Else rgb.B = CByte(b)
Return rgb
End Function
''' <summary>
''' RGBからHSVへの変換
''' </summary>
Public Shared Function ToHsv(ByVal rgb As Rgb) As Hsv
Dim hsv As New Hsv()
Dim max As Short = GetGreatestValue(rgb.R, rgb.G, rgb.B)
Dim min As Short = GetSmallestValue(rgb.R, rgb.G, rgb.B)
Dim d As Single = CSng(max - min)
hsv.V = CByte(max)
If d = 0.0 Then
hsv.S = 0
Else
hsv.S = CByte(d * 255.0F / CSng(max))
End If
If hsv.S = 0 Then
hsv.H = 0
Else
Dim rt As Short = max - CShort(rgb.R * 60.0F / d)
Dim gt As Short = max - CShort(rgb.G * 60.0F / d)
Dim bt As Short = max - CShort(rgb.B * 60.0F / d)
If rgb.R = max Then
hsv.H = bt - gt
ElseIf rgb.G = max Then
hsv.H = 120S + rt - bt
Else
hsv.H = 240S + gt - rt
End If
If hsv.H < 0 Then hsv.H += 360S
End If
Return hsv
End Function
''' <summary>
''' CMYKからHSVへの変換
''' </summary>
Public Shared Function ToHsv(ByVal cmyk As Cmyk) As Hsv
Return ToHsv(ToRgb(cmyk))
End Function
''' <summary>
''' RGBからCMYKへの変換
''' </summary>
Public Shared Function ToCmyk(ByVal rgb As Rgb) As Cmyk
Dim cmyk As New cmyk()
cmyk.K = GetSmallestValue(cmyk.DensityMax - rgb.R, cmyk.DensityMax - rgb.G, cmyk.DensityMax - rgb.B)
cmyk.C = cmyk.DensityMax - rgb.R - cmyk.K
cmyk.M = cmyk.DensityMax - rgb.G - cmyk.K
cmyk.Y = cmyk.DensityMax - rgb.B - cmyk.K
Return cmyk
End Function
''' <summary>
''' HSVからCMYKへの変換
''' </summary>
Public Shared Function ToCmyk(ByVal hsv As Hsv) As Cmyk
Return ToCmyk(ToRgb(hsv))
End Function
End Class
C#でのYCbCr→RGB変換の実装例
この例でyuvはYUV422フォーマット(Y0CbY1Crの順)で格納されたピクセルへのbyte*型ポインタ、bgrはBGRの順で格納されるピクセルへのbyte*型ポインタを表す。
var y0 = +1.164f * (*(yuv++) - 16);
var cb = (*(yuv++) - 128);
var y1 = +1.164f * (*(yuv++) - 16);
var cr = (*(yuv++) - 128);
var db = (+2.018f * cb );
var dg = (-0.391f * cb + -0.813f * cr);
var dr = ( +1.596f * cr);
*(bgr++) = (byte)(y0 + db);
*(bgr++) = (byte)(y0 + dg);
*(bgr++) = (byte)(y0 + dr);
*(bgr++) = (byte)(y1 + db);
*(bgr++) = (byte)(y1 + dg);
*(bgr++) = (byte)(y1 + dr);