Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C\C++] EXIF informatie uitlezen zonder classes onder win32

Pagina: 1
Acties:

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Hoi

Ik heb een programma geschreven voor het uitlezen van EXIF info uit jpg-files, en daarbij is het zo dat ik geen classes heb gebruikt (heeft zo zijn redenen).

Dit heb ik onder Linux gedaan met libexiv2. Helaas is hier voor windows alleen een binary van waar je niet tegenaan kunt linken.

Weet iemand mischien een library die het wel doet onder win32, maar dan zonder classes? IK heb de bekende sites al afgespeurd naar een nette library.

Verwijderd

En wat is het probleem van het zelf even bouwen van die exiv library onder windows? Naar wat ik begrijp van de homepage van die lib moet dat geen probleem zijn...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

En waarom mogen er geen classes zijn?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
.oisyn schreef op maandag 24 september 2007 @ 01:26:
En waarom mogen er geen classes zijn?
onderdeel van een weddenschap :)
klinkt vrij stupide, ik weet het.
En wat is het probleem van het zelf even bouwen van die exiv library onder windows? Naar wat ik begrijp van de homepage van die lib moet dat geen probleem zijn...
Is iets lastiger om mee te distribueren naar doelpc.

net even gekeken: Zie ik niet echt zitten, heb liever een ander alternatief.

[ Voor 8% gewijzigd door Boudewijn op 24-09-2007 01:38 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Boudewijn schreef op maandag 24 september 2007 @ 01:30:
[...]

onderdeel van een weddenschap :)
klinkt vrij stupide, ik weet het.
Dat is het idd. Je kunt namelijk prima OO programmeren zonder gebruik te maken van de bijbehorende language construct (dus C++ classes), net als dat je procedureel kunt programmeren als je wél van classes gebruik maakt. Dus I can't help wondering wat nou ten grondslag lag aan die weddenschap :)

Anyway, waarom wil je per se een library gebruiken? Het lijkt me niet zo heel erg lastig om gewoon zelf een JPEG EXIF reader te maken, aangezien het enige waar je in geïnteresseerd bent is die EXIF informatie (en dus niet het plaatje zelf, dus je hoeft ook geen decoder te schrijven en allerlei formaten te ondersteunen)

[ Voor 25% gewijzigd door .oisyn op 24-09-2007 01:59 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
ja klopt. alleen als ik componenten kan 'reusen' is dat natuurlijk mooi.
toevallig nog een leuk linkje liggen naar zoiets, ik ga zo zelf ook even kijken :)

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Over die weddenschap: ik doe een schoolopdracht door die figuur, omdat ik een wedje heb verloren (heb hbo software engineering afgerond, en doe nu master course aan UU). That's all ;)


okay ik heb besloten het zelf te schrijven.
heb de exif spec erbij gepakt en zie dat het de tag ID's 0x100 en 0x101 zijn die ik wil hebben (wil alleen length en heigth weten) in het geval van TIFF.

geldt dat ook voor jpeg, dat lees ik namelijk niet terug in de exif-2.1 specificatie?
verder; Hoe lees je eigenlijk zoiets nou slim uit?

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 18:53
Ik geloof dat ik voor m'n eigen implementatie voor exif info uit jpeg files te lezen vooral deze specificatie gebruikt heb.

Veel slimmigheid heb je er denk ik niet voor nodig. Je begint gewoon met het lezen tot je de data vind die je nodig hebt of tot er een deel van wat je leest niet meer overeenkomt met je verwachtingen.

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Voor het nageslacht etc (en geinteresseerden):

volgens adion's spec zou elke jpg "ffd8" moeten bevatten als begin van de JPG info.
Nu heb ik van exif.org een sample image gehaald ( sanyo-vpcg250.jpg) en die door od+grep gehaald. en ja idd gevonden:
code:
1
2
boudewijn@zeus ~ $ od -x sanyo-vpcg250.jpg  | grep -in ffd8
56:0001560 007b 0000 003f 0000 ff00 ffd8 00db 00c5


Ik moet de date digitised hebben, uti de EXIF IFD, maar snap neit helemaal hoe dat diagram werkt.
kan iemand met een zetje de goede kant uit geven? (heb dat soort diagrammen wel gezien, maar snap niet welke waarden de labels hebben)

die zit er inderdaad in. Het blijkt btw om de schiet-datum te gaan van het plaatje en niet om de reso, maakt mij niet echt uit.

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 18:53
Die ff d8 moet je niet echt naar zoeken, dat zijn gewoon de 2 eerste bytes van een jpg bestand steeds.
Vermits de exif marker steeds als eerste in het bestand hoort te staan, volgt hierna ff e1
De volgende 2 bytes geven dan de lengte van de app1 marker aan, en daarna kan je dus zoveel bytes lezen.
In de app1 marker zijn dan de eerste 6 bytes exif header, dan 8 bytes tiff header.
De eerste byte in de tiff header bepaald de byte order van de velden die volgen. (Dus of de most significant byte eerst komt of laatst)
De laatste 4 bytes van de tiff header geven een offset aan, maar die zal meestal 8 zijn, wat betekend dat de exif data meteen volgt op de tiff header, anders moet je eerst nog een aantal bytes overslaan.
Dan volgen 2 bytes die aangeven hoeveel entries er in deze ifd zitten.

Per entry volgt er dan: 2 bytes die de Tag ID aangeven, 2 bytes voor het dataformaat, 4 bytes voor het aantal componenten, en dan nog eens 4 bytes voor de eigenlijke data.
Nog een handige pagina is dan deze waar uitgelegd staat welke tag id voor wat staat.

DateTimeOriginal is dan bijvoorbeeld 0x9003, dus je stopt in dit geval met zoeken van zodra je deze tag id tegenkomt.
Omdat het formaat string is zal het data veld echter niet direct de datum bevatten, maar wel een offset. Vanaf deze offset moet je dan 'aantal componenten' bytes lezen en dit is dan de datum in een ascii string.

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
feitelijk gezien zeg je dus:

ga zoeken naar de 9003 (het is een heel basale applicatie, dus ik hoef niet specifiek te gaan checken of de exif data mischien niet direct na de header komt).
code:
1
2
3
boudewijn@zeus ~ $ od -x sanyo-vpcg250.jpg | grep 00005[2-4]
0000520 0004 0000 3230 3030 9003 0002 0014 0000
0000540 022c 0000 9004 0002 0014 0000 0240 0000

Hier vind je hem dus in je foto (bovenstaande doe ik natuurlijk wel in C).
Per entry volgt er dan: 2 bytes die de Tag ID aangeven, 2 bytes voor het dataformaat, 4 bytes voor het aantal componenten, en dan nog eens 4 bytes voor de eigenlijke data.
Nog een handige pagina is dan deze waar uitgelegd staat welke tag id voor wat staat.
0002 == tag id dus
0014 0000 == componenten
022c 0000 == offset
Omdat het formaat string is zal het data veld echter niet direct de datum bevatten, maar wel een offset. Vanaf deze offset moet je dan 'aantal componenten' bytes lezen en dit is dan de datum in een ascii string.
dus ik moet dan 22c bytes vanaf die 022c gaan lezen, en daar vind ik de datum in ASCII?

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 18:53
Ik denk dat de offset telt vanaf het begin van de ifd, dus je zal toch iets meer moeten parsen om dat begin te kennen, vermits je niet weet de hoeveelste tag je gevonden hebt. Verder riskeer je zo natuurlijk wel dat toevallig 9003 al eens voorkwam maar niet als tag id.
Die 0002 is dus trouwens het dataformaat, waar je bij de specificatie voor kan vinden dat dat dus idd betekend dat het een ascii string is.

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
na wat gehamer mag het alsnog met classes (domweg omdat ^^ veel werk is).
Iemand een leuke suggestie voor een lib die ook onder windows werkt.

libexif staat voor morgen op de agenda, maar ik kan me best voorstellen dat iemand hier ook nog een andere lib ervoor kent.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
Wat heeft het parsen van een bestandsformaat met het wel of niet gebruiken van classes te maken en wat heeft het gebruik van classes met de hoeveelheid werk te maken?

BTW De hele Win32 API is plain C dus bevat geen enkele class.

[ Voor 34% gewijzigd door farlane op 28-09-2007 08:44 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 18:53
De hele code voor het uitlezen is bij mij 75 regels, met de informatie die je nu hebt is het echt niet zoveel werk hoor.
Ik heb echter alleen code in Visual Basic, niet in C.
Verder zie ik ook niet goed in hoe dit veel moeilijker/makkelijker wordt met of zonder classes.

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
zou ik die code van je mogen zien?

fijne van het gebruik van classes is dat je gewoon een standaard library ervoor kunt nemen die dus classes gebruikt.
Farlane: in de standaard win32 api zit geen functionaliteit daarvoor meen ik ;)

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
Boudewijn schreef op vrijdag 28 september 2007 @ 14:23:
zou ik die code van je mogen zien?

fijne van het gebruik van classes is dat je gewoon een standaard library ervoor kunt nemen die dus classes gebruikt.
Farlane: in de standaard win32 api zit geen functionaliteit daarvoor meen ik ;)
Erm ... gevalletje klok klepel volgens mij.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 18:53
Je mag mijn code wel zien ja, hoewel dat misschien niet helemaal volgens de policy hier op got is :P
Anyway, ik heb het opgelost in 2 delen, eerst lees ik de volledige app tag, en daarna heb ik een functie om daarin een specifiek veld te zoeken. Veel waardes staan hier ook decimaal, dus om ze terug te vinden in de specs zal je ze misschien ff in hexadecimaal moeten lezen.
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Dim f As Long
f = FreeFile
Open FileN For Binary Access Read As #f
    Dim b() As Byte
    ReDim b(1)
    Get #f, , b
    If b(0) <> 255 Or b(1) <> 216 Then
        Close #f
        Exit Function
    End If
    
    Get #f, , b
    Dim size As Long
    If b(0) = 255 And b(1) = 225 Then
        'APP1 marker
        Get #f, , b
        size = b(0) * CLng(256) + b(1)
        ReDim APP1(size - 3)
        Get #f, , APP1
        LoadFromJPEG = True
    Else
        ReDim APP1(0)
        LoadFromJPEG = False
    End If
