2004.09_Stereogramy_[Programowanie].pdf

(836 KB) Pobierz
439034163 UNPDF
dla programistów
Stereogramy
Marek Sawerwain
nością zetknęło się ze
stereogramami w posta-
ci różnych pocztówek,
a być może oglądało je na ekranie
komputera. Chociaż nie są one już tak
popularne, jak kilka lat temu, to z pew-
nością warto wiedzieć, jak powstają tego
typu obrazy. Wbrew pozorom, technika
rysowania stereogramów, np. takich jak
na dołączonych do artykułu rysunkach,
jest zaskakująco prosta. Algorytm postę-
powania można zapisać w kilkunastu
linijkach kodu.
W tym artykule postaram się przed-
stawić, jak napisać program do genero-
wania prostych stereogramów.
Inaczej postąpimy podczas genero-
wania stereogramu. Gdy użytkownik
wybierze plik, który chce zamienić na
stereogram, to poznamy jego pełną ścież-
kę. Wtedy wczytamy ten plik do pamięci
wykorzystując bibliotekę DevIL .
Nasz program będzie przetwarzał
tylko pliki z tzw. kolorem indeksowanym
(dlaczego stosujemy taki tryb koloru,
zaraz się wyjaśni), natomiast wewnętrzne
mechanizmy GNOME bądź GTK skupiają
się raczej na kolorach typu RGB. Niestety,
ten rodzaj opisu kolorów nie nadaje się
do łatwego generowania stereogramów.
Z tego powodu korzystamy z DevIL ,
gdzie ładowany plik nie jest poddawany
dodatkowej wewnętrznej konwersji.
Po wczytaniu pliku graficznego
i wykonaniu stereogramu, gotowy obraz
zapisujemy do pliku tymczasowego, który
wczytujemy do widgetu GtkImage . Zapis
stereogramu do ostatecznego pliku nastą-
pi dopiero, gdy użytkownik wybierze
opcję Zapisz w naszym programie. Może
to wydać się działaniem naokoło, ale
w ten sposób oszczędzamy sobie sporo
pracy i kłopotów związanych z “żonglo-
waniem” typami kolorów oraz żmudnym
kopiowaniem bloków pamięci.
Powyższe uwagi najlepiej jest zoba-
czyć w formie diagramu, znajdującego się
na Rysunku 1. Jak można się domyśleć,
interfejs nie będzie trudny do zrealizowa-
nia. Jedynym bardziej skomplikowanym
elementem wydaje się sam algorytm
generowania stereogramu.
Ostatnie założenie, jakie chciałbym
przedstawić, jest bodaj najważniej-
sze: stereogramy najlepiej generować
na podstawie czarno-białych ilustra-
cji, a dokładniej z rysunków z paletą
w odcieniach szarości. Stosując taki rodzaj
palety można osiągnąć świetne wyniki.
Niezbędną konwersję obrazu możemy
wykonać programem GIMP , zamieniając
Na płycie CD/DVD
Na płycie CD/DVD znajduje się
kod źródłowy i wykonywalny
programu oraz
wszystkie listingi z artykułu.
Na początek kilka
postanowień
Nasz przyszły program napiszemy
w oparciu o środowisko GTK oraz
GNOME. Będziemy stosować najnowszą
stabilną wersje GNOME o numerze 2.6,
a bibliotekę GTK w wersji 2.4. Nie będzie-
my mozolnie kodować interfejsu, gdyż
użyjemy w tym celu programu GLADE.
Sam program będzie realizował tylko
podstawowe funkcje, takie jak wczy-
tanie obrazu, konwersję na stereogram
oraz jego zapis. Dodamy jeszcze funkcję
wydruku, ponieważ dość łatwo zreali-
zujemy ją przy pomocy API biblioteki
libgnomeprint .
Pomyślmy, jakie najważniejsze zda-
rzenia będą zachodzić w naszym pro-
gramie. Jedną z pierwszych czynności
jest wczytanie pliku graficznego do
programu. Można to zrealizować w łatwy
sposób, wykorzystując gotowy widget
GtkImage . Załadowanie do niego pliku
nie będzie wymagało dużej ilości kodu.
Podobnie w przypadku zapisu gotowego
stereogramu, znajdującego się w GtkIma-
ge – wystarczą dwie linie kodu.
O autorze:
Autor zajmuje się tworzeniem
oprogramowania dla WIN32
i Linuksa. Zainteresowania:
teoria języków programowania
oraz dobra literatura.
Kontakt z autorem:
autorzy@ lpmagazine.org
70 wrzesień 2004
W ielu Czytelników z pew-
439034163.024.png 439034163.025.png 439034163.026.png 439034163.027.png 439034163.001.png
stereogramy dla programistów
kolory na odcienie szarości. Należy rów-
nież wybrać tryb indeksowy, w którym
podamy ilość kolorów. Standardowo
powinniśmy deklarować 256 kolorów,
a raczej poziomów szarości. Dodam jesz-
cze, że rysunki nie powinny posiadać
dużej liczby szczegółów.
Algorytm generowania
stereogramu
Tworzenie stereogramu opiera się na
dość prostej zasadzie. Jako pierw-
szy tworzymy tzw. wzór bazowy. W
naszym programie będzie to losowy
układ pikseli, ale w istocie może to
być cokolwiek, np. fragment obrazu
bądź litery.
Gdy mamy już gotowy wzór
bazowy, możemy przystąpić do
generowania stereogramu. Bierzemy
pierwszy piksel obrazu i sprawdzamy
jego wartość. Jeśli jest równa zeru,
to przenosimy w to miejsce pierwszy
piksel (albo element) wzoru bazowe-
go. Następnie badamy kolejny piksel
obrazu. Jeśli i on będzie równy zeru,
to kopiujemy następny piksel naszego
wzorca. Jeśli nadal będą występować
zera, a nasz wzór jest znacznie krót-
szy niż przetwarzany obraz, to później
będziemy kopiować piksele z już prze-
tworzonego obrazu. Z tego powodu,
jeśli linia obrazu składa się wyłącznie
z zer, to zobaczymy powtarzający się
wzór bazowy – po przeniesieniu całego
wzoru bazowego, analizując linię,
będziemy już przenosić nie elementy
wzorca, ale piksele zawarte w linii
obrazu.
Gdyby piksel miał wartość jeden, to
skopiujemy następny punkt ze wzorca,
np. jeśli aktualnie wskazujemy na trzeci
piksel wzorca, to przenosimy piksel
czwarty. Gdyby badany punkt miałby
wartość dwa, to przeniesiemy piąty
piksel wzorca. Ogólnie, jeśli badany
piksel ma wartość n , a pozycja we wzorcu
ma numer i , to przenosimy piksel z pozy-
cji i+n .
Wypróbujmy teraz nasz sposób
generowania stereogramów na pro-
stym przykładzie. Mamy następujący
rysunek:
Oglądanie stereogramów
Podstawowa zasada oglądania stereo-
gramów polega na skupianiu wzroku
poza obrazem. Powinniśmy niejako
spoglądać przez kartkę i skupiać wzrok
mniej więcej 40-50 cm za kartką.
Jednym z łatwiejszych sposób oglądania
stereogramów jest przybliżenie kartki do
nosa i powolne jej oddalanie. Jeśli będzie-
my utrzymywać to samo skupienie i kieru-
nek wzroku, po paru próbach powinniśmy
zobaczyć przestrzenny obraz. Dość
często łatwiej ogląda się stereogram na
ekranie monitora. Istnieje jeszcze jeden
sposób, który może pomóc, a mianowicie
przeniesienie stereogramu na przezro-
czystą folię i patrzenie przez folię skupia-
jąc wzrok na jakimś przedmiocie.
Powyższy rysunek prezentuje pewien
obraz do testów. Nie zdradzę w tym miej-
scu, co przedstawia.
Niech wzorem bazowym będzie ciąg
znaków: abcde . Pierwszy znak naszego
obrazu to zero, więc przenosimy pierw-
szy znak wzorca, czyli „a”. Przechodzi-
my do następnego punktu, zarówno
w obrazie, jak i we wzorcu. Ponownie
mamy zero, więc przenosimy literę „b”.
Ponieważ pierwszy wiersz składa się
wyłącznie z zer, to nastąpi dokładne
przepisanie wzorca. Przejdźmy teraz
do drugiej linii. Wartość pierwsza - zero
- przeniesie nam pierwszy znak wzorca,
ale drugi badany element zawiera jedyn-
kę. Zgodnie z naszym algorytmem, prze-
niesiemy następny znak po aktualnie
wskazywanym, więc nie będzie to litera
„b”, ale kolejna we wzorcu litera „c”.
W następnym badanym elemencie
sytuacja powtarza się. Ponownie mamy
jedynkę, a we wzorcu jesteśmy na pozy-
cji litery „c”, więc kopiujemy następny
znak – literę „d”. Gdyby zamiast jedynki
była dwójka, a we wzorze bylibyśmy
na pozycji „c”, to należałoby przenieść
literę „e”. Po wszystkich zmianach otrzy-
mamy następujący obraz:
abcde
acdee
acdee
acdee
abcde
Ostatecznie, aby ułatwić oglądanie ste-
reogramu, dodamy wzorzec „abcde” na
początek i koniec każdej linii obrazu
powyżej. Nasz tekstowy stereogram
przyjmie następującą postać:
abcdeabcdeabcde
abcdeacdeeabcde
abcdeacdeeabcde
abcdeacdeeabcde
abcdeabcdeabcde
00000
01110
01110
01110
00000
Generowanie stereogramów jest, jak
widać z powyższego przykładu, łatwym
zadaniem. Widać również, dlaczego
www.lpmagazine.org
71
439034163.002.png 439034163.003.png 439034163.004.png 439034163.005.png
 
dla programistów
sekcji: XResolution/sections . Liczba
sekcji ma również duże znaczenie i tak
naprawdę nie powinna być większa niż 8
(w ostateczności może być ich 10).
Oznacza to ponadto, że wzór bazowy
jest umieszczany na początku każdej linii
bezpośrednio w obrazie. Z tego powodu
lepiej tworzyć obrazy wyśrodkowane
i nieprzylegające do krawędzi.
Sam proces generowania wzoru spro-
wadza się do następującej linii kodu:
in_buf[x]=rand() % 256;
Rysunek 1. Schemat zdarzeń w programie generującym stereogramy
Losujemy tu liczbę z zakresu od 0 do
255, wykorzystując funkcję rand . Ponie-
waż paleta jest w odcieniach szarości
(a przynajmniej taka powinna być, zgod-
nie z naszymi wcześniejszymi założe-
niami), to wylosowane punkty będą się
układać w czarno-biały wzór. Za każdym
razem wzór będzie inny, więc nawet gdy
tworzymy po raz drugi stereogram z tego
samego obrazu, to otrzymamy inny wzór
bazowy. W efekcie nowy stereogram
będzie różnił się od poprzedniego.
Zadaniem drugiej pętli, jak głosi
poprzedzający ją komentarz, jest utwo-
rzenie stereogramu. Podobnie jak
w przypadku generowania wzoru, odczy-
tujemy wiersz obrazu i dokonujemy na
nim odpowiednich operacji. Stereogram
powstaje z danych tuż po wzorze bazo-
wym, dlatego w pętli wewnętrznej warto-
ścią początkową zmiennej x jest wartość
XResolution/sections . Zwróćmy uwagę
na to, że używamy też drugiej zmiennej i
(jej wartością początkową jest zero).
Możemy teraz przystąpić do genero-
wania stereogramu. Odczytujemy aktual-
nie badany piksel (jego numer zawiera
zmienna x ). Jeśli piksel posiada wartość
zero (jest czarny), to na jego miejsce
jest przenoszony piksel o indeksie i .
Zwróćmy uwagę, że i na początku wska-
zuje na wzór bazowy. Jeśli jednak piksel
jest większy od zera, to wybieramy
piksel, zgodnie z naszym algorytmem,
przesunięty o jeden plus wartość piksela
podzieloną przez szesnaście. Następnie,
w obydwu przypadkach, przesuwamy
się we wzorze o jeden piksel, czyli
zwiększamy wartość i o jeden.
Wcześniej, omawiając algorytm, nie
wykonywaliśmy żadnych dodatkowych
operacji, ale dzielenie jest dość ważną
operacją, ponieważ zabezpiecza nas
przed zbyt dużymi przesunięciami.
Operację dzielenia traktujemy także jako
powinniśmy stosować paletę o 256
poziomach szarości. Jeśli w takiej palecie
zero będzie oznaczać kolor czarny, a war-
tość 256 kolor biały, to pozostałe wartości
reprezentują kolory pośrednie. Jest zupeł-
nie naturalne, że możemy traktować sza-
rości jako poziomy głębi. Wykorzystując
odpowiednie przesunięcia wzorca, kodu-
jemy wrażenie głębi.
Jednak, aby dostrzec stereogram,
należy na niego spojrzeć w odpowiedni
sposób. Kilka przydatnych uwag zawiera
ramka Oglądanie stereogramów . Czy-
telników zainteresowanych dokładniej-
szymi informacjami odsyłam do książki
Grafika PC bez tajemnic “, wydanej przez
wydawnictwo Intersoftland w 1995 roku.
nego wiersza to zadanie dla funkcji get_
raster_line . Po wykonaniu czynności
na wierszu, musimy przetworzone dane,
zawarte w buforze, umieścić z powrotem
w obrazie i to zadanie wykonuje funkcja
put_raster_line .
Na początku każdej linii umiesz-
czamy wzór bazowy, a są to po prostu
losowe punkty z palety. Działamy tu
w trochę inny sposób niż w przedstawio-
nym wcześniej opisie algorytmu, gdyż
każda linia posiada swój własny wzór
bazowy. Ponieważ jest to losowy układ
pikseli, to nie wpływa to na ostateczną
postać stereogramu.
Gdy spojrzymy na stereogramy dołą-
czone do artykułu, to widać, że mają
one powtarzające się paski. Owe paski
to sekcje obrazu. Ich zadaniem jest uła-
twienie oglądania stereogramu – łatwiej
skupić wzrok na centrum stereogramu,
gdy powtarzają się na nim pewne wzory.
Z tego powodu cały obraz został podzie-
lony na sekcje i długość wzoru bazowego
jest równa długości sekcji, którą wyzna-
czamy dzieląc rozdzielczość przez liczbę
Implementacja algorytmu
W poprzednim punkcie przedstawiłem
działanie algorytmu, a teraz zajmiemy się
jego implementacją.
Na początku należy utworzyć wzór
podstawowy. Na Listingu 1 jest to pierw-
sza pętla for . W pętli tej przeglądamy
cały obraz linia po linii. Odczytanie jed-
72
wrzesień 2004
439034163.006.png 439034163.007.png 439034163.008.png 439034163.009.png 439034163.010.png 439034163.011.png
 
stereogramy dla programistów
Krótki przepis
na stereogram
Tworzenie stereogramu rozpoczy-
namy od utworzenia rysunku z tzw.
mapą głębokości. Zgodnie z naszymi
założeniami, jest to obraz w odcie-
niach szarości. Kolor czarny oznacza
najbliżej położony obszar, a kolor
biały – najdalej. Tego rodzaju rysunek
z powodzeniem można przygotować
samodzielnie, czego przykładem jest
poniższe „dzieło”:
Listing 1. Procedura tworząca stereogram
void my_make_sirds_image () {
int x , y , i ;
/* tworzenie wzoru */
for ( y = 0 ; y < YResolution ; y ++) {
get_raster_line ( 0 , Xresolution , y , & in_buf [ 0 ]);
for ( x = 0 ; x < ( XResolution / sections ) ; x ++ ) {
in_buf [ x ]= rand () % 255 ;
}
put_raster_line ( 0 , XResolution , y , & in_buf [ 0 ]);
}
/* tworzenie stereogramu */
for ( y = 0 ; y < YResolution ; y ++) {
get_raster_line ( 0 , XResolution , y , & in_buf [ 0 ]);
i = 0 ;
for ( x = XResolution / sections ; x < XResolution ; x ++ ) {
if ( in_buf [ x ]== 0 ) {
in_buf [ x ]= in_buf [ i ];
i ++;
continue ;
}
if ( in_buf [ x ]> 0 ) {
in_buf [ x ]= in_buf [ i + 1 + ( in_buf [ x ] / 16 )];
i ++;
continue ;
}
}
put_raster_line ( 0 , XResolution , y , & in_buf [ 0 ]);
}
}
Gdy dysponujemy rysunkiem, to
możemy go wczytać do naszej aplikacji
i wygenerować stereogram. Powinniśmy
otrzymać obraz podobny do poniższe-
go:
Otrzymany stereogram można dalej
przetwarzać, tzn. takie operacje, jak
skalowanie (w szczególności powięk-
szanie), obracanie czy kolorowanie,
nie niszczą zawartości stereogramu.
Prostym sposobem na uatrakcyjnienie
stereogramu jest nałożenie deseniu np.
prostego gradientu na bazie koloru zie-
lonego. W efekcie otrzymamy kolorowy
stereogram:
pewnego rodzaju skalowanie kolorów –
zamiast 256 stosujemy już tylko 16. Pole-
cam poeksperymentować z tą wartością,
aby przekonać się samemu, jak wpływa
na ostateczny obraz stereogramu.
W taki sposób przedstawia się imple-
mentacja naszego algorytmu. Jak widać,
generowanie stereogramów nie jest trud-
nym zadaniem. Algorytm można unowo-
cześnić wprowadzając kilka innowacji,
np. dodać kolorowe piksele albo określać
własny wzór bazowy.
Funkcją memcpy przenosimy dane ze
zmiennej srids_image do zmiennej
__data . Dane, jak widać, są odpo-
wiednio adresowane. Wyrażenie
y*XResolution przenosi nas na począ-
tek wiersza o numerze y . Następnie
przesuwamy się o from_x bajtów,
aby wskazać na początek potrzeb-
nego nam obszaru. Funkcja memcpy
w ostatnim argumencie oczekuje
podania ilości bajtów do skopiowa-
nia. Będzie to różnica pomiędzy to_x
i from_x , czyli końcem fragmentu
wiersza, który nas interesuje, a jego
początkiem.
W drugiej funkcji wszystkie
obliczenia pozostają niezmienione.
Zamiana dotyczy dwóch pierw-
szych argumentów. Zamieniamy je
miejscami, ponieważ tym razem
przenosimy dane ze zmiennej
__data pod odpowiednie miejsce
w sirds_image :
Odczytywanie i zapis
wiersza obrazu
W implementacji algorytmu używamy
dwóch sprytnych funkcji do odczytu
wiersza ( get_raster_line ) i do jego
zapisu ( put_raster_line ). Obydwie
funkcje to właściwie tylko jedna linia
kodu, zawierająca wywołanie memcpy .
Treść pierwszej funkcji przedstawia się
następująco:
void get_raster_line S
(int from_x, int to_x, int y, S
unsigned char *__data){
memcpy((void*)__data, (void*) S
(sirds_image + (y*XResolution) + S
from_x), to_x – from_x);
}
void put_raster_line S
(int from_x, int to_x, int y, S
unsigned char *__data){
memcpy((void*)(sirds_image + S
(y*XResolution) + from_x), S
(void*)__data, to_x – from_x);
}
www.lpmagazine.org
73
439034163.012.png 439034163.013.png 439034163.014.png 439034163.015.png
 
