| Světlost barvy z jednotlivých složek se počítá podle vzorce 0.3 * R + 0.59 * G + 0.11 * B. Každá barevná složka totiž k výsledné světlosti přispívá jiným dílem. Pak již není problém udělat graf. Celý program by vydal na samostatný článek, takhle je to dost narychlo: 
Public Class MainForm
    Dim max As Integer = 0   'maximální počet pixelů stejné úrovně
    Dim im As Bitmap
    Dim pR(255) As Integer   'počet pixelů s červenou složkou dané intenzity
    Dim pG(255) As Integer   'počet pixelů se zelenou složkou dané intenzity
    Dim pB(255) As Integer   'počet pixelů s modrou složkou dané intenzity
    Dim pS(255) As Integer   'počet pixelů se světlostí dané intenzity
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'nechat uživatele vybrat obrázek a načíst ho do proměnné im
        If OpenFileDialog1.ShowDialog() <> Windows.Forms.DialogResult.OK Then End
        im = Image.FromFile(OpenFileDialog1.FileName)
        ''TOHLE FUNGUJE POMALU PRO VELKÉ OBRÁZKY
        ''--------------------------------------
        'For y As Integer = 0 To im.Height - 1       'projít všechny pixely obrázku
        '    For x As Integer = 0 To im.Width - 1
        '        Dim c As Color = im.GetPixel(x, y)   'GetPixel je pomalé, volejte jej jen jednou a výsledek si uložte
        '        pR(c.R) += 1    'přičíst červený pixel
        '        pG(c.G) += 1    'přičíst zelený pixel
        '        pB(c.B) += 1    'přičíst modrý pixel
        '        pS(c.R * 0.3 + c.G * 0.59 + c.B * 0.11) += 1   'přičíst světlost
        '    Next
        'Next
        'RYCHLEJŠÍ METODA
        '----------------
        'získá se bitová kopie obrázku
        Dim bd As Imaging.BitmapData = im.LockBits(New Rectangle(0, 0, im.Width, im.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
        Dim pixely(bd.Width * bd.Height * 3 - 1) As Byte
        Runtime.InteropServices.Marshal.Copy(bd.Scan0, pixely, 0, pixely.Length)
        im.UnlockBits(bd)
        'teď pracujeme s jednotlivými pixely jako s bajty
        For i As Integer = 0 To pixely.Length - 1 Step 3        'skákat po 3 bajtech
            Dim b As Byte = pixely(i)       'první bajt z trojice je modrá
            Dim g As Byte = pixely(i + 1)   'druhý bajt z trojice je zelená
            Dim r As Byte = pixely(i + 2)   'třetí bajt z trojice je červená
            pR(r) += 1
            pG(g) += 1
            pB(b) += 1
            pS(r * 0.3 + g * 0.59 + b * 0.11) += 1
        Next
        'zjistit maximum
        For i As Integer = 0 To 255
            If pR(i) > max Then max = pR(i)
            If pG(i) > max Then max = pG(i)
            If pB(i) > max Then max = pB(i)
            If pS(i) > max Then max = pS(i)
        Next
        'uvolnit obrázek z paměti
        im = Nothing
    End Sub
    Public Sub Graf(ByVal g As Graphics, ByVal p As Pen, ByVal pole() As Integer, ByVal vyska As Integer)
        'vykreslit graf
        For i As Integer = 0 To 255
            Dim v As Integer = vyska * pole(i) / max
            g.DrawLine(p, i, 255, i, 255 - v)
        Next
    End Sub
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        Graf(e.Graphics, Pens.Red, pR, PictureBox1.Height)
    End Sub
    Private Sub PictureBox2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox2.Paint
        Graf(e.Graphics, Pens.Green, pG, PictureBox2.Height)
    End Sub
    Private Sub PictureBox3_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox3.Paint
        Graf(e.Graphics, Pens.Blue, pB, PictureBox3.Height)
    End Sub
    Private Sub PictureBox4_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox4.Paint
        Graf(e.Graphics, Pens.Black, pS, PictureBox4.Height)
    End Sub
End Class
Navíc protože je metoda GetPixel strašně pomalá (obrázek 800x600 mi trval na slabším stroji cca minutu), je lepší pomocí Marshal.Copy vytáhnout z obrázku pole bajtů. Pokud pole rozsekáme po třech bajtech, získáme jednotlivé pixely - první bajt je modrá složka, druhý zelená a třetí červená.  Ještě k polím pR, pG, pB a pS - včechny sledované položky (červená, zelená, modrá i světlost) mají hodnoty od 0 do 255. Takže v poli pR(40) bude počet pixelů v celém obrázku, jejichž červená složka má hodnotu 40, v poli pS(150) bude zaser počet pixelů se světlostí 150. Pak již jednoduše vykreslím graf - abych 4x neopisoval de facto stejný kód, udělal jsem si proceduru. Pokud to chcete spustit, dejte na formulář 4 pictureboxy o velikosti 256x256 pixelů a jeden OpenFileDialog. |