Page 1 of 1

PictView - otáčení obrázku podle EXIF

Posted: 26 May 2006, 09:01
by Roman
Jak už bylo několikrát uvedeno PictView je perfektní pro prohlížení fotek, ale jedna věc mi hrozně vadí. Neumí automaticky otáčet fotky podle údaje v EXIF (pokud jsou foceny na výšku). Nešlo by to doplnit?

Re: PictView - otáčení obrázku podle EXIF

Posted: 26 May 2006, 09:44
by Jan Patera
Roman wrote:Jak už bylo několikrát uvedeno PictView je perfektní pro prohlížení fotek, ale jedna věc mi hrozně vadí. Neumí automaticky otáčet fotky podle údaje v EXIF (pokud jsou foceny na výšku). Nešlo by to doplnit?
Mame to v planu, diky za pripomenuti :wink: Neco k tematu je zde.

Posted: 27 May 2006, 01:32
by zarevak
Ve výše zmíněném vlákně se píše, že otáčení je časově náročné. Není však možné otáčet obrázek již při otevíranání? Otevření velkého obrázku by se pak nevykreslovalo od shora, ale ze strany, která je v obrázku datově uložena jako "nahoře".

Posted: 27 May 2006, 08:32
by Mem
Až na to, že data obrázkových formátů jsou obvykle ukládána po řádcích, takže by se muselo v souboru skákat a dohledávat pozice sloupců (což si u některých formátů (BMP RLE) nedovedu představit bez toho, že by se dekomprimoval stejně celý řádek). Prostě načtení a vyrotování je imho jediná možnost.

Posted: 27 May 2006, 13:54
by zarevak
Tomu vašemu argumentu moc nerozumím :(
Podle mne jakákoliv bitmapová data lze v paměti reprezentovat dvourozměrným polem pixelů - jeho velikost znám z hlavičky souboru.
Pak už jen toto pole plním pixely obrázku buď po řádcích od shora dolů (v případě většiny formátů) nebo po řádcích od sdola nahoru (v případě většiny BMP souborů) nebo ho také můžu plnit po "datových řádcích" ale v obrázku otočeně po sloupcích zleva-doprava nebo z prava doleva.

v pseudo kódu otočení o -90° hned při načítnání:

Code: Select all

imgWidth = dataHeight;
imgHeight = dataWidth;

img = new RGB[imgWidth, imgHeight];
for (int dx; dx < dataWidth; dx++)
  for (int dy; dy < dataHeight; dy++)
  {
    imgX = dy;
    imgY = dataWidth - dx - 1;
    img[imgX, imgY] = datasource.GetNextPixel();
  }
-> takto načítám data jak jdou do řádcích, ale plním je ve výsledném poli po sloupích. Jen je třeba napsat všechny možnosti otočení a ne jen tento jeden případ.

Posted: 27 May 2006, 17:09
by Mem
Jo, přesně tak, jde mi o to, že při dekompresi můžu vzít celý řádek (nebo klidně větší blok) a ten plácnout na obrazovku. Aby tohle efektivní načtení bylo zachováno i pro simulovanou rotaci, muselo by se číst ze zdrojového souboru ne sekvenčně, ale na přeskáčku (po těch "sloupcích" jak jsem psal). Vy nicméně navrhujete nomální sekvenční čtení a zápis po jednom pixelu, v tom vidím ten problém - při vyrotování se musí postupovat načítáním po jednom pixelu (pokud to neudělá grafická karta při použití akcelerace, což myslím třeba při xBlt z GDI nedělá), a proto je to tak pomalé. První operace (nasypání bloku dat) má ve srovnání s tou druhou minimální časovou složitost, a vy navrhujete pouze tu pomalou druhou operaci provádět už jako součást prvního kroku, v tom žádné urychlení nevidím. Ale možná se v něčem pletu?

Posted: 27 May 2006, 17:10
by Datalog
Netuším, jak to dělá PictView, a nejsem ani odborník na jednotlivé formáty, ale otáčet už při dekódování mi přijde neprůchozí.

Každý typ/formát má už svůj odladěný a lety prověřený algoritmus, který předpokládá nějak stavěné řádky a sloupce. Rozhodně to není plnění pole znak po znaku. Např. lzw komprese (.gif) využívá opakování a zpětné doplnění stejné sekvence - a je sakra rozdíl, jestli máte tu sekvenci v paměti reálně za sebou nebo ob šířku obrázku (x86 mají instrukce pro kopii bloku bytes za sebou a cache procesoru při přístupu do paměti je optimalizována na přímou sekvenci). Takže zde by bylo IMHO rychlejší (nebo přinejmenším stejně rychlé) obraz vytvořit klasicky a až pak otočit.

Takže zaměnit sloupce a řádky už při načítání by u některých formátů teoreticky šlo. Ale fakticky to znamená mít duplikovaný (resp. triplikovaný) algoritmus pro každý formát zvlášť, mnohdy úplně nově vyvíjený (z ohledem na rychlost) a ne vždy přinášející zrychlení oproti sekvenci dekóduj-otoč.

Posted: 27 May 2006, 17:13
by Mem
Datalog: nee, zarevak to myslel tak, že obrázek se načte klasicky sekvenčně (viz ta metoda GetNextPixel), pouze se bude umisťovat do bufferu s obrázkem per pixel (i když pokud se ta obrazová data současně využívají při další dekomprimaci (viz to LZW*), tak by jiná reprezentace pole přinesla problém, to máte pravdu).

Spíš by stálo za to zvážit využití grafické akcelerace a třeba OGL nebo DX pro rotaci, i když tady samozřejmě vyvstává řada dalších problémů (velikosti textur, filtrování atd.).

P.S.: *I když pokud si dobře pamatuji, tak zrovna LZW by měl mít budovaný slovník mimo, fráze v dekódovaném textu využívá LZ77/78, stejně ale je možné, že tuhle kompresi nějaký formát také využívá

Posted: 27 May 2006, 22:32
by Datalog
Mem: díky za ozřejmění, bude to tak jak říkáte.

* LZW: nakolik si pamatuji (málo :D ), LZW potřebuje vytvářet slovník pouze při kompresi, pro urychlení nalezení shodných úseků. Pro rozbalení stále stačí jedno sekvenční okno - nicméně je možné, že i to si dělá bokem a nevyužívá výstupních dat, záleží na implementaci.

EDIT: Tak mi to nedalo a trochu jsem brouzdal po netu a vypadá to, že LZW potřebuje slovník i při dekompresi. Njn, už je to dávno, paměť neslouží :( . Omlouvám se za mystifikace.

Posted: 28 May 2006, 09:57
by Mem
Datalog wrote:EDIT: Tak mi to nedalo a trochu jsem brouzdal po netu a vypadá to, že LZW potřebuje slovník i při dekompresi. Njn, už je to dávno, paměť neslouží :( . Omlouvám se za mystifikace.
Jj, já mám ze školy přeci jen asi blíž, takže si rozdíl mezi LZ77 a LZW ještě celkem vybavuju, u LZW se kódují čísla frází ze slovníku, u LZx ta pozice v okénku jak píšete