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 ?
 

Daestrum

Expert
Licensed User
Longtime User
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

Daestrum

Expert
Licensed User
Longtime User
Javax.swing contains nearly all the same type of components as javafx except they are visually inferior.

Look here
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
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

Daestrum

Expert
Licensed User
Longtime User
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

peacemaker

Expert
Licensed User
Longtime User
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

Daestrum

Expert
Licensed User
Longtime User
A quick (and dirty) example of displaying images (Obviously you will need to change the image filename)
B4X:
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

Daestrum

Expert
Licensed User
Longtime User
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

Daestrum

Expert
Licensed User
Longtime User
I cant test as I dont have jOpenCV for Mat but something like this

B4X:
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

peacemaker

Expert
Licensed User
Longtime User
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

Daestrum

Expert
Licensed User
Longtime User
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

peacemaker

Expert
Licensed User
Longtime User
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

thetahsk

Active Member
Licensed User
Longtime User
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

thetahsk

Active Member
Licensed User
Longtime User
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

peacemaker

Expert
Licensed User
Longtime User
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

thetahsk

Active Member
Licensed User
Longtime User
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

peacemaker

Expert
Licensed User
Longtime User
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
Top