Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Optimize images for Desktop Background display Desktop
I have a large number of irregularly shaped images that I use as Desktop Backgrounds. In Desktop & Screen Saver preferences, 'Fill Screen' or 'Fit to Screen' makes small images ugly, and 'Center' crops large images quite badly -- and I'd rather keep all the images in one folder, and displayed properly.

I wrote a script to pad small images to the screen size, and large images to the screen aspect ratio. It works on the Finder selection and overwrites the input files, so use duplicates. Open the script in AppleScript Editor and change _screenWidth and _screenHeight to match your display. Now, with 'Fill Screen' selected, padded images are always displayed correctly (with a black border), and un-padded images (for me, photos) fill the whole display.

Image events can't read the dimensions of some images such as PICT files. The script will pass over these, and other non-image files. Properly proportioned large images will also be passed over (correct to 2 decimal places). The script contains some notes. Errors are logged by the script.

WARNING: The script overwrites original files, so work on copies. The code follows. It's long, so you may wish to download it from the link above.
--WARNING: This script overwrites original files, work on copies.

-- Change these variables to your screen dimensions…
set _screenWidth to 1280
set _screenHeight to 800

-- Don't change this!
set _screenRatio to _screenWidth / _screenHeight

try
  tell application "Finder"
    with timeout of 600 seconds
      set _selection to selection
    end timeout
    if _selection = {} then error "No files selected…" number 1
  end tell
  
  display dialog "Warning: This script will overwrite selected files.

Please work on duplicates." with title "Pad Images for the Desktop" buttons {"Cancel", "Continue"} default button "Cancel"
  
  set _fileNames to {}
  repeat with _file in _selection
    try
      tell application "Finder" to set _alias to _file as alias
      set _aliasText to _alias as text
      set end of _fileNames to _aliasText
    end try
  end repeat
  if _fileNames = {} then error "No filenames" number 1
  
  tell application "Image Events"
    launch
    repeat with _fileName in _fileNames
      try
        set _image to open _fileName
        
        -- This will throw an error if file is not valid - _image is undefined
        set _dimensions to dimensions of _image
        if _dimensions = {} then error "No dimensions for this file…" number 1 --Not an image, or unable to get dimensions
        
        set {_width, _height} to {item 1 of _dimensions as integer, item 2 of _dimensions as integer}
        
        set _ratio to (_width / _height) -- image aspect ratio
        set _ratio to (_ratio * 100 as integer) / 100 -- round to 2 decimal places
        
        if _width < _screenWidth and _height < _screenHeight then
          -- Image smaller than the screen, pad to screen size
          set {_newWidth, _newHeight} to {_screenWidth, _screenHeight}
        else
          if _ratio = _screenRatio then
            -- Do nothing!
            error "The image doesn't need padding." number 1
          end if
          
          if _width ≥ _height then
            -- 'Landscape' image
            
            if _ratio < _screenRatio then
              -- Pad sides
              set _newWidth to (_height * _screenRatio) as integer
              set _newHeight to _height
            end if
            
            if _ratio > _screenRatio then
              -- Pad top and bottom
              set _newHeight to (_width / _screenRatio) as integer
              set _newWidth to _width
            end if
          else
            -- 'Portrait' image
            set _newWidth to (_height * _screenRatio) as integer
            set _newHeight to _height
          end if
        end if
        
        
        pad _image to dimensions {_newWidth, _newHeight} with pad color {0, 0, 0} -- black
        
        save _image in _fileName
        
        close _image
        
      on error a number b
        try
          close _image
        end try
        log a
      end try
      
    end repeat
  end tell
  
  delay 2
  
  tell application "Finder"
    with timeout of 600 seconds
      set selection to _selection
    end timeout
  end tell
on error a number b
  log "Error: " & a
end try


[crarko adds: I tested this, and it works as described. The easiest way to use this is to put the script in your Scripts menu. I put it in ~/Library/Scripts/Applications/Finder. Then select the images in the Finder and run the script. The script is also mirrored here.]
    •    
  • Currently 4.60 / 5
  • 1
  • 2
  • 3
  • 4
  • 5
  (5 votes cast)
 
[9,452 views]  

Optimize images for Desktop Background display | 6 comments | Create New Account
Click here to return to the 'Optimize images for Desktop Background display' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Optimize images for Desktop Background display
Authored by: wallybear on Oct 26, '10 08:03:57AM

Instead of fixing screen size in the script you can set it programmatically:


tell application "Finder"
set _theScreen to bounds of window of desktop
set _screenWidth to item 3 of _theScreen
set _screenHeight to item 4 of _theScreen
end tell

So it will work even if you change your screen resolution.



