Android Question ImageView Bitmap centered

LucaMs

Expert
Licensed User
Longtime User
I don't know the right definition...
I use a Tool in wich it is named "Streched proportional".

I have not been able to get this "simple" thing:
upload_2014-8-12_15-0-12.png



(boxes represent some ImageView. On the right the two loaded files)

I tried with "normal" code, and also using the Informatix's BetterImageView library.

I post one of the 100 attempts.
B4X:
Sub FitCenterBitmap(Imv As ImageView, Dir As String, FileName As String)
    Imv.Gravity = Gravity.CENTER

    Private bmp As Bitmap = LoadBitmap(Dir, FileName)
    Private NewBmp As Bitmap
    Private NewBmpWidth, NewBmpHeight As Int

    Private ImvBmpWRatio, ImvBmpHRatio As Float
    Private ScaleFactor As Float

    ImvBmpWRatio = Imv.Width / bmp.Width
    ImvBmpHRatio = Imv.Height / bmp.Height

    If ImvBmpWRatio < ImvBmpHRatio Then
        ScaleFactor = ImvBmpWRatio
    Else
        ScaleFactor = ImvBmpHRatio
    End If

    NewBmpWidth = bmp.Width * ScaleFactor
    NewBmpHeight = bmp.Height * ScaleFactor

    NewBmp = CreateScaledBitmap(bmp, NewBmpWidth, NewBmpHeight)
    Imv.Bitmap = NewBmp
End Sub


(I already know that the great Klaus will make me feel ashamed, solving it in two minutes :D)


[P.S. I would prefer even better quality/definition, of course]



Now there are at least two Klaus (Klaus Matle and ... Klaus).

I like to call Klaus: the "great Klaus", but Matle may not be small :), so we could call the first one: "fully Klaus" :) - see his profile.
 
Last edited:

sorex

Expert
Licensed User
Longtime User
ok, tried out my idea during the break at noon.

this seems to do what you want, it's not perfect but I didn't have much time to work on it.

the attached image shows how it works.

B4X:
Sub draw
Dim w,h,cx,cy,s,px,py As Int
Dim r As Float
Dim p As Path

s=DateTime.Now/1000 Mod 60
w=57
h=67

cx=w/2'45
cy=h/2'50
r=h*1.5

rect1.Initialize(0,0,w*2,h*2)
dstmap.DrawRect(rect1,Colors.Black,True,0)

p.Initialize(cx,cy)
For x=0 To s
    px = cx + r * Cos(2 * 3.14 * (x+45) / 60)
    py = cy + r * Sin(2 * 3.14 * (x+45) / 60) 
    p.lineto(px,py)
Next
dstmap.DrawPath(p,Colors.Yellow,True,0)
imgBar.Invalidate
End Sub
 

Attachments

  • timething.gif
    timething.gif
    11.6 KB · Views: 725
  • timething.zip
    22.8 KB · Views: 462
Upvote 0

barx

Well-Known Member
Licensed User
Longtime User
I would do it that way:
B4X:
Sub FitCenterBitmap(Imv As ImageView, Dir As String, FileName As String)
    Private bmp As Bitmap = LoadBitmap(Dir, FileName)
    Private cvs As Canvas
    cvs.Initialize(Imv)
 
    Dim rectDest As Rect
    Dim delta As Int
    If bmp.Width / bmp.Height > Imv.Width / Imv.Height Then
        delta = (Imv.Height - bmp.Height / bmp.Width * Imv.Width) / 2
        rectDest.Initialize(0, delta,Imv.Width, Imv.Height - delta)
    Else
        delta = (Imv.Width - bmp.Width / bmp.Height * Imv.Height) / 2
        rectDest.Initialize(delta, 0, Imv.Width - delta, Imv.Height)
    End If
    cvs.DrawBitmap(bmp, Null, rectDest)
    Imv.Invalidate
End Sub


Very useful code sample @klaus

Out of curiosity how would one create a pan and scan effect. i.e. crop the images long sides to make square?

And does this resize the image to the dimensions of the imageview (create a smaller filesize)?
Thanks
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
... how would one create a pan and scan effect
Sorry, I'm not sure I understand what exactly you mean.
Do you want to take only a square part of the original image ?
Then you need to load the original bitmap and copy the square part onto ImageView.
If you want to move the image you could use a square ScrollView2D view and put the original image onto the internal panel of ScrollView2D.
And does this resize the image to the dimensions of the imageview (create a smaller filesize)?
If you copy only a part of the bitmap and then release the original bitmap I suppose that the memory needed would be reduced.
But I'm not sure, have never made any test to prove it.
 
Upvote 0

barx

Well-Known Member
Licensed User
Longtime User
I guess I did leave it a bit vague. Lol. Here is a better explanation. It all boils back the the Wear data layer lib again. wear data layer can pass bitmaps and files as assets. Obviously because the wear device screen is very small it is said to compress the bitmaps. In my demo app I'm using a basic profile as an example. Profile image, name, age. The image is selected by tapping the square image view and that starts the son tent chooser. I would like the image view to show the selected image. This currently working with your above code to fit to image view. To make it look a little better I would like it show a full square. So the square will show full width and crop top and bottom of length. Does that make sense? Can't really show an example as I'm on phone right now. I then need to to send this with the other info to wear network do don't want to send the full 14 mega pixel image.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
since it's square it gets actually easier.

just use something like (if scaled already to the screen dimensions)

img.left=50%x-img.width
img.top=50%y-img.height

to have it centered to the image center. (some stuff might go out of screen)

cropping it might gain memory but the math can be simular or you cut off at the bottom or right only.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Is this what you are looking for ?
B4X:
Sub SetImage(imv As ImageView, DirName As String, ImageName As String)
    Dim rectSource, rectDest As Rect
    Dim delta As Int
    Dim bmp As Bitmap
    Dim cvs As Canvas
  
    rectDest.Initialize(0, 0, imv.Width, imv.Height)
    bmp.Initialize(DirName, ImageName)

    If bmp.Width > bmp.Height Then
        delta = (bmp.Width - bmp.Height) / 2
        rectSource.Initialize(delta, 0, bmp.Width - delta, bmp.Height)
    Else
        delta = (bmp.Height - bmp.Width) / 2
        rectSource.Initialize(0, delta, bmp.Width, bmp.Height - delta)
    End If
    cvs.Initialize(imv)
    cvs.DrawBitmap(bmp,rectSource, rectDest)
  
    Dim jo = bmp As JavaObject
    jo.RunMethod("recycle", Null)
End Sub
The ImageView must be square.
The smaller side of the image fills the ImageView.
The bigger side is equally croped on both sides.
The original bitmap is relcycled at the end to free memory.

Depending on the with / height ratio the image is
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
I was apparently not awake enought for forumulas so it was wrong :)

50%x-(img.width/2)
or
(100%x-img.width)/2

might work better ;)

Klaus: is that the "official" B4A way to release unused bitmaps?
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
is that the "official" B4A way to release unused bitmaps?
I don't think that there is an 'official' way to recycle bitmaps.
Normaly there should be no need to recycle views, but for big bitmaps it can help to avoid 'Out of memory' propblems.
 
Upvote 0
Top