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

SKAndroidCodec (DEPENDANT PR) #2152

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions binding/Binding/Definitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,83 @@ public readonly override int GetHashCode ()
}
}

public struct SKAndroidCodecOptions : IEquatable<SKAndroidCodecOptions>
{
public static readonly SKAndroidCodecOptions Default;

static SKAndroidCodecOptions()
{
Default = new SKAndroidCodecOptions(SKZeroInitialized.No);
}

public SKAndroidCodecOptions(SKZeroInitialized zeroInitialized)
{
ZeroInitialized = zeroInitialized;
Subset = null;
SampleSize = 1;
}
public SKAndroidCodecOptions(SKZeroInitialized zeroInitialized, SKRectI subset)
{
ZeroInitialized = zeroInitialized;
Subset = subset;
SampleSize = 1;
}
public SKAndroidCodecOptions(SKRectI subset)
{
ZeroInitialized = SKZeroInitialized.No;
Subset = subset;
SampleSize = 1;
}
public SKAndroidCodecOptions(int frameIndex)
{
ZeroInitialized = SKZeroInitialized.No;
Subset = null;
SampleSize = 1;
}
public SKAndroidCodecOptions(int frameIndex, int priorFrame)
{
ZeroInitialized = SKZeroInitialized.No;
Subset = null;
SampleSize = 1;
}

public SKZeroInitialized ZeroInitialized { readonly get; set; }
public SKRectI? Subset { readonly get; set; }
public readonly bool HasSubset => Subset != null;
public int SampleSize { readonly get; set; }

[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete]
public SKTransferFunctionBehavior PremulBehavior
{
readonly get => SKTransferFunctionBehavior.Respect;
set { }
}

public readonly bool Equals(SKAndroidCodecOptions obj) =>
ZeroInitialized == obj.ZeroInitialized &&
Subset == obj.Subset &&
SampleSize == obj.SampleSize;

public readonly override bool Equals(object obj) =>
obj is SKAndroidCodecOptions f && Equals(f);

public static bool operator ==(SKAndroidCodecOptions left, SKAndroidCodecOptions right) =>
left.Equals(right);

public static bool operator !=(SKAndroidCodecOptions left, SKAndroidCodecOptions right) =>
!left.Equals(right);

public readonly override int GetHashCode()
{
var hash = new HashCode();
hash.Add(ZeroInitialized);
hash.Add(Subset);
hash.Add(SampleSize);
return hash.ToHashCode();
}
}

