B4J Question javafx.embed.swing does not exist

peacemaker

Expert
Licensed User
Longtime User
HI, All

I'm trying to make non-ui server's app for OpenCV usage.
And i have such error:

B4X:
B4J Version: 9.10
Parsing code.    (0.01s)
    Java Version: 11
Building folders structure.    (0.02s)
Running custom action.    (0.05s)
Compiling code.    (0.04s)
Compiling layouts code.    (0.00s)
Organizing libraries.    (0.00s)
Compiling generated Java code.    Error
src\peacemaker\sc4\utils.java:4: error: package javafx.embed.swing does not exist
import javafx.embed.swing.SwingFXUtils;
                         ^
Note: src\peacemaker\sc4\cl_matcher.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error

javac 11.0.1

jFX lib is added as Image class is required for pictures.
cl_matcher is my class that uses OpenCV lib: if to remove some code the error is anyway:
B4X:
B4J Version: 9.10
Parsing code.    (0.02s)
    Java Version: 11
Building folders structure.    (0.02s)
Running custom action.    (0.06s)
Compiling code.    (0.03s)
Compiling layouts code.    (0.00s)
Organizing libraries.    (0.00s)
Compiling generated Java code.    Error
src\peacemaker\sc4\utils.java:4: error: package javafx.embed.swing does not exist
import javafx.embed.swing.SwingFXUtils;
                         ^
1 error

javac 11.0.1

How to solve, what is this error ?
 
Because it is a non-ui app it will not have access to any javafx modules. You will need to use javax.swing instead.
 
Upvote 0
Javax.swing contains nearly all the same type of components as javafx except they are visually inferior.

Look here
 
Upvote 0
Seems, it's all due to these subs:
B4X:
'Static code module
Sub Process_Globals
    Private mHighGui As OCVHighGui
End Sub


'***********************************************************************
' jOpenCV Utild functions.
'***********************************************************************

Sub MatToBitmap( myMat As OCVMat) As Image
    Dim J As JavaObject = Me
    Dim im1 As Object = J.RunMethod("convertBufferedToFX", Array(mHighGui.toBufferedImage(myMat)))
    Return im1
End Sub


Sub BitmapToMat(img As Image) As OCVMat
    Dim J As JavaObject = Me
    Dim im1 As Object = J.RunMethod("img2Mat", Array(img))
    Return im1
End Sub

#if JAVA

// https://docs.oracle.com/javase/8/javafx/api/javafx/embed/swing/SwingFXUtils.html
// http://tutorials.jenkov.com/javafx/imageview.html

import javafx.embed.swing.SwingFXUtils;
import javax.swing.*;
import java.awt.*;
import javafx.scene.image.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBuffer;

import com.b4jcv.core.Mat;
import com.b4jcv.core.Core;
import com.b4jcv.core.CvType;

public static javafx.scene.image.Image convertBufferedToFX(java.awt.image.BufferedImage im0)
{
    return SwingFXUtils.toFXImage(im0, null);
}



public static java.awt.image.BufferedImage convertFXToBuffered( javafx.scene.image.Image fxImage)
{
    return SwingFXUtils.fromFXImage(fxImage, null);
}


// https://www.codota.com/code/java/classes/org.opencv.core.Mat
// https://community.oracle.com/tech/developers/discussion/3686898/javafx-bufferedimage-to-mat-opencv
public static Mat img2Mat(javafx.scene.image.Image imageFX)
{
    // First, convert JavaFX image to BufferedImage
    BufferedImage im = convertFXToBuffered(imageFX);

    // A algun lloc diu q si dona errors, fer aixo de baix. // https://stackoverflow.com/questions/14958643/converting-bufferedimage-to-mat-in-opencv
    // Convert INT to BYTE
    // im = new BufferedImage(im.getWidth(), im.getHeight(),BufferedImage.TYPE_3BYTE_BGR);
    // Convert bufferedimage to byte array
    // DataBuffer es una superclass de DataBufferArray, per tant no podem fer casting
    // Necessitem q la imatge original ja tingui un DataBufferByte
    //https://stackoverflow.com/questions/19853265/databuffer-to-databufferbyte-cast-throws-error
   
    BufferedImage bImage = new BufferedImage(im.getWidth(), im.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
    bImage.getGraphics().drawImage(im, 0, 0, null);

    byte[] data = ((DataBufferByte) bImage.getRaster().getDataBuffer()).getData();

    Mat mat = new Mat(bImage.getHeight(), bImage.getWidth(), CvType.CV_8UC3);            // Create a Matrix the same size of image
    mat.put(0, 0, data);                                                                // Fill Matrix with image values

    return mat;
}
#End If

But sorry, i do not understand what to do here
 
Last edited:
Upvote 0
I don't think you have to change much depending where the image comes from, as the code you showed is converting the image to and from Javafx image.
I assume the jOpenCV supplies the image as a bufferedimage, if so the awt/swing can just display that without conversion, you just need to create the ui to display the image (JFrame possibly).
 
Upvote 0
This non-ui app is processing images with already prepared settings (via another UI-app), so the task is just remove all UI-dependencies in this non-UI app.
Samples images are loaded by
B4X:
Dim b As Image =  xui.LoadBitmap(Main.SamplesFolder, fn)
and next must be converted:
B4X:
mSamples(i) = Utils.BitmapToMat(b)   'to Mat object
by those utils code
 
Upvote 0
A quick (and dirty) example of displaying images (Obviously you will need to change the image filename)
Code:
Sub Process_Globals
    
End Sub

Sub AppStart (Args() As String)
    Me.As(JavaObject).RunMethod("doit",Null)
End Sub
#if java
import java.awt.*;  
import javax.swing.JFrame;  
  
public static class MyCanvas extends Canvas{  
      
    public void paint(Graphics g) {  
  
        Toolkit t=Toolkit.getDefaultToolkit();  
        Image i=t.getImage("c:/temp/hannah.jpg");  
        g.drawImage(i, 0,0,this);  
          
    }
}  
public static void doit() {  
        MyCanvas m=new MyCanvas();  
        JFrame f=new JFrame();  
        f.add(m);  
        f.setSize(400,400);  
        f.setVisible(true);  
    }  
  
 
#End If
 
Upvote 0
Sorry, I thought you wanted to display them.
But the code shows how to load them t.getImage(...) the image is a bufferedimage so can go into the mat routine without conversion.
 
Upvote 0
I cant test as I dont have jOpenCV for Mat but something like this

Code:
Sub AppStart (Args() As String)
    Dim thePic As Object = Me.As(JavaObject).RunMethod("getImage",Null)
    Dim mat As Object = Me.as(JavaObject).RunMethod("img2Mat",Array(thePic))
    Log(mat)
End Sub
#if java
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBuffer;

import com.b4jcv.core.Mat;
import com.b4jcv.core.Core;
import com.b4jcv.core.CvType;

 
public static Image getImage() { 
    Toolkit t=Toolkit.getDefaultToolkit(); 
    Image i=t.getImage("c:/temp/hannah.jpg"); 
    return i;   
} 
 
 public static Mat img2Mat(Image image)
{
    BufferedImage bImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
    bImage.getGraphics().drawImage(im, 0, 0, null);
    byte[] data = ((DataBufferByte) bImage.getRaster().getDataBuffer()).getData();
    Mat mat = new Mat(bImage.getHeight(), bImage.getWidth(), CvType.CV_8UC3);            // Create a Matrix the same size of image
    mat.put(0, 0, data);                                                                // Fill Matrix with image values
    return mat;
}
#End If
 
Last edited:
Upvote 0
No, some new errors
B4X:
B4J Version: 9.10
Parsing code.    (0.00s)
    Java Version: 11
Building folders structure.    (0.02s)
Running custom action.    (0.06s)
Compiling code.    (0.00s)
Compiling layouts code.    (0.00s)
Organizing libraries.    (0.00s)
Compiling generated Java code.    Error
B4J line: 32
End Sub
src\b4j\example\main.java:82: error: cannot find symbol
 public static Mat img2Mat(Image image)
               ^
  symbol:   class Mat
  location: class main
1 error

Can you help with fixing the first error, from first post ? How to add absent classes ?
 
Upvote 0
I added the missing imports to example code in post #11.
I don't think it is possible to use/correct the original code (post# 5) as it relies on javafx modules that are not available in a non-ui app.
 
Upvote 0
So the aim to understand how to modify to use these functions in non-ui app. It can work now started by Scheduler in the background, with no possibility to open the interface.
 
Upvote 0
try this

B4X:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\jOpenCVDlls" "."
'
' If you want to distribute it as a standalone package, copy your DLLs to the projects root folder
' DLL names can vary in other jOpenCV versions so be sure to modify accordingly.
#CustomBuildAction: After Packager, %WINDIR%\System32\robocopy.exe, ..\ temp\build\bin\ b4jcv_344_01.dll
#CustomBuildAction: After Packager, %WINDIR%\System32\robocopy.exe, ..\ temp\build\bin\ opencv_ffmpeg344_64.dll
#CustomBuildAction: After Packager, %WINDIR%\System32\robocopy.exe, ..\ temp\build\bin\ tbb12.dll
'
Sub Process_Globals
    Private  mCore As OCVCore
    Private  vcMat As OCVMat
    Private  OCV As OCVHelper
    Private  mType As OCVCvType
    Private  improc As OCVImgproc
    Private  imcodes As OCVImgcodecs
End Sub

Sub AppStart (Args() As String)
    Log("Hello jOpenCV Console")
    vcMat=imcodes.imread1("C:\11\pic.jpg")    '
    ' draw Line (1,1)(100,45)
    improc.line(vcMat,OCV.Point.create(1,1),OCV.Point.create(100,45),OCV.Scalar.create3(128,128,128),5,0,0)
    imcodes.imwrite1("C:\11\pic_0.jpg",vcMat)
End Sub
 
Upvote 0
Ha ! This works ! THANKS !
Absolutely no-trick-way !
For debugging purposes add some simple HighGui functions.

B4X:
Sub Process_Globals
    Private  mCore As OCVCore
    Private  vcMat As OCVMat
    Private  OCV As OCVHelper
    Private  mType As OCVCvType
    Private  improc As OCVImgproc
    Private  imcodes As OCVImgcodecs
    Private  highgui As OCVHighGui
End Sub

Sub AppStart (Args() As String)
    Log("Hello jOpenCV Console")
    vcMat=imcodes.imread1("C:\11\pic.jpg")    '
    ' draw Line (1,1)(100,45)
    improc.line(vcMat,OCV.Point.create(1,1),OCV.Point.create(100,45),OCV.Scalar.create3(128,128,128),5,0,0)
    imcodes.imwrite1("C:\11\pic_0.jpg",vcMat)
    highgui.imshow("Viewer",vcMat)
    highgui.waitKey
    Log("closing console")
End Sub
 
Upvote 0
vcMat=imcodes.imread1("C:\11\pic.jpg")

But strange that if to read my samples pictures like:
B4X:
Dim b As OCVMat =  imcodeсs.imread1(File.Combine(Main.SamplesFolder, fn))
it's always zero-sized mat:

B4X:
Mat [ 0*0*CV_8UC1, isCont=false, isSubmat=false, nativeObj=0x22759f294b0, dataAddr=0x0 ]

Files path has non ASCII-symbols.
 
Last edited:
Upvote 0
But strange that if to read my samples pictures like:
B4X:
Dim b As OCVMat =  imcodeсs.imread1(File.Combine(Main.SamplesFolder, fn))
it's always zero-sized mat:

B4X:
Mat [ 0*0*CV_8UC1, isCont=false, isSubmat=false, nativeObj=0x22759f294b0, dataAddr=0x0 ]

Files path has non ASCII-symbols.

Working fine here. Check path and image file

B4X:
Dim b As OCVMat =  imcodes.imread1(File.Combine("C:\11","pic.jpg"))
    Log(b.cols)
    Log(b.rows)
 
Upvote 0
It's found that it's known trouble: non-ASCII path is not supported by imread\imwrite....looking for solution and for this ...
 
Upvote 0
Back
Top