Make sure to properly read image pixels (#1636)

Fixes #1503
This commit is contained in:
Matthew Leibowitz 2021-03-14 13:46:53 +02:00 коммит произвёл GitHub
Родитель 8be3cd9602
Коммит 7d20f6fda0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 514 добавлений и 62 удалений

Просмотреть файл

@ -15,7 +15,7 @@ parameters:
condition: succeeded() # whether or not to run this template
shouldPublish: true # whether or not to publish the artifacts
configuration: $(CONFIGURATION) # the build configuration
buildExternals: '' # the build number to download externals from
buildExternals: '4555063' # the build number to download externals from
verbosity: $(VERBOSITY) # the level of verbosity to use when building
docker: '' # the Docker image to build and use
dockerArgs: '' # any additional arguments to pass to docker build
@ -26,17 +26,17 @@ parameters:
installEmsdk: false # whether or not to install the Emscripten SDK
jobs:
# - ${{ if and(ne(parameters.buildExternals, ''), startsWith(parameters.name, 'native_')) }}:
# - template: azure-templates-download.yml
# parameters:
# name: ${{ parameters.name }}
# displayName: ${{ parameters.displayName }}
# vmImage: ${{ parameters.vmImage }}
# condition: ${{ parameters.condition }}
# postBuildSteps: ${{ parameters.postBuildSteps }}
# buildExternals: ${{ parameters.buildExternals }}
- ${{ if and(ne(parameters.buildExternals, ''), startsWith(parameters.name, 'native_')) }}:
- template: azure-templates-download.yml
parameters:
name: ${{ parameters.name }}
displayName: ${{ parameters.displayName }}
vmImage: ${{ parameters.vmImage }}
condition: ${{ parameters.condition }}
postBuildSteps: ${{ parameters.postBuildSteps }}
buildExternals: ${{ parameters.buildExternals }}
# - ${{ if or(eq(parameters.buildExternals, ''), not(startsWith(parameters.name, 'native_'))) }}:
- ${{ if or(eq(parameters.buildExternals, ''), not(startsWith(parameters.name, 'native_'))) }}:
- job: ${{ parameters.name }}
displayName: ${{ parameters.displayName }}
timeoutInMinutes: 120

Просмотреть файл

@ -139,9 +139,9 @@ namespace SkiaSharp.Views.Android
}
}
public static Bitmap ToBitmap(this SKPixmap skiaPixmap)
public static Bitmap ToBitmap(this SKImage skiaImage)
{
var info = skiaPixmap.Info;
var info = skiaImage.Info;
// destination values
var config = Bitmap.Config.Argb8888;
@ -172,7 +172,7 @@ namespace SkiaSharp.Views.Android
var ptr = bmp.LockPixels();
// copy
var success = skiaPixmap.ReadPixels(dstInfo, ptr, dstInfo.RowBytes);
var success = skiaImage.ReadPixels(dstInfo, ptr, dstInfo.RowBytes);
// confirm
bmp.UnlockPixels();
@ -183,15 +183,15 @@ namespace SkiaSharp.Views.Android
bmp = null;
}
GC.KeepAlive(skiaImage);
return bmp;
}
public static Bitmap ToBitmap(this SKImage skiaImage)
public static Bitmap ToBitmap(this SKPixmap skiaPixamp)
{
using (var pixmap = skiaImage.PeekPixels())
using (var image = SKImage.FromPixels(skiaPixamp))
{
var bmp = pixmap.ToBitmap();
GC.KeepAlive(skiaImage);
var bmp = image.ToBitmap();
return bmp;
}
}

Просмотреть файл

@ -15,6 +15,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.Android", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.Forms.Android", "..\source\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Android\SkiaSharp.Views.Forms.Android.csproj", "{F962E49D-DC1F-4E93-9F6B-335E2746BCF1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HarfBuzzSharp", "..\binding\HarfBuzzSharp\HarfBuzzSharp.csproj", "{814F4C3B-0767-4A6C-B274-71EAD305D2BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp", "..\binding\SkiaSharp\SkiaSharp.csproj", "{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -47,6 +51,14 @@ Global
{F962E49D-DC1F-4E93-9F6B-335E2746BCF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F962E49D-DC1F-4E93-9F6B-335E2746BCF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F962E49D-DC1F-4E93-9F6B-335E2746BCF1}.Release|Any CPU.Build.0 = Release|Any CPU
{814F4C3B-0767-4A6C-B274-71EAD305D2BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{814F4C3B-0767-4A6C-B274-71EAD305D2BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{814F4C3B-0767-4A6C-B274-71EAD305D2BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{814F4C3B-0767-4A6C-B274-71EAD305D2BF}.Release|Any CPU.Build.0 = Release|Any CPU
{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9C1E6E5-D56B-4B10-946C-6493AE1C57FA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -0,0 +1,75 @@
using Xunit;
namespace SkiaSharp.Views.Android.Tests
{
public class AndroidExtensionsTests : AndroidTests
{
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void PixelBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var image = SKImage.FromBitmap(bitmap);
using var androidBitmap = image.ToBitmap();
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void BitmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var androidBitmap = bitmap.ToBitmap();
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void PixmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var pixmap = bitmap.PeekPixels();
using var androidBitmap = pixmap.ToBitmap();
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void EncodedDataBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var image = SKImage.FromEncodedData(data);
using var androidBitmap = image.ToBitmap();
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
using Android.Graphics;
using SkiaSharp.Tests;
using Xunit;
namespace SkiaSharp.Views.Android.Tests
{
public abstract class AndroidTests : SKTest
{
protected static void ValidateTestBitmap(Bitmap bmp, byte alpha = 255)
{
Assert.NotNull(bmp);
Assert.Equal(40, bmp.Width);
Assert.Equal(40, bmp.Height);
Assert.Equal(Get(SKColors.Red), (uint)bmp.GetPixel(10, 10));
Assert.Equal(Get(SKColors.Green), (uint)bmp.GetPixel(30, 10));
Assert.Equal(Get(SKColors.Blue), (uint)bmp.GetPixel(10, 30));
Assert.Equal(Get(SKColors.Yellow), (uint)bmp.GetPixel(30, 30));
SKColor Get(SKColor color) =>
alpha == 0
? SKColor.Empty
: color.WithAlpha(alpha);
}
}
}

Просмотреть файл

@ -0,0 +1,93 @@
using System.Threading.Tasks;
using Android.App;
using SkiaSharp.Views.Android.Tests;
using Xunit;
namespace SkiaSharp.Views.Forms.Tests
{
public class SKImageSourceHandlerTests : AndroidTests
{
private readonly SKImageSourceHandler handler;
public SKImageSourceHandlerTests()
{
handler = new SKImageSourceHandler();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task PixelBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var image = SKImage.FromBitmap(bitmap);
var source = (SKImageImageSource)image;
using var androidBitmap = await handler.LoadImageAsync(source, Application.Context);
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task BitmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
var source = (SKBitmapImageSource)bitmap;
using var androidBitmap = await handler.LoadImageAsync(source, Application.Context);
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task PixmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var pixmap = bitmap.PeekPixels();
var source = (SKPixmapImageSource)pixmap;
using var androidBitmap = await handler.LoadImageAsync(source, Application.Context);
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task EncodedDataBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var image = SKImage.FromEncodedData(data);
var source = (SKImageImageSource)image;
using var androidBitmap = await handler.LoadImageAsync(source, Application.Context);
ValidateTestBitmap(androidBitmap, alpha);
androidBitmap.Recycle();
}
}
}

Просмотреть файл

@ -94,6 +94,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="AndroidExtensionsTests.cs" />
<Compile Include="AndroidTests.cs" />
<Compile Include="FormsExtensionsTests.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="TestInstrumentation.cs" />
</ItemGroup>

Просмотреть файл

@ -3,100 +3,128 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.808.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.iOS", "..\binding\SkiaSharp.iOS\SkiaSharp.iOS.csproj", "{A4146A87-DB60-4A17-A179-0E2E4255A08E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.iOS", "..\binding\SkiaSharp.iOS\SkiaSharp.iOS.csproj", "{A4146A87-DB60-4A17-A179-0E2E4255A08E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HarfBuzzSharp.iOS", "..\binding\HarfBuzzSharp.iOS\HarfBuzzSharp.iOS.csproj", "{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HarfBuzzSharp.iOS", "..\binding\HarfBuzzSharp.iOS\HarfBuzzSharp.iOS.csproj", "{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.HarfBuzz", "..\source\SkiaSharp.HarfBuzz\SkiaSharp.HarfBuzz\SkiaSharp.HarfBuzz.csproj", "{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.HarfBuzz", "..\source\SkiaSharp.HarfBuzz\SkiaSharp.HarfBuzz\SkiaSharp.HarfBuzz.csproj", "{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Views.iOS", "..\source\SkiaSharp.Views\SkiaSharp.Views.iOS\SkiaSharp.Views.iOS.csproj", "{549F8E22-A756-4E99-A84A-C4E74832DA95}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.iOS", "..\source\SkiaSharp.Views\SkiaSharp.Views.iOS\SkiaSharp.Views.iOS.csproj", "{549F8E22-A756-4E99-A84A-C4E74832DA95}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Views.Forms.iOS", "..\source\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.iOS\SkiaSharp.Views.Forms.iOS.csproj", "{0254162B-6B4A-459E-BD96-3A42A104C144}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.Forms.iOS", "..\source\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.iOS\SkiaSharp.Views.Forms.iOS.csproj", "{0254162B-6B4A-459E-BD96-3A42A104C144}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.iOS.Tests", "SkiaSharp.iOS.Tests\SkiaSharp.iOS.Tests.csproj", "{B73EB308-70BE-49FD-91A7-1D1495663D6D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HarfBuzzSharp", "..\binding\HarfBuzzSharp\HarfBuzzSharp.csproj", "{5D79739D-98C6-48A4-965E-064DB4C59955}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp", "..\binding\SkiaSharp\SkiaSharp.csproj", "{A694283C-FE40-4049-88AB-2CAE678FC087}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|iPhoneSimulator = Release|iPhoneSimulator
Debug|iPhone = Debug|iPhone
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|Any CPU = Release|Any CPU
Release|iPhone = Release|iPhone
Release|iPhoneSimulator = Release|iPhoneSimulator
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|Any CPU.Build.0 = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhone.Build.0 = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|Any CPU.Build.0 = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhone.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhone.Build.0 = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A4146A87-DB60-4A17-A179-0E2E4255A08E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|Any CPU.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhone.Build.0 = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|Any CPU.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhone.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhone.Build.0 = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{D958E2E9-DE32-42E8-AB10-D25E4186C4E1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|Any CPU.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhone.Build.0 = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|Any CPU.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhone.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhone.Build.0 = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A5614B8C-31C8-43A3-9BF9-2719E4BE4D36}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|Any CPU.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhone.Build.0 = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|Any CPU.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhone.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhone.Build.0 = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{549F8E22-A756-4E99-A84A-C4E74832DA95}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|Any CPU.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhone.Build.0 = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|Any CPU.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhone.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhone.Build.0 = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{0254162B-6B4A-459E-BD96-3A42A104C144}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhone.ActiveCfg = Debug|iPhone
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhone.Build.0 = Debug|iPhone
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhone.ActiveCfg = Release|iPhone
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhone.Build.0 = Release|iPhone
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{B73EB308-70BE-49FD-91A7-1D1495663D6D}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|iPhone.Build.0 = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|Any CPU.Build.0 = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|iPhone.ActiveCfg = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|iPhone.Build.0 = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5D79739D-98C6-48A4-965E-064DB4C59955}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|iPhone.Build.0 = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|Any CPU.Build.0 = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|iPhone.ActiveCfg = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|iPhone.Build.0 = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A694283C-FE40-4049-88AB-2CAE678FC087}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -0,0 +1,84 @@
using System.Threading.Tasks;
using SkiaSharp.Views.iOS.Tests;
using Xunit;
namespace SkiaSharp.Views.Forms.Tests
{
public class SKImageSourceHandlerTests : iOSTests
{
private readonly SKImageSourceHandler handler;
public SKImageSourceHandlerTests()
{
handler = new SKImageSourceHandler();
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task PixelBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var image = SKImage.FromBitmap(bitmap);
var source = (SKImageImageSource)image;
using var uiImage = await handler.LoadImageAsync(source);
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task BitmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
var source = (SKBitmapImageSource)bitmap;
using var uiImage = await handler.LoadImageAsync(source);
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task PixmapToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var pixmap = bitmap.PeekPixels();
var source = (SKPixmapImageSource)pixmap;
using var uiImage = await handler.LoadImageAsync(source);
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public async Task EncodedDataBackedImageToBitmap(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var image = SKImage.FromEncodedData(data);
var source = (SKImageImageSource)image;
using var uiImage = await handler.LoadImageAsync(source);
ValidateTestBitmap(uiImage, alpha);
}
}
}

Просмотреть файл

@ -94,9 +94,13 @@
<PackageReference Include="System.Buffers" Version="4.5.1" ExcludeAssets="all" />
</ItemGroup>
<ItemGroup>
<Compile Include="FormsExtensionsTests.cs" />
<Compile Include="iOSExtensionsTests.cs" />
<Compile Include="iOSTests.cs" />
<Compile Include="Main.cs" />
<Compile Include="AppDelegate.cs" />
<Compile Include="TestApplicationDelegate.cs" />
<Compile Include="TestExtensions.cs" />
<None Include="Entitlements.plist" />
<None Include="Info.plist" />
</ItemGroup>

Просмотреть файл

@ -0,0 +1,26 @@
using CoreGraphics;
namespace SkiaSharp.Views.iOS.Tests
{
public static class TestExtensions
{
public static SKColor GetPixel(this CGImage cgImage, int x, int y)
{
var data = cgImage.DataProvider.CopyData();
var bytesPerPixel = cgImage.BitsPerPixel / cgImage.BitsPerComponent;
var offset = (y * cgImage.BytesPerRow) + (x * bytesPerPixel);
var a = data[offset + 3];
var r = data[offset + 0];
var g = data[offset + 1];
var b = data[offset + 2];
if (a == 0)
return SKColor.Empty;
return (SKColor)new SKColorF((float)r / a, (float)g / a, (float)b / a, a / 255f);
}
}
}

Просмотреть файл

@ -0,0 +1,67 @@
using Xunit;
namespace SkiaSharp.Views.iOS.Tests
{
public class iOSExtensionsTests : iOSTests
{
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void PixelBackedImageToUIImage(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var image = SKImage.FromBitmap(bitmap);
using var iosBitmap = image.ToUIImage();
ValidateTestBitmap(iosBitmap, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void BitmapToUIImage(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var uiImage = bitmap.ToUIImage();
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void PixmapToUIImage(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var pixmap = bitmap.PeekPixels();
using var uiImage = pixmap.ToUIImage();
ValidateTestBitmap(uiImage, alpha);
}
[SkippableTheory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
[InlineData(255)]
public void EncodedDataBackedImageToUIImage(byte alpha)
{
using var bitmap = CreateTestBitmap(alpha);
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var image = SKImage.FromEncodedData(data);
using var uiImage = image.ToUIImage();
ValidateTestBitmap(uiImage, alpha);
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
using CoreGraphics;
using SkiaSharp.Tests;
using UIKit;
using Xunit;
namespace SkiaSharp.Views.iOS.Tests
{
public abstract class iOSTests : SKTest
{
protected static void ValidateTestBitmap(UIImage uiImage, byte alpha = 255)
{
var cgImage = uiImage.CGImage;
ValidateTestBitmap(cgImage, alpha);
}
protected static void ValidateTestBitmap(CGImage cgImage, byte alpha = 255)
{
Assert.NotNull(cgImage);
Assert.Equal(40, cgImage.Width);
Assert.Equal(40, cgImage.Height);
Assert.Equal(Get(SKColors.Red), cgImage.GetPixel(10, 10));
Assert.Equal(Get(SKColors.Green), cgImage.GetPixel(30, 10));
Assert.Equal(Get(SKColors.Blue), cgImage.GetPixel(10, 30));
Assert.Equal(Get(SKColors.Yellow), cgImage.GetPixel(30, 30));
SKColor Get(SKColor color) =>
alpha == 0
? SKColor.Empty
: color.WithAlpha(alpha);
}
}
}