| Author |
copy image to windows clipboard?
|
|
| Bryan Oakley 2006-03-02, 7:02 pm |
| Is it possible either with core tcl or an extension to copy an image
from a tk application to the Windows clipboard? If it is possible, can
anyone give me a concrete example?
I want to be able for a user to do a copy/paste operation of an image
between my tk app and a Windows app such as powerpoint.
I'm not looking for any other mechanism to get images into a Windows
app; I specifically want to be able to put images onto the system clipboard.
| |
| Roy Terry 2006-03-02, 7:02 pm |
| "Bryan Oakley" <oakley@bardo.clearlight.com> wrote in message
news:oRDNf.17338$rL5.10869@newssvr27.news.prodigy.net...
> Is it possible either with core tcl or an extension to copy an image
> from a tk application to the Windows clipboard? If it is possible, can
> anyone give me a concrete example?
>
> I want to be able for a user to do a copy/paste operation of an image
> between my tk app and a Windows app such as powerpoint.
>
> I'm not looking for any other mechanism to get images into a Windows
> app; I specifically want to be able to put images onto the system
clipboard.
I think TWAPI is the way to go
http://twapi.sourceforge.net/ looks like you just need to
lookup the format code for images of your desired
type.
| |
| Bryan Oakley 2006-03-02, 7:02 pm |
| Roy Terry wrote:
> clipboard.
> I think TWAPI is the way to go
> http://twapi.sourceforge.net/ looks like you just need to
> lookup the format code for images of your desired
> type.
Thanks! I had forgotten about twapi. Judging from the documentation it
might be just what I need, though a bit overkill for my one simple need.
| |
|
|
Bryan Oakley wrote:
> Is it possible either with core tcl or an extension to copy an image
> from a tk application to the Windows clipboard? If it is possible, can
> anyone give me a concrete example?
>
> I want to be able for a user to do a copy/paste operation of an image
> between my tk app and a Windows app such as powerpoint.
>
> I'm not looking for any other mechanism to get images into a Windows
> app; I specifically want to be able to put images onto the system clipboard.
Bryan,
I think I at least got half of an answer to your question. I used tcom
(comes with AS Tcl), and I copied a graph from excel to Word.
| |
| Bryan Oakley 2006-03-02, 7:02 pm |
| bs wrote:
> Bryan Oakley wrote:
>
>
>
> Bryan,
>
> I think I at least got half of an answer to your question. I used tcom
> (comes with AS Tcl), and I copied a graph from excel to Word.
>
Thanks, but that's not really half my equation. I don't want my tk
application to do anything but put an image on the clipboard. Pasting
that into another app is up to the user using the other app.
I think twapi will do what I want, though I can't test it for a few days
as I don't have a windows box available to me right now.
Thanks anyway.
| |
| palmtcl@yahoo.com 2006-03-05, 6:59 pm |
| If you do use TWAPI, be aware that it does not support format 2
(CF_BITMAP), Use format 8 (CF_DIB). As an example,
package require base64
package require Img
package require twapi
set image [image create photo....]
# First 14 bytes are bitmapfileheader - get rid of this
set data [string range [base64::decode [$image data -format bmp]] 14
end]
twapi::open_clipboard
twapi::empty_clipboard
twapi::write_clipboard 8 $data
twapi::close_clipboard
| |
| walton.paul@gmail.com 2006-03-14, 7:57 am |
| I'm trying to do something similar, except I want to read an image from
the clipboard. I want to read an image after a screenshot is made with
the PrintScreen key. But for some reason it's not working, and I think
it may be related to twapi not supporting format 2.
I guess I should explain what I'm *really* trying to do. I want images
of each open window. I wasn't having any luck trying to figure out how
to do this in a simple way. So what I'm doing with twapi is getting
the handles of all open windows, bringing each to the foreground one at
a time and using twapi::send_keys to simulate an Alt+PrintScreen
keypress which takes a screenshot of the current window. Now I need to
figure out how to get that image data out of the clipboard... Any
ideas?
Paul
| |
| Uwe Klein 2006-03-14, 7:57 am |
| walton.paul@gmail.com wrote:
> I'm trying to do something similar, except I want to read an image from
> the clipboard. I want to read an image after a screenshot is made with
> the PrintScreen key. But for some reason it's not working, and I think
> it may be related to twapi not supporting format 2.
>
> I guess I should explain what I'm *really* trying to do. I want images
> of each open window. I wasn't having any luck trying to figure out how
"every" or "your app only"
> to do this in a simple way. So what I'm doing with twapi is getting
> the handles of all open windows, bringing each to the foreground one at
> a time and using twapi::send_keys to simulate an Alt+PrintScreen
> keypress which takes a screenshot of the current window. Now I need to
> figure out how to get that image data out of the clipboard... Any
> ideas?
>
>
> Paul
>
are you bent on using twapi?
I put this in the last Tcl-URL:
http://wiki.tcl.tk/9127
uwe
| |
| walton.paul@gmail.com 2006-03-14, 7:57 am |
| Hi, Uwe.
I'm not locked into using twapi and I'll use whatever works, but I need
to be able to capture images of all toplevel windows from all
applications. The method in that link works only for Tk windows. The
twapi method I described in my last message works good enough, except
for getting the image data out of the clipboard. Thanks for the
suggestion though.
Paul
| |
| palmtcl@yahoo.com 2006-03-14, 7:57 am |
| Try the following to write clipboard bitmap contents to a file (assumes
image is already in clipboard):
proc write_bmp_file {filename bmp} {
set filehdr [binary format "a2 i x2 x2 i" "BM" [expr {14 + [string
length $bmp]}] 14]
set fd [open $filename w]
fconfigure $fd -translation binary
puts -nonewline $fd $filehdr
puts -nonewline $fd $bmp
close $fd
}
twapi::open_clipboard
write_bmp_file c:/x.bmp [twapi::read_clipboard 8]
twapi::close_clipboard
You can now open c:/x.bmp in MS Paint or Gimp or whatever.
To use this within Tk, you will need some image command extension that
understands BMP formats. Img is one but has some limitations - on my
system Img 1.3 generates an error : "RLE compression not supported for
32-bit pixel values" so you may need to convert the image before using
in Tk.
/Ashok
walton.paul@gmail.com wrote:
> I guess I should explain what I'm *really* trying to do. I want images
> of each open window. I wasn't having any luck trying to figure out how
> to do this in a simple way. So what I'm doing with twapi is getting
> the handles of all open windows, bringing each to the foreground one at
> a time and using twapi::send_keys to simulate an Alt+PrintScreen
> keypress which takes a screenshot of the current window. Now I need to
> figure out how to get that image data out of the clipboard... Any
> ideas?
>
>
> Paul
| |
| walton.paul@gmail.com 2006-03-14, 7:57 am |
| Awsome! Thanks, Ashok. There's only one problem with it. When
viewing the image with Windows Picture Viewer, the last 13 pixels of
the image in the x direction are now the first 13 pixels of the image.
However, the image displays correctly in Paint, and if I open it with
Paint and re-save it, then Paint seems to fix the problem and it now
displays correctly in Picture Viewer. When I convert the unfixed image
to a gif using ImageMagick, the gif image is displayed incorrectly in
both Paint and Picture Viewer. I'm on Windows XP.
I'm guessing the problem is in the 'binary format' line, but I'm still
trying to decipher it. Do you experience the same problem?
Thanks,
Paul
| |
| walton.paul@gmail.com 2006-03-14, 7:57 am |
| I think I figured it out. It seems to work fine if the 14 is changed
to 12:
set filehdr [binary format "a2 i x2 x2 i" "BM" [expr {12 + [string
length $bmp]}] 12]
Thanks for the help.
Paul
| |
| walton.paul@gmail.com 2006-03-14, 7:57 am |
| Well I made a mistake and posted too fast. The 12 does not fix it.
Paul
| |
| walton.paul@gmail.com 2006-03-14, 7:00 pm |
| I got it fixed, and I'm pretty sure this time. The last integer needs
to be 66.
set filehdr [binary format "a2 i x2 x2 i" "BM" [expr {14 + [string
length $bmp]}] 66]
| |
| palmtcl@yahoo.com 2006-03-14, 7:00 pm |
| Well it turns out that the offset (14/66 etc) depends on the bitmap.
Here's a new and improved version of write_bitmap_header that seems to
work much better. I had thought the file header field that contained
the offset to the bitmap was the offset to the bitmap header. It is
actually the offset to the pixel values so we need to skip over the
color table entries etc.
GIMP, XP Picture viewer and Paint all show it correctly. Img still
complains about unsupported RLE format. I'm not sure if that's because
of lingering bugs in this function or it really is a Img unsupported
(but valid) format. Anyways, here's the proc:
proc write_bmp_file {filename bmp} {
# Assumes $bmp is clipboard content in format 8 (CF_DIB)
# First parse the bitmap data to collect header information
binary scan $bmp "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 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 $bmp]}] $bitmap_file_offset]
set fd [open $filename w]
fconfigure $fd -translation binary
puts -nonewline $fd $filehdr
puts -nonewline $fd $bmp
close $fd
}
| |
| Paul Obermeier 2006-03-24, 10:01 pm |
| Hello,
Your assumption about lacks in the Img BMP parser are correct.
I've implemented the missing 16 and 32 bit format parser (for reading only)
and put a new binary version of Img
onto my homepage: http://www.posoft.de/download/tkimg/Img1.3.zip
There is also a little test program (based on your code published here) on
the Tclers Wiki: http://wiki.tcl.tk/15647
If I get positive feedback (hopefully) the changes will make it into the Img
sources on SourceForge.
Paul
P.S.: The 16 and 32 bit based BMP format is typically not used with image
files. Windows uses it, when copying images into the clipboard. So, you
should try to test with 16 and 32 bit display settings.
<palmtcl@yahoo.com> schrieb im Newsbeitrag
news:1142361311.282086.180470@j52g2000cwj.googlegroups.com...
> Well it turns out that the offset (14/66 etc) depends on the bitmap.
> Here's a new and improved version of write_bitmap_header that seems to
> work much better. I had thought the file header field that contained
> the offset to the bitmap was the offset to the bitmap header. It is
> actually the offset to the pixel values so we need to skip over the
> color table entries etc.
> GIMP, XP Picture viewer and Paint all show it correctly. Img still
> complains about unsupported RLE format. I'm not sure if that's because
> of lingering bugs in this function or it really is a Img unsupported
> (but valid) format. Anyways, here's the proc:
>
> proc write_bmp_file {filename bmp} {
> # Assumes $bmp is clipboard content in format 8 (CF_DIB)
>
> # First parse the bitmap data to collect header information
> binary scan $bmp "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 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 $bmp]}] $bitmap_file_offset]
>
> set fd [open $filename w]
> fconfigure $fd -translation binary
>
> puts -nonewline $fd $filehdr
> puts -nonewline $fd $bmp
>
> close $fd
> }
>
| |
| palmtcl@yahoo.com 2006-03-24, 10:01 pm |
| Works for me (XP SP2). I tried it both copy and paste with 16 and
32-bit settings. Thanks
/Ashok
|
|
|
|