1#!/usr/bin/env ruby 2# 3# DarkRoom 4# Takes fullsize screenshots of a web page. 5# Copyright (c) 2007 Justin Palmer. 6# 7# Released under an MIT LICENSE 8# 9# Usage 10# ==== 11# ruby ./darkroom.rb http://activereload.net 12# ruby ./darkroom.rb --output=google.png http://google.com 13# ruby ./darkroom.rb --width=400 --delay=5 http://yahoo.com 14# 15require 'optparse' 16require 'osx/cocoa' 17OSX.require_framework 'Webkit' 18 19module ActiveReload 20 module DarkRoom 21 USER_AGENT = "DarkRoom/0.1" 22 class Photographer 23 def initialize 24 options = {} 25 opts = OptionParser.new do |opts| 26 opts.banner = "Usage: #$0 [options] URL" 27 28 opts.on('-w', '--width=[WIDTH]', Integer, 'Force width of the screenshot') do |v| 29 options[:width] = v 30 end 31 32 opts.on('-h', '--height=[HEIGHT]', Integer, 'Force height of screenshot') do |v| 33 options[:height] = v 34 end 35 36 opts.on('-o', '--output=[FILENAME]', String, 'Specify filename for saving') do |v| 37 options[:output] = v 38 end 39 40 opts.on('-d', '--delay=[DELAY]', Integer, 'Delay in seconds to give web page assets time to load') do |v| 41 options[:delay] = v 42 end 43 44 opts.on_tail('-h', '--help', 'Display this message and exit') do 45 puts opts 46 exit 47 end 48 end.parse! 49 options[:width] ||= 1024 50 options[:height] ||= 0 51 options[:website] = ARGV.first || 'http://google.com' 52 Camera.shoot(options) 53 end 54 end 55 56 class Camera 57 def self.shoot(options) 58 app = OSX::NSApplication.sharedApplication 59 delegate = Processor.alloc.init 60 delegate.options = options 61 app.setDelegate(delegate) 62 app.run 63 end 64 end 65 66 class Processor < OSX::NSObject 67 include OSX 68 attr_accessor :options, :web_view 69 70 def initialize 71 rect = [-16000.0, -16000.0, 100, 100] 72 win = NSWindow.alloc.initWithContentRect_styleMask_backing_defer(rect, NSBorderlessWindowMask, 2, 0) 73 74 @web_view = WebView.alloc.initWithFrame(rect) 75 @web_view.mainFrame.frameView.setAllowsScrolling(false) 76 @web_view.setApplicationNameForUserAgent(USER_AGENT) 77 @web_view.setFrameLoadDelegate(self) 78 79 win.setContentView(@web_view) 80 end 81 82 def applicationDidFinishLaunching(notification) 83 @options[:output] ||= "#{Time.now.strftime('%m-%d-%y-%H%I%S')}.png" 84 @web_view.window.setContentSize([@options[:width], @options[:height]]) 85 @web_view.setFrameSize([@options[:width], @options[:height]]) 86 @web_view.mainFrame.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(@options[:website]))) 87 end 88 89 def webView_didFinishLoadForFrame(web_view, frame) 90 viewport = web_view.mainFrame.frameView.documentView 91 viewport.window.orderFront(nil) 92 viewport.window.display 93 viewport.window.setContentSize([@options[:width], (@options[:height] > 0 ? @options[:height] : viewport.bounds.height)]) 94 viewport.setFrame(viewport.bounds) 95 sleep(@options[:delay]) if @options[:delay] 96 capture_and_save(viewport) 97 end 98 99 def capture_and_save(view) 100 view.lockFocus 101 bitmap = NSBitmapImageRep.alloc.initWithFocusedViewRect(view.bounds) 102 view.unlockFocus 103 104 bitmap.representationUsingType_properties(NSPNGFileType, nil).writeToFile_atomically(@options[:output], true) 105 NSApplication.sharedApplication.terminate(nil) 106 end 107 end 108 end 109end 110ActiveReload::DarkRoom::Photographer.new 111