Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem Exif informace - výpis v C/C++

Dobrý den
Dělám v C/C++ program, co mi má vypsat EXIF informace z JPEG obrázku.Chtěl bych se proto zeptat, zda-li někdo neví o nějakých stručnějších skriptech v češtině, nebo offsetové DEC(vyhledávam adresu pomocí funkce fseek(), která bere pouze long adresu) adresy EXIF informací. Našel jsem i oficiální skripta, ale v jejich tabulkách offsetové adresy nepasovaly při převodu na adresy, které jsem našel při náhodném hledání přes cyklus.
Děkuji za odpovědi.
Změna předmětu, původně: Exif informace (Kráťa)

Jsou zobrazeny jen nové odpovědi. Zobrazit všechny
Předmět Autor Datum
Předpokládám, že na můj dotaz již nebude odpovězeno, ale za optání nic nedám. Když mám tag 9003, což… nový
hajnis 26.12.2011 17:29
hajnis
okrem toho ze nechapem co vlastne teraz mas presne za problem, si asi stale nepochopil to co som pis… nový
MM.. 26.12.2011 20:37
MM..
Nevím, jestli jsem to pochopil správně z té dokumentace. Hledám zase 2byty jednotlivých tagů např. D… nový
hajnis 26.12.2011 21:08
hajnis
Ano ale informace ktora k tomu tagu patri moze byt offset od nejakeho bodu, na ktorom je ten text (n… nový
MM.. 26.12.2011 21:56
MM..
aha takze pocet tych tagov v jednej IFD tabulke urcuje asi to "Interoperability Number". ked je tam… nový
MM.. 26.12.2011 22:16
MM..
Priklad (original jpeg z fotaku): FF D8 - Start Of Image, nema to ziadnu dlzku citam hned dalsi chun… nový
MM.. 26.12.2011 22:59
MM..
A este priklad na motorola endian (to je jpeg z mojho mobilu). Tvoj program MUSI vediet spracovat ob… nový
MM.. 26.12.2011 23:38
MM..
Super!! Fakt moc díky za trpělivost a ochotu, nyní už to chápu.:-) nový
hajnis 27.12.2011 13:46
hajnis
Neni zac (aspon som si nastudoval EXIF :), dufam ze dostanes za jedna, lebo inac pojdem nakopat prof… poslední
MM.. 27.12.2011 13:49
MM..

Předpokládám, že na můj dotaz již nebude odpovězeno, ale za optání nic nedám.
Když mám tag 9003, což je datum pořízení, tak jak zjistím adresu, na které se nechází exif informace o datu a času?
např. adresa, na které se začíná vypisovat datum je: 2227dec, ale adresa na které nacházím tag 9003 je až na řádku 2356, takže úplně mimo. Chci se tedy zeptat:

Jak pomocí onoho tagu( nebo něčeho jiného) zjistím adresu, na které se nachází kýžená data?

Děkuji

okrem toho ze nechapem co vlastne teraz mas presne za problem, si asi stale nepochopil to co som pisal hore? Neexistuju ziadne adresy, existuje len retaz tagov. Prechadzas celu retaz (tag ktory nechces preskocis - pripocitas dlzku) az kym najdes svoj tag. Jeho format je popisany v specifikacii, exif specifikaciu mas (ten pdf subor)
P.S. to znamena ze tag s datumom moze byt aj na adrese milion, napr. ak je medzi tym este tag nahlad dlhy napr. 1MB.

Nevím, jestli jsem to pochopil správně z té dokumentace.
Hledám zase 2byty jednotlivých tagů např. Datum vytvoření(0132.H). Jakmile najdu tento tag, tak by hned za ním měly následovat informace které k tomuto tagu patří, do doby, než následuje další tag ne?

