 |
|
 |
Hi,
Great DLL
But I can't get tag 256 and 257 :
--------------------
Dim X
Dim Y
If ExifRead.GetTagValue(ExifTags.ImageWidth, X) = True and ExifRead.GetTagValue(ExifTags.ImageLength, Y) = True Then
ListBox1.Items.Add("size: " & X & " X " & Y & " Pixels")
End If
--------------------
return nothing
marcus1
|
|
|
|
 |
|
 |
Hi Marcus,
It may simply be that your images don't contain the image width and height. None of my cameras (Nikon D90, Canon A710, Fujifilm FinePix S9500) include these tags in images, probably because they're direct properties of the pixel data itself. Try running the exiftest utiity included in the source pack on one of your images to see which tags are available in your images.
If your images don't contain these tags, you can retrieve it via GDI+:
Image image = Image.FromFile("image.jpg");
Console.WriteLine("Dimensions: {0},{1}", image.Height, image.Width);
There's also a stackoverflow article which describes a faster, but less tested approach.
Cheers,
Simon
|
|
|
|
 |
|
 |
Hi,
I am a bit of a newbie here, particularly when it comes to delegates, lambda, etc. I am trying to build this DLL in VS 2008, but am running into issues with the delegate definition:
private delegate T ConverterMethod<out T>(byte[] data);
I created new files (of course the 2010 solution won't open in 2008), but I receive the following errors: 'Type expected', 'Identifier expected', and '; expected'. I believe delegate behaviour is different in 2010. Is the 'out' keyword causing the issue? I removed it, but then end up will many errors relating to the delegate call. Namely many of these:
Error 1 The type arguments for method 'ExifLib.ExifReader.GetArray(byte[], int, ExifLib.ExifReader.ConverterMethod)' cannot be inferred from the usage. Try specifying the type arguments explicitly. C:\Data\GandCanyon\Code\ExifLib\ExifLib\ExifReader.cs 452 47 ExifLib
I found this link:
http://blogs.msdn.com/b/charlie/archive/2008/10/28/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
Am I on the right track? Any thoughts from anyone in getting this up-and-running in VS 2008?
Thanks in advance!
|
|
|
|
 |
|
 |
Hi,
This is really surprising - I always assumed that if you maintained the same framework, the version of Visual Studio couldn't make a difference to how your code compiled!
Anyway, there are 2 issues here:
ConverterMethod<T> is covariant in the new VS2010 code. It's not needed in the current implementation of ExifLib, but is done to allow more flexibility of delegate assignments in future code. Studio 2008 doesn't know about covariance!
- Visual Studio 2008 isn't as good at type inference as Visual Studio 2010
Here's what you need to change:
- Change
private delegate T ConverterMethod<out T>(byte[] data); to private delegate T ConverterMethod<T>(byte[] data);
- In
ExifReader.GetTagValue, change all calls to GetArray() to use explicit type arguments, i.e, instead of result = (T) (object) GetArray(tagData, fieldLength, ToUint), use result = (T) (object) GetArray<uint>(tagData, fieldLength, ToUint)
Thanks for the interesting question!
modified 29 Feb '12.
|
|
|
|
 |
|
 |
I would probably gain even more traction if it was on nuget.org
Thanks
|
|
|
|
 |
|
|
 |
|
 |
Makersnote: Extremely many numbers - Is it the Image (or a thumpsnail)
Usercomments:Many numbers - but not as many as above
(This goes for pictures from Minolta dImage xi as well as Oly E-620).
UPDATE:
A bit of googling revealed, that MakerNote Tag in itself is a tagged area.
Check here: http://www.exiv2.org/tags-olympus.html[^]
Now I "just" need to find out how to decompose this entry. The quick hit to add the Olympus tags into the ExifTags was a "No hit".
modified 18 Feb '12.
|
|
|
|
 |
|
 |
Hi,
In ExifReader.CreateTagIndex, after the main index is created, the GPS IFD is also indexed (ExifReader.cs:378). Could you do the same with your MakerNote field?
Cheers,
Simon
|
|
|
|
 |
|
 |
your lib work perfect, but I don't find image Title, Keywords info that we can see in Explorer file info in Windows. As I undestood it's not EXIF info? so how to read those data?
modified 5 Feb '12.
|
|
|
|
 |
|
 |
Hi Jan,
The fields you're looking for are contained within the IPTC header of the image. Have a look at this stackoverflow article for information about IPTC data extraction:
Reading IPTC information with C#, .NET Framework 2[^]
Note that the title of the image is also available in the EXIF as "ImageDescription".
Cheers,
Simon
|
|
|
|
 |
|
 |
I love this tool and I really think it needs some more publicity. Have you thought of adding it to nuget? I would love to have it on nuget and wouldn't mind helping.
Thanks for a great tool
|
|
|
|
 |
|
|
 |
|
 |
I was very disappointed when I found GDI does not support some GPS tags on windows XP.
Then I found your code perfectly fit to my project.
Thank you very much!
|
|
|
|
 |
|
 |
Hi Simon,
thanks for your article.
A question : how to get the gps coordinates (lat/long), these don't appear in the list ? (my pic contains these data according to a commercial software)
Thanks for your answer,
Domi.
|
|
|
|
 |
|
 |
Hi Domi,
The GPS data can be extracted using any of the ExifTags.Gps... enums:
double[] gpsLatitude;
if (reader.GetTagValue(ExifTags.GPSLatitude, out gpsLatitude))
{
MessageBox.Show(this, string.Format("Latitude: {0}°{1}'{2}\"", gpsLatitude[0], gpsLatitude[1], gpsLatitude[2]), "Image information", MessageBoxButtons.OK);
}
Cheers,
Simon
|
|
|
|
 |
|
 |
I will check this ASAP !
thanks for your fast reply & for this info, Simon.
Sincerly,
Domi.
|
|
|
|
 |
|
 |
Hello,
I just want to try your library, but can't find the dll to reference you're talking about (Ok, I'm a noob with .net stuff but want to improve my image gallery media center app). Do I have to compile the dll on my own? I first tried to import your two files (ExifReader.cs and ExifTag.cs) into my project. But it won't rebuild anymore with mainly following errors:
* line 285: ("convertedData.SetValue(converter(buffer), elementCount);") => Error: "Delegate 'MyProject.Code.Exif.ExifReader.ConverterMethod' has some invalid arguments"
* line 452: ("private result = (T) (object) GetArray(tagData, fieldLength, ToUShort);" and all other calls to GetArray) => Error "The type arguments for method 'MyProject.Code.Exif.ExifReader.GetArray(byte[], int, MyProject.Code.Exif.ExifReader.ConverterMethod)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Could you please give me a hint with this generics stuff or at least how I can get a compiled dll.
Thanks,
Sebastian
|
|
|
|
 |
|
 |
Hi Sebastian,
The easiest way to get the DLL is to just open ExifLibrary.sln and build it on its own, then take a copy of the compiled DLL from the \bin\Debug or \bin\Release folder. Alternatively, just add the whole ExifLib project to your solution and add a project reference to ExifLib to your existing project.
It's hard for me to tell what your type usage problem is, but I think it'll go away if you follow the above steps.
Cheers,
Simon
|
|
|
|
 |
|
 |
When converting the tagdata to ushort, the bytes are reversed in case of big endian.
For example: orientation 0800 becomes 0080. This results always in zero when converting to ushort.
This is due to a bug in GetTagBytes.
From the spec "4.6.2 IFD Structure"
"In cases where the value fits in 4 bytes, the value itself is recorded.
If the value is smaller than 4 bytes, the value is stored in the 4-byte area starting from the left,
i.e., from the lower end of the byte offset area. For example, in big endian format,
if the type is SHORT and the value is 1, it is recorded as 00010000.H.
So in the method GetTagBytes, we should add
if (dataSize < 4)
{
byte[] data = new byte[dataSize];
Buffer.BlockCopy(tagData, 0, data, 0, dataSize);
return data;
}
|
|
|
|
 |
|
 |
Thanks for the pickup! I've updated GetTagBytes, although I went with Array.Resize instead of Buffer.BlockCopy. Note that Array.Resize doesn't do anything when no size change is required.
Cheers,
Simon
|
|
|
|
 |
|
 |
I modified your speed test method to instead call these respective methods at the bottom of this. And testing with two large (3 and 5mb) reading all the tags yours was around 80% of the speed of GetPropertyItem.
Assuming my tests are relatively accurate, it appears your library should be much faster to get a handful of exif data, but if you wanted to read all the tags from number of images you'd be better off using a different library.
public static void LoadAllTags(ExifReader reader)
{
StringBuilder props = new StringBuilder();
foreach (ushort tagID in Enum.GetValues(typeof(ExifTags)))
{
object val;
if (reader.GetTagValue<object>(tagID, out val))
{
props.Append(val.ToString());
}
}
}
public static void LoadAllTags(Image image)
{
StringBuilder props = new StringBuilder();
foreach (ushort tagID in Enum.GetValues(typeof(ExifTags)))
{
PropertyItem propertyItem = image.GetPropertyItem((int)ExifTags.Model);
string val = BitConverter.ToString(propertyItem.Value, 0);
props.Append(val.ToString());
}
}
|
|
|
|
 |
|
 |
Hi Thymine, and thanks for the feedback.
While my test counts tags read in 5 seconds, yours presumably works out time taken to read all tags. In the end, however, the result is the same - tags per second. The difference you've observed may be one of 2 things:
1. The code was originally written for .NET 2.0 and the imaging libraries in the framework may have improved since then. I certainly haven't tried it with newer frameworks
2. You haven't included the image load time in your test. Since the Image class loads the tags on construction, that's the item you really need to be timing.
If your purpose is to load every tag from the image, you may find it worthwhile altering the "on demand" mode of ExifLib into a serial reader, which would take minimal coding to implement. This would improve efficiency, as it would remove the need for all the stream seek operations performed during tag retrieval.
In the end, for the vast majority of applications, where you don't need to read every EXIF tag from a file, ExifLib will perform much faster than GDI+, which is the purpose for which is was originally written.
All the best,
Simon
|
|
|
|
 |
|
 |
Yes the point I believe I was meaning to make was that for the few cases where someone will want to read every EXIF tag from a file, your library is not optimized.
It sounds like it could be optimized by "altering the "on demand" mode ExifLib into a serial reader" as you mention, so thank you for pointing that out.
When I read only a handful of tags I got similar speed differences as others who have posted (where yours is unbelievably faster), I just wanted to point out that for reading every tag how the code was released is not optimal.
Your library is very useful, and seems like a good way to see how EXIF works.
|
|
|
|
 |
|
 |
Hello!
Thanks for sharing. I ran into a problem trying to extract the ExifTags.FocalLengthIn35mmFilm. I took images from Nikon, Canon, Logitech and some mobiles but no success. ExifTags.Copyright, ExifTags.Make, ExifTags.FocalLength and others are returning correct values while ExifTags.FocalLengthIn35mmFilm comes back empty or 0.0 .
What could I have done wrong? Thanks.
Where do I find a list of the Types for each ExifTags.Tag? That would be helpful.
Which ExifTags.Tag contains the dimensions of the CCD chip?
cheers carin
modified on Sunday, September 5, 2010 11:14 AM
|
|
|
|
 |
|
 |
Hi,
I've just run through some photos from a Canon compact, a Fujifilm bridge, and a Nikon SLR, and they all had the focal length populated (it was a double). Unfortunately data types aren't fixed & may vary between manufacturers, as you can see from some of the previous posts.
There's no sensor size in the EXIF data, but on cameras which populate the FocalLengthIn35mmFilm property, you can work it out from that.
To get a rough list of datatypes, I'd recommend modifying the test app to spit out val.GetType().
|
|
|
|
 |