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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue30350.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:Maui.Controls.Sample.Issues"
x:Class="Maui.Controls.Sample.Issues.Issue30350"
x:DataType="controls:Issue30350">
<ScrollView>
<VerticalStackLayout Padding="20"
Spacing="15">
<Label
AutomationId="WaitForStubControl"
Text="Issue 30350 - IImage downsize broken - images flipped/rotated since 9.0.80"
FontSize="16"
HorizontalOptions="Center"/>

<!-- Original Image Info -->
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Original image: "/>
<Span Text="{Binding OriginalSize}"
FontAttributes="Bold"
TextColor="Blue"/>
</FormattedString>
</Label.FormattedText>
</Label>

<!-- Original Image Display -->
<Image Source="{Binding OriginalSource}"
AutomationId="OriginalImage"
HeightRequest="200"
Aspect="AspectFit"/>

<!-- Downsized Image Info -->
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Downsized image: "/>
<Span Text="{Binding DownsizedImageSize}"
FontAttributes="Bold"
TextColor="Blue"/>
</FormattedString>
</Label.FormattedText>
</Label>

<!-- Downsized Image Display -->
<Image Source="{Binding DownsizedSource}"
AutomationId="DownsizedImage"
HeightRequest="200"
Aspect="AspectFit"/>

<!-- Status -->
<Label x:Name="StatusLabel"
AutomationId="StatusLabel"
Text="Loading images..."
FontSize="14"
HorizontalOptions="Center"
TextColor="Green"/>

</VerticalStackLayout>
</ScrollView>
</controls:TestContentPage>
142 changes: 142 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue30350.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Graphics.Platform;
using IImage = Microsoft.Maui.Graphics.IImage;

namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 30350, "IImage downsize broken starting from 9.0.80 and not fixed in 9.0.81", PlatformAffected.iOS)]
public partial class Issue30350 : TestContentPage
Copy link
Preview

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class does not properly implement INotifyPropertyChanged interface. While it uses OnPropertyChanged() calls, the class should explicitly implement INotifyPropertyChanged and include the event declaration for proper data binding functionality.

Copilot generated this review using guidance from repository custom instructions.

{
private ImageSource _originalSource;
private string _originalSize;
private ImageSource _downsizedSource;
private string _downsizedImageSize;

public Issue30350()
{
InitializeComponent();
BindingContext = this;
}

protected override void Init()
{
// Delay loading to ensure all controls are initialized
Dispatcher.Dispatch(async () => await LoadImagesAsync());
}

public ImageSource OriginalSource
{
get => _originalSource;
set
{
if (Equals(value, _originalSource))
Copy link
Preview

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Equals() on ImageSource objects may not work as expected since ImageSource doesn't override Equals(). Consider using ReferenceEquals() or implement a custom comparison method.

Copilot uses AI. Check for mistakes.

return;
_originalSource = value;
OnPropertyChanged();
}
}

public ImageSource DownsizedSource
{
get => _downsizedSource;
set
{
if (Equals(value, _downsizedSource))
Copy link
Preview

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Equals() on ImageSource objects may not work as expected since ImageSource doesn't override Equals(). Consider using ReferenceEquals() or implement a custom comparison method.

Suggested change
if (Equals(value, _downsizedSource))
if (ReferenceEquals(value, _downsizedSource))

Copilot uses AI. Check for mistakes.

return;
_downsizedSource = value;
OnPropertyChanged();
}
}

public string OriginalSize
{
get => _originalSize;
set
{
if (value == _originalSize)
return;
_originalSize = value;
OnPropertyChanged();
}
}

public string DownsizedImageSize
{
get => _downsizedImageSize;
set
{
if (value == _downsizedImageSize)
return;
_downsizedImageSize = value;
OnPropertyChanged();
}
}

private async Task LoadImagesAsync()
{
try
{
// Check if StatusLabel is available
if (StatusLabel != null)
StatusLabel.Text = "Loading images...";

// Load original image from embedded resource
OriginalSource = ImageSource.FromResource("Controls.TestCases.HostApp.Resources.Images.royals.png");

// Load IImage for processing
var assembly = GetType().GetTypeInfo().Assembly;
using var stream = assembly.GetManifestResourceStream("Controls.TestCases.HostApp.Resources.Images.royals.png");

if (stream == null)
{
if (StatusLabel != null)
StatusLabel.Text = "Error: Could not load royals.png resource";
return;
}

var originalImage = PlatformImage.FromStream(stream);
if (originalImage == null)
{
if (StatusLabel != null)
StatusLabel.Text = "Error: Could not create IImage from stream";
return;
}

OriginalSize = $"{originalImage.Width}x{originalImage.Height}";

// Perform downsize operation - this is where the issue occurs in MAUI 9.0.80+
// The downsized image should be flipped/rotated incorrectly on iOS 9.0.80+
var downsizedImage = originalImage.Downsize(100);
if (downsizedImage == null)
{
if (StatusLabel != null)
StatusLabel.Text = "Error: Downsize operation failed";
return;
}

DownsizedImageSize = $"{downsizedImage.Width}x{downsizedImage.Height}";

// Convert downsized IImage to ImageSource
using var downsizedStream = new MemoryStream();
await downsizedImage.SaveAsync(downsizedStream, ImageFormat.Png);
downsizedStream.Position = 0;

DownsizedSource = ImageSource.FromStream(() => new MemoryStream(downsizedStream.ToArray()));

if (StatusLabel != null)
StatusLabel.Text = "Images loaded. Compare for flipping/rotation issues in MAUI 9.0.80+";
}
catch (Exception ex)
{
if (StatusLabel != null)
StatusLabel.Text = $"Error loading images: {ex.Message}";
}
}
}
}
80 changes: 80 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue30426.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:Maui.Controls.Sample.Issues"
x:Class="Maui.Controls.Sample.Issues.Issue30426">
<ScrollView>
<VerticalStackLayout Padding="20"
Spacing="15">
<Label
AutomationId="WaitForStubControl"
Text="Issue 30426 - IImage Downsize() throws Exception in 9.0.81 when called from background thread on iOS"
FontSize="16"
HorizontalOptions="Center"/>

<!-- Image display area -->
<Border
Stroke="Gray"
StrokeThickness="1"
BackgroundColor="LightGray"
HeightRequest="200"
WidthRequest="300"
HorizontalOptions="Center">
<Image x:Name="DisplayImage"
AutomationId="DisplayImage"
Aspect="AspectFit"
Source="royals.png"/>
</Border>

<!-- File info display -->
<Label x:Name="FileSizeLabel"
AutomationId="FileSizeLabel"
Text="File Size: Not loaded"
FontSize="14"/>

<Label x:Name="DimensionsLabel"
AutomationId="DimensionsLabel"
Text="Dimensions: Not loaded"
FontSize="14"/>

<!-- Load Image Button -->
<Button
x:Name="LoadImageButton"
AutomationId="LoadImageButton"
Text="Load Embedded Image (royals.png)"
Clicked="OnSelectImageClicked"/>

<Label Text="Resize Percentage:"
FontSize="16"/>
<Label x:Name="ResizeLabel"
Text="50%"/>
<Slider x:Name="ResizeSlider"
AutomationId="ResizeSlider"
Minimum="10"
Maximum="100"
Value="50"
ValueChanged="OnResizeSliderChanged"/>

<Button
x:Name="ProcessImageButton"
AutomationId="ProcessImageButton"
Text="Process Image (IImage.Downsize())"
Clicked="OnProcessImageClicked"/>

<!-- Status and results -->
<Label x:Name="StatusLabel"
AutomationId="StatusLabel"
Text="Status: Ready"
FontSize="14"
TextColor="Blue"/>

<Label x:Name="ErrorLabel"
AutomationId="ErrorLabel"
Text=""
FontSize="14"
TextColor="Red"
IsVisible="False"/>

</VerticalStackLayout>
</ScrollView>
</controls:TestContentPage>
Loading
Loading