Question

I'm working on a service for a company project that handles image processing, and one of the methods is supposed to clean the metadata from an image passed to it.

I think implementation I currently have works, but I'm not sure if it's affecting the quality of images or if there's a better way to handle this task. Could you let me know if you know of a better way to do this?

Here's the method in question:

public byte[] CleanMetadata(byte[] data)
{
    Image image;

    if (tryGetImageFromBytes(data, out image))
    {
        Bitmap bitmap = new Bitmap(image);

        using (var graphics = Graphics.FromImage(bitmap))
        {
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.CompositingMode = CompositingMode.SourceCopy;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

            graphics.DrawImage(image, new Point(0, 0));
        }

        ImageConverter converter = new ImageConverter();

        return (byte[])converter.ConvertTo(image, typeof(byte[]));
    }

    return null;
}

And, for reference, the tryGetImageFromBytes method:

private bool tryGetImageFromBytes(byte[] data, out Image image)
{
    try
    {
        using (var ms = new MemoryStream(data))
        {
            image = Image.FromStream(ms);
        }
    }
    catch (ArgumentException)
    {
        image = null;

        return false;
    }

    return true;
}

To reiterate: is there a better way to remove metadata from an image that doesn't involve redrawing it?

Thanks in advance.

Was it helpful?

Solution

Metadata - Gets or sets the metadata that will be associated with this bitmap during encoding.

  • The 'Oops, I (not so accidentally) forgot something way: Open the original bitmap file into a System.drawing.Bitmap object. Clone it to a new Bitmap object. Write the clone's contents to a new file. Like this one-liner:

    ((System.Drawing.Bitmap)System.Drawing.Image.FromFile(@"C:\file.png").Clone()).Save(@"C:\file-nometa.png");

  • The direct file manipulation way (only for JPEG): Blog post about removing the EXIF area.

OTHER TIPS

I would suggest this, the source is here: Removing Exif-Data for jpg file

Changing a bit the 1st function

public Stream PatchAwayExif(Stream inStream)
{
  Stream outStream = new MemoryStream();
  byte[] jpegHeader = new byte[2];
  jpegHeader[0] = (byte)inStream.ReadByte();
  jpegHeader[1] = (byte)inStream.ReadByte();
  if (jpegHeader[0] == 0xff && jpegHeader[1] == 0xd8) //check if it's a jpeg          file
  {
     SkipAppHeaderSection(inStream);
  }
  outStream.WriteByte(0xff);
  outStream.WriteByte(0xd8);

  int readCount;
  byte[] readBuffer = new byte[4096];
  while ((readCount = inStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
  outStream.Write(readBuffer, 0, readCount);

  return outStream;
}

And the second function with no changes, as post

    private void SkipAppHeaderSection(Stream inStream)
    {
        byte[] header = new byte[2];
        header[0] = (byte)inStream.ReadByte();
        header[1] = (byte)inStream.ReadByte();

        while (header[0] == 0xff && (header[1] >= 0xe0 && header[1] <= 0xef))
        {
            int exifLength = inStream.ReadByte();
            exifLength = exifLength << 8;
            exifLength |= inStream.ReadByte();

            for (int i = 0; i < exifLength - 2; i++)
            {
                inStream.ReadByte();
            }
            header[0] = (byte)inStream.ReadByte();
            header[1] = (byte)inStream.ReadByte();
        }
        inStream.Position -= 2; //skip back two bytes
    }

Creating a new bitmap will clear out all the exif data.

var newImage = new Bitmap(image);

If you want to remove only specific info:

private Image RemoveGpsExifInfo(Image image)
{
  foreach (var item in image.PropertyItems)
  {
    // GPS range is from 0x0000 to 0x001F. Full list here -> https://exiftool.org/TagNames/EXIF.html (click on GPS tags)
    if (item.Id <= 0x001F)
    {
      image.RemovePropertyItem(item.Id);
    }
  }

  return image;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top