クリップボードに画像(DIBイメージ)をおくりこむ

Blenderでやりたいことがあったので調べた。

まずwin32clipboardを使えるようにpywin32をインストールする。
https://sourceforge.net/projects/pywin32/


以下のようなコードでRGBのバイト列を画像としてクリップボードに送ることができる。

import win32clipboard
import struct

def createDIB():
  channels=3 # RGB 24bit
  width=2
  height=2
  # header
  dib=struct.pack("<LllHHLLllLL",
      0x28, # size of BITMAPINFOHEADER
      width, # width
      height, # height
      1, # planes
      8*channels, # bit count
      0, # compression
      width*height*channels, # image size
      0, # x pixel per meter
      0, # y pixel per meter
      0, # nummber of pallet colors
      0, # important color index
      )

  # rawdata B, G, R
  dib+=struct.pack("<BBB", 255, 0, 0)
  dib+=struct.pack("<BBB", 0, 255, 0)
  dib+=struct.pack("<BB", 0, 0) # 行ごとに4byte境界にあわせる
  dib+=struct.pack("<BBB", 0, 0, 255)
  dib+=struct.pack("<BBB", 0, 0, 0)
  dib+=struct.pack("<BB", 0, 0) # 行ごとに4byte境界にあわせる

  return dib

win32clipboard.OpenClipboard()
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, createDIB())
win32clipboard.CloseClipboard()

本当はアルファチャンネルがついた画像をおくりたかったのだけどなんか単純に32bitのDIBを送るだけではできなかったし、
Gimp<->sai間とかでもできなかった。ツール間でのアルファチャンネルつきデータをやり取りする標準的な方法自体が無いのかもしれないのでこれでよしとする。
あとRAWデータは下の行から順番に格納されていて4バイト境界に端数が出たら適当に埋める必要があった。

逆にクリップボードからDIBをゲットするコードはこんな感じ。CF_DIBを変えればDIB画像以外も可能。

import win32clipboard

win32clipboard.OpenClipboard()
open('tmp.dat', 'wb').write(win32clipboard.GetClipboardData(win32clipboard.CF_DIB))
win32clipboard.CloseClipboard()