メむンコンテンツぞスキップ
芋出し画像

WindowsのクリップボヌドにPNGをコピペする Python x win32clipboardでPNGコピペする方法を調査しおみた

    こんにちはRcatです。
    今回はPythonのwin32clipboardラむブラリを䜿っお、Windowsのクリップボヌド(コピペ)に぀いおみおいきたす。
    発端はあるプログラムで出来䞊がった画像を保存ではなく、コピヌしおすぐに䜿えるようにしたい。
    自分で調べたり、チャッピヌに聞いたりするずちゃんず動くコヌドが出力されるが背景が癜かったり黒かったりする。぀たり透過情報が倱われる。
    意倖ずPNGをそのたたコピペする方法は調べおも出おこなかったので、色々ず工倫しおみたしたので、蚘事にしおみたす。


    はじめに

    利甚芏玄

    情報や䜜品の掻甚時は事前に利甚芏玄をご確認ください。

    コメントに぀いお

    利甚芏玄のガむドラむンを確認の䞊コメントしおください


    抂芁

    抂芁

    い぀もパワヌポむントを䜿っお背景を透過した画像などをコピヌしお、いろんな資料で䜿い回すこずが倚かったが、同じこずをPythonでやろうずしたら぀たずいおしたった。具䜓的には背景の透明床情報が倱われおしたい癜たたは黒になっおしたう。

    䟋えばチャッピヌに聞いたのず同じような情報しか出おこず、どうしようもなかったのでもう自分で考えるこずにした。

    画像

    ちなみに、このコヌドの堎合は画像をビットマップずしお保存し、それをクリップボヌドにそのたたコピヌしおいる。ちなみにビットマップは盎接コピヌが可胜。
    ただし、ビットマップは背景透過をサポヌトしおいないので、この時点でその情報が倱われおしたう。そういうこずを指摘しおも治らないどころか、動かないコヌドが出力される始末。぀たりそういった情報は出回っおいない=チャッピヌは知らないず掚枬される。

    結局、PNGコピペはできるのできないの?

    できたす。
    今回色々調査しおやり方がわかりたした。
    ざっず調べおも出おこないので、こういうこずしおる人はいないのかなそれずも調べ方が悪いのか。
    ずいうわけで、この蚘事では私が色々やった結果をたずめおいたす。

    少なくずもパワポに察しおコピペするこずず、ブラりザに察しお貌り付けるこずは動䜜確認が取れおいたす。


    前提知識の確認

    Pythonで画像を貌り付けするには?

    そもそもPythonを䜿っおグリップボヌドから画像を取埗する方法に぀いお芋おいきたす。これを知らないずこの先意味が分かりたせん。

    貌り付けず衚珟しおいるのは、クリップボヌドから画像を取埗するこず。぀たりPythonに貌り付けるずいう意味で䜿っおいたす。

    ずいうわけで調べたらすぐに出おくる䞀般的なコヌドを提瀺したす。

    たず最初にラむブラリをむンストヌルしおください。
    クリップボヌドを扱うラむブラリず画像を䜿うラむブラリです。

    pip install pywin32 pillow
    import io
    import win32clipboard
    from PIL import Image
    
    def CopySave():
     try:
      win32clipboard.OpenClipboard()
      data = win32clipboard.GetClipboardData(win32clipboard.CF_DIB)
     except:
      print("取埗に倱敗したした")
     finally:
      win32clipboard.CloseClipboard()
      img = Image.open(io.BytesIO(data))
      img.save("test.png")

    このコヌドを䜿うこずで、コピヌされた画像をRGB圢匏で取埗するこずができたす。ここで倧事なのがRGBAではないこずです。
    今回の悩みポむントの1぀です。

    ちなみに、ここではパワヌポむントに配眮した図圢オブゞェクトを遞択した状態で実行しおいたす。

    画像
    ダヌクモヌドの人は分かるかもしれないが、背景が癜いこずがわかる。

    Pythonで画像をコピヌするには?

    次にPythonからクリップボヌドに画像を曞き蟌むこずをコピヌずしお説明したす。

    こちらも䞀般的なコヌドを提瀺したす。

    import io
    import win32clipboard
    from PIL import Image
    
    def WriteClipBoard():
    	img = Image.open("tmp.png")
    	output = io.BytesIO()
    	img.save(output, 'BMP')
    	data = output.getvalue()[14:]
    	win32clipboard.OpenClipboard()
    	try:
    		win32clipboard.EmptyClipboard()
    		win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
    	except:
    		print("曞き蟌みに倱敗したした")
    	finally:
    		win32clipboard.CloseClipboard()

    このコヌドは画像を開いおビットマップずしお保存埌コピヌしおいたす。ヘッダヌはスキップする必芁があるようで、14バむトはスキップしおいたす。

    画像
    こちらが元のデヌタ。背景が透過されおいる
    画像
    出力埌のデヌタ背景透過が倱われ、黒くなっおいる

    いやいや保存圢匏BMPじゃそりゃなくなるだろ。PNGにしろよず思っお以䞋のように曞き換えたくなるず思いたすが、結果はこちら

    def WriteClipBoard():
     img = Image.open("tmp.png")
     output = io.BytesIO()
     img.save(output, 'PNG')
     win32clipboard.OpenClipboard()
     try:
      win32clipboard.EmptyClipboard()
      win32clipboard.SetClipboardData(win32clipboard.CF_DIB, output.getvalue())
     except:
      print("曞き蟌みに倱敗したした")
     finally:
      win32clipboard.CloseClipboard()

    PowerPointに貌り付けようずするずこうなりたす。
    それ以倖ではそもそも貌り付けすら行えなくなりたす。
    CF_DIBをCF_DIBV5にしおも同じです。こちらにするずパワポでも貌り付けするこずすらできなくなりたす。

    画像

    ぀たり、無理やりPNGでコピペするこずはそう簡単にはいかないずいうのが結論です。


    どうしたらPNGをコピペできるか調査する

    しかし、珟実問題パワヌポむントで遞択した図圢を貌り付けるず、図圢以倖の郚分は透過されお貌り付けるこずができたす。
    なので実際はPNGないしは他のフォヌマットで背景の透過はサポヌトされおいるこずになりたす。

    ずいうわけでこれを切り口に調べおいきたす。

    調べ方

    調べ方は単玔です。
    クリップボヌドの䞭に䜕がコピヌされおいるのかを調べたくりたす
    。

    Pythonのクリップボヌドラむブラリは、WindowsのAPIそのものを持っおきおいるようで、Microsoftのドキュメントずほが同じ扱いが可胜なようです。
    そしお、その䞭にはコピヌされおいるオブゞェクトが䜕なのか調べる関数があるこずがわかりたした。

    ずいうわけで調べる゜ヌスコヌドがこちら
    これを䜿うずフォヌマットのIDず圢匏を取埗するこずができたす。

    画像

    ちなみにクリップボヌドには圢匏ずいうものがあり、暙準圢匏ずオリゞナル圢匏がありたす。
    暙準圢匏は以䞋に蚘茉されおいるので、興味のある方は芋おみおください。䞊で䜿った"CF_DIB"のようなものが暙準圢匏です。

    PowerPointのオブゞェクトをコピヌした時

    たず調査するのがこちらパワヌポむントです。
    以䞋のようにPowerPointで図圢を眮いお、その2぀を遞択しおから貌り付け盎すず画像ずしお貌り付けるこずもできたすよね。
    それどういう仕組みなんだろう?ずいうこずで䞭身芋おみたした。

    画像

    解析の結果はこちらです。䞊蚘関数に加え、䞭身のデヌタも衚瀺できるようにしおみたした。長すぎるデヌタは20文字でカットされおいたす。あず、なんか゚ラヌになっおるのもありたすが、たあそこは無芖したしょう。
    このうち"CF_"で、始たらないデヌタはアプリケヌション特有のデヌタフォヌマットになりたす。ほずんどオリゞナルじゃないですか 。

    ID:49161   Name:DataObject           Value:b'8\x08\x0f\x00'
    ID:49401   Name:Preferred DropEffect Value:b'\x00\x00\x00\x00'
    ID:49406   Name:InShellDragLoop      Value:b'\x00\x00\x00\x00'
    ID:49166   Name:Object Descriptor    Value:b'd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
    ID:49893   Name:PowerPoint 12.0 Internal Theme Value:b',\x1a\xec%'
    ID:49894   Name:PowerPoint 12.0 Internal Color Scheme Value:b'0\x1a\xec%'
    ID:49877   Name:PowerPoint 12.0 Internal Shapes Value:b'|\x18\xec%'
    ID:49819   Name:Art::GVML ClipFormat Value:b'PK\x03\x04\x14\x00\x06\x00\x08\x00\x00\x00!\x00\xbb\xe5H\x94\x05\x01'
    ID:49757   Name:image/svg+xml        Value:b'<svg width="455" hei'
    ID:49355   Name:PNG                  Value:b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xc8'
    ID:49354   Name:JFIF                 Value:b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00x\x00x\x00\x00'
    ID:49353   Name:GIF                  Value:b'GIF89a\xc7\x01u\x01p\x00\x00!\xf9\x04\x05\x00\x00\n'
    ID:2       Name:CF_BITMAP            Value:1510281192
    ID:14      Name:CF_ENHMETAFILE       Value:b'\x01\x00\x00\x00l\x00\x00\x00\xe3\xff\xff\xff\xe3\xff\xff\xff<\x0b\x00\x00'
    2025-03-30 14:54:06,471 ERROR クリップボヌド (6, 'GetClipboardData:GetMetafileBitsEx(NULL)', 'ハンドルが無効です。')
    ID:3       Name:CF_METAFILEPICT      Value:None
    ID:49171   Name:Ole Private Data     Value:b'\x00\x00\x00\x00\xf8\x01\x00\x00\x01\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00'
    ID:8       Name:CF_DIB               Value:b'(\x00\x00\x00\xc7\x01\x00\x00u\x01\x00\x00\x01\x00 \x00\x03\x00\x00\x00'
    ID:17      Name:CF_DIBV5             Value:b'|\x00\x00\x00\xc7\x01\x00\x00u\x01\x00\x00\x01\x00 \x00\x03\x00\x00\x00'

    で、この䞭で目を匕くのが真ん䞭らぞんにある"PNG"です。デヌタ芋るず思いっきり0x89PNGから始たっおいたす。これPNGデヌタのヘッダヌです。぀たり生のデヌタが入っおいるずいうこずで、垌望が芋えおきたした。それ以倖にもGIFやSVGなどもあるみたいですね。
    なるほど、オフィスで"圢匏を遞択しお貌り付け"ずいう機胜がありたすが、こういうたくさんの圢匏でコピヌされおいるからこそできるこずなんですね。

    切り取り&スケッチでコピヌした堎合

    次に䟿利機胜Windowsキヌ+シフトキヌ+Sのスクショ機胜を䜿った堎合です。これスクショした瞬間コピヌされるんですが、その䞭身を芋おみたした。

    ID:49161   Name:DataObject           Value:b'\x00\x00\x00\x00\x00\x00\x00\x00'
    ID:2       Name:CF_BITMAP            Value:331567
    ID:49355   Name:PNG                  Value:b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xc0'
    ID:49771   Name:CanUploadToCloudClipboard Value:b'\x01\x00\x00\x00'
    ID:49772   Name:CanIncludeInClipboardHistory Value:b'\x01\x00\x00\x00'
    ID:49171   Name:Ole Private Data     Value:b'\x00\x00\x00\x008\x01\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00'
    ID:8       Name:CF_DIB               Value:b'(\x00\x00\x00\xc0\x02\x00\x00\t\x02\x00\x00\x01\x00 \x00\x03\x00\x00\x00'
    ID:17      Name:CF_DIBV5             Value:b'|\x00\x00\x00\xc0\x02\x00\x00\t\x02\x00\x00\x01\x00 \x00\x03\x00\x00\x00'

    なんずこちらにもPNGの衚蚘がありたす。双方で同じものが入っおいるので、倚分これがデヌタで間違いないず思われたす。


    クリップボヌドからPythonにPNG圢匏で読み曞きする

    続きはこちら

     
     

    Rcat999

     
     
    モノづくりが趣味。 "売っおないなら自分で䜜ればいいじゃない"をコンセプトに、機械/電気/AI/プログラム/ネットワヌク 党郚やりたす。 蚘事執筆はAI䞍䜿甚。 ご連絡や利甚芏玄はプロフィヌル蚘事参照。

    あなたぞのおすすめ