Search code examples
pythonwindowswinapicamera

Get file location and names from Windows Camera


I was running into troubles using QCamera with focusing and other things, so I thought I can use the Camerasoftware served with Windows 10. Based on the thread of opening the Windows Camera I did some trials to aquire the taken images and use them for my program. In the documentation and its API I didn't find usable snippets (for me), so I created the hack mentioned below. It assumes that the images are in the target folder 'C:\\Users\\*username*\\Pictures\\Camera Roll' which is mentioned in the registry (See below), but I don't know if this is reliable or how to get the proper key name. I don't think that this is the only and cleanest solution. So, my question is how to get taken images and open/close the Camera proper? Actualy the function waits till the 'WindowsCamera.exe' has left the processlist and return newly added images / videos in the target folder

In the registry I found:

Entry: Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders with key name {3B193882-D3AD-4eab-965A-69829D1FB59F}for the target folder. I don't think that this key is usable.

Working example of my hack:

import subprocess
import pathlib
import psutil

def check_for_files(path, pattern):
    print(" check_for_files:", (path, pattern))
    files = []
    for filename in pathlib.Path(path).rglob(pattern):
        files.append (filename)
    return files

def get_Windows_Picture(picpath):
    prefiles = check_for_files(picpath, '*.jpg')
    x = subprocess.call('start microsoft.windows.camera:',  shell=True)
    processlist = [proc.info['name'] for proc in psutil.process_iter (['name'])]
    while 'WindowsCamera.exe' in processlist:
        processlist = [proc.info['name'] for proc in psutil.process_iter (['name'])]
    postfiles = check_for_files(picpath, '*.jpg')
    newfiles = []
    for file in postfiles:
        if file not in prefiles:
            newfiles.append(str(file))
    return newfiles
if __name__ == "__main__":
    picpath = str (pathlib.Path ("C:/Users/*user*/Pictures/Camera Roll"))
    images = get_Windows_Picture(picpath)
    print("Images:", images)

Solution

  • The Camera Roll is a "known Windows folder" which means some APIs can retrieve the exact path (even if it's non-default) for you:

    The knownfolderid documentation will give you the constant name of the required folder (in your case FOLDERID_CameraRoll). As you can see in the linked page, the default is %USERPROFILE%\Pictures\Camera Roll (It's the default, so this doesn't mean it's the same for everyone).

    The problem in Python is that you'll need to use ctypes which can be cumbersome some times (especially in your case when you'll have to deal with GUIDs and releasing the memory returned by the API).

    This gist gives a good example on how to call SHGetKnownFolderPath from Python with ctypes. In your case you'll only need the CameraRoll member in the FOLDERID class so you can greatly simplify the code.

    Side note: Don't poll for the process end, just use the wait() function on the Popen object.