From c315e9d218d9e34f063fba1181f228572c7eb010 Mon Sep 17 00:00:00 2001 From: James South Date: Wed, 30 Apr 2014 19:17:49 +0100 Subject: [PATCH] Cleaning up Test memory stream disposal Former-commit-id: e6e3f207cd0b50972fd35e1ba197f5bb7cc36578 --- .../NET45/ImageFactoryExtensions.cs | 31 +- .../Extensions/ImageExtensions.cs | 70 +- src/ImageProcessor/ImageFactory.cs | 95 +- src/ImageProcessor/ImageProcessor.csproj | 1 - .../Imaging/GifEncoder - Copy.cs | 409 ---- src/ImageProcessor/Imaging/GifEncoder.cs | 2 +- src/ImageProcessorConsole/Program.cs | 2 +- src/Images/meter.gif | Bin 0 -> 22525 bytes .../App_Start/BundleConfig.cs | 31 - .../App_Start/FilterConfig.cs | 13 - .../App_Start/RouteConfig.cs | 23 - .../App_Start/Startup.Auth.cs | 38 - .../Test_Website_MVC5_NET45/Content/Site.css | 42 - .../Content/bootstrap.css.REMOVED.git-id | 1 - .../Content/bootstrap.min.css.REMOVED.git-id | 1 - .../Controllers/AccountController.cs | 408 ---- .../Controllers/HomeController.cs | 30 - .../NET45/Test_Website_MVC5_NET45/Global.asax | 1 - .../Test_Website_MVC5_NET45/Global.asax.cs | 21 - .../Models/AccountViewModels.cs | 63 - .../Models/IdentityModels.cs | 17 - .../Project_Readme.html | 151 -- .../Properties/AssemblyInfo.cs | 35 - .../Scripts/_references.js | Bin 396 -> 0 bytes .../Scripts/bootstrap.js | 2014 ----------------- .../Scripts/bootstrap.min.js | 21 - ...uery-1.10.2.intellisense.js.REMOVED.git-id | 1 - .../Scripts/jquery-1.10.2.js.REMOVED.git-id | 1 - .../jquery-1.10.2.min.js.REMOVED.git-id | 1 - .../jquery-1.10.2.min.map.REMOVED.git-id | 1 - .../Scripts/jquery.validate-vsdoc.js | 1302 ----------- .../Scripts/jquery.validate.js | 1245 ---------- .../Scripts/jquery.validate.min.js | 16 - .../Scripts/jquery.validate.unobtrusive.js | 344 --- .../jquery.validate.unobtrusive.min.js | 19 - .../Scripts/modernizr-2.6.2.js | 1393 ------------ .../Scripts/respond.js | 340 --- .../Scripts/respond.min.js | 20 - .../NET45/Test_Website_MVC5_NET45/Startup.cs | 14 - .../Test_Website_MVC5_NET45.csproj | 278 --- .../Account/ExternalLoginConfirmation.cshtml | 36 - .../Views/Account/ExternalLoginFailure.cshtml | 6 - .../Views/Account/Login.cshtml | 58 - .../Views/Account/Manage.cshtml | 29 - .../Views/Account/Register.cshtml | 41 - .../Account/_ChangePasswordPartial.cshtml | 36 - .../Account/_ExternalLoginsListPartial.cshtml | 31 - .../Account/_RemoveAccountPartial.cshtml | 34 - .../Views/Account/_SetPasswordPartial.cshtml | 32 - .../Views/Home/About.cshtml | 7 - .../Views/Home/Contact.cshtml | 17 - .../Views/Home/Index.cshtml | 32 - .../Views/Shared/Error.cshtml | 9 - .../Views/Shared/_Layout.cshtml | 44 - .../Views/Shared/_LoginPartial.cshtml | 22 - .../Test_Website_MVC5_NET45/Views/Web.config | 35 - .../Views/_ViewStart.cshtml | 3 - .../Test_Website_MVC5_NET45/Web.Debug.config | 30 - .../Web.Release.config | 31 - .../NET45/Test_Website_MVC5_NET45/Web.config | 74 - .../config/imageprocessor/cache.config | 3 - .../config/imageprocessor/processing.config | 43 - .../config/imageprocessor/security.config | 14 - .../NET45/Test_Website_MVC5_NET45/favicon.ico | Bin 32038 -> 0 bytes .../fonts/glyphicons-halflings-regular.eot | Bin 14079 -> 0 bytes .../fonts/glyphicons-halflings-regular.svg | 228 -- .../fonts/glyphicons-halflings-regular.ttf | Bin 29512 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 16448 -> 0 bytes .../Test_Website_MVC5_NET45/packages.config | 31 - .../Test_Website_NET45/Views/Home/Gif.cshtml | 8 + 70 files changed, 87 insertions(+), 9342 deletions(-) delete mode 100644 src/ImageProcessor/Imaging/GifEncoder - Copy.cs create mode 100644 src/Images/meter.gif delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/App_Start/BundleConfig.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/App_Start/FilterConfig.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/App_Start/RouteConfig.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/App_Start/Startup.Auth.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Content/Site.css delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Content/bootstrap.css.REMOVED.git-id delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Content/bootstrap.min.css.REMOVED.git-id delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Controllers/AccountController.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Controllers/HomeController.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Global.asax delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Global.asax.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Models/AccountViewModels.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Models/IdentityModels.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Project_Readme.html delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Properties/AssemblyInfo.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/_references.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/bootstrap.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/bootstrap.min.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery-1.10.2.intellisense.js.REMOVED.git-id delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery-1.10.2.js.REMOVED.git-id delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery-1.10.2.min.js.REMOVED.git-id delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery-1.10.2.min.map.REMOVED.git-id delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery.validate-vsdoc.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery.validate.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery.validate.min.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery.validate.unobtrusive.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/jquery.validate.unobtrusive.min.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/modernizr-2.6.2.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/respond.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/respond.min.js delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Startup.cs delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Test_Website_MVC5_NET45.csproj delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/ExternalLoginConfirmation.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/ExternalLoginFailure.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/Login.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/Manage.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/Register.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/_ChangePasswordPartial.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/_ExternalLoginsListPartial.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/_RemoveAccountPartial.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Account/_SetPasswordPartial.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Home/About.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Home/Contact.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Home/Index.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Shared/Error.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Shared/_Layout.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Shared/_LoginPartial.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/Web.config delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Views/_ViewStart.cshtml delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Web.Debug.config delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Web.Release.config delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/Web.config delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/config/imageprocessor/cache.config delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/config/imageprocessor/processing.config delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/config/imageprocessor/security.config delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/favicon.ico delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/fonts/glyphicons-halflings-regular.eot delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/fonts/glyphicons-halflings-regular.svg delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/fonts/glyphicons-halflings-regular.ttf delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/fonts/glyphicons-halflings-regular.woff delete mode 100644 src/TestWebsites/NET45/Test_Website_MVC5_NET45/packages.config diff --git a/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs b/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs index 2e04c1e818..e32b837de6 100644 --- a/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs +++ b/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs @@ -62,8 +62,9 @@ namespace ImageProcessor.Web // Loop through and process the image. foreach (IGraphicsProcessor graphicsProcessor in graphicsProcessors) { - Image img = graphicsProcessor.ProcessImage(factory); - factory.Update(img); + ProcessImage(graphicsProcessor.ProcessImage, factory); + //Image img = graphicsProcessor.ProcessImage(factory); + //factory.Update(img); } } } @@ -71,26 +72,40 @@ namespace ImageProcessor.Web return factory; } - private void ProcessImage(Func processor) + /// + /// The process image. + /// + /// + /// The processor. + /// + /// + /// The factory. + /// + private static void ProcessImage(Func processor, ImageFactory factory) { - ImageInfo imageInfo = this.Image.GetImageInfo(); + ImageInfo imageInfo = factory.Image.GetImageInfo(factory.ImageFormat); if (imageInfo.IsAnimated) { - using (GifEncoder encoder = new GifEncoder(new MemoryStream(4096), 0, 0, imageInfo.LoopCount)) + Image image; + using (GifEncoder encoder = new GifEncoder(new MemoryStream(4096), null, null, imageInfo.LoopCount)) { foreach (GifFrame frame in imageInfo.GifFrames) { - frame.Image = ColorQuantizer.Quantize(processor.Invoke(this), PixelFormat.Format8bppIndexed); + factory.Update(frame.Image); + frame.Image = new Bitmap(ColorQuantizer.Quantize(processor.Invoke(factory), PixelFormat.Format8bppIndexed)); + encoder.AddFrame(frame); } - this.Image = encoder.Save(); + image = encoder.Save(); } + + factory.Update(image); } else { - this.Image = processor.Invoke(this); + factory.Update(processor.Invoke(factory)); } } } diff --git a/src/ImageProcessor/Extensions/ImageExtensions.cs b/src/ImageProcessor/Extensions/ImageExtensions.cs index 821143af5a..833fdf46e8 100644 --- a/src/ImageProcessor/Extensions/ImageExtensions.cs +++ b/src/ImageProcessor/Extensions/ImageExtensions.cs @@ -14,8 +14,6 @@ namespace ImageProcessor.Extensions using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; - using System.IO; - using ImageProcessor.Imaging; /// @@ -27,41 +25,37 @@ namespace ImageProcessor.Extensions /// Returns information about the given . /// /// - /// The image. + /// The image to extend. + /// + /// + /// The image format. + /// + /// + /// Whether to fetch the images frames. /// /// /// The . /// - public static ImageInfo GetImageInfo(this Image imagex) + public static ImageInfo GetImageInfo(this Image image, ImageFormat format, bool fetchFrames = true) { - string path = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath; - // ReSharper disable once AssignNullToNotNullAttribute - string resolvedPath = Path.Combine(Path.GetDirectoryName(path), "frames"); - DirectoryInfo di = new DirectoryInfo(resolvedPath); - if (!di.Exists) - { - di.Create(); - } - - - ImageInfo info = new ImageInfo(); - - using (Image image = (Image)imagex.Clone()) + ImageInfo info = new ImageInfo + { + Height = image.Height, + Width = image.Width, + IsIndexed = (image.PixelFormat & PixelFormat.Indexed) != 0 + }; + + if (image.RawFormat.Guid == ImageFormat.Gif.Guid && format.Guid == ImageFormat.Gif.Guid) { - info.Height = image.Height; - info.Width = image.Width; - - // Test value of flags using bitwise AND. - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - info.IsIndexed = (image.PixelFormat & PixelFormat.Indexed) != 0; - - if (image.RawFormat.Equals(ImageFormat.Gif)) + if (ImageAnimator.CanAnimate(image)) { - if (ImageAnimator.CanAnimate(image)) + info.IsAnimated = true; + + if (fetchFrames) { FrameDimension frameDimension = new FrameDimension(image.FrameDimensionsList[0]); - int frameCount = image.GetFrameCount(frameDimension); + int last = frameCount - 1; int delay = 0; int index = 0; List gifFrames = new List(); @@ -74,14 +68,14 @@ namespace ImageProcessor.Extensions // Find the frame image.SelectActiveFrame(frameDimension, f); - image.Save(Path.Combine(resolvedPath, f + ".gif"), ImageFormat.Gif); - // TODO: Get positions. - gifFrames.Add(new GifFrame - { - Delay = toAddDelay, - Image = (Image)image.Clone() - }); + gifFrames.Add(new GifFrame { Delay = toAddDelay, Image = (Image)image.Clone() }); + + // Reset the position. + if (f == last) + { + image.SelectActiveFrame(frameDimension, 0); + } delay += toAddDelay; index += 4; @@ -89,17 +83,15 @@ namespace ImageProcessor.Extensions info.GifFrames = gifFrames; info.AnimationLength = delay; - info.IsAnimated = true; - - info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0); // Loop info is stored at byte 20737. + info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0); info.IsLooped = info.LoopCount != 1; } } - - return info; } + + return info; } } } diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs index f6dfa5e446..aac5df72d2 100644 --- a/src/ImageProcessor/ImageFactory.cs +++ b/src/ImageProcessor/ImageFactory.cs @@ -624,14 +624,8 @@ namespace ImageProcessor int width = size.Width; int height = size.Height; - //Dictionary resizeSettings = new Dictionary { { "MaxWidth", width.ToString("G") }, { "MaxHeight", height.ToString("G") } }; - ResizeLayer resizeLayer = new ResizeLayer(new Size(width, height)); - //Resize resize = new Resize { DynamicParameter = resizeLayer, Settings = resizeSettings }; - - //this.Image = resize.ProcessImage(this); - return this.Resize(resizeLayer); } @@ -656,26 +650,6 @@ namespace ImageProcessor Resize resize = new Resize { DynamicParameter = resizeLayer, Settings = resizeSettings }; this.ProcessImage(resize.ProcessImage, resizeLayer.Size.Width, resizeLayer.Size.Height); - - //ImageInfo imageInfo = this.Image.GetImageInfo(); - - //if (imageInfo.IsAnimated) - //{ - // using (GifEncoder encoder = new GifEncoder(new MemoryStream(4096), resizeLayer.Size.Width, resizeLayer.Size.Height, imageInfo.LoopCount)) - // { - // foreach (GifFrame frame in imageInfo.GifFrames) - // { - // frame.Image = ColorQuantizer.Quantize(resize.ProcessImage(this), PixelFormat.Format8bppIndexed); - // encoder.AddFrame(frame); - // } - - // this.Image = encoder.Save(); - // } - //} - //else - //{ - // this.Image = resize.ProcessImage(this); - //} } return this; @@ -979,58 +953,41 @@ namespace ImageProcessor } #endregion - /// - /// Gets a list of images contained within an animated gif. - /// - /// - /// The gif image. - /// - /// - /// The . - /// - protected IEnumerable GetImageFrames(Image gifImage) - { - // Gets the GUID - FrameDimension dimension = new FrameDimension(gifImage.FrameDimensionsList[0]); - - // Total frames in the animation - int frameCount = gifImage.GetFrameCount(dimension); - for (int index = 0; index < frameCount; index++) - { - // Find the frame - gifImage.SelectActiveFrame(dimension, index); - - // Return a copy of it - yield return (Image)gifImage.Clone(); - } - } - /// /// Uses the /// to fix the color palette of gif images. /// private void FixIndexedPallete() { + ImageFormat format = this.ImageFormat; + // Fix the colour palette of indexed images. - if (this.isIndexed) + if (this.isIndexed || format.Equals(ImageFormat.Gif)) { - this.Image = ColorQuantizer.Quantize(this.Image, PixelFormat.Format8bppIndexed); + ImageInfo imageInfo = this.Image.GetImageInfo(format, false); + + if (!imageInfo.IsAnimated) + { + this.Image = ColorQuantizer.Quantize(this.Image, PixelFormat.Format8bppIndexed); + } } } + /// + /// The process image. + /// + /// + /// The processor. + /// + /// + /// The width. + /// + /// + /// The height. + /// private void ProcessImage(Func processor, int width, int height) { - - string path = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath; - // ReSharper disable once AssignNullToNotNullAttribute - string resolvedPath = Path.Combine(Path.GetDirectoryName(path), "frames-resized"); - DirectoryInfo di = new DirectoryInfo(resolvedPath); - if (!di.Exists) - { - di.Create(); - } - - ImageInfo imageInfo = this.Image.GetImageInfo(); + ImageInfo imageInfo = this.Image.GetImageInfo(this.ImageFormat); if (imageInfo.IsAnimated) { @@ -1039,14 +996,8 @@ namespace ImageProcessor foreach (GifFrame frame in imageInfo.GifFrames) { this.Image = frame.Image; - - //frame.Image = new Bitmap(ColorQuantizer.Quantize(processor.Invoke(this), PixelFormat.Format8bppIndexed)); - //using (Image temp = new Bitmap(ColorQuantizer.Quantize(processor.Invoke(this), PixelFormat.Format8bppIndexed))) - //{ - frame.Image = new Bitmap(processor.Invoke(this)); + frame.Image = new Bitmap(ColorQuantizer.Quantize(processor.Invoke(this), PixelFormat.Format8bppIndexed)); encoder.AddFrame(frame); - - //frame.Image.Save(Path.Combine(resolvedPath, counter + ".gif"), ImageFormat.Gif); } this.Image = encoder.Save(); diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index 70471dc0e1..66959a3d79 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -72,7 +72,6 @@ - diff --git a/src/ImageProcessor/Imaging/GifEncoder - Copy.cs b/src/ImageProcessor/Imaging/GifEncoder - Copy.cs deleted file mode 100644 index 075e5ec17a..0000000000 --- a/src/ImageProcessor/Imaging/GifEncoder - Copy.cs +++ /dev/null @@ -1,409 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Imaging -{ - #region - - using System; - using System.Drawing; - using System.Drawing.Imaging; - using System.IO; - using System.Linq; - - #endregion - - /// - /// Encodes multiple images as an animated gif to a stream. - /// - /// Always wire this up in a using block. - /// Disposing the encoder will complete the file. - /// Uses default .NET GIF encoding and adds animation headers. - /// - /// - /// - /// Encodes multiple images as an animated gif to a stream.
- /// ALWAYS ALWAYS ALWAYS wire this up in a using block
- /// Disposing the encoder will complete the file.
- /// Uses default .net GIF encoding and adds animation headers. - ///
- public class GifEncoder2 : IDisposable - { - #region Constants - - /// - /// The application block size. - /// - private const byte ApplicationBlockSize = 0x0b; - - /// - /// The application extension block identifier. - /// - private const int ApplicationExtensionBlockIdentifier = 0xff21; - - /// - /// The application identification. - /// - private const string ApplicationIdentification = "NETSCAPE2.0"; - - /// - /// The file trailer. - /// - private const byte FileTrailer = 0x3b; - - /// - /// The file type. - /// - private const string FileType = "GIF"; - - /// - /// The file version. - /// - private const string FileVersion = "89a"; - - /// - /// The graphic control extension block identifier. - /// - private const int GraphicControlExtensionBlockIdentifier = 0xf921; - - /// - /// The graphic control extension block size. - /// - private const byte GraphicControlExtensionBlockSize = 0x04; - - /// - /// The source color block length. - /// - private const long SourceColorBlockLength = 768; - - /// - /// The source color block position. - /// - private const long SourceColorBlockPosition = 13; - - /// - /// The source global color info position. - /// - private const long SourceGlobalColorInfoPosition = 10; - - /// - /// The source graphic control extension length. - /// - private const long SourceGraphicControlExtensionLength = 8; - - /// - /// The source graphic control extension position. - /// - private const long SourceGraphicControlExtensionPosition = 781; - - /// - /// The source image block header length. - /// - private const long SourceImageBlockHeaderLength = 11; - - /// - /// The source image block position. - /// - private const long SourceImageBlockPosition = 789; - - #endregion - - #region Fields - - /// - /// The _stream. - /// - private readonly Stream _stream; - - /// - /// The _height. - /// - private int? _height; - - /// - /// The _is first image. - /// - private bool _isFirstImage = true; - - /// - /// The _repeat count. - /// - private int? _repeatCount; - - /// - /// The _width. - /// - private int? _width; - - #endregion - - #region Constructors and Destructors - - /// - /// Initializes a new instance of the class. - /// Encodes multiple images as an animated gif to a stream.
- /// ALWAYS ALWAYS ALWAYS wire this in a using block
- /// Disposing the encoder will complete the file.
- /// Uses default .net GIF encoding and adds animation headers. - ///
- /// - /// The stream that will be written to. - /// - /// - /// Sets the width for this gif or null to use the first frame's width. - /// - /// - /// Sets the height for this gif or null to use the first frame's height. - /// - /// - /// The repeat Count. - /// - public GifEncoder2(Stream stream, int? width = null, int? height = null, int? repeatCount = null) - { - this._stream = stream; - this._width = width; - this._height = height; - this._repeatCount = repeatCount; - } - - #endregion - - #region Public Properties - - /// - /// Gets or sets the frame delay. - /// - public TimeSpan FrameDelay { get; set; } - - #endregion - - #region Public Methods and Operators - - /// - /// Adds a frame to this animation. - /// - /// - /// The image to add - /// - /// - /// The positioning x offset this image should be displayed at. - /// - /// - /// The positioning y offset this image should be displayed at. - /// - /// - /// The frame Delay. - /// - public void AddFrame(Image img, int x = 0, int y = 0, TimeSpan? frameDelay = null) - { - using (var gifStream = new MemoryStream()) - { - img.Save(gifStream, ImageFormat.Gif); - if (this._isFirstImage) - { - // Steal the global color table info - this.InitHeader(gifStream, img.Width, img.Height); - } - - this.WriteGraphicControlBlock(gifStream, frameDelay.GetValueOrDefault(this.FrameDelay)); - this.WriteImageBlock(gifStream, !this._isFirstImage, x, y, img.Width, img.Height); - } - - this._isFirstImage = false; - } - - /// - /// The dispose. - /// - public void Dispose() - { - // Complete Application Block - this.WriteByte(0); - - // Complete File - this.WriteByte(FileTrailer); - - // Pushing data - this._stream.Flush(); - } - - #endregion - - #region Methods - - /// - /// The init header. - /// - /// - /// The source gif. - /// - /// - /// The w. - /// - /// - /// The h. - /// - private void InitHeader(Stream sourceGif, int w, int h) - { - // File Header - this.WriteString(FileType); - this.WriteString(FileVersion); - this.WriteShort(this._width.GetValueOrDefault(w)); // Initial Logical Width - this.WriteShort(this._height.GetValueOrDefault(h)); // Initial Logical Height - sourceGif.Position = SourceGlobalColorInfoPosition; - this.WriteByte(sourceGif.ReadByte()); // Global Color Table Info - this.WriteByte(0); // Background Color Index - this.WriteByte(0); // Pixel aspect ratio - this.WriteColorTable(sourceGif); - - // App Extension Header - this.WriteShort(ApplicationExtensionBlockIdentifier); - this.WriteByte(ApplicationBlockSize); - this.WriteString(ApplicationIdentification); - this.WriteByte(3); // Application block length - this.WriteByte(1); - this.WriteShort(this._repeatCount.GetValueOrDefault(0)); // Repeat count for images. - this.WriteByte(0); // terminator - } - - /// - /// The write byte. - /// - /// - /// The value. - /// - private void WriteByte(int value) - { - this._stream.WriteByte(Convert.ToByte(value)); - } - - /// - /// The write color table. - /// - /// - /// The source gif. - /// - private void WriteColorTable(Stream sourceGif) - { - sourceGif.Position = SourceColorBlockPosition; // Locating the image color table - var colorTable = new byte[SourceColorBlockLength]; - sourceGif.Read(colorTable, 0, colorTable.Length); - this._stream.Write(colorTable, 0, colorTable.Length); - } - - /// - /// The write graphic control block. - /// - /// - /// The source gif. - /// - /// - /// The frame delay. - /// - private void WriteGraphicControlBlock(Stream sourceGif, TimeSpan frameDelay) - { - sourceGif.Position = SourceGraphicControlExtensionPosition; // Locating the source GCE - var blockhead = new byte[SourceGraphicControlExtensionLength]; - sourceGif.Read(blockhead, 0, blockhead.Length); // Reading source GCE - - this.WriteShort(GraphicControlExtensionBlockIdentifier); // Identifier - this.WriteByte(GraphicControlExtensionBlockSize); // Block Size - this.WriteByte(blockhead[3] & 0xf7 | 0x08); // Setting disposal flag - this.WriteShort(Convert.ToInt32(frameDelay.TotalMilliseconds / 10)); // Setting frame delay - this.WriteByte(blockhead[6]); // Transparent color index - this.WriteByte(0); // Terminator - } - - /// - /// The write image block. - /// - /// - /// The source gif. - /// - /// - /// The include color table. - /// - /// - /// The x. - /// - /// - /// The y. - /// - /// - /// The h. - /// - /// - /// The w. - /// - private void WriteImageBlock(Stream sourceGif, bool includeColorTable, int x, int y, int h, int w) - { - sourceGif.Position = SourceImageBlockPosition; // Locating the image block - var header = new byte[SourceImageBlockHeaderLength]; - sourceGif.Read(header, 0, header.Length); - this.WriteByte(header[0]); // Separator - this.WriteShort(x); // Position X - this.WriteShort(y); // Position Y - this.WriteShort(h); // Height - this.WriteShort(w); // Width - - if (includeColorTable) - { - // If first frame, use global color table - else use local - sourceGif.Position = SourceGlobalColorInfoPosition; - this.WriteByte(sourceGif.ReadByte() & 0x3f | 0x80); // Enabling local color table - this.WriteColorTable(sourceGif); - } - else - { - this.WriteByte(header[9] & 0x07 | 0x07); // Disabling local color table - } - - this.WriteByte(header[10]); // LZW Min Code Size - - // Read/Write image data - sourceGif.Position = SourceImageBlockPosition + SourceImageBlockHeaderLength; - - int dataLength = sourceGif.ReadByte(); - while (dataLength > 0) - { - var imgData = new byte[dataLength]; - sourceGif.Read(imgData, 0, dataLength); - - this._stream.WriteByte(Convert.ToByte(dataLength)); - this._stream.Write(imgData, 0, dataLength); - dataLength = sourceGif.ReadByte(); - } - - this._stream.WriteByte(0); // Terminator - } - - /// - /// The write short. - /// - /// - /// The value. - /// - private void WriteShort(int value) - { - this._stream.WriteByte(Convert.ToByte(value & 0xff)); - this._stream.WriteByte(Convert.ToByte((value >> 8) & 0xff)); - } - - /// - /// The write string. - /// - /// - /// The value. - /// - private void WriteString(string value) - { - this._stream.Write(value.ToArray().Select(c => (byte)c).ToArray(), 0, value.Length); - } - - #endregion - } -} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/GifEncoder.cs b/src/ImageProcessor/Imaging/GifEncoder.cs index 04050c386d..896c13b604 100644 --- a/src/ImageProcessor/Imaging/GifEncoder.cs +++ b/src/ImageProcessor/Imaging/GifEncoder.cs @@ -150,7 +150,7 @@ namespace ImageProcessor.Imaging private int? width; #endregion - #region Constructors and Destructors + #region Constructors /// /// Initializes a new instance of the class. /// diff --git a/src/ImageProcessorConsole/Program.cs b/src/ImageProcessorConsole/Program.cs index a858704999..7e71a5b382 100644 --- a/src/ImageProcessorConsole/Program.cs +++ b/src/ImageProcessorConsole/Program.cs @@ -36,7 +36,7 @@ namespace ImageProcessorConsole { using (ImageFactory imageFactory = new ImageFactory()) { - Size size = new Size(150, 150); + Size size = new Size(200, 200); ImageFormat format = ImageFormat.Gif; // Load, resize, set the format and quality and save an image. diff --git a/src/Images/meter.gif b/src/Images/meter.gif new file mode 100644 index 0000000000000000000000000000000000000000..03fce3f3a5b70ca8463cefdd94c00e9c7fdbab0f GIT binary patch literal 22525 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 *EHnj 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 i0Mm8DTt^ow`J{C&>c^Y@m)Cy0z5eB?CBzB(new UserStore(new ApplicationDbContext()))) - { - } - - public AccountController(UserManager userManager) - { - UserManager = userManager; - } - - public UserManager UserManager { get; private set; } - - // - // GET: /Account/Login - [AllowAnonymous] - public ActionResult Login(string returnUrl) - { - ViewBag.ReturnUrl = returnUrl; - return View(); - } - - // - // POST: /Account/Login - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task Login(LoginViewModel model, string returnUrl) - { - if (ModelState.IsValid) - { - var user = await UserManager.FindAsync(model.UserName, model.Password); - if (user != null) - { - await SignInAsync(user, model.RememberMe); - return RedirectToLocal(returnUrl); - } - else - { - ModelState.AddModelError("", "Invalid username or password."); - } - } - - // If we got this far, something failed, redisplay form - return View(model); - } - - // - // GET: /Account/Register - [AllowAnonymous] - public ActionResult Register() - { - return View(); - } - - // - // POST: /Account/Register - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task Register(RegisterViewModel model) - { - if (ModelState.IsValid) - { - var user = new ApplicationUser() { UserName = model.UserName }; - var result = await UserManager.CreateAsync(user, model.Password); - if (result.Succeeded) - { - await SignInAsync(user, isPersistent: false); - return RedirectToAction("Index", "Home"); - } - else - { - AddErrors(result); - } - } - - // If we got this far, something failed, redisplay form - return View(model); - } - - // - // POST: /Account/Disassociate - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Disassociate(string loginProvider, string providerKey) - { - ManageMessageId? message = null; - IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey)); - if (result.Succeeded) - { - message = ManageMessageId.RemoveLoginSuccess; - } - else - { - message = ManageMessageId.Error; - } - return RedirectToAction("Manage", new { Message = message }); - } - - // - // GET: /Account/Manage - public ActionResult Manage(ManageMessageId? message) - { - ViewBag.StatusMessage = - message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." - : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." - : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed." - : message == ManageMessageId.Error ? "An error has occurred." - : ""; - ViewBag.HasLocalPassword = HasPassword(); - ViewBag.ReturnUrl = Url.Action("Manage"); - return View(); - } - - // - // POST: /Account/Manage - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Manage(ManageUserViewModel model) - { - bool hasPassword = HasPassword(); - ViewBag.HasLocalPassword = hasPassword; - ViewBag.ReturnUrl = Url.Action("Manage"); - if (hasPassword) - { - if (ModelState.IsValid) - { - IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword); - if (result.Succeeded) - { - return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess }); - } - else - { - AddErrors(result); - } - } - } - else - { - // User does not have a password so remove any validation errors caused by a missing OldPassword field - ModelState state = ModelState["OldPassword"]; - if (state != null) - { - state.Errors.Clear(); - } - - if (ModelState.IsValid) - { - IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword); - if (result.Succeeded) - { - return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess }); - } - else - { - AddErrors(result); - } - } - } - - // If we got this far, something failed, redisplay form - return View(model); - } - - // - // POST: /Account/ExternalLogin - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public ActionResult ExternalLogin(string provider, string returnUrl) - { - // Request a redirect to the external login provider - return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl })); - } - - // - // GET: /Account/ExternalLoginCallback - [AllowAnonymous] - public async Task ExternalLoginCallback(string returnUrl) - { - var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); - if (loginInfo == null) - { - return RedirectToAction("Login"); - } - - // Sign in the user with this external login provider if the user already has a login - var user = await UserManager.FindAsync(loginInfo.Login); - if (user != null) - { - await SignInAsync(user, isPersistent: false); - return RedirectToLocal(returnUrl); - } - else - { - // If the user does not have an account, then prompt the user to create an account - ViewBag.ReturnUrl = returnUrl; - ViewBag.LoginProvider = loginInfo.Login.LoginProvider; - return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName }); - } - } - - // - // POST: /Account/LinkLogin - [HttpPost] - [ValidateAntiForgeryToken] - public ActionResult LinkLogin(string provider) - { - // Request a redirect to the external login provider to link a login for the current user - return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId()); - } - - // - // GET: /Account/LinkLoginCallback - public async Task LinkLoginCallback() - { - var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId()); - if (loginInfo == null) - { - return RedirectToAction("Manage", new { Message = ManageMessageId.Error }); - } - var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login); - if (result.Succeeded) - { - return RedirectToAction("Manage"); - } - return RedirectToAction("Manage", new { Message = ManageMessageId.Error }); - } - - // - // POST: /Account/ExternalLoginConfirmation - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl) - { - if (User.Identity.IsAuthenticated) - { - return RedirectToAction("Manage"); - } - - if (ModelState.IsValid) - { - // Get the information about the user from the external login provider - var info = await AuthenticationManager.GetExternalLoginInfoAsync(); - if (info == null) - { - return View("ExternalLoginFailure"); - } - var user = new ApplicationUser() { UserName = model.UserName }; - var result = await UserManager.CreateAsync(user); - if (result.Succeeded) - { - result = await UserManager.AddLoginAsync(user.Id, info.Login); - if (result.Succeeded) - { - await SignInAsync(user, isPersistent: false); - return RedirectToLocal(returnUrl); - } - } - AddErrors(result); - } - - ViewBag.ReturnUrl = returnUrl; - return View(model); - } - - // - // POST: /Account/LogOff - [HttpPost] - [ValidateAntiForgeryToken] - public ActionResult LogOff() - { - AuthenticationManager.SignOut(); - return RedirectToAction("Index", "Home"); - } - - // - // GET: /Account/ExternalLoginFailure - [AllowAnonymous] - public ActionResult ExternalLoginFailure() - { - return View(); - } - - [ChildActionOnly] - public ActionResult RemoveAccountList() - { - var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId()); - ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1; - return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts); - } - - protected override void Dispose(bool disposing) - { - if (disposing && UserManager != null) - { - UserManager.Dispose(); - UserManager = null; - } - base.Dispose(disposing); - } - - #region Helpers - // Used for XSRF protection when adding external logins - private const string XsrfKey = "XsrfId"; - - private IAuthenticationManager AuthenticationManager - { - get - { - return HttpContext.GetOwinContext().Authentication; - } - } - - private async Task SignInAsync(ApplicationUser user, bool isPersistent) - { - AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); - var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); - AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity); - } - - private void AddErrors(IdentityResult result) - { - foreach (var error in result.Errors) - { - ModelState.AddModelError("", error); - } - } - - private bool HasPassword() - { - var user = UserManager.FindById(User.Identity.GetUserId()); - if (user != null) - { - return user.PasswordHash != null; - } - return false; - } - - public enum ManageMessageId - { - ChangePasswordSuccess, - SetPasswordSuccess, - RemoveLoginSuccess, - Error - } - - private ActionResult RedirectToLocal(string returnUrl) - { - if (Url.IsLocalUrl(returnUrl)) - { - return Redirect(returnUrl); - } - else - { - return RedirectToAction("Index", "Home"); - } - } - - private class ChallengeResult : HttpUnauthorizedResult - { - public ChallengeResult(string provider, string redirectUri) : this(provider, redirectUri, null) - { - } - - public ChallengeResult(string provider, string redirectUri, string userId) - { - LoginProvider = provider; - RedirectUri = redirectUri; - UserId = userId; - } - - public string LoginProvider { get; set; } - public string RedirectUri { get; set; } - public string UserId { get; set; } - - public override void ExecuteResult(ControllerContext context) - { - var properties = new AuthenticationProperties() { RedirectUri = RedirectUri }; - if (UserId != null) - { - properties.Dictionary[XsrfKey] = UserId; - } - context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider); - } - } - #endregion - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Controllers/HomeController.cs b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Controllers/HomeController.cs deleted file mode 100644 index 5080a1bf54..0000000000 --- a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Controllers/HomeController.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; - -namespace Test_Website_MVC5_NET45.Controllers -{ - public class HomeController : Controller - { - public ActionResult Index() - { - return View(); - } - - public ActionResult About() - { - ViewBag.Message = "Your application description page."; - - return View(); - } - - public ActionResult Contact() - { - ViewBag.Message = "Your contact page."; - - return View(); - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Global.asax b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Global.asax deleted file mode 100644 index 98f5cf9430..0000000000 --- a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Global.asax +++ /dev/null @@ -1 +0,0 @@ -<%@ Application Codebehind="Global.asax.cs" Inherits="Test_Website_MVC5_NET45.MvcApplication" Language="C#" %> diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Global.asax.cs b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Global.asax.cs deleted file mode 100644 index a0aa5366f5..0000000000 --- a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Global.asax.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using System.Web.Optimization; -using System.Web.Routing; - -namespace Test_Website_MVC5_NET45 -{ - public class MvcApplication : System.Web.HttpApplication - { - protected void Application_Start() - { - AreaRegistration.RegisterAllAreas(); - FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); - RouteConfig.RegisterRoutes(RouteTable.Routes); - BundleConfig.RegisterBundles(BundleTable.Bundles); - } - } -} diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Models/AccountViewModels.cs b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Models/AccountViewModels.cs deleted file mode 100644 index 6c841db433..0000000000 --- a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Models/AccountViewModels.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Test_Website_MVC5_NET45.Models -{ - public class ExternalLoginConfirmationViewModel - { - [Required] - [Display(Name = "User name")] - public string UserName { get; set; } - } - - public class ManageUserViewModel - { - [Required] - [DataType(DataType.Password)] - [Display(Name = "Current password")] - public string OldPassword { get; set; } - - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "New password")] - public string NewPassword { get; set; } - - [DataType(DataType.Password)] - [Display(Name = "Confirm new password")] - [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } - } - - public class LoginViewModel - { - [Required] - [Display(Name = "User name")] - public string UserName { get; set; } - - [Required] - [DataType(DataType.Password)] - [Display(Name = "Password")] - public string Password { get; set; } - - [Display(Name = "Remember me?")] - public bool RememberMe { get; set; } - } - - public class RegisterViewModel - { - [Required] - [Display(Name = "User name")] - public string UserName { get; set; } - - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "Password")] - public string Password { get; set; } - - [DataType(DataType.Password)] - [Display(Name = "Confirm password")] - [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } - } -} diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Models/IdentityModels.cs b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Models/IdentityModels.cs deleted file mode 100644 index 6f0ec8d065..0000000000 --- a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Models/IdentityModels.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.AspNet.Identity.EntityFramework; - -namespace Test_Website_MVC5_NET45.Models -{ - // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more. - public class ApplicationUser : IdentityUser - { - } - - public class ApplicationDbContext : IdentityDbContext - { - public ApplicationDbContext() - : base("DefaultConnection") - { - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Project_Readme.html b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Project_Readme.html deleted file mode 100644 index cb9e793868..0000000000 --- a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Project_Readme.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Your ASP.NET application - - - - - - -
-
-

This application consists of:

-
    -
  • Sample pages showing basic nav between Home, About, and Contact
  • -
  • Theming using Bootstrap
  • -
  • Authentication, if selected, shows how to register and sign in
  • -
  • ASP.NET features managed using NuGet
  • -
-
- - - - - -
-

Get help

- -
-
- - - \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Properties/AssemblyInfo.cs b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Properties/AssemblyInfo.cs deleted file mode 100644 index bde14ea74f..0000000000 --- a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Test_Website_MVC5_NET45")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Test_Website_MVC5_NET45")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("b611b339-de6d-4308-a532-79f2749956d3")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/_references.js b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/_references.js deleted file mode 100644 index 518a95992a99e9a3b60c01f77668ad6fb1fcbf08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 396 zcmbu5F%H5o3`O6J#2qU30%c$V?vj!qsGxzQ3~+eh$E-|Lk!35kpTGTnEhw*IgX7LX zB=ewWufHJgXgMqLY?&#aR239e>e?}7V*Ou2Qsy8lz7T?{t|AN^t@|Rnw|viur|N1} u%vsBd?=<^Aa>vbdC26l|#A;ZMrnb@>r9RufJSgw-Ah`NpcLHYpnGd@HB diff --git a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/bootstrap.js b/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/bootstrap.js deleted file mode 100644 index 5aa9982eda..0000000000 --- a/src/TestWebsites/NET45/Test_Website_MVC5_NET45/Scripts/bootstrap.js +++ /dev/null @@ -1,2014 +0,0 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ - -/** -* bootstrap.js v3.0.0 by @fat and @mdo -* Copyright 2013 Twitter Inc. -* http://www.apache.org/licenses/LICENSE-2.0 -*/ -if (!jQuery) { throw new Error("Bootstrap requires jQuery") } - -/* ======================================================================== - * Bootstrap: transition.js v3.0.0 - * http://twbs.github.com/bootstrap/javascript.html#transitions - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - 'WebkitTransition' : 'webkitTransitionEnd' - , 'MozTransition' : 'transitionend' - , 'OTransition' : 'oTransitionEnd otransitionend' - , 'transition' : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false, $el = this - $(this).one($.support.transition.end, function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - }) - -}(window.jQuery); - -/* ======================================================================== - * Bootstrap: alert.js v3.0.0 - * http://twbs.github.com/bootstrap/javascript.html#alerts - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // ALERT CLASS DEFINITION - // ====================== - - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = $(selector) - - if (e) e.preventDefault() - - if (!$parent.length) { - $parent = $this.hasClass('alert') ? $this : $this.parent() - } - - $parent.trigger(e = $.Event('close.bs.alert')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - $parent.trigger('closed.bs.alert').remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent - .one($.support.transition.end, removeElement) - .emulateTransitionEnd(150) : - removeElement() - } - - - // ALERT PLUGIN DEFINITION - // ======================= - - var old = $.fn.alert - - $.fn.alert = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') - - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.alert.Constructor = Alert - - - // ALERT NO CONFLICT - // ================= - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - // ALERT DATA-API - // ============== - - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) - -}(window.jQuery); - -/* ======================================================================== - * Bootstrap: button.js v3.0.0 - * http://twbs.github.com/bootstrap/javascript.html#buttons - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // BUTTON PUBLIC CLASS DEFINITION - // ============================== - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - } - - Button.DEFAULTS = { - loadingText: 'loading...' - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() - - state = state + 'Text' - - if (!data.resetText) $el.data('resetText', $el[val]()) - - $el[val](data[state] || this.options[state]) - - // push to event loop to allow forms to submit - setTimeout(function () { - state == 'loadingText' ? - $el.addClass(d).attr(d, d) : - $el.removeClass(d).removeAttr(d); - }, 0) - } - - Button.prototype.toggle = function () { - var $parent = this.$element.closest('[data-toggle="buttons"]') - - if ($parent.length) { - var $input = this.$element.find('input') - .prop('checked', !this.$element.hasClass('active')) - .trigger('change') - if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active') - } - - this.$element.toggleClass('active') - } - - - // BUTTON PLUGIN DEFINITION - // ======================== - - var old = $.fn.button - - $.fn.button = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - $.fn.button.Constructor = Button - - - // BUTTON NO CONFLICT - // ================== - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - // BUTTON DATA-API - // =============== - - $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - e.preventDefault() - }) - -}(window.jQuery); - -/* ======================================================================== - * Bootstrap: carousel.js v3.0.0 - * http://twbs.github.com/bootstrap/javascript.html#carousel - * ======================================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // CAROUSEL CLASS DEFINITION - // ========================= - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = - this.sliding = - this.interval = - this.$active = - this.$items = null - - this.options.pause == 'hover' && this.$element - .on('mouseenter', $.proxy(this.pause, this)) - .on('mouseleave', $.proxy(this.cycle, this)) - } - - Carousel.DEFAULTS = { - interval: 5000 - , pause: 'hover' - , wrap: true - } - - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) - - this.interval && clearInterval(this.interval) - - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - - return this - } - - Carousel.prototype.getActiveIndex = function () { - this.$active = this.$element.find('.item.active') - this.$items = this.$active.parent().children() - - return this.$items.index(this.$active) - } - - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getActiveIndex() - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) return this.$element.one('slid', function () { that.to(pos) }) - if (activeIndex == pos) return this.pause().cycle() - - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) - } - - Carousel.prototype.pause = function (e) { - e || (this.paused = true) - - if (this.$element.find('.next, .prev').length && $.support.transition.end) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - - this.interval = clearInterval(this.interval) - - return this - } - - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } - - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } - - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || $active[type]() - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var fallback = type == 'next' ? 'first' : 'last' - var that = this - - if (!$next.length) { - if (!this.options.wrap) return - $next = this.$element.find('.item')[fallback]() - } - - this.sliding = true - - isCycling && this.pause() - - var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) - - if ($next.hasClass('active')) return - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - this.$element.one('slid', function () { - var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) - $nextIndicator && $nextIndicator.addClass('active') - }) - } - - if ($.support.transition && this.$element.hasClass('slide')) { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one($.support.transition.end, function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { that.$element.trigger('slid') }, 0) - }) - .emulateTransitionEnd(600) - } else { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger('slid') - } - - isCycling && this.cycle() - - return this - } - - - // CAROUSEL PLUGIN DEFINITION - // ========================== - - var old = $.fn.carousel - - $.fn.carousel = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - $.fn.carousel.Constructor = Carousel - - - // CAROUSEL NO CONFLICT - // ==================== - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - - // CAROUSEL DATA-API - // ================= - - $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { - var $this = $(this), href - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false - - $target.carousel(options) - - if (slideIndex = $this.attr('data-slide-to')) { - $target.data('bs.carousel').to(slideIndex) - } - - e.preventDefault() - }) - - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - $carousel.carousel($carousel.data()) - }) - }) - -}(window.jQuery); - -/* ======================================================================== - * Bootstrap: collapse.js v3.0.0 - * http://twbs.github.com/bootstrap/javascript.html#collapse - * ======================================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.transitioning = null - - if (this.options.parent) this.$parent = $(this.options.parent) - if (this.options.toggle) this.toggle() - } - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var actives = this.$parent && this.$parent.find('> .panel > .in') - - if (actives && actives.length) { - var hasData = actives.data('bs.collapse') - if (hasData && hasData.transitioning) return - actives.collapse('hide') - hasData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing') - [dimension](0) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('in') - [dimension]('auto') - this.transitioning = 0 - this.$element.trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one($.support.transition.end, $.proxy(complete, this)) - .emulateTransitionEnd(350) - [dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element - [dimension](this.$element[dimension]()) - [0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse') - .removeClass('in') - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .trigger('hidden.bs.collapse') - .removeClass('collapsing') - .addClass('collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one($.support.transition.end, $.proxy(complete, this)) - .emulateTransitionEnd(350) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - - // COLLAPSE PLUGIN DEFINITION - // ========================== - - var old = $.fn.collapse - - $.fn.collapse = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { - var $this = $(this), href - var target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - var $target = $(target) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - var parent = $this.attr('data-parent') - var $parent = parent && $(parent) - - if (!data || !data.transitioning) { - if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') - $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - } - - $target.collapse(option) - }) - -}(window.jQuery); - -/* ======================================================================== - * Bootstrap: dropdown.js v3.0.0 - * http://twbs.github.com/bootstrap/javascript.html#dropdowns - * ======================================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // DROPDOWN CLASS DEFINITION - // ========================= - - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle=dropdown]' - var Dropdown = function (element) { - var $el = $(element).on('click.bs.dropdown', this.toggle) - } - - Dropdown.prototype.toggle = function (e) { - var $this = $(this) - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we we use a backdrop because click events don't delegate - $(' +
+
+
+

Animated

+ +
+
+