動機
世の中にはExcelを使ってお絵描きをする人という方がいらっしゃいます。
自分は絵心がないのでビットマップファイルをロードして、エクセルシートの背景色の1ビットごとに色付けをするかたちで絵を描くプログラムを作成しました。
かなり雑なプログラムなので動かないこともあるかもしれません。
プログラム
bitmapviewer.bas
Option Explicit
'BITMAPFILEHEADER ヘッダー情報
Dim bfType As String
Dim bfSize As Long
Dim bfReserved1 As Integer
Dim bfReserved2 As Integer
Dim bfOffBits As Long
'BITMAPINFOHEADER ヘッダー情報
Dim bcSize As Long
Dim bcWidth As Long
Dim bcHeight As Long
Dim bcPlanes As Integer
Dim bcBitcount As Integer
Dim biCompression As Long
Dim biSizeImage As Long
Dim biXPixPerMeter As Long
Dim biYPixPerMeter As Long
Dim biClrUsed As Long
Dim biCirImportant As Long
'BITMAPFILEHEADER 操作手続き
Private Sub readBITMAPFILEHEADER(ByRef buf() As Byte)
bfType = Chr(buf(0)) + Chr(buf(1))
bfSize = concat4LEndian(buf(), 2)
bfReserved1 = concat2LEndian(buf(), 6)
bfReserved2 = concat2LEndian(buf(), 8)
bfOffBits = concat4LEndian(buf(), 10)
End Sub
Private Sub showBITMAPFILEHEADER()
Debug.Print "bfType:", bfType
Debug.Print "bfSize:", bfSize
Debug.Print "bfReserved1:", bfReserved1
Debug.Print "bfReserved2:", bfReserved2
Debug.Print "bfOffBits:", bfOffBits
End Sub
'BITMAPINFOHEADER 操作手続き
Public Sub readBITMAPINFOHEADER(ByRef buf() As Byte)
bcSize = concat4LEndian(buf(), 0)
bcWidth = concat4LEndian(buf(), 4)
bcHeight = concat4LEndian(buf(), 8)
bcPlanes = concat2LEndian(buf(), 12)
bcBitcount = concat2LEndian(buf(), 14)
biCompression = concat4LEndian(buf(), 16)
biSizeImage = concat4LEndian(buf(), 20)
biXPixPerMeter = concat4LEndian(buf(), 24)
biYPixPerMeter = concat4LEndian(buf(), 28)
biClrUsed = concat4LEndian(buf(), 32)
biCirImportant = concat4LEndian(buf(), 36)
End Sub
Private Sub showBITMAPINFOHEADER()
Debug.Print "bcSize:", bcSize
Debug.Print "bcWidth:", bcWidth
Debug.Print "bcHeight:", bcHeight
Debug.Print "bcPlanes:", bcPlanes
Debug.Print "bcBitcount:", bcBitcount
Debug.Print "biCompression:", biCompression
Debug.Print "biSizeImage:", biSizeImage
Debug.Print "biXPixPerMeter:", biXPixPerMeter
Debug.Print "biYPixPerMeter:", biYPixPerMeter
Debug.Print "biClrUsed:", biClrUsed
Debug.Print "biCirImportant:", biCirImportant
End Sub
'プライベート共通手続き、関数
Private Function left_shift(ByVal b, ByVal shift As Byte)
Dim bit As Long: bit = b
left_shift = bit * (2 ^ shift)
End Function
Private Function concat2LEndian(ByRef buf() As Byte, ByVal initIndex)
concat2LEndian = left_shift(buf(initIndex + 1), 8) Or buf(initIndex)
End Function
Private Function concat4LEndian(ByRef buf() As Byte, ByVal initIndex)
concat4LEndian = left_shift(buf(initIndex + 3), 24) Or left_shift(buf(initIndex + 2), 16) Or left_shift(buf(initIndex + 1), 8) Or buf(initIndex)
End Function
'メイン手続き
Public Sub displayBitmapImage(ByVal fpath As String)
Dim fn As Integer: fn = FreeFile
Open fpath For Binary Access Read As #fn
Dim wholeSize As Long: wholeSize = LOF(fn)
Dim sizeFileHeader As Integer: sizeFileHeader = 14 - 1
Dim sizeInfoHeader As Integer: sizeInfoHeader = 40 - 1
Dim bufArry() As Byte
Debug.Print "displayBitmapImage"
If (sizeFileHeader + sizeInfoHeader <= wholeSize) Then
ReDim bufArry(sizeFileHeader)
Get #fn, , bufArry
Call readBITMAPFILEHEADER(bufArry)
Call showBITMAPFILEHEADER
ReDim bufArry(sizeInfoHeader)
Get #fn, , bufArry
Call readBITMAPINFOHEADER(bufArry)
Call showBITMAPINFOHEADER
Else
Exit Sub
End If
Dim sizeLineBuf As Integer: sizeLineBuf = (3 * bcWidth) - 1
Dim lineNum As Long: lineNum = bcHeight
Dim iReadSize As Long: iReadSize = sizeFileHeader + 1 + sizeInfoHeader + 1
ReDim bufArry(sizeLineBuf)
Do Until EOF(fn)
Get #fn, , bufArry
Call coloring(lineNum, bufArry, Range("A1").Offset(lineNum, 0))
lineNum = lineNum - 1
iReadSize = iReadSize + sizeLineBuf + 1
If (iReadSize <= wholeSize) And (wholeSize - iReadSize < sizeLineBuf + 1) Then
sizeLineBuf = wholeSize - iReadSize
ReDim bufArry(sizeLineBuf)
End If
DoEvents
Loop
Close #fn
End Sub
Private Sub coloring(ByVal lnum As Long, ByRef lbuf() As Byte, ByRef rng As Range)
Dim R24 As Byte
Dim G24 As Byte
Dim B24 As Byte
Dim it As Long
For it = LBound(lbuf) To UBound(lbuf) - 3 Step 3
B24 = lbuf(it)
G24 = lbuf(it + 1)
R24 = lbuf(it + 2)
rng.Offset(0, it \ 3).Interior.Color = RGB(R24, G24, B24)
Next it
'Debug.Print RGB(R24, G24, B24)
End Sub
Public Sub main()
Sheets(1).Cells.Select
Selection.ColumnWidth = 0.06
Selection.RowHeight = 0.6
Dim filename As String: filename = Application.GetOpenFilename("ビットマップファイル,*.bmp")
If filename = "False" Then Exit Sub
Call displayBitmapImage(filename)
End Sub