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

Png chunk reader codec bitmap #2149

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
504a32e
add /.idea to git ignore
mgood7123 Jul 1, 2022
c418306
Merge pull request #2 from mono/main
mgood7123 Jul 3, 2022
7b9a53e
Merge branch 'mono:main' into main
mgood7123 Jul 7, 2022
de972eb
add SKPngChunkReader
mgood7123 Jul 7, 2022
bcf7b54
add SKPngChunkReader bindings
mgood7123 Jul 7, 2022
f7600da
add renamed SKPngChunkReader bindings
mgood7123 Jul 7, 2022
155a87a
expose more of SKCodec
mgood7123 Jul 7, 2022
996d8cf
expose more SKCodec bindings
mgood7123 Jul 7, 2022
2285f86
expose more of SKBitmap
mgood7123 Jul 7, 2022
bd7ee47
expose more SKBitmap bindings
mgood7123 Jul 7, 2022
4c198f6
remove api meant for other PR
mgood7123 Jul 7, 2022
c5cd679
add cpp files to tizen
mgood7123 Jul 7, 2022
afc7a9f
add json changes
mgood7123 Jul 8, 2022
0c000d4
rename to match
mgood7123 Jul 8, 2022
1fc7c6e
rename to match
mgood7123 Jul 8, 2022
c618eec
rename to match
mgood7123 Jul 9, 2022
3a55937
fix bindings json
mgood7123 Jul 9, 2022
5c3586b
fix params
mgood7123 Jul 9, 2022
dca69e2
fix bindings
mgood7123 Jul 9, 2022
5dfbf18
SKCodec.SelectionPolicy -> SKCodecSelectionPolicy
mgood7123 Jul 9, 2022
4307413
fix enum
mgood7123 Jul 9, 2022
cf7eee8
regenerate bindings
mgood7123 Jul 9, 2022
0c9f33b
fix enum
mgood7123 Jul 9, 2022
c134ffb
fix C# binding callbacks
mgood7123 Jul 9, 2022
334b7c3
fix incorrect member name
mgood7123 Jul 9, 2022
e8bdd75
remove comments, cleanup ReadChunk api
mgood7123 Jul 12, 2022
b362f1a
removed needlessly overriden Dispose
mgood7123 Jul 12, 2022
368b72e
Merge branch 'main' into png_chunk_reader_codec_bitmap
mgood7123 Jul 12, 2022
052ee1c
fix abstract ReadChunk having method body
mgood7123 Aug 6, 2022
b12d3e2
Merge remote-tracking branch 'origin/png_chunk_reader_codec_bitmap' i…
mgood7123 Aug 6, 2022
0325714
Merge branch 'main' into png_chunk_reader_codec_bitmap
mattleibow Aug 8, 2022
b71e029
Merge branch 'main' into pr/2149
mattleibow Aug 14, 2022
6077608
Run code formatter
mattleibow Aug 14, 2022
09a7d2b
reduce overloads
mattleibow Aug 14, 2022
80b5fd1
Adding some tests
mattleibow Aug 15, 2022
44a5ecc
Update SKPngChunkReader.cs
mgood7123 Aug 21, 2022
64241d9
modify for Non Standard chunk
mgood7123 Aug 26, 2022
b6ad3dd
Add files via upload
mgood7123 Aug 26, 2022
ff367a2
Update SKCodecTest.cs
mgood7123 Aug 26, 2022
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
88 changes: 86 additions & 2 deletions binding/Binding/SKBitmap.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Threading;

namespace SkiaSharp
{
Expand Down Expand Up @@ -37,8 +38,6 @@ public static SKFilterQuality ToFilterQuality (this SKBitmapResizeMethod method)
}

// TODO: keep in mind SKBitmap may be going away (according to Google)
// TODO: `ComputeIsOpaque` may be useful
// TODO: `GenerationID` may be useful
// TODO: `GetAddr` and `GetPixel` are confusing

public unsafe class SKBitmap : SKObject, ISKSkipObjectRegistration
Expand Down Expand Up @@ -115,6 +114,56 @@ protected override void Dispose (bool disposing) =>
protected override void DisposeNative () =>
SkiaApi.sk_bitmap_destructor (Handle);

// Other

public bool SetInfo(SKImageInfo info)
{
// bool setInfo (const SkImageInfo &imageInfo, size_t rowBytes=0)
return SetInfo(info, 0);
}

public bool SetInfo(SKImageInfo info, int rowBytes)
{
var cinfo = SKImageInfoNative.FromManaged(ref info);
return SkiaApi.sk_bitmap_set_info(Handle, &cinfo, (IntPtr)rowBytes);
}

public bool ComputeIsOpaque()
{
return SkiaApi.sk_bitmap_compute_is_opaque(Handle);
}

// AllocPixels

public void AllocPixels(SKImageInfo info)
{
AllocPixels(info, info.RowBytes);
}

public void AllocPixels(SKImageInfo info, int rowBytes)
{
if (!TryAllocPixels(info, rowBytes))
{
SKImageInfo i = Info;
throw new OutOfMemoryException("SkBitmap::tryAllocPixels failed "
+ "ColorType:" + i.ColorType + "AlphaType:" + i.AlphaType +
"[w:" + i.Width + " h:" + i.Height + "] rb:" + RowBytes
);
}
}

public void AllocPixels(SKImageInfo info, SKBitmapAllocFlags flags)
{
if (!TryAllocPixels(info, flags))
{
SKImageInfo i = Info;
throw new OutOfMemoryException("SkBitmap::tryAllocPixels failed "
+ "ColorType:" + i.ColorType + "AlphaType:" + i.AlphaType +
"[w:" + i.Width + " h:" + i.Height + "] rb:" + RowBytes
);
}
}

// TryAllocPixels

public bool TryAllocPixels (SKImageInfo info)
Expand Down Expand Up @@ -317,6 +366,8 @@ public bool ExtractAlpha (SKBitmap destination, SKPaint paint, out SKPointI offs
}
}

public SKImage AsImage () => SKImage.FromBitmap (this);

// properties

public bool ReadyToDraw => SkiaApi.sk_bitmap_ready_to_draw (Handle);
Expand Down Expand Up @@ -361,6 +412,10 @@ public int ByteCount {
get { return (int)SkiaApi.sk_bitmap_get_byte_count (Handle); }
}

public uint GenerationId {
get { return (uint)SkiaApi.sk_bitmap_get_generation_id(Handle); }
}

// *Pixels*

public IntPtr GetPixels () =>
Expand Down Expand Up @@ -401,6 +456,14 @@ public void SetColorTable (SKColorTable ct)

// more properties

public SKPixmap Pixmap {
get {
var pixmap = new SKPixmap (SkiaApi.sk_bitmap_get_pixmap (Handle), false); // pixmap is owned by this
pixmap.pixelSource = this;
return pixmap;
}
}
mgood7123 marked this conversation as resolved.
Show resolved Hide resolved

public byte[] Bytes {
get {
var array = GetPixelSpan ().ToArray ();
Expand Down Expand Up @@ -723,6 +786,27 @@ public bool InstallPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKBitm
return SkiaApi.sk_bitmap_install_pixels (Handle, &cinfo, (void*)pixels, (IntPtr)rowBytes, proxy, (void*)ctx);
}

public bool ReadPixels (SKImageInfo info, IntPtr dstpixels, int rowBytes, int x, int y)
{
if (GetPixels() == null) return false;
mgood7123 marked this conversation as resolved.
Show resolved Hide resolved
return Pixmap.ReadPixels(info, dstPixels, rowBytes, x, y);
}

public bool ReadPixels(SKPixmap dstPixmap) => ReadPixels(dstPixmap, 0, 0);

public bool ReadPixels(SKPixmap pixmap, int x, int y)
{
if (GetPixels() == null) return false;
return Pixmap.ReadPixels(dst.Info, dst.Pixels, dst.RowBytes, srcX, srcY);
}

public bool WritePixels(SKPixmap pixmap) => WritePixels(pixmap, 0, 0);

public bool WritePixels(SKPixmap dstPixmap, int x, int y)
{
return SkiaApi.sk_bitmap_write_pixels_at_location(Handle, dstPixmap.Handle, x, y);
}

public bool InstallPixels (SKPixmap pixmap)
{
return SkiaApi.sk_bitmap_install_pixels_with_pixmap (Handle, pixmap.Handle);
Expand Down
118 changes: 107 additions & 11 deletions binding/Binding/SKCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace SkiaSharp
{
// TODO: `Create(...)` should have overloads that accept a SKPngChunkReader
// TODO: missing the `QueryYuv8` and `GetYuv8Planes` members

public unsafe class SKCodec : SKObject, ISKSkipObjectRegistration
Expand All @@ -14,6 +13,25 @@ internal SKCodec (IntPtr handle, bool owns)
{
}

/// <summary>
/// For container formats that contain both still images and image sequences,
/// <br></br> instruct the decoder how the output should be selected. (Refer to comments
/// <br></br> for each value for more details.)
/// </summary>
mattleibow marked this conversation as resolved.
Show resolved Hide resolved
public enum SelectionPolicy
mgood7123 marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// If the container format contains both still images and image sequences,
/// <br></br> SKCodec should choose one of the still images. This is the default.
/// </summary>
preferStillImage,
/// <summary>
/// If the container format contains both still images and image sequences,
/// <br></br> SKCodec should choose one of the image sequences for animation.
/// </summary>
preferAnimation
}

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

Expand Down Expand Up @@ -42,6 +60,13 @@ public SKImageInfo Info {
public SKEncodedImageFormat EncodedFormat =>
SkiaApi.sk_codec_get_encoded_format (Handle);

public SKSizeI Dimensions
{
get {
return Info.Size;
}
}

public SKSizeI GetScaledDimensions (float desiredScale)
{
SKSizeI dimensions;
Expand Down Expand Up @@ -282,48 +307,119 @@ public int GetOutputScanline (int inputScanline) =>
public static SKCodec Create (string filename) =>
Create (filename, out var result);

public static SKCodec Create (string filename, out SKCodecResult result)
public static SKCodec Create(string filename, SKPngChunkReader chunkReader) =>
Create(filename, out var result, chunkReader, SelectionPolicy.preferStillImage);

public static SKCodec Create(string filename, SelectionPolicy selectionPolicy) =>
Create(filename, out var result, null, selectionPolicy);

public static SKCodec Create(string filename, SKPngChunkReader chunkReader, SelectionPolicy selectionPolicy) =>
Create(filename, out var result, chunkReader, selectionPolicy);



public static SKCodec Create(string filename, out SKCodecResult result) =>
Create(filename, out result, null, SelectionPolicy.preferStillImage);

public static SKCodec Create(string filename, out SKCodecResult result, SKPngChunkReader chunkReader) =>
Create (filename, out result, chunkReader, SelectionPolicy.preferStillImage);

public static SKCodec Create(string filename, out SKCodecResult result, SelectionPolicy selectionPolicy) =>
Create (filename, out result, null, selectionPolicy);

public static SKCodec Create (string filename, out SKCodecResult result, SKPngChunkReader chunkReader, SelectionPolicy selectionPolicy)
{
var stream = SKFileStream.OpenStream (filename);
if (stream == null) {
result = SKCodecResult.InternalError;
return null;
}

return Create (stream, out result);
return Create (stream, out result, chunkReader, selectionPolicy);
}



public static SKCodec Create (Stream stream) =>
Create (stream, out var result);

public static SKCodec Create(Stream stream, SKPngChunkReader chunkReader) =>
Create(stream, out var result, chunkReader);

public static SKCodec Create(Stream stream, SelectionPolicy selectionPolicy) =>
Create(stream, out var result, selectionPolicy);

public static SKCodec Create(Stream stream, SKPngChunkReader chunkReader, SelectionPolicy selectionPolicy) =>
Create(stream, out var result, chunkReader, selectionPolicy);



public static SKCodec Create (Stream stream, out SKCodecResult result) =>
Create (WrapManagedStream (stream), out result);

public static SKCodec Create(Stream stream, out SKCodecResult result, SKPngChunkReader chunkReader) =>
Create(WrapManagedStream(stream), out result, chunkReader);

public static SKCodec Create(Stream stream, out SKCodecResult result, SelectionPolicy selectionPolicy) =>
Create(WrapManagedStream(stream), out result, selectionPolicy);

public static SKCodec Create(Stream stream, out SKCodecResult result, SKPngChunkReader chunkReader, SelectionPolicy selectionPolicy) =>
Create(WrapManagedStream(stream), out result, chunkReader, selectionPolicy);



public static SKCodec Create (SKStream stream) =>
Create (stream, out var result);

public static SKCodec Create (SKStream stream, out SKCodecResult result)
public static SKCodec Create(SKStream stream, SKPngChunkReader chunkReader) =>
Create(stream, out var result, chunkReader);

public static SKCodec Create(SKStream stream, SelectionPolicy selectionPolicy) =>
Create(stream, out var result, selectionPolicy);

public static SKCodec Create(SKStream stream, SKPngChunkReader chunkReader, SelectionPolicy selectionPolicy) =>
Create(stream, out var result, chunkReader, selectionPolicy);



public static SKCodec Create(SKStream stream, out SKCodecResult result) =>
Create(stream, out result, null);

public static SKCodec Create(SKStream stream, out SKCodecResult result, SKPngChunkReader chunkReader) =>
Create(stream, out result, chunkReader, SelectionPolicy.preferStillImage);

public static SKCodec Create(SKStream stream, out SKCodecResult result, SelectionPolicy selectionPolicy) =>
Create(stream, out result, null, selectionPolicy);

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

fixed (SKCodecResult* r = &result) {
var codec = GetObject (SkiaApi.sk_codec_new_from_stream (stream.Handle, r));
stream.RevokeOwnership (codec);
fixed (SKCodecResult* r = &result)
{
var codec = GetObject(SkiaApi.sk_codec_new_from_stream(stream.Handle, r, chunkReader == null ? IntPtr.Zero : chunkReader.Handle, (SKCodecSelectionPolicy)selectionPolicy));
stream.RevokeOwnership(codec);
return codec;
}
}


// create (data)

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

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

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

// utils
Expand Down
Loading