Android Code Snippet [B4X][XUI] Image to JPEG byte array with resize/quality options

Discussion in 'Code Snippets' started by OliverA, Apr 11, 2018.

  1. OliverA

    OliverA Well-Known Member Licensed User

    Originally posted a B4J/inline Java version of this in the B4J Code Snippets (https://www.b4x.com/android/forum/t...byte-array-with-resize-quality-options.91746/). @Erel pointed out though that the XUI library had the functionality that I was doing with Java, so I decided to rewrite the routine. This routine uses 100% B4X basic syntax, no inline Java, not even any #If conditionals. Unlike the Java version, this version does not throw any exceptions (on purpose), but instead returns an empty byte array if it finds/encounters any issues (which are Log()'ed).

    Code:
    ' Converts image to JPEG byte array. Ability to resize and adjust JPEG quality.
    ' Negative width and height values = %, such that -50 = 50% and -200 = 200%
    ' Positive width and height values = pixel dimensions
    ' If one value (either width or height) are 0, then the other value is proportionally
    '  calculated from the first.
    ' If both width and height are 0 or -100, no resizing takes place
    ' If quality = -1, use default quality of 75
    ' Will return a zero length byte array if something is wrong with the parameters
    Sub XUIImageToJPEGByteArray(aImage As Object, width As Int, height As Int, quality As Int) As Byte()
       
    'Sanity check quality
       If (quality < -1 And quality > 100Then
           
    Log("Parameter quality not in range (-1..100)")
           
    Return Array As Byte ()
       
    End If
       
    If quality = -1 Then quality = 75

       
    'Sanity check incoming image
       Try
           
    Dim image As B4XBitmap = aImage
       
    Catch
           
    Log(LastException)
           
    Return Array As Byte ()
       
    End Try
      
       
    'Sanity check incoming image dimensions
       Dim oldWidth As Int = image.Width
       
    Dim oldHeight As Int = image.Height
       
    If (oldWidth = 0 And oldHeight = 0 ) Then
           
    Log("Source image with incorrect dimensions")
           
    Return Array As Byte ()
       
    End If

       
    'See if were resizing the image
       Dim  resize As Boolean = True
       
    If ((width = 0 And height = 0Or (width = -100 Or height = -100)) Then resize = False
      
       
    'Resize if necessary
       If (resize) Then
           
    Dim newWidth As Int = width
           
    Dim newHeight As Int = height
           
    'Calculate new dimensions
           If (newWidth < 0Then newWidth = -1 * oldWidth * newWidth / 100
           
    If (newHeight < 0Then newHeight = -1 * oldHeight * newHeight / 100
           
    If (newWidth = 0Then newWidth = oldWidth * newHeight / oldHeight
           
    If (newHeight = 0 ) Then newHeight = oldHeight * newWidth / oldWidth
           
    image = image.Resize(newWidth, newHeight, False)
       
    End If
      
       
    'Convert image to JPEG byte array
       Dim out As OutputStream
       out.InitializeToBytesArray(
    0)
       
    image.WriteToStream(out, quality, "JPEG")
       out.Close
      
       
    'Done
       Return out.ToBytesArray
    End Sub
    Example
    Code:
    Dim bImage As Image
    bImage.Initialize(
    File.DirAssets, "b.png")
    Dim c() As Byte = XUIImageToJPEGByteArray(bImage, -50050)
    'https://www.b4x.com/android/forum/threads/b4x-bytes-to-file.70111/#content
    BytesToFile(File.DirApp, "b.jpg", c)
    Resource used:
    Dim bImage As Image bImage.Initialize(File.DirAssets, "b.png") Dim c() As Byte = ImageToJPEGByteArray(bImage, -50, 0, 50) 'https://www.b4x.com/android/forum/threads/b4x-bytes-to-file.70111/#content BytesToFile(File.DirApp, "b.jpg", c)
     
    Last edited: Apr 11, 2018
    hibrid0, mcvburen, XbNnX_507 and 4 others like this.
  2. Alexander Stolte

    Alexander Stolte Well-Known Member Licensed User

    I try it out and if i compile it with B4J then i run into an Error:

    Code:
    B4J Version: 6.01
    Parsing code.    (
    0.00s)
    Compiling code.    (
    0.16s)
       
    ObfuscatorMap.txt 
    file created in Objects folder.
    Compiling layouts code.    (
    0.00s)
    Organizing libraries.    (
    0.00s)
    Compiling generated Java code.    Error
    B4J line: 
    51
    Dim image As B4XBitmap = aImage
    javac 
    1.8.0_151
    src\b4j\example\main.java:
    137: error: package android.graphics does not exist
    _
    image.setObject((android.graphics.Bitmap)(_aimage));
                                      ^
    1 error
    Attached is the project, maybe i missed something.
     

    Attached Files:

  3. OliverA

    OliverA Well-Known Member Licensed User

    I've just opened your project and it complained about the missing xui library. That should not happen in B4J 6.01, since it has a version of the XUI library included, it's called jXUI. Looks like your using the Android version of the XUI library instead of B4J's internal XUI library (jXUI).

    BTW: Thanks for including a test project. That gave me the clue as to what is going on.
     
    Last edited: May 2, 2018
    Alexander Stolte and Erel like this.
  4. Alexander Stolte

    Alexander Stolte Well-Known Member Licensed User

    ahh ok, did not know that this is already present at B4J. Thanks.
     
  5. Anser

    Anser Well-Known Member Licensed User

    May I know which Library is to be used for the type Image in the code "Dim bImage As Image"

    Code:
    Dim bImage As Image
    bImage.Initialize(
    File.DirAssets, "b.png")
    Dim c() As Byte = XUIImageToJPEGByteArray(bImage, -50050)
    'https://www.b4x.com/android/forum/threads/b4x-bytes-to-file.70111/#content
    BytesToFile(File.DirApp, "b.jpg", c)
     
  6. DonManfred

    DonManfred Expert Licensed User

    This code only works in B4J. I guess the code is NOT useable as B4X (B4A, B4J and B4i).
    The Docs of this Object are pointing out that it is part of the jfx Library which is a B4j Library.
    https://www.b4x.com/b4j/help/jfx.html#image
     
  7. klaus

    klaus Expert Licensed User

    Replace:
    Code:
    Dim bImage As Image
    bImage.Initialize(
    File.DirAssets, "b.png")
    Dim c() As Byte = XUIImageToJPEGByteArray(bImage, -50050)
    'https://www.b4x.com/android/forum/threads/b4x-bytes-to-file.70111/#content
    BytesToFile(File.DirApp, "b.jpg", c)
    By:
    Code:
    Dim bImage As B4XBitmap
    bImage = xui.LoadBitmap(
    File.DirAssets, "b.png")
    Dim c() As Byte = XUIImageToJPEGByteArray(bImage, -50050)
    'https://www.b4x.com/android/forum/threads/b4x-bytes-to-file.70111/#content
    BytesToFile(xui.DefaultFoler, "b.jpg", c)
    And it becomes XUI.
     
    hibrid0, Anser and Star-Dust like this.
  8. Anser

    Anser Well-Known Member Licensed User

    Code:
    Dim bImage As B4XBitmap
    bImage = xui.LoadBitmap(
    File.DirAssets, "b.png")
    Dim c() As Byte = XUIImageToJPEGByteArray(bImage, -50050)
    BytesToFile(
    File.DirDefaultExternal, "b.jpg", c)
    The file created using BytesToFile(File.DirDefaultExternal, "b.jpg", c) is corrupted. Any idea why is it so. ?

    I pick a file from Gallery, then resize and write it to File.DirDefaultExternal, unfortunately the file written is corrupted
    Here is the code that I use
    Code:
    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'These variables can be accessed from all modules.
        Private cc As ContentChooser
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        
    'Do not forget to load the layout file created with the visual designer. For example:
        Activity.LoadLayout("Profile")
        
    If FirstTime Then
            cc.Initialize(
    "cc")
        
    End If
     
    End Sub

    Sub LblFromGallery_Click
        cc.Show(
    "image/*""Choose image")
    End Sub

    Sub cc_Result (Success As Boolean, Dir As String, FileName As String)
        
    Dim realPath As String = GetPathFromContentResult(FileName)

        
    Dim xIV As B4XView = ivProfilePic 'ivProfilePic is an ImageView
        Dim bImage As B4XBitmap
        
    Dim myXui As XUI
        bImage = myXui.LoadBitmap(Dir, FileName)
     
        
    Dim c() As Byte = XUIImageToJPEGByteArray(bImage, -50050)
        
    'When I physicall check this file on File.DirDefaultExternal, it is corrupted
        BytesToFile(File.DirDefaultExternal, "MyProfilePic.jpg", c)
     
        xIV.SetBitmap( LoadBitmapResize(
    File.DirDefaultExternal, "MyProfilePic.jpg"332dip232dipTrue ))
     
    End Sub

    Sub BytesToFile (Dir As String, FileName As String, Data() As Byte)
        
    Dim out As OutputStream = File.OpenOutput(Dir, FileName, False)
        out.WriteBytes(Data, 
    0, Data.Length)
        out.Close
    End Sub

    Sub FileToBytes (Dir As String, FileName As StringAs Byte()
        
    Return Bit.InputStreamToBytes(File.OpenInput(Dir, FileName))
    End Sub
    Later I use the FileToBytes to read the image file and then write the image to a BLOB column in MySQL
    Code:
    Dim c() As Byte = FileToBytes(File.DirDefaultExternal, "MyProfilePic.jpg")
     
    Last edited: Sep 8, 2018
  9. OliverA

    OliverA Well-Known Member Licensed User

    If you upload your project, or at least enough of your project that replicates this issue, I’ll take a look at it
     
    Anser likes this.
  10. Anser

    Anser Well-Known Member Licensed User

    Your Code is working fine. It was my mistake. Sorry for the confusion.
     
  11. Alexander Stolte

    Alexander Stolte Well-Known Member Licensed User

    I use this in a Non-Ui Project, on my local machine, it works good, but on my server (ubuntu) i have this error:
    Code:
    java.lang.RuntimeException: java.lang.NoClassDefFoundError: javafx/scene/image/Image
    I use openjdk version 1.8.9_191 on the server.

    do you know something about it?
     
  12. OliverA

    OliverA Well-Known Member Licensed User

    Looks like the OpenJDK distribution you used did not include JavaFX. That seems to be a common issue. You may want to install a different alternative.
    Source: https://github.com/AdoptOpenJDK/openjdk-build/issues/577#issuecomment-452144377
    Notes:
    1) On the BellSoft site, scroll all the way down to see other versions of their Liberica JDK
    2) Amazon Corretto: https://aws.amazon.com/corretto/
     
  13. Alexander Stolte

    Alexander Stolte Well-Known Member Licensed User

    for what is the JavaFX needed in this function? maybe it is possible to bypass this.
     
  14. OliverA

    OliverA Well-Known Member Licensed User

  15. Alexander Stolte

    Alexander Stolte Well-Known Member Licensed User

    I have a Solution, here is the tutorial. Thanks!
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice