How to save image in clipboard.

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
LogicNg
Posts: 20
Joined: 17 Mar 2021, 05:39

How to save image in clipboard.

02 Sep 2021, 01:19

Let say you have an image in your clipboard, how do you save it into PNG?
User avatar
boiler
Posts: 17121
Joined: 21 Dec 2014, 02:44

Re: How to save image in clipboard.

02 Sep 2021, 01:55

See @SKAN’s ScreenCaptureToPNG in this thread (note there are some forum color tags that need to be removed). I don’t know if he has updated it since then.
LogicNg
Posts: 20
Joined: 17 Mar 2021, 05:39

Re: How to save image in clipboard.

03 Sep 2021, 05:22

Code: Select all

 ^+a::
	msgbox, yo
	If  % SaveClipboardImageAs(BMPF:=A_Temp "\screen.bmp")
		msgbox, hi
	     If % ConvertGraphicsFile(BMPF, (OUTF:=A_Temp "\screen.png"))
	        Runwait, Rundll32.exe %A_Windir%\system32\shimgvw.dll`,ImageView_Fullscreen %OUTF%
	Return
	 
	SaveClipboardImageAs(tImg="") {
	 If ! DllCall("IsClipboardFormatAvailable",UInt,2)
	 	msgbox, failed
	    Return 0
	 $:=ClipboardAll
	 NumPut(0x4D42,$,2), D:=NumGet($,36), NumPut(66+D,$,4), NumPut(0,$,8), NumPut(66,$,12)
	 If ( (Z:=DllCall("_lcreat",Str,tImg,UInt,0)) = -1
	 || DllCall("_lwrite",UInt,Z,UInt,&$+2,UInt,66+D) = -1 || DllCall("_lclose",UInt,Z) = -1 )
	   Return 0
	 Return 1   
	}

	ConvertGraphicsFile(Src, Trg, Ov=1) {
	 Static shlwapi,ShConvertGraphics
	 If ( D="" )
	  D:=DllCall("LoadLibrary",Str,"shlwapi.dll"),CG:=DllCall("GetProcAddress",UInt,D,Int,488)
	 VarSetCapacity(uSrc,(sSz:=StrLen(Src)*2+1)), DllCall("MultiByteToWideChar",Int,0,Int,0
	  ,Str,Src,Int,-1,Str,uSrc,Int,sSz ), VarSetCapacity(uTrg,(tSz:=StrLen(Trg)*2+1))
	 DllCall("MultiByteToWideChar",Int,0,Int,0,Str,Trg,Int,-1,Str,uTrg,Int,tSz)
	Return ! DllCall(CG,Str,uSrc,Str,uTrg,UInt,Ov)
	}
return
I end up with this, but it isn't useable.
Last edited by LogicNg on 03 Sep 2021, 05:49, edited 1 time in total.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: How to save image in clipboard.

03 Sep 2021, 05:43

its runnable once u delete all broken old forum tags from it
LogicNg
Posts: 20
Joined: 17 Mar 2021, 05:39

Re: How to save image in clipboard.

03 Sep 2021, 05:51

It fails at

Code: Select all

If ! DllCall("IsClipboardFormatAvailable",UInt,2)
User avatar
boiler
Posts: 17121
Joined: 21 Dec 2014, 02:44

Re: How to save image in clipboard.

03 Sep 2021, 07:57

I'm not getting it to produce an image either. Some things may have changed with Windows or something since this worked.

By the way, the way you edited it, it would have no chance of working as the function will always return 0 and not continue even if the image conversion worked. You can't just insert a MsgBox after an "if" statement and not mess things up. You made the "return 0" statement unconditional by doing that. Your "MsgBox hi" statement similarly makes the "if" statement that follows it execute unconditionally.
teadrinker
Posts: 4354
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to save image in clipboard.

03 Sep 2021, 08:39

Anyway, using outdated code is not the best choice. As an option:

Code: Select all

destPngFilePath := A_ScriptDir . "\ClipboardImage.png"
hBitmap := GetBitmapFromClipboard()
HBitmapToPng(hBitmap, destPngFilePath)
DllCall("DeleteObject", "Ptr", hBitmap)
Return

GetBitmapFromClipboard() {
   if !DllCall("IsClipboardFormatAvailable", "UInt", CF_BITMAP := 2)
      throw "There is no image in the Clipboard"
   if !DllCall("OpenClipboard", "Ptr", 0)
      throw "OpenClipboard failed"
   hBitmap := DllCall("GetClipboardData", "UInt", CF_BITMAP)
   DllCall("CloseClipboard")
   if !hBitmap
      throw "GetClipboardData failed"
   Return hBitmap
}

HBitmapToPng(hBitmap, destPngFilePath) {
   static CLSID_WICImagingFactory  := "{CACAF262-9370-4615-A13B-9F5539DA4C0A}"
         , IID_IWICImagingFactory  := "{EC5EC8A9-C395-4314-9C77-54D7A935FF70}"
         , GUID_ContainerFormatPng := "{1B7CFAF4-713F-473C-BBCD-6137425FAEAF}"
         , WICBitmapUseAlpha := 0x00000000, GENERIC_WRITE := 0x40000000
         , WICBitmapEncoderNoCache := 0x00000002
         
   VarSetCapacity(GUID, 16, 0)
   DllCall("Ole32\CLSIDFromString", "WStr", GUID_ContainerFormatPng, "Ptr", &GUID)
   IWICImagingFactory := ComObjCreate(CLSID_WICImagingFactory, IID_IWICImagingFactory)
   Vtable( IWICImagingFactory    , CreateBitmapFromHBITMAP := 21 ).Call("Ptr", hBitmap, "Ptr", 0, "UInt", WICBitmapUseAlpha, "PtrP", IWICBitmap)
   Vtable( IWICImagingFactory    , CreateStream            := 14 ).Call("PtrP", IWICStream)
   Vtable( IWICStream            , InitializeFromFilename  := 15 ).Call("WStr", destPngFilePath, "UInt", GENERIC_WRITE)
   Vtable( IWICImagingFactory    , CreateEncoder           :=  8 ).Call("Ptr", &GUID, "Ptr", 0, "PtrP", IWICBitmapEncoder)
   Vtable( IWICBitmapEncoder     , Initialize              :=  3 ).Call("Ptr", IWICStream, "UInt", WICBitmapEncoderNoCache)
   Vtable( IWICBitmapEncoder     , CreateNewFrame          := 10 ).Call("PtrP", IWICBitmapFrameEncode, "Ptr", 0)
   Vtable( IWICBitmapFrameEncode , Initialize              :=  3 ).Call("Ptr", 0)
   Vtable( IWICBitmapFrameEncode , WriteSource             := 11 ).Call("Ptr", IWICBitmap, "Ptr", 0)
   Vtable( IWICBitmapFrameEncode , Commit                  := 12 ).Call()
   Vtable( IWICBitmapEncoder     , Commit                  := 11 ).Call()
   for k, v in [IWICBitmapFrameEncode, IWICBitmapEncoder, IWICStream, IWICBitmap, IWICImagingFactory]
      ObjRelease(v)
}

Vtable(ptr, n) {
   return Func("DllCall").Bind(NumGet(NumGet(ptr+0), A_PtrSize*n), "Ptr", ptr)
}
LogicNg
Posts: 20
Joined: 17 Mar 2021, 05:39

Re: How to save image in clipboard.

03 Sep 2021, 09:54

@boiler Use too much Python :)

@teadrinker Your code works! Thank you all for your help!
LogicNg
Posts: 20
Joined: 17 Mar 2021, 05:39

Re: How to save image in clipboard.

03 Sep 2021, 10:17

For latecomers, if you want to use the current date and time as filename, try this

Code: Select all

destPngFilePath := A_ScriptDir . "\" . A_Now . ".png"
LogicNg
Posts: 20
Joined: 17 Mar 2021, 05:39

Re: How to save image in clipboard.

03 Sep 2021, 20:47

One issue though, normally when you copy an image from MSPaint you can paste it anywhere. When I use @teadrinker's code to save an image copied from MSPaint, it saves a completely white image with exactly the same size as the one I copied, is there a way to fix it?
LogicNg
Posts: 20
Joined: 17 Mar 2021, 05:39

Re: How to save image in clipboard.

04 Sep 2021, 05:28

You are damn amazing, with some minor changes I get it working!

Code: Select all

#NoEnv                                                          ; Screen capture demo for SavePicture()
#SingleInstance, Force                
; Hotkey,  PrintScreen, Fullscreen
; Hotkey, !PrintScreen, ActiveWindow

Return  ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - -    //    end of auto-execute section 

^+a::

  Critical, On
  hBM := 0
  HotKey, %A_ThisHotKey%, Off
  ; OldClipboard := ClipboardAll
  ; Clipboard := ""
  ; SendInput, % (A_ThisLabel="ActiveWindow" ? "!" : "") . "{PrintScreen}"
  ; ClipWait, 1, 1
  hBM := CB_hBMP_Get()  
  ; If (OldClipboard)
  ;   {
  ;       Clipboard := OldClipboard
  ;   }
  Critical, Off

  If ( hBM )
    {
       sFile := A_ScriptDir "\\" A_Now ".png"
       GDIP("Startup")
       SavePicture(hBM, sFile) 
       GDIP("Shutdown")
       DllCall( "DeleteObject", "Ptr",hBM )
       If FileExist(sFile)
        {
          SoundBeep
          Run %sFile%
        }     
    }       
  HotKey, %A_ThisHotKey%, On
Return

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

CB_hBMP_Get() {                                                      ; By SKAN on D297 @ bit.ly/2L81pmP
Local OK := [0,0,0,0]
	OK.1 := DllCall( "OpenClipboard", "Ptr",0 )
  OK.2 := OK.1 ? DllCall( "IsClipboardFormatAvailable", "UInt",8 ) : 0  ; CF_BITMAP
  OK.3 := OK.2 ? DllCall( "GetClipboardData", "UInt", 2, "Ptr" )   : 0
  OK.4 := OK.1 ? DllCall( "CloseClipboard" ) : 0  
Return OK.3 ? DllCall( "CopyImage", "Ptr",OK.3, "Int",0, "Int",0, "Int",0, "UInt",0x200C, "Ptr" )
          + ( ErrorLevel := 0 ) : ( ErrorLevel := !OK.2 ? 1 : 2 ) >> 2          
}

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

SavePicture(hBM, sFile) {                                            ; By SKAN on D293 @ bit.ly/2L81pmP 
Local V,  pBM := VarSetCapacity(V,16,0)>>8,  Ext := LTrim(SubStr(sFile,-3),"."),  E := [0,0,0,0]
Local Enc := 0x557CF400 | Round({"bmp":0, "jpg":1,"jpeg":1,"gif":2,"tif":5,"tiff":5,"png":6}[Ext])
  E[1] := DllCall("gdi32\GetObjectType", "Ptr",hBM ) <> 7
  E[2] := E[1] ? 0 : DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr",hBM, "UInt",0, "PtrP",pBM)
  NumPut(0x2EF31EF8,NumPut(0x0000739A,NumPut(0x11D31A04,NumPut(Enc+0,V,"UInt"),"UInt"),"UInt"),"UInt")
  E[3] := pBM ? DllCall("gdiplus\GdipSaveImageToFile", "Ptr",pBM, "WStr",sFile, "Ptr",&V, "UInt",0) : 1
  E[4] := pBM ? DllCall("gdiplus\GdipDisposeImage", "Ptr",pBM) : 1
Return E[1] ? 0 : E[2] ? -1 : E[3] ? -2 : E[4] ? -3 : 1  
} 

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

GDIP(C:="Startup") {                                                 ; By SKAN on D293 @ bit.ly/2L81pmP
  Static SI:=Chr(!(VarSetCapacity(Si,24,0)>>16)), pToken:=0, hMod:=0, Res:=0, AOK:=0
  If (AOK := (C="Startup" and pToken=0) Or (C<>"Startup" and pToken<>0))  {
      If (C="Startup") {
               hMod := DllCall("LoadLibrary", "Str","gdiplus.dll", "Ptr")
               Res  := DllCall("gdiplus\GdiplusStartup", "PtrP",pToken, "Ptr",&SI, "UInt",0)
      } Else { 
               Res  := DllCall("gdiplus\GdiplusShutdown", "Ptr",pToken )
               DllCall("FreeLibrary", "Ptr",hMod),   hMod:=0,   pToken:=0
   }}  
Return (AOK ? !Res : Res:=0)    
}

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

teadrinker
Posts: 4354
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to save image in clipboard.

04 Sep 2021, 06:27

This variant does not save transparency.
teadrinker
Posts: 4354
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to save image in clipboard.

04 Sep 2021, 06:30

Code: Select all

destPngFilePath := A_ScriptDir . "\ClipboardImage.png"
hBitmap := GetBitmapFromClipboard()
HBitmapToPng(hBitmap, destPngFilePath)
DllCall("DeleteObject", "Ptr", hBitmap)
Return

GetBitmapFromClipboard() {
   static CF_BITMAP := 2, CF_DIB := 8, SRCCOPY := 0x00CC0020
   if !DllCall("IsClipboardFormatAvailable", "UInt", CF_BITMAP)
      throw "There is no image in the Clipboard"
   if !DllCall("OpenClipboard", "Ptr", 0)
      throw "OpenClipboard failed"
   hDIB := DllCall("GetClipboardData", "UInt", CF_DIB, "Ptr")
   hBM  := DllCall("GetClipboardData", "UInt", CF_BITMAP, "Ptr")
   DllCall("CloseClipboard")
   if !hDIB
      throw "GetClipboardData failed"
   pDIB := DllCall("GlobalLock", "Ptr", hDIB, "Ptr")
   width  := NumGet(pDIB +  4, "UInt")
   height := NumGet(pDIB +  8, "UInt")
   bpp    := NumGet(pDIB + 14, "UShort")
   DllCall("GlobalUnlock", "Ptr", pDIB)
   
   hDC := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
   oBM := DllCall("SelectObject", "Ptr", hDC, "Ptr", hBM, "Ptr")
   
   hMDC := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
   hNewBM := CreateDIBSection(width, -height,, bpp)
   oPrevBM := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hNewBM, "Ptr")
   DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", width, "Int", height
                   , "Ptr", hDC , "Int", 0, "Int", 0, "UInt", SRCCOPY)
   DllCall("SelectObject", "Ptr", hDC, "Ptr", oBM, "Ptr")
   DllCall("DeleteDC", "Ptr", hDC), DllCall("DeleteObject", "Ptr", hBM)
   DllCall("SelectObject", "Ptr", hMDC, "Ptr", oPrevBM, "Ptr")
   DllCall("DeleteDC", "Ptr", hMDC)
   Return hNewBM
}

CreateDIBSection(w, h, ByRef ppvBits := 0, bpp := 32) {
   hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
   VarSetCapacity(BITMAPINFO, 40, 0)
   NumPut(40 , BITMAPINFO,  0)
   NumPut( w , BITMAPINFO,  4)
   NumPut( h , BITMAPINFO,  8)
   NumPut( 1 , BITMAPINFO, 12)
   NumPut(bpp, BITMAPINFO, 14)
   hBM := DllCall("CreateDIBSection", "Ptr", hDC, "Ptr", &BITMAPINFO, "UInt", 0
                                    , "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
   DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
   return hBM
}

HBitmapToPng(hBitmap, destPngFilePath) {
   static CLSID_WICImagingFactory  := "{CACAF262-9370-4615-A13B-9F5539DA4C0A}"
         , IID_IWICImagingFactory  := "{EC5EC8A9-C395-4314-9C77-54D7A935FF70}"
         , GUID_ContainerFormatPng := "{1B7CFAF4-713F-473C-BBCD-6137425FAEAF}"
         , WICBitmapUseAlpha := 0x00000000, GENERIC_WRITE := 0x40000000
         , WICBitmapEncoderNoCache := 0x00000002
         
   VarSetCapacity(GUID, 16, 0)
   DllCall("Ole32\CLSIDFromString", "WStr", GUID_ContainerFormatPng, "Ptr", &GUID)
   IWICImagingFactory := ComObjCreate(CLSID_WICImagingFactory, IID_IWICImagingFactory)
   Vtable( IWICImagingFactory    , CreateBitmapFromHBITMAP := 21 ).Call("Ptr", hBitmap, "Ptr", 0, "UInt", WICBitmapUseAlpha, "PtrP", IWICBitmap)
   Vtable( IWICImagingFactory    , CreateStream            := 14 ).Call("PtrP", IWICStream)
   Vtable( IWICStream            , InitializeFromFilename  := 15 ).Call("WStr", destPngFilePath, "UInt", GENERIC_WRITE)
   Vtable( IWICImagingFactory    , CreateEncoder           :=  8 ).Call("Ptr", &GUID, "Ptr", 0, "PtrP", IWICBitmapEncoder)
   Vtable( IWICBitmapEncoder     , Initialize              :=  3 ).Call("Ptr", IWICStream, "UInt", WICBitmapEncoderNoCache)
   Vtable( IWICBitmapEncoder     , CreateNewFrame          := 10 ).Call("PtrP", IWICBitmapFrameEncode, "Ptr", 0)
   Vtable( IWICBitmapFrameEncode , Initialize              :=  3 ).Call("Ptr", 0)
   Vtable( IWICBitmapFrameEncode , WriteSource             := 11 ).Call("Ptr", IWICBitmap, "Ptr", 0)
   Vtable( IWICBitmapFrameEncode , Commit                  := 12 ).Call()
   Vtable( IWICBitmapEncoder     , Commit                  := 11 ).Call()
   for k, v in [IWICBitmapFrameEncode, IWICBitmapEncoder, IWICStream, IWICBitmap, IWICImagingFactory]
      ObjRelease(v)
}

Vtable(ptr, n) {
   return Func("DllCall").Bind(NumGet(NumGet(ptr+0), A_PtrSize*n), "Ptr", ptr)
}
Last edited by teadrinker on 10 Feb 2022, 04:24, edited 1 time in total.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: How to save image in clipboard.

04 Sep 2021, 07:07

You can save hbitmap with transparency without wic.
viewtopic.php?t=63345
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: How to save image in clipboard.

04 Sep 2021, 07:48

After my testings with wic may be up to 4 times slower.
teadrinker
Posts: 4354
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to save image in clipboard.

04 Sep 2021, 09:49

Have you tested my code as it is? If performance matters, it must be transformed to DllCall(NumGet(NumGet ....
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: How to save image in clipboard.

04 Sep 2021, 10:13

I tested as it is.
But I do not see reasons to use wic for such tasks.
Also, what do You mean by saving transparency?
For example Your last code does not save transparency if I copy picture with transparent background from photoshop.
teadrinker
Posts: 4354
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to save image in clipboard.

05 Sep 2021, 12:10

malcev wrote: I tested as it is.
Your test was incorrect. Try this one:

Code: Select all

HBitmapToPng(hBitmap, destPngFilePath) {
   static CLSID_WICImagingFactory  := "{CACAF262-9370-4615-A13B-9F5539DA4C0A}"
         , IID_IWICImagingFactory  := "{EC5EC8A9-C395-4314-9C77-54D7A935FF70}"
         , GUID_ContainerFormatPng := "{1B7CFAF4-713F-473C-BBCD-6137425FAEAF}"
         , WICBitmapUseAlpha := 0x00000000, GENERIC_WRITE := 0x40000000
         , WICBitmapEncoderNoCache := 0x00000002
         
   VarSetCapacity(GUID, 16, 0)
   DllCall("Ole32\CLSIDFromString", "WStr", GUID_ContainerFormatPng, "Ptr", &GUID)
   IWICImagingFactory := ComObjCreate(CLSID_WICImagingFactory, IID_IWICImagingFactory)
   ; IWICImagingFactory::CreateBitmapFromHBITMAP
   DllCall(NumGet(NumGet(IWICImagingFactory + 0) + A_PtrSize*21), "Ptr", IWICImagingFactory, "Ptr", hBitmap, "Ptr", 0, "UInt", WICBitmapUseAlpha, "PtrP", IWICBitmap)
   ; IWICImagingFactory::CreateStream
   DllCall(NumGet(NumGet(IWICImagingFactory + 0) + A_PtrSize*14), "Ptr", IWICImagingFactory, "PtrP", IWICStream)
   ; IWICStream::InitializeFromFilename
   DllCall(NumGet(NumGet(IWICStream + 0) + A_PtrSize*15), "Ptr", IWICStream, "WStr", destPngFilePath, "UInt", GENERIC_WRITE)
   ; IWICImagingFactory::CreateEncoder
   DllCall(NumGet(NumGet(IWICImagingFactory + 0) + A_PtrSize*8), "Ptr", IWICImagingFactory, "Ptr", &GUID, "Ptr", 0, "PtrP", IWICBitmapEncoder)
   ; IWICBitmapEncoder::Initialize
   DllCall(NumGet(NumGet(IWICBitmapEncoder + 0) + A_PtrSize*3), "Ptr", IWICBitmapEncoder, "Ptr", IWICStream, "UInt", WICBitmapEncoderNoCache)
   ; IWICBitmapEncoder::CreateNewFrame
   DllCall(NumGet(NumGet(IWICBitmapEncoder + 0) + A_PtrSize*10), "Ptr", IWICBitmapEncoder, "PtrP", IWICBitmapFrameEncode, "Ptr", 0)
   ; IWICBitmapFrameEncode::Initialize
   DllCall(NumGet(NumGet(IWICBitmapFrameEncode + 0) + A_PtrSize*3), "Ptr", IWICBitmapFrameEncode, "Ptr", 0)
   ; IWICBitmapFrameEncode::WriteSource
   DllCall(NumGet(NumGet(IWICBitmapFrameEncode + 0) + A_PtrSize*11), "Ptr", IWICBitmapFrameEncode, "Ptr", IWICBitmap, "Ptr", 0)
   ; IWICBitmapFrameEncode::Commit
   DllCall(NumGet(NumGet(IWICBitmapFrameEncode + 0) + A_PtrSize*12), "Ptr", IWICBitmapFrameEncode)
   ; IWICBitmapEncoder::Commit
   DllCall(NumGet(NumGet(IWICBitmapEncoder + 0) + A_PtrSize*11), "Ptr", IWICBitmapEncoder)
   for k, v in [IWICBitmapFrameEncode, IWICBitmapEncoder, IWICStream, IWICBitmap, IWICImagingFactory]
      ObjRelease(v)
}
For me WIC works faster.
malcev wrote: But I do not see reasons to use wic for such tasks.
The code works, that's enough. In addition, as I said, WIC works faster, and the size of the resulting file is much smaller. Moreover, this simple and demonstrative example (I mean the previose variant) gives you a possibility to start learninig WIC sintax to use it for more complex tasks.
malcev wrote: Also, what do You mean by saving transparency?
This is a really odd question! :) Try right clicking on the image at the top of this page (AHK AutoHotkey Automation. Hotkeys. Scripting.) and choose «copy image». Then launch my script.
malcev wrote: For example Your last code does not save transparency if I copy picture with transparent background from photoshop.
Can you provide the code to do it? I failed to paste an image copied from PS to Word saving transparency.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Chunjee and 109 guests