13. DOMAČA NALOGA (25.05. - 07.06.) --- 20 točk

Naslov:  SLIKE
Vrednost naloge: 20 točk

Sliko sestavlja zaporedje barvnih pikslov, ki so razporejeni v mreži. Vsaka slika ima tudi določeno velikost, to je višino in širino. Širina pove, koliko pikslov imamo v eni vrstici (koliko je vseh stolpcev), višina pa pove, koliko pikslov imamo v enem stolpcu (koliko je vseh vrstic).

Vsak barvni piksel je sestavljen iz treh osnovnih barv: rdeče, zelene in modre. Tako lahko en piksel predstavimo s trojico števil (r,g,b), kjer r pomeni količino rdeče barve (red), g količino zelene barve (green) ter b količino modre barve (blue). Vse te vrednosti so med (vključno) 0 in 255. Če so vse tri vrednosti enake, dobimo siv odtenek (npr. (128,128,128)). Črno barvo predstavlja (0,0,0), belo pa (255,255,255).

Za to domačo nalogo pri Programiranju 2 smo za shranjevanje slik v datoteki sestavili dva formata zapisa: p2t in p2b.

Format p2t je tekstovna datoteka, v kateri je v prvi vrstici najprej zapisan format, torej niz P2T, nato pa še velikost slike v obliki širina x višina, na primer 800 x 600. V drugi vrstici pa sledi zaporedje števil med 0 in 255, kjer vsaka trojica števil predstavlja en piksel. Piksli v sliki so zapisani od leve proti desni in od zgoraj navzdol. Tak zapis slike je zelo velik, zato pogosto raje uporabljamo format p2b, ki sliko shrani v manjšo datoteko.

Format p2b je binarna datoteka, v kateri so podatki zapisani po bajtih. Prvi trije bajti imajo šestnajstiške vrednosti 50, 32 in 42, kar ustreza desetiškim 80, 50 in 66, kar so natanko ASCII kode črk P, 2 in B (prvi trije bajti torej pomenijo podpis P2B). Sledi velikost slike, in sicer naslednji štirje bajti vsebujejo podatek o širini slike, naslednji štirje pa še o višini slike. Nato sledi zaporedje bajtov, ki določajo piksle slike. Po trije bajti določajo en piksel (njegove r, g in b komponente), piksli slike pa so zapisani od leve proti desni in od zgoraj navzdol.

Tako na primer sliko test.jpg zapišemo v tekstovnem formatu kot test.p2t oziroma v binarnem formatu kot test.p2b, ali pa barvno sliko ikona.png velikosti 10 x 10 pikslov kot ikona.p2t oziroma ikona.p2b.

Napišite program za delo s slikami. Vse razrede in metode implementirajte v datoteki DN13.java. Razred DN13 naj vsebuje metodo main(), ki bo omogočala testiranje vseh ostalih metod. Prvi argument programa bo vedno številka naloge, pomen ostalih argumentov pa je razviden iz opisa pri posamezni nalogi.

1) Napišite razred Piksel, ki predstavlja en piksel v sliki. Razred naj ima privatne atribute za vrednosti rdeče, zelene in modre komponente ter ustrezen konstruktor. Definirajte tudi metodo int[] getKomponente(), ki vrne tabelo z vrednostmi rdeče, zelene in modre komponente tega piksla. Po potrebi v razredu definirajte še druge atribute in metode.

Napišite razred Slika, ki predstavlja eno sliko. Razred naj vsebuje privatne atribute za velikost slike, ime datoteke s sliko ter seznam vseh pikslov slike. V razredu definirajte ustrezen konstruktor (lahko jih je tudi več) ter statično metodo za branje slike iz podane tekstovne datoteke (metoda vrne objekt Slika, ki predstavlja prebrano sliko). Definirajte tudi metode String getIme(), int getSirina(), int getVisina(), Piksel getPiksel(x, y), ki vračajo, po vrsti, ime datoteke s sliko, širino slike, višino slike ter piksel na mestu (x,y) na sliki. Po potrebi v razredu definirajte tudi druge atribute in metode.

Za preizkus delovanja razreda Slika lahko uporabite razred Izrisi, kateremu v konstruktorju podate objekt razreda Slika (v slednjem morajo biti definirane vse zgoraj navedene metode). Razred Izrisi poskrbi za izris te slike v oknu, če pokličete njegovo metodo prikazi(). (V testnem sistemu se slika ne izriše, ampak se na zaslon izpišejo vsi podatki o sliki ter prvi trije in zadnji trije piksli.)

  Slika mojaSlika;
...                              // tu poskrbimo za ustvarjanje objekta mojaSlika
new Izrisi(mojaSlika).prikazi(); // ustvarimo objekt razreda Izrisi in ga prikažemo (to je izris slike v oknu)
Ob klicu programa
java DN13 1 test.p2t
se tako odpre novo okno, v katerem je prikazana slika test.p2t.

2) V razredu Slika napišite še statično metodo, ki prebere sliko iz binarne datoteke, katere ime je podano kot parameter, ter vrne objekt Slika, ki predstavlja prebrano sliko. Tudi za prikaz te slike lahko uporabite razred Izrisi (glej nalogo 1).

Ob klicu programa
java DN13 2 test.p2b
se tako odpre novo okno, v katerem je prikazana slika test.p2b.

