[Win32utils-devel] Getting image size for win32-clipboard

Daniel Berger djberg96 at gmail.com
Sat Apr 18 09:03:28 EDT 2009


On Sat, Apr 18, 2009 at 3:19 AM, Heesob Park <phasis at gmail.com> wrote:
> Hi,
>
> 2009/4/18 Daniel Berger <djberg96 at gmail.com>:
>>
>> I opened up a small .jpg file with Photoshop Elements 5. I did a
>> Ctrl-A + Ctrl-C. This was the result:
>>
>> Header Size: 40
>> Width: 570
>> Height: 570
>> Planes: 1
>> Bit Count: 24
>> Compression: 0
>> Image Size: 0
>> X Per Meter: 112205
>> Y Per Meter: 112205
>> Color Used: 0
>> Color Import: 0
>>
>> Ok...this is strange. I opened up the *same* image in Paint, and did a
>> Ctrl-A + Ctrl-C. This was the result:
>>
>> Header Size: 40
>> Width: 570
>> Height: 570
>> Planes: 1
>> Bit Count: 24
>> Compression: 0
>> Image Size: 975840
>> X Per Meter: 112200
>> Y Per Meter: 112200
>> Color Used: 0
>> Color Import: 0
>>
>> Maybe because it was a jpg instead of a bmp? I'm not sure.
>>
>> In any case, I've got the initial implementation in CVS. I am having
>> some trouble actually copying clipboard contents. I tried this:
>>
>> File.open("test.bmp", "wb"){ |fh| fh.write Clipboard.data(Clipboard::DIB) }
>>
>> The file size is identical, but I can't open the resulting file - MS
>> Paint says it doesn't recognize the format.
>>
>> Please take a look at the code in CVS (and use the latest windows-pr)
>> and see if everything looks alright.
>>
> Here is a patch.
>
> --- clipboard.rb        2009-04-18 18:11:44.000000000 +0900
> +++ clipboard.rb.new    2009-04-18 18:12:03.000000000 +0900
> @@ -234,6 +234,7 @@
>
>          begin
>             address = GlobalLock(handle)
> +           buf_size = GlobalSize(handle)
>             memcpy(bmi, address, bmi.length)
>
>             size        = bmi[0,4].unpack('L').first  # biSize
> @@ -241,6 +242,7 @@
>             compression = bmi[16,4].unpack('L').first # biCompression
>             size_image  = bmi[20,4].unpack('L').first # biSizeImage
>             clr_used    = bmi[32,4].unpack('L').first # biClrUsed
> +           size_image  = buf_size+16 if size_image==0
>
>             # Calculate the header size
>             case bit_count
> @@ -264,9 +266,10 @@
>                   raise Error, "invalid bit count"
>             end # case
>
> -            buf_size = size + 14 + (table_size * 4) + size_image
> +           offset = 0x36 + (table_size*4)
>             buf = 0.chr * buf_size
>             memcpy(buf, address, buf.size)
> +            buf = "\x42\x4D" + [size_image].pack('L') + 0.chr * 4 +
> [offset].pack('L') + buf
>          ensure
>             GlobalUnlock(handle)
>          end

Thanks Heesob, that worked. There are a couple of things I still don't
understand, though. I used the same code as before:

File.open('clippy.bmp', 'wb'){ |fh|
   fh.write Clipboard.data(Clipboard::DIB)
}

The resulting file is larger than the original file in my experiments
by a few bytes. Why? I can't visually detect any differences in the
image, but I thought it was curious.

Also, it seems like we ought to be able to remove the memcpy near the
end, since 'buf' is reassigned anyway. But, if I remove it, I get an
"out of memory" error if I attempt to open the file.

Last, if I replace Clipboard::DIB with Clipboard::ENHMETAFILE I get a segfault.

Regards,

Dan


More information about the win32utils-devel mailing list