Gadu gadu Skype
sie
23

.NET Compact Framework w Visual Studio Express

Spook, Sierpień 23 2010

Skomentowany 5 razy

Ostatnio bardzo często spotykam się w Internecie z pytaniem, czy istnieje możliwość pisania w wersjach Express Visual Studio programów na platformę .NET Compact Framework. Oficjalnie jest to niemożliwe: polityka marketingowa Microsoftu zadecydowała o włączeniu do środowiska wsparcia dla .NET CF dopiero od wersji Professional (dla zainteresowanych, około 3.5k PLN za jedną licencję BOX). Okazuje się jednak, że taka możliwość istnieje. Zaznaczam, iż pomysł nie jest mój, ale mimo usilnych poszukiwań, nie udało mi się odnaleźć pierwotnego artykułu, na bazie którego przygotowałem moje środowisko pod kompilację dla urządzeń mobilnych.

Rozwiązanie jest następujące:

Ekran Windows Mobile z .NET CF Assemblies

  1. Instalujemy na urządzeniu mobilnym .NET Compact Framework 3.5; jeśli takowego nie posiadamy, albo z innego powodu nie chcemy instalować na nim środowiska uruchomieniowego, możemy posłużyć się darmowym emulatorem urządzenia Windows Mobile. Nie zapomnijmy tylko o doinstalowaniu obrazów systemu Windows Mobile. Dodam tylko, że emulator jest uruchamiany z linii poleceń.
  2. Odszukujemy w urządzeniu, w katalogu \Windows serię plików GAC_*.dll (zobacz screen). Każdy z nich stanowi pojedynczą assembly dla .NET CF. Kopiujemy wszystkie (uważamy tylko na wersję – jest w nazwie pliku) na komputer stacjonarny i umieszczamy w wygodnym dla nas katalogu (w moim przypadku jest to D:\Dokumenty\C\C#\CF_Assemblies\3.5).
  3. Zmieniamy nazwy plików według klucza:GAC_mscorlib_v3_5_0_0_cneutral_1.dllnamscorlib.dll
  4. Upewniamy się, że na komputerze jest zainstalowane .NET Framework 3.5 (będziemy korzystali z kompilatora csc.exe, dołączanego do pakietu)
  5. W katalogu projektu C#, który będziemy chcieli kompilować dla .NET CF tworzymy plik wsadowy o następującej treści:
    set compilerdir="C:\windows\Microsoft.NET\Framework\v3.5"
    set asmdir="D:\Dokumenty\C\C#\CF_Assemblies\3.5"
    
    set projectdir="D:\Dokumenty\C\C#\CF\Hello World\"
    %compilerdir%\csc.exe /noconfig /nostdlib /debug+ /optimize-
      /define:DEBUG;MOBILE /out:"%projectdir%HelloWorld.exe"
      /r:%asmdir%\mscorlib.dll /r:%asmdir%\System.dll
      /r:%asmdir%\System.Data.dll /r:%asmdir%\System.Drawing.dll
      /r:%asmdir%\System.Windows.Forms.dll "%projectdir%Form1.cs"
      "%projectdir%Form1.Designer.cs" "%projectdir%Program.cs"
    
    pause
  6. Dla wygody możemy skonfigurować Visual Studio w taki sposób, by po wywołaniu polecenia z menu External Tools był wywoływany plik compile.bat z katalogu projektu. Zadanie to pozostawimy jednak jako ćwiczenie dla studenta :)

I to by było na tyle. Efekt działania przykładowej aplikacji można podziwiać poniżej.

Przykładowy program .NET CF

Na koniec kilka notatek. Po pierwsze, musimy cały czas mieć na uwadze, że o ile VS C# Express nie będzie nam przeszkadzało w projektowaniu aplikacji dla .NET Compact Frameworka, to z drugiej strony nie będzie nam też pomagało. Mam tu na myśli na przykład fakt, iż designer formatki będzie ją projektował pod .NET dla win32, więc – na przykład – po narysowaniu przycisku na formatce i próbie kompilacji dla .NET CF kompilator przerwie kompilację z następującym komunikatem:

Kompilator Microsoft (R) Visual C# 2008 w wersji 3.5.30729.4926
dla programu Microsoft (R) .NET Framework w wersji 3.5
Copyright (C) Microsoft Corporation. Wszelkie prawa zastrzeżone.

