-
Notifications
You must be signed in to change notification settings - Fork 995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for converting the format of a Bitmap #8827
Comments
Tagging subscribers to this area: @safern, @tarekgh Issue DetailsBackgroundGDI+ 1.1 added support for converting the pixel format of an bitmap in-place. Naturally, one can specify a target pixel format, but the function accepts many other parameters to control aspects of the conversion. Unfortunately, the API is not very well designed — it's poorly documented, and many combinations of options seem to be outright ignored or result in vague errors — but a not insubstantial amount of people have wondered how to do this, and the workaround is slow, less flexible, and certainly not obvious. When converting to an indexed pixel format, the
When a standard fixed palette type is used, any ordered or spiral dither type is valid. Otherwise, only One can also specify an alpha threshold percent. Passing a value t specifies that a pixel that is less than t percent fully opaque will map to the transparent color. (If there is no transparent color, the color closest to black will be selected.) This proposal is one of many to add missing GDI+ 1.1 functionality to API ProposalSee the documentation for: namespace System.Drawing.Imaging
{
+ public enum PaletteType
+ {
+ Custom,
+ Optimal,
+ FixedBW,
+ FixedHalftone8,
+ FixedHalftone27,
+ FixedHalftone64,
+ FixedHalftone125,
+ FixedHalftone216,
+ FixedHalftone252,
+ FixedHalftone256
+ }
+ public enum DitherType
+ {
+ None,
+ Solid,
+ ErrorDiffusion,
+ Ordered4x4,
+ Ordered8x8,
+ Ordered16x16,
+ Spiral4x4,
+ Spiral8x8,
+ DualSpiral4x4,
+ DualSpiral8x8
+ }
public sealed class ColorPalette
{
+ public ColorPalette(Color[] customColors);
+ public ColorPalette(PaletteType fixedPaletteType);
+ public static ColorPalette CreateOptimalPalette(int colors, Bitmap bitmap);
}
}
namespace System.Drawing
{
public sealed class Bitmap : System.Drawing.Image
{
! I added the optional parameters. These seem like they are sensible defaults for .NET, but the native definition has no optional parameters.
+ public void ConvertFormat(PixelFormat format, DitherType ditherType = DitherType.None, PaletteType paletteType + PaletteType.Custom, ColorPalette? palette = null, float alphaThresholdPercent = 0);
}
} This requires changes to libgdiplus in order to support it on non-Windows platforms.
|
I just wanna see what these look like! |
@reflectronic I guess this would only work on Windows as this is not implemented in libgdiplus? What would the story for Unix be? |
Setting myself up for a lot of work to contribute to libgdiplus :) |
It is also OK to say these would be supported on Windows only and attribute them correctly so that the platform attributes catch that at compile time if someone tries to use these APIs on non-Windows. |
Well, I suppose now that dotnet/designs#234 is out of the bag, that makes the Unix story a little easier. :-) @safern Would you mind taking a look at some of the issues I’ve proposed and see if they can be marked ready for review? I’ll take up the implementation work for all of them. I know that you are busy, and that these issues are basically the lowest priority, so if you want to wait until 6.0 is fully locked down, I do not have a problem with that. The full list should be:
#8833 also needs a small addition and needs re-review too (I have it posted as a comment). |
Thanks, @reflectronic. Sure I will. I will mark these issues |
I've just noticed this issue today. Shameless self promotion: I happen to have a library that supports converting pixel format of a GDI+ It also supports async, parallelization (but it depends also on the ditherer), cancellation, reporting progress, can be used on Linux (though starting with .NET 6 it might need some tweaks) and does not require libgdiplus changes. |
Minor tweaks from the original proposal.
namespace System.Drawing.Imaging
{
+ public enum PaletteType
+ {
+ Custom,
+ FixedBW,
+ FixedHalftone8,
+ FixedHalftone27,
+ FixedHalftone64,
+ FixedHalftone125,
+ FixedHalftone216,
+ FixedHalftone252,
+ FixedHalftone256
+ }
+ public enum DitherType
+ {
+ None,
+ Solid,
+ ErrorDiffusion,
+ Ordered4x4,
+ Ordered8x8,
+ Ordered16x16,
+ Spiral4x4,
+ Spiral8x8,
+ DualSpiral4x4,
+ DualSpiral8x8
+ }
public sealed class ColorPalette
{
// The array is just used as is (not copied) and exposed in the Entries property, so we don't want to add a ReadOnlySpan overload
+ public ColorPalette(params Color[] customColors);
+ public ColorPalette(PaletteType fixedPaletteType);
+ public static ColorPalette CreateOptimalPalette(int colors, bool useTransparentColor, Bitmap bitmap);
}
}
namespace System.Drawing
{
public sealed class Bitmap : System.Drawing.Image
{
+ public void ConvertFormat(PixelFormat format);
+ public void ConvertFormat(PixelFormat format, DitherType ditherType, PaletteType paletteType = PaletteType.Custom, ColorPalette? palette = null, float alphaThresholdPercent = 0.0f);
}
} |
This change implements Bitmap.ConvertFormat (see dotnet#8827). Until we get through API review some of the methods are under `[RequiresPreviewFeatures]`.
@reflectronic Now that we've fully transferred ownership of System.Drawing to WinForms and transitioned to CsWin32 I'm pushing forward on getting these GDI+ features implemented. If you have any additional feedback please let me know. |
This change implements Bitmap.ConvertFormat (see #8827). Until we get through API review some of the methods are under `[RequiresPreviewFeatures]`.
namespace System.Drawing.Imaging
{
public enum PaletteType
{
Custom,
FixedBlackAndWhite,
FixedHalftone8,
FixedHalftone27,
FixedHalftone64,
FixedHalftone125,
FixedHalftone216,
FixedHalftone252,
FixedHalftone256
}
public enum DitherType
{
None,
Solid,
ErrorDiffusion,
Ordered4x4,
Ordered8x8,
Ordered16x16,
Spiral4x4,
Spiral8x8,
DualSpiral4x4,
DualSpiral8x8
}
public sealed class ColorPalette
{
public ColorPalette(params Color[] customColors);
public ColorPalette(PaletteType fixedPaletteType);
public static ColorPalette CreateOptimalPalette(int colors,
bool useTransparentColor,
Bitmap bitmap);
}
}
namespace System.Drawing
{
public sealed class Bitmap : System.Drawing.Image
{
public void ConvertFormat(PixelFormat format);
public void ConvertFormat(PixelFormat format,
DitherType ditherType,
PaletteType paletteType = PaletteType.Custom,
ColorPalette? palette = null,
float alphaThresholdPercent = 0.0f);
}
} |
This change implements Bitmap.ConvertFormat (see dotnet#8827). Until we get through API review some of the methods are under `[RequiresPreviewFeatures]`.
This updates bitmap conversion and fixed color palette creation to match the final API approval and removes the preview flags. Fixes dotnet#8827
This updates bitmap conversion and fixed color palette creation to match the final API approval and removes the preview flags. Fixes #8827
Background
GDI+ 1.1 added support for converting the pixel format of an bitmap in-place. Naturally, one can specify a target pixel format, but the function accepts many other parameters to control aspects of the conversion. Unfortunately, the API is not very well designed — it's poorly documented, and many combinations of options seem to be outright ignored or result in vague errors — but a not insubstantial amount of people have wondered how to do this, and the workaround is slow, less flexible, and certainly not obvious.
When converting to an indexed pixel format, the
ditherType
,paletteType
, andpalette
parameters become relevant. Color palettes can be provided in order to constrain the colors in the converted image. There are effectively three categories of palettes:When a standard fixed palette type is used, any dither type is valid. Otherwise, only
None
,Solid
, andErrorDiffusion
are valid. (As an exception,DitherTypeOrdered4x4
may be used when converting to a 16 bits-per-pixel format using any palette.) GDI+ will convert from a standard palette specified withpaletteType
to a custom palette passed inpalette
using a nearest-color conversion.One can also specify an alpha threshold percent. Passing a value t specifies that a pixel that is less than t percent fully opaque will map to the transparent color. (If there is no transparent color, the color closest to black will be selected.)
This proposal is one of many to add missing GDI+ 1.1 functionality to
System.Drawing
.Usage Example
API Proposal -- Updated: #8827 (comment)
See the documentation for:
This requires changes to libgdiplus in order to support it on non-Windows platforms.
The text was updated successfully, but these errors were encountered: