Written in Japanese(Shift-JIS)
2011. 2.20
INASOFT
/トップ/目次/管理人のひとこと(ブログ)/RGB画像入れ替えツール

2106328 (+0030)[+0219]

管理人のふたこと Tweet

RGB画像入れ替えツール


公開日:2011/ 2/16
追記日:2011/ 2/20 (ソースコードと、実験的に「いいね!」ボタンを追加)


画像ファイルのピクセルを入れ替えることを思いついてしまったので、こりゃもう、やるっきゃないよってことになりました。



思いついたのは会社の休み時間。VB.NETを使うと、画像のピクセルを簡単に扱えるって話は知っていたのですが、それならば簡単にRGB要素の入れ替えもできるんじゃないか、と思ったら、作らずにはいられませんでした。

ってわけで、作ってみたのが、今日の日記に書いてあるようなもの。

Imports System
Imports System.IO
Imports System.Drawing.Imaging

Public Class Form1

    (中略)

    Private Sub FileDrop(ByVal sender As System.Object, ByVal e As DragEventArgs) Handles Me.DragDrop
        ' 画面上のステータス表示を変更
        LabelStatus.Text = "処理中..."

        ' ドロップされたファイル名の名前を取り出す
        Dim aryFnames As String() = DirectCast(e.Data.GetData(DataFormats.FileDrop), String())

        For Each strFname As String In aryFnames

            Try

                ' ファイルのドロップから取得したファイル名を、パスとファイル名のみ(拡張子以外)と拡張子に分ける
                Dim strDirName As String = Path.GetDirectoryName(strFname)
                Dim strFileNameOnly As String = Path.GetFileNameWithoutExtension(strFname)
                Dim strFileExt As String = Path.GetExtension(strFname)

                ' ファイルの読み出し
                Dim bmp As New Bitmap(strFname)

                ' 読み出したファイルと同サイズのビットマップを準備
                Dim newbmp As New Bitmap(bmp.Width, bmp.Height)

                ' 全ピクセルを走査し、指定されたRGB要素の入れ替えを行う
                Dim x As Integer
                Dim y As Integer
                Dim c As Color

                For y = 0 To bmp.Height - 1
                    For x = 0 To bmp.Width - 1

                        c = bmp.GetPixel(x, y)

                        ' ラジオボタンの選択肢により、入れ替えるRGB要素が変わる
                        If RadioButton_RB.Checked Then
                            newbmp.SetPixel(x, y, Color.FromArgb(c.A, c.B, c.G, c.R))
                        ElseIf RadioButton_RG.Checked Then
                            newbmp.SetPixel(x, y, Color.FromArgb(c.A, c.G, c.R, c.B))
                        Else ' BGを仮定
                            newbmp.SetPixel(x, y, Color.FromArgb(c.A, c.R, c.B, c.G))
                        End If

                    Next
                Next

                ' 新しいファイル名を決定
                Dim strNewFilename As String

                ' ラジオボタンの選択肢により、ファイル名を変える
                If RadioButton_RB.Checked Then
                    strNewFilename = strDirName + "\" + strFileNameOnly + "_rb" + strFileExt
                ElseIf RadioButton_RG.Checked Then
                    strNewFilename = strDirName + "\" + strFileNameOnly + "_rg" + strFileExt
                Else ' BGを仮定
                    strNewFilename = strDirName + "\" + strFileNameOnly + "_bg" + strFileExt
                End If

                ' 新しいファイル名で保存
                newbmp.Save(strNewFilename, Ext2ImageFormat(strFileExt))
                MsgBox(strNewFilename + "に保存しました。", MsgBoxStyle.OkOnly, Me.Text)

                ' 解放しないと、しばらくファイルを掴みっぱなしになるようなので
                newbmp.Dispose()
                bmp.Dispose()

            Catch ex As Exception

                MsgBox(ex.ToString + vbCrLf + vbCrLf + "処理中のファイル名:" + strFname, MsgBoxStyle.OkOnly + MsgBoxStyle.Critical, "エラー")

            End Try


        Next

        ' 画面上のステータス表示を変更
        LabelStatus.Text = "ここに画像ファイルをドロップ"

    End Sub

    Private Sub ListBox1_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Me.DragEnter

        ' ファイルのドロップを許可する
        e.Effect = DragDropEffects.All

    End Sub

    Private Function Ext2ImageFormat(ByVal strExt As String) As ImageFormat
        ' 拡張子 ".*" を、画像フォーマットに変換する
        Select Case strExt.ToUpper
            Case ".JPG", ".JPEG"
                Return ImageFormat.Jpeg

            Case ".ICO"
                Return ImageFormat.Icon

            Case ".BMP", ".DIB"
                Return ImageFormat.Bmp

            Case ".EMF"
                Return ImageFormat.Emf

            Case ".GIF"
                Return ImageFormat.Gif

            Case ".WMF"
                Return ImageFormat.Wmf

            Case ".TIF", "TIFF"
                Return ImageFormat.Tiff

            Case Else
                Return ImageFormat.Png

        End Select

    End Function

End Class

.NET Frameworkでは、ファイルの種類に関係なく、いきなりピクセルに関する処理を記述できます。画像ファイルフォーマットを知らなくても画像処理ができるというのは、ラクでいいですね。

もしこれと同じコードを、C++で、.NETを使わずに書いたと思うと……どれだけ壮大なソースコードができあがってしまうことでしょう。

ダウンロードはとりあえずINASOFTのトップページまでどうぞ。

(.NET 2.0で作ったツールなので、.NET Framework 2.0 が必須になります。まぁ、たいていのPCには入っているので大丈夫だと思いますが)







うむうむ、けっこう想像通りにいっていますね。ちなみに想像通りだったのは左側だけ。一番右側なんて、むしろ秋の風景みたいでキレイじゃないですか。稲の収穫期みたいな? 色の入替えだけで、けっこうキレイな画像ができちゃったな。

ところで、なんでRGBの要素を入れ替えるだけで、こういうバリエーションが生まれるのか。そもそも、どうしてRGBで全ての色が表せるのか、不思議に思ったことはないでしょうか。

僕がコレを最初に不思議に思ったのは、あるテレビメーカーのCMを見たときです。

テレビを4原色にしてみた」という、あのCMですね。

それまでは、RGBだけですべての色を表せていたはずなのに、どうしてRGB以外の色を混ぜることで、色の表現を広げることができるのか。もしかすると、パソコンのRGBだけでは、すべての色を表現できていないのではないか、とすればそれは何か?と思うようになりました。

というわけで、ウィキペディア様で調べてみましたところ…。

どうやら、人間の色の認識自体、そもそも錯覚みたいなモノらしいんですね。

そもそも、人間の目は、RGBの色の割合でしか、色を観ることができません。つまり、「本当に黄色い波長が来ているのか」「もしくは緑と赤の波長が混ざっているのか」は、本来別のモノであるはずなのに、人間の目ではそれらを識別できないのです。

というか、人間の目は、実は感じられないものが多いようなのです。

紫外線や赤外線、X線などの「可視光」以外の電磁波を観ることはもちろんできませんし、偏光についても(一部の例外を除き)観ることはできません。

でもやっぱり、光の暖かさとか、デジタルな波形以外の反射光とか、そういう部分を考えると、やっぱりRGB要素だけでは表現しきれない何かがあるらしいんですね。

例えば、寿司屋の電球。あの電球に照らされたマグロは非常に美味しそうに見えます。しかし、自宅であれと同じ色をRGBで合成して作り、マグロに当てたとしても、同じようなおいしさを表現することはできないんだとか。

それが、RGB以外の光の波長を当てられたときの、マグロからの反射光として、違いが出てくるみたいなんですね。

まぁ僕も物理学者ではないので、詳しい事はわかりませんが、どうやらRGBだけですべてが表現できるわけではない、ということは、よくわかりました。

っていうか、家庭用プリンタの印刷の世界ですら、RGBではなく、CMYKの原色を使ったりしますし、RGBだけですべてを表現できているわけではないんですね。(まぁ、ここは、黒からの加算で色を表現するか、白からの減算で色を表現するかなどの、別要因もありますけど)

詳しくは、ウィキペディアでもっと色々と検索してみると、面白い記事がたくさん見つかると思います。





本ページへは、自己責任の範囲内であれば自由にリンクしていただいて構いません。
本ページに掲載されている内容は、自由にお使いいただいて構いませんが、必ずしも筆者が内容を保証するものではありませんので、ご利用に際しては自己の責任においてお使いいただきますよう、お願いいたします。
このページのURLやアンカーは、サーバ運営・サイト運営・ページ運営・その他の都合により無告知で一時的あるいは永遠に消滅したり、変更したりする可能性がありますので、あらかじめご了承下さい。
本ページは、公開から1年半経過後の任意のタイミングで削除される予定です。本ページの内容は複製・公開していただいて構いません。


/トップ/目次//管理人のひとこと(ブログ)/RGB画像入れ替えツール