2016-03-06 89 views
0

我在剪貼板中有截圖。如何將圖像保存到沒有PIL的剪貼板中?

我已經使用win32clipboard.GetClipboardData(win32con.CF_DIB)來獲取一個字符串,並將該字符串寫入一個.bmp文件,但它不能被圖片查看器打開。

因此,沒有PIL(和其他圖像第三部分庫),如何將剪貼板中的圖像寫入本地?

+1

你有任何*碼*,做了嗎?如果是這樣,不會**包括它**幫助我們回答你? – Tersosauros

+0

**「將剪貼板中的圖像寫入本地」是什麼意思? – martineau

+0

@martineau這意味着我在剪貼板中有截圖,我想將它保存在文件中。 – Kingname

回答

1

您的簡單方法的主要問題是寫入文件的字符串缺少.bmp文件標頭,這是一個BITMAPFILEHEADER結構。

爲了創建文件頭,必須解碼由GetClipboardData()調用返回的字符串中的至少一些信息。對於CF_DIB剪貼板格式,字符串中數據的第一部分將是BITMAPINFOHEADER

這個頭結構是一個非常普遍的,因爲有許多不同類型的DIB,每個組件和壓縮類型都有不同的風格。幸運的是,用於截圖的那個非常簡單 - 未壓縮的RGBA像素。

這一事實使事情變得容易得多,因爲另有決定把在BITMAPFILEHEADERbfOffBits字段中的值會被這樣的事實,在大多數其它情況下也就是跟隨BITMAPINFOHEADER和開始的可變大小的色表很複雜像素陣列。

下面是處理這種情況的示例代碼(僅):

import ctypes 
from ctypes.wintypes import * 
import win32clipboard 
from win32con import * 
import sys 

class BITMAPFILEHEADER(ctypes.Structure): 
    _pack_ = 1 # structure field byte alignment 
    _fields_ = [ 
     ('bfType', WORD), # file type ("BM") 
     ('bfSize', DWORD), # file size in bytes 
     ('bfReserved1', WORD), # must be zero 
     ('bfReserved2', WORD), # must be zero 
     ('bfOffBits', DWORD), # byte offset to the pixel array 
    ] 
SIZEOF_BITMAPFILEHEADER = ctypes.sizeof(BITMAPFILEHEADER) 

class BITMAPINFOHEADER(ctypes.Structure): 
    _pack_ = 1 # structure field byte alignment 
    _fields_ = [ 
     ('biSize', DWORD), 
     ('biWidth', LONG), 
     ('biHeight', LONG), 
     ('biPLanes', WORD), 
     ('biBitCount', WORD), 
     ('biCompression', DWORD), 
     ('biSizeImage', DWORD), 
     ('biXPelsPerMeter', LONG), 
     ('biYPelsPerMeter', LONG), 
     ('biClrUsed', DWORD), 
     ('biClrImportant', DWORD) 
    ] 
SIZEOF_BITMAPINFOHEADER = ctypes.sizeof(BITMAPINFOHEADER) 

win32clipboard.OpenClipboard() 
try: 
    if win32clipboard.IsClipboardFormatAvailable(win32clipboard.CF_DIB): 
     data = win32clipboard.GetClipboardData(win32clipboard.CF_DIB) 
    else: 
     print('clipboard does not contain an image in DIB format') 
     sys.exit(1) 
finally: 
    win32clipboard.CloseClipboard() 

bmih = BITMAPINFOHEADER() 
ctypes.memmove(ctypes.pointer(bmih), data, SIZEOF_BITMAPINFOHEADER) 

if bmih.biCompression != BI_BITFIELDS: # RGBA? 
    print('insupported compression type {}'.format(bmih.biCompression)) 
    sys.exit(1) 

bmfh = BITMAPFILEHEADER() 
ctypes.memset(ctypes.pointer(bmfh), 0, SIZEOF_BITMAPFILEHEADER) # zero structure 
bmfh.bfType = ord('B') | (ord('M') << 8) 
bmfh.bfSize = SIZEOF_BITMAPFILEHEADER + len(data) # file size 
SIZEOF_COLORTABLE = 0 
bmfh.bfOffBits = SIZEOF_BITMAPFILEHEADER + SIZEOF_BITMAPINFOHEADER + SIZEOF_COLORTABLE 

bmp_filename = 'clipboard.bmp' 
with open(bmp_filename, 'wb') as bmp_file: 
    bmp_file.write(bmfh) 
    bmp_file.write(data) 

print('file "{}" created from clipboard image'.format(bmp_filename)) 
+0

你是一個高手!謝謝,這是我想要的。順便說一句,我想將這個答案翻譯成中文,併發布到我的博客,所以我想獲得您的許可,請允許我這樣做。 – Kingname

+0

不客氣。是的,請隨時在您的博客中使用它 - 確保使用我剛發佈的更新版本,我試圖改進解釋(無需更改代碼)。 – martineau

+0

好的,非常感謝 – Kingname

相關問題