[ Reply to This | # ]
Optimize images for Desktop Background display
Authored by: philostein on Oct 26, '10 11:18:22AM
Yeah, I was thought about that, but I read that it's not useful when there are multiple displays:
http://bit.ly/akSeai
Also, it fails when the Desktop window has been deactivated. ;)

This might be better:
set command to "/usr/sbin/system_profiler SPDisplaysDataType | grep Resolution"
set output to words of (do shell script command)
set {dspwidth, dspheight} to {item 2, item 4} of output

I'm not too down with Terminal though…

[ Reply to This | # ]
Optimize images for Desktop Background display
Authored by: wallybear on Oct 26, '10 02:18:06PM
Yes, that works.
This also works:

set _dims to do shell script "defaults read /Library/Preferences/com.apple.windowserver | grep -m 2  -w 'Height\\|Width'"
set {_screenHeight, _screenWidth} to {third word of _dims as number, sixth word of _dims as number}
Edited on Oct 26, '10 02:20:51PM by wallybear


[ Reply to This | # ]
Optimize images for Desktop - improved script
Authored by: tedw on Oct 28, '10 12:26:16AM
Just on a lark, I twiddled with this script. changes are as follows:
  • script now scales the image so that it fills the screen on the "best" dimension (whichever is largest proportionally)
  • added a choose file command for when there is no selection
  • added the fill color as a global variable
  • tightened up and streamlined the code
--WARNING: This script overwrites original files, work on copies.

-- Change these variables to your screen dimensions…
set _screenWidth to 1280
set _screenHeight to 800
set _fillColor to {0, 0, 0} -- black

global _screenWidth, _screenHeight, _fillColor

tell application "Finder" to set _fileNames to selection as alias list
if _fileNames = {} then
	set _fileNames to choose file with prompt "Choose desktop images to pad" of type "public.image" with multiple selections allowed
end if

if _fileNames = {} then error "No filenames selected" number 1

display alert "Pad Images for the Desktop" message "Warning: This script will overwrite selected files. Please work on duplicates." buttons {"Cancel", "Continue"} default button "Cancel"
if button returned of the result is "Cancel" then
	return
end if

repeat with _fileName in _fileNames
	try
		tell application "Image Events"
			set _image to open _fileName
			set {_width, _height} to dimensions of _image
		end tell
		process_image(_width, _height, _image)
	on error a number b
		try
			tell application "Image Events" to close _image
		end try
		log a
	end try
end repeat

to process_image(_width, _height, _image)
	-- image aspect ratio, rounded to 2 decimal places
	set _ratio to (round (100 * _width / _height)) / 100
	
	-- image height/width to screen height/width ratios, for determining proper scaling
	set _heightRatio to (round (100 * _height / _screenHeight)) / 100
	set _widthRatio to (round (100 * _width / _screenWidth)) / 100
	
	if _heightRatio ≥ _widthRatio then
		--scale to height
		set _scalingFactor to 1 / _heightRatio
	else
		--scale to width
		set _scalingFactor to 1 / _widthRatio
	end if
	
	tell application "Image Events"
		scale _image by factor _scalingFactor
		pad _image to dimensions {_screenWidth, _screenHeight} with pad color _fillColor
		save _image
		close _image
	end tell
end process_image


[ Reply to This | # ]
Optimize images for Desktop Background display
Authored by: philostein on Oct 28, '10 05:04:51AM
Thanks tedw, your code is a lot better written than mine, I picked up a few things.

I want to emphasise that the result of tedw's script is substantially different from the original, in that my script keeps the original images' visible dimensions and pads them to the screen ratio. tedw's version scales images to the screen size, which can cause blockiness when scaling small images.

I say for small and large images in one folder, use my script, and for a folder of images larger than the screen, use tedw's (and save some memory). Or perhaps someone would like to combine the two scripts?

[ Reply to This | # ]
Optimize images for Desktop Background display
Authored by: tedw on Oct 28, '10 09:32:04AM
well, modifying the script is straight-forward. If you don't want scaling at all, comment out or delete the

scale _image by factor _scalingFactor

line. Of course, this will mean that images which are larger than the screen size will not be scaled down and may not display correctly. If you're only worried about blockiness, then you can add in a check to keep from scaling up images that are too small. You could do that by adding the following lines after the if statement block in the process_images handler (right before the tell application "Image Events" line):

-- _scaling up by a large factor produces blockiness, so set scaling to 1 and pad instead
if _scalingFactor ≥ 2 then set _scalingFactor to 1
The 2 is a guess (assuming that images which will be scaled up by a factor of 2 might get blocky). 3 or 4 might work as well; I really haven't experimented to see how much scaling Core Image can handle before blockiness sets in.

[ Reply to This | # ]