Reading TIFF Image Metadata - c#

I'm currently writing an application to read a TIFF File and then perform some compression algorithm. I have successfully done that .. But now, I want to read the metadata of the TIFF Image, but can't seem to find the correct way to do that.
What library and function should I use?

Even if I do not know which metadata you need to read, maybe the standard TiffBitmapDecoder class can help you. Take a look to its Metadata property.

From:
http://www.codeproject.com/Articles/7888/A-library-to-simplify-access-to-image-metadata
In .NET Framework, you can store and retrieve metadata by calling the SetPropertyItem and GetPropertyItem methods of the Image class, and you don't have to be concerned with the details of how a particular file format stores that metadata.

Related

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.

Is it possible to add custom metadata to file?

I know that each file has metadata like title, subject, keywords and comments:
But what if I need custom metadata like tags for example?
Is it possible to do it with C#?
I know that each file has metadata like title, subject, keywords and comments
That is not true. Most file types do not have a 'standard' form of metadata.
In particular, PDF files don't have properties that Windows Explorer recognizes.
Metadata (file attributes) is not a function of the filesystem.
Office files use a structured format that allows for such attributes.
Jpeg ues EXIF, a different format
If using NTFS you can store whatever you like in an Alternate data stream
As per Jesper's comment, you can use the DSOFile library to read and write to Custom properties that are stored in ADS.
Works well for me though note the fact that the properties are lost when file is transferred to a different file system, including email.
see http://www.keysolutions.com/blogs/kenyee.nsf/d6plinks/KKYE-79KRU6 for a 64bit implementation, link to MS original and comments.
This will depend on whether the file type you are working with supports this. For example this will not be possible with a text file.
Has anyone thought of using the File ID for this? You can get it via the command
fsutil file queryfileid "C:/my/path/example.txt"
This could be used to store information about this file in a separate storage-file associated with the id.

Compress a file with GZipStream while maintaining its meta-data

How can I get the extension of compressed file after being compressed with System.IO.Compression.GZipStream?
For example, if the original file is named test.doc and compresses to test.gz, how do I know what file extension to use when decompressing?
There is no way to get the file name - in fact there may never be a filename at all, if for example a piece of data is created in memory and then send over a network connection.
Instead of replacing the file extension, why not append it, for example: test.doc.gz
Then you can simply strip it off when decompressing.
I had to do this some time ago. The solution is to use the J# libraries to do it. You still write it in C# however.
http://msdn.microsoft.com/en-us/magazine/cc164129.aspx
That's microsofts answer on the topic.
Not sure what is your question- I assume you want a mechanism to "remember" what the extension was before the compression took place?
If that is the question then the convention of test.doc compressing into test.doc.gz will work.
The test.gz is just a raw byte stream with no meta-data about what has been compressed (for example, original file name, extension etc). What you'd need to do is create an archive that contains the gzip stream and meta-data about each file contained in the archive.
The article linked to in Mech Software's answer provides a pretty reasonable way to implement this.
There was also this question (vaguely related) asked some time back which may help out:
How to compress a directory with the built in .net compression classes?

Is there an easy way to determine the type of a file without knowing the file's extension?

I have a table with a binary column which stores files of a number of different possible filetypes (PDF, BMP, JPEG, WAV, MP3, DOC, MPEG, AVI etc.), but no columns that store either the name or the type of the original file. Is there any easy way for me to process these rows and determine the type of each file stored in the binary column? Preferably it would be a utility that only reads the file headers, so that I don't have to fully extract each file to determine its type.
Clarification: I know that the approach here involves reading just the beginning of each file. I'm looking for a good resource (aka links) that can do this for me without too much fuss. Thanks.
Also, just C#/.NET on Windows, please. I'm not using Linux and can't use Cygwin (doesn't work on Windows CE, among other reasons).
you can use these tools to find the file format.
File Analyser
http://www.softpedia.com/get/Programming/Other-Programming-Files/File-Analyzer.shtml
What Format
http://www.jozy.nl/whatfmt.html
PE file format analyser
http://peid.has.it/
This website may be helpful for you.
http://mark0.net/onlinetrid.aspx
Note:
i have included the download links to make sure that you are getting the right tool name and information.
please verify the source before you download them.
i have used a tool in the past i think it is File Analyser, which will tell you the closest match.
happy tooling.
This is not a complete answer, but a place to start would be a "magic numbers" library. This examines the first few bytes of a file to determine a "magic number", which is compared against a known list of them. This is (at least part) of how the file command on Linux systems works.
Someone else asked a similar question and posted the code used to do exactly this. You should be able to take what is posted here, and slightly modify it so that it pulls from your database.
https://stackoverflow.com/questions/58510
In addition to that, it looks like someone has written a library based off of magic numbers to do this, however, it looks like the site requires registration, and some form of alternate access in order to download this lirbary. The documentation is avaliable for free without registration, that may be helpful.
http://software.topcoder.com/catalog/c_component.jsp?comp=13249160&ver=2
The easiest way I know is to use file command that it is also available in Windows with Cygwin .
A lot of filetypes have well defined headers that begin the file. You could check the first few bytes to check to see how the file begins.
Easiest way to do this would be through access to a *nix (or cygwin) system that has the 'file' command:
$ file visitors.*
visitors.html: HTML document text
visitors.png: PNG image data, 5360 x 2819, 8-bit colormap, non-interlaced
You could write a C# application that piped the first X bytes of each binary column to the file command (using - as the file name)
You need to use some p/invoke interop code to call the SHGetFileInfo method from the Win32 API. This article may also help.

How to get the EXIF data from a file using 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

Categories