forked from dotnet/winforms
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements GDI+ `CachedBitmap` wrapper which allows caching a device dependent copy of `Bitmap`. Rendering is signficantly faster (5x+), although it has a few caveats: - It needs to be regenerated if color depth changes - It cannot be rendered to a Graphics object that has a tranform other than translation (no rotation, scaling) Fixes dotnet#8822
- Loading branch information
1 parent
4ab9606
commit b4552a7
Showing
8 changed files
with
233 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
src/System.Drawing.Common/src/System/Drawing/Imaging/CachedBitmap.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Threading; | ||
|
||
#if NET8_0_OR_GREATER | ||
|
||
|
||
using static System.Drawing.SafeNativeMethods; | ||
|
||
namespace System.Drawing.Imaging; | ||
|
||
/// <summary> | ||
/// A device dependent copy of a <see cref="Bitmap"/> matching a specified <see cref="Graphics"/> object's current | ||
/// device (display) settings. Avoids reformatting step when rendering, which can significantly improve performance. | ||
/// </summary> | ||
/// <remarks> | ||
/// <para> | ||
/// <see cref="CachedBitmap"/> matches the current bit depth of the <see cref="Graphics"/>'s device. If the device bit | ||
/// depth changes, the <see cref="CachedBitmap"/> will no longer be usable and a new instance will need to be created | ||
/// that matches. If the <see cref="CachedBitmap"/> was created against <see cref="PixelFormat.Format32bppRgb"/> it | ||
/// will always work. | ||
/// </para> | ||
/// <para> | ||
/// <see cref="CachedBitmap"/> will not work with any transformations other than translation. | ||
/// </para> | ||
/// <para> | ||
/// <see cref="CachedBitmap"/> cannot be used to draw to a printer or metafile. | ||
/// </para> | ||
/// </remarks> | ||
public sealed class CachedBitmap : IDisposable | ||
{ | ||
private nint _handle; | ||
|
||
/// <summary> | ||
/// Create a device dependent copy of the given <paramref name="bitmap"/> for the device settings of the given | ||
/// <paramref name="graphics"/> | ||
/// </summary> | ||
/// <param name="bitmap">The <see cref="Bitmap"/> to convert.</param> | ||
/// <param name="graphics">The <see cref="Graphics"/> object to use to format the cached copy of the <paramref name="bitmap"/>.</param> | ||
/// <exception cref="ArgumentNullException"><paramref name="bitmap"/> or <paramref name="graphics"/> is <see langword="null"/>.</exception> | ||
public CachedBitmap(Bitmap bitmap, Graphics graphics) | ||
{ | ||
ArgumentNullException.ThrowIfNull(bitmap); | ||
ArgumentNullException.ThrowIfNull(graphics); | ||
|
||
Gdip.CheckStatus(Gdip.GdipCreateCachedBitmap( | ||
new(bitmap, bitmap.nativeImage), | ||
new(graphics, graphics.NativeGraphics), | ||
out _handle)); | ||
} | ||
|
||
internal nint Handle => _handle; | ||
|
||
private void Dispose(bool disposing) | ||
{ | ||
nint handle = Interlocked.Exchange(ref _handle, 0); | ||
if (handle == 0) | ||
{ | ||
return; | ||
} | ||
|
||
int status = Gdip.GdipDeleteCachedBitmap(handle); | ||
if (disposing) | ||
{ | ||
// Don't want to throw on the finalizer thread. | ||
Gdip.CheckStatus(status); | ||
} | ||
} | ||
|
||
~CachedBitmap() => Dispose(disposing: false); | ||
|
||
public void Dispose() | ||
{ | ||
Dispose(disposing: true); | ||
GC.SuppressFinalize(this); | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
src/System.Drawing.Common/tests/Imaging/CachedBitmapTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using Xunit; | ||
|
||
namespace System.Drawing.Imaging.Tests; | ||
|
||
#if NET8_0_OR_GREATER | ||
public class CachedBitmapTests | ||
{ | ||
[Fact] | ||
public void Ctor_Throws_ArgumentNullException() | ||
{ | ||
using var bitmap = new Bitmap(10, 10); | ||
using var graphics = Graphics.FromImage(bitmap); | ||
|
||
Assert.Throws<ArgumentNullException>(() => new CachedBitmap(bitmap, null)); | ||
Assert.Throws<ArgumentNullException>(() => new CachedBitmap(null, graphics)); | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters