AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Crazy Scripting : ScreenCaptureToPNG 25L

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
SKAN



Joined: 26 Dec 2005
Posts: 7159

PostPosted: Sat Aug 30, 2008 11:57 am    Post subject: Crazy Scripting : ScreenCaptureToPNG 25L Reply with quote

Code:
; ScreenCaptureToPNG 25L      Forum Topic : www.autohotkey.com/forum/viewtopic.php?t=35242
; Author:  SKAN - Suresh Kumar A N          Created : 30-Aug-2008 | Modified : 31-Aug-2008
; Credit:  Adapted from  www.autohotkey.com/forum/viewtopic.php?p=97591#97591  by XavierGr

 ~PrintScreen::
~!PrintScreen::
 If  % SaveClipboardImageAs( (BMPF:=A_Temp "\screen.bmp") )
     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)
    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 ; www.autohotkey.com/forum/viewtopic.php?p=190227#190227
 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)
}


Tested and works fine for me in XP-SP2 with 16bit and 32bit screen color quality.
Preview is shown with Windows Picture and Fax Viewer which is convenient and offers many options.

Smile

Edit:
Images not saved properly at 16bit color quality.. now fixed
Code has been compacted from 33 lines to 25 lines

_________________
Suresh Kumar A N


Last edited by SKAN on Mon Sep 01, 2008 11:05 am; edited 2 times in total
Back to top
View user's profile Send private message
Delusion



Joined: 16 Jul 2008
Posts: 117

PostPosted: Sat Aug 30, 2008 3:14 pm    Post subject: Reply with quote

Very Nice Very Happy
Is it possible making it so that it automatically saves the file somewhere though?
_________________
Movie Launcher
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7159

PostPosted: Sat Aug 30, 2008 11:47 pm    Post subject: Reply with quote

Thanks.

It already saves screen.bmp in Temp folder which you may alter per your requirement.

Smile
_________________
Suresh Kumar A N
Back to top
View user's profile Send private message
..:: Free Radical ::..



Joined: 20 Sep 2006
Posts: 47

PostPosted: Sun Aug 31, 2008 4:11 am    Post subject: Another way through DLL call and GDI+ Reply with quote

Here is another way.
Credit to Sean for posting this (Screen Capture with transparent windows)
http://www.autohotkey.com/forum/viewtopic.php?t=18146&start=0&postdays=0&postorder=asc


Adapted here with some modifications. Needs GDI+ helper.

The Function: Include this in your main script
Code:

; Screen Capture

CaptureScreen(aRect = 0, bCursor = False, sFile = "")
{
   If   !aRect
   {
      SysGet, Mon, Monitor, 1
      nL := MonLeft
      nT := MonTop
      nW := MonRight - MonLeft
      nH := MonBottom - MonTop
   }
   Else If   aRect = 1
      WinGetPos, nL, nT, nW, nH, A
   Else If   aRect = 2
   {
      WinGet, hWnd, ID, A
      VarSetCapacity(rt, 16, 0)
      DllCall("GetClientRect" , "Uint", hWnd, "Uint", &rt)
      DllCall("ClientToScreen", "Uint", hWnd, "Uint", &rt)
      nL := NumGet(rt, 0, "int")
      nT := NumGet(rt, 4, "int")
      nW := NumGet(rt, 8)
      nH := NumGet(rt,12)
   }
   Else If   aRect = 3
   {
      MouseGetPos, x1, y1
      Sleep, 5000
      MouseGetPos, x2, y2
      nL := x1
      nT := y1
      nW := x2 - x1
      nH := y2 - y1
   }
   Else
   {
      StringSplit, rt, aRect, `,, %A_Space%%A_Tab%
      nL := rt1
      nT := rt2
      nW := rt3 - rt1
      nH := rt4 - rt2
      znW := rt5
      znH := rt6
   }

   mDC := DllCall("CreateCompatibleDC", "Uint", 0)
   hBM := CreateDIBSection(mDC, nW, nH)
   oBM := DllCall("SelectObject", "Uint", mDC, "Uint", hBM)
   hDC := DllCall("GetDC", "Uint", 0)
   DllCall("BitBlt", "Uint", mDC, "int", 0, "int", 0, "int", nW, "int", nH, "Uint", hDC, "int", nL, "int", nT, "Uint", 0x40000000 | 0x00CC0020)
   DllCall("ReleaseDC", "Uint", 0, "Uint", hDC)
   If   bCursor
      CaptureCursor(mDC, nL, nT)
   DllCall("SelectObject", "Uint", mDC, "Uint", oBM)
   DllCall("DeleteDC", "Uint", mDC)
   If   znW && znH
      hBM := Zoomer(hBM, nW, nH, znW, znH)
   If   sFile = 0
      SetClipboardData(hBM)
   Else   Convert(hBM, sFile), DllCall("DeleteObject", "Uint", hBM)
}

CaptureCursor(hDC, nL, nT)
{
   VarSetCapacity(mi, 20, 0)
   mi := Chr(20)
   DllCall("GetCursorInfo", "Uint", &mi)
   bShow   := NumGet(mi, 4)
   hCursor := NumGet(mi, 8)
   xCursor := NumGet(mi,12)
   yCursor := NumGet(mi,16)

   VarSetCapacity(ni, 20, 0)
   DllCall("GetIconInfo", "Uint", hCursor, "Uint", &ni)
   xHotspot := NumGet(ni, 4)
   yHotspot := NumGet(ni, 8)
   hBMMask  := NumGet(ni,12)
   hBMColor := NumGet(ni,16)

   If   bShow
      DllCall("DrawIcon", "Uint", hDC, "int", xCursor - xHotspot - nL, "int", yCursor - yHotspot - nT, "Uint", hCursor)
   If   hBMMask
      DllCall("DeleteObject", "Uint", hBMMask)
   If   hBMColor
      DllCall("DeleteObject", "Uint", hBMColor)
}

Zoomer(hBM, nW, nH, znW, znH)
{
   mDC1 := DllCall("CreateCompatibleDC", "Uint", 0)
   mDC2 := DllCall("CreateCompatibleDC", "Uint", 0)
   zhBM := CreateDIBSection(mDC2, znW, znH)
   oBM1 := DllCall("SelectObject", "Uint", mDC1, "Uint",  hBM)
   oBM2 := DllCall("SelectObject", "Uint", mDC2, "Uint", zhBM)
   DllCall("SetStretchBltMode", "Uint", mDC2, "int", 4)
   DllCall("StretchBlt", "Uint", mDC2, "int", 0, "int", 0, "int", znW, "int", znH, "Uint", mDC1, "int", 0, "int", 0, "int", nW, "int", nH, "Uint", 0x00CC0020)
   DllCall("SelectObject", "Uint", mDC1, "Uint", oBM1)
   DllCall("SelectObject", "Uint", mDC2, "Uint", oBM2)
   DllCall("DeleteDC", "Uint", mDC1)
   DllCall("DeleteDC", "Uint", mDC2)
   DllCall("DeleteObject", "Uint", hBM)
   Return   zhBM
}

Convert(sFileFr = "", sFileTo = "")
{
   If   sFileTo  =
      sFileTo := A_ScriptDir . "\screen.bmp"
   SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

   If Not   hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
      Return   sFileFr+0 ? SaveHBITMAPToFile(sFileFr, sDirTo . "\" . sNameTo . ".bmp") : ""
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

   If   !sFileFr
   {
      DllCall("OpenClipboard", "Uint", 0)
      If    DllCall("IsClipboardFormatAvailable", "Uint", 2) && (hBM:=DllCall("GetClipboardData", "Uint", 2))
      DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0, "UintP", pImage)
      DllCall("CloseClipboard")
   }
   Else If   sFileFr Is Integer
      DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0, "UintP", pImage)
   Else   DllCall("gdiplus\GdipLoadImageFromFile", "Uint", Unicode4Ansi(wFileFr,sFileFr), "UintP", pImage)

   DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
   VarSetCapacity(ci, nSize)
   DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
   Loop,   %nCount%
   {
      If   !InStr(Ansi4Unicode(NumGet(ci, 76 * (A_Index - 1) + 44)), "." . sExtTo)
         Continue
      pCodec := &ci + 76 * (A_Index - 1)
         Break
   }

   If   pImage
      pCodec   ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage, "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec, "Uint", 0) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pImage, "UintP", hBitmap, "Uint", 0) . SetClipboardData(hBitmap), DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

   DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
   DllCall("FreeLibrary", "Uint", hGdiPlus)
}

CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
{
   NumPut(VarSetCapacity(bi, 40, 0), bi)
   NumPut(nW, bi, 4)
   NumPut(nH, bi, 8)
   NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
   NumPut(0,  bi,16)
   Return   DllCall("gdi32\CreateDIBSection", "Uint", hDC, "Uint", &bi, "Uint", 0, "UintP", pBits, "Uint", 0, "Uint", 0)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hFile:=   DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0, "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16, "Uint", 6, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint", 8, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
   DllCall("CloseHandle", "Uint", hFile)
}

SetClipboardData(hBitmap)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hDIB :=   DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
   pDIB :=   DllCall("GlobalLock", "Uint", hDIB)
   DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
   DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
   DllCall("GlobalUnlock", "Uint", hDIB)
   DllCall("DeleteObject", "Uint", hBitmap)
   DllCall("OpenClipboard", "Uint", 0)
   DllCall("EmptyClipboard")
   DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
   DllCall("CloseClipboard")
}

Unicode4Ansi(ByRef wString, sString)
{
   nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2)
   DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize)
   Return   &wString
}

Ansi4Unicode(pString)
{
   nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
   VarSetCapacity(sString, nSize)
   DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
   Return   sString
}


Set your hotkeys to execute these labels
Code:

CAPTURE:
 Name=%A_Now%
 CaptureScreen(0,0,"Screen.PNG")
 FileMove, Screen.PNG,E:\My Documents\My Pictures\Screenshots\%Name%.PNG
Return

CAPTURE2:
 CoordMode, Mouse, Screen
 CaptureScreen(3,0,"Screen.PNG")
 Name=%A_Now%
 FileMove, Screen.PNG,E:\My Documents\My Pictures\Screenshots\%Name%.PNG
 CoordMode, Mouse, Relative
Return


The first Capture mode is full screen capture.

In the second Capture mode, the screenshot will be between two coordinates which define top-left and bottom -right. Trigger the hotkey with the mouse at the top left position of the area you want to capture and move the mouse within 5 seconds to the bottom right of the area you want to capture.

Simply replace .PNG with .JPG or .BMP in the labels if you want that format and the function will capture to that format (sent as the sFile value).

You can easily adapt this to capture windows instead by changing the aRect value or whether you want the mouse to be captured or not through the bCursor value.

The name of each screenshot is the time of capture

The jpeg capture quality can be changed.

Refer to the discussion thread for details (link posted above)
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7159

PostPosted: Sun Aug 31, 2008 3:38 pm    Post subject: Reply with quote

Update:
Image was not saved properly at 16bit color quality.. now bug fixed
Also, Code has been optimised/compacted from 33 lines to 25 lines

Smile
_________________
Suresh Kumar A N
Back to top
View user's profile Send private message
ArchCarrier



Joined: 03 Jun 2008
Posts: 20

PostPosted: Wed Sep 03, 2008 11:00 am    Post subject: Reply with quote

If you think that last one is still 24 lines too big and you have IrfanView installed, you might like the one I always use:

Code:
^PrintScreen::Run, "%A_ProgramFiles%\IrfanView\i_view32.exe" /capture=1 /convert=c:\PATH_TO\screenshot_$U(`%Y-`%m-`%d_`%H`%M`%S).png


Pressing ctrl+PrintScreen will save a PNG file of the active window. Use /capture=0 or /capture=2 for saving other parts of the screen (I believe 0=fullscreen, 2=inside active window, but I might be wrong).
Back to top
View user's profile Send private message
BoBo²
Guest





PostPosted: Wed Sep 03, 2008 4:17 pm    Post subject: Reply with quote

I like it! Very Happy - have you thought about it to implement a thumbnail option (even nicer/harder, using a ratio parameter like "shrink image to 33% of its original scale"). Shocked Wink

Currently I've to use [Quick Thumbnail], and would be more than happy to get a local AHK! option as well. Cool
Back to top
SKAN



Joined: 26 Dec 2005
Posts: 7159

PostPosted: Wed Sep 03, 2008 7:50 pm    Post subject: Reply with quote

BoBo² wrote:
I like it! Very Happy


Thanks BoBo Very Happy

Quote:
have you thought about it to implement a thumbnail option


Honestly, no... but yes! It is a good idea, but I am not interested in using GDI+ since these kind of short kode are being added to my always- running-script

Let me see if I can produce something creative Rolling Eyes

Edit: Thanks for the link Surprised
_________________
Suresh Kumar A N
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7159

PostPosted: Thu Sep 04, 2008 12:16 pm    Post subject: Reply with quote

BoBo, Smile

Try this: http://www.autohotkey.net/~goyyah/CrazyScripts/ScreenCaptureToPNG/SCTP-Ext1.ahk

After a screen shot / when in preview mode ( Windows Picture and Fax Viewer ),
Keep pressing R to Reduce Screen.bmp to 75% of the current size,
and once done, press C to Create Thumb.jpg

Not an elegant method, but it was fun doing it. Smile
_________________
Suresh Kumar A N
Back to top
View user's profile Send private message
BoBo²
Guest





PostPosted: Thu Sep 04, 2008 1:29 pm    Post subject: Reply with quote

Thx a mill SKAN Very Happy

[Brainfart]
FYI. My current project: create a 'snapshoot-bundle'.
Capture a snapshoot and its thumbnail in one go.
Eg to save the original snapshoot first (I could live without showing it in the viewer), and create its assigned thumbnail, using a (variable but) preset aspect ratio, afterwards from that saved image.
[/Brainfart]
Back to top
tic



Joined: 22 Apr 2007
Posts: 1424

PostPosted: Sat Sep 06, 2008 8:32 pm    Post subject: Reply with quote

I think if you take a look youll find that the gdi+ library is much more flexible and powerful. This took a few minutes to write as a very simple example:

Code:
#SingleInstance, Force
SetBatchLines, -1

#Include, Gdip.ahk

Size := 0.8
FileType = png
Font = Arial

If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
OnExit, Exit

Hotkey, ^PrintScreen, SaveScreen, On
Return

;####################################################################################

SaveScreen:
pBitmap := Gdip_BitmapFromScreen()
Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap)
PBitmapResized := Gdip_CreateBitmap(Round(Width*Size), Round(Height*Size)), G := Gdip_GraphicsFromImage(pBitmapResized)
Gdip_DrawImage(G, pBitmap, 0, 0, Round(Width*Size), Round(Height*Size), 0, 0, Width, Height)
Gdip_TextToGraphics(G, A_Hour ":" A_Min ":" A_Sec "  " A_DD "/" A_MM "/" A_YYYY, "x0 y0 r4 cff000000 s5p", Font, Round(Width*Size), Round(Height*Size))
Gdip_SaveBitmapToFile(PBitmapResized, A_Now "." FileType)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmapResized)
Gdip_DisposeImage(pBitmap)
Return

;####################################################################################

Exit:
Gdip_Shutdown(pToken)
ExitApp
Return


The above code will take a screenshot with ctrl+printscreen and save the file as the chosen filetype in the current folder with the time and date written on the screenshot, and will resize it to the currently chosen fraction of the original size ( 0.8 )
Back to top
View user's profile Send private message
BoBo²
Guest





PostPosted: Sun Sep 07, 2008 12:09 am    Post subject: Reply with quote

Thx tic,
what are the changes to get the active window (ALT+PrintScreen) instead of the whole screen (which I've got after testing your script)?
Back to top
tic



Joined: 22 Apr 2007
Posts: 1424

PostPosted: Sun Sep 07, 2008 12:30 am    Post subject: Reply with quote

BoBo² wrote:
Thx tic,
what are the changes to get the active window (ALT+PrintScreen) instead of the whole screen (which I've got after testing your script)?


Heh, I'm still up Smile

I know I havent documented it Confused but check out the line:

Code:
pBitmap := Gdip_BitmapFromScreen()


That gets a gdi+ bitmap of the screen. passing 0 to it will get a bitmap of all available screens. passing a number will get a bitmap of that specific screen, and passing x|y|w|h will get a bitmap of that specific area

So you could do:

Code:
WinGetPos, X, Y, W, H, A
pBitmap := Gdip_BitmapFromScreen(X "|" Y "|" W "|" H)


But sorry to jack your thread SKAN! If you want to ask any more BoBo² then ask on the gdi+ Smile
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7159

PostPosted: Sun Sep 07, 2008 7:24 am    Post subject: Reply with quote

tic wrote:
But sorry to jack your thread SKAN!


Not at all, it is much related to the topic. Smile
_________________
Suresh Kumar A N
Back to top
View user's profile Send private message
BoBo²
Guest





PostPosted: Sun Sep 07, 2008 10:16 am    Post subject: Reply with quote

Thanks, SKAN + tic
mission accomplished. Very Happy
I'll drop a cross reference post at the gdi+ thread.
Thx for your effort.
Cool
Back to top
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group