There are 2 ways to solve this task, actually. 1st way is a bit more difficult but more efficient.
Read https://docs.microsoft.com/en-us/windows/win32/dataxchg/using-the-clipboard#copying-information-to-the-clipboard and implement this in python module. This was done for perl and worked for me in Win32::Clipboard module https://github.com/jandubois/win32-clipboard/pull/5 At least worked for me (I haven’t rechecked but I am 95% sure it worked, I wrote perl script which rotates image in windows clipboard and placed rotated image back. 2nd way does not require C coding and deep delving into clipboard documentation Tcl/Tk can do this. You can use tcl/tk code from python with tkinter. Below is my tcl/tk script which you can adjust and enjoy. Its not cleaned-up, sorry, but it works. # # version 0.30 # 0.21 23mar2012: "lowercase" button # 0.22 03apr2012: fix table # 0.23 17apr2012: '?'/. # 0.24 27apr2012: smaller button but tooltip! :), also return to prev.application (SetForegroundWindow) # 0.25 04jun2012: Ctrl+lowercase button - UPCASE # Òåêñò->Текст is 4rd and not initially seen # 0.30 - rewrite in tcl/tk, with "twapi" usage # # TODO: automatically invoke copy-paste, # TODO: Ctrl+Click=1st letter upcased, # TODO: very compact mode, bigger on mouse move # TODO: crop-image function, and view-clipboard (because it is the same) # # TODO - Clipboard2Img - to outer lib file! # #puts [encoding names] #encoding system utf-8 set er АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя set el "F<DULT~:PBQRKVYJGHCNEA{WXIO}SM\">Zf,dult`;pbqrkvyjghcnea\[wxio\]sm'.z?" set ee "ÀÁÂÃÄŨÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãä叿çèéêëìíîïðñòóôõö÷øùúûüýþÿ?" package require Tk package require Ttk package require img::bmp package require base64 package require twapi package require tooltip ttk::style theme use alt # winnative clam alt default classic xpnative wm title . {текст clipboard} wm attributes . -topmost 1 -toolwindow 1 wm geometry . 130x56 place [ttk::button .b1 -text {Ntrcn->Текст} -command lat2cyr] -y 0 -x 0 -height 20 -width 110 place [ttk::button .b2 -text {Еуче->Text} -command cyr2lat] -y 20 -x 0 -height 20 -width 110 place [ttk::button .b4 -text {TEXTТеКСт->textтекст} -command lowercase] -y 40 -x 0 -height 20 -relwidth 1 place [ttk::button .b3 -text {Òåêñò->Текст} -command eur2cyr] -y 60 -x 0 -height 20 -relwidth 1 image create photo rotate_ccw -data R0lGODlhEAAQAIIAAPwCBAQCBFxaXIQChEQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM0CLrcHjA6JcK4ET68MrNDoIgjOYbdJ4IXagIa3IqVFAMEOqpfn067ErBxG0qGsCJyyQT4EwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7 image create photo rotate_cw -data R0lGODlhEAAQAIIAAPwCBAQCBIQChFxaXEQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMzCLrcHjA6FaG4YbS6At5BR31UKI4mADGhd31rpbmCuZ6qQLA8XvqT2+QhHLKKxqSy4U8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs= place [ttk::button .b5 -image rotate_cw -command {Img2Clipboard [rotate [Clipboard2Img] -90]}] -y 0 -x 108 -height 20 -width 22 place [ttk::button .b6 -image rotate_ccw -command {Img2Clipboard [rotate [Clipboard2Img] 90]}] -y 20 -x 108 -height 20 -width 22 tooltip::tooltip .b1 {Ntrcn->Текст} tooltip::tooltip .b2 {Еуче->Text} tooltip::tooltip .b3 {Òåêñò->Текст} tooltip::tooltip .b4 {TEXTТеКСт->textтекст; [Ctrl]+click - UPCASE (TEXTТеКСт->TEXTТЕКСТ)} tooltip::tooltip .b5 {rotate clockwise IMAGE that is in clipboard} tooltip::tooltip .b5 {rotate counter-clockwise IMAGE that is in clipboard} #bind . <Motion> perl::mmotion bind .b4 <Control-1> uppercase proc lat2cyr {} { before_get global el er twapi::open_clipboard set s [twapi::read_clipboard_text] set x 0 foreach letter [split $s {}] { set i [string first $letter $el] if {$i != -1} { set s [string replace "$s" $x $x [string index $er $i]] } incr x } twapi::empty_clipboard twapi::write_clipboard_text "$s" twapi::close_clipboard after_put } proc cyr2lat {} { before_get global el er twapi::open_clipboard set s [twapi::read_clipboard_text] set x 0 foreach letter [split $s {}] { set i [string first $letter $er] if {$i != -1} { set s [string replace "$s" $x $x [string index $el $i]] } incr x } twapi::empty_clipboard twapi::write_clipboard_text "$s" twapi::close_clipboard after_put } proc eur2cyr {} { global ee er twapi::open_clipboard set s [twapi::read_clipboard_text] set x 0 foreach letter [split $s {}] { set i [string first $letter $ee] if {$i != -1} { set s [string replace "$s" $x $x [string index $er $i]] } incr x } twapi::empty_clipboard twapi::write_clipboard_text "$s" twapi::close_clipboard } set skip 0 proc lowercase {} { global skip if {$skip != 0} { set skip 0 return } before_get twapi::open_clipboard set s [twapi::read_clipboard_text] twapi::empty_clipboard twapi::write_clipboard_text [string tolower "$s"] twapi::close_clipboard after_put } proc uppercase {} { before_get twapi::open_clipboard set s [twapi::read_clipboard_text] twapi::empty_clipboard twapi::write_clipboard_text [string toupper "$s"] twapi::close_clipboard set skip 1 after_put } # Copy the contents of the Windows clipboard into a photo image. # Return the photo image identifier. proc Clipboard2Img {} { twapi::open_clipboard # Assume clipboard content is in format 8 (CF_DIB) set retVal [catch {twapi::read_clipboard 8} clipData] if { $retVal != 0 } { error "Invalid or no content in clipboard" } # First parse the bitmap data to collect header information binary scan $clipData "iiissiiiiii" \ size width height planes bitcount compression sizeimage \ xpelspermeter ypelspermeter clrused clrimportant # We only handle BITMAPINFOHEADER right now (size must be 40) if {$size != 40} { error "Unsupported bitmap format. Header size=$size" } # We need to figure out the offset to the actual bitmap data # from the start of the file header. For this we need to know the # size of the color table which directly follows the BITMAPINFOHEADER if {$bitcount == 0} { error "Unsupported format: implicit JPEG or PNG" } elseif {$bitcount == 1} { set color_table_size 2 } elseif {$bitcount == 4} { # TBD - Not sure if this is the size or the max size set color_table_size 16 } elseif {$bitcount == 8} { # TBD - Not sure if this is the size or the max size set color_table_size 256 } elseif {$bitcount == 16 || $bitcount == 32} { if {$compression == 0} { # BI_RGB set color_table_size $clrused } elseif {$compression == 3} { # BI_BITFIELDS set color_table_size 3 } else { error "Unsupported compression type '$compression' for bitcount value $bitcount" } } elseif {$bitcount == 24} { set color_table_size $clrused } else { error "Unsupported value '$bitcount' in bitmap bitcount field" } set phImg [image create photo] set filehdr_size 14 ; # sizeof(BITMAPFILEHEADER) set bitmap_file_offset [expr {$filehdr_size+$size+($color_table_size*4)}] set filehdr [binary format "a2 i x2 x2 i" \ "BM" [expr {$filehdr_size + [string length $clipData]}] \ $bitmap_file_offset] append filehdr $clipData $phImg put $filehdr -format bmp twapi::close_clipboard return $phImg } # Copy photo image "phImg" into Windows clipboard. proc Img2Clipboard { phImg } { # First 14 bytes are bitmapfileheader - get rid of this set data [string range [base64::decode [$phImg data -format bmp]] 14 end] twapi::open_clipboard twapi::empty_clipboard twapi::write_clipboard 8 $data twapi::close_clipboard } proc rotate { phImg angle } { set w [image width $phImg] set h [image height $phImg] switch -- $angle { 180 { set tmp [image create photo -width $w -height $h] $tmp copy $phImg -subsample -1 -1 return $tmp } 270 - 90 - -90 { set tmp [image create photo -width $h -height $w] set matrix [string repeat "{[string repeat {0 } $h]} " $w] if { $angle == -90 || $angle == 270 } { set x0 0; set y [expr {$h-1}]; set dx 1; set dy -1 } else { set x0 [expr {$w-1}]; set y 0; set dx -1; set dy 1 } foreach row [$phImg data] { set x $x0 foreach pixel $row { lset matrix $x $y $pixel incr x $dx } incr y $dy } $tmp put $matrix return $tmp } default { error "Invalid angle $angle specified" } } } set fhwnd 0 #proc tcl::mmotion {} {$fhwnd = Win32::GuiTest::GetForegroundWindow} proc before_get {} { #Win32::GuiTest::SendKeys("%{TAB}{PAUSE 100}^{C}"); #пока не работает :( #$fhwnd = Win32::GuiTest::GetForegroundWindow; global fhwnd set fhwnd [twapi::get_foreground_window] } proc after_put {} { global fhwnd twapi::set_foreground_window $fhwnd # #Win32::GuiTest::SendKeys("%{TAB}"); # #Win32::GuiTest::SendKeys("^{V}"); # #Win32::GuiTest::SendMessage($fhwnd,0x100,VK_HOME,0); # #Win32::GuiTest::SendMessage($fhwnd,0x100,VK_SHIFT,0); # #пока не работает :( } From: python-win32 <python-win32-bounces+vadim.konovalov=dell....@python.org> On Behalf Of Mriswithe Sent: Thursday, August 12, 2021 8:09 PM To: Tim Roberts Cc: python-win32@python.org Subject: Re: [python-win32] windows images on clipboard Awesome, thank you so much for that info. That makes my tail chasing make more sense! Thanks for saving me from additional posterior extension pursuit. Last question I think, how do I put a file path reference on the clipboard similar to in explorer selecting a few files and hitting control c ? I think I had tested that with discord and it worked, but not 100% on that. On Thu, Aug 12, 2021, 11:57 AM Tim Roberts <t...@probo.com<mailto:t...@probo.com>> wrote: Mriswithe wrote: > > I was looking at making a little helper app for Windows that will take > an image on your clipboard and ensure it is under 8MB for posting to > discord, and if it isn't, use Pillow to resize it until it is the > right size. > > I can use Pillow's ImageGrab.grabclipboard() to get the image off the > clipboard, but I am a little confused about writing it back. I have > been back and forth between the pywin32 source and the windows docs > for the windows C API, but I don't have any previous experience or > context to know what some pieces are intended to do. > > I found an example to write to it from StackOverflow > (https://stackoverflow.com/questions/34322132/copy-image-to-clipboard > [stackoverflow.com]<https://urldefense.com/v3/__https:/stackoverflow.com/questions/34322132/copy-image-to-clipboard__;!!LpKI!1HpfpiZFnkKD39C6jcA6RY-Uyw-wVFHqIvpPi3wlPNKkdVaL3MhY1aEPz_HFEzOHhGtT$> > <https://stackoverflow.com/questions/34322132/copy-image-to-clipboard > [stackoverflow.com]<https://urldefense.com/v3/__https:/stackoverflow.com/questions/34322132/copy-image-to-clipboard__;!!LpKI!1HpfpiZFnkKD39C6jcA6RY-Uyw-wVFHqIvpPi3wlPNKkdVaL3MhY1aEPz_HFEzOHhGtT$>>), > but I was wanting to dig a little deeper to see what formats other > than BMP I could use to put on the clipboard. My ignorance of C++ and > the Windows APIs and hell the Python C API is really biting me here. You can't. You have to write it as a DIB (Device Independent Bitmap), which is the format in a .BMP file. The Windows clipboard was designed in roughly 1986, before GIF, before JPEG and way, way before PNG. The clipboard is designed for universal interchange, so it really does need to spec the lowest common denominator. If they allowed PNGs, then all of the graphics application in the world would have to be modified to decode PNG data. So, to make your app work, save the result as a BMP. > Is there a bit of an idiots example guide for how to say, put a PNG on > the clipboard or a JPG? Some example code? There is a ton of useful > info in the pywin32 repo, but I haven't found anything that has made > this click for me. There is no idiots guide, because it cannot be done. Well, technically speaking you can put arbitrary binary data into the clipboard, but other graphics applications will not be able to read it. When they look for image data, they look for format CF_DIB, and that means a .BMP. -- Tim Roberts, t...@probo.com<mailto:t...@probo.com> Providenza & Boekelheide, Inc. _______________________________________________ python-win32 mailing list python-win32@python.org<mailto:python-win32@python.org> https://mail.python.org/mailman/listinfo/python-win32 [mail.python.org]<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-win32__;!!LpKI!1HpfpiZFnkKD39C6jcA6RY-Uyw-wVFHqIvpPi3wlPNKkdVaL3MhY1aEPz_HFEzW7GLbK$> Internal Use - Confidential
_______________________________________________ python-win32 mailing list python-win32@python.org https://mail.python.org/mailman/listinfo/python-win32