Browse Source

Tweaking gif frame creation and fixing unc folder access issue

Former-commit-id: e0a7b73bc547b65651a848695000c26072401e31
af/merge-core
James South 12 years ago
parent
commit
8ceafbda80
  1. 3
      src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj
  2. 56
      src/ImageProcessor.Web/NET45/Caching/DiskCache.cs
  3. 2
      src/ImageProcessor.Web/NET45/Configuration/ImageProcessorConfiguration.cs
  4. 2
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  5. 1
      src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj
  6. 28
      src/ImageProcessor/Imaging/Formats/FormatUtilities.cs
  7. 18
      src/ImageProcessor/Imaging/Formats/GifEncoder.cs
  8. 5
      src/ImageProcessorConsole/Program.cs

3
src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj

@ -95,6 +95,9 @@
<Compile Include="..\NET45\Configuration\ImageSecuritySection.cs"> <Compile Include="..\NET45\Configuration\ImageSecuritySection.cs">
<Link>ImageSecuritySection.cs</Link> <Link>ImageSecuritySection.cs</Link>
</Compile> </Compile>
<Compile Include="..\NET45\Extensions\DirectoryInfoExtensions.cs">
<Link>DirectoryInfoExtensions.cs</Link>
</Compile>
<Compile Include="..\NET45\Helpers\CommonParameterParserUtility.cs"> <Compile Include="..\NET45\Helpers\CommonParameterParserUtility.cs">
<Link>CommonParameterParserUtility.cs</Link> <Link>CommonParameterParserUtility.cs</Link>
</Compile> </Compile>

56
src/ImageProcessor.Web/NET45/Caching/DiskCache.cs

@ -22,6 +22,7 @@ namespace ImageProcessor.Web.Caching
using ImageProcessor.Common.Extensions; using ImageProcessor.Common.Extensions;
using ImageProcessor.Web.Configuration; using ImageProcessor.Web.Configuration;
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers; using ImageProcessor.Web.Helpers;
#endregion #endregion
@ -212,37 +213,44 @@ namespace ImageProcessor.Web.Caching
/// </param> /// </param>
private void TrimCachedFolders(string path) private void TrimCachedFolders(string path)
{ {
// ReSharper disable once AssignNullToNotNullAttribute string directory = Path.GetDirectoryName(path);
DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(path));
DirectoryInfo parentDirectoryInfo = directoryInfo.Parent;
// ReSharper disable once PossibleNullReferenceException if (directory != null)
foreach (DirectoryInfo enumerateDirectory in parentDirectoryInfo.EnumerateDirectories())
{ {
IEnumerable<FileInfo> files = enumerateDirectory.EnumerateFiles().OrderBy(f => f.CreationTimeUtc); DirectoryInfo directoryInfo = new DirectoryInfo(directory);
int count = files.Count(); DirectoryInfo parentDirectoryInfo = directoryInfo.Parent;
foreach (FileInfo fileInfo in files) if (parentDirectoryInfo != null)
{ {
try // UNC folders can throw exceptions if the file doesn't exist.
foreach (DirectoryInfo enumerateDirectory in parentDirectoryInfo.SafeEnumerateDirectories())
{ {
// If the group count is equal to the max count minus 1 then we know we IEnumerable<FileInfo> files = enumerateDirectory.EnumerateFiles().OrderBy(f => f.CreationTimeUtc);
// have reduced the number of items below the maximum allowed. int count = files.Count();
// We'll cleanup any orphaned expired files though.
if (!this.IsExpired(fileInfo.CreationTimeUtc) && count <= MaxFilesCount - 1) foreach (FileInfo fileInfo in files)
{ {
break; try
{
// If the group count is equal to the max count minus 1 then we know we
// have reduced the number of items below the maximum allowed.
// We'll cleanup any orphaned expired files though.
if (!this.IsExpired(fileInfo.CreationTimeUtc) && count <= MaxFilesCount - 1)
{
break;
}
// Remove from the cache and delete each CachedImage.
CacheIndexer.Remove(fileInfo.Name);
fileInfo.Delete();
count -= 1;
}
// ReSharper disable once EmptyGeneralCatchClause
catch
{
// Do nothing; skip to the next file.
}
} }
// Remove from the cache and delete each CachedImage.
CacheIndexer.Remove(fileInfo.Name);
fileInfo.Delete();
count -= 1;
}
// ReSharper disable once EmptyGeneralCatchClause
catch
{
// Do nothing; skip to the next file.
} }
} }
} }

2
src/ImageProcessor.Web/NET45/Configuration/ImageProcessorConfiguration.cs

@ -22,8 +22,8 @@ namespace ImageProcessor.Web.Configuration
using ImageProcessor.Common.Extensions; using ImageProcessor.Common.Extensions;
using ImageProcessor.Processors; using ImageProcessor.Processors;
using ImageProcessor.Web.Processors;
using ImageProcessor.Web.Helpers; using ImageProcessor.Web.Helpers;
using ImageProcessor.Web.Processors;
/// <summary> /// <summary>
/// Encapsulates methods to allow the retrieval of ImageProcessor settings. /// Encapsulates methods to allow the retrieval of ImageProcessor settings.

2
src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs

@ -359,7 +359,7 @@ namespace ImageProcessor.Web.HttpModules
IPrincipal user = context.User ?? new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]); IPrincipal user = context.User ?? new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]);
// Do we have permission to call UrlAuthorizationModule.CheckUrlAccessForPrincipal? // Do we have permission to call UrlAuthorizationModule.CheckUrlAccessForPrincipal?
PermissionSet permission = new PermissionSet(PermissionState.Unrestricted); PermissionSet permission = new PermissionSet(PermissionState.None);
permission.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted)); permission.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted));
bool hasPermission = permission.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet); bool hasPermission = permission.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet);

1
src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj

@ -53,6 +53,7 @@
<Compile Include="Configuration\ImageProcessingSection.cs" /> <Compile Include="Configuration\ImageProcessingSection.cs" />
<Compile Include="Configuration\ImageProcessorConfiguration.cs" /> <Compile Include="Configuration\ImageProcessorConfiguration.cs" />
<Compile Include="Configuration\ImageSecuritySection.cs" /> <Compile Include="Configuration\ImageSecuritySection.cs" />
<Compile Include="Extensions\DirectoryInfoExtensions.cs" />
<Compile Include="Helpers\CommonParameterParserUtility.cs" /> <Compile Include="Helpers\CommonParameterParserUtility.cs" />
<Compile Include="Helpers\NativeMethods.cs" /> <Compile Include="Helpers\NativeMethods.cs" />
<Compile Include="Helpers\ResourceHelpers.cs" /> <Compile Include="Helpers\ResourceHelpers.cs" />

28
src/ImageProcessor/Imaging/Formats/FormatUtilities.cs

@ -131,40 +131,42 @@ namespace ImageProcessor.Imaging.Formats
if (fetchFrames) if (fetchFrames)
{ {
FrameDimension frameDimension = new FrameDimension(image.FrameDimensionsList[0]); int frameCount = image.GetFrameCount(FrameDimension.Time);
int frameCount = image.GetFrameCount(frameDimension);
int last = frameCount - 1; int last = frameCount - 1;
int delay = 0; int length = 0;
List<GifFrame> gifFrames = new List<GifFrame>(); List<GifFrame> gifFrames = new List<GifFrame>();
// Get the times stored in the gif.
byte[] times = image.GetPropertyItem((int)ExifPropertyTag.FrameDelay).Value;
for (int i = 0; i < frameCount; i++) for (int i = 0; i < frameCount; i++)
{ {
// Convert each 4-byte chunk into an integer.
// GDI returns a single array with all delays, while Mono returns a different array for each frame. // GDI returns a single array with all delays, while Mono returns a different array for each frame.
image.SelectActiveFrame(frameDimension, i); int delay = BitConverter.ToInt32(times, (4 * i) % times.Length);
byte[] times = image.GetPropertyItem(20736).Value; delay = delay * 10 < 20 ? 20 : delay * 10; // Minimum delay is 20 ms
int thisDelay = BitConverter.ToInt32(times, (4 * i) % times.Length);
int toAddDelay = thisDelay * 10 < 20 ? 20 : thisDelay * 10; // Minimum delay is 20 ms
// Find the frame // Find the frame
image.SelectActiveFrame(frameDimension, i); image.SelectActiveFrame(FrameDimension.Time, i);
// TODO: Get positions. // TODO: Get positions.
gifFrames.Add(new GifFrame { Delay = toAddDelay, Image = (Image)image.Clone() }); gifFrames.Add(new GifFrame { Delay = delay, Image = (Image)image.Clone() });
// Reset the position. // Reset the position.
if (i == last) if (i == last)
{ {
image.SelectActiveFrame(frameDimension, 0); image.SelectActiveFrame(FrameDimension.Time, 0);
} }
delay += toAddDelay; length += delay;
} }
info.GifFrames = gifFrames; info.GifFrames = gifFrames;
info.AnimationLength = delay; info.AnimationLength = length;
// Loop info is stored at byte 20737. // Loop info is stored at byte 20737.
info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0); info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem((int)ExifPropertyTag.LoopCount).Value, 0);
info.IsLooped = info.LoopCount != 1; info.IsLooped = info.LoopCount != 1;
} }
} }

18
src/ImageProcessor/Imaging/Formats/GifEncoder.cs

@ -193,13 +193,6 @@ namespace ImageProcessor.Imaging.Formats
} }
#endregion #endregion
#region Properties
/// <summary>
/// Gets or sets the frame delay.
/// </summary>
public TimeSpan FrameDelay { get; set; }
#endregion
#region Public Methods and Operators #region Public Methods and Operators
/// <summary> /// <summary>
/// Adds a frame to the gif. /// Adds a frame to the gif.
@ -289,13 +282,18 @@ namespace ImageProcessor.Imaging.Formats
{ {
int count = this.repeatCount.GetValueOrDefault(0); int count = this.repeatCount.GetValueOrDefault(0);
// File Header // File Header sinature and version.
this.WriteString(FileType); this.WriteString(FileType);
this.WriteString(FileVersion); this.WriteString(FileVersion);
// Write the logical screen descriptor.
this.WriteShort(this.width.GetValueOrDefault(w)); // Initial Logical Width this.WriteShort(this.width.GetValueOrDefault(w)); // Initial Logical Width
this.WriteShort(this.height.GetValueOrDefault(h)); // Initial Logical Height this.WriteShort(this.height.GetValueOrDefault(h)); // Initial Logical Height
// Read the global color table info.
sourceGif.Position = SourceGlobalColorInfoPosition; sourceGif.Position = SourceGlobalColorInfoPosition;
this.WriteByte(sourceGif.ReadByte()); // Global Color Table Info this.WriteByte(sourceGif.ReadByte());
this.WriteByte(0); // Background Color Index this.WriteByte(0); // Background Color Index
this.WriteByte(0); // Pixel aspect ratio this.WriteByte(0); // Pixel aspect ratio
this.WriteColorTable(sourceGif); this.WriteColorTable(sourceGif);
@ -387,6 +385,7 @@ namespace ImageProcessor.Imaging.Formats
/// </param> /// </param>
private void WriteImageBlock(Stream sourceGif, bool includeColorTable, int x, int y, int h, int w) private void WriteImageBlock(Stream sourceGif, bool includeColorTable, int x, int y, int h, int w)
{ {
// Local Image Descriptor
sourceGif.Position = SourceImageBlockPosition; // Locating the image block sourceGif.Position = SourceImageBlockPosition; // Locating the image block
byte[] header = new byte[SourceImageBlockHeaderLength]; byte[] header = new byte[SourceImageBlockHeaderLength];
sourceGif.Read(header, 0, header.Length); sourceGif.Read(header, 0, header.Length);
@ -435,6 +434,7 @@ namespace ImageProcessor.Imaging.Formats
/// </param> /// </param>
private void WriteShort(int value) private void WriteShort(int value)
{ {
// Leave only one significant byte.
this.inputStream.WriteByte(Convert.ToByte(value & 0xff)); this.inputStream.WriteByte(Convert.ToByte(value & 0xff));
this.inputStream.WriteByte(Convert.ToByte((value >> 8) & 0xff)); this.inputStream.WriteByte(Convert.ToByte((value >> 8) & 0xff));
} }

5
src/ImageProcessorConsole/Program.cs

@ -1,6 +1,7 @@
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
// <copyright file="Program.cs" company="James South"> // <copyright file="Program.cs" company="James South">
// Copyright James South // Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
// <summary> // <summary>
// The program. // The program.
@ -58,7 +59,7 @@ namespace ImageProcessorConsole
// Load, resize, set the format and quality and save an image. // Load, resize, set the format and quality and save an image.
imageFactory.Load(inStream) imageFactory.Load(inStream)
.AutoRotate() //.AutoRotate()
.Constrain(size) .Constrain(size)
//.Format(new WebPFormat()) //.Format(new WebPFormat())
//.Quality(5) //.Quality(5)

Loading…
Cancel
Save