VB2008で画像をコントラスト調整したい

タグの編集
投稿者 モル  (社会人) 投稿日時 2009/12/2 23:45:55
お久しぶりです、モルです。
早速ですが質問に入らせてもらいます。

現在画像を加工しようと色々調べていて、この中学校様のサンプルを使用させていただいています。
そこでサンプルには「明るさの調整」はありますが「コントラストの調整」はどのようにすればいいのでしょうか?

シャープやエンボス系かな?と思い、サンプルで使用されている「Imaging.ImageAttributes」や「Imaging.ColorMatrix」なので検索してみましたが、コントラスト調整は見つけれませんでした。
何か参考になるサイトや方法などありましたら、お教え下さい。
よろしくお願いします。
投稿者 匿名  (社会人) 投稿日時 2009/12/3 04:05:56
http://fireball.loafer.jp/kes/perl/article_48.html
参考になれば
投稿者 あにす  (社会人) 投稿日時 2009/12/3 11:12:34
ちょっと面白そうだったので匿名さんが示したURLを参考に書いてみました。

Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices

Public Class Form1
    Dim imageFilePath As String = "hogehoge.bmp"

    Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load
        Dim img As Image = Image.FromFile(imageFilePath)
        Me.BackgroundImage = GetChangeContrastImage1(img, 2) 'コントラストが2倍になる 
        Me.BackgroundImage = GetChangeContrastImage2(img, 0.5) 'コントラストが1/2になる 
    End Sub

    'GetPixel,SetPixelバージョン、遅い 
    Private Function GetChangeContrastImage1(ByVal image As Image, ByVal contrast As DoubleAs Image
        Dim level As Double = 127.5
        Dim bmp As New Bitmap(image)

        For y As Integer = 0 To bmp.Height - 1
            For x As Integer = 0 To bmp.Width - 1
                Dim pixel As Color = bmp.GetPixel(x, y)
                Dim r, g, b As Byte
                r = Math.Min(Math.Max(Byte.MinValue, (pixel.R - level) * contrast + level), Byte.MaxValue)
                g = Math.Min(Math.Max(Byte.MinValue, (pixel.G - level) * contrast + level), Byte.MaxValue)
                b = Math.Min(Math.Max(Byte.MinValue, (pixel.B - level) * contrast + level), Byte.MaxValue)
                bmp.SetPixel(x, y, Color.FromArgb(r, g, b))
            Next
        Next

        Return bmp
    End Function

    'LockBitsバージョン、速い 
    Private Function GetChangeContrastImage2(ByVal image As Image, ByVal contrast As DoubleAs Image
        Dim level As Double = 127.5
        Dim bmp As New Bitmap(image.Width, image.Height, PixelFormat.Format24bppRgb)

        Using g As Graphics = Graphics.FromImage(bmp)
            g.DrawImage(image, Point.Empty)
        End Using

        Dim bmpData As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Dim bmpDataBytes(bmpData.Stride * bmpData.Height) As Byte
        Marshal.Copy(bmpData.Scan0, bmpDataBytes, 0, bmpDataBytes.Length)

        For i As Integer = 0 To bmpDataBytes.Length - 1
            bmpDataBytes(i) = Math.Min(Math.Max(Byte.MinValue, (bmpDataBytes(i) - level) * contrast + level), Byte.MaxValue)
        Next

        Marshal.Copy(bmpDataBytes, 0, bmpData.Scan0, bmpDataBytes.Length)
        bmp.UnlockBits(bmpData)

        Return bmp
    End Function
End Class


思ったほど泥臭くならなかったです。
投稿者 あにす  (社会人) 投稿日時 2009/12/3 11:39:55
バグ出してました。
38行目の
            g.DrawImage(image, Point.Empty)


            g.DrawImage(image, 0, 0, bmp.Width, bmp.Height)

にしないと画像のサイズがおかしくなってしまうようです。
投稿者 モル  (社会人) 投稿日時 2009/12/3 23:04:03
確認が遅れて申し訳ありませんでした。

匿名様、あにす様、ありがとうございます。
現在試させてもらったらコントラストかかってますね!

GetPixelやSetPixelを使用は流石に1Pixel毎に行うので大きい画像だと厳しいですね。。。
試しに4500x1800のJPG画像をコントラスト10倍で試してみた所

GetPixel,SetPixelバージョン:約19秒
LockBitsバージョン:約3秒

と圧倒的でした。
LockBitsというのは初めて聞いた名称ですのでとても参考になりました。
本当にありがとうございました。