Open deakjahn opened 5 years ago
Just for illustration, in SkiaSharp.Views.Android\SKCanvasView.cs, line 50:
info = new SKImageInfo(0, 0, SKColorType.Rgba8888, SKAlphaType.Premul);
There is no colorspace definition at the end. You can't simply assume that whatever default there is is always the one the user actually wants.
This is a good point. Will a property (and maybe a constructor overload) that provides a place to set the desired colorspace be useful?
How would you want to set/specify a colorspace in your current usage? Also, if you were to specify a colorsapce, what other options will you need for the view to create a correct surface with that colorspace?
A constructor could be OK with UI created in code but doesn't help much with XAML. Isn't a property too late for the initialization? If it can be solved, that would be just fine. You could have an enum with Default and all the ready made spaces but I don't know how you would supply an ICC file if need be.
Perhaps if we knew if the passed SKImageInfo could be replaced later on or had to be absolutely ready and final when the surface is created.
A property might work because I technically only guarantee the surface during the draw method. If you change the colorspace, all we have to do is nuke the surface and invalidate. Then the draw method will re-create the surface with the new colorspace.
I probably will have to create a system like with the Brush of UWP/WPF because some of the colorspaces have additional parameters:
class abstract SKBaseColorSpace {
public SKColorSpace ColorSpace { get; }
}
class SKSrgbColorSpace : SKBaseColorSpace {
public bool IsLinear { get; set; }
}
class SKIccColorSpace : SKBaseColorSpace {
public ImageSource Icc { get; set; } // to byte[]
}
class SKRgbColorSpace : SKBaseColorSpace {
// one of these
public SKNamedGamma Gamma { get; set; } // enum
public SKColorSpaceTransferFn Gamma { get; set; } // struct
// with one of these
public SKColorSpaceGamut Gamut { get; set; } // enum
public SKMatrix44 Gamut { get; set; } // struct
}
<SKCanvasView>
<!-- sRGB -->
<SKSrgbColorSpace IsLinear="true" />
<!-- ICC -->
<SKIccColorSpace Icc="my_colors.icc" />
<!-- RGB -->
<SKRgbColorSpace Gamma="TwoDotTwoCurve" Gamut="AdobeRgb" />
<SKRgbColorSpace Gamma="1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0" Gamut="0.4360747, 0.3850649, 0.1430804, 0.2225045, 0.7168786, 0.0606169, 0.0139322, 0.0971045, 0.7141733" />
<SKCanvasView.ColorSpace>
</SKCanvasView>
This may be harder to do because not everything is great in XAML. Also, this is drawing logic, so there can be no delays.
With the ICC, this file may take a second to load, and we can't have the drawing freezing. So, do we just go with nothing and have bad colors for a few frames? Do we force this to be loaded synchronously and then set - basically this is a byte[] property?
With the RGB, there is a a combo of two properties, each of which can either be an enum value or a matrix-like format.
This might be more complicated than really necessary, although elegant. I could totally accept that spaces that need construction (full CreateRgb
and CreateIcc
) are only available through a constructor. Even if you use XAML predominantly, it's not that big a deal to instantiate one view yourself in specific cases. Then you'd only need to provide an enum for the simple cases:
Default, Srgb, SrgbLinear, AdobeRgb, etc
But you could include specific CreateRgb
cases as well, this might be where AdobeRgb
comes from.
If you only allow the CreateRgb(SKColorSpaceRenderTargetGamma.Linear, SKColorSpaceGamut, SKColorSpaceFlags)
form, then you have a still affordable solution like:
<SKCanvasView ColorSpace="Default" />
<SKCanvasView ColorSpace="Srgb" />
<SKCanvasView ColorSpace="AdobeRgb" />
Or, an alternative solution for the more complicated cases could be a static property that you need to fill in with the space before the canvas view gets created, practically in the constructor before InitializeComponent()
. Then either coefficients or color profiles could be read whenever the user sees fit, during app startup, and simply provided as a ready SKColorSpace
when necessary. And it also can be reused across the application, if necessary (eg. I have a list view where each cell has a canvas, it would be logical to use a single color space instance for them all).
It looks like
SKCanvasView
always get created using anSKImageInfo
that lacks colorspace specification. Wouldn't there be a way to specify the color space we want our canvases to be created with? Converting images allows us to specify color space at both ends but drawing onto the canvas does not, so Skia's color corrected behavior doesn't kick in at all.