take picture with camera

Mac OSX specific forum
spacebuddy
Enthusiast
Enthusiast
Posts: 356
Joined: Thu Jul 02, 2009 5:42 am

take picture with camera

Post by spacebuddy »

Does PB have a function that can take a snapshot from the camera on an iMac?

Thanks :D
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: take picture with camera

Post by wilbert »

No, it doesn't.
If you don't mind a dialog window popping up, the IKPictureTaker class is one of the easiest options.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: take picture with camera

Post by Shardik »

I have taken another route than wilbert proposed by utilizing the QuickTime framework QTKit. The following example code displays the video stream of an inbuilt iSight WebCam. When clicking on the toolbar button a snapshot will be taken and displayed in a second window beneath the first.

The example code below should run on an OS X version beginning with 10.5 (Leopard). I have tested it successfully on OS X 10.6.8 (Snow Leopard) and OS X 10.8.4 (Mountain Lion) with PB 5.11 x86 and x64 in ASCII and Unicode mode and PB 5.11 x64 in ASCII mode. Executing the example code in PB 5.11 x64 in Unicode mode will result in an invalid memory access because of a bug in Pseudotype P-ASCII which is fixed in the current PB 5.20 x64 Beta 13. In that bug posting you will also find workarounds for PB 5.11 x64.

Code: Select all

EnableExplicit

ImportC "/System/Library/Frameworks/QTKit.framework/QTKit" : EndImport

ImportC ""
  sel_registerName(MethodName.P-ASCII)
  class_addMethod(Class.I, Selector.I, Implementation.I, Types.P-ASCII)
EndImport

Define Delegate.I
Define DelegateClass.I
Define Device.I
Define DeviceInput.I
Define NSError.I
Define Session.I
Define TakeSnapshotNow.I
Define View.I

ProcedureC SnapshotCallback(Object.I, Selector.I, View.I, CIImage.I)
  Shared TakeSnapshotNow.I

  Protected CGImage.I
  Protected NSCIImageRep.I
  Protected NSImage.I
  Protected ImageSize.NSSize

  If TakeSnapshotNow
    TakeSnapshotNow = #False

    NSCIImageRep = CocoaMessage(0, CocoaMessage(0, 0,
      "NSBitmapImageRep alloc"), "initWithCIImage:", CIImage)

    If NSCIImageRep
      CGImage = CocoaMessage(0, NSCIImageRep, "CGImage")

      If CGImage
        NSImage = CocoaMessage(0, 0, "NSImage alloc")

        If NSImage
          ImageSize\width = WindowWidth(1) + 4
          ImageSize\height = WindowHeight(1) + 4
          CocoaMessage(0, NSImage, "initWithCGImage:", CGImage,
            "size:@", @ImageSize)
          SetGadgetState(0, NSImage)
          CocoaMessage(0, NSImage, "release")
        EndIf
      EndIf
    EndIf
  EndIf
EndProcedure

Delegate = CocoaMessage(0, CocoaMessage(0, 0,
  "NSApplication sharedApplication"), "delegate")
DelegateClass = CocoaMessage(0, Delegate, "class")
class_addMethod(DelegateClass, sel_registerName("view:willDisplayImage:"),
  @SnapshotCallback(), "v@:@@")

OpenWindow(0, 270, 100, 376, 300, "Press toolbar button for snapshot")

CreateImage(0, 16, 16)

StartDrawing(ImageOutput(0))
  Box(0, 0, 16, 16, $FFFFFF)
  Box(4, 4, 8, 8, $FF)
StopDrawing()

If CreateToolBar(0, WindowID(0))
  ToolBarImageButton(0, ImageID(0))
EndIf

