Page 1 of 1

take picture with camera

Posted: Tue Aug 20, 2013 11:40 pm
by spacebuddy
Does PB have a function that can take a snapshot from the camera on an iMac?

Thanks :D

Re: take picture with camera

Posted: Wed Aug 21, 2013 5:30 am
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.

Re: take picture with camera

Posted: Sat Aug 24, 2013 11:10 pm
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

Re: take picture with camera

Posted: Sat Aug 24, 2013 11:49 pm
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.

Re: take picture with camera

Posted: Sun Aug 25, 2013 9:50 pm
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

Re: take picture with camera

Posted: Mon Aug 26, 2013 2:40 am
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.

Re: take picture with camera

Posted: Mon Aug 26, 2013 3:35 am
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.

Re: take picture with camera

Posted: Mon Aug 26, 2013 5:24 pm
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: