├── .github └── workflows │ └── build.yaml ├── .gitignore ├── Directory.Build.props ├── Images ├── Japanese.256.png ├── README.md ├── SkiaImageView.100.png ├── SkiaImageView.2048.png ├── u1F58C-lowerleftpaintbrush.svg └── u1F5BC-framewithpicture.svg ├── LICENSE ├── README.ja.md ├── README.md ├── SkiaImageView.Avalonia ├── BackingStore.cs ├── Interops.cs ├── Properties │ └── AssemblyInfo.cs ├── SKImageView.cs └── SkiaImageView.Avalonia.csproj ├── SkiaImageView.Avalonia11 ├── Properties │ └── AssemblyInfo.cs └── SkiaImageView.Avalonia11.csproj ├── SkiaImageView.Maui ├── BackingStore.cs ├── Interops.cs ├── Properties │ └── AssemblyInfo.cs ├── SKImageView.cs ├── SkiaImageView.Maui.csproj └── StretchDirection.cs ├── SkiaImageView.Wpf ├── BackingStore.cs ├── Interops.cs ├── Properties │ └── AssemblyInfo.cs ├── SKImageView.cs └── SkiaImageView.Wpf.csproj ├── SkiaImageView.Xamarin.Forms ├── BackingStore.cs ├── Interops.cs ├── Properties │ └── AssemblyInfo.cs ├── SKImageView.cs ├── SkiaImageView.Xamarin.Forms.csproj └── StretchDirection.cs ├── SkiaImageView.sln ├── SkiaImageView ├── Internals.cs └── SKImageView_Common.cs ├── artifacts └── .gitkeep ├── build-nupkg.bat ├── nuget.config └── samples ├── Directory.Build.props ├── SkiaImageView.Avalonia.Sample ├── SkiaImageView.Avalonia.Sample.UI │ ├── App.axaml │ ├── App.axaml.cs │ ├── SkiaImageView.Avalonia.Sample.UI.csproj │ ├── ViewModels │ │ ├── ItemViewModel.cs │ │ └── MainWindowViewModel.cs │ └── Views │ │ ├── Converters │ │ └── ScoreToBrushConverter.cs │ │ ├── MainWindow.axaml │ │ └── MainWindow.axaml.cs └── SkiaImageView.Avalonia.Sample │ ├── Program.cs │ └── SkiaImageView.Avalonia.Sample.csproj ├── SkiaImageView.Avalonia11.Sample ├── SkiaImageView.Avalonia11.Sample.Android │ ├── Icon.png │ ├── MainActivity.cs │ ├── Properties │ │ └── AndroidManifest.xml │ ├── Resources │ │ ├── AboutResources.txt │ │ ├── drawable-night-v31 │ │ │ └── avalonia_anim.xml │ │ ├── drawable-v31 │ │ │ └── avalonia_anim.xml │ │ ├── drawable │ │ │ └── splash_screen.xml │ │ ├── values-night │ │ │ └── colors.xml │ │ ├── values-v31 │ │ │ └── styles.xml │ │ └── values │ │ │ ├── colors.xml │ │ │ └── styles.xml │ └── SkiaImageView.Avalonia11.Sample.Android.csproj ├── SkiaImageView.Avalonia11.Sample.Desktop │ ├── Program.cs │ └── SkiaImageView.Avalonia11.Sample.Desktop.csproj ├── SkiaImageView.Avalonia11.Sample.UI │ ├── App.axaml │ ├── App.axaml.cs │ ├── SkiaImageView.Avalonia11.Sample.UI.csproj │ ├── ViewModels │ │ ├── ItemViewModel.cs │ │ └── MainViewModel.cs │ └── Views │ │ ├── Converters │ │ └── ScoreToBrushConverter.cs │ │ ├── MainView.axaml │ │ ├── MainView.axaml.cs │ │ ├── MainWindow.axaml │ │ └── MainWindow.axaml.cs └── SkiaImageView.Avalonia11.Sample.iOS │ ├── AppDelegate.cs │ ├── Entitlements.plist │ ├── Info.plist │ ├── Main.cs │ ├── Resources │ └── LaunchScreen.xib │ └── SkiaImageView.Avalonia11.Sample.iOS.csproj ├── SkiaImageView.Maui.Sample ├── App.xaml ├── App.xaml.cs ├── AppShell.xaml ├── AppShell.xaml.cs ├── MauiProgram.cs ├── Platforms │ ├── Android │ │ ├── AndroidManifest.xml │ │ ├── MainActivity.cs │ │ ├── MainApplication.cs │ │ └── Resources │ │ │ └── values │ │ │ └── colors.xml │ ├── MacCatalyst │ │ ├── AppDelegate.cs │ │ ├── Info.plist │ │ └── Program.cs │ ├── Tizen │ │ ├── Main.cs │ │ └── tizen-manifest.xml │ ├── Windows │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Package.appxmanifest │ │ └── app.manifest │ └── iOS │ │ ├── AppDelegate.cs │ │ ├── Info.plist │ │ └── Program.cs ├── Properties │ └── launchSettings.json ├── Resources │ ├── AppIcon │ │ ├── appicon.svg │ │ └── appiconfg.svg │ ├── Fonts │ │ ├── OpenSans-Regular.ttf │ │ └── OpenSans-Semibold.ttf │ ├── Images │ │ └── dotnet_bot.svg │ ├── Raw │ │ └── AboutAssets.txt │ ├── Splash │ │ └── splash.svg │ └── Styles │ │ ├── Colors.xaml │ │ └── Styles.xaml ├── SkiaImageView.Maui.Sample.csproj ├── ViewModels │ ├── ItemViewModel.cs │ └── MainContentPageViewModel.cs └── Views │ ├── Converters │ └── ScoreToBrushConverter.cs │ ├── MainPage.xaml │ └── MainPage.xaml.cs ├── SkiaImageView.Sample.Core ├── Models │ ├── Cat.cs │ └── TheCatAPI.cs └── SkiaImageView.Sample.Core.csproj ├── SkiaImageView.Wpf.Sample ├── App.xaml ├── App.xaml.cs ├── Properties │ └── AssemblyInfo.cs ├── SkiaImageView.Wpf.Sample.csproj ├── ViewModels │ ├── ItemViewModel.cs │ └── MainWindowViewModel.cs └── Views │ ├── Converters │ └── ScoreToBrushConverter.cs │ ├── MainWindow.xaml │ └── MainWindow.xaml.cs └── SkiaImageView.Xamarin.Forms.Sample ├── SkiaImageView.Xamarin.Forms.Sample.Android ├── Assets │ └── AboutAssets.txt ├── MainActivity.cs ├── Properties │ ├── AndroidManifest.xml │ └── AssemblyInfo.cs ├── Resources │ ├── AboutResources.txt │ ├── Resource.designer.cs │ ├── layout │ │ ├── Tabbar.xml │ │ └── Toolbar.xml │ ├── mipmap-anydpi-v26 │ │ ├── icon.xml │ │ └── icon_round.xml │ ├── mipmap-hdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ ├── mipmap-mdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ ├── mipmap-xhdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ ├── mipmap-xxhdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ ├── mipmap-xxxhdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ └── values │ │ ├── colors.xml │ │ └── styles.xml └── SkiaImageView.Xamarin.Forms.Sample.Android.csproj ├── SkiaImageView.Xamarin.Forms.Sample.UI ├── App.xaml ├── App.xaml.cs ├── Properties │ └── AssemblyInfo.cs ├── SkiaImageView.Xamarin.Forms.Sample.UI.csproj ├── ViewModels │ ├── ItemViewModel.cs │ └── MainContentPageViewModel.cs └── Views │ ├── Converters │ └── ScoreToBrushConverter.cs │ ├── MainPage.xaml │ └── MainPage.xaml.cs ├── SkiaImageView.Xamarin.Forms.Sample.UWP ├── Assets │ ├── LargeTile.scale-100.png │ ├── LargeTile.scale-200.png │ ├── LargeTile.scale-400.png │ ├── SmallTile.scale-100.png │ ├── SmallTile.scale-200.png │ ├── SmallTile.scale-400.png │ ├── SplashScreen.scale-100.png │ ├── SplashScreen.scale-200.png │ ├── SplashScreen.scale-400.png │ ├── Square150x150Logo.scale-100.png │ ├── Square150x150Logo.scale-200.png │ ├── Square150x150Logo.scale-400.png │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ ├── Square44x44Logo.scale-100.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.scale-400.png │ ├── Square44x44Logo.targetsize-16.png │ ├── Square44x44Logo.targetsize-256.png │ ├── Square44x44Logo.targetsize-48.png │ ├── StoreLogo.backup.png │ ├── StoreLogo.scale-100.png │ ├── StoreLogo.scale-200.png │ ├── StoreLogo.scale-400.png │ ├── Wide310x150Logo.scale-100.png │ ├── Wide310x150Logo.scale-200.png │ └── Wide310x150Logo.scale-400.png ├── MainPage.xaml ├── Package.appxmanifest ├── Properties │ └── Default.rd.xml ├── SkiaImageView.Xamarin.Forms.Sample.UWP.csproj ├── UwpApp.xaml └── UwpApp.xaml.cs └── SkiaImageView.Xamarin.Forms.Sample.iOS ├── AppDelegate.cs ├── Assets.xcassets └── AppIcon.appiconset │ ├── Contents.json │ ├── Icon1024.png │ ├── Icon120.png │ ├── Icon152.png │ ├── Icon167.png │ ├── Icon180.png │ ├── Icon20.png │ ├── Icon29.png │ ├── Icon40.png │ ├── Icon58.png │ ├── Icon60.png │ ├── Icon76.png │ ├── Icon80.png │ └── Icon87.png ├── Entitlements.plist ├── Info.plist ├── Main.cs ├── Properties └── AssemblyInfo.cs ├── Resources ├── Default-568h@2x.png ├── Default-Portrait.png ├── Default-Portrait@2x.png ├── Default.png ├── Default@2x.png └── LaunchScreen.storyboard └── SkiaImageView.Xamarin.Forms.Sample.iOS.csproj /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | latest 5 | enable 6 | AnyCPU 7 | 8 | true 9 | true 10 | false 11 | false 12 | true 13 | git 14 | https://github.com/kekyo/SkiaImageView.git 15 | 16 | SkiaImageView 17 | false 18 | true 19 | $(NoWarn);CS1570;CS1591 20 | 21 | SkiaImageView 22 | SkiaImageView 23 | Copyright (c) Kouji Matsui 24 | Easy way showing SkiaSharp-based image objects onto UI applications. 25 | false 26 | 27 | Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 28 | Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 29 | Apache-2.0 30 | https://github.com/kekyo/SkiaImageView 31 | SkiaImageView.100.png 32 | .pdb 33 | $(NoWarn);NU1605;NU1701;NU1803 34 | 35 | 36 | 37 | portable 38 | false 39 | false 40 | false 41 | 42 | 43 | 44 | embedded 45 | true 46 | true 47 | true 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Images/Japanese.256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/Images/Japanese.256.png -------------------------------------------------------------------------------- /Images/README.md: -------------------------------------------------------------------------------- 1 | The icon images imported from [FireFox emoji](https://github.com/mozilla/fxemoji). 2 | These items exclude FlashCap project copyright notice. 3 | 4 | ---- 5 | 6 | ## License for the Code 7 | 8 | Copyright 2015, Mozilla Foundation 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | 23 | 24 | ## License for the Visual Design 25 | 26 | ### Creative Commons Attribution 4.0 International (CC BY 4.0) 27 | https://creativecommons.org/licenses/by/4.0/legalcode 28 | or for the human readable summary: https://creativecommons.org/licenses/by/4.0/ 29 | 30 | 31 | #### You are free to: 32 | **Share** — copy and redistribute the material in any medium or format 33 | **Adapt** — remix, transform, and build upon the material for any purpose, even commercially. 34 | The licensor cannot revoke these freedoms as long as you follow the license terms. 35 | 36 | 37 | #### Under the following terms: 38 | **Attribution** — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 39 | No additional restrictions — You may not apply legal terms or **technological measures** that legally restrict others from doing anything the license permits. 40 | 41 | #### Notices: 42 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 43 | -------------------------------------------------------------------------------- /Images/SkiaImageView.100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/Images/SkiaImageView.100.png -------------------------------------------------------------------------------- /Images/SkiaImageView.2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/Images/SkiaImageView.2048.png -------------------------------------------------------------------------------- /Images/u1F58C-lowerleftpaintbrush.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 19 | 20 | 21 | 25 | 26 | 27 | 29 | 30 | 31 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /SkiaImageView.Avalonia/BackingStore.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia; 12 | using Avalonia.Media; 13 | using Avalonia.Media.Imaging; 14 | using Avalonia.Platform; 15 | using SkiaSharp; 16 | 17 | namespace SkiaImageView 18 | { 19 | internal sealed class BackingStore 20 | { 21 | private readonly SKImageInfo imageInfo; 22 | private readonly WriteableBitmap writableBitmap; 23 | private ILockedFramebuffer? locker; 24 | 25 | public BackingStore( 26 | int width, int height, ProjectionQuality projectionQuality) 27 | { 28 | this.imageInfo = new( 29 | width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); 30 | this.writableBitmap = new( 31 | new(imageInfo.Width, imageInfo.Height), new(96.0, 96.0), PixelFormat.Bgra8888, AlphaFormat.Premul); 32 | this.locker = this.writableBitmap.Lock(); 33 | } 34 | 35 | public Size Size => 36 | new(this.imageInfo.Width, this.imageInfo.Height); 37 | 38 | public void Finish() 39 | { 40 | this.locker!.Dispose(); 41 | this.locker = null; 42 | } 43 | 44 | public SKSurface GetSurface() => 45 | SKSurface.Create(this.imageInfo, this.locker!.Address, this.locker!.RowBytes); 46 | 47 | public void Draw(DrawingContext drawingContext, Size renderSize) => 48 | drawingContext.DrawImage(this.writableBitmap, new(new(), renderSize)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SkiaImageView.Avalonia/Interops.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia; 12 | using Avalonia.Data; 13 | using Avalonia.Reactive; 14 | using Avalonia.Threading; 15 | using System; 16 | 17 | namespace SkiaImageView; 18 | 19 | internal static class Interops 20 | { 21 | #if AVALONIA 22 | public static AvaloniaProperty Register( 23 | string memberName, TTarget defaultValue, Action changed) 24 | where THost : IAvaloniaObject => 25 | AvaloniaProperty.Register( 26 | memberName, defaultValue, false, BindingMode.OneWay, 27 | null, 28 | null, 29 | (s, isChanged) => 30 | { 31 | if (isChanged) 32 | { 33 | changed((THost)s); 34 | } 35 | }); 36 | 37 | public static Dispatcher GetDispatcher( 38 | this IAvaloniaObject _) => 39 | Dispatcher.UIThread; 40 | #else 41 | 42 | // The same AvaloniaProperty should not be registered twice 43 | #pragma warning disable AVP1001 44 | 45 | public static AvaloniaProperty Register( 46 | string memberName, TTarget defaultValue, Action changed) 47 | where THost : AvaloniaObject 48 | { 49 | var ap = AvaloniaProperty.Register( 50 | memberName, defaultValue, false, BindingMode.OneWay, 51 | null, 52 | null, 53 | false); 54 | 55 | ap.Changed.Subscribe(new AnonymousObserver>( 56 | e => changed((THost)e.Sender))); 57 | 58 | return ap; 59 | } 60 | 61 | public static Dispatcher GetDispatcher( 62 | this AvaloniaObject _) => 63 | Dispatcher.UIThread; 64 | #endif 65 | 66 | public static void InvokeAsynchronously( 67 | this Dispatcher dispatcher, Action action, bool isHigherPriority) => 68 | dispatcher.InvokeAsynchronously( 69 | action, 70 | isHigherPriority); 71 | } 72 | -------------------------------------------------------------------------------- /SkiaImageView.Avalonia/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia.Metadata; 12 | 13 | [assembly: XmlnsDefinition("https://github.com/kekyo/SkiaImageView", "SkiaImageView")] 14 | [assembly: XmlnsPrefix("https://github.com/kekyo/SkiaImageView", "siv")] 15 | -------------------------------------------------------------------------------- /SkiaImageView.Avalonia/SKImageView.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia; 12 | using Avalonia.Controls; 13 | using Avalonia.Media; 14 | using Avalonia.Metadata; 15 | 16 | namespace SkiaImageView; 17 | 18 | partial class SKImageView : Control 19 | { 20 | public static readonly AvaloniaProperty SourceProperty = 21 | Interops.Register( 22 | nameof(Source), null, d => d.OnBitmapChanged()); 23 | 24 | public static readonly AvaloniaProperty StretchProperty = 25 | Interops.Register( 26 | nameof(Stretch), Stretch.None, d => d.Invalidate(false)); 27 | 28 | public static readonly AvaloniaProperty StretchDirectionProperty = 29 | Interops.Register( 30 | nameof(StretchDirection), StretchDirection.Both, d => d.Invalidate(false)); 31 | 32 | public static readonly AvaloniaProperty RenderModeProperty = 33 | Interops.Register( 34 | nameof(RenderMode), RenderMode.AsynchronouslyForFetching, d => d.OnBitmapChanged()); 35 | 36 | public static readonly AvaloniaProperty ProjectionQualityProperty = 37 | Interops.Register( 38 | nameof(ProjectionQuality), 39 | ProjectionQuality.Perfect, 40 | _ => { }); 41 | 42 | static SKImageView() 43 | { 44 | AffectsRender(SourceProperty, StretchProperty, StretchDirectionProperty); 45 | AffectsMeasure(SourceProperty, StretchProperty, StretchDirectionProperty); 46 | } 47 | 48 | private void Invalidate(bool both) 49 | { 50 | if (both) 51 | { 52 | base.InvalidateMeasure(); 53 | } 54 | base.InvalidateVisual(); 55 | } 56 | 57 | [Content] 58 | public object? Source 59 | { 60 | get => this.GetValue(SourceProperty); 61 | set => this.SetValue(SourceProperty, value); 62 | } 63 | 64 | private Size RenderSize => 65 | this.Bounds.Size; 66 | 67 | private void UpdateWith(BackingStore? backingStore) 68 | { 69 | this.backingStore = backingStore; 70 | this.Invalidate(true); 71 | } 72 | 73 | protected override Size MeasureOverride(Size constraint) => 74 | this.InternalMeasureArrangeOverride(constraint); 75 | 76 | protected override Size ArrangeOverride(Size arrangeSize) => 77 | this.InternalMeasureArrangeOverride(arrangeSize); 78 | 79 | public override void Render(DrawingContext drawingContext) 80 | { 81 | base.Render(drawingContext); 82 | 83 | if (this.backingStore is { } backingStore) 84 | { 85 | backingStore.Draw(drawingContext, this.RenderSize); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /SkiaImageView.Avalonia/SkiaImageView.Avalonia.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net461;net48;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;netstandard2.0;netstandard2.1;net5.0;net6.0;net7.0 5 | $(DefineConstants);AVALONIA 6 | SkiaImageView 7 | SkiaImageView.Avalonia 8 | SkiaImageView.Avalonia 9 | skiasharp;avalonia;imaging;control 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /SkiaImageView.Avalonia11/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia.Metadata; 12 | 13 | [assembly: XmlnsDefinition("https://github.com/kekyo/SkiaImageView", "SkiaImageView")] 14 | [assembly: XmlnsPrefix("https://github.com/kekyo/SkiaImageView", "siv")] 15 | -------------------------------------------------------------------------------- /SkiaImageView.Avalonia11/SkiaImageView.Avalonia11.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net461;net48;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;netstandard2.0;netstandard2.1;net5.0;net6.0;net7.0 5 | $(DefineConstants);AVALONIA11 6 | SkiaImageView 7 | SkiaImageView.Avalonia11 8 | SkiaImageView.Avalonia11 9 | skiasharp;avalonia;imaging;control 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /SkiaImageView.Maui/BackingStore.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui.Controls; 12 | using Microsoft.Maui.Graphics; 13 | using SkiaSharp; 14 | using System; 15 | 16 | namespace SkiaImageView; 17 | 18 | internal sealed class BackingStore 19 | { 20 | // HACK: XF requires custom renderrer for drawing independent any bitmap. 21 | // It is force applicable limitation for packaging strategy, be going to separates between platforms. 22 | // So, avoid it by will re-encode bitmap to image stream with PNG format in ImageSource object... 23 | private readonly SKImageInfo imageInfo; 24 | private readonly ProjectionQuality projectionQuality; 25 | private SKBitmap? bitmap; 26 | private ImageSource? imageSource; 27 | 28 | public BackingStore( 29 | int width, int height, ProjectionQuality projectionQuality) 30 | { 31 | this.projectionQuality = projectionQuality; 32 | this.imageInfo = new( 33 | width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); 34 | this.bitmap = new( 35 | imageInfo.Width, imageInfo.Height, SKColorType.Bgra8888, SKAlphaType.Premul); 36 | } 37 | 38 | public BackingStore(Uri url) => 39 | this.imageSource = ImageSource.FromUri(url); 40 | 41 | public Size Size => 42 | new(this.imageInfo.Width, this.imageInfo.Height); 43 | 44 | public void Finish() 45 | { 46 | // Maui is in essence, supposed to be used on smartphones and tablets, 47 | // so a Middle quality of 90 does not seem too out of place. 48 | // The amount of data can be significantly reduced. 49 | var (format, quality) = this.projectionQuality switch 50 | { 51 | ProjectionQuality.Perfect => (SKEncodedImageFormat.Png, 100), 52 | ProjectionQuality.Low => (SKEncodedImageFormat.Jpeg, 80), 53 | ProjectionQuality.High => (SKEncodedImageFormat.Jpeg, 95), 54 | _ => (SKEncodedImageFormat.Jpeg, 90), 55 | }; 56 | 57 | var bitmapData = this.bitmap!.Encode(format, quality); 58 | this.bitmap.Dispose(); 59 | this.bitmap = null; 60 | this.imageSource = ImageSource.FromStream(() => bitmapData.AsStream()); 61 | } 62 | 63 | public SKSurface GetSurface() => 64 | SKSurface.Create(this.imageInfo, this.bitmap!.GetAddress(0, 0), this.bitmap.RowBytes); 65 | 66 | public ImageSource GetImageSource() => 67 | this.imageSource!; 68 | } 69 | -------------------------------------------------------------------------------- /SkiaImageView.Maui/Interops.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui.Controls; 12 | using Microsoft.Maui.Dispatching; 13 | using System; 14 | 15 | namespace SkiaImageView; 16 | 17 | internal static class Interops 18 | { 19 | public static BindableProperty Register( 20 | string memberName, TTarget defaultValue, Action changed) 21 | where THost : BindableObject => 22 | BindableProperty.Create( 23 | memberName, typeof(TTarget), typeof(THost), 24 | defaultValue, BindingMode.OneWay, null, 25 | (s, _, _) => changed((THost)s)); 26 | 27 | public static IDispatcher GetDispatcher( 28 | this BindableObject b) => 29 | b.Dispatcher; 30 | 31 | public static void InvokeAsynchronously( 32 | this IDispatcher dispatcher, Action action, bool isHigherPriority) => 33 | dispatcher.InvokeAsynchronously(action, isHigherPriority); 34 | } 35 | -------------------------------------------------------------------------------- /SkiaImageView.Maui/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui.Controls; 12 | 13 | [assembly: XmlnsDefinition("https://github.com/kekyo/SkiaImageView", "SkiaImageView")] 14 | [assembly: XmlnsPrefix("https://github.com/kekyo/SkiaImageView", "siv")] 15 | -------------------------------------------------------------------------------- /SkiaImageView.Maui/SKImageView.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui; 12 | using Microsoft.Maui.Controls; 13 | using Microsoft.Maui.Graphics; 14 | 15 | namespace SkiaImageView; 16 | 17 | partial class SKImageView : Image 18 | { 19 | public static new readonly BindableProperty SourceProperty = 20 | Interops.Register( 21 | nameof(Source), null, d => d.OnBitmapChanged()); 22 | 23 | public static readonly BindableProperty StretchProperty = 24 | Interops.Register( 25 | nameof(Stretch), Microsoft.Maui.Controls.Stretch.None, d => d.Invalidate(false)); 26 | 27 | public static readonly BindableProperty StretchDirectionProperty = 28 | Interops.Register( 29 | nameof(StretchDirection), StretchDirection.Both, d => d.Invalidate(false)); 30 | 31 | public static readonly BindableProperty RenderModeProperty = 32 | Interops.Register( 33 | nameof(RenderMode), RenderMode.AsynchronouslyForFetching, d => d.OnBitmapChanged()); 34 | 35 | public static readonly BindableProperty ProjectionQualityProperty = 36 | Interops.Register( 37 | nameof(ProjectionQuality), 38 | ProjectionQuality.Middle, // Limited on Maui 39 | _ => { }); 40 | 41 | public SKImageView() => 42 | base.Aspect = Microsoft.Maui.Aspect.AspectFill; 43 | 44 | private void Invalidate(bool both) => 45 | base.InvalidateMeasure(); 46 | 47 | public new object Source 48 | { 49 | get => this.GetValue(SourceProperty); 50 | set => this.SetValue(SourceProperty, value); 51 | } 52 | 53 | public Size RenderSize => 54 | new(base.Width, base.Height); 55 | 56 | private void UpdateWith(BackingStore? backingStore) 57 | { 58 | this.backingStore = backingStore; 59 | base.Source = this.backingStore?.GetImageSource(); 60 | } 61 | 62 | protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) => 63 | new(this.InternalMeasureArrangeOverride(new(widthConstraint, heightConstraint))); 64 | } 65 | -------------------------------------------------------------------------------- /SkiaImageView.Maui/SkiaImageView.Maui.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0;net7.0 5 | true 6 | true 7 | $(DefineConstants);MAUI 8 | SkiaImageView 9 | SkiaImageView.Maui 10 | SkiaImageView.Maui 11 | skiasharp;maui;imaging 12 | true 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SkiaImageView.Maui/StretchDirection.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | namespace SkiaImageView; 12 | 13 | public enum StretchDirection 14 | { 15 | UpOnly, 16 | DownOnly, 17 | Both 18 | } 19 | -------------------------------------------------------------------------------- /SkiaImageView.Wpf/BackingStore.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using SkiaSharp; 12 | using System.Windows; 13 | using System.Windows.Media; 14 | using System.Windows.Media.Imaging; 15 | 16 | namespace SkiaImageView; 17 | 18 | internal sealed class BackingStore 19 | { 20 | private readonly SKImageInfo imageInfo; 21 | private readonly WriteableBitmap writableBitmap; 22 | 23 | public BackingStore( 24 | int width, int height, ProjectionQuality projectionQuality) 25 | { 26 | this.imageInfo = new( 27 | width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); 28 | this.writableBitmap = new( 29 | imageInfo.Width, imageInfo.Height, 96.0, 96.0, PixelFormats.Pbgra32, null); 30 | this.writableBitmap.Lock(); 31 | } 32 | 33 | public Size Size => 34 | new Size(this.imageInfo.Width, this.imageInfo.Height); 35 | 36 | public void Finish() 37 | { 38 | this.writableBitmap.Unlock(); 39 | this.writableBitmap.Freeze(); 40 | } 41 | 42 | public SKSurface GetSurface() => 43 | SKSurface.Create(this.imageInfo, this.writableBitmap.BackBuffer, this.writableBitmap.BackBufferStride); 44 | 45 | public void Draw(DrawingContext drawingContext, Size renderSize) => 46 | drawingContext.DrawImage(this.writableBitmap, new(new(), renderSize)); 47 | } 48 | -------------------------------------------------------------------------------- /SkiaImageView.Wpf/Interops.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using System; 12 | using System.Windows; 13 | using System.Windows.Threading; 14 | 15 | namespace SkiaImageView; 16 | 17 | internal static class Interops 18 | { 19 | public static DependencyProperty Register( 20 | string memberName, TTarget defaultValue, Action changed) 21 | where THost : DependencyObject => 22 | DependencyProperty.Register( 23 | memberName, typeof(TTarget), typeof(THost), 24 | new PropertyMetadata( 25 | defaultValue, 26 | (s, _) => changed((THost)s))); 27 | 28 | public static Dispatcher GetDispatcher( 29 | this DependencyObject d) => 30 | d.Dispatcher; 31 | 32 | public static void InvokeAsynchronously( 33 | this Dispatcher dispatcher, Action action, bool isHigherPriority) => 34 | dispatcher.BeginInvoke( 35 | action, 36 | isHigherPriority ? DispatcherPriority.Normal : DispatcherPriority.ApplicationIdle); 37 | } 38 | -------------------------------------------------------------------------------- /SkiaImageView.Wpf/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using System.Windows.Markup; 12 | 13 | [assembly: XmlnsDefinition("https://github.com/kekyo/SkiaImageView", "SkiaImageView")] 14 | [assembly: XmlnsPrefix("https://github.com/kekyo/SkiaImageView", "siv")] 15 | -------------------------------------------------------------------------------- /SkiaImageView.Wpf/SKImageView.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using System.Windows; 12 | using System.Windows.Controls; 13 | using System.Windows.Media; 14 | 15 | namespace SkiaImageView; 16 | 17 | partial class SKImageView : FrameworkElement 18 | { 19 | public static readonly DependencyProperty SourceProperty = 20 | Interops.Register( 21 | nameof(Source), null, d => d.OnBitmapChanged()); 22 | 23 | public static readonly DependencyProperty StretchProperty = 24 | Interops.Register( 25 | nameof(Stretch), Stretch.None, d => d.Invalidate(false)); 26 | 27 | public static readonly DependencyProperty StretchDirectionProperty = 28 | Interops.Register( 29 | nameof(StretchDirection), StretchDirection.Both, d => d.Invalidate(false)); 30 | 31 | public static readonly DependencyProperty RenderModeProperty = 32 | Interops.Register( 33 | nameof(RenderMode), RenderMode.AsynchronouslyForFetching, d => d.OnBitmapChanged()); 34 | 35 | public static readonly DependencyProperty ProjectionQualityProperty = 36 | Interops.Register( 37 | nameof(ProjectionQuality), 38 | ProjectionQuality.Perfect, 39 | _ => { }); 40 | 41 | private void Invalidate(bool both) 42 | { 43 | if (both) 44 | { 45 | base.InvalidateMeasure(); 46 | } 47 | base.InvalidateVisual(); 48 | } 49 | 50 | public object Source 51 | { 52 | get => this.GetValue(SourceProperty); 53 | set => this.SetValue(SourceProperty, value); 54 | } 55 | 56 | private void UpdateWith(BackingStore? backingStore) 57 | { 58 | this.backingStore = backingStore; 59 | this.Invalidate(true); 60 | } 61 | 62 | protected override Size MeasureOverride(Size constraint) => 63 | this.InternalMeasureArrangeOverride(constraint); 64 | 65 | protected override Size ArrangeOverride(Size arrangeSize) => 66 | this.InternalMeasureArrangeOverride(arrangeSize); 67 | 68 | protected override void OnRender(DrawingContext drawingContext) 69 | { 70 | base.OnRender(drawingContext); 71 | 72 | if (this.backingStore is { } backingStore) 73 | { 74 | backingStore.Draw(drawingContext, this.RenderSize); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /SkiaImageView.Wpf/SkiaImageView.Wpf.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net462;net48;netcoreapp3.0;netcoreapp3.1;net5.0-windows;net6.0-windows;net7.0-windows 5 | true 6 | $(DefineConstants);WPF 7 | SkiaImageView 8 | SkiaImageView.Wpf 9 | SkiaImageView.Wpf 10 | skiasharp;wpf;imaging;control 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /SkiaImageView.Xamarin.Forms/BackingStore.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using SkiaSharp; 12 | using System; 13 | using Xamarin.Forms; 14 | 15 | namespace SkiaImageView 16 | { 17 | internal sealed class BackingStore 18 | { 19 | // HACK: XF requires custom renderrer for drawing independent any bitmap. 20 | // It is force applicable limitation for packaging strategy, be going to separates between platforms. 21 | // So, avoid it by will re-encode bitmap to image stream with PNG format in ImageSource object... 22 | private readonly SKImageInfo imageInfo; 23 | private readonly ProjectionQuality projectionQuality; 24 | private SKBitmap? bitmap; 25 | private ImageSource? imageSource; 26 | 27 | public BackingStore( 28 | int width, int height, ProjectionQuality projectionQuality) 29 | { 30 | this.projectionQuality = projectionQuality; 31 | this.imageInfo = new( 32 | width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); 33 | this.bitmap = new( 34 | imageInfo.Width, imageInfo.Height, SKColorType.Rgba8888, SKAlphaType.Premul); 35 | } 36 | 37 | public BackingStore(Uri url) => 38 | this.imageSource = ImageSource.FromUri(url); 39 | 40 | public Size Size => 41 | new(this.imageInfo.Width, this.imageInfo.Height); 42 | 43 | public void Finish() 44 | { 45 | // Xamarin Forms is in essence, supposed to be used on smartphones and tablets, 46 | // so a Middle quality of 90 does not seem too out of place. 47 | // The amount of data can be significantly reduced. 48 | var (format, quality) = this.projectionQuality switch 49 | { 50 | ProjectionQuality.Perfect => (SKEncodedImageFormat.Png, 100), 51 | ProjectionQuality.Low => (SKEncodedImageFormat.Jpeg, 80), 52 | ProjectionQuality.High => (SKEncodedImageFormat.Jpeg, 95), 53 | _ => (SKEncodedImageFormat.Jpeg, 90), 54 | }; 55 | 56 | var bitmapData = this.bitmap!.Encode(format, quality); 57 | this.bitmap.Dispose(); 58 | this.bitmap = null; 59 | this.imageSource = ImageSource.FromStream(() => bitmapData.AsStream()); 60 | } 61 | 62 | public SKSurface GetSurface() => 63 | SKSurface.Create(this.imageInfo, this.bitmap!.GetAddress(0, 0), this.bitmap.RowBytes); 64 | 65 | public ImageSource GetImageSource() => 66 | this.imageSource!; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SkiaImageView.Xamarin.Forms/Interops.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using System; 12 | using Xamarin.Forms; 13 | 14 | namespace SkiaImageView; 15 | 16 | internal static class Interops 17 | { 18 | public static BindableProperty Register( 19 | string memberName, TTarget defaultValue, Action changed) 20 | where THost : BindableObject => 21 | BindableProperty.Create( 22 | memberName, typeof(TTarget), typeof(THost), 23 | defaultValue, BindingMode.OneWay, null, 24 | (s, _, _) => changed((THost)s)); 25 | 26 | public static IDispatcher GetDispatcher( 27 | this BindableObject b) => 28 | b.Dispatcher; 29 | 30 | public static void InvokeAsynchronously( 31 | this IDispatcher dispatcher, Action action, bool isHigherPriority) => 32 | dispatcher.BeginInvokeOnMainThread(action); 33 | } 34 | -------------------------------------------------------------------------------- /SkiaImageView.Xamarin.Forms/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Xamarin.Forms; 12 | 13 | [assembly: XmlnsDefinition("https://github.com/kekyo/SkiaImageView", "SkiaImageView")] 14 | [assembly: XmlnsPrefix("https://github.com/kekyo/SkiaImageView", "siv")] 15 | -------------------------------------------------------------------------------- /SkiaImageView.Xamarin.Forms/SKImageView.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Xamarin.Forms; 12 | 13 | namespace SkiaImageView; 14 | 15 | partial class SKImageView : Image 16 | { 17 | public static new readonly BindableProperty SourceProperty = 18 | Interops.Register( 19 | nameof(Source), null, d => d.OnBitmapChanged()); 20 | 21 | public static readonly BindableProperty StretchProperty = 22 | Interops.Register( 23 | nameof(Stretch), Stretch.None, d => d.Invalidate(false)); 24 | 25 | public static readonly BindableProperty StretchDirectionProperty = 26 | Interops.Register( 27 | nameof(StretchDirection), StretchDirection.Both, d => d.Invalidate(false)); 28 | 29 | public static readonly BindableProperty RenderModeProperty = 30 | Interops.Register( 31 | nameof(RenderMode), RenderMode.AsynchronouslyForFetching, d => d.OnBitmapChanged()); 32 | 33 | public static readonly BindableProperty ProjectionQualityProperty = 34 | Interops.Register( 35 | nameof(ProjectionQuality), 36 | ProjectionQuality.Middle, // Limited on XF 37 | _ => { }); 38 | 39 | public SKImageView() => 40 | base.Aspect = Aspect.AspectFill; 41 | 42 | private void Invalidate(bool both) => 43 | base.InvalidateMeasure(); 44 | 45 | public new object Source 46 | { 47 | get => this.GetValue(SourceProperty); 48 | set => this.SetValue(SourceProperty, value); 49 | } 50 | 51 | public Size RenderSize => 52 | new(base.Width, base.Height); 53 | 54 | private void UpdateWith(BackingStore? backingStore) 55 | { 56 | this.backingStore = backingStore; 57 | base.Source = this.backingStore?.GetImageSource(); 58 | } 59 | 60 | protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) => 61 | new(this.InternalMeasureArrangeOverride(new(widthConstraint, heightConstraint))); 62 | } 63 | -------------------------------------------------------------------------------- /SkiaImageView.Xamarin.Forms/SkiaImageView.Xamarin.Forms.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | true 6 | $(DefineConstants);XAMARIN_FORMS 7 | SkiaImageView 8 | SkiaImageView.Xamarin.Forms 9 | SkiaImageView.Xamarin.Forms 10 | skiasharp;xamarin-forms;imaging 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SkiaImageView.Xamarin.Forms/StretchDirection.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | namespace SkiaImageView; 12 | 13 | public enum StretchDirection 14 | { 15 | UpOnly, 16 | DownOnly, 17 | Both 18 | } 19 | -------------------------------------------------------------------------------- /artifacts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/artifacts/.gitkeep -------------------------------------------------------------------------------- /build-nupkg.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | rem 5 | rem Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | rem 7 | rem Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | 9 | echo. 10 | echo "===========================================================" 11 | echo "Build SkiaImageView" 12 | echo. 13 | 14 | rem git clean -xfd 15 | 16 | dotnet build -p:Configuration=Release -p:Platform=AnyCPU SkiaImageView.Wpf\SkiaImageView.Wpf.csproj 17 | dotnet build -p:Configuration=Release -p:Platform=AnyCPU SkiaImageView.Xamarin.Forms\SkiaImageView.Xamarin.Forms.csproj 18 | dotnet build -p:Configuration=Release -p:Platform=AnyCPU SkiaImageView.Maui\SkiaImageView.Maui.csproj 19 | dotnet build -p:Configuration=Release -p:Platform=AnyCPU SkiaImageView.Avalonia11\SkiaImageView.Avalonia11.csproj 20 | dotnet build -p:Configuration=Release -p:Platform=AnyCPU SkiaImageView.Avalonia\SkiaImageView.Avalonia.csproj 21 | 22 | dotnet pack -p:Configuration=Release -p:Platform=AnyCPU -o artifacts SkiaImageView.Wpf\SkiaImageView.Wpf.csproj 23 | dotnet pack -p:Configuration=Release -p:Platform=AnyCPU -o artifacts SkiaImageView.Xamarin.Forms\SkiaImageView.Xamarin.Forms.csproj 24 | dotnet pack -p:Configuration=Release -p:Platform=AnyCPU -o artifacts SkiaImageView.Maui\SkiaImageView.Maui.csproj 25 | dotnet pack -p:Configuration=Release -p:Platform=AnyCPU -o artifacts SkiaImageView.Avalonia11\SkiaImageView.Avalonia11.csproj 26 | dotnet pack -p:Configuration=Release -p:Platform=AnyCPU -o artifacts SkiaImageView.Avalonia\SkiaImageView.Avalonia.csproj 27 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $([MSBuild]::Unescape($(BuildDependsOn.Replace('_SayHello;', '').Replace('_VerifyBuildSignature;', '').Replace('_VerifyXcodeVersion;', '').Replace('AfterConnect;', '').Replace('BeforeDisconnect;', '').Replace('_SayGoodbye;', '')))) 8 | false 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.UI/App.axaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.UI/App.axaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia; 12 | using Avalonia.Controls.ApplicationLifetimes; 13 | using Avalonia.Markup.Xaml; 14 | 15 | using SkiaImageView.Sample.Views; 16 | 17 | namespace SkiaImageView.Sample; 18 | 19 | public sealed class App : Application 20 | { 21 | public override void Initialize() => 22 | AvaloniaXamlLoader.Load(this); 23 | 24 | public override void OnFrameworkInitializationCompleted() 25 | { 26 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 27 | { 28 | desktop.MainWindow = new MainWindow(); 29 | } 30 | 31 | base.OnFrameworkInitializationCompleted(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.UI/SkiaImageView.Avalonia.Sample.UI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | latest 6 | enable 7 | portable 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.UI/ViewModels/ItemViewModel.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using SkiaSharp; 13 | 14 | namespace SkiaImageView.Sample.ViewModels; 15 | 16 | [ViewModel] 17 | public sealed class ItemViewModel 18 | { 19 | public string? Title { get; set; } 20 | 21 | public SKBitmap? Image { get; set; } 22 | 23 | public int Score { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.UI/ViewModels/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using SkiaImageView.Sample.Models; 13 | using SkiaSharp; 14 | using System; 15 | using System.Collections.ObjectModel; 16 | using System.Linq; 17 | using System.Threading.Tasks; 18 | 19 | namespace SkiaImageView.Sample.ViewModels; 20 | 21 | [ViewModel] 22 | public sealed class MainWindowViewModel 23 | { 24 | public MainWindowViewModel() 25 | { 26 | // A handler for page appearing 27 | this.Ready = Command.Factory.Create(() => 28 | { 29 | this.IsEnabled = true; 30 | return default; 31 | }); 32 | 33 | // A handler for fetch button 34 | this.Fetch = Command.Factory.Create(async () => 35 | { 36 | // Disable button 37 | this.IsEnabled = false; 38 | 39 | try 40 | { 41 | // Uses The Cat API 42 | var cats = await TheCatAPI.FetchTheCatsAsync(10); 43 | 44 | this.Items.Clear(); 45 | 46 | static async ValueTask FetchImageAsync(Uri url) => 47 | SKBitmap.Decode(await TheCatAPI.FetchImageAsync(url)); 48 | 49 | foreach (var cat in cats) 50 | { 51 | if (cat.Url is { } url) 52 | { 53 | var bleed = cat?.Bleeds.FirstOrDefault(); 54 | this.Items.Add(new ItemViewModel 55 | { 56 | Title = bleed?.Description ?? bleed?.Temperament ?? "(No comment)", 57 | Score = bleed?.Intelligence ?? 5, 58 | Image = await FetchImageAsync(url) 59 | }); 60 | } 61 | } 62 | } 63 | finally 64 | { 65 | // Re-enable button 66 | this.IsEnabled = true; 67 | } 68 | }); 69 | } 70 | 71 | public Command Ready { get; } 72 | 73 | public bool IsEnabled { get; private set; } 74 | 75 | public ObservableCollection Items { get; } = new(); 76 | 77 | public Command Fetch { get; } 78 | } 79 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.UI/Views/Converters/ScoreToBrushConverter.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | 13 | using Avalonia.Media; 14 | 15 | namespace SkiaImageView.Sample.Views.Converters; 16 | 17 | public sealed class ScoreToBrushConverter : ValueConverter 18 | { 19 | private static readonly Brush yellow = new SolidColorBrush(Color.FromArgb(255, 96, 96, 0)); 20 | private static readonly Brush gray = new SolidColorBrush(Color.FromArgb(255, 96, 96, 96)); 21 | 22 | public override bool TryConvert(int from, out Brush result) 23 | { 24 | result = from >= 5 ? yellow : gray; 25 | return true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.UI/Views/MainWindow.axaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 42 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.UI/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia; 12 | using Avalonia.Controls; 13 | using Avalonia.Markup.Xaml; 14 | 15 | namespace SkiaImageView.Sample.Views; 16 | 17 | public sealed class MainWindow : Window 18 | { 19 | public MainWindow() 20 | { 21 | InitializeComponent(); 22 | } 23 | 24 | private void InitializeComponent() => 25 | AvaloniaXamlLoader.Load(this); 26 | } 27 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample/Program.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia; 12 | 13 | namespace SkiaImageView.Sample; 14 | 15 | public static class Program 16 | { 17 | // Initialization code. Don't use any Avalonia, third-party APIs or any 18 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 19 | // yet and stuff might break. 20 | public static void Main(string[] args) => 21 | BuildAvaloniaApp(). 22 | StartWithClassicDesktopLifetime(args); 23 | 24 | // Avalonia configuration, don't remove; also used by visual designer. 25 | public static AppBuilder BuildAvaloniaApp() => 26 | AppBuilder.Configure(). 27 | UsePlatformDetect(). 28 | LogToTrace(); 29 | } 30 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample/SkiaImageView.Avalonia.Sample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | net6.0 6 | 7 | latest 8 | enable 9 | portable 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Icon.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Android.App; 12 | using Android.Content.PM; 13 | using Avalonia; 14 | using Avalonia.Android; 15 | 16 | namespace SkiaImageView.Sample.Android; 17 | 18 | [Activity( 19 | Label = "SkiaImageView.Avalonia11.Sample.Android", 20 | Theme = "@style/MyTheme.NoActionBar", 21 | Icon = "@drawable/icon", 22 | MainLauncher = true, 23 | ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)] 24 | public class MainActivity : AvaloniaMainActivity 25 | { 26 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) 27 | { 28 | return base.CustomizeAppBuilder(builder). 29 | WithInterFont(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.axml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable/ 12 | icon.png 13 | 14 | layout/ 15 | main.axml 16 | 17 | values/ 18 | strings.xml 19 | 20 | In order to get the build system to recognize Android resources, set the build action to 21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 22 | instead operate on resource IDs. When you compile an Android application that uses resources, 23 | the build system will package the resources for distribution and generate a class called "R" 24 | (this is an Android convention) that contains the tokens for each one of the resources 25 | included. For example, for the above Resources layout, this is what the R class would expose: 26 | 27 | public class R { 28 | public class drawable { 29 | public const int icon = 0x123; 30 | } 31 | 32 | public class layout { 33 | public const int main = 0x456; 34 | } 35 | 36 | public class strings { 37 | public const int first_string = 0xabc; 38 | public const int second_string = 0xbcd; 39 | } 40 | } 41 | 42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first 44 | string in the dictionary file values/strings.xml. -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Resources/drawable-night-v31/avalonia_anim.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | 15 | 16 | 20 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | 45 | 46 | 53 | 54 | 55 | 56 | 57 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Resources/drawable/splash_screen.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Resources/values-night/colors.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | #212121 4 | 5 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Resources/values-v31/styles.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 6 | 7 | 17 | 21 | 22 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | #FFFFFF 4 | 5 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Android/SkiaImageView.Avalonia11.Sample.Android.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0-android 6 | 30 7 | enable 8 | latest 9 | com.CompanyName.SkiaImageView.Avalonia11.Sample 10 | 1 11 | 1.0 12 | apk 13 | False 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Resources\drawable\Icon.png 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Desktop/Program.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia; 12 | using System; 13 | 14 | namespace SkiaImageView.Sample; 15 | 16 | public static class Program 17 | { 18 | // Avalonia configuration, don't remove; also used by visual designer. 19 | public static AppBuilder BuildAvaloniaApp() => 20 | AppBuilder.Configure(). 21 | UsePlatformDetect(). 22 | LogToTrace(); 23 | 24 | // Initialization code. Don't use any Avalonia, third-party APIs or any 25 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 26 | // yet and stuff might break. 27 | [STAThread] 28 | public static int Main(string[] args) => 29 | BuildAvaloniaApp(). 30 | StartWithClassicDesktopLifetime(args); 31 | } 32 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.Desktop/SkiaImageView.Avalonia11.Sample.Desktop.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | net6.0 6 | 7 | enable 8 | latest 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/App.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Markup.Xaml; 4 | 5 | using SkiaImageView.Sample.Views; 6 | 7 | namespace SkiaImageView.Sample; 8 | 9 | public sealed class App : Application 10 | { 11 | public override void Initialize() => 12 | AvaloniaXamlLoader.Load(this); 13 | 14 | public override void OnFrameworkInitializationCompleted() 15 | { 16 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 17 | { 18 | desktop.MainWindow = new MainWindow(); 19 | } 20 | if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) 21 | { 22 | singleViewPlatform.MainView = new MainView(); 23 | } 24 | 25 | base.OnFrameworkInitializationCompleted(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/SkiaImageView.Avalonia11.Sample.UI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | enable 6 | latest 7 | true 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | MainWindow.axaml 27 | 28 | 29 | MainView.axaml 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/ViewModels/ItemViewModel.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using SkiaSharp; 13 | 14 | namespace SkiaImageView.Sample.ViewModels; 15 | 16 | [ViewModel] 17 | public sealed class ItemViewModel 18 | { 19 | public string? Title { get; set; } 20 | 21 | public SKBitmap? Image { get; set; } 22 | 23 | public int Score { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using SkiaImageView.Sample.Models; 13 | using SkiaSharp; 14 | using System; 15 | using System.Collections.ObjectModel; 16 | using System.Linq; 17 | using System.Threading.Tasks; 18 | 19 | namespace SkiaImageView.Sample.ViewModels; 20 | 21 | [ViewModel] 22 | public sealed class MainViewModel 23 | { 24 | public MainViewModel() 25 | { 26 | // A handler for window opened 27 | this.Ready = Command.Factory.Create(() => 28 | { 29 | this.IsEnabled = true; 30 | return default; 31 | }); 32 | 33 | // A handler for fetch button 34 | this.Fetch = Command.Factory.Create(async () => 35 | { 36 | // Disable button 37 | this.IsEnabled = false; 38 | 39 | try 40 | { 41 | // Uses The Cat API 42 | var cats = await TheCatAPI.FetchTheCatsAsync(10); 43 | 44 | this.Items.Clear(); 45 | 46 | static async ValueTask FetchImageAsync(Uri url) => 47 | SKBitmap.Decode(await TheCatAPI.FetchImageAsync(url)); 48 | 49 | foreach (var cat in cats) 50 | { 51 | if (cat.Url is { } url) 52 | { 53 | var bleed = cat?.Bleeds.FirstOrDefault(); 54 | this.Items.Add(new ItemViewModel 55 | { 56 | Title = bleed?.Description ?? bleed?.Temperament ?? "(No comment)", 57 | Score = bleed?.Intelligence ?? 5, 58 | Image = await FetchImageAsync(url) 59 | }); 60 | } 61 | } 62 | } 63 | finally 64 | { 65 | // Re-enable button 66 | this.IsEnabled = true; 67 | } 68 | }); 69 | } 70 | 71 | public Command Ready { get; } 72 | 73 | public bool IsEnabled { get; private set; } 74 | 75 | public ObservableCollection Items { get; } = new(); 76 | 77 | public Command Fetch { get; } 78 | } 79 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/Views/Converters/ScoreToBrushConverter.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | 13 | using Avalonia.Media; 14 | 15 | namespace SkiaImageView.Sample.Views.Converters; 16 | 17 | public sealed class ScoreToBrushConverter : ValueConverter 18 | { 19 | private static readonly Brush yellow = new SolidColorBrush(Color.FromArgb(255, 96, 96, 0)); 20 | private static readonly Brush gray = new SolidColorBrush(Color.FromArgb(255, 96, 96, 96)); 21 | 22 | public override bool TryConvert(int from, out Brush result) 23 | { 24 | result = from >= 5 ? yellow : gray; 25 | return true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/Views/MainView.axaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 | 41 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 54 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/Views/MainView.axaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia.Controls; 12 | 13 | namespace SkiaImageView.Sample.Views; 14 | 15 | public sealed partial class MainView : UserControl 16 | { 17 | public MainView() => 18 | InitializeComponent(); 19 | } 20 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/Views/MainWindow.axaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.UI/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Avalonia.Controls; 12 | using Avalonia.Markup.Xaml; 13 | 14 | namespace SkiaImageView.Sample.Views; 15 | 16 | public sealed partial class MainWindow : Window 17 | { 18 | public MainWindow() => 19 | InitializeComponent(); 20 | 21 | private void InitializeComponent() => 22 | AvaloniaXamlLoader.Load(this); 23 | } 24 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.iOS; 3 | using Foundation; 4 | 5 | namespace SkiaImageView.Sample; 6 | 7 | // The UIApplicationDelegate for the application. This class is responsible for launching the 8 | // User Interface of the application, as well as listening (and optionally responding) to 9 | // application events from iOS. 10 | [Register("AppDelegate")] 11 | public partial class AppDelegate : AvaloniaAppDelegate 12 | { 13 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) 14 | { 15 | return base.CustomizeAppBuilder(builder). 16 | WithInterFont(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | SkiaImageView.Avalonia11.Sample 7 | CFBundleIdentifier 8 | companyName.SkiaImageView.Avalonia11.Sample 9 | CFBundleShortVersionString 10 | 1.0 11 | CFBundleVersion 12 | 1.0 13 | LSRequiresIPhoneOS 14 | 15 | MinimumOSVersion 16 | 10.0 17 | UIDeviceFamily 18 | 19 | 1 20 | 2 21 | 22 | UILaunchStoryboardName 23 | LaunchScreen 24 | UIRequiredDeviceCapabilities 25 | 26 | armv7 27 | 28 | UISupportedInterfaceOrientations 29 | 30 | UIInterfaceOrientationPortrait 31 | UIInterfaceOrientationPortraitUpsideDown 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIStatusBarHidden 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.iOS/Main.cs: -------------------------------------------------------------------------------- 1 | using UIKit; 2 | 3 | namespace SkiaImageView.Sample; 4 | 5 | public class Application 6 | { 7 | // This is the main entry point of the application. 8 | static void Main(string[] args) 9 | { 10 | // if you want to use a different Application Delegate class from "AppDelegate" 11 | // you can specify it here. 12 | UIApplication.Main(args, null, typeof(AppDelegate)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Avalonia11.Sample/SkiaImageView.Avalonia11.Sample.iOS/SkiaImageView.Avalonia11.Sample.iOS.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0-ios 6 | 13.0 7 | enable 8 | latest 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/App.xaml: -------------------------------------------------------------------------------- 1 |  2 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui.Controls; 12 | 13 | namespace SkiaImageView.Sample; 14 | 15 | public partial class App : Application 16 | { 17 | public App() 18 | { 19 | InitializeComponent(); 20 | 21 | MainPage = new AppShell(); 22 | } 23 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/AppShell.xaml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 17 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/AppShell.xaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui.Controls; 12 | 13 | namespace SkiaImageView.Sample; 14 | 15 | public partial class AppShell : Shell 16 | { 17 | public AppShell() 18 | { 19 | InitializeComponent(); 20 | } 21 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/MauiProgram.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui.Controls.Hosting; 12 | using Microsoft.Maui.Hosting; 13 | 14 | namespace SkiaImageView.Sample; 15 | 16 | public static class MauiProgram 17 | { 18 | public static MauiApp CreateMauiApp() 19 | { 20 | var builder = MauiApp.CreateBuilder(); 21 | builder. 22 | UseMauiApp(). 23 | ConfigureFonts(fonts => 24 | { 25 | fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); 26 | fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); 27 | }); 28 | 29 | return builder.Build(); 30 | } 31 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Android.App; 12 | using Android.Content.PM; 13 | using Android.OS; 14 | using Microsoft.Maui; 15 | 16 | namespace SkiaImageView.Sample; 17 | 18 | [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] 19 | public class MainActivity : MauiAppCompatActivity 20 | { 21 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Android/MainApplication.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Android.App; 12 | using Android.Runtime; 13 | using Microsoft.Maui; 14 | using Microsoft.Maui.Hosting; 15 | using System; 16 | 17 | namespace SkiaImageView.Sample; 18 | 19 | [Application] 20 | public class MainApplication : MauiApplication 21 | { 22 | public MainApplication(IntPtr handle, JniHandleOwnership ownership) 23 | : base(handle, ownership) 24 | { 25 | } 26 | 27 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 28 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #512BD4 4 | #2B0B98 5 | #2B0B98 6 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/MacCatalyst/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Foundation; 12 | using Microsoft.Maui; 13 | using Microsoft.Maui.Hosting; 14 | 15 | namespace SkiaImageView.Sample; 16 | 17 | [Register("AppDelegate")] 18 | public class AppDelegate : MauiUIApplicationDelegate 19 | { 20 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 21 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/MacCatalyst/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIDeviceFamily 6 | 7 | 1 8 | 2 9 | 10 | UIRequiredDeviceCapabilities 11 | 12 | arm64 13 | 14 | UISupportedInterfaceOrientations 15 | 16 | UIInterfaceOrientationPortrait 17 | UIInterfaceOrientationLandscapeLeft 18 | UIInterfaceOrientationLandscapeRight 19 | 20 | UISupportedInterfaceOrientations~ipad 21 | 22 | UIInterfaceOrientationPortrait 23 | UIInterfaceOrientationPortraitUpsideDown 24 | UIInterfaceOrientationLandscapeLeft 25 | UIInterfaceOrientationLandscapeRight 26 | 27 | XSAppIconAssets 28 | Assets.xcassets/appicon.appiconset 29 | 30 | 31 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/MacCatalyst/Program.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using ObjCRuntime; 12 | using UIKit; 13 | 14 | namespace SkiaImageView.Sample; 15 | 16 | public static class Program 17 | { 18 | // This is the main entry point of the application. 19 | static void Main(string[] args) 20 | { 21 | // if you want to use a different Application Delegate class from "AppDelegate" 22 | // you can specify it here. 23 | UIApplication.Main(args, null, typeof(AppDelegate)); 24 | } 25 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Tizen/Main.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui; 12 | using Microsoft.Maui.Hosting; 13 | using System; 14 | 15 | namespace SkiaImageView.Sample; 16 | 17 | internal class Program : MauiApplication 18 | { 19 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 20 | 21 | static void Main(string[] args) 22 | { 23 | var app = new Program(); 24 | app.Run(args); 25 | } 26 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Tizen/tizen-manifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | maui-appicon-placeholder 7 | 8 | 9 | 10 | 11 | http://tizen.org/privilege/internet 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Windows/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Windows/App.xaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Microsoft.Maui; 12 | using Microsoft.Maui.Hosting; 13 | using Microsoft.UI.Xaml; 14 | 15 | // To learn more about WinUI, the WinUI project structure, 16 | // and more about our project templates, see: http://aka.ms/winui-project-info. 17 | 18 | namespace SkiaImageView.Sample.Maui.WinUI; 19 | 20 | /// 21 | /// Provides application-specific behavior to supplement the default Application class. 22 | /// 23 | public partial class App : MauiWinUIApplication 24 | { 25 | /// 26 | /// Initializes the singleton application object. This is the first line of authored code 27 | /// executed, and as such is the logical equivalent of main() or WinMain(). 28 | /// 29 | public App() 30 | { 31 | this.InitializeComponent(); 32 | } 33 | 34 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 35 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Windows/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | $placeholder$ 12 | User Name 13 | $placeholder$.png 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/Windows/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | true/PM 12 | PerMonitorV2, PerMonitor 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Foundation; 12 | using Microsoft.Maui; 13 | using Microsoft.Maui.Hosting; 14 | 15 | namespace SkiaImageView.Sample; 16 | 17 | [Register("AppDelegate")] 18 | public class AppDelegate : MauiUIApplicationDelegate 19 | { 20 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 21 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LSRequiresIPhoneOS 6 | 7 | UIDeviceFamily 8 | 9 | 1 10 | 2 11 | 12 | UIRequiredDeviceCapabilities 13 | 14 | arm64 15 | 16 | UISupportedInterfaceOrientations 17 | 18 | UIInterfaceOrientationPortrait 19 | UIInterfaceOrientationLandscapeLeft 20 | UIInterfaceOrientationLandscapeRight 21 | 22 | UISupportedInterfaceOrientations~ipad 23 | 24 | UIInterfaceOrientationPortrait 25 | UIInterfaceOrientationPortraitUpsideDown 26 | UIInterfaceOrientationLandscapeLeft 27 | UIInterfaceOrientationLandscapeRight 28 | 29 | XSAppIconAssets 30 | Assets.xcassets/appicon.appiconset 31 | 32 | 33 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Platforms/iOS/Program.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using ObjCRuntime; 12 | using UIKit; 13 | 14 | namespace SkiaImageView.Sample; 15 | 16 | public class Program 17 | { 18 | // This is the main entry point of the application. 19 | static void Main(string[] args) 20 | { 21 | // if you want to use a different Application Delegate class from "AppDelegate" 22 | // you can specify it here. 23 | UIApplication.Main(args, null, typeof(AppDelegate)); 24 | } 25 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Windows Machine": { 4 | "commandName": "MsixPackage", 5 | "nativeDebugging": false 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Resources/AppIcon/appicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Resources/AppIcon/appiconfg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Resources/Fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Maui.Sample/Resources/Fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Resources/Fonts/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Maui.Sample/Resources/Fonts/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Resources/Raw/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories). Deployment of the asset to your application 3 | is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. 4 | 5 | 6 | 7 | These files will be deployed with you package and will be accessible using Essentials: 8 | 9 | async Task LoadMauiAsset() 10 | { 11 | using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); 12 | using var reader = new StreamReader(stream); 13 | 14 | var contents = reader.ReadToEnd(); 15 | } 16 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Resources/Splash/splash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Resources/Styles/Colors.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | #512BD4 8 | #DFD8F7 9 | #2B0B98 10 | White 11 | Black 12 | #E1E1E1 13 | #C8C8C8 14 | #ACACAC 15 | #919191 16 | #6E6E6E 17 | #404040 18 | #212121 19 | #141414 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #F7B548 35 | #FFD590 36 | #FFE5B9 37 | #28C2D1 38 | #7BDDEF 39 | #C3F2F4 40 | #3E8EED 41 | #72ACF1 42 | #A7CBF6 43 | 44 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/SkiaImageView.Maui.Sample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 9 | net6.0-windows10.0.19041.0 10 | Exe 11 | true 12 | true 13 | SkiaImageView.Sample 14 | 15 | 16 | SkiaImageView.Maui.Sample 17 | 18 | 19 | com.SkiaImageView.Maui.Sample 20 | CF5C5A32-54AA-4A21-9D61-9B6B9233EFCF 21 | 22 | 23 | 1.0.0 24 | 1 25 | 26 | 14.2 27 | 14.0 28 | 21.0 29 | 10.0.17763.0 30 | 10.0.17763.0 31 | 6.5 32 | en-us 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/ViewModels/ItemViewModel.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using SkiaSharp; 13 | 14 | namespace SkiaImageView.Sample.ViewModels; 15 | 16 | [ViewModel] 17 | public sealed class ItemViewModel 18 | { 19 | public string? Title { get; set; } 20 | 21 | public SKBitmap? Image { get; set; } 22 | 23 | public int Score { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/ViewModels/MainContentPageViewModel.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using SkiaImageView.Sample.Models; 13 | using SkiaSharp; 14 | using System; 15 | using System.Collections.ObjectModel; 16 | using System.Linq; 17 | using System.Threading.Tasks; 18 | 19 | namespace SkiaImageView.Sample.ViewModels; 20 | 21 | [ViewModel] 22 | public sealed class MainContentPageViewModel 23 | { 24 | public MainContentPageViewModel() 25 | { 26 | // A handler for page appearing 27 | this.Ready = Command.Factory.Create(() => 28 | { 29 | this.IsEnabled = true; 30 | return default; 31 | }); 32 | 33 | // A handler for fetch button 34 | this.Fetch = Command.Factory.Create(async () => 35 | { 36 | // Disable button 37 | this.IsEnabled = false; 38 | 39 | try 40 | { 41 | // Uses The Cat API 42 | var cats = await TheCatAPI.FetchTheCatsAsync(10); 43 | 44 | this.Items.Clear(); 45 | 46 | static async ValueTask FetchImageAsync(Uri url) => 47 | SKBitmap.Decode(await TheCatAPI.FetchImageAsync(url)); 48 | 49 | foreach (var cat in cats) 50 | { 51 | if (cat.Url is { } url) 52 | { 53 | var bleed = cat?.Bleeds.FirstOrDefault(); 54 | this.Items.Add(new ItemViewModel 55 | { 56 | Title = bleed?.Description ?? bleed?.Temperament ?? "(No comment)", 57 | Score = bleed?.Intelligence ?? 5, 58 | Image = await FetchImageAsync(url) 59 | }); 60 | } 61 | } 62 | } 63 | finally 64 | { 65 | // Re-enable button 66 | this.IsEnabled = true; 67 | } 68 | }); 69 | } 70 | 71 | public Command Ready { get; } 72 | 73 | public bool IsEnabled { get; private set; } 74 | 75 | public ObservableCollection Items { get; } = new(); 76 | 77 | public Command Fetch { get; } 78 | } 79 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Views/Converters/ScoreToBrushConverter.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using Microsoft.Maui.Controls; 13 | using Microsoft.Maui.Graphics; 14 | 15 | namespace SkiaImageView.Sample.Views.Converters; 16 | 17 | public sealed class ScoreToBrushConverter : ValueConverter 18 | { 19 | private static readonly Brush yellow = new SolidColorBrush(Color.FromRgba(96, 96, 0, 255)); 20 | private static readonly Brush gray = new SolidColorBrush(Color.FromRgba(96, 96, 96, 255)); 21 | 22 | public override bool TryConvert(int from, out Brush result) 23 | { 24 | result = from >= 5 ? yellow : gray; 25 | return true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Maui.Sample/Views/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 38 | 39 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 53 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Wpf.Sample/Views/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using System.Windows; 12 | 13 | namespace SkiaImageView.Sample.Views; 14 | 15 | public sealed partial class MainWindow : Window 16 | { 17 | public MainWindow() => 18 | InitializeComponent(); 19 | } 20 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with your package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 20 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Android.App; 12 | using Android.Content.PM; 13 | using Android.OS; 14 | using Android.Runtime; 15 | 16 | namespace SkiaImageView.Sample 17 | { 18 | [Activity( 19 | Label = "SkiaImageView.Sample", 20 | Icon = "@mipmap/icon", 21 | Theme = "@style/MainTheme", 22 | MainLauncher = true, 23 | ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )] 24 | public sealed class MainActivity : 25 | global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity 26 | { 27 | protected override void OnCreate(Bundle savedInstanceState) 28 | { 29 | TabLayoutResource = Resource.Layout.Tabbar; 30 | ToolbarResource = Resource.Layout.Toolbar; 31 | 32 | base.OnCreate(savedInstanceState); 33 | 34 | global::Xamarin.Essentials.Platform.Init(this, savedInstanceState); 35 | global::Xamarin.Forms.Forms.Init(this, savedInstanceState); 36 | 37 | LoadApplication(new App()); 38 | } 39 | public override void OnRequestPermissionsResult( 40 | int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) 41 | { 42 | global::Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); 43 | 44 | base.OnRequestPermissionsResult(requestCode, permissions, grantResults); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Epoxy template source code. 4 | // Write your own copyright and note. 5 | // (You can use https://github.com/rubicon-oss/LicenseHeaderManager) 6 | // 7 | //////////////////////////////////////////////////////////////////////////// 8 | 9 | using Android.App; 10 | 11 | // Add some common permissions, these can be removed if not needed 12 | [assembly: UsesPermission(Android.Manifest.Permission.Internet)] 13 | [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] 14 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.xml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable-hdpi/ 12 | icon.png 13 | 14 | drawable-ldpi/ 15 | icon.png 16 | 17 | drawable-mdpi/ 18 | icon.png 19 | 20 | layout/ 21 | main.xml 22 | 23 | values/ 24 | strings.xml 25 | 26 | In order to get the build system to recognize Android resources, set the build action to 27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 28 | instead operate on resource IDs. When you compile an Android application that uses resources, 29 | the build system will package the resources for distribution and generate a class called 30 | "Resource" that contains the tokens for each one of the resources included. For example, 31 | for the above Resources layout, this is what the Resource class would expose: 32 | 33 | public class Resource { 34 | public class drawable { 35 | public const int icon = 0x123; 36 | } 37 | 38 | public class layout { 39 | public const int main = 0x456; 40 | } 41 | 42 | public class strings { 43 | public const int first_string = 0xabc; 44 | public const int second_string = 0xbcd; 45 | } 46 | } 47 | 48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main 49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first 50 | string in the dictionary file values/strings.xml. 51 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/layout/Tabbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 22 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/layout/Toolbar.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 19 | 20 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-anydpi-v26/icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-anydpi-v26/icon_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-hdpi/icon.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-hdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-hdpi/launcher_foreground.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-mdpi/icon.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-mdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-mdpi/launcher_foreground.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xhdpi/icon.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xxhdpi/icon.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xxhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xxhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xxxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xxxhdpi/icon.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kekyo/SkiaImageView/0f67423ed40044eeae64641cfffc6b99272a278f/samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | #FFFFFF 14 | #3F51B5 15 | #303F9F 16 | #FF4081 17 | 18 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.Android/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 28 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.UI/App.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.UI/App.xaml.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using SkiaImageView.Sample.Views; 12 | using Xamarin.Forms; 13 | 14 | namespace SkiaImageView.Sample; 15 | 16 | public sealed partial class App : Application 17 | { 18 | public App() 19 | { 20 | InitializeComponent(); 21 | 22 | MainPage = new MainPage(); 23 | } 24 | 25 | protected override void OnStart() 26 | { 27 | } 28 | 29 | protected override void OnSleep() 30 | { 31 | } 32 | 33 | protected override void OnResume() 34 | { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.UI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Xamarin.Forms.Xaml; 12 | 13 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)] 14 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.UI/SkiaImageView.Xamarin.Forms.Sample.UI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | true 6 | latest 7 | enable 8 | portable 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.UI/ViewModels/ItemViewModel.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using SkiaSharp; 13 | 14 | namespace SkiaImageView.Sample.ViewModels; 15 | 16 | [ViewModel] 17 | public sealed class ItemViewModel 18 | { 19 | public string? Title { get; set; } 20 | 21 | public SKBitmap? Image { get; set; } 22 | 23 | public int Score { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.UI/ViewModels/MainContentPageViewModel.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using SkiaImageView.Sample.Models; 13 | using SkiaSharp; 14 | using System; 15 | using System.Collections.ObjectModel; 16 | using System.Linq; 17 | using System.Threading.Tasks; 18 | 19 | namespace SkiaImageView.Sample.ViewModels; 20 | 21 | [ViewModel] 22 | public sealed class MainContentPageViewModel 23 | { 24 | public MainContentPageViewModel() 25 | { 26 | // A handler for page appearing 27 | this.Ready = Command.Factory.Create(() => 28 | { 29 | this.IsEnabled = true; 30 | return default; 31 | }); 32 | 33 | // A handler for fetch button 34 | this.Fetch = Command.Factory.Create(async () => 35 | { 36 | // Disable button 37 | this.IsEnabled = false; 38 | 39 | try 40 | { 41 | // Uses The Cat API 42 | var cats = await TheCatAPI.FetchTheCatsAsync(10); 43 | 44 | this.Items.Clear(); 45 | 46 | static async ValueTask FetchImageAsync(Uri url) => 47 | SKBitmap.Decode(await TheCatAPI.FetchImageAsync(url)); 48 | 49 | foreach (var cat in cats) 50 | { 51 | if (cat.Url is { } url) 52 | { 53 | var bleed = cat?.Bleeds.FirstOrDefault(); 54 | this.Items.Add(new ItemViewModel 55 | { 56 | Title = bleed?.Description ?? bleed?.Temperament ?? "(No comment)", 57 | Score = bleed?.Intelligence ?? 5, 58 | Image = await FetchImageAsync(url) 59 | }); 60 | } 61 | } 62 | } 63 | finally 64 | { 65 | // Re-enable button 66 | this.IsEnabled = true; 67 | } 68 | }); 69 | } 70 | 71 | public Command Ready { get; } 72 | 73 | public bool IsEnabled { get; private set; } 74 | 75 | public ObservableCollection Items { get; } = new(); 76 | 77 | public Command Fetch { get; } 78 | } 79 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.UI/Views/Converters/ScoreToBrushConverter.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // SkiaImageView - Easy way showing SkiaSharp-based image objects onto UI applications. 4 | // 5 | // Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud) 6 | // 7 | // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0 8 | // 9 | //////////////////////////////////////////////////////////////////////////// 10 | 11 | using Epoxy; 12 | using Xamarin.Forms; 13 | 14 | namespace SkiaImageView.Sample.Views.Converters; 15 | 16 | public sealed class ScoreToBrushConverter : ValueConverter 17 | { 18 | private static readonly Brush yellow = new SolidColorBrush(Color.FromRgba(96, 96, 0, 255)); 19 | private static readonly Brush gray = new SolidColorBrush(Color.FromRgba(96, 96, 96, 255)); 20 | 21 | public override bool TryConvert(int from, out Brush result) 22 | { 23 | result = from >= 5 ? yellow : gray; 24 | return true; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /samples/SkiaImageView.Xamarin.Forms.Sample/SkiaImageView.Xamarin.Forms.Sample.UI/Views/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |