How to get the EXIF data from a file using C# - c#

I would like to write a small program in C# which goes through my jpeg photos and, for example, sorts them into dated folders (using MY dating conventions, dammit...).
Does anyone know a relatively easy way to get at the EXIF data such as Date And Time or Exposure programatically?
Thanks!

As suggested, you can use some 3rd party library, or do it manually (which is not that much work), but the simplest and the most flexible is to perhaps use the built-in functionality in .NET. For more see:
System.Drawing.Image.PropertyItems Property
System.Drawing.Imaging.PropertyItem Class
How to: Read Image Metadata
I say "it’s the most flexible" because .NET does not try to interpret or coalesce the data in any way. For each EXIF you basically get an array of bytes. This may be good or bad depending on how much control you actually want.
Also, I should point out that the property list does not in fact directly correspond to the EXIF values. EXIF itself is stored in multiple tables with overlapping ID’s, but .NET puts everything in one list and redefines ID’s of some items. But as long as you don’t care about the precise EXIF ID’s, you should be fine with the .NET mapping.
Edit: It's possible to do it without loading the full image following this answer: https://stackoverflow.com/a/552642/2097240

Check out this metadata extractor. It is written in Java but has also been ported to C#. I have used the Java version to write a small utility to rename my jpeg files based on the date and model tags. Very easy to use.
EDIT metadata-extractor supports .NET too. It's a very fast and simple library for accessing metadata from images and videos.
It fully supports Exif, as well as IPTC, XMP and many other types of metadata from file types including JPEG, PNG, GIF, PNG, ICO, WebP, PSD, ...
var directories = ImageMetadataReader.ReadMetadata(imagePath);
// print out all metadata
foreach (var directory in directories)
foreach (var tag in directory.Tags)
Console.WriteLine($"{directory.Name} - {tag.Name} = {tag.Description}");
// access the date time
var subIfdDirectory = directories.OfType<ExifSubIfdDirectory>().FirstOrDefault();
var dateTime = subIfdDirectory?.GetDateTime(ExifDirectoryBase.TagDateTime);
It's available via NuGet and the code's on GitHub.

You can use TagLib# which is used by applications such as F-Spot. Besides Exif, it will read a good amount of metadata formats for image, audio and video.
I also like ExifUtils API but it is buggy and is not actively developed.

Here is a link to another similar SO question, which has an answer pointing to this good article on "Reading, writing and photo metadata" in .Net.

Image class has PropertyItems and PropertyIdList properties. You can use them.

Getting EXIF data from a JPEG image involves:
Seeking to the JPEG markers which mentions the beginning of the EXIF data,. e.g. normally oxFFE1 is the marker inserted while encoding EXIF data, which is a APPlication segment, where EXIF data goes.
Parse all the data from say 0xFFE1 to 0xFFE2 . This data would be stream of bytes, in the JPEG encoded file.
ASCII equivalent of these bytes would contain various information related to Image Date, Camera Model Name, Exposure etc...

The command line tool ExifTool by Phil Harvey works with dozens of images formats - including plenty of proprietary RAW formats - and can manipulate a variety of metadata formats including EXIF, GPS, IPTC, XMP, JFIF.
Very easy to use, lightweight, impressive application.

Recently, I used this .NET Metadata API. I have also written a blog post about it, that shows reading, updating, and removing the EXIF data from images using C#.
using (Metadata metadata = new Metadata("image.jpg"))
{
IExif root = metadata.GetRootPackage() as IExif;
if (root != null && root.ExifPackage != null)
{
Console.WriteLine(root.ExifPackage.DateTime);
}
}

fastest way is to use windows api codec that doesn't open file and instead uses cached exif information
var prop = ShellFile.FromFilePath(f).Properties;
var Dimensions = prop.GetProperty("Dimensions").ValueAsObject.ToString();
//1280 x 800

Related

remove Image meta data from Image in C# [duplicate]

I'm writing a service for a project that's going to handle our image processing. One such process is supposed to strip all metadata from the byte[] provided and return the same image as a byte[].
The method I'm currently working on involves always converting the image to a Bitmap, then converting it back to the original format and returning the data from a MemoryStream.
I haven't been able to test it yet but something tells me I'm going to experience some quality loss.
How can I remove all metadata from any image with a common format?
(bmp, gif, png, jpg, icon, tiff)
Not sure how I can narrow that down any further. Would be nice if I got some feedback regarding the downvotes.
For the lossless formats (except JPEG), your idea of loading it as a bitmap and re-saving is fine. Not sure if .NET natively supports TIFFs (I doubt it does).
For JPEGs, as you suggested there may be quality loss if you're re-compressing the file after decompressing it. For that, you might try the ExifLibrary and see if that has anything. If not, there are command line tools (like ImageMagick) that can strip metadata. (If you use ImageMagick, you're all set, since it supports all of your required formats. The command you want is convert -strip.)
For TIFFs, .NET has built-in TiffBitmapDecoder and ...Encoder classes you might be able to use; see here.
In short, using an external tool like ImageMagick is definitely the easiest solution. If you can't use an external tool, you're almost certainly going to need to special-case the formats that .NET doesn't support natively (and the lossy JPEG).
EDIT: I just read that ImageMagick doesn't do lossless stripping with JPEGs, sorry. I guess using the library I linked above, or some other JPEG library, is the best I can think of.

Reading and Writing all JPEG metadata in Silverlight

I've developed a Silverlight application that needs to compress JPEG images on the client. I've been using a library called FJCore to achieve this goal.
One of the biggest issues I'm encountering, however, is the fact that this toolkit requires you to convert the JPEG to a WriteableBitmap first which strips off all the metadata associated with the JPEG such as EXIF, XMP, JFIF, etc. I've modified the source of the FJCore library to persist the EXIF, compress the image, and then reattach the EXIF data. This process works but loses other types of metadata information.
Instead of having to implement a function that saves and writes each different type of metadata that exists for the JPEG format, I am looking for a simplified approach that will allow me to extract all metadata, regardless of type or format, use the FJCore toolkit to compress/resize that image, and then reattach all the previously saved metadata. Some direction or sample code that could help me achieve my goal would be greatly appreciated. Remember, this is a Silverlight application, so those .NET libraries are what I have to work with.
Thank you.
You can do this using FJCore aka ImageTools. All you need to do is add this on line 212:
// Exif. Do something?
headers.Add(header);
https://github.com/briandonahue/FluxJpeg.Core/blob/master/FJCore/Decoder/JpegDecoder.cs
And make sure you copy those headers when resizing:
jpegOut = new DecodedJpeg(
new ImageResizer(jpegIn.Image)
.Resize(320, ResamplingFilters.NearestNeighbor),
jpegIn.MetaHeaders); // Retain EXIF details
Recompile and you should be good to go.

Adding EXIF Info to Images in C#

I want to add basic exif info to images like author,camera model,date etc.Is there a way to do this using the Inbuilt classes without using other external libraries.Does the image formats like JPEG,PNG,TIFF,BMP,GIF Support all EXIF Fields.
System.Drawing allows modifying the image properties with PropertyItems/SetPropertyItem. A sample can be found here.
But this access is quite basic and there are quite a few libraries around (see for instance How to edit EXIF data in .NET). So I wonder if it's worth the trouble.
After all, only JPEG and TIFF files support EXIF metadata according to Wikipedia.

Using C#, how do I search for images in a Windows file system like TinEye.com does on the web?

Hi and thanks for looking!
Update
For the sake of clarity, a third-party .NET library is just fine. Preferably an open-source or free one. The solution need not be native .NET.
Background
I am working on an enterprise web application for which the client has given us thousands of pages of content in MS Word documents that we have to parse, extract data, and send to the content database.
Within these docs are various embedded images representing a larger original image in a separate folder.
The client did not provide any paths to the original source image, so when we see content with an embedded image in the MS Word doc, we have to go through several "assets" folders and look for the corresponding image which is extraordinarily time consuming.
We are already using DocX to parse the documents, so you can assume that we have a list of bitmap images to loop through that we have pulled from the document.
Question
Given a list of bitmaps that we just extracted from the document, how do we search a different folder containing hundreds of images, for the matching image, and then return the file path to it?
TinEye.com does this over the web. I am wondering if, using System.Drawing or something, we can do it on a PC with C#.
Thanks!
Matt
Hate to propose an answer to my own question, but I think I might be on to something here. Here is heuristic/pseudo code for a C# forms app--your thoughts are appreciated:
Part 1
Using System.IO, traverse the "assets" folders and get all images.
For each image, Base64 encode it.
Take the resulting string and place in an XML file:
<Image>
<Path>C:\SomePath</Path>
<EncodedString>[Some Base64 String]<Encoded String>
</Image>
Now we have an XML file containing all original images, in Base64 form, along with their file path.
Part 2
Using DocX, extract all images from MS Word Doc.
For each image, use Linq-to-Xml to search for an exact match in the XML file from Part 1.
If there are no exact matches, start iterating the XML file and computing the Levenshtein distance.
While in the foreach store the XML node Id (or file path) and Levenshtein Distance as a key value pair in an object.
Take the k/v pair with the lowest LD score and return the file path.
For performance, set tolerance so that the foreach stops if a certain original image has an acceptably low LD score when compared to the image extracted from the document.
Since this is a one-off task, I don't need instant performance. So, I could run this tonight before leaving the office and, hopefully, come back tomorrow to a list of paths connecting the original images to the ones embedded in the docs.
UPDATE
The heuristic above worked beautifully! I ended up using the Sift library to efficiently calculate distances between Base64 strings. Specifically, I used their FastDistance() method. Having 100% accuracy on finding the images I need, even if the angle from which the photo was taken is slightly different.
There is no built-in algorithm in the .NET framework for generating image similarity. You'd need to use a third-party library or do it yourself. Lots of image similarity algo questions on SO:
Algorithm for finding similar images
How can I measure the similarity between two images?
comparing images programmatically - lib or class
One more, for .NET: Are there any OK image recognition libraries for .NET?. This one refers you to AForge, which seems to have the algorithm that you are after.
According to this SO answer to a similar question, you should look at OpenCV and VLFeat. The former has a C++ API and the latter a C API, so you would need to write your own P/Invoke wrapper or perhaps wrap them in a C++/CLI facade, which you could call from C#.

How to create an image from a raw data of DICOM image

I have a raw pixel data in a byte[] from a DICOM image.
Now I would like to convert this byte[] to an Image object.
I tried:
Image img = Image.FromStream(new MemoryStream(byteArray));
but this is not working for me. What else should I be using ?
One thing to be aware of is that a dicom "image" is not necessarily just image data. The dicom file format contains much more than raw image data. This may be where you're getting hung up. Consider checking out the dicom file standard which you should be able to find linked on the wikipedia article for dicom. This should help you figure out how to parse out the information you're actually interested in.
You have to do the following
Identify the PIXEL DATA tag from the file. You may use FileStream to read byte by byte.
Read the pixel data
Convert it to RGB
Create a BitMap object from the RGB
Use Graphics class to draw the BitMap on a panel.
The pixel data usually (if not always) ends up at the end of the DICOM data. If you can figure out width, height, stride and color depth, it should be doable to skip to the (7FE0,0010) data element value and just grab the succeeding bytes. This is the trick that most normal image viewers use when they show DICOM images.
There is a C# library called EvilDicom (http://rexcardan.com/evildicom/) that can be used to pull the image out of a DICOM file. It has a tutorial on how to do it on the website.
You should use GDCM.
Grassroots DiCoM is a C++ library for DICOM medical files. It is automatically wrapped to python/C#/Java (using swig). It supports RAW, JPEG 8/12/16bits (lossy/lossless), JPEG 2000, JPEG-LS, RLE and deflated (zlib).
It is portable and is known to run on most system (Win32, linux, MacOSX).
http://gdcm.sourceforge.net/wiki/index.php/GDCM_Release_2.4
See for example:
http://gdcm.sourceforge.net/html/DecompressImage_8cs-example.html
Are you working with a pure standard DICOM File? I've been maintainning a DICOM parser for over a two years and I came across some realy strange DICOM files that didn't completely fulfill the standard (companies implementing their "own" twisted standard DICOM files) . flush you byte array into a file and test whether your image viewer(irfanview, picassa or whatever) can show it. If your code is working with a normal JPEG stream then from my experience , 99.9999% chance that this simply because the file voilate the standard in some strange way ( and believe me , medical companies does that a lot)
Also note that DICOM standard support several variants of the JPEG standard . could be that the Bitmap class doesn't support the data you get from the DICOM file. Can you please write down the transfer syntax?
You are welcome to send me the file (if it's not big) yossi1981#gmail.com , I can check it out , There was a time I've been hex-editing DICOM file for a half a year.
DICOM is a ridiculous specification and I sincerely hope it gets overhauled in the near future. That said Offis has a software suite "DCMTK" which is fairly good at converting dicoms with the various popular encodings. Just trying to skip ahead in the file x-bytes will probably be fine for a single file but if you have a volume or several volumes a more robust strategy is in order. I used DCMTK's conversion code and just grabbed the image bits before they went into a pnm. The file you'll be looking for in DCMTK is dcm2pnm or possibly dcmj2pnm depending on the encoding scheme.
I had a problem with the scale window that I fixed with one of the runtime flags. DCMTK is open source and comes with fairly simple build instructions.

Categories