3) Pri branju slike naj program sproži preverljivo izjemo, če slika ni v pravem formatu. V ta namen napišite svoj razred za izjemo. Predvsem bodite pozorni na podpis slike (začne se z P2T oz. P2B), napačno velikost (prevelika - izven obsega int - ali 0), preveč ali premalo podatkov o pikslih, napačne vrednosti komponent ... V metodi main() ustrezno ulovite izjeme in izpišite napake, do katerih je prišlo.

Naslednji klici programa
java DN13 3 test.p2t
java DN13 3 test.p2b
java DN13 3 test.jpg
v prvih dveh primerih povzročijo prikaz slike v oknu, v tretjem primeru pa se izpiše sporočilo o napaki ("Datoteka ni v formatu P2T/P2B: napaka v imenu datoteke.").

4) Napišite metodo, ki prebere sliko, katere ime datoteke je podano kot drugi argument programa, ter izpiše povprečje vseh pikslov te slike (na dve decimalki natančno). Povprečje pikslov izračunamo tako, da seštejemo vse vrednosti pikslov in jih delimo s številom vseh pikslov. Vrednost posameznega piksla izračunamo tako, da seštejemo vrednosti posameznih komponent (rdeče, zelene in modre), jih delimo s 3 in zaokrožimo navzdol na celo število.

Ob klicu programa
java DN13 4 test.p2b
naj program izpiše
130.48

5) V razredu Slika napišite tudi metodi za zapis slike v binarno datoteko p2b in tekstovno datoteko p2t. Metodi uporabite za pretvorbo slike iz tekstovnega v binarni format in obratno. Delovanje metode preverite tako, da novo (pretvorjeno) sliko preberete in jo izrišete v oknu s pomočjo razreda Izrisi (glej nalogo 1).

Ob klicu programa
java DN13 5 test.p2t
naj program zapiše sliko v binarno datoteko (test.p2b) in jo prikaže. Ob klicu programa
java DN13 5 test.p2b
pa naj program zapiše sliko v tekstovno datoteko (test.p2t) in jo prikaže.

6) "Svetli šiv" na sliki je zaporedje pikslov (dolžina tega zaporedja je enaka višini slike), ki omogočajo sprehod po sliki od prve do zadnje vrstice tako, da na poti obiskujemo najbolj svetle piksle. Začnemo torej z najsvetlejšim pikslom v prvi vrstici, nato pa se pomaknemo navzdol v drugo vrstico na najsvetlejši sosednji piksel (če sta najsvetlejša dva sosednja piksla, vzamemo levega). Sosednji piksli so tisti, ki so neposredno pod ali pa levo oz. desno diagonalno navzdol od podanega piksla. Svetlost piksla določa vrednost piksla (glej nalogo 4); večja kot je, svetlejši je piksel.

Program naj za podano sliko (drugi argument) izpiše, kateri piksli so na svetlem šivu. Izpis poenostavimo tako, da za vsako vrstico izpišemo, koliko pikslov se v vrstici nahaja levo od svetlega šiva (v spodnjem primeru je v prvi vrstici levo od svetlega šiva 57 pikslov).

Ob klicu programa
java DN13 6 test.p2b
naj program izpiše
57
56
55
54
53
53
52
51
50
50
...
7
8
8
7
6

7) Piksle, ki so na svetlem šivu na podani sliki, zamenjajte s črnimi piksli (novo sliko prikažete na zaslonu z uporabo razreda Izrisi) ter novo sliko zapišite v datoteko. Ime nove datoteke je podano kot tretji argument programa (brez končnice; ustrezno končnico naj doda program in je enaka končnici originalne datoteke). Delovanje metode preverite tako, da novo (pretvorjeno) sliko tudi preberete in jo izrišete v oknu s pomočjo razreda Izrisi (glej nalogo 1).

Ob klicu programa
java DN13 7 test.p2t svetli-siv
naj program zapiše sliko z označenim svetlim šivom v tekstovno datoteko svetli-siv.p2t in jo prikaže v oknu. Pri klicu programa
java DN13 7 test.p2b svetli-siv
novo sliko z označenim svetlim šivom zapiše v binarno datoteko svetli-siv.p2b in jo prikaže v oknu.

8) Program naj prebere vse slike, ki so podane kot argumenti programa (lahko jih je poljubno mnogo), ter izpiše imena slik, urejena od najsvetlejše do najtemnejše slike. Svetlost slike določa vrednost povprečja vseh pikslov (glej nalogo 4), ki naj jo tudi izpiše v oklepaju za imenom slike (na dve decimalki natančno). Če imata dve sliki enako svetlost, naj bo prva izpisana tista slika, katere ime je po abecedi prej (pri tem ne ločimo velikih in malih črk). Če je med imeni datotek podano ime direktorija, naj program prebere tudi vse slike iz tega direktorija (ne pa tudi njegovih poddirektorijev).

Ob klicu programa (kjer direktorij slike vsebuje datoteke mala-slika.p2b, nova1.p2b, svetli-siv.p2t, test1.p2t, test2.p2t in velika-slika.p2b)
java DN13 8 test.p2b svetli-siv.p2t slike
naj program izpiše
test.p2b (130.48)
slike/svetli-siv.p2t (130.19)
svetli-siv.p2t (130.19)
slike/velika-slika.p2b (122.81)
slike/mala-slika.p2b (115.46)
slike/test2.p2t (115.46)
slike/nova1.p2b (111.52)
slike/test1.p2t (111.52)

Pred oddajo programa na eUčilnci preverite pravilnost delovanja.