Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Graphics/src/Graphics.Skia/SkiaImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ public async Task SaveAsync(Stream stream, ImageFormat format = ImageFormat.Png,

private Stream GetSkStream(ImageFormat format, float quality)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

// Skia quality range from 0-100, this is supported by jpeg and webp. Higher values correspond to improved visual quality, but less compression.
const int MaxSKQuality = 100;
var skQuality = (int)(MaxSKQuality * quality);
Expand Down
6 changes: 6 additions & 0 deletions src/Graphics/src/Graphics.Win2D/W2DImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public IImage Resize(float width, float height, ResizeMode resizeMode = ResizeMo

public void Save(Stream stream, ImageFormat format = ImageFormat.Png, float quality = 1)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

switch (format)
{
case ImageFormat.Jpeg:
Expand All @@ -85,6 +88,9 @@ public void Save(Stream stream, ImageFormat format = ImageFormat.Png, float qual

public async Task SaveAsync(Stream stream, ImageFormat format = ImageFormat.Png, float quality = 1)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

switch (format)
{
case ImageFormat.Jpeg:
Expand Down
6 changes: 6 additions & 0 deletions src/Graphics/src/Graphics/PlatformImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public IImage Resize(float width, float height, ResizeMode resizeMode = ResizeMo

public void Save(Stream stream, ImageFormat format = ImageFormat.Png, float quality = 1)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

if (format == _originalFormat)
{
stream.Write(_bytes, 0, _bytes.Length);
Expand All @@ -58,6 +61,9 @@ public void Save(Stream stream, ImageFormat format = ImageFormat.Png, float qual

public Task SaveAsync(Stream stream, ImageFormat format = ImageFormat.Png, float quality = 1)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

if (format == _originalFormat)
{
Save(stream, format, quality);
Expand Down
6 changes: 6 additions & 0 deletions src/Graphics/src/Graphics/Platforms/Android/PlatformImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public IImage Resize(float width, float height, ResizeMode resizeMode = ResizeMo

public void Save(Stream stream, ImageFormat format = ImageFormat.Png, float quality = 1)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

switch (format)
{
case ImageFormat.Jpeg:
Expand All @@ -104,6 +107,9 @@ public void Save(Stream stream, ImageFormat format = ImageFormat.Png, float qual

public async Task SaveAsync(Stream stream, ImageFormat format = ImageFormat.Png, float quality = 1)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

switch (format)
{
case ImageFormat.Jpeg:
Expand Down
3 changes: 3 additions & 0 deletions src/Graphics/src/Graphics/Platforms/Mac/PlatformImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public async Task SaveAsync(Stream stream, ImageFormat format = ImageFormat.Png,

private NSData CreateRepresentation(ImageFormat format = ImageFormat.Png, float quality = 1)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

var previous = NSApplication.CheckForIllegalCrossThreadCalls;
NSApplication.CheckForIllegalCrossThreadCalls = false;

Expand Down
3 changes: 3 additions & 0 deletions src/Graphics/src/Graphics/Platforms/iOS/PlatformImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ public async Task SaveAsync(Stream stream, ImageFormat format = ImageFormat.Png,

private NSData CreateData(ImageFormat format = ImageFormat.Png, float quality = 1)
{
if (quality < 0 || quality > 1)
throw new ArgumentOutOfRangeException(nameof(quality), "quality must be in the range of 0..1");

NSData data;
switch (format)
{
Expand Down
107 changes: 107 additions & 0 deletions src/Graphics/tests/DeviceTests/Tests/ImageTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System.Threading.Tasks;
using Microsoft.Maui.Storage;
using Xunit;
using System;

#if WINDOWS
using Microsoft.Maui.Graphics.Win2D;
using PlatformImageLoadingService = Microsoft.Maui.Graphics.Win2D.W2DImageLoadingService;
#else
using Microsoft.Maui.Graphics.Platform;
#endif

namespace Microsoft.Maui.Graphics.DeviceTests;

public class ImageTests
{
[Theory]
[InlineData(ImageFormat.Png, 1.0f)]
[InlineData(ImageFormat.Png, 0.8f)]
[InlineData(ImageFormat.Png, 0.4f)]
[InlineData(ImageFormat.Jpeg, 1.0f)]
[InlineData(ImageFormat.Jpeg, 0.8f)]
[InlineData(ImageFormat.Jpeg, 0.4f)]
public async Task CanGetBytesFromImage(ImageFormat format, float quality)
{
var service = new PlatformImageLoadingService();

using var stream = await FileSystem.OpenAppPackageFileAsync("dotnet_bot.png");
using var image = service.FromStream(stream);

var bytes = image.AsBytes(format, quality);

Assert.NotNull(bytes);
Assert.NotEmpty(bytes);
}

[Theory]
[InlineData(ImageFormat.Png, 1.0f)]
[InlineData(ImageFormat.Png, 0.8f)]
[InlineData(ImageFormat.Png, 0.4f)]
[InlineData(ImageFormat.Jpeg, 1.0f)]
[InlineData(ImageFormat.Jpeg, 0.8f)]
[InlineData(ImageFormat.Jpeg, 0.4f)]
public async Task CanGetStreamFromImage(ImageFormat format, float quality)
{
var service = new PlatformImageLoadingService();

using var stream = await FileSystem.OpenAppPackageFileAsync("dotnet_bot.png");
using var image = service.FromStream(stream);

var newStream = image.AsStream(format, quality);

Assert.NotNull(newStream);
Assert.True(newStream.Length > 0, "Assert.True(newStream.Length > 0)");
}

[Theory]
[InlineData(ImageFormat.Png, 2.0f)]
[InlineData(ImageFormat.Png, 80f)]
[InlineData(ImageFormat.Png, -0.8f)]
[InlineData(ImageFormat.Jpeg, 2.0f)]
[InlineData(ImageFormat.Jpeg, 80f)]
[InlineData(ImageFormat.Jpeg, -0.8f)]
public async Task AsBytesWithQualityOutOfRangeThrowsArgumentException(ImageFormat format, float quality)
{
var service = new PlatformImageLoadingService();

using var stream = await FileSystem.OpenAppPackageFileAsync("dotnet_bot.png");
using var image = service.FromStream(stream);

Assert.Throws<ArgumentOutOfRangeException>(() => image.AsBytes(format, quality));
}

[Theory]
[InlineData(ImageFormat.Png, 2.0f)]
[InlineData(ImageFormat.Png, 80f)]
[InlineData(ImageFormat.Png, -0.8f)]
[InlineData(ImageFormat.Jpeg, 2.0f)]
[InlineData(ImageFormat.Jpeg, 80f)]
[InlineData(ImageFormat.Jpeg, -0.8f)]
public async Task AsBytesAsyncWithQualityOutOfRangeThrowsArgumentException(ImageFormat format, float quality)
{
var service = new PlatformImageLoadingService();

using var stream = await FileSystem.OpenAppPackageFileAsync("dotnet_bot.png");
using var image = service.FromStream(stream);

await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => image.AsBytesAsync(format, quality));
}

[Theory]
[InlineData(ImageFormat.Png, 2.0f)]
[InlineData(ImageFormat.Png, 80f)]
[InlineData(ImageFormat.Png, -0.8f)]
[InlineData(ImageFormat.Jpeg, 2.0f)]
[InlineData(ImageFormat.Jpeg, 80f)]
[InlineData(ImageFormat.Jpeg, -0.8f)]
public async Task AsStreamWithQualityOutOfRangeThrowsArgumentException(ImageFormat format, float quality)
{
var service = new PlatformImageLoadingService();

using var stream = await FileSystem.OpenAppPackageFileAsync("dotnet_bot.png");
using var image = service.FromStream(stream);

Assert.Throws<ArgumentOutOfRangeException>(() => image.AsStream(format, quality));
}
}