+# 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