mirror of https://github.com/SixLabors/ImageSharp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
10 KiB
252 lines
10 KiB
// --------------------------------------------------------------------------------------------------------------------
|
|
// <copyright file="Adjustments.cs" company="James South">
|
|
// Copyright (c) James South.
|
|
// Licensed under the Apache License, Version 2.0.
|
|
// </copyright>
|
|
// <summary>
|
|
// Provides reusable adjustment methods to apply to images.
|
|
// </summary>
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
|
|
namespace ImageProcessor.Imaging.Helpers
|
|
{
|
|
using System;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Threading.Tasks;
|
|
|
|
using ImageProcessor.Common.Extensions;
|
|
|
|
/// <summary>
|
|
/// Provides reusable adjustment methods to apply to images.
|
|
/// </summary>
|
|
public static class Adjustments
|
|
{
|
|
/// <summary>
|
|
/// Adjusts the alpha component of the given image.
|
|
/// </summary>
|
|
/// <param name="source">
|
|
/// The <see cref="Image"/> source to adjust.
|
|
/// </param>
|
|
/// <param name="percentage">
|
|
/// The percentage value between 0 and 100 for adjusting the opacity.
|
|
/// </param>
|
|
/// <param name="rectangle">The rectangle to define the bounds of the area to adjust the opacity.
|
|
/// If null then the effect is applied to the entire image.</param>
|
|
/// <returns>
|
|
/// The <see cref="Bitmap"/> with the alpha component adjusted.
|
|
/// </returns>
|
|
/// <exception cref="ArgumentOutOfRangeException">
|
|
/// Thrown if the percentage value falls outside the acceptable range.
|
|
/// </exception>
|
|
public static Bitmap Alpha(Image source, int percentage, Rectangle? rectangle = null)
|
|
{
|
|
if (percentage > 100 || percentage < 0)
|
|
{
|
|
throw new ArgumentOutOfRangeException("percentage", "Percentage should be between 0 and 100.");
|
|
}
|
|
|
|
float factor = (float)percentage / 100;
|
|
int width = source.Width;
|
|
int height = source.Height;
|
|
|
|
// Traditional examples using a color matrix alter the rgb values also.
|
|
using (FastBitmap bitmap = new FastBitmap(source))
|
|
{
|
|
// Loop through the pixels.
|
|
Parallel.For(
|
|
0,
|
|
height,
|
|
y =>
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
// ReSharper disable AccessToDisposedClosure
|
|
Color color = bitmap.GetPixel(x, y);
|
|
bitmap.SetPixel(x, y, Color.FromArgb(Convert.ToInt32(color.A * factor), color.R, color.G, color.B));
|
|
// ReSharper restore AccessToDisposedClosure
|
|
}
|
|
});
|
|
}
|
|
|
|
return (Bitmap)source;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adjusts the brightness component of the given image.
|
|
/// </summary>
|
|
/// <param name="source">
|
|
/// The <see cref="Image"/> source to adjust.
|
|
/// </param>
|
|
/// <param name="threshold">
|
|
/// The threshold value between -100 and 100 for adjusting the brightness.
|
|
/// </param>
|
|
/// <param name="rectangle">The rectangle to define the bounds of the area to adjust the brightness.
|
|
/// If null then the effect is applied to the entire image.</param>
|
|
/// <returns>
|
|
/// The <see cref="Bitmap"/> with the brightness adjusted.
|
|
/// </returns>
|
|
/// <exception cref="ArgumentOutOfRangeException">
|
|
/// Thrown if the threshold value falls outside the acceptable range.
|
|
/// </exception>
|
|
public static Bitmap Brightness(Image source, int threshold, Rectangle? rectangle = null)
|
|
{
|
|
if (threshold > 100 || threshold < -100)
|
|
{
|
|
throw new ArgumentOutOfRangeException("threshold", "Threshold should be between -100 and 100.");
|
|
}
|
|
|
|
float brightnessFactor = (float)threshold / 100;
|
|
Rectangle bounds = rectangle ?? new Rectangle(0, 0, source.Width, source.Height);
|
|
|
|
ColorMatrix colorMatrix =
|
|
new ColorMatrix(
|
|
new[]
|
|
{
|
|
new float[] { 1, 0, 0, 0, 0 },
|
|
new float[] { 0, 1, 0, 0, 0 },
|
|
new float[] { 0, 0, 1, 0, 0 },
|
|
new float[] { 0, 0, 0, 1, 0 },
|
|
new[] { brightnessFactor, brightnessFactor, brightnessFactor, 0, 1 }
|
|
});
|
|
|
|
using (Graphics graphics = Graphics.FromImage(source))
|
|
{
|
|
using (ImageAttributes imageAttributes = new ImageAttributes())
|
|
{
|
|
imageAttributes.SetColorMatrix(colorMatrix);
|
|
graphics.DrawImage(source, bounds, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, imageAttributes);
|
|
}
|
|
}
|
|
|
|
return (Bitmap)source;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adjusts the contrast component of the given image.
|
|
/// </summary>
|
|
/// <param name="source">
|
|
/// The <see cref="Image"/> source to adjust.
|
|
/// </param>
|
|
/// <param name="threshold">
|
|
/// The threshold value between -100 and 100 for adjusting the contrast.
|
|
/// </param>
|
|
/// <param name="rectangle">The rectangle to define the bounds of the area to adjust the contrast.
|
|
/// If null then the effect is applied to the entire image.</param>
|
|
/// <returns>
|
|
/// The <see cref="Bitmap"/> with the contrast adjusted.
|
|
/// </returns>
|
|
/// <exception cref="ArgumentOutOfRangeException">
|
|
/// Thrown if the threshold value falls outside the acceptable range.
|
|
/// </exception>
|
|
public static Bitmap Contrast(Image source, int threshold, Rectangle? rectangle = null)
|
|
{
|
|
if (threshold > 100 || threshold < -100)
|
|
{
|
|
throw new ArgumentOutOfRangeException("threshold", "Threshold should be between -100 and 100.");
|
|
}
|
|
|
|
Rectangle bounds = rectangle ?? new Rectangle(0, 0, source.Width, source.Height);
|
|
|
|
float contrastFactor = (float)threshold / 100;
|
|
|
|
// Stop at -1 to prevent inversion.
|
|
contrastFactor++;
|
|
float factorTransform = 0.5f * (1.0f - contrastFactor);
|
|
|
|
ColorMatrix colorMatrix =
|
|
new ColorMatrix(
|
|
new[]
|
|
{
|
|
new[] { contrastFactor, 0, 0, 0, 0 },
|
|
new[] { 0, contrastFactor, 0, 0, 0 },
|
|
new[] { 0, 0, contrastFactor, 0, 0 },
|
|
new float[] { 0, 0, 0, 1, 0 },
|
|
new[] { factorTransform, factorTransform, factorTransform, 0, 1 }
|
|
});
|
|
|
|
using (Graphics graphics = Graphics.FromImage(source))
|
|
{
|
|
using (ImageAttributes imageAttributes = new ImageAttributes())
|
|
{
|
|
imageAttributes.SetColorMatrix(colorMatrix);
|
|
graphics.DrawImage(source, bounds, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, imageAttributes);
|
|
}
|
|
}
|
|
|
|
return (Bitmap)source;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adjust the gamma (intensity of the light) component of the given image.
|
|
/// </summary>
|
|
/// <param name="source">
|
|
/// The <see cref="Image"/> source to adjust.
|
|
/// </param>
|
|
/// <param name="value">
|
|
/// The value to adjust the gamma by (typically between .2 and 5).
|
|
/// </param>
|
|
/// <returns>
|
|
/// The <see cref="Bitmap"/> with the gamma adjusted.
|
|
/// </returns>
|
|
/// <exception cref="ArgumentOutOfRangeException">
|
|
/// Thrown if the value falls outside the acceptable range.
|
|
/// </exception>
|
|
public static Bitmap Gamma(Image source, float value)
|
|
{
|
|
if (value > 5 || value < .1)
|
|
{
|
|
throw new ArgumentOutOfRangeException("value", "Value should be between .1 and 5.");
|
|
}
|
|
|
|
int width = source.Width;
|
|
int height = source.Height;
|
|
Bitmap destination = new Bitmap(width, height);
|
|
destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
|
|
|
|
byte[] ramp = new byte[256];
|
|
for (int x = 0; x < 256; ++x)
|
|
{
|
|
byte val = ((255.0 * Math.Pow(x / 255.0, value)) + 0.5).ToByte();
|
|
ramp[x] = val;
|
|
}
|
|
|
|
using (FastBitmap fastSource = new FastBitmap(source))
|
|
{
|
|
using (FastBitmap fastDestination = new FastBitmap(destination))
|
|
{
|
|
Parallel.For(
|
|
0,
|
|
height,
|
|
y =>
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
// ReSharper disable once AccessToDisposedClosure
|
|
Color color = fastSource.GetPixel(x, y);
|
|
byte r = ramp[color.R];
|
|
byte g = ramp[color.G];
|
|
byte b = ramp[color.B];
|
|
|
|
// ReSharper disable once AccessToDisposedClosure
|
|
fastDestination.SetPixel(x, y, Color.FromArgb(color.A, r, g, b));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
//Rectangle rectangle = new Rectangle(0, 0, width, height);
|
|
//using (Graphics graphics = Graphics.FromImage(destination))
|
|
//{
|
|
// using (ImageAttributes attributes = new ImageAttributes())
|
|
// {
|
|
// attributes.SetGamma(value);
|
|
// graphics.DrawImage(source, rectangle, 0, 0, width, height, GraphicsUnit.Pixel, attributes);
|
|
// }
|
|
//}
|
|
|
|
source.Dispose();
|
|
return destination;
|
|
}
|
|
}
|
|
}
|
|
|