Created
October 19, 2008 20:37
-
-
Save d0k/17930 to your computer and use it in GitHub Desktop.
ruby script to convert images inside keynote 4 bundles to PNG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby -w | |
# Converts images inside keynote bundles to PNG | |
# We need RMagick with tiff support installed | |
# You may get libtiff from macports | |
# and RMagick from rubygems | |
# Licensed under GPLv3 | |
require 'rubygems' | |
require 'optparse' | |
require 'zlib' | |
require 'rexml/document' | |
require 'RMagick' | |
# the extensions that will be compressed to PNG | |
EXTENSIONS = ['.tiff', '.pict', '.bmp'] | |
quiet = false | |
clean = false | |
# deletes a directory and all files in it (non-recursive) | |
def deletedir(dir, quiet = false) | |
if File.exists?(dir) | |
Dir.foreach(dir) do |f| | |
fn = dir + File::SEPARATOR + f | |
unless File.directory?(fn) | |
puts "Deleting #{fn}" unless quiet | |
File.unlink(fn) | |
end | |
end | |
puts "Deleting #{dir}" unless quiet | |
Dir.unlink(dir) | |
end | |
end | |
OptionParser.new do |o| | |
o.banner = "Usage: #{$0} [options] filename" | |
o.on('-c', '--[no-]clean', 'clean up temporary files (e.g. thumbnails)') do |v| | |
clean = v | |
end | |
o.on('-q', '--[no-]quiet', 'No output') do |v| | |
quiet = v | |
end | |
o.on_tail("-h", "--help", "Shows this message") do | |
puts o | |
exit | |
end | |
end.parse! | |
if ARGV.length != 1 | |
puts 'Missing argument (try --help)' | |
exit(1) | |
end | |
indir = ARGV.shift + File::SEPARATOR | |
index = indir + 'index.apxl.gz' | |
if clean | |
deletedir(indir + 'thumbs', quiet) # thumbnails will be regenerated by keynote | |
deletedir(indir + 'QuickLook', quiet) # quicklook thumbnail | |
end | |
# read index.apxl.gz | |
doc = nil | |
Zlib::GzipReader.open(index) { |f| doc = REXML::Document.new(f) } | |
# XPath is really slow in REXML :( | |
doc.elements.each('//key:page//sf:data') do |element| | |
name = element.attributes['sf:path'] | |
newname = element.attributes['sf:path'] + '.png' | |
if EXTENSIONS.include?(File.extname(name)) | |
if File.exists?(newname) | |
puts "Won't compress #{name} because #{newname} already exists" unless quiet | |
else | |
# compress image | |
image = Magick::ImageList.new(indir + name) | |
image.write(indir + newname) | |
# write new filename | |
if element.attributes['sf:displayname'] == name # not sure if this is necessary | |
element.attributes['sf:displayname'] = newname | |
end | |
element.attributes['sf:path'] = newname | |
puts "Compressed #{name}" unless quiet | |
File.unlink(indir + name) # delete old file | |
end | |
else | |
puts "Won't compress #{name}" unless quiet | |
end | |
end | |
# write changed xml back | |
Zlib::GzipWriter.open(index) { |f| doc.write(f) } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment