Reading windows file metadata

Get All Metadata Info Of Your Files
Online & For Free – No Registration, No Installation!

Metadata2Go.com is a free online tool that allows you to access the hidden exif & meta data of your files.

Just drag & drop or upload an image, document, video, audio or even e-book file. We will show you all metadata hidden inside the file!

No matter if image metadata, document information or video exif – we check your file for you!

Metadata is, basically, information about other data.

Many files contain extra or even hidden data other than the visual data you see at first glance. E-books, photographs, movies, music and even documents can contain data that you don’t see at first glance.

If you can check a file for it’s exif online, so can anyone else. Knowing all information about your file is crucial in terms of privacy! Check photos or documents you share online for information you may not want to share with the world.

Of course we handle your files 100% secure!

Photos contain exif data that can give you useful information about the picture. Information such as shutter speed and focal length are stored inside an image. Likewise, you can find out where the photo was taken by looking at the location information

An online exif data reader can show you all these hidden information.

Similar to photos, videos contain metadata info about the location where the video was shot. Likewise, container formats like AVI and MP4 contain meta information about codecs, video and audio streams and more.

A metadata viewer reveals information of video files you may not be aware of.

Documents can contain metadata too. They include information such as file size and date of creation, but also information about the author of a document and the software used to create it.

Reading and Writing Metadata

Some image files contain metadata that you can read to determine features of the image. For example, a digital photograph might contain metadata that you can read to determine the make and model of the camera used to capture the image. With Windows GDI+, you can read existing metadata, and you can also write new metadata to image files.

GDI+ provides a uniform way of storing and retrieving metadata from image files in various formats. In GDI+, a piece of metadata is called a property item. 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 about the details of how a particular file format stores that metadata.

GDI+ currently supports metadata for the TIFF, JPEG, Exif, and PNG file formats. The Exif format, which specifies how to store images captured by digital still cameras, is built on top of the TIFF and JPEG formats. Exif uses the TIFF format for uncompressed pixel data and the JPEG format for compressed pixel data.

GDI+ defines a set of property tags that identify property items. Certain tags are general-purpose; that is, they are supported by all of the file formats mentioned in the preceding paragraph. Other tags are special-purpose and apply only to certain formats. If you try to save a property item to a file that does not support that property item, GDI+ ignores the request. More specifically, the Image::SetPropertyItem method returns PropertyNotSupported.

You can determine the property items that are stored in an image file by calling Image::GetPropertyIdList. If you try to retrieve a property item that is not in the file, GDI+ ignores the request. More specifically, the Image::GetPropertyItem method returns PropertyNotFound.

Reading Metadata from a File

The following console application calls the GetPropertySize method of an Image object to determine how many pieces of metadata are in the file FakePhoto.jpg.

The preceding code, along with a particular file, FakePhoto.jpg, produced the following output:

GDI+ stores an individual piece of metadata in a PropertyItem object. You can call the GetAllPropertyItems method of the Image class to retrieve all the metadata from a file. The GetAllPropertyItems method returns an array of PropertyItem objects. Before you call GetAllPropertyItems, you must allocate a buffer large enough to receive that array. You can call the GetPropertySize method of the Image class to get the size (in bytes) of the required buffer.

A PropertyItem object has the following four public members:

id A tag that identifies the metadata item. The values that can be assigned to id (PropertyTagImageTitle, PropertyTagEquipMake, PropertyTagExifExposureTime, and the like) are defined in Gdiplusimaging.h.
length The length, in bytes, of the array of values pointed to by the value data member. Note that if the type data member is set to PropertyTagTypeASCII, then the length data member is the length of a null-terminated character string, including the NULL terminator.
type The data type of the values in the array pointed to by the value data member. Constants (PropertyTagTypeByte, PropertyTagTypeASCII, and the like) that represent various data types are described in Image Property Tag Type Constants.
value A pointer to an array of values.

The following console application reads and displays the seven pieces of metadata in the file FakePhoto.jpg. The main function relies on the helper function PropertyTypeFromWORD, which is shown following the main function.

The preceding console application produces the following output:

The preceding output shows a hexadecimal ID number for each property item. You can look up those ID numbers in Image Property Tag Constants and find out that they represent the following property tags.

Hexadecimal value Property tag
0x0320 0x010f
В 0x0110
В 0x9003
В 0x829a
В 0x5090
В 0x5091
PropertyTagImageTitle PropertyTagEquipMake
В PropertyTagEquipModel
В PropertyTagExifDTOriginal
В PropertyTagExifExposureTime
В PropertyTagLuminanceTable
В PropertyTagChrominanceTable

The second (index 1) property item in the list has id PropertyTagEquipMake and type PropertyTagTypeASCII. The following example, which is a continuation of the previous console application, displays the value of that property item:

The preceding line of code produces the following output:

The fifth (index 4) property item in the list has id PropertyTagExifExposureTime and type PropertyTagTypeRational. That data type (PropertyTagTypeRational) is a pair of LONGs. The following example, which is a continuation of the previous console application, displays those two LONG values as a fraction. That fraction, 1/125, is the exposure time measured in seconds.

The preceding code produces the following output:

Writing Metadata to a File

To write an item of metadata to an Image object, initialize a PropertyItem object and then pass the address of that PropertyItem object to the SetPropertyItem method of the Image object.

The following console application writes one item (the image title) of metadata to an Image object and then saves the image in the disk file FakePhoto2.jpg. The main function relies on the helper function GetEncoderClsid, which is shown in the topic Retrieving the Class Identifier for an Encoder.

Overview of Reading and Writing Image Metadata

This topic provides an overview of how you can use the Windows Imaging Component (WIC)В APIs to read and write metadata that is embedded in image files.

This topic contains the following sections.

Prerequisites

To understand this topic, you should be familiar with the WIC metadata system as described in the WIC Metadata Overview. You should also be familiar with the query language used to read and write metadata, as described in Metadata Query Language Overview.

Introduction

WIC provides application developers with Component Object Model (COM) components to read and write metadata embedded in image files. There are two ways to read and write metadata:

  • Using a query reader/writer and a query expression to query metadata blocks for nested blocks or specific metadata within a block.
  • Using a metadata handler (a metadata reader or a metadata writer) to access the nested metadata blocks or specific metadata within the metadata blocks.

The easiest of these is to use a query reader/writer and a query expression to access the metadata. A query reader (IWICMetadataQueryReader) is used to read metadata while a query writer (IWICMetadataQueryWriter) is used to write metadata. Both of these use a query expression to read or write the desired metadata. Behind the scenes, a query reader (and writer) uses a metadata handler to access the metadata described by the query expression.

The more advanced method is to directly access the metadata handlers. A metadata handler is obtained from the individual frames using a block reader (IWICMetadataBlockReader) or a block writer (IWICMetadataBlockWriter). The two types of metadata handlers available are the metadata reader (IWICMetadataReader) and the metadata writer (IWICMetadataWriter).

The following diagram of the contents of a JPEG image file is used throughout the examples in this topic. The image represented by this diagram was created by using Microsoft Paint; the rating metadata was added by using the Photo Gallery feature of WindowsВ Vista.

Reading Metadadata Using a Query Reader

The easiest way to read metadata is to use the query reader interface, IWICMetadataQueryReader. The query reader enables you to read metadata blocks and items within metadata blocks using a query expression.

There are three ways to obtain a query reader: through a bitmap decoder (IWICBitmapDecoder), through its individual frames (IWICBitmapFrameDecode), or through a query writer (IWICMetadataQueryWriter).

Obtaining a Query Reader

The following example code shows how to obtain a bitmap decoder from the imaging factory and retrieve an individual bitmap frame. This code also performs setup work needed to obtain a query reader from a decoded frame.

The bitmap decoder for the test.jpg file is obtained by using the CreateDecoderFromFilename method of the imaging factory. In this method, the fourth parameter is set to the value WICDecodeMetadataCacheOnDemand from the WICDecodeOptions enumeration. This tells the decoder to cache the metadata when the metadata is needed; either by obtaining a query reader or the underlying metadata reader. Using this option enables you to retain the stream to the metadata required for fast metadata encoding and enables lossless decoding of the JPEG image. Alternatively, you could use the other WICDecodeOptions value, WICDecodeMetadataCacheOnLoad, which caches the embedded image metadata as soon as the image is loaded.

To obtain the frame’s query reader, make a simple call to the frame’s GetMetadataQueryReader method. The following code demonstrates this call.

Similarly, a query reader can also be obtained at the decoder level. A simple call to the decoder’s GetMetadataQueryReader method gets the decoder’s query reader. An decoder’s query reader, unlike a frame’s query reader, reads metadata for an image that is outside of the individual frames. However, this scenario is not common, and the native image formats do not support this capability. The native image CODECS provided by WIC read and write metadata at the frame level even for single-frame formats such as JPEG.

Reading Metadata

Before you move on to actually reading metadata, look at the following diagram of a JPEG file that includes embedded metadata blocks and actual data to retrieve. This diagram provides callouts to specific metadata blocks and items within the image providing the metadata query expression to each block or item.

To query for embedded metadata blocks or specific items by name, call the GetMetadataByName method. This method takes a query expression and a PROPVARIANT in which the metadata item is returned. The following code queries for a nested metadata block and converts the IUnknown component provided by the PROPVARIANT value to a query reader if found.

The query expression «/app1/ifd» is querying for the IFD block nested in the App1 block. The JPEG image file contains the IFD nested metadata block, so the PROPVARIANT is returned with a variable type (vt) of VT_UNKNOWN and a pointer to an IUnknown interface (punkVal). You then query the IUnknown interface for a query reader.

The following code demonstrates a new query based on the new query reader relative to the nested IFD block.

The query expression «/» queries the IFD block for the MicrosoftPhoto rating embedded under tag 18249. The PROPVARIANT value will now contain a value type of VT_UI2 and a data value of 50.

However, it is not necessary to obtain a nested block before querying for specific data values. For instance, instead of querying for the nested IFD and then for the MicrosoftPhoto rating, you can instead use the root metadata block and the query shown in the following code to obtain the same information.

In addition to querying for specific metadata items in a metadata block, you can also enumerate all the metadata items in a metadata block (not including metadata items in nested metadata blocks). To enumerate the metadata items in the current block, the query reader’s GetEnumeration method is used. This method obtains an IEnumString interface populated with the metadata items in the current block. For example, the following code enumerates the XMP rating and MicrosoftPhoto rating for the nested IFD block that was obtained earlier.

For more information on identifying appropriate tags for various image formats and metadata formats, see Native Image Format Metadata Queries.

Additional Query Reader Methods

In addition to reading metadata, you can also obtain additional information about the query reader and obtain metadata through other means. The query reader provides two methods that provide information about the query reader, GetContainerFormat and GetLocation.

With the embedded query reader, you can use GetContainerFormat to determine the type of metadata block, and you can call GetLocation to obtain the path relative to the root metadata block. The following code queries the embedded query reader for its location.

The call to GetContainerFormat for the embedded query reader returns the IFD metadata format GUID. The call to GetLocation returns a namespace of «/app1/ifd»; providing you with the relative path from which subsequent queries to the new query reader will be executed. Of course, the preceding code isn’t very useful, but it does demonstrate how to use the GetLocation method for finding nested metadata blocks.

Writing Metadata Using a Query Writer

Some of the code examples provided in this section are not shown in the context of the actual steps required to write metadata. To view the code examples in the context of a working sample, see the How-to: Re-encode an Image with Metadata tutorial.

The main component for writing metadata is the query writer (IWICMetadataQueryWriter). The query writer enables you to set and remove metadata blocks and items within a metadata block.

Like the query reader, there are three ways to obtain a query writer: through a bitmap encoder (IWICBitmapEncoder), through its individual frames (IWICBitmapFrameEncode), or through a fast metadata encoder (IWICFastMetadataEncoder).

Obtaining a Query Writer

The most common query writer is for an individual frame of a bitmap. This query writer sets and removes an image frame’s metadata blocks and items. To obtain an image frame’s query writer, call the frame’s GetMetadataQueryWriter method. The following code demonstrates the simple method call to obtain a frame’s query writer.

Similarly, a query writer can also be obtained for the encoder level. A simple call to the encoder’s GetMetadataQueryWriter method gets the encoder’s query writer. An encoder’s query writer, unlike a frame’s query writer, writes metadata for an image outside of the individual frame. However, this scenario is not common, and the native image formats do not support this capability. The native image codecs provided by WIC read and write metadata at the frame level even for single-frame formats such as JPEG.

You can also obtain a query writer directly from the imaging factory (IWICImagingFactory). There are two imaging factory methods that return a query writer: CreateQueryWriter and CreateQueryWriterFromReader.

CreateQueryWriter creates a query writer for the specified metadata format and vendor. This query writer enables you to write metadata for a specific metadata format and add it to the image. The following code demonstrates a CreateQueryWriter call to create an XMP query writer.

In this example, the friendly name GUID_MetadataFormatXMP is used as the guidMetadataFormat parameter. It represents the XMP metadata format GUID, and vendor represents the Microsoft created handler. Alternatively, NULL can be passed as the pguidVendor parameter with the same results if no other XMP handler exists. If a custom XMP handler is installed alongside the native XMP handler, passing NULL for the vendor will result in the query writer with the lowest GUID being returned.

CreateQueryWriterFromReader is similar to the CreateQueryWriter method except that it prepopulates the new query writer with the data provided by the query reader. This is useful for re-encoding an image while maintaining the existing metadata, or for removing unwanted metadata. The following code demonstrates a CreateQueryWriterFromReader call.

Adding Metadata

After you obtain a query writer, you can use it to add metadata blocks and items. To write metadata, you use the query writer’s SetMetadataByName method. SetMetadataByName takes two parameters: a query expression (wzName) and a pointer to a PROPVARIANT (pvarValue). The query expression defines the block or item to set while the PROPVARIANT provides the actual data value to set.

The following example demonstrates how to add a title by using the XMP query writer previously obtained by using the CreateQueryWriter method.

In this example, value’s type (vt) is set to VT_LPWSTR , indicating that a string will be used as the data value. Because value‘s type is a string, pwszVal is used to set the title to use. SetMetadataByName is then called using the query expression «/dc:title» and the newly set PROPVARIANT. The query expression used indicates that the title property in the digital camera (dc) schema should be set. Note that the expression is not «/xmp/dc:title»; this is because the query writer is already specific to XMP and does not contain an embedded XMP block, which «/xmp/dc:title» would suggest.

Up to this point you haven’t actually added any metadata to an image frame. You’ve simply populated a query writer with data. To add to a frame a metadata block represented by the query writer, you again call SetMetadataByName using the query writer as the value of the PROPVARIANT. This effectively copies the metadata in the query writer to the image frame. The following code demonstrates how to add the metadata in the XMP query writer previously obtained to a frame’s root metadata block.

In this example, a value type (vt) of VT_UNKOWN is used; indicating a COM interface value type. The XMP query writer (piXMPWriter) is then used as the value of the PROPVARIANT, adding a reference to it by using the AddRef method. Finally, the XMP query writer is set by calling the frame’s SetMetadataByName method and passing the query expression «/», indicating the root block, and the newly set PROPVARIANT.

If the frame already contains the metadata block you are trying to add, the metadata you are adding will be added and existing metadata overwritten.

Removing Metadata

A query writer also enables you to remove metadata by calling the RemoveMetadataByName method. RemoveMetadataByName takes a query expression and removes the metadata block or item if it exists. The following code demonstrates how to remove the title that was previously added.

The following code demonstrates how to remove the entire XMP metadata block.

Copying Metadata for Re-encoding

The code in this section is valid only when the source and destination image formats are the same. You cannot copy all of an image’s metadata in a single operation when encoding to a different image format.

To preserve metadata while re-encoding an image to the same image format, there are methods available for copying all the metadata in a single operation. Each of these operations follows a similar pattern; each sets the decoded frame’s metadata directly into the new frame being encoded.

The preferred method to copy metadata is to initialize the new frame’s block writer with the decoded frame’s block reader. The following code demonstrates this method.

