-# Python program to change the background under windows (tested on windows XP)\r
-\r
-from __future__ import division\r
-\r
-import sys, os\r
-from PIL import Image\r
-\r
-import ctypes\r
-# Kinda like 'from ctypes.windll import user32'\r
-user32 = ctypes.windll.user32\r
-\r
-###sys.stdout = file(os.path.join(os.environ['USERPROFILE'], 'Desktop', 'Output.txt'), 'w')\r
-###sys.stderr = sys.stdout\r
-\r
-def getUnicodeArgs():\r
- LocalFree = ctypes.windll.kernel32.LocalFree\r
-\r
- # Defining the GetCommandLineW function\r
- GetCommandLineW = ctypes.windll.kernel32.GetCommandLineW\r
- GetCommandLineW.restype = ctypes.c_wchar_p\r
-\r
- # Defining the CommandLineToArgvW function\r
- CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW\r
- CommandLineToArgvW.argtypes = (ctypes.c_wchar_p, ctypes.c_void_p)\r
- CommandLineToArgvW.restype = ctypes.c_void_p\r
-\r
- args = GetCommandLineW()\r
- # if args != NULL\r
- if args:\r
- try:\r
- numArgs = ctypes.c_int()\r
- argv_address = CommandLineToArgvW(args, ctypes.byref(numArgs))\r
-\r
- # if argv_address != NULL\r
- if argv_address:\r
- try:\r
- argvArrayType = ctypes.c_wchar_p * numArgs.value\r
- argvArray = argvArrayType.from_address(argv_address)\r
- argv = tuple(unicode(arg) for arg in argvArray)\r
- finally:\r
- # Free the memory in argv_address\r
- LocalFree(argv_address)\r
- finally:\r
- # Free this memory since it isn't needed\r
- LocalFree(args)\r
-\r
-\r
- # Drop the first argument (since this the call to the python interperator\r
- return argv[1:]\r
-\r
-sys.unicode_argv = getUnicodeArgs()\r
-\r
-\r
-# Taken from the Platform SDK\r
-SPI_SETDESKWALLPAPER = 20\r
-SPIF_SENDWININICHANGE = 2\r
-\r
-# Resize an image (returns a new image)\r
-def resize(image, (outputWidth, outputHeight), \r
- fillBoundingBox = False, \r
- cropImage = True,\r
- method = Image.BICUBIC):\r
-\r
- imgWidth, imgHeight = image.size\r
-\r
- if (imgHeight == outputHeight) and (imgWidth == outputWidth):\r
- return image\r
-\r
- aspectRatio = imgHeight / imgWidth\r
- outputAspectRatio = outputHeight / outputWidth\r
-\r
- if fillBoundingBox:\r
- if aspectRatio < outputAspectRatio:\r
- newHeight = outputHeight\r
- newWidth = int(outputHeight / aspectRatio)\r
- # (left, upper, right, lower)\r
- offset = (newWidth - outputWidth) // 2\r
- outputBox = (offset, 0, offset + outputWidth, outputHeight)\r
- else:\r
- newWidth = outputWidth\r
- newHeight = int(outputWidth * aspectRatio)\r
- # (left, upper, right, lower)\r
- offset = (newHeight - outputHeight) // 2\r
- outputBox = (0, offset, newWidth, offset + outputHeight)\r
-\r
- print >>sys.stderr, "Aspects: ", aspectRatio, outputAspectRatio\r
- print >>sys.stderr, "Output: ", outputWidth, outputHeight\r
- print >>sys.stderr, "Img: ", imgWidth, imgHeight\r
- print >>sys.stderr, "new:", newWidth, newHeight\r
- print >>sys.stderr, "CropBox: ", outputBox\r
-\r
- image = image.resize( (newWidth, newHeight), method)\r
- if cropImage and not\\r
- ((newHeight == outputHeight) and (newWidth == outputWidth)):\r
- image = image.crop( outputBox )\r
- else:\r
- raise NotImplementedError\r
-\r
- return image\r
-\r
-# Converts the input image to a bitmap (with optional resizing)\r
-def convertImage(pathToImage, boundingBox = None):\r
- TEMP_FILE = 'pywallpaper.bmp'\r
- newPath = os.path.join(os.getcwd(), TEMP_FILE)\r
-\r
- bmpImg = Image.open(pathToImage)\r
-\r
- if boundingBox is not None:\r
- bmpImg = resize(bmpImg, boundingBox, fillBoundingBox = True)\r
-\r
- # Check the colour space it is in (we only want RGB)\r
- if bmpImg.mode == 'RGBA':\r
- bmpImg = bmpImg.convert('RGB')\r
-\r
- # Save it as a bitmap\r
- bmpImg.save(newPath, "BMP")\r
-\r
- return newPath\r
-\r
-# Actually sets the wallpaper\r
-def updateWall(pathToBMP):\r
- # Parameters for SystemParametersInfoA are:\r
- # (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)\r
- user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER,\r
- 0,\r
- pathToBMP,\r
- SPIF_SENDWININICHANGE)\r
-\r
-###\r
-# Code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/460509\r
-# Gets the size of all monitors attached to this computer)\r
-###\r
-class RECT(ctypes.Structure):\r
- _fields_ = [\r
- ('left', ctypes.c_long),\r
- ('top', ctypes.c_long),\r
- ('right', ctypes.c_long),\r
- ('bottom', ctypes.c_long)\r
- ]\r
- def dump(self):\r
- return map(int, (self.left, self.top, self.right, self.bottom))\r
-\r
-class MONITORINFO(ctypes.Structure):\r
- _fields_ = [\r
- ('cbSize', ctypes.c_ulong),\r
- ('rcMonitor', RECT),\r
- ('rcWork', RECT),\r
- ('dwFlags', ctypes.c_ulong)\r
- ]\r
-\r
-def get_monitors():\r
- retval = []\r
- CBFUNC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(RECT), ctypes.c_double)\r
- def cb(hMonitor, hdcMonitor, lprcMonitor, dwData):\r
- r = lprcMonitor.contents\r
- #print "cb: %s %s %s %s %s %s %s %s" % (hMonitor, type(hMonitor), hdcMonitor, type(hdcMonitor), lprcMonitor, type(lprcMonitor), dwData, type(dwData))\r
- data = [hMonitor]\r
- data.append(r.dump())\r
- retval.append(data)\r
- return 1\r
- cbfunc = CBFUNC(cb)\r
- temp = user32.EnumDisplayMonitors(0, 0, cbfunc, 0)\r
- #print temp\r
- return retval\r
-\r
-def monitor_areas():\r
- retval = []\r
- monitors = get_monitors()\r
- for hMonitor, extents in monitors:\r
- data = [hMonitor]\r
- mi = MONITORINFO()\r
- mi.cbSize = ctypes.sizeof(MONITORINFO)\r
- mi.rcMonitor = RECT()\r
- mi.rcWork = RECT()\r
- res = user32.GetMonitorInfoA(hMonitor, ctypes.byref(mi))\r
- data.append(mi.rcMonitor.dump())\r
- data.append(mi.rcWork.dump())\r
- retval.append(data)\r
- return retval\r
-\r
-###\r
-# End code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/460509\r
-###\r
-\r
-def main():\r
- def getPrimarySize():\r
- monitors = monitor_areas()\r
- monitorID, size, workingSize = monitors[0]\r
- sizeLeft, sizeTop, sizeRight, sizeBottom = size\r
- return (sizeRight - sizeLeft, sizeBottom - sizeTop)\r
- \r
- pathToBMP = convertImage(sys.unicode_argv[1], getPrimarySize())\r
- updateWall(pathToBMP)\r
-\r
-if __name__ == '__main__':\r
- main()\r