Silverlight 2.0 içerisinde Hue / Saturation ve Lightness ile dinamik renk paletleri yaratmanın yolu.

0 dakikada yazıldı

6182 defa okundu

Düzenle

Silverlight 2.0 ile beraber istemci taraflı CLR altyapısı ile aslında
hayal bile edemeyeceğimiz bir sürü işlemi bildiğimiz .NET dilleri ile
yapabiliyoruz. Birazdan yapacağımız örneği Silverlght 2.0 öncesi
herhangi bir teknoloji ile uygulamaya kaltığımızda bir .NET yazılım
geliştiricisi için çok daha acı verici bir süreç söz konusu olabilirdi.
Oysa doğrudan istemci tarafında .NET kullanımı ile çok daha rahat bir
platform sağlanabiliyor.

Silverlight 2.0 Beta 1 içerisinde ister farklı User Control yapıları
olsun veya ister farklı görsel stiller kullanın belirli noktalarda
dinamik olarak Gradient yapıları kurmanız gerekebiliyor. İşte tam da
bu noktada bir rengin geçiş yapabileceği başka uygun bir rengi
programatik olarak bulmak ciddi sıkıntı verebilir. Aslında en basit
çözüm Expression Design gibi programlarda yapabildiğimiz; bir rengin
Hue / Saturation / Lightness değerlerini değiştirmektir. Böylece
rengin ana yapısı değişmese de parlaklık ve ışık miktarı değiştirilerek
farklı geçişler sağlanabilir ve bu farklı renklerden Gradient'lar
dinamik olarak yaratılarak rahatlıkla kullanılabilir. Fakat maalesef
Silverlight ile beraber gelen yapıya baktığımızda biz renklerin RGB
(Red, Green, Blue) olarak geldiğini görüyoruz. Peki Hue, Lightness
ve Saturation nasıl hesaplanıyor? Bu konuda live.com'da ufak bir
araştırma HSL ile RGB arasında çeviri işlemlerinin nasıl yapılacağını
öğrenmemiz için yeterli. Maalesef internette bu işi hazır yapan bir kod
bulamadım. Ben matematik hesaplamaların ve sisteminin mantığının
detayına girmeden sizinle yazmış olduğum kodu paylaşacağım.

Namespace HSLveRGB

    Public Structure HslRenk

        Public Alpha As Double

        Public Hue As Double

        Public Saturation As Double

        Public Lightness As Double

 

        Private Function Normal(ByVal gelen As Double)
As Double

            If gelen  < 0 Then

                gelen  += 1

            End If

            If gelen  > 1 Then

                gelen  -= 1

            End If

            Return gelen

        End Function

 

        Private Shared Function B2P(ByVal gelen As Byte)
As Double

            Dim giden As Double
= gelen

            giden  = giden  / 255

            Return giden

        End Function

 

        Private Shared Function P2B(ByVal gelen As Double)
As Byte

            gelen *= 255

            gelen += 0.5

            If gelen > 255 Then

                gelen = 255

            End If

            If gelen < 0 Then

                gelen = 0

            End If

            Return CByte(gelen)

        End Function

 

        Public Shared Function FromColor(ByVal BirRenk As Color) As HslRenk

            Return
HslRenk.FromArgb(BirRenk.A, BirRenk.R, BirRenk.G, BirRenk.B)

        End Function

 

        Public Function RengiAc(ByVal x As
Double) As HslRenk

            Dim BirRenk As New
HslRenk()

            BirRenk.Alpha = Me.Alpha

            BirRenk.Hue = Me.Hue

            BirRenk.Saturation = Me.Saturation

            BirRenk.Lightness = Math.Min(Math.Max(Me.Lightness + x, 0), 1)

            Return BirRenk

        End Function

 

        Public Shared Function FromArgb(ByVal Alpha As Byte,
ByVal Kirmizi As Byte,
ByVal Yesil As Byte,
ByVal Mavi As Byte)
As HslRenk

            Dim BirRenk As HslRenk = FromRgb(Kirmizi, Yesil, Mavi)

            BirRenk.Alpha = B2P(Alpha)

            Return BirRenk

        End Function

 

        Public Shared Function FromRgb(ByVal Kirmizi As Byte,
ByVal Yesil As Byte,
ByVal Mavi As Byte)
As HslRenk

            Dim BirRenk As New
HslRenk()

            BirRenk.Alpha = 1

            Dim red As Double
= B2P(Kirmizi)

            Dim green As Double
= B2P(Yesil)

            Dim blue As Double
= B2P(Mavi)

            Dim max As Double
= Math.Max(blue, Math.Max(red , green))

            Dim min As Double
= Math.Min(blue, Math.Min(red , green))

            If max = min Then

                BirRenk.Hue = 0

            ElseIf max = red AndAlso green >= blue Then

                BirRenk.Hue = 60 * ((green - blue) / (max - min))

            ElseIf max = red AndAlso green < blue Then

                BirRenk.Hue = 60 * ((green - blue) / (max - min)) + 360

            ElseIf max = green Then

                BirRenk.Hue = 60 * ((blue - red) / (max - min)) + 120

            ElseIf max = blue Then

                BirRenk.Hue = 60 * ((red - green) / (max - min)) + 240

            End If

 

            BirRenk.Lightness = 0.5 * (max + min)

            If max = min Then

                BirRenk.Saturation = 0

            ElseIf BirRenk.Lightness
<= 0.5 Then

                BirRenk.Saturation = (max - min) / (2 *
BirRenk.Lightness)

            ElseIf
BirRenk.Lightness > 0.5 Then

                BirRenk.Saturation = (max - min) / (2 - 2 *
BirRenk.Lightness)

            End If

            Return BirRenk

        End Function

 

        Public Function RengiKoyulastir(ByVal x As
Double) As HslRenk

            Return RengiAc(-x)

        End Function

 

        Private Function Hesap(ByVal Bir  As Double,
ByVal Iki As Double,
ByVal Uc As Double)
As Double

            If Bir < (1 / 6) Then

                Return Iki  + ((Uc  -
Iki ) * 6 * Bir )

            End If

            If Bir < 0.5 Then

                Return Uc

            End If

            If Bir < (2 / 3) Then

                Return Iki  + ((Uc  -
Iki ) * 6 * ((2 / 3) - Bir ))

            End If

            Return Iki

        End Function

 

        Public Function ToColor() As Color

            Dim Bir As Double
= 0

            If Lightness < 0.5 Then

                Bir  = Lightness * (1 + Saturation)

            Else

                Bir  = Lightness + Saturation - (Lightness *
Saturation)

            End If

            Dim Iki As Double
= (2 * Lightness) - Bir

            Dim Key As Double
= Hue / 360

            Dim red As Double
= Hesap(Normal(Key + (1 / 3)), Iki , Bir )

            Dim green As Double
= Hesap(Normal(Key), Iki , Bir)

            Dim blue As Double
= Hesap(Normal(Key - (1 / 3)), Iki , Bir )

            Return
Color.FromArgb(P2B(Alpha), P2B(red ), P2B(green), P2B(blue))

        End Function

    End Structure

End Namespace

Yukarıdaki kodu isterseniz harici bir DLL olarak derleyerek tüm
projelerinizde kullanabilirsiniz. Silverlight içerisindeki kullanımına
da ufak bir örnek ile göz atalım. Aşağıdaki şekilde Silverlight 2.0
uygulamamıza bir dikdörtgen ve Slider yerleştirerek Slider ile
dikdörtgen içerisindeki rengi değiştireceğiz.

<UserControl
x:Class="HSL2RGB.Page"

    xmlns="http://schemas.microsoft.com/client/2007"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="400" Height="300">

    <Grid
x:Name="LayoutRoot"
Background="White">

      <Rectangle
HorizontalAlignment="Stretch"
Margin="43,23,47,124"
VerticalAlignment="Stretch"
Fill="#FFD05D5D"
Stroke="#FF000000"
x:Name="Kutu"/>

      <Slider
Height="24" Margin="43,0,47,82"
VerticalAlignment="Bottom"
x:Name="Slider" ****
Maximum="1" ****
LargeChange="0.1" ****
SmallChange="0.01"/>

    </Grid>

</UserControl>

Özellikle Slider'ın alabildiği maksimum değere dikkat etmekte fayda var.
Bu değer üzerinden bizim daha önceki HSL nesnesini kullanarak
RengiAc ve RengiKoyulastir metodlarını çalıştıracağız. Geçelim
uygulamanın kod kısmına.

Partial Public Class Page

    Inherits UserControl

 

    Public Sub New()

        InitializeComponent()

    End Sub

 

    Dim AnaRenk As Color =
System.Windows.Media.Color.FromArgb(100, 255, 50, 50)

 

    Private Sub Slider_ValueChanged(ByVal sender As Object,
ByVal e As
System.Windows.RoutedPropertyChangedEventArgs(Of Double)) Handles Slider.ValueChanged

        CType(Kutu.Fill,
SolidColorBrush).Color =
HSLveRGB.HslRenk.FromColor(AnaRenk).RengiAc(e.NewValue -
0.5).ToColor

    End Sub

End Class

Yukarıdaki kod içerisinde ilk olarak dikkat edilmesi gereken nokta bizim
global AnaRenk değişkenimiz. Bu değişken içerisinde sürekli bizim
ana rengimiz duruyor ve bu renk üzerinden gerekli işlemleri yaparak
yarattığımız yeni rengi Kutu nesnesinin Fill özelliğine atanmış
SolidColorBrush'ın Color özelliğine aktarıyoruz. RengiAc
metodunu kullanırken de Slider'ın mevcut değerine göre -0.5 ile 0.5
arasında bir değer gelmesini sağlıyoruz. Zaten aynı metod kendisine eksi
değer verildiğinde rengi açmak yerine kapatıyordu.

Böylece rahatlıkla renklerin Hue / Saturation ve Lightness özellikleri
Silverlight tarafında dinamik olarak değiştirilebiliyor. Bu özellikleri
kullanarak sadece tek bir renk üzerinden giderek başka renkler de
yaratıp güzel Gradient yapıları kurabilirsiniz.

Hepinize kolay gelsin.