In this example, the block reader and the block writer are obtained from the source frame and destination frame, respectively. The block writer is then initialized from the block reader. This initializes the block reader with the pre-populated metadata of the block reader.

Another method to copy metadata is to write the metadata block referenced by the query reader using the encoder’s query writer. The following code demonstrates this method.

Here, a query reader is obtained from the decoded frame and then used as the property value of the PROPVARIANT with a value type set to VT_UNKNOWN. The query writer for the encoder is obtained and the query expression «/» is used to set the metadata at the root navigation path. You can also use this method when setting nested metadata blocks, by adjusting the query expression to the desired location.

Similarly, you can create a query writer based on the decoded frame’s query reader by using the imaging factory’s CreateQueryWriterFromReader method. The query writer created in this operation will be prepopulated with the metadata from the query reader and can then be set in the frame. The following code demonstrates the CreateQueryWriterFromReader copy operation.

This method uses a separate query writer is created that is based on the data of the query reader. This new query writer then set in the frame.

Again, these operations to copy metadata only work when the source and destination images have the same format. This is because different image formats store the metadata blocks in different locations. For instance, both JPEG and TIFF support XMP metadata blocks. In JPEG images, the XMP block is at the root metadata block as illustrated in the WIC Metadata Overview. However, in a TIFF image, the XMP block is nested in a root IFD block. The following diagram illustrates the differences between a JPEG image and a TIFF image with the same rating metadata.

Fast Metadata Encoding

It is not always necessary to re-encode an image to write new metadata to it. Metadata can also be written by using a fast metadata encoder. A fast metadata encoder can write a limited amount of metadata to an image without re-encoding the image. This is accomplished by writing the new metadata within the empty padding provided by some metadata formats. The native metadata formats that support metadata padding are Exif, IFD, GPS and XMP.

Adding Padding to Metadata Blocks

Before you can perform fast metadata encoding, there must be room within the metadata block to write more metadata. If there is not enough room within the existing padding to write the new metadata, the fast metadata encoding will fail. To add metadata padding to an image, the image must be re-encoded. You can add padding the same way you would add any other metadata item, by using a query expression, if the metadata block you are padding supports it. The following example demonstrates how to add padding to an IFD block embedded in an App1 block.

To add padding, create a PROPVARIANT of type VT_UI4 and a value corresponding to the number of bytes of padding to add. A typical value is 4096 bytes. The metadata queries for JPEG, TIFF, and JPEG-XR are in this table.

Metadata format JPEG metadata query TIFF, JPEG-XR metadata query
IFD /app1/ifd/PaddingSchema:Padding /ifd/PaddingSchema:Padding
EXIF /app1/ifd/exif/PaddingSchema:Padding /ifd/exif/PaddingSchema:Padding
XMP /xmp/PaddingSchema:Padding /ifd/xmp/PaddingSchema:Padding
GPS /app1/ifd/gps/PaddingSchema:Padding /ifd/gps/PaddingSchema:Padding

Obtaining a Fast Metadata Encoder

When you have an image with metadata padding, a fast metadata encoder can be obtained by using the imaging factory methods CreateFastMetadataEncoderFromDecoder and CreateFastMetadataEncoderFromFrameDecode.

As the name implies, CreateFastMetadataEncoderFromDecoder creates a fast metadata encoder for decoder-level metadata. The native image formats provided by WIC do not support decoder-level metadata but this method is provided in case such an image format is developed in the future.

The more common scenario is to obtain a fast metadata encoder from an image frame by using CreateFastMetadataEncoderFromFrameDecode. The following code obtains a decoded frame’s fast metadata encoder and changes the rating value in the App1 block.

Using the Fast Metadata Encoder

From the fast metadata encoder, you can obtain a query writer. This enables you to write metadata by using a query expression as previously demonstrated. After metadata has been set in the query writer, commit the fast metadata encoder to finalize the metadata update. The following code demonstrates setting and committing the metadata changes

If Commit fails for any reason, you will need to re-encode the image to ensure the new metadata is added to the image.

Читайте также:  Linked file symbol in linux
Оцените статью