Android Question Take photo and upload to my online database ?

tsteward

Well-Known Member
Licensed User
Longtime User
There are a lot of thing on here about camera, so much that it gets overwhelming.
Can someone point me at the easiest solution to.
Provide the user with a button which will open the camera
and after taking a photo upload to my database.

Possibly also resizing the image to reduce data transfer

Thanks in advance
Tony
 

MarkusR

Well-Known Member
Licensed User
Longtime User
there 3 possibilities for taking a photo intent based,camera class old,camera class new.
intent is a easy solution using the build in camera app.
the app open the user take a photo, he say its oks and it return to your app.
https://www.b4x.com/android/forum/threads/intent-based-camera.69215/

if u have a b4j server or other web server u can connect to it via OkHttpUtils2.

u can convert a user defined type with B4XSerializator class.
so if the other side is b4j it can convert it back into the same type.

example type where the Photo byte array is a picture "file"
B4X:
Type Photo(InspectionId As Int, PhotoId As Int, Photo() As Byte, Thumbnail() As Byte, Note As String, AppId As String, Barcode As String)

send a type as byte()
B4X:
Sub Save(Item As SinglePassword)
 
    Dim Data() As Byte

    Dim ser As B4XSerializator
    Data = ser.ConvertObjectToBytes(Item)

    Dim Job As HttpJob
    Job.Initialize("",Me)
    Job.Username = Main.Username
    Job.Password = Main.Password
    Job.PostBytes("https://" & Main.Server & "/request/save",Data) '?cmd=save
 
    Wait For (Job) JobDone(Job As HttpJob)
    If Job.Success Then
    Else
        xui.MsgboxAsync("Save Failed","Error")  
    End If
    Job.Release
 
End Sub

about database, images (.jpg .png file as byte array) can bestore in a binary / blob (sqlite) field.

i used for images (b4a)
B4X:
'...
'Code module
'Subs in this code module will be accessible from all modules.
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

'convert a file content to a bitmap
Sub BytesToBitmap(Data() As Byte) As Bitmap
 
    Dim InputStream As InputStream
    InputStream.InitializeFromBytesArray(Data,0,Data.Length)
 
    Dim NewBitmap As Bitmap
    NewBitmap.Initialize2(InputStream)
 
    InputStream.Close
 
    Return NewBitmap
 
End Sub

'make a jpg as bytes
Public Sub BitmapToBytes(Bmp As Bitmap) As Byte()
    Dim Out As OutputStream
    Out.InitializeToBytesArray(0)
    Bmp.WriteToStream(Out, 100, "JPEG")
    Out.Close
    Return Out.ToBytesArray
End Sub

Sub ThumbnailFromBytes(Data() As Byte) As Byte()

    Log("Thumbnail FromBytes " & DateTime.Date(DateTime.Now))
 
    Dim Bitmap1 As Bitmap
    Bitmap1 = BytesToBitmap(Data)
 
    Log("Bitmap Size " & Bitmap1.Width & " x " & Bitmap1.Height )
 
    Dim Out As OutputStream
    Out = File.OpenOutput(File.DirInternalCache, "Thumbnail.jpg", False)
    Bitmap1.WriteToStream(Out, 70, "JPEG")
    Out.Close
 
    Dim BitmapThumbnail As Bitmap
    BitmapThumbnail = LoadBitmapResize(File.DirInternalCache, "Thumbnail.jpg",128dip,128dip,True)
 
    Dim NewData() As Byte
    NewData =  BitmapToBytes(BitmapThumbnail)

    Log("Thumbnail FromBytes Ready " & DateTime.Date(DateTime.Now) )

    Return NewData
       
End Sub

Sub AdjustImageView(Imv As ImageView, bmp As Bitmap)

    'MR 09.09.2018 (from vb6)

    Dim bx1 As Long
    Dim by1 As Long
 
    Dim bx2 As Long
    Dim by2 As Long
 
    Dim f1 As Float
    Dim f2 As Float

    Dim ox,oy,oxx,oyy As Float

    ox = Imv.Left
    oy = Imv.Top
 
    oxx = Imv.Width
    oyy = Imv.Height
 
    bx1 = bmp.Width
    by1 = bmp.Height
 
    bx2 = oxx
    by2 = oyy

    If bx1 = 0 Or by1 = 0 Then 'größe wie PictureBox
        bx1 = bx2
        by1 = by2
    End If
 
    f1 = 1.0
    f2 = 1.0
 
    If bx1 <> bx2 Then 'ohne ZOOM > mit ZOOM <>
        f1 = bx2 / bx1
    End If
    If by1 <> by2 Then
        f2 = by2 / by1
    End If
 
    If f2 < f1 Then f1 = f2

    Imv.Gravity = Bit.Or( Gravity.FILL,Gravity.CENTER)
 
    Imv.Left = ox + oxx / 2.0 - (bx1 * f1) / 2.0
    Imv.Top = oy + oyy / 2.0 - (by1 * f1) / 2.0
 
    Imv.Width = f1 * bx1
    Imv.Height = f1 * by1
 
    Imv.Bitmap = bmp
 
End Sub

here i used the old camera class direct in b4a.
https://www.b4x.com/android/forum/threads/inspection-and-photo.96943/
 
Last edited:
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Hello @tsteward,
You can easily do all that with the CameraEx class, I do not use Camera2 class simply because it fails on my older phones and tablet devices, where as the original CameraEx class works on both my older and newer devices and is great for taking photos too. Shrinking the photo down can be easily done too.

I personally added a routine the cycles through the phone camera modes until it finds an 3:4 ratio somewhere around the 800*600 ratio, I then set the CameraEx class to use that particular camera mode via CamExt.SetPictureSize.

In Erels example for CameraEx, I added the following to code into the Camera1_Ready sub set and take a smaller photo in size and storage space in databases.

I set the photo size with the following code, I set the physical photo size to a smaller more manageable 4:3 ratio 800*600. For example a 3Mb photo ends up being an 4:3 ratio 800*600 photo of about 800Kb in size.
B4X:
'Loop through to find closest 4:3 ratio (800*600)
            For Each CamResSize As CameraSize In CamExt.GetSupportedPicturesSizes
                Log(CamResSize)
             
                Dim Width As Int = CamResSize.Width
                Dim Height As Int = CamResSize.Height
         
                'GETA AS CLOSE TOO 800 BY 600 4 BY 3 AS POSSIBLE
                If Height <= 600 And Width - Height + Height = Width Then
                    Log($"Resolution = ${Width} by ${Height}"$)
                    CamExt.SetJpegQuality(100) '75 = 75% out of 100% etc
                    CamExt.SetContinuousAutoFocus
                    CamExt.SetPictureSize(Width, Height)
                    'CamExt.SetPreviewSize(Width, Height)
                    CamExt.CommitParameters
                    CamExt.StartPreview
                    Log($"Preview Size = ${CamExt.GetPreviewSize.Width} by ${CamExt.GetPreviewSize.Height}"$)
                    Exit
                End If
            Next

Once I take the 4:3 ratio 800*600 photo for example, I then save the photo directly onto the device. Next I reload the saved photo using BitMap.resize, I then save the photo again using a Canvas as follows.

Setting the quality to 50 shrinks the photo size down even more to about 225Kb +/- 20%, quality is still good.
B4X:
CnvPhoto.Bitmap.WriteToStream(Out, 50, Starter.FileExt) '50 = 50% quality

I have missed out the fact that I actually make an 800*800 square background and I place the 800*600 photo on top of the 800*600 background, then I save the photo. This gives me a perfectly square 800*800 photo (top and bottom can be either white or transparent), but that does not apply to you @tsteward as you never asked for that information ;)

You can now save the photo data directly into your database encoded as Base64, I presume that you already know how to insert data into your own online database. Don't forget to delete the previously saved photos on your device after saving the Base64 data into the database.

I personally always save photos and images directly into databases encoded as Base64, that's my personal option and if other developers don't like it that's really their problem, anyway it's just an easy no messing about solution that has never ever failed me. One of my clients is a Ford parts distributor with 1000's of photos of parts in one of my MySQL online databases on my server. Their database has been running with no issues whatsoever for well over 12 years now.

Anyway, you can use my library HERE to easily convert photos/images into a Base64 string and back again. Just use my library to convert your last saved photo and save the Base64 string directly into your database, you can use the same library to convert and load the Base64 string directly into an ImageView again.

Please note that there are countless solution to your questions, this is just my take on it rightly or wrongly, and it runs seamlessly and fast too.

Enjoy...
 
Last edited:
Upvote 0
Top