RSS

Atrybuty obrazu

Liczba odsłon: 235

Początkowo komputery generowały jedynie TEKST. Całe ekrany tekstu, całe arkusze papieru zapełnione literami, liczbami i – ewentualnie – ramkami lub nawet prostą semigrafiką. Trzeba było dopiero rewolucji komputerów osobistych i domowych, by na ekranach maszyn obliczeniowych pojawiła się GRAFIKA.

Zapisanie informacji o każdym punkcie obrazu (ang. pixel — picture element) wymagało jednak o wiele więcej miejsca w pamięci operacyjnej, niż w przypadku samego tekstu. Dzisiaj może nam się to wydawać śmieszne — w swoich komputerach mamy przecież setki megabajtów, a coraz częściej wręcz gigabajty pamięci operacyjnej. W początkach komputeryzacji jednak typowa pojemność pamięci RAM wynosiła od kilku do kilkudziesięciu kilobajtów i zajmowanie zbyt dużego obszaru tylko po to, by wyświetlić efektowny obraz było po prostu nierozsądne.

Dla przykładu, graficzny ekran komputera Sinclair ZX Spectrum (256×192, 16 kolorów) zajmował w jego pamięci dokładnie 6 912 bajtów. Gdyby zapisywać informacje o samych znakach tekstowych, potrzebne byłoby tylko 1 536 bajtów (rezygnacja z informacji o kolorach ograniczyłaby jeszcze ten obszar do zaledwie 768 bajtów). Zwiększenie liczby barw do 256 i umożliwienie sterowania barwą każdego piksela z osobna wymagałoby już 49 152 bajtów pamięci — dokładnie tyle, w ile był wyposażony cały ten komputer.

Jasne staje się, że wprowadzenie możliwości generowania kolorowego obrazu rastrowego wymagało sprytnego systemu kodowania informacji o obrazie i barwach, by w jak najmniejszej ilości pamięci zmieścić jak najwięcej informacji i dać jak największe możliwości. Od możliwości graficznych komputera zaczął bowiem zależeć sukces komercyjny komputerów domowych, wykorzystywanych przecież głównie do rozrywki (czyli do kolorowych gier wideo).

Pamięć atrybutów

Najprostszym rozwiązaniem, zastosowanym choćby we wspomnianym już mikrokomputerze Sinclair ZX Spectrum czy w całej rodzinie komputerów Commodore (między innymi modele 64 i 128), jest pamięć atrybutów. Rozwiązanie to polega na rozdzieleniu obszarów pamięci opisujących wygląd obrazu (raster) oraz barwy poszczególnych elementów obrazu (pikseli). Ten drugi obszar pamięci nazwano właśnie pamięcią atrybutów.

Sam taki podział nie wprowadzał oczywiście żadnych oszczędności. Aby faktycznie na nim zyskać, poczyniono założenie, że obraz zawiera zazwyczaj spore fragmenty o jednolitej kolorystyce i nie ma potrzeby określania barwy każdego piksela z osobna. Raster obrazu podzielono na komórki (ang. cells) o stałym rozmiarze (najczęściej 8×8 pikseli, zgodnie z rozmiarem rastra pojedynczego znaku w trybie tekstowym); każdej takiej komórce odpowiadało w pamięci atrybutów jedno słowo atrybutów. Widać, że takie założenie pozwalało ograniczyć ilość danych 64 (8×8) razy.

Obraz bez nałożonych atrybutów Obraz z nałożonymi atrybutami

Obraz bez nałożonych atrybutów

Ten sam obraz z nałożonymi przypadkowo atrybutami (poprzez bezpośredni wpis kolejnych wartości liczbowych do pamięci atrybutów)

Słowo – a najczęściej bajt – atrybutów opisujące barwy rastra w komórce zawierało zazwyczaj informację o kolorze tła i kolorze pierwszego planu. Piksele, którym w rastrze odpowiadała wartość 1 przybierały kolor pierwszego planu; pozostałe były wyświetlane w kolorze tła. Zazwyczaj na opis obu barw przypadały po 4 bity, co umożliwiało określenie jednego z 16 kolorów tła (ang. background) i pierwszego planu (ang. foreground); tak było na przykład w przypadku komputerów Commodore 64/128. W przypadku mikrokomputera ZX Spectrum na opis koloru przypadały tylko 3 bity (co dawało 8 możliwych barw), a z pozostałych jeden na bit jaskrawości (umożliwiający podniesienie jaskrawości komórki, wspólnie jednak dla koloru tła i pierwszego planu) oraz jeden na bit migotania (wykorzystywany głównie w pseudotekstowym trybie pracy tego mikrokomputera).

Kadr z gry Tir na nOg Two­rze­nie opro­gra­mo­wania z uwzględ­nie­niem powyż­szych ogra­ni­czeń nie było proste. W przy­padku opro­gra­mo­wania użyt­ko­wego, wyś­wiet­la­ją­cego zaz­wy­czaj sporo tek­stu, było to jesz­cze do opa­no­wa­nia, można było bowiem wy­musić podział ekranu na ob­szary o roz­mia­rach będą­cych wielo­krot­noś­cią roz­miaru komórki atry­butów. Wystar­czyło jednak spróbo­wać wyświet­lić wielo­kolo­rowy wykres liniowy, by uświa­domić sobie ograni­czenia roz­wią­zania z odrębną pamięcią atry­butów: w każdym punkcie prze­cięcia linii wykresu możliwa jest jedynie jedna barwa pierw­szego planu, co uniemoż­liwia wyraźne roz­gra­ni­czenie serii danych.

Jeszcze większe problemy stały przed twórcami gier komputerowych. Te z natury wielokolorowe i dynamiczne twory trzeba było zamknąć w sztywnych ramach reguł podziału obrazu na komórki atrybutów. Stosunkowo łatwo poddawały się temu zabiegowi gry platformowe wyświetlające nie przesuwający się obraz: mapę obszaru gry można było zaprojektować zgodnie z podziałem na komórki, by nigdzie nie było konieczne mieszanie więcej niż dwóch barw w jednym polu atrybutów. Nieźle też było z wieloma grami przygodowymi, w których podzielono obraz na poziome lub pionowe pasy o stałej kolorystyce (jak przedstawiony na obrazie powyżej Tir na nOg). Choć ich oprawa graficzna nie była tak barwna, jakby to było możliwe, algorytm kolorowania obrazu był łatwy do zaprogramowania i działał niezawodnie.

Problem poja­wiał się w momen­cie, gdy konieczne sta­wało się płynne prze­wi­janie większego, wielo­barwnego obszaru gry w zależ­ności od ruchu postaci. Program musiał nie tylko aktuali­zować raster, prze­wi­jając go o jeden lub kilka pik­seli, ale też uwzględ­niać nało­żoną na raster siatkę atry­butów, której przesu­wanie musiało być zsynchro­ni­zo­wane z ruchem rastra.

Przykład konfliktu atrybutów Naj­gor­szą pracę mieli jednak pro­gra­miści gier, w których obraz pos­taci musiał wyróż­niać się barwą lub wędrować po inten­syw­nie pokolo­ro­wanym podłożu. Na obrazie po prawej stro­nie widać przyk­ład gra­fiki zbudo­wanej według tej drugiej zasady: ikona pos­taci jest prawie całko­wicie nie­widoczna w efekcie nało­żenia jej na pokoloro­wany raster tła.

Problem ten nazwano konfliktem atrybutów (ang. attribute clash). Dotykał on w zasadzie wyłącznie mikrokomputerów z rodziny ZX Spectrum, wyposażonych w wyjątkowo prymitywny układ generacji obrazu. W komputerach lepiej przystosowanych do zastosowań rozrywkowych (Atari XL/XE, Commodore 64/128) rozwiązano go na dwa sposoby: wprowadzając tryby wielokolorowe o obniżonej rozdzielczości, mniej zależne od siatki atrybutów, oraz umożliwiając tworzenie ruchomych elementów obrazu – tak zwanych duszków (ang. sprites) – których kolorystyka była całkowicie niezależna od pamięci atrybutów i które mogły być płynnie mieszane z dowolnie stworzonym tłem gry.

Rozwiązanie z pamięcią atrybutów miało również swoje zalety, umożliwiało bowiem bardzo szybkie operowanie kolorystyką obrazu. Aby całkowicie zmienić barwę wcześniej przygotowanego rastra, wystarczyło zmodyfikować kilkaset bajtów pamięci — cecha nie do przecenienia w epoce powolnych mikroprocesorów. Możliwość tę wykorzystywano na przykład do ukrywania obrazu na czas generowania rastra (lub ładowania go z kasety lub z dysku): gotowy raster można było zaprezentować w ułamku sekundy, kopiując blok atrybutów do pamięci atrybutów. Pamięć atrybutów ułatwiała też implementację kodu umożliwiającego wybranie fragmentu obrazu: podświetlenie obszaru wskazujące zakres wyboru można było zrealizować przez modyfikowanie pamięci atrybutów (bez kosztownego czasowo modyfikowania rastra), z możliwością natychmiastowego przywrócenia poprzedniej kolorystyki obrazu w momencie akceptacji lub odrzucenia wyboru.

Dzisiaj technikę opisu kolorystyki obrazu za pomocą pamięci atrybutów stosuje się wyłącznie w tekstowych trybach pracy kart graficznych mikrokomputerów PC. W takim zastosowaniu sprawdza się ona idealnie, gdyż rozmiar komórki (pola) atrybutów odpowiada idealnie rozmiarowi pola znaku, a określanie kilku barw dla jednego znaku pozbawione jest sensu. Nawet najprostsze tryby graficzne wykorzystują już jednak bardziej rozbudowane, dające większe możliwości mechizmy kolorowania rastra.

Paleta barw

Drugi sposób opisu obrazu zdecydowanie zwiększał swobodę programistów, pozwalając określać punkt każdego elementu obrazu z osobna. Wygląd obrazu nie był już opisany jednobarwnym rastrem kolorowanym na podstawie osobnej informacji: każdy z elementów rastra zawierał bezpośrednią informację o własnej barwie.

Oczywiste jest, że ten sposób opisu musiał wymagać większego obszaru pamięci operacyjnej. Podczas gdy wysokorozdzielczy tryb graficzny mikrokomputerów Commodore 64 (320×200, 16 barw) zajmował w pamięci 9 000 bajtów (w tym 8 000 bajtów pamięci rastra i 1 000 bajtów pamięci atrybutów), tryb graficzny niskiej rozdzielczości mikrokomputerów Amstrad CPC (160×200, 16 barw) wymagał 16 000 bajtów — prawie dwukrotnie więcej. Za tę cenę użytkownik dostawał jednak obraz o niezwykle bogatej kolorystyce, możliwej do uzyskania na Commodore tylko przy wykorzystaniu sztuczek programowych, które same często wymagały zajęcia kilku kolejnych kilobajtów pamięci.

Opis elementu rastra mógł być zreali­zo­wany na kilka sposobów. Dwa naj­po­pular­niej­sze to:

Wadą powyższego rozwiązania jest znaczący wzrost skomplikowania programów pragnących modyfikować kolorystykę obrazu. Na przykład, zamiana wszystkich czerwonych pikseli leżących w jakimś obszarze wymaga przeglądnięcia pamięci obrazu, wyszukania odpowiednich kombinacji bitów i zamienienia ich na inne. Rośnie również ilość danych koniecznych do przesunięcia w pamięci w ramach płynnego przewijania obrazu: podczas gdy w przypadku ZX Spectrum przewinięcie obrazu w poziomie o jeden piksel wymaga przeniesienia około 6 KiB danych, ta sama operacja wykonana na Amstradzie oznacza przeniesienie blisko 9 KiB danych — o 30% więcej pracy przy takiej samej mocy obliczeniowej tych komputerów.

Szybko znaleziono jednak sposób na zneutralizowanie tych wad. Wprowadzenie zestawu rejestrów definiujących faktyczne barwy poszczególnych kombinacji bitowych znajdujących się w pamięci obrazu umożliwiło dowolne kształtowanie kolorystyki obrazu bez konieczności modyfikowania rastra — i to jeszcze mniejszym nakładem pracy, niż w przypadku rozwiązania z pamięcią atrybutów. Efekty takie jak płynne rozjaśnienie lub ściemnienie obrazu czy też zmiana kolorystyki na zaciemnioną (sceny nocne) lub zaczerwienioną (sceny w promieniach zachodzącego słońca) stały się kwestią zapisania kilkunastu bajtów w rejestrach barw. Programiści, który nie potrzebowali pełnego zestawu kolorów mogli też zrezygnować z nich na korzyść kilku lub kilkunastu odcieni jednej barwy, uzyskując na ekranie obrazy bardziej już przypominające zdjęcie, niż typową grafikę komputerową. Taki zestaw barw stworzony z myślą o konkretnym obrazie nazywano paletą barw (ang. color palette).

Nieliczne układy graficzne dysponujące pojęciem palety barw nie umożliwiały uzyskania tej skali efektów. Na przykład karta graficzna CGA, stosowana przez krótki okres w mikrokomputerach klasy IBM PC, dysponowała tylko kilkoma narzuconymi odgórnie paletami barw. Z kolei karta graficzna EGA umożliwiała co prawda modyfikowanie poszczególnych elementów palety, jednak tylko w zakresie 64-stopniowej przestrzeni RGBI (dwa bity przypadające na każdą z barw składowych). W świecie PC dopiero układy MCGA i VGA upowszechniły analogowe sterowanie monitorem ekranowym i rozszerzyły spektrum barw do 262 144 pozycji.

Gra Monkey Island w trybie graficznym 320x200 256 kolorów Pojęcie palety barw nieźle spraw­dzało się przy ob­razie cztero-, ośmio- i szes­nas­to­kolo­ro­wym, jed­nak naj­więk­sze zna­czenie zys­kało wraz z upow­szech­nie­niem trybów gra­ficz­nych, w których każdy piksel opi­sany był pełnym bajtem, stano­wiącym indeks do palety barw. Choć obraz opi­sany w ten sposób zaj­mował dosyć sporo pamięci (na przykład popularny swego czasu w grach tryb gra­ficzny 320×200 256 kolorów wymagał 64 000 bajtów pamięci obrazu), dos­to­so­wanie palety barw do charak­teru wyświet­lanego obrazu dawało olbrzymie możli­wości. Z wykorzys­taniem odpo­wied­nich tech­nik optymali­za­cyjnych (ogranicza­jących liczbę unika­towych barw w obrazie do minimum i two­rzą­cych paletę zawiera­jącą właśnie te barwy) można było wyświetlać na ekranie kompu­tera obrazy o niespoty­kanej wcześ­niej, prawie foto­gra­ficznej jakości. Jedno­cześnie zacho­wana była niesamo­wita elastycz­ność roz­wią­zania: progra­mista miał kontrolę nad każdym pikselem obrazu i mógł albo manipu­lować bezpoś­rednio pikselami, zmieniając ich indeksy w palecie barw, albo za pomocą zmian w palecie natychmiast modyfi­kować wygląd wszystkich pikseli o danym indeksie lub całego obrazu.

