Önce özete göz atDersin sonundaki özet, okumaya başlamadan önce yol haritası olarak.
- sRGB'den OKLab'e giden hat sırası değiştirilemeyen duraklardan oluşur: 255'e bölme, gamma kodunu çözme, 3×3 matrisle XYZ'ye geçme, gerekiyorsa beyaz nokta uyarlaması ve hedef uzaya geçiş.
- Gamma kodunu çözmeden matris uygulamak, ışık yerine eğrilmiş sayıları toplar; hata koyu renklerde en büyüktür ve koyu bir ten 21 yerine 51 açıklıkta ölçülür, bu da farklı tenleri eşitsiz biçimde bozan bir ölçüme yol açar.
- Beyaz noktalar D65 ile D50 arasında Bradford gibi bir yöntemle uyarlanır; yazılan kod ya da kullanılan kütüphane, Ottosson'un OKLab tablosu gibi yayımlanmış test değerleriyle ve bağımsız bir hesapla sınanır.
Kısa cevap
Bir rengi sRGB'den XYZ'ye, oradan CIELAB'a ya da OKLab'e taşıyan kod, sırası değiştirilemeyen birkaç duraktan oluşur: önce 0–255 arasındaki kodlanmış değerler 0–1 aralığına bölünür, sonra aktarım eğrisi tersine çevrilerek doğrusal ışığa açılır, ancak ondan sonra 3×3'lük bir matrisle XYZ'ye geçilir ve gerekiyorsa beyaz nokta uyarlanır. Gamma kodunu çözmeden matris uygulamak hatalıdır, çünkü matris ışık miktarlarını toplayan doğrusal bir işlemdir ve kodlanmış değerler ışık miktarı değildir; sonuç, özellikle koyu renklerde büyük hatalar verir: koyu bir ten tonunun CIELAB açıklığı 21 yerine 51 çıkar. Yazılan kod, yayımlanmış test değerleriyle ve güvenilir bir açık kaynak kütüphaneyle karşılaştırılarak doğrulanır.
Bir dönüşüm hattı
EK-13'te cihazlar arasında çeviri yapan profilleri ve cihazdan bağımsız uzayları gördük. Bu ders, o çevirinin bir parçasını kodla yapmayı anlatıyor. Amaç bir kütüphaneyi yeniden yazmak değil, bir kütüphanenin içinde ne olduğunu bilmek ve kendi hesabımızı sınayabilmektir.
sRGB'den OKLab'e giden bir hat beş duraktan oluşur. Birinci durakta 0–255 arasındaki değerler 255'e bölünür ve 0–1 aralığına getirilir. İkinci durakta sRGB aktarım eğrisi tersine çevrilir ve değerler doğrusal ışığa açılır. Üçüncü durakta 3×3'lük bir matrisle doğrusal RGB'den XYZ'ye geçilir. Dördüncü durakta, hedef uzayın beyaz noktası farklıysa, kromatik uyarlama yapılır. Beşinci durakta XYZ'den hedef uzaya, CIELAB'a ya da OKLab'e geçilir. Aşağıdaki tablo, bir ten tonunun, #8D5524'ün, bu duraklardan geçerken aldığı değerleri gösteriyor.
| Durak | İşlem | #8D5524 için değer |
|---|---|---|
| Kodlanmış | 8 bitlik değerler | 141, 85, 36 |
| Bölme | 255'e bölme | 0,5529 · 0,3333 · 0,1412 |
| Doğrusal | aktarım eğrisinin tersi | 0,2664 · 0,0908 · 0,0176 |
| XYZ (D65) | 3×3 matris | 0,1455 · 0,1229 · 0,0327 |
| CIELAB (D65) | küp kök ve ölçekleme | L 41,7 · a 18,9 · b* 37,2 |
| OKLab | iki matris ve küp kök | L 0,504 · a 0,051 · b 0,083 |
Gamma kodunu çözmek
EK-05'te sRGB'nin aktarım eğrisini ve bir değerin neden ışık miktarını değil onun eğriden geçmiş hâlini yazdığını gördük. Kodda bu, her kanal için aynı iki parçalı işlemdir: 0–1 aralığına getirilmiş değer 0,04045'ten küçük ya da ona eşitse 12,92'ye bölünür; değilse 0,055 eklenir, 1,055'e bölünür ve sonuç 2,4 üssüne yükseltilir. Bu işlem, WCAG'ın göreli parlaklık tanımında da aynen yer alır. Ters yönde, doğrusal değerden kodlanmış değere dönmek için eğri ters çevrilir: 0,0031308'den küçük değerler 12,92 ile çarpılır, büyükler 1/2,4'üncü kuvvete yükseltilip 1,055 ile çarpılır ve 0,055 çıkarılır.
Kartın sorusu burada cevap bulur: gamma kodunu çözmeden matris dönüşümü yapmak neden hatalı sonuç verir?
Matris dönüşümü doğrusal bir işlemdir: XYZ'nin her bileşeni, üç kanalın belirli katsayılarla çarpılıp toplanmasıyla bulunur. Bu toplama, ışık miktarları için anlamlıdır; iki ışığın toplamı, ışıkların miktarlarının toplamıdır. Kodlanmış değerler ise ışık miktarı değildir, eğriden geçmiş sayılardır. Matris bu sayılara uygulandığında, ışığı toplamak yerine eğrilmiş sayıları toplar ve sonuç, fiziksel olarak hiçbir ışığa karşılık gelmez.
Hatanın büyüklüğü hesapla görülür. Orta gri, #808080, doğru hesapta CIELAB'da 53,6 açıklık verir; gamma kodu çözülmeden hesaplanırsa 76,2 verir. Bir ten tonu olan #8D5524 doğru hesapta 41,7, hatalı hesapta 67,0 açıklıktadır. Hata koyu renklerde en büyüktür: #4A2C1D doğru hesapta 21,4, hatalı hesapta 51,1 açıklık verir; yanağı #F1C7A9 tonundaki açık bir yüzde ise hata 83,1'e karşı 92,0'dır.
| Renk | Doğru L* | Kodu çözülmeden L* | Hata |
|---|---|---|---|
| #F1C7A9 | 83,1 | 92,0 | +8,9 |
| #808080 | 53,6 | 76,2 | +22,6 |
| #8D5524 | 41,7 | 67,0 | +25,3 |
| #4A2C1D | 21,4 | 51,1 | +29,7 |
Bu tablonun bir sonucu, renk ölçen bir yazılımı yazan herkes için önemlidir. Görüntülerdeki ten tonlarını ölçen, bir kamera ayarını farklı tenlerde sınayan ya da bir yüz fotoğrafının pozlamasını değerlendiren bir kodda bu hata yapılırsa, en büyük sapma en koyu tenlerde ortaya çıkar. Koyu tenler olduklarından çok daha açık ölçülür ve bütün analiz, açık tenlerde küçük, koyu tenlerde büyük bir hatayla eşitsiz biçimde bozulur. Gamma kodunu doğru çözmek, bu yüzden yalnız teknik bir doğruluk değil, farklı tenlere eşit davranan bir ölçümün ön koşuludur.
Matris dönüşümleri
sRGB için doğrusal RGB'den XYZ'ye giden matris, sRGB'nin ana renklerinin kromatiklik koordinatlarından ve D65 beyaz noktasından hesaplanır. Bruce Lindbloom'un renk bilimi sayfalarında verilen değerlerle bu matrisin ilk satırı 0,4124564, 0,3575761 ve 0,1804375; ikinci satırı 0,2126729, 0,7151522 ve 0,0721750; üçüncü satırı 0,0193339, 0,1191920 ve 0,9503041'dir. İkinci satırın EK-02'deki göreli parlaklık katsayılarıyla neredeyse aynı olduğuna dikkat edin: XYZ'nin Y bileşeni zaten göreli parlaklıktır.
Kodda bu matrisin doğru yazıldığını sınamanın basit bir yolu vardır: matris, doğrusal değerleri 1, 1, 1 olan beyaza uygulandığında sonuç D65 beyaz noktası olmalıdır. Hesap bunu verir: X 0,95047, Y 1,00000, Z 1,08883. Ters matris ise XYZ'den doğrusal RGB'ye dönüşü yapar ve iki matrisin çarpımı birim matrise yakın çıkmalıdır.
Beyaz nokta ve kromatik uyarlama
EK-13'te ICC profil bağlantı uzayının D50 beyazını kullandığını gördük. sRGB'den gelen bir renk bu uzaya taşınacaksa, D65'e göre hesaplanmış XYZ değerleri D50'ye uyarlanmalıdır. Aksi hâlde sRGB'nin beyazı, D50 uzayında hafif mavimsi bir renk gibi görünür. Yaygın yöntemlerden biri Bradford dönüşümüdür: XYZ önce bir matrisle koni tepkisine benzer bir uzaya taşınır, orada iki beyaz noktasının oranıyla ölçeklenir ve ters matrisle geri getirilir.
Kodda sınaması yine basittir: D65 beyazı Bradford uyarlamasından geçirildiğinde D50 beyazına, yaklaşık X 0,9642, Y 1,0000, Z 0,8252'ye ulaşmalıdır. #8D5524 tonunun D65'e göre hesaplanmış XYZ değerleri, 0,1455, 0,1229 ve 0,0327, uyarlamadan sonra 0,1537, 0,1255 ve 0,0251 olur; CIELAB'da D50'ye göre açıklığı 42,1'dir, D65'teki 41,7'ye çok yakın, ama a ve b bileşenleri biraz değişir. Beyaz noktasını karıştıran bir kod, bu küçük farkları sistematik bir renk kaymasına dönüştürür.
XYZ'den CIELAB'a ve OKLab'e
CIELAB'a geçiş, XYZ değerlerinin beyaz noktasına bölünmesi, küp kökünün alınması ve ölçeklenmesiyle yapılır; siyaha çok yakın değerlerde küp kök yerine doğrusal bir parça kullanılır. Bu parçanın eşiği ve eğimi, CIE'nin kolorimetri önerilerinde tanımlıdır ve kodda sıklıkla atlanan bir ayrıntıdır.
OKLab'e geçiş, Björn Ottosson'un 2020'de yayımladığı tanımı izler: XYZ önce bir matrisle koni benzeri bir uzaya taşınır, her bileşenin küp kökü alınır ve ikinci bir matrisle OKLab'in açıklık ve iki renk ekseni elde edilir. Ottosson, yazısında uygulamaların sınanması için bir test değeri tablosu da verir.
| X | Y | Z | Beklenen L | Beklenen a | Beklenen b |
|---|---|---|---|---|---|
| 0,950 | 1,000 | 1,089 | 1,000 | 0,000 | 0,000 |
| 1,000 | 0,000 | 0,000 | 0,450 | 1,236 | −0,019 |
| 0,000 | 1,000 | 0,000 | 0,922 | −0,671 | 0,263 |
| 0,000 | 0,000 | 1,000 | 0,153 | −1,415 | −0,449 |
Bu dersteki hesaplar için yazılan kod, dört test değerinin dördünü de üç ondalıkta birebir verir. Test tablosunun yanında ikinci bir sınama daha kolaydır: gidiş–dönüş testi. Bir renk hattın sonuna kadar götürülüp ters yönde geri getirildiğinde, başlangıçtaki 8 bitlik değerler yuvarlama farkı dışında aynen geri gelmelidir; gelmiyorsa bir durakta ters işlem yanlış yazılmıştır. Bir test tablosunu geçmek, kodun her girdi için doğru olduğunu kanıtlamaz; ama matrislerin yanlış yazılması, sıranın karıştırılması ya da bir küp kökün unutulması gibi en yaygın hataları hemen ortaya çıkarır.
Açık kaynak kütüphaneler
Gerçek bir projede bu hattı sıfırdan yazmak yerine, olgun bir kütüphane kullanmak çoğu zaman daha güvenlidir. Python'da colour-science, renk bilimi dönüşümlerini geniş bir kapsamla sunar; colorspacious, VG-07'de renk görme benzetimi için kullandığımız gibi, algısal uzaylara odaklanır. JavaScript'te culori ve colorjs.io, web için renk uzayı dönüşümleri ve CSS renk sözdizimi desteği sunar. Kütüphane kullanmak, bu derste anlatılanları bilme ihtiyacını ortadan kaldırmaz: bir kütüphanenin hangi beyaz noktasını varsaydığını, girdiyi kodlanmış mı doğrusal mı beklediğini ve hangi CIELAB tanımını kullandığını bilmeden alınan sonuç, aynı hataları sessizce yapabilir.
İyi bir uygulama, kendi kodunu ya da seçilen kütüphaneyi yayımlanmış test değerleriyle sınamak ve iki bağımsız yolla, örneğin kendi kodu ile bir kütüphaneyle, aynı rengi hesaplayıp sonuçları karşılaştırmaktır.
Örnek — bir kamera testi için ten ölçümü
Bir ekip, bir telefon kamerasının otomatik pozlamasının açık ve koyu yüzlerde aynı ölçüde isabetli olup olmadığını ölçmek istiyor. Çekilen fotoğraflardaki yanak bölgelerinin ortalama rengi alınacak ve CIELAB açıklığı, aynı kişilerin kontrollü ışıkta ölçülmüş referans değerleriyle karşılaştırılacak.
Ekibin ilk betiği, piksellerin 8 bitlik değerlerini 255'e bölüp doğrudan XYZ matrisiyle çarpıyor. Sonuçlar tuhaf: açık tenlerde küçük, koyu tenlerde çok büyük bir «aşırı pozlama» görünüyor. Kamera koyu tenleri olduklarından çok daha açık gösteriyormuş gibi. Oysa hata kamerada değil betikte: gamma kodu çözülmediği için, yukarıdaki tabloda görüldüğü gibi, koyu bir ten yaklaşık 30 birim daha açık ölçülüyor.
Ekip betiği düzeltiyor. Ortalama, 8 bitlik değerler üzerinden değil, doğrusal ışığa açıldıktan sonra alınıyor, çünkü EK-05'te gördüğümüz gibi ışık ortalamaları doğrusal uzayda alınmalıdır. Dönüşüm hattı Ottosson'un test değerleriyle ve bağımsız bir kütüphaneyle karşılaştırılarak sınanıyor. Sonuçta kameranın gerçek davranışı ortaya çıkıyor ve hata payları, en açıktan en koyuya bütün tenlerde aynı ölçüm yöntemiyle değerlendiriliyor.
Sık yapılan yanlış
Yaygın yanlış"8 bitlik değerleri 255'e bölmek, rengi doğrusal hâle getirir."
255'e bölmek yalnız ölçeği 0–1 aralığına getirir; değerler hâlâ aktarım eğrisinden geçmiş kodlanmış sayılardır ve doğrusal ışığa açılmak için eğrinin tersi uygulanmalıdır.
Yaygın yanlış"Bir kütüphane kullanıyorsam dönüşümün ayrıntılarını bilmem gerekmez."
Kütüphanenin hangi beyaz noktasını varsaydığını, girdiyi kodlanmış mı doğrusal mı beklediğini ve hangi tanımları kullandığını bilmeden alınan sonuç aynı hataları sessizce yapabilir; sonuçlar test değerleriyle sınanmalıdır.
Özet
- sRGB'den OKLab'e giden hat sırası değiştirilemeyen duraklardan oluşur: 255'e bölme, gamma kodunu çözme, 3×3 matrisle XYZ'ye geçme, gerekiyorsa beyaz nokta uyarlaması ve hedef uzaya geçiş.
- Gamma kodunu çözmeden matris uygulamak, ışık yerine eğrilmiş sayıları toplar; hata koyu renklerde en büyüktür ve koyu bir ten 21 yerine 51 açıklıkta ölçülür, bu da farklı tenleri eşitsiz biçimde bozan bir ölçüme yol açar.
- Beyaz noktalar D65 ile D50 arasında Bradford gibi bir yöntemle uyarlanır; yazılan kod ya da kullanılan kütüphane, Ottosson'un OKLab tablosu gibi yayımlanmış test değerleriyle ve bağımsız bir hesapla sınanır.
Kendini sına
- (Kolay) sRGB'den XYZ'ye giden bir dönüşüm hattının ilk üç durağı nedir?
- (Kolay) sRGB'nin ve ICC profil bağlantı uzayının beyaz noktaları nedir?
- (Orta) Gamma kodunu çözmeden matris dönüşümü yapmak neden hatalı sonuç verir?
- (Orta) sRGB'den XYZ'ye matrisin doğru yazıldığı en basit hangi yolla sınanabilir?
- (Zor) Gamma kodunu çözmeden yapılan dönüşümde hata neden koyu renklerde en büyüktür ve bu, farklı tenleri ölçen bir yazılım için ne anlama gelir?
- (Zor) Bir kütüphane kullanan ekip, sonuçlarının doğru olduğundan nasıl emin olabilir?
Cevaplar
- 8 bitlik değerleri 255'e bölmek, aktarım eğrisini tersine çevirerek doğrusal ışığa açmak ve 3×3 matrisle XYZ'ye geçmek («Bir dönüşüm hattı»).
- sRGB için D65, ICC profil bağlantı uzayı için D50 («Beyaz nokta ve kromatik uyarlama»).
- Matris dönüşümü ışık miktarlarını katsayılarla çarpıp toplayan doğrusal bir işlemdir; kodlanmış değerler ise ışık miktarı değil eğriden geçmiş sayılardır. Matris onlara uygulanınca fiziksel hiçbir ışığa karşılık gelmeyen bir sonuç verir; orta gri 53,6 yerine 76,2 açıklıkta ölçülür («Gamma kodunu çözmek»).
- Matrisi doğrusal değerleri 1, 1, 1 olan beyaza uygulamak; sonuç D65 beyaz noktası, yaklaşık X 0,95047, Y 1, Z 1,08883 olmalıdır («Matris dönüşümleri»).
- Aktarım eğrisi koyu değerleri en çok büker; bu yüzden kodlanmış bir koyu değer ile gerçek ışık miktarı arasındaki fark en büyüktür. #4A2C1D 21,4 yerine 51,1, #F1C7A9 ise 83,1 yerine 92,0 açıklıkta ölçülür. Farklı tenleri ölçen bir yazılım, koyu tenleri olduklarından çok daha açık ölçer ve hatası tenlere göre eşitsiz dağılır («Gamma kodunu çözmek», «Örnek — bir kamera testi için ten ölçümü»).
- Kütüphanenin varsaydığı beyaz noktasını, girdiyi kodlanmış mı doğrusal mı beklediğini ve kullandığı tanımları bilmek; sonuçları Ottosson'un tablosu gibi yayımlanmış test değerleriyle sınamak ve aynı rengi bağımsız bir yolla, örneğin kendi koduyla, hesaplayıp karşılaştırmak («Açık kaynak kütüphaneler»).
Kaynaklar
- Björn Ottosson, «A perceptual color space for image processing», 23 Aralık 2020.
- Bruce Lindbloom, «RGB/XYZ Matrices» ve «Chromatic Adaptation», brucelindbloom.com.
- W3C, «Web Content Accessibility Guidelines (WCAG) 2.2», relative luminance tanımı.
- CIE 015:2018, «Colorimetry», 4. baskı.
- colour-science, colorspacious, culori ve colorjs.io açık kaynak renk kütüphaneleri.
Sonraki adım
RH-04 hesaplardan tarihe dönüyor: sarının bir yerde kutsallığın, başka bir yerde tehlikenin ve dikkat çağrısının rengi olmasının nasıl mümkün olduğunu, aynı ton ailesinin kültürler ve yüzyıllar boyunca taşıdığı çelişkili anlamlar üzerinden anlatıyor. RH-05 ise bir rengin toplumsal konumunun nasıl değiştiğine bakıyor: bir deniz salyangozundan elde edilen pahalı bir boyadan bir kimyacının laboratuvarına uzanan yolda morun nasıl herkesin erişebileceği bir renge dönüştüğünü izliyor.