//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
namespace ImageSharp.Tests
{
using System;
using System.Collections.Generic;
using System.Numerics;
using ImageSharp.PixelFormats;
using Xunit.Abstractions;
public abstract partial class TestImageProvider
where TPixel : struct, IPixel
{
///
/// A test image provider that produces test patterns.
///
///
private class TestPatternProvider : BlankProvider
{
static Dictionary> testImages = new Dictionary>();
public TestPatternProvider(int width, int height)
: base(width, height)
{
}
public TestPatternProvider()
: base()
{
}
public override string SourceFileOrDescription => $"TestPattern{this.Width}x{this.Height}";
public override Image GetImage()
{
lock (testImages)
{
if (!testImages.ContainsKey(this.SourceFileOrDescription))
{
Image image = new Image(this.Width, this.Height);
DrawTestPattern(image);
testImages.Add(this.SourceFileOrDescription, image);
}
}
return testImages[this.SourceFileOrDescription].Clone();
}
///
/// Draws the test pattern on an image by drawing 4 other patterns in the for quadrants of the image.
///
///
private static void DrawTestPattern(Image image)
{
// first lets split the image into 4 quadrants
using (PixelAccessor pixels = image.Lock())
{
BlackWhiteChecker(pixels); // top left
VerticalBars(pixels); // top right
TransparentGradients(pixels); // bottom left
Rainbow(pixels); // bottom right
}
}
///
/// Fills the top right quadrant with alternating solid vertical bars.
///
///
private static void VerticalBars(PixelAccessor pixels)
{
// topLeft
int left = pixels.Width / 2;
int right = pixels.Width;
int top = 0;
int bottom = pixels.Height / 2;
int stride = pixels.Width / 12;
TPixel[] c = {
NamedColors.HotPink,
NamedColors.Blue
};
int p = 0;
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
if (x % stride == 0)
{
p++;
p = p % c.Length;
}
pixels[x, y] = c[p];
}
}
}
///
/// fills the top left quadrant with a black and white checker board.
///
///
private static void BlackWhiteChecker(PixelAccessor pixels)
{
// topLeft
int left = 0;
int right = pixels.Width / 2;
int top = 0;
int bottom = pixels.Height / 2;
int stride = pixels.Width / 6;
TPixel[] c = {
NamedColors.Black,
NamedColors.White
};
int p = 0;
for (int y = top; y < bottom; y++)
{
if (y % stride == 0)
{
p++;
p = p % c.Length;
}
int pstart = p;
for (int x = left; x < right; x++)
{
if (x % stride == 0)
{
p++;
p = p % c.Length;
}
pixels[x, y] = c[p];
}
p = pstart;
}
}
///
/// Fills the bottom left quadrent with 3 horizental bars in Red, Green and Blue with a alpha gradient from left (transparent) to right (solid).
///
///
private static void TransparentGradients(PixelAccessor pixels)
{
// topLeft
int left = 0;
int right = pixels.Width / 2;
int top = pixels.Height / 2;
int bottom = pixels.Height;
int height = (int)Math.Ceiling(pixels.Height / 6f);
Vector4 red = Rgba32.Red.ToVector4(); // use real color so we can see har it translates in the test pattern
Vector4 green = Rgba32.Green.ToVector4(); // use real color so we can see har it translates in the test pattern
Vector4 blue = Rgba32.Blue.ToVector4(); // use real color so we can see har it translates in the test pattern
TPixel c = default(TPixel);
for (int x = left; x < right; x++)
{
blue.W = red.W = green.W = (float)x / (float)right;
c.PackFromVector4(red);
int topBand = top;
for (int y = topBand; y < top + height; y++)
{
pixels[x, y] = c;
}
topBand = topBand + height;
c.PackFromVector4(green);
for (int y = topBand; y < topBand + height; y++)
{
pixels[x, y] = c;
}
topBand = topBand + height;
c.PackFromVector4(blue);
for (int y = topBand; y < bottom; y++)
{
pixels[x, y] = c;
}
}
}
///
/// Fills the bottom right quadrant with all the colors producable by converting itterating over a uint and unpacking it.
/// A better algorithm could be used but it works
///
///
private static void Rainbow(PixelAccessor pixels)
{
int left = pixels.Width / 2;
int right = pixels.Width;
int top = pixels.Height / 2;
int bottom = pixels.Height;
int pixelCount = left * top;
uint stepsPerPixel = (uint)(uint.MaxValue / pixelCount);
TPixel c = default(TPixel);
Rgba32 t = new Rgba32(0);
for (int x = left; x < right; x++)
for (int y = top; y < bottom; y++)
{
t.PackedValue += stepsPerPixel;
Vector4 v = t.ToVector4();
//v.W = (x - left) / (float)left;
c.PackFromVector4(v);
pixels[x, y] = c;
}
}
}
}
}