I have spent a lot of time downloading and trying to use various VB6 examples
to obtain photo metadata. I have downloaded and tested literally every example
that exists online today and I have never found one that works on 100% of the
JPG files I encounter. Most of these JPG files are from newer Canon & Nikon
cameras and some of them have been edited and saved with Photoshop will a call
to enter Copyright information into the JPG. Sometimes my routine that calls
these API xxxxx.bas modules will run weeks without encountering a problem JPG
and sometimes only a few days. But time is irrelevant because eventually there
is always one rouge JPG that will cause one of the API calls to abend. The
strange thing is that programs such as iRfanView always show the correct EXIF
information even when the user contributed API module abends. I am not good
enough with API debugging or with understanding the structure of EXIF to debug
API classes and modules that extract or edit the EXIF data.
I also tried using the windows shell to extract "Date Picture Taken" metadata
from a JPG and my tests failed. I am assuming that one must have configured
the viewer for the particular folder being scanned to display these attributes
or the data is not available via a shell call either.
This frustration has led me to search for something else, maybe a DLL that is
more reliable for extracting EXIF data. I first found a GDI+ wrapper for VB6
but with no examples written in VB6 I was not able extract "Date Picture
Taken" or any photo metadata. Examples in Visual Basic 6 seem non existent for
GDI+ (GDIPlus).
Recently I finally found FreeImage with a VB6 wrapper with high hopes. It
support for EXIF but I am in the same situation as GDI+ because I can only
find one example written in VB6 and all it has included is 3 lines of code,
one to open FreeImage, another to convert a TIFF to a PNG file, and a third
line to close FreeImage.
Can someone supply me with more VB6 examples to extract metadata from a JPG. I
will take any other examples you have as well. I found the .NET sample to
enumerate metadata but I am not understanding .NET well enough to translate
that to VB6.
Thanks in advance for any examples or hints. (Please posters requesting I
switch to .NET - I am holding off for a little longer thanks.)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
basically, it is very easy to get an image's metadata with the FreeImage VB6
wrapper. However, interpreting and so actually using EXIF metadata is much
more complicated.
With the VB6 wrapper, you have a VB-friendly structure FREE_IMAGE_TAG, which
provides you the metadata information, one for each metadata tag. Basically,
with FreeImage, a single metadata tag corresponds to a single line in
IrfanView's EXIF information window. Each tag has several fields, that contain
its type, value(s), key (name), description and id.
Especially with EXIF metadata, most of the information is stored by means of
reference numbers. I recommend having a look at the EXIF 2.2 specifiaction at http://www.exif.org/specifications.html
However, this document does not directly relate to FreeImage's metadata
models, but can give you hints on how to interpret the values of the tags.
The fields Description, Key and Id or FREE_IMAGE_TAG correspondent to 'Tag
Name', 'Field Name' and 'Tag ID' of the various tables in the EXIF
specification (Table 4 at 4.6.5 Exif IFD Attribute Information for example)
respectively.
Field StringValue of FREE_IMAGE_TAG is the result of function
FreeImage_TagToString, which interprets most of the tags accordingly. However,
this only results in a string value, which may make it difficult to work with
in an application (read more about FreeImage_TagToString in the FreeImage API
documentation).
It depends on field 'Type', which of the various value fields are filled with
data. Expect for tags of type FIDT_ASCII (String type), field 'Count' contains
the number of values of the tag. If 'Count' is greater than 1, the actual
value is an array from 0 to 'Count' - 1. For FIDT_ASCII typed tags, 'Count'
contains the length of the string.
Field 'Value' is a Variant in VB and contains the properly typed value of the
tag for most tag types (expect for types FIDT_PALETTE and FIDT_(S)RATIONAL).
Tag of type FIDT_(S)RATIONAL are always represented as an array (even if
'Count' is 1, which results in an array with only one member with index 0).
Field 'RationalValue', which is an array of FIRATIONAL, which in turn contains
both numerator and denominator of the value. In that case, field 'Value' also
contains an array of of type Double which holds an approximated value of the
rational (expressed as an IEEE double precision floating value, Double in VB).
Also in FreeImage, metadata is divided into several metadata models. Each
model represents a number of tags, that belong to a certain type of metadata.
FIMD_COMMENTS = 0 single comment or keywords*)
FIMD_EXIF_MAIN = 1 Exif-TIFF metadata
FIMD_EXIF_EXIF = 2 Exif-specific metadata
FIMD_EXIF_GPS = 3 Exif GPS metadata
FIMD_EXIF_MAKERNOTE = 4 Exif maker note metadata
FIMD_EXIF_INTEROP = 5 Exif interoperability metadata
FIMD_IPTC = 6 IPTC/NAA metadata
FIMD_XMP = 7 Abobe XMP metadata
FIMD_GEOTIFF = 8 GeoTIFF metadata
FIMD_ANIMATION = 9 Animation metadata
FIMD_CUSTOM = 10 Used to attach other metadata types to an image
FIMD_EXIF_RAW = 11 Exif metadata as a raw buffer
Not all of these models contain real metadata. For example, FIMD_ANIMATION is
contains an animated GIF's animation data. Read more about FreeImage's
metadata handling in the official FreeImage API documentation.
*) Image comment: you can use the FreeImage_Get/SetimageComment functions to access an image's comment more convenient than using the metadata functions explained below.
Actually, the information you are interested in, is stored in the
FIMD_EXIF_EXIF model. In EXIF as well as in FreeImage, the tag is named
"DateTimeOriginal" and has the id 36867. It is of type FIDT_ASCII, so the date
actually is encoded as a string value. According to the EXIF 2.2
specification, the date's format is "YYYY:MM:DD HH:MM:SS" with time shown in
24-hour format.
Getting all the tags for a certain metadata model with the FreeImage VB6
wrapper is easy. I'll give you a short example, that you could use to get the
creation date of the image.
DimhBitmapAsLongDimTags()AsFREE_IMAGE_TAGDimiAsLongCallFreeImage_InitErrorHandler' Load the imagehBitmap=FreeImage_LoadEx("C:\images\MyExifImage.jpg")' Get all the tags of model FIMD_EXIF_EXIF. Returns the number of tags found.If(FreeImage_GetAllMetadataTags(FIMD_EXIF_EXIF,hBitmap,Tags)>0)Then' We got some tags. Iterate over the tags and watch out for tag "DateTimeOriginal"Fori=0ToUBound(Tags)WithTags(i)If(.Key="DateTimeOriginal")ThenDebug.Print"Image created date: "&.ValueEndIfEndWithNextiEndIf' Don'tforgettounloadtheimage.CallFreeImage_UnloadEx(hBitmap)
Hope this helps.
Carsten
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Excellent!!! Thank you! This was frustrating and I apologize for missing this.
My problem is that I am a learn by example programmer, but maybe that makes me
not a programmer after all but a hacker or some such euphemism :-) What would
be a better word for that, maybe Structure Plagiarist or Cliff Notes Scholar,
or any number of good ones :-) . Thanks again.
Now that I hope you have accepted my apology, would you be up for an iteration
of FIMD_EXIF_MAKERNOTE? I spent the whole day and came up with nothing. I
don't think that all the definitions are in the MFreeImage.bas but I am quite
often wrong :-) :-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am now working on another project. I still need to find the camera model from the exif data. These are the only keys that I find available from the GetAllMetaTags call in your example:
The JPG is created with Canon S100. irFanview shows the data OK. I tried some of the ExifReader.cls files I found here and they crash on the new Canon JPG. Old model Canons are OK as well as Nikon.
UPDATE!!!!!!!!!!!!!!!!
I got it! Coming into using this from the bottom side up and the help here from the topside down (:-), I finally figured out to change the call above to FIMD_EXIF_MAIN and I printed out the results from 3 model cameras JPG examples .... (iteration through the key chain)
DateTime = 2013:01:27 20:15:16
ImageDescription =
Make = Canon
Model = Canon PowerShot S100
Orientation = 6
ResolutionUnit = 2
YCbCrPositioning = 2
===========
Artist =
Copyright =
DateTime = 2012:12:09 19:39:41
Make = NIKON CORPORATION
Model = NIKON D7000
Orientation = 1
ResolutionUnit = 2
Software = Ver.1.02
YCbCrPositioning = 2
===========
DateTime = 2010:10:05 16:24:47
Make = Canon
Model = Canon PowerShot SD850 IS
Orientation = 1
ResolutionUnit = 2
YCbCrPositioning = 1
===========
'Code to produce above: __
On Error Resume Next
Dim workPath as string
Dim dib As Long
Dim Tags() As FREE_IMAGE_TAG
workPath = "C:\yourfolder\yourfile.jpg"
'Assumed: MFreeImage.bas is named in our "Module" list
'Optional: We could iterate through a folder of files
'with the block below using FSO:
'Send subject image name and location to freeimage dll:
dib = FreeImage_Load(FIF_JPEG, workPath, 0)
'Get all the tags of FIMD_EXIF_MAIN. Returns the number of tags found.
If (FreeImage_GetAllMetadataTags(FIMD_EXIF_MAIN, dib, Tags) > 0) Then
' We got some tags. List them all out
For i = 0 To UBound(Tags)
With Tags(i)
Debug.Print " >>>> " & .Key & " = " & .Value
If .key = "Model" Then Msgbox "Model is: " & .value
End With
Next i
Debug.Print "============="
End If
FreeImage_Unload (dib)
Last edit: Don Juane 2013-02-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have spent a lot of time downloading and trying to use various VB6 examples
to obtain photo metadata. I have downloaded and tested literally every example
that exists online today and I have never found one that works on 100% of the
JPG files I encounter. Most of these JPG files are from newer Canon & Nikon
cameras and some of them have been edited and saved with Photoshop will a call
to enter Copyright information into the JPG. Sometimes my routine that calls
these API xxxxx.bas modules will run weeks without encountering a problem JPG
and sometimes only a few days. But time is irrelevant because eventually there
is always one rouge JPG that will cause one of the API calls to abend. The
strange thing is that programs such as iRfanView always show the correct EXIF
information even when the user contributed API module abends. I am not good
enough with API debugging or with understanding the structure of EXIF to debug
API classes and modules that extract or edit the EXIF data.
I also tried using the windows shell to extract "Date Picture Taken" metadata
from a JPG and my tests failed. I am assuming that one must have configured
the viewer for the particular folder being scanned to display these attributes
or the data is not available via a shell call either.
This frustration has led me to search for something else, maybe a DLL that is
more reliable for extracting EXIF data. I first found a GDI+ wrapper for VB6
but with no examples written in VB6 I was not able extract "Date Picture
Taken" or any photo metadata. Examples in Visual Basic 6 seem non existent for
GDI+ (GDIPlus).
Recently I finally found FreeImage with a VB6 wrapper with high hopes. It
support for EXIF but I am in the same situation as GDI+ because I can only
find one example written in VB6 and all it has included is 3 lines of code,
one to open FreeImage, another to convert a TIFF to a PNG file, and a third
line to close FreeImage.
Can someone supply me with more VB6 examples to extract metadata from a JPG. I
will take any other examples you have as well. I found the .NET sample to
enumerate metadata but I am not understanding .NET well enough to translate
that to VB6.
Thanks in advance for any examples or hints. (Please posters requesting I
switch to .NET - I am holding off for a little longer thanks.)
Hi Don Juane,
basically, it is very easy to get an image's metadata with the FreeImage VB6
wrapper. However, interpreting and so actually using EXIF metadata is much
more complicated.
With the VB6 wrapper, you have a VB-friendly structure FREE_IMAGE_TAG, which
provides you the metadata information, one for each metadata tag. Basically,
with FreeImage, a single metadata tag corresponds to a single line in
IrfanView's EXIF information window. Each tag has several fields, that contain
its type, value(s), key (name), description and id.
Especially with EXIF metadata, most of the information is stored by means of
reference numbers. I recommend having a look at the EXIF 2.2 specifiaction at
http://www.exif.org/specifications.html
However, this document does not directly relate to FreeImage's metadata
models, but can give you hints on how to interpret the values of the tags.
The fields Description, Key and Id or FREE_IMAGE_TAG correspondent to 'Tag
Name', 'Field Name' and 'Tag ID' of the various tables in the EXIF
specification (Table 4 at 4.6.5 Exif IFD Attribute Information for example)
respectively.
Field StringValue of FREE_IMAGE_TAG is the result of function
FreeImage_TagToString, which interprets most of the tags accordingly. However,
this only results in a string value, which may make it difficult to work with
in an application (read more about FreeImage_TagToString in the FreeImage API
documentation).
It depends on field 'Type', which of the various value fields are filled with
data. Expect for tags of type FIDT_ASCII (String type), field 'Count' contains
the number of values of the tag. If 'Count' is greater than 1, the actual
value is an array from 0 to 'Count' - 1. For FIDT_ASCII typed tags, 'Count'
contains the length of the string.
Field 'Value' is a Variant in VB and contains the properly typed value of the
tag for most tag types (expect for types FIDT_PALETTE and FIDT_(S)RATIONAL).
Tag of type FIDT_(S)RATIONAL are always represented as an array (even if
'Count' is 1, which results in an array with only one member with index 0).
Field 'RationalValue', which is an array of FIRATIONAL, which in turn contains
both numerator and denominator of the value. In that case, field 'Value' also
contains an array of of type Double which holds an approximated value of the
rational (expressed as an IEEE double precision floating value, Double in VB).
Also in FreeImage, metadata is divided into several metadata models. Each
model represents a number of tags, that belong to a certain type of metadata.
FIMD_COMMENTS = 0 single comment or keywords*)
FIMD_EXIF_MAIN = 1 Exif-TIFF metadata
FIMD_EXIF_EXIF = 2 Exif-specific metadata
FIMD_EXIF_GPS = 3 Exif GPS metadata
FIMD_EXIF_MAKERNOTE = 4 Exif maker note metadata
FIMD_EXIF_INTEROP = 5 Exif interoperability metadata
FIMD_IPTC = 6 IPTC/NAA metadata
FIMD_XMP = 7 Abobe XMP metadata
FIMD_GEOTIFF = 8 GeoTIFF metadata
FIMD_ANIMATION = 9 Animation metadata
FIMD_CUSTOM = 10 Used to attach other metadata types to an image
FIMD_EXIF_RAW = 11 Exif metadata as a raw buffer
Not all of these models contain real metadata. For example, FIMD_ANIMATION is
contains an animated GIF's animation data. Read more about FreeImage's
metadata handling in the official FreeImage API documentation.
*) Image comment: you can use the FreeImage_Get/SetimageComment functions to access an image's comment more convenient than using the metadata functions explained below.
Actually, the information you are interested in, is stored in the
FIMD_EXIF_EXIF model. In EXIF as well as in FreeImage, the tag is named
"DateTimeOriginal" and has the id 36867. It is of type FIDT_ASCII, so the date
actually is encoded as a string value. According to the EXIF 2.2
specification, the date's format is "YYYY:MM:DD HH:MM:SS" with time shown in
24-hour format.
Getting all the tags for a certain metadata model with the FreeImage VB6
wrapper is easy. I'll give you a short example, that you could use to get the
creation date of the image.
Hope this helps.
Carsten
Excellent!!! Thank you! This was frustrating and I apologize for missing this.
My problem is that I am a learn by example programmer, but maybe that makes me
not a programmer after all but a hacker or some such euphemism :-) What would
be a better word for that, maybe Structure Plagiarist or Cliff Notes Scholar,
or any number of good ones :-) . Thanks again.
Now that I hope you have accepted my apology, would you be up for an iteration
of FIMD_EXIF_MAKERNOTE? I spent the whole day and came up with nothing. I
don't think that all the definitions are in the MFreeImage.bas but I am quite
often wrong :-) :-)
I am now working on another project. I still need to find the camera model from the exif data. These are the only keys that I find available from the GetAllMetaTags call in your example:
CameraOwnerName
ColorSpace
ComponentsConfiguration
CompressedBitsPerPixel
CustomRendered
DateTimeDigitized
DateTimeOriginal
DigitalZoomRatio
ExifVersion
ExposureBiasValue
ExposureMode
ExposureTime
FNumber
FileSrc
Flash
FlashPixVersion
FocalLength
FocalPlaneResolutionUnit
FocalPlaneXResolution
FocalPlaneYResolution
ISOSpeedRatings
MaxApertureValue
MeteringMode
PixelXDimension
PixelYDimension
SceneCaptureType
SensingMethod
ShutterSpeedValue
Tag 0x8830
UserComment
WhiteBalance
The JPG is created with Canon S100. irFanview shows the data OK. I tried some of the ExifReader.cls files I found here and they crash on the new Canon JPG. Old model Canons are OK as well as Nikon.
UPDATE!!!!!!!!!!!!!!!!
I got it! Coming into using this from the bottom side up and the help here from the topside down (:-), I finally figured out to change the call above to FIMD_EXIF_MAIN and I printed out the results from 3 model cameras JPG examples .... (iteration through the key chain)
'Code to produce above: __
On Error Resume Next
Dim workPath as string
Dim dib As Long
Dim Tags() As FREE_IMAGE_TAG
workPath = "C:\yourfolder\yourfile.jpg"
'Assumed: MFreeImage.bas is named in our "Module" list
'Optional: We could iterate through a folder of files
'with the block below using FSO:
'Send subject image name and location to freeimage dll:
dib = FreeImage_Load(FIF_JPEG, workPath, 0)
'Get all the tags of FIMD_EXIF_MAIN. Returns the number of tags found.
If (FreeImage_GetAllMetadataTags(FIMD_EXIF_MAIN, dib, Tags) > 0) Then
' We got some tags. List them all out
For i = 0 To UBound(Tags)
With Tags(i)
Debug.Print " >>>> " & .Key & " = " & .Value
If .key = "Model" Then Msgbox "Model is: " & .value
End With
Next i
Debug.Print "============="
End If
FreeImage_Unload (dib)
Last edit: Don Juane 2013-02-20