画像ファイルのピクセルを入れ替えることを思いついてしまったので、こりゃもう、やるっきゃないよってことになりました。
思いついたのは会社の休み時間。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だけですべてを表現できているわけではないんですね。(まぁ、ここは、黒からの加算で色を表現するか、白からの減算で色を表現するかなどの、別要因もありますけど)
詳しくは、ウィキペディアでもっと色々と検索してみると、面白い記事がたくさん見つかると思います。