Browse Source

Adding basic EXIF property item manipulation

Former-commit-id: 499d99a0048d840c7434726d0776035d258faa4b
af/merge-core
James South 12 years ago
parent
commit
9373a5c045
  1. 2
      README.md
  2. 65
      src/ImageProcessor/ImageFactory.cs
  3. 2
      src/ImageProcessor/ImageProcessor.csproj
  4. 1107
      src/ImageProcessor/Imaging/ExifPropertyTag.cs
  5. 58
      src/ImageProcessor/Imaging/ExifPropertyTagType.cs
  6. 18
      src/ImageProcessor/Imaging/ImageUtils.cs
  7. 4
      src/ImageProcessor/Settings.StyleCop

2
README.md

@ -5,4 +5,4 @@ Imageprocessor is a lightweight library written in C# that allows you to manipul
It's fast, extensible, easy to use, comes bundled with some great features and is fully open source.
For full documentation please see [http://jimbobsquarepants.github.io/ImageProcessor/](http://jimbobsquarepants.github.io/ImageProcessor/)
For full documentation please see [http://imageprocessor.org/](http://imageprocessor.org/)

65
src/ImageProcessor/ImageFactory.cs

@ -12,6 +12,7 @@ namespace ImageProcessor
{
#region Using
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
@ -19,7 +20,6 @@ namespace ImageProcessor
using System.IO;
using System.Linq;
using System.Threading;
using ImageProcessor.Extensions;
using ImageProcessor.Imaging;
using ImageProcessor.Imaging.Filters;
@ -37,6 +37,11 @@ namespace ImageProcessor
/// </summary>
private const int DefaultJpegQuality = 90;
/// <summary>
/// Whether to preserve exif metadata
/// </summary>
private readonly bool preserveExifData;
/// <summary>
/// The backup image format.
/// </summary>
@ -66,6 +71,20 @@ namespace ImageProcessor
private bool isDisposed;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ImageFactory"/> class.
/// </summary>
/// <param name="preserveExifData">
/// Whether to preserve exif metadata. Defaults to false.
/// </param>
public ImageFactory(bool preserveExifData = true)
{
this.preserveExifData = preserveExifData;
this.ExifPropertyItems = new ConcurrentDictionary<int, PropertyItem>();
}
#endregion
#region Destructors
/// <summary>
/// Finalizes an instance of the <see cref="T:ImageProcessor.ImageFactory">ImageFactory</see> class.
@ -123,6 +142,11 @@ namespace ImageProcessor
}
}
/// <summary>
/// Gets or sets the exif property items.
/// </summary>
public ConcurrentDictionary<int, PropertyItem> ExifPropertyItems { get; set; }
/// <summary>
/// Gets or sets the original extension.
/// </summary>
@ -157,6 +181,15 @@ namespace ImageProcessor
this.ImageFormat = this.Image.RawFormat;
this.backupImageFormat = this.ImageFormat;
this.isIndexed = ImageUtils.IsIndexed(this.Image);
if (this.preserveExifData)
{
foreach (PropertyItem propertyItem in this.Image.PropertyItems)
{
this.ExifPropertyItems[propertyItem.Id] = propertyItem;
}
}
this.ShouldProcess = true;
return this;
@ -210,6 +243,15 @@ namespace ImageProcessor
this.OriginalExtension = Path.GetExtension(this.ImagePath);
this.ImageFormat = imageFormat;
this.isIndexed = ImageUtils.IsIndexed(this.Image);
if (this.preserveExifData)
{
foreach (PropertyItem propertyItem in this.Image.PropertyItems)
{
this.ExifPropertyItems[propertyItem.Id] = propertyItem;
}
}
this.ShouldProcess = true;
}
}
@ -419,7 +461,7 @@ namespace ImageProcessor
return this;
}
/// <summary>
/// Applies a filter to the current image.
/// </summary>
@ -1032,6 +1074,25 @@ namespace ImageProcessor
{
this.Image = processor.Invoke(this);
}
// Set the property item information from any Exif metadata.
// We do this here so that they can be changed between processor methods.
if (this.preserveExifData)
{
foreach (KeyValuePair<int, PropertyItem> propertItem in this.ExifPropertyItems)
{
try
{
this.Image.SetPropertyItem(propertItem.Value);
}
// ReSharper disable once EmptyGeneralCatchClause
catch
{
// Do nothing. The image format does not handle EXIF data.
// TODO: empty catch is fierce code smell.
}
}
}
}
#endregion
}

2
src/ImageProcessor/ImageProcessor.csproj

@ -67,9 +67,11 @@
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="ImageFactory.cs" />
<Compile Include="Imaging\AnchorPosition.cs" />
<Compile Include="Imaging\ExifPropertyTagType.cs" />
<Compile Include="Imaging\Convolution.cs" />
<Compile Include="Imaging\CropLayer.cs" />
<Compile Include="Imaging\CropMode.cs" />
<Compile Include="Imaging\ExifPropertyTag.cs" />
<Compile Include="Imaging\Filters\MatrixFilterRegexAttribute.cs" />
<Compile Include="Imaging\Filters\MatrixFilters.cs" />
<Compile Include="Imaging\GaussianLayer.cs" />

1107
src/ImageProcessor/Imaging/ExifPropertyTag.cs

File diff suppressed because it is too large

58
src/ImageProcessor/Imaging/ExifPropertyTagType.cs

@ -0,0 +1,58 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ExifPropertyTagType.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Specifies the data type of the values stored in the value data member of that same PropertyItem object.
// <see cref="http://msdn.microsoft.com/en-us/library/system.drawing.imaging.propertyitem.type.aspx" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Imaging
{
/// <summary>
/// Specifies the data type of the values stored in the value data member of that same PropertyItem object.
/// <see cref="http://msdn.microsoft.com/en-us/library/system.drawing.imaging.propertyitem.type.aspx"/>
/// </summary>
public enum ExifPropertyTagType : short
{
/// <summary>Specifies that the value data member is an array of bytes.</summary>
Byte = 1,
/// <summary>
/// Specifies that the value data member is a null-terminated ASCII string. If you set the type data member of a
/// PropertyItem object to ExifPropertyTagTypeASCII, you should set the length data member to the length of the string
/// including the NULL terminator. For example, the string HELLO would have a length of 6.
/// </summary>
ASCII = 2,
/// <summary>Specifies that the value data member is an array of unsigned short (16-bit) integers.</summary>
Int16 = 3,
/// <summary>Specifies that the value data member is an array of unsigned long (32-bit) integers.</summary>
Int32 = 4,
/// <summary>
/// Specifies that the value data member is an array of pairs of unsigned long integers. Each pair represents a
/// fraction; the first integer is the numerator and the second integer is the denominator.
/// </summary>
Rational = 5,
/// <summary>
/// Specifies that the value data member is an array of bytes that can hold values of any data type.
/// </summary>
Undefined = 7,
/// <summary>
/// Specifies that the value data member is an array of signed long (32-bit) integers.
/// </summary>
SLONG = 9,
/// <summary>
/// Specifies that the value data member is an array of pairs of signed long integers. Each pair represents a
/// fraction; the first integer is the numerator and the second integer is the denominator.
/// </summary>
SRational = 10
}
}

18
src/ImageProcessor/Imaging/ImageUtils.cs

@ -11,8 +11,12 @@
namespace ImageProcessor.Imaging
{
#region Using
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
#endregion
/// <summary>
@ -56,5 +60,19 @@ namespace ImageProcessor.Imaging
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
return (image.PixelFormat & PixelFormat.Indexed) != 0;
}
/// <summary>
/// Uses reflection to allow the creation of an instance of <see cref="PropertyItem"/>.
/// </summary>
/// <returns>
/// The <see cref="PropertyItem"/>.
/// </returns>
public static PropertyItem CreatePropertyItem()
{
Type type = typeof(PropertyItem);
ConstructorInfo constructor = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null);
return (PropertyItem)constructor.Invoke(null);
}
}
}

4
src/ImageProcessor/Settings.StyleCop

@ -2,7 +2,11 @@
<GlobalSettings>
<CollectionProperty Name="RecognizedWords">
<Value>behaviour</Value>
<Value>chrominance</Value>
<Value>colour</Value>
<Value>enum</Value>
<Value>exif</Value>
<Value>halftoning</Value>
<Value>lomograph</Value>
<Value>octree</Value>
<Value>quantizer</Value>

Loading…
Cancel
Save