From 6617860e87e6a48f4eeca92cfd1c175a2b36ac8c Mon Sep 17 00:00:00 2001 From: Clinton Ingram Date: Tue, 5 Sep 2017 02:42:10 -0700 Subject: [PATCH] 0.8.0.0 --- doc/main.md | 173 +++++++++++++++++- doc/web.md | 2 + readme.md | 43 +++-- src/MagicScaler/Magic/ConvolutionTransform.cs | 4 +- src/MagicScaler/Magic/KernelMap.cs | 2 +- src/MagicScaler/Magic/MagicImageProcessor.cs | 2 +- src/MagicScaler/MagicScaler.csproj | 6 +- src/MagicScaler/Utilities/MiscExtensions.cs | 2 +- src/MagicScaler/WIC/WicPlanarCache.cs | 2 +- src/WebRSize/WebRSize.csproj | 4 +- 10 files changed, 206 insertions(+), 34 deletions(-) diff --git a/doc/main.md b/doc/main.md index 2ed1dfa7..8b243f5a 100644 --- a/doc/main.md +++ b/doc/main.md @@ -29,15 +29,39 @@ Default Value: true if the runtime/JIT and hardware support hardware-accelerated ### ProcessImage(string, Stream, ProcessImageSettings) -Accepts a file path for the input image, a stream for the output image, and a ProcessImageSettings object for settings. The output stream must allow Seek and Write. +Accepts a file path for the input image, a stream for the output image, and a [ProcessImageSettings](#processimagesettings) object for settings. The output stream must allow Seek and Write. Returns a [ProcessImageResult](#processimageresult). -### ProcessImage(byte[], Stream, ProcessImageSettings) +### ProcessImage(ArraySegment<byte>, Stream, ProcessImageSettings) -Accepts a byte array for the input image, a stream for the output image, and a ProcessImageSettings object for settings. The output stream must allow Seek and Write. +Accepts a byte ArraySegment for the input image, a stream for the output image, and a [ProcessImageSettings](#processimagesettings) object for settings. The output stream must allow Seek and Write. Returns a [ProcessImageResult](#processimageresult). ### ProcessImage(Stream, Stream, ProcessImageSettings) -Accepts a stream for the input image, a stream for the output image, and a ProcessImageSettings object for settings. The output stream must allow Seek and Write. The input stream must allow Seek and Read. +Accepts a stream for the input image, a stream for the output image, and a [ProcessImageSettings](#processimagesettings) object for settings. The output stream must allow Seek and Write. The input stream must allow Seek and Read. Returns a [ProcessImageResult](#processimageresult). + +### ProcessImage(IPixelSource, Stream, ProcessImageSettings) + +Accepts an [IPixelSource](#ipixelsource) input, a stream for the output image, and a [ProcessImageSettings](#processimagesettings) object for settings. The output stream must allow Seek and Write. Returns a [ProcessImageResult](#processimageresult). + +### BuildPipeline(string, ProcessImageSettings) + +Accepts a file path for the input image and a [ProcessImageSettings](#processimagesettings) object for settings. Returns a [ProcessingPipeline](#processingpipeline) for custom processing. + +### BuildPipeline(ArraySegment<byte>, ProcessImageSettings) + +Accepts a byte ArraySegment for the input image and a [ProcessImageSettings](#processimagesettings) object for settings. Returns a [ProcessingPipeline](#processingpipeline) for custom processing. + +### BuildPipeline(Stream, ProcessImageSettings) + +Accepts a stream for the input image and a [ProcessImageSettings](#processimagesettings) object for settings. Returns a [ProcessingPipeline](#processingpipeline) for custom processing. The input stream must allow Seek and Read. + +### BuildPipeline(IPixelSource, ProcessImageSettings) + +Accepts an [IPixelSource](#ipixelsource) input and a [ProcessImageSettings](#processimagesettings) object for settings. Returns a [ProcessingPipeline](#processingpipeline) for custom processing. + +### ExecutePipeline(ProcessingPipeline, Stream) + +Accepts a [ProcessingPipeline](#processingpipeline) and a stream for the output image. This method completes pipeline processing by requesting the processed pixels and saving the output. The output stream must allow Seek and Read. Returns a [ProcessImageResult](#processimageresult). ## GdiImageProcessor @@ -133,7 +157,7 @@ A [GammaMode](#gammamode) value indicating whether the scaling algorithm is appl Default value: GammaMode.Linear -### MetadataNames: IEnumerable +### MetadataNames: IEnumerable<string> A list of metadata policy names or explicit metadata paths to be copied from the input image to the output image. This can be useful for preserving author or copyright EXIF tags in the output image. See the [Windows Photo Metadata Policies](https://msdn.microsoft.com/en-us/library/windows/desktop/ee872003(v=vs.85).aspx) for examples of commonly-used values, or the [Metadata Query Language Overview](https://msdn.microsoft.com/en-us/library/windows/desktop/ee872003(v=vs.85).aspx) for explicit path syntax. @@ -343,3 +367,142 @@ The support radius of the sampling function. The sampling window will be twice The weighting function. This function accepts a distance from the destination sample's center and returns a weight for the sample at that distance. +## ProcessImageResult + +This class encapsulates information about the results of an image processing operation. It includes the settings used for the processing as well as some basic instrumentation. + +### Settings: ProcessImageSettings + +The settings used for the processing operation. If any settings supplied in the input were set to automatic values, this object will reflect the calculated values used. + +### Stats: IEnumerable<PixelSourceStats> + +A collection of [PixelSourceStats](#pixelsourcestats) objects containing information about the number of pixels processed and time taken in each stage of the pipeline. + +## PixelSourceStats + +This class encapsulates basic instrumentation for the [IPixelSource](#ipixelsource) used in each stage of the processing pipeline. + +### CallCount: int + +The number of times CopyPixels() was called on this pixel source. + +### PixelCount: int + +The total number of pixels requested from the pixel source. + +### ProcessingTime: double + +The total processing time (in milliseconds) for this pixel source. Some WIC wrappers may report times that include the processing of chained pixel sources they use and may not, therefore report times accurately. This information is most useful for diagnosing performance issues in your own pixel sources or transforms. + +### SourceName: string + +The name of the pixel source as returned by ToString(). The default ToString() implementation returns the class name, but this may be overridden, so the output may not make sense. + +## IPixelSource + +This interface defines a custom pixel source. It can either retrieve those pixels from an upstream source or can generate them itself. For a sample implementation, refer to the [TestPatternPixelSource](../src/MagicScaler/Magic/TestPatternPixelSource.cs) code. + +### Width: int + +The width of the source image in pixels. + +### Height: int + +The height of the source image in pixels. + +### Format: Guid + +The [WIC pixel format](https://msdn.microsoft.com/en-us/library/windows/desktop/ee719797.aspx) GUID of the source image. For the current version, this must be a value included as one of the [PixelFormats](#pixelformats) static fields. + +### CopyPixels(Rectangle, long, long, IntPtr) + +Copy pixels from the source image. The caller will provide a rectangle specifying an area of interest and an IntPtr that points to a destination byte buffer as well as a stride and buffer length. If writing a custom IPixelSource, it is your responsibility to implement this method to provide pixels to downstream sources and transforms. + +## PixelFormats + +This static class contains member fields for each of the supported WIC pixel format GUIDs. + +### Bgr24bpp + +24 bits-per-pixel. 8 bits-per-channel in BGR channel order. + +### Bgra32bpp + +32 bits-per-pixel. 8 bits-per-channel in BGR channel order, plus an 8-bit alpha channel. + +### Grey8bpp + +8 bits-per-pixel greyscale. + +## IPixelTransform : IPixelSource + +This interface inherits from [IPixelSource](#ipixelsource) and is intended to be used to build a custom processing step. For a sample implementation, refer to the [ColorMatrixTransform](../src/MagicScaler/Magic/ColorMatrixTransform.cs) code. + +### Init(IPixelSource) + +The pipeline will call this method and pass in the upstream pixel source. Use this method to configure the transform according to its own settings and the properties of the upstream source. + +## ProcessingPipeline + +This class represents an image processing pipeline that is configured but not yet executed. This allows for further customization of the processing, such as filtering, before the pipeline is executed and the output image saved. It also allows pixels to be pulled from the pipeline rather than written directly to an output image. + +### PixelSource: IPixelSource + +The [IPixelSource](#ipixelsource) representing the current last step of the pipeline. The image properties and CopyPixels() results reflect all processing that has been configured up to the current point in the pipeline. + +### Settings: ProcessImageSettings + +The [ProcessImageSettings](#processimagesettings) object representing the current state of the settings on this pipeline. Any settings configured with automatic values initially will have their calculated values at this point. + +### Stats: IEnumerable<PixelSourceStats> + +A collection of the [PixelSourceStats](#pixelsourcestats) for all processing up to this point. Until CopyPixels() is called on the PixelSource, there will be no stats to report. + +### AddTransform(IPixelTransform) + +Adds an [IPixelTransform](#ipixeltransform) to the pipeline. This allows for custom filtering of the pipeline output before the final image is saved. + +### ExecutePipeline(Stream) + +This extension method on the [MagicImageProcessor](#magicimageprocessor) requests all pixels from the pipeline and saves the output to a stream. You may use this after configuring the pipeline (e.g. adding filters) if you do not wish to request the pixels from the PixelSource. + +## ImageFileInfo + +This class reads and exposes basic information about an image file from its header. + +### ContainerType: FileFormat + +The [FileFormat](#fileformat) of the image. This is based on the contents of the image, not its file name/extension. + +### FileDate: DateTime + +The last modified date of the image file, if available. + +### FileSize: int + +The size of the image file, in bytes, if available. + +### Frames: FrameInfo[] + +An array of [FrameInfo](#frameinfo) objects, with details about each image frame in the file. + +## FrameInfo + +This class describes a single image frame from within an image file. All valid images have at least one frame, some (e.g. TIFF and GIF) may have many. + +### Width: int + +The width of the image frame in pixels. + +### Height: int + +The height of the image frame in pixels. + +### HasAlpha: bool + +True if the image frame has a separate alpha channel or if it is in an indexed format and any of the color values have a transparency value set. + +### ExifOrientation: Orientation + +The [Exif Orientation](http://www.impulseadventure.com/photo/exif-orientation.html) value stored for this image frame. The Width and Height values are pre-corrected according to this value, so you can ignore it if you are using MagicScaler to process the image, as it performs orientation correction automatically. The integer values defined in the Orientation enumeration match the stored Exif values. diff --git a/doc/web.md b/doc/web.md index ffb180f2..74489d5e 100644 --- a/doc/web.md +++ b/doc/web.md @@ -26,6 +26,7 @@ Processing and caching are managed by an `IHttpModule` implementation called `We The `WebRSizeModule` must receive event notifications for static image requests in your configured folders in order to do its job. There are multiple ways to accomplish this. 1. The module will automatically register itself by using the assembly `PreApplicationStartMethodAttribute`. For some configurations, this may be adequate. However, modules registered programmatically are set up with the `ManagedHandler` [PreCondition](https://blogs.msdn.microsoft.com/david.wang/2006/03/19/iis7-preconditions-and-the-integrated-pipeline/), which means the module will only receive even notifications if a managed `IHttpHandler` is associated with the file extension being requested. For most IIS configurations, image file extensions will be mapped to the unmanaged (and very efficient) IIS static file handler. In these cases, the self-registered module will not receive event notifications and won't work. + 2. You can register the module explicitly in the `system.webServer` section. ``` @@ -36,6 +37,7 @@ The `WebRSizeModule` must receive event notifications for static image requests ``` Omit the `preCondition` attribute on the module entry to ensure it will see all requests, managed or not. The `WebRSizeModule` detects when it has been manually registered and will skip self-registration. This option will always work and is the safe way to go if you are in doubt. + 3. You can set up an explicit handler mapping for image file extension you want to process that maps to a managed `IHttpHandler`. ``` diff --git a/readme.md b/readme.md index afecdd94..c7e6bd69 100644 --- a/readme.md +++ b/readme.md @@ -61,24 +61,31 @@ See the [documentation page](doc/web.md) for more details. Release History --------------- -#### MagicScaler 0.7.1.0 -* Allow 0 Width and Height in Crop Mode from WebRSize. This re-enables crop-only or transcode-only operations. - -#### MagicScaler 0.7.0.0 -* Added .NET Core version. The Core build does not include metadata support (including auto-rotation) due to the absence of CustomMarshaler support in NetStandard <2. -* Added vectorized (SIMD) versions of convolvers and matting/compositing. Can be enabled/disabled via a global setting. -* Added pooling for all internal pixel buffers. Reduces garbage collections overall and improves GC performance related to buffer pinning. -* Added support for greyscale (indexed) BMP output and proper greyscale palettes for indexed PNG and GIF. -* Added support for custom DPI settings. Copy from input image or set explicitly. -* Added support for configuring resampling filter with dictionary config (for use with WebRSize). -* Added global setting to enable/disable the planar processing pipeline. -* Expanded scenarios in which the planar pipeline can be used. It now works for all planar inputs. -* Increased quality of default resamplers for high-ratio downscaling. The improved performance of the convolvers means no penalty for always scaling high-quality. -* Fixed invalid pixel format error when using planar processing with indexed color output. -* Fixed argument out of range error when using planar processing with non-planar output at some output sizes. - -#### WebRSize 0.2.2.0 -* Added allowEnlarge setting to the imageFolders config. This enables/disables image enlarging by the WebRSizeHandler. This value is set to false by default, meaning you will have to opt in to allow enlarging starting with this version. +#### MagicScaler 0.8.0.0 +NOTE: This version contains breaking changes to the API. While your code will most likely not require changes, you will have to rebuild when upgrading. + +* Changed parameter names on public methods to be more descriptive. +* Changed ProcessImage() overloads that accepted byte[] to accept ArraySegment<byte>. +* Added metadata support (including Exif auto-rotation) to the .NET Core version. +* Added ImageFileInfo class to expose basic information read from image headers. +* Added IPixelSource interface to allow clients to feed pixels into the pipeline from custom sources. +* Added IPixelTransform class to allow custom filtering. +* Added ProcessingPipeline class to allow clients to request pixels from the pipeline without saving directly to an image file. +* Added ProcessImageResults class to expose calculated settings used and basic instrumentation. +* Added sample IPixelSource and IPixelTransform implementations. +* Improved fixed-point math accuracy for non-SIMD implementation. +* Improved RGBA performance in SIMD implementation. +* Improved Auto output format logic to match WebRSize. +* Fixed invalid crop values when using Hybrid scaling. +* Fixed invalid crop offsets when using Planar mode. +* UnsharpMaskSettings no longer overrides the Sharpen setting. If Sharpen is false, there will be no auto-sharpening regardless of UnsharpMaskSettings. + +#### WebRSize 0.3.0.0 +NOTE: Cache file naming has changed in this version. You should empty your WebRSize disk cache when upgrading. + +* Changed cache file name generator to use the correct file extension when transcoding to a different format. +* Fixed a bug in the cache file name generator that caused duplicate cache files. +* Improved speed and reduced allocations in the HTTP intercept module. See the [releases page](https://github.com/saucecontrol/PhotoSauce/releases) for previous updates. diff --git a/src/MagicScaler/Magic/ConvolutionTransform.cs b/src/MagicScaler/Magic/ConvolutionTransform.cs index 0d895400..2b30120d 100644 --- a/src/MagicScaler/Magic/ConvolutionTransform.cs +++ b/src/MagicScaler/Magic/ConvolutionTransform.cs @@ -197,7 +197,7 @@ public virtual void Dispose() if (WorkBuff.Array != LineBuff.Array) ArrayPool.Shared.Return(WorkBuff.Array ?? Array.Empty()); - LineBuff = WorkBuff = IntBuff = default(ArraySegment); + LineBuff = WorkBuff = IntBuff = default; } public override string ToString() => XProcessor?.ToString() ?? base.ToString(); @@ -234,7 +234,7 @@ public override void Dispose() base.Dispose(); ArrayPool.Shared.Return(blurBuff.Array ?? Array.Empty()); - blurBuff = default(ArraySegment); + blurBuff = default; } public override string ToString() => $"{processor?.ToString() ?? base.ToString()}: Sharpen"; diff --git a/src/MagicScaler/Magic/KernelMap.cs b/src/MagicScaler/Magic/KernelMap.cs index 486b80c4..0f1c4597 100644 --- a/src/MagicScaler/Magic/KernelMap.cs +++ b/src/MagicScaler/Magic/KernelMap.cs @@ -221,7 +221,7 @@ unsafe public static KernelMap MakeBlurMap(uint size, double radius, int colo public void Dispose() { ArrayPool.Shared.Return(Map.Array ?? Array.Empty()); - Map = default(ArraySegment); + Map = default; } } } \ No newline at end of file diff --git a/src/MagicScaler/Magic/MagicImageProcessor.cs b/src/MagicScaler/Magic/MagicImageProcessor.cs index 4028f3e0..1fa6b121 100644 --- a/src/MagicScaler/Magic/MagicImageProcessor.cs +++ b/src/MagicScaler/Magic/MagicImageProcessor.cs @@ -117,7 +117,7 @@ public static ProcessingPipeline BuildPipeline(IPixelSource imgSource, ProcessIm return new ProcessingPipeline(ctx); } - public static ProcessImageResult ExecutePipeline(ProcessingPipeline pipeline, Stream outStream) + public static ProcessImageResult ExecutePipeline(this ProcessingPipeline pipeline, Stream outStream) { return executePipeline(pipeline.Context, outStream); } diff --git a/src/MagicScaler/MagicScaler.csproj b/src/MagicScaler/MagicScaler.csproj index 0984ac7f..05221f3d 100644 --- a/src/MagicScaler/MagicScaler.csproj +++ b/src/MagicScaler/MagicScaler.csproj @@ -7,8 +7,8 @@ net46;netcoreapp1.0;netcoreapp2.0;netstandard1.3 1.0.4 true - 7 - 0.8.0-beta4 + latest + 0.8.0 Clinton Ingram PhotoSauce MagicScaler @@ -44,7 +44,7 @@ - + diff --git a/src/MagicScaler/Utilities/MiscExtensions.cs b/src/MagicScaler/Utilities/MiscExtensions.cs index 4319fb61..0a726797 100644 --- a/src/MagicScaler/Utilities/MiscExtensions.cs +++ b/src/MagicScaler/Utilities/MiscExtensions.cs @@ -68,7 +68,7 @@ public static ArraySegment Zero(this ArraySegment a) public static TValue GetValueOrDefault(this IDictionary dic, TKey key, Func valueFactory = null) { - return dic.TryGetValue(key, out var value) ? value : valueFactory == null ? default(TValue) : valueFactory(); + return dic.TryGetValue(key, out var value) ? value : valueFactory == null ? default : valueFactory(); } #if NET46 diff --git a/src/MagicScaler/WIC/WicPlanarCache.cs b/src/MagicScaler/WIC/WicPlanarCache.cs index 0983b212..117206ea 100644 --- a/src/MagicScaler/WIC/WicPlanarCache.cs +++ b/src/MagicScaler/WIC/WicPlanarCache.cs @@ -188,7 +188,7 @@ public void Dispose() { ArrayPool.Shared.Return(lineBuffY.Array ?? Array.Empty()); ArrayPool.Shared.Return(lineBuffC.Array ?? Array.Empty()); - lineBuffY = lineBuffC = default(ArraySegment); + lineBuffY = lineBuffC = default; } } diff --git a/src/WebRSize/WebRSize.csproj b/src/WebRSize/WebRSize.csproj index d41324eb..294d47c5 100644 --- a/src/WebRSize/WebRSize.csproj +++ b/src/WebRSize/WebRSize.csproj @@ -5,8 +5,8 @@ PhotoSauce.WebRSize WebRSize net46 - 7 - 0.3.0-beta1 + latest + 0.3.0 Clinton Ingram Web extensions for the MagicScaler library, inlcluding an HTTP request intercept module for automatic image processing. PhotoSauce