午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

エクセルの色の指定のLong値(10進数)とRGBとCMYKとRYBの相互変換…をしたかった

RGBをCMYKに変換は
このへんをみて
Cyan C=(1-R-K)/(1-K)
Magenta M=(1-G-K)/(1-K)
Yellow Y=(1-B-K)/(1-K)
Black(K) K=最小値(1-R,1-G,1-B)
 
CMYKをRGBに変換
Red R=1-最小値(1,C*(1-K)+K)
Green G=1-最小値(1,M*(1-K)+K)
Blue B=1-最小値(1,Y*(1-K)+K)
CMYKとRGBの相互変換の式はこうらしい
色の範囲が違うせいか可逆ではなくて不可逆
 
 
エクセルVBAだとこんな感じになった
’RGB3つの値の入れ物myRGB
Type myRGB
    iRed As Integer
    iGreen As Integer
    iBlue As Integer
End Type

’CMYK4つの値の入れ物myCMYK
Type myCMYK
    iC As Double
    iM As Double
    iY As Double
    iK As Double
End Type
’Long値(セルの塗りつぶしの色とか)をRGBに変換
Function Color2RGB(ByVal myColor As Long) As myRGB
'Color(Long)をRGBにして返す
    Dim iRGB As myRGB
    With iRGB
        .iRed = myColor Mod 256
        .iGreen = Int(myColor / 256) Mod 256
        .iBlue = Int(myColor / 256 / 256)
    End With
    Color2RGB = iRGB
End Function
’CMYKをRGBに変換
Function CMYK2RGB(iCMYK As myCMYK) As myRGB
    Dim iRGB As myRGB
    Dim R As Double, g As Double, b As Double
    Dim Cyan As Double, Mage As Double, Yell As Double, Kblc As Double
    With iCMYK
        Cyan = .iC / 100
        Mage = .iM / 100
        Yell = .iY / 100
        Kblc = .iK / 100
    End With
    With WorksheetFunction
'        r = CInt(1 - (.min(1, Cyan * (1 - Kblc) + Kblc)) * 255)
        R = .min(1, Cyan * (1 - Kblc) + Kblc)
        g = .min(1, Mage * (1 - Kblc) + Kblc)
        b = .min(1, Yell * (1 - Kblc) + Kblc)
    End With
    R = CInt((1 - R) * 255)
    g = CInt((1 - g) * 255)
    b = CInt((1 - b) * 255)
    With iRGB
        .iRed = R
        .iGreen = g
        .iBlue = b
    End With
    CMYK2RGB = iRGB
    
End Function
’Long値(セルの塗りつぶしの色)をCMYKに変換
Function Color2CMYK(myColor As Long) As myCMYK
    Dim iRGB As myRGB
    Dim iCMYK As myCMYK
    Dim R As Double, g As Double, b As Double
    Dim Cy As Double, Ma As Double, Ye As Double, Kb As Double
    iRGB = Color2RGB(myColor)
    With iRGB
        R = .iRed / 255
        g = .iGreen / 255
        b = .iBlue / 255
    End With
'        .iK = WorksheetFunction.min(1 - r, 1 - g, 1 - b)
    Kb = 1 - WorksheetFunction.max(R, g, b)
    If Kb <> 1 Then
        Cy = (1 - R - Kb) / (1 - Kb)
        Ma = (1 - g - Kb) / (1 - Kb)
        Ye = (1 - b - Kb) / (1 - Kb)
    End If
    With iCMYK
        .iC = Cy
        .iM = Ma
        .iY = Ye
        .iK = Kb
    End With
    
    Color2CMYK = iCMYK
End Function
'CMYKボタンのクリックイベント
Private Sub CButtonDisplayCMYK_Click()
    Dim R As Range
    Dim iRGB As myRGB
    Dim iCMYK As myCMYK
    
    If TypeName(Selection) <> "Range" Then Exit Sub
    For Each R In Selection
        iCMYK = Color2CMYK(R.Interior.Color)
        With iCMYK
            R.Value = "'" & CInt(.iC * 100) & "," & CInt(.iM * 100) & "," & CInt(.iY * 100) & "," & CInt(.iK * 100)
        End With
    Next
End Sub
 
CMYKとRGBの変換式はたくさんの解答があったのでほとんどコピペでできた
 
 
 
 
問題はRYB
イメージ 9
基準になるそれぞれの色のRGBの値
同じB(青)でも違う
 
イメージ 10
その他の基準?になる色の違い
赤と黄色以外はかなり違う、これが面白い
 
 
 