Rosnąca moc oblicze­niowa układów graficz­nych i malejące ceny układów pamięci spowodo­wały jednak nagły spadek zna­czenia trybów graficz­nych z paletą barw. Już 5 bitów opisu każdej barwy skła­dowej – a do tego wystar­czyło podwo­jenie roz­miaru pamięci obrazu – pozwa­lało zapom­nieć o two­rzeniu ściśle dostoso­wa­nych do charak­teru obrazu palet barw i zająć się nie prog­ra­mo­wa­niem, a tworze­niem cyfrowych obrazów.

Płaski opis rastra

Ostatnia, od niedawna tak naprawdę stosowana technika opisu kolorystyki obrazu jest najprostsza, lecz zarazem najbardziej rozrzutna i wymagająca największej ilości obliczeń. Polega ona na zapisywaniu w pamięci obrazu bezpośredniego opisu koloru piksela — nie w postaci indeksu (odniesienia) do palety barw, tylko w formie opisu natężenia barw składowych R, G i B.

Ilość pamięci potrzebnej do takiego opisu obrazu jest olbrzymia. Tryb graficzny o rozdzielczości 640×480 i zaledwie 16-bitowym opisie barw potrzebuje 614 400 bajtów pamięci na jeden tylko obraz (płynna animacja wymaga obrazu dwubuforowego, zajmującego dwukrotnie większy obszar pamięci). To dziesięć razy więcej pamięci, niż miał w sobie komputer Commodore 64 i dokładnie tyle, ile montowano w najpopularniejszej odmianie komputera IBM PC/XT. Zwiększenie rozdzielczości do 1280×1024 (z 32-bitowym opisem kolorów) oznacza konieczność przeznaczenia na pamięć obrazu ponad pięciu megabajtów pamięci.

Możliwości generowania obrazu w takim trybie są jednak prawie nieograniczone. Można wyświetlić obraz płaski, renderowany, fotograficzny — wszystko bez żmudnego manipulowania paletami barw i ograniczania wizji artystycznej. Równie proste jest przewijanie obrazu i umieszczanie na nim różnych ruchomych elementów: wszystko zależy od sprawności zastosowanych algorytmów i mocy obliczeniowej komputera, ilość danych do przetworzenia jest bowiem ogromna, a wymagania użytkowników coraz większe.

Co gorsze, nie ma prostego sposobu na szybkie zmodyfikowanie kolorystyki obrazu zapisanego w sposób płaski. Jedyne, co można uczynić, to przeglądnąć wszystkie punktu obszaru podlegającego modyfikacji i zmodyfikować natężenia barw składowych w odpowiedni sposób. Problem był na tyle poważny, że w praktycznie każdym nowoczesnym mikroprocesorze implementuje się obecnie odrębną jednostkę wektorową automatyzującą operacje arytmetyczne na dużych zbiorach upakowanych danych. Choć płynne ściemnienie obrazu z wykorzystaniem rozkazów wektorowych jest zdecydowanie sprawniejsze, wymaga od mikroprocesora wykonania liczby operacji nieporównywalnej z wymaganą do przeprogramowania rejestrów barw (przy zmianie palety kolorów).

Trudno jednak oczekiwać, by nastąpił odwrót od płaskiego opisu obrazu. Daje on grafikom i programistom możliwości ograniczone w praktyce jedynie ich własną kreatywnością i pracowitością. Mikrokomputer wyposażony w nowoczesne układy graficzne musi co prawda wykonywać wiele prostych operacji w sposób programowy, bez wspomagania dostępnego kiedyś specjalizowanego sprzętu, jednak mimo to zarówno jego możliwości, jak i szybkość działania, wzrosły niewyobrażalnie.


Ale ten "tir na nog" to z dzisiejszej perspektywy kaszana. Ale ja w to grałem na commodore c+4 w okolicach 1993r z mapą z "bajtka". Nawet mnie ta gra wciągnęła choć jej nie ukończyłem bo nie czaiłem tego typu gier. Z rozrzewnieniem to wspominam.