d:\Dokumenty\C\C#\CF\Hello World CF\Form1.Designer.cs(51,26): error CS1061:
        Element "System.Windows.Forms.Button" nie zawiera definicji
        "UseVisualStyleBackColor", a nie odnaleziono metody rozszerzającej
        "UseVisualStyleBackColor", która przyjmuje pierwszy argument typu
        "System.Windows.Forms.Button" (czy nie brakuje dyrektywy using lub
        odwołania do zestawu?).

W takiej sytuacji wystarczy zajrzeć do Form1.Designer.cs i usunąć linijkę, w której następuje przypisanie do nieistniejącej w CF własności UseVisualStyleBackColor.

Sprytny programista wpadnie pewnie na jeszcze jeden ciekawy pomysł – otóż assemblies .NET CF można dołączać jako referencje (References) do projektu. Korzyści z takiego rozwiązania są ogromne – natychmiast po dodaniu zacznie działać Code Insight, podpowiadając nam namespace’y, klasy i ich metody oraz własności, co jest bezcenne w przypadku assemblies nie występujących w przypadku win32 – przykładowo Microsoft.WindowsMobile.PocketOutlook.dll

Zachęcam do dzielenia się opiniami na temat programowania dla .NET CF w Visual Studio Express. Może wymyślicie jeszcze ciekawsze usprawnienia?

paź
11

Sudety

Spook, Październik 11 2008

Napisz komentarz

Stoisz na rozstaju dróg. Jest słoneczny, letni poranek, rosa skrzy się na trawie; na nitkach pajęczyny wygląda jak przezroczyste perły. Kropelki wody porozwieszane pomiędzy gałęziami sprawiają wrażenie, jak gdyby ktoś przyozdobił drzewa diamentami. Rozglądasz się; widzisz rozlane, niewielkie leśne jeziorko. Jego powierzchnia jest gładka, marszczona gdzieniegdzie przez poranną bryzę, która niesie Ci zapach lasu. Na brzegu – postrzępiony kapelusz wędkarza, który skoro rano wybrał się na wczesny połów. Obracasz się powoli – słońce przebłyskujące pomiędzy gałęziami drzew wydaje się świecić na zielono. Otacza Cię soczysta, głęboka, żywa zieleń przyprószona tu i ówdzie błękitnymi plamkami niezapominajek albo czerwonym kapeluszem muchomora. Robisz kilka kroków: żwir chrzęści pod Twoimi stopami, a wygrzewające się na poboczu ropuchy niechętnie ustępują Ci drogi. Trącasz jakąś trawę z której zrywa się latająca paleta kolorów – motyl. Robi przed Tobą kilka wdzięcznych ósemek, po czym odlatuje w zacienione, jeszcze, gąszcze lasu.

Stoisz na skale wysuniętej poza zbocza wzgórza na które przed chwilą mozolnie się piąłeś. Rozglądasz się – widzisz głęboki, gęsto zadrzewiony wąwóz, na dnie którego płynie cicho pomarańczowy – od wypłukiwanych tu i ówdzie złóż żelaza – strumyk. Czujesz podmuch wiatru, ale nie jest to już spokojna bryza, ale żywy wiatr tych wzgórz. Zamykasz oczy – i nie słyszysz już szumu drzew, ale czujesz go podróżując wraz z wiatrem, który wciągnął Cię w szaloną podróż. Przelatujesz wąwozem, pokonujesz przełęcz i mkniesz ponad zielonymi płaskowyżami ku dalekim wzniesieniom. A może zawracasz – by przez zielone wrota wylać się na szerokie równiny pokryte szachownicami zasianych pól, czerwienią dachówek pokrywających domy okolicznych wiosek, i błękitem niewielkich jeziorek i strumyków?

Skręcasz z drogi, wijącej się wśród wąwozów i przełęczy by nagle, ku swojemu zdziwieniu, pomiędzy szczytami pobliskich wzniesień dostrzec szeroko rozlane jezioro. Zamyka je tama – jak gdyby zawieszona na sąsiednich szczytach. Na jednym z brzegów pastelowymi kolorami mienią się niewielkie domki, spokojne fale syzyfową pracą próbują podmyć piaszczyste wybrzeże. Wchodzisz na rozchybotany, wiszący mostek. Przed Tobą, w oddali bieli się żagiel, pod Tobą przepływa mała łódka; pozostawia za sobą kilwater, który znika powoli, rozmywając się coraz bardziej na lustrzanej płaszczyźnie. Wchodzisz na tamę; z jednej strony widzisz jezioro, druga znów kusi Cię, byś wzleciał i jak myszołów pomknął nad głęboko werżniętą w góry dolinką, widząc od czasu do czasu stadka krów i owiec albo konopiastogrzywą klacz pasącą się na łące.

***

A Teraz siedzisz w pociągu i z rozrywającym serce żalem widzisz Twoje wzgórza oddalające się od Ciebie w rytm stukotu kół na szynach. Zaciśnięta kurczowo na poręczy ręka drży, bo chciałbyś wyrwać się, uciec, wrócić – choć wiesz, że nie możesz. Jedziesz odwiedzić cywilizację: rozkopane ulice, brudne dzielnice z dziećmi bawiącymi się w błocie podwórek; długie oczekiwania na zatłoczony autobus; ciągnące sie w nieskończoność korki – zrezygnowane i zmęczone twarze ludzi; betonowo-stalowe zbrojenia, które teraz muszą zastąpić Ci korzenie drzew; falujące, wzburzone morze nieznajomych, często wrogich Ci twarzy.

A Twoje wzgórza będą czekać… najpierw postarzeje się wiatr – i zamiast hasać radośnie pośród drzew zacznie zrywać ich liście, które pokryją kolorowym dywanem leśną ściółkę. Potem uśnie, otoczony płynącą bielą, która zagłuszy leśne bicie serca. Drewniane szkielety będą skrzypieć, gnąc się pod naporem śniegu, skarżąc się – świadome swej bezsilności – na samotniczy los.

A później zbudzi się życie – zielone pędy będą walczyć na zacienionej przez starszyznę ziemi o swój promyk słońca, drzewa wypełnią się zielenią, a wiatr znów będzie zapraszał do podróży.

A Ty? Przystaniesz czasami zdumiony, bo w głębi miasta poczujesz nagle zapach zieleni, zapach wolności, która wciąż ciągnie Cię w Twoje strony. A to tylko niegościnny, miejski wiatr zagarnął w Twoje nozdrza złudny zapach z pobliskiego parku…

lut
3

Atlantyda

Spook, Luty 3 2008

Napisz komentarz

Atlantyda – mityczna wyspa, o której dowiadujemy się z ust Platona. Zamieszkana przez ludzi żyjących w pokoju i harmonii; oprócz wspaniałych świątyń i ogrodów otaczających zabudowę miast, królowała na niej nowoczesna technika – według niektórych nawet bardziej zaawansowana od współczesnej.

Tajemnicza: poza źródłowym zapisem Platona w jego księgach (Timajos i Kritias), właściwie nic o niej nie wiemy. Możemy jedynie spekulować o tym, jaka była jej historia, jak wyglądała, jacy byli ludzie, którzy na niej żyli. Niezgłębioną tajemnicą pozostają również jej ostatnie dni – nie wiadomo, czy za jej zniszczenie odpowiada trzęsienie ziemi, wybuch wulkanu, czy inny równie niszczycielski kataklizm. A może wcale nie została zniszczona?

Inspirująca: urzeka swą tajemniczością i marzeniami o Utopii, świecie pokoju, piękna i harmonii. Wielu twórców poddało się jej urokowi i tak powstało wiele książek, filmów, obrazów, albumów muzycznych, nawet gier komputerowych, które starają się przenieść odbiorcę w to niesamowite miejsce.

Atlantydę, ustami Sophii Hapgood, twórcy gry „Indiana Jones and the Fate of Atlantis” opisują następująco:

Here, my friends, is Atlantis – as it might have appeared in its heyday. Glorious, prosperous, socially and technically advanced – beyond our wildest dreams. 5000 years ago – when everyone else still wore animal skins, the mighty spirits of Atlantis dared to build the city where knowledge and power were united in true happiness. Centuries later, the famous philosopher Plato wrote about it; he placed Atlantis on the continent out in the deep ocean.

Choć Atlantyda wydaje się być jedynie mitem, greckim podaniem ludowym usłyszanym i spisanym przez Platona, wielu ludzi wierzy w jej istnienie i nie zaprzestaje jej poszukiwań – prowadzonych naukowymi metodami. Polska Wikipedia informuje:

Mityczną wyspę umiejscawiano w różnych punktach na kuli ziemskiej:
u wybrzeży położonej na peryferiach Europy Skandynawii (autorem tej XVII-wiecznej koncepcji jest Olof Rudbeck),
w rejonie Spitsbergenu, na półkuli południowej (atlantyckie wyspy: Wniebowstąpienia i Św. Heleny miały być jej pozostałościami).

Później skupiono się ponownie na basenie Morza Śródziemnego, gdzie najczęściej wskazywano na wyspę Santoryn (Thira) na Morzu Egejskim. Potwierdzeniem istnienia Atlantydy na tym obszarze miały być wykopaliska prowadzone na Krecie, które wykazały ślady nieznanej dotąd kultury (minojskiej).

Doszukiwano się śladów zatopionego kontynentu w wyspach na Atlantyku: Maderze, Azorach i Wyspach Kanaryjskich. Na dwóch pierwszych nie istniało jednak przed ich odkryciem przez Europejczyków w XIV w. żadne osadnictwo, mieszkańcy Wysp Kanaryjskich, Guanczowie, odznaczający się rozwiniętą kulturą i techniką, zostali jednak wytępieni wcześniej przez Hiszpanów.

Wielu zwolenników ma teoria istnienia Atlantydy w Andach, w okolicach jeziora Titicaca. Stosowną teorię ukuł James M. Allen. Stwierdził on, że cała dzisiejsza Ameryka Południowa była podzielona na 10 królestw. Atlantyda miała się znajdować na płaskowyżu na terenie dzisiejszej Boliwii. Uwiarygodnieniem tej teorii miało być odkrycie na głębokości 27 metrów tajemniczych ruin budowli pod powierzchnią jeziora Titicaca. Dotyczy to również ruin miasta Tiahuanaco. Znaleziska odkryte na jego terenie sugerują, iż jego mieszkańcy opanowali zaawansowane technologie, jak obróbkę metali (wytop w temperaturze +1600oC, co oficjalnie opanowano dopiero w latach 30 XX wieku). Jego ludność obeznana była także ze stawianiem struktur, których elementy były idealnie dopasowane do siebie, niemal z chirurgiczną precyzją. Natomiast wiek Tihuanaco do dziś nie jest jasno określony. Skrajna teoria szacuje go na 16 tysięcy lat, inna na początek I tysiąclecia naszej ery.

Niepewne poszlaki wskazywały również na Karaiby, Morze Północne, Kaukaz i Amazonię. Istnieje też pogląd, jakoby Atlantydą była Antarktyda przed jej zlodowaceniem. Jego zwolennicy powołują się na mapę Orontiusa Fineusa.

Atlantydę identyfikuje się również z południowohiszpańskim antycznym miastem Tartessos.

Zwolennicy innych teorii zakładali, że niedobitki Atlantów (mieszkańców Atlantydy), ocalałych po zatopieniu wyspy, rozproszyły się po świecie, dając podwaliny pod wszystkie cywilizacje Ameryki, Azji i Europy.

Każdego roku powstają nowe koncepcje. W listopadzie 2004 roku amerykańscy naukowcy stwierdzili, że odkryli pozostałości Atlantydy na dnie morskim między Cyprem a Syrią. Pięć miesięcy wcześniej inni naukowcy wypatrzyli Atlantydę na zdjęciach satelitarnych południowej Hiszpanii. W obu przypadkach odkrywcy twierdzą, że to, co znaleźli, dokładnie pasuje do opisu Platona.

Najbardziej racjonalną wydaje się teoria, że mityczną Atlantydą jest Kreta. Według zwolenników tej teorii zagłada kultury minojskiej przypomina kataklizm opisany przez Platona. Podczas erupcji olbrzymiego wulkanu na Thirze powstała gigantyczna fala tsunami, która zniszczyła portowe miasta Krety, dla której handel morski stanowił podstawę gospodarki. Ponadto olbrzymie ilości pyłu wyrzucone podczas eksplozji w atmosferę doprowadziły do zmian klimatycznych trwających około 10 lat (ślady tych popiołów znaleziono, między innymi, w lodowcach Grenlandii), które sprowadziły nieurodzaj, co osłabiło gospodarkę minojskiej Krety. Osłabienie potężnego sąsiada wykorzystali Mykeńczycy z kontynentalnej Grecji, którzy ostatecznie podbili wyspę (czego śladem mają być opisy wojen Greków z Atlantami).

Odnalezione do tej pory dowody są tak nikłe, że o istnieniu Atlantydy można wypowiadać się tylko w terminach wiary. Co więcej, rozsądek podpowiada, że Atlantyda nie tyle nie istniała, co jest odzwierciedleniem jednej ze starożytnych cywilizacji, niefortunnie opisanej w Księgach przez Platona.

A ja jednak wierzę w istnienie Atlantydy – dokładnie takiej, jaka opisywana jest w literaturze czy pokazywana na ekranach telewizorów czy wyświetlaczy komputerowych: wspaniała, dumna, pełna pokoju i harmonii współgrającej z nowoczesną techniką wspomagającą życie jej mieszkańców. Jest to wiara nie poparta ani powodowana jakimikolwiek przesłankami, dowodami czy faktami, nie skłaniająca się ku żadnej współczesnej teorii – są to po prostu, jak to ujął autor jednego z artykułów, zaginione marzenia.

Wśród wszystkich utworów zainspirowanych Zaginionym Lądem, najbardziej godny uwagi wydaje mi się album Davida Arkenstone’a „Atlantis – A Symphonic Journey„. Wrażenie niesamowitej podróży przez czas do mitycznego lądu budują same nazwy poszczególnych utworów:

  1. The Dream Of The Gods
  2. Tower Of Light
  3. In The Gardens Of The Citadel
  4. The Temple Of Poseidon
  5. Jewel Of The Sea
  6. Festival Of The Goddess
  7. The Painted Sails
  8. Across The Great Oceans
  9. Fire And Water
  10. Below The Ocean – The Spirit Of Atlantis

Każdy utwór to osobna opowieść, pokazująca piękno Atlantydy, opisująca jej zagładę („Fire and Water„), a wreszcie przenosząca słuchacza do czasów współczesnych i opisująca – według mnie – podróż przez opustoszałe ulice, zniszczone świątynie i powalone pomniki zatopionego w odmętach oceanu miasta. Wreszcie dynamiczne zakończenie – będące jakby chwilowym powrotem do dni chwały, ostatnim hymnem ku chwale mieszkańców, którzy podzielili równie smutny, co okrutny los dumnego miasta.

Nieco okrojonej wersji utworu można posłuchać jako tła prezentacji znajdującej się w serwisie YouTube:

lis
3

Hubertus

Spook, Listopad 3 2007

Napisz komentarz

Dziś 3. listopada – patronem tego dnia jest święty Hubert.

Za Wikipedią:

Św. Hubert urodził się w 655 roku w Gaskonii, był potomkiem królewskiego rodu Merowingów. Zamiłowanie do polowania odziedziczył po swoim ojcu. Towarzyszył mu często na łowach. Ponoć w wieku 14 lat uratował ojcu życie podczas polowania na niedźwiedzia w Pirenejach. Pełnoletni Hubert udaje się na dwór króla Frankonii, gdzie poślubia córkę Pepina z Heristal. Miał z nią syna Floriberta, późniejszego następcę na biskupstwie Liege.

Młody Hubert najwięcej czasu spędzał w lasach, gdzie nieustannie polował, łowiectwo było jego pasją. Ponoć prowadził także swobodne, wręcz hulaszcze życie. Tak było do roku 695, kiedy polując w Górach Ardeńskich, nie bacząc na nic, w sam Wielki Piątek napotkał białego jelenia z promieniejącym krzyżem w wieńcu. Miał wtedy usłyszeć głos Stwórcy ostrzegający go za jego niepohamowaną pasję i nakazujący mu udać się do Lamberta – biskupa Maastricht – Tongres. Przejęty objawieniem, czyni jak mu głos nakazał. Udaje się na służbę bożą do biskupa Lamberta. Studiuje wiedzę kanoniczną i prowadzi działalność misjonarską w Ardenach i Brabancji. Po śmierci Biskupa Lamberta w 704 lub 705 roku, z rąk papieża Sergiusza otrzymuje sakrę biskupią.

3. listopada (lub w weekend poprzedzający lub następujący po tej dacie) we wszystkich większych stadninach i stajniach obchodzona jest hucznie zabawa zwana Hubertusem. Zaczyna się ona „pogonią za lisem” – jednemu z jeźdźców do lewego ramienia przypina się lisią kitę, którą pozostali jeźdźcy próbują zerwać. Alternatywą może być również sytuacja w której lisa ukrywa się gdzieś w lesie, a uczestnicy mają za zadanie odnalezienie go. Później następuje biesiada przy tradycyjnych potrawach – je się wtedy chleb ze smalcem, bigos oraz pieczoną dziczyznę.

Hubertus jest również obchodzony przez myśliwych – odbywają się wtedy uroczyste polowania podczas których zachowywane są historyczne wzorce i ceremoniały. Środowiska jeździeckie zrezygnowały z tradycyjnego niegdyś polowania na lisa, bowiem „zabawa” ta jest wyjątkowo okrutna – podobno niejednokrotnie zdarzało się, że zaszczute zwierzę zdychało nie od kuli myśliwego, a z wycieńczenia.

Święty Hubert jest patronem myśliwych, jeźdźców, leśników, strzelców, sportowców, kuśnierzy, matematyków i metalowców. Dzisiejszy dzień możemy zatem nazwać dniem jeźdźca – z tej okazji wszystkim jeźdźcom oraz amazonkom życzę wszystkiego najlepszego!

lis
1

StringMatchesMask

Spook, Listopad 1 2007

Napisz komentarz

Potrzebowałem ostatnio funkcji, która sprawdzi, czy nazwa pliku pasuje do zadanej maski. W Internecie w wielu miejscach można znaleźć funkcję StringMatchesMask – jej pierwotna wersja leży chyba na Torrym. Problem polega jednak na tym, że stosuje strategię zachłanną podczas interpretacji gwiazdki, co powoduje z kolei, że stwierdzi, że nazwa adas.txt nie pasuje do wzorca *as.*.

Pozostało mi zatem napisanie poprawionej, rekurencyjnej wersji odpowiedniej funkcji. Rekordów prędkości pewnie nie pobije, ale za to działa poprawnie. Oto jej kod:

function StringMatchesMask(S, mask: string; 
  case_sensitive: Boolean = false): Boolean;

  function InternalStringMatchesMask(PS, PMask: PChar): boolean;

  begin
    while PMask^ <> #0 do
    begin
      case PMask^ of
        '?': begin
            if PS^ = #0 then
            begin
              result := false;
              exit
            end;
            inc(PMask);
            inc(PS);
          end;
        '*': begin
            inc(PMask);
            if PMask^ = #0 then
            begin
              result := true;
              exit
            end;

            while (PS^ <> #0) do
            begin
              if not (PMask^ in ['?', '*']) and (PMask^ <> PS^) then
              begin
                inc(PS);
                if PS^ = #0 then
                begin
                  result := false;
                  exit
                end;
              end else
              begin
                if InternalStringMatchesMask(PS, PMask) then
                begin
                  result := true;
                  exit
                end else
                begin
                  inc(PS^);
                  if PS^ = #0 then
                  begin
                    result := false;
                    exit
                  end;
                end;
              end;
            end;

            result := false;
            exit
          end;
      else begin
          if PMask^ = PS^ then
          begin
            inc(PMask);
            inc(PS);
          end else
          begin
            result := false;
            exit
          end;
        end;
      end;
    end;
    if PS^ = #0 then
      result := true else
      result := false;
  end;

begin
if case_sensitive then
   result:=InternalStringMatchesMask(PChar(s),
                                     PChar(mask)) else
   result:=InternalStringMatchesMask(PChar(UpperCase(s)),
                                     PChar(UpperCase(mask)));
end;
paź
31

HDRI

Spook, Październik 31 2007

Napisz komentarz

Wyobraźmy sobie krajobraz: spod nóg aż po horyzont rozpościerają się łąki, w tle widać wzgórza, a nad nimi unoszą się fantazyjnie ukształtowane chmury. Jest jasny, słoneczny dzień. Chwytasz aparat, celujesz ramką focusa w łąki, robisz zdjęcie – ale od razu na podglądzie widzisz, że choć łąki są soczyście zielone, to niebo stało się jedną wielką, białą, przepaloną plamą. Poprawiasz zdjęcie – tym razem ustawiasz aparat tak, by oświetlenie sceny oszacował na podstawie nieba. Robisz zdjęcie: teraz chmury są bardzo dobrze widoczne, ale z kolei łąki zamieniły się w brudnozieloną albo wręcz czarną plamę. Zirytowany przechodzisz do trybu manualnego i szybko okazuje się, że najlepszy efekt, jaki jesteś w stanie uzyskać to ciemnozielone łąki pod bardzo jasnym, miejscami przepalonym niebem na którym widać ledwo zarysy chmur.

Innym przykładem może być sytuacja, gdy znajdujesz się wewnątrz drewnianego kościółka i chciałbyś uchwycić na zdjęciu wnętrze wraz z witrażem przez który wpadają do wnętrza promienie słońca. Możesz też znajdować się w pomieszczeniu i chciałbyś uchwycić zarówno jego wnętrze jak i widok za oknem. Wszystkie te sytuacje łączy jedno: podczas robienia każdego zdjęcia musisz zdecydować się, czy nie doświetlisz cienie kosztem poprawnego oświetlenia świateł, czy też przepalisz światła kosztem dobrego doświetlenia cieni.

Aby rozwiązać problem robienia zdjęć w takich sytuacjach musimy zastanowić się nad tym, skąd pochodzi problem. Mówiąc potocznie, promienie światła, które wpadają do Twojego oka, oprócz informacji o kolorze niosą ze sobą również pewną energię. Wyobraźmy sobie teraz linijkę: niech wartość „0” oznacza światło, które niesie ze sobą nikłe wartości energii (na przykład przy zachmurzonym niebie nocą), zaś „100” oznacza światło niosące ze sobą ogromne ilości energii – na przykład pochodzące od słońca.

Linijka HDR

Ludzkie oko jest przyrządem bardzo dokładnym i ma bardzo szeroki zakres dynamiki. Oznacza to, że w jednym momencie jest w stanie zarejestrować promienie światła bardzo zróżnicowane pod kątem niesionej ze sobą energii (ang. high dynamic range)

Linijka HDR (oko)

Niestety, zarówno matryca aparatu cyfrowego jak i wyświetlacz LCD lub CRT mają bardzo mały zakres dynamiki – mają możliwość rejestracji lub generowania promieni świetlnych mało zróżnicowanych pod kątem niesionej ze sobą energii.

Linijka HDR (aparat)

Zarówno jednak ludzkie oko, jak i aparat cyfrowy (poprzez regulację czasu naświetlania i stopnia zamknięcia przesłony) mają możliwość regulacji, jaki zakres dynamiki jest w danym momencie rejestrowany. Wyobrażamy to sobie jak przesuwanie ramki w lewo i w prawo na linijce. Przykładowo, gdy patrzymy na gwieździste niebo, ramka znajduje się z lewej strony skali. Gdy natomiast oglądamy plażę i morze podczas słonecznego dnia, ramka znajduje się bardziej z prawej strony.

Po dokonaniu tej obserwacji rodzi się pomysł, który pozwala na obejście ograniczeń technicznych aparatu cyfrowego i wyświetlacza w celu uzyskania bardziej realistycznego zdjęcia:

Linijka HDR (bracketing)

  • Przygotowujemy serię zdjęć danej sceny w taki sposób, aby każdy jej element na conajmniej jednym zdjęciu był dobrze oświetlony. Dla przykładu możemy pomiędzy zdjęciami zmieniać czas naświetlania, zaczynając od jednej sekundy (by doświetlić elementy znajdujące się w cieniach) aż do jednej tysięcznej (co pozwoli poprawnie oświetlić bardzo jasne elementy sceny – na przykład niebo).
  • Wczytujemy zdjęcia do komputera i przetwarzamy je odpowiednim programem, by otrzymać zdjęcie HDR. Jest to realizowane za pomocą skomplikowanych algorytmów, ale sprowadza się do tego, że program z serii zdjęć stara się zdobyć dodatkową informację na temat energii każdego punktu zdjęcia.
  • Wykonujemy operację zwaną mapowaniem HDR do LDR. Oznacza to w praktyce, że program „składa skalę dynamiki” zdjęcia do takiej, która będzie widoczna na wyświetlaczu komputera. Dzięki temu zdjęcie będzie zawierało wszystkie elementy równomiernie doświetlone, bez przepaleń i niedoświetleń.
  • Mapowanie HDR do LDR produkuje często zdjęcia mało kontrastowe. Warto zatem poddać zdjęcia procesowi post-processingu w programie typu Gimp lub Adobe Photoshop, by odpowiednio poprawić kontrast i jasność zdjęć.

Zobaczmy na przykładzie, jak wygląda taki proces.

Po pierwsze, musimy wykonać serię nieporuszonych zdjęć z różnymi ustawieniami ekspozycji sceny. Większość współczesnych aparatów pozwala na wykonanie tzw. bracketingu. W praktyce oznacza to tyle, że aparat robi jedno po drugim automatycznie trzy zdjęcia z których pierwsze ma takie ustawienia ekspozycji, jakie ustalił użytkownik, drugie jest wykonywane w skróconym, w stosunku do pierwszego, czasie naświetlania, wreszcie trzecie – w wydłużonym.

Jeśli ktoś ma zainstalowany w aparacie CHDK, może skorzystać z napisanego przeze mnie skryptu rozszerzonego bracketingu, wykonującego serię dziesięciu zdjęć z różnymi czasami naświetlania:

@title Dlugi bracketing
let i=3
:loop

print "Ustawienie ";i
set_tv i
shoot
let i=i+3

if i>31 then goto "end"
goto "loop"
:end

end

Dla przykładu, poniższe zdjęcia zostały wykonane aparatem Canon Powershot S3 IS z włączonym trybem bracketingu:

Bracketing (-1) Bracketing (0) Bracketing (+1)

Następnie, przy użyciu odpowiedniego programu, zostało z nich złożone zdjęcie HDR, które następnie zostało zmapowane na zdjęcie LDR:

Rezultat mapowania LDR na HDR

Po zmapowaniu wykonałem jeszcze niewielki postprocessing w Gimpie, aby zwiększyć kontrast zdjęcia (mapowanie LDR do HDR przeważnie bardzo go ogranicza).

Mapowanie LDR do HDR (postprocessing)

I to wszystko. Teraz trochę konkretów.

Kluczowym elementem powyższego procesu jest oczywiście program, który przeanalizował zdjęcia i złożył z nich zdjęcie HDR, następnie zmapowane do LDR. Na rynku jest wiele komercyjnych programów – jak choćby EasyHDR (istnieje również wersja darmowa, ale z okrojoną funkcjonalnością), ja korzystam z darmowego Qtpfsgui przemianowanego jakiś czas temu na Luminance HDR.

W powyższym artykule przedstawiłem przykład składania zdjęcia HDR z zachodem słońca. Jednak technika HDR przydaje się również w innych sytuacjach – za każdym razem, gdy na fotografowanej scenie znajdują się elementy różniące się znacząco dynamiką. Przykładem może stać się zdjęcie robione wewnątrz pomieszczenia z widocznym oknem lub drzwiami prowadzącymi na zewnątrz budynku.

HDRI jest bardzo ciekawą techniką pozwalającą na uzyskanie realistycznych zdjęć. Ale, paradoksalnie, bardzo cenną jest umiejętność jej nieużywania. Dzieje się tak dlatego, że czasami niewprawny fotograf zamiast precyzyjnie przygotować ekspozycję, robi bracketing z przekonaniem, że złoży potem dobre zdjęcie na komputerze – zapominając przy tym, że zdjęcie przetworzone komputerowo przestaje być zdjęciem, a staje się grafiką. Ponadto do zrobienia dobrych zdjęć HDR wymagany jest dobry sprzęt, statyw, mnóstwo cierpliwości oraz umiejętności i wiedza z zakresu fotografii – najpierw trzeba umieć dobrze fotografować, by móc potem stosować dodatkowe, zaawansowane techniki.

No, to lecę w plener.