dla programistów
Listing 2. Treść funkcji
on_SirdsGenerate_MNU_activate
srand ( time ( 0 ));
ilInit ();
iluInit ();
ilEnable ( IL_ORIGIN_SET );
ilOriginFunc ( IL_ORIGIN_UPPER_LEFT );
ilGenImages ( 1 , & ImgId );
ilBindImage ( ImgId );
load_image (& filename [ 0 ]);
my_make_sirds_image ();
save_sirds_image
( "/tmp/tmp_image.png" );
ilDeleteImages ( 1 , & ImgId );
gtk_image_set_from_file
( GTK_IMAGE ( ImageWidget ) ,
"/tmp/tmp_image.png" );
ge , więc musimy uzyskać wskazanie
na widget o nazwie ImageWidget . Tym
zajmuje się trzecia linijka kodu z funkcji
main :
okna wybrania katalogu i utworzenia
katalogu. Nas będzie interesować na
razie pierwszy typ okna. Z tego powodu
podaliśmy identyfikator GTK_FILE_CHO-
OSER_ACTION_OPEN . Następne argumenty
precyzują wartości, jakie są zwracane
w zależności od wciśniętego przycisku:
podajemy je parami. Wartość GTK_STOCK_
OPEN oznacza przycisk Otwórz . Po niej
została podana wartość, która zostanie
przekazana, gdy użytkownik wciśnie
ten przycisk. Sytuacja wygląda podobnie
dla następnej pary argumentów: GTK_
STOCK_CANCEL oznacza przycisk Anuluj
i jeśli użytkownik wciśnie ten przycisk,
jako wynik zostanie przekazana wartość
GTK_RESPONSE_CANCEL .
Pozostało nam uruchomienie okna
dialogowego funkcją gtk_dialog_run .
Gdy użytkownik wciśnie jeden z dwóch
wspomnianych przycisków, funkcja
gtk_dialog_run zakończy swoje działa-
nie i zwróci jako wynik jedną z dwóch
podanych wartości: GTK_RESPONSE_ACCEPT
albo GTK_RESPONSE_CANCEL . Przy pomocy
instrukcji warunkowej sprawdzamy, czy
jest to pierwsza z wartości. Przedstawia
się to następująco:
ImageWidget=glade_xml_get_widget S
(xml, "ImageWidget");
Zmienną ImageWidget zadeklarowaliśmy
w sposób normalny dla GTK: GtkWidget
*ImageWidget; .
Pozostały nam jeszcze dwie linie.
Pierwszą podłączamy wszystkie zdefinio-
wane sygnały:
glade_xml_signal_autoconnect(xml);
Program dla środowiska
GNOME/GTK
Gdy mamy już gotowy algorytm gene-
rujący stereogram, to napisanie samego
programu nie będzie trudnym zadaniem.
Tworzenie programu rozpoczynamy
od zbudowania interfejsu w programie
GLADE . Rysunek 2 przedstawia główne
okno naszej aplikacji. Tworzenie inter-
fejsu jest łatwym zadaniem, więc nie
będę go tutaj szerzej omawiał. Zwróćmy
jednak uwagę na to, że menu oraz pasek
z przyciskami są umieszczone w kompo-
nentach GtkHandleBox . Ostatecznie, nasz
program będzie korzystał głównie z kom-
ponentów GTK. Elementy środowiska
GNOME wykorzystamy do implementa-
cji wydruku oraz w oknie dialogowym
O Programie .
Utworzony plik, zawierający
interfejs, np. sirds_app.glade , zosta-
nie wczytany przez naszą aplikację
dzięki bibliotece libglade . Bibliote-
ka libglade posiada cenną cechę,
a mianowicie potrafi samodzielnie
podłączyć sygnały (zdarzenia) do ist-
niejących funkcji, jeśli tylko zgadzają
się nazwy zdarzeń oraz funkcji. To
bardzo upraszcza proces ładowania
i podłączania zdarzeń, bowiem wszyst-
kie niezbędne czynności dokonywane
w funkcji main sprowadzają się do
pięciu linii kodu. W dwóch pierwszych
dokonujemy inicjalizacji biblioteki GTK
oraz ładujemy plik z opisem interfejsu:
a drugą (najważniejszą instrukcją) uru-
chamiamy nasz program:
gtk_main()
Wczytanie
oraz zapis obrazu
Tak naprawdę, aby załadować obraz
z pliku do komponentu GtkImage , wystar-
czy wywołać jedną funkcję o nazwie
gtk_image_set_from_file . Wcześniej użyt-
kownik musi jednak wybrać plik, który
chce wczytać. Nasz program piszemy
w oparciu o najnowszą wersję środowiska
GNOME, więc skorzystamy z nowego
okna dialogowego do wyboru plików.
Pierwszym krokiem jest zadeklarowa-
nie zmiennej okna dialogowego: GtkWid-
get *dialog; . Oprogramowanie nowego
okna dialogowego jest znacznie mniej
kłopotliwe niż poprzednio stosowane
rozwiązanie – wystarczy utworzyć nowy
widget wywołaniem gtk_file_chooser_
dialog_new :
if (gtk_dialog_run
(GTK_DIALOG (dialog)) == GTK_RESPONSE_ S
ACCEPT){
...
}
Sam proces ładowania obrazu do widgetu
GtkImage wymaga poznania nazwy pliku.
W naszym programie nazwę przenosimy
do zmiennej filename :
strcpy(&filename[0], S
gtk_file_chooser_get_filename S
(GTK_FILE_CHOOSER (dialog)));
dialog = gtk_file_chooser_dialog_new S
("Wybierz plik", NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
NULL);
Teraz wystarczy wywołanie gtk_image_
set_from_file , gdzie w drugim argu-
Funkcja przyjmuje wiele parametrów.
W pierwszym podajemy oczywiście tytuł
okna. W drugim powinniśmy wskazać
okno, które jest właścicielem naszego
okienka dialogowego, ale podanie war-
tości NULL w niczym nie przeszkadza.
W trzecim parametrze podajemy, jaki
typ okna dialogowego nas interesuje.
Istnieją cztery podstawowe typy: okno
otwarcia pliku, okno zapisu pliku oraz
gtk_init(&argc, &argv);
xml = glade_xml_new("glade/sirds_ S
app.glade", NULL, NULL);
W naszej aplikacji będziemy ładować
obraz z pliku do widgetu GtkImage bądź
zapisywać na dysk zawartość GtkIma-
Rysunek 2. Interfejs programu w GLADE
74
wrzesień 2004
439034163.016.png 439034163.017.png 439034163.018.png 439034163.019.png 439034163.020.png 439034163.021.png 439034163.022.png 439034163.023.png
Zgłoś jeśli naruszono regulamin