LoginSignup
1
1

More than 5 years have passed since last update.

24bitカラーをRGBに分解する

Last updated at Posted at 2017-01-15

はじめに

VBAで色を表す際は、多くの場合32bit整数であるLong型で表現される。
RGBの値が決まっていればVBA.RGB関数で色を作成することが出来るが、その逆の色の数字からRGBを取得する方法は用意されていない。

そこで自分の勉強も兼ねて、色の変換を行うクラスを作成してみた。

コード

Option Explicit

'色からRGBを取得しやすくするためのクラス
'プロパティ
    'Color      :読み書き:Long   :Long型の色
    'HexColor   :読み    :String :Colorの16進数表示
    'Red        :読み書き:Byte   :ColorのR部分
    'Green      :読み書き:Byte   :ColorのG部分
    'Blue       :読み書き:Byte   :ColorのB部分

'メソッド
    'なし

Private clsColor As Long
Private clsRed As Byte
Private clsGreen As Byte
Private clsBlue As Byte

Private Sub ChangeColor(iColor As Long)
    Select Case iColor
        Case 0 To &HFFFFFF  'RGB(0, 0, 0) To RGB(255, 255, 255)
            'Next
        Case Else
            Call Err.Raise(vbObjectError, VBA.TypeName(Me), "0 から 16777215 の間で指定してください")
    End Select

    Let clsColor = iColor

    Dim tmpColor As Long
    tmpColor = iColor
    Const DIV& = 256

    Let clsRed = tmpColor Mod DIV
    tmpColor = (tmpColor - clsRed) / DIV

    Let clsGreen = tmpColor Mod DIV
    tmpColor = (tmpColor - clsGreen) / DIV

    Let clsBlue = tmpColor Mod DIV

End Sub


Public Property Get Color() As Long
    Let Color = clsColor
End Property

Public Property Let Color(ByVal SetColor As Long)
    Call ChangeColor(SetColor)
End Property


Public Property Get HexColor() As String
    Let HexColor = VBA.Hex$(clsColor)
End Property


Public Property Get Red() As Byte
    Let Red = clsRed
End Property

Public Property Let Red(ByVal iRed As Byte)
    Call ChangeColor(VBA.RGB(VBA.CInt(iRed), VBA.CInt(clsGreen), VBA.CInt(clsBlue)))
End Property


Public Property Get Green() As Byte
    Let Green = clsGreen
End Property

Public Property Let Green(ByVal iGreen As Byte)
    Call ChangeColor(VBA.RGB(VBA.CInt(clsRed), VBA.CInt(iGreen), VBA.CInt(clsBlue)))
End Property


Public Property Get Blue() As Byte
    Let Blue = clsBlue
End Property

Public Property Let Blue(ByVal iBlue As Byte)
    Call ChangeColor(VBA.RGB(VBA.CInt(clsRed), VBA.CInt(clsGreen), VBA.CInt(iBlue)))
End Property

簡易確認用

上記のクラスをRGBColorという名前で作成してください。

Sub RGBColorTest_Tekitou()
    Dim myCls As RGBColor
    Set myCls = New RGBColor

    With myCls
        Debug.Assert .Color = RGB(0, 0, 0)

        .Color = RGB(255, 255, 255)
        Debug.Assert .Color = RGB(255, 255, 255)
        Debug.Assert .Red = 255
        Debug.Assert .Green = 255
        Debug.Assert .Blue = 255
        Debug.Assert .HexColor = "FFFFFF"

        .Blue = 0
        Debug.Assert .Color = RGB(255, 255, 0)
        Debug.Assert .Red = 255
        Debug.Assert .Green = 255
        Debug.Assert .Blue = 0
        Debug.Assert .HexColor = "FFFF"

        .Green = 128
        Debug.Assert .Color = RGB(255, 128, 0)
        Debug.Assert .Red = 255
        Debug.Assert .Green = 128
        Debug.Assert .Blue = 0
        Debug.Assert .HexColor = "80FF"

        On Error Resume Next
            .Color = VBA.RGB(255, 255, 255) + 1
            Debug.Assert Err.Number <> 0
        On Error GoTo 0
    End With
    Stop
End Sub

作成にあたって

当初は色をを16進数表記変換にして、文字列演算でごり押す方法だった。
途中で256で割れば良いことに気付き、現在の形になった。

RGBの値を算出するタイミングとして、

  1. RGB参照時に計算を行う
  2. 色設定時にRGBをまとめて算出する

で迷ったが、フラグ管理が面倒だったため2の方法をとることにした。
また、内部変数のcls~を直接いじるのをChangeColorプロシージャにまとめることで、ロジック部分を集約できた。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1