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)

Předmět Autor Datum
JPEG ma jasne definovanu strujkturu tzv chunky ktore maju hlavicku a typ a ofset a ofset dalsieho ch…
MM.. 09.12.2011 19:07
MM..
Díky zkusím pohledat, jinak ty oficiální skripta jsou z této stránky Exif2-1.PDF (hex adresy jsou ko…
hajnis 09.12.2011 19:14
hajnis
V C/C++ neprogramujem, ale jeden tip Ti dám: www.exiv2.org
pme 09.12.2011 19:19
pme
To právě nevím, jestli můžeme použít, je to totiž projekt do školy, Mě by hlavně zajímalo, jestli ně…
hajnis 09.12.2011 19:23
hajnis
V C sa zapisuje hex cislo pomocou 0xcislo, nepotrebujes nic prevadzat. Adrsesy nesedeli pretoze to v…
MM.. 09.12.2011 19:25
MM..
To je nezmysel prechadzat kazdy bajt, dekoduj hlavicky a dlzky tych "chunkov", tym padom vsetky nepo…
MM.. 09.12.2011 19:20
MM..
Mohl bych se prosím zeptat, jak mám dekódovat ty chunky? Na internetu jsem hledal, kde jsem mohl, al…
hajnis 09.12.2011 22:37
hajnis
Tuto http://en.wikipedia.org/wiki/JPEG#Syntax_and_struc ture mas aspon zakladne veci. Pre teba je za…
MM.. 09.12.2011 23:34
MM..
Takže abych to správně pochopil( promiň už mi to moc nemyslí), tak mám udělat cyklus, který bude zvy…
hajnis 10.12.2011 01:39
hajnis
Pardon, že pořád otravuji, ale již mi to vytisklo toto: w1D0FuPB První hodnota je normální pořadí, d…
hajnis 10.12.2011 11:25
hajnis
predradene F su tam preto ze pouzivas premennu int namiesto unsigned int (a char namiesto unsigned c…
MM.. 10.12.2011 13:10
MM..
To proto, že jsem si na začátku semestru bláhově vybral jeden ze středně těžkých projektů, namísto t…
hajnis 10.12.2011 13:23
hajnis
Neni to zas az tak zlozite 1. Najdes FF D8 2. precitas dalsie 2 bajty = kod chunku. porovnas s tabul…
MM.. 10.12.2011 13:35
MM..
Chapes to blbo precitaj si co som pisal este raz a pomaly. Poté co je najdu, tak přečtu další dva b…
MM.. 10.12.2011 13:08
MM..
Mohu se ještě zeptat, podle jaké kombinace najdu třeba informaci o datu focení? Například hex adresa…
hajnis 14.12.2011 20:35
hajnis
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ž…
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…
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…
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…
MM.. 26.12.2011 21:56
MM..
aha takze pocet tych tagov v jednej IFD tabulke urcuje asi to "Interoperability Number". ked je tam…
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…
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…
MM.. 26.12.2011 23:38
MM..
Super!! Fakt moc díky za trpělivost a ochotu, nyní už to chápu.:-)
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..

JPEG ma jasne definovanu strujkturu tzv chunky ktore maju hlavicku a typ a ofset a ofset dalsieho chunku (resp. dlzku stavajuceho co je stejna vec) atd. takze prechadzas to "retazovo". potrebujes toto alebo nieco ine? Toto najdes googlom ked si das hladat slova napr. jpeg file format structure. Alebo podobne. Hlavne tam je to slovo structure :)

P.S. len pre zaujimavost - dekodovacie programy nezname chunky preskakuju a teda do jpeg sa da skryt "tajny obsah", co sa celkom srandovne pouziva v steganografii. Ale kedze je to pre nejakych tajnos agentos celkom znama vec tak to moc steganograficke uz neni :)

Díky zkusím pohledat, jinak ty oficiální skripta jsou z této stránky Exif2-1.PDF (hex adresy jsou kolem strany 140+-).
Já jsem to prostě jel takto:
(celá struktura byla v cyklu)
fseek (file , i , SEEK_SET);
(proměnná i se při každém cyklu zvyšovala)
hodnota= fread(buffer,1,lSize,file);
(pak jsem to, co bylo na offsetu přečetl a vypsal, později jsem našel nějaké informace na určitých adresách jako jméno foťáku atd..)

Stručně řečeno zjišťoval jsem adresu po adrese, jestli se za ní něco neskrývá.

To právě nevím, jestli můžeme použít, je to totiž projekt do školy, Mě by hlavně zajímalo, jestli nějak nejde převést tu HEX adresu do DEC tak, aby to sedělo, jelikož když jsem to dělal klasickým převodem HEX-DEC tak adresy neseděly.
Ale jinak díky za pomoc ;)

V C sa zapisuje hex cislo pomocou 0xcislo, nepotrebujes nic prevadzat. Adrsesy nesedeli pretoze to v tom dokumente je len priklad. Tie informacie su nepovinne t.j. ta struktura je do urcitej miery "dynamicka", niektory obrazok moze mat GPS informacie, iny obrazok cast o GPS vobec mat nemusi, apod.

To je nezmysel prechadzat kazdy bajt, dekoduj hlavicky a dlzky tych "chunkov", tym padom vsetky nepodstatne veci preskocis a najdes to co chces (EXIF chunk) takmer okamzite.
len si musis najst co som pisal strukturu tych chunkov. Kazdy zacina stejne - 4pismena a dlzka (neviemkolko bajtov zhlavy, najdi si to) tym padom ked ta tento chunk nezaujima (testujes tie 4pismena ci to je nejaky EXIF) tak rovno sa posunies o (dlzka minus 5 ci 6) a tym padom hned citas hlavicku dalsieho chunku a testujes 4pismena ze co to je zac, az kym nenajdes ten exif chunk.
P.S. v ranmci toho EXIF mas podobne "chunkovanie" :-) - to mas popisane v tom tvojom pdf dokumente. T.j. tie offsety nie su pevne, to je len priklad. Zavisi od toho ktore casti tam su a ktore nie. Kazda cast ma hlavicku a dlzku.

Tuto http://en.wikipedia.org/wiki/JPEG#Syntax_and_struc ture mas aspon zakladne veci.
Pre teba je zaujimave to, ze za prve 2bajty 0xFF a 0xD8 znamenaju zaciatok JPEG dat. T.j. ako prve hladas tieto 2 bajty. Mali by byt uplne na zaciatku, ak nie su tak ignorujes vsetko az po tieto 2 bajty.
Za tym 0xFF 0xD8 nasleduje potom 2bajty kod prveho chunku, a podla tej tabulky kodov vies ze jaku ma dlzku. Vacsina su variable size t.j. dalsie 2bajty urcuju dlzku. Takze vies kolko bajtov mas preskocit (minus dva lebo tie 2bajty dlzka sa uz zaratali do dlzky). Ked narazis na kod ktory ma tam v tabulke pevnu dlzku tak sa posunies o tu pevnu dlzku.
Takto prechadzas cely JPEG az po ten kod EOI - koniec obrazka, zbytok dat sa musi ignorovat.

No a takto hladas ten svoj EXIF blok. Ten by mal mat kod APP1 t.j. 0xFF 0xE1. Az toto najdes tak dalsie 2 bajty su dlzka, a potom nasleduju tie EXIF data podla tvojho EXIF pdf dokumentu. V ramci EXIF dat postupujes podobne tiez tam su rozne bloky a kazdy ma nejaku dlzku a mozu tam byt usporiadane ako chcu. T.j. prechadzas cez tie exif data podobne jak som to popisoval v prvom odstavci, akurat kody a dlzky su v tomto bloku podla tej tvojej EXIF specifikacie co uz mas to pdf.

Takže abych to správně pochopil( promiň už mi to moc nemyslí), tak mám udělat cyklus, který bude zvyšovat hex offset od 00 až do doby, kdy dva offsety po sobě budou mít hodnotu 0xFF a další 0xD8? Poté co je najdu, tak přečtu další dva bajty, ve kterých bude napsána adresa první exif informace( počátku) atd atd??

Pardon, že pořád otravuji, ale již mi to vytisklo toto:
w1D0FuPB
První hodnota je normální pořadí, druhá jeho hodnota v hex, třetí je znak char, který vyjadřuje a čtvrtá je tento znak převedený do hex soustavy.
Vyskytly se ale dva problémy:
První- Nevím, proč jsou v té HEX hodnotě předřazená F písmena.
(výpis byl prováděn takto: printf("<%x><%i> %c %u %X \n",i,i,info[i],info[i],info[i]); )

Druhá- číslo 79 na druhém řádku odpovídá po přičtení délce app1, avšak problém je v tom, že Exif informace, které mi to začné vypisovat následují až daleko za koncem app1, přičemž by měly být schované vevnitř.

Neni to zas az tak zlozite
1. Najdes FF D8
2. precitas dalsie 2 bajty = kod chunku. porovnas s tabulkou z wikipedie (bud cez viacere dlhsie if alebo v cykle). Ak to je pevna dlzka tak sa posunies o pevnu dlzku, ak to je variabilna dlzka tak precitas dalsie 2 bajty = dlzka a posunies sa o dlzka-2.
3. bod 2 opakujes az kym nenajdes kod chunku FF E1. Az ho najdes tak si nasiel EXIF, a teda dalsie 2 bajty su dlzka EXIF (tu ani nepotrebujes) a dalsie bajty zavisia podle tej tvojej EXIF specifikacie, bude tam zas opakovane nejaky kod (napr. pre GPS informace) a nejaka dlzka tych GPS informacii, a po tomto useku bude zas nejaky iny kod useku napr. preview a dlzka preview informacii, a tak opaklovane. Tieto kody viz tu EXIF specifikaciu.

Pracuj s unsigned char a unsigned int, aby ti to nerozsirovalo z char na int s tymi FF. char a int ak maju najvyssi bit 1 tak to znamena zaporne cislo (napr. FF je -1) a v tom pripade sa char na int musi rozsirit dolava tymi F (lebo int hodnota -1 je FFFFFFFF). Unsigned nemozu mat zaporne take sa char na int rozsiruje normalne zlava nulami.

Chapes to blbo precitaj si co som pisal este raz a pomaly.

Poté co je najdu, tak přečtu další dva bajty, ve kterých bude napsána adresa první exif informace( počátku) atd atd??

NE. dalsi dva bajty budu kod chunku. Zoznam mas na wikipedii link som uz dal.
v tvojom pripade je to nahodou FF E1, co je EXIF, ale NEMOZES sa na to spoliehat, moze tam byt akykolvek iny chunk (iny chunk by si musel preskocit az kym najdes EXIF)

Mohu se ještě zeptat, podle jaké kombinace najdu třeba informaci o datu focení? Například hex adresa pro zdigitalizování by měla být 9004, tak jak podle této hodnoty poznám, na kterém je řádku? Omlouvám se za trochu hloupé otázky, ale už nad tím sedím tři dny v kuse a stále na nic nemohu přijít.

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