How to avoid "adding up" of opacities in SkiaSharp - c#

I'm currently creating a Xamarin.Forms app. One of my pages uses SkiaSharp to allow users to highlight parts of an image in a text marker style (i.e. a yellow brush with low opacity).
This is how the related SKPaint object is defined:
var strokePaint = new SKPaint()
{
Color = Color.FromRgba(255, 255, 0, 100).ToSKColor(),
Style = SKPaintStyle.Stroke,
StrokeWidth = StrokeWidth
};
That's working fine so far, but what bothers me is that the opacity "increases" when I have multiple overlapping paths, until at some point the underlying picture isn't visible anymore.
What could I do to avoid this overlapping? I was thinking about merging all paths into one, but that doesn't seem to work because the user is allowed to change StrokeWidth in between strokes and I didn't see any way of drawing paths with varying width.
I hope any of you guys has some help for me. Any idea is appreciated!

I'm not super familiar with Skia, but I took a look at the documentation for SKPaint, and it looks like it has a BlendMode property. Based on how similar things work in other systems, that should control how colors are combined. You might have to try different values to get the effect you are looking for. Dst, or Modulate look like good candidates. – Bradley Uffner
Thanks for your answer Bradley! I went with the Darken blend mode and set opacity to 255, which creates a very nice effect when highlighting text (only the darker color is visible, so dark text on a light background becomes dark text on a background of my marker color).

Related

Destructure a solid color into overlayed colors with transparency

I am working on an application, in which I export an image with different shapes (rectangles, circles, polygons and etc). Each shape has its own unique color. Currently, the colors are solid and have no transparency and this gives me a strong limitation: If a shape is placed over another shape, the shape below the first one is lost. This is really bad, because, sometimes there is a very large object, that stays on top and hides more than 100 smaller elements below it. Example image:
The used colors are solid red(255, 0, 0), green(0, 255, 0) and blue(0, 0, 255)
I have an idea how to fix that, but I don't know if it is possible and this is why I am asking here. I want to try to set transparency to each shape (e.g. 0.3/1) and by doing this, I will be able to see all shapes. Example image:
What I want to do, is to find a way to destructure all colors, that compose a particular pixel. For example - in the middle of the picture where all three shapes are overlayed, the color that is generated is a solid one with RGB(163, 124, 141). I want to be able to extract the following colors: RGBA(255,0,0,0.3), RGBA(0,255,0,0.3), RGBA(0,0,255,0.3). Let's say that the Alpha component will be a constant and set to 0.3 if that helps.
As I said, I don't know if this is possible, but any suggestion will be highly appreciated. The programming languages that I use in my project are C#, Go and JavaScript, but any suggestion in another language will be appreciated as well.

Set bits per pixel in WPF-Desktop program

I noticed ugly banding issues when using Gradients in WPF, and saw that a solution was to set the "bits per pixel" property to 32.
The thing is that the property seem to be Windows Phone only, ie not working on a program for desktop devices, since trying to add this string in the ApplicationManifest didn't seem to do anything.
Does anyone know if/how I can set this property?
Thank you.
My function which draws the gradients:
public LinearGradientBrush getGradient(Color c1, Color c2, double opacity)
{
LinearGradientBrush gradient = new LinearGradientBrush();
gradient.StartPoint = new Point(0, 0);
gradient.EndPoint = new Point(1, 1);
gradient.GradientStops.Add(new GradientStop(c1, 0.0));
gradient.GradientStops.Add(new GradientStop(c2, 1.0));
gradient.Opacity = opacity;
return gradient;
}
I draw the gradients off of the two most dominant colors in an AlbumCover. You can see the two colors on the top left of the window. I then call the getGradient-function with this:
getGradient(Colors[0], Colors[1], 0.5); // 0.5 is dynamic depending on the brightness of those colors. Tried with 1 opacity but it's still the same.
Here are the sample images (in PNG and uploaded without compression)
Image1
Image2
Image3
As you can see, there is banding going on. There are worse examples but I can't remember what Cover gave it.
Please notice that Image1 does not have banding on it's AlbumCover. Even though there is a gradient on it.
By doing a quick search I found some suggestions that the issue may be just a visual effect that is a result of having only 256 values for each of R, G and B channels that defines a color and the way that gradients work. If You try to cover a large area with a gradient, it'll divide it into smaller areas filled with solid colors, slightly changing between neighbouring areas. Additionally, there is an optical illusion called Mach bands that makes the borders of the areas even more visible.
Take a look at those links for more information and some suggested solutions:
how to make the brush smooth without lines in the middle
http://social.msdn.microsoft.com/Forums/vstudio/en-US/cea96578-a6b3-4b29-b813-e3643d7770ae/lineargradientbrush-can-see-individual-gradient-steps?forum=wpf
After digging around a long time I finally found the best solution:
Adding a little bit of noise to the image! This does mean I have to draw the gradient myself, but I believe the quality will be much better.
I will update this post with the algorithm itself and examples when I'm done writing.
Stay tuned I guess.

Is there an easy way to alter text colour based on background colour? [duplicate]

This question already has answers here:
Draw text on a .net Control with negative color of the background - blend
(2 answers)
Closed 8 years ago.
I have a menu whereby a user can select colours, I display them like this:
Because I write the colour codes in black, the dark blue background makes it difficult to read and the black is obviously completely hidden. Firstly, this isn't particularly important, the colour is what the user is interested in.
I could put the colour code in a separate box on a white background, but out of interest I wondered if there was some standard code to handle this or some easy method that could be applied to ensure that the text was always readable? If anyone could point me to a resource with any help it would be appreciated.
I would just choose white if the colour is dark and black if it is light. Many applications do that, but I don't think there is standard implementation in .net libraries.
Try something like:
Color ForegroundForBackground(Color bg) {
if(bg.R*2 + bg.G*7 + bg.B < 500)
return Color.White;
else
return Color.Black;
}
You want to use white on pure blue, but not on pure gren and pure red because those look brighter. Tune the number to what looks sensible.
Edit: Since j.k. kindly provided the link to Luminance (colorimetry), I've changes the linear combination to match better (rounded the numbers to 1 digit, don't really need more). Though I suspect the coefficient for green might prove too large in testing.
Yes, it should be possible to adjust the color dynamically.
There are two parts to your question. The first is changing the color and the second is determining what to change the color to.
The first is the more complex of the two. I see two primary options:
Create your own control by inheriting from the existing control and override the appropriate functions to check the background in order to return a contrasting foreground color.
Create a value converter and bind your foreground colors to the return from the converter.
Of those two options, the value converter gives you the greatest portability across controls. But it may or may not work with the UI technology that you're using.
The second step, determining what color to use, is a little bit more straightforward. This and this are two SO questions that deal with reversing or inverting the color. There are some edge cases based upon saturation that may not work the way you expect. Alternatively, if your background colors are limited you can simply use a lookup table and be certain the results are what you expect.

Default 3D chart transparency with ASP.NET Chart Control?

like two guys before me there and second one there I have difficulty with 3D chart.
How to force them to be transparent like this picture:
taken from 3D Area chart example shipped with ASP.NET Chart controls. This chart has ChartColorPalette.BrightPastel pallete, but is transparent.
I have also 3D chart with ChartColorPalette.BrightPastel palette, but is not transparent and I still cannot found way how to make it transparent like example chart. (After examining example markup and codebehind):
The only way I've found is to set the color of series with alpha channel for transparency, or use color palette with transparent colors (for example ChartColorPalette.SemiTransparent) but there must be some other default way which I'm missing.
Reason I really need this to know is that I'm creating graphs without any code behind just using markup, so I'm finding it a little bit redundant to create code snippets only because of this.
Thank you very much for any answers.
Edit: I'm using .NET 3.5 version of ASP.NET charts.
I'd same problem here. Solved using this:
// After all series manipulation, add this
chart.ApplyPaletteColors();
foreach (var serie in chart.Series)
serie.Color = Color.FromArgb(220, serie.Color);
I see you're on this thread too. Unfortunately, you do need to use colors with an alpha channel in order to set transparency AFAIK
Here's a good overview of the palettes available and some basics on manipulating them
My guess is that you could create a new palette by iterating over the colors in the bright pastel palette and adding an alpha channel - if you do this in a global static, perhaps as part of your webapp init logic, you should be able to reference it pretty easily - if you don't want to have any codebehind, you ?may? be able to databind your custom palette to the CustomPalette property, but I can't say with certainty.
If you do use palette, and not one color per series, you have to set color for every point:
myChart.ApplyPaletteColors();
foreach (var series in myChart.Series)
{
foreach (var point in series.Points)
{
point.Color = Color.FromArgb(220, point.Color);
}
}

C# ToolStripPanel Drawing Question

I am trying to get a ToolStripPanel to have the same drawing style as the embedded ToolStrips, so that it looks like one continuous bar. I have the ToolStrips using the ToolStripProfessionalRenderer so that they are styled the same as the Windows Task Bar.
I have gotten close by creating a new Renderer derived from ToolStripProfessionalRenderer:
class CustomRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderToolStripPanelBackground(ToolStripPanelRenderEventArgs e)
{
base.OnRenderToolStripPanelBackground(e);
LinearGradientBrush lgb = new LinearGradientBrush(e.ToolStripPanel.ClientRectangle, this.ColorTable.ToolStripGradientBegin, this.ColorTable.ToolStripGradientEnd, LinearGradientMode.Vertical);
e.Graphics.FillPath(lgb, e.ToolStripPanel.ClientRectangle);
}
}
This creates the gradient look with the correct colors, but they do not match up quite right. It seems as if the gradient has a higher number of colors, so the spread is drawn out longer.
I have accounted for the border of the ToolStrips (which is not shown in this code), yet they still don't match up quite right.
Anyone know how to make this happen?
I finally figured this out -- and I seems so obvious now.
The ColorTable in the ToolStripPanelProfessionalRenderer has three colors we are interested in:
ColorTable.ToolStripGradientBegin
ColorTable.ToolStripGradientMiddle
ColorTable.ToolStripGradientEnd
The background needs to be painted in two parts -- the top gradient, and the bottom gradient.
The top goes from the 'Begin' color to the 'Middle' color, and the bottom goes from the 'Middle' color to the 'End' color.
Looks perfect...
Check the color depth of your setup. We had a similar issue on systems that didn't have 32-bit color. Anything less than 32-bit color, resulted in subtle differences. 32-bit color systems looked fine.
We never did find a solution, but maybe you can push the 32-bit color requirement onto your users. ;-)

Categories