mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: dd3f92b3358e43e8c26e6ad974b8fd1432d3a36d Former-commit-id: e0ce0080191426e2bf6bc73afc0da56bb2545a3c Former-commit-id: ba0189d24efa44c744044a88d05204bc7afecf6eaf/merge-core
3 changed files with 281 additions and 3 deletions
@ -0,0 +1,261 @@ |
|||
|
|||
|
|||
namespace ImageProcessorCore |
|||
{ |
|||
using System.IO; |
|||
using System.Text; |
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
using ImageProcessorCore.Formats; |
|||
|
|||
/// <summary>
|
|||
/// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// The image data is always stored in RGBA format, where the red, green, blue, and
|
|||
/// alpha values are floating point numbers.
|
|||
/// </remarks>
|
|||
public abstract class GenericImage<TPacked> : ImageBase<TPacked> |
|||
where TPacked : IPackedVector |
|||
{ |
|||
/// <summary>
|
|||
/// The default horizontal resolution value (dots per inch) in x direction.
|
|||
/// <remarks>The default value is 96 dots per inch.</remarks>
|
|||
/// </summary>
|
|||
public const double DefaultHorizontalResolution = 96; |
|||
|
|||
/// <summary>
|
|||
/// The default vertical resolution value (dots per inch) in y direction.
|
|||
/// <remarks>The default value is 96 dots per inch.</remarks>
|
|||
/// </summary>
|
|||
public const double DefaultVerticalResolution = 96; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Image"/> class.
|
|||
/// </summary>
|
|||
protected GenericImage() |
|||
{ |
|||
this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Image"/> class
|
|||
/// with the height and the width of the image.
|
|||
/// </summary>
|
|||
/// <param name="width">The width of the image in pixels.</param>
|
|||
/// <param name="height">The height of the image in pixels.</param>
|
|||
protected GenericImage(int width, int height) |
|||
: base(width, height) |
|||
{ |
|||
this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Image"/> class.
|
|||
/// </summary>
|
|||
/// <param name="stream">
|
|||
/// The stream containing image information.
|
|||
/// </param>
|
|||
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="stream"/> is null.</exception>
|
|||
protected GenericImage(Stream stream) |
|||
{ |
|||
Guard.NotNull(stream, nameof(stream)); |
|||
this.Load(stream); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a list of supported image formats.
|
|||
/// </summary>
|
|||
public IReadOnlyCollection<IImageFormat> Formats { get; } = Bootstrapper.Instance.ImageFormats; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the resolution of the image in x- direction. It is defined as
|
|||
/// number of dots per inch and should be an positive value.
|
|||
/// </summary>
|
|||
/// <value>The density of the image in x- direction.</value>
|
|||
public double HorizontalResolution { get; set; } = DefaultHorizontalResolution; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the resolution of the image in y- direction. It is defined as
|
|||
/// number of dots per inch and should be an positive value.
|
|||
/// </summary>
|
|||
/// <value>The density of the image in y- direction.</value>
|
|||
public double VerticalResolution { get; set; } = DefaultVerticalResolution; |
|||
|
|||
/// <summary>
|
|||
/// Gets the width of the image in inches. It is calculated as the width of the image
|
|||
/// in pixels multiplied with the density. When the density is equals or less than zero
|
|||
/// the default value is used.
|
|||
/// </summary>
|
|||
/// <value>The width of the image in inches.</value>
|
|||
public double InchWidth |
|||
{ |
|||
get |
|||
{ |
|||
double resolution = this.HorizontalResolution; |
|||
|
|||
if (resolution <= 0) |
|||
{ |
|||
resolution = DefaultHorizontalResolution; |
|||
} |
|||
|
|||
return this.Width / resolution; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the height of the image in inches. It is calculated as the height of the image
|
|||
/// in pixels multiplied with the density. When the density is equals or less than zero
|
|||
/// the default value is used.
|
|||
/// </summary>
|
|||
/// <value>The height of the image in inches.</value>
|
|||
public double InchHeight |
|||
{ |
|||
get |
|||
{ |
|||
double resolution = this.VerticalResolution; |
|||
|
|||
if (resolution <= 0) |
|||
{ |
|||
resolution = DefaultVerticalResolution; |
|||
} |
|||
|
|||
return this.Height / resolution; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this image is animated.
|
|||
/// </summary>
|
|||
/// <value>
|
|||
/// <c>True</c> if this image is animated; otherwise, <c>false</c>.
|
|||
/// </value>
|
|||
public bool IsAnimated => this.Frames.Count > 0; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the number of times any animation is repeated.
|
|||
/// <remarks>0 means to repeat indefinitely.</remarks>
|
|||
/// </summary>
|
|||
public ushort RepeatCount { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the other frames for the animation.
|
|||
/// </summary>
|
|||
/// <value>The list of frame images.</value>
|
|||
public IList<IImageFrame<TPacked>> Frames { get; } = new List<IImageFrame<TPacked>>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the list of properties for storing meta information about this image.
|
|||
/// </summary>
|
|||
/// <value>A list of image properties.</value>
|
|||
public IList<ImageProperty> Properties { get; } = new List<ImageProperty>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the currently loaded image format.
|
|||
/// </summary>
|
|||
public IImageFormat CurrentImageFormat { get; internal set; } |
|||
|
|||
/// <summary>
|
|||
/// Saves the image to the given stream using the currently loaded image format.
|
|||
/// </summary>
|
|||
/// <param name="stream">The stream to save the image to.</param>
|
|||
/// <exception cref="ArgumentNullException">Thrown if the stream is null.</exception>
|
|||
public void Save(Stream stream) |
|||
{ |
|||
Guard.NotNull(stream, nameof(stream)); |
|||
this.CurrentImageFormat.Encoder.Encode(this, stream); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Saves the image to the given stream using the given image format.
|
|||
/// </summary>
|
|||
/// <param name="stream">The stream to save the image to.</param>
|
|||
/// <param name="format">The format to save the image as.</param>
|
|||
/// <exception cref="ArgumentNullException">Thrown if the stream is null.</exception>
|
|||
public void Save(Stream stream, IImageFormat format) |
|||
{ |
|||
Guard.NotNull(stream, nameof(stream)); |
|||
format.Encoder.Encode(this, stream); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Saves the image to the given stream using the given image encoder.
|
|||
/// </summary>
|
|||
/// <param name="stream">The stream to save the image to.</param>
|
|||
/// <param name="encoder">The encoder to save the image with.</param>
|
|||
/// <exception cref="ArgumentNullException">Thrown if the stream is null.</exception>
|
|||
public void Save(Stream stream, IImageEncoder encoder) |
|||
{ |
|||
Guard.NotNull(stream, nameof(stream)); |
|||
encoder.Encode(this, stream); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a Base64 encoded string from the given image.
|
|||
/// </summary>
|
|||
/// <example>data:image/gif;base64,R0lGODlhAQABAIABAEdJRgAAACwAAAAAAQABAAACAkQBAA==</example>
|
|||
/// <returns>The <see cref="string"/></returns>
|
|||
public override string ToString() |
|||
{ |
|||
using (MemoryStream stream = new MemoryStream()) |
|||
{ |
|||
this.Save(stream); |
|||
stream.Flush(); |
|||
return $"data:{this.CurrentImageFormat.Encoder.MimeType};base64,{Convert.ToBase64String(stream.ToArray())}"; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Loads the image from the given stream.
|
|||
/// </summary>
|
|||
/// <param name="stream">The stream containing image information.</param>
|
|||
/// <exception cref="NotSupportedException">
|
|||
/// Thrown if the stream is not readable nor seekable.
|
|||
/// </exception>
|
|||
private void Load(Stream stream) |
|||
{ |
|||
if (!this.Formats.Any()) { return; } |
|||
|
|||
if (!stream.CanRead) |
|||
{ |
|||
throw new NotSupportedException("Cannot read from the stream."); |
|||
} |
|||
|
|||
if (!stream.CanSeek) |
|||
{ |
|||
throw new NotSupportedException("The stream does not support seeking."); |
|||
} |
|||
|
|||
int maxHeaderSize = this.Formats.Max(x => x.Decoder.HeaderSize); |
|||
if (maxHeaderSize > 0) |
|||
{ |
|||
byte[] header = new byte[maxHeaderSize]; |
|||
|
|||
stream.Position = 0; |
|||
stream.Read(header, 0, maxHeaderSize); |
|||
stream.Position = 0; |
|||
|
|||
IImageFormat format = this.Formats.FirstOrDefault(x => x.Decoder.IsSupportedFileFormat(header)); |
|||
if (format != null) |
|||
{ |
|||
format.Decoder.Decode(this, stream); |
|||
this.CurrentImageFormat = format; |
|||
return; |
|||
} |
|||
} |
|||
|
|||
StringBuilder stringBuilder = new StringBuilder(); |
|||
stringBuilder.AppendLine("Image cannot be loaded. Available formats:"); |
|||
|
|||
foreach (IImageFormat format in this.Formats) |
|||
{ |
|||
stringBuilder.AppendLine("-" + format); |
|||
} |
|||
|
|||
throw new NotSupportedException(stringBuilder.ToString()); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue