0

I want to put a local image into the clipboard using Rust. I used the clipboard-win and image crates. My code is as follows, but it doesn't work.

extern crate clipboard_win;
extern crate image;

use clipboard_win::{formats, Clipboard};
use image::GenericImageView;

fn main() {
    let img = image::open("C:\\Users\\Crash\\Desktop\\20190405221505.png").unwrap();
    Clipboard::new()
        .unwrap()
        .set(formats::CF_BITMAP, &img.raw_pixels());
}

After execution, there seems to be content in the pasteboard, but there is nothing displayed after Ctrl+V. How can I correct this code?

Shepmaster
  • 326,504
  • 69
  • 892
  • 1,159
tantalum
  • 13
  • 5

1 Answers1

1

You have multiple problems.

Format

A PNG format image is not a bitmap format image, even though it is a bitmap.

A thread on MSDN states:

There isn't a standardized clipboard format for PNG.

You can register your own format, but then only you can recognize the clipboard. If you use the standard bitmap or file format then more applications can accept your data.

Error handling

Clipboard::set can fail and it returns a Result. You need to handle this case. The compiler even told you about this:

warning: unused `std::result::Result` that must be used
  --> src\main.rs:11:5
   |
11 | /     Clipboard::new()
12 | |         .unwrap()
13 | |         .set(formats::CF_BITMAP, &data);
   | |________________________________________^
   |
   = note: #[warn(unused_must_use)] on by default
   = note: this `Result` may be an `Err` variant, which should be handled

Don't ignore warnings, especially when trying to debug a problem.


Unfortunately, this is as far as I got:

use clipboard_win::{formats, Clipboard}; // 2.1.2
use image::ImageOutputFormat; // 0.21.0

fn main() {
    let img = image::open("unicorn.png").unwrap();

    let mut data = Vec::new();
    img.write_to(&mut data, ImageOutputFormat::BMP)
        .expect("Unable to transform");

    Clipboard::new()
        .unwrap()
        .set(formats::CF_BITMAP, &data)
        .expect("Unable to set clipboard");
}

Writing data to a file produces a BMP that Paint can read, but the clipboard data is still invalid. While attempting to debug the differences, I ran into low-level crashes in the library, which suggests it may not be ready for general use, despite the 2.x version number.

I believe that the root problem is that

Windows expects

A handle to a bitmap (HBITMAP).

A BITMAP is a struct with a set of information about the bitmap, such as width and height. This is likely different from the on-disk format of the bitmap.

It seems plausible that fitting the bitmap data into this expected format would go a long way to solving the problem.

Another avenue is to look into using CF_DIB instead of CF_BITMAP. Contrary to the linked forum post above, CF_DIB expects a pointer to a BITMAPINFO which has a BITMAPINFOHEADER field. This makes a reference to a BI_PNG compression, which might allow you to submit a PNG without performing transformations.

See also:

Community
  • 1
  • 1
Shepmaster
  • 326,504
  • 69
  • 892
  • 1,159
  • Thank you for pointing out my question. Is there a problem with [clipboard-formats](https://docs.microsoft.com/en-us/windows/desktop/dataxchg/standard-clipboard-formats)? – tantalum Apr 07 '19 at 01:39