RGB renklerle çalıştığınızı varsayalım: her renk üç yoğunluk veya parlaklık ile temsil edilir . "Doğrusal RGB" ve "sRGB" arasında seçim yapmalısınız. Şimdilik, üç farklı yoğunluğu görmezden gelerek işleri basitleştireceğiz ve tek bir yoğunluğa sahip olduğunuzu varsayacağız: yani, yalnızca grinin tonlarıyla uğraşıyorsunuz.
Doğrusal bir renk uzayında, depoladığınız sayılarla temsil ettikleri yoğunluklar arasındaki ilişki doğrusaldır. Pratikte bu, sayıyı ikiye katlarsanız yoğunluğu (grinin açıklığını) ikiye katlarsınız demektir. İki yoğunluğu birbirine eklemek istiyorsanız (iki ışık kaynağının katkılarına göre bir yoğunluğu hesapladığınız için veya opak bir nesnenin üzerine saydam bir nesne eklediğiniz için), bunu yalnızca birlikte iki numara. Herhangi bir tür 2B harmanlama veya 3B gölgeleme ya da neredeyse her türlü görüntü işleme yapıyorsanız, yoğunluklarınızı doğrusal bir renk alanında istersiniz., böylece yoğunluklar üzerinde aynı etkiye sahip olmak için sayıları toplayabilir, çıkarabilir, çarpabilir ve bölebilirsiniz. Çoğu renk işleme ve işleme algoritması, her şeye fazladan ağırlık eklemediğiniz sürece yalnızca doğrusal RGB ile doğru sonuçlar verir.
Kulağa çok kolay geliyor ama bir sorun var. İnsan gözünün ışığa duyarlılığı, düşük yoğunluklarda yüksek yoğunluklara göre daha incedir. Yani, ayırt edebileceğiniz tüm yoğunlukların bir listesini yaparsanız, hafif olanlardan daha karanlık olanlar vardır. Başka bir deyişle, grinin koyu tonlarını, açık grinin tonlarıyla yapabileceğinizden daha iyi ayırt edebilirsiniz. Özellikle, yoğunluğunuzu temsil etmek için 8 bit kullanıyorsanız ve bunu doğrusal bir renk alanında yaparsanız, çok fazla açık gölgeyle ve yeterli koyu gölgeyle karşılaşmazsınız. Karanlık alanlarınızda şeritlenme olurken, açık alanlarınızda, kullanıcının ayırt edemeyeceği beyaza yakın farklı tonlardaki bitleri boşa harcarsınız.
Bu sorunu önlemek ve bu 8 biti en iyi şekilde kullanmak için sRGB kullanma eğilimindeyiz . SRGB standardı, renklerinizi doğrusal olmayan hale getirmek için kullanabileceğiniz bir eğri söyler. Eğri, altta daha sığdır, böylece daha koyu griler ve üstte daha dik olabilir, böylece daha az açık gri elde edersiniz. Sayıyı ikiye katlarsanız, yoğunluğu iki katından daha fazla hissedersiniz. Bu, sRGB renklerini birlikte eklerseniz olması gerekenden daha açık bir sonuç elde edeceğiniz anlamına gelir. Bugünlerde çoğu monitör giriş renklerini sRGB olarak yorumluyor. Dolayısıyla, ekrana bir renk koyduğunuzda veya bunu kanal başına 8 bitlik bir dokuda saklarken, sRGB olarak saklayın , böylece bu 8 bitten en iyi şekilde yararlanın.
Şimdi bir sorunumuz olduğunu fark edeceksiniz: renklerimizin doğrusal uzayda işlenmesini, ancak sRGB'de saklanmasını istiyoruz. Bu, okumada sRGB'den lineer dönüşüme ve yazma sırasında lineerden sRGB'ye dönüşüm yapacağınız anlamına gelir. Doğrusal 8 bit yoğunlukların yeterli koyuluğa sahip olmadığını daha önce söylediğimiz gibi, bu sorunlara neden olur, bu yüzden bir pratik kural daha var: eğer kaçınabiliyorsanız 8 bit doğrusal renkler kullanmayın . 8 bit renklerin her zaman sRGB olduğu kuralını takip etmek geleneksel hale geliyor, bu nedenle sRGB'den lineer dönüşümünüzü, yoğunluğunuzu 8'den 16 bit'e veya tam sayıdan kayan noktaya genişletirken aynı anda yaparsınız; benzer şekilde, kayan nokta işlemenizi bitirdiğinizde, sRGB'ye dönüştürürken aynı anda 8 bite daraltırsınız. Bu kurallara uyarsanız,
Bir sRGB görüntüsü okurken ve doğrusal yoğunluklar istiyorsanız, bu formülü her yoğunluğa uygulayın:
float s = read_channel();
float linear;
if (s <= 0.04045) linear = s / 12.92;
else linear = pow((s + 0.055) / 1.055, 2.4);
Diğer taraftan, bir görüntüyü sRGB olarak yazmak istediğinizde, bu formülü her doğrusal yoğunluğa uygulayın:
float linear = do_processing();
float s;
if (linear <= 0.0031308) s = linear * 12.92;
else s = 1.055 * pow(linear, 1.0/2.4) - 0.055; ( Edited: The previous version is -0.55 )
Her iki durumda da, kayan noktanın değeri 0 ile 1 arasındadır, bu nedenle 8 bitlik tam sayıları okuyorsanız önce 255'e bölmek istersiniz ve 8 bitlik tam sayılar yazıyorsanız 255 ile çarpmak istersiniz. son olarak, genellikle yaptığınız gibi. SRGB ile çalışmak için bilmeniz gereken tek şey bu.
Şimdiye kadar sadece tek bir yoğunlukla uğraştım, ancak renklerle yapılacak daha akıllıca şeyler var. İnsan gözü, farklı parlaklıkları farklı renk tonlarından daha iyi ayırt edebilir (daha teknik olarak, krominanstan daha iyi parlaklık çözünürlüğüne sahiptir), böylece parlaklığı renk tonundan ayrı olarak depolayarak 24 bitinizi daha da iyi kullanabilirsiniz. YUV, YCrCb, vb. Temsillerin yapmaya çalıştığı şey budur. Y kanalı, rengin genel açıklığıdır ve diğer iki kanaldan daha fazla bit kullanır (veya daha fazla uzamsal çözünürlüğe sahiptir). Bu şekilde, RGB yoğunluklarında yaptığınız gibi (her zaman) bir eğri uygulamanıza gerek kalmaz. YUV doğrusal bir renk uzayıdır, bu nedenle Y kanalındaki sayıyı ikiye katlarsanız, rengin açıklığını ikiye katlarsınız, ancak RGB renklerinde olduğu gibi YUV renklerini ekleyemez veya çoğaltamazsınız.
Sanırım bu, sorunuzu yanıtlıyor, bu yüzden kısa bir tarihi notla bitireceğim. SRGB'den önce, eski CRT'ler içlerinde doğrusal olmayan bir yapıya sahipti. Bir piksel için voltajı ikiye katlarsanız, yoğunluğu iki katından daha fazla yaparsınız. Her monitör için daha ne kadar farklıydı ve bu parametre gama olarak adlandırıldı . Bu davranış yararlıydı, çünkü ışıklardan daha fazla koyuluk elde edebileceğiniz anlamına geliyordu, ancak aynı zamanda, önce kalibre etmedikçe, kullanıcının CRT'sinde renklerinizin ne kadar parlak olacağını söyleyemeyeceğiniz anlamına geliyordu. Gamma düzeltmesiBaşladığınız renkleri (muhtemelen doğrusal) dönüştürmek ve bunları kullanıcının CRT'sinin gamasına dönüştürmek anlamına gelir. OpenGL bu çağdan geliyor, bu yüzden sRGB davranışı bazen biraz kafa karıştırıcı oluyor. Ancak GPU satıcıları artık yukarıda anlattığım konvansiyonla çalışma eğilimindedir: bir doku veya çerçeve tamponunda 8 bitlik bir yoğunluğu depoladığınızda, bu sRGB'dir ve renkleri işlerken doğrusaldır. Örneğin, bir OpenGL ES 3.0, her çerçeve arabelleği ve doku, okurken ve yazarken otomatik dönüştürmeyi etkinleştirmek için açabileceğiniz bir "sRGB bayrağı" içerir. Açıkça sRGB dönüşümü veya gama düzeltmesi yapmanız gerekmez.