public partial struct SKFontMetrics
{
private const uint flagsUnderlineThicknessIsValid = (1U << 0);
Expand Down
286 changes: 286 additions & 0 deletions binding/Binding/SKAndroidCodec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
using System;
using System.ComponentModel;
using System.IO;

namespace SkiaSharp
{
public unsafe class SKAndroidCodec : SKObject, ISKSkipObjectRegistration
{
internal SKAndroidCodec(IntPtr handle, bool owns)
: base(handle, owns)
{
}

protected override void Dispose(bool disposing) =>
base.Dispose(disposing);

protected override void DisposeNative() =>
SkiaApi.sk_android_codec_destroy(Handle);

public SKImageInfo Info
{
get
{
SKImageInfoNative cinfo;
SkiaApi.sk_android_codec_get_info(Handle, &cinfo);
return SKImageInfoNative.ToManaged(ref cinfo);
}
}

public SKCodec Codec =>
SKCodec.GetObject(SkiaApi.sk_android_codec_get_codec(Handle));

public SKColorSpaceIccProfile ICCProfile =>
SKColorSpaceIccProfile.GetObject(SkiaApi.sk_android_codec_get_icc_profile(Handle));

public SKEncodedImageFormat EncodedFormat =>
SkiaApi.sk_android_codec_get_encoded_format(Handle);

public SKColorType ComputeOutputColorType(SKColorType requestedColorType)
{
return SkiaApi.sk_android_codec_compute_output_color_type(Handle, requestedColorType.ToNative()).FromNative();
}

public SKAlphaType ComputeOutputAlphaType(bool requestedUnpremul)
{
return SkiaApi.sk_android_codec_compute_output_alpha(Handle, requestedUnpremul);
}

public SKColorSpace ComputeOutputColorSpace(SKColorType outputColorType, SKColorSpace preferredColorSpace)
{
return SKColorSpace.GetObject(SkiaApi.sk_android_codec_compute_output_color_space(Handle, outputColorType.ToNative(), preferredColorSpace == null ? IntPtr.Zero : preferredColorSpace.Handle));
}

public SKSizeI GetSampledDimensions(int sampleSize)
{
SKSizeI dimensions;
SkiaApi.sk_android_codec_get_sampled_dimensions(Handle, sampleSize, &dimensions);
return dimensions;
}

public bool GetSupportedSubset(ref SKRectI desiredSubset)
{
fixed (SKRectI* ds = &desiredSubset)
{
return SkiaApi.sk_android_codec_get_supported_subset(Handle, ds);
}
}

public SKSizeI GetSampledSubsetDimensions(int sampleSize, ref SKRectI desiredSubset)
{
SKSizeI dimensions;
fixed (SKRectI* ds = &desiredSubset)
{
SkiaApi.sk_android_codec_get_sampled_subset_dimensions(Handle, sampleSize, &dimensions, ds);
}
return dimensions;
}

// android pixels

public SKCodecResult GetAndroidPixels (out byte[] pixels, SKAndroidCodecOptions options) =>
GetAndroidPixels (Info, out pixels, options);

public SKCodecResult GetAndroidPixels (SKImageInfo info, out byte[] pixels, SKAndroidCodecOptions options)
{
pixels = new byte[info.BytesSize];
return GetAndroidPixels (info, pixels, options);
}

public SKCodecResult GetAndroidPixels (SKImageInfo info, byte[] pixels, SKAndroidCodecOptions options)
{
if (pixels == null)
throw new ArgumentNullException (nameof (pixels));

fixed (byte* p = pixels) {
return GetAndroidPixels (info, (IntPtr)p, info.RowBytes, options);
}
}

public SKCodecResult GetAndroidPixels (SKImageInfo info, IntPtr pixels, SKAndroidCodecOptions options) =>
GetAndroidPixels (info, pixels, info.RowBytes, options);

public SKCodecResult GetAndroidPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKAndroidCodecOptions options)
{
if (pixels == IntPtr.Zero)
throw new ArgumentNullException (nameof (pixels));

if (options == null)
throw new ArgumentNullException (nameof (options));

var nInfo = SKImageInfoNative.FromManaged (ref info);
var nOptions = new SKAndroidCodecOptionsInternal {
fZeroInitialized = options.ZeroInitialized,
fSubset = null,
fSampleSize = options.SampleSize,
};
var subset = default (SKRectI);
if (options.HasSubset) {
subset = options.Subset.Value;
nOptions.fSubset = &subset;
}
return SkiaApi.sk_android_codec_get_android_pixels (Handle, &nInfo, (void*)pixels, (IntPtr)rowBytes, &nOptions);
}

// android pixels simplified

public byte[] AndroidPixelsSimplified {
get {
var result = GetAndroidPixelsSimplified (out var pixels);
if (result != SKCodecResult.Success && result != SKCodecResult.IncompleteInput) {
throw new Exception (result.ToString ());
}
return pixels;
}
}

public SKCodecResult GetAndroidPixelsSimplified (out byte[] pixels) =>
GetAndroidPixelsSimplified (Info, out pixels);

public SKCodecResult GetAndroidPixelsSimplified (SKImageInfo info, out byte[] pixels)
{
pixels = new byte[info.BytesSize];
return GetAndroidPixelsSimplified (info, pixels);
}

public SKCodecResult GetAndroidPixelsSimplified (SKImageInfo info, byte[] pixels)
{
if (pixels == null)
throw new ArgumentNullException (nameof (pixels));

fixed (byte* p = pixels) {
return GetAndroidPixelsSimplified (info, (IntPtr)p, info.RowBytes);
}
}

public SKCodecResult GetAndroidPixelsSimplified (SKImageInfo info, IntPtr pixels) =>
GetAndroidPixelsSimplified (info, pixels, info.RowBytes);

public SKCodecResult GetAndroidPixelsSimplified (SKImageInfo info, IntPtr pixels, int rowBytes)
{
if (pixels == IntPtr.Zero)
throw new ArgumentNullException (nameof (pixels));

var nInfo = SKImageInfoNative.FromManaged (ref info);
return SkiaApi.sk_android_codec_get_android_pixels_simplified (Handle, &nInfo, (void*)pixels, (IntPtr)rowBytes);
}


// pixels

public byte[] Pixels
{
get
{
var result = GetPixels(out var pixels);
if (result != SKCodecResult.Success && result != SKCodecResult.IncompleteInput)
{
throw new Exception(result.ToString());
}
return pixels;
}
}

public SKCodecResult GetPixels(out byte[] pixels) =>
GetPixels(Info, out pixels);

public SKCodecResult GetPixels(SKImageInfo info, out byte[] pixels)
{
pixels = new byte[info.BytesSize];
return GetPixels(info, pixels);
}

public SKCodecResult GetPixels(SKImageInfo info, byte[] pixels)
{
if (pixels == null)
throw new ArgumentNullException(nameof(pixels));

fixed (byte* p = pixels)
{
return GetPixels(info, (IntPtr)p, info.RowBytes);
}
}

public SKCodecResult GetPixels(SKImageInfo info, IntPtr pixels, int rowBytes)
{
if (pixels == IntPtr.Zero)
throw new ArgumentNullException(nameof(pixels));

var nInfo = SKImageInfoNative.FromManaged(ref info);
return SkiaApi.sk_android_codec_get_pixels(Handle, &nInfo, (void*)pixels, (IntPtr)rowBytes);
}

// create (Codec)

public static SKAndroidCodec Create(SKCodec codec)
{
return Create(codec, SKAndroidCodecExifOrientationBehavior.KIgnore);
}

public static SKAndroidCodec Create(SKCodec codec, SKAndroidCodecExifOrientationBehavior behavior)
{
if (codec == null)
throw new ArgumentNullException(nameof(codec));
var handle = SkiaApi.sk_android_codec_new_from_codec(codec.Handle, behavior);
SKAndroidCodec c = GetObject(handle);
codec.RevokeOwnership(c);
return c;
}

// create (streams)

public static SKAndroidCodec Create(string filename) =>
Create(filename, null);

public static SKAndroidCodec Create(string filename, SKPngChunkReader chunkReader)
{
if (filename == null)
throw new ArgumentNullException (nameof(filename));

var stream = SKFileStream.OpenStream(filename);
if (stream == null)
{
return null;
}

return Create(stream, chunkReader);
}


public static SKAndroidCodec Create(SKStream stream) =>
Create(stream, null);

public static SKAndroidCodec Create(SKStream stream, SKPngChunkReader chunkReader)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
if (stream is SKFileStream filestream && !filestream.IsValid)
throw new ArgumentException("File stream was not valid.", nameof(stream));

var codec = GetObject(SkiaApi.sk_android_codec_new_from_stream(stream.Handle, chunkReader == null ? IntPtr.Zero : chunkReader.Handle));
stream.RevokeOwnership(codec);
return codec;
}


// create (data)

public static SKAndroidCodec Create(SKData data)
{
return Create(data, null);
}

public static SKAndroidCodec Create(SKData data, SKPngChunkReader chunkReader)
{
if (data == null)
throw new ArgumentNullException(nameof(data));

return GetObject(SkiaApi.sk_android_codec_new_from_data(data.Handle, chunkReader == null ? IntPtr.Zero : chunkReader.Handle));
}

// utils

internal static SKAndroidCodec GetObject(IntPtr handle) =>
handle == IntPtr.Zero ? null : new SKAndroidCodec(handle, true);
}
}
3 changes: 3 additions & 0 deletions binding/Binding/SKColorSpaceStructs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -527,5 +527,8 @@ public static SKColorSpaceIccProfile Create (IntPtr data, long length)
}
return icc;
}

internal static SKColorSpaceIccProfile GetObject(IntPtr handle) =>
handle == IntPtr.Zero ? null : new SKColorSpaceIccProfile(handle, true);
}
}
Loading