Ano ale informace ktora k tomu tagu patri moze byt offset od nejakeho bodu, na ktorom je ten text (napr. datum). V pripade textovych tagov to tak aj je, teraz som si to pozrel v exif specifikacii. Ten exif header je dost komplikovany, to si MUSIS precitat presne a aj pochopit.
specifications.html stiahni si specifikaciu 2.2, a tam na strane 116 mas priklad APP1 pre intel endian (II), na stranke 108 mas priklad pre motorola endian (MM), musis si vsimnut aj to ze tagy (resp. vsetky viacbajtove cisla) maju v jednom pripade (intel endian) prehodene byty (byty sa citaju zprava dolava), to by si mal tiez brat do uvahy ak detekujes v EXIf hlavicke "II".
No a tie tabulky su to co je v jpeg chunku FF E1, po tom ako tam je 2byty dlzky a "Exif" a 2byty 00.
T.j. najdes si jpeg chunk FF, E1, 2byty dlzka, "Exif", 00, 00, a za nimi nasleduje struktura podobna jak na strane 108 alebo 116, a tento bod je odteraz offset 0 (tych exif informacii). Napevno je tam 8bytov: 2byty Byte Order (toto si musis zapamatat pre cely zbytok algoritmu ci mas intel endian alebo nie), potom 2byty 002A, potom 4byty offset 0-teho IFD, na ktory by si mal preskocit, rata sa to od toho offsetu tychto EXIF informacii, takze offset 8 je hned nasledujuci bajt (ak tam bude nieco ine jak 8 tak musis preskocit hodnota minus 8 bytov). potom preskocis 2byty interoperability number a potom mas tagy toho 0-teho IFD. Vsimni si ze tie tagy maju pevnu strukturu, 2byty tag, 2byty typ, 4byty dlzka dat, a 4byty offset dat (offset sa rata od toho EXIF offsetu 0, a nie od zaciatku suboru).
A v tej tabulke vidis napriklad ze v tom 0-tom IFD existuje aj tag DateTime (Tag ID 0132 resp. 3201 u intel endianu), a to bude offset na ten datum co tam vidis vo svojom subore. Ten tag 0132 (resp. 3201 pre II) musis hladat, nemozes sa spoliehat ze bude furt na stejnom offsete. Potom pri prechadzani tych tagov musis davat pozor na tag EXIF IFD Offset tam mozu byt dalsie tagy (napr. moze ale NEMUSI tam byt aj tag 9003 (resp 0390 pre II), a ak tam ten tag je, tak bude v subore ulozeny datum a cas este raz (t.j. 2x), neskor. Takze podla toho co pises tak bud nehladas tie tagy spravne ale prehladavs cely subor co JE ZLE ! Bajty 90 03 sa ti mozu nachadzat v subore milionkrat (ako data) a NEbude to tag! Musis prechadzat celu retaz presne podla specifikacie a cislo tagu testovat LEN na mieste kde naozaj to cislo tagu aj ma byt.
Medzi tymi tagmni davas pozor napr. aj ci tam neni tag GPS IFD offset apod. A potom nakoniec tam bude Next IFD offset, co je offset 1-eho IFD ak tam nejaky je (offset sa rata od zaciatku EXIF a nie od zaciatku suboru). Len teraz nejak nechapem jak ma clovek rozpoznat ze uz to neni dalsi tag, ale ze to je ten "Next Ifd Offset". Si to skus najst v tej specifikacii nejak tam musi niekde byt dlzka toho 0-teho IFD alebo co. Ta dlzka asi neni pevna si vsimni ze v roznych prikladoch je dlzka rozna, tie tagy tam mozu a nemusia byt. Neviem zhlavy jak mas rozpoznat koniec IFD tabulky, musis studovat specifikaciu.

aha takze pocet tych tagov v jednej IFD tabulke urcuje asi to "Interoperability Number". ked je tam 0B00 tak to v intel endiane (prehodene byty) znamena ze nasleduje 000B (11 decimalne) tagov, a potom nasleduje "Next IFD pointer" takze mas to jednoznacne zretazene. Opakujem ze tie tagy su vsetky dobrovolne a aj ich pocet je lubovolny takze sa nemomzes spoliehat na ten priklad, musis to scanovat od zaciatku celu retaz tych IFD tabuliek a dokonale respektovat ten format (tag ID testovat len na tych miestach kde ma byt tag ID!), a preskakovat tagy ktore ta nezaujimaju.

Priklad (original jpeg z fotaku):
FF D8 - Start Of Image, nema to ziadnu dlzku citam hned dalsi chunk
FF E1 - jpeg chunk APP1, hned prvy chunk mam exif informacie (keby nie tak preskocim dlzku chunku)
1B 49 - dlzka chunku (tolko bytov -2 by som preskocil keby to nebol APP1 chunk, teraz to len ignorujem)
49 45 78 69 - "Exif", otestujem preistotu ci to je "Exif", alebo ignorujem
00 00 - to tu bude vzdy a ignorujem to
TU JE TERAZ EXIF OFFSET 0 takze bud si vynulujem pocitadlo a ked budem citat nejake bajty tak si budem zvysovat aj pocitadlo aby som vedel kde v subore sa nachadzam a kolko bajtov preskocit na nejaky offset, alebo ak nie tak bude treba pouzivat funkcie na absolutny posun po subore a zapamatat si aktualny offset v subore, v mojom pripade je to offset 12decimalne. Takze napr. exif offset 100 bude u mna v subore absolutny offset 112.
49 49 - "II" takze mam intel endian (vsetky viacbajtove hodnoty sa citaju zprava)
2A 00 - hodnota 002A tu ma byt, a aj je. otestujem alebo ignorujem. (pozn. v motorola endiane tu budu byty 00 2A a nie 2A 00! a aj vsetky dalsie hodnoty budu pre "II" bajtovo zprava a pre "MM" by boli normalne)
08 00 00 00 - nulte IFD zacina na offsete 00000008, t.j. preskocim 8-8 = 0 bytov (pretoze od offsetu 0 som uz precital 8 bytov tak nepreskakujem nic)
0C 00 - bude nasledovat 000C (12decimalne) tagov
0E 01 - tag 010E ma nezaujima, preskocim aj dalsich 2+4+4 bajtov (typ,dlzku dat,offset dat)
0F 01 - tag 010F ma nezaujima, preskocim aj dalsich 2+4+4 bajtov (typ,dlzku dat,offset dat)
.. atd dokopy toto urobim celkovo 12x lebo tolko tu ma byt tagov, a testujem ci som nasiel tag 0132 (bajty 32 01 lebo mam intel endian) alebo 9003 (bajty 03 90 lebo mam intel endian).
a nasiel som:
32 01 - tag Date and Time
02 00 - typ 0002 (asi ascii, viz exif specifikaciu)
14 00 00 00 - dlzka dat = 00000014 hex = 20decimalne
18 01 00 00 - data su na EXIF offsete 00000118 hex, t.j. v mojom subore je to +12decimal lebo viz vyssie a to je 00000124hex. No a ked si pozrem offset 124 hex tak tam mam 20 ASCII bajtov datum a cas suboru.
Keby som pokracoval aj na EXIF IFD tabulku (tag EXIF IFD Offset) alebo aj na next IFD offset po tych 12-tich tagoch, tak by som nasiel aj tag 9003 (bajty 03 90) a tam je zas offset na iny string s datumom a casom. V niektorom subore mozu byt tie tagy obe, v niektorom moze byt len jeden z nich, zavisi od fotaku.

A este priklad na motorola endian (to je jpeg z mojho mobilu). Tvoj program MUSI vediet spracovat oba endiany, napr. si urob fcie CitajWORD a CitajDWORD, napr. (moznosti je mnoho mozes to urobit aj inac napr. aj naslednou konverziou apod)

unsigned int CitajDWORD(endian) {
 unsigned int i, bajt, hodnota=0;
 for (i=0; i<4; i++) {
  bajt = precitas bajt zo suboru;
  if(endian) {
   hodnota<<=8;
   hodnota+=bajt;
  }else{
   hodnota>>=8;
   hodnota+=bajt<<24;
  }
 }
 return(hodnota);
}

pre WORD (2bajty) to ani nemusis cyklom len 2x precitas bajt a ulozis spravne do unsigned int.
Ten priklad jpeg suboru:
FF D8 - Start Of Image, nic nepreskakujem citam dalsi chunk.
FF E0 - tento jpeg chunk ma nezaujima takze musim preskocit
00 10 - dlzka toho chunku je 10hex (16dec), takze musim preskocit presne 16-2= 14 bajtov, lebo 2bajty (dlzku samotnu) som uz precital!
FF E1 - hura mam APP1 chunk
25 06 - dlzka APP1 ma teraz nezaujima, ignorujem
45 78 69 66 - "Exif", otestujem alebo ignorujem
00 00 - ignorujem
TU JE EXIF OFFSET 0 (v mojom pripade je to absolutny offset suboru 1E hex, zapamatam si alebo vynulujem pocitadlo precitanych bajtov)
4D 4D - "MM" - zapamatam si ze mam motorola endian a pouzijem to pri citani vsetkych viacbajtovych hodnot
00 2A - tu ma byt 002A a aj je, otestujem alebo ignorujem.
00 00 00 08 - nulta IPD je na offsete 8, takze preskakujem 8-8=0 takze nic nepreskakujem.
00 09 - bude nasledovat 9 tagov
01 0F - nezaujima ma, preskakujem 2+4+4 dalsich bajtov
01 10 - nezaujima ma, preskakujem 2+4+4 dalsich bajtov
atd presne 9x.
Potom po tych 9 tagoch si precitam 4bajty "next IPD offset" ak je 00000000 tak koncia EXIF tabulky, ak neni 00000000 tak na tom exif offsete je dalsia tabulka s dalsimi EXIF tagmi (zacina 2bajtami poctom tagov a potom tagy a potom zas next IPD offset).
V tomto subore neni ani tag 0132 a ani 9003 takze v nom neni cas ani datum.

Zpět do poradny Odpovědět na původní otázku Nahoru