bLight
bLight

Reputation: 865

Low quality delphi user interface design under Android when using TImage

Since Android phones are released in many different screen resolutions and my user interface is "skinned" using multiple TImage components, I've hit a major development issue, I must scale each of my images relative to the device's screen resolution.

For some reason which I can not understand, under Android, TImage is interpolated using a really low quality scaler (possibly nearest-neighbor), resulting in a very low quality image display (this happens even when the screen scale is taken into consideration and the form's quality is set the high).

Due to this, it means I can either pre-scale and include multiple different resolutions of the same image, hoping that it will look 'close enough' (and bloating my app), or I can use a software algorithm to scale the images in real-time and then cache the result for later runs.

I choose the second option, using a software bicubic scaler, but the problem is that my app has so many image resources, it can take 18 seconds to load the first time on a high end mobile device.

I'm aware it may be possible to do what I need in hardware using OpenGL, but I haven't been able to find a clear/clean example of how this can be done in Delphi for Android. And even if it can be done without having to re-code the entire UI for OpenGL.

Is there something I'm missing design wise? Is a fix from Embarcadero my only chance?

Upvotes: 1

Views: 739

Answers (1)

bLight
bLight

Reputation: 865

It took me a while to lock this down, but here is Android native code that will scale the image in high quality much faster than any pure software solution I could find and optimize:

uses Androidapi.JNI.Media, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNIBridge, FMX.Surfaces, FMX.Helpers.Android;

procedure AndroidResizeBitmap(srcBitmap,dstBitmap : TBitmap);
var
  sJBitmap     : JBitmap;
  ScaledBitmap : JBitmap;
  sSurface     : TBitmapSurface;
begin
  sSurface     := TBitmapSurface.Create;
  sSurface.Assign(srcBitmap);
  sJBitmap     := TJBitmap.JavaClass.createBitmap(sSurface.Width,   sSurface.Height,TJBitmap_Config.JavaClass.ARGB_8888);
  SurfaceToJBitmap(sSurface, sJBitmap);
  ScaledBitmap := TJBitmap.JavaClass.createScaledBitmap(sJBitmap,   dstBitmap.Width, dstBitmap.Height, True);
  sJBitmap     := nil;
  JBitmapToSurface(ScaledBitmap,sSurface);
  ScaledBitmap := nil;
  dstBitmap.Assign(sSurface);
  sSurface.Free;
  sSurface     := nil;
end;

Upvotes: 1

Related Questions