Hi all, does anyone know of a #webcam integration ...
# compose-desktop
m
Hi all, does anyone know of a #webcam integration for #C01D6HTPATV? The official repo at https://github.com/JetBrains/compose-multiplatform/tree/master/examples/imageviewer states: "Camera is not available on Desktop for now. Instead, we will use a random picture." So this is no starting point. I tried to use
Copy code
implementation("org.bytedeco:javacv-platform:1.5.12")
    implementation("org.bytedeco:opencv:4.9.0-1.5.10:macosx-arm64")
but it crashes with Error "long org.opencv.videoio.VideoCapture.VideoCapture_5(int)" - I tried several things... now I'm stuck.
1
u
maybe this with a swing panel http://github.com/sarxos/webcam-capture
m
Hi Elie, thanks... added this and the hello world code but it seems I'm missing the correct architecture:
Caused by: java.lang.UnsatisfiedLinkError: /private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib: dlopen(/private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib, 0x0001): tried: '/opt/homebrew/Cellar/opencv/4.12.0_1/lib/libbridj.dylib' (no such file), '/private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib' (fat file, but missing compatible architecture (have 'x86_64,i386', need 'arm64e' or 'arm64')), '/System/Volumes/Preboot/Cryptexes/OS/private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib' (no such file), '/private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib' (fat file, but missing compatible architecture (have 'x86_64,i386', need 'arm64e' or 'arm64'))
u
I'm sorry I've never had to implement this, I can't help much, I imagine it must be possible to develop a library like this with jna
👍 1
g
I am also interested in this, please let me know if you find / develop something 🤩
e
I've studied this topic a bit and you can use the library.
implementation( "com.github.sarxos:webcam-capture:0.3.12")
It is multiplatform.
Copy code
val imageState = remember { mutableStateOf<androidx.compose.ui.graphics.ImageBitmap?>(null) }
val isRunning = remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
var webcamRef by remember { mutableStateOf<Webcam?>(null) }

Column(modifier = Modifier.padding(8.dp)) {
    Box(
        modifier = Modifier
            .weight(1f)
            .fillMaxWidth(),
        contentAlignment = Alignment.Center
    ) {
        val img = imageState.value
        if (img != null) {
            Image(bitmap = img, contentDescription = "Camera preview", modifier = Modifier.fillMaxSize())
        } else {
            Text("Camera start")
        }
    }

    Spacer(Modifier.height(8.dp))

    Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
        Button(onClick = {
            if (!isRunning.value) {

                isRunning.value = true
                coroutineScope.launch {
                    val cam = Webcam.getDefault()
                    if (cam == null) {
                        isRunning.value = false
                        return@launch
                    }
                    webcamRef = cam
                    cam.viewSize = cam.viewSizes.maxByOrNull { it.width * it.height } ?: cam.viewSize
                    cam.open(true)


                    while (isActive && isRunning.value && cam.isOpen) {
                        val bimg: BufferedImage? = try {
                            cam.image
                        } catch (e: Exception) {
                            null
                        }

                        if (bimg != null) {
                            withContext(Dispatchers.Main) {
                                imageState.value = bimg.toComposeImageBitmap()
                            }
                        }

                        delay(33L) // ~30 FPS
                    }


                    try { cam.close() } catch (_: Exception) {}
                    webcamRef = null
                    isRunning.value = false
                }
            }
        }) {
            Text(if (isRunning.value) "Play" else "Start")
        }
        Button(onClick = {
            isRunning.value = false
            webcamRef?.let {
                try { it.close() } catch (_: Exception) {}
                webcamRef = null
            }
            imageState.value = null
        }) {
            Text("Stop")
        }
    }
}
Copy code
If you want to use this library, you can also implement
Copy code
implementation("org.bytedeco:javacv-platform:1.5.8")
Copy code
val imageState = remember { mutableStateOf<ImageBitmap?>(null) }
val isRunning = remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()

var grabber by remember { mutableStateOf<OpenCVFrameGrabber?>(null) }

Column(modifier = Modifier.fillMaxSize().padding(8.dp)) {
    Box(
        modifier = Modifier
            .weight(1f)
            .fillMaxWidth(),
        contentAlignment = Alignment.Center
    ) {
        val img = imageState.value
        if (img != null) {
            Image(bitmap = img, contentDescription = "Camera", modifier = Modifier.fillMaxSize())
        } else {
            Text("No image")
        }
    }

    Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
        Button(onClick = {
            if (!isRunning.value) {
                isRunning.value = true
                coroutineScope.launch(Dispatchers.IO) {
                    try {
                        val g = OpenCVFrameGrabber.createDefault(0)
                        grabber = g
                        g.start()
                        val converter = Java2DFrameConverter()

                        while (isActive && isRunning.value) {
                            val frame = g.grab()
                            if (frame != null) {
                                val bImage: BufferedImage? = converter.convert(frame)
                                if (bImage != null) {
                                    withContext(Dispatchers.Main) {
                                        imageState.value = bImage.toComposeImageBitmap()
                                    }
                                }
                            }
                            delay(33L) // ~30 FPS
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    } finally {
                        try { grabber?.stop() } catch (_: Exception) {}
                        try { grabber?.release() } catch (_: Exception) {}
                        grabber = null
                        isRunning.value = false
                    }
                }
            }
        }) {
            Text("Start")
        }

        Button(onClick = {
            isRunning.value = false
            coroutineScope.launch {
                try { grabber?.stop() } catch (_: Exception) {}
                try { grabber?.release() } catch (_: Exception) {}
                grabber = null
                imageState.value = null
            }
        }) {
            Text("Stop")
        }
    }
}
Copy code
It seemed to me that the implementation( "com.github.sarxos:webcam-capture:0.3.12"), displays the image faster on the screen
Add this to the image –
Modifier.graphicsLayer(rotationY = 180f)
– to mirror it 🙂
🙌 1
m
Thanks @Egor228000 - I got it already running with the sarxos lib recommended by @אליהו הדס before your post, but the both options help as well. I will test these also, as my project currently only runs on a Windows11 device but fails to get a webcam on a M4 Mac. I will let this thread know what my findings are. Thanks a lot.
🙌 1
Solved. I changed my project to javacv and noticed the following: with the latest version of org.bytedecojavacv platform1.5.12" it fails on Windows x86_64 : java.lang.UnsatisfiedLinkError: C\Users\xxx\.javacpp\cache\opencv 4.11.0 1.5.12 windows x86 64.jar\org\bytedeco\opencv\windows x86 64\jniopencv core.dll Can't find dependent libraries But it works with "org.bytedecojavacv platform1.5.11". On my Silicon Mac M4 it works with both versions now, initially I might had the wrong setup on my Mac. Anyway: thanks a lot!
1
e
I'm glad that everything worked out for you 🙂