[Cuis-dev] Webcam support
Juan Vuletich
juan at cuis.st
Wed Jun 24 10:07:41 PDT 2026
Just pushed #flipBy:on: to the repo. The attach is my suggestion for
CameraMorph. Please review it.
Also keep in mind that if you resize the CameraMorph stretching
differently in x and y (changing the aspect ratio), then rotation will
look weird, as in Cuis we assume scale is just a number.
Thanks,
On 2026-06-24 1:47 PM, Juan Vuletich via Cuis-dev wrote:
> Hi Luciano!
>
> This is so cool! Just pushed it to the Cuis repo.
>
> We need to add #outOfWorld: to Cuis. Let me take a look.
>
> One thing that is not working well is scaling and rotation. To fix it,
> I suggest moving the mirroring of the frame to #nextFrame, for
> instance by adding this at the end:
>
> orientation == #natural ifTrue: [
> displayForm := displayForm flippedBy: #horizontal ].
>
> If you agree, we'd need to keep both the original and mirrored frames
> to avoid allocating a new Form on every frame.
>
> Thanks,
>
> On 2026-06-23 10:36 AM, Luciano Notarfrancesco via Cuis-dev wrote:
>> This package implements basic webcam support using the CameraPlugin
>> included in the stock VM. It's just a quick port from Squeak, I
>> didn't spend a lot of time on it... but at least it seems to work
>> fine on MacOS. Let me know of any problems.
>>
>> To test it, you can just open a new CameraMorph, for example printing
>> this on a workspace:
>> CameraMorph new inspect
>>
>> There's a context menu to turn it on/off, set natural/original
>> orientation, change resolution, etc.
>>
>> If you close it before turning it off, depending on how you close it
>> it might not stop the camera (because #delete is not always sent, how
>> to know when a morph goes outside the world?). If this happens just
>> run CameraMorph allOff.
>>
>> Cheers,
>> Luciano
>>
--
Juan Vuletich
www.cuis.st
github.com/jvuletich
researchgate.net/profile/Juan-Vuletich
independent.academia.edu/JuanVuletich
patents.justia.com/inventor/juan-manuel-vuletich
-------------- next part --------------
'From Cuis7.9 [latest update: #8016] on 24 June 2026 at 2:02:07 pm'!
!classDefinition: #CameraMorph category: #Camera!
BoxMorph subclass: #CameraMorph
instanceVariableNames: 'cameraNumber resolution orientation cameraIsOn displayForm captureDelayMs showFPS framesSinceLastDisplay lastDisplayTime fps capturedForm '
classVariableNames: ''
poolDictionaries: ''
category: 'Camera'!
!CameraMorph methodsFor: 'drawing' stamp: 'jmv 24/Jun/2026, 4:35:54 pm (UTC)'!
drawCameraImageOn: aCanvas
| scale offset |
scale := 1 @ 1.
offset := 0 @ 0.
extent = displayForm extent ifFalse: [scale := extent / displayForm extent].
1 @ 1 = scale
ifTrue: [aCanvas image: displayForm at: offset]
ifFalse:
[| originalTransformation |
originalTransformation := aCanvas currentTransformation.
aCanvas geometryTransformation: (originalTransformation copy translatedBy: offset; scaledBy: scale).
aCanvas image: displayForm at: 0 @ 0.
aCanvas geometryTransformation: originalTransformation].! !
!CameraMorph methodsFor: 'private' stamp: 'jmv 24/Jun/2026, 4:54:23 pm (UTC)'!
initializeDisplayForm
| displayExtent cameraExtent formExtent |
displayExtent := self extentForResolutionName: resolution.
cameraExtent := CameraInterface frameExtent: cameraNumber.
cameraExtent isZero
ifTrue: [formExtent := displayExtent]
ifFalse: [ | camRatio frameRatio |
formExtent := cameraExtent.
camRatio := cameraExtent x / cameraExtent y.
frameRatio := displayExtent x / displayExtent y.
camRatio ~= frameRatio ifTrue: [displayExtent := displayExtent x @ (displayExtent x * camRatio reciprocal)]].
capturedForm := Form extent: formExtent depth: 32.
displayForm := capturedForm.
self morphExtent: displayExtent.! !
!CameraMorph methodsFor: 'private' stamp: 'jmv 24/Jun/2026, 4:54:53 pm (UTC)'!
nextFrame
| frameCount |
frameCount := CameraInterface getFrameForCamera: cameraNumber into: capturedForm bits.
frameCount = 0 ifTrue: [self increaseCaptureDelay].
frameCount > 2 ifTrue: [self decreaseCaptureDelay].
framesSinceLastDisplay := framesSinceLastDisplay + frameCount.
orientation == #natural
ifTrue: [
displayForm == capturedForm
ifTrue: [ displayForm := Form extent: capturedForm extent depth: 32 ].
capturedForm flipBy: #horizontal on: displayForm ]
ifFalse: [ displayForm := capturedForm ].! !
!classDefinition: #CameraMorph category: #Camera!
BoxMorph subclass: #CameraMorph
instanceVariableNames: 'cameraNumber resolution orientation cameraIsOn capturedForm displayForm captureDelayMs showFPS framesSinceLastDisplay lastDisplayTime fps'
classVariableNames: ''
poolDictionaries: ''
category: 'Camera'!
More information about the Cuis-dev
mailing list