Barva
Každý pixel je v bitmapovém souboru reprezentován určitým počtem bitů. Tím je určen počet barev, které může daný pixel nabýt. Je-li počet bitů na pixel, je možno zobrazit barev. Dvouúrovňová (jednobitová) zařízení dovolují zobrazovat dvě úrovně (monochromatické monitory, jehličkové tiskárny). Lidské oko má konečný počet barevných receptorů, které obsáhnou rozsah světelných frekvencí 380-770 nm. Tvrdí se, že lidské oko dovede rozeznat až deset milionů barev (přesný počet se v individuálních případech samozřejmě liší). Zařízení, které je schopno zobrazit 224 = 16 777 216 barev, považujeme proto za true color (pravé barvy). True color zařízení tedy potřebuje 24 = 3*8 bitů = 3byty na pixel. V minulosti byla termínem true color označována i zařízení o 15 resp 16 bitech na pixel (32768 resp. 65536 barev).
Nejčastěji sestrojovanými útvary na výstupním zařízení jsou digitalizovaný bod – pixel, dále digitalizovaná úsečka a digitalizovaná kružnice, resp. její oblouk.
Na většině digitálních zařízení
se na jednotlivé pixely odkazujeme pomocí světové souřadné soustavy. Oproti
zvyklostem analytické geometrie bývá počátek umístěn vlevo nahoře, „osa y“ je
tak orientována shora dolů. Bod, úsečka i kružnice přitom patří mezi tzv.
primitiva, tj. útvary, které lze sestrojit pomocí procedur dodávaných přímo
s jednotlivými grafickými systémy. Například v Delphi jsou objekty, v
nichž je možno provádět grafické konstrukce, vybaveny objektem Canvas – což je
model výše definované digitální roviny. Tento objekt obsahuje objekt Pixels –
matici pixelů, kterým je možné přiřazovat hodnoty – barvy. Například příkaz
Canvas. Pixels[100,150]:= clBlack {colorBlack} obarví černě bod o světových souřadnicích
[100,150]. Konstanta clBlack je předdefinována, podobně jako konstanty
představující další „běžné barvy“ – clWhite, clYellow, atd. Kreslicí plocha je
inicializována jako bílá. Digitální úsečka je realizována dvojicí metod Canvas.MoveTo(x,y)
a Canvas.LineTo(x,y).
První z nich přesouvá „zvednuté kreslící pero“ (objekt Canvas.Pen)
do bodu o specifikovaných světových souřadnicích, druhý činí totéž s „perem
spuštěným“. Podobně je možno sestrojit např. elipsu metodou Ellipse(x1,y1,x2,y2).
Parametry této metody definují úhlopříčku obdélníka s vodorovnými resp.
svislými stranami, do kterých se má elipsa vepsat (je-li takto definován
čtverec, výsledkem je samozřejmě kružnice).
Barvy v osmibitové
hloubce
Pro „běžného uživatele“ těchto
systémů, který je používá k nenáročným grafickým konstrukcím, tento
přístup většinou postačuje. K náročným konstrukcím je však třeba
přistupovat zcela jinak. Přinejmenším je potřeba jinak přistupovat
k barvám. Předdefinovaných odstínů je k dispozici šestnáct a výše uvedený
způsob naprosto neumožňuje např. generovat barevné odstíny potřebné pro
obrazovou analýzu či stínování objektů. Také používání výše uvedených
„předdefinovaných metod“ ke konstrukci primitiv digitální roviny je
problematické. Je sice teoreticky možné, prakticky však mnohdy značně neúnosné.
Při náročných konstrukcích není vyjímkou, že tato primitiva je třeba
sestrojovat řádově stotisíckrát či milionkrát a v těchto případech se
ukazuje, že tyto metody jsou značně pomalé. Algoritmus konstrukce těchto
objektů implementovaný v grafickém systému není znám, neboť tyto konstrukce
bývají předmětem firemních tajemství, jejich kvalitu tedy posuzovat nelze.
Faktem však je že „přehlednost“, „intuitivní zřejmost“ a „programátorské
pohodlí“ běžného uživatele je draze zaplaceno už jen komplikovaným a tím značně
pomalým přístupem k objektu, do kterého se má vlastně kreslit. Například
každá tečka odkazující na zděděný objekt, vlastnost či metodu znamená
přesměrování ukazatele při jeho hledání v programu. Např. v příkazu Image1.Picture.Bitmap.Canvas.Pixels[i,j]:= to
znamená, že k nalezení matice Pixels musí program vždy „projít“ čtyři
adresy a až na páté se dopátrá objektu, do kterého přiřazuje. Čím je
programátorovo pohodlí větší, tím jsou i objekty rozsáhlejší a komplikovanější
a tím komplikovanější je i každé hledání, které se při konstrukci každého
dalšího objektu (v tomto případě bodu) opakuje. Navíc (zřejmě z důvodů
kompatibility) jsou tyto barvy deklarovány jako DWord, tedy jako
dvaatřicetibitové objekty, přestože při tomto přístupu je k dispozici pouze šestnáct
barev a stačily by pouze čtyři bity. Podstatně rychlejší (i když poněkud
komplikovanější) konstrukce bodu spočívá v přímém přístupu do bitmapy. Zde
si ukážeme přístup osmibitový, pixel výstupního zařízení budeme obarvovat
barvou .
Nejdříve je třeba deklarovat jednotlivé barvy jako konstanty:
const
slBlack =0;
slMaroon =1;
slGreen =2;
slOlive =3;
slNavy =4;
slPurple =5;
slTeal =6;
slGray =12;
slSilver =7;
slRed =13;
slLime =14;
slYellow
=15;
slBlue =16;
slFuchsia
=17;
slAqua =18;
slWhite =19;
Tyto
barvy jsou osmibitové. Jejich názvy (např. scanlineAqua) jsem volil odlišně od standardních názvů
označující čtyřiadvacetibitové barevné konstanty v Borland Delphi (colorAqua). Nedojde tak k předefinování a obojí sadu je možno
používat současně - standardní barvy při práci s objektem Canvas, osmibitové
pak při práci se ScanLine.
Barvy ve výše uvedené deklaraci uvádím v pořadí, které odpovídá implicitní paletě formátu *.bmp 256 color imolementované ve Windows95. Hodnoty musí odpovídat hodnotám, generujícím příslušnou barvu na osmibitovém řádku formátu Windows Bitmap. Barev je šestnáct, neboť tento systém musí fungovat i ve čtyřbitové hloubce (např. v nouzovém režimu Windows). Poslední hodnota je však devatenáct, posloupnost hodnot je zajímavá zvláště ve druhém a třetím sloupci. Chybějící hodnoty uvnitř této posloupnosti generují barvy, které mezi základními nejsou. Proč tomu tak je, vědí asi jen vývojoví pracovníci firmy Microsoft.
Dále využijeme pole typu PByteArray,
což je pole ukazatelů na obrazový řádek - ScanLine. Chceme-li použít přímý
přístup, musíme nejdříve vytvořit bitmapu s odpovídající barevnou hloubkou
pixelu Protože typ PByteArray je pole proměnných typu byte, je třeba, aby
barevná hloubka v bitech byla násobkem osmi - nejméně tedy 8 bitů (256 barev)
tak, jako v našem případě:
Procedure InitImage(Image:TImage;Width,Height:Integer);
begin
Image.Align:=alNone;
Image.Picture.Bitmap.PixelFormat:=pf8bit;
Image.Picture.Bitmap.Width:=Width; ¨
Image.Picture.Bitmap.Height:=Height;
Image.Width:=Width;Image.Height:=Height;
end;
Velkou nepříjemností osmibitového přístupu ve Windows je skutečnost, že výše uvedené barevné konstanty odpovídají příslušným barvám pouze v implicitním nastavení palety v systému Windows 95. Vyšší verze mají implicitní paletu definovanou pokaždé jinak. Je ovšem možné vytvořit si vlastní paletu tak, aby byla nezávislá na použité verzi Windows. Výše uvedenou proceduru InitImage doplníme o definici příslušné palety:
Procedure InitColorImage(Image:TImage;Width,Height:Integer);
{pro předefinování
nastavených barev}
var Table
:array[Byte] of TRGBQuad;
begin
Image.Align:=alNone;
Image.Picture.Bitmap.PixelFormat:=pf8bit;
Image.Picture.Bitmap.Width:=Width;
Image.Picture.Bitmap.Height:=Height;
Image.Width:=Width;Image.Height:=Height;
With Image1.Picture.Bitmap do
Begin {předefinovávání
jednotlivých barev}
With Table[0] do
{černá – odstín
slBlack }
begin
rgbRed:=0;rgbGreen:=0;rgbBlue:=0;rgbReserved:=0;
end;
With Table[1] do
{velmi tmavá
červená}
begin
rgbRed:=51;rgbGreen:=0;rgbBlue:=0;rgbReserved:=0;
end;
With Table[14] do
{olivová – odstín
slOlive}
begin
rgbRed:=128;rgbGreen:=128;rgbBlue:=0;rgbReserved:=0;
end;
With Table[180] do
{modrá – odstín
slBlue}
Begin
rgbRed:=0;rgbGreen:=0;rgbBlue:=255;rgbReserved:=0;
end;
With Table[255] do
{bílá – odstín
slWhite}
begin
rgbRed:=255;rgbGreen:=255;rgbBlue:=255;rgbReserved:=0;
end;
{ošetření chybného
nastavení palety}
if
SetDIBColorTable(Canvas.Handle,0,255,table)=0
then RaiseLastWin32Error;
Canvas.Draw(0,0,Image1.Picture.Bitmap); {nastavení palety}
end;
end;
Jednotlivé barvy se nastavují
pomocí tabulky Table (Table[i] nastavuje i-tou barvu v paleté). K tomu,
abychom mohli jednotlivé barvy správně nastavit, musímě vědět, jak je namíchat
z červené, zelené a modré barvy (hodnoty rgbRed, rgbGreen a rgbBlue u
jednotlivých položek). Barvy jsou totiž implementovány v tzv. barevném
systému RGB, o kterém budeme mluvit v kpt. 4. V příští kapitole budeme
používat jednotku Graph2D_256, která výše uvedeným způsobem nastavuje barvy
nezávisle na verzi OS Windows. Konstanty základních barev mají následující
hodnoty:
const
slBlack
=0;
slMaroon
=3;
slGreen
=12;
slOlive
=14;
slNavy
=72;
slPurple
=38;
slTeal
=48;
slGray
=86;
slSilver
=172;
slRed
=5;
slLime
=30;
slYellow
=35;
slBlue
=180;
slFuchsia =185;
slAqua
=210;
slWhite =255;
Často je potřeba v osmibitové hloubce deklarovat ne 256 barev, ale 256 odstínů šedé. Princio je stejný jako v proceduře InitColorImage, šedé odstíny však mají složky R,G,B stejné velikosti – od nuly (černá) do 255 (bílá). Procedura, která takovou paletu nastavuje, pak vypadá následovně:
Procedure InitGrayScaleImage(Image:TImage;Width,Height:Integer);
{pro předefinování
nastavených barev}
var Table
:array[Byte] of TRGBQuad;
I :byte;
begin
Image.Align:=alNone;
Image.Picture.Bitmap.PixelFormat:=pf8bit;
Image.Picture.Bitmap.Width:=Width;
Image.Picture.Bitmap.Height:=Height;
Image.Width:=Width; Image.Height:=Height;
With Image1.Picture.Bitmap do
for i:=0 to 255 do {předefinovávání
jednotlivých barev}
With
Table[i] do
{černá – odstín
slBlack }
begin
rgbRed:=i;rgbGreen:=i;rgbBlue:=i;rgbReserved:=0;
end;
{ošetření chybného nastavení palety}
if
SetDIBColorTable(Canvas.Handle,0,255,table)=0
then RaiseLastWin32Error;
Canvas.Draw(0,0,Image1.Picture.Bitmap); {nastavení palety}
end;
end;
Definice barevné palety je součástí bitmapy. Jestliže tedy do obrázku Image1 nahrajeme 256 barevný bitmapový obrázek, paleta je tímto obrázkem opět předefinována. Naopak předefinujeme-li paletu již nahranému obrázku, docílíme velmi rychlých barevných efektů.
1. Příklad – demonstrace rychlosti obarvení
pixelu: vyplňme původně bílou kreslicí plochu bod po bodu jinou
barvou:
Klasické „pohodlné“ řešení:
Procedure PointFillingOfCanvas(Image:TImage;Color:DWord);
begin
for j:=0 to Image.Height-1 do for
i:=0 to Image.Width-1 do Image.Canvas.Pixels[i,j]:=Color;
end;
Při tomto řešení je implicitně využito toho, že objekt typu TImage v Delphi obsahuje bitmapu s hloubkou pixelů odpovídající režimu grafické karty, který lze ve Windows nastavit z nabídky Start/Nastavení/Ovládací panely/Obrazovka/ Nastavení/Barevná paleta.
Řešení s přímým přístupem: Nejdříve je třeba vytvořit bitmapu s osmibitovou barevnou hloubkou, a to buď barevnou (procedurou InitColorImage), anebo šedotónovou (procedura InitGrayscaleImage). Dále využijeme pole typu PByteArray, což je pole ukazatelů na obrazový řádek - ScanLine.
Nyní k vlastní proceduře na obarvení pixelu. Chceme-li ji vytvořit přehledně, budeme pracovat s jednotlivými pixely jako s uspořádanými dvojicemi celočíselných souřadnic. Globálně je tedy třeba deklarovat typ Pixel:
Type TPixel =array
[1..2] of integer;
který budeme dále používat. Proměnné tohoto typu - pixely pak budeme obarvovat následující procedurou:
Procedure PutPixel(Image:TImage;P:TPixel;Color:Byte);
var SL:PByteArray;
begin
SL:=Image.Picture.Bitmap.ScanLine[P[2]];
SL[P[1]]:=Color;
end;
konečně následuje vyplnění obrazu:
Procedure PointFillingOfScanLine(Image:TImage;Color:Byte);
var P:TPixel;
i,j:Integer;
begin
for j:=0 to Image.Height-1 do
for i:=0 to Image.Width-1 do
begin
P[1]:=i;P[2]:=j;
PutPixel(Image.Canvas.Pixels[i,j]:=Color;
end;
end;
Tato procedura je 20 – 30 krát
rychlejší než dříve uvedená procedura PointFillingOfImage-Canvas (konkrétní
hodnota závisí na právě probíhajících dalších událostech v operačním
systému). Je přehledné, původní přiřazení do matice pixels je pouze nahrazeno
rychlejší procedurou PutPixel. Nevyužívá nicméně beze zbytku předností tohoto
přístupu, jehož cílem je maximální urychlení celého procesu. Dalšího zlepšení
je možné dosáhnout použitím příkazů procedury PutPixel přímo v těle cyklu
a na tuto proceduru vůbec neodkazovat. Programu tak v každém pixelu
digitální roviny odpadne povinnost proceduru PutPixel hledat.
Maximálně rychlé řešení:
Procedure FillingOfScanLines(Image:TImage;Color:Byte);
var
i,j :Integer;
SL:PByteArray;
begin
for
j:=0 to Image.Height-1 do
begin
SL:=Image.Picture.Bitmap.ScanLine[j];
for i:=0 to Image1.Width-1 do SL[i]:=Color;
end;
end;
Poměr zrychlení u tohoto řešení ve srovnání s řešením klasickým se již pohybuje ve stovkách (většinou mezi 300 – 400), podařilo se mi však naměřit již i přes 700. V případě, že celou digitální rovinu neohodnocujeme konstantní hodnotou, ale tuto hodnotu nějakým způsobem počítáme, tento poměr pochopitelně klesá. Část potřebného času totiž zabírají operace s hodnotami, které jsou ve všech případech stejné. Zrychlení nicméně zůstává velmi významné (např. při sestrojení negativu obrazu se pohybuje kolem 200).
Procedura PutPixel provádí ohodnocení pixelu digitální roviny barvou . Chceme-li naopak zjistit aktuální ohodnocení, použijeme "inverzní" proceduru GetPixel:
Procedure GetPixel(Image:TImage;P:TPixel;var Color:Byte);
var SL:PByteArray;
begin
SL:=Image.Picture.Bitmap.ScanLine[P[2]];
Color:=SL[P[1]];
end;
Testový příklad: zde je porovnána rychlost procedur PointFillingOfCanvas a FillingOfScanLines. V obou příkladech se celý obraz bod po bodu vyplní pořadě červenou, zelenou a modrou barvou (v příkladu jsou obě procedury uvedeny bez parametrů).
zdrojový kód a zde můžete program spustit
V dalších řešených příkladech je tento přístup využit ke konstrukci úsečky. Algoritmus bude podrobně popsán v další kapitole. Výsledkem je konstrukce podstatně rychlejší, než standardní Canvas.MoveTo - Canvas.LineTo:
zdrojový kód a zde můžete program spustit
Tato „rychlá úsečka“ je použita k hranovým konstrukcím ploch, jejichž rychlost můžeme opět porovnat s „tradičním“ přístupem.
Zde najdeme zdrojový kód a zde můžete program spustit
Později tento přístup využijeme také k rychlým operacím s obrazy tak jak je ukázáno v tomto příkladě, k němuž
zde najdeme zdrojový kód a zde můžete program spustit
Vznik barevného vjemu – omezení oka - velikost vnímaných objektů
- počet barev
Velikost fyzického pixelu na obrazovce - řádově desetiny milimetru. Několik
takových pixelů o různých barvách není oko schopno rozlišit. Zraková
informace je v mozku integrována a my vnímáme třeba i barvu,
která na výstupním zařízení vůbec není zobrazena.
Barevné systémy – barvy jsou
realizovány mícháním základních barev.
Aditivní systém "nepopsaný" podklad černý, barvy
vznikají přidáváním základních barev.
R(ed)G(reen)B(lue) – monitory
Barevný prostor RGB (RGB krychle)
Zde si můžeme ukázat, jak zobrazovat řezy RGB krychle rovnoběžně s některou
souřadnou rovinou:
To samozřejmě zatím nebudeme dělat v rovnoběžném či středovém promítání,
řez zobrazíme jako čtverec ve skutečné velikosti:
Příklad 1: Sestrojme řez RGB krychlí rovnoběžný s některou z jejích stěn. Zvolme např. řez rovnoběžný s rovinou Green-Blue, procházející na ose Red hodnotou 128 (viz připojený obrázek). Prozatím ho samozřejmě nebudeme sestrojovat v axonometrii, spokojíme se se skutečnou velikostí. S použitím objektu Canvas by tato procedura mohla vypadat např takto:
procedure TForm1.Cut_Of_RGB (Sender: TObject);
const Red=128;
var Green,Blue:Byte;
begin
for
Green:=0 to 255 do for Blue:=0 to 255 do
Canvas.Pixels[Green,Blue]:=Red+256*Green+256*256*Blue;
end;
Proměnné Green a Blue nám kromě definice intenzity barevných složek poslouží jako proměnné v cyklech: vnější přidává zelenou v řádku, vnitřní modrou po sloupcích. Původně šedý povrch našeho okna (proměnná jménem Canvas - plátno) je objekt typu TCanvas (typ plátno). Toto „plátno“ má řadu vlastností, které nám umožní na něj malovat. Obsahuje např matici Pixels (body). Každý bod je uložen na třech bytech (R,G,B). K vlastnostem objektových proměnných se dostáváme „přes tečku“. Zadáme-li tedy např. Canvas. Pixels[50,50]:= 9856050, je na bod o světových souřadnicích [50,50] uložena barva definovaná trojicí (R,G,B)=(50,100,150) (šedomodrá), neboť 9856050=50 + 100*256 + 150*256*256.
V řešení, jehož zdrojový kód najdete zde a spustitelný kód zde,
je použita procedura PutPixel
přistupující do bitmapy pomocí matice Scanline.
Při použití pokročilejších programátorských technik může řešení vypadat
např. takto:
Příklad 2: stínování barev: Barevný odstín je v systému RGB dán poměrem barevných složek Red, Green, Blue, jas jejich absolutní velikostí. Chceme-li měnit jas barvy při zachování odstínu, musíme zachovat poměr složek a plynule měnit jejich velikost. To lze provést např. takto:
procedure TForm1.AreaShading(Sender: TObject);
const
{definice barevného
odstínu - poměru barevných složek}
Red_Portion=255;Green_Portion=127;Blue_Portion=127;
var Red,Green,Blue,
{barevné složky}
Value :Byte; {pro změnu
jasu barevných složkek}
begin
for Value:=255 downto 0 do {od
nejvyššího do nejnižšího jasu}
begin
{nastavení barevných
složek}
Red:=Trunc(Value*Red_Portion/255);
Green:=Trunc(Value*Green_Portion/255);
Blue :=Trunc(Value*Blue_Portion/255);
With Draw2D.Image1.Canvas
do
begin
Pen.Color:=Red+256*Green+256*256*Blue; {barva pera}
{vodorovná úsečka přes šířku plochy}
MoveTo(0,255-Value);LineTo(256,255-Value);
end;
end;
end;
Barevný odstín nemusíme samozřejmě zadávat „natvrdo“ tak, jako v předchozí ukázce. Lze ho vybrat pomocí
Objektu typu
TPictureDialog z lišty Dialogs, který vyvolá standardní editor barev, o
kterém už byla řeč. Hodnotu barvy - Color - lze přímo použít ve standardních
kreslících metodách a objektech (Pixels, Pen, Brush atd.), pro naše účely je
však třeba z této barvy „vyoperovat“ barevné složky Red, Green, Blue,
např:
procedure
TForm1.ColorChange(Sender: TObject);
begin
if
ColorDialog1.Execute then
begin
Blue_Portion:=ColorDialog1.Color div (256*256);
Green_Portion:=(ColorDialog1.Color - 256*256*Blue_Portion) div 256;
Red_Portion:=ColorDialog1.Color - 256*256*Blue_Portion
- 256*Green_Portion;
end;
end;
V programu je samozřejmě potřeba zařídit, aby takto nastavené hodnoty Red_Portion Green_Portion, Blue_Portion mohla převzít výše uvedená procedura AreaShading (např. jejich globální deklarací).
Zde najdete kompletní zdrojový kód a zde spustitelný kód.
Příklad 3: Sestavme program, který
sestrojí drsný podklad osvětlený z pravého dolního rohu.
Barevný odstín je volen pomocí
Color Dialogu, jako v předchozím příkladě. „Úhlopříčného“ stínu dosáhneme
funkcí, která má v levém horním rohu (x=0, y=0) hodnotu 0 (roh je tmavý), v pravém dolním
rohu (x=255, y=255) pak hodnotu 255 (roh je světlý) a po druhé úhlopříčce
je konstantní. Tyto podmínky splňuje např. funkce z =(x+y)/2 Výsledek však
není příliš hezký (stín je příliš velký a celý obrázek je velmi tmavý).
V našem příkladu proto byla tato funkce umístěna do argumentu funkce
arctan. Obraz je nyní celý černý. Funkci musíme vynásobit vhodnou konstantou,
abychom posunuli supremum množiny funkčních hodnot z p/2
na 255. Stín zde nyní naopak není téměř vůbec. Vydělením argumentu vhodným
číslem však docílíme potřebné velikosti. „Zdrsnění“ plochy docílíme funkcí
Random, jejíž hodnoty jsou náhodná čísla z intervalu á0;1).
Tento interval je roztažen konstantou Roughness. Čím je tato konstanta vyšší,
povrch se jeví drsnější. Po této úpravě však hodnota z může „vypadnout“
z intervalu á0;255ñ, což je třeba ošetřit
(viz následující řádek programu). Hodnoty Red, Green, Blue nastavíme podobně,
jako v předchozím příkladu. Plochu však nemůžeme vyplňovat úsečkami, neboť
se zde barva mění po jednotlivých pixelech:
procedure
TForm1.AreaShading(Sender: TObject);
const Roughness=20;
var Red,Green,Blue,x,y:Byte;
z
:Double;
begin
for y:=0 to 255 do
begin
for x:=0 to 255 do
begin
z:=2*255/pi*arctan((x+y)/160); {funkce určující tvar stínu}
z:=z+2*Roughness*Random-Roughness; {"zdrsnění"
plochy randomem}
if z<0 {ošetření
přetečení intervalu <0,255>}
then z:=0 else if z>255 then z:=255;
Red :=Trunc(z*Red_Portion/255); {nastavení hodnot složek}
Green:=Trunc(z*Green_Portion/255);
Blue :=Trunc(z*Blue_Portion/255);
{vykreslení bodu}
Image1.Canvas.Pixels[x,y]:=Red
+256*Green+256*256*Blue;
end;
end;
end;
V řešeném příkladu je opět využit
rychlejší přístup do bitmapy procedurou PutPixel.
Zde najdete kompletní zdrojový kód a zde spustitelný kód.
Subtraktivní
systém: "nepopsaný"
podklad černý, barvy vznikají přidáváním základních barev
C(yan)M(agenta)Y(ellow) – tiskárny, z praktických důvodů se
přidává černá C(yan)M(agenta)Y(ellow)(blac)K
(kvalitnější černá, šetří inkoust)
Barevný prostor CMY (CMY krychle)
Řezy
v prostoru RGB: Řez
prostoru rovinou konstantního
jasu
Řezy rovinami konstantního jasu v prostoru mají zásadní význam
při konstrukci dalších barevných prostorů.
Prostor CIE
Konkrétní realizaci uživatelského
výběru barev známe ze standardního color dialogu systému Windows:
Barevné palety: velmi často se stává, že potřebujeme využít jen některé z barev, které nabízí daný barevný prostor a které navíc potřebujeme mít seřazeny podle jistého kriteria (např. první barva černá, druhá žlutá, třetí modrá atd.). Budeme-li chtít např. sestrojit mapu jistého území, použijeme jisté odstíny modré podle hloubky vodních nádrží, jisté odstíny zelené pro nížiny a hnědé pro hory. Přitom např. fialové, růžové a jiné odstíny nebudeme vůbec potřebovat. Barvy budou číslovány podle nadmořské výšky. Chceme-li modelovat rozklad světla hranolem, budeme potřebovat pouze složky spektra, jejichž pořadí bude určeno vlnovou délkou světla. Je samozřejmě otázkou, jakým mechanismem tento výběr provést a očíslovat. Jednou z možností je v příslušném barevném prostoru zadat křivku, procházející požadovanými barvami, přičemž pořadí barev je určeno parametrizací křivky. (tak např. vznikla třetí paleta v ukázce). V případě, že je paleta nespojitá (viz přechod mezi vodou a nížinou), musí být nespojitá i příslušná křivka v barevném prostoru. Ve složitějších případech, kdy paletu není jednoduché určit rovnicí, můžeme paletu definovat např. tabulkou hodnot (viz druhá ukázky, která je interpretací tabulky citlivosti lidského oka na jednotlivé vlnové délky viditelného světla), popř. může být paleta definována přímo obrazem (v našem případě např. příslušným barevným proužkem).
Zde najdete kompletní zdrojový kód a
zde spustitelný kód.