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

[FEATURE] Expose API for registering new codecs #2992

Open
1 task done
TomEdwardsEnscape opened this issue Sep 9, 2024 · 4 comments
Open
1 task done

[FEATURE] Expose API for registering new codecs #2992

TomEdwardsEnscape opened this issue Sep 9, 2024 · 4 comments

Comments

@TomEdwardsEnscape
Copy link

Is your feature request related to a problem?

I want to add new image codecs for image formats which are not supported by the built-in Skia codecs. This is not currently possible, even though Skia itself supports it. There is no C# API and the C++ API has been excluded from the native library.

Describe the solution you would like

The native API, SkCodec::Register, requires a pointer to a C++ object.

Since this is not easy to wrap in C#, it would be acceptable just to expose the native API in your build of the native Skia library. We can then write and register a codec ourselves in a small native library.

Describe alternatives you have considered

There are no alternatives.

Additional context

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct
@TomEdwardsEnscape
Copy link
Author

I dug into things and found that the non-exported method isn't a decision made by the SkiaSharp team, but a result of the mono/skia repo missing this upsteam bug fix: google/skia@ec70dfb

@mattleibow
Copy link
Contributor

How would the perfect C# API look?

In my tired brain, it came up with this:

void Test()
{
	RegisterDecoder("png", new PngDecoder());
}

void RegisterDecoder(string id, ISKCodecDecoder decoder)
{
}

interface ISKCodecDecoder
{
	bool CanDecode(ReadOnlySpan<byte> data);

	SKCodec Decode(SKStream stream, out SKCodecResult result);
}

Not sure we need to expose the exact same API that skia uses.

@mattleibow
Copy link
Contributor

Looking at the code for SKCodec, there are quite a few things that we will need to first expose before you can possibly inherit from SKCodec.

@TomEdwardsEnscape
Copy link
Author

Our use can also requires encoding. It's reasonable to separate the two interfaces, but having them merged and throwing NotSupportedException is also OK.

A way to retrieve a codec by name is required, since the current Encode methods use the SKEncodedImageFormat enum, which cannot be extended. We don't need to do anything special for the decoder as Skia automatically finds the correct one.

The ideal interface would bypass the SKCodec type entirely, and just convert between a stream and an image, or vice versa. However there are a lot of fiddly methods on the native SKCodec class, and some (or even most) may need to be implemented in C# too.

public static class SKCodec
{
	public static ISKCodecEncoder GetEncoder(string extension) {}

	void RegisterEncoder(string id, ISKCodecEncoder encoder) {}
	void RegisterDecoder(string id, ISKCodecDecoder decoder) {}

	public static void Encode(this SKImage, string extension, SKStream destination) {}
	public static SKData Encode(this SKImage image, string extension) {}
}

interface ISKCodecEncoder
{
	void Encode(SKImage image, SKStream destination);
	SKData Encode(SKImage image);
}

interface ISKCodecDecoder
{
	bool CanDecode(ReadOnlySpan<byte> data);

	SKImage Decode(SKStream source);
}

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

Successfully merging a pull request may close this issue.

2 participants