mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: a28745bb3a7a48769718459f660aee59dc6727fd Former-commit-id: 3cea324866d570efa674f7ea8cfcf964a3283f58 Former-commit-id: 8eb414b88e6c70055d2653818694c0fc8c95ba83pull/17/head
5 changed files with 226 additions and 30 deletions
@ -0,0 +1,193 @@ |
|||||
|
// <copyright file="PixelOperations.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor |
||||
|
{ |
||||
|
using System; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Performs per-pixel operations.
|
||||
|
/// </summary>
|
||||
|
public static class PixelOperations |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The array of bytes representing each possible value of color component
|
||||
|
/// converted from sRGB to the linear color space.
|
||||
|
/// </summary>
|
||||
|
private static readonly Lazy<byte[]> LinearBytes = new Lazy<byte[]>(GetLinearBytes); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The array of bytes representing each possible value of color component
|
||||
|
/// converted from linear to the sRGB color space.
|
||||
|
/// </summary>
|
||||
|
private static readonly Lazy<byte[]> SrgbBytes = new Lazy<byte[]>(GetSrgbBytes); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The array of bytes representing each possible value of color component
|
||||
|
/// converted from gamma to the linear color space.
|
||||
|
/// </summary>
|
||||
|
private static readonly Lazy<byte[]> LinearGammaBytes = new Lazy<byte[]>(GetLinearGammaBytes); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The array of bytes representing each possible value of color component
|
||||
|
/// converted from linear to the gamma color space.
|
||||
|
/// </summary>
|
||||
|
private static readonly Lazy<byte[]> GammaLinearBytes = new Lazy<byte[]>(GetGammaLinearBytes); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts an pixel from an sRGB color-space to the equivalent linear color-space.
|
||||
|
/// </summary>
|
||||
|
/// <param name="composite">
|
||||
|
/// The <see cref="Bgra"/> to convert.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="Bgra"/>.
|
||||
|
/// </returns>
|
||||
|
public static Bgra ToLinear(Bgra composite) |
||||
|
{ |
||||
|
// Create only once and lazily.
|
||||
|
// byte[] ramp = LinearGammaBytes.Value;
|
||||
|
byte[] ramp = LinearBytes.Value; |
||||
|
|
||||
|
return new Bgra(ramp[composite.B], ramp[composite.G], ramp[composite.R], composite.A); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts a pixel from a linear color-space to the equivalent sRGB color-space.
|
||||
|
/// </summary>
|
||||
|
/// <param name="linear">
|
||||
|
/// The <see cref="Bgra"/> to convert.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="Bgra"/>.
|
||||
|
/// </returns>
|
||||
|
public static Bgra ToSrgb(Bgra linear) |
||||
|
{ |
||||
|
// Create only once and lazily.
|
||||
|
// byte[] ramp = GammaLinearBytes.Value;
|
||||
|
byte[] ramp = SrgbBytes.Value; |
||||
|
|
||||
|
return new Bgra(ramp[linear.B], ramp[linear.G], ramp[linear.R], linear.A); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets an array of bytes representing each possible value of color component
|
||||
|
/// converted from sRGB to the linear color space.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="T:byte[]"/>.
|
||||
|
/// </returns>
|
||||
|
private static byte[] GetLinearBytes() |
||||
|
{ |
||||
|
byte[] ramp = new byte[256]; |
||||
|
for (int x = 0; x < 256; ++x) |
||||
|
{ |
||||
|
byte val = (255f * SrgbToLinear(x / 255f)).ToByte(); |
||||
|
ramp[x] = val; |
||||
|
} |
||||
|
|
||||
|
return ramp; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets an array of bytes representing each possible value of color component
|
||||
|
/// converted from linear to the sRGB color space.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="T:byte[]"/>.
|
||||
|
/// </returns>
|
||||
|
private static byte[] GetSrgbBytes() |
||||
|
{ |
||||
|
byte[] ramp = new byte[256]; |
||||
|
for (int x = 0; x < 256; ++x) |
||||
|
{ |
||||
|
byte val = (255f * LinearToSrgb(x / 255f)).ToByte(); |
||||
|
ramp[x] = val; |
||||
|
} |
||||
|
|
||||
|
return ramp; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the correct linear value from an sRGB signal.
|
||||
|
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
|
||||
|
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
|
||||
|
/// </summary>
|
||||
|
/// <param name="signal">The signal value to convert.</param>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="float"/>.
|
||||
|
/// </returns>
|
||||
|
private static float SrgbToLinear(float signal) |
||||
|
{ |
||||
|
float a = 0.055f; |
||||
|
|
||||
|
if (signal <= 0.04045) |
||||
|
{ |
||||
|
return signal / 12.92f; |
||||
|
} |
||||
|
|
||||
|
return (float)Math.Pow((signal + a) / (1 + a), 2.4); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the correct sRGB value from an linear signal.
|
||||
|
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
|
||||
|
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
|
||||
|
/// </summary>
|
||||
|
/// <param name="signal">The signal value to convert.</param>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="float"/>.
|
||||
|
/// </returns>
|
||||
|
private static float LinearToSrgb(float signal) |
||||
|
{ |
||||
|
float a = 0.055f; |
||||
|
|
||||
|
if (signal <= 0.0031308) |
||||
|
{ |
||||
|
return signal * 12.92f; |
||||
|
} |
||||
|
|
||||
|
return ((float)((1 + a) * Math.Pow(signal, 1 / 2.4f))) - a; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets an array of bytes representing each possible value of color component
|
||||
|
/// converted from gamma to the linear color space.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="T:byte[]"/>.
|
||||
|
/// </returns>
|
||||
|
private static byte[] GetLinearGammaBytes() |
||||
|
{ |
||||
|
byte[] ramp = new byte[256]; |
||||
|
for (int x = 0; x < 256; ++x) |
||||
|
{ |
||||
|
byte val = (255f * Math.Pow(x / 255f, 2.2)).ToByte(); |
||||
|
ramp[x] = val; |
||||
|
} |
||||
|
|
||||
|
return ramp; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets an array of bytes representing each possible value of color component
|
||||
|
/// converted from linear to the gamma color space.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="T:byte[]"/>.
|
||||
|
/// </returns>
|
||||
|
private static byte[] GetGammaLinearBytes() |
||||
|
{ |
||||
|
byte[] ramp = new byte[256]; |
||||
|
for (int x = 0; x < 256; ++x) |
||||
|
{ |
||||
|
byte val = (255f * Math.Pow(x / 255f, 1 / 2.2)).ToByte(); |
||||
|
ramp[x] = val; |
||||
|
} |
||||
|
|
||||
|
return ramp; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue