iOS Question ImageView in B4i is pixelated

Martin Larsen

Active Member
Licensed User
Longtime User
I have a problem with images in ImageViews which in B4i are very pixelated in contrast to B4A where the same images are sharp.

Examples below with images cut out from app screenshots. B4A is first.
1601471713199.png
1601471746488.png


The effect is real, it is not just caused by the screenshots.

How can I fix this problem?

Example app attached.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I haven't ran your code, however the problem is here:
B4X:
x = x.Resize(ImageView1.Width, ImageView1.Height, True)
Don't resize the image. You will reduce its scale. It also hurts performance, though it is not relevant in this simple case.

Best solution is to use B4XImageView from XUI Views and set the scaling to FIT.
 
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
Don't resize the image. You will reduce its scale.

You are right, I just found out seconds before your reply. However, in the original example (taken from a real app) I had to resize to make it work. It is used by the imageslider and without resizing and even with scaling = FIT, it doesn't scale and shows only a part of the image. I will look into that a bit more and come back.

Best solution is to use B4XImageView from XUI Views and set the scaling to FIT.

I already tried B4XImageView but it doesn't compile in B4i. I guess it misses the library. It should be an internal library, and I am using v6.80. It works in B4A.
 
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
I have come a bit closer. The ImageSlider actually doesn't use ImageView at all. The image is loaded directly in ShowImage:

B4X:
Private Sub ShowImage (bmp As B4XBitmap, MovingToNext As Boolean)
    NextPanel.GetView(0).SetBitmap(bmp)
    ...
End Sub

If I use GetDeviceLayoutValues.NonnormalizedScale or don't scale at all, the image will not fit in the slider. Only a part of it is shown. There is no ImageSlider.ContentMode property.

How can I make the image fit in the slider without down scaling it?

Also, why does the same code work perfectly in B4A without quality loss?
 
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
I have attached a modified project using ImageSlider instead of ImageView.

On Android the image is sharp, on IOS it is pixelated.
B4X:
Sub ImageSlider1_GetImage (Index As Int) As ResumableSub
    Wait For (DownloadImage) Complete (bmp As B4XBitmap)
    Dim scale As Float = 1
    #if B4i
'    if scale is set as below, the image is not resized correctly
'    scale = GetDeviceLayoutValues.NonnormalizedScale
    #End If
    bmp = bmp.Resize(ImageSlider1.WindowBase.Width*scale, ImageSlider1.WindowBase.Height*scale, True)
    Return bmp
End Sub

If I uncomment line 6 in B4i, the image is not resized to fit. It is way to large. And with scale = 1 it is blurred.
 

Attachments

  • imageview.zip
    9.5 KB · Views: 196
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
V1.12 is attached. I haven't tested it enough so I'm not updating the official library.

GetImage code:
B4X:
Sub ImageSlider1_GetImage (Index As Int) As ResumableSub
    Wait For (DownloadImage) Complete (bmp As B4XBitmap)
    bmp = bmp.Resize(ImageSlider1.WindowBase.Width * ImageSlider1.ImageScale, ImageSlider1.WindowBase.Height * ImageSlider1.ImageScale, True)
    Return bmp
End Sub
 

Attachments

  • ImageSlider.bas
    7.2 KB · Views: 182
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
It works :)

From your code I can see that when scaling outside ImageSlider library, the image got twice as big as it should.

I have two suggestions for the library now that you are about to update it:

1. Add a OnShow event which is useful for doing stuff whenever a new image is shown. I have already included it in my local version and used it for a long time:

B4X:
Private Sub ShowImage (bmp As B4XBitmap, MovingToNext As Boolean)
    NextPanel.GetView(0).SetBitmap(bmp)
    ...
    NextPanel = p
    DrawIndicators
    CallSub2(mCallBack, mEventName & "_Show", CurrentIndex)
End Sub

2. Add #event headers for OnClick (and OnShow) in the library. Just like for GetImage.
B4X:
#Event: Click (Index As Int)
#Event: Show (Index As Int)
 
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
Ok, I guess it's a matter of words :) But it is still very useful with a OnShow event, and if people don't need it, it doesn't harm (and it's just a single line). The #Event attribute is convenient for generating events from the designer. It also makes it more intuitive (discoverable) by letting users know from the designer that eg. the Click event exists.
 
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
Shouldn't the same mods be made to ShowStartImage?

B4X:
Public Sub ShowStartImage (bmp As B4XBitmap)
    NextPanel.GetView(0).SetBitmap(bmp)
    NextPanel.GetView(0).SetLayoutAnimated(0, WindowBase.Width / 2 - bmp.Width / 2 / ImageScale, _
        WindowBase.Height / 2 - bmp.Height / 2 / ImageScale, bmp.Width / ImageScale, bmp.Height / ImageScale)
    NextPanel.Visible = True
End Sub
 
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
ShowStartImage is great for presenting the first image in the slider. It makes the initial appearance much better. However, when you then move to the next slide, you will see a temporary empty panel which does not look good.

With this mod of ShowStartImage, the transition is perfect:

B4X:
Public Sub ShowStartImage (bmp As B4XBitmap)
    CurrentIndex = 0
    CurrentPanel.GetView(0).SetBitmap(bmp)
    CurrentPanel.GetView(0).SetLayoutAnimated(0, WindowBase.Width / 2 - bmp.Width / 2 / ImageScale, _
        WindowBase.Height / 2 - bmp.Height / 2 / ImageScale, bmp.Width / ImageScale, bmp.Height / ImageScale)
    CurrentPanel.Visible = True
End Sub

I have replaced NextPanel with CurrentPanel and set CurrentIndex = 0 instead of -1. This is because you should skip directly to the second image when using ShowStartImage as the first image has already been shown.
 
Upvote 0
Top