3D-Grabber
Joined: 07 May 2007 Posts: 4 Location: Zurich - Switzerland
|
Posted: Tue May 08, 2007 4:18 pm Post subject: Window to the World - Panoramio Wallpaper Changer |
|
|
Window to the World - Panoramio Wallpaper Changer
Panoramio is a community driven photo sharing service. The photos can be geotagged. There is a Panoramio layer on Google Earth and Google Maps which shows the photos on the globe. There are over 2 million photos online, most of them very good quality.
This script puts every now then a new Panoramio photo on your desktop (interval adjustable - default 5 minutes). Photos are annotated with title, location, author, ... (customizable). Only photos that can be reasonably displayed on the screen are choosen (size / aspect ratio). The script uses the ImageMagick command line tool to process the photos (Freeware, bundled with the .zip), Titan's XPath (thanks) and some other code snippets from his site.
And no, it does not use "Active Desktop" (eek..!)
Version 0.8
Download: www.autohotkey.net/3D-Grabber/WttW.zip
(just unpack and place anywhere)
only tested on XP MCE so far...
no options dialog yet! edit WttW.ini directly
in the pipeline:
- options dialog
- prefetch photos, next button
- open in browser button (see photo on panoramio.com)
- open in google earth button (if installed)
- favorites
feedback and suggestions welcome!
greets
3D
| Code: |
#SingleInstance ignore
#Include %A_ScriptDir%\Include
#Include XPath.ahk
Menu, Tray, Icon, WttW.ico
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MainLoop:
ImageNo := DownloadRandomImage()
ConvertedImagePath := ConvertImage(ImageNo)
UpdateWallpaper(ConvertedImagePath)
DeletePastImages(ImageNo)
Sleep, GetOption("Interval") * 1000
Goto MainLoop
ExitApp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
UpdateWallpaper(ConvertedImagePath)
{
RegWrite, REG_SZ, HKEY_CURRENT_USER, Control Panel\Desktop, Wallpaper, %ConvertedImagePath%
Run, %A_WinDir%\System32\RUNDLL32.EXE user32.dll`,UpdatePerUserSystemParameters
Info := CreateInfoString(ImageNoFromFileName(ConvertedImagePath))
Info := RegExReplace(Info," - ","`n")
Menu, Tray, Tip, %Info%
}
DeletePastImages(ImageNo)
{
Loop, %A_ScriptDir%\Photos\*.*
{
Filename := RegExReplace(A_LoopFileName,"." A_LoopFileExt "$","")
if (Filename != ImageNo)
FileDelete, %A_LoopFileFullPath%
}
}
ConvertImage(ImageNo)
{
JpgFile := JpgFileOf(ImageNo)
BmpFile := BmpFileOf(ImageNo)
GetScreenDimensions(ScreenX, ScreenY, ScreenW, ScreenH)
GetTaskbarDimensions(TaskbarX, TaskbarY, TaskbarW, TaskbarH)
GetVisibleDesktopDimensions(DesktopX, DesktopY, DesktopW, DesktopH)
; ===================== create Background ====================
If (GetOption("NothingBehindTaskbar") = "true")
{
BgW := DesktopW
BgH := DesktopH
}
else
{
BgW := ScreenW
BgH := ScreenH
}
BackgroundCmd := "-size " BgW "x" BgH " xc:black "
; ===================== Resize =======================
ImgTargetW := ReadImageInfo(ImageNo,"ConvertedHorizontalResolution")
ImgTargetH := ReadImageInfo(ImageNo,"ConvertedVerticalResolution")
ResizeCmd := "( " JpgFile " -resize " ImgTargetW "x" ImgTargetH "! ) "
; ===================== compose resized img over bg =======================
ComposeBgImgCmd := "-gravity center -composite "
; ===================== overlay info string ======================
If(GetOption("ShowInfo") = "true")
{
InfoString := CreateInfoString(ImageNo)
InfoString := " " InfoString " " ; for box style
FileDelete, InfoString.txt
FileAppend, %InfoString%, InfoString.txt
InfoPosition := GetOption("InfoPosition")
InfoDist := GetOption("InfoBorderDistance")
dx := "+0"
dy := "+0"
if(InStr(InfoPosition,"South") || InStr(InfoPosition,"North"))
dy := "+" InfoDist
if(InStr(InfoPosition,"West") || InStr(InfoPosition,"East"))
dx := "+" InfoDist
InfoStyle := GetOption("InfoStyle")
if (InfoStyle = "Outline")
{
Outline := "-stroke #000000 -strokewidth 3 -annotate " dx dy " @InfoString.txt "
Stroke := "-stroke none -fill #FFFFFF -annotate " dx dy " @InfoString.txt "
InfoStyleCmd := Outline Stroke " "
}
else if (InfoStyle = "Box")
{
InfoStyleCmd := "-fill white -box #00000080 -annotate " dx dy " @InfoString.txt "
}
TextSize:=GetOption("InfoTextSize")
InfoStringCmd := "-encoding unicode -gravity " InfoPosition " -pointsize " TextSize " " InfoStyleCmd
}
else
InfoStringCmd := ""
; ===================== create Taskbar Background ====================
If (GetOption("NothingBehindTaskbar") = "true")
TBBGCmd := "( -size " ScreenW "x" ScreenH " xc:black ) +swap -gravity None -geometry +" DesktopX "+" DesktopY " -composite "
else
TBBGCmd := ""
; ===================== assemble command ====================
Command := A_ScriptDir "\ImageMagick\convert " BackgroundCmd ResizeCmd ComposeBgImgCmd InfoStringCmd TBBGCmd BmpFile
;MsgBox %Command%
; ===================== run command ====================
FileDelete, conv.cmd ; just to be sure
FileAppend, %Command%, conv.cmd
RunWait, conv.cmd ,,Hide
if (ErrorLevel)
return 0
; ===================== delete tmp files ====================
FileDelete, conv.cmd
FileDelete, InfoString.txt
return BmpFile
}
CreateInfoString(ImageNo)
{
InfoString := ""
If(GetOption("ShowInfoImageNo") = "true")
InfoString := InfoString "#" FormatInteger(ImageNo) " - "
If(GetOption("ShowInfoTitle") = "true" && !InStr(ReadImageInfo(ImageNo,"Title"),"untitled") && StrLen(ReadImageInfo(ImageNo,"Title")) > 0 )
InfoString := InfoString ReadImageInfo(ImageNo,"Title") " - "
If(GetOption("ShowInfoLocation") = "true" && StrLen(ReadImageInfo(ImageNo,"Location")) > 0)
InfoString := InfoString ReadImageInfo(ImageNo,"Location") " - "
If(GetOption("ShowInfoAuthor") = "true" && StrLen(ReadImageInfo(ImageNo,"Author")) > 0)
InfoString := InfoString "by " ReadImageInfo(ImageNo,"Author") " - "
If(GetOption("ShowInfoResolution") = "true")
InfoString := InfoString ReadImageInfo(ImageNo,"HorizontalResolution") "x" ReadImageInfo(ImageNo,"VerticalResolution") " - "
If(GetOption("ShowInfoLatLon") = "true")
{
lat := ReadImageInfo(ImageNo,"Latitude")
lon := ReadImageInfo(ImageNo,"Longitude")
latlonavailable := RegExMatch(lat, "\d") * RegExMatch(lon, "\d") ; test if lat/lon contain at least one digit
if (latlonavailable)
{
latlon := "lat " lat "° lon " lon "°"
InfoString := InfoString latlon " - "
}
}
If(GetOption("ShowInfoViews") = "true")
InfoString := InfoString "viewed " ReadImageInfo(ImageNo,"Views") "x - "
return RegExReplace(InfoString," - $","") ; cut final -
}
DownloadRandomImage()
{
NewestKnownImage := GetOption("NewestKnownImage")
NoOfConnectionAttempts := GetOption("NoOfConnectionAttempts")
MaxImageNo := NewestKnownImage*1.1
Attempt := 1
RetryAnotherOne:
Random, ImageNo, 1, %MaxImageNo%
ImageNo := Floor(ImageNo)
RetryToConnect:
ImgInfoResult := GetImageInfo(ImageNo, Title, Location, Author, ImgW, ImgH, Lat, Lon, Views)
;========================= connection ==========================
if (ImgInfoResult = "ErrFailedToConnect")
{
if (Attempt <= NoOfConnectionAttempts)
{
Attempt++
Goto RetryToConnect
}
Else
return 0
}
; ========================= handle not existing ==========================
if (ImgInfoResult = "ErrImageDoesNotExist") ; retry with another one
Goto RetryAnotherOne
; ========================== newest img discovered =====================
if (ImageNo > NewestKnownImage)
{
NewestKnownImage := ImageNo
SetOption("NewestKnownImage", NewestKnownImage)
}
; ======================== filter ================================
if (GetOption("OnlyGeoTagged") = "true" && StrLen(Lat)*StrLen(Lon) = 0 )
{
Discarded := GetOption("ImagesRefused"), Discarded++, SetOption("ImagesRefused", Discarded)
Goto RetryAnotherOne
}
; ======================== geometry constraints =====================
if (!CheckTransformationConstraints(ImgW, ImgH, ConvertedW, ConvertedH))
{
Discarded := GetOption("ImagesRefused"), Discarded++, SetOption("ImagesRefused", Discarded)
Goto RetryAnotherOne
}
; ====================== Download full size image =========================
ImagePath := JpgFileOf(ImageNo)
UrlDownloadToFile, http://www.panoramio.com/photos/original/%ImageNo%.jpg, %ImagePath%
if (ErrorLevel)
return 0
ImgRead := GetOption("ImagesAccepted"), ImgRead++, SetOption("ImagesAccepted", ImgRead)
; ====================== write image ini file ============================
WriteImageInfo(ImageNo, "Title" , Title)
WriteImageInfo(ImageNo, "Location" , Location)
WriteImageInfo(ImageNo, "Author" , Author)
WriteImageInfo(ImageNo, "HorizontalResolution" , ImgW)
WriteImageInfo(ImageNo, "VerticalResolution" , ImgH)
WriteImageInfo(ImageNo, "ConvertedHorizontalResolution" , ConvertedW)
WriteImageInfo(ImageNo, "ConvertedVerticalResolution" , ConvertedH)
WriteImageInfo(ImageNo, "Latitude" , Lat)
WriteImageInfo(ImageNo, "Longitude" , Lon)
WriteImageInfo(ImageNo, "Views" , Views)
return ImageNo
}
CheckTransformationConstraints(SourceW, SourceH, ByRef ConvertedW, ByRef ConvertedH)
{
;========================== min size constraints ============================
If(SourceW < GetOption("MinHorizontalSize") || SourceH < GetOption("MinVerticalSize"))
return 0
;========================== aspect ratio constraints ============================
GetScreenDimensions(ScreenX, ScreenY, ScreenW, ScreenH)
GetVisibleDesktopDimensions(DesktopX, DesktopY, DesktopW, DesktopH)
if (GetOption("NothingBehindTaskbar") = "true" )
{
TargetW := DesktopW
TargetH := DesktopH
}
else
{
TargetW := ScreenW
TargetH := ScreenH
}
SourceRatio := SourceW / SourceH
TargetRatio := TargetW / TargetH
MaxHorizontalStretch := RegExReplace(GetOption("MaxHorizontalStretch"),"\D","") / 100 ; remove % sign
MaxVerticalStretch := RegExReplace(GetOption("MaxVerticalStretch") ,"\D","") / 100
MaxHorizontalBlack := RegExReplace(GetOption("MaxHorizontalBlack") ,"\D","") / 100
MaxVerticalBlack := RegExReplace(GetOption("MaxVerticalBlack") ,"\D","") / 100
if (TargetRatio > SourceRatio)
{
x:= (1 + MaxHorizontalStretch)/(1 - MaxVerticalBlack)
;srx:=SourceRatio * x
;MsgBox TargetRatio %TargetRatio% > SourceRatio %SourceRatio% x= %x% SR * x = %srx%
if(SourceRatio * x >= TargetRatio)
{
ConvertedW := Floor( (TargetH / SourceH) * SourceW * (1 + MaxHorizontalStretch) ) ; stretch it to the max
if(ConvertedW > TargetW)
ConvertedW := TargetW
ConvertedH := TargetH
return 1
}
else
return 0
}
else
{
x:= (1 + MaxVerticalStretch)/(1 - MaxHorizontalBlack)
;srx:=SourceRatio / x
;MsgBox TargetRatio %TargetRatio% < SourceRatio %SourceRatio% x= %x% SR / x = %srx%
if(SourceRatio / x <= TargetRatio )
{
ConvertedW := TargetW
ConvertedH := Floor( (TargetW / SourceW) * SourceH *(1 + MaxVerticalStretch) ) ; stretch it to the max
if(ConvertedH > TargetH)
ConvertedH := TargetH
return 1
}
else
return 0
}
}
FormatInteger(_number)
{
local fn, fnl
fnl := StrLen(_number) * 2 ; More than enough...
VarSetCapacity(fn, fnl)
DllCall("GetNumberFormat", "UInt", 0x400, "UInt", 0, "Str", _number, "UInt", 0, "Str", fn, "Int", fnl)
StringTrimRight, trim ,fn, 3
Return trim
}
GetOption(name)
{
IniRead, ReturnVar, WttW.ini, Settings, %name%
return ReturnVar
}
SetOption(name,value)
{
IniWrite, %value%, WttW.ini, Settings, %name%
return ErrorLevel
}
ImageNoFromFileName(FileName)
{
RegExMatch(FileName,"(\d+).*?$",s)
ImageNo := s1
return ImageNo
}
IniFileOf(FileNameOrImageNo)
{
ImageNo := ImageNoFromFileName(FileNameOrImageNo)
IniFile := A_ScriptDir "\Photos\" ImageNo ".ini"
return IniFile
}
BmpFileOf(FileNameOrImageNo)
{
ImageNo := ImageNoFromFileName(FileNameOrImageNo)
BmpFile := A_ScriptDir "\Photos\" ImageNo ".bmp"
return BmpFile
}
JpgFileOf(FileNameOrImageNo)
{
ImageNo := ImageNoFromFileName(FileNameOrImageNo)
JpgFile := A_ScriptDir "\Photos\" ImageNo ".jpg"
return JpgFile
}
WriteImageInfo(ImageNoOrName, Field, Value)
{
IniFile := IniFileOf(ImageNoOrName)
IniWrite, %Value%, %IniFile%, Info, %Field%
return ErrorLevel
}
ReadImageInfo(ImageNoOrName, Field)
{
IniFile := IniFileOf(ImageNoOrName)
IniRead, Value, %IniFile%, Info, %Field%
return Value
}
GetScreenDimensions(ByRef ScreenX, ByRef ScreenY, ByRef ScreenW, ByRef ScreenH)
{
WinGetPos, ScreenX, ScreenY, ScreenW, ScreenH, Program Manager
}
GetTaskbarDimensions(ByRef TaskbarX, ByRef TaskbarY, ByRef TaskbarW, ByRef TaskbarH)
{
WinGetPos TaskbarX, TaskbarY, TaskbarW, TaskbarH, ahk_class Shell_TrayWnd
GetScreenDimensions(ScreenX, ScreenY, ScreenW, ScreenH)
; ======== 'crop' if taskbar bigger than screen (classic theme in xp) ====
if (TaskbarX < ScreenX)
TaskbarX := ScreenX
if (TaskbarY < ScreenY)
TaskbarY := ScreenY
if( TaskbarX + TaskbarW > ScreenX + ScreenW )
TaskbarW := ScreenX + ScreenW - TaskbarX
if( TaskbarY + TaskbarH > ScreenY + ScreenH )
TaskbarH := ScreenY + ScreenH - TaskbarY
; ========
}
GetVisibleDesktopDimensions(ByRef DesktopX, ByRef DesktopY, ByRef DesktopW, ByRef DesktopH)
{
; ========================= get screen and taskbar dims =======================
GetScreenDimensions(ScreenX, ScreenY, ScreenW, ScreenH)
GetTaskbarDimensions(TaskbarX, TaskbarY, TaskbarW, TaskbarH)
; ========================= defaults image size/dims =========================
DesktopX := ScreenX, DesktopY := ScreenY, DesktopW := ScreenW, DesktopH := ScreenH
; ========================= HORIZONTAL TASKBAR =========================
if(TaskbarW = ScreenW) ; taskbar has same width as desktop
{
DesktopH := ScreenH - TaskbarH
if( TaskbarY = ScreenY ) ;Top position
DesktopY := ScreenY + TaskbarH
}
; ========================= VERTICAL TASKBAR =========================
if( TaskbarH = ScreenH ) ; taskbar has same height as desktop
{
DesktopW := ScreenW - TaskbarW
if( TaskbarX = ScreenX )
DesktopX := ScreenX + TaskbarW ; left position
}
}
GetImageInfo(ImageNumber, ByRef Title, ByRef Location, ByRef Author,ByRef DimX, ByRef DimY, ByRef Lat, ByRef Lon, ByRef Views)
{
; =============== download preview doc ================
UrlDownloadToFile, http://www.panoramio.com/photo/%ImageNumber%, page.html
if (ErrorLevel)
return "ErrFailedToConnect"
; =============== read file =====================
FileRead, Page, page.html
xml := XmlDoc("page.html") ; load as XML document
; =============== check if image exists ==============
if(InStr(Page,"This photo does not exist"))
return "ErrImageDoesNotExist"
; =============== extract Title ================
tit := XPath(xml, "/html/body/div[1]/div[3]/div[1]/div[1]/img[1]/@title")
RegExMatch(tit,"'(.*)'",t)
Title := t1
Title := RegExReplace(Title,",",",")
; =============== extract Location ================
loc := XPath(xml, "/html/body/div[1]/div[3]/div[1]/div[1]/p/text()")
PosEndDescritpion:=InStr(loc,"<") - 4
Location := SubStr(loc,1,PosEndDescritpion)
Location := RegExReplace(Location,",",",")
; =============== extract Author ================
Author := XPath(xml, "/html/body/div[1]/div[3]/div[1]/div[1]/p[1]/a[1]/text()")
Author := RegExReplace(Author,",",",")
; =============== extract size ================
size := XPath(xml, "/html/body/div[1]/div[3]/div[1]/div[1]/p[1]/a[2]/@title")
RegExMatch(size,"(\d+) x (\d+)",s)
DimX := s1
DimY := s2
; =============== extract lat/lon ================
RegExMatch(Page,"abbr class='latitude' title='(.*?)'>",s) ; the ? after * makes the latter non-greedy
Lat := s1
RegExMatch(Page,"abbr class='longitude' title='(.*?)'>",s)
Lon := s1
; =============== extract Views ================
RegExMatch(Page,"Viewed (\d+) times",s)
Views := s1
; =============== delete tmp file ===============
FileDelete, page.html
return "OK"
}
|
|
|