Close #f

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Public Function getField(ByVal field As Long) As String
Dim Pos As Long, i As Long

If UBound(APP1) < 18 Then Exit Function

For i = 0 To 5
    ExifHeader(i) = APP1(Pos + i)
Next
Pos = Pos + 6

For i = 0 To 7
    TiffHeader(i) = APP1(Pos + i)
Next
Pos = Pos + 8

'0x4949 = Intel Byte alignment, 0x4d4d = Motorola Byte alignment
If TiffHeader(0) = &H49 Then
    byteAlignment = 0
Else
    byteAlignment = 1
End If

'Last 4 bytes: offset to first IDF
Dim idfOffset As Long
idfOffset = readLong(TiffHeader, 4)
Pos = idfOffset + 6

Dim exifIFDOffset As Long
Dim nbEntries As Long
nbEntries = readShort(APP1, Pos)
Pos = Pos + 2
For i = 1 To nbEntries
    Dim tagNumber As Long, dataFormat As Long
    tagNumber = readShort(APP1, Pos)
    Pos = Pos + 2
    dataFormat = readShort(APP1, Pos)
    Pos = Pos + 2
    Dim nrOfComponents, data As Long
    nrOfComponents = readLong(APP1, Pos)
    Pos = Pos + 4
    If dataFormat = 3 Then
        data = readShort(APP1, Pos)
        Pos = Pos + 2
        'Last 2 bytes are ignored since data type is 'unsigned short'
        'readShort(APP1, pos)
        Pos = Pos + 2
    Else
        data = readLong(APP1, Pos)
        Pos = Pos + 4
    End If
    
    If tagNumber = 34665 Then exifIFDOffset = data
    If tagNumber = field Then
        getField = data
    End If
Next

End Function


Dataformaat string houd deze code ook nog geen rekening mee omdat ik dat zelf nog niet nodig had tot nog toe, maar je krijgt dan wel de offset waarde terug, waarmee je normaal wel verder kan.
De readShort en readLong functies houden verder rekening met de byte order om de waardes op de juiste manier in te lezen.

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Private Function readLong(ByRef data() As Byte, ByVal Pos As Long) As Long
If byteAlignment = 0 Then
    readLong = data(Pos) + data(Pos + 1) * CLng(256) + data(Pos + 2) * CLng(65536) + data(Pos + 3) * 16777216
Else
    readLong = data(Pos + 3) + data(Pos + 2) * CLng(256) + data(Pos + 1) * CLng(65536) + data(Pos) * 16777216
End If
End Function

Private Function readShort(ByRef data() As Byte, ByVal Pos As Long) As Long
If byteAlignment = 0 Then
    readShort = data(Pos) + data(Pos + 1) * CLng(256)
Else
    readShort = data(Pos + 1) + data(Pos) * CLng(256)
End If
End Function

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 15:10

Creepy

Tactical Espionage Splatterer

No offence, maar we praten hier over een stuk binaire data dat ook nog eens gedocumenteerd is. Kleine moeite om hier zelf een parser voor te schrijven die niet OO is opgezet. Wat is dan nu nog het probleem?

Daarnaast is "mag ik je code zien" gewoon een ordinair scriptrequest. Zie ook Programming Beleid - Scriptrequests. Een beetje programmeur moet toch in staat zijn om met de link die Adion geeft zelf iets in elkaar te zetten. Nofi uiteraard maar als je dat niet lukt kan en je wilt als ontwikkelaar aan de slag lijkt het me verstandiger om een andere baan te gaan zoeken.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
dat is geen scriptrequest mijns inziens.
temeer daar hij Basic code heeft en ik het in C doe :)

verder: bedocumenteerd? vind je? alle 10 de vormen van 'standaard' zoals fabricanten het inzetten. nofi, maar laat me niet lachen.

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 18:53
Het is hoogstens wat onduidelijk omdat er verschillende standaarden gecombineerd worden, maar die specificatie die ik gaf lijkt me idd toch vrij duidelijk. Daarmee heb ik mijn code geschreven, en met die code heb ik tot nog toe alle exif info kunnen lezen uit jpg's van verschillende camera's.

Het moeilijkste was eigenlijk om dit soort beschrijving te vinden en niet een aantal documenten van 100+ pagina's te moeten doornemen, daar heb ik wel een redelijke tijd naar het zoeken geweest.

VirtualDJ 2024 - Fast Image Resizer - Instagram

Pagina: 1