Browse Source

Merge branch 'master' into antonfirsov/reduce-pool-size

af/merge-core
Anton Firsov 8 years ago
committed by GitHub
parent
commit
e3ee64c700
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      ImageSharp.sln.DotSettings
  2. 12
      src/ImageSharp/Formats/Bmp/BmpDecoder.cs
  3. 134
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  4. 17
      src/ImageSharp/Formats/Gif/GifDecoder.cs
  5. 177
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  6. 5
      src/ImageSharp/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs
  7. 2
      src/ImageSharp/Formats/IImageDecoder.cs
  8. 21
      src/ImageSharp/Formats/IImageInfoDetector.cs
  9. 13
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs
  10. 25
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
  11. 14
      src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
  12. 25
      src/ImageSharp/Formats/PixelTypeInfo.cs
  13. 11
      src/ImageSharp/Formats/Png/PngDecoder.cs
  14. 93
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  15. 12
      src/ImageSharp/Image/IImage.cs
  16. 35
      src/ImageSharp/Image/IImageInfo.cs
  17. 14
      src/ImageSharp/Image/Image.Decode.cs
  18. 31
      src/ImageSharp/Image/Image.FromStream.cs
  19. 41
      src/ImageSharp/Image/ImageInfo.cs
  20. 21
      src/ImageSharp/Image/Image{TPixel}.cs
  21. 236
      src/ImageSharp/ImageSharp.csproj
  22. 19
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
  23. 59
      tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
  24. 15
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  25. 16
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  26. 17
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
  27. 7
      tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs
  28. 6
      tests/ImageSharp.Tests/Image/ImageLoadTests.cs
  29. 1
      tests/ImageSharp.Tests/ImageSharp.Tests.csproj
  30. 2
      tests/ImageSharp.Tests/TestFileSystem.cs
  31. 10
      tests/ImageSharp.Tests/TestFormat.cs
  32. 3
      tests/ImageSharp.Tests/TestImages.cs
  33. 24
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
  34. 3
      tests/Images/Input/Png/bpp1.png
  35. 3
      tests/Images/Input/Png/gray_4bpp.png
  36. 3
      tests/Images/Input/Png/palette-8bpp.png

10
ImageSharp.sln.DotSettings

@ -38,10 +38,15 @@
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE_SHIFTED_2</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CONSTRUCTOR_INITIALIZER_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">ALWAYS</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_TYPE_CONSTRAINTS_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_EMBEDDED_STATEMENT_STYLE/@EntryValue">ON_SINGLE_LINE</s:String>
@ -370,8 +375,13 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>

12
src/ImageSharp/Formats/Bmp/BmpDecoder.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.IO;
using SixLabors.ImageSharp.PixelFormats;
@ -23,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Formats will be supported in a later releases. We advise always
/// to use only 24 Bit Windows bitmaps.
/// </remarks>
public sealed class BmpDecoder : IImageDecoder, IBmpDecoderOptions
public sealed class BmpDecoder : IImageDecoder, IBmpDecoderOptions, IImageInfoDetector
{
/// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
@ -34,5 +32,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp
return new BmpDecoderCore(configuration, this).Decode<TPixel>(stream);
}
/// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");
return new BmpDecoderCore(configuration, this).Identify(stream);
}
}
}

134
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -5,6 +5,7 @@ using System;
using System.IO;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Bmp
@ -94,62 +95,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public Image<TPixel> Decode<TPixel>(Stream stream)
where TPixel : struct, IPixel<TPixel>
{
this.currentStream = stream;
try
{
this.ReadFileHeader();
this.ReadInfoHeader();
// see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517
// If the height is negative, then this is a Windows bitmap whose origin
// is the upper-left corner and not the lower-left.The inverted flag
// indicates a lower-left origin.Our code will be outputting an
// upper-left origin pixel array.
bool inverted = false;
if (this.infoHeader.Height < 0)
{
inverted = true;
this.infoHeader.Height = -this.infoHeader.Height;
}
int colorMapSize = -1;
if (this.infoHeader.ClrUsed == 0)
{
if (this.infoHeader.BitsPerPixel == 1 ||
this.infoHeader.BitsPerPixel == 4 ||
this.infoHeader.BitsPerPixel == 8)
{
colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4;
}
}
else
{
colorMapSize = this.infoHeader.ClrUsed * 4;
}
byte[] palette = null;
if (colorMapSize > 0)
{
// 256 * 4
if (colorMapSize > 1024)
{
throw new ImageFormatException($"Invalid bmp colormap size '{colorMapSize}'");
}
palette = new byte[colorMapSize];
this.currentStream.Read(palette, 0, colorMapSize);
}
if (this.infoHeader.Width > int.MaxValue || this.infoHeader.Height > int.MaxValue)
{
throw new ArgumentOutOfRangeException(
$"The input bitmap '{this.infoHeader.Width}x{this.infoHeader.Height}' is "
+ $"bigger then the max allowed size '{int.MaxValue}x{int.MaxValue}'");
}
this.ReadImageHeaders(stream, out bool inverted, out byte[] palette);
var image = new Image<TPixel>(this.configuration, this.infoHeader.Width, this.infoHeader.Height);
using (PixelAccessor<TPixel> pixels = image.Lock())
@ -192,6 +140,16 @@ namespace SixLabors.ImageSharp.Formats.Bmp
}
}
/// <summary>
/// Reads the raw image information from the specified stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
public IImageInfo Identify(Stream stream)
{
this.ReadImageHeaders(stream, out _, out _);
return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, new ImageMetaData());
}
/// <summary>
/// Returns the y- value based on the given height.
/// </summary>
@ -624,5 +582,73 @@ namespace SixLabors.ImageSharp.Formats.Bmp
Offset = BitConverter.ToInt32(data, 10)
};
}
/// <summary>
/// Reads the <see cref="BmpFileHeader"/> and <see cref="BmpInfoHeader"/> from the stream and sets the corresponding fields.
/// </summary>
private void ReadImageHeaders(Stream stream, out bool inverted, out byte[] palette)
{
this.currentStream = stream;
try
{
this.ReadFileHeader();
this.ReadInfoHeader();
// see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517
// If the height is negative, then this is a Windows bitmap whose origin
// is the upper-left corner and not the lower-left.The inverted flag
// indicates a lower-left origin.Our code will be outputting an
// upper-left origin pixel array.
inverted = false;
if (this.infoHeader.Height < 0)
{
inverted = true;
this.infoHeader.Height = -this.infoHeader.Height;
}
int colorMapSize = -1;
if (this.infoHeader.ClrUsed == 0)
{
if (this.infoHeader.BitsPerPixel == 1 ||
this.infoHeader.BitsPerPixel == 4 ||
this.infoHeader.BitsPerPixel == 8)
{
colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4;
}
}
else
{
colorMapSize = this.infoHeader.ClrUsed * 4;
}
palette = null;
if (colorMapSize > 0)
{
// 256 * 4
if (colorMapSize > 1024)
{
throw new ImageFormatException($"Invalid bmp colormap size '{colorMapSize}'");
}
palette = new byte[colorMapSize];
this.currentStream.Read(palette, 0, colorMapSize);
}
if (this.infoHeader.Width > int.MaxValue || this.infoHeader.Height > int.MaxValue)
{
throw new ArgumentOutOfRangeException(
$"The input bitmap '{this.infoHeader.Width}x{this.infoHeader.Height}' is "
+ $"bigger then the max allowed size '{int.MaxValue}x{int.MaxValue}'");
}
}
catch (IndexOutOfRangeException e)
{
throw new ImageFormatException("Bitmap does not have a valid format.", e);
}
}
}
}

17
src/ImageSharp/Formats/Gif/GifDecoder.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SixLabors.ImageSharp.PixelFormats;
@ -12,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Decoder for generating an image out of a gif encoded stream.
/// </summary>
public sealed class GifDecoder : IImageDecoder, IGifDecoderOptions
public sealed class GifDecoder : IImageDecoder, IGifDecoderOptions, IImageInfoDetector
{
/// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
@ -33,8 +31,17 @@ namespace SixLabors.ImageSharp.Formats.Gif
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
where TPixel : struct, IPixel<TPixel>
{
var decoder = new GifDecoderCore<TPixel>(configuration, this);
return decoder.Decode(stream);
var decoder = new GifDecoderCore(configuration, this);
return decoder.Decode<TPixel>(stream);
}
/// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");
var decoder = new GifDecoderCore(configuration, this);
return decoder.Identify(stream);
}
}
}

177
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -17,9 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Performs the gif decoding operation.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal sealed class GifDecoderCore<TPixel>
where TPixel : struct, IPixel<TPixel>
internal sealed class GifDecoderCore
{
/// <summary>
/// The temp buffer used to reduce allocations.
@ -46,11 +44,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary>
private int globalColorTableLength;
/// <summary>
/// The previous frame.
/// </summary>
private ImageFrame<TPixel> previousFrame;
/// <summary>
/// The area to restore.
/// </summary>
@ -72,12 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
private ImageMetaData metaData;
/// <summary>
/// The image to decode the information to.
/// </summary>
private Image<TPixel> image;
/// <summary>
/// Initializes a new instance of the <see cref="GifDecoderCore{TPixel}"/> class.
/// Initializes a new instance of the <see cref="GifDecoderCore"/> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="options">The decoder options.</param>
@ -107,28 +95,17 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Decodes the stream to the image.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="stream">The stream containing image data. </param>
/// <returns>The decoded image</returns>
public Image<TPixel> Decode(Stream stream)
public Image<TPixel> Decode<TPixel>(Stream stream)
where TPixel : struct, IPixel<TPixel>
{
Image<TPixel> image = null;
ImageFrame<TPixel> previousFrame = null;
try
{
this.metaData = new ImageMetaData();
this.currentStream = stream;
// Skip the identifier
this.currentStream.Skip(6);
this.ReadLogicalScreenDescriptor();
if (this.logicalScreenDescriptor.GlobalColorTableFlag)
{
this.globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
this.globalColorTable = Buffer<byte>.CreateClean(this.globalColorTableLength);
// Read the global color table from the stream
stream.Read(this.globalColorTable.Array, 0, this.globalColorTableLength);
}
this.ReadLogicalScreenDescriptorAndGlobalColorTable(stream);
// Loop though the respective gif parts and read the data.
int nextFlag = stream.ReadByte();
@ -136,12 +113,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
if (nextFlag == GifConstants.ImageLabel)
{
if (this.previousFrame != null && this.DecodingMode == FrameDecodingMode.First)
if (previousFrame != null && this.DecodingMode == FrameDecodingMode.First)
{
break;
}
this.ReadFrame();
this.ReadFrame(ref image, ref previousFrame);
}
else if (nextFlag == GifConstants.ExtensionIntroducer)
{
@ -184,7 +161,72 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.globalColorTable?.Dispose();
}
return this.image;
return image;
}
/// <summary>
/// Reads the raw image information from the specified stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
public IImageInfo Identify(Stream stream)
{
try
{
this.ReadLogicalScreenDescriptorAndGlobalColorTable(stream);
// Loop though the respective gif parts and read the data.
int nextFlag = stream.ReadByte();
while (nextFlag != GifConstants.Terminator)
{
if (nextFlag == GifConstants.ImageLabel)
{
// Skip image block
this.Skip(0);
}
else if (nextFlag == GifConstants.ExtensionIntroducer)
{
int label = stream.ReadByte();
switch (label)
{
case GifConstants.GraphicControlLabel:
// Skip graphic control extension block
this.Skip(0);
break;
case GifConstants.CommentLabel:
this.ReadComments();
break;
case GifConstants.ApplicationExtensionLabel:
// The application extension length should be 11 but we've got test images that incorrectly
// set this to 252.
int appLength = stream.ReadByte();
this.Skip(appLength); // No need to read.
break;
case GifConstants.PlainTextLabel:
int plainLength = stream.ReadByte();
this.Skip(plainLength); // Not supported by any known decoder.
break;
}
}
else if (nextFlag == GifConstants.EndIntroducer)
{
break;
}
nextFlag = stream.ReadByte();
if (nextFlag == -1)
{
break;
}
}
}
finally
{
this.globalColorTable?.Dispose();
}
return new ImageInfo(new PixelTypeInfo(this.logicalScreenDescriptor.BitsPerPixel), this.logicalScreenDescriptor.Width, this.logicalScreenDescriptor.Height, this.metaData);
}
/// <summary>
@ -242,6 +284,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
Width = BitConverter.ToInt16(this.buffer, 0),
Height = BitConverter.ToInt16(this.buffer, 2),
BitsPerPixel = (this.buffer[4] & 0x07) + 1, // The lowest 3 bits represent the bit depth minus 1
BackgroundColorIndex = this.buffer[5],
PixelAspectRatio = this.buffer[6],
GlobalColorTableFlag = ((packed & 0x80) >> 7) == 1,
@ -308,7 +351,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Reads an individual gif frame.
/// </summary>
private void ReadFrame()
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The image to decode the information to.</param>
/// <param name="previousFrame">The previous frame.</param>
private void ReadFrame<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPixel> previousFrame)
where TPixel : struct, IPixel<TPixel>
{
GifImageDescriptor imageDescriptor = this.ReadImageDescriptor();
@ -327,7 +374,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
indices = Buffer<byte>.CreateClean(imageDescriptor.Width * imageDescriptor.Height);
this.ReadFrameIndices(imageDescriptor, indices);
this.ReadFrameColors(indices, localColorTable ?? this.globalColorTable, imageDescriptor);
this.ReadFrameColors(ref image, ref previousFrame, indices, localColorTable ?? this.globalColorTable, imageDescriptor);
// Skip any remaining blocks
this.Skip(0);
@ -357,10 +404,14 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Reads the frames colors, mapping indices to colors.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The image to decode the information to.</param>
/// <param name="previousFrame">The previous frame.</param>
/// <param name="indices">The indexed pixels.</param>
/// <param name="colorTable">The color table containing the available colors.</param>
/// <param name="descriptor">The <see cref="GifImageDescriptor"/></param>
private void ReadFrameColors(Span<byte> indices, Span<byte> colorTable, GifImageDescriptor descriptor)
private void ReadFrameColors<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPixel> previousFrame, Span<byte> indices, Span<byte> colorTable, GifImageDescriptor descriptor)
where TPixel : struct, IPixel<TPixel>
{
int imageWidth = this.logicalScreenDescriptor.Width;
int imageHeight = this.logicalScreenDescriptor.Height;
@ -371,30 +422,30 @@ namespace SixLabors.ImageSharp.Formats.Gif
ImageFrame<TPixel> imageFrame;
if (this.previousFrame == null)
if (previousFrame == null)
{
// This initializes the image to become fully transparent because the alpha channel is zero.
this.image = new Image<TPixel>(this.configuration, imageWidth, imageHeight, this.metaData);
image = new Image<TPixel>(this.configuration, imageWidth, imageHeight, this.metaData);
this.SetFrameMetaData(this.image.Frames.RootFrame.MetaData);
this.SetFrameMetaData(image.Frames.RootFrame.MetaData);
imageFrame = this.image.Frames.RootFrame;
imageFrame = image.Frames.RootFrame;
}
else
{
if (this.graphicsControlExtension != null &&
this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
{
prevFrame = this.previousFrame;
prevFrame = previousFrame;
}
currentFrame = this.image.Frames.AddFrame(this.previousFrame); // This clones the frame and adds it the collection
currentFrame = image.Frames.AddFrame(previousFrame); // This clones the frame and adds it the collection
this.SetFrameMetaData(currentFrame.MetaData);
imageFrame = currentFrame;
this.RestoreToBackground(imageFrame);
this.RestoreToBackground(imageFrame, image.Width, image.Height);
}
int i = 0;
@ -466,11 +517,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (prevFrame != null)
{
this.previousFrame = prevFrame;
previousFrame = prevFrame;
return;
}
this.previousFrame = currentFrame ?? this.image.Frames.RootFrame;
previousFrame = currentFrame ?? image.Frames.RootFrame;
if (this.graphicsControlExtension != null &&
this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground)
@ -482,8 +533,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Restores the current frame area to the background.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="frame">The frame.</param>
private void RestoreToBackground(ImageFrame<TPixel> frame)
/// <param name="imageWidth">Width of the image.</param>
/// <param name="imageHeight">Height of the image.</param>
private void RestoreToBackground<TPixel>(ImageFrame<TPixel> frame, int imageWidth, int imageHeight)
where TPixel : struct, IPixel<TPixel>
{
if (this.restoreArea == null)
{
@ -491,8 +546,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
// Optimization for when the size of the frame is the same as the image size.
if (this.restoreArea.Value.Width == this.image.Width &&
this.restoreArea.Value.Height == this.image.Height)
if (this.restoreArea.Value.Width == imageWidth &&
this.restoreArea.Value.Height == imageHeight)
{
using (PixelAccessor<TPixel> pixelAccessor = frame.Lock())
{
@ -533,5 +588,29 @@ namespace SixLabors.ImageSharp.Formats.Gif
meta.DisposalMethod = this.graphicsControlExtension.DisposalMethod;
}
}
/// <summary>
/// Reads the logical screen descriptor and global color table blocks
/// </summary>
/// <param name="stream">The stream containing image data. </param>
private void ReadLogicalScreenDescriptorAndGlobalColorTable(Stream stream)
{
this.metaData = new ImageMetaData();
this.currentStream = stream;
// Skip the identifier
this.currentStream.Skip(6);
this.ReadLogicalScreenDescriptor();
if (this.logicalScreenDescriptor.GlobalColorTableFlag)
{
this.globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
this.globalColorTable = Buffer<byte>.CreateClean(this.globalColorTableLength);
// Read the global color table from the stream
stream.Read(this.globalColorTable.Array, 0, this.globalColorTableLength);
}
}
}
}

5
src/ImageSharp/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs

@ -22,6 +22,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary>
public short Height { get; set; }
/// <summary>
/// Gets or sets the color depth, in number of bits per pixel.
/// </summary>
public int BitsPerPixel { get; set; }
/// <summary>
/// Gets or sets the index at the Global Color Table for the Background Color.
/// The Background Color is the color used for those

2
src/ImageSharp/Formats/IImageDecoder.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.IO;
using SixLabors.ImageSharp.PixelFormats;

21
src/ImageSharp/Formats/IImageInfoDetector.cs

@ -0,0 +1,21 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.IO;
namespace SixLabors.ImageSharp.Formats
{
/// <summary>
/// Encapsulates methods used for detecting the raw image information without fully decoding it.
/// </summary>
public interface IImageInfoDetector
{
/// <summary>
/// Reads the raw image information from the specified stream.
/// </summary>
/// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>The <see cref="PixelTypeInfo"/> object</returns>
IImageInfo Identify(Configuration configuration, Stream stream);
}
}

13
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
/// <summary>
/// Image decoder for generating an image out of a jpg stream.
/// </summary>
internal sealed class OrigJpegDecoder : IImageDecoder, IJpegDecoderOptions
internal sealed class OrigJpegDecoder : IImageDecoder, IJpegDecoderOptions, IImageInfoDetector
{
/// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
@ -27,5 +27,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
return decoder.Decode<TPixel>(stream);
}
}
/// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");
using (var decoder = new OrigJpegDecoderCore(configuration, this))
{
return decoder.Identify(stream);
}
}
}
}

25
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs

@ -31,6 +31,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
/// </summary>
public const int MaxTq = 3;
/// <summary>
/// The only supported precision
/// </summary>
public const int SupportedPrecision = 8;
// Complex value type field + mutable + available to other classes = the field MUST NOT be private :P
#pragma warning disable SA1401 // FieldsMustBePrivate
@ -122,6 +127,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
IEnumerable<IJpegComponent> IRawJpegData.Components => this.Components;
/// <summary>
/// Gets the color depth, in number of bits per pixel.
/// </summary>
public int BitsPerPixel => this.ComponentCount * SupportedPrecision;
/// <summary>
/// Gets the image height
/// </summary>
@ -173,7 +183,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
public ImageMetaData MetaData { get; private set; }
/// <summary>
/// Decodes the image from the specified <see cref="Stream"/> and sets
/// Decodes the image from the specified <see cref="Stream"/> and sets
/// the data to image.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
@ -187,6 +197,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
return this.PostProcessIntoImage<TPixel>();
}
/// <summary>
/// Reads the raw image information from the specified stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
public IImageInfo Identify(Stream stream)
{
this.ParseStream(stream, true);
return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData);
}
/// <inheritdoc />
public void Dispose()
{
@ -627,7 +648,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
this.InputProcessor.ReadFull(this.Temp, 0, remaining);
// We only support 8-bit precision.
if (this.Temp[0] != 8)
if (this.Temp[0] != SupportedPrecision)
{
throw new ImageFormatException("Only 8-Bit precision supported.");
}

14
src/ImageSharp/Formats/Jpeg/JpegDecoder.cs

@ -4,7 +4,6 @@
using System.IO;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort;
using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Jpeg
@ -12,7 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <summary>
/// Image decoder for generating an image out of a jpg stream.
/// </summary>
public sealed class JpegDecoder : IImageDecoder, IJpegDecoderOptions
public sealed class JpegDecoder : IImageDecoder, IJpegDecoderOptions, IImageInfoDetector
{
/// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
@ -30,5 +29,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
return decoder.Decode<TPixel>(stream);
}
}
/// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");
using (var decoder = new OrigJpegDecoderCore(configuration, this))
{
return decoder.Identify(stream);
}
}
}
}

25
src/ImageSharp/Formats/PixelTypeInfo.cs

@ -0,0 +1,25 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats
{
/// <summary>
/// Contains information about the pixels that make up an images visual data.
/// </summary>
public class PixelTypeInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="PixelTypeInfo"/> class.
/// </summary>
/// <param name="bitsPerPixel">Color depth, in number of bits per pixel.</param>
internal PixelTypeInfo(int bitsPerPixel)
{
this.BitsPerPixel = bitsPerPixel;
}
/// <summary>
/// Gets color depth, in number of bits per pixel.
/// </summary>
public int BitsPerPixel { get; }
}
}

11
src/ImageSharp/Formats/Png/PngDecoder.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SixLabors.ImageSharp.PixelFormats;
@ -29,7 +27,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// </list>
/// </para>
/// </remarks>
public sealed class PngDecoder : IImageDecoder, IPngDecoderOptions
public sealed class PngDecoder : IImageDecoder, IPngDecoderOptions, IImageInfoDetector
{
/// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
@ -54,5 +52,12 @@ namespace SixLabors.ImageSharp.Formats.Png
var decoder = new PngDecoderCore(configuration, this);
return decoder.Decode<TPixel>(stream);
}
/// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream)
{
var decoder = new PngDecoderCore(configuration, this);
return decoder.Identify(stream);
}
}
}

93
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -237,7 +237,7 @@ namespace SixLabors.ImageSharp.Formats.Png
deframeStream.AllocateNewBytes(currentChunk.Length);
this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame);
stream.Read(this.crcBuffer, 0, 4);
this.currentStream.Read(this.crcBuffer, 0, 4);
break;
case PngChunkTypes.Palette:
byte[] pal = new byte[currentChunk.Length];
@ -278,6 +278,66 @@ namespace SixLabors.ImageSharp.Formats.Png
}
}
/// <summary>
/// Reads the raw image information from the specified stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
public IImageInfo Identify(Stream stream)
{
var metadata = new ImageMetaData();
this.currentStream = stream;
this.currentStream.Skip(8);
try
{
PngChunk currentChunk;
while (!this.isEndChunkReached && (currentChunk = this.ReadChunk()) != null)
{
try
{
switch (currentChunk.Type)
{
case PngChunkTypes.Header:
this.ReadHeaderChunk(currentChunk.Data);
this.ValidateHeader();
break;
case PngChunkTypes.Physical:
this.ReadPhysicalChunk(metadata, currentChunk.Data);
break;
case PngChunkTypes.Data:
this.SkipChunkDataAndCrc(currentChunk);
break;
case PngChunkTypes.Text:
this.ReadTextChunk(metadata, currentChunk.Data, currentChunk.Length);
break;
case PngChunkTypes.End:
this.isEndChunkReached = true;
break;
}
}
finally
{
// Data is rented in ReadChunkData()
if (currentChunk.Data != null)
{
ArrayPool<byte>.Shared.Return(currentChunk.Data);
}
}
}
}
finally
{
this.scanline?.Dispose();
this.previousScanline?.Dispose();
}
if (this.header == null)
{
throw new ImageFormatException("PNG Image does not contain a header chunk");
}
return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata);
}
/// <summary>
/// Converts a byte array to a new array where each value in the original array is represented by the specified number of bits.
/// </summary>
@ -379,6 +439,28 @@ namespace SixLabors.ImageSharp.Formats.Png
this.scanline = Buffer<byte>.CreateClean(this.bytesPerScanline);
}
/// <summary>
/// Calculates the correct number of bits per pixel for the given color type.
/// </summary>
/// <returns>The <see cref="int"/></returns>
private int CalculateBitsPerPixel()
{
switch (this.pngColorType)
{
case PngColorType.Grayscale:
case PngColorType.Palette:
return this.header.BitDepth;
case PngColorType.GrayscaleWithAlpha:
return this.header.BitDepth * 2;
case PngColorType.Rgb:
return this.header.BitDepth * 3;
case PngColorType.RgbWithAlpha:
return this.header.BitDepth * 4;
default:
throw new NotSupportedException("Unsupported PNG color type");
}
}
/// <summary>
/// Calculates the correct number of bytes per pixel for the given color type.
/// </summary>
@ -1181,6 +1263,15 @@ namespace SixLabors.ImageSharp.Formats.Png
}
}
/// <summary>
/// Skips the chunk data and the cycle redundancy chunk read from the data.
/// </summary>
private void SkipChunkDataAndCrc(PngChunk chunk)
{
this.currentStream.Skip(chunk.Length);
this.currentStream.Skip(4);
}
/// <summary>
/// Reads the chunk data from the stream.
/// </summary>

12
src/ImageSharp/Image/IImage.cs

@ -0,0 +1,12 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp
{
/// <summary>
/// Encapsulates the properties and methods that describe an image.
/// </summary>
public interface IImage : IImageInfo
{
}
}

35
src/ImageSharp/Image/IImageInfo.cs

@ -0,0 +1,35 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.MetaData;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Encapsulates properties that descibe basic image information including dimensions, pixel type information
/// and additional metadata
/// </summary>
public interface IImageInfo
{
/// <summary>
/// Gets information about the image pixels.
/// </summary>
PixelTypeInfo PixelType { get; }
/// <summary>
/// Gets the width.
/// </summary>
int Width { get; }
/// <summary>
/// Gets the height.
/// </summary>
int Height { get; }
/// <summary>
/// Gets the metadata of the image.
/// </summary>
ImageMetaData MetaData { get; }
}
}

14
src/ImageSharp/Image/Image.Decode.cs

@ -79,5 +79,19 @@ namespace SixLabors.ImageSharp
Image<TPixel> img = decoder.Decode<TPixel>(config, stream);
return (img, format);
}
/// <summary>
/// Reads the raw image information from the specified stream.
/// </summary>
/// <param name="stream">The stream.</param>
/// <param name="config">the configuration.</param>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
private static IImageInfo InternalIdentity(Stream stream, Configuration config)
{
var detector = DiscoverDecoder(stream, config, out IImageFormat _) as IImageInfoDetector;
return detector?.Identify(config, stream);
}
}
}

31
src/ImageSharp/Image/Image.FromStream.cs

@ -36,6 +36,37 @@ namespace SixLabors.ImageSharp
return WithSeekableStream(stream, s => InternalDetectFormat(s, config ?? Configuration.Default));
}
/// <summary>
/// By reading the header on the provided stream this reads the raw image information.
/// </summary>
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(Stream stream)
{
return Identify(null, stream);
}
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="stream">The image stream to read the information from.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Configuration config, Stream stream)
{
return WithSeekableStream(stream, s => InternalIdentity(s, config ?? Configuration.Default));
}
/// <summary>
/// Create a new instance of the <see cref="Image{Rgba32}"/> class from the given stream.
/// </summary>

41
src/ImageSharp/Image/ImageInfo.cs

@ -0,0 +1,41 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.MetaData;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Contains information about the image including dimensions, pixel type information and additional metadata
/// </summary>
internal sealed class ImageInfo : IImageInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageInfo"/> class.
/// </summary>
/// <param name="pixelType">The image pixel type information.</param>
/// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param>
/// <param name="metaData">The images metadata.</param>
public ImageInfo(PixelTypeInfo pixelType, int width, int height, ImageMetaData metaData)
{
this.PixelType = pixelType;
this.Width = width;
this.Height = height;
this.MetaData = metaData;
}
/// <inheritdoc />
public PixelTypeInfo PixelType { get; }
/// <inheritdoc />
public int Width { get; }
/// <inheritdoc />
public int Height { get; }
/// <inheritdoc />
public ImageMetaData MetaData { get; }
}
}

21
src/ImageSharp/Image/Image{TPixel}.cs

@ -5,9 +5,9 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp
/// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
public sealed partial class Image<TPixel> : IDisposable, IConfigurable
public sealed partial class Image<TPixel> : IImage, IDisposable, IConfigurable
where TPixel : struct, IPixel<TPixel>
{
private Configuration configuration;
@ -61,6 +61,7 @@ namespace SixLabors.ImageSharp
internal Image(Configuration configuration, int width, int height, ImageMetaData metadata)
{
this.configuration = configuration ?? Configuration.Default;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8);
this.MetaData = metadata ?? new ImageMetaData();
this.frames = new ImageFrameCollection<TPixel>(this, width, height);
}
@ -75,6 +76,7 @@ namespace SixLabors.ImageSharp
internal Image(Configuration configuration, ImageMetaData metadata, IEnumerable<ImageFrame<TPixel>> frames)
{
this.configuration = configuration ?? Configuration.Default;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8);
this.MetaData = metadata ?? new ImageMetaData();
this.frames = new ImageFrameCollection<TPixel>(this, frames);
@ -85,19 +87,16 @@ namespace SixLabors.ImageSharp
/// </summary>
Configuration IConfigurable.Configuration => this.configuration;
/// <summary>
/// Gets the width.
/// </summary>
/// <inheritdoc/>
public PixelTypeInfo PixelType { get; }
/// <inheritdoc/>
public int Width => this.frames.RootFrame.Width;
/// <summary>
/// Gets the height.
/// </summary>
/// <inheritdoc/>
public int Height => this.frames.RootFrame.Height;
/// <summary>
/// Gets the meta data of the image.
/// </summary>
/// <inheritdoc/>
public ImageMetaData MetaData { get; private set; } = new ImageMetaData();
/// <summary>

236
src/ImageSharp/ImageSharp.csproj

@ -1,120 +1,120 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>A cross-platform library for the processing of image files; written in C#</Description>
<AssemblyTitle>SixLabors.ImageSharp</AssemblyTitle>
<VersionPrefix Condition="$(packageversion) != ''">$(packageversion)</VersionPrefix>
<VersionPrefix Condition="$(packageversion) == ''">0.0.1</VersionPrefix>
<Authors>Six Labors and contributors</Authors>
<TargetFrameworks>netstandard1.1;netstandard1.3;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>SixLabors.ImageSharp</AssemblyName>
<PackageId>SixLabors.ImageSharp</PackageId>
<PackageTags>Image Resize Crop Gif Jpg Jpeg Bitmap Png Core</PackageTags>
<PackageIconUrl>https://raw.githubusercontent.com/SixLabors/ImageSharp/master/build/icons/imagesharp-logo-128.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/SixLabors/ImageSharp</PackageProjectUrl>
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/SixLabors/ImageSharp</RepositoryUrl>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateNeutralResourcesLanguageAttribute>false</GenerateNeutralResourcesLanguageAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<DebugType Condition="$(codecov) != ''">full</DebugType>
<DebugType Condition="$(codecov) == ''">portable</DebugType>
<DebugSymbols>True</DebugSymbols>
<Features>IOperation</Features>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Shared\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SixLabors.Core" Version="1.0.0-beta0004" />
<AdditionalFiles Include="..\..\stylecop.json" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta004">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Buffers" Version="4.4.0" />
<PackageReference Include="System.Memory" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.1' OR '$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
</ItemGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>..\..\ImageSharp.ruleset</CodeAnalysisRuleSet>
<RootNamespace>SixLabors.ImageSharp</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<None Update="Formats\Jpeg\Common\Block8x8F.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Block8x8F.Generated.cs</LastGenOutput>
</None>
<None Update="Formats\Jpeg\Components\Block8x8F.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Block8x8F.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\PixelOperations{TPixel}.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>PixelOperations{TPixel}.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Rgba32.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Rgba32.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\PixelBlenders\PorterDuffFunctions.Generated.tt">
<LastGenOutput>PorterDuffFunctions.Generated.cs</LastGenOutput>
<Generator>TextTemplatingFileGenerator</Generator>
</None>
<None Update="PixelFormats\PixelBlenders\DefaultPixelBlenders.Generated.tt">
<LastGenOutput>DefaultPixelBlenders.Generated.cs</LastGenOutput>
<Generator>TextTemplatingFileGenerator</Generator>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Formats\Jpeg\Common\Block8x8F.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Block8x8F.Generated.tt</DependentUpon>
</Compile>
<Compile Update="Formats\Jpeg\Components\Block8x8F.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Block8x8F.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\PixelOperations{TPixel}.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>PixelOperations{TPixel}.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Rgba32.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Rgba32.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\PixelBlenders\DefaultPixelBlenders.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>DefaultPixelBlenders.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\PixelBlenders\PorterDuffFunctions.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>PorterDuffFunctions.Generated.tt</DependentUpon>
</Compile>
</ItemGroup>
<PropertyGroup>
<Description>A cross-platform library for the processing of image files; written in C#</Description>
<AssemblyTitle>SixLabors.ImageSharp</AssemblyTitle>
<VersionPrefix Condition="$(packageversion) != ''">$(packageversion)</VersionPrefix>
<VersionPrefix Condition="$(packageversion) == ''">0.0.1</VersionPrefix>
<Authors>Six Labors and contributors</Authors>
<TargetFrameworks>netstandard1.1;netstandard1.3;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>SixLabors.ImageSharp</AssemblyName>
<PackageId>SixLabors.ImageSharp</PackageId>
<PackageTags>Image Resize Crop Gif Jpg Jpeg Bitmap Png Core</PackageTags>
<PackageIconUrl>https://raw.githubusercontent.com/SixLabors/ImageSharp/master/build/icons/imagesharp-logo-128.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/SixLabors/ImageSharp</PackageProjectUrl>
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/SixLabors/ImageSharp</RepositoryUrl>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateNeutralResourcesLanguageAttribute>false</GenerateNeutralResourcesLanguageAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<DebugType Condition="$(codecov) != ''">full</DebugType>
<DebugType Condition="$(codecov) == ''">portable</DebugType>
<DebugSymbols>True</DebugSymbols>
<Features>IOperation</Features>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Shared\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SixLabors.Core" Version="1.0.0-beta0004" />
<AdditionalFiles Include="..\..\stylecop.json" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta004">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Buffers" Version="4.4.0" />
<PackageReference Include="System.Memory" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.1' OR '$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
</ItemGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>..\..\ImageSharp.ruleset</CodeAnalysisRuleSet>
<RootNamespace>SixLabors.ImageSharp</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<None Update="Formats\Jpeg\Common\Block8x8F.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Block8x8F.Generated.cs</LastGenOutput>
</None>
<None Update="Formats\Jpeg\Components\Block8x8F.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Block8x8F.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\PixelOperations{TPixel}.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>PixelOperations{TPixel}.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Rgba32.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Rgba32.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\PixelBlenders\PorterDuffFunctions.Generated.tt">
<LastGenOutput>PorterDuffFunctions.Generated.cs</LastGenOutput>
<Generator>TextTemplatingFileGenerator</Generator>
</None>
<None Update="PixelFormats\PixelBlenders\DefaultPixelBlenders.Generated.tt">
<LastGenOutput>DefaultPixelBlenders.Generated.cs</LastGenOutput>
<Generator>TextTemplatingFileGenerator</Generator>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Formats\Jpeg\Common\Block8x8F.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Block8x8F.Generated.tt</DependentUpon>
</Compile>
<Compile Update="Formats\Jpeg\Components\Block8x8F.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Block8x8F.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\PixelOperations{TPixel}.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>PixelOperations{TPixel}.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Rgba32.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Rgba32.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\PixelBlenders\DefaultPixelBlenders.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>DefaultPixelBlenders.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\PixelBlenders\PorterDuffFunctions.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>PorterDuffFunctions.Generated.tt</DependentUpon>
</Compile>
</ItemGroup>
</Project>

19
tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

@ -8,6 +8,8 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests
{
using System.IO;
using SixLabors.ImageSharp.Formats.Bmp;
public class BmpDecoderTests : FileTestBase
@ -35,5 +37,20 @@ namespace SixLabors.ImageSharp.Tests
image.CompareToOriginal(provider);
}
}
[Theory]
[InlineData(TestImages.Bmp.Car, 24)]
[InlineData(TestImages.Bmp.F, 24)]
[InlineData(TestImages.Bmp.NegHeight, 24)]
[InlineData(TestImages.Bmp.Bit8, 8)]
[InlineData(TestImages.Bmp.Bit8Inverted, 8)]
public void DetectPixelSize(string imagePath, int expectedPixelSize)
{
TestFile testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
}
}
}
}
}

59
tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs

@ -3,11 +3,19 @@
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests
{
using System;
public class GeneralFormatTests : FileTestBase
{
[Theory]
@ -146,5 +154,56 @@ namespace SixLabors.ImageSharp.Tests
}
}
}
[Theory]
[InlineData(10, 10, "png")]
[InlineData(100, 100, "png")]
[InlineData(100, 10, "png")]
[InlineData(10, 100, "png")]
[InlineData(10, 10, "gif")]
[InlineData(100, 100, "gif")]
[InlineData(100, 10, "gif")]
[InlineData(10, 100, "gif")]
[InlineData(10, 10, "bmp")]
[InlineData(100, 100, "bmp")]
[InlineData(100, 10, "bmp")]
[InlineData(10, 100, "bmp")]
[InlineData(10, 10, "jpg")]
[InlineData(100, 100, "jpg")]
[InlineData(100, 10, "jpg")]
[InlineData(10, 100, "jpg")]
public void CanIdentifyImageLoadedFromBytes(int width, int height, string format)
{
using (Image<Rgba32> image = Image.LoadPixelData(new Rgba32[width * height], width, height))
{
using (var memoryStream = new MemoryStream())
{
image.Save(memoryStream, GetEncoder(format));
memoryStream.Position = 0;
var imageInfo = Image.Identify(memoryStream);
Assert.Equal(imageInfo.Width, width);
Assert.Equal(imageInfo.Height, height);
}
}
}
private static IImageEncoder GetEncoder(string format)
{
switch (format)
{
case "png":
return new PngEncoder();
case "gif":
return new GifEncoder();
case "bmp":
return new BmpEncoder();
case "jpg":
return new JpegEncoder();
default:
throw new ArgumentOutOfRangeException(nameof(format), format, null);
}
}
}
}

15
tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs

@ -10,6 +10,7 @@ using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests
{
using System.IO;
using SixLabors.ImageSharp.Advanced;
public class GifDecoderTests
@ -119,6 +120,20 @@ namespace SixLabors.ImageSharp.Tests
}
}
[Theory]
[InlineData(TestImages.Gif.Cheers, 8)]
[InlineData(TestImages.Gif.Giphy, 8)]
[InlineData(TestImages.Gif.Rings, 8)]
[InlineData(TestImages.Gif.Trans, 8)]
public void DetectPixelSize(string imagePath, int expectedPixelSize)
{
TestFile testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
}
}
[Fact]
public void CanDecodeIntermingledImages()
{

16
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -385,5 +385,21 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.Output.WriteLine($"Difference for PORT: {portReport.DifferencePercentageString}");
}
}
[Theory]
[InlineData(TestImages.Jpeg.Progressive.Progress, 24)]
[InlineData(TestImages.Jpeg.Progressive.Fb, 24)]
[InlineData(TestImages.Jpeg.Baseline.Cmyk, 32)]
[InlineData(TestImages.Jpeg.Baseline.Ycck, 32)]
[InlineData(TestImages.Jpeg.Baseline.Jpeg400, 8)]
[InlineData(TestImages.Jpeg.Baseline.Snake, 24)]
public void DetectPixelSize(string imagePath, int expectedPixelSize)
{
TestFile testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
}
}
}
}

17
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

@ -184,6 +184,23 @@ namespace SixLabors.ImageSharp.Tests
}
}
[Theory]
[InlineData(TestImages.Png.Bpp1, 1)]
[InlineData(TestImages.Png.Gray4Bpp, 4)]
[InlineData(TestImages.Png.Palette8Bpp, 8)]
[InlineData(TestImages.Png.Pd, 24)]
[InlineData(TestImages.Png.Blur, 32)]
[InlineData(TestImages.Png.Rgb48Bpp, 48)]
[InlineData(TestImages.Png.Rgb48BppInterlaced, 48)]
public void DetectPixelSize(string imagePath, int expectedPixelSize)
{
TestFile testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
}
}
[Theory]
[InlineData(PngChunkTypes.Header)]
[InlineData(PngChunkTypes.Palette)]

7
tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs

@ -38,20 +38,20 @@ namespace SixLabors.ImageSharp.Tests
this.fileSystem = new Mock<IFileSystem>();
this.LocalConfiguration = new Configuration()
this.LocalConfiguration = new Configuration
{
FileSystem = this.fileSystem.Object
};
this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object);
TestFormat.RegisterGloablTestFormat();
TestFormat.RegisterGlobalTestFormat();
this.Marker = Guid.NewGuid().ToByteArray();
this.DataStream = TestFormat.GlobalTestFormat.CreateStream(this.Marker);
this.FilePath = Guid.NewGuid().ToString();
this.fileSystem.Setup(x => x.OpenRead(this.FilePath)).Returns(this.DataStream);
TestFileSystem.RegisterGloablTestFormat();
TestFileSystem.RegisterGlobalTestFormat();
TestFileSystem.Global.AddFile(this.FilePath, this.DataStream);
}
@ -83,7 +83,6 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(localImageFormat, type);
}
[Fact]
public void DiscoverImageFormatStream()
{

6
tests/ImageSharp.Tests/Image/ImageLoadTests.cs

@ -53,21 +53,21 @@ namespace SixLabors.ImageSharp.Tests
this.fileSystem = new Mock<IFileSystem>();
this.LocalConfiguration = new Configuration()
this.LocalConfiguration = new Configuration
{
FileSystem = this.fileSystem.Object
};
this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object);
this.LocalConfiguration.SetDecoder(localImageFormatMock.Object, this.localDecoder.Object);
TestFormat.RegisterGloablTestFormat();
TestFormat.RegisterGlobalTestFormat();
this.Marker = Guid.NewGuid().ToByteArray();
this.DataStream = TestFormat.GlobalTestFormat.CreateStream(this.Marker);
this.FilePath = Guid.NewGuid().ToString();
this.fileSystem.Setup(x => x.OpenRead(this.FilePath)).Returns(this.DataStream);
TestFileSystem.RegisterGloablTestFormat();
TestFileSystem.RegisterGlobalTestFormat();
TestFileSystem.Global.AddFile(this.FilePath, this.DataStream);
}

1
tests/ImageSharp.Tests/ImageSharp.Tests.csproj

@ -17,6 +17,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CoreCompat.System.Drawing" Version="1.0.0-beta006" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="xunit" Version="2.3.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0" />
<PackageReference Include="Moq" Version="4.7.137" />

2
tests/ImageSharp.Tests/TestFileSystem.cs

@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests
public static TestFileSystem Global { get; } = new TestFileSystem();
public static void RegisterGloablTestFormat()
public static void RegisterGlobalTestFormat()
{
Configuration.Default.FileSystem = Global;
}

10
tests/ImageSharp.Tests/TestFormat.cs

@ -20,15 +20,15 @@ namespace SixLabors.ImageSharp.Tests
{
public static TestFormat GlobalTestFormat { get; } = new TestFormat();
public static void RegisterGloablTestFormat()
public static void RegisterGlobalTestFormat()
{
Configuration.Default.Configure(GlobalTestFormat);
}
public TestFormat()
{
this.Encoder = new TestEncoder(this); ;
this.Decoder = new TestDecoder(this); ;
this.Encoder = new TestEncoder(this);
this.Decoder = new TestDecoder(this);
}
public List<DecodeOperation> DecodeCalls { get; } = new List<DecodeOperation>();
@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Tests
config = config
});
// TODO record this happend so we an verify it.
// TODO record this happend so we can verify it.
return this.testFormat.Sample<TPixel>();
}
@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Tests
public void Encode<TPixel>(Image<TPixel> image, Stream stream) where TPixel : struct, IPixel<TPixel>
{
// TODO record this happend so we an verify it.
// TODO record this happend so we can verify it.
}
}
}

3
tests/ImageSharp.Tests/TestImages.cs

@ -24,6 +24,9 @@ namespace SixLabors.ImageSharp.Tests
public const string Powerpoint = "Png/pp.png";
public const string SplashInterlaced = "Png/splash-interlaced.png";
public const string Interlaced = "Png/interlaced.png";
public const string Palette8Bpp = "Png/palette-8bpp.png";
public const string Bpp1 = "Png/bpp1.png";
public const string Gray4Bpp = "Png/gray_4bpp.png";
public const string Rgb48Bpp = "Png/rgb-48bpp.png";
public const string CalliphoraPartial = "Png/CalliphoraPartial.png";
public const string CalliphoraPartialGrayscale = "Png/CalliphoraPartialGrayscale.png";

24
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs

@ -1,19 +1,16 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
{
public class SystemDrawingReferenceDecoder : IImageDecoder
public class SystemDrawingReferenceDecoder : IImageDecoder, IImageInfoDetector
{
public static SystemDrawingReferenceDecoder Instance { get; } = new SystemDrawingReferenceDecoder();
@ -22,7 +19,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
{
using (var sourceBitmap = new System.Drawing.Bitmap(stream))
{
if (sourceBitmap.PixelFormat == PixelFormat.Format32bppArgb)
if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb)
{
return SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap<TPixel>(sourceBitmap);
}
@ -32,12 +29,12 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
sourceBitmap.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
using (var g = Graphics.FromImage(convertedBitmap))
using (var g = System.Drawing.Graphics.FromImage(convertedBitmap))
{
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.DrawImage(sourceBitmap, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
}
@ -45,5 +42,14 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
}
}
}
public IImageInfo Identify(Configuration configuration, Stream stream)
{
using (var sourceBitmap = new System.Drawing.Bitmap(stream))
{
var pixelType = new PixelTypeInfo(System.Drawing.Image.GetPixelFormatSize(sourceBitmap.PixelFormat));
return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetaData());
}
}
}
}

3
tests/Images/Input/Png/bpp1.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:364e9fac6467570afe2f23e432d4f7df10dd2dd53920d4f2c743ac0f8519f1e0
size 4403

3
tests/Images/Input/Png/gray_4bpp.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e7c6d6cbd959e84001e559702c31e313d065c9cc25808c190c4d4a1f564d4357
size 7396

3
tests/Images/Input/Png/palette-8bpp.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7bfbc244f4b0672d6a12a1f73ec062bcf762f229268b99aa4b9ffd8447512471
size 9171
Loading…
Cancel
Save