OpenWindow(1, WindowX(0) + WindowWidth(0) + 10, 132, WindowWidth(0),
  WindowHeight(0), "Captured image",
  #PB_Window_SystemMenu | #PB_Window_Invisible)
ImageGadget(0, 0, 0, WindowWidth(1), WindowHeight(1), 0)
CocoaMessage(0, GadgetID(0), "setImageScaling:", 0)

Session = CocoaMessage(0, CocoaMessage(0, 0, "QTCaptureSession alloc"), "init")

If Session
  View = CocoaMessage(0, CocoaMessage(0, 0, "QTCaptureView alloc"), "init")

  If View
    CocoaMessage(0, View, "setDelegate:", Delegate)
    CocoaMessage(0, WindowID(0), "setContentView:", View)
    Device = CocoaMessage(0, 0,
      "QTCaptureDevice defaultInputDeviceWithMediaType:$", @"vide")

    If Device
      If CocoaMessage(0, Device, "open:", @NSError) = #YES
        DeviceInput = CocoaMessage(0, CocoaMessage(0, 0,
          "QTCaptureDeviceInput alloc"), "initWithDevice:", Device)

        If DeviceInput
          If CocoaMessage(0, Session, "addInput:", DeviceInput, "error:",
            @NSError) = #YES
            CocoaMessage(0, View, "setCaptureSession:", Session)
            CocoaMessage(0, Session, "startRunning")

            Repeat
              Select WaitWindowEvent()
                Case #PB_Event_CloseWindow
                  Break
                Case #PB_Event_Menu
                  If EventMenu() = 0
                    TakeSnapshotNow = #True
                    HideWindow(1, #False)
                  EndIf
              EndSelect
            ForEver

            CocoaMessage(0, Session, "stopRunning")
            CocoaMessage(0, Device, "close")
            CocoaMessage(0, DeviceInput, "release")
            CocoaMessage(0, Session, "release")
          EndIf
        EndIf
      EndIf
    EndIf
  EndIf
EndIf
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: take picture with camera

Post by WilliamL »

Shardik,

I'm getting the stream, in a window, and when I click the toolbar I get another window (the correct size) but it is white.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: take picture with camera

Post by Shardik »

William,

I am sorry that my example code does not display the snapshot on your Mac. On which exact Mac model did you try? On my iMac11,2 (summer 2010, Intel Core i5 with 3.6 GHz, ATI Radeon HD 5670, screen resolution 1920 x 1080) my example code works like a charme.

Perhaps it may be a matter of your retina display with a much bigger resolution so that the conversion from CGImage to NSImage or the downscaling from 1280x1024 to 376x300 doesn't work anymore. Unfortunately I have no access to a newer Mac with retina display for testing. But you may try the following modified example which directly saves the snapshot to /tmp/Snapshot.jpg without downscaling. The /tmp folder is normally hidden, so that you have to click onto "Goto" in the menu bar of the finder, select "Goto folder..." and type "/tmp" to jump to the folder /tmp and to view the file "Snapshot.jpg". I hope it will work for you... :wink:

Code: Select all

EnableExplicit

ImportC "/System/Library/Frameworks/QTKit.framework/QTKit" : EndImport

ImportC ""
  sel_registerName(MethodName.P-ASCII)
  class_addMethod(Class.I, Selector.I, Implementation.I, Types.P-ASCII)
EndImport

Define Delegate.I
Define DelegateClass.I
Define Device.I
Define DeviceInput.I
Define NSError.I
Define Session.I
Define SnapshotFile.S = GetTemporaryDirectory() + "Snapshot.jpg"
Define TakeSnapshotNow.I
Define View.I

ProcedureC SnapshotCallback(Object.I, Selector.I, View.I, CIImage.I)
  Shared SnapshotFile.S
  Shared TakeSnapshotNow.I

  Protected NSCIImageRep.I
  Protected NSData.I

  If TakeSnapshotNow
    NSCIImageRep = CocoaMessage(0, CocoaMessage(0, 0, "NSBitmapImageRep alloc"), "initWithCIImage:", CIImage)
    NSData = CocoaMessage(0, NSCIImageRep, "representationUsingType:", #NSJPEGFileType, "properties:", 0)

    If CocoaMessage(0, NSData, "writeToFile:$", @SnapshotFile,
      "atomically:", #NO) = #YES
    EndIf

    PostEvent(#PB_Event_CloseWindow)
  EndIf
EndProcedure

Delegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
DelegateClass = CocoaMessage(0, Delegate, "class")
class_addMethod(DelegateClass, sel_registerName("view:willDisplayImage:"), @SnapshotCallback(), "v@:@@")

OpenWindow(0, 270, 100, 376, 300, "Press toolbar button for snapshot")

CreateImage(0, 16, 16)

StartDrawing(ImageOutput(0))
  Box(0, 0, 16, 16, $FFFFFF)
  Box(4, 4, 8, 8, $FF)
StopDrawing()

If CreateToolBar(0, WindowID(0))
  ToolBarImageButton(0, ImageID(0))
EndIf

Session = CocoaMessage(0, CocoaMessage(0, 0, "QTCaptureSession alloc"), "init")

If Session
  View = CocoaMessage(0, CocoaMessage(0, 0, "QTCaptureView alloc"), "init")

  If View
    CocoaMessage(0, View, "setDelegate:", Delegate)
    CocoaMessage(0, WindowID(0), "setContentView:", View)
    Device = CocoaMessage(0, 0, "QTCaptureDevice defaultInputDeviceWithMediaType:$", @"vide")

    If Device
      If CocoaMessage(0, Device, "open:", @NSError) = #YES
        DeviceInput = CocoaMessage(0, CocoaMessage(0, 0,
          "QTCaptureDeviceInput alloc"), "initWithDevice:", Device)

        If DeviceInput
          If CocoaMessage(0, Session, "addInput:", DeviceInput, "error:", @NSError) = #YES
            CocoaMessage(0, View, "setCaptureSession:", Session)
            CocoaMessage(0, Session, "startRunning")

            Repeat
              Select WaitWindowEvent()
                Case #PB_Event_CloseWindow
                  If TakeSnapshotNow
                    CloseWindow(0)
                    MessageRequester("Info", "Snapshot was saved to " + SnapshotFile)
                  EndIf

                  Break
                Case #PB_Event_Menu
                  If EventMenu() = 0
                    TakeSnapshotNow = #True
                  EndIf
              EndSelect
            ForEver

            CocoaMessage(0, Session, "stopRunning")
            CocoaMessage(0, Device, "close")
            CocoaMessage(0, DeviceInput, "release")
            CocoaMessage(0, Session, "release")
          EndIf
        EndIf
      EndIf
    EndIf
  EndIf
EndIf
spacebuddy
Enthusiast
Enthusiast
Posts: 356
Joined: Thu Jul 02, 2009 5:42 am

Re: take picture with camera

Post by spacebuddy »

WilliamL wrote:Shardik,

I'm getting the stream, in a window, and when I click the toolbar I get another window (the correct size) but it is white.
I am getting the exact same thing on my iMac with built-in cam.
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: take picture with camera

Post by WilliamL »

Hey Shardik, that works! I got the jpg in the temp folder but I thought it would be George Clooney and it was just me. :lol:

I only mentioned that it didn't work but did not want to bother you further. If I had wanted it badly I would have been more specific. I have no idea why it would be different on my laptop and I surely don't expect you to know. I'm not that interested in looking at myself.

I appreciate all your contributions and want to try most of them just to see how they work.

Thanks again.

@spacebuddy.. nice to hear from you, I hate it when I'm the only one with the odd result.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
spacebuddy
Enthusiast
Enthusiast
Posts: 356
Joined: Thu Jul 02, 2009 5:42 am

Re: take picture with camera

Post by spacebuddy »

WilliamL wrote:Hey Shardik, that works! I got the jpg in the temp folder but I thought it would be George Clooney and it was just me. :lol:

I only mentioned that it didn't work but did not want to bother you further. If I had wanted it badly I would have been more specific. I have no idea why it would be different on my laptop and I surely don't expect you to know. I'm not that interested in looking at myself.

I appreciate all your contributions and want to try most of them just to see how they work.

Thanks again.

@spacebuddy.. nice to hear from you, I hate it when I'm the only one with the odd result.

Thanks William :D

The second example worked for me too.. Just looked at my picture, getting so old :shock:
Post Reply