Android Question File Rotation... Can't Get It Done!

Shadow&Max

Active Member
Licensed User
Longtime User
This is weird.

I can rotate the bitmap ok, but the actual container doesn't change.

I want to rotate a bitmap that's in portrait mode, to landscape, and save it as that landscape size. It appears that when I rotate the bitmap, and save it, it's saved as the horizontal picture, inside a portrait container, much of which is black above and below the rotated pic. So, in what's saved, I end up with the rotated image the width of which is the width of the portrait container and the height is only a small portion of the portrait picture, but the rotated picture is in the correct proportions.

I've tried several of the things I found on the site, but still come up with the same result. Here's where I am now:

B4X:
Sub RotateView(v As View, bmp As Bitmap, degrees As Float)
    Dim c As Canvas
    Dim R As Rect
    'Dim imgratio As Long
    Dim hh2,hw2 As Int
    hh2 = v.Height
    hw2 = v.Width

    c.Initialize(v)
    R.Initialize(0,0,v.Height,v.Width)
    c.DrawRect(R,Colors.transparent,True,0)
    c.DrawBitmapRotated(bmp,Null,R,degrees)
   
    v.SetBackgroundImage(c.Bitmap)

    v.Invalidate
   
    Dim out As OutputStream
    Dim rfile As String
   
    rfile = "rotatetemp.jpg"
    out = File.OpenOutput(File.DirInternal, rfile, False)
    c.Bitmap.WriteToStream(out, 100, "JPEG")
    out.Close
    ResizePreviewPhoto(File.DirInternal,rfile)
    SetPreviewLayout

End Sub

Sub SetPreviewLayout  '(bwidth As Int, bheight As Int)

    'ivPreview.Height = bwidth
    'ivPreview.Width = bheight
   
    ivPreview.Top = (btnShoot.Top / 2) - (ivPreview.Height / 2)
    ivPreview.Left = iv.Left + ((iv.Width / 2) - (ivPreview.Width / 2) )
    DoEvents
    btnRotateLeft.Top = (ivPreview.Top + ivPreview.Height / 2) - btnRotateLeft.Height / 2
    btnRotateRight.Top = btnRotateLeft.Top
    btnRotateLeft.Left = ivPreview.Left - btnRotateLeft.Width - 20dip
    btnRotateRight.Left = ivPreview.Left + ivPreview.Width +  20dip   
End Sub

Sub ResizePreviewPhoto (Dir As String, FileName As String)
    Dim bm2 As Bitmap
    bm2.InitializeSample(Dir, FileName, 100dip, 100dip)
    hip = bm2.Height
    wip = bm2.Width
    ivPreview.Bitmap = bm2
        If hip = wip Then 'It's Square
            ivPreview.Height = 100dip
            ivPreview.Width = 100dip
        Else If hip > wip Then 'It's Portrait
            imageratio = (wip / hip)
            ivPreview.Height = 100dip
            ivPreview.Width = ivPreview.Height  * imageratio  '- 20dip
        Else 'It's Landscape
            imageratio = (hip / wip)
            ivPreview.Width = 100dip 'pnl.Width '- 40dip
            ivPreview.Height = ivPreview.Width * imageratio
        End If
End Sub

I don't know what to do next. This SHOULD work, shouldn't it? If not, where'd I go wrong here?
 

MoraviaVenus

Member
Licensed User
Longtime User
Hi Erel,

I have used your RotateImage function from post #8, but when I run my app on some devices (e.g. LG G Pad tablet or Sony Xperia E3), I get OutOfMemoryError. On the other hand, on some another devices (e.g. Sony Xperia Z3 or high end Samsung phone) works smoothly.

Downsampling image due to lack of memory.
main_rotateimage (B4A line: 903)
NewImage = bmp.RunMethod("createBitmap", Array
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:130)
at b4a.ArtAngels.main._rotateimage(main.java:2865)
at b4a.ArtAngels.main._showcroppingenvironment(main.java:3155)
at b4a.ArtAngels.main._btncropimage_click(main.java:891)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:78)
at android.view.View.performClick(View.java:4442)
at android.view.View$PerformClick.run(View.java:18471)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:809)
at android.graphics.Bitmap.createBitmap(Bitmap.java:786)
at android.graphics.Bitmap.createBitmap(Bitmap.java:718)
... 23 more

My aim is to rotate high resolution images 90 degrees clockwise.

Please, how can I avoid OutOfMemoryError?

Thank you.
 
Upvote 0

Shadow&Max

Active Member
Licensed User
Longtime User
It's really tough to do. You're taking a high res picture and loading it into memory. Then you're rotating that so you're creating another bitmap in memory. They're both huge in size. And there's a lot going on in the phone as well. I bet that the phones that work have more internal memory than the group that doesn't. 16GB on a phone isn't the amount of usable memory you have to work with... it's just the overall storage space.

This is a guess, but I remember that when I was playing with this, certain devices worked and others didn't. The ones with more workable memory seemed not to falter.
 
Upvote 0

MoraviaVenus

Member
Licensed User
Longtime User
Hi Shadow&Max,

thank you for diagnostics.

Please, is there other approach, how can I rotate image outside of memory?

My code is crashing on line:

NewImage = bmp.RunMethod("createBitmap", Array(original, 0, 0, original.Width, original.Height, matrix, True))​

... where NewImage is global variable.

Thank you.
 
Upvote 0
Top