ImageAttributes
Contains information about how bitmap and metafile colors are manipulated during rendering.
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.Graphics.Gdi;
using Windows.Win32.Graphics.GdiPlus;
namespace System.Drawing.Imaging
{
[StructLayout(LayoutKind.Sequential)]
[NullableContext(1)]
[Nullable(0)]
public sealed class ImageAttributes : ICloneable, IDisposable
{
[NullableContext(0)]
[InlineArray(32)]
private struct StackBuffer
{
internal (ARGB, ARGB) _element0;
}
private const int ColorMapStackSpace = 32;
[Nullable(0)]
internal unsafe GpImageAttributes* _nativeImageAttributes;
[NullableContext(0)]
internal unsafe void SetNativeImageAttributes(GpImageAttributes* handle)
{
if (handle == null)
throw new ArgumentNullException("handle");
_nativeImageAttributes = handle;
}
public unsafe ImageAttributes()
{
GpImageAttributes* nativeImageAttributes = default(GpImageAttributes*);
PInvokeGdiPlus.GdipCreateImageAttributes(&nativeImageAttributes).ThrowIfFailed();
SetNativeImageAttributes(nativeImageAttributes);
}
[NullableContext(0)]
internal unsafe ImageAttributes(GpImageAttributes* newNativeImageAttributes)
{
SetNativeImageAttributes(newNativeImageAttributes);
}
public unsafe void Dispose()
{
if (_nativeImageAttributes != null) {
if (Gdip.Initialized)
PInvokeGdiPlus.GdipDisposeImageAttributes(_nativeImageAttributes);
_nativeImageAttributes = null;
GC.SuppressFinalize(this);
}
}
~ImageAttributes()
{
Dispose();
}
public unsafe object Clone()
{
GpImageAttributes* newNativeImageAttributes = default(GpImageAttributes*);
PInvokeGdiPlus.GdipCloneImageAttributes(_nativeImageAttributes, &newNativeImageAttributes).ThrowIfFailed();
GC.KeepAlive(this);
return new ImageAttributes(newNativeImageAttributes);
}
public void SetColorMatrix(ColorMatrix newColorMatrix)
{
SetColorMatrix(newColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Default);
}
public void SetColorMatrix(ColorMatrix newColorMatrix, ColorMatrixFlag flags)
{
SetColorMatrix(newColorMatrix, flags, ColorAdjustType.Default);
}
public void SetColorMatrix(ColorMatrix newColorMatrix, ColorMatrixFlag mode, ColorAdjustType type)
{
SetColorMatrices(newColorMatrix, null, mode, type);
}
public void ClearColorMatrix()
{
ClearColorMatrix(ColorAdjustType.Default);
}
public unsafe void ClearColorMatrix(ColorAdjustType type)
{
PInvokeGdiPlus.GdipSetImageAttributesColorMatrix(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, false, null, null, ColorMatrixFlags.ColorMatrixFlagsDefault).ThrowIfFailed();
GC.KeepAlive(this);
}
public void SetColorMatrices(ColorMatrix newColorMatrix, [Nullable(2)] ColorMatrix grayMatrix)
{
SetColorMatrices(newColorMatrix, grayMatrix, ColorMatrixFlag.Default, ColorAdjustType.Default);
}
public void SetColorMatrices(ColorMatrix newColorMatrix, [Nullable(2)] ColorMatrix grayMatrix, ColorMatrixFlag flags)
{
SetColorMatrices(newColorMatrix, grayMatrix, flags, ColorAdjustType.Default);
}
public unsafe void SetColorMatrices(ColorMatrix newColorMatrix, [Nullable(2)] ColorMatrix grayMatrix, ColorMatrixFlag mode, ColorAdjustType type)
{
ArgumentNullException.ThrowIfNull(newColorMatrix, "newColorMatrix");
if (grayMatrix == null) {
fixed (float* ptr = &newColorMatrix.GetPinnableReference()) {
void* colorMatrix = ptr;
PInvokeGdiPlus.GdipSetImageAttributesColorMatrix(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, true, (global::Windows.Win32.Graphics.GdiPlus.ColorMatrix*)colorMatrix, null, (ColorMatrixFlags)mode).ThrowIfFailed();
}
} else {
fixed (float* ptr = &newColorMatrix.GetPinnableReference()) {
void* colorMatrix2 = ptr;
fixed (float* ptr2 = &grayMatrix.GetPinnableReference()) {
void* grayMatrix2 = ptr2;
PInvokeGdiPlus.GdipSetImageAttributesColorMatrix(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, true, (global::Windows.Win32.Graphics.GdiPlus.ColorMatrix*)colorMatrix2, (global::Windows.Win32.Graphics.GdiPlus.ColorMatrix*)grayMatrix2, (ColorMatrixFlags)mode).ThrowIfFailed();
}
}
}
GC.KeepAlive(this);
}
public void SetThreshold(float threshold)
{
SetThreshold(threshold, ColorAdjustType.Default);
}
public void SetThreshold(float threshold, ColorAdjustType type)
{
SetThreshold(threshold, type, true);
}
public void ClearThreshold()
{
ClearThreshold(ColorAdjustType.Default);
}
public void ClearThreshold(ColorAdjustType type)
{
SetThreshold(0, type, false);
}
private unsafe void SetThreshold(float threshold, ColorAdjustType type, bool enableFlag)
{
PInvokeGdiPlus.GdipSetImageAttributesThreshold(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, enableFlag, threshold).ThrowIfFailed();
GC.KeepAlive(this);
}
public void SetGamma(float gamma)
{
SetGamma(gamma, ColorAdjustType.Default);
}
public void SetGamma(float gamma, ColorAdjustType type)
{
SetGamma(gamma, type, true);
}
public void ClearGamma()
{
ClearGamma(ColorAdjustType.Default);
}
public void ClearGamma(ColorAdjustType type)
{
SetGamma(0, type, false);
}
private unsafe void SetGamma(float gamma, ColorAdjustType type, bool enableFlag)
{
PInvokeGdiPlus.GdipSetImageAttributesGamma(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, enableFlag, gamma).ThrowIfFailed();
GC.KeepAlive(this);
}
public void SetNoOp()
{
SetNoOp(ColorAdjustType.Default);
}
public void SetNoOp(ColorAdjustType type)
{
SetNoOp(type, true);
}
public void ClearNoOp()
{
ClearNoOp(ColorAdjustType.Default);
}
public void ClearNoOp(ColorAdjustType type)
{
SetNoOp(type, false);
}
private unsafe void SetNoOp(ColorAdjustType type, bool enableFlag)
{
PInvokeGdiPlus.GdipSetImageAttributesNoOp(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, enableFlag).ThrowIfFailed();
GC.KeepAlive(this);
}
public void SetColorKey(Color colorLow, Color colorHigh)
{
SetColorKey(colorLow, colorHigh, ColorAdjustType.Default);
}
public void SetColorKey(Color colorLow, Color colorHigh, ColorAdjustType type)
{
SetColorKey(colorLow, colorHigh, type, true);
}
public void ClearColorKey()
{
ClearColorKey(ColorAdjustType.Default);
}
public void ClearColorKey(ColorAdjustType type)
{
SetColorKey(Color.Empty, Color.Empty, type, false);
}
private unsafe void SetColorKey(Color colorLow, Color colorHigh, ColorAdjustType type, bool enableFlag)
{
PInvokeGdiPlus.GdipSetImageAttributesColorKeys(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, enableFlag, (uint)colorLow.ToArgb(), (uint)colorHigh.ToArgb()).ThrowIfFailed();
GC.KeepAlive(this);
}
public void SetOutputChannel(ColorChannelFlag flags)
{
SetOutputChannel(flags, ColorAdjustType.Default);
}
public void SetOutputChannel(ColorChannelFlag flags, ColorAdjustType type)
{
SetOutputChannel(type, flags, true);
}
public void ClearOutputChannel()
{
ClearOutputChannel(ColorAdjustType.Default);
}
public void ClearOutputChannel(ColorAdjustType type)
{
SetOutputChannel(type, ColorChannelFlag.ColorChannelLast, false);
}
private unsafe void SetOutputChannel(ColorAdjustType type, ColorChannelFlag flags, bool enableFlag)
{
PInvokeGdiPlus.GdipSetImageAttributesOutputChannel(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, enableFlag, (ColorChannelFlags)flags).ThrowIfFailed();
GC.KeepAlive(this);
}
public void SetOutputChannelColorProfile(string colorProfileFilename)
{
SetOutputChannelColorProfile(colorProfileFilename, ColorAdjustType.Default);
}
public unsafe void SetOutputChannelColorProfile(string colorProfileFilename, ColorAdjustType type)
{
Path.GetFullPath(colorProfileFilename);
IntPtr intPtr;
if (colorProfileFilename == null)
intPtr = (IntPtr)(void*)null;
else {
ref reference = ref colorProfileFilename.GetPinnableReference();
intPtr = (IntPtr)(&reference);
}
char* value = (char*)(long)intPtr;
PInvokeGdiPlus.GdipSetImageAttributesOutputChannelColorProfile(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, true, value).ThrowIfFailed();
ref reference = ref *(char*)null;
GC.KeepAlive(this);
}
public void ClearOutputChannelColorProfile()
{
ClearOutputChannel(ColorAdjustType.Default);
}
public unsafe void ClearOutputChannelColorProfile(ColorAdjustType type)
{
PInvokeGdiPlus.GdipSetImageAttributesOutputChannel(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, false, ColorChannelFlags.ColorChannelFlagsLast).ThrowIfFailed();
GC.KeepAlive(this);
}
public void SetRemapTable(params ColorMap[] map)
{
SetRemapTable(map, ColorAdjustType.Default);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void SetRemapTable(ColorMap[] map, ColorAdjustType type)
{
ArgumentNullException.ThrowIfNull(map, "map");
SetRemapTable(type, map);
}
public void SetRemapTable([ParamCollection] [ScopedRef] [Nullable(new byte[] {
0,
1
})] ReadOnlySpan<ColorMap> map)
{
SetRemapTable(ColorAdjustType.Default, map);
}
[NullableContext(0)]
public void SetRemapTable([ParamCollection] [ScopedRef] ReadOnlySpan<(Color OldColor, Color NewColor)> map)
{
SetRemapTable(ColorAdjustType.Default, map);
}
public unsafe void SetRemapTable(ColorAdjustType type, [ParamCollection] [ScopedRef] [Nullable(new byte[] {
0,
1
})] ReadOnlySpan<ColorMap> map)
{
StackBuffer buffer = default(StackBuffer);
BufferScope<(ARGB, ARGB)> bufferScope = new BufferScope<(ARGB, ARGB)>(global::<PrivateImplementationDetails>.InlineArrayAsSpan<StackBuffer, (ARGB, ARGB)>(ref buffer, 32), map.Length);
try {
for (int i = 0; i < map.Length; i++) {
ref(ARGB, ARGB) reference = ref bufferScope[i];
Color color = map[i].OldColor;
ARGB item = ref color;
Color color2 = map[i].NewColor;
reference = (item, ref color2);
}
fixed ((ARGB, ARGB)* ptr = &bufferScope.GetPinnableReference()) {
void* map2 = ptr;
PInvokeGdiPlus.GdipSetImageAttributesRemapTable(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, true, (uint)map.Length, (global::Windows.Win32.Graphics.GdiPlus.ColorMap*)map2).ThrowIfFailed();
}
GC.KeepAlive(this);
} finally {
bufferScope.Dispose();
}
}
[NullableContext(0)]
public unsafe void SetRemapTable(ColorAdjustType type, [ParamCollection] [ScopedRef] ReadOnlySpan<(Color OldColor, Color NewColor)> map)
{
StackBuffer buffer = default(StackBuffer);
BufferScope<(ARGB, ARGB)> bufferScope = new BufferScope<(ARGB, ARGB)>(global::<PrivateImplementationDetails>.InlineArrayAsSpan<StackBuffer, (ARGB, ARGB)>(ref buffer, 32), map.Length);
try {
for (int i = 0; i < map.Length; i++) {
bufferScope[i] = (ref map[i].OldColor, ref map[i].NewColor);
}
fixed ((ARGB, ARGB)* ptr = &bufferScope.GetPinnableReference()) {
void* map2 = ptr;
PInvokeGdiPlus.GdipSetImageAttributesRemapTable(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, true, (uint)map.Length, (global::Windows.Win32.Graphics.GdiPlus.ColorMap*)map2).ThrowIfFailed();
}
GC.KeepAlive(this);
} finally {
bufferScope.Dispose();
}
}
public void ClearRemapTable()
{
ClearRemapTable(ColorAdjustType.Default);
}
public unsafe void ClearRemapTable(ColorAdjustType type)
{
PInvokeGdiPlus.GdipSetImageAttributesRemapTable(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type, false, 0, null).ThrowIfFailed();
GC.KeepAlive(this);
}
public void SetBrushRemapTable(params ColorMap[] map)
{
SetRemapTable(map, ColorAdjustType.Brush);
}
public void SetBrushRemapTable([ParamCollection] [ScopedRef] [Nullable(new byte[] {
0,
1
})] ReadOnlySpan<ColorMap> map)
{
SetRemapTable(ColorAdjustType.Brush, map);
}
[NullableContext(0)]
public void SetBrushRemapTable([ParamCollection] [ScopedRef] ReadOnlySpan<(Color OldColor, Color NewColor)> map)
{
SetRemapTable(ColorAdjustType.Brush, map);
}
public void ClearBrushRemapTable()
{
ClearRemapTable(ColorAdjustType.Brush);
}
public void SetWrapMode(System.Drawing.Drawing2D.WrapMode mode)
{
SetWrapMode(mode, default(Color), false);
}
public void SetWrapMode(System.Drawing.Drawing2D.WrapMode mode, Color color)
{
SetWrapMode(mode, color, false);
}
public unsafe void SetWrapMode(System.Drawing.Drawing2D.WrapMode mode, Color color, bool clamp)
{
PInvokeGdiPlus.GdipSetImageAttributesWrapMode(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.WrapMode)mode, (uint)color.ToArgb(), clamp).ThrowIfFailed();
GC.KeepAlive(this);
}
public unsafe void GetAdjustedPalette(ColorPalette palette, ColorAdjustType type)
{
BufferScope<uint> bufferScope = palette.ConvertToBuffer();
try {
fixed (uint* ptr = &bufferScope.GetPinnableReference()) {
void* colorPalette = ptr;
PInvokeGdiPlus.GdipGetImageAttributesAdjustedPalette(_nativeImageAttributes, (global::Windows.Win32.Graphics.GdiPlus.ColorPalette*)colorPalette, (global::Windows.Win32.Graphics.GdiPlus.ColorAdjustType)type).ThrowIfFailed();
}
GC.KeepAlive(this);
} finally {
bufferScope.Dispose();
}
}
}
}