Jump to content
Hans♫

Load of JPG fails - only on MacOS Sonoma running on Intel!

Recommended Posts

This must be a bug in Delphi, but it seems to be out of my hands, so for now we just replace our JPG files with PNG files.

However, in case someone would experience similar problems or want to look into it, here is what I have found.

 

We load the exact same jpg file using the exact same code, but the result:

Windows: OK

iOS: OK

Android: OK

MacOS not Sonoma: OK

MacOS Sonoma with ARM processor: OK

MacOS Sonoma with Intel processor: Exception

 

Stacktrace:

System.Error(System.TRuntimeError)(reInvalidOp)
System.FRaiseExcept(unsigned int, bool)(1,true)
System._Round(long double)(NaN)
Fmx.Multiresbitmap.TBitmapOfItem.DoChange()($000060000198c420)
Fmx.Graphics.TBitmap.BitmapChanged()($000060000198c420)
Fmx.Graphics.TBitmap.SetSize(int, int)($000060000198c420,3000,1496)
Fmx.Graphics.TBitmap.AssignFromSurface(Fmx.Surfaces.TBitmapSurface*)($000060000198c420,$0000600003388c00)
Fmx.Graphics.TBitmap.Assign(System.Classes.TPersistent*)($000060000198c420,$0000600003388c00)
Fmx.Graphics.TBitmap.LoadFromStream(System.Classes.TStream*)($000060000198c420,$0000600002846a80)
Uoscommon.LoadBitmapResource(Fmx.Graphics.TBitmap*, System.UnicodeString)($000060000198c420,'HomeBackGround2048')
Fomain.tMainForm.FormCreate(System.TObject*)($00007fd5090cfa00)
Fmx.Forms.TCommonCustomForm.AfterConstruction()($00007fd5090cfa00)
System._AfterConstruction(System.TObject*)(0x7fd5090cfa00)
Fomain.tMainForm.tMainForm(System.Classes.TComponent*)($00007fd5090cfa00,true,$00007fd509907af0)
Fmx.Forms.TApplication.CreateForm(System.Classes.TComponentClass, void*)($00007fd509907af0,0x1021a0bd0,0x1021a46d0)
Fmx.Forms.TApplication.RealCreateForms()($00007fd509907af0)
Fmx.Platform.Mac.TPlatformCocoa.Run()($00007fd508715880)
Fmx.Forms.TApplication.Run()($00007fd509907af0)
main(1,0x7ff7bfeff8e0,0x7ff7bfeff8f0,0x7ff7bfeff9a0)
:00007FF80ED623A6 ??

It happens when calling "Round" in this procedure:

procedure TBitmapOfItem.DoChange;
begin
  inherited;
  if (FBitmapItem <> nil) and (not FBitmapItem.FDormantChanging) then
  begin
    FIsChanged := True;
    FBitmapItem.FWidth := Round(Width); //<- exception here. Width is an integer property with value 3000
    FBitmapItem.FHeight := Round(Height);
    if (FBitmapItem.Component <> nil) and ([csLoading, csDestroying] * FBitmapItem.Component.ComponentState = []) and
      (FBitmapItem.Collection is TCustomMultiResBitmap) and
      (TCustomMultiResBitmap(FBitmapItem.Collection).UpdateCount = 0) then
      FBitmapItem.Changed(False);
  end;
end;

The Round function being called that raises the exception:

function _Round(Val: Extended): Int64;
type
  TWords = Array[0..4] of Word;
  PWords = ^TWords;
begin
  if (PWords(@Val)^[4] and $7FFF) >= $403F then
    FRaiseExcept(feeINVALID);
  Result := llrintl(Val);
end;

The image being loaded is added to the project as a ressource with the ID "HomeBackGround2048", which refers to a JPG image with dimensions 3000x1496. We load it using this function:

procedure LoadBitmapResource(const aBitmap: TBitmap; const aResourceName: string);
var lStream: TResourceStream;
begin
  lStream := TResourceStream.Create(HInstance, aResourceName, RT_RCDATA);
  try
    aBitmap.LoadFromStream(lStream);
  finally
    lStream.Free;
  end;
end;

 

Share this post


Link to post

This is a known issue. Reported as https://quality.embarcadero.com/browse/RSP-40939

 

The issue is caused by some change on OS level which trashes the FPU. Above report contains a patch containing fpu_init2 procedure which needs to be called after loading from stream. The patch seems to solve the issue in particular scenario for the reporter. 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×