Skip to content
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

SKCanvasView default colorspace #732

Open
deakjahn opened this issue Dec 15, 2018 · 5 comments
Open

SKCanvasView default colorspace #732

deakjahn opened this issue Dec 15, 2018 · 5 comments

Comments

@deakjahn
Copy link

deakjahn commented Dec 15, 2018

It looks like SKCanvasView always get created using an SKImageInfo 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.

VS bug #753284

@deakjahn
Copy link
Author

deakjahn commented Dec 17, 2018

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.

@mattleibow
Copy link
Contributor

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?

@deakjahn
Copy link
Author

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.

@mattleibow
Copy link
Contributor

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.

@deakjahn
Copy link
Author

deakjahn commented Dec 18, 2018

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: New
Development

No branches or pull requests

3 participants