RYBをRGBに変換するのはJavaScript?のコードが見つかったので
これをエクセルVBAで書いてみたのが
Function MagicColors()
    Dim magic, mW, my, mR, mO, mB, mg, mP, mK
    mW = Array(1, 1, 1)         '白
    my = Array(1, 1, 0)         '黄色
    mR = Array(1, 0, 0)         '赤
    mO = Array(1, 0.5, 0)       '橙
    mB = Array(0.163, 0.373, 0.6) '青
    mg = Array(0, 0.66, 0.2)    '緑
    mP = Array(0.5, 0, 0.5)     '紫
    mK = Array(0.2, 0.094, 0)   '黒
    magic = Array(mW, my, mR, mO, mB, mg, mP, mK)
    
    MagicColors = magic
    
End Function
Function cubicInt(t, A, b)
    Dim myWeight
    myWeight = t * t * (3 - 2 * t)
    cubicInt = A + myWeight * (b - A)
End Function
Function getR(iR, iY, iB, magic)
    Dim x0, x1, x2, x3, y0, y1
    
    x0 = cubicInt(iB, magic(0)(0), magic(4)(0))
    x1 = cubicInt(iB, magic(1)(0), magic(5)(0))
    x2 = cubicInt(iB, magic(2)(0), magic(6)(0))
    x3 = cubicInt(iB, magic(3)(0), magic(7)(0))
    y0 = cubicInt(iY, x0, x1)
    y1 = cubicInt(iY, x2, x3)
    getR = cubicInt(iR, y0, y1)
End Function
Function getG(iR, iY, iB, magic)
    Dim x0, x1, x2, x3, y0, y1
    
    x0 = cubicInt(iB, magic(0)(1), magic(4)(1))
    x1 = cubicInt(iB, magic(1)(1), magic(5)(1))
    x2 = cubicInt(iB, magic(2)(1), magic(6)(1))
    x3 = cubicInt(iB, magic(3)(1), magic(7)(1))
    y0 = cubicInt(iY, x0, x1)
    y1 = cubicInt(iY, x2, x3)
    getG = cubicInt(iR, y0, y1)
End Function
Function getB(iR, iY, iB, magic)
    Dim x0, x1, x2, x3, y0, y1
    
    x0 = cubicInt(iB, magic(0)(2), magic(4)(2))
    x1 = cubicInt(iB, magic(1)(2), magic(5)(2))
    x2 = cubicInt(iB, magic(2)(2), magic(6)(2))
    x3 = cubicInt(iB, magic(3)(2), magic(7)(2))
    y0 = cubicInt(iY, x0, x1)
    y1 = cubicInt(iY, x2, x3)
    getB = cubicInt(iR, y0, y1)
End Function
Function RYB2RGBtest(iRYB As TypeRYB) As myRGB
    r = iRYB.iR
    Y = iRYB.iY
    b = iRYB.iB
    
    Dim magic
    magic = MagicColors
    
    Dim R1, G1, B1
    R1 = getR(r, Y, b, magic)
    G1 = getG(r, Y, b, magic)
    B1 = getB(r, Y, b, magic)
    
    R1 = R1 * 255
    G1 = G1 * 255
    B1 = B1 * 255
    R1 = WorksheetFunction.Ceiling(R1, 1)
    G1 = WorksheetFunction.Ceiling(G1, 1)
    B1 = WorksheetFunction.Ceiling(B1, 1)
    Dim iRGB As myRGB
    With iRGB
        .iRed = R1
        .iGreen = G1
        .iBlue = B1
    End With
    RYB2RGBtest = iRGB
End Function
 
 
 
上のRYBをRGBに変換するのを使うときはこんな感じ
Sub testryb2rgb()
    Dim iRYB As TypeRYB
    Dim iRGB As myRGB
    With iRYB
        .iR = 0
        .iY = 1
        .iB = 1
    End With
    iRGB = RYB2RGBtest(iRYB)
End Sub
これを実行すると
R=0、G=169、B=51が得られる
 
イメージ 12


 
’RYBの青(0,0,1)をRGBに変換
Sub testryb2rgb()
    Dim iRYB As TypeRYB
    Dim iRGB As myRGB
    With iRYB
        .iR = 0
        .iY = 0
        .iB = 1
    End With
    iRGB = RYB2RGBtest(iRYB)
End Sub
イメージ 13
 
R=42,G=96,B=153
本当はG=95みたいなんだけど1違うのは小数点を切り上げているからかな
でもだいたいあっている

 
ってことでRYBをRGBに変換はできたんだけど
逆のRGBをRYBに変換するのが見つからない
というか見つかるのは本当のRYBじゃなくてRYBに似たものしか見つからない
本当のRYBのB(青)はRGBに変換すると42,95,153になる青
イメージ 14
これがRYBの基準になるB(青)
 
イメージ 15
RGBのB(青)(0,0,255)はこれ
見つかるのはRGBのBにRYBのBを合わせたものばかり
node-rgb2ryb/rgb2ryb.js at master · bahamas10/node-rgb2ryb · GitHub
拡張子みたいなのが.jsだからJavaScriptなのかな
これにはRGBとRYBの相互変換が書いてあるので両方共エクセルVBAで書いて

で使っているのが↓になる

 
’RGBをRYBに似たものに変換
Function RGB2RYB(iRGB As myRGB) As TypeRYB
    Dim r, g, b
    r = iRGB.iRed / 255
    g = iRGB.iGreen / 255
    b = iRGB.iBlue / 255
    Dim w
    w = WorksheetFunction.min(r, g, b)
    r = r - w
    g = g - w
    b = b - w
    Dim mg
    mg = WorksheetFunction.max(r, g, b)
    Dim Y
    Y = WorksheetFunction.min(r, g)
    r = r - Y
    g = g - Y
    If b <> 0 And g <> 0 Then
        b = b / 2
        g = g / 2
    End If
    
    Y = Y + g
    b = b + g
    
    Dim my
    my = WorksheetFunction.max(r, Y, b)
    If my <> 0 Then
        Dim n
        n = mg / my
        r = r * n
        Y = Y * n
        b = b * n
    End If
    
    r = r + w
    Y = Y + w
    b = b + w
    
    Dim iRYB As TypeRYB
    With iRYB
        .iR = r
        .iY = Y
        .iB = b
    End With
    RGB2RYB = iRYB
    
End Function

’RYBに似たものからRGBに変換
Function RYB2RGB(iRYB As TypeRYB) As myRGB
    Dim w
    Dim r, Y, b
    With iRYB
        r = .iR
        Y = .iY
        b = .iB
    End With
    
    w = WorksheetFunction.min(r, Y, b)
    r = r - w
    Y = Y - w
    b = b - w
    
    Dim my
    my = WorksheetFunction.max(r, Y, b)
    Dim g
    g = WorksheetFunction.min(Y, b)
    Y = Y - g
    b = b - g
    If b <> 0 And g <> 0 Then
        b = b / 2
        g = g / 2
    End If
    
    r = r + Y
    g = g + Y
    
    Dim mg
    mg = WorksheetFunction.max(r, g, b)
    If mg <> 0 Then
        Dim n
        n = my / mg
        r = r * n
        g = g * n
        b = b * n
    End If
    
    r = r + w
    g = g + w
    b = b + w
    
    Dim iRGB As myRGB
    With iRGB
        .iRed = CInt(r * 255)
        .iGreen = CInt(g * 255)
        .iBlue = CInt(b * 255)
    End With
    
    RYB2RGB = iRGB
    
End Function
これだとあんまり面白くない感じなんだよなあ
やっぱり本物っぽい方で変換したい
 
ググって
blufiro: RYB Color Wheel
ここ見たら面白いのがあった
HSV-RYB relationってところ
これを見て
RYBのそれぞれの値を0.1づつ変化させたらどうなるのか見てみた

f:id:gogowaten:20191019113725p:plain

 
左のRGBのそれぞれの値を読み取ってRGBに変換してセルに色を塗って
色を塗ったところの数値はHSLのH(色相)の値
右のRGBはその色のRGBの値
数字だけ見てもよくわからないからグラフにして
イメージ 2
曲線だらけ
なのでRGBを一旦HSLに変換してからRYBに変換ってのも僕にはムリだー
どうなってるんだこれ
 

f:id:gogowaten:20191019113929p:plain

 

 
これを基準にしたんだけど
他のところを見ると
 
RYB color model - Wikipedia, the free encyclopedia

イメージ 4

 

イメージ 5

 

f:id:gogowaten:20191019114028p:plain

 

同じ赤や黄色でも微妙に色が違っていてわかんなくなってきたぞー
 
 
RGBではなく赤・黄・青の「RYB」カラーモデルで色を選択する方法とは? - GIGAZINE
日本語で少し説明のあるここ見ると
やっぱり
ここなのかなあって気がするけど
イメージ 7
 
この青よりもう少し鮮やかな
 
イメージ 8
こっちのほうがいいかなとも思う
 
記事を投稿したら貼り付けた画像がいくつか消えたぞー(3回目くらい)
イメージ 11
前回は文字数制限がどうとか言われたけど
文字数カウントしたら8991文字だから制限の2万文字以内だぞー
最終的にこの記事だけで3回画像を貼り直したよ
  1. 記事を投稿する
  2. 貼り付けた画像のいつくかが消えていたので記事の編集
  3. 貼り付け直して記事を投稿する
  4. 別の画像が消えているので2へ戻る(゚д゚)
 
2019/10/19追記
文字数制限や画像が消えるのはヤフーブログのときのもの
追記ここまで
 
 
 
関連記事