“Photo metadata is a set of data describing and providing information about rights and administration of an image.” - iptc.org
In other words, metadata is information stored with a photo. It includes information about the device that took the picture, the location, the camera settings, copyrights, and more.
In this blog post, I am not going to share with you how to read this information but how to remove it.
As metadata can contain information about the GPS location and device that took the pic, you won't probably let people see other users' location using their images in your application. Imagine you implement your social media, where people can upload pics and watch others users' pics. If metadata is not deleted from the uploaded images, this might cause privacy concerns for your application's users.
Now let's see how he can do that in a . NET.
I found some open source NuGet packages which can be used to read and also remove metadata from images.
GitHub Project | NuGet Link | Can read metadata ? | Can remove metadata ? |
---|---|---|---|
dlemstra/Magick.NET | Magick.NET-Q16-AnyCPU | Yes | Yes |
SixLabors/ImageSharp | SixLabors.ImageSharp | Yes | Yes |
I have already tried these libraries and I found them very interesting. They give you an option to save the image in a different format from the original after metadata is removed. So I will show you how to use each of them.
Magick.NET-Q16-AnyCPU
Magick.NET-Q16-AnyCPU
can be found here on NuGet and can be installed by copying and pasting the following command into your Package Manager Console within Visual Studio (Tools > NuGet Package Manager > Package Manager Console).
Install-Package Magick.NET-Q16-AnyCPU
Alternatively, if you're using .NET Core then you can install Magick.NET-Q16-AnyCPU
via the CLI with the following command:
dotnet add package Magick.NET-Q16-AnyCPU
using ImageMagick;
using var image = new MagickImage("path_to_the_image/image.jpg");
// Or use Sytem.IO.Stream instead of path
using var image = new MagickImage(streamObject);
// Exif profile: Camera settings, GPS location, Date, Time Zone, ... etc
var exifProfile = heicImage.GetExifProfile();
// IPTC profile: Copyright, Permissions and licenses, Creator's information and contact details, Rights usage terms, ...etc
var iptcProfile = heicImage.GetIptcProfile();
// Xmp profile: IPTC with additionnal information
var xmpProfile = heicImage.GetXmpProfile();
if(exifProfile != null) image.RemoveProfile(exifProfile);
if(iptcProfile != null) image.RemoveProfile(iptcProfile);
if(xmpProfile != null) image.RemoveProfile(xmpProfile);
image.Format = MagickFormat.Png; // Change the output format if needed
await image.WriteAsync("images/user-000001.png");
// Instead of saving the image, if you want to return an array of byte
byte[] data = image.ToByteArray();
Complete code
using ImageMagick;
// Load the image
using var image = new MagickImage("path_to_the_image/image.jpg");
// Or use Sytem.IO.Stream instead of path
using var image = new MagickImage(streamObject);
// Exif profile contain information like the device that took the photo, Camera settings, GPS location, Date, Time Zone, ... etc
var exifProfile = heicImage.GetExifProfile();
// IPTC profile: Copyright, Permissions and licenses, Creator's information and contact details, Rights usage terms, ...etc
var iptcProfile = heicImage.GetIptcProfile();
// Xmp profile: IPTC with additionnal information
var xmpProfile = heicImage.GetXmpProfile();
// Remove metadata if exists
if(exifProfile != null) image.RemoveProfile(exifProfile);
if(iptcProfile != null) image.RemoveProfile(iptcProfile);
if(xmpProfile != null) image.RemoveProfile(xmpProfile);
// Finally save the image without metadata
image.Format = MagickFormat.Png; // Change the output format if needed
await image.WriteAsync("images/user-000001.png");
// Instead of saving the image, if you want to return an array of byte
byte[] data = image.ToByteArray();
Please note: In case you are manipulating HEIC format, the WriteAsync
method does not support it, you will need to convert it to another format (png, jpg, jpeg,... for example).
SixLabors.ImageSharp
Just like we installed the previous NuGet package, SixLabors.ImageSharp
can be installed through the Package Manager Console.
Install-Package SixLabors.ImageSharp
or via .NET CLI
dotnet add package SixLabors.ImageSharp
using SixLabors.ImageSharp;
using var image = await Image.LoadAsync("path_to_the_image/image.jpg");
// Or use Sytem.IO.Stream instead of path
using var image = await Image.LoadAsync(streamObject);
image.Metadata.ExifProfile = null;
image.Metadata.IptcProfile = null;
image.Metadata.XmpProfile = null;
using SixLabors.ImageSharp.Formats.Jpeg;
await image.SaveAsync("images/user-000001.jpg");
// Convert the image to a different format
await image.SaveAsPngAsync("...");
await image.SaveAsGifAsync("...");
await image.SaveAsJpegAsync("...");
await image.SaveAsPbmAsync("...");
await image.SaveAsTiffAsync("...");
await image.SaveAsTgaAsync("...");
await image.SaveAsWebpAsync("...");
await image.SaveAsBmpAsync("...");
// Or convert the output image to base64 string
var imageToBase64String = image.ToBase64String(JpegFormat.Instance);
// alternatively, write the image to an output stream as a JPEG file
using var stream = new MemoryStream();
await image.SaveAsJpegAsync(stream);
Complete code
using SixLabors.ImageSharp;
// Load the image
using var image = await Image.LoadAsync("path_to_the_image/image.jpg");
// Remove metadata
image.Metadata.ExifProfile = null;
image.Metadata.IptcProfile = null;
image.Metadata.XmpProfile = null;
// Save the image without metadata
await image.SaveAsync("images/user-000001.jpg");
SixLabors.ImageSharp
supports only Webp, PNG, TIFF, GIF, TGA, BMP, PBM, and JPEG formats. This means you cannot load an image of any other format than those I have listed.
If you find this blog post useful, please share it on your favorite social media. Don't forget to follow me on GitHub and Twitter. To send me a message, please use the contact form or DM me on Twitter.
Quick Links