diff --git a/README.md b/README.md index 14d8451e7..f6afafeb1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ ImageProcessor =============== -Imageprocessor is a lightweight library written in C# that allows you to manipulate images on-the-fly using .NET 4.0. +[![Build status](https://ci.appveyor.com/api/projects/status/8ypr7527dnao04yr)](https://ci.appveyor.com/project/JamesSouth/imageprocessor) + +Imageprocessor is a lightweight library written in C# that allows you to manipulate images on-the-fly using .NET 4.5+ It's fast, extensible, easy to use, comes bundled with some great features and is fully open source. @@ -26,8 +28,8 @@ I want the next version of ImageProcessor to run on all devices. Sadly it looks ImageProcessor's documentation, included in this repo in the gh_pages directory, is built with [Jekyll](http://jekyllrb.com) and publicly hosted on GitHub Pages at . The docs may also be run locally. ### Running documentation locally -1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v1.5.x). +1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v2.2.x). - **Windows users:** Read [this unofficial guide](https://github.com/juthilo/run-jekyll-on-windows/) to get Jekyll up and running without problems. 2. From the root `/ImageProcessor` directory, run `jekyll serve` in the command line. 3. Open in your browser to navigate to your site. -Learn more about using Jekyll by reading its [documentation](http://jekyllrb.com/docs/home/). \ No newline at end of file +Learn more about using Jekyll by reading its [documentation](http://jekyllrb.com/docs/home/). diff --git a/build/Build.ImageProcessor.Plugins.WebP.proj b/build/Build.ImageProcessor.Plugins.WebP.proj new file mode 100644 index 000000000..c2fca90fd --- /dev/null +++ b/build/Build.ImageProcessor.Plugins.WebP.proj @@ -0,0 +1,54 @@ + + + .\ + + + + + + + + Release + _BuildOutput\ + False + $(MSBuildProjectDirectory)\$(BuildFolder) + $(BuildFolderAbsolutePath)ImageProcessor.Plugins.WebP\lib\net45 + ..\src\Plugins\ImageProcessor\ImageProcessor.Plugins.WebP\ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/Build.ImageProcessor.Web.proj b/build/Build.ImageProcessor.Web.proj index ab35a64e4..ae6936faf 100644 --- a/build/Build.ImageProcessor.Web.proj +++ b/build/Build.ImageProcessor.Web.proj @@ -2,15 +2,15 @@ .\ - - - - - + Release _BuildOutput\ @@ -19,42 +19,39 @@ $(MSBuildProjectDirectory)\$(BuildFolder) $(BuildFolder)bin\ $(BuildFolderRelativeToProjects)bin\ - $(BuildFolderAbsolutePath)ImageProcessor.Web\lib\net40 - $(BuildFolderAbsolutePath)ImageProcessor.Web\lib\net45 + $(BuildFolderAbsolutePath)ImageProcessor.Web\lib\net45 ..\src\ImageProcessor.Web\ - - + - - - - + + - + - - - + + + - + - \ No newline at end of file + diff --git a/build/Build.ImageProcessor.proj b/build/Build.ImageProcessor.proj index 930275286..134c1ed9f 100644 --- a/build/Build.ImageProcessor.proj +++ b/build/Build.ImageProcessor.proj @@ -2,53 +2,53 @@ .\ - - - - - + Release _BuildOutput\ False $(MSBuildProjectDirectory)\$(BuildFolder) - $(BuildFolderAbsolutePath)ImageProcessor\lib\ + $(BuildFolderAbsolutePath)ImageProcessor\lib\net45 ..\src\ImageProcessor\ - - + - + - + - + - - + + - + - \ No newline at end of file + diff --git a/build/Build.bat b/build/Build.bat index 09aff3d86..0014058f0 100644 --- a/build/Build.bat +++ b/build/Build.bat @@ -1,24 +1,24 @@ @ECHO OFF -SET version=1.9.5.0 -SET webversion=3.3.0.0 -SET webconfigversion=1.1.3.0 -ECHO Building ImageProcessor %version%, ImageProcess.Web %webversion% and ImageProcess.Web.Config %webconfigversion% +SET version=2.0.0.0 +SET webversion=4.0.0.0 +SET webconfigversion=2.0.0.0 +SET webppluginversion=1.0.0.0 -ECHO Installing the Microsoft.Bcl.Build package before anything else, otherwise you'd have to run build.cmd twice -SET nuGetFolder=%CD%\..\src\packages\ -..\src\.nuget\NuGet.exe install ..\src\ImageProcessor.Web\NET4\packages.config -OutputDirectory %nuGetFolder% +ECHO Building ImageProcessor %version%, ImageProcessor.Web %webversion%, ImageProcessor.Web.Config %webconfigversion%, and ImageProcessor.Plugins.WebP %webppluginversion% ECHO Removing _BuildOutput directory so everything is nice and clean RD _BuildOutput /q /s %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.ImageProcessor.proj" /p:BUILD_RELEASE=%version% /p:BUILD_COMMENT=%comment% %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.ImageProcessor.Web.proj" /p:BUILD_RELEASE=%webversion% /p:BUILD_COMMENT=%comment% +%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.ImageProcessor.Plugins.WebP.proj" /p:BUILD_RELEASE=%webppluginversion% /p:BUILD_COMMENT=%comment% ECHO Packing the NuGet release files ..\src\.nuget\NuGet.exe pack NuSpecs\ImageProcessor.nuspec -Version %version% ..\src\.nuget\NuGet.exe pack NuSpecs\ImageProcessor.Web.nuspec -Version %webversion% ..\src\.nuget\NuGet.exe pack NuSpecs\ImageProcessor.Web.Config.nuspec -Version %webconfigversion% +..\src\.nuget\NuGet.exe pack NuSpecs\ImageProcessor.Plugins.WebP.nuspec -Version %webppluginversion% PAUSE IF ERRORLEVEL 1 GOTO :showerror diff --git a/build/NuSpecs/ImageProcessor.Plugins.WebP.nuspec b/build/NuSpecs/ImageProcessor.Plugins.WebP.nuspec new file mode 100644 index 000000000..2b73746c5 --- /dev/null +++ b/build/NuSpecs/ImageProcessor.Plugins.WebP.nuspec @@ -0,0 +1,32 @@ + + + + ImageProcessor.Plugins.WebP + 1.0.0.0 + ImageProcessor.Plugins.WebP + James South + James South + http://imageprocessor.org + http://raw.githubusercontent.com/JimBobSquarePants/ImageProcessor/master/build/content/imageprocessor.128.png + false + Adds support to ImageProcessor for the WebP image format. + +If you use ImageProcessor please get in touch via my twitter @james_m_south + +Feedback is always welcome + Adds support to ImageProcessor for the WebP image format. + + James South + en-GB + Image Imaging ASP Performance Processing HttpModule Cache Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png WebP Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated + + + + + + + + + + + diff --git a/build/NuSpecs/ImageProcessor.Web.Config.nuspec b/build/NuSpecs/ImageProcessor.Web.Config.nuspec index b3105cd50..45786ebd5 100644 --- a/build/NuSpecs/ImageProcessor.Web.Config.nuspec +++ b/build/NuSpecs/ImageProcessor.Web.Config.nuspec @@ -1,4 +1,4 @@ - + ImageProcessor.Web.Config @@ -14,26 +14,22 @@ If you use ImageProcessor please get in touch via my twitter @james_m_south Feedback is always welcome - ImageProcessor.Web configuration settings for ASP.NET websites. + ImageProcessor.Web configuration settings for ASP.NET websites. James South en-GB - Image Imaging ASP Performance Processing HttpModule Cache Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated + Image Imaging ASP Performance Processing HttpModule Cache Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png WebP Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated - - - - - - + + - - - + + + - \ No newline at end of file + diff --git a/build/NuSpecs/ImageProcessor.Web.nuspec b/build/NuSpecs/ImageProcessor.Web.nuspec index e706fbf27..9f765206e 100644 --- a/build/NuSpecs/ImageProcessor.Web.nuspec +++ b/build/NuSpecs/ImageProcessor.Web.nuspec @@ -1,4 +1,4 @@ - + ImageProcessor.Web @@ -13,8 +13,6 @@ Methods include: Resize, Rotate, Rounded Corners, Flip, Crop, Watermark, Filter, Saturation, Brightness, Contrast, Quality, Format, Vignette, Gaussian Blur, Gaussian Sharpen, and Transparency. -This package also requires Microsoft.Bcl.Async on .NET 4.0 which will be added on install if applicable. - If you use ImageProcessor please get in touch via my twitter @james_m_south Feedback is always welcome @@ -22,21 +20,15 @@ Feedback is always welcome James South en-GB - Image Imaging ASP Performance Processing HttpModule Cache Resize AutoRotate Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated EXIF + Image Imaging ASP Performance Processing HttpModule Cache Resize AutoRotate Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png WebP Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated EXIF - - - - - - + - - \ No newline at end of file + diff --git a/build/NuSpecs/ImageProcessor.nuspec b/build/NuSpecs/ImageProcessor.nuspec index 80bdd79a1..2b9c8af53 100644 --- a/build/NuSpecs/ImageProcessor.nuspec +++ b/build/NuSpecs/ImageProcessor.nuspec @@ -9,21 +9,20 @@ http://imageprocessor.org http://raw.githubusercontent.com/JimBobSquarePants/ImageProcessor/master/build/content/imageprocessor.128.png false - Image Processor is an easy to use and extend processing library written in C#. Its fluent API makes common imaging tasks very simple to perform. + Image Processor is an easy to use and extend processing library written in C#. Its fluent API makes common imaging tasks very simple to perform. Methods include; Resize, Rotate, Rounded Corners, Flip, Crop, Watermark, Filter, Saturation, Brightness, Contrast, Quality, Format, Vignette, Gaussian Blur, Gaussian Sharpen, and Transparency. If you use ImageProcessor please get in touch on my twitter @james_m_south. - Feedback is always welcome. A library for manipulating image files written in C#. James South en-GB - Image Imaging ASP Performance Processing Resize AutoRotate Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated EXIF + Image Imaging ASP Performance Processing Resize AutoRotate Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png WebP Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated EXIF - + - \ No newline at end of file + diff --git a/build/content/ImageProcessor.Plugins.WebP/web.config.transform b/build/content/ImageProcessor.Plugins.WebP/web.config.transform new file mode 100644 index 000000000..aaa15b857 --- /dev/null +++ b/build/content/ImageProcessor.Plugins.WebP/web.config.transform @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/build/content/ImageProcessor.Web.Config/web.config.transform b/build/content/ImageProcessor.Web.Config/web.config.transform index 84b0a6f96..3c88a71b1 100644 --- a/build/content/ImageProcessor.Web.Config/web.config.transform +++ b/build/content/ImageProcessor.Web.Config/web.config.transform @@ -2,9 +2,9 @@ -
-
-
+
+
+
diff --git a/build/content/ImageProcessor.Web/web.config.transform b/build/content/ImageProcessor.Web/web.config.transform index a541ff10e..7d02ee462 100644 --- a/build/content/ImageProcessor.Web/web.config.transform +++ b/build/content/ImageProcessor.Web/web.config.transform @@ -7,6 +7,10 @@ + + + + diff --git a/src/ImageProcessor.UnitTests/Extensions/DoubleExtensionsUnitTests.cs b/src/ImageProcessor.UnitTests/Extensions/DoubleExtensionsUnitTests.cs new file mode 100644 index 000000000..91b62d74f --- /dev/null +++ b/src/ImageProcessor.UnitTests/Extensions/DoubleExtensionsUnitTests.cs @@ -0,0 +1,38 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Runs unit tests on the extension methods +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.UnitTests.Extensions +{ + using Common.Extensions; + using NUnit.Framework; + + /// + /// Test harness for the DoubleExtensions extension methods + /// + [TestFixture] + public class DoubleExtensionsUnitTests + { + /// + /// Tests the double to byte conversion + /// + /// Double input + /// Expected result + [Test] + [TestCase(-10, 0x0)] + [TestCase(1.5, 0x1)] + [TestCase(25.7, 0x19)] + [TestCase(1289047, 0xFF)] + public void TestDoubleToByte(double input, byte expected) + { + byte result = input.ToByte(); + Assert.AreEqual(expected, result); + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Extensions/IntegerExtensionsUnitTests.cs b/src/ImageProcessor.UnitTests/Extensions/IntegerExtensionsUnitTests.cs new file mode 100644 index 000000000..2adbe3b17 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Extensions/IntegerExtensionsUnitTests.cs @@ -0,0 +1,37 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Runs unit tests on the extension methods +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.UnitTests.Extensions +{ + using Common.Extensions; + using NUnit.Framework; + + /// + /// Provides a test harness for the integer extension class + /// + [TestFixture] + public class IntegerExtensionsUnitTests + { + /// + /// Tests the "ToByte" extension + /// + /// Integer input + /// Expected result + [Test] + [TestCase(21, 0x15)] + [TestCase(190, 0xBE)] + [TestCase(3156, 0xFF)] + public void ToByteTest(int input, byte expected) + { + byte result = input.ToByte(); + Assert.AreEqual(expected, result); + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs b/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs index ccbad8b4e..6412226b5 100644 --- a/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs +++ b/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs @@ -11,7 +11,10 @@ namespace ImageProcessor.UnitTests { using System; + using System.Collections.Generic; + using System.Drawing; using System.IO; + using System.Linq; using NUnit.Framework; /// @@ -21,29 +24,562 @@ namespace ImageProcessor.UnitTests public class ImageFactoryUnitTests { /// - /// The path to the binary's folder + /// The list of images. Designed to speed up the tests a little. /// - private readonly string localPath = Path.GetDirectoryName(new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath); + private IEnumerable images; /// /// Tests the loading of image from a file /// [Test] - [TestCase("Chrysanthemum.jpg", "image/jpeg")] - [TestCase("Desert.jpg", "image/jpeg")] - [TestCase("cmyk.png", "image/png")] - [TestCase("Penguins.bmp", "image/bmp")] - [TestCase("Penguins.gif", "image/gif")] - public void TestLoadImageFromFile(string fileName, string expectedMime) + public void TestLoadImageFromFile() { - var testPhoto = Path.Combine(this.localPath, string.Format("Images/{0}", fileName)); - using (ImageFactory imageFactory = new ImageFactory()) + foreach (FileInfo file in this.ListInputFiles()) { - imageFactory.Load(testPhoto); - Assert.AreEqual(testPhoto, imageFactory.ImagePath); - Assert.AreEqual(expectedMime, imageFactory.MimeType); - Assert.IsNotNull(imageFactory.Image); + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Assert.AreEqual(file.FullName, imageFactory.ImagePath); + Assert.IsNotNull(imageFactory.Image); + } } } + + /// + /// Tests the loading of image from a memory stream + /// + [Test] + public void TestLoadImageFromMemory() + { + foreach (FileInfo file in this.ListInputFiles()) + { + byte[] photoBytes = File.ReadAllBytes(file.FullName); + + using (MemoryStream inStream = new MemoryStream(photoBytes)) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(inStream); + Assert.AreEqual(null, imageFactory.ImagePath); + Assert.IsNotNull(imageFactory.Image); + } + } + } + } + + /// + /// Tests that the save method actually saves a file + /// + [Test] + public void TestSaveToDisk() + { + foreach (FileInfo file in this.ListInputFiles()) + { + string outputFileName = string.Format("./output/{0}", file.Name); + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + imageFactory.Save(outputFileName); + Assert.AreEqual(true, File.Exists(outputFileName)); + } + } + } + + /// + /// Tests that the save method actually writes to memory + /// + [Test] + public void TestSaveToMemory() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + using (MemoryStream s = new MemoryStream()) + { + imageFactory.Save(s); + s.Seek(0, SeekOrigin.Begin); + Assert.AreEqual(true, s.Capacity > 0); + } + } + } + } + + /// + /// Tests that a filter is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectAlpha() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Alpha(50); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that brightness changes is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectBrightness() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Brightness(50); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that background color changes are really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectBackgroundColor() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.BackgroundColor(Color.Yellow); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a contrast change is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectContrast() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Contrast(50); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a saturation change is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectSaturation() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Saturation(50); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a tint change is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectTint() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Tint(Color.FromKnownColor(KnownColor.AliceBlue)); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a vignette change is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectVignette() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Vignette(Color.FromKnownColor(KnownColor.AliceBlue)); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a filter is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectWatermark() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Watermark(new Imaging.TextLayer + { + FontFamily = new FontFamily("Arial"), + FontSize = 10, + Position = new Point(10, 10), + Text = "Lorem ipsum dolor" + }); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a filter is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectBlur() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.GaussianBlur(5); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a filter is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectBlurWithLayer() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.GaussianBlur(new Imaging.GaussianLayer { Sigma = 10, Size = 5, Threshold = 2 }); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a filter is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectSharpen() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.GaussianSharpen(5); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that a filter is really applied by checking that the image is modified + /// + [Test] + public void TestApplyEffectSharpenWithLayer() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.GaussianSharpen(new Imaging.GaussianLayer { Sigma = 10, Size = 5, Threshold = 2 }); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that all filters can be applied + /// + [Test] + public void TestApplyEffectFilter() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.BlackWhite); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.Comic); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.Gotham); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.GreyScale); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.HiSatch); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.Invert); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.Lomograph); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.LoSatch); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.Polaroid); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + + imageFactory.Filter(Imaging.Filters.MatrixFilters.Sepia); + Assert.AreNotEqual(original, imageFactory.Image); + imageFactory.Reset(); + } + } + } + + /// + /// Tests that a filter is really applied by checking that the image is modified + /// + [Test] + public void TestRoundedCorners() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.RoundedCorners(new Imaging.RoundedCornerLayer(5)); + Assert.AreNotEqual(original, imageFactory.Image); + } + } + } + + /// + /// Tests that the image is well resized using constraints + /// + [Test] + public void TestResizeConstraints() + { + const int MaxSize = 200; + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + imageFactory.Constrain(new Size(MaxSize, MaxSize)); + Assert.LessOrEqual(imageFactory.Image.Width, MaxSize); + Assert.LessOrEqual(imageFactory.Image.Height, MaxSize); + } + } + } + + /// + /// Tests that the image is well cropped + /// + [Test] + public void TestCrop() + { + const int MaxSize = 20; + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Crop(new Rectangle(0, 0, MaxSize, MaxSize)); + Assert.AreNotEqual(original, imageFactory.Image); + Assert.AreEqual(MaxSize, imageFactory.Image.Width); + Assert.LessOrEqual(MaxSize, imageFactory.Image.Height); + } + } + } + + /// + /// Tests that the image is well cropped + /// + [Test] + public void TestCropWithCropLayer() + { + const int MaxSize = 20; + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Crop(new Imaging.CropLayer(0, 0, MaxSize, MaxSize, Imaging.CropMode.Pixels)); + Assert.AreNotEqual(original, imageFactory.Image); + Assert.AreEqual(MaxSize, imageFactory.Image.Width); + Assert.LessOrEqual(MaxSize, imageFactory.Image.Height); + } + } + } + + /// + /// Tests that the image is flipped + /// + [Test] + public void TestFlip() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Flip(true); + Assert.AreNotEqual(original, imageFactory.Image); + Assert.AreEqual(original.Width, imageFactory.Image.Width); + Assert.AreEqual(original.Height, imageFactory.Image.Height); + imageFactory.Reset(); + + imageFactory.Flip(false); + Assert.AreNotEqual(original, imageFactory.Image); + Assert.AreEqual(original.Width, imageFactory.Image.Width); + Assert.AreEqual(original.Height, imageFactory.Image.Height); + } + } + } + + /// + /// Tests that the image is resized + /// + [Test] + public void TestResize() + { + const int NewSize = 150; + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + imageFactory.Resize(new Size(NewSize, NewSize)); + Assert.AreEqual(NewSize, imageFactory.Image.Width); + Assert.AreEqual(NewSize, imageFactory.Image.Height); + } + } + } + + /// + /// Tests that the image is resized + /// + [Test] + public void TestResizeWithLayer() + { + const int NewSize = 150; + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + imageFactory.Resize(new Imaging.ResizeLayer(new Size(NewSize, NewSize), Imaging.ResizeMode.Stretch, Imaging.AnchorPosition.Left)); + Assert.AreEqual(NewSize, imageFactory.Image.Width); + Assert.AreEqual(NewSize, imageFactory.Image.Height); + } + } + } + + /// + /// Tests that the image is resized + /// + [Test] + public void TestRotate() + { + foreach (FileInfo file in this.ListInputFiles()) + { + using (ImageFactory imageFactory = new ImageFactory()) + { + imageFactory.Load(file.FullName); + Image original = (Image)imageFactory.Image.Clone(); + imageFactory.Rotate(90); + Assert.AreEqual(original.Height, imageFactory.Image.Width); + Assert.AreEqual(original.Width, imageFactory.Image.Height); + } + } + } + + /// + /// Gets the files matching the given extensions. + /// + /// The . + /// The extensions. + /// A collection of + /// The extensions variable is null. + private static IEnumerable GetFilesByExtensions(DirectoryInfo dir, params string[] extensions) + { + if (extensions == null) + { + throw new ArgumentNullException("extensions"); + } + + IEnumerable files = dir.EnumerateFiles(); + return files.Where(f => extensions.Contains(f.Extension, StringComparer.OrdinalIgnoreCase)); + } + + /// + /// Lists the input files in the Images folder + /// + /// The list of files. + private IEnumerable ListInputFiles() + { + if (this.images != null) + { + return this.images; + } + + DirectoryInfo directoryInfo = new DirectoryInfo("./Images"); + + this.images = GetFilesByExtensions(directoryInfo, new[] { ".jpg", ".jpeg", ".png", ".gif", ".tiff", ".bmp", ".webp" }); + + return this.images; + } } } \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj b/src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj index 6fb6fd2bd..7fa981bcf 100644 --- a/src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj +++ b/src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj @@ -3,13 +3,18 @@ Debug AnyCPU - {03CA9055-F997-428C-BF28-F50F991777C6} + {633B1C4C-4823-47BE-9A01-A665F3118C8C} Library ImageProcessor.UnitTests ImageProcessor.UnitTests Client ..\ true + + + ..\ + true + v4.5 true @@ -20,6 +25,7 @@ prompt 4 false + false full @@ -28,6 +34,7 @@ prompt 4 false + false @@ -39,8 +46,11 @@ - - + + PreserveNewest + + + @@ -51,92 +61,65 @@ - - Images\Chrysanthemum.jpg - PreserveNewest - - - Images\Desert.jpg + + PreserveNewest - - Images\Hydrangeas.jpg + PreserveNewest - - Images\Jellyfish.jpg + PreserveNewest - - Images\Koala.jpg + PreserveNewest - - Images\Lighthouse.jpg + PreserveNewest - - Images\Penguins-200.jpg + PreserveNewest - - Images\Penguins-8.png + PreserveNewest - - Images\Penguins.bmp + PreserveNewest - - Images\Penguins.gif + PreserveNewest - - Images\Penguins.jpg + PreserveNewest - - Images\Penguins.png + PreserveNewest - - Images\Penguins.tif + PreserveNewest - - Images\Tulips.jpg + PreserveNewest - - Images\bus.jpg + PreserveNewest - - Images\cmyk.jpg + PreserveNewest - - Images\cmyk.png + PreserveNewest - - Images\jrt.jpg + PreserveNewest - - Images\meter.gif + PreserveNewest - - Images\rocks.jpg + PreserveNewest - - Images\rotate.jpg - PreserveNewest - - - Images\sample1.jpg + PreserveNewest @@ -172,4 +155,7 @@ + + + \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/autorotate.jpg.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/autorotate.jpg.REMOVED.git-id new file mode 100644 index 000000000..1b5e335ff --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/autorotate.jpg.REMOVED.git-id @@ -0,0 +1 @@ +75b37593bb2e505bf4fbe874eaf30debd6161c2e \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/cmyk-profile-euroscale.jpg.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/cmyk-profile-euroscale.jpg.REMOVED.git-id new file mode 100644 index 000000000..11eb19931 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/cmyk-profile-euroscale.jpg.REMOVED.git-id @@ -0,0 +1 @@ +d0a1a39a6729e826098ae5e987c22c34c989b7e3 \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/cmyk.jpg.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/cmyk.jpg.REMOVED.git-id new file mode 100644 index 000000000..9ba0b9f39 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/cmyk.jpg.REMOVED.git-id @@ -0,0 +1 @@ +9160894da31fedebb1fcd64eb57ca173187c63a6 \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/color-vision-test.gif.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/color-vision-test.gif.REMOVED.git-id new file mode 100644 index 000000000..ed1d0b80b --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/color-vision-test.gif.REMOVED.git-id @@ -0,0 +1 @@ +b169fac4f1591e81e91c0bb6fed6dcf62a34c80e \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/exif-Tulips.jpg.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/exif-Tulips.jpg.REMOVED.git-id new file mode 100644 index 000000000..20704f4a9 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/exif-Tulips.jpg.REMOVED.git-id @@ -0,0 +1 @@ +9d7e7964a2285363171929315b15ec69f14831ef \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/exif-rocks.jpg.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/exif-rocks.jpg.REMOVED.git-id new file mode 100644 index 000000000..2e03e238f --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/exif-rocks.jpg.REMOVED.git-id @@ -0,0 +1 @@ +be31c9c0dea90586e2965208611fad024f6a5b08 \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/format-Penguins-8bit.png.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/format-Penguins-8bit.png.REMOVED.git-id new file mode 100644 index 000000000..c48cdc177 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/format-Penguins-8bit.png.REMOVED.git-id @@ -0,0 +1 @@ +51ccec74a0351599de104f166b32d2860acaf089 \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/format-Penguins.bmp.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/format-Penguins.bmp.REMOVED.git-id new file mode 100644 index 000000000..9ba53bc67 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/format-Penguins.bmp.REMOVED.git-id @@ -0,0 +1 @@ +d7adbea2db4e3388541e31a229e5741677aaa7fd \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/format-Penguins.gif.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/format-Penguins.gif.REMOVED.git-id new file mode 100644 index 000000000..225d59af3 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/format-Penguins.gif.REMOVED.git-id @@ -0,0 +1 @@ +b301e58d431a78d3f17be53be1cdc94c86286389 \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/format-Penguins.jpg.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/format-Penguins.jpg.REMOVED.git-id new file mode 100644 index 000000000..06482dbd9 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/format-Penguins.jpg.REMOVED.git-id @@ -0,0 +1 @@ +ee5a15e7f8fc2655d5c1fc736a05857ab3d885bd \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/format-Penguins.png.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/format-Penguins.png.REMOVED.git-id new file mode 100644 index 000000000..4ab6b372b --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/format-Penguins.png.REMOVED.git-id @@ -0,0 +1 @@ +b6434b5a35e989d4fa71ede1a8316fedeee7ae5f \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/format-Penguins.tif.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/format-Penguins.tif.REMOVED.git-id new file mode 100644 index 000000000..5f7b97e71 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/format-Penguins.tif.REMOVED.git-id @@ -0,0 +1 @@ +c789aaec248568c24394b05c02db4233e0c5a4eb \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/format-animated.gif.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/format-animated.gif.REMOVED.git-id new file mode 100644 index 000000000..ac3664d5f --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/format-animated.gif.REMOVED.git-id @@ -0,0 +1 @@ +a41fb1117e1d730a4a488dcb67e0b867aa3c614e \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/hi-color.png b/src/ImageProcessor.UnitTests/Images/hi-color.png new file mode 100644 index 000000000..2ac0f7629 Binary files /dev/null and b/src/ImageProcessor.UnitTests/Images/hi-color.png differ diff --git a/src/ImageProcessor.UnitTests/Images/hi-contrast.jpg b/src/ImageProcessor.UnitTests/Images/hi-contrast.jpg new file mode 100644 index 000000000..a425cbc9e Binary files /dev/null and b/src/ImageProcessor.UnitTests/Images/hi-contrast.jpg differ diff --git a/src/ImageProcessor.UnitTests/Images/hi-saturation.jpg b/src/ImageProcessor.UnitTests/Images/hi-saturation.jpg new file mode 100644 index 000000000..e4c58f3ed Binary files /dev/null and b/src/ImageProcessor.UnitTests/Images/hi-saturation.jpg differ diff --git a/src/ImageProcessor.UnitTests/Images/profile-adobe-rgb.jpg.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/profile-adobe-rgb.jpg.REMOVED.git-id new file mode 100644 index 000000000..8064ffb21 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/profile-adobe-rgb.jpg.REMOVED.git-id @@ -0,0 +1 @@ +189f79f9b9604c5413aba928662d84edd426142d \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/profile-srgb.jpg.REMOVED.git-id b/src/ImageProcessor.UnitTests/Images/profile-srgb.jpg.REMOVED.git-id new file mode 100644 index 000000000..101151778 --- /dev/null +++ b/src/ImageProcessor.UnitTests/Images/profile-srgb.jpg.REMOVED.git-id @@ -0,0 +1 @@ +f731bdf700d2718f528317263264e5466374c5e5 \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/Images/size-Penguins-200.jpg b/src/ImageProcessor.UnitTests/Images/size-Penguins-200.jpg new file mode 100644 index 000000000..a9aa44d3d Binary files /dev/null and b/src/ImageProcessor.UnitTests/Images/size-Penguins-200.jpg differ diff --git a/src/ImageProcessor.UnitTests/Images/text-over-transparent.png b/src/ImageProcessor.UnitTests/Images/text-over-transparent.png new file mode 100644 index 000000000..7435dc6ba Binary files /dev/null and b/src/ImageProcessor.UnitTests/Images/text-over-transparent.png differ diff --git a/src/ImageProcessor.UnitTests/Images/udendørs.jpg b/src/ImageProcessor.UnitTests/Images/udendørs.jpg new file mode 100644 index 000000000..48af69a24 Binary files /dev/null and b/src/ImageProcessor.UnitTests/Images/udendørs.jpg differ diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Properties/AssemblyInfo.cs b/src/ImageProcessor.UnitTests/Properties/AssemblyInfo.cs similarity index 79% rename from src/TestWebsites/NET45/Test_Website_Webforms_NET45/Properties/AssemblyInfo.cs rename to src/ImageProcessor.UnitTests/Properties/AssemblyInfo.cs index 4d0e965bc..fb042a1d3 100644 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Properties/AssemblyInfo.cs +++ b/src/ImageProcessor.UnitTests/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ 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_Webforms_NET45")] +[assembly: AssemblyTitle("ImageProcessor.UnitTests2")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Test_Website_Webforms_NET45")] +[assembly: AssemblyProduct("ImageProcessor.UnitTests2")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -20,7 +20,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("0f9a8d30-dcae-41a0-9543-ef2ec5e2ca6d")] +[assembly: Guid("3003f5a6-eb11-4eee-bfaa-448deb3a31d9")] // Version information for an assembly consists of the following four values: // @@ -29,7 +29,8 @@ using System.Runtime.InteropServices; // Build Number // Revision // -// You can specify all the values or you can default the Revision and Build Numbers +// You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/ImageProcessor.UnitTests/RegularExpressionUnitTests.cs b/src/ImageProcessor.UnitTests/RegularExpressionUnitTests.cs deleted file mode 100644 index fcd45df4a..000000000 --- a/src/ImageProcessor.UnitTests/RegularExpressionUnitTests.cs +++ /dev/null @@ -1,217 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Unit tests for the ImageProcessor regular expressions -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.UnitTests -{ - using System; - using System.Drawing; - using ImageProcessor.Imaging; - using ImageProcessor.Processors; - using NUnit.Framework; - - /// - /// Test harness for the regular expressions - /// - [TestFixture] - public class RegularExpressionUnitTests - { - /// - /// The alpha regex unit test. - /// - [Test] - public void TestAlphaRegex() - { - const string Querystring = "alpha=56"; - const int Expected = 56; - - Alpha alpha = new Alpha(); - alpha.MatchRegexIndex(Querystring); - - int actual = alpha.DynamicParameter; - - Assert.AreEqual(Expected, actual); - } - - /// - /// The brightness regex unit test. - /// - [Test] - public void TestBrightnessRegex() - { - const string Querystring = "brightness=56"; - const int Expected = 56; - - Brightness brightness = new Brightness(); - brightness.MatchRegexIndex(Querystring); - - int actual = brightness.DynamicParameter; - - Assert.AreEqual(Expected, actual); - } - - /// - /// The contrast regex unit test. - /// - [Test] - public void TestContrastRegex() - { - const string Querystring = "contrast=56"; - const int Expected = 56; - - Contrast contrast = new Contrast(); - contrast.MatchRegexIndex(Querystring); - - int actual = contrast.DynamicParameter; - - Assert.AreEqual(Expected, actual); - } - - /// - /// The rotate regex unit test. - /// - [Test] - public void TestCropRegex() - { - const string Querystring = "crop=0,0,150,300"; - CropLayer expected = new CropLayer(0, 0, 150, 300, CropMode.Pixels); - - Crop crop = new Crop(); - crop.MatchRegexIndex(Querystring); - - CropLayer actual = crop.DynamicParameter; - Assert.AreEqual(expected, actual); - } - - /// - /// The filter regex unit test. - /// - [Test] - public void TestFilterRegex() - { - // Should really write more for the other filters. - const string Querystring = "filter=lomograph"; - const string Expected = "lomograph"; - - Filter filter = new Filter(); - filter.MatchRegexIndex(Querystring); - - string actual = filter.DynamicParameter; - - Assert.AreEqual(Expected, actual); - } - - /// - /// The format regex unit test. - /// - [Test] - public void TestFormatRegex() - { - const string Querystring = "format=gif"; - const string Expected = "gif"; - - Format format = new Format(); - format.MatchRegexIndex(Querystring); - - string actual = format.DynamicParameter; - - Assert.AreEqual(Expected, actual); - } - - /// - /// The quality regex unit test. - /// - [Test] - public void TestQualityRegex() - { - const string Querystring = "quality=56"; - const int Expected = 56; - - Quality quality = new Quality(); - quality.MatchRegexIndex(Querystring); - - int actual = quality.DynamicParameter; - - Assert.AreEqual(Expected, actual); - } - - /// - /// The resize regex unit test. - /// - [Test] - public void TestResizeRegex() - { - const string Querystring = "width=300"; - ResizeLayer expected = new ResizeLayer(new Size(300, 0)); - - Resize resize = new Resize(); - - resize.MatchRegexIndex(Querystring); - ResizeLayer actual = resize.DynamicParameter; - - Assert.AreEqual(expected, actual); - } - - /// - /// The rotate regex unit test. - /// - [Test] - public void TestRotateRegex() - { - const string Querystring = "rotate=270"; - RotateLayer expected = new RotateLayer(270, Color.Transparent); - - Rotate rotate = new Rotate(); - rotate.MatchRegexIndex(Querystring); - - RotateLayer actual = rotate.DynamicParameter; - - Assert.AreEqual(expected, actual); - } - - /// - /// The rounded corners regex unit test. - /// - [Test] - public void TestRoundedCornersRegex() - { - const string Querystring = "roundedcorners=30"; - RoundedCornerLayer expected = new RoundedCornerLayer(30, true, true, true, true); - - RoundedCorners roundedCorners = new RoundedCorners(); - roundedCorners.MatchRegexIndex(Querystring); - - RoundedCornerLayer actual = roundedCorners.DynamicParameter; - - Assert.AreEqual(expected, actual); - } - - /// - /// The rounded corners regex unit test. - /// - [Test] - public void TestTintRegex() - { - const string HexQuerystring = "tint=6aa6cc"; - const string RgbaQuerystring = "tint=106,166,204,255"; - Color expectedHex = ColorTranslator.FromHtml("#" + "6aa6cc"); - Color expectedRgba = Color.FromArgb(255, 106, 166, 204); - - Tint tint = new Tint(); - tint.MatchRegexIndex(HexQuerystring); - Color actualHex = tint.DynamicParameter; - Assert.AreEqual(expectedHex, actualHex); - - tint = new Tint(); - tint.MatchRegexIndex(RgbaQuerystring); - Color actualRgba = tint.DynamicParameter; - Assert.AreEqual(expectedRgba, actualRgba); - } - } -} \ No newline at end of file diff --git a/src/ImageProcessor.UnitTests/packages.config b/src/ImageProcessor.UnitTests/packages.config index 5a3253fcb..a18b325a4 100644 --- a/src/ImageProcessor.UnitTests/packages.config +++ b/src/ImageProcessor.UnitTests/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/ImageProcessor.Web.UnitTests/Extensions/StringExtensionsUnitTests.cs b/src/ImageProcessor.Web.UnitTests/Extensions/StringExtensionsUnitTests.cs new file mode 100644 index 000000000..3e9053aed --- /dev/null +++ b/src/ImageProcessor.Web.UnitTests/Extensions/StringExtensionsUnitTests.cs @@ -0,0 +1,160 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Test harness for the string extensions +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.UnitTests.Extensions +{ + using System; + using System.Collections.Generic; + + using ImageProcessor.Web.Extensions; + using NUnit.Framework; + + /// + /// Test harness for the string extensions + /// + [TestFixture] + public class StringExtensionsUnitTests + { + /// + /// Tests the passing to an integer array + /// + [Test] + public void TestToIntegerArray() + { + Dictionary data = new Dictionary + { + { + "123-456,78-90", + new[] { 123, 456, 78, 90 } + }, + { + "87390174,741897498,74816,748297,57355", + new[] + { + 87390174, 741897498, 74816, + 748297, 57355 + } + }, + { "1-2-3", new[] { 1, 2, 3 } } + }; + + foreach (KeyValuePair item in data) + { + int[] result = item.Key.ToPositiveIntegerArray(); + Assert.AreEqual(item.Value, result); + } + } + + /// + /// Tests the passing to an float array + /// + [Test] + public void TestToFloatArray() + { + Dictionary data = new Dictionary + { + { + "12.3-4.56,78-9.0", + new[] { 12.3F, 4.56F, 78, 9 } + }, + { + "87390.174,7.41897498,748.16,748297,5.7355", + new[] + { + 87390.174F, 7.41897498F, + 748.16F, 748297, 5.7355F + } + }, + { "1-2-3", new float[] { 1, 2, 3 } } + }; + + foreach (KeyValuePair item in data) + { + float[] result = item.Key.ToPositiveFloatArray(); + Assert.AreEqual(item.Value, result); + } + } + + /// + /// Tests the MD5 fingerprint + /// + /// The input value + /// The expected output of the hash + [Test] + [TestCase("test input", "2e7f7a62eabf0993239ca17c78c464d9")] + [TestCase("lorem ipsum dolor", "96ee002fee25e8b675a477c9750fa360")] + [TestCase("LoReM IpSuM DoLoR", "41e201da794c7fbdb8ce5526a71c8c83")] + [TestCase("1234567890", "e15e31c3d8898c92ab172a4311be9e84")] + public void TestToMd5Fingerprint(string input, string expected) + { + string result = input.ToMD5Fingerprint(); + bool comparison = result.Equals(expected, StringComparison.InvariantCultureIgnoreCase); + Assert.True(comparison); + } + + /// + /// Tests the SHA-1 fingerprint + /// + /// The input value + /// The expected output of the hash + [Test] + [TestCase("test input", "49883b34e5a0f48224dd6230f471e9dc1bdbeaf5")] + [TestCase("lorem ipsum dolor", "75899ad8827a32493928903aecd6e931bf36f967")] + [TestCase("LoReM IpSuM DoLoR", "2f44519afae72fc0837b72c6b53cb11338a1f916")] + [TestCase("1234567890", "01b307acba4f54f55aafc33bb06bbbf6ca803e9a")] + public void TestToSHA1Fingerprint(string input, string expected) + { + string result = input.ToSHA1Fingerprint(); + bool comparison = result.Equals(expected, StringComparison.InvariantCultureIgnoreCase); + Assert.True(comparison); + } + + /// + /// Tests if the value is a valid URI path name. I.E the path part of a uri. + /// + /// The value to test + /// Whether the value is correct + /// + /// The full RFC3986 does not seem to pass the test with the square brackets + /// ':' is failing for some reason in VS but not elsewhere. Could be a build issue. + /// + [Test] + [TestCase("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", true)] + [TestCase("-", true)] + [TestCase(".", true)] + [TestCase("_", true)] + [TestCase("~", true)] + [TestCase(":", true)] + [TestCase("/", true)] + [TestCase("?", true)] + [TestCase("#", false)] + [TestCase("[", false)] + [TestCase("]", false)] + [TestCase("@", true)] + [TestCase("!", true)] + [TestCase("$", true)] + [TestCase("&", true)] + [TestCase("'", true)] + [TestCase("(", true)] + [TestCase(")", true)] + [TestCase("*", true)] + [TestCase("+", true)] + [TestCase(",", true)] + [TestCase(";", true)] + [TestCase("=", true)] + [TestCase("lorem ipsum", false)] + [TestCase("é", false)] + public void TestIsValidUriPathName(string input, bool expected) + { + bool result = input.IsValidVirtualPathName(); + Assert.AreEqual(expected, result); + } + } +} diff --git a/src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj b/src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj new file mode 100644 index 000000000..d89506079 --- /dev/null +++ b/src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj @@ -0,0 +1,112 @@ + + + + Debug + AnyCPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260} + Library + Properties + ImageProcessor.Web.UnitTests + ImageProcessor.Web.UnitTests + v4.5 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + ..\ + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + ..\packages\NUnit.2.6.3\lib\nunit.framework.dll + + + + + + + + + + + + + + + + + + + + + + + {d011a778-59c8-4bfa-a770-c350216bf161} + ImageProcessor.Web + + + {3b5dd734-fb7a-487d-8ce6-55e7af9aea7e} + ImageProcessor + + + {2cf69699-959a-44dc-a281-4e2596c25043} + ImageProcessor.Plugins.WebP + + + + + + + False + + + False + + + False + + + False + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/src/TestWebsites/NET4/Properties/AssemblyInfo.cs b/src/ImageProcessor.Web.UnitTests/Properties/AssemblyInfo.cs similarity index 75% rename from src/TestWebsites/NET4/Properties/AssemblyInfo.cs rename to src/ImageProcessor.Web.UnitTests/Properties/AssemblyInfo.cs index 499251b9f..db6aa3c94 100644 --- a/src/TestWebsites/NET4/Properties/AssemblyInfo.cs +++ b/src/ImageProcessor.Web.UnitTests/Properties/AssemblyInfo.cs @@ -5,12 +5,12 @@ 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")] +[assembly: AssemblyTitle("ImageProcessor.Web.UnitTests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Test")] -[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyProduct("ImageProcessor.Web.UnitTests")] +[assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -20,7 +20,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("34f4c859-67cc-40d2-97ae-27e8c7157052")] +[assembly: Guid("74919969-6a75-4d26-b1b8-0626aa10af6d")] // Version information for an assembly consists of the following four values: // @@ -29,7 +29,8 @@ using System.Runtime.InteropServices; // Build Number // Revision // -// You can specify all the values or you can default the Revision and Build Numbers +// You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs b/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs new file mode 100644 index 000000000..2f66b1057 --- /dev/null +++ b/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs @@ -0,0 +1,474 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Unit tests for the ImageProcessor regular expressions +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.UnitTests +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using ImageProcessor.Imaging; + using ImageProcessor.Imaging.Filters; + using ImageProcessor.Imaging.Formats; + using ImageProcessor.Plugins.WebP.Imaging.Formats; + + using NUnit.Framework; + + /// + /// Test harness for the regular expressions + /// + [TestFixture] + public class RegularExpressionUnitTests + { + /// + /// The alpha regex unit test. + /// + /// + /// The input string. + /// + /// + /// The expected result. + /// + [Test] + [TestCase("alpha=66", 66)] + [TestCase("alpha=-66", 66)] + [TestCase("alpha=101", 1)] + [TestCase("alpha=-101", 1)] + [TestCase("alpha=000053", 53)] + public void TestAlphaRegex(string input, int expected) + { + Processors.Alpha alpha = new Processors.Alpha(); + alpha.MatchRegexIndex(input); + int result = alpha.Processor.DynamicParameter; + + Assert.AreEqual(expected, result); + } + + /// + /// The contrast regex unit test. + /// + /// + /// The input string. + /// + /// + /// The expected result. + /// + [Test] + [TestCase("brightness=56", 56)] + [TestCase("brightness=84", 84)] + [TestCase("brightness=66", 66)] + [TestCase("brightness=101", 1)] + [TestCase("brightness=00001", 1)] + [TestCase("brightness=-50", -50)] + [TestCase("brightness=0", 0)] + public void TestBrightnesstRegex(string input, int expected) + { + Processors.Brightness brightness = new Processors.Brightness(); + brightness.MatchRegexIndex(input); + int result = brightness.Processor.DynamicParameter; + + Assert.AreEqual(expected, result); + } + + /// + /// The contrast regex unit test. + /// + /// + /// The input string. + /// + /// + /// The expected result. + /// + [Test] + [TestCase("contrast=56", 56)] + [TestCase("contrast=84", 84)] + [TestCase("contrast=66", 66)] + [TestCase("contrast=101", 1)] + [TestCase("contrast=00001", 1)] + [TestCase("contrast=-50", -50)] + [TestCase("contrast=0", 0)] + public void TestContrastRegex(string input, int expected) + { + Processors.Contrast contrast = new Processors.Contrast(); + contrast.MatchRegexIndex(input); + int result = contrast.Processor.DynamicParameter; + + Assert.AreEqual(expected, result); + } + + /// + /// The rotate regex unit test. + /// + [Test] + public void TestCropRegex() + { + const string Querystring = "crop=0,0,150,300"; + CropLayer expected = new CropLayer(0, 0, 150, 300, CropMode.Pixels); + + Processors.Crop crop = new Processors.Crop(); + crop.MatchRegexIndex(Querystring); + + CropLayer actual = crop.Processor.DynamicParameter; + Assert.AreEqual(expected, actual); + } + + /// + /// The filter regex unit test. + /// + [Test] + + public void TestFilterRegex() + { + Dictionary data = new Dictionary + { + { + "filter=lomograph", MatrixFilters.Lomograph + }, + { + "filter=polaroid", MatrixFilters.Polaroid + }, + { + "filter=comic", MatrixFilters.Comic + }, + { + "filter=greyscale", MatrixFilters.GreyScale + }, + { + "filter=blackwhite", MatrixFilters.BlackWhite + }, + { + "filter=invert", MatrixFilters.Invert + }, + { + "filter=gotham", MatrixFilters.Gotham + }, + { + "filter=hisatch", MatrixFilters.HiSatch + }, + { + "filter=losatch", MatrixFilters.LoSatch + }, + { + "filter=sepia", MatrixFilters.Sepia + } + }; + + Processors.Filter filter = new Processors.Filter(); + foreach (KeyValuePair item in data) + { + filter.MatchRegexIndex(item.Key); + IMatrixFilter result = filter.Processor.DynamicParameter; + Assert.AreEqual(item.Value, result); + } + } + + /// + /// The format regex unit test. + /// + /// + /// The input querystring. + /// + /// + /// The expected type. + /// + [Test] + [TestCase("format=bmp", typeof(BitmapFormat))] + [TestCase("format=png", typeof(PngFormat))] + [TestCase("format=png8", typeof(PngFormat))] + [TestCase("format=jpeg", typeof(JpegFormat))] + [TestCase("format=jpg", typeof(JpegFormat))] + [TestCase("format=gif", typeof(GifFormat))] + [TestCase("format=webp", typeof(WebPFormat))] + public void TestFormatRegex(string input, Type expected) + { + Processors.Format format = new Processors.Format(); + format.MatchRegexIndex(input); + Type result = format.Processor.DynamicParameter.GetType(); + + Assert.AreEqual(expected, result); + } + + /// + /// The quality regex unit test. + /// + /// + /// The input. + /// + /// + /// The expected result. + /// + [Test] + [TestCase("quality=56", 56)] + [TestCase("quality=84", 84)] + [TestCase("quality=66", 66)] + [TestCase("quality=101", 1)] + [TestCase("quality=00001", 1)] + [TestCase("quality=-50", 50)] + [TestCase("quality=0", 0)] + public void TestQualityRegex(string input, int expected) + { + Processors.Quality quality = new Processors.Quality(); + quality.MatchRegexIndex(input); + int result = quality.Processor.DynamicParameter; + + Assert.AreEqual(expected, result); + } + + /// + /// The meta regex unit test. + /// + /// + /// The input. + /// + /// + /// The expected result. + /// + [Test] + [TestCase("meta=true", true)] + [TestCase("meta=false", false)] + public void TestMetaRegex(string input, bool expected) + { + Processors.Meta meta = new Processors.Meta(); + meta.MatchRegexIndex(input); + bool result = meta.Processor.DynamicParameter; + + Assert.AreEqual(expected, result); + } + + /// + /// The resize regex unit test. + /// + [Test] + public void TestResizeRegex() + { + Dictionary data = new Dictionary + { + { + "width=300", new ResizeLayer(new Size(300, 0)) + }, + { + "height=300", new ResizeLayer(new Size(0, 300)) + }, + { + "height=300&mode=crop", new ResizeLayer(new Size(0, 300), ResizeMode.Crop) + }, + { + "width=300&mode=crop", new ResizeLayer(new Size(300, 0), ResizeMode.Crop) + }, + { + "width=600&heightratio=0.416", new ResizeLayer(new Size(600, 250)) + }, + { + "width=600&height=250&mode=max", new ResizeLayer(new Size(600, 250), ResizeMode.Max) + } + }; + + Processors.Resize resize = new Processors.Resize(); + foreach (KeyValuePair item in data) + { + resize.MatchRegexIndex(item.Key); + ResizeLayer result = resize.Processor.DynamicParameter; + Assert.AreEqual(item.Value, result); + } + } + + /// + /// The rotate regex unit test. + /// + /// + /// The input string. + /// + /// + /// The expected result. + /// + [Test] + [TestCase("rotate=0", 0)] + [TestCase("rotate=270", 270)] + [TestCase("rotate=-270", 0)] + [TestCase("rotate=angle-28", 28)] + public void TestRotateRegex(string input, int expected) + { + Processors.Rotate rotate = new Processors.Rotate(); + rotate.MatchRegexIndex(input); + + int result = rotate.Processor.DynamicParameter; + + Assert.AreEqual(expected, result); + } + + /// + /// The rounded corners regex unit test. + /// + [Test] + public void TestRoundedCornersRegex() + { + Dictionary data = new Dictionary + { + { + "roundedcorners=30", new RoundedCornerLayer(30) + }, + { + "roundedcorners=radius-26|tl-true|tr-false|bl-true|br-false", new RoundedCornerLayer(26, true, false, true, false) + }, + { + "roundedcorners=26,tl=true,tr=false,bl=true,br=false", new RoundedCornerLayer(26, true, false, true, false) + } + }; + + Processors.RoundedCorners roundedCorners = new Processors.RoundedCorners(); + foreach (KeyValuePair item in data) + { + roundedCorners.MatchRegexIndex(item.Key); + RoundedCornerLayer result = roundedCorners.Processor.DynamicParameter; + Assert.AreEqual(item.Value, result); + } + } + + /// + /// The saturation regex unit test. + /// + /// + /// The input string. + /// + /// + /// The expected result. + /// + [Test] + [TestCase("saturation=56", 56)] + [TestCase("saturation=84", 84)] + [TestCase("saturation=66", 66)] + [TestCase("saturation=101", 1)] + [TestCase("saturation=00001", 1)] + [TestCase("saturation=-50", -50)] + [TestCase("saturation=0", 0)] + public void TestSaturationRegex(string input, int expected) + { + Processors.Saturation saturation = new Processors.Saturation(); + saturation.MatchRegexIndex(input); + int result = saturation.Processor.DynamicParameter; + + Assert.AreEqual(expected, result); + } + + /// + /// The tint regex unit test. + /// + [Test] + public void TestTintRegex() + { + Dictionary data = new Dictionary + { + { + "tint=6aa6cc", ColorTranslator.FromHtml("#" + "6aa6cc") + }, + { + "tint=106,166,204,255", Color.FromArgb(255, 106, 166, 204) + }, + { + "tint=fff", Color.FromArgb(255, 255, 255, 255) + }, + { + "tint=white", Color.White + } + }; + + Processors.Tint tint = new Processors.Tint(); + foreach (KeyValuePair item in data) + { + tint.MatchRegexIndex(item.Key); + Color result = tint.Processor.DynamicParameter; + Assert.AreEqual(item.Value, result); + } + } + + /// + /// The vignette regex unit test. + /// + [Test] + public void TestVignetteRegex() + { + Dictionary data = new Dictionary + { + { + "vignette", Color.Black + }, + { + "vignette=true", Color.Black + }, + { + "vignette=6aa6cc", ColorTranslator.FromHtml("#" + "6aa6cc") + }, + { + "vignette=106,166,204,255", Color.FromArgb(255, 106, 166, 204) + }, + { + "vignette=fff", Color.FromArgb(255, 255, 255, 255) + }, + { + "vignette=white", Color.White + } + }; + + Processors.Vignette vignette = new Processors.Vignette(); + foreach (KeyValuePair item in data) + { + vignette.MatchRegexIndex(item.Key); + Color result = vignette.Processor.DynamicParameter; + Assert.AreEqual(item.Value, result); + } + } + + /// + /// The watermark regex unit test. + /// + [Test] + public void TestWaterMarkRegex() + { + Dictionary data = new Dictionary + { + { + "watermark=text-watermark goodness,color-fff,size-36,style-italic,opacity-80,position-30,150,shadow-true,font-arial", + new TextLayer + { + Text = "watermark goodness", + FontColor = ColorTranslator.FromHtml("#" + "ffffff"), + FontSize = 36, + Style = FontStyle.Italic, + Opacity = 80, + Position = new Point(30, 150), + DropShadow = true, + FontFamily = new FontFamily("arial") + } + }, + { + "watermark=watermark goodness&color=fff&fontsize=36&fontstyle=italic&fontopacity=80&textposition=30,150&textshadow=true&fontfamily=arial", + new TextLayer + { + Text = "watermark goodness", + FontColor = ColorTranslator.FromHtml("#" + "ffffff"), + FontSize = 36, + Style = FontStyle.Italic, + Opacity = 80, + Position = new Point(30, 150), + DropShadow = true, + FontFamily = new FontFamily("arial") + } + } + }; + + Processors.Watermark watermark = new Processors.Watermark(); + foreach (KeyValuePair item in data) + { + watermark.MatchRegexIndex(item.Key); + TextLayer result = watermark.Processor.DynamicParameter; + Assert.AreEqual(item.Value, result); + } + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web.UnitTests/packages.config b/src/ImageProcessor.Web.UnitTests/packages.config new file mode 100644 index 000000000..139d5138c --- /dev/null +++ b/src/ImageProcessor.Web.UnitTests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/Caching/CacheIndexer.cs b/src/ImageProcessor.Web/Caching/CacheIndexer.cs similarity index 70% rename from src/ImageProcessor.Web/NET45/Caching/CacheIndexer.cs rename to src/ImageProcessor.Web/Caching/CacheIndexer.cs index cd40c9439..e69e65c59 100644 --- a/src/ImageProcessor.Web/NET45/Caching/CacheIndexer.cs +++ b/src/ImageProcessor.Web/Caching/CacheIndexer.cs @@ -10,13 +10,9 @@ namespace ImageProcessor.Web.Caching { - #region Using using System.Collections.Generic; using System.IO; using System.Runtime.Caching; - using System.Threading.Tasks; - using ImageProcessor.Web.Helpers; - #endregion /// /// Represents an in memory collection of keys and values whose operations are concurrent. @@ -34,19 +30,32 @@ namespace ImageProcessor.Web.Caching /// The matching the given key if the contains an element with /// the specified key; otherwise, null. /// - public static async Task GetValueAsync(string cachedPath) + public static CachedImage GetValue(string cachedPath) { string key = Path.GetFileNameWithoutExtension(cachedPath); CachedImage cachedImage = (CachedImage)MemCache.GetItem(key); if (cachedImage == null) { - cachedImage = await TaskHelpers.Run(() => GetCachedImage(cachedPath)); + // FileInfo is thread safe. + FileInfo fileInfo = new FileInfo(cachedPath); - if (cachedImage != null) + if (!fileInfo.Exists) { - Add(cachedImage); + return null; } + + // Pull the latest info. + fileInfo.Refresh(); + + cachedImage = new CachedImage + { + Key = Path.GetFileNameWithoutExtension(cachedPath), + Path = cachedPath, + CreationTimeUtc = fileInfo.CreationTimeUtc + }; + + Add(cachedImage); } return cachedImage; @@ -87,35 +96,5 @@ namespace ImageProcessor.Web.Caching return cachedImage; } #endregion - - /// - /// Creates a new cached image from the cache instance on disk. - /// - /// - /// The cache path. - /// - /// - /// The from the cache instance on disk. - /// - private static CachedImage GetCachedImage(string cachePath) - { - // FileInfo is thread safe. - FileInfo fileInfo = new FileInfo(cachePath); - - if (!fileInfo.Exists) - { - return null; - } - - // Pull the latest info. - fileInfo.Refresh(); - - return new CachedImage - { - Key = Path.GetFileNameWithoutExtension(cachePath), - Path = cachePath, - CreationTimeUtc = fileInfo.CreationTimeUtc - }; - } } } \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/Caching/CachedImage.cs b/src/ImageProcessor.Web/Caching/CachedImage.cs similarity index 97% rename from src/ImageProcessor.Web/NET45/Caching/CachedImage.cs rename to src/ImageProcessor.Web/Caching/CachedImage.cs index f775ac1c8..511c2b318 100644 --- a/src/ImageProcessor.Web/NET45/Caching/CachedImage.cs +++ b/src/ImageProcessor.Web/Caching/CachedImage.cs @@ -10,9 +10,7 @@ namespace ImageProcessor.Web.Caching { - #region Using using System; - #endregion /// /// Describes a cached image diff --git a/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs b/src/ImageProcessor.Web/Caching/DiskCache.cs similarity index 66% rename from src/ImageProcessor.Web/NET45/Caching/DiskCache.cs rename to src/ImageProcessor.Web/Caching/DiskCache.cs index c046cfd8a..c21d52b6a 100644 --- a/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs +++ b/src/ImageProcessor.Web/Caching/DiskCache.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. @@ -13,15 +13,12 @@ namespace ImageProcessor.Web.Caching #region Using using System; using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; - using System.Threading.Tasks; - using System.Web; using System.Web.Hosting; - using ImageProcessor.Extensions; - using ImageProcessor.Web.Config; + + using ImageProcessor.Web.Configuration; using ImageProcessor.Web.Extensions; using ImageProcessor.Web.Helpers; #endregion @@ -35,29 +32,29 @@ namespace ImageProcessor.Web.Caching /// /// The maximum number of days to cache files on the system for. /// - internal static readonly int MaxFileCachedDuration = ImageProcessorConfig.Instance.MaxCacheDays; + internal static readonly int MaxFileCachedDuration = ImageProcessorConfiguration.Instance.MaxCacheDays; /// /// The maximum number of files allowed in the directory. /// /// - /// NTFS directories can handle up to 10,000 files in the directory before slowing down. + /// NTFS directories can handle up to 10,000 files in the directory before slowing down. /// This will help us to ensure that don't go over that limit. - /// - /// - /// + /// + /// + /// /// private const int MaxFilesCount = 100; /// /// The virtual cache path. /// - private static readonly string VirtualCachePath = ImageProcessorConfig.Instance.VirtualCachePath; + private static readonly string VirtualCachePath = ImageProcessorConfiguration.Instance.VirtualCachePath; /// /// The absolute path to virtual cache path on the server. /// - private static readonly string AbsoluteCachePath = HostingEnvironment.MapPath(ImageProcessorConfig.Instance.VirtualCachePath); + private static readonly string AbsoluteCachePath = HostingEnvironment.MapPath(ImageProcessorConfiguration.Instance.VirtualCachePath); /// /// The request path for the image. @@ -74,11 +71,6 @@ namespace ImageProcessor.Web.Caching /// private readonly string imageName; - /// - /// Whether the request is for a remote image. - /// - private readonly bool isRemote; - /// /// The physical cached path. /// @@ -103,22 +95,17 @@ namespace ImageProcessor.Web.Caching /// /// The image name. /// - /// - /// Whether the request is for a remote image. - /// - public DiskCache(string requestPath, string fullPath, string imageName, bool isRemote) + public DiskCache(string requestPath, string fullPath, string imageName) { this.requestPath = requestPath; this.fullPath = fullPath; this.imageName = imageName; - this.isRemote = isRemote; // Get the physical and virtual paths. this.GetCachePaths(); } #endregion - #region Properties /// /// Gets the cached path. /// @@ -140,20 +127,73 @@ namespace ImageProcessor.Web.Caching return this.virtualCachedPath; } } - #endregion #region Methods - #region Internal + #region Public + /// + /// Trims a cached folder ensuring that it does not exceed the maximum file count. + /// + /// + /// The path to the folder. + /// + public static void TrimCachedFolders(string path) + { + string directory = Path.GetDirectoryName(path); + + if (directory != null) + { + DirectoryInfo directoryInfo = new DirectoryInfo(directory); + DirectoryInfo parentDirectoryInfo = directoryInfo.Parent; + + if (parentDirectoryInfo != null) + { + // UNC folders can throw exceptions if the file doesn't exist. + foreach (DirectoryInfo enumerateDirectory in parentDirectoryInfo.SafeEnumerateDirectories()) + { + IEnumerable files = enumerateDirectory.EnumerateFiles().OrderBy(f => f.CreationTimeUtc); + int count = files.Count(); + + foreach (FileInfo fileInfo in files) + { + 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 (!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. + } + } + } + } + } + } + /// /// Adds an image to the cache. /// - internal void AddImageToCache() + /// + /// The path to the cached image. + /// + public void AddImageToCache(string cachedPath) { - string key = Path.GetFileNameWithoutExtension(this.CachedPath); + string key = Path.GetFileNameWithoutExtension(cachedPath); CachedImage cachedImage = new CachedImage { Key = key, - Path = this.CachedPath, + Path = cachedPath, CreationTimeUtc = DateTime.UtcNow }; @@ -163,119 +203,58 @@ namespace ImageProcessor.Web.Caching /// /// Returns a value indicating whether the original file is new or has been updated. /// + /// + /// The path to the cached image. + /// /// /// True if the the original file is new or has been updated; otherwise, false. /// - internal async Task IsNewOrUpdatedFileAsync() + public bool IsNewOrUpdatedFile(string cachedPath) { - string path = this.CachedPath; bool isUpdated = false; - CachedImage cachedImage; + CachedImage cachedImage = CacheIndexer.GetValue(cachedPath); - if (this.isRemote) + if (cachedImage == null) { - cachedImage = await CacheIndexer.GetValueAsync(path); - - if (cachedImage != null) - { - // Can't check the last write time so check to see if the cached image is set to expire - // or if the max age is different. - if (this.IsExpired(cachedImage.CreationTimeUtc)) - { - CacheIndexer.Remove(path); - isUpdated = true; - } - } - else - { - // Nothing in the cache so we should return true. - isUpdated = true; - } + // Nothing in the cache so we should return true. + isUpdated = true; } else { - // Test now for locally requested files. - cachedImage = await CacheIndexer.GetValueAsync(path); - - if (cachedImage == null) + // Check to see if the cached image is set to expire. + if (IsExpired(cachedImage.CreationTimeUtc)) { - // Nothing in the cache so we should return true. + CacheIndexer.Remove(cachedPath); isUpdated = true; } } return isUpdated; } - - /// - /// Trims a cached folder ensuring that it does not exceed the maximum file count. - /// - /// - /// The path to the folder. - /// - /// - /// The . - /// - internal async Task TrimCachedFolderAsync(string path) - { - await TaskHelpers.Run(() => this.TrimCachedFolders(path)); - } #endregion #region Private /// - /// Trims a cached folder ensuring that it does not exceed the maximum file count. + /// Gets a value indicating whether the given images creation date is out with + /// the prescribed limit. /// - /// - /// The path to the folder. + /// + /// The creation date. /// - private void TrimCachedFolders(string path) + /// + /// The true if the date is out with the limit, otherwise; false. + /// + private static bool IsExpired(DateTime creationDate) { - string directory = Path.GetDirectoryName(path); - if (directory != null) - { - DirectoryInfo directoryInfo = new DirectoryInfo(directory); - DirectoryInfo parentDirectoryInfo = directoryInfo.Parent; - - foreach (DirectoryInfo enumerateDirectory in parentDirectoryInfo.SafeEnumerateDirectories()) - { - IEnumerable files = enumerateDirectory.EnumerateFiles().OrderBy(f => f.CreationTimeUtc); - int count = files.Count(); - - foreach (FileInfo fileInfo in files) - { - 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. - } - } - } - } + return creationDate.AddDays(MaxFileCachedDuration) < DateTime.UtcNow.AddDays(-MaxFileCachedDuration); } /// - /// Gets the full transformed cached path for the image. - /// The images are stored in paths that are based upon the sha1 of their full request path + /// Gets the full transformed cached paths for the image. + /// The images are stored in paths that are based upon the SHA1 of their full request path /// taking the individual characters of the hash to determine their location. /// This allows us to store millions of images. /// - [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")] private void GetCachePaths() { string streamHash = string.Empty; @@ -286,7 +265,7 @@ namespace ImageProcessor.Web.Caching { if (new Uri(this.requestPath).IsFile) { - // Get the hash for the filestream. That way we can ensure that if the image is + // Get the hash for the filestream. That way we can ensure that if the image is // updated but has the same name we will know. FileInfo imageFileInfo = new FileInfo(this.requestPath); if (imageFileInfo.Exists) @@ -306,8 +285,8 @@ namespace ImageProcessor.Web.Caching streamHash = string.Empty; } - // Use an sha1 hash of the full path including the querystring to create the image name. - // That name can also be used as a key for the cached image and we should be able to use + // Use an sha1 hash of the full path including the querystring to create the image name. + // That name can also be used as a key for the cached image and we should be able to use // The characters of that hash as sub-folders. string parsedExtension = ImageHelpers.GetExtension(this.fullPath); string fallbackExtension = this.imageName.Substring(this.imageName.LastIndexOf(".", StringComparison.Ordinal) + 1); @@ -326,22 +305,7 @@ namespace ImageProcessor.Web.Caching this.virtualCachedPath = Path.Combine(VirtualCachePath, virtualPathFromKey, cachedFileName).Replace(@"\", "/"); } } - - /// - /// Gets a value indicating whether the given images creation date is out with - /// the prescribed limit. - /// - /// - /// The creation date. - /// - /// - /// The true if the date is out with the limit, otherwise; false. - /// - private bool IsExpired(DateTime creationDate) - { - return creationDate.AddDays(MaxFileCachedDuration) < DateTime.UtcNow.AddDays(-MaxFileCachedDuration); - } #endregion #endregion } -} \ No newline at end of file +} diff --git a/src/ImageProcessor.Web/NET45/Caching/MemCache.cs b/src/ImageProcessor.Web/Caching/MemCache.cs similarity index 100% rename from src/ImageProcessor.Web/NET45/Caching/MemCache.cs rename to src/ImageProcessor.Web/Caching/MemCache.cs diff --git a/src/ImageProcessor.Web/NET45/Config/ImageCacheSection.cs b/src/ImageProcessor.Web/Configuration/ImageCacheSection.cs similarity index 94% rename from src/ImageProcessor.Web/NET45/Config/ImageCacheSection.cs rename to src/ImageProcessor.Web/Configuration/ImageCacheSection.cs index 6bda16a44..1f868fc04 100644 --- a/src/ImageProcessor.Web/NET45/Config/ImageCacheSection.cs +++ b/src/ImageProcessor.Web/Configuration/ImageCacheSection.cs @@ -8,18 +8,15 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Web.Config +namespace ImageProcessor.Web.Configuration { - #region Using using System.Configuration; using System.IO; using System.Xml; - using ImageProcessor.Extensions; + using ImageProcessor.Web.Extensions; using ImageProcessor.Web.Helpers; - #endregion - /// /// Represents an image cache section within a configuration file. /// @@ -79,7 +76,7 @@ namespace ImageProcessor.Web.Config return imageCacheSection; } - string section = ResourceHelpers.ResourceAsString("ImageProcessor.Web.Config.Resources.cache.config"); + string section = ResourceHelpers.ResourceAsString("ImageProcessor.Web.Configuration.Resources.cache.config"); XmlReader reader = new XmlTextReader(new StringReader(section)); imageCacheSection = new ImageCacheSection(); imageCacheSection.DeserializeSection(reader); diff --git a/src/ImageProcessor.Web/NET45/Config/ImageProcessingSection.cs b/src/ImageProcessor.Web/Configuration/ImageProcessingSection.cs similarity index 98% rename from src/ImageProcessor.Web/NET45/Config/ImageProcessingSection.cs rename to src/ImageProcessor.Web/Configuration/ImageProcessingSection.cs index d1018ba89..23f8bc9ca 100644 --- a/src/ImageProcessor.Web/NET45/Config/ImageProcessingSection.cs +++ b/src/ImageProcessor.Web/Configuration/ImageProcessingSection.cs @@ -5,11 +5,11 @@ // // // Represents an image processing section within a configuration file. -// Nested syntax adapted from +// Nested syntax adapted from // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Web.Config +namespace ImageProcessor.Web.Configuration { #region Using using System.Configuration; @@ -21,7 +21,7 @@ namespace ImageProcessor.Web.Config /// /// Represents an image processing section within a configuration file. - /// Nested syntax adapted from + /// Nested syntax adapted from /// public sealed class ImageProcessingSection : ConfigurationSection { @@ -83,7 +83,7 @@ namespace ImageProcessor.Web.Config return imageProcessingSection; } - string section = ResourceHelpers.ResourceAsString("ImageProcessor.Web.Config.Resources.processing.config"); + string section = ResourceHelpers.ResourceAsString("ImageProcessor.Web.Configuration.Resources.processing.config"); XmlReader reader = new XmlTextReader(new StringReader(section)); imageProcessingSection = new ImageProcessingSection(); imageProcessingSection.DeserializeSection(reader); diff --git a/src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs b/src/ImageProcessor.Web/Configuration/ImageProcessorConfiguration.cs similarity index 87% rename from src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs rename to src/ImageProcessor.Web/Configuration/ImageProcessorConfiguration.cs index c85c25039..a9684c9c5 100644 --- a/src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs +++ b/src/ImageProcessor.Web/Configuration/ImageProcessorConfiguration.cs @@ -1,38 +1,39 @@ // -------------------------------------------------------------------------------------------------------------------- -// +// // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. // // // Encapsulates methods to allow the retrieval of ImageProcessor settings. -// +// // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Web.Config +namespace ImageProcessor.Web.Configuration { - #region Using using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web.Compilation; + + using ImageProcessor.Common.Extensions; using ImageProcessor.Processors; - #endregion + using ImageProcessor.Web.Processors; /// /// Encapsulates methods to allow the retrieval of ImageProcessor settings. - /// + /// /// - public sealed class ImageProcessorConfig + public sealed class ImageProcessorConfiguration { #region Fields /// /// A new instance Initializes a new instance of the class. /// with lazy initialization. /// - private static readonly Lazy Lazy = - new Lazy(() => new ImageProcessorConfig()); + private static readonly Lazy Lazy = + new Lazy(() => new ImageProcessorConfiguration()); /// /// A collection of the elements @@ -64,10 +65,11 @@ namespace ImageProcessor.Web.Config #endregion #region Constructors + /// - /// Prevents a default instance of the class from being created. + /// Prevents a default instance of the class from being created. /// - private ImageProcessorConfig() + private ImageProcessorConfiguration() { this.LoadGraphicsProcessors(); } @@ -75,9 +77,9 @@ namespace ImageProcessor.Web.Config #region Properties /// - /// Gets the current instance of the class. + /// Gets the current instance of the class. /// - public static ImageProcessorConfig Instance + public static ImageProcessorConfiguration Instance { get { @@ -88,7 +90,7 @@ namespace ImageProcessor.Web.Config /// /// Gets the list of available GraphicsProcessors. /// - public IList GraphicsProcessors { get; private set; } + public IList GraphicsProcessors { get; private set; } /// /// Gets a value indicating whether to preserve exif meta data. @@ -292,23 +294,23 @@ namespace ImageProcessor.Web.Config { if (GetImageProcessingSection().Plugins.AutoLoadPlugins) { - Type type = typeof(IGraphicsProcessor); + Type type = typeof(IWebGraphicsProcessor); try { // Build a list of native IGraphicsProcessor instances. List availableTypes = BuildManager.GetReferencedAssemblies() .Cast() - .SelectMany(s => s.GetTypes()) - .Where(t => t != null && type.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract) + .SelectMany(s => s.GetLoadableTypes()) + .Where(t => type.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract) .ToList(); // Create them and add. - this.GraphicsProcessors = availableTypes.Select(x => (Activator.CreateInstance(x) as IGraphicsProcessor)).ToList(); + this.GraphicsProcessors = availableTypes.Select(x => (Activator.CreateInstance(x) as IWebGraphicsProcessor)).ToList(); // Add the available settings. - foreach (IGraphicsProcessor processor in this.GraphicsProcessors) + foreach (IWebGraphicsProcessor webProcessor in this.GraphicsProcessors) { - processor.Settings = this.GetPluginSettings(processor.GetType().Name); + webProcessor.Processor.Settings = this.GetPluginSettings(webProcessor.GetType().Name); } } catch (ReflectionTypeLoadException) @@ -332,25 +334,25 @@ namespace ImageProcessor.Web.Config private void LoadGraphicsProcessorsFromConfiguration() { ImageProcessingSection.PluginElementCollection pluginConfigs = imageProcessingSection.Plugins; - this.GraphicsProcessors = new List(); + this.GraphicsProcessors = new List(); foreach (ImageProcessingSection.PluginElement pluginConfig in pluginConfigs) { Type type = Type.GetType(pluginConfig.Type); if (type == null) { - throw new TypeLoadException("Couldn't load IGraphicsProcessor: " + pluginConfig.Type); + throw new TypeLoadException("Couldn't load IWebGraphicsProcessor: " + pluginConfig.Type); } - this.GraphicsProcessors.Add(Activator.CreateInstance(type) as IGraphicsProcessor); + this.GraphicsProcessors.Add(Activator.CreateInstance(type) as IWebGraphicsProcessor); } // Add the available settings. - foreach (IGraphicsProcessor processor in this.GraphicsProcessors) + foreach (IWebGraphicsProcessor webProcessor in this.GraphicsProcessors) { - processor.Settings = this.GetPluginSettings(processor.GetType().Name); + webProcessor.Processor.Settings = this.GetPluginSettings(webProcessor.GetType().Name); } } #endregion } -} +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs b/src/ImageProcessor.Web/Configuration/ImageSecuritySection.cs similarity index 98% rename from src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs rename to src/ImageProcessor.Web/Configuration/ImageSecuritySection.cs index 824cf8277..c58b07579 100644 --- a/src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs +++ b/src/ImageProcessor.Web/Configuration/ImageSecuritySection.cs @@ -8,7 +8,7 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Web.Config +namespace ImageProcessor.Web.Configuration { #region Using using System; @@ -116,7 +116,7 @@ namespace ImageProcessor.Web.Config return imageSecuritySection; } - string section = ResourceHelpers.ResourceAsString("ImageProcessor.Web.Config.Resources.security.config"); + string section = ResourceHelpers.ResourceAsString("ImageProcessor.Web.Configuration.Resources.security.config"); XmlReader reader = new XmlTextReader(new StringReader(section)); imageSecuritySection = new ImageSecuritySection(); imageSecuritySection.DeserializeSection(reader); diff --git a/src/ImageProcessor.Web/Configuration/Resources/cache.config b/src/ImageProcessor.Web/Configuration/Resources/cache.config new file mode 100644 index 000000000..c9b64a68a --- /dev/null +++ b/src/ImageProcessor.Web/Configuration/Resources/cache.config @@ -0,0 +1 @@ + diff --git a/src/ImageProcessor.Web/Configuration/Resources/processing.config b/src/ImageProcessor.Web/Configuration/Resources/processing.config new file mode 100644 index 000000000..ce00ddffa --- /dev/null +++ b/src/ImageProcessor.Web/Configuration/Resources/processing.config @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/Config/Resources/security.config b/src/ImageProcessor.Web/Configuration/Resources/security.config similarity index 100% rename from src/ImageProcessor.Web/NET45/Config/Resources/security.config rename to src/ImageProcessor.Web/Configuration/Resources/security.config diff --git a/src/ImageProcessor.Web/NET45/Extensions/DirectoryInfoExtensions.cs b/src/ImageProcessor.Web/Extensions/DirectoryInfoExtensions.cs similarity index 99% rename from src/ImageProcessor.Web/NET45/Extensions/DirectoryInfoExtensions.cs rename to src/ImageProcessor.Web/Extensions/DirectoryInfoExtensions.cs index 07c47e522..2ec477257 100644 --- a/src/ImageProcessor.Web/NET45/Extensions/DirectoryInfoExtensions.cs +++ b/src/ImageProcessor.Web/Extensions/DirectoryInfoExtensions.cs @@ -53,4 +53,4 @@ namespace ImageProcessor.Web.Extensions return directories; } } -} \ No newline at end of file +} diff --git a/src/ImageProcessor/Extensions/StringExtensions.cs b/src/ImageProcessor.Web/Extensions/StringExtensions.cs similarity index 74% rename from src/ImageProcessor/Extensions/StringExtensions.cs rename to src/ImageProcessor.Web/Extensions/StringExtensions.cs index 318146a9b..5ec1fdf4b 100644 --- a/src/ImageProcessor/Extensions/StringExtensions.cs +++ b/src/ImageProcessor.Web/Extensions/StringExtensions.cs @@ -8,16 +8,14 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Extensions +namespace ImageProcessor.Web.Extensions { - #region Using using System; using System.Globalization; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; - #endregion /// /// Encapsulates a series of time saving extension methods to the class. @@ -66,50 +64,8 @@ namespace ImageProcessor.Extensions .ToString().ToLowerInvariant(); } } - - /// - /// Creates an SHA256 fingerprint of the String. - /// - /// The String instance that this method extends. - /// An SHA256 fingerprint of the String. - public static string ToSHA256Fingerprint(this string expression) - { - byte[] bytes = Encoding.ASCII.GetBytes(expression.ToCharArray()); - - using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider()) - { - byte[] hash = sha256.ComputeHash(bytes); - - // Concatenate the hash bytes into one long String. - return hash.Aggregate( - new StringBuilder(64), - (sb, b) => sb.Append(b.ToString("X2", CultureInfo.InvariantCulture))) - .ToString().ToLowerInvariant(); - } - } - - /// - /// Creates an SHA512 fingerprint of the String. - /// - /// The String instance that this method extends. - /// An SHA256 fingerprint of the String. - public static string ToSHA512Fingerprint(this string expression) - { - byte[] bytes = Encoding.ASCII.GetBytes(expression.ToCharArray()); - - using (SHA512CryptoServiceProvider sha512 = new SHA512CryptoServiceProvider()) - { - byte[] hash = sha512.ComputeHash(bytes); - - // Concatenate the hash bytes into one long String. - return hash.Aggregate( - new StringBuilder(70), - (sb, b) => sb.Append(b.ToString("X2", CultureInfo.InvariantCulture))) - .ToString().ToLowerInvariant(); - } - } #endregion - + #region Numbers /// /// Creates an array of integers scraped from the String. diff --git a/src/ImageProcessor.Web/Helpers/AsyncDuplicateLock.cs b/src/ImageProcessor.Web/Helpers/AsyncDuplicateLock.cs new file mode 100644 index 000000000..47f14c81c --- /dev/null +++ b/src/ImageProcessor.Web/Helpers/AsyncDuplicateLock.cs @@ -0,0 +1,134 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Throttles duplicate requests. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace ImageProcessor.Web.Helpers +{ + using System; + using System.Collections.Concurrent; + using System.Threading; + using System.Threading.Tasks; + + /// + /// Throttles duplicate requests. + /// Based loosely on + /// + public sealed class AsyncDuplicateLock + { + /// + /// The collection of semaphore slims. + /// + private static readonly ConcurrentDictionary SemaphoreSlims + = new ConcurrentDictionary(); + + /// + /// Locks against the given key. + /// + /// + /// The key that identifies the current object. + /// + /// + /// The disposable . + /// + public IDisposable Lock(object key) + { + DisposableScope releaser = new DisposableScope( + key, + s => + { + SemaphoreSlim locker; + if (SemaphoreSlims.TryRemove(s, out locker)) + { + locker.Release(); + locker.Dispose(); + } + }); + + SemaphoreSlim semaphore = SemaphoreSlims.GetOrAdd(key, new SemaphoreSlim(1, 1)); + semaphore.Wait(); + return releaser; + } + + /// + /// Asynchronously locks against the given key. + /// + /// + /// The key that identifies the current object. + /// + /// + /// The disposable . + /// + public Task LockAsync(object key) + { + DisposableScope releaser = new DisposableScope( + key, + s => + { + SemaphoreSlim locker; + if (SemaphoreSlims.TryRemove(s, out locker)) + { + locker.Release(); + locker.Dispose(); + } + }); + + Task releaserTask = Task.FromResult(releaser as IDisposable); + SemaphoreSlim semaphore = SemaphoreSlims.GetOrAdd(key, new SemaphoreSlim(1, 1)); + + Task waitTask = semaphore.WaitAsync(); + + return waitTask.IsCompleted + ? releaserTask + : waitTask.ContinueWith( + (_, r) => (IDisposable)r, + releaser, + CancellationToken.None, + TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + } + + /// + /// The disposable scope. + /// + private sealed class DisposableScope : IDisposable + { + /// + /// The key + /// + private readonly object key; + + /// + /// The close scope action. + /// + private readonly Action closeScopeAction; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The key. + /// + /// + /// The close scope action. + /// + public DisposableScope(object key, Action closeScopeAction) + { + this.key = key; + this.closeScopeAction = closeScopeAction; + } + + /// + /// The dispose. + /// + public void Dispose() + { + this.closeScopeAction(this.key); + } + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Helpers/CommonParameterParserUtility.cs b/src/ImageProcessor.Web/Helpers/CommonParameterParserUtility.cs new file mode 100644 index 000000000..3e8362d08 --- /dev/null +++ b/src/ImageProcessor.Web/Helpers/CommonParameterParserUtility.cs @@ -0,0 +1,268 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to correctly parse querystring parameters. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Helpers +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Globalization; + using System.Text; + using System.Text.RegularExpressions; + + using ImageProcessor.Common.Extensions; + using ImageProcessor.Imaging; + using ImageProcessor.Web.Extensions; + + /// + /// Encapsulates methods to correctly parse querystring parameters. + /// + public static class CommonParameterParserUtility + { + /// + /// The collection of known colors. + /// + private static readonly Dictionary KnownColors = new Dictionary(); + + /// + /// The regular expression to search strings for colors. + /// + private static readonly Regex ColorRegex = BuildColorRegex(); + + /// + /// The regular expression to search strings for angles. + /// + private static readonly Regex AngleRegex = new Regex(@"(rotate|angle)(=|-)(?:3[0-5][0-9]|[12][0-9]{2}|[1-9][0-9]?)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for values between 1 and 100. + /// + private static readonly Regex In100RangeRegex = new Regex(@"(-?(0*(?:[1-9][0-9]?|100)))", RegexOptions.Compiled); + + /// + /// The sharpen regex. + /// + private static readonly Regex BlurSharpenRegex = new Regex(@"(blur|sharpen)=\d+", RegexOptions.Compiled); + + /// + /// The sigma regex. + /// + private static readonly Regex SigmaRegex = new Regex(@"sigma(=|-)\d+(.?\d+)?", RegexOptions.Compiled); + + /// + /// The threshold regex. + /// + private static readonly Regex ThresholdRegex = new Regex(@"threshold(=|-)\d+", RegexOptions.Compiled); + + /// + /// Returns the correct containing the angle for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct containing the angle for the given string. + /// + public static int ParseAngle(string input) + { + foreach (Match match in AngleRegex.Matches(input)) + { + // Split on angle + int angle; + string value = match.Value.Split(new[] { '=', '-' })[1]; + int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out angle); + return angle; + } + + // No rotate - matches the RotateLayer default. + return 0; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct + /// + public static Color ParseColor(string input) + { + foreach (Match match in ColorRegex.Matches(input)) + { + string value = match.Value.Split(new[] { '=', '-' })[1]; + + if (KnownColors.ContainsKey(value)) + { + return Color.FromKnownColor(KnownColors[value]); + } + + if (value.Contains(",")) + { + int[] split = value.ToPositiveIntegerArray(); + byte red = split[0].ToByte(); + byte green = split[1].ToByte(); + byte blue = split[2].ToByte(); + byte alpha = split[3].ToByte(); + + return Color.FromArgb(alpha, red, green, blue); + } + + // Split on color-hex + return ColorTranslator.FromHtml("#" + value); + } + + return Color.Transparent; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct between -100 and 100. + /// + public static int ParseIn100Range(string input) + { + int value = 0; + foreach (Match match in In100RangeRegex.Matches(input)) + { + value = int.Parse(match.Value, CultureInfo.InvariantCulture); + } + + return value; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The maximum size to set the Gaussian kernel to. + /// + /// + /// The maximum Sigma value (standard deviation) for Gaussian function used to calculate the kernel. + /// + /// + /// The maximum threshold value, which is added to each weighted sum of pixels. + /// + /// + /// The correct . + /// + public static GaussianLayer ParseGaussianLayer(string input, int maxSize, double maxSigma, int maxThreshold) + { + int size = ParseBlurSharpen(input); + double sigma = ParseSigma(input); + int threshold = ParseThreshold(input); + + size = maxSize < size ? maxSize : size; + sigma = maxSigma < sigma ? maxSigma : sigma; + threshold = maxThreshold < threshold ? maxThreshold : threshold; + + return new GaussianLayer(size, sigma, threshold); + } + + /// + /// Returns the correct containing the blur value + /// for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct for the given string. + /// + private static int ParseBlurSharpen(string input) + { + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (Match match in BlurSharpenRegex.Matches(input)) + { + return Convert.ToInt32(match.Value.Split('=')[1]); + } + + return 0; + } + + /// + /// Returns the correct containing the sigma value + /// for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct for the given string. + /// + private static double ParseSigma(string input) + { + foreach (Match match in SigmaRegex.Matches(input)) + { + // split on text- + return Convert.ToDouble(match.Value.Split(new[] { '=', '-' })[1]); + } + + return 1.4d; + } + + /// + /// Returns the correct containing the threshold value + /// for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct for the given string. + /// + private static int ParseThreshold(string input) + { + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (Match match in ThresholdRegex.Matches(input)) + { + return Convert.ToInt32(match.Value.Split(new[] { '=', '-' })[1]); + } + + return 0; + } + + /// + /// Builds a regular expression for the three main colour types. + /// + /// + /// The to match colors. + /// + private static Regex BuildColorRegex() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(@"(bgcolor|color|tint|vignette)(=|-)(\d+,\d+,\d+,\d+|([0-9a-fA-F]{3}){1,2}|("); + + KnownColor[] knownColors = (KnownColor[])Enum.GetValues(typeof(KnownColor)); + + for (int i = 0; i < knownColors.Length; i++) + { + KnownColor knownColor = knownColors[i]; + string name = knownColor.ToString().ToLowerInvariant(); + + KnownColors.Add(name, knownColor); + + stringBuilder.Append(i > 0 ? "|" + name : name); + } + + stringBuilder.Append("))"); + + return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase); + } + } +} diff --git a/src/ImageProcessor.Web/Helpers/ImageHelpers.cs b/src/ImageProcessor.Web/Helpers/ImageHelpers.cs new file mode 100644 index 000000000..e52f5aa3b --- /dev/null +++ b/src/ImageProcessor.Web/Helpers/ImageHelpers.cs @@ -0,0 +1,133 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The image helpers. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Helpers +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Text.RegularExpressions; + using ImageProcessor.Configuration; + using ImageProcessor.Imaging.Formats; + + /// + /// The image helpers. + /// + public static class ImageHelpers + { + /// + /// The regex pattern. + /// + private static readonly string ExtensionRegexPattern = BuildExtensionRegexPattern(); + + /// + /// The image format regex. + /// + private static readonly Regex FormatRegex = new Regex(@"(\.?)(png8|" + ExtensionRegexPattern + ")", RegexOptions.IgnoreCase | RegexOptions.RightToLeft); + + /// + /// The image format regex for matching the file format at the end of a string. + /// + private static readonly Regex EndFormatRegex = new Regex(@"(\.)" + ExtensionRegexPattern + "$", RegexOptions.IgnoreCase | RegexOptions.RightToLeft); + + /// + /// Checks a given string to check whether the value contains a valid image extension. + /// + /// The string containing the filename to check. + /// True the value contains a valid image extension, otherwise false. + public static bool IsValidImageExtension(string fileName) + { + return EndFormatRegex.IsMatch(fileName); + } + + /// + /// Returns the correct file extension for the given string input + /// + /// + /// The string to parse. + /// + /// + /// The correct file extension for the given string input if it can find one; otherwise an empty string. + /// + public static string GetExtension(string input) + { + Match match = FormatRegex.Match(input); + + if (match.Success) + { + // Ah the enigma that is the png file. + if (match.Value.ToLowerInvariant().EndsWith("png8")) + { + return "png"; + } + + return match.Value; + } + + return string.Empty; + } + + /// + /// Get the correct mime-type for the given string input. + /// + /// + /// The identifier. + /// + /// + /// The matching the correct mime-type. + /// + public static string GetMimeType(string identifier) + { + identifier = GetExtension(identifier).Replace(".", string.Empty); + List formats = ImageProcessorBootstrapper.Instance.SupportedImageFormats.ToList(); + ISupportedImageFormat format = formats.FirstOrDefault(f => f.FileExtensions.Any(e => e.Equals(identifier, StringComparison.InvariantCultureIgnoreCase))); + + if (format != null) + { + return format.MimeType; + } + + return string.Empty; + } + + /// + /// Builds a regular expression from the type, this allows extensibility. + /// + /// + /// The to match matrix filters. + /// + private static string BuildExtensionRegexPattern() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append("("); + int counter = 0; + foreach (ISupportedImageFormat imageFormat in ImageProcessorBootstrapper.Instance.SupportedImageFormats) + { + foreach (string fileExtension in imageFormat.FileExtensions) + { + if (counter == 0) + { + stringBuilder.Append(fileExtension.ToLowerInvariant()); + } + else + { + stringBuilder.AppendFormat("|{0}", fileExtension.ToLowerInvariant()); + } + } + + counter++; + } + + stringBuilder.Append(")"); + return stringBuilder.ToString(); + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Helpers/NativeMethods.cs b/src/ImageProcessor.Web/Helpers/NativeMethods.cs new file mode 100644 index 000000000..9e983438c --- /dev/null +++ b/src/ImageProcessor.Web/Helpers/NativeMethods.cs @@ -0,0 +1,44 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides access to unmanaged native methods. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Helpers +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Provides access to unmanaged native methods. + /// + internal class NativeMethods + { + /// + /// Loads the specified module into the address space of the calling process. + /// The specified module may cause other modules to be loaded. + /// + /// + /// The name of the module. This can be either a library module or + /// an executable module. + /// + /// If the function succeeds, the return value is a handle to the module; otherwise null. + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr LoadLibrary(string libname); + + /// + /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. + /// When the reference count reaches zero, the module is unloaded from the address space of the calling + /// process and the handle is no longer valid. + /// + /// A handle to the loaded library module. + /// The LoadLibrary, LoadLibraryEx, GetModuleHandle, or GetModuleHandleEx function returns this handle. + /// If the function succeeds, the return value is nonzero; otherwise zero. + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + public static extern bool FreeLibrary(IntPtr hModule); + } +} diff --git a/src/ImageProcessor.Web/Helpers/PostProcessingEventArgs.cs b/src/ImageProcessor.Web/Helpers/PostProcessingEventArgs.cs new file mode 100644 index 000000000..a11fbc069 --- /dev/null +++ b/src/ImageProcessor.Web/Helpers/PostProcessingEventArgs.cs @@ -0,0 +1,25 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The post processing event arguments. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Helpers +{ + using System; + + /// + /// The post processing event arguments. + /// + public class PostProcessingEventArgs : EventArgs + { + /// + /// Gets or sets the cached image path. + /// + public string CachedImagePath { get; set; } + } +} diff --git a/src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs b/src/ImageProcessor.Web/Helpers/RemoteFile.cs similarity index 87% rename from src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs rename to src/ImageProcessor.Web/Helpers/RemoteFile.cs index 05c2f9753..679157dc1 100644 --- a/src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs +++ b/src/ImageProcessor.Web/Helpers/RemoteFile.cs @@ -13,13 +13,16 @@ namespace ImageProcessor.Web.Helpers #region Using using System; using System.Collections.Generic; + using System.Diagnostics; using System.Globalization; using System.IO; using System.Net; using System.Security; using System.Text; using System.Threading.Tasks; - using ImageProcessor.Web.Config; + using System.Web; + + using ImageProcessor.Web.Configuration; #endregion /// @@ -40,7 +43,7 @@ namespace ImageProcessor.Web.Helpers /// There shouldn't be any security issues there, as the internal WebRequest instance is still calling it remotely. /// Any local files that shouldn't be accessed by this won't be allowed by the remote call. /// - /// Adapted from BlogEngine.Net + /// Adapted from BlogEngine.Net /// internal sealed class RemoteFile { @@ -48,27 +51,27 @@ namespace ImageProcessor.Web.Helpers /// /// The white-list of url[s] from which to download remote files. /// - public static readonly ImageSecuritySection.SafeUrl[] RemoteFileWhiteListExtensions = ImageProcessorConfig.Instance.RemoteFileWhiteListExtensions; + public static readonly ImageSecuritySection.SafeUrl[] RemoteFileWhiteListExtensions = ImageProcessorConfiguration.Instance.RemoteFileWhiteListExtensions; /// /// The white-list of url[s] from which to download remote files. /// - private static readonly Uri[] RemoteFileWhiteList = ImageProcessorConfig.Instance.RemoteFileWhiteList; + private static readonly Uri[] RemoteFileWhiteList = ImageProcessorConfiguration.Instance.RemoteFileWhiteList; /// /// The length of time, in milliseconds, that a remote file download attempt can last before timing out. /// - private static readonly int TimeoutMilliseconds = ImageProcessorConfig.Instance.Timeout; + private static readonly int TimeoutMilliseconds = ImageProcessorConfiguration.Instance.Timeout; /// /// The maximum size, in bytes, that a remote file download attempt can download. /// - private static readonly int MaxBytes = ImageProcessorConfig.Instance.MaxBytes; + private static readonly int MaxBytes = ImageProcessorConfiguration.Instance.MaxBytes; /// /// Whether to allow remote downloads. /// - private static readonly bool AllowRemoteDownloads = ImageProcessorConfig.Instance.AllowRemoteDownloads; + private static readonly bool AllowRemoteDownloads = ImageProcessorConfiguration.Instance.AllowRemoteDownloads; /// /// Whether this RemoteFile instance is ignoring remote download rules set in the current application @@ -241,27 +244,43 @@ namespace ImageProcessor.Web.Helpers /// internal async Task GetWebResponseAsync() { - WebResponse response = await this.GetWebRequest().GetResponseAsync(); + WebResponse response = null; + try + { + response = await this.GetWebRequest().GetResponseAsync(); + } + catch (WebException ex) + { + if (ex.Status == WebExceptionStatus.NameResolutionFailure) + { + throw new HttpException(404, "No image exists at " + Uri); + } - long contentLength = response.ContentLength; + throw; + } - // WebResponse.ContentLength doesn't always know the value, it returns -1 in this case. - if (contentLength == -1) + if (response != null) { - // Response headers may still have the Content-Length inside of it. - string headerContentLength = response.Headers["Content-Length"]; + long contentLength = response.ContentLength; - if (!string.IsNullOrWhiteSpace(headerContentLength)) + // WebResponse.ContentLength doesn't always know the value, it returns -1 in this case. + if (contentLength == -1) { - contentLength = long.Parse(headerContentLength, CultureInfo.InvariantCulture); + // Response headers may still have the Content-Length inside of it. + string headerContentLength = response.Headers["Content-Length"]; + + if (!string.IsNullOrWhiteSpace(headerContentLength)) + { + contentLength = long.Parse(headerContentLength, CultureInfo.InvariantCulture); + } } - } - // We don't need to check the url here since any external urls are available only from the web.config. - if ((this.MaxDownloadSize > 0) && (contentLength > this.MaxDownloadSize)) - { - response.Close(); - throw new SecurityException("An attempt to download a remote file has been halted because the file is larger than allowed."); + // We don't need to check the url here since any external urls are available only from the web.config. + if ((this.MaxDownloadSize > 0) && (contentLength > this.MaxDownloadSize)) + { + response.Close(); + throw new SecurityException("An attempt to download a remote file has been halted because the file is larger than allowed."); + } } return response; diff --git a/src/ImageProcessor.Web/NET45/Helpers/ResourceHelpers.cs b/src/ImageProcessor.Web/Helpers/ResourceHelpers.cs similarity index 100% rename from src/ImageProcessor.Web/NET45/Helpers/ResourceHelpers.cs rename to src/ImageProcessor.Web/Helpers/ResourceHelpers.cs diff --git a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs similarity index 69% rename from src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs rename to src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs index 289062965..c5e4c24a8 100644 --- a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. @@ -12,7 +12,6 @@ namespace ImageProcessor.Web.HttpModules { #region Using using System; - using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -23,14 +22,14 @@ namespace ImageProcessor.Web.HttpModules using System.Security.Permissions; using System.Security.Principal; using System.Text.RegularExpressions; - using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.Hosting; using System.Web.Security; - using ImageProcessor.Extensions; + using ImageProcessor.Web.Caching; - using ImageProcessor.Web.Config; + using ImageProcessor.Web.Configuration; + using ImageProcessor.Web.Extensions; using ImageProcessor.Web.Helpers; #endregion @@ -45,10 +44,20 @@ namespace ImageProcessor.Web.HttpModules /// private const string CachedResponseTypeKey = "CACHED_IMAGE_RESPONSE_TYPE_054F217C-11CF-49FF-8D2F-698E8E6EB58F"; + /// + /// The key for storing the cached path of the current image. + /// + private const string CachedPathKey = "CACHED_IMAGE_PATH_TYPE_E0741478-C17B-433D-96A8-6CDA797644E9"; + + /// + /// The key for storing the file dependency of the current image. + /// + private const string CachedResponseFileDependency = "CACHED_IMAGE_DEPENDENCY_054F217C-11CF-49FF-8D2F-698E8E6EB58F"; + /// /// The regular expression to search strings for. /// - private static readonly Regex PresetRegex = new Regex(@"preset=[^&]*", RegexOptions.Compiled); + private static readonly Regex PresetRegex = new Regex(@"preset=[^&]+", RegexOptions.Compiled); /// /// The assembly version. @@ -56,9 +65,9 @@ namespace ImageProcessor.Web.HttpModules private static readonly string AssemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); /// - /// The collection of SemaphoreSlims for identifying given locking individual queries. + /// The locker for preventing duplicate requests. /// - private static readonly ConcurrentDictionary SemaphoreSlims = new ConcurrentDictionary(); + private static readonly AsyncDuplicateLock Locker = new AsyncDuplicateLock(); /// /// The value to prefix any remote image requests with to ensure they get captured. @@ -86,11 +95,11 @@ namespace ImageProcessor.Web.HttpModules #region Destructors /// - /// Finalizes an instance of the class. + /// Finalizes an instance of the class. /// /// /// Use C# destructor syntax for finalization code. - /// This destructor will run only if the Dispose method + /// This destructor will run only if the Dispose method /// does not get called. /// It gives your base class the opportunity to finalize. /// Do not provide destructors in types derived from this class. @@ -104,33 +113,38 @@ namespace ImageProcessor.Web.HttpModules } #endregion + /// + /// The event that is called when a new image is processed. + /// + public static event EventHandler OnPostProcessing; + #region IHttpModule Members /// /// Initializes a module and prepares it to handle requests. /// /// - /// An that provides - /// access to the methods, properties, and events common to all + /// An that provides + /// access to the methods, properties, and events common to all /// application objects within an ASP.NET application /// public void Init(HttpApplication context) { if (remotePrefix == null) { - remotePrefix = ImageProcessorConfig.Instance.RemotePrefix; + remotePrefix = ImageProcessorConfiguration.Instance.RemotePrefix; } if (preserveExifMetaData == null) { - preserveExifMetaData = ImageProcessorConfig.Instance.PreserveExifMetaData; + preserveExifMetaData = ImageProcessorConfiguration.Instance.PreserveExifMetaData; } -#if NET45 - EventHandlerTaskAsyncHelper wrapper = new EventHandlerTaskAsyncHelper(this.PostAuthorizeRequest); - context.AddOnPostAuthorizeRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler); -#else - context.PostAuthorizeRequest += this.PostAuthorizeRequest; -#endif + EventHandlerTaskAsyncHelper postAuthorizeHelper = new EventHandlerTaskAsyncHelper(this.PostAuthorizeRequest); + context.AddOnPostAuthorizeRequestAsync(postAuthorizeHelper.BeginEventHandler, postAuthorizeHelper.EndEventHandler); + + EventHandlerTaskAsyncHelper postProcessHelper = new EventHandlerTaskAsyncHelper(this.PostProcessImage); + context.AddOnPostRequestHandlerExecuteAsync(postProcessHelper.BeginEventHandler, postProcessHelper.EndEventHandler); + context.PreSendRequestHeaders += this.ContextPreSendRequestHeaders; } @@ -143,28 +157,12 @@ namespace ImageProcessor.Web.HttpModules // This object will be cleaned up by the Dispose method. // Therefore, you should call GC.SupressFinalize to - // take this object off the finalization queue + // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time. GC.SuppressFinalize(this); } - /// - /// Gets the specific for the given id. - /// - /// - /// The id representing the . - /// - /// - /// The for the given id. - /// - private static SemaphoreSlim GetSemaphoreSlim(string id) - { - id = id.ToMD5Fingerprint(); - SemaphoreSlim semaphore = SemaphoreSlims.GetOrAdd(id, new SemaphoreSlim(1, 1)); - return semaphore; - } - /// /// Disposes the object and frees resources for the Garbage Collector. /// @@ -179,12 +177,6 @@ namespace ImageProcessor.Web.HttpModules if (disposing) { // Dispose of any managed resources here. - //foreach (KeyValuePair semaphore in SemaphoreSlims) - //{ - // semaphore.Value.Dispose(); - //} - - //SemaphoreSlims.Clear(); } // Call the appropriate methods to clean up @@ -194,8 +186,6 @@ namespace ImageProcessor.Web.HttpModules } #endregion -#if NET45 - /// /// Occurs when the user for the current request has been authorized. /// @@ -214,20 +204,41 @@ namespace ImageProcessor.Web.HttpModules return this.ProcessImageAsync(context); } -#else - /// - /// Occurs when the user for the current request has been authorized. + /// Occurs when the ASP.NET event handler finishes execution. /// - /// The source of the event. - /// An EventArgs that contains the event data. - private async void PostAuthorizeRequest(object sender, EventArgs e) + /// + /// The source of the event. + /// + /// + /// An EventArgs that contains the event data. + /// + /// + /// The . + /// + private Task PostProcessImage(object sender, EventArgs e) { HttpContext context = ((HttpApplication)sender).Context; - await this.ProcessImageAsync(context); - } + object cachedPathObject = context.Items[CachedPathKey]; -#endif + if (cachedPathObject != null) + { + string cachedPath = cachedPathObject.ToString(); + + // Trim the cache. + DiskCache.TrimCachedFolders(cachedPath); + + // Fire the post processing event. + EventHandler handler = OnPostProcessing; + if (handler != null) + { + context.Items[CachedPathKey] = null; + return Task.Run(() => handler(this, new PostProcessingEventArgs { CachedImagePath = cachedPath })); + } + } + + return Task.FromResult(null); + } /// /// Occurs just before ASP.NET send HttpHeaders to the client. @@ -239,15 +250,18 @@ namespace ImageProcessor.Web.HttpModules HttpContext context = ((HttpApplication)sender).Context; object responseTypeObject = context.Items[CachedResponseTypeKey]; + object dependencyFileObject = context.Items[CachedResponseFileDependency]; - if (responseTypeObject != null) + if (responseTypeObject != null && dependencyFileObject != null) { string responseType = (string)responseTypeObject; + List dependencyFiles = (List)dependencyFileObject; // Set the headers - this.SetHeaders(context, responseType); + this.SetHeaders(context, responseType, dependencyFiles); context.Items[CachedResponseTypeKey] = null; + context.Items[CachedResponseFileDependency] = null; } } @@ -256,8 +270,8 @@ namespace ImageProcessor.Web.HttpModules /// Processes the image. /// /// - /// the HttpContext object that provides - /// references to the intrinsic server objects + /// the HttpContext object that provides + /// references to the intrinsic server objects /// /// /// The . @@ -336,7 +350,7 @@ namespace ImageProcessor.Web.HttpModules { string hashedUrlParameters = urlParameters.ToMD5Fingerprint(); - // TODO: Add hash for querystring parameters. + // TODO: Add hash for querystring parameters? imageName += hashedUrlParameters; fullPath += hashedUrlParameters; } @@ -346,12 +360,13 @@ namespace ImageProcessor.Web.HttpModules } // Create a new cache to help process and cache the request. - DiskCache cache = new DiskCache(requestPath, fullPath, imageName, isRemote); + DiskCache cache = new DiskCache(requestPath, fullPath, imageName); + string cachedPath = cache.CachedPath; // Since we are now rewriting the path we need to check again that the current user has access // to the rewritten path. // Get the user for the current request - // If the user is anonymous or authentication doesn't work for this suffix avoid a NullReferenceException + // If the user is anonymous or authentication doesn't work for this suffix avoid a NullReferenceException // in the UrlAuthorizationModule by creating a generic identity. string virtualCachedPath = cache.VirtualCachedPath; @@ -361,9 +376,11 @@ namespace ImageProcessor.Web.HttpModules PermissionSet permission = new PermissionSet(PermissionState.None); permission.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted)); bool hasPermission = permission.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet); + bool isAllowed = true; - // Run the rewritten path past the auth system again, using the result as the default "AllowAccess" value + // Run the rewritten path past the authorization system again. + // We can then use the result as the default "AllowAccess" value if (hasPermission && !context.SkipAuthorization) { isAllowed = UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualCachedPath, user, "GET"); @@ -372,29 +389,23 @@ namespace ImageProcessor.Web.HttpModules if (isAllowed) { // Is the file new or updated? - bool isNewOrUpdated = await cache.IsNewOrUpdatedFileAsync(); + bool isNewOrUpdated = cache.IsNewOrUpdatedFile(cachedPath); // Only process if the file has been updated. if (isNewOrUpdated) { - string cachedPath = cache.CachedPath; - // Process the image. using (ImageFactory imageFactory = new ImageFactory(preserveExifMetaData != null && preserveExifMetaData.Value)) { if (isRemote) { - Uri uri = new Uri(requestPath + "?" + urlParameters); - - RemoteFile remoteFile = new RemoteFile(uri, false); - - // Prevent response blocking. - WebResponse webResponse = await remoteFile.GetWebResponseAsync().ConfigureAwait(false); - - SemaphoreSlim semaphore = GetSemaphoreSlim(cachedPath); - try + using (await Locker.LockAsync(cachedPath)) { - semaphore.Wait(); + Uri uri = new Uri(requestPath + "?" + urlParameters); + RemoteFile remoteFile = new RemoteFile(uri, false); + + // Prevent response blocking. + WebResponse webResponse = await remoteFile.GetWebResponseAsync().ConfigureAwait(false); using (MemoryStream memoryStream = new MemoryStream()) { @@ -406,82 +417,86 @@ namespace ImageProcessor.Web.HttpModules { responseStream.CopyTo(memoryStream); + // Reset the position of the stream to ensure we're reading the correct part. + memoryStream.Position = 0; + // Process the Image imageFactory.Load(memoryStream) - .AddQueryString(queryString) - .AutoProcess() + .AutoProcess(queryString) .Save(cachedPath); - // Store the response type in the context for later retrieval. - context.Items[CachedResponseTypeKey] = imageFactory.MimeType; - // Add to the cache. - cache.AddImageToCache(); + cache.AddImageToCache(cachedPath); - // Trim the cache. - await cache.TrimCachedFolderAsync(cachedPath); + // Store the cached path, response type, and cache dependency in the context for later retrieval. + context.Items[CachedPathKey] = cachedPath; + context.Items[CachedResponseTypeKey] = imageFactory.CurrentImageFormat.MimeType; + context.Items[CachedResponseFileDependency] = new List { cachedPath }; } } } } } - finally - { - semaphore.Release(); - } } else { - // Check to see if the file exists. - // ReSharper disable once AssignNullToNotNullAttribute - FileInfo fileInfo = new FileInfo(requestPath); - - if (!fileInfo.Exists) + using (Locker.Lock(cachedPath)) { - throw new HttpException(404, "No image exists at " + fullPath); - } + // Check to see if the file exists. + // ReSharper disable once AssignNullToNotNullAttribute + FileInfo fileInfo = new FileInfo(requestPath); - SemaphoreSlim semaphore = GetSemaphoreSlim(cachedPath); - try - { - semaphore.Wait(); + if (!fileInfo.Exists) + { + throw new HttpException(404, "No image exists at " + fullPath); + } // Process the Image - imageFactory.Load(fullPath).AutoProcess().Save(cachedPath); - - // Store the response type in the context for later retrieval. - context.Items[CachedResponseTypeKey] = imageFactory.MimeType; + imageFactory.Load(requestPath) + .AutoProcess(queryString) + .Save(cachedPath); // Add to the cache. - cache.AddImageToCache(); + cache.AddImageToCache(cachedPath); - // Trim the cache. - await cache.TrimCachedFolderAsync(cachedPath); - } - finally - { - semaphore.Release(); + // Store the cached path, response type, and cache dependencies in the context for later retrieval. + context.Items[CachedPathKey] = cachedPath; + context.Items[CachedResponseTypeKey] = imageFactory.CurrentImageFormat.MimeType; + context.Items[CachedResponseFileDependency] = new List { requestPath, cachedPath }; } } } } - string incomingEtag = context.Request.Headers["If-None-Match"]; + // Image is from the cache so the mime-type will need to be set. + if (context.Items[CachedResponseTypeKey] == null) + { + string mimetype = ImageHelpers.GetMimeType(cachedPath); + + if (!string.IsNullOrEmpty(mimetype)) + { + context.Items[CachedResponseTypeKey] = mimetype; + } + } + + string incomingEtag = context.Request.Headers["If" + "-None-Match"]; if (incomingEtag != null && !isNewOrUpdated) { - // Explicitly set the Content-Length header so the client doesn't wait for - // content but keeps the connection open for other requests + // Set the Content-Length header so the client doesn't wait for + // content but keeps the connection open for other requests. context.Response.AddHeader("Content-Length", "0"); context.Response.StatusCode = (int)HttpStatusCode.NotModified; context.Response.SuppressContent = true; - context.Response.AddFileDependency(context.Server.MapPath(virtualCachedPath)); - this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey]); if (!isRemote) { + // Set the headers and quit. + this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey], new List { requestPath, cachedPath }); return; } + + this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey], new List { cachedPath }); } // The cached file is valid so just rewrite the path. @@ -494,7 +509,7 @@ namespace ImageProcessor.Web.HttpModules } else if (isRemote) { - // Just repoint to the external url. + // Just re-point to the external url. HttpContext.Current.Response.Redirect(requestPath); } } @@ -505,21 +520,31 @@ namespace ImageProcessor.Web.HttpModules /// See http://en.wikipedia.org/wiki/HTTP_ETag /// /// - /// the HttpContext object that provides - /// references to the intrinsic server objects + /// the HttpContext object that provides + /// references to the intrinsic server objects + /// + /// + /// The HTTP MIME type to to send. /// - /// The HTTP MIME type to to send. - private void SetHeaders(HttpContext context, string responseType) + /// + /// The dependency path for the cache dependency. + /// + private void SetHeaders(HttpContext context, string responseType, IEnumerable dependencyPaths) { HttpResponse response = context.Response; response.ContentType = responseType; - response.AddHeader("Image-Served-By", "ImageProcessor.Web/" + AssemblyVersion); + if (response.Headers["Image-Served-By"] == null) + { + response.AddHeader("Image-Served-By", "ImageProcessor.Web/" + AssemblyVersion); + } HttpCachePolicy cache = response.Cache; cache.SetCacheability(HttpCacheability.Public); cache.VaryByHeaders["Accept-Encoding"] = true; + + context.Response.AddFileDependencies(dependencyPaths.ToArray()); cache.SetLastModifiedFromFileDependencies(); int maxDays = DiskCache.MaxFileCachedDuration; @@ -547,7 +572,7 @@ namespace ImageProcessor.Web.HttpModules string preset = match.Value.Split('=')[1]; // We use the processor config system to store the preset values. - string replacements = ImageProcessorConfig.Instance.GetPresetSettings(preset); + string replacements = ImageProcessorConfiguration.Instance.GetPresetSettings(preset); queryString = Regex.Replace(queryString, preset, replacements ?? string.Empty); } } @@ -556,4 +581,4 @@ namespace ImageProcessor.Web.HttpModules } #endregion } -} \ No newline at end of file +} diff --git a/src/ImageProcessor.Web/ImageFactoryExtensions.cs b/src/ImageProcessor.Web/ImageFactoryExtensions.cs new file mode 100644 index 000000000..ee51be516 --- /dev/null +++ b/src/ImageProcessor.Web/ImageFactoryExtensions.cs @@ -0,0 +1,66 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Extends the ImageFactory class to provide a fluent API. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web +{ + #region Using + using System.Collections.Generic; + using System.Linq; + using ImageProcessor.Web.Configuration; + using ImageProcessor.Web.Processors; + #endregion + + /// + /// Extends the ImageFactory class to provide a fluent API. + /// + public static class ImageFactoryExtensions + { + /// + /// The object to lock against. + /// + private static readonly object SyncRoot = new object(); + + /// + /// Auto processes image files based on any query string parameters added to the image path. + /// + /// + /// The current instance of the class + /// that this method extends. + /// + /// The collection of querystring parameters to process. + /// + /// The current instance of the class. + /// + public static ImageFactory AutoProcess(this ImageFactory factory, string queryString) + { + if (factory.ShouldProcess) + { + // It's faster to lock and run through our activated list than to create new instances. + lock (SyncRoot) + { + // Get a list of all graphics processors that have parsed and matched the query string. + List graphicsProcessors = + ImageProcessorConfiguration.Instance.GraphicsProcessors + .Where(x => x.MatchRegexIndex(queryString) != int.MaxValue) + .OrderBy(y => y.SortOrder) + .ToList(); + + // Loop through and process the image. + foreach (IWebGraphicsProcessor graphicsProcessor in graphicsProcessors) + { + factory.CurrentImageFormat.ApplyProcessor(graphicsProcessor.Processor.ProcessImage, factory); + } + } + } + + return factory; + } + } +} diff --git a/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj b/src/ImageProcessor.Web/ImageProcessor.Web.csproj similarity index 65% rename from src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj rename to src/ImageProcessor.Web/ImageProcessor.Web.csproj index c2a7c9403..47b69f8ac 100644 --- a/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj +++ b/src/ImageProcessor.Web/ImageProcessor.Web.csproj @@ -49,33 +49,58 @@ - - - - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + - + {3b5dd734-fb7a-487d-8ce6-55e7af9aea7e} ImageProcessor - + Designer - + Designer - + diff --git a/src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj b/src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj deleted file mode 100644 index 1bd78044d..000000000 --- a/src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj +++ /dev/null @@ -1,146 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43} - Library - Properties - ImageProcessor.Web - ImageProcessor.Web - v4.0 - 512 - ..\..\ - true - - - true - full - false - bin\Debug\ - TRACE;DEBUG;USE_CSHARP_SQLITE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE;USE_CSHARP_SQLITE - prompt - 4 - - - true - bin\All\ - TRACE;DEBUG;USE_CSHARP_SQLITE - full - AnyCPU - prompt - - - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll - - - - - - - ..\..\packages\Microsoft.Bcl.1.1.9\lib\net40\System.IO.dll - True - - - - ..\..\packages\Microsoft.Bcl.1.1.9\lib\net40\System.Runtime.dll - - - - ..\..\packages\Microsoft.Bcl.1.1.9\lib\net40\System.Threading.Tasks.dll - - - - - - - - - CacheIndexer.cs - - - - MemCache.cs - - - - - - - DirectoryInfoExtensions.cs - - - ImageHelpers.cs - - - - ResourceHelpers.cs - - - - - - - - - {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E} - ImageProcessor - - - - - Config\Resources\cache.config - - - Config\Resources\processing.config - - - Config\Resources\security.config - - - Designer - - - Designer - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET4/Settings.StyleCop b/src/ImageProcessor.Web/NET4/Settings.StyleCop deleted file mode 100644 index 253825567..000000000 --- a/src/ImageProcessor.Web/NET4/Settings.StyleCop +++ /dev/null @@ -1,11 +0,0 @@ - - - - - James South - Copyright (c) James South. -Licensed under the Apache License, Version 2.0. - - - - \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET4/app.config b/src/ImageProcessor.Web/NET4/app.config deleted file mode 100644 index 31d365ae5..000000000 --- a/src/ImageProcessor.Web/NET4/app.config +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET4/packages.config b/src/ImageProcessor.Web/NET4/packages.config deleted file mode 100644 index c7068f590..000000000 --- a/src/ImageProcessor.Web/NET4/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/Config/Resources/cache.config b/src/ImageProcessor.Web/NET45/Config/Resources/cache.config deleted file mode 100644 index 1caab6358..000000000 --- a/src/ImageProcessor.Web/NET45/Config/Resources/cache.config +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/Config/Resources/processing.config b/src/ImageProcessor.Web/NET45/Config/Resources/processing.config deleted file mode 100644 index e792c3950..000000000 --- a/src/ImageProcessor.Web/NET45/Config/Resources/processing.config +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs b/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs deleted file mode 100644 index c5000851e..000000000 --- a/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// The image helpers. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Web.Helpers -{ - #region Using - using System.Text.RegularExpressions; - #endregion - - /// - /// The image helpers. - /// - public static class ImageHelpers - { - /// - /// The image format regex. - /// - private static readonly Regex FormatRegex = new Regex(@"(\.?)(j(pg|peg)|bmp|png|gif|ti(ff|f)|ico)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.RightToLeft); - - /// - /// The image format regex for matching the file format at the end of a string. - /// - private static readonly Regex EndFormatRegex = new Regex(@"(\.)(j(pg|peg)|bmp|png|gif|ti(ff|f)|ico)$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.RightToLeft); - - /// - /// Checks a given string to check whether the value contains a valid image extension. - /// - /// The string containing the filename to check. - /// True the value contains a valid image extension, otherwise false. - public static bool IsValidImageExtension(string fileName) - { - return EndFormatRegex.IsMatch(fileName); - } - - /// - /// Returns the correct file extension for the given string input - /// - /// - /// The string to parse. - /// - /// - /// The correct file extension for the given string input if it can find one; otherwise an empty string. - /// - public static string GetExtension(string input) - { - Match match = FormatRegex.Matches(input)[0]; - return match.Success ? match.Value : string.Empty; - } - } -} diff --git a/src/ImageProcessor.Web/NET45/Helpers/TaskHelpers.cs b/src/ImageProcessor.Web/NET45/Helpers/TaskHelpers.cs deleted file mode 100644 index 961498c09..000000000 --- a/src/ImageProcessor.Web/NET45/Helpers/TaskHelpers.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Provides some syntactic sugar to run tasks. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Web.Helpers -{ - #region Using - using System; - using System.Threading.Tasks; - #endregion - - /// - /// Provides some syntactic sugar to run tasks. - /// - public sealed class TaskHelpers - { - /// - /// Queues the specified work to run on the ThreadPool and returns a Task handle for that work. - /// - /// The work to execute asynchronously - /// A Task that represents the work queued to execute in the ThreadPool. - /// - /// The parameter was null. - /// - public static Task Run(Action action) - { - return Task.Factory.StartNew(action); - } - - /// - /// Queues the specified work to run on the ThreadPool and returns a proxy for the - /// Task(TResult) returned by . - /// - /// The type of the result returned by the proxy Task. - /// The work to execute asynchronously - /// A Task(TResult) that represents a proxy for the Task(TResult) returned by . - /// - /// The parameter was null. - /// - public static Task Run(Func function) - { - return Task.Factory.StartNew(function); - } - } -} diff --git a/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs b/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs deleted file mode 100644 index 0c8788cd9..000000000 --- a/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs +++ /dev/null @@ -1,130 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Extends the ImageFactory class to provide a fluent API. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Web -{ - #region Using - - using System; - using System.Collections.Generic; - using System.Drawing; - using System.Drawing.Imaging; - using System.IO; - using System.Linq; - using ImageProcessor.Extensions; - using ImageProcessor.Imaging; - using ImageProcessor.Processors; - using ImageProcessor.Web.Config; - #endregion - - /// - /// Extends the ImageFactory class to provide a fluent API. - /// - public static class ImageFactoryExtensions - { - /// - /// The object to lock against. - /// - private static readonly object SyncRoot = new object(); - - /// - /// Auto processes image files based on any query string parameters added to the image path. - /// - /// - /// The current instance of the class - /// that this method extends. - /// - /// - /// The current instance of the class. - /// - public static ImageFactory AutoProcess(this ImageFactory factory) - { - if (factory.ShouldProcess) - { - // It's faster to lock and run through our activated list than to create new instances. - lock (SyncRoot) - { - // Get a list of all graphics processors that have parsed and matched the query string. - List graphicsProcessors = - ImageProcessorConfig.Instance.GraphicsProcessors - .Where(x => x.MatchRegexIndex(factory.QueryString) != int.MaxValue) - .OrderBy(y => y.SortOrder) - .ToList(); - - // Loop through and process the image. - foreach (IGraphicsProcessor graphicsProcessor in graphicsProcessors) - { - ApplyProcessor(graphicsProcessor.ProcessImage, factory); - } - } - } - - return factory; - } - - /// - /// Processes the image. - /// - /// - /// The processor. - /// - /// - /// The factory. - /// - private static void ApplyProcessor(Func processor, ImageFactory factory) - { - ImageInfo imageInfo = factory.Image.GetImageInfo(factory.ImageFormat); - - if (imageInfo.IsAnimated) - { - OctreeQuantizer quantizer = new OctreeQuantizer(255, 8); - - // We don't dispose of the memory stream as that is disposed when a new image is created and doing so - // beforehand will cause an exception. - MemoryStream stream = new MemoryStream(); - using (GifEncoder encoder = new GifEncoder(stream, null, null, imageInfo.LoopCount)) - { - foreach (GifFrame frame in imageInfo.GifFrames) - { - factory.Update(frame.Image); - frame.Image = quantizer.Quantize(processor.Invoke(factory)); - encoder.AddFrame(frame); - } - } - - stream.Position = 0; - factory.Update(Image.FromStream(stream)); - } - else - { - factory.Update(processor.Invoke(factory)); - } - - // Set the property item information from any Exif metadata. - // We do this here so that they can be changed between processor methods. - if (factory.PreserveExifData) - { - foreach (KeyValuePair propertItem in factory.ExifPropertyItems) - { - try - { - factory.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. - } - } - } - } - } -} diff --git a/src/ImageProcessor.Web/NET45/Settings.StyleCop b/src/ImageProcessor.Web/NET45/Settings.StyleCop deleted file mode 100644 index 05e1b6c70..000000000 --- a/src/ImageProcessor.Web/NET45/Settings.StyleCop +++ /dev/null @@ -1,18 +0,0 @@ - - - - exif - Mutexes - querystring - - - - - - James South - Copyright (c) James South. -Licensed under the Apache License, Version 2.0. - - - - \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Alpha.cs b/src/ImageProcessor.Web/Processors/Alpha.cs new file mode 100644 index 000000000..eec352608 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Alpha.cs @@ -0,0 +1,90 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to change the alpha component of the image to effect its transparency. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System; + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Encapsulates methods to change the alpha component of the image to effect its transparency. + /// + public class Alpha : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"alpha=[^&|,]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Alpha() + { + this.Processor = new ImageProcessor.Processors.Alpha(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + int percentage = Math.Abs(CommonParameterParserUtility.ParseIn100Range(match.Value)); + this.Processor.DynamicParameter = percentage; + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} diff --git a/src/ImageProcessor.Web/Processors/AutoRotate.cs b/src/ImageProcessor.Web/Processors/AutoRotate.cs new file mode 100644 index 000000000..6fc01dfc6 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/AutoRotate.cs @@ -0,0 +1,94 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Performs auto-rotation to ensure that EXIF defined rotation is reflected in +// the final image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + + /// + /// Performs auto-rotation to ensure that EXIF defined rotation is reflected in + /// the final image. + /// + public class AutoRotate : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"autorotate=true", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public AutoRotate() + { + this.Processor = new ImageProcessor.Processors.AutoRotate(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder + { + get; + private set; + } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/BackgroundColor.cs b/src/ImageProcessor.Web/Processors/BackgroundColor.cs new file mode 100644 index 000000000..edc9c3b68 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/BackgroundColor.cs @@ -0,0 +1,88 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Changes the background color of an image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Changes the background color of an image. + /// + public class BackgroundColor : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"bgcolor(=|-)[^&]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public BackgroundColor() + { + this.Processor = new ImageProcessor.Processors.BackgroundColor(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + this.Processor.DynamicParameter = CommonParameterParserUtility.ParseColor(match.Value); + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Brightness.cs b/src/ImageProcessor.Web/Processors/Brightness.cs new file mode 100644 index 000000000..abd8528d1 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Brightness.cs @@ -0,0 +1,89 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to change the brightness component of the image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Encapsulates methods to change the brightness component of the image. + /// + public class Brightness : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"brightness=[^&|,]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Brightness() + { + this.Processor = new ImageProcessor.Processors.Brightness(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + int percentage = CommonParameterParserUtility.ParseIn100Range(match.Value); + this.Processor.DynamicParameter = percentage; + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Contrast.cs b/src/ImageProcessor.Web/Processors/Contrast.cs new file mode 100644 index 000000000..2b9a501af --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Contrast.cs @@ -0,0 +1,89 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to change the contrast component of the image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Encapsulates methods to change the contrast component of the image. + /// + public class Contrast : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"contrast=[^&|,]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Contrast() + { + this.Processor = new ImageProcessor.Processors.Contrast(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + int percentage = CommonParameterParserUtility.ParseIn100Range(match.Value); + this.Processor.DynamicParameter = percentage; + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Crop.cs b/src/ImageProcessor.Web/Processors/Crop.cs new file mode 100644 index 000000000..c669c8e1b --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Crop.cs @@ -0,0 +1,167 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Crops an image to the given directions. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text; + using System.Text.RegularExpressions; + + using ImageProcessor.Imaging; + using ImageProcessor.Processors; + using ImageProcessor.Web.Extensions; + + /// + /// Crops an image to the given directions. + /// + public class Crop : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + /// + private static readonly Regex QueryRegex = new Regex(@"(crop=|cropmode=)[^&]+", RegexOptions.Compiled); + + /// + /// The coordinate regex. + /// + private static readonly Regex CoordinateRegex = new Regex(@"crop=\d+(.\d+)?[,-]\d+(.\d+)?[,-]\d+(.\d+)?[,-]\d+(.\d+)?", RegexOptions.Compiled); + + /// + /// The mode regex. + /// + private static readonly Regex ModeRegex = new Regex(@"cropmode=(pixels|percent)", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Crop() + { + this.Processor = new ImageProcessor.Processors.Crop(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + // First merge the matches so we can parse . + StringBuilder stringBuilder = new StringBuilder(); + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + } + + stringBuilder.Append(match.Value); + + index += 1; + } + } + + if (this.SortOrder < int.MaxValue) + { + // Match syntax + string toParse = stringBuilder.ToString(); + + float[] coordinates = this.ParseCoordinates(toParse); + CropMode cropMode = this.ParseMode(toParse); + + CropLayer cropLayer = new CropLayer(coordinates[0], coordinates[1], coordinates[2], coordinates[3], cropMode); + this.Processor.DynamicParameter = cropLayer; + } + + return this.SortOrder; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct . + /// + private CropMode ParseMode(string input) + { + foreach (Match match in ModeRegex.Matches(input)) + { + // Split on = + string mode = match.Value.Split('=')[1]; + + switch (mode) + { + case "percent": + return CropMode.Percentage; + case "pixels": + return CropMode.Pixels; + } + } + + return CropMode.Pixels; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct . + /// + private float[] ParseCoordinates(string input) + { + float[] floats = { }; + + foreach (Match match in CoordinateRegex.Matches(input)) + { + floats = match.Value.ToPositiveFloatArray(); + } + + return floats; + } + } +} diff --git a/src/ImageProcessor.Web/Processors/Filter.cs b/src/ImageProcessor.Web/Processors/Filter.cs new file mode 100644 index 000000000..ab9353c78 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Filter.cs @@ -0,0 +1,161 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods with which to add filters to an image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using System.Text; + using System.Text.RegularExpressions; + using ImageProcessor.Imaging.Filters; + using ImageProcessor.Processors; + + /// + /// Encapsulates methods with which to add filters to an image. + /// + public class Filter : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = BuildRegex(); + + /// + /// Initializes a new instance of the class. + /// + public Filter() + { + this.Processor = new ImageProcessor.Processors.Filter(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder + { + get; + private set; + } + + /// + /// Gets the processor. + /// + /// + /// The processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + this.Processor.DynamicParameter = this.ParseFilter(match.Value.Split('=')[1]); + } + + index += 1; + } + } + + return this.SortOrder; + } + + /// + /// Builds a regular expression from the type, this allows extensibility. + /// + /// + /// The to match matrix filters. + /// + private static Regex BuildRegex() + { + const BindingFlags Flags = BindingFlags.Public | BindingFlags.Static; + Type type = typeof(MatrixFilters); + IEnumerable filters = type.GetProperties(Flags) + .Where(p => p.PropertyType.IsAssignableFrom(typeof(IMatrixFilter))) + .ToList(); + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append("filter=("); + int counter = 0; + + foreach (PropertyInfo filter in filters) + { + if (counter == 0) + { + stringBuilder.Append(filter.Name.ToLowerInvariant()); + } + else + { + stringBuilder.AppendFormat("|{0}", filter.Name.ToLowerInvariant()); + } + + counter++; + } + + stringBuilder.Append(")"); + + return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase); + } + + /// + /// Parses the input string to return the correct . + /// + /// + /// The identifier. + /// + /// + /// The . + /// + private IMatrixFilter ParseFilter(string identifier) + { + const BindingFlags Flags = BindingFlags.Public | BindingFlags.Static; + + Type type = typeof(MatrixFilters); + PropertyInfo filter = + type.GetProperties(Flags) + .Where(p => p.PropertyType.IsAssignableFrom(typeof(IMatrixFilter))) + .First(p => p.Name.Equals(identifier, StringComparison.InvariantCultureIgnoreCase)); + + return filter.GetValue(null, null) as IMatrixFilter; + } + } +} diff --git a/src/ImageProcessor.Web/Processors/Flip.cs b/src/ImageProcessor.Web/Processors/Flip.cs new file mode 100644 index 000000000..085962030 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Flip.cs @@ -0,0 +1,103 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Flips an image horizontally or vertically. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Drawing; + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + + /// + /// Flips an image horizontally or vertically. + /// + public class Flip : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"flip=(horizontal|vertical|both)", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Flip() + { + this.Processor = new ImageProcessor.Processors.Flip(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + string direction = match.Value.Split('=')[1]; + + switch (direction) + { + case "horizontal": + this.Processor.DynamicParameter = RotateFlipType.RotateNoneFlipX; + break; + case "vertical": + this.Processor.DynamicParameter = RotateFlipType.RotateNoneFlipY; + break; + default: + this.Processor.DynamicParameter = RotateFlipType.RotateNoneFlipXY; + break; + } + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Format.cs b/src/ImageProcessor.Web/Processors/Format.cs new file mode 100644 index 000000000..7b57d7ddd --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Format.cs @@ -0,0 +1,166 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Sets the output of the image to a specific format. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Text.RegularExpressions; + + using ImageProcessor.Configuration; + using ImageProcessor.Imaging.Formats; + using ImageProcessor.Processors; + + /// + /// Sets the output of the image to a specific format. + /// + public class Format : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = BuildRegex(); + + /// + /// Initializes a new instance of the class. + /// + public Format() + { + this.Processor = new ImageProcessor.Processors.Format(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + + ISupportedImageFormat format = this.ParseFormat(match.Value.Split('=')[1]); + if (format != null) + { + this.Processor.DynamicParameter = format; + } + } + + index += 1; + } + } + + return this.SortOrder; + } + + /// + /// Builds a regular expression from the type, this allows extensibility. + /// + /// + /// The to match matrix filters. + /// + private static Regex BuildRegex() + { + StringBuilder stringBuilder = new StringBuilder(); + + // png8 is a special case for determining indexed pngs. + stringBuilder.Append("format=(png8"); + foreach (ISupportedImageFormat imageFormat in ImageProcessorBootstrapper.Instance.SupportedImageFormats) + { + foreach (string fileExtension in imageFormat.FileExtensions) + { + stringBuilder.AppendFormat("|{0}", fileExtension.ToLowerInvariant()); + } + } + + stringBuilder.Append(")"); + + return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase); + } + + /// + /// Parses the input string to return the correct . + /// + /// + /// The identifier. + /// + /// + /// The . + /// + private ISupportedImageFormat ParseFormat(string identifier) + { + identifier = identifier.ToLowerInvariant(); + string finalIdentifier = identifier.Equals("png8") ? "png" : identifier; + ISupportedImageFormat newFormat = null; + List formats = ImageProcessorBootstrapper.Instance.SupportedImageFormats.ToList(); + ISupportedImageFormat format = formats.FirstOrDefault(f => f.FileExtensions.Any(e => e.Equals(finalIdentifier, StringComparison.InvariantCultureIgnoreCase))); + + if (format != null) + { + // Return a new instance as we want to use instance properties. + newFormat = Activator.CreateInstance(format.GetType()) as ISupportedImageFormat; + + if (newFormat != null) + { + // I wish this wasn't hard-coded but there's no way I can + // find to preserve the palette. + if (identifier.Equals("png8")) + { + newFormat.IsIndexed = true; + } + else if (identifier.Equals("png")) + { + newFormat.IsIndexed = false; + } + } + } + + return newFormat; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/GaussianBlur.cs b/src/ImageProcessor.Web/Processors/GaussianBlur.cs new file mode 100644 index 000000000..d6e66232b --- /dev/null +++ b/src/ImageProcessor.Web/Processors/GaussianBlur.cs @@ -0,0 +1,101 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Applies a Gaussian blur to the image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Globalization; + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Applies a Gaussian blur to the image. + /// + public class GaussianBlur : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"blur=[^&]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public GaussianBlur() + { + this.Processor = new ImageProcessor.Processors.GaussianBlur(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + + // Normalise and set the variables. + int maxSize; + double maxSigma; + int maxThreshold; + + int.TryParse(this.Processor.Settings["MaxSize"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxSize); + double.TryParse(this.Processor.Settings["MaxSigma"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxSigma); + int.TryParse(this.Processor.Settings["MaxThreshold"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxThreshold); + + this.Processor.DynamicParameter = CommonParameterParserUtility.ParseGaussianLayer(queryString, maxSize, maxSigma, maxThreshold); + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/GaussianSharpen.cs b/src/ImageProcessor.Web/Processors/GaussianSharpen.cs new file mode 100644 index 000000000..67adf7b3d --- /dev/null +++ b/src/ImageProcessor.Web/Processors/GaussianSharpen.cs @@ -0,0 +1,101 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Applies a Gaussian sharpen to the image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Globalization; + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Applies a Gaussian sharpen to the image. + /// + public class GaussianSharpen : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"sharpen=[^&]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public GaussianSharpen() + { + this.Processor = new ImageProcessor.Processors.GaussianSharpen(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + + // Normalise and set the variables. + int maxSize; + double maxSigma; + int maxThreshold; + + int.TryParse(this.Processor.Settings["MaxSize"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxSize); + double.TryParse(this.Processor.Settings["MaxSigma"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxSigma); + int.TryParse(this.Processor.Settings["MaxThreshold"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxThreshold); + + this.Processor.DynamicParameter = CommonParameterParserUtility.ParseGaussianLayer(queryString, maxSize, maxSigma, maxThreshold); + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/IWebGraphicsProcessor.cs b/src/ImageProcessor.Web/Processors/IWebGraphicsProcessor.cs new file mode 100644 index 000000000..b15d86d30 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/IWebGraphicsProcessor.cs @@ -0,0 +1,51 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Defines properties and methods for ImageProcessor.Web Plugins. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + + /// + /// Defines properties and methods for ImageProcessor.Web Plugins. + /// + public interface IWebGraphicsProcessor + { + #region Properties + /// + /// Gets the regular expression to search strings for. + /// + Regex RegexPattern { get; } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + int SortOrder { get; } + + /// + /// Gets the associated graphics processor. + /// + IGraphicsProcessor Processor { get; } + #endregion + + #region Methods + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + int MatchRegexIndex(string queryString); + #endregion + } +} diff --git a/src/ImageProcessor.Web/Processors/Meta.cs b/src/ImageProcessor.Web/Processors/Meta.cs new file mode 100644 index 000000000..14aee5714 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Meta.cs @@ -0,0 +1,92 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to control preservation of meta information. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + + /// + /// Encapsulates methods to control preservation of meta information. + /// + public class Meta : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"meta=(true|false)", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Meta() + { + this.Processor = new ImageProcessor.Processors.Meta(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + + bool preserve = bool.Parse(match.Value.Split('=')[1]); + + this.Processor.DynamicParameter = preserve; + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Quality.cs b/src/ImageProcessor.Web/Processors/Quality.cs new file mode 100644 index 000000000..b392aecb5 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Quality.cs @@ -0,0 +1,90 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to change the quality component of the image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System; + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Encapsulates methods to change the quality component of the image. + /// + public class Quality : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"quality=[^&|,]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Quality() + { + this.Processor = new ImageProcessor.Processors.Quality(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + int percentage = Math.Abs(CommonParameterParserUtility.ParseIn100Range(match.Value)); + this.Processor.DynamicParameter = percentage; + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} diff --git a/src/ImageProcessor.Web/Processors/Resize.cs b/src/ImageProcessor.Web/Processors/Resize.cs new file mode 100644 index 000000000..3c1772911 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Resize.cs @@ -0,0 +1,325 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Resizes an image to the given dimensions. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Text.RegularExpressions; + + using ImageProcessor.Imaging; + using ImageProcessor.Processors; + using ImageProcessor.Web.Extensions; + + /// + /// Resizes an image to the given dimensions. + /// + public class Resize : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"(width|height)=|(width|height)ratio=|mode=|anchor=|center=|upscale=", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the size attribute. + /// + private static readonly Regex SizeRegex = new Regex(@"(width|height)=\d+", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the ratio attribute. + /// + private static readonly Regex RatioRegex = new Regex(@"(width|height)ratio=\d+(.\d+)?", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the mode attribute. + /// + private static readonly Regex ModeRegex = new Regex(@"mode=(pad|stretch|crop|max)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the anchor attribute. + /// + private static readonly Regex AnchorRegex = new Regex(@"anchor=(top|bottom|left|right|center)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the center attribute. + /// + private static readonly Regex CenterRegex = new Regex(@"center=\d+(.\d+)?[,-]\d+(.\d+)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the upscale attribute. + /// + private static readonly Regex UpscaleRegex = new Regex(@"upscale=false", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Resize() + { + this.Processor = new ImageProcessor.Processors.Resize(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + // First merge the matches so we can parse . + StringBuilder stringBuilder = new StringBuilder(); + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + stringBuilder.Append(queryString); + } + + index += 1; + } + } + + // Match syntax + string toParse = stringBuilder.ToString(); + + Size size = this.ParseSize(toParse); + ResizeLayer resizeLayer = new ResizeLayer(size) + { + ResizeMode = this.ParseMode(toParse), + AnchorPosition = this.ParsePosition(toParse), + Upscale = !UpscaleRegex.IsMatch(toParse), + CenterCoordinates = this.ParseCoordinates(toParse), + }; + + this.Processor.DynamicParameter = resizeLayer; + + // Correctly parse any restrictions. + string restrictions; + this.Processor.Settings.TryGetValue("RestrictTo", out restrictions); + ((ImageProcessor.Processors.Resize)this.Processor).RestrictedSizes = this.ParseRestrictions(restrictions); + return this.SortOrder; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The . + /// + private Size ParseSize(string input) + { + const string Width = "width="; + const string Height = "height="; + const string WidthRatio = "widthratio="; + const string HeightRatio = "heightratio="; + Size size = new Size(); + + // First merge the matches so we can parse . + StringBuilder stringBuilder = new StringBuilder(); + foreach (Match match in SizeRegex.Matches(input)) + { + stringBuilder.Append(match.Value); + } + + // First cater for single dimensions. + string value = stringBuilder.ToString(); + + if (input.Contains(Width) && !input.Contains(Height)) + { + size = new Size(value.ToPositiveIntegerArray()[0], 0); + } + + if (input.Contains(Height) && !input.Contains(Width)) + { + size = new Size(0, value.ToPositiveIntegerArray()[0]); + } + + // Both dimensions supplied. + if (input.Contains(Height) && input.Contains(Width)) + { + int[] dimensions = value.ToPositiveIntegerArray(); + + // Check the order in which they have been supplied. + size = input.IndexOf(Width, StringComparison.Ordinal) < input.IndexOf(Height, StringComparison.Ordinal) + ? new Size(dimensions[0], dimensions[1]) + : new Size(dimensions[1], dimensions[0]); + } + + // Calculate any ratio driven sizes. + if (size.Width == 0 || size.Height == 0) + { + stringBuilder.Clear(); + foreach (Match match in RatioRegex.Matches(input)) + { + stringBuilder.Append(match.Value); + } + + value = stringBuilder.ToString(); + + // Replace 0 width + if (size.Width == 0 && size.Height > 0 && input.Contains(WidthRatio) && !input.Contains(HeightRatio)) + { + size.Width = (int)Math.Ceiling(value.ToPositiveFloatArray()[0] * size.Height); + } + + // Replace 0 height + if (size.Height == 0 && size.Width > 0 && input.Contains(HeightRatio) && !input.Contains(WidthRatio)) + { + size.Height = (int)Math.Ceiling(value.ToPositiveFloatArray()[0] * size.Width); + } + } + + return size; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct . + /// + private ResizeMode ParseMode(string input) + { + foreach (Match match in ModeRegex.Matches(input)) + { + // Split on = + string mode = match.Value.Split('=')[1]; + + switch (mode) + { + case "stretch": + return ResizeMode.Stretch; + case "crop": + return ResizeMode.Crop; + case "max": + return ResizeMode.Max; + default: + return ResizeMode.Pad; + } + } + + return ResizeMode.Pad; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct . + /// + private AnchorPosition ParsePosition(string input) + { + foreach (Match match in AnchorRegex.Matches(input)) + { + // Split on = + string anchor = match.Value.Split('=')[1]; + + switch (anchor) + { + case "top": + return AnchorPosition.Top; + case "bottom": + return AnchorPosition.Bottom; + case "left": + return AnchorPosition.Left; + case "right": + return AnchorPosition.Right; + default: + return AnchorPosition.Center; + } + } + + return AnchorPosition.Center; + } + + /// + /// Parses the coordinates. + /// + /// The input. + /// The array containing the coordinates + private float[] ParseCoordinates(string input) + { + float[] floats = { }; + + foreach (Match match in CenterRegex.Matches(input)) + { + floats = match.Value.ToPositiveFloatArray(); + } + + return floats; + } + + /// + /// Returns a of sizes to restrict resizing to. + /// + /// + /// The input. + /// + /// + /// The to restrict resizing to. + /// + private List ParseRestrictions(string input) + { + List sizes = new List(); + + if (!string.IsNullOrWhiteSpace(input)) + { + sizes.AddRange(input.Split(',').Select(this.ParseSize)); + } + + return sizes; + } + } +} diff --git a/src/ImageProcessor.Web/Processors/Rotate.cs b/src/ImageProcessor.Web/Processors/Rotate.cs new file mode 100644 index 000000000..7ab41f7da --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Rotate.cs @@ -0,0 +1,96 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to rotate an image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Encapsulates methods to rotate an image. + /// + public class Rotate : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"(rotate|angle)(=|-)[^&|,]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Rotate() + { + this.Processor = new ImageProcessor.Processors.Rotate(); + } + + #region IGraphicsProcessor Members + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder + { + get; + private set; + } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + this.Processor.DynamicParameter = CommonParameterParserUtility.ParseAngle(match.Value); + } + + index += 1; + } + } + + return this.SortOrder; + } + #endregion + } +} diff --git a/src/ImageProcessor.Web/Processors/RoundedCorners.cs b/src/ImageProcessor.Web/Processors/RoundedCorners.cs new file mode 100644 index 000000000..001130c14 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/RoundedCorners.cs @@ -0,0 +1,173 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to add rounded corners to an image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Globalization; + using System.Text.RegularExpressions; + using ImageProcessor.Imaging; + using ImageProcessor.Processors; + + /// + /// Encapsulates methods to add rounded corners to an image. + /// + public class RoundedCorners : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"roundedcorners=[^&]+", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the angle attribute. + /// + private static readonly Regex RadiusRegex = new Regex(@"(roundedcorners|radius)(=|-)(\d+)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the top left attribute. + /// + private static readonly Regex TopLeftRegex = new Regex(@"tl(=|-)(true|false)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the top right attribute. + /// + private static readonly Regex TopRightRegex = new Regex(@"tr(=|-)(true|false)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the bottom left attribute. + /// + private static readonly Regex BottomLeftRegex = new Regex(@"bl(=|-)(true|false)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the bottom right attribute. + /// + private static readonly Regex BottomRightRegex = new Regex(@"br(=|-)(true|false)", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public RoundedCorners() + { + this.Processor = new ImageProcessor.Processors.RoundedCorners(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + + RoundedCornerLayer roundedCornerLayer = new RoundedCornerLayer( + this.ParseRadius(queryString), + this.ParseCorner(TopLeftRegex, queryString), + this.ParseCorner(TopRightRegex, queryString), + this.ParseCorner(BottomLeftRegex, queryString), + this.ParseCorner(BottomRightRegex, queryString)); + + this.Processor.DynamicParameter = roundedCornerLayer; + } + + index += 1; + } + } + + return this.SortOrder; + } + + #region Private Methods + /// + /// Returns the correct containing the radius for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct containing the radius for the given string. + /// + private int ParseRadius(string input) + { + foreach (Match match in RadiusRegex.Matches(input)) + { + // Split on radius- + int radius; + int.TryParse(match.Value.Split(new[] { '=', '-' })[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius); + return radius; + } + + // No corners - matches the RoundedCorner default. + return 0; + } + + /// + /// Returns a either true or false. + /// + /// + /// The corner. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct true or false. + /// + private bool ParseCorner(Regex corner, string input) + { + foreach (Match match in corner.Matches(input)) + { + // Split on corner- + bool cornerRound; + bool.TryParse(match.Value.Split(new[] { '=', '-' })[1], out cornerRound); + return cornerRound; + } + + // No corners - matches the RoundedCorner default. + return true; + } + #endregion + } +} diff --git a/src/ImageProcessor.Web/Processors/Saturation.cs b/src/ImageProcessor.Web/Processors/Saturation.cs new file mode 100644 index 000000000..02a750ab1 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Saturation.cs @@ -0,0 +1,92 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to change the saturation component of the image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Encapsulates methods to change the saturation component of the image. + /// + /// + /// + /// + public class Saturation : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"saturation=[^&|,]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Saturation() + { + this.Processor = new ImageProcessor.Processors.Saturation(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + int percentage = CommonParameterParserUtility.ParseIn100Range(match.Value); + this.Processor.DynamicParameter = percentage; + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Tint.cs b/src/ImageProcessor.Web/Processors/Tint.cs new file mode 100644 index 000000000..73fef8b3f --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Tint.cs @@ -0,0 +1,85 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Tints an image with the given color. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Tints an image with the given color. + /// + public class Tint : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"tint=[^&]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Tint() + { + this.Processor = new ImageProcessor.Processors.Tint(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get { return QueryRegex; } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// The query string to search. + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + this.Processor.DynamicParameter = CommonParameterParserUtility.ParseColor(match.Value); + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Vignette.cs b/src/ImageProcessor.Web/Processors/Vignette.cs new file mode 100644 index 000000000..7dc7259d3 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Vignette.cs @@ -0,0 +1,98 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods with which to add a vignette image effect to an image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Drawing; + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; + + /// + /// Encapsulates methods with which to add a vignette image effect to an image. + /// + public class Vignette : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"vignette(=true)?[^&]+", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Vignette() + { + this.Processor = new ImageProcessor.Processors.Vignette(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + + Color color = CommonParameterParserUtility.ParseColor(match.Value); + if (color.Equals(Color.Transparent)) + { + color = Color.Black; + } + + this.Processor.DynamicParameter = color; + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/Processors/Watermark.cs b/src/ImageProcessor.Web/Processors/Watermark.cs new file mode 100644 index 000000000..0e2afa126 --- /dev/null +++ b/src/ImageProcessor.Web/Processors/Watermark.cs @@ -0,0 +1,341 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to add a watermark text overlay to an image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Drawing; + using System.Drawing.Text; + using System.Globalization; + using System.Linq; + using System.Text.RegularExpressions; + + using ImageProcessor.Imaging; + using ImageProcessor.Processors; + using ImageProcessor.Web.Extensions; + using ImageProcessor.Web.Helpers; + + /// + /// Encapsulates methods to add a watermark text overlay to an image. + /// + public class Watermark : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"watermark=[^&]+", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the text attribute. + /// + private static readonly Regex TextRegex = new Regex(@"(watermark=[^text-]|text-)[^/:?#\[\]@!$&'()*%\|,;=&]+", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the position attribute. + /// + private static readonly Regex PositionRegex = new Regex(@"(text)?position(=|-)\d+[-,]\d+", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the font size attribute. + /// + private static readonly Regex FontSizeRegex = new Regex(@"((font)?)size(=|-)\d{1,3}", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the font style attribute. + /// + private static readonly Regex FontStyleRegex = new Regex(@"((font)?)style(=|-)(bold|italic|regular|strikeout|underline)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the font family attribute. + /// + private static readonly Regex FontFamilyRegex = new Regex(@"font(family)?(=|-)[^/:?#\[\]@!$&'()*%\|,;=0-9]+", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the opacity attribute. + /// + private static readonly Regex OpacityRegex = new Regex(@"((font)?)opacity(=|-)(?:100|[1-9]?[0-9])", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the shadow attribute. + /// + private static readonly Regex ShadowRegex = new Regex(@"((text|font|drop)?)shadow(=|-)true", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Watermark() + { + this.Processor = new ImageProcessor.Processors.Watermark(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + public int MatchRegexIndex(string queryString) + { + int index = 0; + + // Set the sort order to max to allow filtering. + this.SortOrder = int.MaxValue; + + foreach (Match match in this.RegexPattern.Matches(queryString)) + { + if (match.Success) + { + if (index == 0) + { + // Set the index on the first instance only. + this.SortOrder = match.Index; + + TextLayer textLayer = new TextLayer + { + Text = this.ParseText(queryString), + Position = this.ParsePosition(queryString), + FontColor = this.ParseColor(queryString), + FontSize = this.ParseFontSize(queryString), + FontFamily = this.ParseFontFamily(queryString), + Style = this.ParseFontStyle(queryString), + DropShadow = this.ParseDropShadow(queryString) + }; + + textLayer.Opacity = this.ParseOpacity(queryString, textLayer.FontColor); + + this.Processor.DynamicParameter = textLayer; + } + + index += 1; + } + } + + return this.SortOrder; + } + + #region Private Methods + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct for the given string. + /// + private string ParseText(string input) + { + foreach (Match match in TextRegex.Matches(input)) + { + // split on text- + return match.Value.Split(new[] { '=', '-' })[1].Replace("+", " "); + } + + return string.Empty; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct + /// + private Point ParsePosition(string input) + { + foreach (Match match in PositionRegex.Matches(input)) + { + int[] position = match.Value.ToPositiveIntegerArray(); + + if (position != null) + { + int x = position[0]; + int y = position[1]; + + return new Point(x, y); + } + } + + return Point.Empty; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct + /// + private Color ParseColor(string input) + { + Color textColor = CommonParameterParserUtility.ParseColor(input); + if (!textColor.Equals(Color.Transparent)) + { + return textColor; + } + + return Color.Black; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct + /// + private int ParseFontSize(string input) + { + foreach (Match match in FontSizeRegex.Matches(input)) + { + // split on size-value + return int.Parse(match.Value.Split(new[] { '=', '-' })[1], CultureInfo.InvariantCulture); + } + + // Matches the default number in TextLayer. + return 48; + } + + /// + /// Returns the correct for the given string. + /// + /// + /// The string containing the respective font style. + /// + /// + /// The correct + /// + private FontStyle ParseFontStyle(string input) + { + FontStyle fontStyle = FontStyle.Bold; + + foreach (Match match in FontStyleRegex.Matches(input)) + { + // split on style- + switch (match.Value.Split(new[] + { + '=', '-' + })[1]) + { + case "italic": + fontStyle = FontStyle.Italic; + break; + case "regular": + fontStyle = FontStyle.Regular; + break; + case "strikeout": + fontStyle = FontStyle.Strikeout; + break; + case "underline": + fontStyle = FontStyle.Underline; + break; + } + } + + return fontStyle; + } + + /// + /// Returns the correct containing the font family for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct containing the font family for the given string. + /// + private FontFamily ParseFontFamily(string input) + { + foreach (Match match in FontFamilyRegex.Matches(input)) + { + // split on font- + string font = match.Value.Split(new[] { '=', '-' })[1].Replace("+", " "); + + return new FontFamily(font); + } + + return new FontFamily(GenericFontFamilies.SansSerif); + } + + /// + /// Returns the correct containing the opacity for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The of the current . + /// + /// + /// The correct containing the opacity for the given string. + /// + private int ParseOpacity(string input, Color color) + { + if (color.A < 255) + { + return (color.A / 255) * 100; + } + + foreach (Match match in OpacityRegex.Matches(input)) + { + // Split on opacity- + return int.Parse(match.Value.Split(new[] { '=', '-' })[1], CultureInfo.InvariantCulture); + } + + // Full opacity - matches the TextLayer default. + return 100; + } + + /// + /// Returns a value indicating whether the watermark is to have a shadow. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The true if the watermark is to have a shadow; otherwise false. + /// + private bool ParseDropShadow(string input) + { + return ShadowRegex.Matches(input).Cast().Any(); + } + + #endregion + } +} diff --git a/src/ImageProcessor.Web/NET45/Properties/AssemblyInfo.cs b/src/ImageProcessor.Web/Properties/AssemblyInfo.cs similarity index 66% rename from src/ImageProcessor.Web/NET45/Properties/AssemblyInfo.cs rename to src/ImageProcessor.Web/Properties/AssemblyInfo.cs index 831e5543e..4f1c51a1e 100644 --- a/src/ImageProcessor.Web/NET45/Properties/AssemblyInfo.cs +++ b/src/ImageProcessor.Web/Properties/AssemblyInfo.cs @@ -1,14 +1,19 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// AssemblyInfo.cs +// +// -------------------------------------------------------------------------------------------------------------------- + +using System.Reflection; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// 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. -using System.Web; - -using ImageProcessor.Web.HttpModules; - [assembly: AssemblyTitle("ImageProcessor.Web")] [assembly: AssemblyDescription("A library for on-the-fly processing of image files with ASP.NET written in C#")] [assembly: AssemblyConfiguration("James South")] @@ -18,8 +23,8 @@ using ImageProcessor.Web.HttpModules; [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 +// 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)] @@ -29,11 +34,11 @@ using ImageProcessor.Web.HttpModules; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -// You can specify all the values or you can default the Build and Revision Numbers +// You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.3.0.0")] -[assembly: AssemblyFileVersion("3.3.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("4.0.0.0")] +[assembly: AssemblyFileVersion("4.0.0.0")] diff --git a/src/ImageProcessor.Web/Settings.StyleCop b/src/ImageProcessor.Web/Settings.StyleCop new file mode 100644 index 000000000..09dd1de03 --- /dev/null +++ b/src/ImageProcessor.Web/Settings.StyleCop @@ -0,0 +1,7 @@ + + + + dllimport + + + \ No newline at end of file diff --git a/src/ImageProcessor.sln b/src/ImageProcessor.sln index 186a446c7..5009fba41 100644 --- a/src/ImageProcessor.sln +++ b/src/ImageProcessor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -VisualStudioVersion = 12.0.30110.0 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30501.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C427A497-74DC-49B1-8420-D6E68354F29B}" ProjectSection(SolutionItems) = preProject @@ -18,21 +18,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{1E656C EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor", "ImageProcessor\ImageProcessor.csproj", "{3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web.Tests", "Web.Test\Web.Tests.csproj", "{23CE0FC0-9E59-4C93-A604-A4A98A6284D1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test_Website_MVC_NET4", "TestWebsites\NET4\Test_Website_MVC_NET4.csproj", "{30327C08-7574-4D7E-AC95-6A58753C6855}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web", "ImageProcessor.Web\ImageProcessor.Web.csproj", "{D011A778-59C8-4BFA-A770-C350216BF161}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test_Website_MVC_NET45", "TestWebsites\NET45\Test_Website_NET45\Test_Website_MVC_NET45.csproj", "{F6A208E9-C18F-43E9-B051-3C6EED30FDAF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Plugins.WebP", "Plugins\ImageProcessor\ImageProcessor.Plugins.WebP\ImageProcessor.Plugins.WebP.csproj", "{2CF69699-959A-44DC-A281-4E2596C25043}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web_NET4", "ImageProcessor.Web\NET4\ImageProcessor.Web_NET4.csproj", "{4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessorConsole", "ImageProcessorConsole\ImageProcessorConsole.csproj", "{7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web_NET45", "ImageProcessor.Web\NET45\ImageProcessor.Web_NET45.csproj", "{D011A778-59C8-4BFA-A770-C350216BF161}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web.UnitTests", "ImageProcessor.Web.UnitTests\ImageProcessor.Web.UnitTests.csproj", "{961340C8-8C93-401D-A0A2-FF9EC61E5260}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test_Website_Webforms_NET45", "TestWebsites\NET45\Test_Website_Webforms_NET45\Test_Website_Webforms_NET45.csproj", "{8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.UnitTests", "ImageProcessor.UnitTests\ImageProcessor.UnitTests.csproj", "{633B1C4C-4823-47BE-9A01-A665F3118C8C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessorConsole", "ImageProcessorConsole\ImageProcessorConsole.csproj", "{7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web.Tests", "Web.Test\Web.Tests.csproj", "{23CE0FC0-9E59-4C93-A604-A4A98A6284D1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.UnitTests", "ImageProcessor.UnitTests\ImageProcessor.UnitTests.csproj", "{03CA9055-F997-428C-BF28-F50F991777C6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test_Website_MVC", "TestWebsites\MVC\Test_Website_MVC.csproj", "{F6A208E9-C18F-43E9-B051-3C6EED30FDAF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -47,56 +45,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {03CA9055-F997-428C-BF28-F50F991777C6}.All|Any CPU.ActiveCfg = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.All|Any CPU.Build.0 = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.All|Mixed Platforms.ActiveCfg = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.All|Mixed Platforms.Build.0 = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.All|x86.ActiveCfg = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.All|x86.Build.0 = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Debug|x86.ActiveCfg = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Debug|x86.Build.0 = Debug|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Release|Any CPU.Build.0 = Release|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Release|x86.ActiveCfg = Release|Any CPU - {03CA9055-F997-428C-BF28-F50F991777C6}.Release|x86.Build.0 = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|Any CPU.ActiveCfg = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|Any CPU.Build.0 = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|Mixed Platforms.ActiveCfg = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|Mixed Platforms.Build.0 = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|x86.ActiveCfg = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Debug|x86.ActiveCfg = Debug|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|Any CPU.Build.0 = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|x86.ActiveCfg = Release|Any CPU - {30327C08-7574-4D7E-AC95-6A58753C6855}.All|Any CPU.ActiveCfg = All|Any CPU - {30327C08-7574-4D7E-AC95-6A58753C6855}.All|Any CPU.Build.0 = All|Any CPU - {30327C08-7574-4D7E-AC95-6A58753C6855}.All|Mixed Platforms.ActiveCfg = All|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.All|Mixed Platforms.Build.0 = All|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.All|x86.ActiveCfg = All|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.All|x86.Build.0 = All|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {30327C08-7574-4D7E-AC95-6A58753C6855}.Debug|Any CPU.Build.0 = Debug|Any CPU - {30327C08-7574-4D7E-AC95-6A58753C6855}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.Debug|x86.ActiveCfg = Debug|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.Debug|x86.Build.0 = Debug|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.Release|Any CPU.ActiveCfg = Release|Any CPU - {30327C08-7574-4D7E-AC95-6A58753C6855}.Release|Any CPU.Build.0 = Release|Any CPU - {30327C08-7574-4D7E-AC95-6A58753C6855}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.Release|Mixed Platforms.Build.0 = Release|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.Release|x86.ActiveCfg = Release|x86 - {30327C08-7574-4D7E-AC95-6A58753C6855}.Release|x86.Build.0 = Release|x86 {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}.All|Any CPU.ActiveCfg = All|Any CPU {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}.All|Any CPU.Build.0 = All|Any CPU {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}.All|Mixed Platforms.ActiveCfg = All|Any CPU @@ -112,51 +60,6 @@ Global {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}.Release|Mixed Platforms.Build.0 = Release|Any CPU {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}.Release|x86.ActiveCfg = Release|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.All|Any CPU.ActiveCfg = All|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.All|Any CPU.Build.0 = All|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.All|Mixed Platforms.ActiveCfg = All|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.All|Mixed Platforms.Build.0 = All|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.All|x86.ActiveCfg = All|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Debug|x86.ActiveCfg = Debug|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Release|Any CPU.Build.0 = Release|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4F7050F2-465F-4E10-8DB2-2FB97AC6AA43}.Release|x86.ActiveCfg = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|Any CPU.ActiveCfg = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|Any CPU.Build.0 = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|Mixed Platforms.ActiveCfg = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|Mixed Platforms.Build.0 = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|x86.ActiveCfg = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|x86.ActiveCfg = Debug|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|Any CPU.Build.0 = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|x86.ActiveCfg = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.All|Any CPU.ActiveCfg = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.All|Any CPU.Build.0 = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.All|Mixed Platforms.ActiveCfg = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.All|Mixed Platforms.Build.0 = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.All|x86.ActiveCfg = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Debug|x86.ActiveCfg = Debug|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Release|Any CPU.Build.0 = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2}.Release|x86.ActiveCfg = Release|Any CPU {D011A778-59C8-4BFA-A770-C350216BF161}.All|Any CPU.ActiveCfg = Release|Any CPU {D011A778-59C8-4BFA-A770-C350216BF161}.All|Any CPU.Build.0 = Release|Any CPU {D011A778-59C8-4BFA-A770-C350216BF161}.All|Mixed Platforms.ActiveCfg = Release|Any CPU @@ -172,6 +75,80 @@ Global {D011A778-59C8-4BFA-A770-C350216BF161}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {D011A778-59C8-4BFA-A770-C350216BF161}.Release|Mixed Platforms.Build.0 = Release|Any CPU {D011A778-59C8-4BFA-A770-C350216BF161}.Release|x86.ActiveCfg = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.All|Any CPU.ActiveCfg = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.All|Any CPU.Build.0 = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.All|Mixed Platforms.ActiveCfg = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.All|Mixed Platforms.Build.0 = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.All|x86.ActiveCfg = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|x86.ActiveCfg = Debug|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Release|Any CPU.Build.0 = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2CF69699-959A-44DC-A281-4E2596C25043}.Release|x86.ActiveCfg = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|Any CPU.ActiveCfg = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|Any CPU.Build.0 = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|Mixed Platforms.ActiveCfg = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|Mixed Platforms.Build.0 = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.All|x86.ActiveCfg = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Debug|x86.ActiveCfg = Debug|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|Any CPU.Build.0 = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}.Release|x86.ActiveCfg = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.All|Any CPU.ActiveCfg = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.All|Any CPU.Build.0 = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.All|Mixed Platforms.ActiveCfg = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.All|Mixed Platforms.Build.0 = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.All|x86.ActiveCfg = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Debug|Any CPU.Build.0 = Debug|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Debug|x86.ActiveCfg = Debug|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Release|Any CPU.ActiveCfg = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Release|Any CPU.Build.0 = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {961340C8-8C93-401D-A0A2-FF9EC61E5260}.Release|x86.ActiveCfg = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.All|Any CPU.ActiveCfg = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.All|Any CPU.Build.0 = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.All|Mixed Platforms.ActiveCfg = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.All|Mixed Platforms.Build.0 = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.All|x86.ActiveCfg = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Debug|x86.ActiveCfg = Debug|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Release|Any CPU.Build.0 = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {633B1C4C-4823-47BE-9A01-A665F3118C8C}.Release|x86.ActiveCfg = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|Any CPU.ActiveCfg = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|Any CPU.Build.0 = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|Mixed Platforms.ActiveCfg = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|Mixed Platforms.Build.0 = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.All|x86.ActiveCfg = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Debug|x86.ActiveCfg = Debug|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|Any CPU.Build.0 = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {23CE0FC0-9E59-4C93-A604-A4A98A6284D1}.Release|x86.ActiveCfg = Release|Any CPU {F6A208E9-C18F-43E9-B051-3C6EED30FDAF}.All|Any CPU.ActiveCfg = Release|Any CPU {F6A208E9-C18F-43E9-B051-3C6EED30FDAF}.All|Any CPU.Build.0 = Release|Any CPU {F6A208E9-C18F-43E9-B051-3C6EED30FDAF}.All|Mixed Platforms.ActiveCfg = Release|Any CPU @@ -188,14 +165,12 @@ Global {F6A208E9-C18F-43E9-B051-3C6EED30FDAF}.Release|Mixed Platforms.Build.0 = Release|Any CPU {F6A208E9-C18F-43E9-B051-3C6EED30FDAF}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection - GlobalSection(NestedProjects) = preSolution + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = ImageProcessorConsole\ImageProcessorConsole.csproj EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = ImageProcessor.vsmdi EndGlobalSection diff --git a/src/ImageProcessor.sln.DotSettings b/src/ImageProcessor.sln.DotSettings new file mode 100644 index 000000000..824137ce2 --- /dev/null +++ b/src/ImageProcessor.sln.DotSettings @@ -0,0 +1,18 @@ + + BGRA + BPP + DT + FPX + FR + ICC + ISO + JPEG + JPEGAC + JPEGDC + JPEGQ + LPI + MD + OECF + REF + SRGB + SS \ No newline at end of file diff --git a/src/ImageProcessor/Common/Exceptions/ImageFormatException.cs b/src/ImageProcessor/Common/Exceptions/ImageFormatException.cs new file mode 100644 index 000000000..1d4169a88 --- /dev/null +++ b/src/ImageProcessor/Common/Exceptions/ImageFormatException.cs @@ -0,0 +1,40 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The exception that is thrown when loading the supported image format types has failed. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Common.Exceptions +{ + using System; + + /// + /// The exception that is thrown when loading the supported image format types has failed. + /// + [Serializable] + public sealed class ImageFormatException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public ImageFormatException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public ImageFormatException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/ImageProcessor/Common/Exceptions/ImageProcessingException.cs b/src/ImageProcessor/Common/Exceptions/ImageProcessingException.cs new file mode 100644 index 000000000..02b6be4f2 --- /dev/null +++ b/src/ImageProcessor/Common/Exceptions/ImageProcessingException.cs @@ -0,0 +1,40 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The exception that is thrown when processing an image has failed. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Common.Exceptions +{ + using System; + + /// + /// The exception that is thrown when processing an image has failed. + /// + [Serializable] + public sealed class ImageProcessingException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public ImageProcessingException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public ImageProcessingException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/ImageProcessor/Common/Extensions/AssemblyExtensions.cs b/src/ImageProcessor/Common/Extensions/AssemblyExtensions.cs new file mode 100644 index 000000000..e37480ff0 --- /dev/null +++ b/src/ImageProcessor/Common/Extensions/AssemblyExtensions.cs @@ -0,0 +1,50 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates a series of time saving extension methods to the class. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Common.Extensions +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + + /// + /// Encapsulates a series of time saving extension methods to the class. + /// + public static class AssemblyExtensions + { + /// + /// Gets a collection of loadable types from the given assembly. + /// Adapted from + /// + /// + /// The to load the types from. + /// + /// + /// The loadable . + /// + public static IEnumerable GetLoadableTypes(this Assembly assembly) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + + try + { + return assembly.GetTypes(); + } + catch (ReflectionTypeLoadException ex) + { + return ex.Types.Where(t => t != null); + } + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Extensions/DoubleExtensions.cs b/src/ImageProcessor/Common/Extensions/DoubleExtensions.cs similarity index 97% rename from src/ImageProcessor/Extensions/DoubleExtensions.cs rename to src/ImageProcessor/Common/Extensions/DoubleExtensions.cs index a21817df1..acc5b12c3 100644 --- a/src/ImageProcessor/Extensions/DoubleExtensions.cs +++ b/src/ImageProcessor/Common/Extensions/DoubleExtensions.cs @@ -8,7 +8,7 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Extensions +namespace ImageProcessor.Common.Extensions { /// /// Encapsulates a series of time saving extension methods to the class. diff --git a/src/ImageProcessor/Extensions/IntegerExtensions.cs b/src/ImageProcessor/Common/Extensions/IntegerExtensions.cs similarity index 97% rename from src/ImageProcessor/Extensions/IntegerExtensions.cs rename to src/ImageProcessor/Common/Extensions/IntegerExtensions.cs index d969e780e..e04798c0b 100644 --- a/src/ImageProcessor/Extensions/IntegerExtensions.cs +++ b/src/ImageProcessor/Common/Extensions/IntegerExtensions.cs @@ -8,7 +8,7 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Extensions +namespace ImageProcessor.Common.Extensions { using System.Globalization; diff --git a/src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs b/src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs new file mode 100644 index 000000000..89b4ddee1 --- /dev/null +++ b/src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs @@ -0,0 +1,161 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The ImageProcessor bootstrapper. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Configuration +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using System.IO; + using System.Linq; + using System.Reflection; + + using ImageProcessor.Common.Extensions; + using ImageProcessor.Imaging.Formats; + + /// + /// The ImageProcessor bootstrapper. + /// + public class ImageProcessorBootstrapper + { + /// + /// A new instance Initializes a new instance of the class. + /// with lazy initialization. + /// + private static readonly Lazy Lazy = + new Lazy(() => new ImageProcessorBootstrapper()); + + /// + /// Prevents a default instance of the class from being created. + /// + private ImageProcessorBootstrapper() + { + this.NativeBinaryFactory = new NativeBinaryFactory(); + this.LoadSupportedImageFormats(); + } + + /// + /// Gets the current instance of the class. + /// + public static ImageProcessorBootstrapper Instance + { + get + { + return Lazy.Value; + } + } + + /// + /// Gets the supported image formats. + /// + public IEnumerable SupportedImageFormats { get; private set; } + + /// + /// Gets the native binary factory for registering embedded (unmanaged) binaries. + /// + public NativeBinaryFactory NativeBinaryFactory { get; private set; } + + /// + /// Creates a list, using reflection, of supported image formats that ImageProcessor can run. + /// + private void LoadSupportedImageFormats() + { + if (this.SupportedImageFormats == null) + { + Type type = typeof(ISupportedImageFormat); + + // Get any referenced but not used assemblies. + Assembly executingAssembly = Assembly.GetExecutingAssembly(); + string targetBasePath = Path.GetDirectoryName(new Uri(executingAssembly.Location).LocalPath); + + // ReSharper disable once AssignNullToNotNullAttribute + FileInfo[] files = new DirectoryInfo(targetBasePath).GetFiles("*.dll", SearchOption.AllDirectories); + + HashSet found = new HashSet(); + foreach (FileInfo fileInfo in files) + { + try + { + AssemblyName assemblyName = AssemblyName.GetAssemblyName(fileInfo.FullName); + + if (!AppDomain.CurrentDomain.GetAssemblies() + .Any(a => AssemblyName.ReferenceMatchesDefinition(assemblyName, a.GetName()))) + { + // In a web app, this assembly will automatically be bound from the + // Asp.Net Temporary folder from where the site actually runs. + Assembly.Load(assemblyName); + this.LoadReferencedAssemblies(found, Assembly.Load(assemblyName)); + } + } + catch (Exception ex) + { + // Log the exception for debugging only. There could be any old junk + // thrown in to the bin folder by someone else. + Debug.WriteLine(ex.Message); + } + } + + List availableTypes = AppDomain.CurrentDomain + .GetAssemblies() + .SelectMany(a => a.GetLoadableTypes()) + .Where(t => type.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract) + .ToList(); + + this.SupportedImageFormats = availableTypes + .Select(f => (Activator.CreateInstance(f) as ISupportedImageFormat)).ToList(); + } + } + + /// + /// Loads any referenced assemblies into the current application domain. + /// + /// + /// The collection containing the name of already found assemblies. + /// + /// + /// The assembly to load from. + /// + private void LoadReferencedAssemblies(HashSet found, Assembly assembly) + { + // Used to avoid duplicates + ArrayList results = new ArrayList(); + + // Resulting info + Stack stack = new Stack(); + + // Stack of names + // Store root assembly (level 0) directly into results list + stack.Push(assembly.ToString()); + + // Do a pre-order, non-recursive traversal + while (stack.Count > 0) + { + string info = (string)stack.Pop(); + + // Get next assembly + if (!found.Contains(info)) + { + found.Add(info); + results.Add(info); + + // Store it to results ArrayList + Assembly child = Assembly.Load(info); + AssemblyName[] subchild = child.GetReferencedAssemblies(); + + for (int i = subchild.Length - 1; i >= 0; --i) + { + stack.Push(subchild[i].ToString()); + } + } + } + } + } +} diff --git a/src/ImageProcessor/Configuration/NativeBinaryFactory.cs b/src/ImageProcessor/Configuration/NativeBinaryFactory.cs new file mode 100644 index 000000000..16ab92261 --- /dev/null +++ b/src/ImageProcessor/Configuration/NativeBinaryFactory.cs @@ -0,0 +1,216 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Controls the loading and unloading of any native binaries required by ImageProcessor. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Configuration +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Reflection; + + /// + /// Controls the loading and unloading of any native binaries required by ImageProcessor. + /// + public class NativeBinaryFactory : IDisposable + { + /// + /// Whether the process is running in 64bit mode. Used for calling the correct dllimport method. + /// + private static readonly bool Is64Bit = Environment.Is64BitProcess; + + /// + /// The native binaries. + /// + private static ConcurrentDictionary nativeBinaries; + + /// + /// A value indicating whether this instance of the given entity has been disposed. + /// + /// if this instance has been disposed; otherwise, . + /// + /// If the entity is disposed, it must not be disposed a second + /// time. The isDisposed field is set the first time the entity + /// is disposed. If the isDisposed field is true, then the Dispose() + /// method will not dispose again. This help not to prolong the entity's + /// life in the Garbage Collector. + /// + private bool isDisposed; + + /// + /// Initializes a new instance of the class. + /// + public NativeBinaryFactory() + { + nativeBinaries = new ConcurrentDictionary(); + } + + /// + /// Finalizes an instance of the ImageFactory class. + /// + /// + /// Use C# destructor syntax for finalization code. + /// This destructor will run only if the Dispose method + /// does not get called. + /// It gives your base class the opportunity to finalize. + /// Do not provide destructors in types derived from this class. + /// + ~NativeBinaryFactory() + { + // Do not re-create Dispose clean-up code here. + // Calling Dispose(false) is optimal in terms of + // readability and maintainability. + this.Dispose(false); + } + + /// + /// Gets a value indicating whether the operating environment is 64 bit. + /// + public bool Is64BitEnvironment + { + get + { + return Is64Bit; + } + } + + /// + /// Registers any embedded native (unmanaged) binaries required by ImageProcessor. + /// + /// + /// The name of the native binary. + /// + /// + /// The resource bytes containing the native binary. + /// + /// + /// Thrown if the binary cannot be registered. + /// + public void RegisterNativeBinary(string name, byte[] resourceBytes) + { + nativeBinaries.GetOrAdd( + name, + b => + { + IntPtr pointer; + string folder = Is64BitEnvironment ? "x64" : "x86"; + Assembly assembly = Assembly.GetExecutingAssembly(); + string targetBasePath = new Uri(assembly.Location).LocalPath; + string targetPath = Path.GetFullPath(Path.Combine(targetBasePath, "..\\" + folder + "\\" + name)); + + // Copy the file across if necessary. + FileInfo fileInfo = new FileInfo(targetPath); + bool rewrite = true; + if (fileInfo.Exists) + { + byte[] existing = File.ReadAllBytes(targetPath); + + if (resourceBytes.SequenceEqual(existing)) + { + rewrite = false; + } + } + + if (rewrite) + { + // ReSharper disable once AssignNullToNotNullAttribute + DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(targetPath)); + if (!directoryInfo.Exists) + { + directoryInfo.Create(); + } + + File.WriteAllBytes(targetPath, resourceBytes); + } + + try + { +#if !__MonoCS__ + // Load the binary into memory. + pointer = NativeMethods.LoadLibrary(targetPath); +#else + // Load the binary into memory. The second parameter forces it to load immediately. + pointer = NativeMethods.dlopen(targetPath, 2); +#endif + } + catch (Exception ex) + { + throw new ApplicationException(ex.Message); + } + + if (pointer == IntPtr.Zero) + { + throw new ApplicationException("Cannot load " + name); + } + + return pointer; + }); + } + + /// + /// Disposes the object and frees resources for the Garbage Collector. + /// + public void Dispose() + { + this.Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// Disposes the object and frees resources for the Garbage Collector. + /// + /// If true, the object gets disposed. + protected virtual void Dispose(bool disposing) + { + if (this.isDisposed) + { + return; + } + + if (disposing) + { + // Dispose of any managed resources here. + } + + // Call the appropriate methods to clean up + // unmanaged resources here. + this.FreeNativeBinaries(); + + // Note disposing is done. + this.isDisposed = true; + } + + /// + /// Frees the reference to the native binaries. + /// + private void FreeNativeBinaries() + { + foreach (KeyValuePair nativeBinary in nativeBinaries) + { + IntPtr pointer = nativeBinary.Value; + +#if !__MonoCS__ + // According to http://stackoverflow.com/a/2445558/427899 you need to call this twice. + NativeMethods.FreeLibrary(pointer); + NativeMethods.FreeLibrary(pointer); +#else + NativeMethods.dlclose(pointer); +#endif + } + } + } +} diff --git a/src/ImageProcessor/Configuration/NativeMethods.cs b/src/ImageProcessor/Configuration/NativeMethods.cs new file mode 100644 index 000000000..895de7fe5 --- /dev/null +++ b/src/ImageProcessor/Configuration/NativeMethods.cs @@ -0,0 +1,72 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides access to unmanaged native methods. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Configuration +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Provides access to unmanaged native methods. + /// + internal class NativeMethods + { + /// + /// Loads the specified module into the address space of the calling process. + /// The specified module may cause other modules to be loaded. + /// + /// + /// The name of the module. This can be either a library module or + /// an executable module. + /// + /// If the function succeeds, the return value is a handle to the module; otherwise null. + [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)] + public static extern IntPtr LoadLibrary(string libname); + + /// + /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. + /// When the reference count reaches zero, the module is unloaded from the address space of the calling + /// process and the handle is no longer valid. + /// + /// A handle to the loaded library module. + /// The LoadLibrary, LoadLibraryEx, GetModuleHandle, or GetModuleHandleEx function returns this handle. + /// If the function succeeds, the return value is nonzero; otherwise zero. + [DllImport("kernel32", SetLastError = true)] + public static extern bool FreeLibrary(IntPtr hModule); + + /// + /// Loads the specified module into the address space of the calling process. + /// The specified module may cause other modules to be loaded. + /// + /// + /// The name of the module. This can be either a library module or + /// an executable module. + /// + /// + /// The flag indicating whether to load the library immediately or lazily. + /// + /// + /// If the function succeeds, the return value is a handle to the module; otherwise null. + /// + [System.Runtime.InteropServices.DllImport("libdl")] + public static extern IntPtr dlopen(string libname, int flags); + + /// + /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. + /// When the reference count reaches zero, the module is unloaded from the address space of the calling + /// process and the handle is no longer valid. + /// + /// A handle to the loaded library module. + /// The LoadLibrary, LoadLibraryEx, GetModuleHandle, or GetModuleHandleEx function returns this handle. + /// If the function succeeds, the return value is nonzero; otherwise zero. + [System.Runtime.InteropServices.DllImport("libdl")] + public static extern int dlclose(IntPtr hModule); + } +} diff --git a/src/ImageProcessor/Extensions/ImageExtensions.cs b/src/ImageProcessor/Extensions/ImageExtensions.cs deleted file mode 100644 index a4134016e..000000000 --- a/src/ImageProcessor/Extensions/ImageExtensions.cs +++ /dev/null @@ -1,98 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Encapsulates a series of time saving extension methods to the class. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Extensions -{ - using System; - using System.Collections.Generic; - using System.Drawing; - using System.Drawing.Imaging; - using ImageProcessor.Imaging; - - /// - /// Encapsulates a series of time saving extension methods to the class. - /// - public static class ImageExtensions - { - /// - /// Returns information about the given . - /// - /// - /// The image to extend. - /// - /// - /// The image format. - /// - /// - /// Whether to fetch the images frames. - /// - /// - /// The . - /// - public static ImageInfo GetImageInfo(this Image image, ImageFormat format, bool fetchFrames = true) - { - ImageInfo info = new ImageInfo - { - Height = image.Height, - Width = image.Width, - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - IsIndexed = (image.PixelFormat & PixelFormat.Indexed) != 0 - }; - - if (image.RawFormat.Guid == ImageFormat.Gif.Guid && format.Guid == ImageFormat.Gif.Guid) - { - 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(); - - for (int f = 0; f < frameCount; f++) - { - int thisDelay = BitConverter.ToInt32(image.GetPropertyItem(20736).Value, index); - int toAddDelay = thisDelay * 10 < 20 ? 20 : thisDelay * 10; // Minimum delay is 20 ms - - // Find the frame - image.SelectActiveFrame(frameDimension, f); - - // TODO: Get positions. - gifFrames.Add(new GifFrame { Delay = toAddDelay, Image = (Image)image.Clone() }); - - // Reset the position. - if (f == last) - { - image.SelectActiveFrame(frameDimension, 0); - } - - delay += toAddDelay; - index += 4; - } - - info.GifFrames = gifFrames; - info.AnimationLength = delay; - - // Loop info is stored at byte 20737. - info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0); - info.IsLooped = info.LoopCount != 1; - } - } - } - - return info; - } - } -} diff --git a/src/ImageProcessor/Extensions/ImageFormatExtensions.cs b/src/ImageProcessor/Extensions/ImageFormatExtensions.cs deleted file mode 100644 index 036a4153e..000000000 --- a/src/ImageProcessor/Extensions/ImageFormatExtensions.cs +++ /dev/null @@ -1,149 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Encapsulates a series of time saving extension methods to the -// class. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Extensions -{ - #region - using System.Drawing.Imaging; - using System.Linq; - #endregion - - /// - /// Encapsulates a series of time saving extension methods to the class. - /// - public static class ImageFormatExtensions - { - /// - /// Gets the correct mime-type for the given . - /// - /// The . - /// The correct mime-type for the given . - public static string GetMimeType(this ImageFormat imageFormat) - { - if (imageFormat.Equals(ImageFormat.Icon)) - { - return "image/x-icon"; - } - - ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); - return codecs.First(codec => codec.FormatID == imageFormat.Guid).MimeType; - } - - /// - /// Gets the name for the given . - /// - /// - /// The to get the name for. - /// - /// - /// The representing the name of the . - /// - public static string GetName(this ImageFormat format) - { - if (format.Guid == ImageFormat.MemoryBmp.Guid) - { - return "MemoryBMP"; - } - - if (format.Guid == ImageFormat.Bmp.Guid) - { - return "Bmp"; - } - - if (format.Guid == ImageFormat.Emf.Guid) - { - return "Emf"; - } - - if (format.Guid == ImageFormat.Wmf.Guid) - { - return "Wmf"; - } - - if (format.Guid == ImageFormat.Gif.Guid) - { - return "Gif"; - } - - if (format.Guid == ImageFormat.Jpeg.Guid) - { - return "Jpeg"; - } - - if (format.Guid == ImageFormat.Png.Guid) - { - return "Png"; - } - - if (format.Guid == ImageFormat.Tiff.Guid) - { - return "Tiff"; - } - - if (format.Guid == ImageFormat.Exif.Guid) - { - return "Exif"; - } - - if (format.Guid == ImageFormat.Icon.Guid) - { - return "Icon"; - } - - return "[ImageFormat: " + format.Guid + "]"; - } - - /// - /// Returns the correct file extension for the given . - /// - /// - /// The to return the extension for. - /// - /// - /// The original Extension. - /// - /// - /// The correct file extension for the given . - /// - public static string GetFileExtension(this ImageFormat imageFormat, string originalExtension) - { - string name = imageFormat.GetName(); - - switch (name) - { - case "Icon": - return ".ico"; - case "Gif": - return ".gif"; - case "Bmp": - return ".bmp"; - case "Png": - return ".png"; - case "Tiff": - if (!string.IsNullOrWhiteSpace(originalExtension) && originalExtension.ToUpperInvariant() == ".TIF") - { - return ".tif"; - } - - return ".tiff"; - case "Jpeg": - if (!string.IsNullOrWhiteSpace(originalExtension) && originalExtension.ToUpperInvariant() == ".JPG") - { - return ".jpg"; - } - - break; - } - - return null; - } - } -} \ No newline at end of file diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs index c82fbd882..6b87c0ca9 100644 --- a/src/ImageProcessor/ImageFactory.cs +++ b/src/ImageProcessor/ImageFactory.cs @@ -14,15 +14,14 @@ namespace ImageProcessor using System; using System.Collections.Concurrent; using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Drawing.Imaging; using System.IO; - using System.Linq; - using System.Threading; - using ImageProcessor.Extensions; + + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging; using ImageProcessor.Imaging.Filters; + using ImageProcessor.Imaging.Formats; using ImageProcessor.Processors; #endregion @@ -33,24 +32,14 @@ namespace ImageProcessor { #region Fields /// - /// The default quality for jpeg files. - /// - private const int DefaultJpegQuality = 90; - - /// - /// The backup image format. + /// The default quality for image files. /// - private ImageFormat backupImageFormat; + private const int DefaultQuality = 90; /// - /// The memory stream for storing any input stream to prevent disposal. + /// The backup supported image format. /// - private MemoryStream inputStream; - - /// - /// Whether the image is indexed. - /// - private bool isIndexed; + private ISupportedImageFormat backupFormat; /// /// A value indicating whether this instance of the given entity has been disposed. @@ -101,41 +90,20 @@ namespace ImageProcessor #endregion #region Properties - /// - /// Gets the local image for manipulation. - /// - public Image Image { get; private set; } - /// /// Gets the path to the local image for manipulation. /// public string ImagePath { get; private set; } - /// - /// Gets the query-string parameters for web image manipulation. - /// - public string QueryString { get; private set; } - /// /// Gets a value indicating whether the image factory should process the file. /// public bool ShouldProcess { get; private set; } /// - /// Gets the file format of the image. + /// Gets the supported image format. /// - public ImageFormat ImageFormat { get; private set; } - - /// - /// Gets the mime type. - /// - public string MimeType - { - get - { - return this.ImageFormat.GetMimeType(); - } - } + public ISupportedImageFormat CurrentImageFormat { get; private set; } /// /// Gets or sets a value indicating whether to preserve exif metadata. @@ -148,44 +116,52 @@ namespace ImageProcessor public ConcurrentDictionary ExifPropertyItems { get; set; } /// - /// Gets or sets the original extension. + /// Gets or the local image for manipulation. /// - internal string OriginalExtension { get; set; } + public Image Image { get; internal set; } /// - /// Gets or sets the quality of output for jpeg images as a percentile. + /// Gets or sets the stream for storing any input stream to prevent disposal. /// - internal int JpegQuality { get; set; } + internal Stream InputStream { get; set; } #endregion #region Methods /// /// Loads the image to process. Always call this method first. /// - /// - /// The containing the image information. + /// + /// The containing the image information. /// /// /// The current instance of the class. /// - public ImageFactory Load(MemoryStream memoryStream) + public ImageFactory Load(Stream stream) { + ISupportedImageFormat format = FormatUtilities.GetFormat(stream); + + if (format == null) + { + throw new ImageFormatException("Input stream is not a supported format."); + } + // Set our image as the memory stream value. - this.Image = Image.FromStream(memoryStream, true); + this.Image = format.Load(stream); // Store the stream so we can dispose of it later. - this.inputStream = memoryStream; + this.InputStream = stream; // Set the other properties. - this.JpegQuality = DefaultJpegQuality; - this.ImageFormat = this.Image.RawFormat; - this.backupImageFormat = this.ImageFormat; - this.isIndexed = ImageUtils.IsIndexed(this.Image); + format.Quality = DefaultQuality; + format.IsIndexed = FormatUtilities.IsIndexed(this.Image); + this.backupFormat = format; + this.CurrentImageFormat = format; // Always load the data. - foreach (PropertyItem propertyItem in this.Image.PropertyItems) + // TODO. Some custom data doesn't seem to get copied by default methods. + foreach (int id in this.Image.PropertyIdList) { - this.ExifPropertyItems[propertyItem.Id] = propertyItem; + this.ExifPropertyItems[id] = this.Image.GetPropertyItem(id); } this.ShouldProcess = true; @@ -202,24 +178,21 @@ namespace ImageProcessor /// public ImageFactory Load(string imagePath) { - // Remove any querystring parameters passed by web requests. - string[] paths = imagePath.Split('?'); - string path = paths[0]; - string query = string.Empty; - - if (paths.Length > 1) - { - query = paths[1]; - } - - if (File.Exists(path)) + FileInfo fileInfo = new FileInfo(imagePath); + if (fileInfo.Exists) { - this.ImagePath = path; - this.QueryString = query; + this.ImagePath = imagePath; // Open a file stream to prevent the need for lock. - using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read)) + using (FileStream fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read)) { + ISupportedImageFormat format = FormatUtilities.GetFormat(fileStream); + + if (format == null) + { + throw new ImageFormatException("Input stream is not a supported format."); + } + MemoryStream memoryStream = new MemoryStream(); // Copy the stream. @@ -229,18 +202,16 @@ namespace ImageProcessor fileStream.Position = memoryStream.Position = 0; // Set our image as the memory stream value. - this.Image = Image.FromStream(memoryStream, true); + this.Image = format.Load(memoryStream); // Store the stream so we can dispose of it later. - this.inputStream = memoryStream; + this.InputStream = memoryStream; // Set the other properties. - this.JpegQuality = DefaultJpegQuality; - ImageFormat imageFormat = this.Image.RawFormat; - this.backupImageFormat = imageFormat; - this.OriginalExtension = Path.GetExtension(this.ImagePath); - this.ImageFormat = imageFormat; - this.isIndexed = ImageUtils.IsIndexed(this.Image); + format.Quality = DefaultQuality; + format.IsIndexed = FormatUtilities.IsIndexed(this.Image); + this.backupFormat = format; + this.CurrentImageFormat = format; // Always load the data. foreach (PropertyItem propertyItem in this.Image.PropertyItems) @@ -251,22 +222,9 @@ namespace ImageProcessor this.ShouldProcess = true; } } - - return this; - } - - /// - /// Updates the specified image. Used by the various IProcessors. - /// - /// The image. - /// - /// The current instance of the class. - /// - public ImageFactory Update(Image image) - { - if (this.ShouldProcess) + else { - this.Image = image; + throw new FileNotFoundException(imagePath); } return this; @@ -283,39 +241,25 @@ namespace ImageProcessor if (this.ShouldProcess) { // Set our new image as the memory stream value. - Image newImage = Image.FromStream(this.inputStream, true); +#if !__MonoCS__ + Image newImage = Image.FromStream(this.InputStream, true); +#else + Image newImage = Image.FromStream(this.InputStream); +#endif // Dispose and reassign the image. this.Image.Dispose(); this.Image = newImage; // Set the other properties. - this.JpegQuality = DefaultJpegQuality; - this.ImageFormat = this.backupImageFormat; - this.isIndexed = ImageUtils.IsIndexed(this.Image); + this.CurrentImageFormat = this.backupFormat; + this.CurrentImageFormat.Quality = DefaultQuality; } return this; } #region Manipulation - /// - /// Adds a query-string to the image factory to allow auto-processing of remote files. - /// - /// The query-string parameter to process. - /// - /// The current instance of the class. - /// - public ImageFactory AddQueryString(string query) - { - if (this.ShouldProcess) - { - this.QueryString = query; - } - - return this; - } - /// /// Changes the opacity of the current image. /// @@ -337,7 +281,7 @@ namespace ImageProcessor } Alpha alpha = new Alpha { DynamicParameter = percentage }; - this.ApplyProcessor(alpha.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(alpha.ProcessImage, this); } return this; @@ -355,7 +299,7 @@ namespace ImageProcessor if (this.ShouldProcess) { AutoRotate autoRotate = new AutoRotate(); - this.ApplyProcessor(autoRotate.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(autoRotate.ProcessImage, this); } return this; @@ -382,7 +326,27 @@ namespace ImageProcessor } Brightness brightness = new Brightness { DynamicParameter = percentage }; - this.ApplyProcessor(brightness.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(brightness.ProcessImage, this); + } + + return this; + } + + /// + /// Changes the background color of the current image. + /// + /// + /// The to paint the image with. + /// + /// + /// The current instance of the class. + /// + public ImageFactory BackgroundColor(Color color) + { + if (this.ShouldProcess) + { + BackgroundColor backgroundColor = new BackgroundColor { DynamicParameter = color }; + this.CurrentImageFormat.ApplyProcessor(backgroundColor.ProcessImage, this); } return this; @@ -401,7 +365,7 @@ namespace ImageProcessor { if (this.ShouldProcess) { - ResizeLayer layer = new ResizeLayer(size, Color.Transparent, ResizeMode.Max); + ResizeLayer layer = new ResizeLayer(size, ResizeMode.Max); return this.Resize(layer); } @@ -430,7 +394,7 @@ namespace ImageProcessor } Contrast contrast = new Contrast { DynamicParameter = percentage }; - this.ApplyProcessor(contrast.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(contrast.ProcessImage, this); } return this; @@ -460,7 +424,7 @@ namespace ImageProcessor /// Crops the current image to the given location and size. /// /// - /// The containing the coordinates and mode to crop the image with. + /// The containing the coordinates and mode to crop the image with. /// /// /// The current instance of the class. @@ -470,28 +434,7 @@ namespace ImageProcessor if (this.ShouldProcess) { Crop crop = new Crop { DynamicParameter = cropLayer }; - this.ApplyProcessor(crop.ProcessImage); - } - - return this; - } - - /// - /// Applies a filter to the current image. - /// - /// - /// The name of the filter to add to the image. - /// - /// - /// The current instance of the class. - /// - [Obsolete("Will be removed in next major version. Filter(IMatrixFilter matrixFilter) instead.")] - public ImageFactory Filter(string filterName) - { - if (this.ShouldProcess) - { - Filter filter = new Filter { DynamicParameter = filterName }; - this.ApplyProcessor(filter.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(crop.ProcessImage, this); } return this; @@ -512,7 +455,7 @@ namespace ImageProcessor if (this.ShouldProcess) { Filter filter = new Filter { DynamicParameter = matrixFilter }; - this.ApplyProcessor(filter.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(filter.ProcessImage, this); } return this; @@ -527,16 +470,16 @@ namespace ImageProcessor /// /// The current instance of the class. /// - public ImageFactory Flip(bool flipVertically) + public ImageFactory Flip(bool flipVertically = false) { if (this.ShouldProcess) { - RotateFlipType rotateFlipType = flipVertically == false - ? RotateFlipType.RotateNoneFlipX - : RotateFlipType.RotateNoneFlipY; + RotateFlipType rotateFlipType = flipVertically + ? RotateFlipType.RotateNoneFlipY + : RotateFlipType.RotateNoneFlipX; Flip flip = new Flip { DynamicParameter = rotateFlipType }; - this.ApplyProcessor(flip.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(flip.ProcessImage, this); } return this; @@ -545,18 +488,15 @@ namespace ImageProcessor /// /// Sets the output format of the current image to the matching . /// - /// The . to set the image to. - /// Whether the pixel format of the image should be indexed. Used for generating Png8 images. + /// The . to set the image to. /// /// The current instance of the class. /// - [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")] - public ImageFactory Format(ImageFormat imageFormat, bool indexedFormat = false) + public ImageFactory Format(ISupportedImageFormat format) { if (this.ShouldProcess) { - this.isIndexed = indexedFormat; - this.ImageFormat = imageFormat; + this.CurrentImageFormat = format; } return this; @@ -603,7 +543,7 @@ namespace ImageProcessor if (this.ShouldProcess) { GaussianBlur gaussianBlur = new GaussianBlur { DynamicParameter = gaussianLayer }; - this.ApplyProcessor(gaussianBlur.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(gaussianBlur.ProcessImage, this); } return this; @@ -650,7 +590,7 @@ namespace ImageProcessor if (this.ShouldProcess) { GaussianSharpen gaussianSharpen = new GaussianSharpen { DynamicParameter = gaussianLayer }; - this.ApplyProcessor(gaussianSharpen.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(gaussianSharpen.ProcessImage, this); } return this; @@ -670,7 +610,7 @@ namespace ImageProcessor { if (this.ShouldProcess) { - this.JpegQuality = percentage; + this.CurrentImageFormat.Quality = percentage; } return this; @@ -712,10 +652,10 @@ namespace ImageProcessor { if (this.ShouldProcess) { - var resizeSettings = new Dictionary { { "MaxWidth", resizeLayer.Size.Width.ToString("G") }, { "MaxHeight", resizeLayer.Size.Height.ToString("G") } }; + Dictionary resizeSettings = new Dictionary { { "MaxWidth", resizeLayer.Size.Width.ToString("G") }, { "MaxHeight", resizeLayer.Size.Height.ToString("G") } }; Resize resize = new Resize { DynamicParameter = resizeLayer, Settings = resizeSettings }; - this.ApplyProcessor(resize.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(resize.ProcessImage, this); } return this; @@ -724,24 +664,51 @@ namespace ImageProcessor /// /// Rotates the current image by the given angle. /// - /// - /// The containing the properties to rotate the image. + /// + /// The angle at which to rotate the image in degrees. /// /// /// The current instance of the class. /// - public ImageFactory Rotate(RotateLayer rotateLayer) + public ImageFactory Rotate(int degrees) { if (this.ShouldProcess) { // Sanitize the input. - if (rotateLayer.Angle > 360 || rotateLayer.Angle < 0) + if (degrees > 360 || degrees < 0) { - rotateLayer.Angle = 0; + degrees = 0; } - Rotate rotate = new Rotate { DynamicParameter = rotateLayer }; - this.ApplyProcessor(rotate.ProcessImage); + Rotate rotate = new Rotate { DynamicParameter = degrees }; + this.CurrentImageFormat.ApplyProcessor(rotate.ProcessImage, this); + } + + return this; + } + + /// + /// Adds rounded corners to the current image. + /// + /// + /// The radius at which the corner will be rounded. + /// + /// + /// The current instance of the class. + /// + public ImageFactory RoundedCorners(int radius) + { + if (this.ShouldProcess) + { + if (radius < 0) + { + radius = 0; + } + + RoundedCornerLayer roundedCornerLayer = new RoundedCornerLayer(radius); + + RoundedCorners roundedCorners = new RoundedCorners { DynamicParameter = roundedCornerLayer }; + this.CurrentImageFormat.ApplyProcessor(roundedCorners.ProcessImage, this); } return this; @@ -766,7 +733,7 @@ namespace ImageProcessor } RoundedCorners roundedCorners = new RoundedCorners { DynamicParameter = roundedCornerLayer }; - this.ApplyProcessor(roundedCorners.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(roundedCorners.ProcessImage, this); } return this; @@ -793,7 +760,7 @@ namespace ImageProcessor } Saturation saturate = new Saturation { DynamicParameter = percentage }; - this.ApplyProcessor(saturate.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(saturate.ProcessImage, this); } return this; @@ -813,7 +780,7 @@ namespace ImageProcessor if (this.ShouldProcess) { Tint tint = new Tint { DynamicParameter = color }; - this.ApplyProcessor(tint.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(tint.ProcessImage, this); } return this; @@ -822,15 +789,24 @@ namespace ImageProcessor /// /// Adds a vignette image effect to the current image. /// + /// + /// The to tint the image with. Defaults to black. + /// /// /// The current instance of the class. /// - public ImageFactory Vignette() + public ImageFactory Vignette(Color? color = null) { if (this.ShouldProcess) { - Vignette vignette = new Vignette(); - this.ApplyProcessor(vignette.ProcessImage); + Vignette vignette = new Vignette + { + DynamicParameter = color.HasValue && !color.Equals(Color.Transparent) + ? color.Value + : Color.Black + }; + + this.CurrentImageFormat.ApplyProcessor(vignette.ProcessImage, this); } return this; @@ -851,7 +827,7 @@ namespace ImageProcessor if (this.ShouldProcess) { Watermark watermark = new Watermark { DynamicParameter = textLayer }; - this.ApplyProcessor(watermark.ProcessImage); + this.CurrentImageFormat.ApplyProcessor(watermark.ProcessImage, this); } return this; @@ -859,7 +835,9 @@ namespace ImageProcessor #endregion /// - /// Saves the current image to the specified file path. + /// Saves the current image to the specified file path. If the extension does not + /// match the correct extension for the current format it will be replaced by the + /// correct default value. /// /// The path to save the image to. /// @@ -869,93 +847,14 @@ namespace ImageProcessor { if (this.ShouldProcess) { - // We need to check here if the path has an extension and remove it if so. - // This is so we can add the correct image format. - int length = filePath.LastIndexOf(".", StringComparison.Ordinal); - string extension = this.ImageFormat.GetFileExtension(this.OriginalExtension); - - if (length == -1) - { - filePath = filePath + extension; - } - - // Fix the colour palette of indexed images. - this.FixIndexedPallete(); - - // 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 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. - } - } - } - // ReSharper disable once AssignNullToNotNullAttribute DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(filePath)); - - if (this.ImageFormat.Equals(ImageFormat.Jpeg)) - { - // Jpegs can be saved with different settings to include a quality setting for the JPEG compression. - // This improves output compression and quality. - using (EncoderParameters encoderParameters = ImageUtils.GetEncodingParameters(this.JpegQuality)) - { - ImageCodecInfo imageCodecInfo = - ImageCodecInfo.GetImageEncoders() - .FirstOrDefault(ici => ici.MimeType.Equals(this.MimeType, StringComparison.OrdinalIgnoreCase)); - - if (imageCodecInfo != null) - { - for (int i = 0; i < 3; i++) - { - try - { - if (!directoryInfo.Exists) - { - directoryInfo.Create(); - } - - this.Image.Save(filePath, imageCodecInfo, encoderParameters); - break; - } - catch (Exception) - { - Thread.Sleep(200); - } - } - } - } - } - else + if (!directoryInfo.Exists) { - for (int i = 0; i < 3; i++) - { - try - { - if (!directoryInfo.Exists) - { - directoryInfo.Create(); - } - - this.Image.Save(filePath, this.ImageFormat); - break; - } - catch (Exception) - { - Thread.Sleep(200); - } - } + directoryInfo.Create(); } + + this.Image = this.CurrentImageFormat.Save(filePath, this.Image); } return this; @@ -964,58 +863,17 @@ namespace ImageProcessor /// /// Saves the current image to the specified output stream. /// - /// + /// /// The to save the image information to. /// /// /// The current instance of the class. /// - public ImageFactory Save(MemoryStream memoryStream) + public ImageFactory Save(Stream stream) { if (this.ShouldProcess) { - // Fix the colour palette of gif and png8 images. - this.FixIndexedPallete(); - - // 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 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. - } - } - } - - if (this.ImageFormat.Equals(ImageFormat.Jpeg)) - { - // Jpegs can be saved with different settings to include a quality setting for the JPEG compression. - // This improves output compression and quality. - using (EncoderParameters encoderParameters = ImageUtils.GetEncodingParameters(this.JpegQuality)) - { - ImageCodecInfo imageCodecInfo = - ImageCodecInfo.GetImageEncoders().FirstOrDefault( - ici => ici.MimeType.Equals(this.MimeType, StringComparison.OrdinalIgnoreCase)); - - if (imageCodecInfo != null) - { - this.Image.Save(memoryStream, imageCodecInfo, encoderParameters); - } - } - } - else - { - this.Image.Save(memoryStream, this.ImageFormat); - } + this.Image = this.CurrentImageFormat.Save(stream, this.Image); } return this; @@ -1054,10 +912,10 @@ namespace ImageProcessor if (this.Image != null) { // Dispose of the memory stream from Load and the image. - if (this.inputStream != null) + if (this.InputStream != null) { - this.inputStream.Dispose(); - this.inputStream = null; + this.InputStream.Dispose(); + this.InputStream = null; } this.Image.Dispose(); @@ -1071,62 +929,6 @@ namespace ImageProcessor this.isDisposed = true; } #endregion - - /// - /// 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 || format.Equals(ImageFormat.Gif)) - { - ImageInfo imageInfo = this.Image.GetImageInfo(format, false); - - if (!imageInfo.IsAnimated) - { - this.Image = new OctreeQuantizer(255, 8).Quantize(this.Image); - } - } - } - - /// - /// Applies the given processor the current image. - /// - /// - /// The processor delegate. - /// - private void ApplyProcessor(Func processor) - { - ImageInfo imageInfo = this.Image.GetImageInfo(this.ImageFormat); - - if (imageInfo.IsAnimated) - { - OctreeQuantizer quantizer = new OctreeQuantizer(255, 8); - - // We don't dispose of the memory stream as that is disposed when a new image is created and doing so - // beforehand will cause an exception. - MemoryStream stream = new MemoryStream(); - using (GifEncoder encoder = new GifEncoder(stream, null, null, imageInfo.LoopCount)) - { - foreach (GifFrame frame in imageInfo.GifFrames) - { - this.Image = frame.Image; - frame.Image = quantizer.Quantize(processor.Invoke(this)); - encoder.AddFrame(frame); - } - } - - stream.Position = 0; - this.Image = Image.FromStream(stream); - } - else - { - this.Image = processor.Invoke(this); - } - } #endregion } } diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index 8719e3c85..bdaeb9ba9 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -1,20 +1,20 @@  - + + Debug AnyCPU - 8.0.30703 - 2.0 {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E} Library Properties ImageProcessor ImageProcessor - v4.0 + v4.5 512 ..\ true - Client + + true @@ -25,7 +25,7 @@ prompt 4 bin\Debug\ImageProcessor.XML - false + false pdbonly @@ -35,6 +35,7 @@ prompt 4 bin\Release\ImageProcessor.XML + false true @@ -46,6 +47,9 @@ prompt false true + 4 + false + false @@ -57,14 +61,18 @@ + - - - - - - + + + + + + + + + @@ -72,11 +80,19 @@ - + + + + + + + + + - - + + @@ -91,19 +107,18 @@ - - - + + diff --git a/src/ImageProcessor/Imaging/Convolution.cs b/src/ImageProcessor/Imaging/Convolution.cs index be3f585e9..bc8496ab2 100644 --- a/src/ImageProcessor/Imaging/Convolution.cs +++ b/src/ImageProcessor/Imaging/Convolution.cs @@ -14,7 +14,8 @@ namespace ImageProcessor.Imaging using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; - using ImageProcessor.Extensions; + + using ImageProcessor.Common.Extensions; /// /// Provides methods for applying blurring and sharpening effects to an image.. @@ -256,7 +257,7 @@ namespace ImageProcessor.Imaging /// /// Processes the given kernel to produce an array of pixels representing a bitmap. /// - /// The the image to process. + /// The image to process. /// The Gaussian kernel to use when performing the method /// A processed bitmap. public Bitmap ProcessKernel(Bitmap sourceBitmap, double[,] kernel) diff --git a/src/ImageProcessor/Imaging/ExifPropertyTag.cs b/src/ImageProcessor/Imaging/ExifPropertyTag.cs index 3e714d03c..d3c26ff53 100644 --- a/src/ImageProcessor/Imaging/ExifPropertyTag.cs +++ b/src/ImageProcessor/Imaging/ExifPropertyTag.cs @@ -13,7 +13,6 @@ namespace ImageProcessor.Imaging /// /// The following enum gives descriptions of the property items supported by Windows GDI+. /// - /// TODO: Add more XML descriptions. /// public enum ExifPropertyTag { @@ -159,12 +158,12 @@ namespace ImageProcessor.Imaging ExifDTOrig = 0x9003, /// - /// Null-terminated character string that specifies a fraction of a second for the PropertyTagExifDTOrig tag. + /// Null-terminated character string that specifies a fraction of a second for the tag. /// ExifDTOrigSS = 0x9291, /// - /// Null-terminated character string that specifies a fraction of a second for the PropertyTagDateTime tag. + /// Null-terminated character string that specifies a fraction of a second for the tag. /// ExifDTSubsec = 0x9290, @@ -214,27 +213,31 @@ namespace ImageProcessor.Imaging ExifFocalLength = 0x920A, /// - /// Unit of measure for PropertyTagExifFocalXRes and PropertyTagExifFocalYRes. + /// Unit of measure for and . /// ExifFocalResUnit = 0xA210, /// - /// Number of pixels in the image width (x) direction per unit on the camera focal plane. The unit is specified in PropertyTagExifFocalResUnit. + /// Number of pixels in the image width (x) direction per unit on the camera focal plane. The unit is specified + /// in . /// ExifFocalXRes = 0xA20E, /// - /// Number of pixels in the image height (y) direction per unit on the camera focal plane. The unit is specified in PropertyTagExifFocalResUnit. + /// Number of pixels in the image height (y) direction per unit on the camera focal plane. The unit is specified + /// in . /// ExifFocalYRes = 0xA20F, /// - /// FlashPix format version supported by an FPXR file. If the FPXR function supports FlashPix format version 1.0, this is indicated similarly to PropertyTagExifVer by recording 0100 as a 4-byte ASCII string. Because the type is PropertyTagTypeUndefined, there is no NULL terminator. + /// FlashPix format version supported by an FPXR file. If the FPXR function supports FlashPix format version 1.0, + /// this is indicated similarly to by recording 0100 as a 4-byte ASCII string. + /// Because the type is , there is no NULL terminator. /// ExifFPXVer = 0xA000, /// - /// Private tag used by GDI+. Not for public use. GDI+ uses this tag to locate Exif-specific information. + /// Private tag used by GDI+. Not for public use. GDI+ uses this tag to locate Exif specific information. /// ExifIFD = 0x8769, @@ -319,17 +322,23 @@ namespace ImageProcessor.Imaging ExifSubjectDist = 0x9206, /// - /// Location of the main subject in the scene. The value of this tag represents the pixel at the center of the main subject relative to the left edge. The first value indicates the column number, and the second value indicates the row number. + /// Location of the main subject in the scene. The value of this tag represents the pixel at the center + /// of the main subject relative to the left edge. The first value indicates the column number, and + /// the second value indicates the row number. /// ExifSubjectLoc = 0xA214, /// - /// Comment tag. A tag used by EXIF users to write keywords or comments about the image besides those in PropertyTagImageDescription and without the character-code limitations of the PropertyTagImageDescription tag. + /// Comment tag. A tag used by EXIF users to write keywords or comments about the image besides those + /// in and without the character-code limitations of + /// the tag. /// ExifUserComment = 0x9286, /// - /// Version of the EXIF standard supported. Nonexistence of this field is taken to mean nonconformance to the standard. Conformance to the standard is indicated by recording 0210 as a 4-byte ASCII string. Because the type is PropertyTagTypeUndefined, there is no NULL terminator. + /// Version of the EXIF standard supported. Nonexistence of this field is taken to mean non-conformance to the + /// standard. Conformance to the standard is indicated by recording 0210 as a 4-byte ASCII string. + /// Because the type is , there is no NULL terminator. /// ExifVer = 0x9000, @@ -369,7 +378,7 @@ namespace ImageProcessor.Imaging GlobalPalette = 0x5102, /// - /// Altitude, in meters, based on the reference altitude specified by PropertyTagGpsAltitudeRef. + /// Altitude, in meters, based on the reference altitude specified by . /// GpsAltitude = 0x0006, @@ -394,297 +403,325 @@ namespace ImageProcessor.Imaging GpsDestDist = 0x001A, /// - /// Null-terminated character string that specifies the unit used to express the distance to the destination point. K, M, and N represent kilometers, miles, and knots respectively. + /// Null-terminated character string that specifies the unit used to express the distance to the destination point. + /// K, M, and N represent kilometers, miles, and knots respectively. /// GpsDestDistRef = 0x0019, /// - /// Latitude of the destination point. The latitude is expressed as three rational values giving the degrees, minutes, and seconds respectively. When degrees, minutes, and seconds are expressed, the format is dd/1, mm/1, ss/1. When degrees and minutes are used and, for example, fractions of minutes are given up to two decimal places, the format is dd/1, mmmm/100, 0/1. + /// Latitude of the destination point. The latitude is expressed as three rational values giving the degrees, + /// minutes, and seconds respectively. When degrees, minutes, and seconds are expressed, the format is + /// dd/1, mm/1, ss/1. When degrees and minutes are used and, for example, fractions of minutes are given up to + /// two decimal places, the format is dd/1, mmmm/100, 0/1. /// GpsDestLat = 0x0014, /// - /// The gps dest lat ref. + /// Null-terminated character string that specifies whether the latitude of the destination point is north or south + /// latitude. N specifies north latitude, and S specifies south latitude. /// GpsDestLatRef = 0x0013, /// - /// The gps dest long. + /// Longitude of the destination point. The longitude is expressed as three rational values giving the degrees, minutes, and seconds respectively. When degrees, minutes, and seconds are expressed, the format is ddd/1, mm/1, ss/1. When degrees and minutes are used and, for example, fractions of minutes are given up to two decimal places, the format is ddd/1, mmmm/100, 0/1. /// GpsDestLong = 0x0016, /// - /// The gps dest long ref. + /// Null-terminated character string that specifies whether the longitude of the destination point is east or west longitude. E specifies east longitude, and W specifies west longitude. /// GpsDestLongRef = 0x0015, /// - /// The gps gps dop. + /// GPS DOP (data degree of precision). An HDOP value is written during 2-D measurement, and a PDOP value is written during 3-D measurement. /// GpsGpsDop = 0x000B, /// - /// The gps gps measure mode. + /// Null-terminated character string that specifies the GPS measurement mode. 2 specifies 2-D measurement, and 3 specifies 3-D measurement. /// GpsGpsMeasureMode = 0x000A, /// - /// The gps gps satellites. + /// Null-terminated character string that specifies the GPS satellites used for measurements. This tag can be used to specify the ID number, angle of elevation, azimuth, SNR, and other information about each satellite. The format is not specified. If the GPS receiver is incapable of taking measurements, the value of the tag must be set to NULL. /// GpsGpsSatellites = 0x0008, /// - /// The gps gps status. + /// Null-terminated character string that specifies the status of the GPS receiver when the image is recorded. A means measurement is in progress, and V means the measurement is Interoperability. /// GpsGpsStatus = 0x0009, /// - /// The gps gps time. + /// Time as coordinated universal time (UTC). The value is expressed as three rational numbers that give the hour, minute, and second. /// GpsGpsTime = 0x0007, /// - /// The gps ifd. + /// Offset to a block of GPS property items. Property items whose tags have the prefix Gps are stored in the GPS block. + /// The GPS property items are defined in the EXIF specification. GDI+ uses this tag to locate GPS information, + /// but GDI+ does not expose this tag for public use. /// GpsIFD = 0x8825, /// - /// The gps img dir. + /// Direction of the image when it was captured. The range of values is from 0.00 to 359.99. /// GpsImgDir = 0x0011, /// - /// The gps img dir ref. + /// Null-terminated character string that specifies the reference for the direction of the image when it is captured. T specifies true direction, and M specifies magnetic direction. /// GpsImgDirRef = 0x0010, /// - /// The gps latitude. + /// Latitude. Latitude is expressed as three rational values giving the degrees, minutes, and seconds respectively. When degrees, minutes, and seconds are expressed, the format is dd/1, mm/1, ss/1. When degrees and minutes are used and, for example, fractions of minutes are given up to two decimal places, the format is dd/1, mmmm/100, 0/1. /// GpsLatitude = 0x0002, /// - /// The gps latitude ref. + /// Null-terminated character string that specifies whether the longitude is east or west longitude. + /// E specifies east longitude, and W specifies west longitude. /// GpsLatitudeRef = 0x0001, /// - /// The gps longitude. + /// Longitude. Longitude is expressed as three rational values giving the degrees, minutes, and seconds + /// respectively. When degrees, minutes and seconds are expressed, the format is ddd/1, mm/1, ss/1. + /// When degrees and minutes are used and, for example, fractions of minutes are given up to two + /// decimal places, the format is ddd/1, mmmm/100, 0/1. /// GpsLongitude = 0x0004, /// - /// The gps longitude ref. + /// Null-terminated character string that specifies whether the longitude is east or west longitude. + /// E specifies east longitude, and W specifies west longitude. /// GpsLongitudeRef = 0x0003, /// - /// The gps map datum. + /// Null-terminated character string that specifies geodetic survey data used by the GPS receiver. + /// If the survey data is restricted to Japan, the value of this tag is TOKYO or WGS-84. /// GpsMapDatum = 0x0012, /// - /// The gps speed. + /// Speed of the GPS receiver movement. /// GpsSpeed = 0x000D, /// - /// The gps speed ref. + /// Null-terminated character string that specifies the unit used to express the GPS receiver speed of movement. + /// K, M, and N represent kilometers per hour, miles per hour, and knots respectively. /// GpsSpeedRef = 0x000C, /// - /// The gps track. + /// Direction of GPS receiver movement. The range of values is from 0.00 to 359.99. /// GpsTrack = 0x000F, /// - /// The gps track ref. + /// Null-terminated character string that specifies the reference for giving the direction of + /// GPS receiver movement. T specifies true direction, and M specifies magnetic direction. /// GpsTrackRef = 0x000E, /// - /// The gps ver. + /// Version of the Global Positioning Systems (GPS) IFD, given as 2.0.0.0. This tag is mandatory when + /// the tag is present. When the version is 2.0.0.0, the tag value is 0x02000000. /// GpsVer = 0x0000, /// - /// The gray response curve. + /// For each possible pixel value in a grayscale image, the optical density of that pixel value. /// GrayResponseCurve = 0x0123, /// - /// The gray response unit. + /// Precision of the number specified by . 1 specifies tenths, + /// 2 specifies hundredths, 3 specifies thousandths, and so on. /// GrayResponseUnit = 0x0122, /// - /// The grid size. + /// Block of information about grids and guides. /// GridSize = 0x5011, /// - /// The halftone degree. + /// Angle for screen. /// HalftoneDegree = 0x500C, /// - /// The halftone hints. + /// Information used by the halftone function. /// HalftoneHints = 0x0141, /// - /// The halftone lpi. + /// Ink's screen frequency, in lines per inch. /// HalftoneLPI = 0x500A, /// - /// The halftone lpi unit. + /// Units for the screen frequency. /// HalftoneLPIUnit = 0x500B, /// - /// The halftone misc. + /// Miscellaneous halftone information. /// HalftoneMisc = 0x500E, /// - /// The halftone screen. + /// Boolean value that specifies whether to use the printer's default screens. /// HalftoneScreen = 0x500F, /// - /// The halftone shape. + /// Shape of the halftone dots. /// HalftoneShape = 0x500D, /// - /// The host computer. + /// Null-terminated character string that specifies the computer and/or operating system used to create the image. /// HostComputer = 0x013C, /// - /// The icc profile. + /// ICC profile embedded in the image. /// ICCProfile = 0x8773, /// - /// The icc profile descriptor. + /// Null-terminated character string that identifies an ICC profile. /// ICCProfileDescriptor = 0x0302, /// - /// The image description. + /// Null-terminated character string that specifies the title of the image. /// ImageDescription = 0x010E, /// - /// The image height. + /// Number of pixel rows. /// ImageHeight = 0x0101, /// - /// The image title. + /// Null-terminated character string that specifies the title of the image. /// ImageTitle = 0x0320, /// - /// The image width. + /// Number of pixels per row. /// ImageWidth = 0x0100, /// - /// The index background. + /// Index of the background color in the palette of a GIF image. /// IndexBackground = 0x5103, /// - /// The index transparent. + /// Index of the transparent color in the palette of a GIF image. /// IndexTransparent = 0x5104, /// - /// The ink names. + /// Sequence of concatenated, null-terminated, character strings that specify the names of the + /// inks used in a separated image. /// InkNames = 0x014D, /// - /// The ink set. + /// Set of inks used in a separated image. /// InkSet = 0x014C, /// - /// The jpegac tables. + /// For each color component, the offset to the AC Huffman table for that component. + /// See also . /// JPEGACTables = 0x0209, /// - /// The jpegdc tables. + /// For each color component, the offset to the DC Huffman table (or lossless Huffman table) for that + /// component. See also . /// JPEGDCTables = 0x0208, /// - /// The jpeg inter format. + /// Offset to the start of a JPEG bitstream. /// JPEGInterFormat = 0x0201, /// - /// The jpeg inter length. + /// Length, in bytes, of the JPEG bitstream. /// JPEGInterLength = 0x0202, /// - /// The jpeg lossless predictors. + /// For each color component, a lossless predictor-selection value for that component. + /// See also . /// JPEGLosslessPredictors = 0x0205, /// - /// The jpeg point transforms. + /// For each color component, a point transformation value for that component. + /// See also . /// JPEGPointTransforms = 0x0206, /// - /// The jpeg proc. + /// JPEG compression process. /// JPEGProc = 0x0200, /// - /// The jpegq tables. + /// For each color component, the offset to the quantization table for that + /// component. See also . /// JPEGQTables = 0x0207, /// - /// The jpeg quality. + /// Private tag used by the Adobe Photoshop format. Not for public use. /// JPEGQuality = 0x5010, /// - /// The jpeg restart interval. + /// Length of the restart interval. /// JPEGRestartInterval = 0x0203, /// - /// The loop count. + /// For an animated GIF image, the number of times to display the animation. + /// A value of 0 specifies that the animation should be displayed infinitely. /// LoopCount = 0x5101, /// - /// The luminance table. + /// Luminance table. The luminance table and the chrominance table are used to control JPEG quality. + /// A valid luminance or chrominance table has 64 entries of type . + /// If an image has either a luminance table or a chrominance table, then it must have both tables. /// LuminanceTable = 0x5090, /// - /// The max sample value. + /// For each color component, the maximum value assigned to that component. + /// See also . /// MaxSampleValue = 0x0119, /// - /// The min sample value. + /// For each color component, the minimum value assigned to that component. + /// See also . /// MinSampleValue = 0x0118, /// - /// The new subfile type. + /// Type of data in a subfile. /// NewSubfileType = 0x00FE, @@ -694,17 +731,17 @@ namespace ImageProcessor.Imaging NumberOfInks = 0x014E, /// - /// The orientation. + /// Image orientation viewed in terms of rows and columns. /// Orientation = 0x0112, /// - /// The page name. + /// Null-terminated character string that specifies the name of the page from which the image was scanned. /// PageName = 0x011D, /// - /// The page number. + /// Page number of the page from which the image was scanned. /// PageNumber = 0x0129, @@ -714,42 +751,42 @@ namespace ImageProcessor.Imaging PaletteHistogram = 0x5113, /// - /// The photometric interp. + /// How pixel data will be interpreted. /// PhotometricInterp = 0x0106, /// - /// The pixel per unit x. + /// Pixels per unit in the x direction. /// PixelPerUnitX = 0x5111, /// - /// The pixel per unit y. + /// Pixels per unit in the y direction. /// PixelPerUnitY = 0x5112, /// - /// The pixel unit. + /// Unit for and . /// PixelUnit = 0x5110, /// - /// The planar config. + /// Whether pixel components are recorded in chunky or planar format. /// PlanarConfig = 0x011C, /// - /// The predictor. + /// TType of prediction scheme that was applied to the image data before the encoding scheme was applied. /// Predictor = 0x013D, /// - /// The primary chromaticities. + /// For each of the three primary colors in the image, the chromaticity of that color. /// PrimaryChromaticities = 0x013F, /// - /// The print flags. + /// Sequence of one-byte Boolean values that specify printing options. /// PrintFlags = 0x5005, @@ -764,7 +801,7 @@ namespace ImageProcessor.Imaging PrintFlagsBleedWidthScale = 0x5009, /// - /// The print flags crop. + /// The print flags crop marks. /// PrintFlagsCrop = 0x5007, @@ -774,357 +811,381 @@ namespace ImageProcessor.Imaging PrintFlagsVersion = 0x5006, /// - /// The ref black white. + /// Reference black point value and reference white point value. /// REFBlackWhite = 0x0214, /// - /// The resolution unit. + /// Unit of measure for the horizontal resolution and the vertical resolution. /// ResolutionUnit = 0x0128, /// - /// The resolution x length unit. + /// Units in which to display the image width. /// ResolutionXLengthUnit = 0x5003, /// - /// The resolution x unit. + /// Units in which to display horizontal resolution. /// ResolutionXUnit = 0x5001, /// - /// The resolution y length unit. + /// Units in which to display the image height. /// ResolutionYLengthUnit = 0x5004, /// - /// The resolution y unit. + /// Units in which to display vertical resolution. /// ResolutionYUnit = 0x5002, /// - /// The rows per strip. + /// Number of rows per strip. See also and . /// RowsPerStrip = 0x0116, /// - /// The sample format. + /// For each color component, the numerical format (unsigned, signed, floating point) of that component. + /// See also . /// SampleFormat = 0x0153, /// - /// The samples per pixel. + /// Number of color components per pixel. /// SamplesPerPixel = 0x0115, /// - /// The s max sample value. + /// For each color component, the maximum value of that component. See also . /// SMaxSampleValue = 0x0155, /// - /// The s min sample value. + /// For each color component, the minimum value of that component. See also . /// SMinSampleValue = 0x0154, /// - /// The software used. + /// Null-terminated character string that specifies the name and version of the software or + /// firmware of the device used to generate the image. /// SoftwareUsed = 0x0131, /// - /// The srgb rendering intent. + /// How the image should be displayed as defined by the International Color Consortium (ICC). If a GDI+ Image object + /// is constructed with the useEmbeddedColorManagement parameter set to TRUE, then GDI+ renders the image + /// according to the specified rendering intent. The intent can be set to perceptual, relative colorimetric, + /// saturation, or absolute colorimetric. /// SRGBRenderingIntent = 0x0303, /// - /// The strip bytes count. + /// For each strip, the total number of bytes in that strip. /// StripBytesCount = 0x0117, /// - /// The strip offsets. + /// For each strip, the byte offset of that strip. See also + /// and . /// StripOffsets = 0x0111, /// - /// The subfile type. + /// The type of data in a subfile. /// SubfileType = 0x00FF, /// - /// The t 4 option. + /// Set of flags that relate to T4 encoding. /// T4Option = 0x0124, /// - /// The t 6 option. + /// Set of flags that relate to T6 encoding. /// T6Option = 0x0125, /// - /// The target printer. + /// Null-terminated character string that describes the intended printing environment. /// TargetPrinter = 0x0151, /// - /// The thresh holding. + /// Technique used to convert from gray pixels to black and white pixels. /// ThreshHolding = 0x0107, /// - /// The thumbnail artist. + /// Null-terminated character string that specifies the name of the person who created the thumbnail image. /// ThumbnailArtist = 0x5034, /// - /// The thumbnail bits per sample. + /// Number of bits per color component in the thumbnail image. See also . /// ThumbnailBitsPerSample = 0x5022, /// - /// The thumbnail color depth. + /// Bits per pixel (BPP) for the thumbnail image. /// ThumbnailColorDepth = 0x5015, /// - /// The thumbnail compressed size. + /// Compressed size, in bytes, of the thumbnail image. /// ThumbnailCompressedSize = 0x5019, /// - /// The thumbnail compression. + /// Compression scheme used for thumbnail image data. /// ThumbnailCompression = 0x5023, /// - /// The thumbnail copy right. + /// Null-terminated character string that contains copyright information for the thumbnail image. /// ThumbnailCopyRight = 0x503B, /// - /// The thumbnail data. + /// Raw thumbnail bits in JPEG or RGB format. Depends on . /// ThumbnailData = 0x501B, /// - /// The thumbnail date time. + /// Date and time the thumbnail image was created. See also . /// ThumbnailDateTime = 0x5033, /// - /// The thumbnail equip make. + /// Null-terminated character string that specifies the manufacturer of the equipment used to + /// record the thumbnail image. /// ThumbnailEquipMake = 0x5026, /// - /// The thumbnail equip model. + /// Null-terminated character string that specifies the model name or model number of the + /// equipment used to record the thumbnail image. /// ThumbnailEquipModel = 0x5027, /// - /// The thumbnail format. + /// Format of the thumbnail image. /// ThumbnailFormat = 0x5012, /// - /// The thumbnail height. + /// Height, in pixels, of the thumbnail image. /// ThumbnailHeight = 0x5014, /// - /// The thumbnail image description. + /// Null-terminated character string that specifies the title of the image. /// ThumbnailImageDescription = 0x5025, /// - /// The thumbnail image height. + /// Number of pixel rows in the thumbnail image. /// ThumbnailImageHeight = 0x5021, /// - /// The thumbnail image width. + /// Number of pixels per row in the thumbnail image. /// ThumbnailImageWidth = 0x5020, /// - /// The thumbnail orientation. + /// Thumbnail image orientation in terms of rows and columns. See also . /// ThumbnailOrientation = 0x5029, /// - /// The thumbnail photometric interp. + /// How thumbnail pixel data will be interpreted. /// ThumbnailPhotometricInterp = 0x5024, /// - /// The thumbnail planar config. + /// Whether pixel components in the thumbnail image are recorded in chunky or planar format. + /// See also . /// ThumbnailPlanarConfig = 0x502F, /// - /// The thumbnail planes. + /// Number of color planes for the thumbnail image. /// ThumbnailPlanes = 0x5016, /// - /// The thumbnail primary chromaticities. + /// For each of the three primary colors in the thumbnail image, the chromaticity + /// of that color. See also . /// ThumbnailPrimaryChromaticities = 0x5036, /// - /// The thumbnail raw bytes. + /// Byte offset between rows of pixel data. /// ThumbnailRawBytes = 0x5017, /// - /// The thumbnail ref black white. + /// Reference black point value and reference white point value + /// for the thumbnail image. See also . /// ThumbnailRefBlackWhite = 0x503A, /// - /// The thumbnail resolution unit. + /// Unit of measure for the horizontal resolution and the vertical resolution of + /// the thumbnail image. See also . /// ThumbnailResolutionUnit = 0x5030, /// - /// The thumbnail resolution x. + /// Thumbnail resolution in the width direction. + /// The resolution unit is given in . /// ThumbnailResolutionX = 0x502D, /// - /// The thumbnail resolution y. + /// Thumbnail resolution in the height direction. The resolution unit is given + /// in . /// ThumbnailResolutionY = 0x502E, /// - /// The thumbnail rows per strip. + /// Number of rows per strip in the thumbnail image. See also + /// and . /// ThumbnailRowsPerStrip = 0x502B, /// - /// The thumbnail samples per pixel. + /// Number of color components per pixel in the thumbnail image. /// ThumbnailSamplesPerPixel = 0x502A, /// - /// The thumbnail size. + /// Total size, in bytes, of the thumbnail image. /// ThumbnailSize = 0x5018, /// - /// The thumbnail software used. + /// Null-terminated character string that specifies the name and version of the software + /// or firmware of the device used to generate the thumbnail image. /// ThumbnailSoftwareUsed = 0x5032, /// - /// The thumbnail strip bytes count. + /// For each thumbnail image strip, the total number of bytes in that strip. /// ThumbnailStripBytesCount = 0x502C, /// - /// The thumbnail strip offsets. + /// For each strip in the thumbnail image, the byte offset of that strip. See also + /// and . /// ThumbnailStripOffsets = 0x5028, /// - /// The thumbnail transfer function. + /// Tables that specify transfer functions for the thumbnail image. See also . /// ThumbnailTransferFunction = 0x5031, /// - /// The thumbnail white point. + /// Chromaticity of the white point of the thumbnail image. See also . /// ThumbnailWhitePoint = 0x5035, /// - /// The thumbnail width. + /// Width, in pixels, of the thumbnail image. /// ThumbnailWidth = 0x5013, /// - /// The thumbnail y cb cr coefficients. + /// Coefficients for transformation from RGB to YCbCr data for the thumbnail image. + /// See also . /// ThumbnailYCbCrCoefficients = 0x5037, /// - /// The thumbnail y cb cr positioning. + /// Position of chrominance components in relation to the luminance component for + /// the thumbnail image. See also . /// ThumbnailYCbCrPositioning = 0x5039, /// - /// The thumbnail y cb cr subsampling. + /// Sampling ratio of chrominance components in relation to the luminance component for + /// the thumbnail image. See also . /// ThumbnailYCbCrSubsampling = 0x5038, /// - /// The tile byte counts. + /// For each tile, the number of bytes in that tile. /// TileByteCounts = 0x0145, /// - /// The tile length. + /// Number of pixel rows in each tile. /// TileLength = 0x0143, /// - /// The tile offset. + /// For each tile, the byte offset of that tile. /// TileOffset = 0x0144, /// - /// The tile width. + /// Number of pixel columns in each tile. /// TileWidth = 0x0142, /// - /// The transfer function. + /// Tables that specify transfer functions for the image. /// TransferFunction = 0x012D, /// - /// The transfer range. + /// Table of values that extends the range of the transfer function. /// TransferRange = 0x0156, /// - /// The white point. + /// Chromaticity of the white point of the image. /// WhitePoint = 0x013E, /// - /// The x position. + /// Offset from the left side of the page to the left side of the image. + /// The unit of measure is specified by . /// XPosition = 0x011E, /// - /// The x resolution. + /// Number of pixels per unit in the image width (x) direction. + /// The unit is specified by . /// XResolution = 0x011A, /// - /// The y cb cr coefficients. + /// Coefficients for transformation from RGB to YCbCr image data. /// YCbCrCoefficients = 0x0211, /// - /// The y cb cr positioning. + /// Position of chrominance components in relation to the luminance component. /// YCbCrPositioning = 0x0213, /// - /// The y cb cr subsampling. + /// Sampling ratio of chrominance components in relation to the luminance component. /// YCbCrSubsampling = 0x0212, /// - /// The y position. + /// Offset from the top of the page to the top of the image. The unit of measure + /// is specified by . /// YPosition = 0x011F, /// - /// The y resolution. + /// Number of pixels per unit in the image height (y) direction. The unit is specified + /// by . /// YResolution = 0x011B } diff --git a/src/ImageProcessor/Imaging/ExifPropertyTagType.cs b/src/ImageProcessor/Imaging/ExifPropertyTagType.cs index 63f9bc3a4..1d0d470f7 100644 --- a/src/ImageProcessor/Imaging/ExifPropertyTagType.cs +++ b/src/ImageProcessor/Imaging/ExifPropertyTagType.cs @@ -5,7 +5,7 @@ // // // Specifies the data type of the values stored in the value data member of that same PropertyItem object. -// +// // // -------------------------------------------------------------------------------------------------------------------- diff --git a/src/ImageProcessor/Imaging/Filters/BlackWhiteMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/BlackWhiteMatrixFilter.cs index 0d3920b14..47cd4c540 100644 --- a/src/ImageProcessor/Imaging/Filters/BlackWhiteMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/BlackWhiteMatrixFilter.cs @@ -11,10 +11,6 @@ namespace ImageProcessor.Imaging.Filters { #region Using - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; using System.Drawing; using System.Drawing.Imaging; #endregion @@ -22,12 +18,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add a black and white filter to an image. /// - internal class BlackWhiteMatrixFilter : IMatrixFilter + internal class BlackWhiteMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.BlackWhite; } } @@ -36,7 +32,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -44,7 +40,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { diff --git a/src/ImageProcessor/Imaging/Filters/ColorMatrixes.cs b/src/ImageProcessor/Imaging/Filters/ColorMatrixes.cs index fd54cef22..4861d2481 100644 --- a/src/ImageProcessor/Imaging/Filters/ColorMatrixes.cs +++ b/src/ImageProcessor/Imaging/Filters/ColorMatrixes.cs @@ -10,10 +10,7 @@ namespace ImageProcessor.Imaging.Filters { - #region Using - using System.Diagnostics.CodeAnalysis; using System.Drawing.Imaging; - #endregion /// /// A list of available color matrices to apply to an image. @@ -21,199 +18,248 @@ namespace ImageProcessor.Imaging.Filters internal static class ColorMatrixes { /// - /// Gets Sepia. + /// The for generating the black and white filter. /// - internal static ColorMatrix Sepia + private static ColorMatrix blackWhite; + + /// + /// Gets the for generating the high pass + /// on the comic book filter. + /// + private static ColorMatrix comicHigh; + + /// + /// Gets for generating the low pass + /// on the comic book filter. + /// + private static ColorMatrix comicLow; + + /// + /// The for generating the greyscale filter. + /// + private static ColorMatrix greyScale; + + /// + /// The for generating the high saturation filter. + /// + private static ColorMatrix hiSatch; + + /// + /// The for generating the invert filter. + /// + private static ColorMatrix invert; + + /// + /// The for generating the lomograph filter. + /// + private static ColorMatrix lomograph; + + /// + /// The for generating the low saturation filter. + /// + private static ColorMatrix loSatch; + + /// + /// The for generating the polaroid filter. + /// + private static ColorMatrix polaroid; + + /// + /// The for generating the sepia filter. + /// + private static ColorMatrix sepia; + + /// + /// Gets the for generating the black and white filter. + /// + internal static ColorMatrix BlackWhite { get { - return new ColorMatrix( - new float[][] + return blackWhite ?? (blackWhite = new ColorMatrix( + new[] { - new float[] { .393f, .349f, .272f, 0, 0 }, - new float[] { .769f, .686f, .534f, 0, 0 }, - new float[] { .189f, .168f, .131f, 0, 0 }, + new[] { 1.5f, 1.5f, 1.5f, 0, 0 }, + new[] { 1.5f, 1.5f, 1.5f, 0, 0 }, + new[] { 1.5f, 1.5f, 1.5f, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, - new float[] { 0, 0, 0, 0, 1 } - }); + new float[] { -1, -1, -1, 0, 1 } + })); } } /// - /// Gets BlackWhite. + /// Gets the for generating the high pass + /// on the comic book filter. /// - internal static ColorMatrix BlackWhite + internal static ColorMatrix ComicHigh { get { - return new ColorMatrix( - new float[][] + return comicHigh ?? (comicHigh = new ColorMatrix( + new[] { - new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, - new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, - new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, + new[] { 2, -0.5f, -0.5f, 0, 0 }, + new[] { -0.5f, 2, -0.5f, 0, 0 }, + new[] { -0.5f, -0.5f, 2, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, - new float[] { -1, -1, -1, 0, 1 } - }); + new float[] { 0, 0, 0, 0, 1 } + })); } } /// - /// Gets Polaroid. + /// Gets for generating the low pass + /// on the comic book filter. /// - internal static ColorMatrix Polaroid + internal static ColorMatrix ComicLow { get { - return new ColorMatrix( - new float[][] + return comicLow ?? (comicLow = new ColorMatrix( + new[] { - new float[] { 1.638f, -0.062f, -0.262f, 0, 0 }, - new float[] { -0.122f, 1.378f, -0.122f, 0, 0 }, - new float[] { 1.016f, -0.016f, 1.383f, 0, 0 }, + new float[] { 1, 0, 0, 0, 0 }, + new float[] { 0, 1, 0, 0, 0 }, + new float[] { 0, 0, 1, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, - new float[] { 0.06f, -0.05f, -0.05f, 0, 1 } - }); + new[] { .075f, .075f, .075f, 0, 1 } + })); } } /// - /// Gets Lomograph. + /// Gets the for generating the greyscale filter. /// - [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")] - internal static ColorMatrix Lomograph + internal static ColorMatrix GreyScale { get { - return new ColorMatrix( - new float[][] + return greyScale ?? (greyScale = new ColorMatrix( + new[] { - new float[] { 1.50f, 0, 0, 0, 0 }, - new float[] { 0, 1.45f, 0, 0, 0 }, - new float[] { 0, 0, 1.09f, 0, 0 }, + new[] { .33f, .33f, .33f, 0, 0 }, + new[] { .59f, .59f, .59f, 0, 0 }, + new[] { .11f, .11f, .11f, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, - new float[] { -0.10f, 0.05f, -0.08f, 0, 1 } - }); + new float[] { 0, 0, 0, 0, 1 } + })); } } /// - /// Gets GreyScale. + /// Gets the for generating the high saturation filter. /// - internal static ColorMatrix GreyScale + internal static ColorMatrix HiSatch { get { - return new ColorMatrix( - new float[][] + return hiSatch ?? (hiSatch = new ColorMatrix( + new[] { - new float[] { .33f, .33f, .33f, 0, 0 }, - new float[] { .59f, .59f, .59f, 0, 0 }, - new float[] { .11f, .11f, .11f, 0, 0 }, + new float[] { 3, -1, -1, 0, 0 }, + new float[] { -1, 3, -1, 0, 0 }, + new float[] { -1, -1, 3, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, new float[] { 0, 0, 0, 0, 1 } - }); + })); } } /// - /// Gets Invert. + /// Gets the for generating the invert filter. /// internal static ColorMatrix Invert { get { - return new ColorMatrix( - new float[][] + return invert ?? (invert = new ColorMatrix( + new[] { new float[] { -1, 0, 0, 0, 0 }, new float[] { 0, -1, 0, 0, 0 }, new float[] { 0, 0, -1, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, new float[] { 1, 1, 1, 0, 1 } - }); + })); } } /// - /// Gets HiSatch. + /// Gets the for generating the lomograph filter. /// - [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")] - internal static ColorMatrix HiSatch + internal static ColorMatrix Lomograph { get { - return new ColorMatrix( - new float[][] - { - new float[] { 3, -1, -1, 0, 0 }, - new float[] { -1, 3, -1, 0, 0 }, - new float[] { -1, -1, 3, 0, 0 }, - new float[] { 0, 0, 0, 1, 0 }, - new float[] { 0, 0, 0, 0, 1 } - }); + return lomograph + ?? (lomograph = new ColorMatrix( + new[] + { + new[] { 1.50f, 0, 0, 0, 0 }, + new[] { 0, 1.45f, 0, 0, 0 }, + new[] { 0, 0, 1.09f, 0, 0 }, + new float[] { 0, 0, 0, 1, 0 }, + new[] { -0.10f, 0.05f, -0.08f, 0, 1 } + })); } } /// - /// Gets LoSatch. + /// Gets the for generating the low saturation filter. /// - [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")] internal static ColorMatrix LoSatch { get { - return new ColorMatrix( - new float[][] + return loSatch ?? (loSatch = new ColorMatrix( + new[] { new float[] { 1, 0, 0, 0, 0 }, new float[] { 0, 1, 0, 0, 0 }, new float[] { 0, 0, 1, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, - new float[] { .25f, .25f, .25f, 0, 1 } - }); + new[] { .25f, .25f, .25f, 0, 1 } + })); } } /// - /// Gets for generating the high pass - /// on the comic book filter. + /// Gets the for generating the polaroid filter. /// - internal static ColorMatrix ComicHigh + internal static ColorMatrix Polaroid { get { - return new ColorMatrix( - new float[][] + return polaroid ?? (polaroid = new ColorMatrix( + new[] { - new float[] { 2, -0.5f, -0.5f, 0, 0 }, - new float[] { -0.5f, 2, -0.5f, 0, 0 }, - new float[] { -0.5f, -0.5f, 2, 0, 0 }, + new[] { 1.638f, -0.062f, -0.262f, 0, 0 }, + new[] { -0.122f, 1.378f, -0.122f, 0, 0 }, + new[] { 1.016f, -0.016f, 1.383f, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, - new float[] { 0, 0, 0, 0, 1 } - }); + new[] { 0.06f, -0.05f, -0.05f, 0, 1 } + })); } } /// - /// Gets for generating the low pass - /// on the comic book filter. + /// Gets the for generating the sepia filter. /// - internal static ColorMatrix ComicLow + internal static ColorMatrix Sepia { get { - return new ColorMatrix( - new float[][] + return sepia ?? (sepia = new ColorMatrix( + new[] { - new float[] { 1, 0, 0, 0, 0 }, - new float[] { 0, 1, 0, 0, 0 }, - new float[] { 0, 0, 1, 0, 0 }, + new[] { .393f, .349f, .272f, 0, 0 }, + new[] { .769f, .686f, .534f, 0, 0 }, + new[] { .189f, .168f, .131f, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, - new float[] { .075f, .075f, .075f, 0, 1 } - }); + new float[] { 0, 0, 0, 0, 1 } + })); } } - } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Filters/ComicMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/ComicMatrixFilter.cs index 2f46693cb..7d90d0bf9 100644 --- a/src/ImageProcessor/Imaging/Filters/ComicMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/ComicMatrixFilter.cs @@ -18,14 +18,14 @@ namespace ImageProcessor.Imaging.Filters using System.Drawing.Imaging; using System.Runtime.InteropServices; - using ImageProcessor.Extensions; + using ImageProcessor.Common.Extensions; #endregion /// /// Encapsulates methods with which to add a comic filter to an image. /// - internal class ComicMatrixFilter : IMatrixFilter + internal class ComicMatrixFilter : MatrixFilterBase { /// /// Enumerates Argb color channels. @@ -38,16 +38,6 @@ namespace ImageProcessor.Imaging.Filters /// Blue = 0, - /// - /// The green channel - /// - Green = 1, - - /// - /// The red channel - /// - Red = 2, - /// /// The alpha channel /// @@ -57,7 +47,7 @@ namespace ImageProcessor.Imaging.Filters /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.ComicLow; } } @@ -66,7 +56,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -74,7 +64,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { // Bitmaps for comic pattern Bitmap highBitmap = null; @@ -147,7 +137,7 @@ namespace ImageProcessor.Imaging.Filters graphics.DrawImage(highBitmap, 0, 0); graphics.DrawImage(lowBitmap, 0, 0); graphics.DrawImage(edgeBitmap, 0, 0); - + // Draw an edge around the image. using (Pen blackPen = new Pen(Color.Black)) { diff --git a/src/ImageProcessor/Imaging/Filters/GothamMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/GothamMatrixFilter.cs index ddbb92128..7db4d3400 100644 --- a/src/ImageProcessor/Imaging/Filters/GothamMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/GothamMatrixFilter.cs @@ -22,12 +22,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add a gotham filter to an image. /// - internal class GothamMatrixFilter : IMatrixFilter + internal class GothamMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.GreyScale; } } @@ -36,7 +36,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -44,7 +44,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { @@ -79,13 +79,13 @@ namespace ImageProcessor.Imaging.Filters } // Add brightness and contrast to finish the effect. - factory.Update(newImage); + factory.Image = newImage; Brightness brightness = new Brightness { DynamicParameter = 5 }; - newImage = (Bitmap)brightness.ProcessImage(factory); + newImage = brightness.ProcessImage(factory); - factory.Update(newImage); + factory.Image = newImage; Contrast contrast = new Contrast { DynamicParameter = 85 }; - newImage = (Bitmap)contrast.ProcessImage(factory); + newImage = contrast.ProcessImage(factory); // Reassign the image. image.Dispose(); diff --git a/src/ImageProcessor/Imaging/Filters/GreyScaleMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/GreyScaleMatrixFilter.cs index 677ac1c97..11cee5b2f 100644 --- a/src/ImageProcessor/Imaging/Filters/GreyScaleMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/GreyScaleMatrixFilter.cs @@ -18,12 +18,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add a greyscale filter to an image. /// - internal class GreyScaleMatrixFilter : IMatrixFilter + internal class GreyScaleMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.GreyScale; } } @@ -32,7 +32,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -40,7 +40,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { diff --git a/src/ImageProcessor/Imaging/Filters/HiSatchMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/HiSatchMatrixFilter.cs index 5a8db565d..035d43f73 100644 --- a/src/ImageProcessor/Imaging/Filters/HiSatchMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/HiSatchMatrixFilter.cs @@ -18,12 +18,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add a high saturated filter to an image. /// - internal class HiSatchMatrixFilter : IMatrixFilter + internal class HiSatchMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.HiSatch; } } @@ -32,7 +32,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -40,7 +40,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { @@ -61,4 +61,4 @@ namespace ImageProcessor.Imaging.Filters return image; } } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Filters/IMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/IMatrixFilter.cs index 3c773000e..04d0977b4 100644 --- a/src/ImageProcessor/Imaging/Filters/IMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/IMatrixFilter.cs @@ -30,7 +30,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process diff --git a/src/ImageProcessor/Imaging/Filters/InvertMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/InvertMatrixFilter.cs index fbf8be63f..c36c607e5 100644 --- a/src/ImageProcessor/Imaging/Filters/InvertMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/InvertMatrixFilter.cs @@ -18,12 +18,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add an inverted filter to an image. /// - internal class InvertMatrixFilter : IMatrixFilter + internal class InvertMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.Invert; } } @@ -32,7 +32,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -40,7 +40,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { @@ -61,4 +61,4 @@ namespace ImageProcessor.Imaging.Filters return image; } } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Filters/LoSatchMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/LoSatchMatrixFilter.cs index dbbbcb799..040aa9ef9 100644 --- a/src/ImageProcessor/Imaging/Filters/LoSatchMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/LoSatchMatrixFilter.cs @@ -18,12 +18,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add a low saturated filter to an image. /// - internal class LoSatchMatrixFilter : IMatrixFilter + internal class LoSatchMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.LoSatch; } } @@ -32,7 +32,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -40,7 +40,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { diff --git a/src/ImageProcessor/Imaging/Filters/LomographMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/LomographMatrixFilter.cs index c44bce5c8..24d86c76f 100644 --- a/src/ImageProcessor/Imaging/Filters/LomographMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/LomographMatrixFilter.cs @@ -19,12 +19,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add a lomograph filter to an image. /// - internal class LomographMatrixFilter : IMatrixFilter + internal class LomographMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.Lomograph; } } @@ -33,7 +33,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -41,7 +41,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { @@ -50,15 +50,14 @@ namespace ImageProcessor.Imaging.Filters attributes.SetColorMatrix(this.Matrix); Rectangle rectangle = new Rectangle(0, 0, image.Width, image.Height); - graphics.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); } } // Add a vignette to finish the effect. - factory.Update(newImage); + factory.Image = newImage; Vignette vignette = new Vignette(); - newImage = (Bitmap)vignette.ProcessImage(factory); + newImage = vignette.ProcessImage(factory); // Reassign the image. image.Dispose(); diff --git a/src/ImageProcessor/Imaging/Filters/MatrixFilterBase.cs b/src/ImageProcessor/Imaging/Filters/MatrixFilterBase.cs new file mode 100644 index 000000000..bff9d621e --- /dev/null +++ b/src/ImageProcessor/Imaging/Filters/MatrixFilterBase.cs @@ -0,0 +1,70 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The matrix filter base contains equality methods. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Filters +{ + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// The matrix filter base contains equality methods. + /// + public abstract class MatrixFilterBase : IMatrixFilter + { + /// + /// Gets the for this filter instance. + /// + public abstract ColorMatrix Matrix { get; } + + /// + /// Processes the image. + /// + /// The current instance of the + /// class containing + /// the image to process. + /// The current image to process + /// The new Image to return + /// + /// The processed image from the current instance of the class. + /// + public abstract Image TransformImage(ImageFactory factory, Image image, Image newImage); + + /// + /// Determines whether the specified , is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object obj) + { + IMatrixFilter filter = obj as IMatrixFilter; + + if (filter == null) + { + return false; + } + + return this.GetType().Name == filter.GetType().Name + && this.Matrix.Equals(filter.Matrix); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + return this.GetType().Name.GetHashCode() + this.Matrix.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Filters/MatrixFilterRegexAttribute.cs b/src/ImageProcessor/Imaging/Filters/MatrixFilterRegexAttribute.cs deleted file mode 100644 index ebd5db379..000000000 --- a/src/ImageProcessor/Imaging/Filters/MatrixFilterRegexAttribute.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// The filter attribute for identifying matrix filter properties. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Imaging.Filters -{ - using System; - - /// - /// The filter attribute for identifying matrix filter properties. - /// - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] - public class MatrixFilterRegexAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The regex identifier. - /// - public MatrixFilterRegexAttribute(string regexIdentifier) - { - this.RegexIdentifier = regexIdentifier; - } - - /// - /// Gets the regex identifier. - /// - public string RegexIdentifier { get; private set; } - } -} diff --git a/src/ImageProcessor/Imaging/Filters/MatrixFilters.cs b/src/ImageProcessor/Imaging/Filters/MatrixFilters.cs index 8159a4c03..99b7a705b 100644 --- a/src/ImageProcessor/Imaging/Filters/MatrixFilters.cs +++ b/src/ImageProcessor/Imaging/Filters/MatrixFilters.cs @@ -18,9 +18,8 @@ namespace ImageProcessor.Imaging.Filters public static class MatrixFilters { /// - /// Gets the black white filter. + /// Gets the for generating the black and white filter. /// - [MatrixFilterRegex("blackwhite")] public static IMatrixFilter BlackWhite { get @@ -30,9 +29,8 @@ namespace ImageProcessor.Imaging.Filters } /// - /// Gets the comic filter. + /// Gets the for generating the comic filter. /// - [MatrixFilterRegex("comic")] public static IMatrixFilter Comic { get @@ -42,9 +40,8 @@ namespace ImageProcessor.Imaging.Filters } /// - /// Gets the gotham filter. + /// Gets the for generating the gotham filter. /// - [MatrixFilterRegex("gotham")] public static IMatrixFilter Gotham { get @@ -54,9 +51,8 @@ namespace ImageProcessor.Imaging.Filters } /// - /// Gets the greyscale filter. + /// Gets the for generating the greyscale filter. /// - [MatrixFilterRegex("greyscale")] public static IMatrixFilter GreyScale { get @@ -66,9 +62,8 @@ namespace ImageProcessor.Imaging.Filters } /// - /// Gets the high saturation filter. + /// Gets the for generating the high saturation filter. /// - [MatrixFilterRegex("hisatch")] public static IMatrixFilter HiSatch { get @@ -78,9 +73,8 @@ namespace ImageProcessor.Imaging.Filters } /// - /// Gets the invert filter. + /// Gets the for generating the invert filter. /// - [MatrixFilterRegex("invert")] public static IMatrixFilter Invert { get @@ -90,9 +84,8 @@ namespace ImageProcessor.Imaging.Filters } /// - /// Gets the lomograph filter. + /// Gets the for generating the lomograph filter. /// - [MatrixFilterRegex("lomograph")] public static IMatrixFilter Lomograph { get @@ -102,21 +95,19 @@ namespace ImageProcessor.Imaging.Filters } /// - /// Gets the low saturation filter. + /// Gets the for generating the low saturation filter. /// - [MatrixFilterRegex("losatch")] public static IMatrixFilter LoSatch { get { - return new LomographMatrixFilter(); + return new LoSatchMatrixFilter(); } } /// - /// Gets the polaroid filter. + /// Gets the for generating the polaroid filter. /// - [MatrixFilterRegex("polaroid")] public static IMatrixFilter Polaroid { get @@ -126,9 +117,8 @@ namespace ImageProcessor.Imaging.Filters } /// - /// Gets the sepia filter. + /// Gets the for generating the sepia filter. /// - [MatrixFilterRegex("sepia")] public static IMatrixFilter Sepia { get @@ -137,4 +127,4 @@ namespace ImageProcessor.Imaging.Filters } } } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Filters/PolaroidMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/PolaroidMatrixFilter.cs index 947c79f25..39ccdceea 100644 --- a/src/ImageProcessor/Imaging/Filters/PolaroidMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/PolaroidMatrixFilter.cs @@ -20,12 +20,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add a Polaroid filter to an image. /// - internal class PolaroidMatrixFilter : IMatrixFilter + internal class PolaroidMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.Polaroid; } } @@ -34,7 +34,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -42,7 +42,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { @@ -85,7 +85,7 @@ namespace ImageProcessor.Imaging.Filters } // Add a vignette to finish the effect. - factory.Update(newImage); + factory.Image = newImage; Vignette vignette = new Vignette(); newImage = vignette.ProcessImage(factory); diff --git a/src/ImageProcessor/Imaging/Filters/SepiaMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/SepiaMatrixFilter.cs index 2a35b6f50..d2f263bb7 100644 --- a/src/ImageProcessor/Imaging/Filters/SepiaMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/SepiaMatrixFilter.cs @@ -18,12 +18,12 @@ namespace ImageProcessor.Imaging.Filters /// /// Encapsulates methods with which to add a sepia filter to an image. /// - internal class SepiaMatrixFilter : IMatrixFilter + internal class SepiaMatrixFilter : MatrixFilterBase { /// /// Gets the for this filter instance. /// - public ColorMatrix Matrix + public override ColorMatrix Matrix { get { return ColorMatrixes.Sepia; } } @@ -32,7 +32,7 @@ namespace ImageProcessor.Imaging.Filters /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The current image to process @@ -40,7 +40,7 @@ namespace ImageProcessor.Imaging.Filters /// /// The processed image from the current instance of the class. /// - public Image TransformImage(ImageFactory factory, Image image, Image newImage) + public override Image TransformImage(ImageFactory factory, Image image, Image newImage) { using (Graphics graphics = Graphics.FromImage(newImage)) { @@ -61,4 +61,4 @@ namespace ImageProcessor.Imaging.Filters return image; } } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Formats/BitmapFormat.cs b/src/ImageProcessor/Imaging/Formats/BitmapFormat.cs new file mode 100644 index 000000000..de1efd4c0 --- /dev/null +++ b/src/ImageProcessor/Imaging/Formats/BitmapFormat.cs @@ -0,0 +1,65 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides the necessary information to support bitmap images. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Formats +{ + using System.Drawing.Imaging; + using System.Text; + + /// + /// Provides the necessary information to support bitmap images. + /// + public class BitmapFormat : FormatBase + { + /// + /// Gets the file headers. + /// + public override byte[][] FileHeaders + { + get + { + return new[] { Encoding.ASCII.GetBytes("BM") }; + } + } + + /// + /// Gets the list of file extensions. + /// + public override string[] FileExtensions + { + get + { + return new[] { "bmp" }; + } + } + + /// + /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. + /// + public override string MimeType + { + get + { + return "image/bmp"; + } + } + + /// + /// Gets the . + /// + public override ImageFormat ImageFormat + { + get + { + return ImageFormat.Bmp; + } + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Formats/FormatBase.cs b/src/ImageProcessor/Imaging/Formats/FormatBase.cs new file mode 100644 index 000000000..189bad8c3 --- /dev/null +++ b/src/ImageProcessor/Imaging/Formats/FormatBase.cs @@ -0,0 +1,160 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The supported format base implement this class when building a supported format. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Formats +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + + /// + /// The supported format base. Implement this class when building a supported format. + /// + public abstract class FormatBase : ISupportedImageFormat + { + /// + /// Initializes a new instance of the class. + /// + protected FormatBase() + { + this.Quality = 90; + } + + /// + /// Gets the file headers. + /// + public abstract byte[][] FileHeaders { get; } + + /// + /// Gets the list of file extensions. + /// + public abstract string[] FileExtensions { get; } + + /// + /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. + /// + public abstract string MimeType { get; } + + /// + /// Gets the default file extension. + /// + public string DefaultExtension + { + get + { + return this.MimeType.Replace("image/", string.Empty); + } + } + + /// + /// Gets the file format of the image. + /// + public abstract ImageFormat ImageFormat { get; } + + /// + /// Gets or sets a value indicating whether the image format is indexed. + /// + public bool IsIndexed { get; set; } + + /// + /// Gets or sets the quality of output for images. + /// + public int Quality { get; set; } + + /// + /// Applies the given processor the current image. + /// + /// The processor delegate. + /// The . + public virtual void ApplyProcessor(Func processor, ImageFactory factory) + { + factory.Image = processor.Invoke(factory); + } + + /// + /// Decodes the image to process. + /// + /// + /// The containing the image information. + /// + /// + /// The . + /// + public virtual Image Load(Stream stream) + { +#if !__MonoCS__ + return Image.FromStream(stream, true); +#else + return Image.FromStream(stream); +#endif + } + + /// + /// Saves the current image to the specified output stream. + /// + /// The to save the image information to. + /// The to save. + /// + /// The . + /// + public virtual Image Save(Stream stream, Image image) + { + image.Save(stream, this.ImageFormat); + stream.Position = 0; + return image; + } + + /// + /// Saves the current image to the specified file path. + /// + /// The path to save the image to. + /// The + /// to save. + /// + /// The . + /// + public virtual Image Save(string path, Image image) + { + image.Save(path, this.ImageFormat); + return image; + } + + /// + /// Determines whether the specified , is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object obj) + { + ISupportedImageFormat format = obj as ISupportedImageFormat; + + if (format == null) + { + return false; + } + + return this.MimeType.Equals(format.MimeType) && this.IsIndexed.Equals(format.IsIndexed); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + return this.MimeType.GetHashCode(); + } + } +} diff --git a/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs b/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs new file mode 100644 index 000000000..53025bf42 --- /dev/null +++ b/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs @@ -0,0 +1,218 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Utility methods for working with supported image formats. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Formats +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + using System.Linq; + using System.Reflection; + + using ImageProcessor.Configuration; + + /// + /// Utility methods for working with supported image formats. + /// + public static class FormatUtilities + { + /// + /// Gets the correct from the given stream. + /// + /// + /// + /// The to read from. + /// + /// + /// The . + /// + public static ISupportedImageFormat GetFormat(Stream stream) + { + // Reset the position of the stream to ensure we're reading the correct part. + stream.Position = 0; + + IEnumerable supportedImageFormats = + ImageProcessorBootstrapper.Instance.SupportedImageFormats; + + byte[] buffer = new byte[4]; + stream.Read(buffer, 0, buffer.Length); + + foreach (ISupportedImageFormat supportedImageFormat in supportedImageFormats) + { + byte[][] headers = supportedImageFormat.FileHeaders; + + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (byte[] header in headers) + { + if (header.SequenceEqual(buffer.Take(header.Length))) + { + stream.Position = 0; + + // Return a new instance as we want to use instance properties. + return Activator.CreateInstance(supportedImageFormat.GetType()) as ISupportedImageFormat; + } + } + } + + stream.Position = 0; + return null; + } + + /// + /// Returns a value indicating whether the given image is indexed. + /// + /// + /// The to test. + /// + /// + /// The true if the image is indexed; otherwise, false. + /// + public static bool IsIndexed(Image image) + { + // Test value of flags using bitwise AND. + // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags + return (image.PixelFormat & PixelFormat.Indexed) != 0; + } + + /// + /// Returns a value indicating whether the given image is indexed. + /// + /// + /// The to test. + /// + /// + /// The true if the image is animated; otherwise, false. + /// + public static bool IsAnimated(Image image) + { + return ImageAnimator.CanAnimate(image); + } + + /// + /// Returns information about the given . + /// + /// + /// The image to extend. + /// + /// + /// The image format. + /// + /// + /// Whether to fetch the images frames. + /// + /// + /// The . + /// + public static GifInfo GetGifInfo(Image image, ImageFormat format, bool fetchFrames = true) + { + if (image.RawFormat.Guid != ImageFormat.Gif.Guid && format.Guid != ImageFormat.Gif.Guid) + { + throw new ArgumentException("Image is not a gif."); + } + + GifInfo info = new GifInfo + { + Height = image.Height, + Width = image.Width + }; + + if (IsAnimated(image)) + { + info.IsAnimated = true; + + if (fetchFrames) + { + int frameCount = image.GetFrameCount(FrameDimension.Time); + int last = frameCount - 1; + int length = 0; + + List gifFrames = new List(); + + // Get the times stored in the gif. + byte[] times = image.GetPropertyItem((int)ExifPropertyTag.FrameDelay).Value; + + 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. + int delay = BitConverter.ToInt32(times, (4 * i) % times.Length); + delay = delay * 10 < 20 ? 20 : delay * 10; // Minimum delay is 20 ms + + // Find the frame + image.SelectActiveFrame(FrameDimension.Time, i); + + // TODO: Get positions. + gifFrames.Add(new GifFrame { Delay = delay, Image = (Image)image.Clone() }); + + // Reset the position. + if (i == last) + { + image.SelectActiveFrame(FrameDimension.Time, 0); + } + + length += delay; + } + + info.GifFrames = gifFrames; + info.AnimationLength = length; + + // Loop info is stored at byte 20737. + info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem((int)ExifPropertyTag.LoopCount).Value, 0); + info.IsLooped = info.LoopCount != 1; + } + } + + return info; + } + + /// + /// Returns an instance of EncodingParameters for jpeg compression. + /// + /// The quality to return the image at. + /// The encodingParameters for jpeg compression. + public static EncoderParameters GetEncodingParameters(int quality) + { + EncoderParameters encoderParameters = null; + try + { + // Create a series of encoder parameters. + encoderParameters = new EncoderParameters(1); + + // Set the quality. + encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality); + } + catch + { + if (encoderParameters != null) + { + encoderParameters.Dispose(); + } + } + + return encoderParameters; + } + + /// + /// Uses reflection to allow the creation of an instance of . + /// + /// + /// The . + /// + 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); + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/GifEncoder.cs b/src/ImageProcessor/Imaging/Formats/GifEncoder.cs similarity index 92% rename from src/ImageProcessor/Imaging/GifEncoder.cs rename to src/ImageProcessor/Imaging/Formats/GifEncoder.cs index 442b0a2d7..826ddf42f 100644 --- a/src/ImageProcessor/Imaging/GifEncoder.cs +++ b/src/ImageProcessor/Imaging/Formats/GifEncoder.cs @@ -9,19 +9,17 @@ // Always wire this up in a using block. // Disposing the encoder will complete the file. // Uses default .NET GIF encoding and adds animation headers. -// Adapted from +// Adapted from // // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Imaging +namespace ImageProcessor.Imaging.Formats { - #region Using using System; using System.Drawing.Imaging; using System.IO; using System.Linq; - #endregion /// /// Encodes multiple images as an animated gif to a stream. @@ -195,13 +193,6 @@ namespace ImageProcessor.Imaging } #endregion - #region Properties - /// - /// Gets or sets the frame delay. - /// - public TimeSpan FrameDelay { get; set; } - #endregion - #region Public Methods and Operators /// /// Adds a frame to the gif. @@ -291,31 +282,30 @@ namespace ImageProcessor.Imaging { int count = this.repeatCount.GetValueOrDefault(0); - // File Header + // File Header signature and version. this.WriteString(FileType); this.WriteString(FileVersion); + + // Write the logical screen descriptor. this.WriteShort(this.width.GetValueOrDefault(w)); // Initial Logical Width this.WriteShort(this.height.GetValueOrDefault(h)); // Initial Logical Height + + // Read the global color table info. sourceGif.Position = SourceGlobalColorInfoPosition; - this.WriteByte(sourceGif.ReadByte()); // Global Color Table Info + this.WriteByte(sourceGif.ReadByte()); + this.WriteByte(0); // Background Color Index this.WriteByte(0); // Pixel aspect ratio this.WriteColorTable(sourceGif); - // The different browsers interpret the spec differently when adding a loop. - // If the loop count is one IE and FF < 3 (incorrectly) loop an extra number of times. - // Removing the Netscape header should fix this. - if (count != 1) - { - // Application Extension Header - this.WriteShort(ApplicationExtensionBlockIdentifier); - this.WriteByte(ApplicationBlockSize); - this.WriteString(ApplicationIdentification); - this.WriteByte(3); // Application block length - this.WriteByte(1); - this.WriteShort(count); // Repeat count for images. - this.WriteByte(0); // Terminator - } + // Application Extension Header + this.WriteShort(ApplicationExtensionBlockIdentifier); + this.WriteByte(ApplicationBlockSize); + this.WriteString(ApplicationIdentification); + this.WriteByte(3); // Application block length + this.WriteByte(1); + this.WriteShort(count); // Repeat count for images. + this.WriteByte(0); // Terminator } /// @@ -361,7 +351,7 @@ namespace ImageProcessor.Imaging this.WriteShort(GraphicControlExtensionBlockIdentifier); // Identifier this.WriteByte(GraphicControlExtensionBlockSize); // Block Size this.WriteByte(blockhead[3] & 0xf7 | 0x08); // Setting disposal flag - this.WriteShort(Convert.ToInt32(frameDelay / 10)); // Setting frame delay + this.WriteShort(Convert.ToInt32(frameDelay / 10.0f)); // Setting frame delay this.WriteByte(blockhead[6]); // Transparent color index this.WriteByte(0); // Terminator } @@ -389,6 +379,7 @@ namespace ImageProcessor.Imaging /// 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 byte[] header = new byte[SourceImageBlockHeaderLength]; sourceGif.Read(header, 0, header.Length); @@ -437,6 +428,7 @@ namespace ImageProcessor.Imaging /// private void WriteShort(int value) { + // Leave only one significant byte. this.inputStream.WriteByte(Convert.ToByte(value & 0xff)); this.inputStream.WriteByte(Convert.ToByte((value >> 8) & 0xff)); } diff --git a/src/ImageProcessor/Imaging/Formats/GifFormat.cs b/src/ImageProcessor/Imaging/Formats/GifFormat.cs new file mode 100644 index 000000000..dffccb99b --- /dev/null +++ b/src/ImageProcessor/Imaging/Formats/GifFormat.cs @@ -0,0 +1,142 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides the necessary information to support gif images. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Formats +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + using System.Text; + + /// + /// Provides the necessary information to support gif images. + /// + public class GifFormat : FormatBase + { + /// + /// Gets the file headers. + /// + public override byte[][] FileHeaders + { + get + { + return new[] { Encoding.ASCII.GetBytes("GIF") }; + } + } + + /// + /// Gets the list of file extensions. + /// + public override string[] FileExtensions + { + get + { + return new[] { "gif" }; + } + } + + /// + /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. + /// + public override string MimeType + { + get + { + return "image/gif"; + } + } + + /// + /// Gets the . + /// + public override ImageFormat ImageFormat + { + get + { + return ImageFormat.Gif; + } + } + + /// + /// Applies the given processor the current image. + /// + /// The processor delegate. + /// The . + public override void ApplyProcessor(Func processor, ImageFactory factory) + { + GifInfo info = FormatUtilities.GetGifInfo(factory.Image, this.ImageFormat); + + if (info.IsAnimated) + { + OctreeQuantizer quantizer = new OctreeQuantizer(255, 8); + + // We don't dispose of the memory stream as that is disposed when a new image is created and doing so + // beforehand will cause an exception. + MemoryStream stream = new MemoryStream(); + using (GifEncoder encoder = new GifEncoder(stream, null, null, info.LoopCount)) + { + foreach (GifFrame frame in info.GifFrames) + { + factory.Image = frame.Image; + frame.Image = quantizer.Quantize(processor.Invoke(factory)); + encoder.AddFrame(frame); + } + } + + stream.Position = 0; + factory.Image = Image.FromStream(stream); + } + else + { + base.ApplyProcessor(processor, factory); + } + } + + /// + /// Saves the current image to the specified output stream. + /// + /// + /// The to save the image information to. + /// + /// The to save. + /// + /// The . + /// + public override Image Save(Stream stream, Image image) + { + if (!FormatUtilities.IsAnimated(image)) + { + image = new OctreeQuantizer(255, 8).Quantize(image); + } + + return base.Save(stream, image); + } + + /// + /// Saves the current image to the specified file path. + /// + /// The path to save the image to. + /// The + /// to save. + /// + /// The . + /// + public override Image Save(string path, Image image) + { + if (!FormatUtilities.IsAnimated(image)) + { + image = new OctreeQuantizer(255, 8).Quantize(image); + } + + return base.Save(path, image); + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/GifFrame.cs b/src/ImageProcessor/Imaging/Formats/GifFrame.cs similarity index 96% rename from src/ImageProcessor/Imaging/GifFrame.cs rename to src/ImageProcessor/Imaging/Formats/GifFrame.cs index 9a2e1e20b..943961cb9 100644 --- a/src/ImageProcessor/Imaging/GifFrame.cs +++ b/src/ImageProcessor/Imaging/Formats/GifFrame.cs @@ -8,7 +8,7 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Imaging +namespace ImageProcessor.Imaging.Formats { using System.Drawing; diff --git a/src/ImageProcessor/Extensions/ImageInfo.cs b/src/ImageProcessor/Imaging/Formats/GifInfo.cs similarity index 83% rename from src/ImageProcessor/Extensions/ImageInfo.cs rename to src/ImageProcessor/Imaging/Formats/GifInfo.cs index ebb55c631..2fdc1d715 100644 --- a/src/ImageProcessor/Extensions/ImageInfo.cs +++ b/src/ImageProcessor/Imaging/Formats/GifInfo.cs @@ -1,15 +1,15 @@ // -------------------------------------------------------------------------------------------------------------------- -// +// // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. // // // Provides information about an image. -// +// // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Extensions +namespace ImageProcessor.Imaging.Formats { using System.Collections.Generic; using ImageProcessor.Imaging; @@ -18,7 +18,7 @@ namespace ImageProcessor.Extensions /// Provides information about an image. /// /// - public class ImageInfo + public class GifInfo { /// /// Gets or sets the image width. @@ -30,11 +30,6 @@ namespace ImageProcessor.Extensions /// public int Height { get; set; } - /// - /// Gets or sets a value indicating whether the image is indexed. - /// - public bool IsIndexed { get; set; } - /// /// Gets or sets a value indicating whether the image is animated. /// diff --git a/src/ImageProcessor/Imaging/Formats/ISupportedImageFormat.cs b/src/ImageProcessor/Imaging/Formats/ISupportedImageFormat.cs new file mode 100644 index 000000000..05e69260a --- /dev/null +++ b/src/ImageProcessor/Imaging/Formats/ISupportedImageFormat.cs @@ -0,0 +1,108 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The SupportedImageFormat interface providing information about image formats to ImageProcessor. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Formats +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + + /// + /// The SupportedImageFormat interface providing information about image formats to ImageProcessor. + /// + public interface ISupportedImageFormat + { + /// + /// Gets the file headers. + /// + byte[][] FileHeaders { get; } + + /// + /// Gets the list of file extensions. + /// + string[] FileExtensions { get; } + + /// + /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. + /// + string MimeType { get; } + + /// + /// Gets the default file extension. + /// + string DefaultExtension { get; } + + /// + /// Gets the file format of the image. + /// + ImageFormat ImageFormat { get; } + + /// + /// Gets or sets a value indicating whether the image format is indexed. + /// + bool IsIndexed { get; set; } + + /// + /// Gets or sets the quality of output for images. + /// + int Quality { get; set; } + + #region Methods + /// + /// Applies the given processor the current image. + /// + /// + /// The processor delegate. + /// + /// + /// The . + /// + void ApplyProcessor(Func processor, ImageFactory factory); + + /// + /// Loads the image to process. + /// + /// + /// The containing the image information. + /// + /// + /// The . + /// + Image Load(Stream stream); + + /// + /// Saves the current image to the specified output stream. + /// + /// + /// The to save the image information to. + /// + /// + /// The to save. + /// + /// + /// The . + /// + Image Save(Stream stream, Image image); + + /// + /// Saves the current image to the specified file path. + /// + /// The path to save the image to. + /// + /// The to save. + /// + /// + /// The . + /// + Image Save(string path, Image image); + #endregion + } +} diff --git a/src/ImageProcessor/Imaging/Formats/JpegFormat.cs b/src/ImageProcessor/Imaging/Formats/JpegFormat.cs new file mode 100644 index 000000000..ae5fd05c3 --- /dev/null +++ b/src/ImageProcessor/Imaging/Formats/JpegFormat.cs @@ -0,0 +1,146 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides the necessary information to support jpeg images. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Formats +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + using System.Linq; + + /// + /// Provides the necessary information to support jpeg images. + /// + public sealed class JpegFormat : FormatBase + { + /// + /// Gets the file headers. + /// + public override byte[][] FileHeaders + { + get + { + return new[] { new byte[] { 255, 216, 255 } }; + } + } + + /// + /// Gets the list of file extensions. + /// + public override string[] FileExtensions + { + get + { + return new[] { "jpeg", "jpg" }; + } + } + + /// + /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. + /// + public override string MimeType + { + get + { + return "image/jpeg"; + } + } + + /// + /// Gets the . + /// + public override ImageFormat ImageFormat + { + get + { + return ImageFormat.Jpeg; + } + } + + /// + /// Applies the given processor the current image. + /// + /// The processor delegate. + /// The . + public override void ApplyProcessor(Func processor, ImageFactory factory) + { + base.ApplyProcessor(processor, factory); + + // Set the property item information from any Exif metadata. + // We do this here so that they can be changed between processor methods. + if (factory.PreserveExifData) + { + foreach (KeyValuePair propertItem in factory.ExifPropertyItems) + { + factory.Image.SetPropertyItem(propertItem.Value); + } + } + } + + /// + /// Saves the current image to the specified output stream. + /// + /// + /// The to save the image information to. + /// + /// The to save. + /// + /// The . + /// + public override Image Save(Stream stream, Image image) + { + // Jpegs can be saved with different settings to include a quality setting for the JPEG compression. + // This improves output compression and quality. + using (EncoderParameters encoderParameters = FormatUtilities.GetEncodingParameters(this.Quality)) + { + ImageCodecInfo imageCodecInfo = + ImageCodecInfo.GetImageEncoders() + .FirstOrDefault(ici => ici.MimeType.Equals(this.MimeType, StringComparison.OrdinalIgnoreCase)); + + if (imageCodecInfo != null) + { + image.Save(stream, imageCodecInfo, encoderParameters); + } + } + + return image; + } + + /// + /// Saves the current image to the specified file path. + /// + /// The path to save the image to. + /// The + /// to save. + /// + /// The . + /// + public override Image Save(string path, Image image) + { + // Jpegs can be saved with different settings to include a quality setting for the JPEG compression. + // This improves output compression and quality. + using (EncoderParameters encoderParameters = FormatUtilities.GetEncodingParameters(this.Quality)) + { + ImageCodecInfo imageCodecInfo = + ImageCodecInfo.GetImageEncoders() + .FirstOrDefault(ici => ici.MimeType.Equals(this.MimeType, StringComparison.OrdinalIgnoreCase)); + + if (imageCodecInfo != null) + { + image.Save(path, imageCodecInfo, encoderParameters); + } + } + + return image; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Formats/PngFormat.cs b/src/ImageProcessor/Imaging/Formats/PngFormat.cs new file mode 100644 index 000000000..cbfd938dd --- /dev/null +++ b/src/ImageProcessor/Imaging/Formats/PngFormat.cs @@ -0,0 +1,105 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides the necessary information to support png images. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Formats +{ + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + + /// + /// Provides the necessary information to support png images. + /// + public class PngFormat : FormatBase + { + /// + /// Gets the file headers. + /// + public override byte[][] FileHeaders + { + get + { + return new[] { new byte[] { 137, 80, 78, 71 } }; + } + } + + /// + /// Gets the list of file extensions. + /// Obviously png8 isn't a valid file extension but it's a neat way to + /// add the value to the format method detection. + /// + public override string[] FileExtensions + { + get + { + return new[] { "png" }; + } + } + + /// + /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. + /// + public override string MimeType + { + get + { + return "image/png"; + } + } + + /// + /// Gets the . + /// + public override ImageFormat ImageFormat + { + get + { + return ImageFormat.Png; + } + } + + /// + /// Saves the current image to the specified output stream. + /// + /// The to save the image information to. + /// The to save. + /// + /// The . + /// + public override Image Save(Stream stream, Image image) + { + if (this.IsIndexed) + { + image = new OctreeQuantizer(255, 8).Quantize(image); + } + + return base.Save(stream, image); + } + + /// + /// Saves the current image to the specified file path. + /// + /// The path to save the image to. + /// The + /// to save. + /// + /// The . + /// + public override Image Save(string path, Image image) + { + if (this.IsIndexed) + { + image = new OctreeQuantizer(255, 8).Quantize(image); + } + + return base.Save(path, image); + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/Formats/TiffFormat.cs b/src/ImageProcessor/Imaging/Formats/TiffFormat.cs new file mode 100644 index 000000000..59229dd88 --- /dev/null +++ b/src/ImageProcessor/Imaging/Formats/TiffFormat.cs @@ -0,0 +1,91 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides the necessary information to support tiff images. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Formats +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Provides the necessary information to support tiff images. + /// + public class TiffFormat : FormatBase + { + /// + /// Gets the file headers. + /// + public override byte[][] FileHeaders + { + get + { + return new[] + { + new byte[] { 73, 73, 42, 0 }, + new byte[] { 77, 77, 0, 42 } + }; + } + } + + /// + /// Gets the list of file extensions. + /// + public override string[] FileExtensions + { + get + { + return new[] { "tiff", "tif" }; + } + } + + /// + /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. + /// + public override string MimeType + { + get + { + return "image/tiff"; + } + } + + /// + /// Gets the . + /// + public override ImageFormat ImageFormat + { + get + { + return ImageFormat.Tiff; + } + } + + /// + /// Applies the given processor the current image. + /// + /// The processor delegate. + /// The . + public override void ApplyProcessor(Func processor, ImageFactory factory) + { + base.ApplyProcessor(processor, factory); + + // Set the property item information from any Exif metadata. + // We do this here so that they can be changed between processor methods. + if (factory.PreserveExifData) + { + foreach (KeyValuePair propertItem in factory.ExifPropertyItems) + { + factory.Image.SetPropertyItem(propertItem.Value); + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/ImageUtils.cs b/src/ImageProcessor/Imaging/ImageUtils.cs deleted file mode 100644 index 7c338a79e..000000000 --- a/src/ImageProcessor/Imaging/ImageUtils.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Encapsulates useful image utility methods. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Imaging -{ - #region Using - - using System; - using System.Drawing; - using System.Drawing.Imaging; - using System.Reflection; - - #endregion - - /// - /// Encapsulates useful image utility methods. - /// - public static class ImageUtils - { - /// - /// Returns an instance of EncodingParameters for jpeg compression. - /// - /// The quality to return the image at. - /// The encodingParameters for jpeg compression. - public static EncoderParameters GetEncodingParameters(int quality) - { - EncoderParameters encoderParameters = null; - try - { - // Create a series of encoder parameters. - encoderParameters = new EncoderParameters(1); - - // Set the quality. - encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality); - } - catch - { - if (encoderParameters != null) - { - encoderParameters.Dispose(); - } - } - - return encoderParameters; - } - - /// Returns a value indicating whether or not the given bitmap is indexed. - /// The image to check - /// Whether or not the given bitmap is indexed. - public static bool IsIndexed(Image image) - { - // Test value of flags using bitwise AND. - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - return (image.PixelFormat & PixelFormat.Indexed) != 0; - } - - /// - /// Uses reflection to allow the creation of an instance of . - /// - /// - /// The . - /// - 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); - } - } -} diff --git a/src/ImageProcessor/Imaging/ResizeLayer.cs b/src/ImageProcessor/Imaging/ResizeLayer.cs index 4fe81645b..dc5185922 100644 --- a/src/ImageProcessor/Imaging/ResizeLayer.cs +++ b/src/ImageProcessor/Imaging/ResizeLayer.cs @@ -26,10 +26,6 @@ namespace ImageProcessor.Imaging /// /// The containing the width and height to set the image to. /// - /// - /// The to set as the background color. - /// Used for image formats that do not support transparency (Default transparent) - /// /// /// The resize mode to apply to resized image. (Default ResizeMode.Pad) /// @@ -41,14 +37,12 @@ namespace ImageProcessor.Imaging /// public ResizeLayer( Size size, - Color? backgroundColor = null, ResizeMode resizeMode = ResizeMode.Pad, AnchorPosition anchorPosition = AnchorPosition.Center, bool upscale = true) { this.Size = size; this.Upscale = upscale; - this.BackgroundColor = backgroundColor ?? Color.Transparent; this.ResizeMode = resizeMode; this.AnchorPosition = anchorPosition; } @@ -60,11 +54,6 @@ namespace ImageProcessor.Imaging /// public Size Size { get; set; } - /// - /// Gets or sets the background color. - /// - public Color BackgroundColor { get; set; } - /// /// Gets or sets the resize mode. /// @@ -111,7 +100,6 @@ namespace ImageProcessor.Imaging return this.Size == resizeLayer.Size && this.ResizeMode == resizeLayer.ResizeMode && this.AnchorPosition == resizeLayer.AnchorPosition - && this.BackgroundColor == resizeLayer.BackgroundColor && this.Upscale == resizeLayer.Upscale; } @@ -126,8 +114,7 @@ namespace ImageProcessor.Imaging return this.Size.GetHashCode() + this.ResizeMode.GetHashCode() + this.AnchorPosition.GetHashCode() + - this.BackgroundColor.GetHashCode() + this.Upscale.GetHashCode(); } } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/ResponseType.cs b/src/ImageProcessor/Imaging/ResponseType.cs deleted file mode 100644 index 2cda9c16b..000000000 --- a/src/ImageProcessor/Imaging/ResponseType.cs +++ /dev/null @@ -1,63 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// ----------------------------------------------------------------------- - -namespace ImageProcessor.Imaging -{ - #region Using - using System.ComponentModel; - #endregion - - /// - /// Globally available enumeration which specifies the correct HTTP MIME type of - /// the output stream for different response types. - /// - /// http://en.wikipedia.org/wiki/Internet_media_type"/ - /// - /// - public enum ResponseType - { - #region Image - /// - /// The correct HTTP MIME type of the output stream for bmp images. - /// - [DescriptionAttribute("image/bmp")] - Bmp, - - /// - /// The correct HTTP MIME type of the output stream for gif images. - /// - [DescriptionAttribute("image/gif")] - Gif, - - /// - /// The correct HTTP MIME type of the output stream for jpeg images. - /// - [DescriptionAttribute("image/jpeg")] - Jpeg, - - /// - /// The correct HTTP MIME type of the output stream for png images. - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Png", Justification = "File extension name")] - [DescriptionAttribute("image/png")] - Png, - - /// - /// The correct HTTP MIME type of the output stream for svg images. - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Svg", Justification = "File extension name")] - [DescriptionAttribute("image/svg+xml")] - Svg, - - /// - /// The correct HTTP MIME type of the output stream for tiff images. - /// - [DescriptionAttribute("image/tiff")] - Tiff, - #endregion - } -} diff --git a/src/ImageProcessor/Imaging/RotateLayer.cs b/src/ImageProcessor/Imaging/RotateLayer.cs deleted file mode 100644 index 0b7c956ba..000000000 --- a/src/ImageProcessor/Imaging/RotateLayer.cs +++ /dev/null @@ -1,104 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// ----------------------------------------------------------------------- - -namespace ImageProcessor.Imaging -{ - #region Using - using System.Drawing; - #endregion - - /// - /// Encapsulates the properties required to rotate an image. - /// - public class RotateLayer - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public RotateLayer() - { - this.BackgroundColor = Color.Transparent; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The angle at which to rotate the image. - /// - public RotateLayer(int angle) - { - this.Angle = angle; - this.BackgroundColor = Color.Transparent; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The angle at which to rotate the image. - /// - /// - /// The to set as the background color. - /// Used for image formats that do not support transparency - /// - public RotateLayer(int angle, Color backgroundColor) - { - this.Angle = angle; - this.BackgroundColor = backgroundColor; - } - #endregion - - #region Properties - /// - /// Gets or sets the angle at which to rotate the image. - /// - public int Angle { get; set; } - - /// - /// Gets or sets the background color. - /// - public Color BackgroundColor { get; set; } - #endregion - - /// - /// Returns a value that indicates whether the specified object is an - /// object that is equivalent to - /// this object. - /// - /// - /// The object to test. - /// - /// - /// True if the given object is an object that is equivalent to - /// this object; otherwise, false. - /// - public override bool Equals(object obj) - { - RotateLayer rotate = obj as RotateLayer; - - if (rotate == null) - { - return false; - } - - return this.Angle == rotate.Angle && this.BackgroundColor == rotate.BackgroundColor; - } - - /// - /// Returns a hash code value that represents this object. - /// - /// - /// A hash code that represents this object. - /// - public override int GetHashCode() - { - return this.Angle.GetHashCode() + this.BackgroundColor.GetHashCode(); - } - } -} diff --git a/src/ImageProcessor/Imaging/RoundedCornerLayer.cs b/src/ImageProcessor/Imaging/RoundedCornerLayer.cs index edfcfd33e..05606d4b2 100644 --- a/src/ImageProcessor/Imaging/RoundedCornerLayer.cs +++ b/src/ImageProcessor/Imaging/RoundedCornerLayer.cs @@ -1,65 +1,25 @@ -namespace ImageProcessor.Imaging -{ - #region Using - using System.Drawing; - #endregion +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates the properties required to add rounded corners to an image. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace ImageProcessor.Imaging +{ /// /// Encapsulates the properties required to add rounded corners to an image. /// public class RoundedCornerLayer { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public RoundedCornerLayer() - { - this.Radius = 10; - this.BackgroundColor = Color.Transparent; - this.TopLeft = true; - this.TopRight = true; - this.BottomLeft = true; - this.BottomRight = true; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The radius at which the corner will be done. - /// - /// - /// Set if top left is rounded - /// - /// - /// Set if top right is rounded - /// - /// - /// Set if bottom left is rounded - /// - /// - /// Set if bottom right is rounded - /// - public RoundedCornerLayer(int radius, bool topLeft, bool topRight, bool bottomLeft, bool bottomRight) - { - this.Radius = radius; - this.BackgroundColor = Color.Transparent; - this.TopLeft = topLeft; - this.TopRight = topRight; - this.BottomLeft = bottomLeft; - this.BottomRight = bottomRight; - } - /// /// Initializes a new instance of the class. /// /// - /// The radius at which the corner will be done. - /// - /// - /// The to set as the background color. - /// Used for image formats that do not support transparency + /// The radius at which the corner will be rounded. /// /// /// Set if top left is rounded @@ -73,16 +33,14 @@ /// /// Set if bottom right is rounded /// - public RoundedCornerLayer(int radius, Color backgroundColor, bool topLeft, bool topRight, bool bottomLeft, bool bottomRight) + public RoundedCornerLayer(int radius, bool topLeft = true, bool topRight = true, bool bottomLeft = true, bool bottomRight = true) { this.Radius = radius; - this.BackgroundColor = backgroundColor; this.TopLeft = topLeft; this.TopRight = topRight; this.BottomLeft = bottomLeft; this.BottomRight = bottomRight; } - #endregion #region Properties /// @@ -90,11 +48,6 @@ /// public int Radius { get; set; } - /// - /// Gets or sets the background color. - /// - public Color BackgroundColor { get; set; } - /// /// Gets or sets a value indicating whether top left corners are to be added. /// @@ -137,7 +90,7 @@ return false; } - return this.Radius == rounded.Radius && this.BackgroundColor == rounded.BackgroundColor + return this.Radius == rounded.Radius && this.TopLeft == rounded.TopLeft && this.TopRight == rounded.TopRight && this.BottomLeft == rounded.BottomLeft && this.BottomRight == rounded.BottomRight; } @@ -150,7 +103,7 @@ /// public override int GetHashCode() { - return this.Radius.GetHashCode() + this.BackgroundColor.GetHashCode() + + return this.Radius.GetHashCode() + this.TopLeft.GetHashCode() + this.TopRight.GetHashCode() + this.BottomLeft.GetHashCode() + this.BottomRight.GetHashCode(); } diff --git a/src/ImageProcessor/Imaging/TextLayer.cs b/src/ImageProcessor/Imaging/TextLayer.cs index ae72fd9ae..490b7f95e 100644 --- a/src/ImageProcessor/Imaging/TextLayer.cs +++ b/src/ImageProcessor/Imaging/TextLayer.cs @@ -10,11 +10,8 @@ namespace ImageProcessor.Imaging { - #region Using - - using System; using System.Drawing; - #endregion + using System.Drawing.Text; /// /// Encapsulates the properties required to add a layer of text to an image. @@ -37,6 +34,11 @@ namespace ImageProcessor.Imaging /// private FontStyle fontStyle = FontStyle.Regular; + /// + /// The font family to render the text. + /// + private FontFamily fontFamily = new FontFamily(GenericFontFamilies.SansSerif); + /// /// The font size to render the text. /// @@ -55,21 +57,28 @@ namespace ImageProcessor.Imaging public string Text { get; set; } /// - /// Gets or sets the Color to render the font. + /// Gets or sets the to render the font. /// /// Defaults to black. /// /// - public Color TextColor + public Color FontColor { get { return this.textColor; } set { this.textColor = value; } } /// - /// Gets or sets the name of the font. + /// Gets or sets the name of the font family. + /// + /// Defaults to generic sans-serif font family. + /// /// - public string Font { get; set; } + public FontFamily FontFamily + { + get { return this.fontFamily; } + set { this.fontFamily = value; } + } /// /// Gets or sets the size of the font in pixels. @@ -100,17 +109,8 @@ namespace ImageProcessor.Imaging /// public int Opacity { - get - { - int alpha = (int)Math.Ceiling((this.opacity / 100d) * 255); - - return alpha < 255 ? alpha : 255; - } - - set - { - this.opacity = value; - } + get { return this.opacity; } + set { this.opacity = value; } } /// @@ -127,5 +127,54 @@ namespace ImageProcessor.Imaging /// public bool DropShadow { get; set; } #endregion + + /// + /// Returns a value that indicates whether the specified object is an + /// object that is equivalent to + /// this object. + /// + /// + /// The object to test. + /// + /// + /// True if the given object is an object that is equivalent to + /// this object; otherwise, false. + /// + public override bool Equals(object obj) + { + TextLayer textLayer = obj as TextLayer; + + if (textLayer == null) + { + return false; + } + + return this.Text == textLayer.Text + && this.FontColor == textLayer.FontColor + && this.FontFamily.Equals(textLayer.FontFamily) + && this.FontSize == textLayer.FontSize + && this.Style == textLayer.Style + && this.DropShadow == textLayer.DropShadow + && this.Opacity == textLayer.Opacity + && this.Position == textLayer.Position; + } + + /// + /// Returns a hash code value that represents this object. + /// + /// + /// A hash code that represents this object. + /// + public override int GetHashCode() + { + return this.Text.GetHashCode() + + this.FontColor.GetHashCode() + + this.FontFamily.GetHashCode() + + this.FontSize.GetHashCode() + + this.Style.GetHashCode() + + this.DropShadow.GetHashCode() + + this.Opacity.GetHashCode() + + this.Position.GetHashCode(); + } } } diff --git a/src/ImageProcessor/Processors/Alpha.cs b/src/ImageProcessor/Processors/Alpha.cs index 61463a6ab..a27e5f6f9 100644 --- a/src/ImageProcessor/Processors/Alpha.cs +++ b/src/ImageProcessor/Processors/Alpha.cs @@ -10,13 +10,12 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; - using System.Globalization; - using System.Text.RegularExpressions; - #endregion + + using ImageProcessor.Common.Exceptions; /// /// Encapsulates methods to change the alpha component of the image to effect its transparency. @@ -24,21 +23,11 @@ namespace ImageProcessor.Processors public class Alpha : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - /// - private static readonly Regex QueryRegex = new Regex(@"alpha=(?:100|[1-9]?[0-9])", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Alpha() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -50,15 +39,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -68,47 +48,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - int percentage = int.Parse(match.Value.Split('=')[1], CultureInfo.InvariantCulture); - - this.DynamicParameter = percentage; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -135,23 +79,32 @@ namespace ImageProcessor.Processors { imageAttributes.SetColorMatrix(colorMatrix); - graphics.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, imageAttributes); + graphics.DrawImage( + image, + new Rectangle(0, 0, image.Width, image.Height), + 0, + 0, + image.Width, + image.Height, + GraphicsUnit.Pixel, + imageAttributes); image.Dispose(); image = newImage; } } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/AutoRotate.cs b/src/ImageProcessor/Processors/AutoRotate.cs index e99f6c905..7368d2574 100644 --- a/src/ImageProcessor/Processors/AutoRotate.cs +++ b/src/ImageProcessor/Processors/AutoRotate.cs @@ -11,9 +11,11 @@ namespace ImageProcessor.Processors { + using System; using System.Collections.Generic; using System.Drawing; - using System.Text.RegularExpressions; + + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging; /// @@ -23,19 +25,11 @@ namespace ImageProcessor.Processors public class AutoRotate : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"autorotate=true", RegexOptions.Compiled); - - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public AutoRotate() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -47,15 +41,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -65,43 +50,10 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// - /// The the current instance of the + /// The current instance of the /// class containing /// the image to process. /// @@ -144,12 +96,14 @@ namespace ImageProcessor.Processors image = newImage; } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; diff --git a/src/ImageProcessor/Processors/BackgroundColor.cs b/src/ImageProcessor/Processors/BackgroundColor.cs new file mode 100644 index 000000000..a41396f90 --- /dev/null +++ b/src/ImageProcessor/Processors/BackgroundColor.cs @@ -0,0 +1,87 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Changes the background color of an image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Processors +{ + using System; + using System.Collections.Generic; + using System.Drawing; + + using ImageProcessor.Common.Exceptions; + + /// + /// Changes the background color of an image. + /// + public class BackgroundColor : IGraphicsProcessor + { + /// + /// Initializes a new instance of the class. + /// + public BackgroundColor() + { + this.Settings = new Dictionary(); + } + + /// + /// Gets or sets the DynamicParameter. + /// + public dynamic DynamicParameter { get; set; } + + /// + /// Gets or sets any additional settings required by the processor. + /// + public Dictionary Settings { get; set; } + + /// + /// Processes the image. + /// + /// The current instance of the + /// class containing + /// the image to process. + /// + /// The processed image from the current instance of the class. + /// + public Image ProcessImage(ImageFactory factory) + { + Bitmap newImage = null; + Image image = factory.Image; + + try + { + Color backgroundColor = this.DynamicParameter; + newImage = new Bitmap(image.Width, image.Height); + + // Make a graphics object from the empty bitmap. + using (Graphics graphics = Graphics.FromImage(newImage)) + { + // Fill the background. + graphics.Clear(backgroundColor); + + // Draw passed in image onto graphics object. + graphics.DrawImage(image, 0, 0); + } + + image.Dispose(); + image = newImage; + } + catch (Exception ex) + { + if (newImage != null) + { + newImage.Dispose(); + } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); + } + + return image; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/Processors/Brightness.cs b/src/ImageProcessor/Processors/Brightness.cs index 914f15d0a..a16f33e5c 100644 --- a/src/ImageProcessor/Processors/Brightness.cs +++ b/src/ImageProcessor/Processors/Brightness.cs @@ -10,13 +10,12 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; - using System.Globalization; - using System.Text.RegularExpressions; - #endregion + + using ImageProcessor.Common.Exceptions; /// /// Encapsulates methods to change the brightness component of the image. @@ -24,21 +23,11 @@ namespace ImageProcessor.Processors public class Brightness : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// + /// Initializes a new instance of the class. /// - private static readonly Regex QueryRegex = new Regex(@"brightness=(-?(?:100)|-?([1-9]?[0-9]))", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern + public Brightness() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -50,15 +39,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -68,47 +48,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - int percentage = int.Parse(match.Value.Split('=')[1], CultureInfo.InvariantCulture); - - this.DynamicParameter = percentage; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -125,16 +69,14 @@ namespace ImageProcessor.Processors newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb); - ColorMatrix colorMatrix = new ColorMatrix( - new float[][] - { - new float[] { 1, 0, 0, 0, 0 }, - new float[] { 0, 1, 0, 0, 0 }, - new float[] { 0, 0, 1, 0, 0 }, - new float[] { 0, 0, 0, 1, 0 }, - new float[] { brightnessFactor, brightnessFactor, brightnessFactor, 0, 1 } - }); - + ColorMatrix colorMatrix = + new ColorMatrix( + new[] + { + new float[] { 1, 0, 0, 0, 0 }, new float[] { 0, 1, 0, 0, 0 }, + new float[] { 0, 0, 1, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, + new[] { brightnessFactor, brightnessFactor, brightnessFactor, 0, 1 } + }); using (Graphics graphics = Graphics.FromImage(newImage)) { @@ -142,23 +84,32 @@ namespace ImageProcessor.Processors { imageAttributes.SetColorMatrix(colorMatrix); - graphics.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, imageAttributes); + graphics.DrawImage( + image, + new Rectangle(0, 0, image.Width, image.Height), + 0, + 0, + image.Width, + image.Height, + GraphicsUnit.Pixel, + imageAttributes); image.Dispose(); image = newImage; } } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/Contrast.cs b/src/ImageProcessor/Processors/Contrast.cs index 545a4b0c2..4170e660a 100644 --- a/src/ImageProcessor/Processors/Contrast.cs +++ b/src/ImageProcessor/Processors/Contrast.cs @@ -10,13 +10,12 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; - using System.Globalization; - using System.Text.RegularExpressions; - #endregion + + using ImageProcessor.Common.Exceptions; /// /// Encapsulates methods to change the contrast component of the image. @@ -24,21 +23,11 @@ namespace ImageProcessor.Processors public class Contrast : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - /// - private static readonly Regex QueryRegex = new Regex(@"contrast=(-?(?:100)|-?([1-9]?[0-9]))", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Contrast() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -50,15 +39,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -68,47 +48,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - int percentage = int.Parse(match.Value.Split('=')[1], CultureInfo.InvariantCulture); - - this.DynamicParameter = percentage; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -130,13 +74,13 @@ namespace ImageProcessor.Processors newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb); ColorMatrix colorMatrix = new ColorMatrix( - new float[][] + new[] { - new float[] { contrastFactor, 0, 0, 0, 0 }, - new float[] { 0, contrastFactor, 0, 0, 0 }, - new float[] { 0, 0, contrastFactor, 0, 0 }, + new[] { contrastFactor, 0, 0, 0, 0 }, + new[] { 0, contrastFactor, 0, 0, 0 }, + new[] { 0, 0, contrastFactor, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, - new float[] { factorTransform, factorTransform, factorTransform, 0, 1 } + new[] { factorTransform, factorTransform, factorTransform, 0, 1 } }); using (Graphics graphics = Graphics.FromImage(newImage)) @@ -152,16 +96,17 @@ namespace ImageProcessor.Processors } } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/Crop.cs b/src/ImageProcessor/Processors/Crop.cs index b2ff1493e..d0b8cb9ae 100644 --- a/src/ImageProcessor/Processors/Crop.cs +++ b/src/ImageProcessor/Processors/Crop.cs @@ -10,50 +10,26 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; - using System.Text; - using System.Text.RegularExpressions; - using ImageProcessor.Extensions; + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging; - #endregion - /// /// Crops an image to the given directions. /// public class Crop : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - /// - private static readonly Regex QueryRegex = new Regex(@"crop=\d+(.\d+)?[,-]\d+(.\d+)?[,-]\d+(.\d+)?[,-]\d+(.\d+)?|cropmode=(pixels|percent)", RegexOptions.Compiled); - - /// - /// The coordinate regex. - /// - private static readonly Regex CoordinateRegex = new Regex(@"crop=\d+(.\d+)?[,-]\d+(.\d+)?[,-]\d+(.\d+)?[,-]\d+(.\d+)?", RegexOptions.Compiled); - - /// - /// The mode regex. - /// - private static readonly Regex ModeRegex = new Regex(@"cropmode=(pixels|percent)", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Crop() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -65,15 +41,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -83,61 +50,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - // First merge the matches so we can parse . - StringBuilder stringBuilder = new StringBuilder(); - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - } - - stringBuilder.Append(match.Value); - - index += 1; - } - } - - if (this.SortOrder < int.MaxValue) - { - // Match syntax - string toParse = stringBuilder.ToString(); - - float[] coordinates = this.ParseCoordinates(toParse); - CropMode cropMode = this.ParseMode(toParse); - - CropLayer cropLayer = new CropLayer(coordinates[0], coordinates[1], coordinates[2], coordinates[3], cropMode); - this.DynamicParameter = cropLayer; - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -159,7 +76,7 @@ namespace ImageProcessor.Processors // Work out the percentages. float left = cropLayer.Left * sourceWidth; float top = cropLayer.Top * sourceHeight; - float width = (1 - cropLayer.Left - cropLayer.Right) * sourceWidth; + float width = (1 - cropLayer.Left - cropLayer.Right) * sourceWidth; float height = (1 - cropLayer.Top - cropLayer.Bottom) * sourceHeight; rectangleF = new RectangleF(left, top, width, height); @@ -216,65 +133,17 @@ namespace ImageProcessor.Processors } } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } - } - return image; - } - #endregion - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct . - /// - private CropMode ParseMode(string input) - { - foreach (Match match in ModeRegex.Matches(input)) - { - // Split on = - string mode = match.Value.Split('=')[1]; - - switch (mode) - { - case "percent": - return CropMode.Percentage; - case "pixels": - return CropMode.Pixels; - } + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } - return CropMode.Pixels; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct . - /// - private float[] ParseCoordinates(string input) - { - float[] floats = { }; - - foreach (Match match in CoordinateRegex.Matches(input)) - { - floats = match.Value.ToPositiveFloatArray(); - } - - return floats; + return image; } } } diff --git a/src/ImageProcessor/Processors/Filter.cs b/src/ImageProcessor/Processors/Filter.cs index 2673c7a29..e8130afa3 100644 --- a/src/ImageProcessor/Processors/Filter.cs +++ b/src/ImageProcessor/Processors/Filter.cs @@ -10,17 +10,13 @@ namespace ImageProcessor.Processors { - #region Using using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; - using System.Linq; - using System.Reflection; - using System.Text; - using System.Text.RegularExpressions; + + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging.Filters; - #endregion /// /// Encapsulates methods with which to add filters to an image. @@ -28,20 +24,11 @@ namespace ImageProcessor.Processors public class Filter : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = BuildRegex(); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Filter() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -53,15 +40,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -71,45 +49,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - this.DynamicParameter = match.Value.Split('=')[1]; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -123,85 +67,24 @@ namespace ImageProcessor.Processors try { newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb); - - IMatrixFilter matrix = this.DynamicParameter as IMatrixFilter ?? this.ParseFilter((string)this.DynamicParameter); + IMatrixFilter matrix = this.DynamicParameter; if (matrix != null) { return matrix.TransformImage(factory, image, newImage); } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } - } - return image; - } - #endregion - - /// - /// Builds a regular expression from the type, this allows extensibility. - /// - /// - /// The to match matrix filters. - /// - private static Regex BuildRegex() - { - const BindingFlags Flags = BindingFlags.Public | BindingFlags.Static; - Type type = typeof(MatrixFilters); - IEnumerable filters = type.GetProperties(Flags) - .Where(p => p.IsDefined(typeof(MatrixFilterRegexAttribute), false)) - .ToList(); - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.Append("filter=("); - int counter = 0; - - foreach (PropertyInfo filter in filters) - { - MatrixFilterRegexAttribute attribute = (MatrixFilterRegexAttribute)filter.GetCustomAttributes(typeof(MatrixFilterRegexAttribute), false).First(); - - if (counter == 0) - { - stringBuilder.Append(attribute.RegexIdentifier); - } - else - { - stringBuilder.AppendFormat("|{0}", attribute.RegexIdentifier); - } - - counter++; + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } - stringBuilder.Append(")"); - - return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase | RegexOptions.Compiled); - } - - /// - /// Parses the filter. - /// - /// - /// The identifier. - /// - /// - /// The . - /// - private IMatrixFilter ParseFilter(string identifier) - { - const BindingFlags Flags = BindingFlags.Public | BindingFlags.Static; - - Type type = typeof(MatrixFilters); - PropertyInfo filter = - type.GetProperties(Flags) - .Where(p => p.IsDefined(typeof(MatrixFilterRegexAttribute), false)) - .First(p => ((MatrixFilterRegexAttribute)p.GetCustomAttributes(typeof(MatrixFilterRegexAttribute), false).First()).RegexIdentifier == identifier); - - return filter.GetValue(null, null) as IMatrixFilter; + return image; } } } diff --git a/src/ImageProcessor/Processors/Flip.cs b/src/ImageProcessor/Processors/Flip.cs index c845ba281..839edc34d 100644 --- a/src/ImageProcessor/Processors/Flip.cs +++ b/src/ImageProcessor/Processors/Flip.cs @@ -10,11 +10,11 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; - using System.Text.RegularExpressions; - #endregion + + using ImageProcessor.Common.Exceptions; /// /// Flips an image horizontally or vertically. @@ -22,21 +22,11 @@ namespace ImageProcessor.Processors public class Flip : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - /// - private static readonly Regex QueryRegex = new Regex(@"flip=(horizontal|vertical|both)", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Flip() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -48,15 +38,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -66,58 +47,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - string direction = match.Value.Split('=')[1]; - - switch (direction) - { - case "horizontal": - this.DynamicParameter = RotateFlipType.RotateNoneFlipX; - break; - case "vertical": - this.DynamicParameter = RotateFlipType.RotateNoneFlipY; - break; - default: - this.DynamicParameter = RotateFlipType.RotateNoneFlipXY; - break; - } - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -140,16 +74,17 @@ namespace ImageProcessor.Processors image.Dispose(); image = newImage; } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/Format.cs b/src/ImageProcessor/Processors/Format.cs index 97173b836..2695180af 100644 --- a/src/ImageProcessor/Processors/Format.cs +++ b/src/ImageProcessor/Processors/Format.cs @@ -10,12 +10,12 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; - using System.Drawing.Imaging; - using System.Text.RegularExpressions; - #endregion + + using ImageProcessor.Common.Exceptions; + using ImageProcessor.Imaging.Formats; /// /// Sets the output of the image to a specific format. @@ -23,20 +23,11 @@ namespace ImageProcessor.Processors public class Format : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"format=(j(pg|peg)|pn(g8|g)|bmp|gif|ti(ff|f)|ico)", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Format() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -48,15 +39,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -66,45 +48,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - this.DynamicParameter = match.Value.Split('=')[1]; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -112,44 +60,17 @@ namespace ImageProcessor.Processors /// public Image ProcessImage(ImageFactory factory) { - string format = this.DynamicParameter; - bool isIndexed = false; - ImageFormat imageFormat; - switch (format) + try { - case "png": - imageFormat = ImageFormat.Png; - break; - case "png8": - imageFormat = ImageFormat.Png; - isIndexed = true; - break; - case "bmp": - imageFormat = ImageFormat.Bmp; - break; - case "gif": - imageFormat = ImageFormat.Gif; - isIndexed = true; - break; - case "tif": - case "tiff": - imageFormat = ImageFormat.Tiff; - break; - case "ico": - imageFormat = ImageFormat.Icon; - break; - default: - // Should be a jpeg or jpg. - imageFormat = ImageFormat.Jpeg; - break; + ISupportedImageFormat format = this.DynamicParameter; + factory.Format(format); + } + catch (Exception ex) + { + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } - - // Set the internal property. - factory.OriginalExtension = string.Format(".{0}", format); - factory.Format(imageFormat, isIndexed); return factory.Image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/GaussianBlur.cs b/src/ImageProcessor/Processors/GaussianBlur.cs index d96ee7f54..1ddf9e787 100644 --- a/src/ImageProcessor/Processors/GaussianBlur.cs +++ b/src/ImageProcessor/Processors/GaussianBlur.cs @@ -13,8 +13,8 @@ namespace ImageProcessor.Processors using System; using System.Collections.Generic; using System.Drawing; - using System.Globalization; - using System.Text.RegularExpressions; + + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging; /// @@ -22,38 +22,12 @@ namespace ImageProcessor.Processors /// public class GaussianBlur : IGraphicsProcessor { - #region Fields - /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"blur=[^&]*", RegexOptions.Compiled); - - /// - /// The blur regex. - /// - private static readonly Regex BlurRegex = new Regex(@"blur=\d+", RegexOptions.Compiled); - - /// - /// The sigma regex. - /// - private static readonly Regex SigmaRegex = new Regex(@"sigma-\d+(.?\d+)?", RegexOptions.Compiled); - /// - /// The threshold regex. + /// Initializes a new instance of the class. /// - private static readonly Regex ThresholdRegex = new Regex(@"threshold-\d+", RegexOptions.Compiled); - #endregion - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern + public GaussianBlur() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -61,70 +35,15 @@ namespace ImageProcessor.Processors /// public dynamic DynamicParameter { get; set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder { get; private set; } - /// /// Gets or sets any additional settings required by the processor. /// public Dictionary Settings { get; set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// The query string to search. - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - - // Normalise and set the variables. - int maxSize; - double maxSigma; - int maxThreshold; - - int.TryParse(this.Settings["MaxSize"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxSize); - double.TryParse(this.Settings["MaxSigma"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxSigma); - int.TryParse(this.Settings["MaxThreshold"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxThreshold); - - int size = this.ParseBlur(match.Value); - double sigma = this.ParseSigma(match.Value); - int threshold = this.ParseThreshold(match.Value); - - size = maxSize < size ? maxSize : size; - sigma = maxSigma < sigma ? maxSigma : sigma; - threshold = maxThreshold < threshold ? maxThreshold : threshold; - - this.DynamicParameter = new GaussianLayer(size, sigma, threshold); - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The processed image from the current instance of the class. @@ -137,7 +56,7 @@ namespace ImageProcessor.Processors try { newImage = new Bitmap(image); - GaussianLayer gaussianLayer = (GaussianLayer)this.DynamicParameter; + GaussianLayer gaussianLayer = this.DynamicParameter; Convolution convolution = new Convolution(gaussianLayer.Sigma) { Threshold = gaussianLayer.Threshold }; double[,] kernel = convolution.CreateGuassianBlurFilter(gaussianLayer.Size); @@ -146,81 +65,17 @@ namespace ImageProcessor.Processors image.Dispose(); image = newImage; } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } - } - - return image; - } - #endregion - - #region Private - /// - /// Returns the correct containing the sigma value - /// for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct for the given string. - /// - private double ParseSigma(string input) - { - foreach (Match match in SigmaRegex.Matches(input)) - { - // split on text- - return Convert.ToDouble(match.Value.Split('-')[1]); - } - - return 1.4d; - } - /// - /// Returns the correct containing the threshold value - /// for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct for the given string. - /// - private int ParseThreshold(string input) - { - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (Match match in ThresholdRegex.Matches(input)) - { - return Convert.ToInt32(match.Value.Split('-')[1]); + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } - return 0; - } - - /// - /// Returns the correct containing the blur value - /// for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct for the given string. - /// - private int ParseBlur(string input) - { - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (Match match in BlurRegex.Matches(input)) - { - return Convert.ToInt32(match.Value.Split('=')[1]); - } - - return 0; + return image; } - #endregion } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Processors/GaussianSharpen.cs b/src/ImageProcessor/Processors/GaussianSharpen.cs index 8c4672bf6..8aaf84e5d 100644 --- a/src/ImageProcessor/Processors/GaussianSharpen.cs +++ b/src/ImageProcessor/Processors/GaussianSharpen.cs @@ -13,8 +13,8 @@ namespace ImageProcessor.Processors using System; using System.Collections.Generic; using System.Drawing; - using System.Globalization; - using System.Text.RegularExpressions; + + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging; /// @@ -22,38 +22,12 @@ namespace ImageProcessor.Processors /// public class GaussianSharpen : IGraphicsProcessor { - #region Fields - /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"sharpen=[^&]*", RegexOptions.Compiled); - - /// - /// The sharpen regex. - /// - private static readonly Regex SharpenRegex = new Regex(@"sharpen=\d+", RegexOptions.Compiled); - - /// - /// The sigma regex. - /// - private static readonly Regex SigmaRegex = new Regex(@"sigma-\d+(.?\d+)?", RegexOptions.Compiled); - /// - /// The threshold regex. + /// Initializes a new instance of the class. /// - private static readonly Regex ThresholdRegex = new Regex(@"threshold-\d+", RegexOptions.Compiled); - #endregion - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern + public GaussianSharpen() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -61,70 +35,15 @@ namespace ImageProcessor.Processors /// public dynamic DynamicParameter { get; set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder { get; private set; } - /// /// Gets or sets any additional settings required by the processor. /// public Dictionary Settings { get; set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// The query string to search. - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - - // Normalise and set the variables. - int maxSize; - double maxSigma; - int maxThreshold; - - int.TryParse(this.Settings["MaxSize"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxSize); - double.TryParse(this.Settings["MaxSigma"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxSigma); - int.TryParse(this.Settings["MaxThreshold"], NumberStyles.Any, CultureInfo.InvariantCulture, out maxThreshold); - - int size = this.ParseSharpen(match.Value); - double sigma = this.ParseSigma(match.Value); - int threshold = this.ParseThreshold(match.Value); - - size = maxSize < size ? maxSize : size; - sigma = maxSigma < sigma ? maxSigma : sigma; - threshold = maxThreshold < threshold ? maxThreshold : threshold; - - this.DynamicParameter = new GaussianLayer(size, sigma, threshold); - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// The processed image from the current instance of the class. @@ -137,7 +56,7 @@ namespace ImageProcessor.Processors try { newImage = new Bitmap(image); - GaussianLayer gaussianLayer = (GaussianLayer)this.DynamicParameter; + GaussianLayer gaussianLayer = this.DynamicParameter; Convolution convolution = new Convolution(gaussianLayer.Sigma) { Threshold = gaussianLayer.Threshold }; double[,] kernel = convolution.CreateGuassianSharpenFilter(gaussianLayer.Size); @@ -146,81 +65,17 @@ namespace ImageProcessor.Processors image.Dispose(); image = newImage; } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } - } - - return image; - } - #endregion - - #region Private - /// - /// Returns the correct containing the sigma value - /// for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct for the given string. - /// - private double ParseSigma(string input) - { - foreach (Match match in SigmaRegex.Matches(input)) - { - // split on text- - return Convert.ToDouble(match.Value.Split('-')[1]); - } - - return 1.4d; - } - /// - /// Returns the correct containing the threshold value - /// for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct for the given string. - /// - private int ParseThreshold(string input) - { - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (Match match in ThresholdRegex.Matches(input)) - { - return Convert.ToInt32(match.Value.Split('-')[1]); + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } - return 0; - } - - /// - /// Returns the correct containing the sharpen value - /// for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct for the given string. - /// - private int ParseSharpen(string input) - { - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (Match match in SharpenRegex.Matches(input)) - { - return Convert.ToInt32(match.Value.Split('=')[1]); - } - - return 0; + return image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/IGraphicsProcessor.cs b/src/ImageProcessor/Processors/IGraphicsProcessor.cs index 148c7a7e4..79f3e66c6 100644 --- a/src/ImageProcessor/Processors/IGraphicsProcessor.cs +++ b/src/ImageProcessor/Processors/IGraphicsProcessor.cs @@ -23,43 +23,22 @@ namespace ImageProcessor.Processors { #region Properties /// - /// Gets the regular expression to search strings for. + /// Gets or sets the DynamicParameter. /// - Regex RegexPattern { get; } - - /// - /// Gets DynamicParameter. - /// - dynamic DynamicParameter { get; } - - /// - /// Gets the order in which this processor is to be used in a chain. - /// - int SortOrder { get; } + dynamic DynamicParameter { get; set; } /// /// Gets or sets any additional settings required by the processor. /// - Dictionary Settings { get; set; } + Dictionary Settings { get; set; } #endregion #region Methods - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - int MatchRegexIndex(string queryString); - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// diff --git a/src/ImageProcessor/Processors/Meta.cs b/src/ImageProcessor/Processors/Meta.cs new file mode 100644 index 000000000..5eb2eabeb --- /dev/null +++ b/src/ImageProcessor/Processors/Meta.cs @@ -0,0 +1,74 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to control preservation of meta information. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Processors +{ + using System; + using System.Collections.Generic; + using System.Drawing; + + using ImageProcessor.Common.Exceptions; + + /// + /// Encapsulates methods to control preservation of meta information. + /// + public class Meta : IGraphicsProcessor + { + /// + /// Initializes a new instance of the class. + /// + public Meta() + { + this.Settings = new Dictionary(); + } + + /// + /// Gets or sets DynamicParameter. + /// + public dynamic DynamicParameter + { + get; + set; + } + + /// + /// Gets or sets any additional settings required by the processor. + /// + public Dictionary Settings + { + get; + set; + } + + /// + /// Processes the image. + /// + /// + /// The current instance of the class containing + /// the image to process. + /// + /// + /// The processed image from the current instance of the class. + /// + public Image ProcessImage(ImageFactory factory) + { + try + { + factory.PreserveExifData = this.DynamicParameter; + } + catch (Exception ex) + { + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); + } + + return factory.Image; + } + } +} diff --git a/src/ImageProcessor/Processors/Quality.cs b/src/ImageProcessor/Processors/Quality.cs index 97b4b7651..015c519eb 100644 --- a/src/ImageProcessor/Processors/Quality.cs +++ b/src/ImageProcessor/Processors/Quality.cs @@ -10,12 +10,11 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; - using System.Globalization; - using System.Text.RegularExpressions; - #endregion + + using ImageProcessor.Common.Exceptions; /// /// Encapsulates methods to change the quality component of the image. @@ -23,20 +22,11 @@ namespace ImageProcessor.Processors public class Quality : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"quality=(?:100|[1-9]?[0-9])", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Quality() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -48,15 +38,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -66,47 +47,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - int percentage = int.Parse(match.Value.Split('=')[1], CultureInfo.InvariantCulture); - - this.DynamicParameter = percentage; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -114,11 +59,16 @@ namespace ImageProcessor.Processors /// public Image ProcessImage(ImageFactory factory) { - // Set the internal property. - factory.JpegQuality = this.DynamicParameter; + try + { + factory.CurrentImageFormat.Quality = this.DynamicParameter; + } + catch (Exception ex) + { + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); + } return factory.Image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/Resize.cs b/src/ImageProcessor/Processors/Resize.cs index 2c2bbbcb4..845f477f8 100644 --- a/src/ImageProcessor/Processors/Resize.cs +++ b/src/ImageProcessor/Processors/Resize.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. @@ -10,7 +10,6 @@ namespace ImageProcessor.Processors { - #region Using using System; using System.Collections.Generic; using System.Drawing; @@ -18,11 +17,9 @@ namespace ImageProcessor.Processors using System.Drawing.Imaging; using System.Globalization; using System.Linq; - using System.Text; - using System.Text.RegularExpressions; - using ImageProcessor.Extensions; + + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging; - #endregion /// /// Resizes an image to the given dimensions. @@ -30,55 +27,11 @@ namespace ImageProcessor.Processors public class Resize : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"(width|height)=|(width|height)ratio=|mode=|anchor=|center=|bgcolor=|upscale=", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the size attribute. - /// - private static readonly Regex SizeRegex = new Regex(@"(width|height)=\d+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the ratio attribute. - /// - private static readonly Regex RatioRegex = new Regex(@"(width|height)ratio=\d+(.\d+)?", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the mode attribute. - /// - private static readonly Regex ModeRegex = new Regex(@"mode=(pad|stretch|crop|max)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the anchor attribute. - /// - private static readonly Regex AnchorRegex = new Regex(@"anchor=(top|bottom|left|right|center)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the center attribute. - /// - private static readonly Regex CenterRegex = new Regex(@"center=\d+(.\d+)?[,-]\d+(.\d+)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the color attribute. + /// Initializes a new instance of the class. /// - private static readonly Regex ColorRegex = new Regex(@"bgcolor=(transparent|\d+,\d+,\d+,\d+|([0-9a-fA-F]{3}){1,2})", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the upscale attribute. - /// - private static readonly Regex UpscaleRegex = new Regex(@"upscale=false", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern + public Resize() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -90,15 +43,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -109,62 +53,15 @@ namespace ImageProcessor.Processors } /// - /// The position in the original string where the first character of the captured substring was found. + /// Gets or sets the list of sizes to restrict resizing methods to. /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - // First merge the matches so we can parse . - StringBuilder stringBuilder = new StringBuilder(); - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - stringBuilder.Append(queryString); - } - - index += 1; - } - } - - // Match syntax - string toParse = stringBuilder.ToString(); - - Size size = this.ParseSize(toParse); - ResizeLayer resizeLayer = new ResizeLayer(size) - { - ResizeMode = this.ParseMode(toParse), - AnchorPosition = this.ParsePosition(toParse), - BackgroundColor = this.ParseColor(toParse), - Upscale = !UpscaleRegex.IsMatch(toParse), - CenterCoordinates = this.ParseCoordinates(toParse), - }; - - this.DynamicParameter = resizeLayer; - - return this.SortOrder; - } + public List RestrictedSizes { get; set; } /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -176,27 +73,23 @@ namespace ImageProcessor.Processors int height = this.DynamicParameter.Size.Height ?? 0; ResizeMode mode = this.DynamicParameter.ResizeMode; AnchorPosition anchor = this.DynamicParameter.AnchorPosition; - Color backgroundColor = this.DynamicParameter.BackgroundColor; bool upscale = this.DynamicParameter.Upscale; float[] centerCoordinates = this.DynamicParameter.CenterCoordinates; int defaultMaxWidth; int defaultMaxHeight; - string restrictions; - this.Settings.TryGetValue("RestrictTo", out restrictions); + int.TryParse(this.Settings["MaxWidth"], NumberStyles.Any, CultureInfo.InvariantCulture, out defaultMaxWidth); int.TryParse(this.Settings["MaxHeight"], NumberStyles.Any, CultureInfo.InvariantCulture, out defaultMaxHeight); - List restrictedSizes = this.ParseRestrictions(restrictions); - return this.ResizeImage(factory, width, height, defaultMaxWidth, defaultMaxHeight, restrictedSizes, backgroundColor, mode, anchor, upscale, centerCoordinates); + return this.ResizeImage(factory, width, height, defaultMaxWidth, defaultMaxHeight, this.RestrictedSizes, mode, anchor, upscale, centerCoordinates); } - #endregion /// /// The resize image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -214,9 +107,6 @@ namespace ImageProcessor.Processors /// /// A containing image resizing restrictions. /// - /// - /// The background color to pad the image with. - /// /// /// The mode with which to resize the image. /// @@ -239,7 +129,6 @@ namespace ImageProcessor.Processors int defaultMaxWidth, int defaultMaxHeight, List restrictedSizes, - Color backgroundColor, ResizeMode resizeMode = ResizeMode.Pad, AnchorPosition anchorPosition = AnchorPosition.Center, bool upscale = true, @@ -266,7 +155,7 @@ namespace ImageProcessor.Processors int destinationX = 0; int destinationY = 0; - // Change the destination rectangle coordinates if padding and + // Change the destination rectangle coordinates if padding and // there has been a set width and height. if (resizeMode == ResizeMode.Pad && width > 0 && height > 0) { @@ -286,7 +175,7 @@ namespace ImageProcessor.Processors } } - // Change the destination rectangle coordinates if cropping and + // Change the destination rectangle coordinates if cropping and // there has been a set width and height. if (resizeMode == ResizeMode.Crop && width > 0 && height > 0) { @@ -403,7 +292,7 @@ namespace ImageProcessor.Processors } // Restrict sizes - if (restrictedSizes.Any()) + if (restrictedSizes != null && restrictedSizes.Any()) { bool reject = true; foreach (Size restrictedSize in restrictedSizes) @@ -462,7 +351,6 @@ namespace ImageProcessor.Processors using (ImageAttributes wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); - graphics.Clear(backgroundColor); Rectangle destRect = new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight); graphics.DrawImage(image, destRect, 0, 0, sourceWidth, sourceHeight, GraphicsUnit.Pixel, wrapMode); } @@ -473,232 +361,17 @@ namespace ImageProcessor.Processors } } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } - } - - return image; - } - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The . - /// - private Size ParseSize(string input) - { - const string Width = "width="; - const string Height = "height="; - const string WidthRatio = "widthratio="; - const string HeightRatio = "heightratio="; - Size size = new Size(); - - // First merge the matches so we can parse . - StringBuilder stringBuilder = new StringBuilder(); - foreach (Match match in SizeRegex.Matches(input)) - { - stringBuilder.Append(match.Value); - } - - // First cater for single dimensions. - string value = stringBuilder.ToString(); - - if (input.Contains(Width) && !input.Contains(Height)) - { - size = new Size(value.ToPositiveIntegerArray()[0], 0); - } - - if (input.Contains(Height) && !input.Contains(Width)) - { - size = new Size(0, value.ToPositiveIntegerArray()[0]); - } - - // Both dimensions supplied. - if (input.Contains(Height) && input.Contains(Width)) - { - int[] dimensions = value.ToPositiveIntegerArray(); - - // Check the order in which they have been supplied. - size = input.IndexOf(Width, StringComparison.Ordinal) < input.IndexOf(Height, StringComparison.Ordinal) - ? new Size(dimensions[0], dimensions[1]) - : new Size(dimensions[1], dimensions[0]); + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } - // Calculate any ratio driven sizes. - if (size.Width == 0 || size.Height == 0) - { - stringBuilder.Clear(); - foreach (Match match in RatioRegex.Matches(input)) - { - stringBuilder.Append(match.Value); - } - - value = stringBuilder.ToString(); - - // Replace 0 width - if (size.Width == 0 && size.Height > 0 && input.Contains(WidthRatio) && !input.Contains(HeightRatio)) - { - size.Width = (int)Math.Ceiling(value.ToPositiveFloatArray()[0] * size.Height); - } - - // Replace 0 height - if (size.Height == 0 && size.Width > 0 && input.Contains(HeightRatio) && !input.Contains(WidthRatio)) - { - size.Height = (int)Math.Ceiling(value.ToPositiveFloatArray()[0] * size.Width); - } - } - - return size; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct . - /// - private ResizeMode ParseMode(string input) - { - foreach (Match match in ModeRegex.Matches(input)) - { - // Split on = - string mode = match.Value.Split('=')[1]; - - switch (mode) - { - case "stretch": - return ResizeMode.Stretch; - case "crop": - return ResizeMode.Crop; - case "max": - return ResizeMode.Max; - default: - return ResizeMode.Pad; - } - } - - return ResizeMode.Pad; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct . - /// - private AnchorPosition ParsePosition(string input) - { - foreach (Match match in AnchorRegex.Matches(input)) - { - // Split on = - string anchor = match.Value.Split('=')[1]; - - switch (anchor) - { - case "top": - return AnchorPosition.Top; - case "bottom": - return AnchorPosition.Bottom; - case "left": - return AnchorPosition.Left; - case "right": - return AnchorPosition.Right; - default: - return AnchorPosition.Center; - } - } - - return AnchorPosition.Center; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct - /// - private Color ParseColor(string input) - { - foreach (Match match in ColorRegex.Matches(input)) - { - string value = match.Value.Split('=')[1]; - - if (value == "transparent") - { - return Color.Transparent; - } - - if (value.Contains(",")) - { - int[] split = value.ToPositiveIntegerArray(); - byte red = split[0].ToByte(); - byte green = split[1].ToByte(); - byte blue = split[2].ToByte(); - byte alpha = split[3].ToByte(); - - return Color.FromArgb(alpha, red, green, blue); - } - - // Split on color-hex - return ColorTranslator.FromHtml("#" + value); - } - - return Color.Transparent; - } - - /// - /// Returns a of sizes to restrict resizing to. - /// - /// - /// The input. - /// - /// - /// The to restrict resizing to. - /// - private List ParseRestrictions(string input) - { - List sizes = new List(); - - if (!string.IsNullOrWhiteSpace(input)) - { - sizes.AddRange(input.Split(',').Select(this.ParseSize)); - } - - return sizes; - } - - /// - /// Parses the coordinates. - /// - /// The input. - /// The array containing the coordinates - private float[] ParseCoordinates(string input) - { - float[] floats = { }; - - foreach (Match match in CenterRegex.Matches(input)) - { - floats = match.Value.ToPositiveFloatArray(); - } - - return floats; + return image; } } } diff --git a/src/ImageProcessor/Processors/Rotate.cs b/src/ImageProcessor/Processors/Rotate.cs index 0547fad06..2e5931dcc 100644 --- a/src/ImageProcessor/Processors/Rotate.cs +++ b/src/ImageProcessor/Processors/Rotate.cs @@ -10,15 +10,12 @@ namespace ImageProcessor.Processors { - #region Using using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; - using System.Globalization; - using System.Text.RegularExpressions; - using ImageProcessor.Imaging; - #endregion + + using ImageProcessor.Common.Exceptions; /// /// Encapsulates methods to rotate an image. @@ -26,30 +23,11 @@ namespace ImageProcessor.Processors public class Rotate : IGraphicsProcessor { /// - /// The regular expression to search strings for. + /// Initializes a new instance of the class. /// - private static readonly Regex QueryRegex = new Regex(@"rotate=((?:3[0-5][0-9]|[12][0-9]{2}|[1-9][0-9]?)|angle-(?:3[0-5][0-9]|[12][0-9]{2}|[1-9][0-9]?)[\|,]bgcolor-([0-9a-fA-F]{3}){1,2})", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the angle attribute. - /// - private static readonly Regex AngleRegex = new Regex(@"angle-(?:3[0-5][0-9]|[12][0-9]{2}|[1-9][0-9]?)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the color attribute. - /// - private static readonly Regex ColorRegex = new Regex(@"bgcolor-([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern + public Rotate() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -61,15 +39,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -79,62 +48,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - - RotateLayer rotateLayer; - - string toParse = match.Value; - - if (toParse.Contains("bgcolor")) - { - rotateLayer = new RotateLayer(this.ParseAngle(toParse), this.ParseColor(toParse)); - } - else - { - int degrees; - int.TryParse(match.Value.Split('=')[1], NumberStyles.Any, CultureInfo.InvariantCulture, out degrees); - - rotateLayer = new RotateLayer(degrees); - } - - this.DynamicParameter = rotateLayer; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -147,31 +65,30 @@ namespace ImageProcessor.Processors try { - RotateLayer rotateLayer = this.DynamicParameter; - int angle = rotateLayer.Angle; - Color backgroundColor = rotateLayer.BackgroundColor; + int angle = this.DynamicParameter; // Center of the image float rotateAtX = Math.Abs(image.Width / 2); float rotateAtY = Math.Abs(image.Height / 2); // Create a rotated image. - newImage = this.RotateImage(image, rotateAtX, rotateAtY, angle, backgroundColor); + newImage = this.RotateImage(image, rotateAtX, rotateAtY, angle); image.Dispose(); image = newImage; } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion #region Private Methods /// @@ -181,12 +98,11 @@ namespace ImageProcessor.Processors /// The horizontal pixel coordinate at which to rotate the image. /// The vertical pixel coordinate at which to rotate the image. /// The angle in degrees at which to rotate the image. - /// The background color to fill an image with. /// The image rotated to the given angle at the given position. /// /// Based on /// - private Bitmap RotateImage(Image image, float rotateAtX, float rotateAtY, float angle, Color backgroundColor) + private Bitmap RotateImage(Image image, float rotateAtX, float rotateAtY, float angle) { int width, height, x, y; @@ -242,14 +158,9 @@ namespace ImageProcessor.Processors { // Reduce the jagged edge. graphics.SmoothingMode = SmoothingMode.HighQuality; - - // Contrary to everything I have read bicubic is producing the best results. graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighSpeed; - - // Fill the background. - graphics.Clear(backgroundColor); + graphics.CompositingQuality = CompositingQuality.HighQuality; // Put the rotation point in the "center" of the image graphics.TranslateTransform(rotateAtX + x, rotateAtY + y); @@ -266,49 +177,6 @@ namespace ImageProcessor.Processors return newImage; } - - /// - /// Returns the correct containing the angle for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct containing the angle for the given string. - /// - private int ParseAngle(string input) - { - foreach (Match match in AngleRegex.Matches(input)) - { - // Split on angle- - int angle; - int.TryParse(match.Value.Split('-')[1], NumberStyles.Any, CultureInfo.InvariantCulture, out angle); - return angle; - } - - // No rotate - matches the RotateLayer default. - return 0; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct - /// - private Color ParseColor(string input) - { - foreach (Match match in ColorRegex.Matches(input)) - { - // split on color-hex - return ColorTranslator.FromHtml("#" + match.Value.Split('-')[1]); - } - - return Color.Transparent; - } #endregion } } diff --git a/src/ImageProcessor/Processors/RoundedCorners.cs b/src/ImageProcessor/Processors/RoundedCorners.cs index 042a6b7f0..97c0f6078 100644 --- a/src/ImageProcessor/Processors/RoundedCorners.cs +++ b/src/ImageProcessor/Processors/RoundedCorners.cs @@ -10,14 +10,13 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; - using System.Globalization; - using System.Text.RegularExpressions; + + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging; - #endregion /// /// Encapsulates methods to add rounded corners to an image. @@ -25,50 +24,11 @@ namespace ImageProcessor.Processors public class RoundedCorners : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"roundedcorners=(\d+|[^&]*)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the angle attribute. - /// - private static readonly Regex RadiusRegex = new Regex(@"radius-(\d+)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the color attribute. - /// - private static readonly Regex ColorRegex = new Regex(@"bgcolor-([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the top left attribute. + /// Initializes a new instance of the class. /// - private static readonly Regex TopLeftRegex = new Regex(@"tl-(true|false)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the top right attribute. - /// - private static readonly Regex TopRightRegex = new Regex(@"tr-(true|false)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the bottom left attribute. - /// - private static readonly Regex BottomLeftRegex = new Regex(@"bl-(true|false)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the bottom right attribute. - /// - private static readonly Regex BottomRightRegex = new Regex(@"br-(true|false)", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern + public RoundedCorners() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -80,15 +40,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -98,62 +49,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - - RoundedCornerLayer roundedCornerLayer; - - string toParse = match.Value; - - if (toParse.Contains("bgcolor")) - { - roundedCornerLayer = new RoundedCornerLayer(this.ParseRadius(toParse), this.ParseColor(toParse), this.ParseCorner(TopLeftRegex, toParse), this.ParseCorner(TopRightRegex, toParse), this.ParseCorner(BottomLeftRegex, toParse), this.ParseCorner(BottomRightRegex, toParse)); - } - else - { - int radius; - int.TryParse(match.Value.Split('=')[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius); - - roundedCornerLayer = new RoundedCornerLayer(radius, this.ParseCorner(TopLeftRegex, toParse), this.ParseCorner(TopRightRegex, toParse), this.ParseCorner(BottomLeftRegex, toParse), this.ParseCorner(BottomRightRegex, toParse)); - } - - this.DynamicParameter = roundedCornerLayer; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -168,43 +68,41 @@ namespace ImageProcessor.Processors { RoundedCornerLayer roundedCornerLayer = this.DynamicParameter; int radius = roundedCornerLayer.Radius; - Color backgroundColor = roundedCornerLayer.BackgroundColor; bool topLeft = roundedCornerLayer.TopLeft; bool topRight = roundedCornerLayer.TopRight; bool bottomLeft = roundedCornerLayer.BottomLeft; bool bottomRight = roundedCornerLayer.BottomRight; - // Create a rotated image. - newImage = this.RoundCornerImage(image, radius, backgroundColor, topLeft, topRight, bottomLeft, bottomRight); + // Create a rounded image. + newImage = this.RoundCornerImage(image, radius, topLeft, topRight, bottomLeft, bottomRight); image.Dispose(); image = newImage; } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion - #region Private Methods /// /// Adds rounded corners to the image /// /// The image to add corners too /// The radius of the corners. - /// The background color to fill an image with. /// If the top left corner will have a rounded corner? /// If the top right corner will have a rounded corner? /// If the bottom left corner will have a rounded corner? /// If the bottom right corner will have a rounded corner? /// The image with rounded corners. - private Bitmap RoundCornerImage(Image image, int cornerRadius, Color backgroundColor, bool topLeft = false, bool topRight = false, bool bottomLeft = false, bool bottomRight = false) + private Bitmap RoundCornerImage(Image image, int cornerRadius, bool topLeft = false, bool topRight = false, bool bottomLeft = false, bool bottomRight = false) { int width = image.Width; int height = image.Height; @@ -219,14 +117,9 @@ namespace ImageProcessor.Processors { // Reduce the jagged edge. graphics.SmoothingMode = SmoothingMode.HighQuality; - - // Contrary to everything I have read bicubic is producing the best results. graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighSpeed; - - // Fill the background. - graphics.Clear(backgroundColor); + graphics.CompositingQuality = CompositingQuality.HighQuality; // Add rounded corners using (GraphicsPath path = new GraphicsPath()) @@ -280,75 +173,5 @@ namespace ImageProcessor.Processors return newImage; } - - /// - /// Returns the correct containing the radius for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct containing the radius for the given string. - /// - private int ParseRadius(string input) - { - foreach (Match match in RadiusRegex.Matches(input)) - { - // Split on radius- - int radius; - int.TryParse(match.Value.Split('-')[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius); - return radius; - } - - // No rotate - matches the RotateLayer default. - return 0; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct - /// - private Color ParseColor(string input) - { - foreach (Match match in ColorRegex.Matches(input)) - { - // split on color-hex - return ColorTranslator.FromHtml("#" + match.Value.Split('-')[1]); - } - - return Color.Transparent; - } - - /// - /// Returns a either true or false. - /// - /// - /// The corner. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct true or false. - /// - private bool ParseCorner(Regex corner, string input) - { - foreach (Match match in corner.Matches(input)) - { - // Split on corner- - bool cornerRound; - bool.TryParse(match.Value.Split('-')[1], out cornerRound); - return cornerRound; - } - - // No rotate - matches the RotateLayer default. - return true; - } - #endregion } } diff --git a/src/ImageProcessor/Processors/Saturation.cs b/src/ImageProcessor/Processors/Saturation.cs index e3be5c312..ede958489 100644 --- a/src/ImageProcessor/Processors/Saturation.cs +++ b/src/ImageProcessor/Processors/Saturation.cs @@ -10,14 +10,12 @@ namespace ImageProcessor.Processors { - #region Using + using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; - using System.Globalization; - using System.Text.RegularExpressions; - #endregion + using ImageProcessor.Common.Exceptions; /// /// Encapsulates methods to change the saturation component of the image. @@ -28,21 +26,11 @@ namespace ImageProcessor.Processors public class Saturation : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// + /// Initializes a new instance of the class. /// - private static readonly Regex QueryRegex = new Regex(@"saturation=(-?(?:100)|-?([1-9]?[0-9]))", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern + public Saturation() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -54,15 +42,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -72,47 +51,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - int percentage = int.Parse(match.Value.Split('=')[1], CultureInfo.InvariantCulture); - - this.DynamicParameter = percentage; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -142,19 +85,19 @@ namespace ImageProcessor.Processors ColorMatrix colorMatrix = new ColorMatrix( - new float[][] + new[] { - new float[] + new[] { saturationComplementR + saturationFactor, saturationComplementR, saturationComplementR, 0, 0 }, - new float[] + new[] { saturationComplementG, saturationComplementG + saturationFactor, saturationComplementG, 0, 0 }, - new float[] + new[] { saturationComplementB, saturationComplementB, saturationComplementB + saturationFactor, 0, 0 @@ -184,16 +127,17 @@ namespace ImageProcessor.Processors } } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/Tint.cs b/src/ImageProcessor/Processors/Tint.cs index 37341552e..603c7fd11 100644 --- a/src/ImageProcessor/Processors/Tint.cs +++ b/src/ImageProcessor/Processors/Tint.cs @@ -4,7 +4,7 @@ // Licensed under the Apache License, Version 2.0. // // -// Tints an image with the given colour. +// Tints an image with the given color. // // -------------------------------------------------------------------------------------------------------------------- @@ -15,27 +15,20 @@ namespace ImageProcessor.Processors using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; - using System.Text.RegularExpressions; - using ImageProcessor.Extensions; + + using ImageProcessor.Common.Exceptions; /// - /// Tints an image with the given colour. + /// Tints an image with the given color. /// public class Tint : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"tint=(\d+,\d+,\d+,\d+|([0-9a-fA-F]{3}){1,2})", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Tint() { - get { return QueryRegex; } + this.Settings = new Dictionary(); } /// @@ -43,55 +36,16 @@ namespace ImageProcessor.Processors /// public dynamic DynamicParameter { get; set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder { get; private set; } - /// /// Gets or sets any additional settings required by the processor. /// public Dictionary Settings { get; set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - this.DynamicParameter = this.ParseColor(match.Value); - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -104,7 +58,7 @@ namespace ImageProcessor.Processors try { - Color tintColour = (Color)this.DynamicParameter; + Color tintColour = this.DynamicParameter; float[][] colorMatrixElements = { new[] { tintColour.R / 255f, 0, 0, 0, 0 }, // Red @@ -132,52 +86,18 @@ namespace ImageProcessor.Processors image = newImage; } } - - return image; } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } - } - - return image; - } - #endregion - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct - /// - private Color ParseColor(string input) - { - foreach (Match match in QueryRegex.Matches(input)) - { - string value = match.Value.Split('=')[1]; - - if (value.Contains(",")) - { - int[] split = value.ToPositiveIntegerArray(); - byte red = split[0].ToByte(); - byte green = split[1].ToByte(); - byte blue = split[2].ToByte(); - byte alpha = split[3].ToByte(); - - return Color.FromArgb(alpha, red, green, blue); - } - // Split on color-hex - return ColorTranslator.FromHtml("#" + value); + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } - return Color.Transparent; + return image; } } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Processors/Vignette.cs b/src/ImageProcessor/Processors/Vignette.cs index 4236078e8..3be2beee1 100644 --- a/src/ImageProcessor/Processors/Vignette.cs +++ b/src/ImageProcessor/Processors/Vignette.cs @@ -10,13 +10,12 @@ namespace ImageProcessor.Processors { - #region Using using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; - using System.Text.RegularExpressions; - #endregion + + using ImageProcessor.Common.Exceptions; /// /// Encapsulates methods with which to add a vignette image effect to an image. @@ -24,20 +23,12 @@ namespace ImageProcessor.Processors public class Vignette : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"vignette=true", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. + /// Initializes a new instance of the class. /// - public Regex RegexPattern + public Vignette() { - get - { - return QueryRegex; - } + this.DynamicParameter = Color.Black; + this.Settings = new Dictionary(); } /// @@ -49,15 +40,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -67,46 +49,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - bool doVignette; - this.DynamicParameter = bool.TryParse(match.Value.Split('=')[1], out doVignette); - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -139,12 +86,15 @@ namespace ImageProcessor.Processors path.AddEllipse(ellipsebounds); using (PathGradientBrush brush = new PathGradientBrush(path)) { - // Fill a rectangle with an elliptical gradient brush that goes from white to black. - // Change the colour from white to pure transparent black and from black to pure opaque black. - // This has the effect of painting the far corners black and shade less on the way in to the centre. + // Fill a rectangle with an elliptical gradient brush that goes from transparent to opaque. + // This has the effect of painting the far corners with the given color and shade less on the way in to the centre. + Color baseColor = (Color)this.DynamicParameter; + Color centerColor = Color.FromArgb(0, baseColor.R, baseColor.G, baseColor.B); + Color edgeColor = Color.FromArgb(255, baseColor.R, baseColor.G, baseColor.B); + brush.WrapMode = WrapMode.Tile; - brush.CenterColor = Color.FromArgb(0, 0, 0, 0); - brush.SurroundColors = new[] { Color.FromArgb(255, 0, 0, 0) }; + brush.CenterColor = centerColor; + brush.SurroundColors = new[] { edgeColor }; Blend blend = new Blend { @@ -166,16 +116,17 @@ namespace ImageProcessor.Processors } } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion } } \ No newline at end of file diff --git a/src/ImageProcessor/Processors/Watermark.cs b/src/ImageProcessor/Processors/Watermark.cs index 586f04404..e14ed7cb5 100644 --- a/src/ImageProcessor/Processors/Watermark.cs +++ b/src/ImageProcessor/Processors/Watermark.cs @@ -4,86 +4,31 @@ // Licensed under the Apache License, Version 2.0. // // -// Encapsulates methods to change the alpha component of the image to effect its transparency. +// Encapsulates methods to add a watermark text overlay to an image. // // -------------------------------------------------------------------------------------------------------------------- namespace ImageProcessor.Processors { - #region Using - using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Text; - using System.Globalization; - using System.Linq; - using System.Text.RegularExpressions; - using ImageProcessor.Extensions; + using ImageProcessor.Common.Exceptions; using ImageProcessor.Imaging; - #endregion /// - /// Encapsulates methods to change the alpha component of the image to effect its transparency. + /// Encapsulates methods to add a watermark text overlay to an image. /// public class Watermark : IGraphicsProcessor { /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"watermark=[^&]*", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the text attribute. - /// - private static readonly Regex TextRegex = new Regex(@"text-[^/:?#\[\]@!$&'()*%\|,;=]+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the position attribute. - /// - private static readonly Regex PositionRegex = new Regex(@"position-\d+[-,]\d+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the color attribute. + /// Initializes a new instance of the class. /// - private static readonly Regex ColorRegex = new Regex(@"color-([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the font size attribute. - /// - private static readonly Regex FontSizeRegex = new Regex(@"size-\d{1,3}", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the font style attribute. - /// - private static readonly Regex FontStyleRegex = new Regex(@"style-(bold|italic|regular|strikeout|underline)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the font family attribute. - /// - private static readonly Regex FontFamilyRegex = new Regex(@"font-[^/:?#\[\]@!$&'()*%\|,;=0-9]+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the opacity attribute. - /// - private static readonly Regex OpacityRegex = new Regex(@"opacity-(?:100|[1-9]?[0-9])", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the shadow attribute. - /// - private static readonly Regex ShadowRegex = new Regex(@"shadow-true", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern + public Watermark() { - get - { - return QueryRegex; - } + this.Settings = new Dictionary(); } /// @@ -95,15 +40,6 @@ namespace ImageProcessor.Processors set; } - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - /// /// Gets or sets any additional settings required by the processor. /// @@ -113,59 +49,11 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - - TextLayer textLayer = new TextLayer(); - - string toParse = match.Value; - - textLayer.Text = this.ParseText(toParse); - textLayer.Position = this.ParsePosition(toParse); - textLayer.TextColor = this.ParseColor(toParse); - textLayer.FontSize = this.ParseFontSize(toParse); - textLayer.Font = this.ParseFontFamily(toParse); - textLayer.Style = this.ParseFontStyle(toParse); - textLayer.Opacity = this.ParseOpacity(toParse); - textLayer.DropShadow = this.ParseDropShadow(toParse); - - this.DynamicParameter = textLayer; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// /// - /// The the current instance of the class containing + /// The current instance of the class containing /// the image to process. /// /// @@ -181,17 +69,17 @@ namespace ImageProcessor.Processors newImage = new Bitmap(image); TextLayer textLayer = this.DynamicParameter; string text = textLayer.Text; - int opacity = textLayer.Opacity; + int opacity = Math.Min((int)Math.Ceiling((textLayer.Opacity / 100f) * 255), 255); int fontSize = textLayer.FontSize; FontStyle fontStyle = textLayer.Style; using (Graphics graphics = Graphics.FromImage(newImage)) { - using (Font font = this.GetFont(textLayer.Font, fontSize, fontStyle)) + using (Font font = this.GetFont(textLayer.FontFamily, fontSize, fontStyle)) { using (StringFormat drawFormat = new StringFormat()) { - using (Brush brush = new SolidBrush(Color.FromArgb(opacity, textLayer.TextColor))) + using (Brush brush = new SolidBrush(Color.FromArgb(opacity, textLayer.FontColor))) { Point origin = textLayer.Position; @@ -244,233 +132,50 @@ namespace ImageProcessor.Processors image = newImage; } } - catch + catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } + + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return image; } - #endregion - #region Private Methods /// - /// Returns the correct for the given parameters + /// Returns the correct for the given parameters. /// - /// - /// The font. + /// + /// The name of the font. /// /// /// The font size. /// /// - /// The font style. + /// The style. /// /// /// The correct /// - private Font GetFont(string font, int fontSize, FontStyle fontStyle) + private Font GetFont(FontFamily fontFamily, int fontSize, FontStyle fontStyle) { try { - using (FontFamily fontFamily = new FontFamily(font)) + using (fontFamily) { return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel); } } catch { - using (FontFamily fontFamily = FontFamily.GenericSansSerif) + using (FontFamily genericFontFamily = FontFamily.GenericSansSerif) { - return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel); + return new Font(genericFontFamily, fontSize, fontStyle, GraphicsUnit.Pixel); } } } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct for the given string. - /// - private string ParseText(string input) - { - foreach (Match match in TextRegex.Matches(input)) - { - // split on text- - return match.Value.Split('-')[1].Replace("+", " "); - } - - return string.Empty; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct - /// - private Point ParsePosition(string input) - { - foreach (Match match in PositionRegex.Matches(input)) - { - int[] position = match.Value.ToPositiveIntegerArray(); - - if (position != null) - { - int x = position[0]; - int y = position[1]; - - return new Point(x, y); - } - } - - return Point.Empty; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct - /// - private Color ParseColor(string input) - { - foreach (Match match in ColorRegex.Matches(input)) - { - // split on color-hex - return ColorTranslator.FromHtml("#" + match.Value.Split('-')[1]); - } - - return Color.Black; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct - /// - private int ParseFontSize(string input) - { - foreach (Match match in FontSizeRegex.Matches(input)) - { - // split on size-value - return int.Parse(match.Value.Split('-')[1], CultureInfo.InvariantCulture); - } - - // Matches the default number in TextLayer. - return 48; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The string containing the respective font style. - /// - /// - /// The correct - /// - private FontStyle ParseFontStyle(string input) - { - FontStyle fontStyle = FontStyle.Bold; - - foreach (Match match in FontStyleRegex.Matches(input)) - { - // split on style- - switch (match.Value.Split('-')[1]) - { - case "italic": - fontStyle = FontStyle.Italic; - break; - case "regular": - fontStyle = FontStyle.Regular; - break; - case "strikeout": - fontStyle = FontStyle.Strikeout; - break; - case "underline": - fontStyle = FontStyle.Underline; - break; - } - } - - return fontStyle; - } - - /// - /// Returns the correct containing the font family for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct containing the font family for the given string. - /// - private string ParseFontFamily(string input) - { - foreach (Match match in FontFamilyRegex.Matches(input)) - { - // split on font- - string font = match.Value.Split('-')[1].Replace("+", " "); - - return font; - } - - return string.Empty; - } - - /// - /// Returns the correct containing the opacity for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct containing the opacity for the given string. - /// - private int ParseOpacity(string input) - { - foreach (Match match in OpacityRegex.Matches(input)) - { - // split on opacity- - return int.Parse(match.Value.Split('-')[1], CultureInfo.InvariantCulture); - } - - // full opacity - matches the Textlayer default. - return 100; - } - - /// - /// Returns a value indicating whether the watermark is to have a shadow. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The true if the watermark is to have a shadow; otherwise false. - /// - private bool ParseDropShadow(string input) - { - return ShadowRegex.Matches(input).Cast().Any(); - } - - #endregion } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Properties/AssemblyInfo.cs b/src/ImageProcessor/Properties/AssemblyInfo.cs index 39cdaa406..9fc155a5a 100644 --- a/src/ImageProcessor/Properties/AssemblyInfo.cs +++ b/src/ImageProcessor/Properties/AssemblyInfo.cs @@ -1,9 +1,17 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// AssemblyInfo.cs +// +// -------------------------------------------------------------------------------------------------------------------- + +using System.Reflection; using System.Runtime.InteropServices; -using System.Security; -// General Information about an assembly is controlled through the following +// 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("ImageProcessor")] @@ -15,8 +23,8 @@ using System.Security; [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 +// 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)] @@ -26,12 +34,11 @@ using System.Security; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -// You can specify all the values or you can default the Build and Revision Numbers +// You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.5.0")] -[assembly: AssemblyFileVersion("1.9.5.0")] - +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] \ No newline at end of file diff --git a/src/ImageProcessor/Settings.StyleCop b/src/ImageProcessor/Settings.StyleCop index ceca99cde..085067600 100644 --- a/src/ImageProcessor/Settings.StyleCop +++ b/src/ImageProcessor/Settings.StyleCop @@ -1,24 +1,17 @@ - behaviour - chrominance - colour - enum - exif - halftoning - lomograph - octree - quantizer + bitstream + dd + ddd + dllimport + gps + mmmm + orig + specifier + ss + subfile + ver - - - - James South - Copyright (c) James South. -Licensed under the Apache License, Version 2.0. - - - \ No newline at end of file diff --git a/src/ImageProcessorConsole/App.config b/src/ImageProcessorConsole/App.config index 9c05822ff..d1428ad71 100644 --- a/src/ImageProcessorConsole/App.config +++ b/src/ImageProcessorConsole/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/src/ImageProcessorConsole/ImageProcessorConsole.csproj b/src/ImageProcessorConsole/ImageProcessorConsole.csproj index 09423698e..1afd8ef0e 100644 --- a/src/ImageProcessorConsole/ImageProcessorConsole.csproj +++ b/src/ImageProcessorConsole/ImageProcessorConsole.csproj @@ -1,5 +1,5 @@  - + Debug @@ -9,9 +9,11 @@ Properties ImageProcessorConsole ImageProcessorConsole + v4.5 512 true - Client + + AnyCPU @@ -54,6 +56,10 @@ {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E} ImageProcessor + + {2cf69699-959a-44dc-a281-4e2596c25043} + ImageProcessor.Plugins.WebP + + \ No newline at end of file diff --git a/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/NativeMethods.cs b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/NativeMethods.cs new file mode 100644 index 000000000..a04c44923 --- /dev/null +++ b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/NativeMethods.cs @@ -0,0 +1,130 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides access to unmanaged native methods. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Plugins.WebP.Imaging.Formats +{ + using System; + using System.IO; + using System.Reflection; + using System.Runtime.InteropServices; + + using ImageProcessor.Configuration; + + /// + /// Provides access to unmanaged native methods. + /// + internal static class NativeMethods + { + /// + /// Initializes static members of the class. + /// + static NativeMethods() + { + string folder = ImageProcessorBootstrapper.Instance.NativeBinaryFactory.Is64BitEnvironment ? "x64" : "x86"; + string name = string.Format("ImageProcessor.Plugins.WebP.Resources.Unmanaged.{0}.libwebp.dll", folder); + Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name); + + using (MemoryStream memoryStream = new MemoryStream()) + { + if (stream != null) + { + stream.CopyTo(memoryStream); + ImageProcessorBootstrapper.Instance.NativeBinaryFactory.RegisterNativeBinary("libwebp.dll", memoryStream.ToArray()); + } + } + } + + #region WebP + /// + /// Validate the WebP image header and retrieve the image height and width. Pointers *width and *height can be passed NULL if deemed irrelevant + /// + /// + /// Pointer to WebP image data + /// + /// + /// This is the size of the memory block pointed to by data containing the image data + /// + /// + /// The width range is limited currently from 1 to 16383 + /// + /// + /// The height range is limited currently from 1 to 16383 + /// + /// + /// 1 if success, otherwise error code returned in the case of (a) formatting error(s). + /// + [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")] + public static extern int WebPGetInfo(IntPtr data, uint dataSize, out int width, out int height); + + /// + /// Decode WEBP image pointed to by *data and returns BGR samples into a pre-allocated buffer + /// + /// + /// Pointer to WebP image data + /// + /// + /// This is the size of the memory block pointed to by data containing the image data + /// + /// + /// Pointer to decoded WebP image + /// + /// + /// Size of allocated buffer + /// + /// + /// Specifies the distance between scan-lines + /// + /// + /// output_buffer if function succeeds; NULL otherwise + /// + [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")] + public static extern IntPtr WebPDecodeBGRAInto(IntPtr data, uint dataSize, IntPtr outputBuffer, int outputBufferSize, int outputStride); + + /// + /// Lossy encoding images pointed to by *data in WebP format + /// + /// + /// Pointer to RGB image data + /// + /// + /// The width range is limited currently from 1 to 16383 + /// + /// + /// The height range is limited currently from 1 to 16383 + /// + /// + /// The stride. + /// + /// + /// Ranges from 0 (lower quality) to 100 (highest quality). Controls the loss and quality during compression + /// + /// + /// output_buffer with WebP image + /// + /// + /// Size of WebP Image + /// + [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")] + public static extern int WebPEncodeBGRA(IntPtr rgb, int width, int height, int stride, float qualityFactor, out IntPtr output); + + /// + /// Frees the unmanaged memory. + /// + /// + /// The pointer. + /// + /// + /// 1 if success, otherwise error code returned in the case of (a) error(s). + /// + [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")] + public static extern int WebPFree(IntPtr pointer); + #endregion + } +} diff --git a/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/WebPFormat.cs b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/WebPFormat.cs new file mode 100644 index 000000000..0bc2e2b7b --- /dev/null +++ b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/WebPFormat.cs @@ -0,0 +1,275 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides the necessary information to support webp images. +// Adapted from +// by Jose M. Piñeiro +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Plugins.WebP.Imaging.Formats +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + using System.Runtime.InteropServices; + using System.Text; + + using ImageProcessor.Common.Exceptions; + using ImageProcessor.Imaging.Formats; + + /// + /// Provides the necessary information to support webp images. + /// Adapted from + /// by Jose M. Piñeiro + /// + [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")] + public class WebPFormat : FormatBase + { + /// + /// Gets the file headers. + /// + public override byte[][] FileHeaders + { + get + { + return new[] { Encoding.ASCII.GetBytes("RIFF") }; + } + } + + /// + /// Gets the list of file extensions. + /// + public override string[] FileExtensions + { + get + { + return new[] { "webp" }; + } + } + + /// + /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. + /// + public override string MimeType + { + get + { + return "image/webp"; + } + } + + /// + /// Gets the file format of the image. + /// + public override ImageFormat ImageFormat + { + get + { + return null; + } + } + + /// + /// Applies the given processor the current image. + /// + /// The processor delegate. + /// The . + public override void ApplyProcessor(Func processor, ImageFactory factory) + { + base.ApplyProcessor(processor, factory); + + // Set the property item information from any Exif metadata. + // We do this here so that they can be changed between processor methods. + if (factory.PreserveExifData) + { + foreach (KeyValuePair propertItem in factory.ExifPropertyItems) + { + factory.Image.SetPropertyItem(propertItem.Value); + } + } + } + + /// + /// Decodes the image to process. + /// + /// + /// The containing the image information. + /// + /// + /// The . + /// + public override Image Load(Stream stream) + { + byte[] bytes = new byte[stream.Length]; + stream.Read(bytes, 0, bytes.Length); + return Decode(bytes); + } + + /// + /// Saves the current image to the specified file path. + /// + /// The path to save the image to. + /// The + /// to save. + /// + /// The . + /// + public override Image Save(string path, Image image) + { + byte[] bytes; + + // Encode in webP format. + if (EncodeLossly((Bitmap)image, this.Quality, out bytes)) + { + File.WriteAllBytes(path, bytes); + } + + return image; + } + + /// + /// Saves the current image to the specified output stream. + /// + /// The to save the image information to. + /// The to save. + /// + /// The . + /// + public override Image Save(Stream stream, Image image) + { + byte[] bytes; + + // Encode in webP format. + if (EncodeLossly((Bitmap)image, this.Quality, out bytes)) + { + using (MemoryStream memoryStream = new MemoryStream(bytes)) + { + memoryStream.CopyTo(stream); + memoryStream.Position = stream.Position = 0; + } + } + else + { + throw new ImageFormatException("Unable to encode WebP image."); + } + + return image; + } + + /// + /// Decodes a WebP image + /// + /// + /// The data to uncompress + /// + /// + /// The . + /// + private static Bitmap Decode(byte[] webpData) + { + // Get the image width and height + GCHandle pinnedWebP = GCHandle.Alloc(webpData, GCHandleType.Pinned); + IntPtr ptrData = pinnedWebP.AddrOfPinnedObject(); + uint dataSize = (uint)webpData.Length; + + Bitmap bitmap = null; + BitmapData bitmapData = null; + IntPtr outputBuffer = IntPtr.Zero; + int width; + int height; + + if (NativeMethods.WebPGetInfo(ptrData, dataSize, out width, out height) != 1) + { + throw new ImageFormatException("WebP image header is corrupted."); + } + + try + { + // Create a BitmapData and Lock all pixels to be written + bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); + + // Allocate memory for uncompress image + int outputBufferSize = bitmapData.Stride * height; + outputBuffer = Marshal.AllocHGlobal(outputBufferSize); + + // Uncompress the image + outputBuffer = NativeMethods.WebPDecodeBGRAInto(ptrData, dataSize, outputBuffer, outputBufferSize, bitmapData.Stride); + + // Write image to bitmap using Marshal + byte[] buffer = new byte[outputBufferSize]; + Marshal.Copy(outputBuffer, buffer, 0, outputBufferSize); + Marshal.Copy(buffer, 0, bitmapData.Scan0, outputBufferSize); + } + finally + { + // Unlock the pixels + if (bitmap != null) + { + bitmap.UnlockBits(bitmapData); + } + + // Free memory + pinnedWebP.Free(); + Marshal.FreeHGlobal(outputBuffer); + } + + return bitmap; + } + + /// + /// Lossy encodes the image in bitmap. + /// + /// + /// Bitmap with the image + /// + /// + /// Quality. 0 = minimum ... 100 = maximum quality + /// + /// + /// The byte array containing the encoded image data. + /// + /// + /// True if success; False otherwise + /// + private static bool EncodeLossly(Bitmap bitmap, int quality, out byte[] webpData) + { + webpData = null; + BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + IntPtr unmanagedData = IntPtr.Zero; + bool encoded; + + try + { + // Attempt to lossy encode the image. + int size = NativeMethods.WebPEncodeBGRA(bmpData.Scan0, bitmap.Width, bitmap.Height, bmpData.Stride, quality, out unmanagedData); + + // Copy image compress data to output array + webpData = new byte[size]; + Marshal.Copy(unmanagedData, webpData, 0, size); + encoded = true; + } + catch + { + encoded = false; + } + finally + { + // Unlock the pixels + bitmap.UnlockBits(bmpData); + + // Free memory + NativeMethods.WebPFree(unmanagedData); + } + + return encoded; + } + } +} \ No newline at end of file diff --git a/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Properties/AssemblyInfo.cs b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..8fe6f724f --- /dev/null +++ b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +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("ImageProcessor.Plugins.WebP")] +[assembly: AssemblyDescription("Adds support to ImageProcessor for the WebP image format.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("James South")] +[assembly: AssemblyProduct("ImageProcessor.Plugins.WebP")] +[assembly: AssemblyCopyright("Copyright © James South")] +[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("bf160db5-2ea7-4c85-9b0e-f1ddf2595e37")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id new file mode 100644 index 000000000..35684c541 --- /dev/null +++ b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id @@ -0,0 +1 @@ +dcadab1b5b86469758707bff22558b33e5c51552 \ No newline at end of file diff --git a/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id new file mode 100644 index 000000000..129db9826 --- /dev/null +++ b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id @@ -0,0 +1 @@ +ad47008dd1e64ea220bc745e28f568277434d661 \ No newline at end of file diff --git a/src/Settings.StyleCop b/src/Settings.StyleCop new file mode 100644 index 000000000..437aad55d --- /dev/null +++ b/src/Settings.StyleCop @@ -0,0 +1,42 @@ + + + + behaviour + bootstrapper + cb + chrominance + colour + enum + exif + Mutexes + querystring + halftoning + interp + lomograph + Lomograph + lossy + octree + png + quantizer + uncalibrated + webp + + + + + + James South + Copyright (c) James South. +Licensed under the Apache License, Version 2.0. + + + + + + hi + lo + + + + + \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_NET45/App_Start/FilterConfig.cs b/src/TestWebsites/MVC/App_Start/FilterConfig.cs similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/App_Start/FilterConfig.cs rename to src/TestWebsites/MVC/App_Start/FilterConfig.cs diff --git a/src/TestWebsites/NET45/Test_Website_NET45/App_Start/RouteConfig.cs b/src/TestWebsites/MVC/App_Start/RouteConfig.cs similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/App_Start/RouteConfig.cs rename to src/TestWebsites/MVC/App_Start/RouteConfig.cs diff --git a/src/TestWebsites/NET45/Test_Website_NET45/App_Start/WebApiConfig.cs b/src/TestWebsites/MVC/App_Start/WebApiConfig.cs similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/App_Start/WebApiConfig.cs rename to src/TestWebsites/MVC/App_Start/WebApiConfig.cs diff --git a/src/TestWebsites/NET4/Content/responsive.min.css.REMOVED.git-id b/src/TestWebsites/MVC/Content/responsive.min.css.REMOVED.git-id similarity index 100% rename from src/TestWebsites/NET4/Content/responsive.min.css.REMOVED.git-id rename to src/TestWebsites/MVC/Content/responsive.min.css.REMOVED.git-id diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Controllers/HomeController.cs b/src/TestWebsites/MVC/Controllers/HomeController.cs similarity index 91% rename from src/TestWebsites/NET45/Test_Website_NET45/Controllers/HomeController.cs rename to src/TestWebsites/MVC/Controllers/HomeController.cs index 02fc35575..1eae92d44 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Controllers/HomeController.cs +++ b/src/TestWebsites/MVC/Controllers/HomeController.cs @@ -41,6 +41,11 @@ namespace Test_Website_NET45.Controllers return View(); } + public ActionResult WebP() + { + return View(); + } + public ActionResult External() { return this.View(); diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Global.asax b/src/TestWebsites/MVC/Global.asax similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/Global.asax rename to src/TestWebsites/MVC/Global.asax diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Global.asax.cs b/src/TestWebsites/MVC/Global.asax.cs similarity index 56% rename from src/TestWebsites/NET45/Test_Website_NET45/Global.asax.cs rename to src/TestWebsites/MVC/Global.asax.cs index 66099ae16..54afb402f 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Global.asax.cs +++ b/src/TestWebsites/MVC/Global.asax.cs @@ -8,6 +8,12 @@ using System.Web.Routing; namespace Test_Website_NET45 { + using System.Diagnostics; + using System.Threading.Tasks; + + using ImageProcessor.Web.Helpers; + using ImageProcessor.Web.HttpModules; + // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication @@ -19,6 +25,15 @@ namespace Test_Website_NET45 WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); + + // Test the post processing event. + ImageProcessingModule.OnPostProcessing += (sender, args) => Debug.WriteLine(args.CachedImagePath); + //ImageProcessingModule.OnPostProcessing += this.WritePath; + } + + private async void WritePath(object sender, PostProcessingEventArgs e) + { + await Task.Run(() => Debug.WriteLine(e.CachedImagePath)); } } } \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Properties/AssemblyInfo.cs b/src/TestWebsites/MVC/Properties/AssemblyInfo.cs similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/Properties/AssemblyInfo.cs rename to src/TestWebsites/MVC/Properties/AssemblyInfo.cs diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj b/src/TestWebsites/MVC/Test_Website_MVC.csproj similarity index 95% rename from src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj rename to src/TestWebsites/MVC/Test_Website_MVC.csproj index 96f09d69b..9cdaaaad9 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj +++ b/src/TestWebsites/MVC/Test_Website_MVC.csproj @@ -151,14 +151,18 @@ - + {d011a778-59c8-4bfa-a770-c350216bf161} - ImageProcessor.Web_NET45 + ImageProcessor.Web - + {3b5dd734-fb7a-487d-8ce6-55e7af9aea7e} ImageProcessor + + {2cf69699-959a-44dc-a281-4e2596c25043} + ImageProcessor.Plugins.WebP + @@ -191,6 +195,9 @@ + + + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) diff --git a/src/TestWebsites/NET4/Views/Home/Bmp.cshtml b/src/TestWebsites/MVC/Views/Home/Bmp.cshtml similarity index 100% rename from src/TestWebsites/NET4/Views/Home/Bmp.cshtml rename to src/TestWebsites/MVC/Views/Home/Bmp.cshtml diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/External.cshtml b/src/TestWebsites/MVC/Views/Home/External.cshtml similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/Views/Home/External.cshtml rename to src/TestWebsites/MVC/Views/Home/External.cshtml diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Gif.cshtml b/src/TestWebsites/MVC/Views/Home/Gif.cshtml similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Gif.cshtml rename to src/TestWebsites/MVC/Views/Home/Gif.cshtml diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml b/src/TestWebsites/MVC/Views/Home/Index.cshtml similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml rename to src/TestWebsites/MVC/Views/Home/Index.cshtml diff --git a/src/TestWebsites/NET4/Views/Home/Png.cshtml b/src/TestWebsites/MVC/Views/Home/Png.cshtml similarity index 89% rename from src/TestWebsites/NET4/Views/Home/Png.cshtml rename to src/TestWebsites/MVC/Views/Home/Png.cshtml index d01e7ae8c..e7619e233 100644 --- a/src/TestWebsites/NET4/Views/Home/Png.cshtml +++ b/src/TestWebsites/MVC/Views/Home/Png.cshtml @@ -94,6 +94,13 @@

Alpha

+
+

Rounded Corners

+

Old Syntax

+ +

New Syntax

+ +
diff --git a/src/TestWebsites/NET4/Views/Home/Png8.cshtml b/src/TestWebsites/MVC/Views/Home/Png8.cshtml similarity index 100% rename from src/TestWebsites/NET4/Views/Home/Png8.cshtml rename to src/TestWebsites/MVC/Views/Home/Png8.cshtml diff --git a/src/TestWebsites/NET4/Views/Home/Tiff.cshtml b/src/TestWebsites/MVC/Views/Home/Tiff.cshtml similarity index 100% rename from src/TestWebsites/NET4/Views/Home/Tiff.cshtml rename to src/TestWebsites/MVC/Views/Home/Tiff.cshtml diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Bmp.cshtml b/src/TestWebsites/MVC/Views/Home/WebP.cshtml similarity index 56% rename from src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Bmp.cshtml rename to src/TestWebsites/MVC/Views/Home/WebP.cshtml index 26b21ad46..ff03d1240 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Bmp.cshtml +++ b/src/TestWebsites/MVC/Views/Home/WebP.cshtml @@ -1,18 +1,18 @@ @{ - ViewBag.Title = "Bmp"; + ViewBag.Title = "WebP"; }
-

Bmp

+

WebP

Resized

- +

Cropped

- +
@@ -21,47 +21,47 @@

blackwhite

- +

comic

- +

lomograph

- +

greyscale

- +

polaroid

- +

sepia

- +

gotham

- +

hisatch

- +

losatch

- +
@@ -69,11 +69,11 @@

Watermark

- +

Format

- +
@@ -81,11 +81,11 @@

Rotate

- +

Quality

- +
@@ -93,7 +93,7 @@

Alpha

- +
diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml b/src/TestWebsites/MVC/Views/Shared/_Layout.cshtml similarity index 95% rename from src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml rename to src/TestWebsites/MVC/Views/Shared/_Layout.cshtml index 74af019a2..5f8255ea4 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml +++ b/src/TestWebsites/MVC/Views/Shared/_Layout.cshtml @@ -29,6 +29,7 @@
  • @Html.ActionLink("Png8", "Png8")
  • @Html.ActionLink("Bmp", "Bmp")
  • @Html.ActionLink("Tiff", "Tiff")
  • +
  • @Html.ActionLink("WebP", "WebP")
  • @Html.ActionLink("External", "External")
  • diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Web.config b/src/TestWebsites/MVC/Views/Web.config similarity index 99% rename from src/TestWebsites/NET45/Test_Website_NET45/Views/Web.config rename to src/TestWebsites/MVC/Views/Web.config index 826ce19e8..3d9efc26a 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Web.config +++ b/src/TestWebsites/MVC/Views/Web.config @@ -45,11 +45,11 @@ + - diff --git a/src/TestWebsites/NET4/Views/_ViewStart.cshtml b/src/TestWebsites/MVC/Views/_ViewStart.cshtml similarity index 100% rename from src/TestWebsites/NET4/Views/_ViewStart.cshtml rename to src/TestWebsites/MVC/Views/_ViewStart.cshtml diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Web.Debug.config b/src/TestWebsites/MVC/Web.Debug.config similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/Web.Debug.config rename to src/TestWebsites/MVC/Web.Debug.config diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Web.Release.config b/src/TestWebsites/MVC/Web.Release.config similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/Web.Release.config rename to src/TestWebsites/MVC/Web.Release.config diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Web.config b/src/TestWebsites/MVC/Web.config similarity index 88% rename from src/TestWebsites/NET45/Test_Website_NET45/Web.config rename to src/TestWebsites/MVC/Web.config index a11127fee..e2f38f0a4 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Web.config +++ b/src/TestWebsites/MVC/Web.config @@ -7,9 +7,9 @@ -
    -
    -
    +
    +
    +
    @@ -28,7 +28,7 @@ - + @@ -44,10 +44,15 @@ + + + + + @@ -59,6 +64,5 @@ - diff --git a/src/TestWebsites/NET4/config/imageprocessor/cache.config b/src/TestWebsites/MVC/config/imageprocessor/cache.config similarity index 100% rename from src/TestWebsites/NET4/config/imageprocessor/cache.config rename to src/TestWebsites/MVC/config/imageprocessor/cache.config diff --git a/src/TestWebsites/MVC/config/imageprocessor/processing.config b/src/TestWebsites/MVC/config/imageprocessor/processing.config new file mode 100644 index 000000000..2dc2d374e --- /dev/null +++ b/src/TestWebsites/MVC/config/imageprocessor/processing.config @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/security.config b/src/TestWebsites/MVC/config/imageprocessor/security.config similarity index 86% rename from src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/security.config rename to src/TestWebsites/MVC/config/imageprocessor/security.config index 78b957605..d4781f99c 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/security.config +++ b/src/TestWebsites/MVC/config/imageprocessor/security.config @@ -1,9 +1,9 @@  - + - + diff --git a/src/TestWebsites/NET45/Test_Website_NET45/packages.config b/src/TestWebsites/MVC/packages.config similarity index 100% rename from src/TestWebsites/NET45/Test_Website_NET45/packages.config rename to src/TestWebsites/MVC/packages.config diff --git a/src/TestWebsites/NET4/Controllers/HomeController.cs b/src/TestWebsites/NET4/Controllers/HomeController.cs deleted file mode 100644 index 88b37915f..000000000 --- a/src/TestWebsites/NET4/Controllers/HomeController.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; - -namespace Test.Controllers -{ - public class HomeController : Controller - { - // - // GET: /Home/ - - public ActionResult Index() - { - return this.View(); - } - - public ActionResult Png() - { - return this.View(); - } - - public ActionResult Png8() - { - return this.View(); - } - - public ActionResult Gif() - { - return this.View(); - } - - public ActionResult Bmp() - { - return View(); - } - - public ActionResult Tiff() - { - return View(); - } - - public ActionResult External() - { - return this.View(); - } - - } -} diff --git a/src/TestWebsites/NET4/Global.asax b/src/TestWebsites/NET4/Global.asax deleted file mode 100644 index 5798265d5..000000000 --- a/src/TestWebsites/NET4/Global.asax +++ /dev/null @@ -1 +0,0 @@ -<%@ Application Codebehind="Global.asax.cs" Inherits="Test.MvcApplication" Language="C#" %> diff --git a/src/TestWebsites/NET4/Global.asax.cs b/src/TestWebsites/NET4/Global.asax.cs deleted file mode 100644 index 1d151b372..000000000 --- a/src/TestWebsites/NET4/Global.asax.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using System.Web.Routing; - -namespace Test -{ - // Note: For instructions on enabling IIS6 or IIS7 classic mode, - // visit http://go.microsoft.com/?LinkId=9394801 - - public class MvcApplication : System.Web.HttpApplication - { - public static void RegisterGlobalFilters(GlobalFilterCollection filters) - { - filters.Add(new HandleErrorAttribute()); - } - - public static void RegisterRoutes(RouteCollection routes) - { - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); - - routes.MapRoute( - "Default", // Route name - "{controller}/{action}/{id}", // URL with parameters - new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults - ); - - } - - protected void Application_Start() - { - AreaRegistration.RegisterAllAreas(); - - RegisterGlobalFilters(GlobalFilters.Filters); - RegisterRoutes(RouteTable.Routes); - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET4/Scripts/img.srcsect.pollyfill.js b/src/TestWebsites/NET4/Scripts/img.srcsect.pollyfill.js deleted file mode 100644 index 9eaa4e2ed..000000000 --- a/src/TestWebsites/NET4/Scripts/img.srcsect.pollyfill.js +++ /dev/null @@ -1,103 +0,0 @@ -(function ($) { - // http: //www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#attr-img-srcset - - // Regexes for matching queries. - var rSrc = /[^\s]+/, - rWidth = /(\d+)w/, - rRatio = /(\d+)x/; - - // Detect retina display - // http: //www.quirksmode.org/blog/archives/2012/06/devicepixelrati.html - var pixelRatio = (window.devicePixelRatio || 1); - - // Cache the images as theres no point querying them twice. - var imageList = []; - - // http://lodash.com/docs/#debounce - var debounce = function (func, wait, immediate) { - var args, - result, - thisArg, - timeoutId; - - function delayed() { - timeoutId = null; - if (!immediate) { - func.apply(thisArg, args); - } - } - - return function () { - var isImmediate = immediate && !timeoutId; - args = arguments; - thisArg = this; - - clearTimeout(timeoutId); - timeoutId = setTimeout(delayed, wait); - - if (isImmediate) { - result = func.apply(thisArg, args); - } - return result; - }; - }; - - var getImgSrc = function (image) { - var imgSrc = null, imgWidth = 0, i, - imgSrcParts = image.attributes["srcset"].nodeValue.split(","), - len = imgSrcParts.length, - width = $(window).width(); - - for (i = 0; i < len; i += 1) { - - // This is just a rough play on the algorithm. - var newImgSrc = imgSrcParts[i].match(rSrc)[0], - newImgWidth = rWidth.test(imgSrcParts[i]) ? parseInt(imgSrcParts[i].match(rWidth)[1], 10) : 1, // Use 1 for truthy - newPixelRatio = rRatio.test(imgSrcParts[i]) ? parseInt(imgSrcParts[i].match(rRatio)[1], 10) : 1; - - if ((newImgWidth > imgWidth && width > newImgWidth && newPixelRatio === pixelRatio)) { - - imgWidth = newImgWidth || imgWidth; - imgSrc = newImgSrc; - } - } - - // Return null - return imgSrc; - }; - - $(window).resize(function () { - - $.each(imageList, function () { - var self = this, - checkImage = function () { - var src = getImgSrc(self); - - if (src) { - self.src = src; - } - - }, - lazyCheck = debounce(checkImage, 100); - - // Run debounced - lazyCheck(); - - }); - - }); - - $(window).load(function () { - $("img[srcset]").each(function () { - - var src = getImgSrc(this); - - if (src) { - this.src = src; - } - - imageList.push(this); - }); - }); - -} (jQuery)); \ No newline at end of file diff --git a/src/TestWebsites/NET4/Test_Website_MVC_NET4.csproj b/src/TestWebsites/NET4/Test_Website_MVC_NET4.csproj deleted file mode 100644 index 6158a3bce..000000000 --- a/src/TestWebsites/NET4/Test_Website_MVC_NET4.csproj +++ /dev/null @@ -1,246 +0,0 @@ - - - - - Debug - AnyCPU - - - 2.0 - {30327C08-7574-4D7E-AC95-6A58753C6855} - {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Test - Test - v4.0 - false - false - - - - - 4.0 - - - - - ..\..\ - true - true - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - true - bin\ - DEBUG;TRACE - full - AnyCPU - prompt - - - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll - - - - ..\..\packages\Microsoft.Bcl.1.1.9\lib\net40\System.IO.dll - - - - ..\..\packages\Microsoft.Bcl.1.1.9\lib\net40\System.Runtime.dll - - - ..\..\packages\Microsoft.Bcl.1.1.9\lib\net40\System.Threading.Tasks.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - Global.asax - - - - - - - - - Designer - - - Web.config - - - Web.config - - - - - - - - - - - - {4f7050f2-465f-4e10-8db2-2fb97ac6aa43} - ImageProcessor.Web_NET4 - - - {3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E} - ImageProcessor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - true - bin\ - DEBUG;TRACE - full - x86 - prompt - MinimumRecommendedRules.ruleset - - - bin\ - TRACE - true - pdbonly - x86 - prompt - MinimumRecommendedRules.ruleset - - - true - bin\ - DEBUG;TRACE - full - x86 - prompt - MinimumRecommendedRules.ruleset - - - - - - - - - - - - - False - True - 21961 - / - - - False - False - - - False - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET4/Views/Home/External.cshtml b/src/TestWebsites/NET4/Views/Home/External.cshtml deleted file mode 100644 index 220d6a0a9..000000000 --- a/src/TestWebsites/NET4/Views/Home/External.cshtml +++ /dev/null @@ -1,14 +0,0 @@ -@{ - ViewBag.Title = "External"; -} -

    External

    -
    -
    -
    - -
    -
    - -
    -
    -
    diff --git a/src/TestWebsites/NET4/Views/Home/Gif.cshtml b/src/TestWebsites/NET4/Views/Home/Gif.cshtml deleted file mode 100644 index cb7c3ba25..000000000 --- a/src/TestWebsites/NET4/Views/Home/Gif.cshtml +++ /dev/null @@ -1,99 +0,0 @@ -@{ - ViewBag.Title = "Gif"; -} -
    -

    Gif

    -
    -
    -
    -

    Resized

    - -
    -
    -

    Cropped

    - -
    -
    -
    -
    -

    Filter

    -
    -
    -

    blackwhite

    - -
    -
    -

    comic

    - -
    -
    -
    -
    -

    lomograph

    - -
    -
    -

    greyscale

    - -
    -
    -
    -
    -

    polaroid

    - -
    -
    -

    sepia

    - -
    -
    -
    -
    -

    gotham

    - -
    -
    -

    hisatch

    - -
    -
    -
    -
    -

    losatch

    - -
    -
    -
    -
    -
    -
    -

    Watermark

    - -
    -
    -

    Format

    - -
    -
    -
    -
    -
    -
    -

    Rotate

    - -
    -
    -

    Quality

    - -
    -
    -
    -
    -
    -
    -

    Alpha

    - -
    -
    -
    -
    diff --git a/src/TestWebsites/NET4/Views/Home/Index.cshtml b/src/TestWebsites/NET4/Views/Home/Index.cshtml deleted file mode 100644 index adde1b4a6..000000000 --- a/src/TestWebsites/NET4/Views/Home/Index.cshtml +++ /dev/null @@ -1,191 +0,0 @@ -@{ - ViewBag.Title = "Home Page"; -} -
    -

    Jpg

    -
    -
    -
    -

    Resized

    - -

    Foreign language test.

    - - -
    -
    -

    Cropped

    - -
    -
    -
    -
    -
    -

    Reside Pad

    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Resize Crop

    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Resize Max

    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Resize Stretch

    -
    - -
    -
    - -
    -
    -
    -
    -

    Filter

    -
    -
    -

    blackwhite

    - -
    -
    -

    comic

    - -
    -
    -
    -
    -

    lomograph

    - -
    -
    -

    greyscale

    - -
    -
    -
    -
    -

    polaroid

    - -
    -
    -

    sepia

    - -
    -
    -
    -
    -

    gotham

    - -
    -
    -

    hisatch

    - -
    -
    -
    -
    -

    losatch

    - -
    -
    -
    -
    -
    -
    -

    Watermark

    - -
    -
    -

    Format

    - -
    -
    -
    -
    -
    -
    -

    Rotate

    - -
    -
    -

    Quality

    - -
    -
    -
    -
    -
    -
    -

    Alpha

    - -
    -
    -

    Remote

    -
    -
    -
    -
    -
    -
    -

    Flip - horizontal

    - -
    -
    -

    Flip - vertical

    - -
    -
    -
    -
    - - -
    -

    Color Profiles

    - @*
    -
    -
    -

    CMYK original jpg

    - -
    -
    -

    sRGB original jpg

    - -
    -
    -
    *@ -
    -
    -
    -

    CMYK resized jpg

    - -
    - -
    -

    sRGB resized jpg

    - -
    -
    -
    -
    diff --git a/src/TestWebsites/NET4/Views/Shared/_Layout.cshtml b/src/TestWebsites/NET4/Views/Shared/_Layout.cshtml deleted file mode 100644 index 2a812b676..000000000 --- a/src/TestWebsites/NET4/Views/Shared/_Layout.cshtml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - @ViewBag.Title - - - - -
    -
    -

    ImageProcessor NET4

    -
    - -
    - @RenderBody() -
    -
    - - diff --git a/src/TestWebsites/NET4/Views/Web.config b/src/TestWebsites/NET4/Views/Web.config deleted file mode 100644 index a4def2a3d..000000000 --- a/src/TestWebsites/NET4/Views/Web.config +++ /dev/null @@ -1,58 +0,0 @@ - - - - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/TestWebsites/NET4/Web.Debug.config b/src/TestWebsites/NET4/Web.Debug.config deleted file mode 100644 index 2c6dd51a7..000000000 --- a/src/TestWebsites/NET4/Web.Debug.config +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET4/Web.Release.config b/src/TestWebsites/NET4/Web.Release.config deleted file mode 100644 index 4122d79bf..000000000 --- a/src/TestWebsites/NET4/Web.Release.config +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET4/Web.config b/src/TestWebsites/NET4/Web.config deleted file mode 100644 index 1417ff9bf..000000000 --- a/src/TestWebsites/NET4/Web.config +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET4/config/imageprocessor/processing.config b/src/TestWebsites/NET4/config/imageprocessor/processing.config deleted file mode 100644 index 85283e9f2..000000000 --- a/src/TestWebsites/NET4/config/imageprocessor/processing.config +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/TestWebsites/NET4/config/imageprocessor/security.config b/src/TestWebsites/NET4/config/imageprocessor/security.config deleted file mode 100644 index 44fbb5d64..000000000 --- a/src/TestWebsites/NET4/config/imageprocessor/security.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/TestWebsites/NET4/packages.config b/src/TestWebsites/NET4/packages.config deleted file mode 100644 index c7068f590..000000000 --- a/src/TestWebsites/NET4/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Content/responsive.min.css.REMOVED.git-id b/src/TestWebsites/NET45/Test_Website_NET45/Content/responsive.min.css.REMOVED.git-id deleted file mode 100644 index bcf841f2a..000000000 --- a/src/TestWebsites/NET45/Test_Website_NET45/Content/responsive.min.css.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -e0fbb23ec0c6b4a6980ac29f0c71b82ff900eebc \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Png.cshtml b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Png.cshtml deleted file mode 100644 index d01e7ae8c..000000000 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Png.cshtml +++ /dev/null @@ -1,99 +0,0 @@ -@{ - ViewBag.Title = "Png"; -} -
    -

    Png

    -
    -
    -
    -

    Resized

    - -
    -
    -

    Cropped

    - -
    -
    -
    -
    -

    Filter

    -
    -
    -

    blackwhite

    - -
    -
    -

    comic

    - -
    -
    -
    -
    -

    lomograph

    - -
    -
    -

    greyscale

    - -
    -
    -
    -
    -

    polaroid

    - -
    -
    -

    sepia

    - -
    -
    -
    -
    -

    gotham

    - -
    -
    -

    hisatch

    - -
    -
    -
    -
    -

    losatch

    - -
    -
    -
    -
    -
    -
    -

    Watermark

    - -
    -
    -

    Format

    - -
    -
    -
    -
    -
    -
    -

    Rotate

    - -
    -
    -

    Quality

    - -
    -
    -
    -
    -
    -
    -

    Alpha

    - -
    -
    -
    -
    diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Png8.cshtml b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Png8.cshtml deleted file mode 100644 index 8784c836f..000000000 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Png8.cshtml +++ /dev/null @@ -1,100 +0,0 @@ -@{ - ViewBag.Title = "Png8"; -} - -
    -

    Png8

    -
    -
    -
    -

    Resized

    - -
    -
    -

    Cropped

    - -
    -
    -
    -
    -

    Filter

    -
    -
    -

    blackwhite

    - -
    -
    -

    comic

    - -
    -
    -
    -
    -

    lomograph

    - -
    -
    -

    greyscale

    - -
    -
    -
    -
    -

    polaroid

    - -
    -
    -

    sepia

    - -
    -
    -
    -
    -

    gotham

    - -
    -
    -

    hisatch

    - -
    -
    -
    -
    -

    losatch

    - -
    -
    -
    -
    -
    -
    -

    Watermark

    - -
    -
    -

    Format

    - -
    -
    -
    -
    -
    -
    -

    Rotate

    - -
    -
    -

    Quality

    - -
    -
    -
    -
    -
    -
    -

    Alpha

    - -
    -
    -
    -
    diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Tiff.cshtml b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Tiff.cshtml deleted file mode 100644 index 091e068fb..000000000 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Tiff.cshtml +++ /dev/null @@ -1,99 +0,0 @@ -@{ - ViewBag.Title = "Tiff"; -} -
    -

    Tiff

    -
    -
    -
    -

    Resized

    - -
    -
    -

    Cropped

    - -
    -
    -
    -
    -

    Filter

    -
    -
    -

    blackwhite

    - -
    -
    -

    comic

    - -
    -
    -
    -
    -

    lomograph

    - -
    -
    -

    greyscale

    - -
    -
    -
    -
    -

    polaroid

    - -
    -
    -

    sepia

    - -
    -
    -
    -
    -

    gotham

    - -
    -
    -

    hisatch

    - -
    -
    -
    -
    -

    losatch

    - -
    -
    -
    -
    -
    -
    -

    Watermark

    - -
    -
    -

    Format

    - -
    -
    -
    -
    -
    -
    -

    Rotate

    - -
    -
    -

    Quality

    - -
    -
    -
    -
    -
    -
    -

    Alpha

    - -
    -
    -
    -
    diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/_ViewStart.cshtml b/src/TestWebsites/NET45/Test_Website_NET45/Views/_ViewStart.cshtml deleted file mode 100644 index efda124b1..000000000 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/_ViewStart.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@{ - Layout = "~/Views/Shared/_Layout.cshtml"; -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/cache.config b/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/cache.config deleted file mode 100644 index e4a9c5e9a..000000000 --- a/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/cache.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config b/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config deleted file mode 100644 index 6aa5af4ea..000000000 --- a/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx deleted file mode 100644 index 64c61ae9e..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx +++ /dev/null @@ -1,34 +0,0 @@ -<%@ Page Title="About" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="About.aspx.cs" Inherits="Test_Website_Webforms_NET45.About" %> - - -
    -

    <%: Title %>.

    -

    Your app description page.

    -
    - -
    -

    - Use this area to provide additional information. -

    - -

    - Use this area to provide additional information. -

    - -

    - Use this area to provide additional information. -

    -
    - - -
    \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx.cs deleted file mode 100644 index 46187efb7..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace Test_Website_Webforms_NET45 -{ - public partial class About : Page - { - protected void Page_Load(object sender, EventArgs e) - { - - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx.designer.cs deleted file mode 100644 index a2d829ae3..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/About.aspx.designer.cs +++ /dev/null @@ -1,17 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45 -{ - - public partial class About - { - - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx deleted file mode 100644 index 9a04e8149..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx +++ /dev/null @@ -1,47 +0,0 @@ -<%@ Page Title="Log in" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="Test_Website_Webforms_NET45.Account.Login" %> -<%@ Register Src="~/Account/OpenAuthProviders.ascx" TagPrefix="uc" TagName="OpenAuthProviders" %> - - -
    -

    <%: Title %>.

    -
    -
    -

    Use a local account to log in.

    - - -

    - -

    -
    - Log in Form -
      -
    1. - User name - - -
    2. -
    3. - Password - - -
    4. -
    5. - - Remember me? -
    6. -
    - -
    -
    -
    -

    - Register - if you don't have an account. -

    -
    - -
    -

    Use another service to log in.

    - -
    -
    diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx.cs deleted file mode 100644 index 234c882fe..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace Test_Website_Webforms_NET45.Account -{ - public partial class Login : Page - { - protected void Page_Load(object sender, EventArgs e) - { - RegisterHyperLink.NavigateUrl = "Register"; - OpenAuthLogin.ReturnUrl = Request.QueryString["ReturnUrl"]; - - var returnUrl = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]); - if (!String.IsNullOrEmpty(returnUrl)) - { - RegisterHyperLink.NavigateUrl += "?ReturnUrl=" + returnUrl; - } - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx.designer.cs deleted file mode 100644 index b021637f7..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Login.aspx.designer.cs +++ /dev/null @@ -1,35 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45.Account -{ - - - public partial class Login - { - - /// - /// RegisterHyperLink control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink RegisterHyperLink; - - /// - /// OpenAuthLogin control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Test_Website_Webforms_NET45.Account.OpenAuthProviders OpenAuthLogin; - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx deleted file mode 100644 index 4675b60af..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx +++ /dev/null @@ -1,126 +0,0 @@ -<%@ Page Title="Manage Account" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Manage.aspx.cs" Inherits="Test_Website_Webforms_NET45.Account.Manage" %> -<%@ Register Src="~/Account/OpenAuthProviders.ascx" TagPrefix="uc" TagName="OpenAuthProviders" %> - - -
    -

    <%: Title %>.

    -
    - -
    - -

    <%: SuccessMessage %>

    -
    - -

    You're logged in as <%: User.Identity.Name %>.

    - - -

    - You do not have a local password for this site. Add a local - password so you can log in without an external login. -

    -
    - Set Password Form -
      -
    1. - Password - - - - - -
    2. -
    3. - Confirm password - - - -
    4. -
    - -
    -
    - - -

    Change password

    - - -

    - -

    -
    - Change password details -
      -
    1. - Current password - - -
    2. -
    3. - New password - - -
    4. -
    5. - Confirm new password - - - -
    6. -
    - -
    -
    -
    -
    -
    - -
    - - - - -

    Registered external logins

    - - - - - -
    ServiceUser NameLast Used 
    -
    - - - - <%#: Item.ProviderDisplayName %> - <%#: Item.ProviderUserName %> - <%#: ConvertToDisplayDateTime(Item.LastUsedUtc) %> - - - - - - -
    - -

    Add an external login

    - -
    -
    diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx.cs deleted file mode 100644 index 311c127ff..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -using Microsoft.AspNet.Membership.OpenAuth; - -namespace Test_Website_Webforms_NET45.Account -{ - public partial class Manage : System.Web.UI.Page - { - protected string SuccessMessage - { - get; - private set; - } - - protected bool CanRemoveExternalLogins - { - get; - private set; - } - - protected void Page_Load() - { - if (!IsPostBack) - { - // Determine the sections to render - var hasLocalPassword = OpenAuth.HasLocalPassword(User.Identity.Name); - setPassword.Visible = !hasLocalPassword; - changePassword.Visible = hasLocalPassword; - - CanRemoveExternalLogins = hasLocalPassword; - - // Render success message - var message = Request.QueryString["m"]; - if (message != null) - { - // Strip the query string from action - Form.Action = ResolveUrl("~/Account/Manage"); - - SuccessMessage = - message == "ChangePwdSuccess" ? "Your password has been changed." - : message == "SetPwdSuccess" ? "Your password has been set." - : message == "RemoveLoginSuccess" ? "The external login was removed." - : String.Empty; - successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage); - } - } - - } - - protected void setPassword_Click(object sender, EventArgs e) - { - if (IsValid) - { - var result = OpenAuth.AddLocalPassword(User.Identity.Name, password.Text); - if (result.IsSuccessful) - { - Response.Redirect("~/Account/Manage?m=SetPwdSuccess"); - } - else - { - - ModelState.AddModelError("NewPassword", result.ErrorMessage); - - } - } - } - - - public IEnumerable GetExternalLogins() - { - var accounts = OpenAuth.GetAccountsForUser(User.Identity.Name); - CanRemoveExternalLogins = CanRemoveExternalLogins || accounts.Count() > 1; - return accounts; - } - - public void RemoveExternalLogin(string providerName, string providerUserId) - { - var m = OpenAuth.DeleteAccount(User.Identity.Name, providerName, providerUserId) - ? "?m=RemoveLoginSuccess" - : String.Empty; - Response.Redirect("~/Account/Manage" + m); - } - - - protected static string ConvertToDisplayDateTime(DateTime? utcDateTime) - { - // You can change this method to convert the UTC date time into the desired display - // offset and format. Here we're converting it to the server timezone and formatting - // as a short date and a long time string, using the current thread culture. - return utcDateTime.HasValue ? utcDateTime.Value.ToLocalTime().ToString("G") : "[never]"; - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx.designer.cs deleted file mode 100644 index f746b03b4..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Manage.aspx.designer.cs +++ /dev/null @@ -1,66 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45.Account -{ - - - public partial class Manage - { - - /// - /// successMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder successMessage; - - /// - /// setPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder setPassword; - - /// - /// password control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox password; - - - - /// - /// confirmPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox confirmPassword; - - /// - /// changePassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder changePassword; - - - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx deleted file mode 100644 index 27fe593c0..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx +++ /dev/null @@ -1,21 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="OpenAuthProviders.ascx.cs" Inherits="Test_Website_Webforms_NET45.Account.OpenAuthProviders" %> - -
    - Log in using another service - - - - - - - -
    -

    There are no external authentication services configured. See this article for details on setting up this ASP.NET application to support logging in via external services.

    -
    -
    -
    -
    \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx.cs deleted file mode 100644 index 98ac696ba..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Web; -using Microsoft.AspNet.Membership.OpenAuth; - -namespace Test_Website_Webforms_NET45.Account -{ - public partial class OpenAuthProviders : System.Web.UI.UserControl - { - protected void Page_Load(object sender, EventArgs e) - { - - if (IsPostBack) - { - var provider = Request.Form["provider"]; - if (provider == null) - { - return; - } - - var redirectUrl = "~/Account/RegisterExternalLogin"; - if (!String.IsNullOrEmpty(ReturnUrl)) - { - var resolvedReturnUrl = ResolveUrl(ReturnUrl); - redirectUrl += "?ReturnUrl=" + HttpUtility.UrlEncode(resolvedReturnUrl); - } - - OpenAuth.RequestAuthentication(provider, redirectUrl); - } - } - - - - public string ReturnUrl { get; set; } - - - public IEnumerable GetProviderNames() - { - return OpenAuth.AuthenticationClients.GetAll(); - } - - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx.designer.cs deleted file mode 100644 index 4433c3d0c..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/OpenAuthProviders.ascx.designer.cs +++ /dev/null @@ -1,27 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45.Account -{ - - - public partial class OpenAuthProviders - { - - /// - /// providerDetails control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ListView providerDetails; - - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx deleted file mode 100644 index 74a7221d5..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx +++ /dev/null @@ -1,62 +0,0 @@ -<%@ Page Title="Register" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Register.aspx.cs" Inherits="Test_Website_Webforms_NET45.Account.Register" %> - - -
    -

    <%: Title %>.

    -

    Use the form below to create a new account.

    -
    - - - - - - - - - -

    - Passwords are required to be a minimum of <%: Membership.MinRequiredPasswordLength %> characters in length. -

    - -

    - -

    - -
    - Registration Form -
      -
    1. - User name - - -
    2. -
    3. - Email address - - -
    4. -
    5. - Password - - -
    6. -
    7. - Confirm password - - - -
    8. -
    - -
    -
    - -
    -
    -
    -
    \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx.cs deleted file mode 100644 index e36cc3174..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Security; -using System.Web.UI; -using System.Web.UI.WebControls; -using Microsoft.AspNet.Membership.OpenAuth; - -namespace Test_Website_Webforms_NET45.Account -{ - public partial class Register : Page - { - protected void Page_Load(object sender, EventArgs e) - { - RegisterUser.ContinueDestinationPageUrl = Request.QueryString["ReturnUrl"]; - } - - protected void RegisterUser_CreatedUser(object sender, EventArgs e) - { - FormsAuthentication.SetAuthCookie(RegisterUser.UserName, createPersistentCookie: false); - - string continueUrl = RegisterUser.ContinueDestinationPageUrl; - if (!OpenAuth.IsLocalUrl(continueUrl)) - { - continueUrl = "~/"; - } - Response.Redirect(continueUrl); - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx.designer.cs deleted file mode 100644 index af06bbb97..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Register.aspx.designer.cs +++ /dev/null @@ -1,35 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45.Account -{ - - - public partial class Register - { - - /// - /// RegisterUser control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CreateUserWizard RegisterUser; - - /// - /// RegisterUserWizardStep control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CreateUserWizardStep RegisterUserWizardStep; - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx deleted file mode 100644 index a5914d591..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx +++ /dev/null @@ -1,35 +0,0 @@ -<%@ Page Language="C#" Title="Register an external login" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="RegisterExternalLogin.aspx.cs" Inherits="Test_Website_Webforms_NET45.Account.RegisterExternalLogin" %> - -
    -

    Register with your <%: ProviderDisplayName %> account

    -

    <%: ProviderUserName %>.

    -
    - - - - - - -
    - Association Form -

    - You've authenticated with <%: ProviderDisplayName %> as - <%: ProviderUserName %>. Please enter a user name below for the current site - and click the Log in button. -

    -
      - -
    - - -
    -
    -
    diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx.cs deleted file mode 100644 index 18b667b12..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Web; -using System.Web.Security; -using DotNetOpenAuth.AspNet; -using Microsoft.AspNet.Membership.OpenAuth; - -namespace Test_Website_Webforms_NET45.Account -{ - public partial class RegisterExternalLogin : System.Web.UI.Page - { - protected string ProviderName - { - get { return (string)ViewState["ProviderName"] ?? String.Empty; } - private set { ViewState["ProviderName"] = value; } - } - - protected string ProviderDisplayName - { - get { return (string)ViewState["ProviderDisplayName"] ?? String.Empty; } - private set { ViewState["ProviderDisplayName"] = value; } - } - - protected string ProviderUserId - { - get { return (string)ViewState["ProviderUserId"] ?? String.Empty; } - private set { ViewState["ProviderUserId"] = value; } - } - - protected string ProviderUserName - { - get { return (string)ViewState["ProviderUserName"] ?? String.Empty; } - private set { ViewState["ProviderUserName"] = value; } - } - - protected void Page_Load() - { - if (!IsPostBack) - { - ProcessProviderResult(); - } - } - - protected void logIn_Click(object sender, EventArgs e) - { - CreateAndLoginUser(); - } - - protected void cancel_Click(object sender, EventArgs e) - { - RedirectToReturnUrl(); - } - - private void ProcessProviderResult() - { - // Process the result from an auth provider in the request - ProviderName = OpenAuth.GetProviderNameFromCurrentRequest(); - - if (String.IsNullOrEmpty(ProviderName)) - { - Response.Redirect(FormsAuthentication.LoginUrl); - } - - // Build the redirect url for OpenAuth verification - var redirectUrl = "~/Account/RegisterExternalLogin"; - var returnUrl = Request.QueryString["ReturnUrl"]; - if (!String.IsNullOrEmpty(returnUrl)) - { - redirectUrl += "?ReturnUrl=" + HttpUtility.UrlEncode(returnUrl); - } - - // Verify the OpenAuth payload - var authResult = OpenAuth.VerifyAuthentication(redirectUrl); - ProviderDisplayName = OpenAuth.GetProviderDisplayName(ProviderName); - if (!authResult.IsSuccessful) - { - Title = "External login failed"; - userNameForm.Visible = false; - - ModelState.AddModelError("Provider", String.Format("External login {0} failed.", ProviderDisplayName)); - - // To view this error, enable page tracing in web.config () and visit ~/Trace.axd - Trace.Warn("OpenAuth", String.Format("There was an error verifying authentication with {0})", ProviderDisplayName), authResult.Error); - return; - } - - // User has logged in with provider successfully - // Check if user is already registered locally - if (OpenAuth.Login(authResult.Provider, authResult.ProviderUserId, createPersistentCookie: false)) - { - RedirectToReturnUrl(); - } - - // Store the provider details in ViewState - ProviderName = authResult.Provider; - ProviderUserId = authResult.ProviderUserId; - ProviderUserName = authResult.UserName; - - // Strip the query string from action - Form.Action = ResolveUrl(redirectUrl); - - if (User.Identity.IsAuthenticated) - { - // User is already authenticated, add the external login and redirect to return url - OpenAuth.AddAccountToExistingUser(ProviderName, ProviderUserId, ProviderUserName, User.Identity.Name); - RedirectToReturnUrl(); - } - else - { - // User is new, ask for their desired membership name - userName.Text = authResult.UserName; - } - } - - private void CreateAndLoginUser() - { - if (!IsValid) - { - return; - } - - var createResult = OpenAuth.CreateUser(ProviderName, ProviderUserId, ProviderUserName, userName.Text); - if (!createResult.IsSuccessful) - { - - ModelState.AddModelError("UserName", createResult.ErrorMessage); - - } - else - { - // User created & associated OK - if (OpenAuth.Login(ProviderName, ProviderUserId, createPersistentCookie: false)) - { - RedirectToReturnUrl(); - } - } - } - - private void RedirectToReturnUrl() - { - var returnUrl = Request.QueryString["ReturnUrl"]; - if (!String.IsNullOrEmpty(returnUrl) && OpenAuth.IsLocalUrl(returnUrl)) - { - Response.Redirect(returnUrl); - } - else - { - Response.Redirect("~/"); - } - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx.designer.cs deleted file mode 100644 index d3bd505c4..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/RegisterExternalLogin.aspx.designer.cs +++ /dev/null @@ -1,39 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45.Account -{ - - - public partial class RegisterExternalLogin - { - - - - /// - /// userNameForm control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder userNameForm; - - /// - /// userName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox userName; - - - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Web.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Web.config deleted file mode 100644 index 90fe314f6..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Account/Web.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/AuthConfig.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/AuthConfig.cs deleted file mode 100644 index 24093ce83..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/AuthConfig.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using Microsoft.AspNet.Membership.OpenAuth; - -namespace Test_Website_Webforms_NET45 -{ - internal static class AuthConfig - { - public static void RegisterOpenAuth() - { - // See http://go.microsoft.com/fwlink/?LinkId=252803 for details on setting up this ASP.NET - // application to support logging in via external services. - - //OpenAuth.AuthenticationClients.AddTwitter( - // consumerKey: "your Twitter consumer key", - // consumerSecret: "your Twitter consumer secret"); - - //OpenAuth.AuthenticationClients.AddFacebook( - // appId: "your Facebook app id", - // appSecret: "your Facebook app secret"); - - //OpenAuth.AuthenticationClients.AddMicrosoft( - // clientId: "your Microsoft account client id", - // clientSecret: "your Microsoft account client secret"); - - //OpenAuth.AuthenticationClients.AddGoogle(); - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/BundleConfig.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/BundleConfig.cs deleted file mode 100644 index 6e3260970..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/BundleConfig.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Optimization; - -namespace Test_Website_Webforms_NET45 -{ - public class BundleConfig - { - // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254726 - public static void RegisterBundles(BundleCollection bundles) - { - bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").Include( - "~/Scripts/WebForms/WebForms.js", - "~/Scripts/WebForms/WebUIValidation.js", - "~/Scripts/WebForms/MenuStandards.js", - "~/Scripts/WebForms/Focus.js", - "~/Scripts/WebForms/GridView.js", - "~/Scripts/WebForms/DetailsView.js", - "~/Scripts/WebForms/TreeView.js", - "~/Scripts/WebForms/WebParts.js")); - - bundles.Add(new ScriptBundle("~/bundles/MsAjaxJs").Include( - "~/Scripts/WebForms/MsAjax/MicrosoftAjax.js", - "~/Scripts/WebForms/MsAjax/MicrosoftAjaxApplicationServices.js", - "~/Scripts/WebForms/MsAjax/MicrosoftAjaxTimer.js", - "~/Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js")); - - // Use the Development version of Modernizr to develop with and learn from. Then, when you’re - // ready for production, use the build tool at http://modernizr.com to pick only the tests you need - bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( - "~/Scripts/modernizr-*")); - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/RouteConfig.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/RouteConfig.cs deleted file mode 100644 index 52270811a..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/App_Start/RouteConfig.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Web; -using System.Web.Routing; -using Microsoft.AspNet.FriendlyUrls; - -namespace Test_Website_Webforms_NET45 -{ - public static class RouteConfig - { - public static void RegisterRoutes(RouteCollection routes) - { - routes.EnableFriendlyUrls(); - } - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Bundle.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Bundle.config deleted file mode 100644 index 669a33e5b..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Bundle.config +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx deleted file mode 100644 index 0535364da..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx +++ /dev/null @@ -1,50 +0,0 @@ -<%@ Page Title="Contact" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Contact.aspx.cs" Inherits="Test_Website_Webforms_NET45.Contact" %> - - -
    -

    <%: Title %>.

    -

    Your contact page.

    -
    - -
    -
    -

    Phone:

    -
    -

    - Main: - 425.555.0100 -

    -

    - After Hours: - 425.555.0199 -

    -
    - -
    -
    -

    Email:

    -
    -

    - Support: - Support@example.com -

    -

    - Marketing: - Marketing@example.com -

    -

    - General: - General@example.com -

    -
    - -
    -
    -

    Address:

    -
    -

    - One Microsoft Way
    - Redmond, WA 98052-6399 -

    -
    -
    \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx.cs deleted file mode 100644 index 52bee3d3a..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace Test_Website_Webforms_NET45 -{ - public partial class Contact : Page - { - protected void Page_Load(object sender, EventArgs e) - { - - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx.designer.cs deleted file mode 100644 index bfda2b100..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Contact.aspx.designer.cs +++ /dev/null @@ -1,15 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45 -{ - public partial class Contact - { - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Content/Site.css b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Content/Site.css deleted file mode 100644 index 3f7b9164f..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Content/Site.css +++ /dev/null @@ -1,734 +0,0 @@ -html { - background-color: #e2e2e2; - margin: 0; - padding: 0; -} - -body { - background-color: #fff; - border-top: solid 10px #000; - color: #333; - font-size: .85em; - font-family: "Segoe UI", Verdana, Helvetica, Sans-Serif; - margin: 0; - padding: 0; -} - -a { - color: #333; - outline: none; - padding-left: 3px; - padding-right: 3px; - text-decoration: underline; -} - - a:link, a:visited, - a:active, a:hover { - color: #333; - } - - a:hover { - background-color: #c7d1d6; - } - -header, footer, hgroup, -nav, section { - display: block; -} - -mark { - background-color: #a6dbed; - padding-left: 5px; - padding-right: 5px; -} - -.float-left { - float: left; -} - -.float-right { - float: right; -} - -.clear-fix:after { - content: "."; - clear: both; - display: block; - height: 0; - visibility: hidden; -} - -h1, h2, h3, -h4, h5, h6 { - color: #000; - margin-bottom: 0; - padding-bottom: 0; -} - -h1 { - font-size: 2em; -} - -h2 { - font-size: 1.75em; -} - -h3 { - font-size: 1.2em; -} - -h4 { - font-size: 1.1em; -} - -h5, h6 { - font-size: 1em; -} - - h5 a:link, h5 a:visited, h5 a:active { - padding: 0; - text-decoration: none; - } - -/* main layout -----------------------------------------------------------*/ -.content-wrapper { - margin: 0 auto; - max-width: 960px; -} - -#body { - background-color: #efeeef; - clear: both; - padding-bottom: 35px; -} - - .main-content { - background: url("../Images/accent.png") no-repeat; - padding-left: 10px; - padding-top: 30px; - } - - .featured + .main-content { - background: url("../Images/heroAccent.png") no-repeat; - } - -header .content-wrapper { - padding-top: 20px; -} - -footer { - clear: both; - background-color: #e2e2e2; - font-size: .8em; - height: 100px; -} - - -/* site title -----------------------------------------------------------*/ -.site-title { - color: #c8c8c8; - font-family: Rockwell, Consolas, "Courier New", Courier, monospace; - font-size: 2.3em; - margin: 0; -} - -.site-title a, .site-title a:hover, .site-title a:active { - background: none; - color: #c8c8c8; - outline: none; - text-decoration: none; -} - - -/* login -----------------------------------------------------------*/ -#login { - display: block; - font-size: .85em; - margin: 0 0 10px; - text-align: right; -} - - #login a { - background-color: #d3dce0; - margin-left: 10px; - margin-right: 3px; - padding: 2px 3px; - text-decoration: none; - } - - #login a.username { - background: none; - margin-left: 0px; - text-decoration: underline; - } - - #login ul { - margin: 0; - } - - #login li { - display: inline; - list-style: none; - } - - -/* menu -----------------------------------------------------------*/ -ul#menu { - font-size: 1.3em; - font-weight: 600; - margin: 0 0 5px; - padding: 0; - text-align: right; -} - - ul#menu li { - display: inline; - list-style: none; - padding-left: 15px; - } - - ul#menu li a { - background: none; - color: #999; - text-decoration: none; - } - - ul#menu li a:hover { - color: #333; - text-decoration: none; - } - - -/* page elements -----------------------------------------------------------*/ -/* featured */ -.featured { - background-color: #fff; -} - - .featured .content-wrapper { - background-color: #7ac0da; - background-image: -ms-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%); - background-image: -o-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%); - background-image: -webkit-gradient(linear, left top, right top, color-stop(0, #7ac0da), color-stop(1, #a4d4e6)); - background-image: -webkit-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%); - background-image: linear-gradient(left, #7ac0da 0%, #a4d4e6 100%); - color: #3e5667; - padding: 20px 40px 30px 40px; - } - - .featured hgroup.title h1, .featured hgroup.title h2 { - color: #fff; - } - - .featured p { - font-size: 1.1em; - } - -/* page titles */ -hgroup.title { - margin-bottom: 10px; -} - -hgroup.title h1, hgroup.title h2 { - display: inline; -} - -hgroup.title h2 { - font-weight: normal; - margin-left: 3px; -} - -/* features */ -section.feature { - width: 300px; - float: left; - padding: 10px; -} - -/* ordered list */ -ol.round { - list-style-type: none; - padding-left: 0; -} - - ol.round li { - margin: 25px 0; - padding-left: 45px; - } - - ol.round li.zero { - background: url("../Images/orderedList0.png") no-repeat; - } - - ol.round li.one { - background: url("../Images/orderedList1.png") no-repeat; - } - - ol.round li.two { - background: url("../Images/orderedList2.png") no-repeat; - } - - ol.round li.three { - background: url("../Images/orderedList3.png") no-repeat; - } - - ol.round li.four { - background: url("../Images/orderedList4.png") no-repeat; - } - - ol.round li.five { - background: url("../Images/orderedList5.png") no-repeat; - } - - ol.round li.six { - background: url("../Images/orderedList6.png") no-repeat; - } - - ol.round li.seven { - background: url("../Images/orderedList7.png") no-repeat; - } - - ol.round li.eight { - background: url("../Images/orderedList8.png") no-repeat; - } - - ol.round li.nine { - background: url("../Images/orderedList9.png") no-repeat; - } - -/* content */ -article { - float: left; - width: 70%; -} - -aside { - float: right; - width: 25%; -} - - aside ul { - list-style: none; - padding: 0; - } - - aside ul li { - background: url("../Images/bullet.png") no-repeat 0 50%; - padding: 2px 0 2px 20px; - } - -.label { - font-weight: 700; -} - -/* login page */ -#loginForm { - border-right: solid 2px #c8c8c8; - float: left; - width: 55%; -} - - #loginForm .validation-error { - display: block; - margin-left: 15px; - } - -#socialLoginForm { - margin-left: 40px; - float: left; - width: 40%; -} - - #socialLoginForm h2 { - margin-bottom: 5px; - } - -fieldset.open-auth-providers { - margin-top: 15px; -} - - fieldset.open-auth-providers button { - margin-bottom: 12px; - } - -/* contact */ -.contact h3 { - font-size: 1.2em; -} - -.contact p { - margin: 5px 0 0 10px; -} - -.contact iframe { - border: 1px solid #333; - margin: 5px 0 0 10px; -} - -/* forms */ -fieldset { - border: none; - margin: 0; - padding: 0; -} - - fieldset legend { - display: none; - } - - fieldset ol { - padding: 0; - list-style: none; - } - - fieldset ol li { - padding-bottom: 5px; - } - - label { - display: block; - font-size: 1.2em; - font-weight: 600; - } - - label.checkbox { - display: inline; - } - - input, textarea { - border: 1px solid #e2e2e2; - background: #fff; - color: #333; - font-size: 1.2em; - margin: 5px 0 6px 0; - padding: 5px; - width: 300px; - } - - textarea { - font-family: inherit; - width: 500px; - } - - input:focus, textarea:focus { - border: 1px solid #7ac0da; - } - - input[type="checkbox"] { - background: transparent; - border: inherit; - width: auto; - } - - input[type="submit"], - input[type="button"], - button { - background-color: #d3dce0; - border: 1px solid #787878; - cursor: pointer; - font-size: 1.2em; - font-weight: 600; - padding: 7px; - margin-right: 8px; - width: auto; - } - - td input[type="submit"], - td input[type="button"], - td button { - font-size: 1em; - padding: 4px; - margin-right: 4px; - } - -/* info and errors */ -.message-info { - border: 1px solid; - clear: both; - padding: 10px 20px; -} - -.message-error { - clear: both; - color: #e80c4d; - font-size: 1.1em; - font-weight: bold; - margin: 20px 0 10px 0; -} - -.message-success { - color: #7ac0da; - font-size: 1.3em; - font-weight: bold; - margin: 20px 0 10px 0; -} - -.error { - color: #e80c4d; -} - -/* styles for validation helpers */ -.field-validation-error { - color: #e80c4d; - font-weight: bold; -} - -.field-validation-valid { - display: none; -} - -input.input-validation-error { - border: 1px solid #e80c4d; -} - -input[type="checkbox"].input-validation-error { - border: 0 none; -} - -.validation-summary-errors { - color: #e80c4d; - font-weight: bold; - font-size: 1.1em; -} - -.validation-summary-valid { - display: none; -} - -/* tables -----------------------------------------------------------*/ -table { - border-collapse: collapse; - border-spacing: 0; - margin-top: 0.75em; - border: 0 none; -} - -th { - font-size: 1.2em; - text-align: left; - border: none 0px; - padding-left: 0; -} - - th a { - display: block; - position: relative; - - } - - th a:link, th a:visited, th a:active, th a:hover { - color: #333; - font-weight: 600; - text-decoration: none; - padding: 0; - } - - th a:hover { - color: #000; - } - - th.asc a, th.desc a { - margin-right: .75em; - } - - th.asc a:after, th.desc a:after { - display: block; - position: absolute; - right: 0em; - top: 0; - font-size: 0.75em; - } - - th.asc a:after { - content: '▲'; - } - - th.desc a:after { - content: '▼'; - } - -td { - padding: 0.25em 2em 0.25em 0em; - border: 0 none; -} - -tr.pager td { - padding: 0 0.25em 0 0; -} - - -/******************** -* Mobile Styles * -********************/ -@media only screen and (max-width: 850px) { - - /* header - ----------------------------------------------------------*/ - header .float-left, - header .float-right { - float: none; - } - - /* logo */ - header .site-title { - margin: 10px; - text-align: center; - } - - /* login */ - #login { - font-size: .85em; - margin: 0 0 12px; - text-align: center; - } - - #login ul { - margin: 5px 0; - padding: 0; - } - - #login li { - display: inline; - list-style: none; - margin: 0; - padding: 0; - } - - #login a { - background: none; - color: #999; - font-weight: 600; - margin: 2px; - padding: 0; - } - - #login a:hover { - color: #333; - } - - /* menu */ - nav { - margin-bottom: 5px; - } - - ul#menu { - margin: 0; - padding: 0; - text-align: center; - } - - ul#menu li { - margin: 0; - padding: 0; - } - - - /* main layout - ----------------------------------------------------------*/ - .main-content, - .featured + .main-content { - background-position: 10px 0; - } - - .content-wrapper { - padding-right: 10px; - padding-left: 10px; - } - - .featured .content-wrapper { - padding: 10px; - } - - /* page content */ - article, aside { - float: none; - width: 100%; - } - - /* ordered list */ - ol.round { - list-style-type: none; - padding-left: 0; - } - - ol.round li { - padding-left: 10px; - margin: 25px 0; - } - - ol.round li.zero, - ol.round li.one, - ol.round li.two, - ol.round li.three, - ol.round li.four, - ol.round li.five, - ol.round li.six, - ol.round li.seven, - ol.round li.eight, - ol.round li.nine { - background: none; - } - - /* features */ - section.feature { - float: none; - padding: 10px; - width: auto; - } - - section.feature img { - color: #999; - content: attr(alt); - font-size: 1.5em; - font-weight: 600; - } - - /* forms */ - input { - width: 90%; - } - - - - /* login page */ - #loginForm { - border-right: none; - float: none; - width: auto; - } - - #loginForm .validation-error { - display: block; - margin-left: 15px; - } - - #socialLoginForm { - margin-left: 0; - float: none; - width: auto; - } - - /* footer - ----------------------------------------------------------*/ - footer .float-left, - footer .float-right { - float: none; - } - - footer { - text-align: center; - height: auto; - padding: 10px 0; - } - - footer p { - margin: 0; - } -} -/* END: Mobile Styles */ diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx deleted file mode 100644 index dfbff0bc7..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx +++ /dev/null @@ -1,42 +0,0 @@ -<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Test_Website_Webforms_NET45._Default" %> - - - - - -

    We suggest the following:

    - - - -
      -
    1. -
      Getting Started
      - ASP.NET Web Forms lets you build dynamic websites using a familiar drag-and-drop, event-driven model. - A design surface and hundreds of controls and components let you rapidly build sophisticated, powerful UI-driven sites with data access. - Learn more… -
    2. -
    3. -
      Add NuGet packages and jump-start your coding
      - NuGet makes it easy to install and update free libraries and tools. - Learn more… -
    4. -
    5. -
      Find Web Hosting
      - You can easily find a web hosting company that offers the right mix of features and price for your applications. - Learn more… -
    6. -
    -
    diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx.cs deleted file mode 100644 index f3f45bac2..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace Test_Website_Webforms_NET45 -{ - public partial class _Default : Page - { - protected void Page_Load(object sender, EventArgs e) - { - - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx.designer.cs deleted file mode 100644 index ff8b62699..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Default.aspx.designer.cs +++ /dev/null @@ -1,17 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45 -{ - - - public partial class _Default - { - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Global.asax b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Global.asax deleted file mode 100644 index bd198613c..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Global.asax +++ /dev/null @@ -1 +0,0 @@ -<%@ Application Codebehind="Global.asax.cs" Inherits="Test_Website_Webforms_NET45.Global" Language="C#" %> diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Global.asax.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Global.asax.cs deleted file mode 100644 index 0ce814eed..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Global.asax.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Optimization; -using System.Web.Routing; -using System.Web.Security; -using Test_Website_Webforms_NET45; - -namespace Test_Website_Webforms_NET45 -{ - public class Global : HttpApplication - { - void Application_Start(object sender, EventArgs e) - { - // Code that runs on application startup - BundleConfig.RegisterBundles(BundleTable.Bundles); - AuthConfig.RegisterOpenAuth(); - RouteConfig.RegisterRoutes(RouteTable.Routes); - } - - void Application_End(object sender, EventArgs e) - { - // Code that runs on application shutdown - - } - - void Application_Error(object sender, EventArgs e) - { - // Code that runs when an unhandled error occurs - - } - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/DetailsView.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/DetailsView.js deleted file mode 100644 index a36a49894..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/DetailsView.js +++ /dev/null @@ -1,34 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/DetailsView.js -function DetailsView() { - this.pageIndex = null; - this.dataKeys = null; - this.createPropertyString = DetailsView_createPropertyString; - this.setStateField = DetailsView_setStateValue; - this.getHiddenFieldContents = DetailsView_getHiddenFieldContents; - this.stateField = null; - this.panelElement = null; - this.callback = null; -} -function DetailsView_createPropertyString() { - return createPropertyStringFromValues_DetailsView(this.pageIndex, this.dataKeys); -} -function DetailsView_setStateValue() { - this.stateField.value = this.createPropertyString(); -} -function DetailsView_OnCallback (result, context) { - var value = new String(result); - var valsArray = value.split("|"); - var innerHtml = valsArray[2]; - for (var i = 3; i < valsArray.length; i++) { - innerHtml += "|" + valsArray[i]; - } - context.panelElement.innerHTML = innerHtml; - context.stateField.value = createPropertyStringFromValues_DetailsView(valsArray[0], valsArray[1]); -} -function DetailsView_getHiddenFieldContents(arg) { - return arg + "|" + this.stateField.value; -} -function createPropertyStringFromValues_DetailsView(pageIndex, dataKeys) { - var value = new Array(pageIndex, dataKeys); - return value.join("|"); -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/Focus.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/Focus.js deleted file mode 100644 index 2de90df66..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/Focus.js +++ /dev/null @@ -1,93 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/Focus.js -function WebForm_FindFirstFocusableChild(control) { - if (!control || !(control.tagName)) { - return null; - } - var tagName = control.tagName.toLowerCase(); - if (tagName == "undefined") { - return null; - } - var children = control.childNodes; - if (children) { - for (var i = 0; i < children.length; i++) { - try { - if (WebForm_CanFocus(children[i])) { - return children[i]; - } - else { - var focused = WebForm_FindFirstFocusableChild(children[i]); - if (WebForm_CanFocus(focused)) { - return focused; - } - } - } catch (e) { - } - } - } - return null; -} -function WebForm_AutoFocus(focusId) { - var targetControl; - if (__nonMSDOMBrowser) { - targetControl = document.getElementById(focusId); - } - else { - targetControl = document.all[focusId]; - } - var focused = targetControl; - if (targetControl && (!WebForm_CanFocus(targetControl)) ) { - focused = WebForm_FindFirstFocusableChild(targetControl); - } - if (focused) { - try { - focused.focus(); - if (__nonMSDOMBrowser) { - focused.scrollIntoView(false); - } - if (window.__smartNav) { - window.__smartNav.ae = focused.id; - } - } - catch (e) { - } - } -} -function WebForm_CanFocus(element) { - if (!element || !(element.tagName)) return false; - var tagName = element.tagName.toLowerCase(); - return (!(element.disabled) && - (!(element.type) || element.type.toLowerCase() != "hidden") && - WebForm_IsFocusableTag(tagName) && - WebForm_IsInVisibleContainer(element) - ); -} -function WebForm_IsFocusableTag(tagName) { - return (tagName == "input" || - tagName == "textarea" || - tagName == "select" || - tagName == "button" || - tagName == "a"); -} -function WebForm_IsInVisibleContainer(ctrl) { - var current = ctrl; - while((typeof(current) != "undefined") && (current != null)) { - if (current.disabled || - ( typeof(current.style) != "undefined" && - ( ( typeof(current.style.display) != "undefined" && - current.style.display == "none") || - ( typeof(current.style.visibility) != "undefined" && - current.style.visibility == "hidden") ) ) ) { - return false; - } - if (typeof(current.parentNode) != "undefined" && - current.parentNode != null && - current.parentNode != current && - current.parentNode.tagName.toLowerCase() != "body") { - current = current.parentNode; - } - else { - return true; - } - } - return true; -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/GridView.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/GridView.js deleted file mode 100644 index e24c2d73f..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/GridView.js +++ /dev/null @@ -1,36 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/GridView.js -function GridView() { - this.pageIndex = null; - this.sortExpression = null; - this.sortDirection = null; - this.dataKeys = null; - this.createPropertyString = GridView_createPropertyString; - this.setStateField = GridView_setStateValue; - this.getHiddenFieldContents = GridView_getHiddenFieldContents; - this.stateField = null; - this.panelElement = null; - this.callback = null; -} -function GridView_createPropertyString() { - return createPropertyStringFromValues_GridView(this.pageIndex, this.sortDirection, this.sortExpression, this.dataKeys); -} -function GridView_setStateValue() { - this.stateField.value = this.createPropertyString(); -} -function GridView_OnCallback (result, context) { - var value = new String(result); - var valsArray = value.split("|"); - var innerHtml = valsArray[4]; - for (var i = 5; i < valsArray.length; i++) { - innerHtml += "|" + valsArray[i]; - } - context.panelElement.innerHTML = innerHtml; - context.stateField.value = createPropertyStringFromValues_GridView(valsArray[0], valsArray[1], valsArray[2], valsArray[3]); -} -function GridView_getHiddenFieldContents(arg) { - return arg + "|" + this.stateField.value; -} -function createPropertyStringFromValues_GridView(pageIndex, sortDirection, sortExpression, dataKeys) { - var value = new Array(pageIndex, sortDirection, sortExpression, dataKeys); - return value.join("|"); -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjax.js.REMOVED.git-id b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjax.js.REMOVED.git-id deleted file mode 100644 index 39a827e0f..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjax.js.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -884acce8ae436ffaa7d481a9e97e9d0a96253389 \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxApplicationServices.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxApplicationServices.js deleted file mode 100644 index 6410f841c..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxApplicationServices.js +++ /dev/null @@ -1,6 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/MicrosoftAjaxApplicationServices.js -//---------------------------------------------------------- -// Copyright (C) Microsoft Corporation. All rights reserved. -//---------------------------------------------------------- -// MicrosoftAjaxApplicationServices.js -Type._registerScript("MicrosoftAjaxApplicationServices.js",["MicrosoftAjaxWebServices.js"]);Type.registerNamespace("Sys.Services");Sys.Services._ProfileService=function(){Sys.Services._ProfileService.initializeBase(this);this.properties={}};Sys.Services._ProfileService.DefaultWebServicePath="";Sys.Services._ProfileService.prototype={_defaultLoadCompletedCallback:null,_defaultSaveCompletedCallback:null,_path:"",_timeout:0,get_defaultLoadCompletedCallback:function(){return this._defaultLoadCompletedCallback},set_defaultLoadCompletedCallback:function(a){this._defaultLoadCompletedCallback=a},get_defaultSaveCompletedCallback:function(){return this._defaultSaveCompletedCallback},set_defaultSaveCompletedCallback:function(a){this._defaultSaveCompletedCallback=a},get_path:function(){return this._path||""},load:function(c,d,e,f){var b,a;if(!c){a="GetAllPropertiesForCurrentUser";b={authenticatedUserOnly:false}}else{a="GetPropertiesForCurrentUser";b={properties:this._clonePropertyNames(c),authenticatedUserOnly:false}}this._invoke(this._get_path(),a,false,b,Function.createDelegate(this,this._onLoadComplete),Function.createDelegate(this,this._onLoadFailed),[d,e,f])},save:function(d,b,c,e){var a=this._flattenProperties(d,this.properties);this._invoke(this._get_path(),"SetPropertiesForCurrentUser",false,{values:a.value,authenticatedUserOnly:false},Function.createDelegate(this,this._onSaveComplete),Function.createDelegate(this,this._onSaveFailed),[b,c,e,a.count])},_clonePropertyNames:function(e){var c=[],d={};for(var b=0;b=0;c--){var f=d[c];if(!g||f.autoRemove)$removeHandler(a,b,f.handler)}}a._events=null}};Sys.UI.DomEvent._disposeHandlers=function(){Sys.UI.DomEvent._clearHandlers(this,true);var b=this._chainDispose,a=typeof b;if(a!=="undefined"){this.dispose=b;this._chainDispose=null;if(a==="function")this.dispose()}};var $removeHandler=Sys.UI.DomEvent.removeHandler=function(b,a,c){Sys.UI.DomEvent._removeHandler(b,a,c)};Sys.UI.DomEvent._removeHandler=function(a,e,f){var d=null,c=a._events[e];for(var b=0,g=c.length;b=3){d+=parseInt(b.borderLeftWidth);e+=parseInt(b.borderTopWidth)}}b=Sys.UI.DomElement._getCurrentStyle(c);var h=b?b.position:null;if(!h||h!=="absolute")for(a=c.parentNode;a;a=a.parentNode){f=a.tagName?a.tagName.toUpperCase():null;if(f!=="BODY"&&f!=="HTML"&&(a.scrollLeft||a.scrollTop)){d-=a.scrollLeft||0;e-=a.scrollTop||0}b=Sys.UI.DomElement._getCurrentStyle(a);var i=b?b.position:null;if(i&&i==="absolute")break}return new Sys.UI.Point(d,e)};else Sys.UI.DomElement.getLocation=function(d){if(d.window&&d.window===d||d.nodeType===9)return new Sys.UI.Point(0,0);var e=0,f=0,a,i=null,g=null,b=null;for(a=d;a;i=a,(g=b,a=a.offsetParent)){var c=a.tagName?a.tagName.toUpperCase():null;b=Sys.UI.DomElement._getCurrentStyle(a);if((a.offsetLeft||a.offsetTop)&&!(c==="BODY"&&(!g||g.position!=="absolute"))){e+=a.offsetLeft;f+=a.offsetTop}if(i!==null&&b){if(c!=="TABLE"&&c!=="TD"&&c!=="HTML"){e+=parseInt(b.borderLeftWidth)||0;f+=parseInt(b.borderTopWidth)||0}if(c==="TABLE"&&(b.position==="relative"||b.position==="absolute")){e+=parseInt(b.marginLeft)||0;f+=parseInt(b.marginTop)||0}}}b=Sys.UI.DomElement._getCurrentStyle(d);var h=b?b.position:null;if(!h||h!=="absolute")for(a=d.parentNode;a;a=a.parentNode){c=a.tagName?a.tagName.toUpperCase():null;if(c!=="BODY"&&c!=="HTML"&&(a.scrollLeft||a.scrollTop)){e-=a.scrollLeft||0;f-=a.scrollTop||0;b=Sys.UI.DomElement._getCurrentStyle(a);if(b){e+=parseInt(b.borderLeftWidth)||0;f+=parseInt(b.borderTopWidth)||0}}}return new Sys.UI.Point(e,f)};Sys.UI.DomElement.isDomElement=function(a){return Sys._isDomElement(a)};Sys.UI.DomElement.removeCssClass=function(d,c){var a=" "+d.className+" ",b=a.indexOf(" "+c+" ");if(b>=0)d.className=(a.substr(0,b)+" "+a.substring(b+c.length+1,a.length)).trim()};Sys.UI.DomElement.resolveElement=function(b,c){var a=b;if(!a)return null;if(typeof a==="string")a=Sys.UI.DomElement.getElementById(a,c);return a};Sys.UI.DomElement.raiseBubbleEvent=function(c,d){var b=c;while(b){var a=b.control;if(a&&a.onBubbleEvent&&a.raiseBubbleEvent){Sys.UI.DomElement._raiseBubbleEventFromControl(a,c,d);return}b=b.parentNode}};Sys.UI.DomElement._raiseBubbleEventFromControl=function(a,b,c){if(!a.onBubbleEvent(b,c))a._raiseBubbleEvent(b,c)};Sys.UI.DomElement.setLocation=function(b,c,d){var a=b.style;a.position="absolute";a.left=c+"px";a.top=d+"px"};Sys.UI.DomElement.toggleCssClass=function(b,a){if(Sys.UI.DomElement.containsCssClass(b,a))Sys.UI.DomElement.removeCssClass(b,a);else Sys.UI.DomElement.addCssClass(b,a)};Sys.UI.DomElement.getVisibilityMode=function(a){return a._visibilityMode===Sys.UI.VisibilityMode.hide?Sys.UI.VisibilityMode.hide:Sys.UI.VisibilityMode.collapse};Sys.UI.DomElement.setVisibilityMode=function(a,b){Sys.UI.DomElement._ensureOldDisplayMode(a);if(a._visibilityMode!==b){a._visibilityMode=b;if(Sys.UI.DomElement.getVisible(a)===false)if(a._visibilityMode===Sys.UI.VisibilityMode.hide)a.style.display=a._oldDisplayMode;else a.style.display="none";a._visibilityMode=b}};Sys.UI.DomElement.getVisible=function(b){var a=b.currentStyle||Sys.UI.DomElement._getCurrentStyle(b);if(!a)return true;return a.visibility!=="hidden"&&a.display!=="none"};Sys.UI.DomElement.setVisible=function(a,b){if(b!==Sys.UI.DomElement.getVisible(a)){Sys.UI.DomElement._ensureOldDisplayMode(a);a.style.visibility=b?"visible":"hidden";if(b||a._visibilityMode===Sys.UI.VisibilityMode.hide)a.style.display=a._oldDisplayMode;else a.style.display="none"}};Sys.UI.DomElement._ensureOldDisplayMode=function(a){if(!a._oldDisplayMode){var b=a.currentStyle||Sys.UI.DomElement._getCurrentStyle(a);a._oldDisplayMode=b?b.display:null;if(!a._oldDisplayMode||a._oldDisplayMode==="none")switch(a.tagName.toUpperCase()){case "DIV":case "P":case "ADDRESS":case "BLOCKQUOTE":case "BODY":case "COL":case "COLGROUP":case "DD":case "DL":case "DT":case "FIELDSET":case "FORM":case "H1":case "H2":case "H3":case "H4":case "H5":case "H6":case "HR":case "IFRAME":case "LEGEND":case "OL":case "PRE":case "TABLE":case "TD":case "TH":case "TR":case "UL":a._oldDisplayMode="block";break;case "LI":a._oldDisplayMode="list-item";break;default:a._oldDisplayMode="inline"}}};Sys.UI.DomElement._getWindow=function(a){var b=a.ownerDocument||a.document||a;return b.defaultView||b.parentWindow};Sys.UI.DomElement._getCurrentStyle=function(a){if(a.nodeType===3)return null;var c=Sys.UI.DomElement._getWindow(a);if(a.documentElement)a=a.documentElement;var b=c&&a!==c&&c.getComputedStyle?c.getComputedStyle(a,null):a.currentStyle||a.style;if(!b&&Sys.Browser.agent===Sys.Browser.Safari&&a.style){var g=a.style.display,f=a.style.position;a.style.position="absolute";a.style.display="block";var e=c.getComputedStyle(a,null);a.style.display=g;a.style.position=f;b={};for(var d in e)b[d]=e[d];b.display="none"}return b};Sys.IContainer=function(){};Sys.IContainer.prototype={};Sys.IContainer.registerInterface("Sys.IContainer");Sys.ApplicationLoadEventArgs=function(b,a){Sys.ApplicationLoadEventArgs.initializeBase(this);this._components=b;this._isPartialLoad=a};Sys.ApplicationLoadEventArgs.prototype={get_components:function(){return this._components},get_isPartialLoad:function(){return this._isPartialLoad}};Sys.ApplicationLoadEventArgs.registerClass("Sys.ApplicationLoadEventArgs",Sys.EventArgs);Sys._Application=function(){Sys._Application.initializeBase(this);this._disposableObjects=[];this._components={};this._createdComponents=[];this._secondPassComponents=[];this._unloadHandlerDelegate=Function.createDelegate(this,this._unloadHandler);Sys.UI.DomEvent.addHandler(window,"unload",this._unloadHandlerDelegate);this._domReady()};Sys._Application.prototype={_creatingComponents:false,_disposing:false,_deleteCount:0,get_isCreatingComponents:function(){return this._creatingComponents},get_isDisposing:function(){return this._disposing},add_init:function(a){if(this._initialized)a(this,Sys.EventArgs.Empty);else this.get_events().addHandler("init",a)},remove_init:function(a){this.get_events().removeHandler("init",a)},add_load:function(a){this.get_events().addHandler("load",a)},remove_load:function(a){this.get_events().removeHandler("load",a)},add_unload:function(a){this.get_events().addHandler("unload",a)},remove_unload:function(a){this.get_events().removeHandler("unload",a)},addComponent:function(a){this._components[a.get_id()]=a},beginCreateComponents:function(){this._creatingComponents=true},dispose:function(){if(!this._disposing){this._disposing=true;if(this._timerCookie){window.clearTimeout(this._timerCookie);delete this._timerCookie}if(this._endRequestHandler){Sys.WebForms.PageRequestManager.getInstance().remove_endRequest(this._endRequestHandler);delete this._endRequestHandler}if(this._beginRequestHandler){Sys.WebForms.PageRequestManager.getInstance().remove_beginRequest(this._beginRequestHandler);delete this._beginRequestHandler}if(window.pageUnload)window.pageUnload(this,Sys.EventArgs.Empty);var c=this.get_events().getHandler("unload");if(c)c(this,Sys.EventArgs.Empty);var b=Array.clone(this._disposableObjects);for(var a=0,f=b.length;a=0;b--){var d=i[b],f=d.dispose;if(f&&typeof f==="function")d.dispose();else{var e=d.control;if(e&&typeof e.dispose==="function")e.dispose()}var a=d._behaviors;if(a)this._disposeComponents(a);a=d._components;if(a){this._disposeComponents(a);d._components=null}}if(!j){var f=c.dispose;if(f&&typeof f==="function")c.dispose();else{var e=c.control;if(e&&typeof e.dispose==="function")e.dispose()}var a=c._behaviors;if(a)this._disposeComponents(a);a=c._components;if(a){this._disposeComponents(a);c._components=null}}}},endCreateComponents:function(){var b=this._secondPassComponents;for(var a=0,d=b.length;a1000){var c=[];for(var d=0,f=b.length;d=0;b--){var c=a[b];if(typeof c.dispose==="function")c.dispose()}},_domReady:function(){var a,g,f=this;function b(){f.initialize()}var c=function(){Sys.UI.DomEvent.removeHandler(window,"load",c);b()};Sys.UI.DomEvent.addHandler(window,"load",c);if(document.addEventListener)try{document.addEventListener("DOMContentLoaded",a=function(){document.removeEventListener("DOMContentLoaded",a,false);b()},false)}catch(h){}else if(document.attachEvent)if(window==window.top&&document.documentElement.doScroll){var e,d=document.createElement("div");a=function(){try{d.doScroll("left")}catch(c){e=window.setTimeout(a,0);return}d=null;b()};a()}else document.attachEvent("onreadystatechange",a=function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",a);b()}})},_raiseInit:function(){var a=this.get_events().getHandler("init");if(a){this.beginCreateComponents();a(this,Sys.EventArgs.Empty);this.endCreateComponents()}},_unloadHandler:function(){this.dispose()}};Sys._Application.registerClass("Sys._Application",Sys.Component,Sys.IContainer);Sys.Application=new Sys._Application;var $find=Sys.Application.findComponent;Sys.UI.Behavior=function(b){Sys.UI.Behavior.initializeBase(this);this._element=b;var a=b._behaviors;if(!a)b._behaviors=[this];else a[a.length]=this};Sys.UI.Behavior.prototype={_name:null,get_element:function(){return this._element},get_id:function(){var a=Sys.UI.Behavior.callBaseMethod(this,"get_id");if(a)return a;if(!this._element||!this._element.id)return "";return this._element.id+"$"+this.get_name()},get_name:function(){if(this._name)return this._name;var a=Object.getTypeName(this),b=a.lastIndexOf(".");if(b!==-1)a=a.substr(b+1);if(!this.get_isInitialized())this._name=a;return a},set_name:function(a){this._name=a},initialize:function(){Sys.UI.Behavior.callBaseMethod(this,"initialize");var a=this.get_name();if(a)this._element[a]=this},dispose:function(){Sys.UI.Behavior.callBaseMethod(this,"dispose");var a=this._element;if(a){var c=this.get_name();if(c)a[c]=null;var b=a._behaviors;Array.remove(b,this);if(b.length===0)a._behaviors=null;delete this._element}}};Sys.UI.Behavior.registerClass("Sys.UI.Behavior",Sys.Component);Sys.UI.Behavior.getBehaviorByName=function(b,c){var a=b[c];return a&&Sys.UI.Behavior.isInstanceOfType(a)?a:null};Sys.UI.Behavior.getBehaviors=function(a){if(!a._behaviors)return [];return Array.clone(a._behaviors)};Sys.UI.Behavior.getBehaviorsByType=function(d,e){var a=d._behaviors,c=[];if(a)for(var b=0,f=a.length;b0){var d=[];for(var c=0;c=d)break;a=Function._validateParameter(g[b],f,h);if(a){a.popStackFrame();return a}}return null};Function._validateParameterCount=function(j,d,i){var a,c,b=d.length,e=j.length;if(eb){c=true;for(a=0;a0&&(d=0};Array.dequeue=function(a){return a.shift()};Array.forEach=function(b,e,d){for(var a=0,f=b.length;a=0)b.splice(a,1);return a>=0};Array.removeAt=function(a,b){a.splice(b,1)};Sys._indexOf=function(d,e,a){if(typeof e==="undefined")return -1;var c=d.length;if(c!==0){a=a-0;if(isNaN(a))a=0;else{if(isFinite(a))a=a-a%1;if(a<0)a=Math.max(0,c+a)}for(var b=a;b-1){Sys.Browser.agent=Sys.Browser.InternetExplorer;Sys.Browser.version=parseFloat(navigator.userAgent.match(/MSIE (\d+\.\d+)/)[1]);if(Sys.Browser.version>=8)if(document.documentMode>=7)Sys.Browser.documentMode=document.documentMode;Sys.Browser.hasDebuggerStatement=true}else if(navigator.userAgent.indexOf(" Firefox/")>-1){Sys.Browser.agent=Sys.Browser.Firefox;Sys.Browser.version=parseFloat(navigator.userAgent.match(/Firefox\/(\d+\.\d+)/)[1]);Sys.Browser.name="Firefox";Sys.Browser.hasDebuggerStatement=true}else if(navigator.userAgent.indexOf(" AppleWebKit/")>-1){Sys.Browser.agent=Sys.Browser.Safari;Sys.Browser.version=parseFloat(navigator.userAgent.match(/AppleWebKit\/(\d+(\.\d+)?)/)[1]);Sys.Browser.name="Safari"}else if(navigator.userAgent.indexOf("Opera/")>-1)Sys.Browser.agent=Sys.Browser.Opera;Sys.EventArgs=function(){};Sys.EventArgs.registerClass("Sys.EventArgs");Sys.EventArgs.Empty=new Sys.EventArgs;Sys.CancelEventArgs=function(){Sys.CancelEventArgs.initializeBase(this);this._cancel=false};Sys.CancelEventArgs.prototype={get_cancel:function(){return this._cancel},set_cancel:function(a){this._cancel=a}};Sys.CancelEventArgs.registerClass("Sys.CancelEventArgs",Sys.EventArgs);Sys.EventHandlerList=function(){this._list={}};Sys.EventHandlerList.prototype={_addHandler:function(b,a){Array.add(this._getEvent(b,true),a)},addHandler:function(b,a){this._addHandler(b,a)},_removeHandler:function(c,b){var a=this._getEvent(c);if(!a)return;Array.remove(a,b)},removeHandler:function(b,a){this._removeHandler(b,a)},getHandler:function(b){var a=this._getEvent(b);if(!a||a.length===0)return null;a=Array.clone(a);return function(c,d){for(var b=0,e=a.length;b=0;d--){var k=h[d].trim();b=a[k];if(typeof b!=="number")throw Error.argument("value",String.format(Sys.Res.enumInvalidValue,c.split(",")[d].trim(),this.__typeName));j|=b}return j}}function Sys$Enum$toString(c){if(typeof c==="undefined"||c===null)return this.__string;var d=this.prototype,a;if(!this.__flags||c===0){for(a in d)if(d[a]===c)return a}else{var b=this.__sortedValues;if(!b){b=[];for(a in d)b[b.length]={key:a,value:d[a]};b.sort(function(a,b){return a.value-b.value});this.__sortedValues=b}var e=[],g=c;for(a=b.length-1;a>=0;a--){var h=b[a],f=h.value;if(f===0)continue;if((f&c)===f){e[e.length]=h.key;g-=f;if(g===0)break}}if(e.length&&g===0)return e.reverse().join(", ")}return ""}Type.prototype.registerEnum=function(b,c){Sys.__upperCaseTypes[b.toUpperCase()]=this;for(var a in this.prototype)this[a]=this.prototype[a];this.__typeName=b;this.parse=Sys$Enum$parse;this.__string=this.toString();this.toString=Sys$Enum$toString;this.__flags=c;this.__enum=true};Type.isEnum=function(a){if(typeof a==="undefined"||a===null)return false;return !!a.__enum};Type.isFlags=function(a){if(typeof a==="undefined"||a===null)return false;return !!a.__flags};Sys.CollectionChange=function(e,a,c,b,d){this.action=e;if(a)if(!(a instanceof Array))a=[a];this.newItems=a||null;if(typeof c!=="number")c=-1;this.newStartingIndex=c;if(b)if(!(b instanceof Array))b=[b];this.oldItems=b||null;if(typeof d!=="number")d=-1;this.oldStartingIndex=d};Sys.CollectionChange.registerClass("Sys.CollectionChange");Sys.NotifyCollectionChangedAction=function(){throw Error.notImplemented()};Sys.NotifyCollectionChangedAction.prototype={add:0,remove:1,reset:2};Sys.NotifyCollectionChangedAction.registerEnum("Sys.NotifyCollectionChangedAction");Sys.NotifyCollectionChangedEventArgs=function(a){this._changes=a;Sys.NotifyCollectionChangedEventArgs.initializeBase(this)};Sys.NotifyCollectionChangedEventArgs.prototype={get_changes:function(){return this._changes||[]}};Sys.NotifyCollectionChangedEventArgs.registerClass("Sys.NotifyCollectionChangedEventArgs",Sys.EventArgs);Sys.INotifyPropertyChange=function(){};Sys.INotifyPropertyChange.prototype={};Sys.INotifyPropertyChange.registerInterface("Sys.INotifyPropertyChange");Sys.PropertyChangedEventArgs=function(a){Sys.PropertyChangedEventArgs.initializeBase(this);this._propertyName=a};Sys.PropertyChangedEventArgs.prototype={get_propertyName:function(){return this._propertyName}};Sys.PropertyChangedEventArgs.registerClass("Sys.PropertyChangedEventArgs",Sys.EventArgs);Sys.Observer=function(){};Sys.Observer.registerClass("Sys.Observer");Sys.Observer.makeObservable=function(a){var c=a instanceof Array,b=Sys.Observer;if(a.setValue===b._observeMethods.setValue)return a;b._addMethods(a,b._observeMethods);if(c)b._addMethods(a,b._arrayMethods);return a};Sys.Observer._addMethods=function(c,b){for(var a in b)c[a]=b[a]};Sys.Observer._addEventHandler=function(c,a,b){Sys.Observer._getContext(c,true).events._addHandler(a,b)};Sys.Observer.addEventHandler=function(c,a,b){Sys.Observer._addEventHandler(c,a,b)};Sys.Observer._removeEventHandler=function(c,a,b){Sys.Observer._getContext(c,true).events._removeHandler(a,b)};Sys.Observer.removeEventHandler=function(c,a,b){Sys.Observer._removeEventHandler(c,a,b)};Sys.Observer.raiseEvent=function(b,e,d){var c=Sys.Observer._getContext(b);if(!c)return;var a=c.events.getHandler(e);if(a)a(b,d)};Sys.Observer.addPropertyChanged=function(b,a){Sys.Observer._addEventHandler(b,"propertyChanged",a)};Sys.Observer.removePropertyChanged=function(b,a){Sys.Observer._removeEventHandler(b,"propertyChanged",a)};Sys.Observer.beginUpdate=function(a){Sys.Observer._getContext(a,true).updating=true};Sys.Observer.endUpdate=function(b){var a=Sys.Observer._getContext(b);if(!a||!a.updating)return;a.updating=false;var d=a.dirty;a.dirty=false;if(d){if(b instanceof Array){var c=a.changes;a.changes=null;Sys.Observer.raiseCollectionChanged(b,c)}Sys.Observer.raisePropertyChanged(b,"")}};Sys.Observer.isUpdating=function(b){var a=Sys.Observer._getContext(b);return a?a.updating:false};Sys.Observer._setValue=function(a,j,g){var b,f,k=a,d=j.split(".");for(var i=0,m=d.length-1;i-1&&ac.Calendar.TwoDigitYearMax)a-=100}return a};Date._getEra=function(e,c){if(!c)return 0;var b,d=e.getTime();for(var a=0,f=c.length;a=b)return a}return 0};Date._getEraYear=function(d,b,e,c){var a=d.getFullYear();if(!c&&b.eras)a-=b.eras[e+3];return a};Date._getParseRegExp=function(b,e){if(!b._parseRegExp)b._parseRegExp={};else if(b._parseRegExp[e])return b._parseRegExp[e];var c=Date._expandFormat(b,e);c=c.replace(/([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g,"\\\\$1");var a=new Sys.StringBuilder("^"),j=[],f=0,i=0,h=Date._getTokenRegExp(),d;while((d=h.exec(c))!==null){var l=c.slice(f,d.index);f=h.lastIndex;i+=Date._appendPreOrPostMatch(l,a);if(i%2===1){a.append(d[0]);continue}switch(d[0]){case "dddd":case "ddd":case "MMMM":case "MMM":case "gg":case "g":a.append("(\\D+)");break;case "tt":case "t":a.append("(\\D*)");break;case "yyyy":a.append("(\\d{4})");break;case "fff":a.append("(\\d{3})");break;case "ff":a.append("(\\d{2})");break;case "f":a.append("(\\d)");break;case "dd":case "d":case "MM":case "M":case "yy":case "y":case "HH":case "H":case "hh":case "h":case "mm":case "m":case "ss":case "s":a.append("(\\d\\d?)");break;case "zzz":a.append("([+-]?\\d\\d?:\\d{2})");break;case "zz":case "z":a.append("([+-]?\\d\\d?)");break;case "/":a.append("(\\"+b.DateSeparator+")")}Array.add(j,d[0])}Date._appendPreOrPostMatch(c.slice(f),a);a.append("$");var k=a.toString().replace(/\s+/g,"\\s+"),g={"regExp":k,"groups":j};b._parseRegExp[e]=g;return g};Date._getTokenRegExp=function(){return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g};Date.parseLocale=function(a){return Date._parse(a,Sys.CultureInfo.CurrentCulture,arguments)};Date.parseInvariant=function(a){return Date._parse(a,Sys.CultureInfo.InvariantCulture,arguments)};Date._parse=function(h,d,i){var a,c,b,f,e,g=false;for(a=1,c=i.length;a31)return null;break;case "MMMM":c=k._getMonthIndex(a);if(c<0||c>11)return null;break;case "MMM":c=k._getAbbrMonthIndex(a);if(c<0||c>11)return null;break;case "M":case "MM":c=parseInt(a,10)-1;if(c<0||c>11)return null;break;case "y":case "yy":e=Date._expandYear(g,parseInt(a,10));if(e<0||e>9999)return null;break;case "yyyy":e=parseInt(a,10);if(e<0||e>9999)return null;break;case "h":case "hh":d=parseInt(a,10);if(d===12)d=0;if(d<0||d>11)return null;break;case "H":case "HH":d=parseInt(a,10);if(d<0||d>23)return null;break;case "m":case "mm":p=parseInt(a,10);if(p<0||p>59)return null;break;case "s":case "ss":q=parseInt(a,10);if(q<0||q>59)return null;break;case "tt":case "t":var z=a.toUpperCase();v=z===g.PMDesignator.toUpperCase();if(!v&&z!==g.AMDesignator.toUpperCase())return null;break;case "f":f=parseInt(a,10)*100;if(f<0||f>999)return null;break;case "ff":f=parseInt(a,10)*10;if(f<0||f>999)return null;break;case "fff":f=parseInt(a,10);if(f<0||f>999)return null;break;case "dddd":i=k._getDayIndex(a);if(i<0||i>6)return null;break;case "ddd":i=k._getAbbrDayIndex(a);if(i<0||i>6)return null;break;case "zzz":var u=a.split(/:/);if(u.length!==2)return null;h=parseInt(u[0],10);if(h<-12||h>13)return null;var m=parseInt(u[1],10);if(m<0||m>59)return null;l=h*60+(a.startsWith("-")?-m:m);break;case "z":case "zz":h=parseInt(a,10);if(h<-12||h>13)return null;l=h*60;break;case "g":case "gg":var o=a;if(!o||!g.eras)return null;o=o.toLowerCase().trim();for(var r=0,F=g.eras.length;r0)return this.toLocaleString();else return this.toString();var o=["n %","n%","%n"],n=["-n %","-n%","-%n"],p=["(n)","-n","- n","n-","n -"],m=["$n","n$","$ n","n $"],l=["($n)","-$n","$-n","$n-","(n$)","-n$","n-$","n$-","-n $","-$ n","n $-","$ n-","$ -n","n- $","($ n)","(n $)"];function g(a,c,d){for(var b=a.length;b1?parseInt(e[1]):0;e=b.split(".");b=e[0];a=e.length>1?e[1]:"";var q;if(c>0){a=g(a,c,false);b+=a.slice(0,c);a=a.substr(c)}else if(c<0){c=-c;b=g(b,c+1,true);a=b.slice(-c,b.length)+a;b=b.slice(0,-c)}if(i>0){if(a.length>i)a=a.slice(0,i);else a=g(a,i,false);a=p+a}else a="";var d=b.length-1,f="";while(d>=0){if(h===0||h>d)if(f.length>0)return b.slice(0,d+1)+n+f+a;else return b.slice(0,d+1)+a;if(f.length>0)f=b.slice(d-h+1,d+1)+n+f;else f=b.slice(d-h+1,d+1);d-=h;if(k1)b=parseInt(e.slice(1),10);var c;switch(e.charAt(0)){case "d":case "D":c="n";if(b!==-1)d=g(""+d,b,true);if(this<0)d=-d;break;case "c":case "C":if(this<0)c=l[a.CurrencyNegativePattern];else c=m[a.CurrencyPositivePattern];if(b===-1)b=a.CurrencyDecimalDigits;d=i(Math.abs(this),b,a.CurrencyGroupSizes,a.CurrencyGroupSeparator,a.CurrencyDecimalSeparator);break;case "n":case "N":if(this<0)c=p[a.NumberNegativePattern];else c="n";if(b===-1)b=a.NumberDecimalDigits;d=i(Math.abs(this),b,a.NumberGroupSizes,a.NumberGroupSeparator,a.NumberDecimalSeparator);break;case "p":case "P":if(this<0)c=n[a.PercentNegativePattern];else c=o[a.PercentPositivePattern];if(b===-1)b=a.PercentDecimalDigits;d=i(Math.abs(this)*100,b,a.PercentGroupSizes,a.PercentGroupSeparator,a.PercentDecimalSeparator);break;default:throw Error.format(Sys.Res.formatBadFormatSpecifier)}var k=/n|\$|-|%/g,f="";for(;true;){var q=k.lastIndex,h=k.exec(c);f+=c.slice(q,h?h.index:c.length);if(!h)break;switch(h[0]){case "n":f+=d;break;case "$":f+=a.CurrencySymbol;break;case "-":if(/[1-9]/.test(d))f+=a.NegativeSign;break;case "%":f+=a.PercentSymbol}}return f};Sys.CultureInfo=function(c,b,a){this.name=c;this.numberFormat=b;this.dateTimeFormat=a};Sys.CultureInfo.prototype={_getDateTimeFormats:function(){if(!this._dateTimeFormats){var a=this.dateTimeFormat;this._dateTimeFormats=[a.MonthDayPattern,a.YearMonthPattern,a.ShortDatePattern,a.ShortTimePattern,a.LongDatePattern,a.LongTimePattern,a.FullDateTimePattern,a.RFC1123Pattern,a.SortableDateTimePattern,a.UniversalSortableDateTimePattern]}return this._dateTimeFormats},_getIndex:function(c,d,e){var b=this._toUpper(c),a=Array.indexOf(d,b);if(a===-1)a=Array.indexOf(e,b);return a},_getMonthIndex:function(a){if(!this._upperMonths){this._upperMonths=this._toUpperArray(this.dateTimeFormat.MonthNames);this._upperMonthsGenitive=this._toUpperArray(this.dateTimeFormat.MonthGenitiveNames)}return this._getIndex(a,this._upperMonths,this._upperMonthsGenitive)},_getAbbrMonthIndex:function(a){if(!this._upperAbbrMonths){this._upperAbbrMonths=this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthNames);this._upperAbbrMonthsGenitive=this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthGenitiveNames)}return this._getIndex(a,this._upperAbbrMonths,this._upperAbbrMonthsGenitive)},_getDayIndex:function(a){if(!this._upperDays)this._upperDays=this._toUpperArray(this.dateTimeFormat.DayNames);return Array.indexOf(this._upperDays,this._toUpper(a))},_getAbbrDayIndex:function(a){if(!this._upperAbbrDays)this._upperAbbrDays=this._toUpperArray(this.dateTimeFormat.AbbreviatedDayNames);return Array.indexOf(this._upperAbbrDays,this._toUpper(a))},_toUpperArray:function(c){var b=[];for(var a=0,d=c.length;a0&&a.charAt(0)==="#")a=a.substring(1);return a};Sys._Application.prototype.get_enableHistory=function(){return this._enableHistory};Sys._Application.prototype.set_enableHistory=function(a){this._enableHistory=a};Sys._Application.prototype.add_navigate=function(a){this.get_events().addHandler("navigate",a)};Sys._Application.prototype.remove_navigate=function(a){this.get_events().removeHandler("navigate",a)};Sys._Application.prototype.addHistoryPoint=function(c,f){this._ensureHistory();var b=this._state;for(var a in c){var d=c[a];if(d===null){if(typeof b[a]!=="undefined")delete b[a]}else b[a]=d}var e=this._serializeState(b);this._historyPointIsNew=true;this._setState(e,f);this._raiseNavigate()};Sys._Application.prototype.setServerId=function(a,b){this._clientId=a;this._uniqueId=b};Sys._Application.prototype.setServerState=function(a){this._ensureHistory();this._state.__s=a;this._updateHiddenField(a)};Sys._Application.prototype._deserializeState=function(a){var e={};a=a||"";var b=a.indexOf("&&");if(b!==-1&&b+27){var e=document.title;document.title=c;this._setState(a);document.title=e}else this._setState(a);this._raiseNavigate()}else{this._setState(a);this._raiseNavigate()}}};Sys._Application.prototype._raiseNavigate=function(){var d=this._historyPointIsNew,c=this.get_events().getHandler("navigate"),b={};for(var a in this._state)if(a!=="__s")b[a]=this._state[a];var e=new Sys.HistoryEventArgs(b);if(c)c(this,e);if(!d){var f;try{if(Sys.Browser.agent===Sys.Browser.Firefox&&window.location.hash&&(!window.frameElement||window.top.location.hash))Sys.Browser.version<3.5?window.history.go(0):(location.hash=this.get_stateString())}catch(g){}}};Sys._Application.prototype._serializeState=function(d){var b=[];for(var a in d){var e=d[a];if(a==="__s")var c=e;else b[b.length]=a+"="+encodeURIComponent(e)}return b.join("&")+(c?"&&"+c:"")};Sys._Application.prototype._setState=function(a,b){if(this._enableHistory){a=a||"";if(a!==this._currentEntry){if(window.theForm){var d=window.theForm.action,e=d.indexOf("#");window.theForm.action=(e!==-1?d.substring(0,e):d)+"#"+a}if(this._historyFrame&&this._historyPointIsNew){var f=document.createElement("div");f.appendChild(document.createTextNode(b||document.title));var g=f.innerHTML;this._ignoreIFrame=true;var c=this._historyFrame.contentWindow.document;c.open("javascript:''");c.write(""+g+"parent.Sys.Application._onIFrameLoad('+Sys.Serialization.JavaScriptSerializer.serialize(a)+");");c.close()}this._ignoreTimer=false;this._currentEntry=a;if(this._historyFrame||this._historyPointIsNew){var h=this.get_stateString();if(a!==h){window.location.hash=a;this._currentEntry=this.get_stateString();if(typeof b!=="undefined"&&b!==null)document.title=b}}this._historyPointIsNew=false}}};Sys._Application.prototype._updateHiddenField=function(b){if(this._clientId){var a=document.getElementById(this._clientId);if(a)a.value=b}}; diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxNetwork.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxNetwork.js deleted file mode 100644 index b5ac8fb0e..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxNetwork.js +++ /dev/null @@ -1,6 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/MicrosoftAjaxNetwork.js -//---------------------------------------------------------- -// Copyright (C) Microsoft Corporation. All rights reserved. -//---------------------------------------------------------- -// MicrosoftAjaxNetwork.js -Type._registerScript("MicrosoftAjaxNetwork.js",["MicrosoftAjaxSerialization.js"]);if(!window.XMLHttpRequest)window.XMLHttpRequest=function(){var b=["Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP"];for(var a=0,c=b.length;a0)this._timer=window.setTimeout(Function.createDelegate(this,this._onTimeout),d);this._xmlHttpRequest.send(c);this._started=true},getResponseHeader:function(b){var a;try{a=this._xmlHttpRequest.getResponseHeader(b)}catch(c){}if(!a)a="";return a},getAllResponseHeaders:function(){return this._xmlHttpRequest.getAllResponseHeaders()},get_responseData:function(){return this._xmlHttpRequest.responseText},get_statusCode:function(){var a=0;try{a=this._xmlHttpRequest.status}catch(b){}return a},get_statusText:function(){return this._xmlHttpRequest.statusText},get_xml:function(){var a=this._xmlHttpRequest.responseXML;if(!a||!a.documentElement){a=Sys.Net.XMLDOM(this._xmlHttpRequest.responseText);if(!a||!a.documentElement)return null}else if(navigator.userAgent.indexOf("MSIE")!==-1&&typeof a.setProperty!="undefined")a.setProperty("SelectionLanguage","XPath");if(a.documentElement.namespaceURI==="http://www.mozilla.org/newlayout/xml/parsererror.xml"&&a.documentElement.tagName==="parsererror")return null;if(a.documentElement.firstChild&&a.documentElement.firstChild.tagName==="parsererror")return null;return a},abort:function(){if(this._aborted||this._responseAvailable||this._timedOut)return;this._aborted=true;this._clearTimer();if(this._xmlHttpRequest&&!this._responseAvailable){this._xmlHttpRequest.onreadystatechange=Function.emptyMethod;this._xmlHttpRequest.abort();this._xmlHttpRequest=null;this._webRequest.completed(Sys.EventArgs.Empty)}}};Sys.Net.XMLHttpExecutor.registerClass("Sys.Net.XMLHttpExecutor",Sys.Net.WebRequestExecutor);Sys.Net._WebRequestManager=function(){this._defaultTimeout=0;this._defaultExecutorType="Sys.Net.XMLHttpExecutor"};Sys.Net._WebRequestManager.prototype={add_invokingRequest:function(a){this._get_eventHandlerList().addHandler("invokingRequest",a)},remove_invokingRequest:function(a){this._get_eventHandlerList().removeHandler("invokingRequest",a)},add_completedRequest:function(a){this._get_eventHandlerList().addHandler("completedRequest",a)},remove_completedRequest:function(a){this._get_eventHandlerList().removeHandler("completedRequest",a)},_get_eventHandlerList:function(){if(!this._events)this._events=new Sys.EventHandlerList;return this._events},get_defaultTimeout:function(){return this._defaultTimeout},set_defaultTimeout:function(a){this._defaultTimeout=a},get_defaultExecutorType:function(){return this._defaultExecutorType},set_defaultExecutorType:function(a){this._defaultExecutorType=a},executeRequest:function(webRequest){var executor=webRequest.get_executor();if(!executor){var failed=false;try{var executorType=eval(this._defaultExecutorType);executor=new executorType}catch(a){failed=true}webRequest.set_executor(executor)}if(executor.get_aborted())return;var evArgs=new Sys.Net.NetworkRequestEventArgs(webRequest),handler=this._get_eventHandlerList().getHandler("invokingRequest");if(handler)handler(this,evArgs);if(!evArgs.get_cancel())executor.executeRequest()}};Sys.Net._WebRequestManager.registerClass("Sys.Net._WebRequestManager");Sys.Net.WebRequestManager=new Sys.Net._WebRequestManager;Sys.Net.NetworkRequestEventArgs=function(a){Sys.Net.NetworkRequestEventArgs.initializeBase(this);this._webRequest=a};Sys.Net.NetworkRequestEventArgs.prototype={get_webRequest:function(){return this._webRequest}};Sys.Net.NetworkRequestEventArgs.registerClass("Sys.Net.NetworkRequestEventArgs",Sys.CancelEventArgs);Sys.Net.WebRequest=function(){this._url="";this._headers={};this._body=null;this._userContext=null;this._httpVerb=null;this._executor=null;this._invokeCalled=false;this._timeout=0};Sys.Net.WebRequest.prototype={add_completed:function(a){this._get_eventHandlerList().addHandler("completed",a)},remove_completed:function(a){this._get_eventHandlerList().removeHandler("completed",a)},completed:function(b){var a=Sys.Net.WebRequestManager._get_eventHandlerList().getHandler("completedRequest");if(a)a(this._executor,b);a=this._get_eventHandlerList().getHandler("completed");if(a)a(this._executor,b)},_get_eventHandlerList:function(){if(!this._events)this._events=new Sys.EventHandlerList;return this._events},get_url:function(){return this._url},set_url:function(a){this._url=a},get_headers:function(){return this._headers},get_httpVerb:function(){if(this._httpVerb===null){if(this._body===null)return "GET";return "POST"}return this._httpVerb},set_httpVerb:function(a){this._httpVerb=a},get_body:function(){return this._body},set_body:function(a){this._body=a},get_userContext:function(){return this._userContext},set_userContext:function(a){this._userContext=a},get_executor:function(){return this._executor},set_executor:function(a){this._executor=a;this._executor._set_webRequest(this)},get_timeout:function(){if(this._timeout===0)return Sys.Net.WebRequestManager.get_defaultTimeout();return this._timeout},set_timeout:function(a){this._timeout=a},getResolvedUrl:function(){return Sys.Net.WebRequest._resolveUrl(this._url)},invoke:function(){Sys.Net.WebRequestManager.executeRequest(this);this._invokeCalled=true}};Sys.Net.WebRequest._resolveUrl=function(b,a){if(b&&b.indexOf("://")!==-1)return b;if(!a||a.length===0){var d=document.getElementsByTagName("base")[0];if(d&&d.href&&d.href.length>0)a=d.href;else a=document.URL}var c=a.indexOf("?");if(c!==-1)a=a.substr(0,c);c=a.indexOf("#");if(c!==-1)a=a.substr(0,c);a=a.substr(0,a.lastIndexOf("/")+1);if(!b||b.length===0)return a;if(b.charAt(0)==="/"){var e=a.indexOf("://"),g=a.indexOf("/",e+3);return a.substr(0,g)+b}else{var f=a.lastIndexOf("/");return a.substr(0,f+1)+b}};Sys.Net.WebRequest._createQueryString=function(c,b,f){b=b||encodeURIComponent;var h=0,e,g,d,a=new Sys.StringBuilder;if(c)for(d in c){e=c[d];if(typeof e==="function")continue;g=Sys.Serialization.JavaScriptSerializer.serialize(e);if(h++)a.append("&");a.append(d);a.append("=");a.append(b(g))}if(f){if(h)a.append("&");a.append(f)}return a.toString()};Sys.Net.WebRequest._createUrl=function(a,b,c){if(!b&&!c)return a;var d=Sys.Net.WebRequest._createQueryString(b,null,c);return d.length?a+(a&&a.indexOf("?")>=0?"&":"?")+d:a};Sys.Net.WebRequest.registerClass("Sys.Net.WebRequest");Sys._ScriptLoaderTask=function(b,a){this._scriptElement=b;this._completedCallback=a};Sys._ScriptLoaderTask.prototype={get_scriptElement:function(){return this._scriptElement},dispose:function(){if(this._disposed)return;this._disposed=true;this._removeScriptElementHandlers();Sys._ScriptLoaderTask._clearScript(this._scriptElement);this._scriptElement=null},execute:function(){if(this._ensureReadyStateLoaded())this._executeInternal()},_executeInternal:function(){this._addScriptElementHandlers();document.getElementsByTagName("head")[0].appendChild(this._scriptElement)},_ensureReadyStateLoaded:function(){if(this._useReadyState()&&this._scriptElement.readyState!=="loaded"&&this._scriptElement.readyState!=="complete"){this._scriptDownloadDelegate=Function.createDelegate(this,this._executeInternal);$addHandler(this._scriptElement,"readystatechange",this._scriptDownloadDelegate);return false}return true},_addScriptElementHandlers:function(){if(this._scriptDownloadDelegate){$removeHandler(this._scriptElement,"readystatechange",this._scriptDownloadDelegate);this._scriptDownloadDelegate=null}this._scriptLoadDelegate=Function.createDelegate(this,this._scriptLoadHandler);if(this._useReadyState())$addHandler(this._scriptElement,"readystatechange",this._scriptLoadDelegate);else $addHandler(this._scriptElement,"load",this._scriptLoadDelegate);if(this._scriptElement.addEventListener){this._scriptErrorDelegate=Function.createDelegate(this,this._scriptErrorHandler);this._scriptElement.addEventListener("error",this._scriptErrorDelegate,false)}},_removeScriptElementHandlers:function(){if(this._scriptLoadDelegate){var a=this.get_scriptElement();if(this._scriptDownloadDelegate){$removeHandler(this._scriptElement,"readystatechange",this._scriptDownloadDelegate);this._scriptDownloadDelegate=null}if(this._useReadyState()&&this._scriptLoadDelegate)$removeHandler(a,"readystatechange",this._scriptLoadDelegate);else $removeHandler(a,"load",this._scriptLoadDelegate);if(this._scriptErrorDelegate){this._scriptElement.removeEventListener("error",this._scriptErrorDelegate,false);this._scriptErrorDelegate=null}this._scriptLoadDelegate=null}},_scriptErrorHandler:function(){if(this._disposed)return;this._completedCallback(this.get_scriptElement(),false)},_scriptLoadHandler:function(){if(this._disposed)return;var a=this.get_scriptElement();if(this._useReadyState()&&a.readyState!=="complete")return;this._completedCallback(a,true)},_useReadyState:function(){return Sys.Browser.agent===Sys.Browser.InternetExplorer&&(Sys.Browser.version<9||(document.documentMode||0)<9)}};Sys._ScriptLoaderTask.registerClass("Sys._ScriptLoaderTask",null,Sys.IDisposable);Sys._ScriptLoaderTask._clearScript=function(a){if(!Sys.Debug.isDebug&&a.parentNode)a.parentNode.removeChild(a)}; diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxSerialization.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxSerialization.js deleted file mode 100644 index f8f13d844..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MSAjax/MicrosoftAjaxSerialization.js +++ /dev/null @@ -1,6 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/MicrosoftAjaxSerialization.js -//---------------------------------------------------------- -// Copyright (C) Microsoft Corporation. All rights reserved. -//---------------------------------------------------------- -// MicrosoftAjaxSerialization.js -Type._registerScript("MicrosoftAjaxSerialization.js",["MicrosoftAjaxCore.js"]);Type.registerNamespace("Sys.Serialization");Sys.Serialization.JavaScriptSerializer=function(){};Sys.Serialization.JavaScriptSerializer.registerClass("Sys.Serialization.JavaScriptSerializer");Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs=[];Sys.Serialization.JavaScriptSerializer._charsToEscape=[];Sys.Serialization.JavaScriptSerializer._dateRegEx=new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)(?:[a-zA-Z]|(?:\\+|-)[0-9]{4})?\\)\\\\/\\"',"g");Sys.Serialization.JavaScriptSerializer._escapeChars={};Sys.Serialization.JavaScriptSerializer._escapeRegEx=new RegExp('["\\\\\\x00-\\x1F]',"i");Sys.Serialization.JavaScriptSerializer._escapeRegExGlobal=new RegExp('["\\\\\\x00-\\x1F]',"g");Sys.Serialization.JavaScriptSerializer._jsonRegEx=new RegExp("[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]","g");Sys.Serialization.JavaScriptSerializer._jsonStringRegEx=new RegExp('"(\\\\.|[^"\\\\])*"',"g");Sys.Serialization.JavaScriptSerializer._serverTypeFieldName="__type";Sys.Serialization.JavaScriptSerializer._init=function(){var c=["\\u0000","\\u0001","\\u0002","\\u0003","\\u0004","\\u0005","\\u0006","\\u0007","\\b","\\t","\\n","\\u000b","\\f","\\r","\\u000e","\\u000f","\\u0010","\\u0011","\\u0012","\\u0013","\\u0014","\\u0015","\\u0016","\\u0017","\\u0018","\\u0019","\\u001a","\\u001b","\\u001c","\\u001d","\\u001e","\\u001f"];Sys.Serialization.JavaScriptSerializer._charsToEscape[0]="\\";Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs["\\"]=new RegExp("\\\\","g");Sys.Serialization.JavaScriptSerializer._escapeChars["\\"]="\\\\";Sys.Serialization.JavaScriptSerializer._charsToEscape[1]='"';Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs['"']=new RegExp('"',"g");Sys.Serialization.JavaScriptSerializer._escapeChars['"']='\\"';for(var a=0;a<32;a++){var b=String.fromCharCode(a);Sys.Serialization.JavaScriptSerializer._charsToEscape[a+2]=b;Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs[b]=new RegExp(b,"g");Sys.Serialization.JavaScriptSerializer._escapeChars[b]=c[a]}};Sys.Serialization.JavaScriptSerializer._serializeBooleanWithBuilder=function(b,a){a.append(b.toString())};Sys.Serialization.JavaScriptSerializer._serializeNumberWithBuilder=function(a,b){if(isFinite(a))b.append(String(a));else throw Error.invalidOperation(Sys.Res.cannotSerializeNonFiniteNumbers)};Sys.Serialization.JavaScriptSerializer._serializeStringWithBuilder=function(a,c){c.append('"');if(Sys.Serialization.JavaScriptSerializer._escapeRegEx.test(a)){if(Sys.Serialization.JavaScriptSerializer._charsToEscape.length===0)Sys.Serialization.JavaScriptSerializer._init();if(a.length<128)a=a.replace(Sys.Serialization.JavaScriptSerializer._escapeRegExGlobal,function(a){return Sys.Serialization.JavaScriptSerializer._escapeChars[a]});else for(var d=0;d<34;d++){var b=Sys.Serialization.JavaScriptSerializer._charsToEscape[d];if(a.indexOf(b)!==-1)if(Sys.Browser.agent===Sys.Browser.Opera||Sys.Browser.agent===Sys.Browser.FireFox)a=a.split(b).join(Sys.Serialization.JavaScriptSerializer._escapeChars[b]);else a=a.replace(Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs[b],Sys.Serialization.JavaScriptSerializer._escapeChars[b])}}c.append(a);c.append('"')};Sys.Serialization.JavaScriptSerializer._serializeWithBuilder=function(b,a,i,g){var c;switch(typeof b){case "object":if(b)if(Number.isInstanceOfType(b))Sys.Serialization.JavaScriptSerializer._serializeNumberWithBuilder(b,a);else if(Boolean.isInstanceOfType(b))Sys.Serialization.JavaScriptSerializer._serializeBooleanWithBuilder(b,a);else if(String.isInstanceOfType(b))Sys.Serialization.JavaScriptSerializer._serializeStringWithBuilder(b,a);else if(Array.isInstanceOfType(b)){a.append("[");for(c=0;c0)a.append(",");Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(b[c],a,false,g)}a.append("]")}else{if(Date.isInstanceOfType(b)){a.append('"\\/Date(');a.append(b.getTime());a.append(')\\/"');break}var d=[],f=0;for(var e in b){if(e.startsWith("$"))continue;if(e===Sys.Serialization.JavaScriptSerializer._serverTypeFieldName&&f!==0){d[f++]=d[0];d[0]=e}else d[f++]=e}if(i)d.sort();a.append("{");var j=false;for(c=0;c0){var b=Array.dequeue(c.scriptsToLoad),f=this._scriptLoadedDelegate;if(b.fallback){var g=b.fallback;delete b.fallback;var d=this;f=function(b,a){a||function(){var a=d._createScriptElement({src:g});d._currentTask=new Sys._ScriptLoaderTask(a,d._scriptLoadedDelegate);d._currentTask.execute()}()}}var a=this._createScriptElement(b);if(a.text&&Sys.Browser.agent===Sys.Browser.Safari){a.innerHTML=a.text;delete a.text}if(typeof b.src==="string"){this._currentTask=new Sys._ScriptLoaderTask(a,f);this._currentTask.execute()}else{document.getElementsByTagName("head")[0].appendChild(a);Sys._ScriptLoaderTask._clearScript(a);this._loadScriptsInternal()}}else{this._stopSession();var e=c.allScriptsLoadedCallback;if(e)e(this);this._nextSession()}},_nextSession:function(){if(this._sessions.length===0){this._loading=false;this._currentSession=null;return}this._loading=true;var a=Array.dequeue(this._sessions);this._currentSession=a;if(a.scriptTimeout>0)this._timeoutCookie=window.setTimeout(Function.createDelegate(this,this._scriptLoadTimeoutHandler),a.scriptTimeout*1000);this._loadScriptsInternal()},_raiseError:function(){var b=this._currentSession.scriptLoadFailedCallback,a=this._currentTask.get_scriptElement();this._stopSession();if(b){b(this,a);this._nextSession()}else{this._loading=false;throw Sys._ScriptLoader._errorScriptLoadFailed(a.src)}},_scriptLoadedHandler:function(a,b){if(b){Array.add(Sys._ScriptLoader._getLoadedScripts(),a.src);this._currentTask.dispose();this._currentTask=null;this._loadScriptsInternal()}else this._raiseError()},_scriptLoadTimeoutHandler:function(){var a=this._currentSession.scriptLoadTimeoutCallback;this._stopSession();if(a)a(this);this._nextSession()},_stopSession:function(){if(this._timeoutCookie){window.clearTimeout(this._timeoutCookie);this._timeoutCookie=null}if(this._currentTask){this._currentTask.dispose();this._currentTask=null}}};Sys._ScriptLoader.registerClass("Sys._ScriptLoader",null,Sys.IDisposable);Sys._ScriptLoader.getInstance=function(){var a=Sys._ScriptLoader._activeInstance;if(!a)a=Sys._ScriptLoader._activeInstance=new Sys._ScriptLoader;return a};Sys._ScriptLoader.isScriptLoaded=function(b){var a=document.createElement("script");a.src=b;return Array.contains(Sys._ScriptLoader._getLoadedScripts(),a.src)};Sys._ScriptLoader.readLoadedScripts=function(){if(!Sys._ScriptLoader._referencedScripts){var c=Sys._ScriptLoader._referencedScripts=[],d=document.getElementsByTagName("script");for(var b=d.length-1;b>=0;b--){var e=d[b],a=e.src;if(a.length)if(!Array.contains(c,a))Array.add(c,a)}}};Sys._ScriptLoader._errorScriptLoadFailed=function(b){var a;a=Sys.Res.scriptLoadFailed;var d="Sys.ScriptLoadFailedException: "+String.format(a,b),c=Error.create(d,{name:"Sys.ScriptLoadFailedException","scriptUrl":b});c.popStackFrame();return c};Sys._ScriptLoader._getLoadedScripts=function(){if(!Sys._ScriptLoader._referencedScripts){Sys._ScriptLoader._referencedScripts=[];Sys._ScriptLoader.readLoadedScripts()}return Sys._ScriptLoader._referencedScripts};Sys.WebForms.PageRequestManager=function(){this._form=null;this._activeDefaultButton=null;this._activeDefaultButtonClicked=false;this._updatePanelIDs=null;this._updatePanelClientIDs=null;this._updatePanelHasChildrenAsTriggers=null;this._asyncPostBackControlIDs=null;this._asyncPostBackControlClientIDs=null;this._postBackControlIDs=null;this._postBackControlClientIDs=null;this._scriptManagerID=null;this._pageLoadedHandler=null;this._additionalInput=null;this._onsubmit=null;this._onSubmitStatements=[];this._originalDoPostBack=null;this._originalDoPostBackWithOptions=null;this._originalFireDefaultButton=null;this._originalDoCallback=null;this._isCrossPost=false;this._postBackSettings=null;this._request=null;this._onFormSubmitHandler=null;this._onFormElementClickHandler=null;this._onWindowUnloadHandler=null;this._asyncPostBackTimeout=null;this._controlIDToFocus=null;this._scrollPosition=null;this._processingRequest=false;this._scriptDisposes={};this._transientFields=["__VIEWSTATEENCRYPTED","__VIEWSTATEFIELDCOUNT"];this._textTypes=/^(text|password|hidden|search|tel|url|email|number|range|color|datetime|date|month|week|time|datetime-local)$/i};Sys.WebForms.PageRequestManager.prototype={_get_eventHandlerList:function(){if(!this._events)this._events=new Sys.EventHandlerList;return this._events},get_isInAsyncPostBack:function(){return this._request!==null},add_beginRequest:function(a){this._get_eventHandlerList().addHandler("beginRequest",a)},remove_beginRequest:function(a){this._get_eventHandlerList().removeHandler("beginRequest",a)},add_endRequest:function(a){this._get_eventHandlerList().addHandler("endRequest",a)},remove_endRequest:function(a){this._get_eventHandlerList().removeHandler("endRequest",a)},add_initializeRequest:function(a){this._get_eventHandlerList().addHandler("initializeRequest",a)},remove_initializeRequest:function(a){this._get_eventHandlerList().removeHandler("initializeRequest",a)},add_pageLoaded:function(a){this._get_eventHandlerList().addHandler("pageLoaded",a)},remove_pageLoaded:function(a){this._get_eventHandlerList().removeHandler("pageLoaded",a)},add_pageLoading:function(a){this._get_eventHandlerList().addHandler("pageLoading",a)},remove_pageLoading:function(a){this._get_eventHandlerList().removeHandler("pageLoading",a)},abortPostBack:function(){if(!this._processingRequest&&this._request){this._request.get_executor().abort();this._request=null}},beginAsyncPostBack:function(c,a,f,d,e){if(d&&typeof Page_ClientValidate==="function"&&!Page_ClientValidate(e||null))return;this._postBackSettings=this._createPostBackSettings(true,c,a);var b=this._form;b.__EVENTTARGET.value=a||"";b.__EVENTARGUMENT.value=f||"";this._isCrossPost=false;this._additionalInput=null;this._onFormSubmit()},_cancelPendingCallbacks:function(){for(var a=0,e=window.__pendingCallbacks.length;a0)theForm.action=a.actionUrl;if(a.trackFocus){var c=theForm.elements["__LASTFOCUS"];if(typeof c!="undefined"&&c!=null)if(typeof document.activeElement=="undefined")c.value=a.eventTarget;else{var b=document.activeElement;if(typeof b!="undefined"&&b!=null)if(typeof b.id!="undefined"&&b.id!=null&&b.id.length>0)c.value=b.id;else if(typeof b.name!="undefined")c.value=b.name}}}if(a.clientSubmit)this._doPostBack(a.eventTarget,a.eventArgument)},_elementContains:function(b,a){while(a){if(a===b)return true;a=a.parentNode}return false},_endPostBack:function(a,d,f){if(this._request===d.get_webRequest()){this._processingRequest=false;this._additionalInput=null;this._request=null}var e=this._get_eventHandlerList().getHandler("endRequest"),b=false;if(e){var c=new Sys.WebForms.EndRequestEventArgs(a,f?f.dataItems:{},d);e(this,c);b=c.get_errorHandled()}if(a&&!b)throw a},_ensureUniqueIds:function(a){if(!a)return a;a=a instanceof Array?a:[a];var c=[];for(var b=0,f=a.length;b-1?this._updatePanelIDs[d]:e)}return c},_findNearestElement:function(a){while(a.length>0){var d=this._uniqueIDToClientID(a),c=document.getElementById(d);if(c)return c;var b=a.lastIndexOf("$");if(b===-1)return null;a=a.substring(0,b)}return null},_findText:function(b,a){var c=Math.max(0,a-20),d=Math.min(b.length,a+20);return b.substring(c,d)},_fireDefaultButton:function(a,d){if(a.keyCode===13){var c=a.srcElement||a.target;if(!c||c.tagName.toLowerCase()!=="textarea"){var b=document.getElementById(d);if(b&&typeof b.click!=="undefined"){this._activeDefaultButton=b;this._activeDefaultButtonClicked=false;try{b.click()}finally{this._activeDefaultButton=null}a.cancelBubble=true;if(typeof a.stopPropagation==="function")a.stopPropagation();return false}}}return true},_getPageLoadedEventArgs:function(n,c){var m=[],l=[],k=c?c.version4:false,d=c?c.updatePanelData:null,e,g,h,b;if(!d){e=this._updatePanelIDs;g=this._updatePanelClientIDs;h=null;b=null}else{e=d.updatePanelIDs;g=d.updatePanelClientIDs;h=d.childUpdatePanelIDs;b=d.panelsToRefreshIDs}var a,f,j,i;if(b)for(a=0,f=b.length;a-1))Array.add(i,document.getElementById(l[a]))}return new Sys.WebForms.PageLoadingEventArgs(j,i,f.dataItems)},_getPostBackSettings:function(a,c){var d=a,b=null;while(a){if(a.id){if(!b&&Array.contains(this._asyncPostBackControlClientIDs,a.id))b=this._createPostBackSettings(true,null,c,d);else if(!b&&Array.contains(this._postBackControlClientIDs,a.id))return this._createPostBackSettings(false);else{var e=Array.indexOf(this._updatePanelClientIDs,a.id);if(e!==-1)if(this._updatePanelHasChildrenAsTriggers[e])return this._createPostBackSettings(true,[this._updatePanelIDs[e]],c,d);else return this._createPostBackSettings(true,null,c,d)}if(!b&&this._matchesParentIDInList(a.id,this._asyncPostBackControlClientIDs))b=this._createPostBackSettings(true,null,c,d);else if(!b&&this._matchesParentIDInList(a.id,this._postBackControlClientIDs))return this._createPostBackSettings(false)}a=a.parentNode}if(!b)return this._createPostBackSettings(false);else return b},_getScrollPosition:function(){var a=document.documentElement;if(a&&(this._validPosition(a.scrollLeft)||this._validPosition(a.scrollTop)))return {x:a.scrollLeft,y:a.scrollTop};else{a=document.body;if(a&&(this._validPosition(a.scrollLeft)||this._validPosition(a.scrollTop)))return {x:a.scrollLeft,y:a.scrollTop};else if(this._validPosition(window.pageXOffset)||this._validPosition(window.pageYOffset))return {x:window.pageXOffset,y:window.pageYOffset};else return {x:0,y:0}}},_initializeInternal:function(f,g,a,b,e,c,d){if(this._prmInitialized)throw Error.invalidOperation(Sys.WebForms.Res.PRM_CannotRegisterTwice);this._prmInitialized=true;this._masterPageUniqueID=d;this._scriptManagerID=f;this._form=Sys.UI.DomElement.resolveElement(g);this._onsubmit=this._form.onsubmit;this._form.onsubmit=null;this._onFormSubmitHandler=Function.createDelegate(this,this._onFormSubmit);this._onFormElementClickHandler=Function.createDelegate(this,this._onFormElementClick);this._onWindowUnloadHandler=Function.createDelegate(this,this._onWindowUnload);Sys.UI.DomEvent.addHandler(this._form,"submit",this._onFormSubmitHandler);Sys.UI.DomEvent.addHandler(this._form,"click",this._onFormElementClickHandler);Sys.UI.DomEvent.addHandler(window,"unload",this._onWindowUnloadHandler);this._originalDoPostBack=window.__doPostBack;if(this._originalDoPostBack)window.__doPostBack=Function.createDelegate(this,this._doPostBack);this._originalDoPostBackWithOptions=window.WebForm_DoPostBackWithOptions;if(this._originalDoPostBackWithOptions)window.WebForm_DoPostBackWithOptions=Function.createDelegate(this,this._doPostBackWithOptions);this._originalFireDefaultButton=window.WebForm_FireDefaultButton;if(this._originalFireDefaultButton)window.WebForm_FireDefaultButton=Function.createDelegate(this,this._fireDefaultButton);this._originalDoCallback=window.WebForm_DoCallback;if(this._originalDoCallback)window.WebForm_DoCallback=Function.createDelegate(this,this._doCallback);this._pageLoadedHandler=Function.createDelegate(this,this._pageLoadedInitialLoad);Sys.UI.DomEvent.addHandler(window,"load",this._pageLoadedHandler);if(a)this._updateControls(a,b,e,c,true)},_matchesParentIDInList:function(c,b){for(var a=0,d=b.length;a=c.length){e=this._findText(c,c.length);break}D=c.substr(b,i);b+=i;if(c.charAt(b)!=="|"){e=this._findText(c,b);break}b++;Array.add(k,{type:E,id:F,content:D})}if(e){this._endPostBack(this._createPageRequestManagerParserError(String.format(Sys.WebForms.Res.PRM_ParserErrorDetails,e)),h,null);return null}var x=[],w=[],q=[],j=[],t=[],C=[],A=[],z=[],v=[],s=[],m,p,u,n,o,r,y,g;for(var l=0,G=k.length;l=4)a.content=unescape(a.content);if(Sys.Browser.agent===Sys.Browser.InternetExplorer){var f=document.createElement("a");f.style.display="none";f.attachEvent("onclick",B);f.href=a.content;this._form.parentNode.insertBefore(f,this._form);f.click();f.detachEvent("onclick",B);this._form.parentNode.removeChild(f);function B(a){a.cancelBubble=true}}else window.location.href=a.content;return null;case "error":this._endPostBack(this._createPageRequestManagerServerError(Number.parseInvariant(a.id),a.content),h,null);return null;case "pageTitle":document.title=a.content;break;case "focus":this._controlIDToFocus=a.content;break;default:this._endPostBack(this._createPageRequestManagerParserError(String.format(Sys.WebForms.Res.PRM_UnknownToken,a.type)),h,null);return null}}return {version4:g?parseFloat(g.content)>=4:false,executor:h,updatePanelNodes:x,hiddenFieldNodes:w,arrayDeclarationNodes:q,scriptBlockNodes:j,scriptStartupNodes:t,expandoNodes:C,onSubmitNodes:A,dataItemNodes:z,dataItemJsonNodes:v,scriptDisposeNodes:s,asyncPostBackControlIDsNode:m,postBackControlIDsNode:p,updatePanelIDsNode:u,asyncPostBackTimeoutNode:n,childUpdatePanelIDsNode:o,panelsToRefreshNode:r,formActionNode:y}},_processUpdatePanelArrays:function(e,q,r,f){var d,c,b;if(e){var i=e.length,j=f?2:1;d=new Array(i/j);c=new Array(i/j);b=new Array(i/j);for(var g=0,h=0;g0)f=window.setTimeout(v,e);k.execute();return null}var d=new Sys.Net.WebRequest;d.set_url(u);d.get_headers()["Content-Type"]="application/json; charset=utf-8";if(!m){o=Sys.Serialization.JavaScriptSerializer.serialize(l);if(o==="{}")o=""}d.set_body(o);d.add_completed(x);if(e&&e>0)d.set_timeout(e);d.invoke();function x(d){if(d.get_responseAvailable()){var f=d.get_statusCode(),c=null;try{var e=d.getResponseHeader("Content-Type");if(e.startsWith("application/json"))c=d.get_object();else if(e.startsWith("text/xml"))c=d.get_xml();else c=d.get_responseData()}catch(m){}var k=d.getResponseHeader("jsonerror"),h=k==="true";if(h){if(c)c=new Sys.Net.WebServiceError(false,c.Message,c.StackTrace,c.ExceptionType,c)}else if(e.startsWith("application/json"))c=!c||typeof c.d==="undefined"?c:c.d;if(f<200||f>=300||h){if(b){if(!c||!h)c=new Sys.Net.WebServiceError(false,String.format(Sys.Res.webServiceFailedNoMsg,a));c._statusCode=f;b(c,g,a)}}else if(j)j(c,g,a)}else{var i;if(d.get_timedOut())i=String.format(Sys.Res.webServiceTimedOut,a);else i=String.format(Sys.Res.webServiceFailedNoMsg,a);if(b)b(new Sys.Net.WebServiceError(d.get_timedOut(),i,"",""),g,a)}}return d};Sys.Net.WebServiceProxy._generateTypedConstructor=function(a){return function(b){if(b)for(var c in b)this[c]=b[c];this.__type=a}};Sys._jsonp=0;Sys.Net.WebServiceProxy._xdomain=/^\s*([a-zA-Z0-9\+\-\.]+\:)\/\/([^?#\/]+)/;Sys.Net.WebServiceError=function(d,e,c,a,b){this._timedOut=d;this._message=e;this._stackTrace=c;this._exceptionType=a;this._errorObject=b;this._statusCode=-1};Sys.Net.WebServiceError.prototype={get_timedOut:function(){return this._timedOut},get_statusCode:function(){return this._statusCode},get_message:function(){return this._message},get_stackTrace:function(){return this._stackTrace||""},get_exceptionType:function(){return this._exceptionType||""},get_errorObject:function(){return this._errorObject||null}};Sys.Net.WebServiceError.registerClass("Sys.Net.WebServiceError"); diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/Menu.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/Menu.js deleted file mode 100644 index 27a78fa02..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/Menu.js +++ /dev/null @@ -1,898 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/Menu.js -var __rootMenuItem; -var __menuInterval; -var __scrollPanel; -var __disappearAfter = 500; -function Menu_ClearInterval() { - if (__menuInterval) { - window.clearInterval(__menuInterval); - } -} -function Menu_Collapse(item) { - Menu_SetRoot(item); - if (__rootMenuItem) { - Menu_ClearInterval(); - if (__disappearAfter >= 0) { - __menuInterval = window.setInterval("Menu_HideItems()", __disappearAfter); - } - } -} -function Menu_Expand(item, horizontalOffset, verticalOffset, hideScrollers) { - Menu_ClearInterval(); - var tr = item.parentNode.parentNode.parentNode.parentNode.parentNode; - var horizontal = true; - if (!tr.id) { - horizontal = false; - tr = tr.parentNode; - } - var child = Menu_FindSubMenu(item); - if (child) { - var data = Menu_GetData(item); - if (!data) { - return null; - } - child.rel = tr.id; - child.x = horizontalOffset; - child.y = verticalOffset; - if (horizontal) child.pos = "bottom"; - PopOut_Show(child.id, hideScrollers, data); - } - Menu_SetRoot(item); - if (child) { - if (!document.body.__oldOnClick && document.body.onclick) { - document.body.__oldOnClick = document.body.onclick; - } - if (__rootMenuItem) { - document.body.onclick = Menu_HideItems; - } - } - Menu_ResetSiblings(tr); - return child; -} -function Menu_FindMenu(item) { - if (item && item.menu) return item.menu; - var tr = item.parentNode.parentNode.parentNode.parentNode.parentNode; - if (!tr.id) { - tr = tr.parentNode; - } - for (var i = tr.id.length - 1; i >= 0; i--) { - if (tr.id.charAt(i) < '0' || tr.id.charAt(i) > '9') { - var menu = WebForm_GetElementById(tr.id.substr(0, i)); - if (menu) { - item.menu = menu; - return menu; - } - } - } - return null; -} -function Menu_FindNext(item) { - var a = WebForm_GetElementByTagName(item, "A"); - var parent = Menu_FindParentContainer(item); - var first = null; - if (parent) { - var links = WebForm_GetElementsByTagName(parent, "A"); - var match = false; - for (var i = 0; i < links.length; i++) { - var link = links[i]; - if (Menu_IsSelectable(link)) { - if (Menu_FindParentContainer(link) == parent) { - if (match) { - return link; - } - else if (!first) { - first = link; - } - } - if (!match && link == a) { - match = true; - } - } - } - } - return first; -} -function Menu_FindParentContainer(item) { - if (item.menu_ParentContainerCache) return item.menu_ParentContainerCache; - var a = (item.tagName.toLowerCase() == "a") ? item : WebForm_GetElementByTagName(item, "A"); - var menu = Menu_FindMenu(a); - if (menu) { - var parent = item; - while (parent && parent.tagName && - parent.id != menu.id && - parent.tagName.toLowerCase() != "div") { - parent = parent.parentNode; - } - item.menu_ParentContainerCache = parent; - return parent; - } -} -function Menu_FindParentItem(item) { - var parentContainer = Menu_FindParentContainer(item); - var parentContainerID = parentContainer.id; - var len = parentContainerID.length; - if (parentContainerID && parentContainerID.substr(len - 5) == "Items") { - var parentItemID = parentContainerID.substr(0, len - 5); - return WebForm_GetElementById(parentItemID); - } - return null; -} -function Menu_FindPrevious(item) { - var a = WebForm_GetElementByTagName(item, "A"); - var parent = Menu_FindParentContainer(item); - var last = null; - if (parent) { - var links = WebForm_GetElementsByTagName(parent, "A"); - for (var i = 0; i < links.length; i++) { - var link = links[i]; - if (Menu_IsSelectable(link)) { - if (link == a && last) { - return last; - } - if (Menu_FindParentContainer(link) == parent) { - last = link; - } - } - } - } - return last; -} -function Menu_FindSubMenu(item) { - var tr = item.parentNode.parentNode.parentNode.parentNode.parentNode; - if (!tr.id) { - tr=tr.parentNode; - } - return WebForm_GetElementById(tr.id + "Items"); -} -function Menu_Focus(item) { - if (item && item.focus) { - var pos = WebForm_GetElementPosition(item); - var parentContainer = Menu_FindParentContainer(item); - if (!parentContainer.offset) { - parentContainer.offset = 0; - } - var posParent = WebForm_GetElementPosition(parentContainer); - var delta; - if (pos.y + pos.height > posParent.y + parentContainer.offset + parentContainer.clippedHeight) { - delta = pos.y + pos.height - posParent.y - parentContainer.offset - parentContainer.clippedHeight; - PopOut_Scroll(parentContainer, delta); - } - else if (pos.y < posParent.y + parentContainer.offset) { - delta = posParent.y + parentContainer.offset - pos.y; - PopOut_Scroll(parentContainer, -delta); - } - PopOut_HideScrollers(parentContainer); - item.focus(); - } -} -function Menu_GetData(item) { - if (!item.data) { - var a = (item.tagName.toLowerCase() == "a" ? item : WebForm_GetElementByTagName(item, "a")); - var menu = Menu_FindMenu(a); - try { - item.data = eval(menu.id + "_Data"); - } - catch(e) {} - } - return item.data; -} -function Menu_HideItems(items) { - if (document.body.__oldOnClick) { - document.body.onclick = document.body.__oldOnClick; - document.body.__oldOnClick = null; - } - Menu_ClearInterval(); - if (!items || ((typeof(items.tagName) == "undefined") && (items instanceof Event))) { - items = __rootMenuItem; - } - var table = items; - if ((typeof(table) == "undefined") || (table == null) || !table.tagName || (table.tagName.toLowerCase() != "table")) { - table = WebForm_GetElementByTagName(table, "TABLE"); - } - if ((typeof(table) == "undefined") || (table == null) || !table.tagName || (table.tagName.toLowerCase() != "table")) { - return; - } - var rows = table.rows ? table.rows : table.firstChild.rows; - var isVertical = false; - for (var r = 0; r < rows.length; r++) { - if (rows[r].id) { - isVertical = true; - break; - } - } - var i, child, nextLevel; - if (isVertical) { - for(i = 0; i < rows.length; i++) { - if (rows[i].id) { - child = WebForm_GetElementById(rows[i].id + "Items"); - if (child) { - Menu_HideItems(child); - } - } - else if (rows[i].cells[0]) { - nextLevel = WebForm_GetElementByTagName(rows[i].cells[0], "TABLE"); - if (nextLevel) { - Menu_HideItems(nextLevel); - } - } - } - } - else if (rows[0]) { - for(i = 0; i < rows[0].cells.length; i++) { - if (rows[0].cells[i].id) { - child = WebForm_GetElementById(rows[0].cells[i].id + "Items"); - if (child) { - Menu_HideItems(child); - } - } - else { - nextLevel = WebForm_GetElementByTagName(rows[0].cells[i], "TABLE"); - if (nextLevel) { - Menu_HideItems(rows[0].cells[i].firstChild); - } - } - } - } - if (items && items.id) { - PopOut_Hide(items.id); - } -} -function Menu_HoverDisabled(item) { - var node = (item.tagName.toLowerCase() == "td") ? - item: - item.cells[0]; - var data = Menu_GetData(item); - if (!data) return; - node = WebForm_GetElementByTagName(node, "table").rows[0].cells[0].childNodes[0]; - if (data.disappearAfter >= 200) { - __disappearAfter = data.disappearAfter; - } - Menu_Expand(node, data.horizontalOffset, data.verticalOffset); -} -function Menu_HoverDynamic(item) { - var node = (item.tagName.toLowerCase() == "td") ? - item: - item.cells[0]; - var data = Menu_GetData(item); - if (!data) return; - var nodeTable = WebForm_GetElementByTagName(node, "table"); - if (data.hoverClass) { - nodeTable.hoverClass = data.hoverClass; - WebForm_AppendToClassName(nodeTable, data.hoverClass); - } - node = nodeTable.rows[0].cells[0].childNodes[0]; - if (data.hoverHyperLinkClass) { - node.hoverHyperLinkClass = data.hoverHyperLinkClass; - WebForm_AppendToClassName(node, data.hoverHyperLinkClass); - } - if (data.disappearAfter >= 200) { - __disappearAfter = data.disappearAfter; - } - Menu_Expand(node, data.horizontalOffset, data.verticalOffset); -} -function Menu_HoverRoot(item) { - var node = (item.tagName.toLowerCase() == "td") ? - item: - item.cells[0]; - var data = Menu_GetData(item); - if (!data) { - return null; - } - var nodeTable = WebForm_GetElementByTagName(node, "table"); - if (data.staticHoverClass) { - nodeTable.hoverClass = data.staticHoverClass; - WebForm_AppendToClassName(nodeTable, data.staticHoverClass); - } - node = nodeTable.rows[0].cells[0].childNodes[0]; - if (data.staticHoverHyperLinkClass) { - node.hoverHyperLinkClass = data.staticHoverHyperLinkClass; - WebForm_AppendToClassName(node, data.staticHoverHyperLinkClass); - } - return node; -} -function Menu_HoverStatic(item) { - var node = Menu_HoverRoot(item); - var data = Menu_GetData(item); - if (!data) return; - __disappearAfter = data.disappearAfter; - Menu_Expand(node, data.horizontalOffset, data.verticalOffset); -} -function Menu_IsHorizontal(item) { - if (item) { - var a = ((item.tagName && (item.tagName.toLowerCase == "a")) ? item : WebForm_GetElementByTagName(item, "A")); - if (!a) { - return false; - } - var td = a.parentNode.parentNode.parentNode.parentNode.parentNode; - if (td.id) { - return true; - } - } - return false; -} -function Menu_IsSelectable(link) { - return (link && link.href) -} -function Menu_Key(item) { - var event; - if (window.event) { - event = window.event; - } - else { - event = item; - item = event.currentTarget; - } - var key = (event ? event.keyCode : -1); - var data = Menu_GetData(item); - if (!data) return; - var horizontal = Menu_IsHorizontal(item); - var a = WebForm_GetElementByTagName(item, "A"); - var nextItem, parentItem, previousItem; - if ((!horizontal && key == 38) || (horizontal && key == 37)) { - previousItem = Menu_FindPrevious(item); - while (previousItem && previousItem.disabled) { - previousItem = Menu_FindPrevious(previousItem); - } - if (previousItem) { - Menu_Focus(previousItem); - Menu_Expand(previousItem, data.horizontalOffset, data.verticalOffset, true); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return; - } - } - if ((!horizontal && key == 40) || (horizontal && key == 39)) { - if (horizontal) { - var subMenu = Menu_FindSubMenu(a); - if (subMenu && subMenu.style && subMenu.style.visibility && - subMenu.style.visibility.toLowerCase() == "hidden") { - Menu_Expand(a, data.horizontalOffset, data.verticalOffset, true); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return; - } - } - nextItem = Menu_FindNext(item); - while (nextItem && nextItem.disabled) { - nextItem = Menu_FindNext(nextItem); - } - if (nextItem) { - Menu_Focus(nextItem); - Menu_Expand(nextItem, data.horizontalOffset, data.verticalOffset, true); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return; - } - } - if ((!horizontal && key == 39) || (horizontal && key == 40)) { - var children = Menu_Expand(a, data.horizontalOffset, data.verticalOffset, true); - if (children) { - var firstChild; - children = WebForm_GetElementsByTagName(children, "A"); - for (var i = 0; i < children.length; i++) { - if (!children[i].disabled && Menu_IsSelectable(children[i])) { - firstChild = children[i]; - break; - } - } - if (firstChild) { - Menu_Focus(firstChild); - Menu_Expand(firstChild, data.horizontalOffset, data.verticalOffset, true); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return; - } - } - else { - parentItem = Menu_FindParentItem(item); - while (parentItem && !Menu_IsHorizontal(parentItem)) { - parentItem = Menu_FindParentItem(parentItem); - } - if (parentItem) { - nextItem = Menu_FindNext(parentItem); - while (nextItem && nextItem.disabled) { - nextItem = Menu_FindNext(nextItem); - } - if (nextItem) { - Menu_Focus(nextItem); - Menu_Expand(nextItem, data.horizontalOffset, data.verticalOffset, true); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return; - } - } - } - } - if ((!horizontal && key == 37) || (horizontal && key == 38)) { - parentItem = Menu_FindParentItem(item); - if (parentItem) { - if (Menu_IsHorizontal(parentItem)) { - previousItem = Menu_FindPrevious(parentItem); - while (previousItem && previousItem.disabled) { - previousItem = Menu_FindPrevious(previousItem); - } - if (previousItem) { - Menu_Focus(previousItem); - Menu_Expand(previousItem, data.horizontalOffset, data.verticalOffset, true); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return; - } - } - var parentA = WebForm_GetElementByTagName(parentItem, "A"); - if (parentA) { - Menu_Focus(parentA); - } - Menu_ResetSiblings(parentItem); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return; - } - } - if (key == 27) { - Menu_HideItems(); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return; - } -} -function Menu_ResetSiblings(item) { - var table = (item.tagName.toLowerCase() == "td") ? - item.parentNode.parentNode.parentNode : - item.parentNode.parentNode; - var isVertical = false; - for (var r = 0; r < table.rows.length; r++) { - if (table.rows[r].id) { - isVertical = true; - break; - } - } - var i, child, childNode; - if (isVertical) { - for(i = 0; i < table.rows.length; i++) { - childNode = table.rows[i]; - if (childNode != item) { - child = WebForm_GetElementById(childNode.id + "Items"); - if (child) { - Menu_HideItems(child); - } - } - } - } - else { - for(i = 0; i < table.rows[0].cells.length; i++) { - childNode = table.rows[0].cells[i]; - if (childNode != item) { - child = WebForm_GetElementById(childNode.id + "Items"); - if (child) { - Menu_HideItems(child); - } - } - } - } - Menu_ResetTopMenus(table, table, 0, true); -} -function Menu_ResetTopMenus(table, doNotReset, level, up) { - var i, child, childNode; - if (up && table.id == "") { - var parentTable = table.parentNode.parentNode.parentNode.parentNode; - if (parentTable.tagName.toLowerCase() == "table") { - Menu_ResetTopMenus(parentTable, doNotReset, level + 1, true); - } - } - else { - if (level == 0 && table != doNotReset) { - if (table.rows[0].id) { - for(i = 0; i < table.rows.length; i++) { - childNode = table.rows[i]; - child = WebForm_GetElementById(childNode.id + "Items"); - if (child) { - Menu_HideItems(child); - } - } - } - else { - for(i = 0; i < table.rows[0].cells.length; i++) { - childNode = table.rows[0].cells[i]; - child = WebForm_GetElementById(childNode.id + "Items"); - if (child) { - Menu_HideItems(child); - } - } - } - } - else if (level > 0) { - for (i = 0; i < table.rows.length; i++) { - for (var j = 0; j < table.rows[i].cells.length; j++) { - var subTable = table.rows[i].cells[j].firstChild; - if (subTable && subTable.tagName.toLowerCase() == "table") { - Menu_ResetTopMenus(subTable, doNotReset, level - 1, false); - } - } - } - } - } -} -function Menu_RestoreInterval() { - if (__menuInterval && __rootMenuItem) { - Menu_ClearInterval(); - __menuInterval = window.setInterval("Menu_HideItems()", __disappearAfter); - } -} -function Menu_SetRoot(item) { - var newRoot = Menu_FindMenu(item); - if (newRoot) { - if (__rootMenuItem && __rootMenuItem != newRoot) { - Menu_HideItems(); - } - __rootMenuItem = newRoot; - } -} -function Menu_Unhover(item) { - var node = (item.tagName.toLowerCase() == "td") ? - item: - item.cells[0]; - var nodeTable = WebForm_GetElementByTagName(node, "table"); - if (nodeTable.hoverClass) { - WebForm_RemoveClassName(nodeTable, nodeTable.hoverClass); - } - node = nodeTable.rows[0].cells[0].childNodes[0]; - if (node.hoverHyperLinkClass) { - WebForm_RemoveClassName(node, node.hoverHyperLinkClass); - } - Menu_Collapse(node); -} -function PopOut_Clip(element, y, height) { - if (element && element.style) { - element.style.clip = "rect(" + y + "px auto " + (y + height) + "px auto)"; - element.style.overflow = "hidden"; - } -} -function PopOut_Down(scroller) { - Menu_ClearInterval(); - var panel; - if (scroller) { - panel = scroller.parentNode - } - else { - panel = __scrollPanel; - } - if (panel && ((panel.offset + panel.clippedHeight) < panel.physicalHeight)) { - PopOut_Scroll(panel, 2) - __scrollPanel = panel; - PopOut_ShowScrollers(panel); - PopOut_Stop(); - __scrollPanel.interval = window.setInterval("PopOut_Down()", 8); - } - else { - PopOut_ShowScrollers(panel); - } -} -function PopOut_Hide(panelId) { - var panel = WebForm_GetElementById(panelId); - if (panel && panel.tagName.toLowerCase() == "div") { - panel.style.visibility = "hidden"; - panel.style.display = "none"; - panel.offset = 0; - panel.scrollTop = 0; - var table = WebForm_GetElementByTagName(panel, "TABLE"); - if (table) { - WebForm_SetElementY(table, 0); - } - if (window.navigator && window.navigator.appName == "Microsoft Internet Explorer" && - !window.opera) { - var childFrameId = panel.id + "_MenuIFrame"; - var childFrame = WebForm_GetElementById(childFrameId); - if (childFrame) { - childFrame.style.display = "none"; - } - } - } -} -function PopOut_HideScrollers(panel) { - if (panel && panel.style) { - var up = WebForm_GetElementById(panel.id + "Up"); - var dn = WebForm_GetElementById(panel.id + "Dn"); - if (up) { - up.style.visibility = "hidden"; - up.style.display = "none"; - } - if (dn) { - dn.style.visibility = "hidden"; - dn.style.display = "none"; - } - } -} -function PopOut_Position(panel, hideScrollers) { - if (window.opera) { - panel.parentNode.removeChild(panel); - document.forms[0].appendChild(panel); - } - var rel = WebForm_GetElementById(panel.rel); - var relTable = WebForm_GetElementByTagName(rel, "TABLE"); - var relCoordinates = WebForm_GetElementPosition(relTable ? relTable : rel); - var panelCoordinates = WebForm_GetElementPosition(panel); - var panelHeight = ((typeof(panel.physicalHeight) != "undefined") && (panel.physicalHeight != null)) ? - panel.physicalHeight : - panelCoordinates.height; - panel.physicalHeight = panelHeight; - var panelParentCoordinates; - if (panel.offsetParent) { - panelParentCoordinates = WebForm_GetElementPosition(panel.offsetParent); - } - else { - panelParentCoordinates = new Object(); - panelParentCoordinates.x = 0; - panelParentCoordinates.y = 0; - } - var overflowElement = WebForm_GetElementById("__overFlowElement"); - if (!overflowElement) { - overflowElement = document.createElement("img"); - overflowElement.id="__overFlowElement"; - WebForm_SetElementWidth(overflowElement, 1); - document.body.appendChild(overflowElement); - } - WebForm_SetElementHeight(overflowElement, panelHeight + relCoordinates.y + parseInt(panel.y ? panel.y : 0)); - overflowElement.style.visibility = "visible"; - overflowElement.style.display = "inline"; - var clientHeight = 0; - var clientWidth = 0; - if (window.innerHeight) { - clientHeight = window.innerHeight; - clientWidth = window.innerWidth; - } - else if (document.documentElement && document.documentElement.clientHeight) { - clientHeight = document.documentElement.clientHeight; - clientWidth = document.documentElement.clientWidth; - } - else if (document.body && document.body.clientHeight) { - clientHeight = document.body.clientHeight; - clientWidth = document.body.clientWidth; - } - var scrollTop = 0; - var scrollLeft = 0; - if (typeof(window.pageYOffset) != "undefined") { - scrollTop = window.pageYOffset; - scrollLeft = window.pageXOffset; - } - else if (document.documentElement && (typeof(document.documentElement.scrollTop) != "undefined")) { - scrollTop = document.documentElement.scrollTop; - scrollLeft = document.documentElement.scrollLeft; - } - else if (document.body && (typeof(document.body.scrollTop) != "undefined")) { - scrollTop = document.body.scrollTop; - scrollLeft = document.body.scrollLeft; - } - overflowElement.style.visibility = "hidden"; - overflowElement.style.display = "none"; - var bottomWindowBorder = clientHeight + scrollTop; - var rightWindowBorder = clientWidth + scrollLeft; - var position = panel.pos; - if ((typeof(position) == "undefined") || (position == null) || (position == "")) { - position = (WebForm_GetElementDir(rel) == "rtl" ? "middleleft" : "middleright"); - } - position = position.toLowerCase(); - var y = relCoordinates.y + parseInt(panel.y ? panel.y : 0) - panelParentCoordinates.y; - var borderParent = (rel && rel.parentNode && rel.parentNode.parentNode && rel.parentNode.parentNode.parentNode - && rel.parentNode.parentNode.parentNode.tagName.toLowerCase() == "div") ? - rel.parentNode.parentNode.parentNode : null; - WebForm_SetElementY(panel, y); - PopOut_SetPanelHeight(panel, panelHeight, true); - var clip = false; - var overflow; - if (position.indexOf("top") != -1) { - y -= panelHeight; - WebForm_SetElementY(panel, y); - if (y < -panelParentCoordinates.y) { - y = -panelParentCoordinates.y; - WebForm_SetElementY(panel, y); - if (panelHeight > clientHeight - 2) { - clip = true; - PopOut_SetPanelHeight(panel, clientHeight - 2); - } - } - } - else { - if (position.indexOf("bottom") != -1) { - y += relCoordinates.height; - WebForm_SetElementY(panel, y); - } - overflow = y + panelParentCoordinates.y + panelHeight - bottomWindowBorder; - if (overflow > 0) { - y -= overflow; - WebForm_SetElementY(panel, y); - if (y < -panelParentCoordinates.y) { - y = 2 - panelParentCoordinates.y + scrollTop; - WebForm_SetElementY(panel, y); - clip = true; - PopOut_SetPanelHeight(panel, clientHeight - 2); - } - } - } - if (!clip) { - PopOut_SetPanelHeight(panel, panel.clippedHeight, true); - } - var panelParentOffsetY = 0; - if (panel.offsetParent) { - panelParentOffsetY = WebForm_GetElementPosition(panel.offsetParent).y; - } - var panelY = ((typeof(panel.originY) != "undefined") && (panel.originY != null)) ? - panel.originY : - y - panelParentOffsetY; - panel.originY = panelY; - if (!hideScrollers) { - PopOut_ShowScrollers(panel); - } - else { - PopOut_HideScrollers(panel); - } - var x = relCoordinates.x + parseInt(panel.x ? panel.x : 0) - panelParentCoordinates.x; - if (borderParent && borderParent.clientLeft) { - x += 2 * borderParent.clientLeft; - } - WebForm_SetElementX(panel, x); - if (position.indexOf("left") != -1) { - x -= panelCoordinates.width; - WebForm_SetElementX(panel, x); - if (x < -panelParentCoordinates.x) { - WebForm_SetElementX(panel, -panelParentCoordinates.x); - } - } - else { - if (position.indexOf("right") != -1) { - x += relCoordinates.width; - WebForm_SetElementX(panel, x); - } - overflow = x + panelParentCoordinates.x + panelCoordinates.width - rightWindowBorder; - if (overflow > 0) { - if (position.indexOf("bottom") == -1 && relCoordinates.x > panelCoordinates.width) { - x -= relCoordinates.width + panelCoordinates.width; - } - else { - x -= overflow; - } - WebForm_SetElementX(panel, x); - if (x < -panelParentCoordinates.x) { - WebForm_SetElementX(panel, -panelParentCoordinates.x); - } - } - } -} -function PopOut_Scroll(panel, offsetDelta) { - var table = WebForm_GetElementByTagName(panel, "TABLE"); - if (!table) return; - table.style.position = "relative"; - var tableY = (table.style.top ? parseInt(table.style.top) : 0); - panel.offset += offsetDelta; - WebForm_SetElementY(table, tableY - offsetDelta); -} -function PopOut_SetPanelHeight(element, height, doNotClip) { - if (element && element.style) { - var size = WebForm_GetElementPosition(element); - element.physicalWidth = size.width; - element.clippedHeight = height; - WebForm_SetElementHeight(element, height - (element.clientTop ? (2 * element.clientTop) : 0)); - if (doNotClip && element.style) { - element.style.clip = "rect(auto auto auto auto)"; - } - else { - PopOut_Clip(element, 0, height); - } - } -} -function PopOut_Show(panelId, hideScrollers, data) { - var panel = WebForm_GetElementById(panelId); - if (panel && panel.tagName.toLowerCase() == "div") { - panel.style.visibility = "visible"; - panel.style.display = "inline"; - if (!panel.offset || hideScrollers) { - panel.scrollTop = 0; - panel.offset = 0; - var table = WebForm_GetElementByTagName(panel, "TABLE"); - if (table) { - WebForm_SetElementY(table, 0); - } - } - PopOut_Position(panel, hideScrollers); - var z = 1; - var isIE = window.navigator && window.navigator.appName == "Microsoft Internet Explorer" && !window.opera; - if (isIE && data) { - var childFrameId = panel.id + "_MenuIFrame"; - var childFrame = WebForm_GetElementById(childFrameId); - var parent = panel.offsetParent; - if (!childFrame) { - childFrame = document.createElement("iframe"); - childFrame.id = childFrameId; - childFrame.src = (data.iframeUrl ? data.iframeUrl : "about:blank"); - childFrame.style.position = "absolute"; - childFrame.style.display = "none"; - childFrame.scrolling = "no"; - childFrame.frameBorder = "0"; - if (parent.tagName.toLowerCase() == "html") { - document.body.appendChild(childFrame); - } - else { - parent.appendChild(childFrame); - } - } - var pos = WebForm_GetElementPosition(panel); - var parentPos = WebForm_GetElementPosition(parent); - WebForm_SetElementX(childFrame, pos.x - parentPos.x); - WebForm_SetElementY(childFrame, pos.y - parentPos.y); - WebForm_SetElementWidth(childFrame, pos.width); - WebForm_SetElementHeight(childFrame, pos.height); - childFrame.style.display = "block"; - if (panel.currentStyle && panel.currentStyle.zIndex && panel.currentStyle.zIndex != "auto") { - z = panel.currentStyle.zIndex; - } - else if (panel.style.zIndex) { - z = panel.style.zIndex; - } - } - panel.style.zIndex = z; - } -} -function PopOut_ShowScrollers(panel) { - if (panel && panel.style) { - var up = WebForm_GetElementById(panel.id + "Up"); - var dn = WebForm_GetElementById(panel.id + "Dn"); - var cnt = 0; - if (up && dn) { - if (panel.offset && panel.offset > 0) { - up.style.visibility = "visible"; - up.style.display = "inline"; - cnt++; - if (panel.clientWidth) { - WebForm_SetElementWidth(up, panel.clientWidth - - (up.clientLeft ? (2 * up.clientLeft) : 0)); - } - WebForm_SetElementY(up, 0); - } - else { - up.style.visibility = "hidden"; - up.style.display = "none"; - } - if (panel.offset + panel.clippedHeight + 2 <= panel.physicalHeight) { - dn.style.visibility = "visible"; - dn.style.display = "inline"; - cnt++; - if (panel.clientWidth) { - WebForm_SetElementWidth(dn, panel.clientWidth - - (dn.clientLeft ? (2 * dn.clientLeft) : 0)); - } - WebForm_SetElementY(dn, panel.clippedHeight - WebForm_GetElementPosition(dn).height - - (panel.clientTop ? (2 * panel.clientTop) : 0)); - } - else { - dn.style.visibility = "hidden"; - dn.style.display = "none"; - } - if (cnt == 0) { - panel.style.clip = "rect(auto auto auto auto)"; - } - } - } -} -function PopOut_Stop() { - if (__scrollPanel && __scrollPanel.interval) { - window.clearInterval(__scrollPanel.interval); - } - Menu_RestoreInterval(); -} -function PopOut_Up(scroller) { - Menu_ClearInterval(); - var panel; - if (scroller) { - panel = scroller.parentNode - } - else { - panel = __scrollPanel; - } - if (panel && panel.offset && panel.offset > 0) { - PopOut_Scroll(panel, -2); - __scrollPanel = panel; - PopOut_ShowScrollers(panel); - PopOut_Stop(); - __scrollPanel.interval = window.setInterval("PopOut_Up()", 8); - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MenuStandards.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MenuStandards.js deleted file mode 100644 index 95decdd0b..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/MenuStandards.js +++ /dev/null @@ -1,697 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/MenuStandards.js -if (!window.Sys) { window.Sys = {}; } -if (!Sys.WebForms) { Sys.WebForms = {}; } -Sys.WebForms.Menu = function(options) { - this.items = []; - this.depth = options.depth || 1; - this.parentMenuItem = options.parentMenuItem; - this.element = Sys.WebForms.Menu._domHelper.getElement(options.element); - if (this.element.tagName === 'DIV') { - var containerElement = this.element; - this.element = Sys.WebForms.Menu._domHelper.firstChild(containerElement); - this.element.tabIndex = options.tabIndex || 0; - options.element = containerElement; - options.menu = this; - this.container = new Sys.WebForms._MenuContainer(options); - Sys.WebForms.Menu._domHelper.setFloat(this.element, this.container.rightToLeft ? "right" : "left"); - } - else { - this.container = options.container; - this.keyMap = options.keyMap; - } - Sys.WebForms.Menu._elementObjectMapper.map(this.element, this); - if (this.parentMenuItem && this.parentMenuItem.parentMenu) { - this.parentMenu = this.parentMenuItem.parentMenu; - this.rootMenu = this.parentMenu.rootMenu; - if (!this.element.id) { - this.element.id = (this.container.element.id || 'menu') + ':submenu:' + Sys.WebForms.Menu._elementObjectMapper._computedId; - } - if (this.depth > this.container.staticDisplayLevels) { - this.displayMode = "dynamic"; - this.element.style.display = "none"; - this.element.style.position = "absolute"; - if (this.rootMenu && this.container.orientation === 'horizontal' && this.parentMenu.isStatic()) { - this.element.style.top = "100%"; - if (this.container.rightToLeft) { - this.element.style.right = "0px"; - } - else { - this.element.style.left = "0px"; - } - } - else { - this.element.style.top = "0px"; - if (this.container.rightToLeft) { - this.element.style.right = "100%"; - } - else { - this.element.style.left = "100%"; - } - } - if (this.container.rightToLeft) { - this.keyMap = Sys.WebForms.Menu._keyboardMapping.verticalRtl; - } - else { - this.keyMap = Sys.WebForms.Menu._keyboardMapping.vertical; - } - } - else { - this.displayMode = "static"; - this.element.style.display = "block"; - if (this.container.orientation === 'horizontal') { - Sys.WebForms.Menu._domHelper.setFloat(this.element, this.container.rightToLeft ? "right" : "left"); - } - } - } - Sys.WebForms.Menu._domHelper.appendCssClass(this.element, this.displayMode); - var children = this.element.childNodes; - var count = children.length; - for (var i = 0; i < count; i++) { - var node = children[i]; - if (node.nodeType !== 1) { - continue; - } - var topLevelMenuItem = null; - if (this.parentMenuItem) { - topLevelMenuItem = this.parentMenuItem.topLevelMenuItem; - } - var menuItem = new Sys.WebForms.MenuItem(this, node, topLevelMenuItem); - var previousMenuItem = this.items[this.items.length - 1]; - if (previousMenuItem) { - menuItem.previousSibling = previousMenuItem; - previousMenuItem.nextSibling = menuItem; - } - this.items[this.items.length] = menuItem; - } -}; -Sys.WebForms.Menu.prototype = { - blur: function() { if (this.container) this.container.blur(); }, - collapse: function() { - this.each(function(menuItem) { - menuItem.hover(false); - menuItem.blur(); - var childMenu = menuItem.childMenu; - if (childMenu) { - childMenu.collapse(); - } - }); - this.hide(); - }, - doDispose: function() { this.each(function(item) { item.doDispose(); }); }, - each: function(fn) { - var count = this.items.length; - for (var i = 0; i < count; i++) { - fn(this.items[i]); - } - }, - firstChild: function() { return this.items[0]; }, - focus: function() { if (this.container) this.container.focus(); }, - get_displayed: function() { return this.element.style.display !== 'none'; }, - get_focused: function() { - if (this.container) { - return this.container.focused; - } - return false; - }, - handleKeyPress: function(keyCode) { - if (this.keyMap.contains(keyCode)) { - if (this.container.focusedMenuItem) { - this.container.focusedMenuItem.navigate(keyCode); - return; - } - var firstChild = this.firstChild(); - if (firstChild) { - this.container.navigateTo(firstChild); - } - } - }, - hide: function() { - if (!this.get_displayed()) { - return; - } - this.each(function(item) { - if (item.childMenu) { - item.childMenu.hide(); - } - }); - if (!this.isRoot()) { - if (this.get_focused()) { - this.container.navigateTo(this.parentMenuItem); - } - this.element.style.display = 'none'; - } - }, - isRoot: function() { return this.rootMenu === this; }, - isStatic: function() { return this.displayMode === 'static'; }, - lastChild: function() { return this.items[this.items.length - 1]; }, - show: function() { this.element.style.display = 'block'; } -}; -if (Sys.WebForms.Menu.registerClass) { - Sys.WebForms.Menu.registerClass('Sys.WebForms.Menu'); -} -Sys.WebForms.MenuItem = function(parentMenu, listElement, topLevelMenuItem) { - this.keyMap = parentMenu.keyMap; - this.parentMenu = parentMenu; - this.container = parentMenu.container; - this.element = listElement; - this.topLevelMenuItem = topLevelMenuItem || this; - this._anchor = Sys.WebForms.Menu._domHelper.firstChild(listElement); - while (this._anchor && this._anchor.tagName !== 'A') { - this._anchor = Sys.WebForms.Menu._domHelper.nextSibling(this._anchor); - } - if (this._anchor) { - this._anchor.tabIndex = -1; - var subMenu = this._anchor; - while (subMenu && subMenu.tagName !== 'UL') { - subMenu = Sys.WebForms.Menu._domHelper.nextSibling(subMenu); - } - if (subMenu) { - this.childMenu = new Sys.WebForms.Menu({ element: subMenu, parentMenuItem: this, depth: parentMenu.depth + 1, container: this.container, keyMap: this.keyMap }); - if (!this.childMenu.isStatic()) { - Sys.WebForms.Menu._domHelper.appendCssClass(this.element, 'has-popup'); - Sys.WebForms.Menu._domHelper.appendAttributeValue(this.element, 'aria-haspopup', this.childMenu.element.id); - } - } - } - Sys.WebForms.Menu._elementObjectMapper.map(listElement, this); - Sys.WebForms.Menu._domHelper.appendAttributeValue(listElement, 'role', 'menuitem'); - Sys.WebForms.Menu._domHelper.appendCssClass(listElement, parentMenu.displayMode); - if (this._anchor) { - Sys.WebForms.Menu._domHelper.appendCssClass(this._anchor, parentMenu.displayMode); - } - this.element.style.position = "relative"; - if (this.parentMenu.depth == 1 && this.container.orientation == 'horizontal') { - Sys.WebForms.Menu._domHelper.setFloat(this.element, this.container.rightToLeft ? "right" : "left"); - } - if (!this.container.disabled) { - Sys.WebForms.Menu._domHelper.addEvent(this.element, 'mouseover', Sys.WebForms.MenuItem._onmouseover); - Sys.WebForms.Menu._domHelper.addEvent(this.element, 'mouseout', Sys.WebForms.MenuItem._onmouseout); - } -}; -Sys.WebForms.MenuItem.prototype = { - applyUp: function(fn, condition) { - condition = condition || function(menuItem) { return menuItem; }; - var menuItem = this; - var lastMenuItem = null; - while (condition(menuItem)) { - fn(menuItem); - lastMenuItem = menuItem; - menuItem = menuItem.parentMenu.parentMenuItem; - } - return lastMenuItem; - }, - blur: function() { this.setTabIndex(-1); }, - doDispose: function() { - Sys.WebForms.Menu._domHelper.removeEvent(this.element, 'mouseover', Sys.WebForms.MenuItem._onmouseover); - Sys.WebForms.Menu._domHelper.removeEvent(this.element, 'mouseout', Sys.WebForms.MenuItem._onmouseout); - if (this.childMenu) { - this.childMenu.doDispose(); - } - }, - focus: function() { - if (!this.parentMenu.get_displayed()) { - this.parentMenu.show(); - } - this.setTabIndex(0); - this.container.focused = true; - this._anchor.focus(); - }, - get_highlighted: function() { return /(^|\s)highlighted(\s|$)/.test(this._anchor.className); }, - getTabIndex: function() { return this._anchor.tabIndex; }, - highlight: function(highlighting) { - if (highlighting) { - this.applyUp(function(menuItem) { - menuItem.parentMenu.parentMenuItem.highlight(true); - }, - function(menuItem) { - return !menuItem.parentMenu.isStatic() && menuItem.parentMenu.parentMenuItem; - } - ); - Sys.WebForms.Menu._domHelper.appendCssClass(this._anchor, 'highlighted'); - } - else { - Sys.WebForms.Menu._domHelper.removeCssClass(this._anchor, 'highlighted'); - this.setTabIndex(-1); - } - }, - hover: function(hovering) { - if (hovering) { - var currentHoveredItem = this.container.hoveredMenuItem; - if (currentHoveredItem) { - currentHoveredItem.hover(false); - } - var currentFocusedItem = this.container.focusedMenuItem; - if (currentFocusedItem && currentFocusedItem !== this) { - currentFocusedItem.hover(false); - } - this.applyUp(function(menuItem) { - if (menuItem.childMenu && !menuItem.childMenu.get_displayed()) { - menuItem.childMenu.show(); - } - }); - this.container.hoveredMenuItem = this; - this.highlight(true); - } - else { - var menuItem = this; - while (menuItem) { - menuItem.highlight(false); - if (menuItem.childMenu) { - if (!menuItem.childMenu.isStatic()) { - menuItem.childMenu.hide(); - } - } - menuItem = menuItem.parentMenu.parentMenuItem; - } - } - }, - isSiblingOf: function(menuItem) { return menuItem.parentMenu === this.parentMenu; }, - mouseout: function() { - var menuItem = this, - id = this.container.pendingMouseoutId, - disappearAfter = this.container.disappearAfter; - if (id) { - window.clearTimeout(id); - } - if (disappearAfter > -1) { - this.container.pendingMouseoutId = - window.setTimeout(function() { menuItem.hover(false); }, disappearAfter); - } - }, - mouseover: function() { - var id = this.container.pendingMouseoutId; - if (id) { - window.clearTimeout(id); - this.container.pendingMouseoutId = null; - } - this.hover(true); - if (this.container.menu.get_focused()) { - this.container.navigateTo(this); - } - }, - navigate: function(keyCode) { - switch (this.keyMap[keyCode]) { - case this.keyMap.next: - this.navigateNext(); - break; - case this.keyMap.previous: - this.navigatePrevious(); - break; - case this.keyMap.child: - this.navigateChild(); - break; - case this.keyMap.parent: - this.navigateParent(); - break; - case this.keyMap.tab: - this.navigateOut(); - break; - } - }, - navigateChild: function() { - var subMenu = this.childMenu; - if (subMenu) { - var firstChild = subMenu.firstChild(); - if (firstChild) { - this.container.navigateTo(firstChild); - } - } - else { - if (this.container.orientation === 'horizontal') { - var nextItem = this.topLevelMenuItem.nextSibling || this.topLevelMenuItem.parentMenu.firstChild(); - if (nextItem == this.topLevelMenuItem) { - return; - } - this.topLevelMenuItem.childMenu.hide(); - this.container.navigateTo(nextItem); - if (nextItem.childMenu) { - this.container.navigateTo(nextItem.childMenu.firstChild()); - } - } - } - }, - navigateNext: function() { - if (this.childMenu) { - this.childMenu.hide(); - } - var nextMenuItem = this.nextSibling; - if (!nextMenuItem && this.parentMenu.isRoot()) { - nextMenuItem = this.parentMenu.parentMenuItem; - if (nextMenuItem) { - nextMenuItem = nextMenuItem.nextSibling; - } - } - if (!nextMenuItem) { - nextMenuItem = this.parentMenu.firstChild(); - } - if (nextMenuItem) { - this.container.navigateTo(nextMenuItem); - } - }, - navigateOut: function() { - this.parentMenu.blur(); - }, - navigateParent: function() { - var parentMenu = this.parentMenu, - horizontal = this.container.orientation === 'horizontal'; - if (!parentMenu) return; - if (horizontal && this.childMenu && parentMenu.isRoot()) { - this.navigateChild(); - return; - } - if (parentMenu.parentMenuItem && !parentMenu.isRoot()) { - if (horizontal && this.parentMenu.depth === 2) { - var previousItem = this.parentMenu.parentMenuItem.previousSibling; - if (!previousItem) { - previousItem = this.parentMenu.rootMenu.lastChild(); - } - this.topLevelMenuItem.childMenu.hide(); - this.container.navigateTo(previousItem); - if (previousItem.childMenu) { - this.container.navigateTo(previousItem.childMenu.firstChild()); - } - } - else { - this.parentMenu.hide(); - } - } - }, - navigatePrevious: function() { - if (this.childMenu) { - this.childMenu.hide(); - } - var previousMenuItem = this.previousSibling; - if (previousMenuItem) { - var childMenu = previousMenuItem.childMenu; - if (childMenu && childMenu.isRoot()) { - previousMenuItem = childMenu.lastChild(); - } - } - if (!previousMenuItem && this.parentMenu.isRoot()) { - previousMenuItem = this.parentMenu.parentMenuItem; - } - if (!previousMenuItem) { - previousMenuItem = this.parentMenu.lastChild(); - } - if (previousMenuItem) { - this.container.navigateTo(previousMenuItem); - } - }, - setTabIndex: function(index) { if (this._anchor) this._anchor.tabIndex = index; } -}; -Sys.WebForms.MenuItem._onmouseout = function(e) { - var menuItem = Sys.WebForms.Menu._elementObjectMapper.getMappedObject(this); - if (!menuItem) { - return; - } - menuItem.mouseout(); - Sys.WebForms.Menu._domHelper.cancelEvent(e); -}; -Sys.WebForms.MenuItem._onmouseover = function(e) { - var menuItem = Sys.WebForms.Menu._elementObjectMapper.getMappedObject(this); - if (!menuItem) { - return; - } - menuItem.mouseover(); - Sys.WebForms.Menu._domHelper.cancelEvent(e); -}; -Sys.WebForms.Menu._domHelper = { - addEvent: function(element, eventName, fn, useCapture) { - if (element.addEventListener) { - element.addEventListener(eventName, fn, !!useCapture); - } - else { - element['on' + eventName] = fn; - } - }, - appendAttributeValue: function(element, name, value) { - this.updateAttributeValue('append', element, name, value); - }, - appendCssClass: function(element, value) { - this.updateClassName('append', element, name, value); - }, - appendString: function(getString, setString, value) { - var currentValue = getString(); - if (!currentValue) { - setString(value); - return; - } - var regex = this._regexes.getRegex('(^| )' + value + '($| )'); - if (regex.test(currentValue)) { - return; - } - setString(currentValue + ' ' + value); - }, - cancelEvent: function(e) { - var event = e || window.event; - if (event) { - event.cancelBubble = true; - if (event.stopPropagation) { - event.stopPropagation(); - } - } - }, - contains: function(ancestor, descendant) { - for (; descendant && (descendant !== ancestor); descendant = descendant.parentNode) { } - return !!descendant; - }, - firstChild: function(element) { - var child = element.firstChild; - if (child && child.nodeType !== 1) { - child = this.nextSibling(child); - } - return child; - }, - getElement: function(elementOrId) { return typeof elementOrId === 'string' ? document.getElementById(elementOrId) : elementOrId; }, - getElementDirection: function(element) { - if (element) { - if (element.dir) { - return element.dir; - } - return this.getElementDirection(element.parentNode); - } - return "ltr"; - }, - getKeyCode: function(event) { return event.keyCode || event.charCode || 0; }, - insertAfter: function(element, elementToInsert) { - var next = element.nextSibling; - if (next) { - element.parentNode.insertBefore(elementToInsert, next); - } - else if (element.parentNode) { - element.parentNode.appendChild(elementToInsert); - } - }, - nextSibling: function(element) { - var sibling = element.nextSibling; - while (sibling) { - if (sibling.nodeType === 1) { - return sibling; - } - sibling = sibling.nextSibling; - } - }, - removeAttributeValue: function(element, name, value) { - this.updateAttributeValue('remove', element, name, value); - }, - removeCssClass: function(element, value) { - this.updateClassName('remove', element, name, value); - }, - removeEvent: function(element, eventName, fn, useCapture) { - if (element.removeEventListener) { - element.removeEventListener(eventName, fn, !!useCapture); - } - else if (element.detachEvent) { - element.detachEvent('on' + eventName, fn) - } - element['on' + eventName] = null; - }, - removeString: function(getString, setString, valueToRemove) { - var currentValue = getString(); - if (currentValue) { - var regex = this._regexes.getRegex('(\\s|\\b)' + valueToRemove + '$|\\b' + valueToRemove + '\\s+'); - setString(currentValue.replace(regex, '')); - } - }, - setFloat: function(element, direction) { - element.style.styleFloat = direction; - element.style.cssFloat = direction; - }, - updateAttributeValue: function(operation, element, name, value) { - this[operation + 'String']( - function() { - return element.getAttribute(name); - }, - function(newValue) { - element.setAttribute(name, newValue); - }, - value - ); - }, - updateClassName: function(operation, element, name, value) { - this[operation + 'String']( - function() { - return element.className; - }, - function(newValue) { - element.className = newValue; - }, - value - ); - }, - _regexes: { - getRegex: function(pattern) { - var regex = this[pattern]; - if (!regex) { - this[pattern] = regex = new RegExp(pattern); - } - return regex; - } - } -}; -Sys.WebForms.Menu._elementObjectMapper = { - _computedId: 0, - _mappings: {}, - _mappingIdName: 'Sys.WebForms.Menu.Mapping', - getMappedObject: function(element) { - var id = element[this._mappingIdName]; - if (id) { - return this._mappings[this._mappingIdName + ':' + id]; - } - }, - map: function(element, theObject) { - var mappedObject = element[this._mappingIdName]; - if (mappedObject === theObject) { - return; - } - var objectId = element[this._mappingIdName] || element.id || '%' + (++this._computedId); - element[this._mappingIdName] = objectId; - this._mappings[this._mappingIdName + ':' + objectId] = theObject; - theObject.mappingId = objectId; - } -}; -Sys.WebForms.Menu._keyboardMapping = new (function() { - var LEFT_ARROW = 37; - var UP_ARROW = 38; - var RIGHT_ARROW = 39; - var DOWN_ARROW = 40; - var TAB = 9; - var ESCAPE = 27; - this.vertical = { next: 0, previous: 1, child: 2, parent: 3, tab: 4 }; - this.vertical[DOWN_ARROW] = this.vertical.next; - this.vertical[UP_ARROW] = this.vertical.previous; - this.vertical[RIGHT_ARROW] = this.vertical.child; - this.vertical[LEFT_ARROW] = this.vertical.parent; - this.vertical[TAB] = this.vertical[ESCAPE] = this.vertical.tab; - this.verticalRtl = { next: 0, previous: 1, child: 2, parent: 3, tab: 4 }; - this.verticalRtl[DOWN_ARROW] = this.verticalRtl.next; - this.verticalRtl[UP_ARROW] = this.verticalRtl.previous; - this.verticalRtl[LEFT_ARROW] = this.verticalRtl.child; - this.verticalRtl[RIGHT_ARROW] = this.verticalRtl.parent; - this.verticalRtl[TAB] = this.verticalRtl[ESCAPE] = this.verticalRtl.tab; - this.horizontal = { next: 0, previous: 1, child: 2, parent: 3, tab: 4 }; - this.horizontal[RIGHT_ARROW] = this.horizontal.next; - this.horizontal[LEFT_ARROW] = this.horizontal.previous; - this.horizontal[DOWN_ARROW] = this.horizontal.child; - this.horizontal[UP_ARROW] = this.horizontal.parent; - this.horizontal[TAB] = this.horizontal[ESCAPE] = this.horizontal.tab; - this.horizontalRtl = { next: 0, previous: 1, child: 2, parent: 3, tab: 4 }; - this.horizontalRtl[RIGHT_ARROW] = this.horizontalRtl.previous; - this.horizontalRtl[LEFT_ARROW] = this.horizontalRtl.next; - this.horizontalRtl[DOWN_ARROW] = this.horizontalRtl.child; - this.horizontalRtl[UP_ARROW] = this.horizontalRtl.parent; - this.horizontalRtl[TAB] = this.horizontalRtl[ESCAPE] = this.horizontalRtl.tab; - this.horizontal.contains = this.horizontalRtl.contains = this.vertical.contains = this.verticalRtl.contains = function(keycode) { - return this[keycode] != null; - }; -})(); -Sys.WebForms._MenuContainer = function(options) { - this.focused = false; - this.disabled = options.disabled; - this.staticDisplayLevels = options.staticDisplayLevels || 1; - this.element = options.element; - this.orientation = options.orientation || 'vertical'; - this.disappearAfter = options.disappearAfter; - this.rightToLeft = Sys.WebForms.Menu._domHelper.getElementDirection(this.element) === 'rtl'; - Sys.WebForms.Menu._elementObjectMapper.map(this.element, this); - this.menu = options.menu; - this.menu.rootMenu = this.menu; - this.menu.displayMode = 'static'; - this.menu.element.style.position = 'relative'; - this.menu.element.style.width = 'auto'; - if (this.orientation === 'vertical') { - Sys.WebForms.Menu._domHelper.appendAttributeValue(this.menu.element, 'role', 'menu'); - if (this.rightToLeft) { - this.menu.keyMap = Sys.WebForms.Menu._keyboardMapping.verticalRtl; - } - else { - this.menu.keyMap = Sys.WebForms.Menu._keyboardMapping.vertical; - } - } - else { - Sys.WebForms.Menu._domHelper.appendAttributeValue(this.menu.element, 'role', 'menubar'); - if (this.rightToLeft) { - this.menu.keyMap = Sys.WebForms.Menu._keyboardMapping.horizontalRtl; - } - else { - this.menu.keyMap = Sys.WebForms.Menu._keyboardMapping.horizontal; - } - } - var floatBreak = document.createElement('div'); - floatBreak.style.clear = this.rightToLeft ? "right" : "left"; - this.element.appendChild(floatBreak); - Sys.WebForms.Menu._domHelper.setFloat(this.element, this.rightToLeft ? "right" : "left"); - Sys.WebForms.Menu._domHelper.insertAfter(this.element, floatBreak); - if (!this.disabled) { - Sys.WebForms.Menu._domHelper.addEvent(this.menu.element, 'focus', this._onfocus, true); - Sys.WebForms.Menu._domHelper.addEvent(this.menu.element, 'keydown', this._onkeydown); - var menuContainer = this; - this.element.dispose = function() { - if (menuContainer.element.dispose) { - menuContainer.element.dispose = null; - Sys.WebForms.Menu._domHelper.removeEvent(menuContainer.menu.element, 'focus', menuContainer._onfocus, true); - Sys.WebForms.Menu._domHelper.removeEvent(menuContainer.menu.element, 'keydown', menuContainer._onkeydown); - menuContainer.menu.doDispose(); - } - }; - Sys.WebForms.Menu._domHelper.addEvent(window, 'unload', function() { - if (menuContainer.element.dispose) { - menuContainer.element.dispose(); - } - }); - } -}; -Sys.WebForms._MenuContainer.prototype = { - blur: function() { - this.focused = false; - this.isBlurring = false; - this.menu.collapse(); - this.focusedMenuItem = null; - }, - focus: function(e) { this.focused = true; }, - navigateTo: function(menuItem) { - if (this.focusedMenuItem && this.focusedMenuItem !== this) { - this.focusedMenuItem.highlight(false); - } - menuItem.highlight(true); - menuItem.focus(); - this.focusedMenuItem = menuItem; - }, - _onfocus: function(e) { - var event = e || window.event; - if (event.srcElement && this) { - if (Sys.WebForms.Menu._domHelper.contains(this.element, event.srcElement)) { - if (!this.focused) { - this.focus(); - } - } - } - }, - _onkeydown: function(e) { - var thisMenu = Sys.WebForms.Menu._elementObjectMapper.getMappedObject(this); - var keyCode = Sys.WebForms.Menu._domHelper.getKeyCode(e || window.event); - if (thisMenu) { - thisMenu.handleKeyPress(keyCode); - } - } -}; diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/SmartNav.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/SmartNav.js deleted file mode 100644 index e9e95d2e7..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/SmartNav.js +++ /dev/null @@ -1,280 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/SmartNav.js -var snSrc; -if ((typeof(window.__smartNav) == "undefined") || (window.__smartNav == null)) -{ - window.__smartNav = new Object(); - window.__smartNav.update = function() - { - var sn = window.__smartNav; - var fd; - document.detachEvent("onstop", sn.stopHif); - sn.inPost = false; - try { fd = frames["__hifSmartNav"].document; } catch (e) {return;} - var fdr = fd.getElementsByTagName("asp_smartnav_rdir"); - if (fdr.length > 0) - { - if ((typeof(sn.sHif) == "undefined") || (sn.sHif == null)) - { - sn.sHif = document.createElement("IFRAME"); - sn.sHif.name = "__hifSmartNav"; - sn.sHif.style.display = "none"; - sn.sHif.src = snSrc; - } - try {window.location = fdr[0].url;} catch (e) {}; - return; - } - var fdurl = fd.location.href; - var index = fdurl.indexOf(snSrc); - if ((index != -1 && index == fdurl.length-snSrc.length) - || fdurl == "about:blank") - return; - var fdurlb = fdurl.split("?")[0]; - if (document.location.href.indexOf(fdurlb) < 0) - { - document.location.href=fdurl; - return; - } - sn._savedOnLoad = window.onload; - window.onload = null; - window.__smartNav.updateHelper(); - } - window.__smartNav.updateHelper = function() - { - if (document.readyState != "complete") - { - window.setTimeout(window.__smartNav.updateHelper, 25); - return; - } - window.__smartNav.loadNewContent(); - } - window.__smartNav.loadNewContent = function() - { - var sn = window.__smartNav; - var fd; - try { fd = frames["__hifSmartNav"].document; } catch (e) {return;} - if ((typeof(sn.sHif) != "undefined") && (sn.sHif != null)) - { - sn.sHif.removeNode(true); - sn.sHif = null; - } - var hdm = document.getElementsByTagName("head")[0]; - var hk = hdm.childNodes; - var tt = null; - var i; - for (i = hk.length - 1; i>= 0; i--) - { - if (hk[i].tagName == "TITLE") - { - tt = hk[i].outerHTML; - continue; - } - if (hk[i].tagName != "BASEFONT" || hk[i].innerHTML.length == 0) - hdm.removeChild(hdm.childNodes[i]); - } - var kids = fd.getElementsByTagName("head")[0].childNodes; - for (i = 0; i < kids.length; i++) - { - var tn = kids[i].tagName; - var k = document.createElement(tn); - k.id = kids[i].id; - k.mergeAttributes(kids[i]); - switch(tn) - { - case "TITLE": - if (tt == kids[i].outerHTML) - continue; - k.innerText = kids[i].text; - hdm.insertAdjacentElement("afterbegin", k); - continue; - case "BASEFONT" : - if (kids[i].innerHTML.length > 0) - continue; - break; - default: - var o = document.createElement("BODY"); - o.innerHTML = "" + kids[i].outerHTML + ""; - k = o.firstChild; - break; - } - if((typeof(k) != "undefined") && (k != null)) - hdm.appendChild(k); - } - document.body.clearAttributes(); - document.body.id = fd.body.id; - document.body.mergeAttributes(fd.body); - var newBodyLoad = fd.body.onload; - if ((typeof(newBodyLoad) != "undefined") && (newBodyLoad != null)) - document.body.onload = newBodyLoad; - else - document.body.onload = sn._savedOnLoad; - var s = "" + fd.body.innerHTML + ""; - if ((typeof(sn.hif) != "undefined") && (sn.hif != null)) - { - var hifP = sn.hif.parentElement; - if ((typeof(hifP) != "undefined") && (hifP != null)) - sn.sHif=hifP.removeChild(sn.hif); - } - document.body.innerHTML = s; - var sc = document.scripts; - for (i = 0; i < sc.length; i++) - { - sc[i].text = sc[i].text; - } - sn.hif = document.all("__hifSmartNav"); - if ((typeof(sn.hif) != "undefined") && (sn.hif != null)) - { - var hif = sn.hif; - sn.hifName = "__hifSmartNav" + (new Date()).getTime(); - frames["__hifSmartNav"].name = sn.hifName; - sn.hifDoc = hif.contentWindow.document; - if (sn.ie5) - hif.parentElement.removeChild(hif); - window.setTimeout(sn.restoreFocus,0); - } - if (typeof(window.onload) == "string") - { - try { eval(window.onload) } catch (e) {}; - } - else if ((typeof(window.onload) != "undefined") && (window.onload != null)) - { - try { window.onload() } catch (e) {}; - } - sn._savedOnLoad = null; - sn.attachForm(); - }; - window.__smartNav.restoreFocus = function() - { - if (window.__smartNav.inPost == true) return; - var curAe = document.activeElement; - var sAeId = window.__smartNav.ae; - if (((typeof(sAeId) == "undefined") || (sAeId == null)) || - (typeof(curAe) != "undefined") && (curAe != null) && (curAe.id == sAeId || curAe.name == sAeId)) - return; - var ae = document.all(sAeId); - if ((typeof(ae) == "undefined") || (ae == null)) return; - try { ae.focus(); } catch(e){}; - } - window.__smartNav.saveHistory = function() - { - if ((typeof(window.__smartNav.hif) != "undefined") && (window.__smartNav.hif != null)) - window.__smartNav.hif.removeNode(); - if ((typeof(window.__smartNav.sHif) != "undefined") && (window.__smartNav.sHif != null) - && (typeof(document.all[window.__smartNav.siHif]) != "undefined") - && (document.all[window.__smartNav.siHif] != null)) { - document.all[window.__smartNav.siHif].insertAdjacentElement( - "BeforeBegin", window.__smartNav.sHif); - } - } - window.__smartNav.stopHif = function() - { - document.detachEvent("onstop", window.__smartNav.stopHif); - var sn = window.__smartNav; - if (((typeof(sn.hifDoc) == "undefined") || (sn.hifDoc == null)) && - (typeof(sn.hif) != "undefined") && (sn.hif != null)) - { - try {sn.hifDoc = sn.hif.contentWindow.document;} - catch(e){sn.hifDoc=null} - } - if (sn.hifDoc != null) - { - try {sn.hifDoc.execCommand("stop");} catch (e){} - } - } - window.__smartNav.init = function() - { - var sn = window.__smartNav; - window.__smartNav.form.__smartNavPostBack.value = 'true'; - document.detachEvent("onstop", sn.stopHif); - document.attachEvent("onstop", sn.stopHif); - try { if (window.event.returnValue == false) return; } catch(e) {} - sn.inPost = true; - if ((typeof(document.activeElement) != "undefined") && (document.activeElement != null)) - { - var ae = document.activeElement.id; - if (ae.length == 0) - ae = document.activeElement.name; - sn.ae = ae; - } - else - sn.ae = null; - try {document.selection.empty();} catch (e) {} - if ((typeof(sn.hif) == "undefined") || (sn.hif == null)) - { - sn.hif = document.all("__hifSmartNav"); - sn.hifDoc = sn.hif.contentWindow.document; - } - if ((typeof(sn.hifDoc) != "undefined") && (sn.hifDoc != null)) - try {sn.hifDoc.designMode = "On";} catch(e){}; - if ((typeof(sn.hif.parentElement) == "undefined") || (sn.hif.parentElement == null)) - document.body.appendChild(sn.hif); - var hif = sn.hif; - hif.detachEvent("onload", sn.update); - hif.attachEvent("onload", sn.update); - window.__smartNav.fInit = true; - }; - window.__smartNav.submit = function() - { - window.__smartNav.fInit = false; - try { window.__smartNav.init(); } catch(e) {} - if (window.__smartNav.fInit) { - window.__smartNav.form._submit(); - } - }; - window.__smartNav.attachForm = function() - { - var cf = document.forms; - for (var i=0; i"); - break; - } - } - var snfm = window.__smartNav.form; - if ((typeof(snfm) == "undefined") || (snfm == null)) return false; - var sft = snfm.target; - if (sft.length != 0 && sft.indexOf("__hifSmartNav") != 0) return false; - var sfc = snfm.action.split("?")[0]; - var url = window.location.href.split("?")[0]; - if (url.charAt(url.length-1) != '/' && url.lastIndexOf(sfc) + sfc.length != url.length) return false; - if (snfm.__formAttached == true) return true; - snfm.__formAttached = true; - snfm.attachEvent("onsubmit", window.__smartNav.init); - snfm._submit = snfm.submit; - snfm.submit = window.__smartNav.submit; - snfm.target = window.__smartNav.hifName; - return true; - }; - window.__smartNav.hifName = "__hifSmartNav" + (new Date()).getTime(); - window.__smartNav.ie5 = navigator.appVersion.indexOf("MSIE 5") > 0; - var rc = window.__smartNav.attachForm(); - var hif = document.all("__hifSmartNav"); - if ((typeof(snSrc) == "undefined") || (snSrc == null)) { - if (typeof(window.dialogHeight) != "undefined") { - snSrc = "IEsmartnav1"; - hif.src = snSrc; - } else { - snSrc = hif.src; - } - } - if (rc) - { - var fsn = frames["__hifSmartNav"]; - fsn.name = window.__smartNav.hifName; - window.__smartNav.siHif = hif.sourceIndex; - try { - if (fsn.document.location != snSrc) - { - fsn.document.designMode = "On"; - hif.attachEvent("onload",window.__smartNav.update); - window.__smartNav.hif = hif; - } - } - catch (e) { window.__smartNav.hif = hif; } - window.attachEvent("onbeforeunload", window.__smartNav.saveHistory); - } - else - window.__smartNav = null; -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/TreeView.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/TreeView.js deleted file mode 100644 index e49f26045..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/TreeView.js +++ /dev/null @@ -1,220 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/TreeView.js -function TreeView_HoverNode(data, node) { - if (!data) { - return; - } - node.hoverClass = data.hoverClass; - WebForm_AppendToClassName(node, data.hoverClass); - if (__nonMSDOMBrowser) { - node = node.childNodes[node.childNodes.length - 1]; - } - else { - node = node.children[node.children.length - 1]; - } - node.hoverHyperLinkClass = data.hoverHyperLinkClass; - WebForm_AppendToClassName(node, data.hoverHyperLinkClass); -} -function TreeView_GetNodeText(node) { - var trNode = WebForm_GetParentByTagName(node, "TR"); - var outerNodes; - if (trNode.childNodes[trNode.childNodes.length - 1].getElementsByTagName) { - outerNodes = trNode.childNodes[trNode.childNodes.length - 1].getElementsByTagName("A"); - if (!outerNodes || outerNodes.length == 0) { - outerNodes = trNode.childNodes[trNode.childNodes.length - 1].getElementsByTagName("SPAN"); - } - } - var textNode = (outerNodes && outerNodes.length > 0) ? - outerNodes[0].childNodes[0] : - trNode.childNodes[trNode.childNodes.length - 1].childNodes[0]; - return (textNode && textNode.nodeValue) ? textNode.nodeValue : ""; -} -function TreeView_PopulateNode(data, index, node, selectNode, selectImageNode, lineType, text, path, databound, datapath, parentIsLast) { - if (!data) { - return; - } - var context = new Object(); - context.data = data; - context.node = node; - context.selectNode = selectNode; - context.selectImageNode = selectImageNode; - context.lineType = lineType; - context.index = index; - context.isChecked = "f"; - var tr = WebForm_GetParentByTagName(node, "TR"); - if (tr) { - var checkbox = tr.getElementsByTagName("INPUT"); - if (checkbox && (checkbox.length > 0)) { - for (var i = 0; i < checkbox.length; i++) { - if (checkbox[i].type.toLowerCase() == "checkbox") { - if (checkbox[i].checked) { - context.isChecked = "t"; - } - break; - } - } - } - } - var param = index + "|" + data.lastIndex + "|" + databound + context.isChecked + parentIsLast + "|" + - text.length + "|" + text + datapath.length + "|" + datapath + path; - TreeView_PopulateNodeDoCallBack(context, param); -} -function TreeView_ProcessNodeData(result, context) { - var treeNode = context.node; - if (result.length > 0) { - var ci = result.indexOf("|", 0); - context.data.lastIndex = result.substring(0, ci); - ci = result.indexOf("|", ci + 1); - var newExpandState = result.substring(context.data.lastIndex.length + 1, ci); - context.data.expandState.value += newExpandState; - var chunk = result.substr(ci + 1); - var newChildren, table; - if (__nonMSDOMBrowser) { - var newDiv = document.createElement("div"); - newDiv.innerHTML = chunk; - table = WebForm_GetParentByTagName(treeNode, "TABLE"); - newChildren = null; - if ((typeof(table.nextSibling) == "undefined") || (table.nextSibling == null)) { - table.parentNode.insertBefore(newDiv.firstChild, table.nextSibling); - newChildren = table.previousSibling; - } - else { - table = table.nextSibling; - table.parentNode.insertBefore(newDiv.firstChild, table); - newChildren = table.previousSibling; - } - newChildren = document.getElementById(treeNode.id + "Nodes"); - } - else { - table = WebForm_GetParentByTagName(treeNode, "TABLE"); - table.insertAdjacentHTML("afterEnd", chunk); - newChildren = document.all[treeNode.id + "Nodes"]; - } - if ((typeof(newChildren) != "undefined") && (newChildren != null)) { - TreeView_ToggleNode(context.data, context.index, treeNode, context.lineType, newChildren); - treeNode.href = document.getElementById ? - "javascript:TreeView_ToggleNode(" + context.data.name + "," + context.index + ",document.getElementById('" + treeNode.id + "'),'" + context.lineType + "',document.getElementById('" + newChildren.id + "'))" : - "javascript:TreeView_ToggleNode(" + context.data.name + "," + context.index + "," + treeNode.id + ",'" + context.lineType + "'," + newChildren.id + ")"; - if ((typeof(context.selectNode) != "undefined") && (context.selectNode != null) && context.selectNode.href && - (context.selectNode.href.indexOf("javascript:TreeView_PopulateNode", 0) == 0)) { - context.selectNode.href = treeNode.href; - } - if ((typeof(context.selectImageNode) != "undefined") && (context.selectImageNode != null) && context.selectNode.href && - (context.selectImageNode.href.indexOf("javascript:TreeView_PopulateNode", 0) == 0)) { - context.selectImageNode.href = treeNode.href; - } - } - context.data.populateLog.value += context.index + ","; - } - else { - var img = treeNode.childNodes ? treeNode.childNodes[0] : treeNode.children[0]; - if ((typeof(img) != "undefined") && (img != null)) { - var lineType = context.lineType; - if (lineType == "l") { - img.src = context.data.images[13]; - } - else if (lineType == "t") { - img.src = context.data.images[10]; - } - else if (lineType == "-") { - img.src = context.data.images[16]; - } - else { - img.src = context.data.images[3]; - } - var pe; - if (__nonMSDOMBrowser) { - pe = treeNode.parentNode; - pe.insertBefore(img, treeNode); - pe.removeChild(treeNode); - } - else { - pe = treeNode.parentElement; - treeNode.style.visibility="hidden"; - treeNode.style.display="none"; - pe.insertAdjacentElement("afterBegin", img); - } - } - } -} -function TreeView_SelectNode(data, node, nodeId) { - if (!data) { - return; - } - if ((typeof(data.selectedClass) != "undefined") && (data.selectedClass != null)) { - var id = data.selectedNodeID.value; - if (id.length > 0) { - var selectedNode = document.getElementById(id); - if ((typeof(selectedNode) != "undefined") && (selectedNode != null)) { - WebForm_RemoveClassName(selectedNode, data.selectedHyperLinkClass); - selectedNode = WebForm_GetParentByTagName(selectedNode, "TD"); - WebForm_RemoveClassName(selectedNode, data.selectedClass); - } - } - WebForm_AppendToClassName(node, data.selectedHyperLinkClass); - node = WebForm_GetParentByTagName(node, "TD"); - WebForm_AppendToClassName(node, data.selectedClass) - } - data.selectedNodeID.value = nodeId; -} -function TreeView_ToggleNode(data, index, node, lineType, children) { - if (!data) { - return; - } - var img = node.childNodes[0]; - var newExpandState; - try { - if (children.style.display == "none") { - children.style.display = "block"; - newExpandState = "e"; - if ((typeof(img) != "undefined") && (img != null)) { - if (lineType == "l") { - img.src = data.images[15]; - } - else if (lineType == "t") { - img.src = data.images[12]; - } - else if (lineType == "-") { - img.src = data.images[18]; - } - else { - img.src = data.images[5]; - } - img.alt = data.collapseToolTip.replace(/\{0\}/, TreeView_GetNodeText(node)); - } - } - else { - children.style.display = "none"; - newExpandState = "c"; - if ((typeof(img) != "undefined") && (img != null)) { - if (lineType == "l") { - img.src = data.images[14]; - } - else if (lineType == "t") { - img.src = data.images[11]; - } - else if (lineType == "-") { - img.src = data.images[17]; - } - else { - img.src = data.images[4]; - } - img.alt = data.expandToolTip.replace(/\{0\}/, TreeView_GetNodeText(node)); - } - } - } - catch(e) {} - data.expandState.value = data.expandState.value.substring(0, index) + newExpandState + data.expandState.value.slice(index + 1); -} -function TreeView_UnhoverNode(node) { - if (!node.hoverClass) { - return; - } - WebForm_RemoveClassName(node, node.hoverClass); - if (__nonMSDOMBrowser) { - node = node.childNodes[node.childNodes.length - 1]; - } - else { - node = node.children[node.children.length - 1]; - } - WebForm_RemoveClassName(node, node.hoverHyperLinkClass); -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebForms.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebForms.js deleted file mode 100644 index 699284893..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebForms.js +++ /dev/null @@ -1,567 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/WebForms.js -function WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit) { - this.eventTarget = eventTarget; - this.eventArgument = eventArgument; - this.validation = validation; - this.validationGroup = validationGroup; - this.actionUrl = actionUrl; - this.trackFocus = trackFocus; - this.clientSubmit = clientSubmit; -} -function WebForm_DoPostBackWithOptions(options) { - var validationResult = true; - if (options.validation) { - if (typeof(Page_ClientValidate) == 'function') { - validationResult = Page_ClientValidate(options.validationGroup); - } - } - if (validationResult) { - if ((typeof(options.actionUrl) != "undefined") && (options.actionUrl != null) && (options.actionUrl.length > 0)) { - theForm.action = options.actionUrl; - } - if (options.trackFocus) { - var lastFocus = theForm.elements["__LASTFOCUS"]; - if ((typeof(lastFocus) != "undefined") && (lastFocus != null)) { - if (typeof(document.activeElement) == "undefined") { - lastFocus.value = options.eventTarget; - } - else { - var active = document.activeElement; - if ((typeof(active) != "undefined") && (active != null)) { - if ((typeof(active.id) != "undefined") && (active.id != null) && (active.id.length > 0)) { - lastFocus.value = active.id; - } - else if (typeof(active.name) != "undefined") { - lastFocus.value = active.name; - } - } - } - } - } - } - if (options.clientSubmit) { - __doPostBack(options.eventTarget, options.eventArgument); - } -} -var __pendingCallbacks = new Array(); -var __synchronousCallBackIndex = -1; -function WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync) { - var postData = __theFormPostData + - "__CALLBACKID=" + WebForm_EncodeCallback(eventTarget) + - "&__CALLBACKPARAM=" + WebForm_EncodeCallback(eventArgument); - if (theForm["__EVENTVALIDATION"]) { - postData += "&__EVENTVALIDATION=" + WebForm_EncodeCallback(theForm["__EVENTVALIDATION"].value); - } - var xmlRequest,e; - try { - xmlRequest = new XMLHttpRequest(); - } - catch(e) { - try { - xmlRequest = new ActiveXObject("Microsoft.XMLHTTP"); - } - catch(e) { - } - } - var setRequestHeaderMethodExists = true; - try { - setRequestHeaderMethodExists = (xmlRequest && xmlRequest.setRequestHeader); - } - catch(e) {} - var callback = new Object(); - callback.eventCallback = eventCallback; - callback.context = context; - callback.errorCallback = errorCallback; - callback.async = useAsync; - var callbackIndex = WebForm_FillFirstAvailableSlot(__pendingCallbacks, callback); - if (!useAsync) { - if (__synchronousCallBackIndex != -1) { - __pendingCallbacks[__synchronousCallBackIndex] = null; - } - __synchronousCallBackIndex = callbackIndex; - } - if (setRequestHeaderMethodExists) { - xmlRequest.onreadystatechange = WebForm_CallbackComplete; - callback.xmlRequest = xmlRequest; - // e.g. http: - var action = theForm.action || document.location.pathname, fragmentIndex = action.indexOf('#'); - if (fragmentIndex !== -1) { - action = action.substr(0, fragmentIndex); - } - if (!__nonMSDOMBrowser) { - var queryIndex = action.indexOf('?'); - if (queryIndex !== -1) { - var path = action.substr(0, queryIndex); - if (path.indexOf("%") === -1) { - action = encodeURI(path) + action.substr(queryIndex); - } - } - else if (action.indexOf("%") === -1) { - action = encodeURI(action); - } - } - xmlRequest.open("POST", action, true); - xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); - xmlRequest.send(postData); - return; - } - callback.xmlRequest = new Object(); - var callbackFrameID = "__CALLBACKFRAME" + callbackIndex; - var xmlRequestFrame = document.frames[callbackFrameID]; - if (!xmlRequestFrame) { - xmlRequestFrame = document.createElement("IFRAME"); - xmlRequestFrame.width = "1"; - xmlRequestFrame.height = "1"; - xmlRequestFrame.frameBorder = "0"; - xmlRequestFrame.id = callbackFrameID; - xmlRequestFrame.name = callbackFrameID; - xmlRequestFrame.style.position = "absolute"; - xmlRequestFrame.style.top = "-100px" - xmlRequestFrame.style.left = "-100px"; - try { - if (callBackFrameUrl) { - xmlRequestFrame.src = callBackFrameUrl; - } - } - catch(e) {} - document.body.appendChild(xmlRequestFrame); - } - var interval = window.setInterval(function() { - xmlRequestFrame = document.frames[callbackFrameID]; - if (xmlRequestFrame && xmlRequestFrame.document) { - window.clearInterval(interval); - xmlRequestFrame.document.write(""); - xmlRequestFrame.document.close(); - xmlRequestFrame.document.write('
    '); - xmlRequestFrame.document.close(); - xmlRequestFrame.document.forms[0].action = theForm.action; - var count = __theFormPostCollection.length; - var element; - for (var i = 0; i < count; i++) { - element = __theFormPostCollection[i]; - if (element) { - var fieldElement = xmlRequestFrame.document.createElement("INPUT"); - fieldElement.type = "hidden"; - fieldElement.name = element.name; - fieldElement.value = element.value; - xmlRequestFrame.document.forms[0].appendChild(fieldElement); - } - } - var callbackIdFieldElement = xmlRequestFrame.document.createElement("INPUT"); - callbackIdFieldElement.type = "hidden"; - callbackIdFieldElement.name = "__CALLBACKID"; - callbackIdFieldElement.value = eventTarget; - xmlRequestFrame.document.forms[0].appendChild(callbackIdFieldElement); - var callbackParamFieldElement = xmlRequestFrame.document.createElement("INPUT"); - callbackParamFieldElement.type = "hidden"; - callbackParamFieldElement.name = "__CALLBACKPARAM"; - callbackParamFieldElement.value = eventArgument; - xmlRequestFrame.document.forms[0].appendChild(callbackParamFieldElement); - if (theForm["__EVENTVALIDATION"]) { - var callbackValidationFieldElement = xmlRequestFrame.document.createElement("INPUT"); - callbackValidationFieldElement.type = "hidden"; - callbackValidationFieldElement.name = "__EVENTVALIDATION"; - callbackValidationFieldElement.value = theForm["__EVENTVALIDATION"].value; - xmlRequestFrame.document.forms[0].appendChild(callbackValidationFieldElement); - } - var callbackIndexFieldElement = xmlRequestFrame.document.createElement("INPUT"); - callbackIndexFieldElement.type = "hidden"; - callbackIndexFieldElement.name = "__CALLBACKINDEX"; - callbackIndexFieldElement.value = callbackIndex; - xmlRequestFrame.document.forms[0].appendChild(callbackIndexFieldElement); - xmlRequestFrame.document.forms[0].submit(); - } - }, 10); -} -function WebForm_CallbackComplete() { - for (var i = 0; i < __pendingCallbacks.length; i++) { - callbackObject = __pendingCallbacks[i]; - if (callbackObject && callbackObject.xmlRequest && (callbackObject.xmlRequest.readyState == 4)) { - if (!__pendingCallbacks[i].async) { - __synchronousCallBackIndex = -1; - } - __pendingCallbacks[i] = null; - var callbackFrameID = "__CALLBACKFRAME" + i; - var xmlRequestFrame = document.getElementById(callbackFrameID); - if (xmlRequestFrame) { - xmlRequestFrame.parentNode.removeChild(xmlRequestFrame); - } - WebForm_ExecuteCallback(callbackObject); - } - } -} -function WebForm_ExecuteCallback(callbackObject) { - var response = callbackObject.xmlRequest.responseText; - if (response.charAt(0) == "s") { - if ((typeof(callbackObject.eventCallback) != "undefined") && (callbackObject.eventCallback != null)) { - callbackObject.eventCallback(response.substring(1), callbackObject.context); - } - } - else if (response.charAt(0) == "e") { - if ((typeof(callbackObject.errorCallback) != "undefined") && (callbackObject.errorCallback != null)) { - callbackObject.errorCallback(response.substring(1), callbackObject.context); - } - } - else { - var separatorIndex = response.indexOf("|"); - if (separatorIndex != -1) { - var validationFieldLength = parseInt(response.substring(0, separatorIndex)); - if (!isNaN(validationFieldLength)) { - var validationField = response.substring(separatorIndex + 1, separatorIndex + validationFieldLength + 1); - if (validationField != "") { - var validationFieldElement = theForm["__EVENTVALIDATION"]; - if (!validationFieldElement) { - validationFieldElement = document.createElement("INPUT"); - validationFieldElement.type = "hidden"; - validationFieldElement.name = "__EVENTVALIDATION"; - theForm.appendChild(validationFieldElement); - } - validationFieldElement.value = validationField; - } - if ((typeof(callbackObject.eventCallback) != "undefined") && (callbackObject.eventCallback != null)) { - callbackObject.eventCallback(response.substring(separatorIndex + validationFieldLength + 1), callbackObject.context); - } - } - } - } -} -function WebForm_FillFirstAvailableSlot(array, element) { - var i; - for (i = 0; i < array.length; i++) { - if (!array[i]) break; - } - array[i] = element; - return i; -} -var __nonMSDOMBrowser = (window.navigator.appName.toLowerCase().indexOf('explorer') == -1); -var __theFormPostData = ""; -var __theFormPostCollection = new Array(); -var __callbackTextTypes = /^(text|password|hidden|search|tel|url|email|number|range|color|datetime|date|month|week|time|datetime-local)$/i; -function WebForm_InitCallback() { - var formElements = theForm.elements, - count = formElements.length, - element; - for (var i = 0; i < count; i++) { - element = formElements[i]; - var tagName = element.tagName.toLowerCase(); - if (tagName == "input") { - var type = element.type; - if ((__callbackTextTypes.test(type) || ((type == "checkbox" || type == "radio") && element.checked)) - && (element.id != "__EVENTVALIDATION")) { - WebForm_InitCallbackAddField(element.name, element.value); - } - } - else if (tagName == "select") { - var selectCount = element.options.length; - for (var j = 0; j < selectCount; j++) { - var selectChild = element.options[j]; - if (selectChild.selected == true) { - WebForm_InitCallbackAddField(element.name, element.value); - } - } - } - else if (tagName == "textarea") { - WebForm_InitCallbackAddField(element.name, element.value); - } - } -} -function WebForm_InitCallbackAddField(name, value) { - var nameValue = new Object(); - nameValue.name = name; - nameValue.value = value; - __theFormPostCollection[__theFormPostCollection.length] = nameValue; - __theFormPostData += WebForm_EncodeCallback(name) + "=" + WebForm_EncodeCallback(value) + "&"; -} -function WebForm_EncodeCallback(parameter) { - if (encodeURIComponent) { - return encodeURIComponent(parameter); - } - else { - return escape(parameter); - } -} -var __disabledControlArray = new Array(); -function WebForm_ReEnableControls() { - if (typeof(__enabledControlArray) == 'undefined') { - return false; - } - var disabledIndex = 0; - for (var i = 0; i < __enabledControlArray.length; i++) { - var c; - if (__nonMSDOMBrowser) { - c = document.getElementById(__enabledControlArray[i]); - } - else { - c = document.all[__enabledControlArray[i]]; - } - if ((typeof(c) != "undefined") && (c != null) && (c.disabled == true)) { - c.disabled = false; - __disabledControlArray[disabledIndex++] = c; - } - } - setTimeout("WebForm_ReDisableControls()", 0); - return true; -} -function WebForm_ReDisableControls() { - for (var i = 0; i < __disabledControlArray.length; i++) { - __disabledControlArray[i].disabled = true; - } -} -function WebForm_SimulateClick(element, event) { - var clickEvent; - if (element) { - if (element.click) { - element.click(); - } else { - clickEvent = document.createEvent("MouseEvents"); - clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); - if (!element.dispatchEvent(clickEvent)) { - return true; - } - } - event.cancelBubble = true; - if (event.stopPropagation) { - event.stopPropagation(); - } - return false; - } - return true; -} -function WebForm_FireDefaultButton(event, target) { - if (event.keyCode == 13) { - var src = event.srcElement || event.target; - if (src && - ((src.tagName.toLowerCase() == "input") && - (src.type.toLowerCase() == "submit" || src.type.toLowerCase() == "button")) || - ((src.tagName.toLowerCase() == "a") && - (src.href != null) && (src.href != "")) || - (src.tagName.toLowerCase() == "textarea")) { - return true; - } - var defaultButton; - if (__nonMSDOMBrowser) { - defaultButton = document.getElementById(target); - } - else { - defaultButton = document.all[target]; - } - if (defaultButton) { - return WebForm_SimulateClick(defaultButton, event); - } - } - return true; -} -function WebForm_GetScrollX() { - if (__nonMSDOMBrowser) { - return window.pageXOffset; - } - else { - if (document.documentElement && document.documentElement.scrollLeft) { - return document.documentElement.scrollLeft; - } - else if (document.body) { - return document.body.scrollLeft; - } - } - return 0; -} -function WebForm_GetScrollY() { - if (__nonMSDOMBrowser) { - return window.pageYOffset; - } - else { - if (document.documentElement && document.documentElement.scrollTop) { - return document.documentElement.scrollTop; - } - else if (document.body) { - return document.body.scrollTop; - } - } - return 0; -} -function WebForm_SaveScrollPositionSubmit() { - if (__nonMSDOMBrowser) { - theForm.elements['__SCROLLPOSITIONY'].value = window.pageYOffset; - theForm.elements['__SCROLLPOSITIONX'].value = window.pageXOffset; - } - else { - theForm.__SCROLLPOSITIONX.value = WebForm_GetScrollX(); - theForm.__SCROLLPOSITIONY.value = WebForm_GetScrollY(); - } - if ((typeof(this.oldSubmit) != "undefined") && (this.oldSubmit != null)) { - return this.oldSubmit(); - } - return true; -} -function WebForm_SaveScrollPositionOnSubmit() { - theForm.__SCROLLPOSITIONX.value = WebForm_GetScrollX(); - theForm.__SCROLLPOSITIONY.value = WebForm_GetScrollY(); - if ((typeof(this.oldOnSubmit) != "undefined") && (this.oldOnSubmit != null)) { - return this.oldOnSubmit(); - } - return true; -} -function WebForm_RestoreScrollPosition() { - if (__nonMSDOMBrowser) { - window.scrollTo(theForm.elements['__SCROLLPOSITIONX'].value, theForm.elements['__SCROLLPOSITIONY'].value); - } - else { - window.scrollTo(theForm.__SCROLLPOSITIONX.value, theForm.__SCROLLPOSITIONY.value); - } - if ((typeof(theForm.oldOnLoad) != "undefined") && (theForm.oldOnLoad != null)) { - return theForm.oldOnLoad(); - } - return true; -} -function WebForm_TextBoxKeyHandler(event) { - if (event.keyCode == 13) { - var target; - if (__nonMSDOMBrowser) { - target = event.target; - } - else { - target = event.srcElement; - } - if ((typeof(target) != "undefined") && (target != null)) { - if (typeof(target.onchange) != "undefined") { - target.onchange(); - event.cancelBubble = true; - if (event.stopPropagation) event.stopPropagation(); - return false; - } - } - } - return true; -} -function WebForm_TrimString(value) { - return value.replace(/^\s+|\s+$/g, '') -} -function WebForm_AppendToClassName(element, className) { - var currentClassName = ' ' + WebForm_TrimString(element.className) + ' '; - className = WebForm_TrimString(className); - var index = currentClassName.indexOf(' ' + className + ' '); - if (index === -1) { - element.className = (element.className === '') ? className : element.className + ' ' + className; - } -} -function WebForm_RemoveClassName(element, className) { - var currentClassName = ' ' + WebForm_TrimString(element.className) + ' '; - className = WebForm_TrimString(className); - var index = currentClassName.indexOf(' ' + className + ' '); - if (index >= 0) { - element.className = WebForm_TrimString(currentClassName.substring(0, index) + ' ' + - currentClassName.substring(index + className.length + 1, currentClassName.length)); - } -} -function WebForm_GetElementById(elementId) { - if (document.getElementById) { - return document.getElementById(elementId); - } - else if (document.all) { - return document.all[elementId]; - } - else return null; -} -function WebForm_GetElementByTagName(element, tagName) { - var elements = WebForm_GetElementsByTagName(element, tagName); - if (elements && elements.length > 0) { - return elements[0]; - } - else return null; -} -function WebForm_GetElementsByTagName(element, tagName) { - if (element && tagName) { - if (element.getElementsByTagName) { - return element.getElementsByTagName(tagName); - } - if (element.all && element.all.tags) { - return element.all.tags(tagName); - } - } - return null; -} -function WebForm_GetElementDir(element) { - if (element) { - if (element.dir) { - return element.dir; - } - return WebForm_GetElementDir(element.parentNode); - } - return "ltr"; -} -function WebForm_GetElementPosition(element) { - var result = new Object(); - result.x = 0; - result.y = 0; - result.width = 0; - result.height = 0; - if (element.offsetParent) { - result.x = element.offsetLeft; - result.y = element.offsetTop; - var parent = element.offsetParent; - while (parent) { - result.x += parent.offsetLeft; - result.y += parent.offsetTop; - var parentTagName = parent.tagName.toLowerCase(); - if (parentTagName != "table" && - parentTagName != "body" && - parentTagName != "html" && - parentTagName != "div" && - parent.clientTop && - parent.clientLeft) { - result.x += parent.clientLeft; - result.y += parent.clientTop; - } - parent = parent.offsetParent; - } - } - else if (element.left && element.top) { - result.x = element.left; - result.y = element.top; - } - else { - if (element.x) { - result.x = element.x; - } - if (element.y) { - result.y = element.y; - } - } - if (element.offsetWidth && element.offsetHeight) { - result.width = element.offsetWidth; - result.height = element.offsetHeight; - } - else if (element.style && element.style.pixelWidth && element.style.pixelHeight) { - result.width = element.style.pixelWidth; - result.height = element.style.pixelHeight; - } - return result; -} -function WebForm_GetParentByTagName(element, tagName) { - var parent = element.parentNode; - var upperTagName = tagName.toUpperCase(); - while (parent && (parent.tagName.toUpperCase() != upperTagName)) { - parent = parent.parentNode ? parent.parentNode : parent.parentElement; - } - return parent; -} -function WebForm_SetElementHeight(element, height) { - if (element && element.style) { - element.style.height = height + "px"; - } -} -function WebForm_SetElementWidth(element, width) { - if (element && element.style) { - element.style.width = width + "px"; - } -} -function WebForm_SetElementX(element, x) { - if (element && element.style) { - element.style.left = x + "px"; - } -} -function WebForm_SetElementY(element, y) { - if (element && element.style) { - element.style.top = y + "px"; - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebParts.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebParts.js deleted file mode 100644 index 7a8d0abae..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebParts.js +++ /dev/null @@ -1,647 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/WebParts.js -var __wpm = null; -function Point(x, y) { - this.x = x; - this.y = y; -} -function __wpTranslateOffset(x, y, offsetElement, relativeToElement, includeScroll) { - while ((typeof(offsetElement) != "undefined") && (offsetElement != null) && (offsetElement != relativeToElement)) { - x += offsetElement.offsetLeft; - y += offsetElement.offsetTop; - var tagName = offsetElement.tagName; - if ((tagName != "TABLE") && (tagName != "BODY")) { - x += offsetElement.clientLeft; - y += offsetElement.clientTop; - } - if (includeScroll && (tagName != "BODY")) { - x -= offsetElement.scrollLeft; - y -= offsetElement.scrollTop; - } - offsetElement = offsetElement.offsetParent; - } - return new Point(x, y); -} -function __wpGetPageEventLocation(event, includeScroll) { - if ((typeof(event) == "undefined") || (event == null)) { - event = window.event; - } - return __wpTranslateOffset(event.offsetX, event.offsetY, event.srcElement, null, includeScroll); -} -function __wpClearSelection() { - document.selection.empty(); -} -function WebPart(webPartElement, webPartTitleElement, zone, zoneIndex, allowZoneChange) { - this.webPartElement = webPartElement; - this.allowZoneChange = allowZoneChange; - this.zone = zone; - this.zoneIndex = zoneIndex; - this.title = ((typeof(webPartTitleElement) != "undefined") && (webPartTitleElement != null)) ? - webPartTitleElement.innerText : ""; - webPartElement.__webPart = this; - if ((typeof(webPartTitleElement) != "undefined") && (webPartTitleElement != null)) { - webPartTitleElement.style.cursor = "move"; - webPartTitleElement.attachEvent("onmousedown", WebPart_OnMouseDown); - webPartElement.attachEvent("ondragstart", WebPart_OnDragStart); - webPartElement.attachEvent("ondrag", WebPart_OnDrag); - webPartElement.attachEvent("ondragend", WebPart_OnDragEnd); - } - this.UpdatePosition = WebPart_UpdatePosition; - this.Dispose = WebPart_Dispose; -} -function WebPart_Dispose() { - this.webPartElement.__webPart = null -} -function WebPart_OnMouseDown() { - var currentEvent = window.event; - var draggedWebPart = WebPart_GetParentWebPartElement(currentEvent.srcElement); - if ((typeof(draggedWebPart) == "undefined") || (draggedWebPart == null)) { - return; - } - document.selection.empty(); - try { - __wpm.draggedWebPart = draggedWebPart; - __wpm.DragDrop(); - } - catch (e) { - __wpm.draggedWebPart = draggedWebPart; - window.setTimeout("__wpm.DragDrop()", 0); - } - currentEvent.returnValue = false; - currentEvent.cancelBubble = true; -} -function WebPart_OnDragStart() { - var currentEvent = window.event; - var webPartElement = currentEvent.srcElement; - if ((typeof(webPartElement.__webPart) == "undefined") || (webPartElement.__webPart == null)) { - currentEvent.returnValue = false; - currentEvent.cancelBubble = true; - return; - } - var dataObject = currentEvent.dataTransfer; - dataObject.effectAllowed = __wpm.InitiateWebPartDragDrop(webPartElement); -} -function WebPart_OnDrag() { - __wpm.ContinueWebPartDragDrop(); -} -function WebPart_OnDragEnd() { - __wpm.CompleteWebPartDragDrop(); -} -function WebPart_GetParentWebPartElement(containedElement) { - var elem = containedElement; - while ((typeof(elem.__webPart) == "undefined") || (elem.__webPart == null)) { - elem = elem.parentElement; - if ((typeof(elem) == "undefined") || (elem == null)) { - break; - } - } - return elem; -} -function WebPart_UpdatePosition() { - var location = __wpTranslateOffset(0, 0, this.webPartElement, null, false); - this.middleX = location.x + this.webPartElement.offsetWidth / 2; - this.middleY = location.y + this.webPartElement.offsetHeight / 2; -} -function Zone(zoneElement, zoneIndex, uniqueID, isVertical, allowLayoutChange, highlightColor) { - var webPartTable = null; - if (zoneElement.rows.length == 1) { - webPartTableContainer = zoneElement.rows[0].cells[0]; - } - else { - webPartTableContainer = zoneElement.rows[1].cells[0]; - } - var i; - for (i = 0; i < webPartTableContainer.childNodes.length; i++) { - var node = webPartTableContainer.childNodes[i]; - if (node.tagName == "TABLE") { - webPartTable = node; - break; - } - } - this.zoneElement = zoneElement; - this.zoneIndex = zoneIndex; - this.webParts = new Array(); - this.uniqueID = uniqueID; - this.isVertical = isVertical; - this.allowLayoutChange = allowLayoutChange; - this.allowDrop = false; - this.webPartTable = webPartTable; - this.highlightColor = highlightColor; - this.savedBorderColor = (webPartTable != null) ? webPartTable.style.borderColor : null; - this.dropCueElements = new Array(); - if (webPartTable != null) { - if (isVertical) { - for (i = 0; i < webPartTable.rows.length; i += 2) { - this.dropCueElements[i / 2] = webPartTable.rows[i].cells[0].childNodes[0]; - } - } - else { - for (i = 0; i < webPartTable.rows[0].cells.length; i += 2) { - this.dropCueElements[i / 2] = webPartTable.rows[0].cells[i].childNodes[0]; - } - } - } - this.AddWebPart = Zone_AddWebPart; - this.GetWebPartIndex = Zone_GetWebPartIndex; - this.ToggleDropCues = Zone_ToggleDropCues; - this.UpdatePosition = Zone_UpdatePosition; - this.Dispose = Zone_Dispose; - webPartTable.__zone = this; - webPartTable.attachEvent("ondragenter", Zone_OnDragEnter); - webPartTable.attachEvent("ondrop", Zone_OnDrop); -} -function Zone_Dispose() { - for (var i = 0; i < this.webParts.length; i++) { - this.webParts[i].Dispose(); - } - this.webPartTable.__zone = null; -} -function Zone_OnDragEnter() { - var handled = __wpm.ProcessWebPartDragEnter(); - var currentEvent = window.event; - if (handled) { - currentEvent.returnValue = false; - currentEvent.cancelBubble = true; - } -} -function Zone_OnDragOver() { - var handled = __wpm.ProcessWebPartDragOver(); - var currentEvent = window.event; - if (handled) { - currentEvent.returnValue = false; - currentEvent.cancelBubble = true; - } -} -function Zone_OnDrop() { - var handled = __wpm.ProcessWebPartDrop(); - var currentEvent = window.event; - if (handled) { - currentEvent.returnValue = false; - currentEvent.cancelBubble = true; - } -} -function Zone_GetParentZoneElement(containedElement) { - var elem = containedElement; - while ((typeof(elem.__zone) == "undefined") || (elem.__zone == null)) { - elem = elem.parentElement; - if ((typeof(elem) == "undefined") || (elem == null)) { - break; - } - } - return elem; -} -function Zone_AddWebPart(webPartElement, webPartTitleElement, allowZoneChange) { - var webPart = null; - var zoneIndex = this.webParts.length; - if (this.allowLayoutChange && __wpm.IsDragDropEnabled()) { - webPart = new WebPart(webPartElement, webPartTitleElement, this, zoneIndex, allowZoneChange); - } - else { - webPart = new WebPart(webPartElement, null, this, zoneIndex, allowZoneChange); - } - this.webParts[zoneIndex] = webPart; - return webPart; -} -function Zone_ToggleDropCues(show, index, ignoreOutline) { - if (ignoreOutline == false) { - this.webPartTable.style.borderColor = (show ? this.highlightColor : this.savedBorderColor); - } - if (index == -1) { - return; - } - var dropCue = this.dropCueElements[index]; - if (dropCue && dropCue.style) { - if (dropCue.style.height == "100%" && !dropCue.webPartZoneHorizontalCueResized) { - var oldParentHeight = dropCue.parentElement.clientHeight; - var realHeight = oldParentHeight - 10; - dropCue.style.height = realHeight + "px"; - var dropCueVerticalBar = dropCue.getElementsByTagName("DIV")[0]; - if (dropCueVerticalBar && dropCueVerticalBar.style) { - dropCueVerticalBar.style.height = dropCue.style.height; - var heightDiff = (dropCue.parentElement.clientHeight - oldParentHeight); - if (heightDiff) { - dropCue.style.height = (realHeight - heightDiff) + "px"; - dropCueVerticalBar.style.height = dropCue.style.height; - } - } - dropCue.webPartZoneHorizontalCueResized = true; - } - dropCue.style.visibility = (show ? "visible" : "hidden"); - } -} -function Zone_GetWebPartIndex(location) { - var x = location.x; - var y = location.y; - if ((x < this.webPartTableLeft) || (x > this.webPartTableRight) || - (y < this.webPartTableTop) || (y > this.webPartTableBottom)) { - return -1; - } - var vertical = this.isVertical; - var webParts = this.webParts; - var webPartsCount = webParts.length; - for (var i = 0; i < webPartsCount; i++) { - var webPart = webParts[i]; - if (vertical) { - if (y < webPart.middleY) { - return i; - } - } - else { - if (x < webPart.middleX) { - return i; - } - } - } - return webPartsCount; -} -function Zone_UpdatePosition() { - var topLeft = __wpTranslateOffset(0, 0, this.webPartTable, null, false); - this.webPartTableLeft = topLeft.x; - this.webPartTableTop = topLeft.y; - this.webPartTableRight = (this.webPartTable != null) ? topLeft.x + this.webPartTable.offsetWidth : topLeft.x; - this.webPartTableBottom = (this.webPartTable != null) ? topLeft.y + this.webPartTable.offsetHeight : topLeft.y; - for (var i = 0; i < this.webParts.length; i++) { - this.webParts[i].UpdatePosition(); - } -} -function WebPartDragState(webPartElement, effect) { - this.webPartElement = webPartElement; - this.dropZoneElement = null; - this.dropIndex = -1; - this.effect = effect; - this.dropped = false; -} -function WebPartMenu(menuLabelElement, menuDropDownElement, menuElement) { - this.menuLabelElement = menuLabelElement; - this.menuDropDownElement = menuDropDownElement; - this.menuElement = menuElement; - this.menuLabelElement.__menu = this; - this.menuLabelElement.attachEvent('onclick', WebPartMenu_OnClick); - this.menuLabelElement.attachEvent('onkeypress', WebPartMenu_OnKeyPress); - this.menuLabelElement.attachEvent('onmouseenter', WebPartMenu_OnMouseEnter); - this.menuLabelElement.attachEvent('onmouseleave', WebPartMenu_OnMouseLeave); - if ((typeof(this.menuDropDownElement) != "undefined") && (this.menuDropDownElement != null)) { - this.menuDropDownElement.__menu = this; - } - this.menuItemStyle = ""; - this.menuItemHoverStyle = ""; - this.popup = null; - this.hoverClassName = ""; - this.hoverColor = ""; - this.oldColor = this.menuLabelElement.style.color; - this.oldTextDecoration = this.menuLabelElement.style.textDecoration; - this.oldClassName = this.menuLabelElement.className; - this.Show = WebPartMenu_Show; - this.Hide = WebPartMenu_Hide; - this.Hover = WebPartMenu_Hover; - this.Unhover = WebPartMenu_Unhover; - this.Dispose = WebPartMenu_Dispose; - var menu = this; - this.disposeDelegate = function() { menu.Dispose(); }; - window.attachEvent('onunload', this.disposeDelegate); -} -function WebPartMenu_Dispose() { - this.menuLabelElement.__menu = null; - this.menuDropDownElement.__menu = null; - window.detachEvent('onunload', this.disposeDelegate); -} -function WebPartMenu_Show() { - if ((typeof(__wpm.menu) != "undefined") && (__wpm.menu != null)) { - __wpm.menu.Hide(); - } - var menuHTML = - "" + - this.menuElement.innerHTML + - ""; - var width = 16; - var height = 16; - this.popup = window.createPopup(); - __wpm.menu = this; - var popupDocument = this.popup.document; - popupDocument.write(menuHTML); - this.popup.show(0, 0, width, height); - var popupBody = popupDocument.body; - width = popupBody.scrollWidth; - height = popupBody.scrollHeight; - if (width < this.menuLabelElement.offsetWidth) { - width = this.menuLabelElement.offsetWidth + 16; - } - if (this.menuElement.innerHTML.indexOf("progid:DXImageTransform.Microsoft.Shadow") != -1) { - popupBody.style.paddingRight = "4px"; - } - popupBody.__wpm = __wpm; - popupBody.__wpmDeleteWarning = __wpmDeleteWarning; - popupBody.__wpmCloseProviderWarning = __wpmCloseProviderWarning; - popupBody.popup = this.popup; - this.popup.hide(); - this.popup.show(0, this.menuLabelElement.offsetHeight, width, height, this.menuLabelElement); -} -function WebPartMenu_Hide() { - if (__wpm.menu == this) { - __wpm.menu = null; - if ((typeof(this.popup) != "undefined") && (this.popup != null)) { - this.popup.hide(); - this.popup = null; - } - } -} -function WebPartMenu_Hover() { - if (this.labelHoverClassName != "") { - this.menuLabelElement.className = this.menuLabelElement.className + " " + this.labelHoverClassName; - } - if (this.labelHoverColor != "") { - this.menuLabelElement.style.color = this.labelHoverColor; - } -} -function WebPartMenu_Unhover() { - if (this.labelHoverClassName != "") { - this.menuLabelElement.style.textDecoration = this.oldTextDecoration; - this.menuLabelElement.className = this.oldClassName; - } - if (this.labelHoverColor != "") { - this.menuLabelElement.style.color = this.oldColor; - } -} -function WebPartMenu_OnClick() { - var menu = window.event.srcElement.__menu; - if ((typeof(menu) != "undefined") && (menu != null)) { - window.event.returnValue = false; - window.event.cancelBubble = true; - menu.Show(); - } -} -function WebPartMenu_OnKeyPress() { - if (window.event.keyCode == 13) { - var menu = window.event.srcElement.__menu; - if ((typeof(menu) != "undefined") && (menu != null)) { - window.event.returnValue = false; - window.event.cancelBubble = true; - menu.Show(); - } - } -} -function WebPartMenu_OnMouseEnter() { - var menu = window.event.srcElement.__menu; - if ((typeof(menu) != "undefined") && (menu != null)) { - menu.Hover(); - } -} -function WebPartMenu_OnMouseLeave() { - var menu = window.event.srcElement.__menu; - if ((typeof(menu) != "undefined") && (menu != null)) { - menu.Unhover(); - } -} -function WebPartManager() { - this.overlayContainerElement = null; - this.zones = new Array(); - this.dragState = null; - this.menu = null; - this.draggedWebPart = null; - this.AddZone = WebPartManager_AddZone; - this.IsDragDropEnabled = WebPartManager_IsDragDropEnabled; - this.DragDrop = WebPartManager_DragDrop; - this.InitiateWebPartDragDrop = WebPartManager_InitiateWebPartDragDrop; - this.CompleteWebPartDragDrop = WebPartManager_CompleteWebPartDragDrop; - this.ContinueWebPartDragDrop = WebPartManager_ContinueWebPartDragDrop; - this.ProcessWebPartDragEnter = WebPartManager_ProcessWebPartDragEnter; - this.ProcessWebPartDragOver = WebPartManager_ProcessWebPartDragOver; - this.ProcessWebPartDrop = WebPartManager_ProcessWebPartDrop; - this.ShowHelp = WebPartManager_ShowHelp; - this.ExportWebPart = WebPartManager_ExportWebPart; - this.Execute = WebPartManager_Execute; - this.SubmitPage = WebPartManager_SubmitPage; - this.UpdatePositions = WebPartManager_UpdatePositions; - window.attachEvent("onunload", WebPartManager_Dispose); -} -function WebPartManager_Dispose() { - for (var i = 0; i < __wpm.zones.length; i++) { - __wpm.zones[i].Dispose(); - } - window.detachEvent("onunload", WebPartManager_Dispose); -} -function WebPartManager_AddZone(zoneElement, uniqueID, isVertical, allowLayoutChange, highlightColor) { - var zoneIndex = this.zones.length; - var zone = new Zone(zoneElement, zoneIndex, uniqueID, isVertical, allowLayoutChange, highlightColor); - this.zones[zoneIndex] = zone; - return zone; -} -function WebPartManager_IsDragDropEnabled() { - return ((typeof(this.overlayContainerElement) != "undefined") && (this.overlayContainerElement != null)); -} -function WebPartManager_DragDrop() { - if ((typeof(this.draggedWebPart) != "undefined") && (this.draggedWebPart != null)) { - var tempWebPart = this.draggedWebPart; - this.draggedWebPart = null; - tempWebPart.dragDrop(); - window.setTimeout("__wpClearSelection()", 0); - } -} -function WebPartManager_InitiateWebPartDragDrop(webPartElement) { - var webPart = webPartElement.__webPart; - this.UpdatePositions(); - this.dragState = new WebPartDragState(webPartElement, "move"); - var location = __wpGetPageEventLocation(window.event, true); - var overlayContainerElement = this.overlayContainerElement; - overlayContainerElement.style.left = location.x - webPartElement.offsetWidth / 2; - overlayContainerElement.style.top = location.y + 4 + (webPartElement.clientTop ? webPartElement.clientTop : 0); - overlayContainerElement.style.display = "block"; - overlayContainerElement.style.width = webPartElement.offsetWidth; - overlayContainerElement.style.height = webPartElement.offsetHeight; - overlayContainerElement.appendChild(webPartElement.cloneNode(true)); - if (webPart.allowZoneChange == false) { - webPart.zone.allowDrop = true; - } - else { - for (var i = 0; i < __wpm.zones.length; i++) { - var zone = __wpm.zones[i]; - if (zone.allowLayoutChange) { - zone.allowDrop = true; - } - } - } - document.body.attachEvent("ondragover", Zone_OnDragOver); - return "move"; -} -function WebPartManager_CompleteWebPartDragDrop() { - var dragState = this.dragState; - this.dragState = null; - if ((typeof(dragState.dropZoneElement) != "undefined") && (dragState.dropZoneElement != null)) { - dragState.dropZoneElement.__zone.ToggleDropCues(false, dragState.dropIndex, false); - } - document.body.detachEvent("ondragover", Zone_OnDragOver); - for (var i = 0; i < __wpm.zones.length; i++) { - __wpm.zones[i].allowDrop = false; - } - this.overlayContainerElement.removeChild(this.overlayContainerElement.firstChild); - this.overlayContainerElement.style.display = "none"; - if ((typeof(dragState) != "undefined") && (dragState != null) && (dragState.dropped == true)) { - var currentZone = dragState.webPartElement.__webPart.zone; - var currentZoneIndex = dragState.webPartElement.__webPart.zoneIndex; - if ((currentZone != dragState.dropZoneElement.__zone) || - ((currentZoneIndex != dragState.dropIndex) && - (currentZoneIndex != (dragState.dropIndex - 1)))) { - var eventTarget = dragState.dropZoneElement.__zone.uniqueID; - var eventArgument = "Drag:" + dragState.webPartElement.id + ":" + dragState.dropIndex; - this.SubmitPage(eventTarget, eventArgument); - } - } -} -function WebPartManager_ContinueWebPartDragDrop() { - var dragState = this.dragState; - if ((typeof(dragState) != "undefined") && (dragState != null)) { - var style = this.overlayContainerElement.style; - var location = __wpGetPageEventLocation(window.event, true); - style.left = location.x - dragState.webPartElement.offsetWidth / 2; - style.top = location.y + 4 + (dragState.webPartElement.clientTop ? dragState.webPartElement.clientTop : 0); - } -} -function WebPartManager_Execute(script) { - if (this.menu) { - this.menu.Hide(); - } - var scriptReference = new Function(script); - return (scriptReference() != false); -} -function WebPartManager_ProcessWebPartDragEnter() { - var dragState = __wpm.dragState; - if ((typeof(dragState) != "undefined") && (dragState != null)) { - var currentEvent = window.event; - var newDropZoneElement = Zone_GetParentZoneElement(currentEvent.srcElement); - if ((typeof(newDropZoneElement.__zone) == "undefined") || (newDropZoneElement.__zone == null) || - (newDropZoneElement.__zone.allowDrop == false)) { - newDropZoneElement = null; - } - var newDropIndex = -1; - if ((typeof(newDropZoneElement) != "undefined") && (newDropZoneElement != null)) { - newDropIndex = newDropZoneElement.__zone.GetWebPartIndex(__wpGetPageEventLocation(currentEvent, false)); - if (newDropIndex == -1) { - newDropZoneElement = null; - } - } - if (dragState.dropZoneElement != newDropZoneElement) { - if ((typeof(dragState.dropZoneElement) != "undefined") && (dragState.dropZoneElement != null)) { - dragState.dropZoneElement.__zone.ToggleDropCues(false, dragState.dropIndex, false); - } - dragState.dropZoneElement = newDropZoneElement; - dragState.dropIndex = newDropIndex; - if ((typeof(newDropZoneElement) != "undefined") && (newDropZoneElement != null)) { - newDropZoneElement.__zone.ToggleDropCues(true, newDropIndex, false); - } - } - else if (dragState.dropIndex != newDropIndex) { - if (dragState.dropIndex != -1) { - dragState.dropZoneElement.__zone.ToggleDropCues(false, dragState.dropIndex, false); - } - dragState.dropIndex = newDropIndex; - if ((typeof(newDropZoneElement) != "undefined") && (newDropZoneElement != null)) { - newDropZoneElement.__zone.ToggleDropCues(true, newDropIndex, false); - } - } - if ((typeof(dragState.dropZoneElement) != "undefined") && (dragState.dropZoneElement != null)) { - currentEvent.dataTransfer.effectAllowed = dragState.effect; - } - return true; - } - return false; -} -function WebPartManager_ProcessWebPartDragOver() { - var dragState = __wpm.dragState; - var currentEvent = window.event; - var handled = false; - if ((typeof(dragState) != "undefined") && (dragState != null) && - (typeof(dragState.dropZoneElement) != "undefined") && (dragState.dropZoneElement != null)) { - var dropZoneElement = Zone_GetParentZoneElement(currentEvent.srcElement); - if ((typeof(dropZoneElement) != "undefined") && (dropZoneElement != null) && (dropZoneElement.__zone.allowDrop == false)) { - dropZoneElement = null; - } - if (((typeof(dropZoneElement) == "undefined") || (dropZoneElement == null)) && - (typeof(dragState.dropZoneElement) != "undefined") && (dragState.dropZoneElement != null)) { - dragState.dropZoneElement.__zone.ToggleDropCues(false, __wpm.dragState.dropIndex, false); - dragState.dropZoneElement = null; - dragState.dropIndex = -1; - } - else if ((typeof(dropZoneElement) != "undefined") && (dropZoneElement != null)) { - var location = __wpGetPageEventLocation(currentEvent, false); - var newDropIndex = dropZoneElement.__zone.GetWebPartIndex(location); - if (newDropIndex == -1) { - dropZoneElement = null; - } - if (dragState.dropZoneElement != dropZoneElement) { - if ((dragState.dropIndex != -1) || (typeof(dropZoneElement) == "undefined") || (dropZoneElement == null)) { - dragState.dropZoneElement.__zone.ToggleDropCues(false, __wpm.dragState.dropIndex, false); - } - dragState.dropZoneElement = dropZoneElement; - } - else { - dragState.dropZoneElement.__zone.ToggleDropCues(false, dragState.dropIndex, true); - } - dragState.dropIndex = newDropIndex; - if ((typeof(dropZoneElement) != "undefined") && (dropZoneElement != null)) { - dropZoneElement.__zone.ToggleDropCues(true, newDropIndex, false); - } - } - handled = true; - } - if ((typeof(dragState) == "undefined") || (dragState == null) || - (typeof(dragState.dropZoneElement) == "undefined") || (dragState.dropZoneElement == null)) { - currentEvent.dataTransfer.effectAllowed = "none"; - } - return handled; -} -function WebPartManager_ProcessWebPartDrop() { - var dragState = this.dragState; - if ((typeof(dragState) != "undefined") && (dragState != null)) { - var currentEvent = window.event; - var dropZoneElement = Zone_GetParentZoneElement(currentEvent.srcElement); - if ((typeof(dropZoneElement) != "undefined") && (dropZoneElement != null) && (dropZoneElement.__zone.allowDrop == false)) { - dropZoneElement = null; - } - if ((typeof(dropZoneElement) != "undefined") && (dropZoneElement != null) && (dragState.dropZoneElement == dropZoneElement)) { - dragState.dropped = true; - } - return true; - } - return false; -} -function WebPartManager_ShowHelp(helpUrl, helpMode) { - if ((typeof(this.menu) != "undefined") && (this.menu != null)) { - this.menu.Hide(); - } - if (helpMode == 0 || helpMode == 1) { - if (helpMode == 0) { - var dialogInfo = "edge: Sunken; center: yes; help: no; resizable: yes; status: no"; - window.showModalDialog(helpUrl, null, dialogInfo); - } - else { - window.open(helpUrl, null, "scrollbars=yes,resizable=yes,status=no,toolbar=no,menubar=no,location=no"); - } - } - else if (helpMode == 2) { - window.location = helpUrl; - } -} -function WebPartManager_ExportWebPart(exportUrl, warn, confirmOnly) { - if (warn == true && __wpmExportWarning.length > 0 && this.personalizationScopeShared != true) { - if (confirm(__wpmExportWarning) == false) { - return false; - } - } - if (confirmOnly == false) { - window.location = exportUrl; - } - return true; -} -function WebPartManager_UpdatePositions() { - for (var i = 0; i < this.zones.length; i++) { - this.zones[i].UpdatePosition(); - } -} -function WebPartManager_SubmitPage(eventTarget, eventArgument) { - if ((typeof(this.menu) != "undefined") && (this.menu != null)) { - this.menu.Hide(); - } - __doPostBack(eventTarget, eventArgument); -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebUIValidation.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebUIValidation.js deleted file mode 100644 index a160ee8d8..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/WebForms/WebUIValidation.js +++ /dev/null @@ -1,684 +0,0 @@ -//CdnPath=http://ajax.aspnetcdn.com/ajax/4.5/6/WebUIValidation.js -var Page_ValidationVer = "125"; -var Page_IsValid = true; -var Page_BlockSubmit = false; -var Page_InvalidControlToBeFocused = null; -var Page_TextTypes = /^(text|password|file|search|tel|url|email|number|range|color|datetime|date|month|week|time|datetime-local)$/i; -function ValidatorUpdateDisplay(val) { - if (typeof(val.display) == "string") { - if (val.display == "None") { - return; - } - if (val.display == "Dynamic") { - val.style.display = val.isvalid ? "none" : "inline"; - return; - } - } - if ((navigator.userAgent.indexOf("Mac") > -1) && - (navigator.userAgent.indexOf("MSIE") > -1)) { - val.style.display = "inline"; - } - val.style.visibility = val.isvalid ? "hidden" : "visible"; -} -function ValidatorUpdateIsValid() { - Page_IsValid = AllValidatorsValid(Page_Validators); -} -function AllValidatorsValid(validators) { - if ((typeof(validators) != "undefined") && (validators != null)) { - var i; - for (i = 0; i < validators.length; i++) { - if (!validators[i].isvalid) { - return false; - } - } - } - return true; -} -function ValidatorHookupControlID(controlID, val) { - if (typeof(controlID) != "string") { - return; - } - var ctrl = document.getElementById(controlID); - if ((typeof(ctrl) != "undefined") && (ctrl != null)) { - ValidatorHookupControl(ctrl, val); - } - else { - val.isvalid = true; - val.enabled = false; - } -} -function ValidatorHookupControl(control, val) { - if (typeof(control.tagName) != "string") { - return; - } - if (control.tagName != "INPUT" && control.tagName != "TEXTAREA" && control.tagName != "SELECT") { - var i; - for (i = 0; i < control.childNodes.length; i++) { - ValidatorHookupControl(control.childNodes[i], val); - } - return; - } - else { - if (typeof(control.Validators) == "undefined") { - control.Validators = new Array; - var eventType; - if (control.type == "radio") { - eventType = "onclick"; - } else { - eventType = "onchange"; - if (typeof(val.focusOnError) == "string" && val.focusOnError == "t") { - ValidatorHookupEvent(control, "onblur", "ValidatedControlOnBlur(event); "); - } - } - ValidatorHookupEvent(control, eventType, "ValidatorOnChange(event); "); - if (Page_TextTypes.test(control.type)) { - ValidatorHookupEvent(control, "onkeypress", - "event = event || window.event; if (!ValidatedTextBoxOnKeyPress(event)) { event.cancelBubble = true; if (event.stopPropagation) event.stopPropagation(); return false; } "); - } - } - control.Validators[control.Validators.length] = val; - } -} -function ValidatorHookupEvent(control, eventType, functionPrefix) { - var ev = control[eventType]; - if (typeof(ev) == "function") { - ev = ev.toString(); - ev = ev.substring(ev.indexOf("{") + 1, ev.lastIndexOf("}")); - } - else { - ev = ""; - } - control[eventType] = new Function("event", functionPrefix + " " + ev); -} -function ValidatorGetValue(id) { - var control; - control = document.getElementById(id); - if (typeof(control.value) == "string") { - return control.value; - } - return ValidatorGetValueRecursive(control); -} -function ValidatorGetValueRecursive(control) -{ - if (typeof(control.value) == "string" && (control.type != "radio" || control.checked == true)) { - return control.value; - } - var i, val; - for (i = 0; i twoDigitCutoffYear) ? (cutoffYearCentury - 100 + year) : (cutoffYearCentury + year)); - } - var num, cleanInput, m, exp; - if (dataType == "Integer") { - exp = /^\s*[-\+]?\d+\s*$/; - if (op.match(exp) == null) - return null; - num = parseInt(op, 10); - return (isNaN(num) ? null : num); - } - else if(dataType == "Double") { - exp = new RegExp("^\\s*([-\\+])?(\\d*)\\" + val.decimalchar + "?(\\d*)\\s*$"); - m = op.match(exp); - if (m == null) - return null; - if (m[2].length == 0 && m[3].length == 0) - return null; - cleanInput = (m[1] != null ? m[1] : "") + (m[2].length>0 ? m[2] : "0") + (m[3].length>0 ? "." + m[3] : ""); - num = parseFloat(cleanInput); - return (isNaN(num) ? null : num); - } - else if (dataType == "Currency") { - var hasDigits = (val.digits > 0); - var beginGroupSize, subsequentGroupSize; - var groupSizeNum = parseInt(val.groupsize, 10); - if (!isNaN(groupSizeNum) && groupSizeNum > 0) { - beginGroupSize = "{1," + groupSizeNum + "}"; - subsequentGroupSize = "{" + groupSizeNum + "}"; - } - else { - beginGroupSize = subsequentGroupSize = "+"; - } - exp = new RegExp("^\\s*([-\\+])?((\\d" + beginGroupSize + "(\\" + val.groupchar + "\\d" + subsequentGroupSize + ")+)|\\d*)" - + (hasDigits ? "\\" + val.decimalchar + "?(\\d{0," + val.digits + "})" : "") - + "\\s*$"); - m = op.match(exp); - if (m == null) - return null; - if (m[2].length == 0 && hasDigits && m[5].length == 0) - return null; - cleanInput = (m[1] != null ? m[1] : "") + m[2].replace(new RegExp("(\\" + val.groupchar + ")", "g"), "") + ((hasDigits && m[5].length > 0) ? "." + m[5] : ""); - num = parseFloat(cleanInput); - return (isNaN(num) ? null : num); - } - else if (dataType == "Date") { - var yearFirstExp = new RegExp("^\\s*((\\d{4})|(\\d{2}))([-/]|\\. ?)(\\d{1,2})\\4(\\d{1,2})\\.?\\s*$"); - m = op.match(yearFirstExp); - var day, month, year; - if (m != null && (((typeof(m[2]) != "undefined") && (m[2].length == 4)) || val.dateorder == "ymd")) { - day = m[6]; - month = m[5]; - year = (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3], 10)); - } - else { - if (val.dateorder == "ymd"){ - return null; - } - var yearLastExp = new RegExp("^\\s*(\\d{1,2})([-/]|\\. ?)(\\d{1,2})(?:\\s|\\2)((\\d{4})|(\\d{2}))(?:\\s\u0433\\.|\\.)?\\s*$"); - m = op.match(yearLastExp); - if (m == null) { - return null; - } - if (val.dateorder == "mdy") { - day = m[3]; - month = m[1]; - } - else { - day = m[1]; - month = m[3]; - } - year = ((typeof(m[5]) != "undefined") && (m[5].length == 4)) ? m[5] : GetFullYear(parseInt(m[6], 10)); - } - month -= 1; - var date = new Date(year, month, day); - if (year < 100) { - date.setFullYear(year); - } - return (typeof(date) == "object" && year == date.getFullYear() && month == date.getMonth() && day == date.getDate()) ? date.valueOf() : null; - } - else { - return op.toString(); - } -} -function ValidatorCompare(operand1, operand2, operator, val) { - var dataType = val.type; - var op1, op2; - if ((op1 = ValidatorConvert(operand1, dataType, val)) == null) - return false; - if (operator == "DataTypeCheck") - return true; - if ((op2 = ValidatorConvert(operand2, dataType, val)) == null) - return true; - switch (operator) { - case "NotEqual": - return (op1 != op2); - case "GreaterThan": - return (op1 > op2); - case "GreaterThanEqual": - return (op1 >= op2); - case "LessThan": - return (op1 < op2); - case "LessThanEqual": - return (op1 <= op2); - default: - return (op1 == op2); - } -} -function CompareValidatorEvaluateIsValid(val) { - var value = ValidatorGetValue(val.controltovalidate); - if (ValidatorTrim(value).length == 0) - return true; - var compareTo = ""; - if ((typeof(val.controltocompare) != "string") || - (typeof(document.getElementById(val.controltocompare)) == "undefined") || - (null == document.getElementById(val.controltocompare))) { - if (typeof(val.valuetocompare) == "string") { - compareTo = val.valuetocompare; - } - } - else { - compareTo = ValidatorGetValue(val.controltocompare); - } - var operator = "Equal"; - if (typeof(val.operator) == "string") { - operator = val.operator; - } - return ValidatorCompare(value, compareTo, operator, val); -} -function CustomValidatorEvaluateIsValid(val) { - var value = ""; - if (typeof(val.controltovalidate) == "string") { - value = ValidatorGetValue(val.controltovalidate); - if ((ValidatorTrim(value).length == 0) && - ((typeof(val.validateemptytext) != "string") || (val.validateemptytext != "true"))) { - return true; - } - } - var args = { Value:value, IsValid:true }; - if (typeof(val.clientvalidationfunction) == "string") { - eval(val.clientvalidationfunction + "(val, args) ;"); - } - return args.IsValid; -} -function RegularExpressionValidatorEvaluateIsValid(val) { - var value = ValidatorGetValue(val.controltovalidate); - if (ValidatorTrim(value).length == 0) - return true; - var rx = new RegExp(val.validationexpression); - var matches = rx.exec(value); - return (matches != null && value == matches[0]); -} -function ValidatorTrim(s) { - var m = s.match(/^\s*(\S+(\s+\S+)*)\s*$/); - return (m == null) ? "" : m[1]; -} -function RequiredFieldValidatorEvaluateIsValid(val) { - return (ValidatorTrim(ValidatorGetValue(val.controltovalidate)) != ValidatorTrim(val.initialvalue)) -} -function RangeValidatorEvaluateIsValid(val) { - var value = ValidatorGetValue(val.controltovalidate); - if (ValidatorTrim(value).length == 0) - return true; - return (ValidatorCompare(value, val.minimumvalue, "GreaterThanEqual", val) && - ValidatorCompare(value, val.maximumvalue, "LessThanEqual", val)); -} -function ValidationSummaryOnSubmit(validationGroup) { - if (typeof(Page_ValidationSummaries) == "undefined") - return; - var summary, sums, s; - var headerSep, first, pre, post, end; - for (sums = 0; sums < Page_ValidationSummaries.length; sums++) { - summary = Page_ValidationSummaries[sums]; - if (!summary) continue; - summary.style.display = "none"; - if (!Page_IsValid && IsValidationGroupMatch(summary, validationGroup)) { - var i; - if (summary.showsummary != "False") { - summary.style.display = ""; - if (typeof(summary.displaymode) != "string") { - summary.displaymode = "BulletList"; - } - switch (summary.displaymode) { - case "List": - headerSep = "
    "; - first = ""; - pre = ""; - post = "
    "; - end = ""; - break; - case "BulletList": - default: - headerSep = ""; - first = "
      "; - pre = "
    • "; - post = "
    • "; - end = "
    "; - break; - case "SingleParagraph": - headerSep = " "; - first = ""; - pre = ""; - post = " "; - end = "
    "; - break; - } - s = ""; - if (typeof(summary.headertext) == "string") { - s += summary.headertext + headerSep; - } - s += first; - for (i=0; i= 0) { - Page_Validators.splice(index, 1); - } - } - function addNormalizedAttribute(name, normalizedName) { - normalizedAttributes[name.toLowerCase()] = normalizedName; - } - function parseSpecificAttribute(selector, attribute, validatorsArray) { - return $(selector).find("[" + attribute + "='true']").each(function (index, element) { - addValidationExpando(element); - element.dispose = function () { dispose(element); element.dispose = null; }; - if ($.inArray(element, validatorsArray) === -1) { - validatorsArray.push(element); - } - }).length; - } - function parse(selector) { - var length = parseSpecificAttribute(selector, dataValidationAttribute, Page_Validators); - length += parseSpecificAttribute(selector, dataValidationSummaryAttribute, Page_ValidationSummaries); - return length; - } - function loadValidators() { - if (typeof (ValidatorOnLoad) === "function") { - ValidatorOnLoad(); - } - if (typeof (ValidatorOnSubmit) === "undefined") { - window.ValidatorOnSubmit = function () { - return Page_ValidationActive ? ValidatorCommonOnSubmit() : true; - }; - } - } - function registerUpdatePanel() { - if (window.Sys && Sys.WebForms && Sys.WebForms.PageRequestManager) { - var prm = Sys.WebForms.PageRequestManager.getInstance(), - postBackElement, endRequestHandler; - if (prm.get_isInAsyncPostBack()) { - endRequestHandler = function (sender, args) { - if (parse(document)) { - loadValidators(); - } - prm.remove_endRequest(endRequestHandler); - endRequestHandler = null; - }; - prm.add_endRequest(endRequestHandler); - } - prm.add_beginRequest(function (sender, args) { - postBackElement = args.get_postBackElement(); - }); - prm.add_pageLoaded(function (sender, args) { - var i, panels, valFound = 0; - if (typeof (postBackElement) === "undefined") { - return; - } - panels = args.get_panelsUpdated(); - for (i = 0; i < panels.length; i++) { - valFound += parse(panels[i]); - } - panels = args.get_panelsCreated(); - for (i = 0; i < panels.length; i++) { - valFound += parse(panels[i]); - } - if (valFound) { - loadValidators(); - } - }); - } - } - $(function () { - if (typeof (Page_Validators) === "undefined") { - window.Page_Validators = []; - } - if (typeof (Page_ValidationSummaries) === "undefined") { - window.Page_ValidationSummaries = []; - } - if (typeof (Page_ValidationActive) === "undefined") { - window.Page_ValidationActive = false; - } - $.WebFormValidator = { - addNormalizedAttribute: addNormalizedAttribute, - parse: parse - }; - if (parse(document)) { - loadValidators(); - } - registerUpdatePanel(); - }); - } (jQuery)); -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/_references.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/_references.js deleted file mode 100644 index 0ca0a912a..000000000 Binary files a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/_references.js and /dev/null differ diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/jquery-1.8.2.intellisense.js.REMOVED.git-id b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/jquery-1.8.2.intellisense.js.REMOVED.git-id deleted file mode 100644 index a18346019..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/jquery-1.8.2.intellisense.js.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -9f45b0ed8605eda0194fc9690c4026852a8c2fa2 \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/modernizr-2.6.2.js b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/modernizr-2.6.2.js deleted file mode 100644 index cbfe1f390..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Scripts/modernizr-2.6.2.js +++ /dev/null @@ -1,1416 +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. - * - * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton; http://www.modernizr.com/license/ - * - * Includes matchMedia polyfill; Copyright (c) 2010 Filament Group, Inc; http://opensource.org/licenses/MIT - * - * Includes material adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js; Copyright 2009-2012 by contributors; http://opensource.org/licenses/MIT - * - * Includes material from css-support; Copyright (c) 2005-2012 Diego Perini; https://github.com/dperini/css-support/blob/master/LICENSE - * - * NUGET: END LICENSE TEXT */ - -/*! - * Modernizr v2.6.2 - * www.modernizr.com - * - * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton - * Available under the BSD and MIT licenses: www.modernizr.com/license/ - */ - -/* - * Modernizr tests which native CSS3 and HTML5 features are available in - * the current UA and makes the results available to you in two ways: - * as properties on a global Modernizr object, and as classes on the - * element. This information allows you to progressively enhance - * your pages with a granular level of control over the experience. - * - * Modernizr has an optional (not included) conditional resource loader - * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). - * To get a build that includes Modernizr.load(), as well as choosing - * which tests to include, go to www.modernizr.com/download/ - * - * Authors Faruk Ates, Paul Irish, Alex Sexton - * Contributors Ryan Seddon, Ben Alman - */ - -window.Modernizr = (function( window, document, undefined ) { - - var version = '2.6.2', - - Modernizr = {}, - - /*>>cssclasses*/ - // option for enabling the HTML classes to be added - enableClasses = true, - /*>>cssclasses*/ - - docElement = document.documentElement, - - /** - * Create our "modernizr" element that we do most feature tests on. - */ - mod = 'modernizr', - modElem = document.createElement(mod), - mStyle = modElem.style, - - /** - * Create the input element for various Web Forms feature tests. - */ - inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ , - - /*>>smile*/ - smile = ':)', - /*>>smile*/ - - toString = {}.toString, - - // TODO :: make the prefixes more granular - /*>>prefixes*/ - // List of property values to set for css tests. See ticket #21 - prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), - /*>>prefixes*/ - - /*>>domprefixes*/ - // Following spec is to expose vendor-specific style properties as: - // elem.style.WebkitBorderRadius - // and the following would be incorrect: - // elem.style.webkitBorderRadius - - // Webkit ghosts their properties in lowercase but Opera & Moz do not. - // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ - // erik.eae.net/archives/2008/03/10/21.48.10/ - - // More here: github.com/Modernizr/Modernizr/issues/issue/21 - omPrefixes = 'Webkit Moz O ms', - - cssomPrefixes = omPrefixes.split(' '), - - domPrefixes = omPrefixes.toLowerCase().split(' '), - /*>>domprefixes*/ - - /*>>ns*/ - ns = {'svg': 'http://www.w3.org/2000/svg'}, - /*>>ns*/ - - tests = {}, - inputs = {}, - attrs = {}, - - classes = [], - - slice = classes.slice, - - featureName, // used in testing loop - - - /*>>teststyles*/ - // Inject element with style element and some CSS rules - injectElementWithStyles = function( rule, callback, nodes, testnames ) { - - var style, ret, node, docOverflow, - div = document.createElement('div'), - // After page load injecting a fake body doesn't work so check if body exists - body = document.body, - // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. - fakeBody = body || document.createElement('body'); - - if ( parseInt(nodes, 10) ) { - // In order not to give false positives we create a node for each test - // This also allows the method to scale for unspecified uses - while ( nodes-- ) { - node = document.createElement('div'); - node.id = testnames ? testnames[nodes] : mod + (nodes + 1); - div.appendChild(node); - } - } - - // '].join(''); - div.id = mod; - // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. - // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 - (body ? div : fakeBody).innerHTML += style; - fakeBody.appendChild(div); - if ( !body ) { - //avoid crashing IE8, if background image is used - fakeBody.style.background = ''; - //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible - fakeBody.style.overflow = 'hidden'; - docOverflow = docElement.style.overflow; - docElement.style.overflow = 'hidden'; - docElement.appendChild(fakeBody); - } - - ret = callback(div, rule); - // If this is done after page load we don't want to remove the body so check if body exists - if ( !body ) { - fakeBody.parentNode.removeChild(fakeBody); - docElement.style.overflow = docOverflow; - } else { - div.parentNode.removeChild(div); - } - - return !!ret; - - }, - /*>>teststyles*/ - - /*>>mq*/ - // adapted from matchMedia polyfill - // by Scott Jehl and Paul Irish - // gist.github.com/786768 - testMediaQuery = function( mq ) { - - var matchMedia = window.matchMedia || window.msMatchMedia; - if ( matchMedia ) { - return matchMedia(mq).matches; - } - - var bool; - - injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { - bool = (window.getComputedStyle ? - getComputedStyle(node, null) : - node.currentStyle)['position'] == 'absolute'; - }); - - return bool; - - }, - /*>>mq*/ - - - /*>>hasevent*/ - // - // isEventSupported determines if a given element supports the given event - // kangax.github.com/iseventsupported/ - // - // The following results are known incorrects: - // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative - // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 - // ... - isEventSupported = (function() { - - var TAGNAMES = { - 'select': 'input', 'change': 'input', - 'submit': 'form', 'reset': 'form', - 'error': 'img', 'load': 'img', 'abort': 'img' - }; - - function isEventSupported( eventName, element ) { - - element = element || document.createElement(TAGNAMES[eventName] || 'div'); - eventName = 'on' + eventName; - - // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those - var isSupported = eventName in element; - - if ( !isSupported ) { - // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element - if ( !element.setAttribute ) { - element = document.createElement('div'); - } - if ( element.setAttribute && element.removeAttribute ) { - element.setAttribute(eventName, ''); - isSupported = is(element[eventName], 'function'); - - // If property was created, "remove it" (by setting value to `undefined`) - if ( !is(element[eventName], 'undefined') ) { - element[eventName] = undefined; - } - element.removeAttribute(eventName); - } - } - - element = null; - return isSupported; - } - return isEventSupported; - })(), - /*>>hasevent*/ - - // TODO :: Add flag for hasownprop ? didn't last time - - // hasOwnProperty shim by kangax needed for Safari 2.0 support - _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; - - if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { - hasOwnProp = function (object, property) { - return _hasOwnProperty.call(object, property); - }; - } - else { - hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ - return ((property in object) && is(object.constructor.prototype[property], 'undefined')); - }; - } - - // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js - // es5.github.com/#x15.3.4.5 - - if (!Function.prototype.bind) { - Function.prototype.bind = function bind(that) { - - var target = this; - - if (typeof target != "function") { - throw new TypeError(); - } - - var args = slice.call(arguments, 1), - bound = function () { - - if (this instanceof bound) { - - var F = function(){}; - F.prototype = target.prototype; - var self = new F(); - - var result = target.apply( - self, - args.concat(slice.call(arguments)) - ); - if (Object(result) === result) { - return result; - } - return self; - - } else { - - return target.apply( - that, - args.concat(slice.call(arguments)) - ); - - } - - }; - - return bound; - }; - } - - /** - * setCss applies given styles to the Modernizr DOM node. - */ - function setCss( str ) { - mStyle.cssText = str; - } - - /** - * setCssAll extrapolates all vendor-specific css strings. - */ - function setCssAll( str1, str2 ) { - return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); - } - - /** - * is returns a boolean for if typeof obj is exactly type. - */ - function is( obj, type ) { - return typeof obj === type; - } - - /** - * contains returns a boolean for if substr is found within str. - */ - function contains( str, substr ) { - return !!~('' + str).indexOf(substr); - } - - /*>>testprop*/ - - // testProps is a generic CSS / DOM property test. - - // In testing support for a given CSS property, it's legit to test: - // `elem.style[styleName] !== undefined` - // If the property is supported it will return an empty string, - // if unsupported it will return undefined. - - // We'll take advantage of this quick test and skip setting a style - // on our modernizr element, but instead just testing undefined vs - // empty string. - - // Because the testing of the CSS property names (with "-", as - // opposed to the camelCase DOM properties) is non-portable and - // non-standard but works in WebKit and IE (but not Gecko or Opera), - // we explicitly reject properties with dashes so that authors - // developing in WebKit or IE first don't end up with - // browser-specific content by accident. - - function testProps( props, prefixed ) { - for ( var i in props ) { - var prop = props[i]; - if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { - return prefixed == 'pfx' ? prop : true; - } - } - return false; - } - /*>>testprop*/ - - // TODO :: add testDOMProps - /** - * testDOMProps is a generic DOM property test; if a browser supports - * a certain property, it won't return undefined for it. - */ - function testDOMProps( props, obj, elem ) { - for ( var i in props ) { - var item = obj[props[i]]; - if ( item !== undefined) { - - // return the property name as a string - if (elem === false) return props[i]; - - // let's bind a function - if (is(item, 'function')){ - // default to autobind unless override - return item.bind(elem || obj); - } - - // return the unbound function or obj or value - return item; - } - } - return false; - } - - /*>>testallprops*/ - /** - * testPropsAll tests a list of DOM properties we want to check against. - * We specify literally ALL possible (known and/or likely) properties on - * the element including the non-vendor prefixed one, for forward- - * compatibility. - */ - function testPropsAll( prop, prefixed, elem ) { - - var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), - props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); - - // did they call .prefixed('boxSizing') or are we just testing a prop? - if(is(prefixed, "string") || is(prefixed, "undefined")) { - return testProps(props, prefixed); - - // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) - } else { - props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); - return testDOMProps(props, prefixed, elem); - } - } - /*>>testallprops*/ - - - /** - * Tests - * ----- - */ - - // The *new* flexbox - // dev.w3.org/csswg/css3-flexbox - - tests['flexbox'] = function() { - return testPropsAll('flexWrap'); - }; - - // The *old* flexbox - // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ - - tests['flexboxlegacy'] = function() { - return testPropsAll('boxDirection'); - }; - - // On the S60 and BB Storm, getContext exists, but always returns undefined - // so we actually have to call getContext() to verify - // github.com/Modernizr/Modernizr/issues/issue/97/ - - tests['canvas'] = function() { - var elem = document.createElement('canvas'); - return !!(elem.getContext && elem.getContext('2d')); - }; - - tests['canvastext'] = function() { - return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); - }; - - // webk.it/70117 is tracking a legit WebGL feature detect proposal - - // We do a soft detect which may false positive in order to avoid - // an expensive context creation: bugzil.la/732441 - - tests['webgl'] = function() { - return !!window.WebGLRenderingContext; - }; - - /* - * The Modernizr.touch test only indicates if the browser supports - * touch events, which does not necessarily reflect a touchscreen - * device, as evidenced by tablets running Windows 7 or, alas, - * the Palm Pre / WebOS (touch) phones. - * - * Additionally, Chrome (desktop) used to lie about its support on this, - * but that has since been rectified: crbug.com/36415 - * - * We also test for Firefox 4 Multitouch Support. - * - * For more info, see: modernizr.github.com/Modernizr/touch.html - */ - - tests['touch'] = function() { - var bool; - - if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { - bool = true; - } else { - injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { - bool = node.offsetTop === 9; - }); - } - - return bool; - }; - - - // geolocation is often considered a trivial feature detect... - // Turns out, it's quite tricky to get right: - // - // Using !!navigator.geolocation does two things we don't want. It: - // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 - // 2. Disables page caching in WebKit: webk.it/43956 - // - // Meanwhile, in Firefox < 8, an about:config setting could expose - // a false positive that would throw an exception: bugzil.la/688158 - - tests['geolocation'] = function() { - return 'geolocation' in navigator; - }; - - - tests['postmessage'] = function() { - return !!window.postMessage; - }; - - - // Chrome incognito mode used to throw an exception when using openDatabase - // It doesn't anymore. - tests['websqldatabase'] = function() { - return !!window.openDatabase; - }; - - // Vendors had inconsistent prefixing with the experimental Indexed DB: - // - Webkit's implementation is accessible through webkitIndexedDB - // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB - // For speed, we don't test the legacy (and beta-only) indexedDB - tests['indexedDB'] = function() { - return !!testPropsAll("indexedDB", window); - }; - - // documentMode logic from YUI to filter out IE8 Compat Mode - // which false positives. - tests['hashchange'] = function() { - return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); - }; - - // Per 1.6: - // This used to be Modernizr.historymanagement but the longer - // name has been deprecated in favor of a shorter and property-matching one. - // The old API is still available in 1.6, but as of 2.0 will throw a warning, - // and in the first release thereafter disappear entirely. - tests['history'] = function() { - return !!(window.history && history.pushState); - }; - - tests['draganddrop'] = function() { - var div = document.createElement('div'); - return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); - }; - - // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10 - // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17. - // FF10 still uses prefixes, so check for it until then. - // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/ - tests['websockets'] = function() { - return 'WebSocket' in window || 'MozWebSocket' in window; - }; - - - // css-tricks.com/rgba-browser-support/ - tests['rgba'] = function() { - // Set an rgba() color and check the returned value - - setCss('background-color:rgba(150,255,150,.5)'); - - return contains(mStyle.backgroundColor, 'rgba'); - }; - - tests['hsla'] = function() { - // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, - // except IE9 who retains it as hsla - - setCss('background-color:hsla(120,40%,100%,.5)'); - - return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); - }; - - tests['multiplebgs'] = function() { - // Setting multiple images AND a color on the background shorthand property - // and then querying the style.background property value for the number of - // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! - - setCss('background:url(https://),url(https://),red url(https://)'); - - // If the UA supports multiple backgrounds, there should be three occurrences - // of the string "url(" in the return value for elemStyle.background - - return (/(url\s*\(.*?){3}/).test(mStyle.background); - }; - - - - // this will false positive in Opera Mini - // github.com/Modernizr/Modernizr/issues/396 - - tests['backgroundsize'] = function() { - return testPropsAll('backgroundSize'); - }; - - tests['borderimage'] = function() { - return testPropsAll('borderImage'); - }; - - - // Super comprehensive table about all the unique implementations of - // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance - - tests['borderradius'] = function() { - return testPropsAll('borderRadius'); - }; - - // WebOS unfortunately false positives on this test. - tests['boxshadow'] = function() { - return testPropsAll('boxShadow'); - }; - - // FF3.0 will false positive on this test - tests['textshadow'] = function() { - return document.createElement('div').style.textShadow === ''; - }; - - - tests['opacity'] = function() { - // Browsers that actually have CSS Opacity implemented have done so - // according to spec, which means their return values are within the - // range of [0.0,1.0] - including the leading zero. - - setCssAll('opacity:.55'); - - // The non-literal . in this regex is intentional: - // German Chrome returns this value as 0,55 - // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 - return (/^0.55$/).test(mStyle.opacity); - }; - - - // Note, Android < 4 will pass this test, but can only animate - // a single property at a time - // daneden.me/2011/12/putting-up-with-androids-bullshit/ - tests['cssanimations'] = function() { - return testPropsAll('animationName'); - }; - - - tests['csscolumns'] = function() { - return testPropsAll('columnCount'); - }; - - - tests['cssgradients'] = function() { - /** - * For CSS Gradients syntax, please see: - * webkit.org/blog/175/introducing-css-gradients/ - * developer.mozilla.org/en/CSS/-moz-linear-gradient - * developer.mozilla.org/en/CSS/-moz-radial-gradient - * dev.w3.org/csswg/css3-images/#gradients- - */ - - var str1 = 'background-image:', - str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', - str3 = 'linear-gradient(left top,#9f9, white);'; - - setCss( - // legacy webkit syntax (FIXME: remove when syntax not in use anymore) - (str1 + '-webkit- '.split(' ').join(str2 + str1) + - // standard syntax // trailing 'background-image:' - prefixes.join(str3 + str1)).slice(0, -str1.length) - ); - - return contains(mStyle.backgroundImage, 'gradient'); - }; - - - tests['cssreflections'] = function() { - return testPropsAll('boxReflect'); - }; - - - tests['csstransforms'] = function() { - return !!testPropsAll('transform'); - }; - - - tests['csstransforms3d'] = function() { - - var ret = !!testPropsAll('perspective'); - - // Webkit's 3D transforms are passed off to the browser's own graphics renderer. - // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in - // some conditions. As a result, Webkit typically recognizes the syntax but - // will sometimes throw a false positive, thus we must do a more thorough check: - if ( ret && 'webkitPerspective' in docElement.style ) { - - // Webkit allows this media query to succeed only if the feature is enabled. - // `@media (transform-3d),(-webkit-transform-3d){ ... }` - injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { - ret = node.offsetLeft === 9 && node.offsetHeight === 3; - }); - } - return ret; - }; - - - tests['csstransitions'] = function() { - return testPropsAll('transition'); - }; - - - /*>>fontface*/ - // @font-face detection routine by Diego Perini - // javascript.nwbox.com/CSSSupport/ - - // false positives: - // WebOS github.com/Modernizr/Modernizr/issues/342 - // WP7 github.com/Modernizr/Modernizr/issues/538 - tests['fontface'] = function() { - var bool; - - injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) { - var style = document.getElementById('smodernizr'), - sheet = style.sheet || style.styleSheet, - cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; - - bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; - }); - - return bool; - }; - /*>>fontface*/ - - // CSS generated content detection - tests['generatedcontent'] = function() { - var bool; - - injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) { - bool = node.offsetHeight >= 3; - }); - - return bool; - }; - - - - // These tests evaluate support of the video/audio elements, as well as - // testing what types of content they support. - // - // We're using the Boolean constructor here, so that we can extend the value - // e.g. Modernizr.video // true - // Modernizr.video.ogg // 'probably' - // - // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 - // thx to NielsLeenheer and zcorpan - - // Note: in some older browsers, "no" was a return value instead of empty string. - // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 - // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 - - tests['video'] = function() { - var elem = document.createElement('video'), - bool = false; - - // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); - - // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 - bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); - - bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); - } - - } catch(e) { } - - return bool; - }; - - tests['audio'] = function() { - var elem = document.createElement('audio'), - bool = false; - - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); - bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); - - // Mimetypes accepted: - // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements - // bit.ly/iphoneoscodecs - bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); - bool.m4a = ( elem.canPlayType('audio/x-m4a;') || - elem.canPlayType('audio/aac;')) .replace(/^no$/,''); - } - } catch(e) { } - - return bool; - }; - - - // In FF4, if disabled, window.localStorage should === null. - - // Normally, we could not test that directly and need to do a - // `('localStorage' in window) && ` test first because otherwise Firefox will - // throw bugzil.la/365772 if cookies are disabled - - // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem - // will throw the exception: - // QUOTA_EXCEEDED_ERRROR DOM Exception 22. - // Peculiarly, getItem and removeItem calls do not throw. - - // Because we are forced to try/catch this, we'll go aggressive. - - // Just FWIW: IE8 Compat mode supports these features completely: - // www.quirksmode.org/dom/html5.html - // But IE8 doesn't support either with local files - - tests['localstorage'] = function() { - try { - localStorage.setItem(mod, mod); - localStorage.removeItem(mod); - return true; - } catch(e) { - return false; - } - }; - - tests['sessionstorage'] = function() { - try { - sessionStorage.setItem(mod, mod); - sessionStorage.removeItem(mod); - return true; - } catch(e) { - return false; - } - }; - - - tests['webworkers'] = function() { - return !!window.Worker; - }; - - - tests['applicationcache'] = function() { - return !!window.applicationCache; - }; - - - // Thanks to Erik Dahlstrom - tests['svg'] = function() { - return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; - }; - - // specifically for SVG inline in HTML, not within XHTML - // test page: paulirish.com/demo/inline-svg - tests['inlinesvg'] = function() { - var div = document.createElement('div'); - div.innerHTML = ''; - return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; - }; - - // SVG SMIL animation - tests['smil'] = function() { - return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); - }; - - // This test is only for clip paths in SVG proper, not clip paths on HTML content - // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg - - // However read the comments to dig into applying SVG clippaths to HTML content here: - // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 - tests['svgclippaths'] = function() { - return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); - }; - - /*>>webforms*/ - // input features and input types go directly onto the ret object, bypassing the tests loop. - // Hold this guy to execute in a moment. - function webforms() { - /*>>input*/ - // Run through HTML5's new input attributes to see if the UA understands any. - // We're using f which is the element created early on - // Mike Taylr has created a comprehensive resource for testing these attributes - // when applied to all input types: - // miketaylr.com/code/input-type-attr.html - // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary - - // Only input placeholder is tested while textarea's placeholder is not. - // Currently Safari 4 and Opera 11 have support only for the input placeholder - // Both tests are available in feature-detects/forms-placeholder.js - Modernizr['input'] = (function( props ) { - for ( var i = 0, len = props.length; i < len; i++ ) { - attrs[ props[i] ] = !!(props[i] in inputElem); - } - if (attrs.list){ - // safari false positive's on datalist: webk.it/74252 - // see also github.com/Modernizr/Modernizr/issues/146 - attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); - } - return attrs; - })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); - /*>>input*/ - - /*>>inputtypes*/ - // Run through HTML5's new input types to see if the UA understands any. - // This is put behind the tests runloop because it doesn't return a - // true/false like all the other tests; instead, it returns an object - // containing each input type with its corresponding true/false value - - // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ - Modernizr['inputtypes'] = (function(props) { - - for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { - - inputElem.setAttribute('type', inputElemType = props[i]); - bool = inputElem.type !== 'text'; - - // We first check to see if the type we give it sticks.. - // If the type does, we feed it a textual value, which shouldn't be valid. - // If the value doesn't stick, we know there's input sanitization which infers a custom UI - if ( bool ) { - - inputElem.value = smile; - inputElem.style.cssText = 'position:absolute;visibility:hidden;'; - - if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { - - docElement.appendChild(inputElem); - defaultView = document.defaultView; - - // Safari 2-4 allows the smiley as a value, despite making a slider - bool = defaultView.getComputedStyle && - defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && - // Mobile android web browser has false positive, so must - // check the height to see if the widget is actually there. - (inputElem.offsetHeight !== 0); - - docElement.removeChild(inputElem); - - } else if ( /^(search|tel)$/.test(inputElemType) ){ - // Spec doesn't define any special parsing or detectable UI - // behaviors so we pass these through as true - - // Interestingly, opera fails the earlier test, so it doesn't - // even make it here. - - } else if ( /^(url|email)$/.test(inputElemType) ) { - // Real url and email support comes with prebaked validation. - bool = inputElem.checkValidity && inputElem.checkValidity() === false; - - } else { - // If the upgraded input compontent rejects the :) text, we got a winner - bool = inputElem.value != smile; - } - } - - inputs[ props[i] ] = !!bool; - } - return inputs; - })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); - /*>>inputtypes*/ - } - /*>>webforms*/ - - - // End of test definitions - // ----------------------- - - - - // Run through all tests and detect their support in the current UA. - // todo: hypothetically we could be doing an array of tests and use a basic loop here. - for ( var feature in tests ) { - if ( hasOwnProp(tests, feature) ) { - // run the test, throw the return value into the Modernizr, - // then based on that boolean, define an appropriate className - // and push it into an array of classes we'll join later. - featureName = feature.toLowerCase(); - Modernizr[featureName] = tests[feature](); - - classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); - } - } - - /*>>webforms*/ - // input tests need to run. - Modernizr.input || webforms(); - /*>>webforms*/ - - - /** - * addTest allows the user to define their own feature tests - * the result will be added onto the Modernizr object, - * as well as an appropriate className set on the html element - * - * @param feature - String naming the feature - * @param test - Function returning true if feature is supported, false if not - */ - Modernizr.addTest = function ( feature, test ) { - if ( typeof feature == 'object' ) { - for ( var key in feature ) { - if ( hasOwnProp( feature, key ) ) { - Modernizr.addTest( key, feature[ key ] ); - } - } - } else { - - feature = feature.toLowerCase(); - - if ( Modernizr[feature] !== undefined ) { - // we're going to quit if you're trying to overwrite an existing test - // if we were to allow it, we'd do this: - // var re = new RegExp("\\b(no-)?" + feature + "\\b"); - // docElement.className = docElement.className.replace( re, '' ); - // but, no rly, stuff 'em. - return Modernizr; - } - - test = typeof test == 'function' ? test() : test; - - if (typeof enableClasses !== "undefined" && enableClasses) { - docElement.className += ' ' + (test ? '' : 'no-') + feature; - } - Modernizr[feature] = test; - - } - - return Modernizr; // allow chaining. - }; - - - // Reset modElem.cssText to nothing to reduce memory footprint. - setCss(''); - modElem = inputElem = null; - - /*>>shiv*/ - /*! HTML5 Shiv v3.6.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ - ;(function(window, document) { - /*jshint evil:true */ - /** Preset options */ - var options = window.html5 || {}; - - /** Used to skip problem elements */ - var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; - - /** Not all elements can be cloned in IE **/ - var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; - - /** Detect whether the browser supports default html5 styles */ - var supportsHtml5Styles; - - /** Name of the expando, to work with multiple documents or to re-shiv one document */ - var expando = '_html5shiv'; - - /** The id for the the documents expando */ - var expanID = 0; - - /** Cached data for each document */ - var expandoData = {}; - - /** Detect whether the browser supports unknown elements */ - var supportsUnknownElements; - - (function() { - try { - var a = document.createElement('a'); - a.innerHTML = ''; - //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles - supportsHtml5Styles = ('hidden' in a); - - supportsUnknownElements = a.childNodes.length == 1 || (function() { - // assign a false positive if unable to shiv - (document.createElement)('a'); - var frag = document.createDocumentFragment(); - return ( - typeof frag.cloneNode == 'undefined' || - typeof frag.createDocumentFragment == 'undefined' || - typeof frag.createElement == 'undefined' - ); - }()); - } catch(e) { - supportsHtml5Styles = true; - supportsUnknownElements = true; - } - - }()); - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a style sheet with the given CSS text and adds it to the document. - * @private - * @param {Document} ownerDocument The document. - * @param {String} cssText The CSS text. - * @returns {StyleSheet} The style element. - */ - function addStyleSheet(ownerDocument, cssText) { - var p = ownerDocument.createElement('p'), - parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; - - p.innerHTML = 'x'; - return parent.insertBefore(p.lastChild, parent.firstChild); - } - - /** - * Returns the value of `html5.elements` as an array. - * @private - * @returns {Array} An array of shived element node names. - */ - function getElements() { - var elements = html5.elements; - return typeof elements == 'string' ? elements.split(' ') : elements; - } - - /** - * Returns the data associated to the given document - * @private - * @param {Document} ownerDocument The document. - * @returns {Object} An object of data. - */ - function getExpandoData(ownerDocument) { - var data = expandoData[ownerDocument[expando]]; - if (!data) { - data = {}; - expanID++; - ownerDocument[expando] = expanID; - expandoData[expanID] = data; - } - return data; - } - - /** - * returns a shived element for the given nodeName and document - * @memberOf html5 - * @param {String} nodeName name of the element - * @param {Document} ownerDocument The context document. - * @returns {Object} The shived element. - */ - function createElement(nodeName, ownerDocument, data){ - if (!ownerDocument) { - ownerDocument = document; - } - if(supportsUnknownElements){ - return ownerDocument.createElement(nodeName); - } - if (!data) { - data = getExpandoData(ownerDocument); - } - var node; - - if (data.cache[nodeName]) { - node = data.cache[nodeName].cloneNode(); - } else if (saveClones.test(nodeName)) { - node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); - } else { - node = data.createElem(nodeName); - } - - // Avoid adding some elements to fragments in IE < 9 because - // * Attributes like `name` or `type` cannot be set/changed once an element - // is inserted into a document/fragment - // * Link elements with `src` attributes that are inaccessible, as with - // a 403 response, will cause the tab/window to crash - // * Script elements appended to fragments will execute when their `src` - // or `text` property is set - return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node; - } - - /** - * returns a shived DocumentFragment for the given document - * @memberOf html5 - * @param {Document} ownerDocument The context document. - * @returns {Object} The shived DocumentFragment. - */ - function createDocumentFragment(ownerDocument, data){ - if (!ownerDocument) { - ownerDocument = document; - } - if(supportsUnknownElements){ - return ownerDocument.createDocumentFragment(); - } - data = data || getExpandoData(ownerDocument); - var clone = data.frag.cloneNode(), - i = 0, - elems = getElements(), - l = elems.length; - for(;i>shiv*/ - - // Assign private properties to the return object with prefix - Modernizr._version = version; - - // expose these for the plugin API. Look in the source for how to join() them against your input - /*>>prefixes*/ - Modernizr._prefixes = prefixes; - /*>>prefixes*/ - /*>>domprefixes*/ - Modernizr._domPrefixes = domPrefixes; - Modernizr._cssomPrefixes = cssomPrefixes; - /*>>domprefixes*/ - - /*>>mq*/ - // Modernizr.mq tests a given media query, live against the current state of the window - // A few important notes: - // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false - // * A max-width or orientation query will be evaluated against the current state, which may change later. - // * You must specify values. Eg. If you are testing support for the min-width media query use: - // Modernizr.mq('(min-width:0)') - // usage: - // Modernizr.mq('only screen and (max-width:768)') - Modernizr.mq = testMediaQuery; - /*>>mq*/ - - /*>>hasevent*/ - // Modernizr.hasEvent() detects support for a given event, with an optional element to test on - // Modernizr.hasEvent('gesturestart', elem) - Modernizr.hasEvent = isEventSupported; - /*>>hasevent*/ - - /*>>testprop*/ - // Modernizr.testProp() investigates whether a given style property is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testProp('pointerEvents') - Modernizr.testProp = function(prop){ - return testProps([prop]); - }; - /*>>testprop*/ - - /*>>testallprops*/ - // Modernizr.testAllProps() investigates whether a given style property, - // or any of its vendor-prefixed variants, is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testAllProps('boxSizing') - Modernizr.testAllProps = testPropsAll; - /*>>testallprops*/ - - - /*>>teststyles*/ - // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards - // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) - Modernizr.testStyles = injectElementWithStyles; - /*>>teststyles*/ - - - /*>>prefixed*/ - // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input - // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' - - // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. - // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: - // - // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); - - // If you're trying to ascertain which transition end event to bind to, you might do something like... - // - // var transEndEventNames = { - // 'WebkitTransition' : 'webkitTransitionEnd', - // 'MozTransition' : 'transitionend', - // 'OTransition' : 'oTransitionEnd', - // 'msTransition' : 'MSTransitionEnd', - // 'transition' : 'transitionend' - // }, - // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; - - Modernizr.prefixed = function(prop, obj, elem){ - if(!obj) { - return testPropsAll(prop, 'pfx'); - } else { - // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' - return testPropsAll(prop, obj, elem); - } - }; - /*>>prefixed*/ - - - /*>>cssclasses*/ - // Remove "no-js" class from element, if it exists: - docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + - - // Add the new classes to the element. - (enableClasses ? ' js ' + classes.join(' ') : ''); - /*>>cssclasses*/ - - return Modernizr; - -})(this, this.document); diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master deleted file mode 100644 index ba076a8eb..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master +++ /dev/null @@ -1,87 +0,0 @@ -<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="Test_Website_Webforms_NET45.SiteMaster" %> - - - - - - <%: Page.Title %> - My ASP.NET Application - - <%: Scripts.Render("~/bundles/modernizr") %> - - - - - - - -
    - - - <%--To learn more about bundling scripts in ScriptManager see http://go.microsoft.com/fwlink/?LinkID=272931&clcid=0x409 --%> - <%--Framework Scripts--%> - - - - - - - - - - - - <%--Site Scripts--%> - - - -
    -
    -
    -

    - your logo here -

    -
    -
    -
    - - - - - -

    - Hello, - ! - -

    -
    -
    -
    - -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    -

    © <%: DateTime.Now.Year %> - My ASP.NET Application

    -
    -
    -
    -
    - - diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master.cs deleted file mode 100644 index af0b65b85..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Security; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace Test_Website_Webforms_NET45 -{ - public partial class SiteMaster : MasterPage - { - private const string AntiXsrfTokenKey = "__AntiXsrfToken"; - private const string AntiXsrfUserNameKey = "__AntiXsrfUserName"; - private string _antiXsrfTokenValue; - - protected void Page_Init(object sender, EventArgs e) - { - // The code below helps to protect against XSRF attacks - var requestCookie = Request.Cookies[AntiXsrfTokenKey]; - Guid requestCookieGuidValue; - if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue)) - { - // Use the Anti-XSRF token from the cookie - _antiXsrfTokenValue = requestCookie.Value; - Page.ViewStateUserKey = _antiXsrfTokenValue; - } - else - { - // Generate a new Anti-XSRF token and save to the cookie - _antiXsrfTokenValue = Guid.NewGuid().ToString("N"); - Page.ViewStateUserKey = _antiXsrfTokenValue; - - var responseCookie = new HttpCookie(AntiXsrfTokenKey) - { - HttpOnly = true, - Value = _antiXsrfTokenValue - }; - if (FormsAuthentication.RequireSSL && Request.IsSecureConnection) - { - responseCookie.Secure = true; - } - Response.Cookies.Set(responseCookie); - } - - Page.PreLoad += master_Page_PreLoad; - } - - protected void master_Page_PreLoad(object sender, EventArgs e) - { - if (!IsPostBack) - { - // Set Anti-XSRF token - ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey; - ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty; - } - else - { - // Validate the Anti-XSRF token - if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue - || (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty)) - { - throw new InvalidOperationException("Validation of Anti-XSRF token failed."); - } - } - } - - protected void Page_Load(object sender, EventArgs e) - { - - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master.designer.cs deleted file mode 100644 index bc639e2c3..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Master.designer.cs +++ /dev/null @@ -1,44 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45 -{ - - - public partial class SiteMaster - { - - /// - /// HeadContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder HeadContent; - - /// - /// FeaturedContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder FeaturedContent; - - /// - /// MainContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder MainContent; - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master deleted file mode 100644 index 785a93ae7..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master +++ /dev/null @@ -1,23 +0,0 @@ -<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Mobile.master.cs" Inherits="Test_Website_Webforms_NET45.Site_Mobile" %> -<%@ Register Src="~/ViewSwitcher.ascx" TagPrefix="friendlyUrls" TagName="ViewSwitcher" %> - - - - - - - - - -
    -
    -

    Mobile Master Page

    - -
    - -
    - -
    -
    - - diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master.cs deleted file mode 100644 index 1f9edc034..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace Test_Website_Webforms_NET45 -{ - public partial class Site_Mobile : System.Web.UI.MasterPage - { - protected void Page_Load(object sender, EventArgs e) - { - - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master.designer.cs deleted file mode 100644 index 489df4def..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Site.Mobile.Master.designer.cs +++ /dev/null @@ -1,51 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45 { - - - public partial class Site_Mobile { - - /// - /// HeadContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder HeadContent; - - /// - /// form1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form1; - - /// - /// FeaturedContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder FeaturedContent; - - /// - /// MainContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder MainContent; - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Test_Website_Webforms_NET45.csproj b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Test_Website_Webforms_NET45.csproj deleted file mode 100644 index 424aabccd..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Test_Website_Webforms_NET45.csproj +++ /dev/null @@ -1,325 +0,0 @@ - - - - - Debug - AnyCPU - - - 2.0 - {8DA47D8C-DB1A-4D82-843F-896AB9C3B3D2} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Test_Website_Webforms_NET45 - Test_Website_Webforms_NET45 - v4.5 - true - - - - - ..\..\..\ - true - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - False - ..\..\..\packages\WebGrease.1.1.0\lib\Antlr3.Runtime.dll - - - - - - - - - - - - - - - - - - - - - - True - ..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - ..\..\..\packages\Microsoft.AspNet.ScriptManager.MSAjax.4.5.6\lib\net45\Microsoft.ScriptManager.MSAjax.dll - - - ..\..\..\packages\Microsoft.AspNet.ScriptManager.WebForms.4.5.6\lib\net45\Microsoft.ScriptManager.WebForms.dll - - - ..\..\..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll - - - ..\..\..\packages\Microsoft.AspNet.Web.Optimization.1.0.0\lib\net40\System.Web.Optimization.dll - - - ..\..\..\packages\Microsoft.AspNet.Providers.Core.1.2\lib\net40\System.Web.Providers.dll - - - False - ..\..\..\packages\DotNetOpenAuth.Core.4.1.4.12333\lib\net40-full\DotNetOpenAuth.Core.dll - - - False - ..\..\..\packages\DotNetOpenAuth.OAuth.Core.4.1.4.12333\lib\net40-full\DotNetOpenAuth.OAuth.dll - - - False - ..\..\..\packages\DotNetOpenAuth.OAuth.Consumer.4.1.4.12333\lib\net40-full\DotNetOpenAuth.OAuth.Consumer.dll - - - False - ..\..\..\packages\DotNetOpenAuth.OpenId.Core.4.1.4.12333\lib\net40-full\DotNetOpenAuth.OpenId.dll - - - False - ..\..\..\packages\DotNetOpenAuth.OpenId.RelyingParty.4.1.4.12333\lib\net40-full\DotNetOpenAuth.OpenId.RelyingParty.dll - - - False - ..\..\..\packages\DotNetOpenAuth.AspNet.4.1.4.12333\lib\net40-full\DotNetOpenAuth.AspNet.dll - - - ..\..\..\packages\Microsoft.AspNet.Membership.OpenAuth.1.0.1\lib\net45\Microsoft.AspNet.Membership.OpenAuth.dll - - - True - ..\..\..\packages\Microsoft.AspNet.Web.Optimization.WebForms.1.0.0\lib\net45\Microsoft.AspNet.Web.Optimization.WebForms.dll - - - ..\..\..\packages\Microsoft.AspNet.FriendlyUrls.Core.1.0.0\lib\net45\Microsoft.AspNet.FriendlyUrls.dll - - - False - ..\..\..\packages\WebGrease.1.1.0\lib\WebGrease.dll - - - - - - - - - - - - - - Designer - - - Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - - - Web.config - - - Web.config - - - - - - - About.aspx - ASPXCodeBehind - - - About.aspx - - - Login.aspx - ASPXCodeBehind - - - Login.aspx - - - Manage.aspx - ASPXCodeBehind - - - Manage.aspx - - - OpenAuthProviders.ascx - ASPXCodeBehind - - - OpenAuthProviders.ascx - - - Register.aspx - ASPXCodeBehind - - - Register.aspx - - - RegisterExternalLogin.aspx - ASPXCodeBehind - - - RegisterExternalLogin.aspx - - - - Contact.aspx - ASPXCodeBehind - - - Contact.aspx - - - Default.aspx - ASPXCodeBehind - - - Default.aspx - - - Global.asax - - - - Site.Master - ASPXCodeBehind - - - Site.Master - - - Site.Mobile.Master - ASPXCodeBehind - - - Site.Mobile.Master - - - ViewSwitcher.ascx - ASPXCodeBehind - - - ViewSwitcher.ascx - - - - - - - - - - - - {d011a778-59c8-4bfa-a770-c350216bf161} - ImageProcessor.Web_NET45 - - - {3b5dd734-fb7a-487d-8ce6-55e7af9aea7e} - ImageProcessor - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - - True - True - 0 - / - http://localhost:56894/ - False - False - - - False - - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx deleted file mode 100644 index 5e111b38a..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx +++ /dev/null @@ -1,4 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ViewSwitcher.ascx.cs" Inherits="Test_Website_Webforms_NET45.ViewSwitcher" %> -
    - <%: CurrentView %> view | Switch to <%: AlternateView %> -
    \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx.cs deleted file mode 100644 index 14656f1a9..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Routing; -using System.Web.UI; -using System.Web.UI.WebControls; -using Microsoft.AspNet.FriendlyUrls.Resolvers; - -namespace Test_Website_Webforms_NET45 -{ - public partial class ViewSwitcher : System.Web.UI.UserControl - { - protected string CurrentView { get; private set; } - - protected string AlternateView { get; private set; } - - protected string SwitchUrl { get; private set; } - - protected void Page_Load(object sender, EventArgs e) - { - // Determine current view - var isMobile = WebFormsFriendlyUrlResolver.IsMobileView(new HttpContextWrapper(Context)); - CurrentView = isMobile ? "Mobile" : "Desktop"; - - // Determine alternate view - AlternateView = isMobile ? "Desktop" : "Mobile"; - - // Create switch URL from the route, e.g. ~/__FriendlyUrls_SwitchView/Mobile?ReturnUrl=/Page - var switchViewRouteName = "AspNet.FriendlyUrls.SwitchView"; - var switchViewRoute = RouteTable.Routes[switchViewRouteName]; - if (switchViewRoute == null) - { - // Friendly URLs is not enabled or the name of the swith view route is out of sync - this.Visible = false; - return; - } - var url = GetRouteUrl(switchViewRouteName, new { view = AlternateView }); - url += "?ReturnUrl=" + HttpUtility.UrlEncode(Request.RawUrl); - SwitchUrl = url; - } - } -} \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx.designer.cs b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx.designer.cs deleted file mode 100644 index 98e5b2d53..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/ViewSwitcher.ascx.designer.cs +++ /dev/null @@ -1,15 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Test_Website_Webforms_NET45 { - - - public partial class ViewSwitcher { - } -} diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.Debug.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.Debug.config deleted file mode 100644 index 2e302f9f9..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.Debug.config +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.Release.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.Release.config deleted file mode 100644 index c35844462..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.Release.config +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.config deleted file mode 100644 index 5a11c1783..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/Web.config +++ /dev/null @@ -1,102 +0,0 @@ - - - - - -
    - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/cache.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/cache.config deleted file mode 100644 index e4a9c5e9a..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/cache.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/processing.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/processing.config deleted file mode 100644 index 654a9fbd6..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/processing.config +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/security.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/security.config deleted file mode 100644 index 8a5716290..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/security.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/favicon.ico b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/favicon.ico deleted file mode 100644 index a3a799985..000000000 Binary files a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/favicon.ico and /dev/null differ diff --git a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/packages.config b/src/TestWebsites/NET45/Test_Website_Webforms_NET45/packages.config deleted file mode 100644 index 319f73f4f..000000000 --- a/src/TestWebsites/NET45/Test_Website_Webforms_NET45/packages.config +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Web.Test/WebTest1.webtest b/src/Web.Test/WebTest1.webtest index d150d46e0..a6c37f1cd 100644 --- a/src/Web.Test/WebTest1.webtest +++ b/src/Web.Test/WebTest1.webtest @@ -1,7 +1,7 @@  - + - + diff --git a/src/packages/repositories.config b/src/packages/repositories.config index 73ccce20c..3406fa91f 100644 --- a/src/packages/repositories.config +++ b/src/packages/repositories.config @@ -1,8 +1,12 @@  + + + + \ No newline at end of file