mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
33 changed files with 8878 additions and 8889 deletions
@ -1,99 +1,99 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using System.Buffers; |
using System.Buffers; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
|
||||
using SixLabors.ImageSharp.Memory; |
using SixLabors.ImageSharp.Memory; |
||||
using SixLabors.ImageSharp.PixelFormats; |
using SixLabors.ImageSharp.PixelFormats; |
||||
using SixLabors.Memory; |
using SixLabors.Memory; |
||||
using SixLabors.Primitives; |
using SixLabors.Primitives; |
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors.Drawing |
namespace SixLabors.ImageSharp.Processing.Processors.Drawing |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Combines two images together by blending the pixels.
|
/// Combines two images together by blending the pixels.
|
||||
/// </summary>
|
/// </summary>
|
||||
public class DrawImageProcessor : IImageProcessor |
public class DrawImageProcessor : IImageProcessor |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DrawImageProcessor"/> class.
|
/// Initializes a new instance of the <see cref="DrawImageProcessor"/> class.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="image">The image to blend.</param>
|
/// <param name="image">The image to blend.</param>
|
||||
/// <param name="location">The location to draw the blended image.</param>
|
/// <param name="location">The location to draw the blended image.</param>
|
||||
/// <param name="colorBlendingMode">The blending mode to use when drawing the image.</param>
|
/// <param name="colorBlendingMode">The blending mode to use when drawing the image.</param>
|
||||
/// <param name="alphaCompositionMode">The Alpha blending mode to use when drawing the image.</param>
|
/// <param name="alphaCompositionMode">The Alpha blending mode to use when drawing the image.</param>
|
||||
/// <param name="opacity">The opacity of the image to blend.</param>
|
/// <param name="opacity">The opacity of the image to blend.</param>
|
||||
public DrawImageProcessor( |
public DrawImageProcessor( |
||||
Image image, |
Image image, |
||||
Point location, |
Point location, |
||||
PixelColorBlendingMode colorBlendingMode, |
PixelColorBlendingMode colorBlendingMode, |
||||
PixelAlphaCompositionMode alphaCompositionMode, |
PixelAlphaCompositionMode alphaCompositionMode, |
||||
float opacity) |
float opacity) |
||||
{ |
{ |
||||
this.Image = image; |
this.Image = image; |
||||
this.Location = location; |
this.Location = location; |
||||
this.ColorBlendingMode = colorBlendingMode; |
this.ColorBlendingMode = colorBlendingMode; |
||||
this.AlphaCompositionMode = alphaCompositionMode; |
this.AlphaCompositionMode = alphaCompositionMode; |
||||
this.Opacity = opacity; |
this.Opacity = opacity; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the image to blend.
|
/// Gets the image to blend.
|
||||
/// </summary>
|
/// </summary>
|
||||
public Image Image { get; } |
public Image Image { get; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the location to draw the blended image.
|
/// Gets the location to draw the blended image.
|
||||
/// </summary>
|
/// </summary>
|
||||
public Point Location { get; } |
public Point Location { get; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the blending mode to use when drawing the image.
|
/// Gets the blending mode to use when drawing the image.
|
||||
/// </summary>
|
/// </summary>
|
||||
public PixelColorBlendingMode ColorBlendingMode { get; } |
public PixelColorBlendingMode ColorBlendingMode { get; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the Alpha blending mode to use when drawing the image.
|
/// Gets the Alpha blending mode to use when drawing the image.
|
||||
/// </summary>
|
/// </summary>
|
||||
public PixelAlphaCompositionMode AlphaCompositionMode { get; } |
public PixelAlphaCompositionMode AlphaCompositionMode { get; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the opacity of the image to blend.
|
/// Gets the opacity of the image to blend.
|
||||
/// </summary>
|
/// </summary>
|
||||
public float Opacity { get; } |
public float Opacity { get; } |
||||
|
|
||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||
public IImageProcessor<TPixelBg> CreatePixelSpecificProcessor<TPixelBg>() |
public IImageProcessor<TPixelBg> CreatePixelSpecificProcessor<TPixelBg>() |
||||
where TPixelBg : struct, IPixel<TPixelBg> |
where TPixelBg : struct, IPixel<TPixelBg> |
||||
{ |
{ |
||||
var visitor = new ProcessorFactoryVisitor<TPixelBg>(this); |
var visitor = new ProcessorFactoryVisitor<TPixelBg>(this); |
||||
this.Image.AcceptVisitor(visitor); |
this.Image.AcceptVisitor(visitor); |
||||
return visitor.Result; |
return visitor.Result; |
||||
} |
} |
||||
|
|
||||
private class ProcessorFactoryVisitor<TPixelBg> : IImageVisitor |
private class ProcessorFactoryVisitor<TPixelBg> : IImageVisitor |
||||
where TPixelBg : struct, IPixel<TPixelBg> |
where TPixelBg : struct, IPixel<TPixelBg> |
||||
{ |
{ |
||||
private readonly DrawImageProcessor definition; |
private readonly DrawImageProcessor definition; |
||||
|
|
||||
public ProcessorFactoryVisitor(DrawImageProcessor definition) |
public ProcessorFactoryVisitor(DrawImageProcessor definition) |
||||
{ |
{ |
||||
this.definition = definition; |
this.definition = definition; |
||||
} |
} |
||||
|
|
||||
public IImageProcessor<TPixelBg> Result { get; private set; } |
public IImageProcessor<TPixelBg> Result { get; private set; } |
||||
|
|
||||
public void Visit<TPixelFg>(Image<TPixelFg> image) |
public void Visit<TPixelFg>(Image<TPixelFg> image) |
||||
where TPixelFg : struct, IPixel<TPixelFg> |
where TPixelFg : struct, IPixel<TPixelFg> |
||||
{ |
{ |
||||
this.Result = new DrawImageProcessor<TPixelBg, TPixelFg>( |
this.Result = new DrawImageProcessor<TPixelBg, TPixelFg>( |
||||
image, |
image, |
||||
this.definition.Location, |
this.definition.Location, |
||||
this.definition.ColorBlendingMode, |
this.definition.ColorBlendingMode, |
||||
this.definition.AlphaCompositionMode, |
this.definition.AlphaCompositionMode, |
||||
this.definition.Opacity); |
this.definition.Opacity); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,45 +1,45 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
using SixLabors.ImageSharp.PixelFormats; |
||||
using SixLabors.Memory; |
using SixLabors.Memory; |
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors.Drawing |
namespace SixLabors.ImageSharp.Processing.Processors.Drawing |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Defines a processor to fill an <see cref="Image"/> with the given <see cref="IBrush"/>
|
/// Defines a processor to fill an <see cref="Image"/> with the given <see cref="IBrush"/>
|
||||
/// using blending defined by the given <see cref="GraphicsOptions"/>.
|
/// using blending defined by the given <see cref="GraphicsOptions"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
public class FillProcessor : IImageProcessor |
public class FillProcessor : IImageProcessor |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FillProcessor"/> class.
|
/// Initializes a new instance of the <see cref="FillProcessor"/> class.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="brush">The brush to use for filling.</param>
|
/// <param name="brush">The brush to use for filling.</param>
|
||||
/// <param name="options">The <see cref="GraphicsOptions"/> defining how to blend the brush pixels over the image pixels.</param>
|
/// <param name="options">The <see cref="GraphicsOptions"/> defining how to blend the brush pixels over the image pixels.</param>
|
||||
public FillProcessor(IBrush brush, GraphicsOptions options) |
public FillProcessor(IBrush brush, GraphicsOptions options) |
||||
{ |
{ |
||||
this.Brush = brush; |
this.Brush = brush; |
||||
this.Options = options; |
this.Options = options; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the <see cref="IBrush"/> used for filling the destination image.
|
/// Gets the <see cref="IBrush"/> used for filling the destination image.
|
||||
/// </summary>
|
/// </summary>
|
||||
public IBrush Brush { get; } |
public IBrush Brush { get; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the <see cref="GraphicsOptions"/> defining how to blend the brush pixels over the image pixels.
|
/// Gets the <see cref="GraphicsOptions"/> defining how to blend the brush pixels over the image pixels.
|
||||
/// </summary>
|
/// </summary>
|
||||
public GraphicsOptions Options { get; } |
public GraphicsOptions Options { get; } |
||||
|
|
||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||
public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>() |
public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>() |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
return new FillProcessor<TPixel>(this); |
return new FillProcessor<TPixel>(this); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,163 +1,163 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using SixLabors.Fonts; |
using SixLabors.Fonts; |
||||
using SixLabors.ImageSharp.PixelFormats; |
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing |
namespace SixLabors.ImageSharp.Processing |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Options for influencing the drawing functions.
|
/// Options for influencing the drawing functions.
|
||||
/// </summary>
|
/// </summary>
|
||||
public struct TextGraphicsOptions |
public struct TextGraphicsOptions |
||||
{ |
{ |
||||
private const int DefaultTextDpi = 72; |
private const int DefaultTextDpi = 72; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Represents the default <see cref="TextGraphicsOptions"/>.
|
/// Represents the default <see cref="TextGraphicsOptions"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); |
public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); |
||||
|
|
||||
private float? blendPercentage; |
private float? blendPercentage; |
||||
|
|
||||
private int? antialiasSubpixelDepth; |
private int? antialiasSubpixelDepth; |
||||
|
|
||||
private bool? antialias; |
private bool? antialias; |
||||
|
|
||||
private bool? applyKerning; |
private bool? applyKerning; |
||||
|
|
||||
private float? tabWidth; |
private float? tabWidth; |
||||
|
|
||||
private float? dpiX; |
private float? dpiX; |
||||
|
|
||||
private float? dpiY; |
private float? dpiY; |
||||
|
|
||||
private HorizontalAlignment? horizontalAlignment; |
private HorizontalAlignment? horizontalAlignment; |
||||
|
|
||||
private VerticalAlignment? verticalAlignment; |
private VerticalAlignment? verticalAlignment; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TextGraphicsOptions" /> struct.
|
/// Initializes a new instance of the <see cref="TextGraphicsOptions" /> struct.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
||||
public TextGraphicsOptions(bool enableAntialiasing) |
public TextGraphicsOptions(bool enableAntialiasing) |
||||
{ |
{ |
||||
this.applyKerning = true; |
this.applyKerning = true; |
||||
this.tabWidth = 4; |
this.tabWidth = 4; |
||||
this.WrapTextWidth = 0; |
this.WrapTextWidth = 0; |
||||
this.horizontalAlignment = HorizontalAlignment.Left; |
this.horizontalAlignment = HorizontalAlignment.Left; |
||||
this.verticalAlignment = VerticalAlignment.Top; |
this.verticalAlignment = VerticalAlignment.Top; |
||||
|
|
||||
this.antialiasSubpixelDepth = 16; |
this.antialiasSubpixelDepth = 16; |
||||
this.ColorBlendingMode = PixelColorBlendingMode.Normal; |
this.ColorBlendingMode = PixelColorBlendingMode.Normal; |
||||
this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; |
this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; |
||||
this.blendPercentage = 1; |
this.blendPercentage = 1; |
||||
this.antialias = enableAntialiasing; |
this.antialias = enableAntialiasing; |
||||
this.dpiX = DefaultTextDpi; |
this.dpiX = DefaultTextDpi; |
||||
this.dpiY = DefaultTextDpi; |
this.dpiY = DefaultTextDpi; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating whether antialiasing should be applied.
|
/// Gets or sets a value indicating whether antialiasing should be applied.
|
||||
/// </summary>
|
/// </summary>
|
||||
public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } |
public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled.
|
/// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled.
|
||||
/// </summary>
|
/// </summary>
|
||||
public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } |
public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the blending percentage to apply to the drawing operation
|
/// Gets or sets a value indicating the blending percentage to apply to the drawing operation
|
||||
/// </summary>
|
/// </summary>
|
||||
public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } |
public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } |
||||
|
|
||||
// In the future we could expose a PixelBlender<TPixel> directly on here
|
// In the future we could expose a PixelBlender<TPixel> directly on here
|
||||
// or some forms of PixelBlender factory for each pixel type. Will need
|
// or some forms of PixelBlender factory for each pixel type. Will need
|
||||
// some API thought post V1.
|
// some API thought post V1.
|
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the color blending percentage to apply to the drawing operation
|
/// Gets or sets a value indicating the color blending percentage to apply to the drawing operation
|
||||
/// </summary>
|
/// </summary>
|
||||
public PixelColorBlendingMode ColorBlendingMode { get; set; } |
public PixelColorBlendingMode ColorBlendingMode { get; set; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the color blending percentage to apply to the drawing operation
|
/// Gets or sets a value indicating the color blending percentage to apply to the drawing operation
|
||||
/// </summary>
|
/// </summary>
|
||||
public PixelAlphaCompositionMode AlphaCompositionMode { get; set; } |
public PixelAlphaCompositionMode AlphaCompositionMode { get; set; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating whether the text should be drawing with kerning enabled.
|
/// Gets or sets a value indicating whether the text should be drawing with kerning enabled.
|
||||
/// </summary>
|
/// </summary>
|
||||
public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } |
public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the number of space widths a tab should lock to.
|
/// Gets or sets a value indicating the number of space widths a tab should lock to.
|
||||
/// </summary>
|
/// </summary>
|
||||
public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } |
public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating if greater than zero determine the width at which text should wrap.
|
/// Gets or sets a value indicating if greater than zero determine the width at which text should wrap.
|
||||
/// </summary>
|
/// </summary>
|
||||
public float WrapTextWidth { get; set; } |
public float WrapTextWidth { get; set; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the DPI to render text along the X axis.
|
/// Gets or sets a value indicating the DPI to render text along the X axis.
|
||||
/// </summary>
|
/// </summary>
|
||||
public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } |
public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the DPI to render text along the Y axis.
|
/// Gets or sets a value indicating the DPI to render text along the Y axis.
|
||||
/// </summary>
|
/// </summary>
|
||||
public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } |
public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating how to align the text relative to the rendering space.
|
/// Gets or sets a value indicating how to align the text relative to the rendering space.
|
||||
/// If <see cref="WrapTextWidth"/> is greater than zero it will align relative to the space
|
/// If <see cref="WrapTextWidth"/> is greater than zero it will align relative to the space
|
||||
/// defined by the location and width, if <see cref="WrapTextWidth"/> equals zero, and thus
|
/// defined by the location and width, if <see cref="WrapTextWidth"/> equals zero, and thus
|
||||
/// wrapping disabled, then the alignment is relative to the drawing location.
|
/// wrapping disabled, then the alignment is relative to the drawing location.
|
||||
/// </summary>
|
/// </summary>
|
||||
public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } |
public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating how to align the text relative to the rendering space.
|
/// Gets or sets a value indicating how to align the text relative to the rendering space.
|
||||
/// </summary>
|
/// </summary>
|
||||
public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } |
public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="GraphicsOptions"/> to <see cref="TextGraphicsOptions"/>.
|
/// Performs an implicit conversion from <see cref="GraphicsOptions"/> to <see cref="TextGraphicsOptions"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||
/// <returns>
|
/// <returns>
|
||||
/// The result of the conversion.
|
/// The result of the conversion.
|
||||
/// </returns>
|
/// </returns>
|
||||
public static implicit operator TextGraphicsOptions(GraphicsOptions options) |
public static implicit operator TextGraphicsOptions(GraphicsOptions options) |
||||
{ |
{ |
||||
return new TextGraphicsOptions(options.Antialias) |
return new TextGraphicsOptions(options.Antialias) |
||||
{ |
{ |
||||
AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, |
AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, |
||||
blendPercentage = options.BlendPercentage, |
blendPercentage = options.BlendPercentage, |
||||
ColorBlendingMode = options.ColorBlendingMode, |
ColorBlendingMode = options.ColorBlendingMode, |
||||
AlphaCompositionMode = options.AlphaCompositionMode |
AlphaCompositionMode = options.AlphaCompositionMode |
||||
}; |
}; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Performs an explicit conversion from <see cref="TextGraphicsOptions"/> to <see cref="GraphicsOptions"/>.
|
/// Performs an explicit conversion from <see cref="TextGraphicsOptions"/> to <see cref="GraphicsOptions"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||
/// <returns>
|
/// <returns>
|
||||
/// The result of the conversion.
|
/// The result of the conversion.
|
||||
/// </returns>
|
/// </returns>
|
||||
public static explicit operator GraphicsOptions(TextGraphicsOptions options) |
public static explicit operator GraphicsOptions(TextGraphicsOptions options) |
||||
{ |
{ |
||||
return new GraphicsOptions(options.Antialias) |
return new GraphicsOptions(options.Antialias) |
||||
{ |
{ |
||||
AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, |
AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, |
||||
ColorBlendingMode = options.ColorBlendingMode, |
ColorBlendingMode = options.ColorBlendingMode, |
||||
AlphaCompositionMode = options.AlphaCompositionMode, |
AlphaCompositionMode = options.AlphaCompositionMode, |
||||
BlendPercentage = options.BlendPercentage |
BlendPercentage = options.BlendPercentage |
||||
}; |
}; |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,164 +1,164 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using SixLabors.ImageSharp.Formats; |
using SixLabors.ImageSharp.Formats; |
||||
using SixLabors.ImageSharp.Formats.Bmp; |
using SixLabors.ImageSharp.Formats.Bmp; |
||||
using SixLabors.ImageSharp.Formats.Gif; |
using SixLabors.ImageSharp.Formats.Gif; |
||||
using SixLabors.ImageSharp.Formats.Jpeg; |
using SixLabors.ImageSharp.Formats.Jpeg; |
||||
using SixLabors.ImageSharp.Formats.Png; |
using SixLabors.ImageSharp.Formats.Png; |
||||
using SixLabors.ImageSharp.IO; |
using SixLabors.ImageSharp.IO; |
||||
using SixLabors.ImageSharp.Processing; |
using SixLabors.ImageSharp.Processing; |
||||
using SixLabors.Memory; |
using SixLabors.Memory; |
||||
|
|
||||
namespace SixLabors.ImageSharp |
namespace SixLabors.ImageSharp |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Provides configuration code which allows altering default behaviour or extending the library.
|
/// Provides configuration code which allows altering default behaviour or extending the library.
|
||||
/// </summary>
|
/// </summary>
|
||||
public sealed class Configuration |
public sealed class Configuration |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// A lazily initialized configuration default instance.
|
/// A lazily initialized configuration default instance.
|
||||
/// </summary>
|
/// </summary>
|
||||
private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance); |
private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance); |
||||
|
|
||||
private int maxDegreeOfParallelism = Environment.ProcessorCount; |
private int maxDegreeOfParallelism = Environment.ProcessorCount; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Configuration" /> class.
|
/// Initializes a new instance of the <see cref="Configuration" /> class.
|
||||
/// </summary>
|
/// </summary>
|
||||
public Configuration() |
public Configuration() |
||||
{ |
{ |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Configuration" /> class.
|
/// Initializes a new instance of the <see cref="Configuration" /> class.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="configurationModules">A collection of configuration modules to register</param>
|
/// <param name="configurationModules">A collection of configuration modules to register</param>
|
||||
public Configuration(params IConfigurationModule[] configurationModules) |
public Configuration(params IConfigurationModule[] configurationModules) |
||||
{ |
{ |
||||
if (configurationModules != null) |
if (configurationModules != null) |
||||
{ |
{ |
||||
foreach (IConfigurationModule p in configurationModules) |
foreach (IConfigurationModule p in configurationModules) |
||||
{ |
{ |
||||
p.Configure(this); |
p.Configure(this); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the default <see cref="Configuration"/> instance.
|
/// Gets the default <see cref="Configuration"/> instance.
|
||||
/// </summary>
|
/// </summary>
|
||||
public static Configuration Default { get; } = Lazy.Value; |
public static Configuration Default { get; } = Lazy.Value; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets the maximum number of concurrent tasks enabled in ImageSharp algorithms
|
/// Gets or sets the maximum number of concurrent tasks enabled in ImageSharp algorithms
|
||||
/// configured with this <see cref="Configuration"/> instance.
|
/// configured with this <see cref="Configuration"/> instance.
|
||||
/// Initialized with <see cref="Environment.ProcessorCount"/> by default.
|
/// Initialized with <see cref="Environment.ProcessorCount"/> by default.
|
||||
/// </summary>
|
/// </summary>
|
||||
public int MaxDegreeOfParallelism |
public int MaxDegreeOfParallelism |
||||
{ |
{ |
||||
get => this.maxDegreeOfParallelism; |
get => this.maxDegreeOfParallelism; |
||||
set |
set |
||||
{ |
{ |
||||
if (value <= 0) |
if (value <= 0) |
||||
{ |
{ |
||||
throw new ArgumentOutOfRangeException(nameof(this.MaxDegreeOfParallelism)); |
throw new ArgumentOutOfRangeException(nameof(this.MaxDegreeOfParallelism)); |
||||
} |
} |
||||
|
|
||||
this.maxDegreeOfParallelism = value; |
this.maxDegreeOfParallelism = value; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the currently registered <see cref="IImageFormat"/>s.
|
/// Gets the currently registered <see cref="IImageFormat"/>s.
|
||||
/// </summary>
|
/// </summary>
|
||||
public IEnumerable<IImageFormat> ImageFormats => this.ImageFormatsManager.ImageFormats; |
public IEnumerable<IImageFormat> ImageFormats => this.ImageFormatsManager.ImageFormats; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source.
|
/// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source.
|
||||
/// </summary>
|
/// </summary>
|
||||
public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; |
public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets the <see cref="ImageFormatManager"/> that is currently in use.
|
/// Gets or sets the <see cref="ImageFormatManager"/> that is currently in use.
|
||||
/// </summary>
|
/// </summary>
|
||||
public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager(); |
public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets the <see cref="MemoryAllocator"/> that is currently in use.
|
/// Gets or sets the <see cref="MemoryAllocator"/> that is currently in use.
|
||||
/// </summary>
|
/// </summary>
|
||||
public MemoryAllocator MemoryAllocator { get; set; } = ArrayPoolMemoryAllocator.CreateDefault(); |
public MemoryAllocator MemoryAllocator { get; set; } = ArrayPoolMemoryAllocator.CreateDefault(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the maximum header size of all the formats.
|
/// Gets the maximum header size of all the formats.
|
||||
/// </summary>
|
/// </summary>
|
||||
internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize; |
internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets the filesystem helper for accessing the local file system.
|
/// Gets or sets the filesystem helper for accessing the local file system.
|
||||
/// </summary>
|
/// </summary>
|
||||
internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); |
internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets the working buffer size hint for image processors.
|
/// Gets or sets the working buffer size hint for image processors.
|
||||
/// The default value is 1MB.
|
/// The default value is 1MB.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <remarks>
|
/// <remarks>
|
||||
/// Currently only used by Resize.
|
/// Currently only used by Resize.
|
||||
/// </remarks>
|
/// </remarks>
|
||||
internal int WorkingBufferSizeHintInBytes { get; set; } = 1 * 1024 * 1024; |
internal int WorkingBufferSizeHintInBytes { get; set; } = 1 * 1024 * 1024; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets the image operations provider factory.
|
/// Gets or sets the image operations provider factory.
|
||||
/// </summary>
|
/// </summary>
|
||||
internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); |
internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Registers a new format provider.
|
/// Registers a new format provider.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="configuration">The configuration provider to call configure on.</param>
|
/// <param name="configuration">The configuration provider to call configure on.</param>
|
||||
public void Configure(IConfigurationModule configuration) |
public void Configure(IConfigurationModule configuration) |
||||
{ |
{ |
||||
Guard.NotNull(configuration, nameof(configuration)); |
Guard.NotNull(configuration, nameof(configuration)); |
||||
configuration.Configure(this); |
configuration.Configure(this); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Creates a shallow copy of the <see cref="Configuration"/>.
|
/// Creates a shallow copy of the <see cref="Configuration"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <returns>A new configuration instance.</returns>
|
/// <returns>A new configuration instance.</returns>
|
||||
public Configuration Clone() |
public Configuration Clone() |
||||
{ |
{ |
||||
return new Configuration |
return new Configuration |
||||
{ |
{ |
||||
MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, |
MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, |
||||
ImageFormatsManager = this.ImageFormatsManager, |
ImageFormatsManager = this.ImageFormatsManager, |
||||
MemoryAllocator = this.MemoryAllocator, |
MemoryAllocator = this.MemoryAllocator, |
||||
ImageOperationsProvider = this.ImageOperationsProvider, |
ImageOperationsProvider = this.ImageOperationsProvider, |
||||
ReadOrigin = this.ReadOrigin, |
ReadOrigin = this.ReadOrigin, |
||||
FileSystem = this.FileSystem, |
FileSystem = this.FileSystem, |
||||
WorkingBufferSizeHintInBytes = this.WorkingBufferSizeHintInBytes, |
WorkingBufferSizeHintInBytes = this.WorkingBufferSizeHintInBytes, |
||||
}; |
}; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Creates the default instance with the following <see cref="IConfigurationModule"/>s preregistered:
|
/// Creates the default instance with the following <see cref="IConfigurationModule"/>s preregistered:
|
||||
/// <see cref="PngConfigurationModule"/>
|
/// <see cref="PngConfigurationModule"/>
|
||||
/// <see cref="JpegConfigurationModule"/>
|
/// <see cref="JpegConfigurationModule"/>
|
||||
/// <see cref="GifConfigurationModule"/>
|
/// <see cref="GifConfigurationModule"/>
|
||||
/// <see cref="BmpConfigurationModule"/>.
|
/// <see cref="BmpConfigurationModule"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <returns>The default configuration of <see cref="Configuration"/>.</returns>
|
/// <returns>The default configuration of <see cref="Configuration"/>.</returns>
|
||||
internal static Configuration CreateDefaultInstance() |
internal static Configuration CreateDefaultInstance() |
||||
{ |
{ |
||||
return new Configuration( |
return new Configuration( |
||||
new PngConfigurationModule(), |
new PngConfigurationModule(), |
||||
new JpegConfigurationModule(), |
new JpegConfigurationModule(), |
||||
new GifConfigurationModule(), |
new GifConfigurationModule(), |
||||
new BmpConfigurationModule()); |
new BmpConfigurationModule()); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,201 +1,201 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using System; |
using System; |
||||
using System.Collections.Concurrent; |
using System.Collections.Concurrent; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using System.Linq; |
using System.Linq; |
||||
|
|
||||
namespace SixLabors.ImageSharp.Formats |
namespace SixLabors.ImageSharp.Formats |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Collection of Image Formats to be used in <see cref="Configuration" /> class.
|
/// Collection of Image Formats to be used in <see cref="Configuration" /> class.
|
||||
/// </summary>
|
/// </summary>
|
||||
public class ImageFormatManager |
public class ImageFormatManager |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Used for locking against as there is no ConcurrentSet type.
|
/// Used for locking against as there is no ConcurrentSet type.
|
||||
/// <see href="https://github.com/dotnet/corefx/issues/6318"/>
|
/// <see href="https://github.com/dotnet/corefx/issues/6318"/>
|
||||
/// </summary>
|
/// </summary>
|
||||
private static readonly object HashLock = new object(); |
private static readonly object HashLock = new object(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
|
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
|
||||
/// </summary>
|
/// </summary>
|
||||
private readonly ConcurrentDictionary<IImageFormat, IImageEncoder> mimeTypeEncoders = new ConcurrentDictionary<IImageFormat, IImageEncoder>(); |
private readonly ConcurrentDictionary<IImageFormat, IImageEncoder> mimeTypeEncoders = new ConcurrentDictionary<IImageFormat, IImageEncoder>(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
|
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
|
||||
/// </summary>
|
/// </summary>
|
||||
private readonly ConcurrentDictionary<IImageFormat, IImageDecoder> mimeTypeDecoders = new ConcurrentDictionary<IImageFormat, IImageDecoder>(); |
private readonly ConcurrentDictionary<IImageFormat, IImageDecoder> mimeTypeDecoders = new ConcurrentDictionary<IImageFormat, IImageDecoder>(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// The list of supported <see cref="IImageFormat"/>s.
|
/// The list of supported <see cref="IImageFormat"/>s.
|
||||
/// </summary>
|
/// </summary>
|
||||
private readonly HashSet<IImageFormat> imageFormats = new HashSet<IImageFormat>(); |
private readonly HashSet<IImageFormat> imageFormats = new HashSet<IImageFormat>(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// The list of supported <see cref="IImageFormatDetector"/>s.
|
/// The list of supported <see cref="IImageFormatDetector"/>s.
|
||||
/// </summary>
|
/// </summary>
|
||||
private ConcurrentBag<IImageFormatDetector> imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>(); |
private ConcurrentBag<IImageFormatDetector> imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImageFormatManager" /> class.
|
/// Initializes a new instance of the <see cref="ImageFormatManager" /> class.
|
||||
/// </summary>
|
/// </summary>
|
||||
public ImageFormatManager() |
public ImageFormatManager() |
||||
{ |
{ |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the maximum header size of all the formats.
|
/// Gets the maximum header size of all the formats.
|
||||
/// </summary>
|
/// </summary>
|
||||
internal int MaxHeaderSize { get; private set; } |
internal int MaxHeaderSize { get; private set; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the currently registered <see cref="IImageFormat"/>s.
|
/// Gets the currently registered <see cref="IImageFormat"/>s.
|
||||
/// </summary>
|
/// </summary>
|
||||
public IEnumerable<IImageFormat> ImageFormats => this.imageFormats; |
public IEnumerable<IImageFormat> ImageFormats => this.imageFormats; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the currently registered <see cref="IImageFormatDetector"/>s.
|
/// Gets the currently registered <see cref="IImageFormatDetector"/>s.
|
||||
/// </summary>
|
/// </summary>
|
||||
internal IEnumerable<IImageFormatDetector> FormatDetectors => this.imageFormatDetectors; |
internal IEnumerable<IImageFormatDetector> FormatDetectors => this.imageFormatDetectors; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the currently registered <see cref="IImageDecoder"/>s.
|
/// Gets the currently registered <see cref="IImageDecoder"/>s.
|
||||
/// </summary>
|
/// </summary>
|
||||
internal IEnumerable<KeyValuePair<IImageFormat, IImageDecoder>> ImageDecoders => this.mimeTypeDecoders; |
internal IEnumerable<KeyValuePair<IImageFormat, IImageDecoder>> ImageDecoders => this.mimeTypeDecoders; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the currently registered <see cref="IImageEncoder"/>s.
|
/// Gets the currently registered <see cref="IImageEncoder"/>s.
|
||||
/// </summary>
|
/// </summary>
|
||||
internal IEnumerable<KeyValuePair<IImageFormat, IImageEncoder>> ImageEncoders => this.mimeTypeEncoders; |
internal IEnumerable<KeyValuePair<IImageFormat, IImageEncoder>> ImageEncoders => this.mimeTypeEncoders; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Registers a new format provider.
|
/// Registers a new format provider.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="format">The format to register as a known format.</param>
|
/// <param name="format">The format to register as a known format.</param>
|
||||
public void AddImageFormat(IImageFormat format) |
public void AddImageFormat(IImageFormat format) |
||||
{ |
{ |
||||
Guard.NotNull(format, nameof(format)); |
Guard.NotNull(format, nameof(format)); |
||||
Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); |
Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); |
||||
Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); |
Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); |
||||
|
|
||||
lock (HashLock) |
lock (HashLock) |
||||
{ |
{ |
||||
if (!this.imageFormats.Contains(format)) |
if (!this.imageFormats.Contains(format)) |
||||
{ |
{ |
||||
this.imageFormats.Add(format); |
this.imageFormats.Add(format); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// For the specified file extensions type find the e <see cref="IImageFormat"/>.
|
/// For the specified file extensions type find the e <see cref="IImageFormat"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="extension">The extension to discover</param>
|
/// <param name="extension">The extension to discover</param>
|
||||
/// <returns>The <see cref="IImageFormat"/> if found otherwise null</returns>
|
/// <returns>The <see cref="IImageFormat"/> if found otherwise null</returns>
|
||||
public IImageFormat FindFormatByFileExtension(string extension) |
public IImageFormat FindFormatByFileExtension(string extension) |
||||
{ |
{ |
||||
Guard.NotNullOrWhiteSpace(extension, nameof(extension)); |
Guard.NotNullOrWhiteSpace(extension, nameof(extension)); |
||||
|
|
||||
if (extension[0] == '.') |
if (extension[0] == '.') |
||||
{ |
{ |
||||
extension = extension.Substring(1); |
extension = extension.Substring(1); |
||||
} |
} |
||||
|
|
||||
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); |
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// For the specified mime type find the <see cref="IImageFormat"/>.
|
/// For the specified mime type find the <see cref="IImageFormat"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="mimeType">The mime-type to discover</param>
|
/// <param name="mimeType">The mime-type to discover</param>
|
||||
/// <returns>The <see cref="IImageFormat"/> if found; otherwise null</returns>
|
/// <returns>The <see cref="IImageFormat"/> if found; otherwise null</returns>
|
||||
public IImageFormat FindFormatByMimeType(string mimeType) |
public IImageFormat FindFormatByMimeType(string mimeType) |
||||
{ |
{ |
||||
return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); |
return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Sets a specific image encoder as the encoder for a specific image format.
|
/// Sets a specific image encoder as the encoder for a specific image format.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="imageFormat">The image format to register the encoder for.</param>
|
/// <param name="imageFormat">The image format to register the encoder for.</param>
|
||||
/// <param name="encoder">The encoder to use,</param>
|
/// <param name="encoder">The encoder to use,</param>
|
||||
public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) |
public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) |
||||
{ |
{ |
||||
Guard.NotNull(imageFormat, nameof(imageFormat)); |
Guard.NotNull(imageFormat, nameof(imageFormat)); |
||||
Guard.NotNull(encoder, nameof(encoder)); |
Guard.NotNull(encoder, nameof(encoder)); |
||||
this.AddImageFormat(imageFormat); |
this.AddImageFormat(imageFormat); |
||||
this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); |
this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Sets a specific image decoder as the decoder for a specific image format.
|
/// Sets a specific image decoder as the decoder for a specific image format.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="imageFormat">The image format to register the encoder for.</param>
|
/// <param name="imageFormat">The image format to register the encoder for.</param>
|
||||
/// <param name="decoder">The decoder to use,</param>
|
/// <param name="decoder">The decoder to use,</param>
|
||||
public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) |
public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) |
||||
{ |
{ |
||||
Guard.NotNull(imageFormat, nameof(imageFormat)); |
Guard.NotNull(imageFormat, nameof(imageFormat)); |
||||
Guard.NotNull(decoder, nameof(decoder)); |
Guard.NotNull(decoder, nameof(decoder)); |
||||
this.AddImageFormat(imageFormat); |
this.AddImageFormat(imageFormat); |
||||
this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); |
this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Removes all the registered image format detectors.
|
/// Removes all the registered image format detectors.
|
||||
/// </summary>
|
/// </summary>
|
||||
public void ClearImageFormatDetectors() |
public void ClearImageFormatDetectors() |
||||
{ |
{ |
||||
this.imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>(); |
this.imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>(); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Adds a new detector for detecting mime types.
|
/// Adds a new detector for detecting mime types.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="detector">The detector to add</param>
|
/// <param name="detector">The detector to add</param>
|
||||
public void AddImageFormatDetector(IImageFormatDetector detector) |
public void AddImageFormatDetector(IImageFormatDetector detector) |
||||
{ |
{ |
||||
Guard.NotNull(detector, nameof(detector)); |
Guard.NotNull(detector, nameof(detector)); |
||||
this.imageFormatDetectors.Add(detector); |
this.imageFormatDetectors.Add(detector); |
||||
this.SetMaxHeaderSize(); |
this.SetMaxHeaderSize(); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// For the specified mime type find the decoder.
|
/// For the specified mime type find the decoder.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="format">The format to discover</param>
|
/// <param name="format">The format to discover</param>
|
||||
/// <returns>The <see cref="IImageDecoder"/> if found otherwise null</returns>
|
/// <returns>The <see cref="IImageDecoder"/> if found otherwise null</returns>
|
||||
public IImageDecoder FindDecoder(IImageFormat format) |
public IImageDecoder FindDecoder(IImageFormat format) |
||||
{ |
{ |
||||
Guard.NotNull(format, nameof(format)); |
Guard.NotNull(format, nameof(format)); |
||||
|
|
||||
return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder) |
return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder) |
||||
? decoder |
? decoder |
||||
: null; |
: null; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// For the specified mime type find the encoder.
|
/// For the specified mime type find the encoder.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="format">The format to discover</param>
|
/// <param name="format">The format to discover</param>
|
||||
/// <returns>The <see cref="IImageEncoder"/> if found otherwise null</returns>
|
/// <returns>The <see cref="IImageEncoder"/> if found otherwise null</returns>
|
||||
public IImageEncoder FindEncoder(IImageFormat format) |
public IImageEncoder FindEncoder(IImageFormat format) |
||||
{ |
{ |
||||
Guard.NotNull(format, nameof(format)); |
Guard.NotNull(format, nameof(format)); |
||||
|
|
||||
return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder) |
return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder) |
||||
? encoder |
? encoder |
||||
: null; |
: null; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Sets the max header size.
|
/// Sets the max header size.
|
||||
/// </summary>
|
/// </summary>
|
||||
private void SetMaxHeaderSize() |
private void SetMaxHeaderSize() |
||||
{ |
{ |
||||
this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); |
this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
Binary file not shown.
Binary file not shown.
@ -1,177 +1,177 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
namespace SixLabors.ImageSharp |
namespace SixLabors.ImageSharp |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Options for influencing the drawing functions.
|
/// Options for influencing the drawing functions.
|
||||
/// </summary>
|
/// </summary>
|
||||
public struct GraphicsOptions |
public struct GraphicsOptions |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Represents the default <see cref="GraphicsOptions"/>.
|
/// Represents the default <see cref="GraphicsOptions"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
public static readonly GraphicsOptions Default = new GraphicsOptions(true); |
public static readonly GraphicsOptions Default = new GraphicsOptions(true); |
||||
|
|
||||
private float? blendPercentage; |
private float? blendPercentage; |
||||
|
|
||||
private int? antialiasSubpixelDepth; |
private int? antialiasSubpixelDepth; |
||||
|
|
||||
private bool? antialias; |
private bool? antialias; |
||||
|
|
||||
private PixelColorBlendingMode colorBlendingMode; |
private PixelColorBlendingMode colorBlendingMode; |
||||
|
|
||||
private PixelAlphaCompositionMode alphaCompositionMode; |
private PixelAlphaCompositionMode alphaCompositionMode; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
|
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
||||
public GraphicsOptions(bool enableAntialiasing) |
public GraphicsOptions(bool enableAntialiasing) |
||||
{ |
{ |
||||
this.colorBlendingMode = PixelColorBlendingMode.Normal; |
this.colorBlendingMode = PixelColorBlendingMode.Normal; |
||||
this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; |
this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; |
||||
this.blendPercentage = 1; |
this.blendPercentage = 1; |
||||
this.antialiasSubpixelDepth = 16; |
this.antialiasSubpixelDepth = 16; |
||||
this.antialias = enableAntialiasing; |
this.antialias = enableAntialiasing; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
|
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
||||
/// <param name="opacity">blending percentage to apply to the drawing operation</param>
|
/// <param name="opacity">blending percentage to apply to the drawing operation</param>
|
||||
public GraphicsOptions(bool enableAntialiasing, float opacity) |
public GraphicsOptions(bool enableAntialiasing, float opacity) |
||||
{ |
{ |
||||
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); |
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); |
||||
|
|
||||
this.colorBlendingMode = PixelColorBlendingMode.Normal; |
this.colorBlendingMode = PixelColorBlendingMode.Normal; |
||||
this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; |
this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; |
||||
this.blendPercentage = opacity; |
this.blendPercentage = opacity; |
||||
this.antialiasSubpixelDepth = 16; |
this.antialiasSubpixelDepth = 16; |
||||
this.antialias = enableAntialiasing; |
this.antialias = enableAntialiasing; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
|
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
||||
/// <param name="opacity">blending percentage to apply to the drawing operation</param>
|
/// <param name="opacity">blending percentage to apply to the drawing operation</param>
|
||||
/// <param name="blending">color blending mode to apply to the drawing operation</param>
|
/// <param name="blending">color blending mode to apply to the drawing operation</param>
|
||||
public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) |
public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) |
||||
{ |
{ |
||||
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); |
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); |
||||
|
|
||||
this.colorBlendingMode = blending; |
this.colorBlendingMode = blending; |
||||
this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; |
this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; |
||||
this.blendPercentage = opacity; |
this.blendPercentage = opacity; |
||||
this.antialiasSubpixelDepth = 16; |
this.antialiasSubpixelDepth = 16; |
||||
this.antialias = enableAntialiasing; |
this.antialias = enableAntialiasing; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
|
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
||||
/// <param name="opacity">blending percentage to apply to the drawing operation</param>
|
/// <param name="opacity">blending percentage to apply to the drawing operation</param>
|
||||
/// <param name="blending">color blending mode to apply to the drawing operation</param>
|
/// <param name="blending">color blending mode to apply to the drawing operation</param>
|
||||
/// <param name="composition">alpha composition mode to apply to the drawing operation</param>
|
/// <param name="composition">alpha composition mode to apply to the drawing operation</param>
|
||||
public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) |
public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) |
||||
{ |
{ |
||||
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); |
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); |
||||
|
|
||||
this.colorBlendingMode = blending; |
this.colorBlendingMode = blending; |
||||
this.alphaCompositionMode = composition; |
this.alphaCompositionMode = composition; |
||||
this.blendPercentage = opacity; |
this.blendPercentage = opacity; |
||||
this.antialiasSubpixelDepth = 16; |
this.antialiasSubpixelDepth = 16; |
||||
this.antialias = enableAntialiasing; |
this.antialias = enableAntialiasing; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating whether antialiasing should be applied.
|
/// Gets or sets a value indicating whether antialiasing should be applied.
|
||||
/// </summary>
|
/// </summary>
|
||||
public bool Antialias |
public bool Antialias |
||||
{ |
{ |
||||
get => this.antialias ?? true; |
get => this.antialias ?? true; |
||||
set => this.antialias = value; |
set => this.antialias = value; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled.
|
/// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled.
|
||||
/// </summary>
|
/// </summary>
|
||||
public int AntialiasSubpixelDepth |
public int AntialiasSubpixelDepth |
||||
{ |
{ |
||||
get => this.antialiasSubpixelDepth ?? 16; |
get => this.antialiasSubpixelDepth ?? 16; |
||||
set => this.antialiasSubpixelDepth = value; |
set => this.antialiasSubpixelDepth = value; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the blending percentage to apply to the drawing operation
|
/// Gets or sets a value indicating the blending percentage to apply to the drawing operation
|
||||
/// </summary>
|
/// </summary>
|
||||
public float BlendPercentage |
public float BlendPercentage |
||||
{ |
{ |
||||
get => (this.blendPercentage ?? 1).Clamp(0, 1); |
get => (this.blendPercentage ?? 1).Clamp(0, 1); |
||||
set => this.blendPercentage = value; |
set => this.blendPercentage = value; |
||||
} |
} |
||||
|
|
||||
// In the future we could expose a PixelBlender<TPixel> directly on here
|
// In the future we could expose a PixelBlender<TPixel> directly on here
|
||||
// or some forms of PixelBlender factory for each pixel type. Will need
|
// or some forms of PixelBlender factory for each pixel type. Will need
|
||||
// some API thought post V1.
|
// some API thought post V1.
|
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the color blending mode to apply to the drawing operation
|
/// Gets or sets a value indicating the color blending mode to apply to the drawing operation
|
||||
/// </summary>
|
/// </summary>
|
||||
public PixelColorBlendingMode ColorBlendingMode |
public PixelColorBlendingMode ColorBlendingMode |
||||
{ |
{ |
||||
get => this.colorBlendingMode; |
get => this.colorBlendingMode; |
||||
set => this.colorBlendingMode = value; |
set => this.colorBlendingMode = value; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets or sets a value indicating the alpha composition mode to apply to the drawing operation
|
/// Gets or sets a value indicating the alpha composition mode to apply to the drawing operation
|
||||
/// </summary>
|
/// </summary>
|
||||
public PixelAlphaCompositionMode AlphaCompositionMode |
public PixelAlphaCompositionMode AlphaCompositionMode |
||||
{ |
{ |
||||
get => this.alphaCompositionMode; |
get => this.alphaCompositionMode; |
||||
set => this.alphaCompositionMode = value; |
set => this.alphaCompositionMode = value; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Evaluates if a given SOURCE color can completely replace a BACKDROP color given the current blending and composition settings.
|
/// Evaluates if a given SOURCE color can completely replace a BACKDROP color given the current blending and composition settings.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="color">the color</param>
|
/// <param name="color">the color</param>
|
||||
/// <returns>true if the color can be considered opaque</returns>
|
/// <returns>true if the color can be considered opaque</returns>
|
||||
/// <remarks>
|
/// <remarks>
|
||||
/// Blending and composition is an expensive operation, in some cases, like
|
/// Blending and composition is an expensive operation, in some cases, like
|
||||
/// filling with a solid color, the blending can be avoided by a plain color replacement.
|
/// filling with a solid color, the blending can be avoided by a plain color replacement.
|
||||
/// This method can be useful for such processors to select the fast path.
|
/// This method can be useful for such processors to select the fast path.
|
||||
/// </remarks>
|
/// </remarks>
|
||||
internal bool IsOpaqueColorWithoutBlending(Color color) |
internal bool IsOpaqueColorWithoutBlending(Color color) |
||||
{ |
{ |
||||
if (this.ColorBlendingMode != PixelColorBlendingMode.Normal) |
if (this.ColorBlendingMode != PixelColorBlendingMode.Normal) |
||||
{ |
{ |
||||
return false; |
return false; |
||||
} |
} |
||||
|
|
||||
if (this.AlphaCompositionMode != PixelAlphaCompositionMode.SrcOver && |
if (this.AlphaCompositionMode != PixelAlphaCompositionMode.SrcOver && |
||||
this.AlphaCompositionMode != PixelAlphaCompositionMode.Src) |
this.AlphaCompositionMode != PixelAlphaCompositionMode.Src) |
||||
{ |
{ |
||||
return false; |
return false; |
||||
} |
} |
||||
|
|
||||
if (this.BlendPercentage != 1f) |
if (this.BlendPercentage != 1f) |
||||
{ |
{ |
||||
return false; |
return false; |
||||
} |
} |
||||
|
|
||||
if (color.ToVector4().W != 1f) |
if (color.ToVector4().W != 1f) |
||||
{ |
{ |
||||
return false; |
return false; |
||||
} |
} |
||||
|
|
||||
return true; |
return true; |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
File diff suppressed because it is too large
@ -1,114 +1,114 @@ |
|||||
<# |
<# |
||||
// Copyright (c) Six Labors and contributors. |
// Copyright (c) Six Labors and contributors. |
||||
// Licensed under the Apache License, Version 2.0. |
// Licensed under the Apache License, Version 2.0. |
||||
#> |
#> |
||||
<#@ template debug="false" hostspecific="false" language="C#" #> |
<#@ template debug="false" hostspecific="false" language="C#" #> |
||||
<#@ assembly name="System.Core" #> |
<#@ assembly name="System.Core" #> |
||||
<#@ import namespace="System.Linq" #> |
<#@ import namespace="System.Linq" #> |
||||
<#@ import namespace="System.Text" #> |
<#@ import namespace="System.Text" #> |
||||
<#@ import namespace="System.Collections.Generic" #> |
<#@ import namespace="System.Collections.Generic" #> |
||||
<#@ output extension=".cs" #> |
<#@ output extension=".cs" #> |
||||
// Copyright (c) Six Labors and contributors. |
// Copyright (c) Six Labors and contributors. |
||||
// Licensed under the Apache License, Version 2.0. |
// Licensed under the Apache License, Version 2.0. |
||||
|
|
||||
// <auto-generated /> |
// <auto-generated /> |
||||
using System; |
using System; |
||||
using System.Numerics; |
using System.Numerics; |
||||
using System.Buffers; |
using System.Buffers; |
||||
|
|
||||
using SixLabors.ImageSharp.Memory; |
using SixLabors.ImageSharp.Memory; |
||||
using SixLabors.Memory; |
using SixLabors.Memory; |
||||
|
|
||||
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders |
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders |
||||
{ |
{ |
||||
/// <summary> |
/// <summary> |
||||
/// Collection of Porter Duff alpha blending functions applying different composition models. |
/// Collection of Porter Duff alpha blending functions applying different composition models. |
||||
/// </summary> |
/// </summary> |
||||
/// <remarks> |
/// <remarks> |
||||
/// These functions are designed to be a general solution for all color cases, |
/// These functions are designed to be a general solution for all color cases, |
||||
/// that is, they take in account the alpha value of both the backdrop |
/// that is, they take in account the alpha value of both the backdrop |
||||
/// and source, and there's no need to alpha-premultiply neither the backdrop |
/// and source, and there's no need to alpha-premultiply neither the backdrop |
||||
/// nor the source. |
/// nor the source. |
||||
/// Note there are faster functions for when the backdrop color is known |
/// Note there are faster functions for when the backdrop color is known |
||||
/// to be opaque |
/// to be opaque |
||||
/// </remarks> |
/// </remarks> |
||||
internal static class DefaultPixelBlenders<TPixel> |
internal static class DefaultPixelBlenders<TPixel> |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
|
|
||||
<# |
<# |
||||
string[] composers = new []{ |
string[] composers = new []{ |
||||
"Src", |
"Src", |
||||
"SrcAtop", |
"SrcAtop", |
||||
"SrcOver", |
"SrcOver", |
||||
"SrcIn", |
"SrcIn", |
||||
"SrcOut", |
"SrcOut", |
||||
"Dest", |
"Dest", |
||||
"DestAtop", |
"DestAtop", |
||||
"DestOver", |
"DestOver", |
||||
"DestIn", |
"DestIn", |
||||
"DestOut", |
"DestOut", |
||||
"Clear", |
"Clear", |
||||
"Xor", |
"Xor", |
||||
}; |
}; |
||||
|
|
||||
string[] blenders = new []{ |
string[] blenders = new []{ |
||||
"Normal", |
"Normal", |
||||
"Multiply", |
"Multiply", |
||||
"Add", |
"Add", |
||||
"Subtract", |
"Subtract", |
||||
"Screen", |
"Screen", |
||||
"Darken", |
"Darken", |
||||
"Lighten", |
"Lighten", |
||||
"Overlay", |
"Overlay", |
||||
"HardLight" |
"HardLight" |
||||
}; |
}; |
||||
|
|
||||
foreach(var composer in composers) { |
foreach(var composer in composers) { |
||||
foreach(var blender in blenders) { |
foreach(var blender in blenders) { |
||||
|
|
||||
string blender_composer= $"{blender}{composer}"; |
string blender_composer= $"{blender}{composer}"; |
||||
|
|
||||
#> |
#> |
||||
internal class <#= blender_composer#> : PixelBlender<TPixel> |
internal class <#= blender_composer#> : PixelBlender<TPixel> |
||||
{ |
{ |
||||
/// <summary> |
/// <summary> |
||||
/// Gets the static instance of this blender. |
/// Gets the static instance of this blender. |
||||
/// </summary> |
/// </summary> |
||||
public static <#=blender_composer#> Instance { get; } = new <#=blender_composer#>(); |
public static <#=blender_composer#> Instance { get; } = new <#=blender_composer#>(); |
||||
|
|
||||
/// <inheritdoc /> |
/// <inheritdoc /> |
||||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
public override TPixel Blend(TPixel background, TPixel source, float amount) |
||||
{ |
{ |
||||
TPixel dest = default; |
TPixel dest = default; |
||||
dest.FromScaledVector4(PorterDuffFunctions.<#=blender_composer#>(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); |
dest.FromScaledVector4(PorterDuffFunctions.<#=blender_composer#>(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); |
||||
return dest; |
return dest; |
||||
} |
} |
||||
|
|
||||
/// <inheritdoc /> |
/// <inheritdoc /> |
||||
protected override void BlendFunction(Span<Vector4> destination, ReadOnlySpan<Vector4> background, ReadOnlySpan<Vector4> source, float amount) |
protected override void BlendFunction(Span<Vector4> destination, ReadOnlySpan<Vector4> background, ReadOnlySpan<Vector4> source, float amount) |
||||
{ |
{ |
||||
amount = amount.Clamp(0, 1); |
amount = amount.Clamp(0, 1); |
||||
for (int i = 0; i < destination.Length; i++) |
for (int i = 0; i < destination.Length; i++) |
||||
{ |
{ |
||||
destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount); |
destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
/// <inheritdoc /> |
/// <inheritdoc /> |
||||
protected override void BlendFunction(Span<Vector4> destination, ReadOnlySpan<Vector4> background, ReadOnlySpan<Vector4> source, ReadOnlySpan<float> amount) |
protected override void BlendFunction(Span<Vector4> destination, ReadOnlySpan<Vector4> background, ReadOnlySpan<Vector4> source, ReadOnlySpan<float> amount) |
||||
{ |
{ |
||||
for (int i = 0; i < destination.Length; i++) |
for (int i = 0; i < destination.Length; i++) |
||||
{ |
{ |
||||
destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount[i].Clamp(0, 1)); |
destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount[i].Clamp(0, 1)); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
<# |
<# |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
#> |
#> |
||||
} |
} |
||||
} |
} |
||||
File diff suppressed because it is too large
@ -1,183 +1,183 @@ |
|||||
<# |
<# |
||||
// Copyright (c) Six Labors and contributors. |
// Copyright (c) Six Labors and contributors. |
||||
// Licensed under the Apache License, Version 2.0. |
// Licensed under the Apache License, Version 2.0. |
||||
#> |
#> |
||||
<#@ template debug="false" hostspecific="false" language="C#" #> |
<#@ template debug="false" hostspecific="false" language="C#" #> |
||||
<#@ assembly name="System.Core" #> |
<#@ assembly name="System.Core" #> |
||||
<#@ import namespace="System.Linq" #> |
<#@ import namespace="System.Linq" #> |
||||
<#@ import namespace="System.Text" #> |
<#@ import namespace="System.Text" #> |
||||
<#@ import namespace="System.Collections.Generic" #> |
<#@ import namespace="System.Collections.Generic" #> |
||||
<#@ output extension=".cs" #> |
<#@ output extension=".cs" #> |
||||
// Copyright (c) Six Labors and contributors. |
// Copyright (c) Six Labors and contributors. |
||||
// Licensed under the Apache License, Version 2.0. |
// Licensed under the Apache License, Version 2.0. |
||||
|
|
||||
// <auto-generated /> |
// <auto-generated /> |
||||
|
|
||||
<# |
<# |
||||
// Note use of MethodImplOptions.NoInlining. We have tests that are failing on certain architectures when |
// Note use of MethodImplOptions.NoInlining. We have tests that are failing on certain architectures when |
||||
// AggresiveInlining is used. Confirmed on Intel i7-6600U in 64bit. |
// AggresiveInlining is used. Confirmed on Intel i7-6600U in 64bit. |
||||
#> |
#> |
||||
|
|
||||
using System; |
using System; |
||||
using System.Numerics; |
using System.Numerics; |
||||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||||
|
|
||||
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders |
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders |
||||
{ |
{ |
||||
internal static partial class PorterDuffFunctions |
internal static partial class PorterDuffFunctions |
||||
{ |
{ |
||||
|
|
||||
<# void GeneratePixelBlenders(string blender) { #> |
<# void GeneratePixelBlenders(string blender) { #> |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>Src(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>Src(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return source; |
return source; |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>SrcAtop(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>SrcAtop(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return Atop(backdrop, source, <#=blender#>(backdrop, source)); |
return Atop(backdrop, source, <#=blender#>(backdrop, source)); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>SrcOver(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>SrcOver(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return Over(backdrop, source, <#=blender#>(backdrop, source)); |
return Over(backdrop, source, <#=blender#>(backdrop, source)); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>SrcIn(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>SrcIn(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return In(backdrop, source, <#=blender#>(backdrop, source)); |
return In(backdrop, source, <#=blender#>(backdrop, source)); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>SrcOut(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>SrcOut(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return Out(backdrop, source); |
return Out(backdrop, source); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>Dest(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>Dest(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
return backdrop; |
return backdrop; |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>DestAtop(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>DestAtop(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return Atop(source, backdrop, <#=blender#>(source, backdrop)); |
return Atop(source, backdrop, <#=blender#>(source, backdrop)); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>DestOver(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>DestOver(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return Over(source, backdrop, <#=blender#>(source, backdrop)); |
return Over(source, backdrop, <#=blender#>(source, backdrop)); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>DestIn(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>DestIn(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return In(source, backdrop, <#=blender#>(source, backdrop)); |
return In(source, backdrop, <#=blender#>(source, backdrop)); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>DestOut(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>DestOut(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return Out(source, backdrop); |
return Out(source, backdrop); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>Xor(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>Xor(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return Xor(backdrop, source); |
return Xor(backdrop, source); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] |
[MethodImpl(MethodImplOptions.NoInlining)] |
||||
public static Vector4 <#=blender#>Clear(Vector4 backdrop, Vector4 source, float opacity) |
public static Vector4 <#=blender#>Clear(Vector4 backdrop, Vector4 source, float opacity) |
||||
{ |
{ |
||||
source.W *= opacity; |
source.W *= opacity; |
||||
|
|
||||
return Clear(backdrop, source); |
return Clear(backdrop, source); |
||||
} |
} |
||||
<# } #> |
<# } #> |
||||
|
|
||||
|
|
||||
<# void GenerateGenericPixelBlender(string blender, string composer) { #> |
<# void GenerateGenericPixelBlender(string blender, string composer) { #> |
||||
|
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static TPixel <#=blender#><#=composer#><TPixel>(TPixel backdrop, TPixel source, float opacity) |
public static TPixel <#=blender#><#=composer#><TPixel>(TPixel backdrop, TPixel source, float opacity) |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
opacity = opacity.Clamp(0, 1); |
opacity = opacity.Clamp(0, 1); |
||||
TPixel dest = default; |
TPixel dest = default; |
||||
dest.FromScaledVector4(<#=blender#><#=composer#>(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); |
dest.FromScaledVector4(<#=blender#><#=composer#>(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); |
||||
return dest; |
return dest; |
||||
} |
} |
||||
|
|
||||
<# } #> |
<# } #> |
||||
|
|
||||
<# |
<# |
||||
|
|
||||
string[] composers = new []{ |
string[] composers = new []{ |
||||
"Src", |
"Src", |
||||
"SrcAtop", |
"SrcAtop", |
||||
"SrcOver", |
"SrcOver", |
||||
"SrcIn", |
"SrcIn", |
||||
"SrcOut", |
"SrcOut", |
||||
"Dest", |
"Dest", |
||||
"DestAtop", |
"DestAtop", |
||||
"DestOver", |
"DestOver", |
||||
"DestIn", |
"DestIn", |
||||
"DestOut", |
"DestOut", |
||||
"Clear", |
"Clear", |
||||
"Xor", |
"Xor", |
||||
}; |
}; |
||||
|
|
||||
string[] blenders = new []{ |
string[] blenders = new []{ |
||||
"Normal", |
"Normal", |
||||
"Multiply", |
"Multiply", |
||||
"Add", |
"Add", |
||||
"Subtract", |
"Subtract", |
||||
"Screen", |
"Screen", |
||||
"Darken", |
"Darken", |
||||
"Lighten", |
"Lighten", |
||||
"Overlay", |
"Overlay", |
||||
"HardLight" |
"HardLight" |
||||
}; |
}; |
||||
|
|
||||
foreach(var blender in blenders) |
foreach(var blender in blenders) |
||||
{ |
{ |
||||
GeneratePixelBlenders(blender); |
GeneratePixelBlenders(blender); |
||||
|
|
||||
foreach(var composer in composers) |
foreach(var composer in composers) |
||||
{ |
{ |
||||
GenerateGenericPixelBlender(blender,composer); |
GenerateGenericPixelBlender(blender,composer); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
#> |
#> |
||||
} |
} |
||||
} |
} |
||||
@ -1,238 +1,238 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using System; |
using System; |
||||
using System.Numerics; |
using System.Numerics; |
||||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||||
|
|
||||
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders |
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Collection of Porter Duff Color Blending and Alpha Composition Functions.
|
/// Collection of Porter Duff Color Blending and Alpha Composition Functions.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <remarks>
|
/// <remarks>
|
||||
/// These functions are designed to be a general solution for all color cases,
|
/// These functions are designed to be a general solution for all color cases,
|
||||
/// that is, they take in account the alpha value of both the backdrop
|
/// that is, they take in account the alpha value of both the backdrop
|
||||
/// and source, and there's no need to alpha-premultiply neither the backdrop
|
/// and source, and there's no need to alpha-premultiply neither the backdrop
|
||||
/// nor the source.
|
/// nor the source.
|
||||
/// Note there are faster functions for when the backdrop color is known
|
/// Note there are faster functions for when the backdrop color is known
|
||||
/// to be opaque
|
/// to be opaque
|
||||
/// </remarks>
|
/// </remarks>
|
||||
internal static partial class PorterDuffFunctions |
internal static partial class PorterDuffFunctions |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Source over backdrop
|
/// Source over backdrop
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Normal(Vector4 backdrop, Vector4 source) |
public static Vector4 Normal(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
return source; |
return source; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Source multiplied by backdrop
|
/// Source multiplied by backdrop
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Multiply(Vector4 backdrop, Vector4 source) |
public static Vector4 Multiply(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
return backdrop * source; |
return backdrop * source; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Source added to backdrop
|
/// Source added to backdrop
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Add(Vector4 backdrop, Vector4 source) |
public static Vector4 Add(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
return Vector4.Min(Vector4.One, backdrop + source); |
return Vector4.Min(Vector4.One, backdrop + source); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Source subtracted from backdrop
|
/// Source subtracted from backdrop
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Subtract(Vector4 backdrop, Vector4 source) |
public static Vector4 Subtract(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
return Vector4.Max(Vector4.Zero, backdrop - source); |
return Vector4.Max(Vector4.Zero, backdrop - source); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Complement of source multiplied by the complement of backdrop
|
/// Complement of source multiplied by the complement of backdrop
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Screen(Vector4 backdrop, Vector4 source) |
public static Vector4 Screen(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
return Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source)); |
return Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source)); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Per element, chooses the smallest value of source and backdrop
|
/// Per element, chooses the smallest value of source and backdrop
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Darken(Vector4 backdrop, Vector4 source) |
public static Vector4 Darken(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
return Vector4.Min(backdrop, source); |
return Vector4.Min(backdrop, source); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Per element, chooses the largest value of source and backdrop
|
/// Per element, chooses the largest value of source and backdrop
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Lighten(Vector4 backdrop, Vector4 source) |
public static Vector4 Lighten(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
return Vector4.Max(backdrop, source); |
return Vector4.Max(backdrop, source); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Overlays source over backdrop
|
/// Overlays source over backdrop
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Overlay(Vector4 backdrop, Vector4 source) |
public static Vector4 Overlay(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
float cr = OverlayValueFunction(backdrop.X, source.X); |
float cr = OverlayValueFunction(backdrop.X, source.X); |
||||
float cg = OverlayValueFunction(backdrop.Y, source.Y); |
float cg = OverlayValueFunction(backdrop.Y, source.Y); |
||||
float cb = OverlayValueFunction(backdrop.Z, source.Z); |
float cb = OverlayValueFunction(backdrop.Z, source.Z); |
||||
|
|
||||
return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); |
return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Hard light effect
|
/// Hard light effect
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color</param>
|
/// <param name="backdrop">Backdrop color</param>
|
||||
/// <param name="source">Source color</param>
|
/// <param name="source">Source color</param>
|
||||
/// <returns>Output color</returns>
|
/// <returns>Output color</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 HardLight(Vector4 backdrop, Vector4 source) |
public static Vector4 HardLight(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
float cr = OverlayValueFunction(source.X, backdrop.X); |
float cr = OverlayValueFunction(source.X, backdrop.X); |
||||
float cg = OverlayValueFunction(source.Y, backdrop.Y); |
float cg = OverlayValueFunction(source.Y, backdrop.Y); |
||||
float cb = OverlayValueFunction(source.Z, backdrop.Z); |
float cb = OverlayValueFunction(source.Z, backdrop.Z); |
||||
|
|
||||
return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); |
return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Helper function for Overlay andHardLight modes
|
/// Helper function for Overlay andHardLight modes
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="backdrop">Backdrop color element</param>
|
/// <param name="backdrop">Backdrop color element</param>
|
||||
/// <param name="source">Source color element</param>
|
/// <param name="source">Source color element</param>
|
||||
/// <returns>Overlay value</returns>
|
/// <returns>Overlay value</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
private static float OverlayValueFunction(float backdrop, float source) |
private static float OverlayValueFunction(float backdrop, float source) |
||||
{ |
{ |
||||
return backdrop <= 0.5f ? (2 * backdrop * source) : 1 - ((2 * (1 - source)) * (1 - backdrop)); |
return backdrop <= 0.5f ? (2 * backdrop * source) : 1 - ((2 * (1 - source)) * (1 - backdrop)); |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Over(Vector4 dst, Vector4 src, Vector4 blend) |
public static Vector4 Over(Vector4 dst, Vector4 src, Vector4 blend) |
||||
{ |
{ |
||||
// calculate weights
|
// calculate weights
|
||||
float blendW = dst.W * src.W; |
float blendW = dst.W * src.W; |
||||
float dstW = dst.W - blendW; |
float dstW = dst.W - blendW; |
||||
float srcW = src.W - blendW; |
float srcW = src.W - blendW; |
||||
|
|
||||
// calculate final alpha
|
// calculate final alpha
|
||||
float alpha = dstW + srcW + blendW; |
float alpha = dstW + srcW + blendW; |
||||
|
|
||||
// calculate final color
|
// calculate final color
|
||||
Vector4 color = (dst * dstW) + (src * srcW) + (blend * blendW); |
Vector4 color = (dst * dstW) + (src * srcW) + (blend * blendW); |
||||
|
|
||||
// unpremultiply
|
// unpremultiply
|
||||
color /= MathF.Max(alpha, Constants.Epsilon); |
color /= MathF.Max(alpha, Constants.Epsilon); |
||||
color.W = alpha; |
color.W = alpha; |
||||
|
|
||||
return color; |
return color; |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Atop(Vector4 dst, Vector4 src, Vector4 blend) |
public static Vector4 Atop(Vector4 dst, Vector4 src, Vector4 blend) |
||||
{ |
{ |
||||
// calculate weights
|
// calculate weights
|
||||
float blendW = dst.W * src.W; |
float blendW = dst.W * src.W; |
||||
float dstW = dst.W - blendW; |
float dstW = dst.W - blendW; |
||||
|
|
||||
// calculate final alpha
|
// calculate final alpha
|
||||
float alpha = dstW + blendW; |
float alpha = dstW + blendW; |
||||
|
|
||||
// calculate final color
|
// calculate final color
|
||||
Vector4 color = (dst * dstW) + (blend * blendW); |
Vector4 color = (dst * dstW) + (blend * blendW); |
||||
|
|
||||
// unpremultiply
|
// unpremultiply
|
||||
color /= MathF.Max(alpha, Constants.Epsilon); |
color /= MathF.Max(alpha, Constants.Epsilon); |
||||
color.W = alpha; |
color.W = alpha; |
||||
|
|
||||
return color; |
return color; |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 In(Vector4 dst, Vector4 src, Vector4 blend) |
public static Vector4 In(Vector4 dst, Vector4 src, Vector4 blend) |
||||
{ |
{ |
||||
float alpha = dst.W * src.W; |
float alpha = dst.W * src.W; |
||||
|
|
||||
Vector4 color = src * alpha; // premultiply
|
Vector4 color = src * alpha; // premultiply
|
||||
color /= MathF.Max(alpha, Constants.Epsilon); // unpremultiply
|
color /= MathF.Max(alpha, Constants.Epsilon); // unpremultiply
|
||||
color.W = alpha; |
color.W = alpha; |
||||
|
|
||||
return color; |
return color; |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Out(Vector4 dst, Vector4 src) |
public static Vector4 Out(Vector4 dst, Vector4 src) |
||||
{ |
{ |
||||
float alpha = (1 - dst.W) * src.W; |
float alpha = (1 - dst.W) * src.W; |
||||
|
|
||||
Vector4 color = src * alpha; // premultiply
|
Vector4 color = src * alpha; // premultiply
|
||||
color /= MathF.Max(alpha, Constants.Epsilon); // unpremultiply
|
color /= MathF.Max(alpha, Constants.Epsilon); // unpremultiply
|
||||
color.W = alpha; |
color.W = alpha; |
||||
|
|
||||
return color; |
return color; |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
public static Vector4 Xor(Vector4 dst, Vector4 src) |
public static Vector4 Xor(Vector4 dst, Vector4 src) |
||||
{ |
{ |
||||
float srcW = 1 - dst.W; |
float srcW = 1 - dst.W; |
||||
float dstW = 1 - src.W; |
float dstW = 1 - src.W; |
||||
|
|
||||
float alpha = (src.W * srcW) + (dst.W * dstW); |
float alpha = (src.W * srcW) + (dst.W * dstW); |
||||
Vector4 color = (src.W * src * srcW) + (dst.W * dst * dstW); |
Vector4 color = (src.W * src * srcW) + (dst.W * dst * dstW); |
||||
|
|
||||
// unpremultiply
|
// unpremultiply
|
||||
color /= MathF.Max(alpha, Constants.Epsilon); |
color /= MathF.Max(alpha, Constants.Epsilon); |
||||
color.W = alpha; |
color.W = alpha; |
||||
|
|
||||
return color; |
return color; |
||||
} |
} |
||||
|
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
private static Vector4 Clear(Vector4 backdrop, Vector4 source) |
private static Vector4 Clear(Vector4 backdrop, Vector4 source) |
||||
{ |
{ |
||||
return Vector4.Zero; |
return Vector4.Zero; |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,170 +1,170 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using System; |
using System; |
||||
using System.Buffers; |
using System.Buffers; |
||||
using System.Numerics; |
using System.Numerics; |
||||
|
|
||||
using SixLabors.ImageSharp.Memory; |
using SixLabors.ImageSharp.Memory; |
||||
|
|
||||
namespace SixLabors.ImageSharp.PixelFormats |
namespace SixLabors.ImageSharp.PixelFormats |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Abstract base class for calling pixel composition functions
|
/// Abstract base class for calling pixel composition functions
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
||||
internal abstract class PixelBlender<TPixel> |
internal abstract class PixelBlender<TPixel> |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Blend 2 pixels together.
|
/// Blend 2 pixels together.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="background">The background color.</param>
|
/// <param name="background">The background color.</param>
|
||||
/// <param name="source">The source color.</param>
|
/// <param name="source">The source color.</param>
|
||||
/// <param name="amount">
|
/// <param name="amount">
|
||||
/// A value between 0 and 1 indicating the weight of the second source vector.
|
/// A value between 0 and 1 indicating the weight of the second source vector.
|
||||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
||||
/// </param>
|
/// </param>
|
||||
/// <returns>The final pixel value after composition</returns>
|
/// <returns>The final pixel value after composition</returns>
|
||||
public abstract TPixel Blend(TPixel background, TPixel source, float amount); |
public abstract TPixel Blend(TPixel background, TPixel source, float amount); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Blend 2 rows together.
|
/// Blend 2 rows together.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="destination">destination span</param>
|
/// <param name="destination">destination span</param>
|
||||
/// <param name="background">the background span</param>
|
/// <param name="background">the background span</param>
|
||||
/// <param name="source">the source span</param>
|
/// <param name="source">the source span</param>
|
||||
/// <param name="amount">
|
/// <param name="amount">
|
||||
/// A value between 0 and 1 indicating the weight of the second source vector.
|
/// A value between 0 and 1 indicating the weight of the second source vector.
|
||||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
||||
/// </param>
|
/// </param>
|
||||
protected abstract void BlendFunction( |
protected abstract void BlendFunction( |
||||
Span<Vector4> destination, |
Span<Vector4> destination, |
||||
ReadOnlySpan<Vector4> background, |
ReadOnlySpan<Vector4> background, |
||||
ReadOnlySpan<Vector4> source, |
ReadOnlySpan<Vector4> source, |
||||
float amount); |
float amount); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Blend 2 rows together.
|
/// Blend 2 rows together.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="destination">destination span</param>
|
/// <param name="destination">destination span</param>
|
||||
/// <param name="background">the background span</param>
|
/// <param name="background">the background span</param>
|
||||
/// <param name="source">the source span</param>
|
/// <param name="source">the source span</param>
|
||||
/// <param name="amount">
|
/// <param name="amount">
|
||||
/// A span with values between 0 and 1 indicating the weight of the second source vector.
|
/// A span with values between 0 and 1 indicating the weight of the second source vector.
|
||||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
||||
/// </param>
|
/// </param>
|
||||
protected abstract void BlendFunction( |
protected abstract void BlendFunction( |
||||
Span<Vector4> destination, |
Span<Vector4> destination, |
||||
ReadOnlySpan<Vector4> background, |
ReadOnlySpan<Vector4> background, |
||||
ReadOnlySpan<Vector4> source, |
ReadOnlySpan<Vector4> source, |
||||
ReadOnlySpan<float> amount); |
ReadOnlySpan<float> amount); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Blends 2 rows together
|
/// Blends 2 rows together
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="configuration"><see cref="Configuration"/> to use internally</param>
|
/// <param name="configuration"><see cref="Configuration"/> to use internally</param>
|
||||
/// <param name="destination">the destination span</param>
|
/// <param name="destination">the destination span</param>
|
||||
/// <param name="background">the background span</param>
|
/// <param name="background">the background span</param>
|
||||
/// <param name="source">the source span</param>
|
/// <param name="source">the source span</param>
|
||||
/// <param name="amount">
|
/// <param name="amount">
|
||||
/// A span with values between 0 and 1 indicating the weight of the second source vector.
|
/// A span with values between 0 and 1 indicating the weight of the second source vector.
|
||||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
||||
/// </param>
|
/// </param>
|
||||
public void Blend( |
public void Blend( |
||||
Configuration configuration, |
Configuration configuration, |
||||
Span<TPixel> destination, |
Span<TPixel> destination, |
||||
ReadOnlySpan<TPixel> background, |
ReadOnlySpan<TPixel> background, |
||||
ReadOnlySpan<TPixel> source, |
ReadOnlySpan<TPixel> source, |
||||
ReadOnlySpan<float> amount) |
ReadOnlySpan<float> amount) |
||||
{ |
{ |
||||
this.Blend<TPixel>(configuration, destination, background, source, amount); |
this.Blend<TPixel>(configuration, destination, background, source, amount); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Blends 2 rows together
|
/// Blends 2 rows together
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <typeparam name="TPixelSrc">the pixel format of the source span</typeparam>
|
/// <typeparam name="TPixelSrc">the pixel format of the source span</typeparam>
|
||||
/// <param name="configuration"><see cref="Configuration"/> to use internally</param>
|
/// <param name="configuration"><see cref="Configuration"/> to use internally</param>
|
||||
/// <param name="destination">the destination span</param>
|
/// <param name="destination">the destination span</param>
|
||||
/// <param name="background">the background span</param>
|
/// <param name="background">the background span</param>
|
||||
/// <param name="source">the source span</param>
|
/// <param name="source">the source span</param>
|
||||
/// <param name="amount">
|
/// <param name="amount">
|
||||
/// A span with values between 0 and 1 indicating the weight of the second source vector.
|
/// A span with values between 0 and 1 indicating the weight of the second source vector.
|
||||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
||||
/// </param>
|
/// </param>
|
||||
public void Blend<TPixelSrc>( |
public void Blend<TPixelSrc>( |
||||
Configuration configuration, |
Configuration configuration, |
||||
Span<TPixel> destination, |
Span<TPixel> destination, |
||||
ReadOnlySpan<TPixel> background, |
ReadOnlySpan<TPixel> background, |
||||
ReadOnlySpan<TPixelSrc> source, |
ReadOnlySpan<TPixelSrc> source, |
||||
ReadOnlySpan<float> amount) |
ReadOnlySpan<float> amount) |
||||
where TPixelSrc : struct, IPixel<TPixelSrc> |
where TPixelSrc : struct, IPixel<TPixelSrc> |
||||
{ |
{ |
||||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
||||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
||||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
||||
|
|
||||
using (IMemoryOwner<Vector4> buffer = |
using (IMemoryOwner<Vector4> buffer = |
||||
configuration.MemoryAllocator.Allocate<Vector4>(destination.Length * 3)) |
configuration.MemoryAllocator.Allocate<Vector4>(destination.Length * 3)) |
||||
{ |
{ |
||||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
||||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
||||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
||||
|
|
||||
ReadOnlySpan<TPixel> sourcePixels = background.Slice(0, background.Length); |
ReadOnlySpan<TPixel> sourcePixels = background.Slice(0, background.Length); |
||||
PixelOperations<TPixel>.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); |
PixelOperations<TPixel>.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); |
||||
ReadOnlySpan<TPixelSrc> sourcePixels1 = source.Slice(0, background.Length); |
ReadOnlySpan<TPixelSrc> sourcePixels1 = source.Slice(0, background.Length); |
||||
PixelOperations<TPixelSrc>.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); |
PixelOperations<TPixelSrc>.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); |
||||
|
|
||||
this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); |
this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); |
||||
|
|
||||
Span<Vector4> sourceVectors = destinationSpan.Slice(0, background.Length); |
Span<Vector4> sourceVectors = destinationSpan.Slice(0, background.Length); |
||||
PixelOperations<TPixel>.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); |
PixelOperations<TPixel>.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Blends 2 rows together
|
/// Blends 2 rows together
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <typeparam name="TPixelSrc">the pixel format of the source span</typeparam>
|
/// <typeparam name="TPixelSrc">the pixel format of the source span</typeparam>
|
||||
/// <param name="configuration"><see cref="Configuration"/> to use internally</param>
|
/// <param name="configuration"><see cref="Configuration"/> to use internally</param>
|
||||
/// <param name="destination">the destination span</param>
|
/// <param name="destination">the destination span</param>
|
||||
/// <param name="background">the background span</param>
|
/// <param name="background">the background span</param>
|
||||
/// <param name="source">the source span</param>
|
/// <param name="source">the source span</param>
|
||||
/// <param name="amount">
|
/// <param name="amount">
|
||||
/// A value between 0 and 1 indicating the weight of the second source vector.
|
/// A value between 0 and 1 indicating the weight of the second source vector.
|
||||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
||||
/// </param>
|
/// </param>
|
||||
public void Blend<TPixelSrc>( |
public void Blend<TPixelSrc>( |
||||
Configuration configuration, |
Configuration configuration, |
||||
Span<TPixel> destination, |
Span<TPixel> destination, |
||||
ReadOnlySpan<TPixel> background, |
ReadOnlySpan<TPixel> background, |
||||
ReadOnlySpan<TPixelSrc> source, |
ReadOnlySpan<TPixelSrc> source, |
||||
float amount) |
float amount) |
||||
where TPixelSrc : struct, IPixel<TPixelSrc> |
where TPixelSrc : struct, IPixel<TPixelSrc> |
||||
{ |
{ |
||||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
||||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
||||
Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); |
Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); |
||||
|
|
||||
using (IMemoryOwner<Vector4> buffer = |
using (IMemoryOwner<Vector4> buffer = |
||||
configuration.MemoryAllocator.Allocate<Vector4>(destination.Length * 3)) |
configuration.MemoryAllocator.Allocate<Vector4>(destination.Length * 3)) |
||||
{ |
{ |
||||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
||||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
||||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
||||
|
|
||||
ReadOnlySpan<TPixel> sourcePixels = background.Slice(0, background.Length); |
ReadOnlySpan<TPixel> sourcePixels = background.Slice(0, background.Length); |
||||
PixelOperations<TPixel>.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); |
PixelOperations<TPixel>.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); |
||||
ReadOnlySpan<TPixelSrc> sourcePixels1 = source.Slice(0, background.Length); |
ReadOnlySpan<TPixelSrc> sourcePixels1 = source.Slice(0, background.Length); |
||||
PixelOperations<TPixelSrc>.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); |
PixelOperations<TPixelSrc>.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); |
||||
|
|
||||
this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); |
this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); |
||||
|
|
||||
Span<Vector4> sourceVectors = destinationSpan.Slice(0, background.Length); |
Span<Vector4> sourceVectors = destinationSpan.Slice(0, background.Length); |
||||
PixelOperations<TPixel>.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); |
PixelOperations<TPixel>.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,217 +1,217 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats.PixelBlenders; |
using SixLabors.ImageSharp.PixelFormats.PixelBlenders; |
||||
|
|
||||
namespace SixLabors.ImageSharp.PixelFormats |
namespace SixLabors.ImageSharp.PixelFormats |
||||
{ |
{ |
||||
/// <content>
|
/// <content>
|
||||
/// Provides access to pixel blenders
|
/// Provides access to pixel blenders
|
||||
/// </content>
|
/// </content>
|
||||
public partial class PixelOperations<TPixel> |
public partial class PixelOperations<TPixel> |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Find an instance of the pixel blender.
|
/// Find an instance of the pixel blender.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="options">the blending and composition to apply</param>
|
/// <param name="options">the blending and composition to apply</param>
|
||||
/// <returns>A <see cref="PixelBlender{TPixel}"/>.</returns>
|
/// <returns>A <see cref="PixelBlender{TPixel}"/>.</returns>
|
||||
internal PixelBlender<TPixel> GetPixelBlender(GraphicsOptions options) |
internal PixelBlender<TPixel> GetPixelBlender(GraphicsOptions options) |
||||
{ |
{ |
||||
return this.GetPixelBlender(options.ColorBlendingMode, options.AlphaCompositionMode); |
return this.GetPixelBlender(options.ColorBlendingMode, options.AlphaCompositionMode); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Find an instance of the pixel blender.
|
/// Find an instance of the pixel blender.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="colorMode">The color blending mode to apply</param>
|
/// <param name="colorMode">The color blending mode to apply</param>
|
||||
/// <param name="alphaMode">The alpha composition mode to apply</param>
|
/// <param name="alphaMode">The alpha composition mode to apply</param>
|
||||
/// <returns>A <see cref="PixelBlender{TPixel}"/>.</returns>
|
/// <returns>A <see cref="PixelBlender{TPixel}"/>.</returns>
|
||||
internal virtual PixelBlender<TPixel> GetPixelBlender(PixelColorBlendingMode colorMode, PixelAlphaCompositionMode alphaMode) |
internal virtual PixelBlender<TPixel> GetPixelBlender(PixelColorBlendingMode colorMode, PixelAlphaCompositionMode alphaMode) |
||||
{ |
{ |
||||
switch (alphaMode) |
switch (alphaMode) |
||||
{ |
{ |
||||
case PixelAlphaCompositionMode.Clear: |
case PixelAlphaCompositionMode.Clear: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyClear.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyClear.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddClear.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddClear.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractClear.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractClear.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenClear.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenClear.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenClear.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenClear.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenClear.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenClear.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayClear.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayClear.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightClear.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightClear.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalClear.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalClear.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.Xor: |
case PixelAlphaCompositionMode.Xor: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyXor.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyXor.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddXor.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddXor.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractXor.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractXor.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenXor.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenXor.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenXor.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenXor.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenXor.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenXor.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayXor.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayXor.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightXor.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightXor.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalXor.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalXor.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.Src: |
case PixelAlphaCompositionMode.Src: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrc.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrc.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrc.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrc.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrc.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrc.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrc.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrc.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrc.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrc.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrc.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrc.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrc.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrc.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrc.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrc.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalSrc.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalSrc.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.SrcAtop: |
case PixelAlphaCompositionMode.SrcAtop: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcAtop.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcAtop.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcAtop.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcAtop.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcAtop.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcAtop.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcAtop.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcAtop.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcAtop.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcAtop.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcAtop.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcAtop.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcAtop.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcAtop.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcAtop.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcAtop.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalSrcAtop.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalSrcAtop.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.SrcIn: |
case PixelAlphaCompositionMode.SrcIn: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcIn.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcIn.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcIn.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcIn.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcIn.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcIn.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcIn.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcIn.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcIn.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcIn.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcIn.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcIn.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcIn.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcIn.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcIn.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcIn.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalSrcIn.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalSrcIn.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.SrcOut: |
case PixelAlphaCompositionMode.SrcOut: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcOut.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcOut.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcOut.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcOut.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcOut.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcOut.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcOut.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcOut.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcOut.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcOut.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcOut.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcOut.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcOut.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcOut.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcOut.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcOut.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalSrcOut.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalSrcOut.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.Dest: |
case PixelAlphaCompositionMode.Dest: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDest.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDest.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDest.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDest.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDest.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDest.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDest.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDest.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDest.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDest.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDest.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDest.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDest.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDest.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDest.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDest.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalDest.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalDest.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.DestAtop: |
case PixelAlphaCompositionMode.DestAtop: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestAtop.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestAtop.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestAtop.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestAtop.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestAtop.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestAtop.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestAtop.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestAtop.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestAtop.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestAtop.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestAtop.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestAtop.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestAtop.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestAtop.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestAtop.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestAtop.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalDestAtop.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalDestAtop.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.DestIn: |
case PixelAlphaCompositionMode.DestIn: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestIn.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestIn.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestIn.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestIn.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestIn.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestIn.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestIn.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestIn.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestIn.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestIn.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestIn.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestIn.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestIn.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestIn.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestIn.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestIn.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalDestIn.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalDestIn.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.DestOut: |
case PixelAlphaCompositionMode.DestOut: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestOut.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestOut.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestOut.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestOut.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestOut.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestOut.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestOut.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestOut.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestOut.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestOut.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestOut.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestOut.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestOut.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestOut.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestOut.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestOut.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalDestOut.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalDestOut.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.DestOver: |
case PixelAlphaCompositionMode.DestOver: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestOver.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestOver.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestOver.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestOver.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestOver.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestOver.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestOver.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestOver.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestOver.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestOver.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestOver.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestOver.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestOver.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestOver.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestOver.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestOver.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalDestOver.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalDestOver.Instance; |
||||
} |
} |
||||
|
|
||||
case PixelAlphaCompositionMode.SrcOver: |
case PixelAlphaCompositionMode.SrcOver: |
||||
default: |
default: |
||||
switch (colorMode) |
switch (colorMode) |
||||
{ |
{ |
||||
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcOver.Instance; |
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcOver.Instance; |
||||
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcOver.Instance; |
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcOver.Instance; |
||||
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcOver.Instance; |
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcOver.Instance; |
||||
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcOver.Instance; |
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcOver.Instance; |
||||
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcOver.Instance; |
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcOver.Instance; |
||||
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcOver.Instance; |
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcOver.Instance; |
||||
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcOver.Instance; |
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcOver.Instance; |
||||
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcOver.Instance; |
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcOver.Instance; |
||||
case PixelColorBlendingMode.Normal: |
case PixelColorBlendingMode.Normal: |
||||
default: return DefaultPixelBlenders<TPixel>.NormalSrcOver.Instance; |
default: return DefaultPixelBlenders<TPixel>.NormalSrcOver.Instance; |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,177 +1,177 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using System.Linq; |
using System.Linq; |
||||
using SixLabors.ImageSharp.PixelFormats; |
using SixLabors.ImageSharp.PixelFormats; |
||||
using SixLabors.ImageSharp.Processing; |
using SixLabors.ImageSharp.Processing; |
||||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
||||
using SixLabors.Primitives; |
using SixLabors.Primitives; |
||||
using Xunit; |
using Xunit; |
||||
|
|
||||
// ReSharper disable InconsistentNaming
|
// ReSharper disable InconsistentNaming
|
||||
namespace SixLabors.ImageSharp.Tests.Drawing |
namespace SixLabors.ImageSharp.Tests.Drawing |
||||
{ |
{ |
||||
[GroupOutput("Drawing")] |
[GroupOutput("Drawing")] |
||||
public class SolidFillBlendedShapesTests |
public class SolidFillBlendedShapesTests |
||||
{ |
{ |
||||
public static IEnumerable<object[]> modes = GetAllModeCombinations(); |
public static IEnumerable<object[]> modes = GetAllModeCombinations(); |
||||
|
|
||||
private static IEnumerable<object[]> GetAllModeCombinations() |
private static IEnumerable<object[]> GetAllModeCombinations() |
||||
{ |
{ |
||||
foreach (var composition in Enum.GetValues(typeof(PixelAlphaCompositionMode))) |
foreach (var composition in Enum.GetValues(typeof(PixelAlphaCompositionMode))) |
||||
{ |
{ |
||||
foreach (var blending in Enum.GetValues(typeof(PixelColorBlendingMode))) |
foreach (var blending in Enum.GetValues(typeof(PixelColorBlendingMode))) |
||||
{ |
{ |
||||
yield return new object[] { blending, composition }; |
yield return new object[] { blending, composition }; |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
|
|
||||
[Theory] |
[Theory] |
||||
[WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] |
[WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] |
||||
public void _1DarkBlueRect_2BlendHotPinkRect<TPixel>( |
public void _1DarkBlueRect_2BlendHotPinkRect<TPixel>( |
||||
TestImageProvider<TPixel> provider, |
TestImageProvider<TPixel> provider, |
||||
PixelColorBlendingMode blending, |
PixelColorBlendingMode blending, |
||||
PixelAlphaCompositionMode composition) |
PixelAlphaCompositionMode composition) |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
using (Image<TPixel> img = provider.GetImage()) |
using (Image<TPixel> img = provider.GetImage()) |
||||
{ |
{ |
||||
int scaleX = img.Width / 100; |
int scaleX = img.Width / 100; |
||||
int scaleY = img.Height / 100; |
int scaleY = img.Height / 100; |
||||
img.Mutate( |
img.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
Color.DarkBlue, |
Color.DarkBlue, |
||||
new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY) |
new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY) |
||||
) |
) |
||||
.Fill(new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode=composition }, |
.Fill(new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode=composition }, |
||||
Color.HotPink, |
Color.HotPink, |
||||
new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY)) |
new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY)) |
||||
); |
); |
||||
|
|
||||
VerifyImage(provider, blending, composition, img); |
VerifyImage(provider, blending, composition, img); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] |
[WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] |
||||
public void _1DarkBlueRect_2BlendHotPinkRect_3BlendTransparentEllipse<TPixel>( |
public void _1DarkBlueRect_2BlendHotPinkRect_3BlendTransparentEllipse<TPixel>( |
||||
TestImageProvider<TPixel> provider, |
TestImageProvider<TPixel> provider, |
||||
PixelColorBlendingMode blending, |
PixelColorBlendingMode blending, |
||||
PixelAlphaCompositionMode composition) |
PixelAlphaCompositionMode composition) |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
using (Image<TPixel> img = provider.GetImage()) |
using (Image<TPixel> img = provider.GetImage()) |
||||
{ |
{ |
||||
int scaleX = img.Width / 100; |
int scaleX = img.Width / 100; |
||||
int scaleY = img.Height / 100; |
int scaleY = img.Height / 100; |
||||
img.Mutate( |
img.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
Color.DarkBlue, |
Color.DarkBlue, |
||||
new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); |
new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); |
||||
img.Mutate( |
img.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, |
new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, |
||||
Color.HotPink, |
Color.HotPink, |
||||
new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY))); |
new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY))); |
||||
img.Mutate( |
img.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, |
new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, |
||||
Color.Transparent, |
Color.Transparent, |
||||
new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) |
new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) |
||||
); |
); |
||||
|
|
||||
VerifyImage(provider, blending, composition, img); |
VerifyImage(provider, blending, composition, img); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] |
[WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] |
||||
public void _1DarkBlueRect_2BlendHotPinkRect_3BlendSemiTransparentRedEllipse<TPixel>( |
public void _1DarkBlueRect_2BlendHotPinkRect_3BlendSemiTransparentRedEllipse<TPixel>( |
||||
TestImageProvider<TPixel> provider, |
TestImageProvider<TPixel> provider, |
||||
PixelColorBlendingMode blending, |
PixelColorBlendingMode blending, |
||||
PixelAlphaCompositionMode composition) |
PixelAlphaCompositionMode composition) |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
using (Image<TPixel> img = provider.GetImage()) |
using (Image<TPixel> img = provider.GetImage()) |
||||
{ |
{ |
||||
int scaleX = (img.Width / 100); |
int scaleX = (img.Width / 100); |
||||
int scaleY = (img.Height / 100); |
int scaleY = (img.Height / 100); |
||||
img.Mutate( |
img.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
Color.DarkBlue, |
Color.DarkBlue, |
||||
new Rectangle(0 * scaleX, 40, 100 * scaleX, 20 * scaleY))); |
new Rectangle(0 * scaleX, 40, 100 * scaleX, 20 * scaleY))); |
||||
img.Mutate( |
img.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, |
new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, |
||||
Color.HotPink, |
Color.HotPink, |
||||
new Rectangle(20 * scaleX, 0, 30 * scaleX, 100 * scaleY))); |
new Rectangle(20 * scaleX, 0, 30 * scaleX, 100 * scaleY))); |
||||
|
|
||||
var transparentRed = Color.Red.WithAlpha(0.5f); |
var transparentRed = Color.Red.WithAlpha(0.5f); |
||||
|
|
||||
img.Mutate( |
img.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, |
new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, |
||||
transparentRed, |
transparentRed, |
||||
new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) |
new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) |
||||
); |
); |
||||
|
|
||||
VerifyImage(provider, blending, composition, img); ; |
VerifyImage(provider, blending, composition, img); ; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] |
[WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] |
||||
public void _1DarkBlueRect_2BlendBlackEllipse<TPixel>( |
public void _1DarkBlueRect_2BlendBlackEllipse<TPixel>( |
||||
TestImageProvider<TPixel> provider, |
TestImageProvider<TPixel> provider, |
||||
PixelColorBlendingMode blending, |
PixelColorBlendingMode blending, |
||||
PixelAlphaCompositionMode composition) |
PixelAlphaCompositionMode composition) |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
using(Image<TPixel> dstImg = provider.GetImage(), srcImg = provider.GetImage()) |
using(Image<TPixel> dstImg = provider.GetImage(), srcImg = provider.GetImage()) |
||||
{ |
{ |
||||
int scaleX = (dstImg.Width / 100); |
int scaleX = (dstImg.Width / 100); |
||||
int scaleY = (dstImg.Height / 100); |
int scaleY = (dstImg.Height / 100); |
||||
|
|
||||
dstImg.Mutate( |
dstImg.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
Color.DarkBlue, |
Color.DarkBlue, |
||||
new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); |
new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); |
||||
|
|
||||
srcImg.Mutate( |
srcImg.Mutate( |
||||
x => x.Fill( |
x => x.Fill( |
||||
Color.Black, |
Color.Black, |
||||
new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY))); |
new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY))); |
||||
|
|
||||
dstImg.Mutate( |
dstImg.Mutate( |
||||
x => x.DrawImage(srcImg, new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }) |
x => x.DrawImage(srcImg, new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }) |
||||
); |
); |
||||
|
|
||||
VerifyImage(provider, blending, composition, dstImg); |
VerifyImage(provider, blending, composition, dstImg); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
private static void VerifyImage<TPixel>( |
private static void VerifyImage<TPixel>( |
||||
TestImageProvider<TPixel> provider, |
TestImageProvider<TPixel> provider, |
||||
PixelColorBlendingMode blending, |
PixelColorBlendingMode blending, |
||||
PixelAlphaCompositionMode composition, |
PixelAlphaCompositionMode composition, |
||||
Image<TPixel> img) |
Image<TPixel> img) |
||||
where TPixel : struct, IPixel<TPixel> |
where TPixel : struct, IPixel<TPixel> |
||||
{ |
{ |
||||
img.DebugSave( |
img.DebugSave( |
||||
provider, |
provider, |
||||
new { composition, blending }, |
new { composition, blending }, |
||||
appendPixelTypeToFileName: false, |
appendPixelTypeToFileName: false, |
||||
appendSourceFileOrDescription: false); |
appendSourceFileOrDescription: false); |
||||
|
|
||||
var comparer = ImageComparer.TolerantPercentage(0.01f, 3); |
var comparer = ImageComparer.TolerantPercentage(0.01f, 3); |
||||
img.CompareFirstFrameToReferenceOutput(comparer, |
img.CompareFirstFrameToReferenceOutput(comparer, |
||||
provider, |
provider, |
||||
new { composition, blending }, |
new { composition, blending }, |
||||
appendPixelTypeToFileName: false, |
appendPixelTypeToFileName: false, |
||||
appendSourceFileOrDescription: false); |
appendSourceFileOrDescription: false); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,146 +1,146 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using System; |
using System; |
||||
using System.IO; |
using System.IO; |
||||
using System.Linq; |
using System.Linq; |
||||
using Moq; |
using Moq; |
||||
using SixLabors.ImageSharp.Formats; |
using SixLabors.ImageSharp.Formats; |
||||
using SixLabors.ImageSharp.Formats.Bmp; |
using SixLabors.ImageSharp.Formats.Bmp; |
||||
using SixLabors.ImageSharp.Formats.Gif; |
using SixLabors.ImageSharp.Formats.Gif; |
||||
using SixLabors.ImageSharp.Formats.Jpeg; |
using SixLabors.ImageSharp.Formats.Jpeg; |
||||
using SixLabors.ImageSharp.Formats.Png; |
using SixLabors.ImageSharp.Formats.Png; |
||||
using SixLabors.ImageSharp.PixelFormats; |
using SixLabors.ImageSharp.PixelFormats; |
||||
using Xunit; |
using Xunit; |
||||
|
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests |
namespace SixLabors.ImageSharp.Tests |
||||
{ |
{ |
||||
public class ImageFormatManagerTests |
public class ImageFormatManagerTests |
||||
{ |
{ |
||||
public ImageFormatManager FormatsManagerEmpty { get; } |
public ImageFormatManager FormatsManagerEmpty { get; } |
||||
public ImageFormatManager DefaultFormatsManager { get; } |
public ImageFormatManager DefaultFormatsManager { get; } |
||||
|
|
||||
public ImageFormatManagerTests() |
public ImageFormatManagerTests() |
||||
{ |
{ |
||||
this.DefaultFormatsManager = Configuration.CreateDefaultInstance().ImageFormatsManager; |
this.DefaultFormatsManager = Configuration.CreateDefaultInstance().ImageFormatsManager; |
||||
this.FormatsManagerEmpty = new ImageFormatManager(); |
this.FormatsManagerEmpty = new ImageFormatManager(); |
||||
} |
} |
||||
|
|
||||
[Fact] |
[Fact] |
||||
public void IfAutoloadWellKnownFormatsIsTrueAllFormatsAreLoaded() |
public void IfAutoloadWellKnownFormatsIsTrueAllFormatsAreLoaded() |
||||
{ |
{ |
||||
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<PngEncoder>().Count()); |
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<PngEncoder>().Count()); |
||||
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<BmpEncoder>().Count()); |
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<BmpEncoder>().Count()); |
||||
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<JpegEncoder>().Count()); |
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<JpegEncoder>().Count()); |
||||
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<GifEncoder>().Count()); |
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<GifEncoder>().Count()); |
||||
|
|
||||
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<PngDecoder>().Count()); |
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<PngDecoder>().Count()); |
||||
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<BmpDecoder>().Count()); |
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<BmpDecoder>().Count()); |
||||
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<JpegDecoder>().Count()); |
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<JpegDecoder>().Count()); |
||||
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<BmpDecoder>().Count()); |
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<BmpDecoder>().Count()); |
||||
} |
} |
||||
|
|
||||
[Fact] |
[Fact] |
||||
public void AddImageFormatDetectorNullthrows() |
public void AddImageFormatDetectorNullthrows() |
||||
{ |
{ |
||||
Assert.Throws<ArgumentNullException>(() => |
Assert.Throws<ArgumentNullException>(() => |
||||
{ |
{ |
||||
this.DefaultFormatsManager.AddImageFormatDetector(null); |
this.DefaultFormatsManager.AddImageFormatDetector(null); |
||||
}); |
}); |
||||
} |
} |
||||
|
|
||||
[Fact] |
[Fact] |
||||
public void RegisterNullMimeTypeEncoder() |
public void RegisterNullMimeTypeEncoder() |
||||
{ |
{ |
||||
Assert.Throws<ArgumentNullException>(() => |
Assert.Throws<ArgumentNullException>(() => |
||||
{ |
{ |
||||
this.DefaultFormatsManager.SetEncoder(null, new Mock<IImageEncoder>().Object); |
this.DefaultFormatsManager.SetEncoder(null, new Mock<IImageEncoder>().Object); |
||||
}); |
}); |
||||
Assert.Throws<ArgumentNullException>(() => |
Assert.Throws<ArgumentNullException>(() => |
||||
{ |
{ |
||||
this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null); |
this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null); |
||||
}); |
}); |
||||
Assert.Throws<ArgumentNullException>(() => |
Assert.Throws<ArgumentNullException>(() => |
||||
{ |
{ |
||||
this.DefaultFormatsManager.SetEncoder(null, null); |
this.DefaultFormatsManager.SetEncoder(null, null); |
||||
}); |
}); |
||||
} |
} |
||||
|
|
||||
[Fact] |
[Fact] |
||||
public void RegisterNullSetDecoder() |
public void RegisterNullSetDecoder() |
||||
{ |
{ |
||||
Assert.Throws<ArgumentNullException>(() => |
Assert.Throws<ArgumentNullException>(() => |
||||
{ |
{ |
||||
this.DefaultFormatsManager.SetDecoder(null, new Mock<IImageDecoder>().Object); |
this.DefaultFormatsManager.SetDecoder(null, new Mock<IImageDecoder>().Object); |
||||
}); |
}); |
||||
Assert.Throws<ArgumentNullException>(() => |
Assert.Throws<ArgumentNullException>(() => |
||||
{ |
{ |
||||
this.DefaultFormatsManager.SetDecoder(BmpFormat.Instance, null); |
this.DefaultFormatsManager.SetDecoder(BmpFormat.Instance, null); |
||||
}); |
}); |
||||
Assert.Throws<ArgumentNullException>(() => |
Assert.Throws<ArgumentNullException>(() => |
||||
{ |
{ |
||||
this.DefaultFormatsManager.SetDecoder(null, null); |
this.DefaultFormatsManager.SetDecoder(null, null); |
||||
}); |
}); |
||||
} |
} |
||||
|
|
||||
[Fact] |
[Fact] |
||||
public void RegisterMimeTypeEncoderReplacesLast() |
public void RegisterMimeTypeEncoderReplacesLast() |
||||
{ |
{ |
||||
IImageEncoder encoder1 = new Mock<IImageEncoder>().Object; |
IImageEncoder encoder1 = new Mock<IImageEncoder>().Object; |
||||
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); |
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); |
||||
IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); |
IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); |
||||
Assert.Equal(encoder1, found); |
Assert.Equal(encoder1, found); |
||||
|
|
||||
IImageEncoder encoder2 = new Mock<IImageEncoder>().Object; |
IImageEncoder encoder2 = new Mock<IImageEncoder>().Object; |
||||
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); |
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); |
||||
IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); |
IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); |
||||
Assert.Equal(encoder2, found2); |
Assert.Equal(encoder2, found2); |
||||
Assert.NotEqual(found, found2); |
Assert.NotEqual(found, found2); |
||||
} |
} |
||||
|
|
||||
[Fact] |
[Fact] |
||||
public void RegisterMimeTypeDecoderReplacesLast() |
public void RegisterMimeTypeDecoderReplacesLast() |
||||
{ |
{ |
||||
IImageDecoder decoder1 = new Mock<IImageDecoder>().Object; |
IImageDecoder decoder1 = new Mock<IImageDecoder>().Object; |
||||
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); |
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); |
||||
IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); |
IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); |
||||
Assert.Equal(decoder1, found); |
Assert.Equal(decoder1, found); |
||||
|
|
||||
IImageDecoder decoder2 = new Mock<IImageDecoder>().Object; |
IImageDecoder decoder2 = new Mock<IImageDecoder>().Object; |
||||
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); |
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); |
||||
IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); |
IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); |
||||
Assert.Equal(decoder2, found2); |
Assert.Equal(decoder2, found2); |
||||
Assert.NotEqual(found, found2); |
Assert.NotEqual(found, found2); |
||||
} |
} |
||||
|
|
||||
[Fact] |
[Fact] |
||||
public void AddFormatCallsConfig() |
public void AddFormatCallsConfig() |
||||
{ |
{ |
||||
var provider = new Mock<IConfigurationModule>(); |
var provider = new Mock<IConfigurationModule>(); |
||||
var config = new Configuration(); |
var config = new Configuration(); |
||||
config.Configure(provider.Object); |
config.Configure(provider.Object); |
||||
|
|
||||
provider.Verify(x => x.Configure(config)); |
provider.Verify(x => x.Configure(config)); |
||||
} |
} |
||||
|
|
||||
[Fact] |
[Fact] |
||||
public void DetectFormatAllocatesCleanBuffer() |
public void DetectFormatAllocatesCleanBuffer() |
||||
{ |
{ |
||||
byte[] jpegImage; |
byte[] jpegImage; |
||||
using (var buffer = new MemoryStream()) |
using (var buffer = new MemoryStream()) |
||||
{ |
{ |
||||
using (var image = new Image<Rgba32>(100, 100)) |
using (var image = new Image<Rgba32>(100, 100)) |
||||
{ |
{ |
||||
image.SaveAsJpeg(buffer); |
image.SaveAsJpeg(buffer); |
||||
jpegImage = buffer.ToArray(); |
jpegImage = buffer.ToArray(); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
byte[] invalidImage = { 1, 2, 3 }; |
byte[] invalidImage = { 1, 2, 3 }; |
||||
|
|
||||
Assert.Equal(Image.DetectFormat(jpegImage), JpegFormat.Instance); |
Assert.Equal(Image.DetectFormat(jpegImage), JpegFormat.Instance); |
||||
Assert.True(Image.DetectFormat(invalidImage) is null); |
Assert.True(Image.DetectFormat(invalidImage) is null); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,56 +1,56 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders |
namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders |
||||
{ |
{ |
||||
using SixLabors.ImageSharp.PixelFormats; |
using SixLabors.ImageSharp.PixelFormats; |
||||
using SixLabors.ImageSharp.Processing; |
using SixLabors.ImageSharp.Processing; |
||||
|
|
||||
using Xunit; |
using Xunit; |
||||
|
|
||||
public class PorterDuffCompositorTests |
public class PorterDuffCompositorTests |
||||
{ |
{ |
||||
// TODO: Add other modes to compare.
|
// TODO: Add other modes to compare.
|
||||
public static readonly TheoryData<PixelAlphaCompositionMode> CompositingOperators = |
public static readonly TheoryData<PixelAlphaCompositionMode> CompositingOperators = |
||||
new TheoryData<PixelAlphaCompositionMode> |
new TheoryData<PixelAlphaCompositionMode> |
||||
{ |
{ |
||||
PixelAlphaCompositionMode.Src, |
PixelAlphaCompositionMode.Src, |
||||
PixelAlphaCompositionMode.SrcAtop, |
PixelAlphaCompositionMode.SrcAtop, |
||||
PixelAlphaCompositionMode.SrcOver, |
PixelAlphaCompositionMode.SrcOver, |
||||
PixelAlphaCompositionMode.SrcIn, |
PixelAlphaCompositionMode.SrcIn, |
||||
PixelAlphaCompositionMode.SrcOut, |
PixelAlphaCompositionMode.SrcOut, |
||||
PixelAlphaCompositionMode.Dest, |
PixelAlphaCompositionMode.Dest, |
||||
PixelAlphaCompositionMode.DestAtop, |
PixelAlphaCompositionMode.DestAtop, |
||||
PixelAlphaCompositionMode.DestOver, |
PixelAlphaCompositionMode.DestOver, |
||||
PixelAlphaCompositionMode.DestIn, |
PixelAlphaCompositionMode.DestIn, |
||||
PixelAlphaCompositionMode.DestOut, |
PixelAlphaCompositionMode.DestOut, |
||||
PixelAlphaCompositionMode.Clear, |
PixelAlphaCompositionMode.Clear, |
||||
PixelAlphaCompositionMode.Xor |
PixelAlphaCompositionMode.Xor |
||||
}; |
}; |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[WithFile(TestImages.Png.PDDest, nameof(CompositingOperators), PixelTypes.Rgba32)] |
[WithFile(TestImages.Png.PDDest, nameof(CompositingOperators), PixelTypes.Rgba32)] |
||||
public void PorterDuffOutputIsCorrect(TestImageProvider<Rgba32> provider, PixelAlphaCompositionMode mode) |
public void PorterDuffOutputIsCorrect(TestImageProvider<Rgba32> provider, PixelAlphaCompositionMode mode) |
||||
{ |
{ |
||||
var srcFile = TestFile.Create(TestImages.Png.PDSrc); |
var srcFile = TestFile.Create(TestImages.Png.PDSrc); |
||||
using (Image<Rgba32> src = srcFile.CreateRgba32Image()) |
using (Image<Rgba32> src = srcFile.CreateRgba32Image()) |
||||
using (Image<Rgba32> dest = provider.GetImage()) |
using (Image<Rgba32> dest = provider.GetImage()) |
||||
{ |
{ |
||||
GraphicsOptions options = new GraphicsOptions |
GraphicsOptions options = new GraphicsOptions |
||||
{ |
{ |
||||
AlphaCompositionMode = mode |
AlphaCompositionMode = mode |
||||
}; |
}; |
||||
|
|
||||
using (Image<Rgba32> res = dest.Clone(x => x.DrawImage(src, options))) |
using (Image<Rgba32> res = dest.Clone(x => x.DrawImage(src, options))) |
||||
{ |
{ |
||||
string combinedMode = mode.ToString(); |
string combinedMode = mode.ToString(); |
||||
|
|
||||
if (combinedMode != "Src" && combinedMode.StartsWith("Src")) combinedMode = combinedMode.Substring(3); |
if (combinedMode != "Src" && combinedMode.StartsWith("Src")) combinedMode = combinedMode.Substring(3); |
||||
|
|
||||
res.DebugSave(provider, combinedMode); |
res.DebugSave(provider, combinedMode); |
||||
res.CompareToReferenceOutput(provider, combinedMode); |
res.CompareToReferenceOutput(provider, combinedMode); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,266 +1,266 @@ |
|||||
|
|
||||
JPEGsnoop 1.8.0 by Calvin Hass |
JPEGsnoop 1.8.0 by Calvin Hass |
||||
http://www.impulseadventure.com/photo/ |
http://www.impulseadventure.com/photo/ |
||||
------------------------------------- |
------------------------------------- |
||||
|
|
||||
Filename: [.\Floorplan.jpg] |
Filename: [.\Floorplan.jpg] |
||||
Filesize: [161577] Bytes |
Filesize: [161577] Bytes |
||||
|
|
||||
Start Offset: 0x00000000 |
Start Offset: 0x00000000 |
||||
*** Marker: SOI (xFFD8) *** |
*** Marker: SOI (xFFD8) *** |
||||
OFFSET: 0x00000000 |
OFFSET: 0x00000000 |
||||
|
|
||||
*** Marker: APP0 (xFFE0) *** |
*** Marker: APP0 (xFFE0) *** |
||||
OFFSET: 0x00000002 |
OFFSET: 0x00000002 |
||||
Length = 16 |
Length = 16 |
||||
Identifier = [JFIF] |
Identifier = [JFIF] |
||||
version = [1.1] |
version = [1.1] |
||||
density = 300 x 300 DPI (dots per inch) |
density = 300 x 300 DPI (dots per inch) |
||||
thumbnail = 0 x 0 |
thumbnail = 0 x 0 |
||||
|
|
||||
*** Marker: APP1 (xFFE1) *** |
*** Marker: APP1 (xFFE1) *** |
||||
OFFSET: 0x00000014 |
OFFSET: 0x00000014 |
||||
Length = 13464 |
Length = 13464 |
||||
Identifier = [Exif] |
Identifier = [Exif] |
||||
Identifier TIFF = 0x[4D4D002A 00000008] |
Identifier TIFF = 0x[4D4D002A 00000008] |
||||
Endian = Motorola (big) |
Endian = Motorola (big) |
||||
TAG Mark x002A = 0x002A |
TAG Mark x002A = 0x002A |
||||
|
|
||||
EXIF IFD0 @ Absolute 0x00000026 |
EXIF IFD0 @ Absolute 0x00000026 |
||||
Dir Length = 0x000A |
Dir Length = 0x000A |
||||
[Model ] = "Photosmart Plus B209a-m" |
[Model ] = "Photosmart Plus B209a-m" |
||||
[Orientation ] = 1 = Row 0: top, Col 0: left |
[Orientation ] = 1 = Row 0: top, Col 0: left |
||||
[XResolution ] = 300/1 |
[XResolution ] = 300/1 |
||||
[YResolution ] = 300/1 |
[YResolution ] = 300/1 |
||||
[ResolutionUnit ] = Inch |
[ResolutionUnit ] = Inch |
||||
[Software ] = "Windows Photo Editor 10.0.10011.16384" |
[Software ] = "Windows Photo Editor 10.0.10011.16384" |
||||
[DateTime ] = "2016:01:02 20:17:37" |
[DateTime ] = "2016:01:02 20:17:37" |
||||
[ExifOffset ] = @ 0x091A |
[ExifOffset ] = @ 0x091A |
||||
Offset to Next IFD = 0x000011B6 |
Offset to Next IFD = 0x000011B6 |
||||
|
|
||||
EXIF IFD1 @ Absolute 0x000011D4 |
EXIF IFD1 @ Absolute 0x000011D4 |
||||
Dir Length = 0x0006 |
Dir Length = 0x0006 |
||||
[Compression ] = JPEG |
[Compression ] = JPEG |
||||
[XResolution ] = 96/1 |
[XResolution ] = 96/1 |
||||
[YResolution ] = 96/1 |
[YResolution ] = 96/1 |
||||
[ResolutionUnit ] = Inch |
[ResolutionUnit ] = Inch |
||||
[JpegIFOffset ] = @ +0x1214 = @ 0x1232 |
[JpegIFOffset ] = @ +0x1214 = @ 0x1232 |
||||
[JpegIFByteCount ] = 0x[0000227C] / 8828 |
[JpegIFByteCount ] = 0x[0000227C] / 8828 |
||||
Offset to Next IFD = 0x00000000 |
Offset to Next IFD = 0x00000000 |
||||
|
|
||||
EXIF SubIFD @ Absolute 0x00000938 |
EXIF SubIFD @ Absolute 0x00000938 |
||||
Dir Length = 0x0008 |
Dir Length = 0x0008 |
||||
[DateTimeOriginal ] = "2016:01:02 19:22:28" |
[DateTimeOriginal ] = "2016:01:02 19:22:28" |
||||
[DateTimeDigitized ] = "2016:01:02 19:22:28" |
[DateTimeDigitized ] = "2016:01:02 19:22:28" |
||||
[SubSecTimeOriginal ] = "00" |
[SubSecTimeOriginal ] = "00" |
||||
[SubSecTimeDigitized ] = "00" |
[SubSecTimeDigitized ] = "00" |
||||
[ColorSpace ] = sRGB |
[ColorSpace ] = sRGB |
||||
[ExifImageWidth ] = 0x[00000922] / 2338 |
[ExifImageWidth ] = 0x[00000922] / 2338 |
||||
[ExifImageHeight ] = 0x[000008C9] / 2249 |
[ExifImageHeight ] = 0x[000008C9] / 2249 |
||||
|
|
||||
*** Marker: APP1 (xFFE1) *** |
*** Marker: APP1 (xFFE1) *** |
||||
OFFSET: 0x000034AE |
OFFSET: 0x000034AE |
||||
Length = 12772 |
Length = 12772 |
||||
Identifier = [http://ns.adobe.com/xap/1.0/] |
Identifier = [http://ns.adobe.com/xap/1.0/] |
||||
XMP = |
XMP = |
||||
|<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?> |
|<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?> |
||||
|<x:xmpmeta xmlns:x="adobe:ns:meta/"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b" xmlns:xmp="http://ns.adobe.com/xap/1.0/"><xmp:CreatorTool>Windows Photo Editor 10.0.10011.16384</xmp:CreatorTool><xmp:CreateDate>2016-01-02T19:22:28</xmp:CreateDate></rdf:Description></rdf:RDF></x:xmpmeta> |
|<x:xmpmeta xmlns:x="adobe:ns:meta/"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b" xmlns:xmp="http://ns.adobe.com/xap/1.0/"><xmp:CreatorTool>Windows Photo Editor 10.0.10011.16384</xmp:CreatorTool><xmp:CreateDate>2016-01-02T19:22:28</xmp:CreateDate></rdf:Description></rdf:RDF></x:xmpmeta> |
||||
|
|
||||
*** Marker: DQT (xFFDB) *** |
*** Marker: DQT (xFFDB) *** |
||||
Define a Quantization Table. |
Define a Quantization Table. |
||||
OFFSET: 0x00006694 |
OFFSET: 0x00006694 |
||||
Table length = 67 |
Table length = 67 |
||||
---- |
---- |
||||
Precision=8 bits |
Precision=8 bits |
||||
Destination ID=0 (Luminance) |
Destination ID=0 (Luminance) |
||||
DQT, Row #0: 3 2 2 3 5 8 10 12 |
DQT, Row #0: 3 2 2 3 5 8 10 12 |
||||
DQT, Row #1: 2 2 3 4 5 12 12 11 |
DQT, Row #1: 2 2 3 4 5 12 12 11 |
||||
DQT, Row #2: 3 3 3 5 8 11 14 11 |
DQT, Row #2: 3 3 3 5 8 11 14 11 |
||||
DQT, Row #3: 3 3 4 6 10 17 16 12 |
DQT, Row #3: 3 3 4 6 10 17 16 12 |
||||
DQT, Row #4: 4 4 7 11 14 22 21 15 |
DQT, Row #4: 4 4 7 11 14 22 21 15 |
||||
DQT, Row #5: 5 7 11 13 16 21 23 18 |
DQT, Row #5: 5 7 11 13 16 21 23 18 |
||||
DQT, Row #6: 10 13 16 17 21 24 24 20 |
DQT, Row #6: 10 13 16 17 21 24 24 20 |
||||
DQT, Row #7: 14 18 19 20 22 20 21 20 |
DQT, Row #7: 14 18 19 20 22 20 21 20 |
||||
Approx quality factor = 90.06 (scaling=19.88 variance=1.14) |
Approx quality factor = 90.06 (scaling=19.88 variance=1.14) |
||||
|
|
||||
*** Marker: SOF0 (Baseline DCT) (xFFC0) *** |
*** Marker: SOF0 (Baseline DCT) (xFFC0) *** |
||||
OFFSET: 0x000066D9 |
OFFSET: 0x000066D9 |
||||
Frame header length = 11 |
Frame header length = 11 |
||||
Precision = 8 |
Precision = 8 |
||||
Number of Lines = 645 |
Number of Lines = 645 |
||||
Samples per Line = 976 |
Samples per Line = 976 |
||||
Image Size = 976 x 645 |
Image Size = 976 x 645 |
||||
Raw Image Orientation = Landscape |
Raw Image Orientation = Landscape |
||||
Number of Img components = 1 |
Number of Img components = 1 |
||||
Component[1]: ID=0x01, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) |
Component[1]: ID=0x01, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) |
||||
|
|
||||
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
||||
OFFSET: 0x000066E6 |
OFFSET: 0x000066E6 |
||||
Huffman table length = 31 |
Huffman table length = 31 |
||||
---- |
---- |
||||
Destination ID = 0 |
Destination ID = 0 |
||||
Class = 0 (DC / Lossless Table) |
Class = 0 (DC / Lossless Table) |
||||
Codes of length 01 bits (000 total): |
Codes of length 01 bits (000 total): |
||||
Codes of length 02 bits (001 total): 00 |
Codes of length 02 bits (001 total): 00 |
||||
Codes of length 03 bits (005 total): 01 02 03 04 05 |
Codes of length 03 bits (005 total): 01 02 03 04 05 |
||||
Codes of length 04 bits (001 total): 06 |
Codes of length 04 bits (001 total): 06 |
||||
Codes of length 05 bits (001 total): 07 |
Codes of length 05 bits (001 total): 07 |
||||
Codes of length 06 bits (001 total): 08 |
Codes of length 06 bits (001 total): 08 |
||||
Codes of length 07 bits (001 total): 09 |
Codes of length 07 bits (001 total): 09 |
||||
Codes of length 08 bits (001 total): 0A |
Codes of length 08 bits (001 total): 0A |
||||
Codes of length 09 bits (001 total): 0B |
Codes of length 09 bits (001 total): 0B |
||||
Codes of length 10 bits (000 total): |
Codes of length 10 bits (000 total): |
||||
Codes of length 11 bits (000 total): |
Codes of length 11 bits (000 total): |
||||
Codes of length 12 bits (000 total): |
Codes of length 12 bits (000 total): |
||||
Codes of length 13 bits (000 total): |
Codes of length 13 bits (000 total): |
||||
Codes of length 14 bits (000 total): |
Codes of length 14 bits (000 total): |
||||
Codes of length 15 bits (000 total): |
Codes of length 15 bits (000 total): |
||||
Codes of length 16 bits (000 total): |
Codes of length 16 bits (000 total): |
||||
Total number of codes: 012 |
Total number of codes: 012 |
||||
|
|
||||
|
|
||||
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
||||
OFFSET: 0x00006707 |
OFFSET: 0x00006707 |
||||
Huffman table length = 181 |
Huffman table length = 181 |
||||
---- |
---- |
||||
Destination ID = 0 |
Destination ID = 0 |
||||
Class = 1 (AC Table) |
Class = 1 (AC Table) |
||||
Codes of length 01 bits (000 total): |
Codes of length 01 bits (000 total): |
||||
Codes of length 02 bits (002 total): 01 02 |
Codes of length 02 bits (002 total): 01 02 |
||||
Codes of length 03 bits (001 total): 03 |
Codes of length 03 bits (001 total): 03 |
||||
Codes of length 04 bits (003 total): 00 04 11 |
Codes of length 04 bits (003 total): 00 04 11 |
||||
Codes of length 05 bits (003 total): 05 12 21 |
Codes of length 05 bits (003 total): 05 12 21 |
||||
Codes of length 06 bits (002 total): 31 41 |
Codes of length 06 bits (002 total): 31 41 |
||||
Codes of length 07 bits (004 total): 06 13 51 61 |
Codes of length 07 bits (004 total): 06 13 51 61 |
||||
Codes of length 08 bits (003 total): 07 22 71 |
Codes of length 08 bits (003 total): 07 22 71 |
||||
Codes of length 09 bits (005 total): 14 32 81 91 A1 |
Codes of length 09 bits (005 total): 14 32 81 91 A1 |
||||
Codes of length 10 bits (005 total): 08 23 42 B1 C1 |
Codes of length 10 bits (005 total): 08 23 42 B1 C1 |
||||
Codes of length 11 bits (004 total): 15 52 D1 F0 |
Codes of length 11 bits (004 total): 15 52 D1 F0 |
||||
Codes of length 12 bits (004 total): 24 33 62 72 |
Codes of length 12 bits (004 total): 24 33 62 72 |
||||
Codes of length 13 bits (000 total): |
Codes of length 13 bits (000 total): |
||||
Codes of length 14 bits (000 total): |
Codes of length 14 bits (000 total): |
||||
Codes of length 15 bits (001 total): 82 |
Codes of length 15 bits (001 total): 82 |
||||
Codes of length 16 bits (125 total): 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 |
Codes of length 16 bits (125 total): 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 |
||||
37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 |
37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 |
||||
57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 |
57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 |
||||
77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 |
77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 |
||||
96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 |
96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 |
||||
B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA |
B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA |
||||
D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 |
D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 |
||||
E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA |
E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA |
||||
Total number of codes: 162 |
Total number of codes: 162 |
||||
|
|
||||
|
|
||||
*** Marker: SOS (Start of Scan) (xFFDA) *** |
*** Marker: SOS (Start of Scan) (xFFDA) *** |
||||
OFFSET: 0x000067BE |
OFFSET: 0x000067BE |
||||
Scan header length = 8 |
Scan header length = 8 |
||||
Number of img components = 1 |
Number of img components = 1 |
||||
Component[1]: selector=0x01, table=0(DC),0(AC) |
Component[1]: selector=0x01, table=0(DC),0(AC) |
||||
Spectral selection = 0 .. 63 |
Spectral selection = 0 .. 63 |
||||
Successive approximation = 0x00 |
Successive approximation = 0x00 |
||||
|
|
||||
|
|
||||
*** Decoding SCAN Data *** |
*** Decoding SCAN Data *** |
||||
OFFSET: 0x000067C8 |
OFFSET: 0x000067C8 |
||||
Scan Decode Mode: No IDCT (DC only) |
Scan Decode Mode: No IDCT (DC only) |
||||
NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT] |
NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT] |
||||
|
|
||||
Scan Data encountered marker 0xFFD9 @ 0x00027727.0 |
Scan Data encountered marker 0xFFD9 @ 0x00027727.0 |
||||
|
|
||||
Compression stats: |
Compression stats: |
||||
Compression Ratio: 4.66:1 |
Compression Ratio: 4.66:1 |
||||
Bits per pixel: 1.72:1 |
Bits per pixel: 1.72:1 |
||||
|
|
||||
Huffman code histogram stats: |
Huffman code histogram stats: |
||||
Huffman Table: (Dest ID: 0, Class: DC) |
Huffman Table: (Dest ID: 0, Class: DC) |
||||
# codes of length 01 bits: 0 ( 0%) |
# codes of length 01 bits: 0 ( 0%) |
||||
# codes of length 02 bits: 3571 ( 36%) |
# codes of length 02 bits: 3571 ( 36%) |
||||
# codes of length 03 bits: 4320 ( 44%) |
# codes of length 03 bits: 4320 ( 44%) |
||||
# codes of length 04 bits: 925 ( 9%) |
# codes of length 04 bits: 925 ( 9%) |
||||
# codes of length 05 bits: 456 ( 5%) |
# codes of length 05 bits: 456 ( 5%) |
||||
# codes of length 06 bits: 313 ( 3%) |
# codes of length 06 bits: 313 ( 3%) |
||||
# codes of length 07 bits: 291 ( 3%) |
# codes of length 07 bits: 291 ( 3%) |
||||
# codes of length 08 bits: 6 ( 0%) |
# codes of length 08 bits: 6 ( 0%) |
||||
# codes of length 09 bits: 0 ( 0%) |
# codes of length 09 bits: 0 ( 0%) |
||||
# codes of length 10 bits: 0 ( 0%) |
# codes of length 10 bits: 0 ( 0%) |
||||
# codes of length 11 bits: 0 ( 0%) |
# codes of length 11 bits: 0 ( 0%) |
||||
# codes of length 12 bits: 0 ( 0%) |
# codes of length 12 bits: 0 ( 0%) |
||||
# codes of length 13 bits: 0 ( 0%) |
# codes of length 13 bits: 0 ( 0%) |
||||
# codes of length 14 bits: 0 ( 0%) |
# codes of length 14 bits: 0 ( 0%) |
||||
# codes of length 15 bits: 0 ( 0%) |
# codes of length 15 bits: 0 ( 0%) |
||||
# codes of length 16 bits: 0 ( 0%) |
# codes of length 16 bits: 0 ( 0%) |
||||
|
|
||||
Huffman Table: (Dest ID: 0, Class: AC) |
Huffman Table: (Dest ID: 0, Class: AC) |
||||
# codes of length 01 bits: 0 ( 0%) |
# codes of length 01 bits: 0 ( 0%) |
||||
# codes of length 02 bits: 78118 ( 44%) |
# codes of length 02 bits: 78118 ( 44%) |
||||
# codes of length 03 bits: 22349 ( 13%) |
# codes of length 03 bits: 22349 ( 13%) |
||||
# codes of length 04 bits: 35264 ( 20%) |
# codes of length 04 bits: 35264 ( 20%) |
||||
# codes of length 05 bits: 18811 ( 11%) |
# codes of length 05 bits: 18811 ( 11%) |
||||
# codes of length 06 bits: 4312 ( 2%) |
# codes of length 06 bits: 4312 ( 2%) |
||||
# codes of length 07 bits: 8245 ( 5%) |
# codes of length 07 bits: 8245 ( 5%) |
||||
# codes of length 08 bits: 4682 ( 3%) |
# codes of length 08 bits: 4682 ( 3%) |
||||
# codes of length 09 bits: 1584 ( 1%) |
# codes of length 09 bits: 1584 ( 1%) |
||||
# codes of length 10 bits: 1900 ( 1%) |
# codes of length 10 bits: 1900 ( 1%) |
||||
# codes of length 11 bits: 324 ( 0%) |
# codes of length 11 bits: 324 ( 0%) |
||||
# codes of length 12 bits: 116 ( 0%) |
# codes of length 12 bits: 116 ( 0%) |
||||
# codes of length 13 bits: 0 ( 0%) |
# codes of length 13 bits: 0 ( 0%) |
||||
# codes of length 14 bits: 0 ( 0%) |
# codes of length 14 bits: 0 ( 0%) |
||||
# codes of length 15 bits: 6 ( 0%) |
# codes of length 15 bits: 6 ( 0%) |
||||
# codes of length 16 bits: 639 ( 0%) |
# codes of length 16 bits: 639 ( 0%) |
||||
|
|
||||
YCC clipping in DC: |
YCC clipping in DC: |
||||
Y component: [<0= 0] [>255= 0] |
Y component: [<0= 0] [>255= 0] |
||||
Cb component: [<0= 0] [>255= 0] |
Cb component: [<0= 0] [>255= 0] |
||||
Cr component: [<0= 0] [>255= 0] |
Cr component: [<0= 0] [>255= 0] |
||||
|
|
||||
RGB clipping in DC: |
RGB clipping in DC: |
||||
R component: [<0= 0] [>255= 0] |
R component: [<0= 0] [>255= 0] |
||||
G component: [<0= 0] [>255= 0] |
G component: [<0= 0] [>255= 0] |
||||
B component: [<0= 0] [>255= 0] |
B component: [<0= 0] [>255= 0] |
||||
|
|
||||
Average Pixel Luminance (Y): |
Average Pixel Luminance (Y): |
||||
Y=[231] (range: 0..255) |
Y=[231] (range: 0..255) |
||||
|
|
||||
Brightest Pixel Search: |
Brightest Pixel Search: |
||||
YCC=[ 1017, 0, 0] RGB=[255,255,255] @ MCU[ 7, 0] |
YCC=[ 1017, 0, 0] RGB=[255,255,255] @ MCU[ 7, 0] |
||||
|
|
||||
Finished Decoding SCAN Data |
Finished Decoding SCAN Data |
||||
Number of RESTART markers decoded: 0 |
Number of RESTART markers decoded: 0 |
||||
Next position in scan buffer: Offset 0x00027726.4 |
Next position in scan buffer: Offset 0x00027726.4 |
||||
|
|
||||
|
|
||||
*** Marker: EOI (End of Image) (xFFD9) *** |
*** Marker: EOI (End of Image) (xFFD9) *** |
||||
OFFSET: 0x00027727 |
OFFSET: 0x00027727 |
||||
|
|
||||
|
|
||||
*** Searching Compression Signatures *** |
*** Searching Compression Signatures *** |
||||
|
|
||||
Signature: 015C645021E37D3469A6B652789383DB |
Signature: 015C645021E37D3469A6B652789383DB |
||||
Signature (Rotated): 01D400C125EB43B05762A66347B271F7 |
Signature (Rotated): 01D400C125EB43B05762A66347B271F7 |
||||
File Offset: 0 bytes |
File Offset: 0 bytes |
||||
Chroma subsampling: Gray |
Chroma subsampling: Gray |
||||
EXIF Make/Model: OK [???] [Photosmart Plus B209a-m] |
EXIF Make/Model: OK [???] [Photosmart Plus B209a-m] |
||||
EXIF Makernotes: NONE |
EXIF Makernotes: NONE |
||||
EXIF Software: OK [Windows Photo Editor 10.0.10011.16384] |
EXIF Software: OK [Windows Photo Editor 10.0.10011.16384] |
||||
|
|
||||
Searching Compression Signatures: (3347 built-in, 0 user(*) ) |
Searching Compression Signatures: (3347 built-in, 0 user(*) ) |
||||
|
|
||||
EXIF.Make / Software EXIF.Model Quality Subsamp Match? |
EXIF.Make / Software EXIF.Model Quality Subsamp Match? |
||||
------------------------- ----------------------------------- ---------------- -------------- |
------------------------- ----------------------------------- ---------------- -------------- |
||||
SW :[IJG Library ] [090 Gray ] |
SW :[IJG Library ] [090 Gray ] |
||||
|
|
||||
The following IJG-based editors also match this signature: |
The following IJG-based editors also match this signature: |
||||
SW :[GIMP ] [090 Gray ] |
SW :[GIMP ] [090 Gray ] |
||||
SW :[IrfanView ] [090 Gray ] |
SW :[IrfanView ] [090 Gray ] |
||||
SW :[idImager ] [090 Gray ] |
SW :[idImager ] [090 Gray ] |
||||
SW :[FastStone Image Viewer ] [090 Gray ] |
SW :[FastStone Image Viewer ] [090 Gray ] |
||||
SW :[NeatImage ] [090 Gray ] |
SW :[NeatImage ] [090 Gray ] |
||||
SW :[Paint.NET ] [090 Gray ] |
SW :[Paint.NET ] [090 Gray ] |
||||
SW :[Photomatix ] [090 Gray ] |
SW :[Photomatix ] [090 Gray ] |
||||
SW :[XnView ] [090 Gray ] |
SW :[XnView ] [090 Gray ] |
||||
|
|
||||
Based on the analysis of compression characteristics and EXIF metadata: |
Based on the analysis of compression characteristics and EXIF metadata: |
||||
|
|
||||
ASSESSMENT: Class 2 - Image has high probability of being processed/edited |
ASSESSMENT: Class 2 - Image has high probability of being processed/edited |
||||
|
|
||||
|
|
||||
|
|||||
@ -1,434 +1,434 @@ |
|||||
|
|
||||
JPEGsnoop 1.8.0 by Calvin Hass |
JPEGsnoop 1.8.0 by Calvin Hass |
||||
http://www.impulseadventure.com/photo/ |
http://www.impulseadventure.com/photo/ |
||||
------------------------------------- |
------------------------------------- |
||||
|
|
||||
Filename: [.\badrst.jpg] |
Filename: [.\badrst.jpg] |
||||
Filesize: [74497] Bytes |
Filesize: [74497] Bytes |
||||
|
|
||||
Start Offset: 0x00000000 |
Start Offset: 0x00000000 |
||||
*** Marker: SOI (xFFD8) *** |
*** Marker: SOI (xFFD8) *** |
||||
OFFSET: 0x00000000 |
OFFSET: 0x00000000 |
||||
|
|
||||
*** Marker: APP0 (xFFE0) *** |
*** Marker: APP0 (xFFE0) *** |
||||
OFFSET: 0x00000002 |
OFFSET: 0x00000002 |
||||
Length = 16 |
Length = 16 |
||||
Identifier = [JFIF] |
Identifier = [JFIF] |
||||
version = [1.1] |
version = [1.1] |
||||
density = 96 x 96 DPI (dots per inch) |
density = 96 x 96 DPI (dots per inch) |
||||
thumbnail = 0 x 0 |
thumbnail = 0 x 0 |
||||
|
|
||||
*** Marker: APP1 (xFFE1) *** |
*** Marker: APP1 (xFFE1) *** |
||||
OFFSET: 0x00000014 |
OFFSET: 0x00000014 |
||||
Length = 8628 |
Length = 8628 |
||||
Identifier = [Exif] |
Identifier = [Exif] |
||||
Identifier TIFF = 0x[4D4D002A 00000008] |
Identifier TIFF = 0x[4D4D002A 00000008] |
||||
Endian = Motorola (big) |
Endian = Motorola (big) |
||||
TAG Mark x002A = 0x002A |
TAG Mark x002A = 0x002A |
||||
|
|
||||
EXIF IFD0 @ Absolute 0x00000026 |
EXIF IFD0 @ Absolute 0x00000026 |
||||
Dir Length = 0x0003 |
Dir Length = 0x0003 |
||||
[Orientation ] = 1 = Row 0: top, Col 0: left |
[Orientation ] = 1 = Row 0: top, Col 0: left |
||||
[ExifOffset ] = @ 0x083E |
[ExifOffset ] = @ 0x083E |
||||
Offset to Next IFD = 0x000010B6 |
Offset to Next IFD = 0x000010B6 |
||||
|
|
||||
EXIF IFD1 @ Absolute 0x000010D4 |
EXIF IFD1 @ Absolute 0x000010D4 |
||||
Dir Length = 0x0006 |
Dir Length = 0x0006 |
||||
[Compression ] = JPEG |
[Compression ] = JPEG |
||||
[XResolution ] = 96/1 |
[XResolution ] = 96/1 |
||||
[YResolution ] = 96/1 |
[YResolution ] = 96/1 |
||||
[ResolutionUnit ] = Inch |
[ResolutionUnit ] = Inch |
||||
[JpegIFOffset ] = @ +0x1114 = @ 0x1132 |
[JpegIFOffset ] = @ +0x1114 = @ 0x1132 |
||||
[JpegIFByteCount ] = 0x[00001097] / 4247 |
[JpegIFByteCount ] = 0x[00001097] / 4247 |
||||
Offset to Next IFD = 0x00000000 |
Offset to Next IFD = 0x00000000 |
||||
|
|
||||
EXIF SubIFD @ Absolute 0x0000085C |
EXIF SubIFD @ Absolute 0x0000085C |
||||
Dir Length = 0x0005 |
Dir Length = 0x0005 |
||||
[DateTimeOriginal ] = "2016:02:28 11:17:08" |
[DateTimeOriginal ] = "2016:02:28 11:17:08" |
||||
[DateTimeDigitized ] = "2016:02:28 11:17:08" |
[DateTimeDigitized ] = "2016:02:28 11:17:08" |
||||
[SubSecTimeOriginal ] = "06" |
[SubSecTimeOriginal ] = "06" |
||||
[SubSecTimeDigitized ] = "06" |
[SubSecTimeDigitized ] = "06" |
||||
|
|
||||
*** Marker: APP1 (xFFE1) *** |
*** Marker: APP1 (xFFE1) *** |
||||
OFFSET: 0x000021CA |
OFFSET: 0x000021CA |
||||
Length = 2464 |
Length = 2464 |
||||
Identifier = [http://ns.adobe.com/xap/1.0/] |
Identifier = [http://ns.adobe.com/xap/1.0/] |
||||
XMP = |
XMP = |
||||
|<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?> |
|<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?> |
||||
|<x:xmpmeta xmlns:x="adobe:ns:meta/"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b" xmlns:xmp="http://ns.adobe.com/xap/1.0/"><xmp:CreateDate>2016-02-28T11:17:08.057</xmp:CreateDate></rdf:Description></rdf:RDF></x:xmpmeta> |
|<x:xmpmeta xmlns:x="adobe:ns:meta/"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b" xmlns:xmp="http://ns.adobe.com/xap/1.0/"><xmp:CreateDate>2016-02-28T11:17:08.057</xmp:CreateDate></rdf:Description></rdf:RDF></x:xmpmeta> |
||||
|
|
||||
*** Marker: DQT (xFFDB) *** |
*** Marker: DQT (xFFDB) *** |
||||
Define a Quantization Table. |
Define a Quantization Table. |
||||
OFFSET: 0x00002B6C |
OFFSET: 0x00002B6C |
||||
Table length = 67 |
Table length = 67 |
||||
---- |
---- |
||||
Precision=8 bits |
Precision=8 bits |
||||
Destination ID=0 (Luminance) |
Destination ID=0 (Luminance) |
||||
DQT, Row #0: 3 2 2 3 5 8 10 12 |
DQT, Row #0: 3 2 2 3 5 8 10 12 |
||||
DQT, Row #1: 2 2 3 4 5 12 12 11 |
DQT, Row #1: 2 2 3 4 5 12 12 11 |
||||
DQT, Row #2: 3 3 3 5 8 11 14 11 |
DQT, Row #2: 3 3 3 5 8 11 14 11 |
||||
DQT, Row #3: 3 3 4 6 10 17 16 12 |
DQT, Row #3: 3 3 4 6 10 17 16 12 |
||||
DQT, Row #4: 4 4 7 11 14 22 21 15 |
DQT, Row #4: 4 4 7 11 14 22 21 15 |
||||
DQT, Row #5: 5 7 11 13 16 21 23 18 |
DQT, Row #5: 5 7 11 13 16 21 23 18 |
||||
DQT, Row #6: 10 13 16 17 21 24 24 20 |
DQT, Row #6: 10 13 16 17 21 24 24 20 |
||||
DQT, Row #7: 14 18 19 20 22 20 21 20 |
DQT, Row #7: 14 18 19 20 22 20 21 20 |
||||
Approx quality factor = 90.06 (scaling=19.88 variance=1.14) |
Approx quality factor = 90.06 (scaling=19.88 variance=1.14) |
||||
|
|
||||
*** Marker: DQT (xFFDB) *** |
*** Marker: DQT (xFFDB) *** |
||||
Define a Quantization Table. |
Define a Quantization Table. |
||||
OFFSET: 0x00002BB1 |
OFFSET: 0x00002BB1 |
||||
Table length = 67 |
Table length = 67 |
||||
---- |
---- |
||||
Precision=8 bits |
Precision=8 bits |
||||
Destination ID=1 (Chrominance) |
Destination ID=1 (Chrominance) |
||||
DQT, Row #0: 3 4 5 9 20 20 20 20 |
DQT, Row #0: 3 4 5 9 20 20 20 20 |
||||
DQT, Row #1: 4 4 5 13 20 20 20 20 |
DQT, Row #1: 4 4 5 13 20 20 20 20 |
||||
DQT, Row #2: 5 5 11 20 20 20 20 20 |
DQT, Row #2: 5 5 11 20 20 20 20 20 |
||||
DQT, Row #3: 9 13 20 20 20 20 20 20 |
DQT, Row #3: 9 13 20 20 20 20 20 20 |
||||
DQT, Row #4: 20 20 20 20 20 20 20 20 |
DQT, Row #4: 20 20 20 20 20 20 20 20 |
||||
DQT, Row #5: 20 20 20 20 20 20 20 20 |
DQT, Row #5: 20 20 20 20 20 20 20 20 |
||||
DQT, Row #6: 20 20 20 20 20 20 20 20 |
DQT, Row #6: 20 20 20 20 20 20 20 20 |
||||
DQT, Row #7: 20 20 20 20 20 20 20 20 |
DQT, Row #7: 20 20 20 20 20 20 20 20 |
||||
Approx quality factor = 89.93 (scaling=20.14 variance=0.34) |
Approx quality factor = 89.93 (scaling=20.14 variance=0.34) |
||||
|
|
||||
*** Marker: SOF0 (Baseline DCT) (xFFC0) *** |
*** Marker: SOF0 (Baseline DCT) (xFFC0) *** |
||||
OFFSET: 0x00002BF6 |
OFFSET: 0x00002BF6 |
||||
Frame header length = 17 |
Frame header length = 17 |
||||
Precision = 8 |
Precision = 8 |
||||
Number of Lines = 480 |
Number of Lines = 480 |
||||
Samples per Line = 640 |
Samples per Line = 640 |
||||
Image Size = 640 x 480 |
Image Size = 640 x 480 |
||||
Raw Image Orientation = Landscape |
Raw Image Orientation = Landscape |
||||
Number of Img components = 3 |
Number of Img components = 3 |
||||
Component[1]: ID=0x01, Samp Fac=0x22 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) |
Component[1]: ID=0x01, Samp Fac=0x22 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) |
||||
Component[2]: ID=0x02, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cb) |
Component[2]: ID=0x02, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cb) |
||||
Component[3]: ID=0x03, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cr) |
Component[3]: ID=0x03, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cr) |
||||
|
|
||||
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
||||
OFFSET: 0x00002C09 |
OFFSET: 0x00002C09 |
||||
Huffman table length = 31 |
Huffman table length = 31 |
||||
---- |
---- |
||||
Destination ID = 0 |
Destination ID = 0 |
||||
Class = 0 (DC / Lossless Table) |
Class = 0 (DC / Lossless Table) |
||||
Codes of length 01 bits (000 total): |
Codes of length 01 bits (000 total): |
||||
Codes of length 02 bits (001 total): 00 |
Codes of length 02 bits (001 total): 00 |
||||
Codes of length 03 bits (005 total): 01 02 03 04 05 |
Codes of length 03 bits (005 total): 01 02 03 04 05 |
||||
Codes of length 04 bits (001 total): 06 |
Codes of length 04 bits (001 total): 06 |
||||
Codes of length 05 bits (001 total): 07 |
Codes of length 05 bits (001 total): 07 |
||||
Codes of length 06 bits (001 total): 08 |
Codes of length 06 bits (001 total): 08 |
||||
Codes of length 07 bits (001 total): 09 |
Codes of length 07 bits (001 total): 09 |
||||
Codes of length 08 bits (001 total): 0A |
Codes of length 08 bits (001 total): 0A |
||||
Codes of length 09 bits (001 total): 0B |
Codes of length 09 bits (001 total): 0B |
||||
Codes of length 10 bits (000 total): |
Codes of length 10 bits (000 total): |
||||
Codes of length 11 bits (000 total): |
Codes of length 11 bits (000 total): |
||||
Codes of length 12 bits (000 total): |
Codes of length 12 bits (000 total): |
||||
Codes of length 13 bits (000 total): |
Codes of length 13 bits (000 total): |
||||
Codes of length 14 bits (000 total): |
Codes of length 14 bits (000 total): |
||||
Codes of length 15 bits (000 total): |
Codes of length 15 bits (000 total): |
||||
Codes of length 16 bits (000 total): |
Codes of length 16 bits (000 total): |
||||
Total number of codes: 012 |
Total number of codes: 012 |
||||
|
|
||||
|
|
||||
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
||||
OFFSET: 0x00002C2A |
OFFSET: 0x00002C2A |
||||
Huffman table length = 181 |
Huffman table length = 181 |
||||
---- |
---- |
||||
Destination ID = 0 |
Destination ID = 0 |
||||
Class = 1 (AC Table) |
Class = 1 (AC Table) |
||||
Codes of length 01 bits (000 total): |
Codes of length 01 bits (000 total): |
||||
Codes of length 02 bits (002 total): 01 02 |
Codes of length 02 bits (002 total): 01 02 |
||||
Codes of length 03 bits (001 total): 03 |
Codes of length 03 bits (001 total): 03 |
||||
Codes of length 04 bits (003 total): 00 04 11 |
Codes of length 04 bits (003 total): 00 04 11 |
||||
Codes of length 05 bits (003 total): 05 12 21 |
Codes of length 05 bits (003 total): 05 12 21 |
||||
Codes of length 06 bits (002 total): 31 41 |
Codes of length 06 bits (002 total): 31 41 |
||||
Codes of length 07 bits (004 total): 06 13 51 61 |
Codes of length 07 bits (004 total): 06 13 51 61 |
||||
Codes of length 08 bits (003 total): 07 22 71 |
Codes of length 08 bits (003 total): 07 22 71 |
||||
Codes of length 09 bits (005 total): 14 32 81 91 A1 |
Codes of length 09 bits (005 total): 14 32 81 91 A1 |
||||
Codes of length 10 bits (005 total): 08 23 42 B1 C1 |
Codes of length 10 bits (005 total): 08 23 42 B1 C1 |
||||
Codes of length 11 bits (004 total): 15 52 D1 F0 |
Codes of length 11 bits (004 total): 15 52 D1 F0 |
||||
Codes of length 12 bits (004 total): 24 33 62 72 |
Codes of length 12 bits (004 total): 24 33 62 72 |
||||
Codes of length 13 bits (000 total): |
Codes of length 13 bits (000 total): |
||||
Codes of length 14 bits (000 total): |
Codes of length 14 bits (000 total): |
||||
Codes of length 15 bits (001 total): 82 |
Codes of length 15 bits (001 total): 82 |
||||
Codes of length 16 bits (125 total): 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 |
Codes of length 16 bits (125 total): 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 |
||||
37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 |
37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 |
||||
57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 |
57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 |
||||
77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 |
77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 |
||||
96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 |
96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 |
||||
B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA |
B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA |
||||
D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 |
D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 |
||||
E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA |
E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA |
||||
Total number of codes: 162 |
Total number of codes: 162 |
||||
|
|
||||
|
|
||||
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
||||
OFFSET: 0x00002CE1 |
OFFSET: 0x00002CE1 |
||||
Huffman table length = 31 |
Huffman table length = 31 |
||||
---- |
---- |
||||
Destination ID = 1 |
Destination ID = 1 |
||||
Class = 0 (DC / Lossless Table) |
Class = 0 (DC / Lossless Table) |
||||
Codes of length 01 bits (000 total): |
Codes of length 01 bits (000 total): |
||||
Codes of length 02 bits (003 total): 00 01 02 |
Codes of length 02 bits (003 total): 00 01 02 |
||||
Codes of length 03 bits (001 total): 03 |
Codes of length 03 bits (001 total): 03 |
||||
Codes of length 04 bits (001 total): 04 |
Codes of length 04 bits (001 total): 04 |
||||
Codes of length 05 bits (001 total): 05 |
Codes of length 05 bits (001 total): 05 |
||||
Codes of length 06 bits (001 total): 06 |
Codes of length 06 bits (001 total): 06 |
||||
Codes of length 07 bits (001 total): 07 |
Codes of length 07 bits (001 total): 07 |
||||
Codes of length 08 bits (001 total): 08 |
Codes of length 08 bits (001 total): 08 |
||||
Codes of length 09 bits (001 total): 09 |
Codes of length 09 bits (001 total): 09 |
||||
Codes of length 10 bits (001 total): 0A |
Codes of length 10 bits (001 total): 0A |
||||
Codes of length 11 bits (001 total): 0B |
Codes of length 11 bits (001 total): 0B |
||||
Codes of length 12 bits (000 total): |
Codes of length 12 bits (000 total): |
||||
Codes of length 13 bits (000 total): |
Codes of length 13 bits (000 total): |
||||
Codes of length 14 bits (000 total): |
Codes of length 14 bits (000 total): |
||||
Codes of length 15 bits (000 total): |
Codes of length 15 bits (000 total): |
||||
Codes of length 16 bits (000 total): |
Codes of length 16 bits (000 total): |
||||
Total number of codes: 012 |
Total number of codes: 012 |
||||
|
|
||||
|
|
||||
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
*** Marker: DHT (Define Huffman Table) (xFFC4) *** |
||||
OFFSET: 0x00002D02 |
OFFSET: 0x00002D02 |
||||
Huffman table length = 181 |
Huffman table length = 181 |
||||
---- |
---- |
||||
Destination ID = 1 |
Destination ID = 1 |
||||
Class = 1 (AC Table) |
Class = 1 (AC Table) |
||||
Codes of length 01 bits (000 total): |
Codes of length 01 bits (000 total): |
||||
Codes of length 02 bits (002 total): 00 01 |
Codes of length 02 bits (002 total): 00 01 |
||||
Codes of length 03 bits (001 total): 02 |
Codes of length 03 bits (001 total): 02 |
||||
Codes of length 04 bits (002 total): 03 11 |
Codes of length 04 bits (002 total): 03 11 |
||||
Codes of length 05 bits (004 total): 04 05 21 31 |
Codes of length 05 bits (004 total): 04 05 21 31 |
||||
Codes of length 06 bits (004 total): 06 12 41 51 |
Codes of length 06 bits (004 total): 06 12 41 51 |
||||
Codes of length 07 bits (003 total): 07 61 71 |
Codes of length 07 bits (003 total): 07 61 71 |
||||
Codes of length 08 bits (004 total): 13 22 32 81 |
Codes of length 08 bits (004 total): 13 22 32 81 |
||||
Codes of length 09 bits (007 total): 08 14 42 91 A1 B1 C1 |
Codes of length 09 bits (007 total): 08 14 42 91 A1 B1 C1 |
||||
Codes of length 10 bits (005 total): 09 23 33 52 F0 |
Codes of length 10 bits (005 total): 09 23 33 52 F0 |
||||
Codes of length 11 bits (004 total): 15 62 72 D1 |
Codes of length 11 bits (004 total): 15 62 72 D1 |
||||
Codes of length 12 bits (004 total): 0A 16 24 34 |
Codes of length 12 bits (004 total): 0A 16 24 34 |
||||
Codes of length 13 bits (000 total): |
Codes of length 13 bits (000 total): |
||||
Codes of length 14 bits (001 total): E1 |
Codes of length 14 bits (001 total): E1 |
||||
Codes of length 15 bits (002 total): 25 F1 |
Codes of length 15 bits (002 total): 25 F1 |
||||
Codes of length 16 bits (119 total): 17 18 19 1A 26 27 28 29 2A 35 36 37 38 39 3A 43 |
Codes of length 16 bits (119 total): 17 18 19 1A 26 27 28 29 2A 35 36 37 38 39 3A 43 |
||||
44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A 63 |
44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A 63 |
||||
64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A 82 |
64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A 82 |
||||
83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99 |
83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99 |
||||
9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 |
9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 |
||||
B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 |
B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 |
||||
D6 D7 D8 D9 DA E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 |
D6 D7 D8 D9 DA E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 |
||||
F4 F5 F6 F7 F8 F9 FA |
F4 F5 F6 F7 F8 F9 FA |
||||
Total number of codes: 162 |
Total number of codes: 162 |
||||
|
|
||||
|
|
||||
*** Marker: DRI (Restart Interval) (xFFDD) *** |
*** Marker: DRI (Restart Interval) (xFFDD) *** |
||||
OFFSET: 0x00002DB9 |
OFFSET: 0x00002DB9 |
||||
Length = 4 |
Length = 4 |
||||
interval = 600 |
interval = 600 |
||||
|
|
||||
*** Marker: SOS (Start of Scan) (xFFDA) *** |
*** Marker: SOS (Start of Scan) (xFFDA) *** |
||||
OFFSET: 0x00002DBF |
OFFSET: 0x00002DBF |
||||
Scan header length = 12 |
Scan header length = 12 |
||||
Number of img components = 3 |
Number of img components = 3 |
||||
Component[1]: selector=0x01, table=0(DC),0(AC) |
Component[1]: selector=0x01, table=0(DC),0(AC) |
||||
Component[2]: selector=0x02, table=1(DC),1(AC) |
Component[2]: selector=0x02, table=1(DC),1(AC) |
||||
Component[3]: selector=0x03, table=1(DC),1(AC) |
Component[3]: selector=0x03, table=1(DC),1(AC) |
||||
Spectral selection = 0 .. 63 |
Spectral selection = 0 .. 63 |
||||
Successive approximation = 0x00 |
Successive approximation = 0x00 |
||||
|
|
||||
|
|
||||
*** Decoding SCAN Data *** |
*** Decoding SCAN Data *** |
||||
OFFSET: 0x00002DCD |
OFFSET: 0x00002DCD |
||||
Scan Decode Mode: No IDCT (DC only) |
Scan Decode Mode: No IDCT (DC only) |
||||
NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT] |
NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT] |
||||
|
|
||||
Expect Restart interval elapsed @ 0x00008802.4 |
Expect Restart interval elapsed @ 0x00008802.4 |
||||
ERROR: Restart marker not detected |
ERROR: Restart marker not detected |
||||
*** ERROR: Can't find huffman bitstring @ 0x00008802.5, table 0, value [0xffffffe0] |
*** ERROR: Can't find huffman bitstring @ 0x00008802.5, table 0, value [0xffffffe0] |
||||
*** ERROR: Bad huffman code @ 0x00008802.4 |
*** ERROR: Bad huffman code @ 0x00008802.4 |
||||
*** ERROR: Bad scan data in MCU(0,15): Lum CSS(0,0) @ Offset 0x00008802.5 |
*** ERROR: Bad scan data in MCU(0,15): Lum CSS(0,0) @ Offset 0x00008802.5 |
||||
MCU located at pixel=(0,240) |
MCU located at pixel=(0,240) |
||||
*** ERROR: Can't find huffman bitstring @ 0x00008802.6, table 0, value [0xffffffc0] |
*** ERROR: Can't find huffman bitstring @ 0x00008802.6, table 0, value [0xffffffc0] |
||||
*** ERROR: Bad huffman code @ 0x00008802.5 |
*** ERROR: Bad huffman code @ 0x00008802.5 |
||||
*** ERROR: Bad scan data in MCU(0,15): Lum CSS(1,0) @ Offset 0x00008802.6 |
*** ERROR: Bad scan data in MCU(0,15): Lum CSS(1,0) @ Offset 0x00008802.6 |
||||
MCU located at pixel=(8,240) |
MCU located at pixel=(8,240) |
||||
*** ERROR: Can't find huffman bitstring @ 0x00008802.7, table 0, value [0xffffff80] |
*** ERROR: Can't find huffman bitstring @ 0x00008802.7, table 0, value [0xffffff80] |
||||
*** ERROR: Bad huffman code @ 0x00008802.6 |
*** ERROR: Bad huffman code @ 0x00008802.6 |
||||
*** ERROR: Bad scan data in MCU(0,15): Lum CSS(0,1) @ Offset 0x00008802.7 |
*** ERROR: Bad scan data in MCU(0,15): Lum CSS(0,1) @ Offset 0x00008802.7 |
||||
MCU located at pixel=(0,248) |
MCU located at pixel=(0,248) |
||||
*** ERROR: Can't find huffman bitstring @ 0x00008803.0, table 0, value [0xffffffff] |
*** ERROR: Can't find huffman bitstring @ 0x00008803.0, table 0, value [0xffffffff] |
||||
*** ERROR: Bad huffman code @ 0x00008802.7 |
*** ERROR: Bad huffman code @ 0x00008802.7 |
||||
*** ERROR: Bad scan data in MCU(0,15): Lum CSS(1,1) @ Offset 0x00008803.0 |
*** ERROR: Bad scan data in MCU(0,15): Lum CSS(1,1) @ Offset 0x00008803.0 |
||||
MCU located at pixel=(8,248) |
MCU located at pixel=(8,248) |
||||
*** ERROR: Can't find huffman bitstring @ 0x00008803.1, table 1, value [0xfffffffe] |
*** ERROR: Can't find huffman bitstring @ 0x00008803.1, table 1, value [0xfffffffe] |
||||
*** ERROR: Bad huffman code @ 0x00008803.0 |
*** ERROR: Bad huffman code @ 0x00008803.0 |
||||
*** ERROR: Bad scan data in MCU(0,15): Chr(Cb) CSS(0,0) @ Offset 0x00008803.1 |
*** ERROR: Bad scan data in MCU(0,15): Chr(Cb) CSS(0,0) @ Offset 0x00008803.1 |
||||
MCU located at pixel=(0,240) |
MCU located at pixel=(0,240) |
||||
*** ERROR: Can't find huffman bitstring @ 0x00008803.2, table 1, value [0xfffffffc] |
*** ERROR: Can't find huffman bitstring @ 0x00008803.2, table 1, value [0xfffffffc] |
||||
*** ERROR: Bad huffman code @ 0x00008803.1 |
*** ERROR: Bad huffman code @ 0x00008803.1 |
||||
*** ERROR: Bad scan data in MCU(0,15): Chr(Cr) CSS(0,0) @ Offset 0x00008803.2 |
*** ERROR: Bad scan data in MCU(0,15): Chr(Cr) CSS(0,0) @ Offset 0x00008803.2 |
||||
MCU located at pixel=(0,240) |
MCU located at pixel=(0,240) |
||||
*** ERROR: Can't find huffman bitstring @ 0x00008803.3, table 0, value [0xfffffff8] |
*** ERROR: Can't find huffman bitstring @ 0x00008803.3, table 0, value [0xfffffff8] |
||||
*** ERROR: Bad huffman code @ 0x00008803.2 |
*** ERROR: Bad huffman code @ 0x00008803.2 |
||||
Only reported first 20 instances of this message... |
Only reported first 20 instances of this message... |
||||
|
|
||||
Compression stats: |
Compression stats: |
||||
Compression Ratio: 14.80:1 |
Compression Ratio: 14.80:1 |
||||
Bits per pixel: 1.62:1 |
Bits per pixel: 1.62:1 |
||||
|
|
||||
Huffman code histogram stats: |
Huffman code histogram stats: |
||||
Huffman Table: (Dest ID: 0, Class: DC) |
Huffman Table: (Dest ID: 0, Class: DC) |
||||
# codes of length 01 bits: 40 ( 1%) |
# codes of length 01 bits: 40 ( 1%) |
||||
# codes of length 02 bits: 202 ( 4%) |
# codes of length 02 bits: 202 ( 4%) |
||||
# codes of length 03 bits: 3515 ( 73%) |
# codes of length 03 bits: 3515 ( 73%) |
||||
# codes of length 04 bits: 423 ( 9%) |
# codes of length 04 bits: 423 ( 9%) |
||||
# codes of length 05 bits: 338 ( 7%) |
# codes of length 05 bits: 338 ( 7%) |
||||
# codes of length 06 bits: 228 ( 5%) |
# codes of length 06 bits: 228 ( 5%) |
||||
# codes of length 07 bits: 54 ( 1%) |
# codes of length 07 bits: 54 ( 1%) |
||||
# codes of length 08 bits: 0 ( 0%) |
# codes of length 08 bits: 0 ( 0%) |
||||
# codes of length 09 bits: 0 ( 0%) |
# codes of length 09 bits: 0 ( 0%) |
||||
# codes of length 10 bits: 0 ( 0%) |
# codes of length 10 bits: 0 ( 0%) |
||||
# codes of length 11 bits: 0 ( 0%) |
# codes of length 11 bits: 0 ( 0%) |
||||
# codes of length 12 bits: 0 ( 0%) |
# codes of length 12 bits: 0 ( 0%) |
||||
# codes of length 13 bits: 0 ( 0%) |
# codes of length 13 bits: 0 ( 0%) |
||||
# codes of length 14 bits: 0 ( 0%) |
# codes of length 14 bits: 0 ( 0%) |
||||
# codes of length 15 bits: 0 ( 0%) |
# codes of length 15 bits: 0 ( 0%) |
||||
# codes of length 16 bits: 0 ( 0%) |
# codes of length 16 bits: 0 ( 0%) |
||||
|
|
||||
Huffman Table: (Dest ID: 1, Class: DC) |
Huffman Table: (Dest ID: 1, Class: DC) |
||||
# codes of length 01 bits: 20 ( 1%) |
# codes of length 01 bits: 20 ( 1%) |
||||
# codes of length 02 bits: 1657 ( 69%) |
# codes of length 02 bits: 1657 ( 69%) |
||||
# codes of length 03 bits: 311 ( 13%) |
# codes of length 03 bits: 311 ( 13%) |
||||
# codes of length 04 bits: 232 ( 10%) |
# codes of length 04 bits: 232 ( 10%) |
||||
# codes of length 05 bits: 123 ( 5%) |
# codes of length 05 bits: 123 ( 5%) |
||||
# codes of length 06 bits: 49 ( 2%) |
# codes of length 06 bits: 49 ( 2%) |
||||
# codes of length 07 bits: 8 ( 0%) |
# codes of length 07 bits: 8 ( 0%) |
||||
# codes of length 08 bits: 0 ( 0%) |
# codes of length 08 bits: 0 ( 0%) |
||||
# codes of length 09 bits: 0 ( 0%) |
# codes of length 09 bits: 0 ( 0%) |
||||
# codes of length 10 bits: 0 ( 0%) |
# codes of length 10 bits: 0 ( 0%) |
||||
# codes of length 11 bits: 0 ( 0%) |
# codes of length 11 bits: 0 ( 0%) |
||||
# codes of length 12 bits: 0 ( 0%) |
# codes of length 12 bits: 0 ( 0%) |
||||
# codes of length 13 bits: 0 ( 0%) |
# codes of length 13 bits: 0 ( 0%) |
||||
# codes of length 14 bits: 0 ( 0%) |
# codes of length 14 bits: 0 ( 0%) |
||||
# codes of length 15 bits: 0 ( 0%) |
# codes of length 15 bits: 0 ( 0%) |
||||
# codes of length 16 bits: 0 ( 0%) |
# codes of length 16 bits: 0 ( 0%) |
||||
|
|
||||
Huffman Table: (Dest ID: 0, Class: AC) |
Huffman Table: (Dest ID: 0, Class: AC) |
||||
# codes of length 01 bits: 0 ( 0%) |
# codes of length 01 bits: 0 ( 0%) |
||||
# codes of length 02 bits: 32135 ( 43%) |
# codes of length 02 bits: 32135 ( 43%) |
||||
# codes of length 03 bits: 8668 ( 12%) |
# codes of length 03 bits: 8668 ( 12%) |
||||
# codes of length 04 bits: 15771 ( 21%) |
# codes of length 04 bits: 15771 ( 21%) |
||||
# codes of length 05 bits: 7559 ( 10%) |
# codes of length 05 bits: 7559 ( 10%) |
||||
# codes of length 06 bits: 2518 ( 3%) |
# codes of length 06 bits: 2518 ( 3%) |
||||
# codes of length 07 bits: 3834 ( 5%) |
# codes of length 07 bits: 3834 ( 5%) |
||||
# codes of length 08 bits: 1387 ( 2%) |
# codes of length 08 bits: 1387 ( 2%) |
||||
# codes of length 09 bits: 1122 ( 2%) |
# codes of length 09 bits: 1122 ( 2%) |
||||
# codes of length 10 bits: 562 ( 1%) |
# codes of length 10 bits: 562 ( 1%) |
||||
# codes of length 11 bits: 234 ( 0%) |
# codes of length 11 bits: 234 ( 0%) |
||||
# codes of length 12 bits: 131 ( 0%) |
# codes of length 12 bits: 131 ( 0%) |
||||
# codes of length 13 bits: 0 ( 0%) |
# codes of length 13 bits: 0 ( 0%) |
||||
# codes of length 14 bits: 0 ( 0%) |
# codes of length 14 bits: 0 ( 0%) |
||||
# codes of length 15 bits: 57 ( 0%) |
# codes of length 15 bits: 57 ( 0%) |
||||
# codes of length 16 bits: 286 ( 0%) |
# codes of length 16 bits: 286 ( 0%) |
||||
|
|
||||
Huffman Table: (Dest ID: 1, Class: AC) |
Huffman Table: (Dest ID: 1, Class: AC) |
||||
# codes of length 01 bits: 0 ( 0%) |
# codes of length 01 bits: 0 ( 0%) |
||||
# codes of length 02 bits: 4525 ( 57%) |
# codes of length 02 bits: 4525 ( 57%) |
||||
# codes of length 03 bits: 1153 ( 14%) |
# codes of length 03 bits: 1153 ( 14%) |
||||
# codes of length 04 bits: 1341 ( 17%) |
# codes of length 04 bits: 1341 ( 17%) |
||||
# codes of length 05 bits: 543 ( 7%) |
# codes of length 05 bits: 543 ( 7%) |
||||
# codes of length 06 bits: 281 ( 4%) |
# codes of length 06 bits: 281 ( 4%) |
||||
# codes of length 07 bits: 14 ( 0%) |
# codes of length 07 bits: 14 ( 0%) |
||||
# codes of length 08 bits: 93 ( 1%) |
# codes of length 08 bits: 93 ( 1%) |
||||
# codes of length 09 bits: 23 ( 0%) |
# codes of length 09 bits: 23 ( 0%) |
||||
# codes of length 10 bits: 3 ( 0%) |
# codes of length 10 bits: 3 ( 0%) |
||||
# codes of length 11 bits: 3 ( 0%) |
# codes of length 11 bits: 3 ( 0%) |
||||
# codes of length 12 bits: 0 ( 0%) |
# codes of length 12 bits: 0 ( 0%) |
||||
# codes of length 13 bits: 0 ( 0%) |
# codes of length 13 bits: 0 ( 0%) |
||||
# codes of length 14 bits: 2 ( 0%) |
# codes of length 14 bits: 2 ( 0%) |
||||
# codes of length 15 bits: 0 ( 0%) |
# codes of length 15 bits: 0 ( 0%) |
||||
# codes of length 16 bits: 0 ( 0%) |
# codes of length 16 bits: 0 ( 0%) |
||||
|
|
||||
YCC clipping in DC: |
YCC clipping in DC: |
||||
Y component: [<0= 0] [>255= 0] |
Y component: [<0= 0] [>255= 0] |
||||
Cb component: [<0= 0] [>255= 0] |
Cb component: [<0= 0] [>255= 0] |
||||
Cr component: [<0= 0] [>255= 0] |
Cr component: [<0= 0] [>255= 0] |
||||
|
|
||||
RGB clipping in DC: |
RGB clipping in DC: |
||||
R component: [<0= 0] [>255= 0] |
R component: [<0= 0] [>255= 0] |
||||
G component: [<0= 0] [>255= 0] |
G component: [<0= 0] [>255= 0] |
||||
B component: [<0= 0] [>255= 0] |
B component: [<0= 0] [>255= 0] |
||||
|
|
||||
Average Pixel Luminance (Y): |
Average Pixel Luminance (Y): |
||||
Y=[103] (range: 0..255) |
Y=[103] (range: 0..255) |
||||
|
|
||||
Brightest Pixel Search: |
Brightest Pixel Search: |
||||
YCC=[ 1014, -3, -27] RGB=[248,255,252] @ MCU[ 0, 13] |
YCC=[ 1014, -3, -27] RGB=[248,255,252] @ MCU[ 0, 13] |
||||
|
|
||||
Finished Decoding SCAN Data |
Finished Decoding SCAN Data |
||||
Number of RESTART markers decoded: 1 |
Number of RESTART markers decoded: 1 |
||||
Next position in scan buffer: Offset 0x0001210E.0 |
Next position in scan buffer: Offset 0x0001210E.0 |
||||
|
|
||||
|
|
||||
*** Skipped 10 marker pad bytes *** |
*** Skipped 10 marker pad bytes *** |
||||
*** Marker: RST# *** |
*** Marker: RST# *** |
||||
OFFSET: 0x0000880D |
OFFSET: 0x0000880D |
||||
WARNING: Restart marker [0xFFD0] detected outside scan |
WARNING: Restart marker [0xFFD0] detected outside scan |
||||
Stopping decode |
Stopping decode |
||||
Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs |
Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs |
||||
|
|
||||
*** Searching Compression Signatures *** |
*** Searching Compression Signatures *** |
||||
|
|
||||
Signature: 013BA18D5561625796E986FDBC09F846 |
Signature: 013BA18D5561625796E986FDBC09F846 |
||||
Signature (Rotated): 01AC57E12793DFA7C46C704625C5AF0F |
Signature (Rotated): 01AC57E12793DFA7C46C704625C5AF0F |
||||
File Offset: 0 bytes |
File Offset: 0 bytes |
||||
Chroma subsampling: 2x2 |
Chroma subsampling: 2x2 |
||||
EXIF Make/Model: NONE |
EXIF Make/Model: NONE |
||||
EXIF Makernotes: NONE |
EXIF Makernotes: NONE |
||||
EXIF Software: NONE |
EXIF Software: NONE |
||||
|
|
||||
Searching Compression Signatures: (3347 built-in, 0 user(*) ) |
Searching Compression Signatures: (3347 built-in, 0 user(*) ) |
||||
|
|
||||
EXIF.Make / Software EXIF.Model Quality Subsamp Match? |
EXIF.Make / Software EXIF.Model Quality Subsamp Match? |
||||
------------------------- ----------------------------------- ---------------- -------------- |
------------------------- ----------------------------------- ---------------- -------------- |
||||
CAM:[??? ] [Treo 680 ] [ ] Yes |
CAM:[??? ] [Treo 680 ] [ ] Yes |
||||
CAM:[Canon ] [Canon PowerShot Pro1 ] [fine ] No |
CAM:[Canon ] [Canon PowerShot Pro1 ] [fine ] No |
||||
CAM:[NIKON ] [E2500 ] [FINE ] No |
CAM:[NIKON ] [E2500 ] [FINE ] No |
||||
CAM:[NIKON ] [E3100 ] [FINE ] No |
CAM:[NIKON ] [E3100 ] [FINE ] No |
||||
CAM:[NIKON ] [E4500 ] [FINE ] No |
CAM:[NIKON ] [E4500 ] [FINE ] No |
||||
CAM:[NIKON ] [E5000 ] [FINE ] No |
CAM:[NIKON ] [E5000 ] [FINE ] No |
||||
CAM:[NIKON ] [E5700 ] [FINE ] No |
CAM:[NIKON ] [E5700 ] [FINE ] No |
||||
CAM:[NIKON ] [E775 ] [FINE ] No |
CAM:[NIKON ] [E775 ] [FINE ] No |
||||
CAM:[NIKON ] [E885 ] [FINE ] No |
CAM:[NIKON ] [E885 ] [FINE ] No |
||||
CAM:[OLYMPUS OPTICAL CO.,LTD ] [C3040Z ] [ ] No |
CAM:[OLYMPUS OPTICAL CO.,LTD ] [C3040Z ] [ ] No |
||||
CAM:[PENTAX ] [PENTAX Optio 550 ] [ ] No |
CAM:[PENTAX ] [PENTAX Optio 550 ] [ ] No |
||||
CAM:[Research In Motion ] [BlackBerry 9530 ] [Superfine ] Yes |
CAM:[Research In Motion ] [BlackBerry 9530 ] [Superfine ] Yes |
||||
CAM:[SEIKO EPSON CORP. ] [PhotoPC 3000Z ] [ ] No |
CAM:[SEIKO EPSON CORP. ] [PhotoPC 3000Z ] [ ] No |
||||
CAM:[SONY ] [DSC-H7 ] [ ] No |
CAM:[SONY ] [DSC-H7 ] [ ] No |
||||
CAM:[SONY ] [DSC-H9 ] [ ] No |
CAM:[SONY ] [DSC-H9 ] [ ] No |
||||
CAM:[SONY ] [DSC-S90 ] [ ] No |
CAM:[SONY ] [DSC-S90 ] [ ] No |
||||
CAM:[SONY ] [DSC-W1 ] [ ] No |
CAM:[SONY ] [DSC-W1 ] [ ] No |
||||
CAM:[SONY ] [SONY ] [ ] No |
CAM:[SONY ] [SONY ] [ ] No |
||||
SW :[ACDSee ] [ ] |
SW :[ACDSee ] [ ] |
||||
SW :[FixFoto ] [fine ] |
SW :[FixFoto ] [fine ] |
||||
SW :[IJG Library ] [090 ] |
SW :[IJG Library ] [090 ] |
||||
SW :[ZoomBrowser EX ] [high ] |
SW :[ZoomBrowser EX ] [high ] |
||||
|
|
||||
The following IJG-based editors also match this signature: |
The following IJG-based editors also match this signature: |
||||
SW :[GIMP ] [090 ] |
SW :[GIMP ] [090 ] |
||||
SW :[IrfanView ] [090 ] |
SW :[IrfanView ] [090 ] |
||||
SW :[idImager ] [090 ] |
SW :[idImager ] [090 ] |
||||
SW :[FastStone Image Viewer ] [090 ] |
SW :[FastStone Image Viewer ] [090 ] |
||||
SW :[NeatImage ] [090 ] |
SW :[NeatImage ] [090 ] |
||||
SW :[Paint.NET ] [090 ] |
SW :[Paint.NET ] [090 ] |
||||
SW :[Photomatix ] [090 ] |
SW :[Photomatix ] [090 ] |
||||
SW :[XnView ] [090 ] |
SW :[XnView ] [090 ] |
||||
|
|
||||
Based on the analysis of compression characteristics and EXIF metadata: |
Based on the analysis of compression characteristics and EXIF metadata: |
||||
|
|
||||
ASSESSMENT: Class 1 - Image is processed/edited |
ASSESSMENT: Class 1 - Image is processed/edited |
||||
|
|
||||
This may be a new software editor for the database. |
This may be a new software editor for the database. |
||||
If this file is processed, and editor doesn't appear in list above, |
If this file is processed, and editor doesn't appear in list above, |
||||
PLEASE ADD TO DATABASE with [Tools->Add Camera to DB] |
PLEASE ADD TO DATABASE with [Tools->Add Camera to DB] |
||||
|
|
||||
|
|
||||
*** Additional Info *** |
*** Additional Info *** |
||||
NOTE: Data exists after EOF, range: 0x00000000-0x00012301 (74497 bytes) |
NOTE: Data exists after EOF, range: 0x00000000-0x00012301 (74497 bytes) |
||||
|
|||||
Loading…
Reference in new issue