Apple Event: May 7th at 7 am PT

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

AppleScript to take screenshot of a specific area and save to desktop

Hello,


I need to have an Applescript that takes a screenshot (or invokes Mac OS X's screen picture taking) of a specific area of the screen (say from 911x173 to 1738x794) and then saves the result in .png on the desktop with date and time (much like a cmd-shift-4 would do).


Any help much appreciated.


Thanks in advance.

Peter 🙂


++++

CinemaDisplay 24"-OTHER, OS X Mavericks (10.9), 2.6 GHz Intel Core i7, 8 GB/750 GB

Posted on Dec 7, 2013 6:33 AM

Reply
Question marked as Best reply

Posted on Dec 7, 2013 11:06 AM

Hello


You may try something like the following script. I assumed (911, 173) and (1738, 794) are x, y-coordinates of top-left and bottom-right corners of target rectangle. It will yield a png file named "yyyy-mm-dd hh.mm.ss.png" on desktop.


set {l, t, r, b} to {911, 173, 1738, 794}
set {x, y, w, h} to {l, t, r - l, b - t}
screencapture(x, y, w, h)

on screencapture(x, y, w, h)
    (*
        number x, y, w, h: rectangle parameters
            (x, y) = x, y-coordinates of origin point
            (w, h) = width and height of rectangle
            
        * screen shot is saved as ~/Desktop/yyyy-mm-dd hh.mm.ss.png
    *)
    set args to ""
    repeat with a in {x, y, w, h}
        set args to args & space & ("" & a)'s quoted form
    end repeat
    considering numeric strings
        if (system info)'s system version < "10.9" then
            set ruby to "/usr/bin/ruby"
        else
            set ruby to "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby"
        end if
    end considering
    do shell script ruby & " <<'EOF' - " & args & "
require 'osx/cocoa'
include OSX
raise AugumentError, \"Usage: #{File.basename($0)} x, y, w, h\" unless ARGV.length == 4
x, y, w, h = ARGV.map {|a| a.to_f}
outfile = File.expand_path(%x[date +'%F %H.%M.%S.png'].chomp, '~/Desktop')
img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h))
brep = NSBitmapImageRep.alloc.initWithCGImage(img)
data = brep.objc_send(
    :representationUsingType, NSPNGFileType,
    :properties, {})
data.objc_send(
    :writeToFile, outfile,
    :atomically, false)
EOF"
end screencapture


Hope this may help,

H

23 replies

Nov 8, 2016 9:25 PM in response to VikingOSX

And here is the PyObjC reproduction of Hiroto's Ruby/Cocoa screen capture solution. The code here can be made executable and run from the Terminal, or integrated into an AppleScript in place of the existing do shell script ruby HERE document.


#!/usr/bin/python

# coding: utf-8

"""

scap.py


Specify screen capture coordinates on command-line, and generate

image to Desktop as Screen Shot YYYY-mm-dd at hh.mm.ss [AM|PM].png


The {x, y} below would be the screen coordinates for the starting point,

and the {w, h} would be the ending coordinates of the chosen screen area.


Usage: scap.py x y w h

"""


from Quartz.CoreGraphics import (CGDisplayCreateImageForRect, CGMainDisplayID,

CGRectMake)

from AppKit import NSBitmapImageRep, NSPNGFileType


import time

import os

import sys


desktop = os.path.expanduser('~/Desktop')

outfile = time.strftime("Screen Shot %F at %H.%M.%S %p.png")

outpath = os.path.join(desktop, outfile)


if not len(sys.argv) == 5:

raise Exception("Usage: {} x y w h ".format(__file__))

sys.exit(1)

x, y, w, h = map(float, sys.argv[1:])


# grab an area of the screen bounded by x, y, w, h coordinates.

img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h))

brep = NSBitmapImageRep.alloc().initWithCGImage_(img)

pngData = brep.representationUsingType_properties_(NSPNGFileType, None)

pngData.writeToFile_atomically_(outpath, False)

sys.exit(0)


Here is a PNG screen grab taken by this code of itself.

User uploaded file

Nov 9, 2016 12:54 AM in response to VikingOSX

Dear VikingOSX,


Thank you for your answers. I tried your AppleScript solution. It starts normal, ask for the coordinates but when I type the four numbers with comas, I have an error message like this:


error "screencapture: cannot write file to intended destination, 25,25,125,125" number 1


Did I something wrong?

I use a MacBook Air with a second display. Is it a problem?


Thank you,

fabee

Nov 9, 2016 5:19 AM in response to deek5

If the -R option does not exist in screencapture, how is it that my tested, and working scripts (El Capitan, macOS Sierra) take full advantage of that feature?


Life is more than reading, and the screencapture man page omits the -R option — yet providing screencapture with a false (-h) option causes it to dump out the real supported options list.


The code that I posted is designed around the original post requirements.

Nov 9, 2016 5:35 AM in response to fabee.zz

I just copied, and pasted the posted AppleScript into my Script Editor (El Capitan 10.11.6), compiled, and ran it. It worked correctly, and without error. The same is true on macOS Sierra 10.12.1.


What specific version of OS X are you using? I don't have two displays, but as written, the script should default to the primary desktop.

Nov 9, 2016 4:52 PM in response to fabee.zz

Hello


RubyCocoa is no longer part of standard installation of OS X 10.10 or later. Although you can build and install RubyCocoa 1.2.0 that supports Ruby 2.0 from source code, it would be overkill just to take a screencapture of specified region.


So here's an AppleScript script that is a wrapper of pyobjc script to do the same thing as the original rubycocoa script. PyObjC is part of standard installation of OS X 10.5 through 10.12.



--APPLESCRIPT set {l, t, r, b} to {911, 173, 1738, 794} set {x, y, w, h} to {l, t, r - l, b - t} screencapture(x, y, w, h) on screencapture(x, y, w, h) (* number x, y, w, h: rectangle parameters (x, y) = x, y-coordinates of origin point (w, h) = width and height of rectangle return string: file name of saved screen shot * screen shot is saved as ~/Desktop/yyyy-mm-dd hh.mm.ss.png *) set args to "" repeat with a in {x, y, w, h} set args to args & space & ("" & a)'s quoted form end repeat do shell script "/usr/bin/python <<'EOF' - " & args & " # coding: utf-8 # # file: # screencapture.py # # function: # create screen capture of specified rectangle and save it as time-stamped png image on desktop # # usage e.g.: # ./screencapture.py x y w h # x, y, w, h: rect(point(x, y), size(w, h)) # # version: # 0.10 # - draft # import sys, os, objc, time import Quartz.CoreGraphics as CG import AppKit as OSX # # manual loading of bridgesupport metadata for CGDisplayCreateImageForRect() is required under OS X 10.6.8 # CG_BRIDGESUPPORT = '''<?xml version=\"1.0\" standalone=\"yes\"?> <!DOCTYPE signatures SYSTEM \"file://localhost/System/Library/DTDs/BridgeSupport.dtd\"> <signatures version=\"0.9\"> <function name='CGDisplayCreateImageForRect'> <arg type='I'/> <arg type64='{CGRect={CGPoint=dd}{CGSize=dd}}' type='{CGRect={CGPoint=ff}{CGSize=ff}}'/> <retval already_retained='true' type='^{CGImage=}'/> </function> </signatures>''' objc.parseBridgeSupport( CG_BRIDGESUPPORT, globals(), objc.pathForFramework('/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework') ) def usage(): sys.stderr.write('Usage: %s x y w h\\n' % os.path.basename(sys.argv[0])) sys.exit(1) def main(): if not len(sys.argv) == 5: usage() x, y, w, h = [ float(a) for a in sys.argv[1:5] ] outfile = os.path.join( os.path.expanduser('~/Desktop'), time.strftime('%F %H.%M.%S.png', time.localtime()) ) # outfile = ~/Desktop/yyyy-mm-dd hh.mm.ss.png img = CGDisplayCreateImageForRect(CG.CGMainDisplayID(), CG.CGRectMake(x, y, w, h)) brep = OSX.NSBitmapImageRep.alloc().initWithCGImage_(img) data = brep.representationUsingType_properties_(OSX.NSPNGFileType, {}) data.writeToFile_atomically_(outfile, False) sys.stdout.write('%s\\n' % os.path.basename(outfile)) main() EOF" end screencapture --END OF APPLESCRIPT




And in case, here's the underlying pyobjc script if you prefer to use it in shell.



#!/usr/bin/python # coding: utf-8 # # file: # screencapture.py # # function: # create screen capture of specified rectangle and save it as png image on desktop # # usage e.g.: # ./screencapture.py x y w h # x, y, w, h: rect(point(x, y), size(w, h)) # # version: # 0.10 # - draft # import sys, os, objc, time import Quartz.CoreGraphics as CG import AppKit as OSX # # manual loading of bridgesupport metadata for CGDisplayCreateImageForRect() is required under OS X 10.6.8 # CG_BRIDGESUPPORT = '''<?xml version="1.0" standalone="yes"?> <!DOCTYPE signatures SYSTEM "file://localhost/System/Library/DTDs/BridgeSupport.dtd"> <signatures version="0.9"> <function name='CGDisplayCreateImageForRect'> <arg type='I'/> <arg type64='{CGRect={CGPoint=dd}{CGSize=dd}}' type='{CGRect={CGPoint=ff}{CGSize=ff}}'/> <retval already_retained='true' type='^{CGImage=}'/> </function> </signatures>''' objc.parseBridgeSupport( CG_BRIDGESUPPORT, globals(), objc.pathForFramework('/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework') ) def usage(): sys.stderr.write('Usage: %s x y w h\n' % os.path.basename(sys.argv[0])) sys.exit(1) def main(): if not len(sys.argv) == 5: usage() x, y, w, h = [ float(a) for a in sys.argv[1:5] ] outfile = os.path.join( os.path.expanduser('~/Desktop'), time.strftime('%F %H.%M.%S.png', time.localtime()) ) # outfile = ~/Desktop/yyyy-mm-dd hh.mm.ss.png img = CGDisplayCreateImageForRect(CG.CGMainDisplayID(), CG.CGRectMake(x, y, w, h)) brep = OSX.NSBitmapImageRep.alloc().initWithCGImage_(img) data = brep.representationUsingType_properties_(OSX.NSPNGFileType, {}) data.writeToFile_atomically_(outfile, False) sys.stdout.write('%s\n' % os.path.basename(outfile)) main()




Scripts are briefly tested with pobjc 2.2b3 and python 2.6.1 under OS X 10.6.8.


Good luck,

H

AppleScript to take screenshot of a specific area and save to desktop

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.