Browse Source

Add dominant pixel encoding.

Add functionality as described at
https://manu.ninja/dominant-colors-for-lazy-loading-images

Former-commit-id: 6877d52aec61a5cff850b8fc52b98fe4328db115
Former-commit-id: 231b6016c32e434d9699fd01b90662257c7edb59
Former-commit-id: 504ae4d40e60270d85797b646b659becd4303500
pull/1/head
James South 10 years ago
parent
commit
d476751d9d
  1. 48
      src/ImageProcessorCore/ImageExtensions.cs
  2. 26
      tests/ImageProcessorCore.Tests/Formats/EncoderDecoderTests.cs

48
src/ImageProcessorCore/ImageExtensions.cs

@ -10,6 +10,7 @@ namespace ImageProcessorCore
using Formats;
using ImageProcessorCore.Quantizers;
using ImageProcessorCore.Samplers;
/// <summary>
@ -51,6 +52,53 @@ namespace ImageProcessorCore
/// <exception cref="ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsGif(this ImageBase source, Stream stream, int quality = 256) => new GifEncoder() { Quality = quality }.Encode(source, stream);
/// <summary>
/// Returns a 1x1 pixel Base64 encoded gif from the given image containing a single dominant color.
/// </summary>
/// <remarks>
/// The idea and code is based on the article at <see href="https://manu.ninja/dominant-colors-for-lazy-loading-images"/>
/// </remarks>
/// <param name="source">The image this method extends.</param>
/// <returns>The <see cref="string"/></returns>
public static string ToBase64GifPixelString(this Image source)
{
// Leave the original image intact
using (Image temp = new Image(source))
{
Bgra32 color = new OctreeQuantizer().Quantize(temp.Resize(250, 250), 1).Palette[0];
byte[] gif = {
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, // Header
0x01, 0x00, 0x01, 0x00, 0x80, 0x01, 0x00, // Logical Screen Descriptor
color.R, color.G, color.B, 0x00, 0x00, 0x00, // Global Color Table
0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, // Image Descriptor
0x02, 0x02, 0x44, 0x01, 0x00 // Image Data
};
return "data:image/gif;base64," + Convert.ToBase64String(gif);
}
}
/// <summary>
/// Returns a 3x3 pixel Base64 encoded gif from the given image.
/// </summary>
/// <remarks>
/// The idea and code is based on the article at <see href="https://manu.ninja/dominant-colors-for-lazy-loading-images"/>
/// </remarks>
/// <param name="source">The image this method extends.</param>
/// <returns>The <see cref="string"/></returns>
public static string ToBase64GifString(this Image source)
{
// Leave the original image intact
using (Image temp = new Image(source))
using (MemoryStream stream = new MemoryStream())
{
temp.Resize(3, 3).SaveAsGif(stream);
stream.Flush();
return "data:image/gif;base64," + Convert.ToBase64String(stream.ToArray());
}
}
/// <summary>
/// Applies the collection of processors to the image.
/// <remarks>This method does not resize the target image.</remarks>

26
tests/ImageProcessorCore.Tests/Formats/EncoderDecoderTests.cs

@ -17,6 +17,32 @@ namespace ImageProcessorCore.Tests
public class EncoderDecoderTests : FileTestBase
{
[Fact]
public void ImageCanEncodeToDominantPixel()
{
if (!Directory.Exists("TestOutput/Dominant"))
{
Directory.CreateDirectory("TestOutput/Dominant");
}
foreach (string file in Files)
{
using (FileStream stream = File.OpenRead(file))
{
Stopwatch watch = Stopwatch.StartNew();
using (Image image = new Image(stream))
{
string filename = "TestOutput/Dominant/" + Path.GetFileNameWithoutExtension(file) + ".txt";
string filename2 = "TestOutput/Dominant/Pixel-" + Path.GetFileNameWithoutExtension(file) + ".txt";
File.WriteAllText(filename, image.ToBase64GifString());
File.WriteAllText(filename2, image.ToBase64GifPixelString());
}
Trace.WriteLine($"{watch.ElapsedMilliseconds}ms");
}
}
}
[Fact]
public void DecodeThenEncodeImageFromStreamShouldSucceed()
{

Loading…
Cancel
Save