Apa sifat dasar dari ruang RGB linier dan apa sifat dasar ruang RGB non-linier? Ketika berbicara tentang nilai di dalam setiap saluran dalam 8 (atau lebih) bit tersebut, apa yang berubah?
Di OpenGL, warna adalah nilai 3 + 1, dan dengan ini maksud saya RGB + alpha, dengan 8 bit dicadangkan untuk setiap saluran, dan ini adalah bagian yang saya dapatkan dengan jelas.
Tetapi ketika datang ke koreksi gamma, saya tidak mengerti apa efek bekerja di ruang RGB non-linier.
Karena saya tahu cara menggunakan kurva dalam perangkat lunak grafis untuk pengeditan foto, penjelasan saya adalah bahwa dalam ruang RGB linier Anda mengambil nilai apa adanya, tanpa manipulasi dan tidak ada fungsi matematika yang terpasang, alih-alih ketika itu non-linier masing-masing saluran biasanya berkembang mengikuti perilaku fungsi daya klasik.
Kalaupun saya menganggap penjelasan ini sebagai yang asli, saya masih belum mengerti apa itu ruang linier nyata, karena setelah perhitungan semua ruang RGB non-linier menjadi linier dan yang terpenting dari semua saya tidak mendapatkan bagian di mana non -Ruang warna linier lebih cocok untuk mata manusia karena pada akhirnya semua ruang RGB linier untuk apa yang saya pahami.
Jawaban:
Katakanlah Anda bekerja dengan warna RGB: setiap warna diwakili dengan tiga intensitas atau kecerahan. Anda harus memilih antara "RGB linier" dan "sRGB". Untuk saat ini, kami akan menyederhanakan berbagai hal dengan mengabaikan tiga intensitas berbeda, dan menganggap Anda hanya memiliki satu intensitas: yaitu, Anda hanya berurusan dengan bayangan abu-abu.
Dalam ruang warna linier, hubungan antara angka yang Anda simpan dan intensitas yang direpresentasikannya adalah linier. Secara praktis, ini berarti bahwa jika Anda menggandakan angkanya, Anda menggandakan intensitas (kecerahan abu-abu). Jika Anda ingin menambahkan dua intensitas bersamaan (karena Anda menghitung intensitas berdasarkan kontribusi dua sumber cahaya, atau karena Anda menambahkan objek transparan di atas objek buram), Anda dapat melakukannya hanya dengan menambahkan dua angka bersama. Jika Anda melakukan pencampuran 2D atau bayangan 3D, atau hampir semua pemrosesan gambar, Anda ingin intensitas Anda dalam ruang warna linier., jadi Anda bisa menambah, mengurangi, mengalikan, dan membagi angka untuk mendapatkan efek yang sama pada intensitas. Sebagian besar algoritme pemrosesan dan rendering warna hanya memberikan hasil yang benar dengan RGB linier, kecuali Anda menambahkan bobot ekstra pada semuanya.
Kedengarannya sangat mudah, tapi ada masalah. Kepekaan mata manusia terhadap cahaya lebih baik pada intensitas rendah daripada intensitas tinggi. Artinya, jika Anda membuat daftar semua intensitas yang dapat Anda bedakan, ada lebih banyak intensitas gelap daripada yang terang. Dengan kata lain, Anda dapat membedakan warna abu-abu gelap lebih baik daripada warna abu-abu terang. Secara khusus, jika Anda menggunakan 8 bit untuk mewakili intensitas Anda, dan Anda melakukan ini dalam ruang warna linier, Anda akan mendapatkan terlalu banyak bayangan terang, dan tidak cukup bayangan gelap. Anda mendapatkan garis melintang di area gelap Anda, sementara di area terang Anda, Anda membuang-buang bit pada berbagai nuansa hampir putih yang tidak dapat dibedakan oleh pengguna.
Untuk menghindari masalah ini, dan memanfaatkan 8 bit tersebut dengan sebaik-baiknya, kami cenderung menggunakan sRGB . Standar sRGB memberi tahu Anda kurva yang akan digunakan, untuk membuat warna Anda non-linier. Kurva lebih dangkal di bagian bawah, sehingga Anda dapat memiliki lebih banyak abu-abu gelap, dan lebih curam di bagian atas, sehingga Anda memiliki lebih sedikit abu-abu terang. Jika Anda menggandakan angkanya, Anda akan menggandakan intensitasnya. Ini berarti bahwa jika Anda menambahkan warna sRGB bersamaan, Anda akan mendapatkan hasil yang lebih terang dari yang seharusnya. Saat ini, sebagian besar monitor menafsirkan warna input mereka sebagai sRGB. Jadi, saat Anda meletakkan warna di layar, atau menyimpannya dalam tekstur 8-bit-per-saluran, simpan sebagai sRGB , sehingga Anda dapat memanfaatkan 8 bit tersebut dengan sebaik-baiknya.
Anda akan melihat kami sekarang memiliki masalah: kami ingin warna kami diproses dalam ruang linier, tetapi disimpan dalam sRGB. Ini berarti Anda akhirnya melakukan konversi sRGB-ke-linier saat dibaca, dan konversi linier-ke-sRGB saat tulis. Seperti yang telah kita katakan bahwa intensitas 8-bit linier tidak memiliki cukup gelap, ini akan menimbulkan masalah, jadi ada satu aturan praktis lagi: jangan gunakan warna linier 8-bit jika Anda dapat menghindarinya. Menjadi konvensional untuk mengikuti aturan bahwa warna 8-bit selalu sRGB, jadi Anda melakukan konversi sRGB-ke-linier pada saat yang sama dengan memperluas intensitas Anda dari 8 menjadi 16 bit, atau dari integer ke floating-point; demikian pula, setelah Anda menyelesaikan pemrosesan floating-point, Anda mempersempit menjadi 8 bit pada saat yang sama dengan mengonversi ke sRGB. Jika Anda mengikuti aturan ini,
Saat Anda membaca gambar sRGB, dan Anda menginginkan intensitas linier, terapkan rumus ini ke setiap intensitas:
Sebaliknya, saat Anda ingin menulis gambar sebagai sRGB, terapkan rumus ini ke setiap intensitas linier:
Dalam kedua kasus, nilai floating-point berkisar dari 0 hingga 1, jadi jika Anda membaca bilangan bulat 8-bit, Anda ingin membagi dengan 255 terlebih dahulu, dan jika Anda menulis bilangan bulat 8-bit, Anda ingin mengalikan dengan 255 terakhir, dengan cara yang sama seperti biasanya. Itu saja yang perlu Anda ketahui untuk bekerja dengan sRGB.
Sampai sekarang, saya hanya berurusan dengan satu intensitas, tetapi ada hal-hal cerdas yang berkaitan dengan warna. Mata manusia dapat membedakan kecerahan yang berbeda dengan lebih baik daripada warna yang berbeda (secara teknis, ini memiliki resolusi luminansi yang lebih baik daripada chrominance), sehingga Anda dapat menggunakan 24 bit Anda dengan lebih baik dengan menyimpan kecerahan secara terpisah dari warnanya. Inilah yang coba dilakukan oleh representasi YUV, YCrCb, dll. Saluran Y adalah kecerahan warna keseluruhan, dan menggunakan lebih banyak bit (atau memiliki resolusi spasial lebih banyak) daripada dua saluran lainnya. Dengan cara ini, Anda tidak (selalu) perlu menerapkan kurva seperti yang Anda lakukan dengan intensitas RGB. YUV adalah ruang warna linier, jadi jika Anda menggandakan angka di saluran Y, Anda menggandakan kecerahan warna, tetapi Anda tidak dapat menambahkan atau mengalikan warna YUV bersama-sama seperti yang Anda bisa dengan warna RGB, jadi '
Saya pikir itu menjawab pertanyaan Anda, jadi saya akan mengakhiri dengan catatan sejarah singkat. Sebelum sRGB, CRT lama biasanya memiliki non-linearitas yang tertanam di dalamnya. Jika Anda menggandakan tegangan untuk satu piksel, Anda akan melipatgandakan intensitas. Berapa banyak lagi yang berbeda untuk setiap monitor, dan parameter ini disebut gamma . Perilaku ini berguna karena itu berarti Anda bisa mendapatkan lebih banyak kegelapan daripada cahaya, tetapi itu juga berarti Anda tidak dapat mengetahui seberapa terang warna Anda pada CRT pengguna, kecuali Anda mengkalibrasi terlebih dahulu. Koreksi gammaberarti mengubah warna yang Anda mulai (mungkin linier) dan mengubahnya untuk gamma CRT pengguna. OpenGL berasal dari era ini, itulah sebabnya perilaku sRGB-nya terkadang sedikit membingungkan. Tetapi vendor GPU sekarang cenderung bekerja dengan konvensi yang saya jelaskan di atas: bahwa ketika Anda menyimpan intensitas 8-bit dalam tekstur atau framebuffer, itu adalah sRGB, dan saat Anda memproses warna, itu linier. Misalnya, OpenGL ES 3.0, setiap framebuffer dan tekstur memiliki "tanda sRGB" yang dapat Anda aktifkan untuk mengaktifkan konversi otomatis saat membaca dan menulis. Anda tidak perlu secara eksplisit melakukan konversi sRGB atau koreksi gamma sama sekali.
sumber
Saya bukan "ahli pendeteksi warna manusia", tetapi saya telah menemukan hal serupa pada konversi YUV-> RGB. Ada bobot yang berbeda untuk saluran R / G / B, jadi jika Anda mengubah warna sumber dengan x, nilai RGB mengubah kuantitas yang berbeda.
Seperti yang dikatakan, saya bukan ahli, bagaimanapun, saya pikir, jika Anda ingin melakukan transformasi warna-benar, Anda harus melakukannya di ruang YUV, lalu mengubahnya menjadi RGB (atau melakukan operasi yang setara secara matematis pada RGB, waspadalah kehilangan data). Selain itu, saya tidak yakin YUV adalah representasi warna asli terbaik, tetapi kamera video menyediakan format itu, di situlah saya menemukan masalah.
Berikut adalah rumus ajaib YUV-> RGB dengan nomor rahasia yang disertakan: http://www.fourcc.org/fccyvrgb.php
sumber