URLhttps://learnscript.net/zh-hant/pygame/image/
    複製連結移至說明  範例

    如何載入和儲存遊戲影像?以及影像與位元組序列的轉換等問題

    閱讀 16:57·字數 5087·更新 
    Youtube 頻道
    訂閱 375

    雖然本節的範例中包含繪製影像的程式碼,但本節不會講解與影像繪製相關的問題,要了解繪製,請檢視如何繪製表面(影像,字型)?以及色彩混合模式,裁剪區域,鎖定等問題一節。

    Pygame 中的 image 模組

    Pygame 套件的image模組,包含了與影像相關的功能,主要涉及影像的載入,影像的儲存,以及影像的轉換,當你匯入pygame模組時,image模組會被pygame模組匯入。事實上,Pygame 套件並不包含一個名稱為Image的類別,image模組只會傳回或操作繪製了影像的Surface物件。

    判斷遊戲是否支援擴充的影像格式

    image模組的get_extended函式,可用於判斷遊戲是否支援擴充的影像格式,這通常取決於你所安裝的 Pygame 版本,但無論如何,Pygame 總是支援未壓縮的bmp影像格式。

    get_extended()

    傳回值

    如果get_extended函式傳回True,那麽表示遊戲支援擴充的影像格式。

    extended.py
    from pygame import image
    
    print(f'支援擴充的影像格式?{image.get_extended()}')
    支援擴充的影像格式?True

    為遊戲載入影像

    image模組的loadload_basicload_extended函式,可用於載入影像並傳回一個繪製了影像的Surface表面物件,其中,loadload_extended函式可以自行判斷影像的格式,但有時需要通過檔案的副檔名來完成此目標,load_basic函式則只能載入bmp格式的影像。

    當 Pygame 不支援擴充的影像格式時,image模組的load_extended函式會引發例外狀況NotImplementedError: loading images of extended format is not available。至於如何判斷 Pygame 是否支援擴充的影像格式,你可以檢視判斷遊戲是否支援擴充的影像格式一段。

    load(filename, namehint='')
    load_basic(filename)
    load_extended(filename, namehint='')

    filename 參數

    filename參數是表示影像檔案路徑的字串,或包含影像檔案路徑的類路徑(path-like)物件,或包含影像資料的IO物件。

    namehint 參數

    namehint參數是一個用於提示檔案副檔名的字串,如果filename參數是一個IO物件,並且你希望傳遞檔案副檔名的話。

    傳回值

    loadload_basicload_extended函式的傳回值是繪製了影像的Surface表面物件。

    load,load_extended 函式能夠載入的影像格式有哪些?

    如果 Pygame 支援完整的擴充影像格式,那麽loadload_extended函式能夠載入以下的影像格式,bmpgif(不支援動畫),jpegjpg),lbmpbmpgmppm),pcxpngpnmsvg(有限的支援),tga(非壓縮),tifftif),webpxpm

    load,load_basic,load_extended 函式所傳回的 Surface 物件需要進行轉換

    在大部分情況下,你需要對loadload_basicload_extended函式所傳回的Surface物件進行轉換,呼叫他們的convertconvert_alpha方法,以便在視窗中快速進行繪製。

    在下面的範例中,我們使用 Python 的open函式開啟了影像檔案sky.webp,並將傳回的IO物件傳遞給了load函式。

    load.py
    # 在執行腳本前,請將命令列跳躍至 load.py 所在的目錄
    from pygame import image, display
    
    # 通過 IO 物件載入影像檔案 sky.webp data = open('sky.webp', 'rb') sky = image.load(data)
    # 直接載入影像檔案 candy.png candy = image.load_extended('candy.png')
    # 建立遊戲視窗,繪製天空和糖果,並等候 2 秒鐘 s = display.set_mode((800, 600)) s.blit(sky, (0, 0)) s.blit(candy, (100, 100)) display.flip()
    import time time.sleep(2)

    將遊戲畫面儲存為影像

    image模組的savesave_extended函式,可用於將繪製了影像的Surface表面物件儲存為檔案或IO物件。一個遊戲中可能包含多個Surface物件,他們也許繪製了遊戲中的某個角色或視窗的整個顯示區域。savesave_extended函式可根據檔案的副檔名來決定影像格式,如果無法得知檔案副檔名,那麽影像格式將被認定為tga(非壓縮)。

    當 Pygame 不支援擴充的影像格式時,save_extended函式會引發例外狀況NotImplementedError: saving images of extended format is not available。至於如何判斷 Pygame 是否支援擴充的影像格式,你可以檢視判斷遊戲是否支援擴充的影像格式一段。

    save(surface, filename, namehint='')
    save_extended(surface, filename, namehint='')

    surface 參數

    surface參數是需要被轉換的Surface表面物件。

    filename 參數

    filename參數是表示影像檔案路徑的字串,或包含影像檔案路徑的類路徑(path-like)物件,或可儲存影像資料的IO物件。

    namehint 參數

    namehint參數是一個用於提示檔案副檔名的字串,如果filename參數是一個IO物件,並且你希望傳遞檔案副檔名的話。

    save,save_extended 函式能夠儲存的影像格式有哪些?

    如果 Pygame 支援完整的擴充影像格式,那麽savesave_extended函式能夠將Surface表面物件儲存為以下的影像格式,bmpjpegjpg),pngtga(非壓縮)。

    save.py
    # 在執行腳本前,請將命令列跳躍至 save.py 所在的目錄
    from pygame import image, Surface
    
    # 載入影像檔案,並將他們繪製在表面物件 surface 中 sky = image.load('sky.webp') candy = image.load_extended('candy.png')
    surface = Surface((800, 600)) surface.blit(sky, (0, 0)) surface.blit(candy, (100, 100))

    # 將 surface 儲存至檔案,影像格式為 jpg image.save(surface, 'combine.jpg')

    save,save_extended 函式所使用的 IO 物件需要改變指標位置才能被重新載入

    如果使用savesave_extended函式,將Surface表面物件儲存至某個IO物件,那麽可能需要將IO物件的指標移動至開頭,才能使用image模組重新載入該IO物件。

    在下面的範例中,我們將Surface物件儲存到了IO物件中,之後需要呼叫IO物件的seek方法將指標移動至開頭,否則重新載入IO物件可能會導致例外狀況pygame.error: Unsupported image format

    reload.py
    # 在執行腳本前,請將命令列跳躍至 reload.py 所在的目錄
    from pygame import image
    
    # 將 surface 儲存至 IO 物件 import io bs = io.BytesIO() sky = image.load('sky.webp') # 指定影像格式為 png image.save(sky, bs, '.png')
    # 重新載入 IO 物件之前,需要將指標移動至開頭 bs.seek(0) new_sky = image.load(bs, '.png')

    將影像轉換為位元組序列物件

    image模組的tobytes函式,可用於將繪製了影像的Surface表面物件轉換為一個bytes位元組序列物件。當你使用該函式時,通常是希望將遊戲影像傳遞給其他 Python 套件進行處理。

    image模組的tostring函式與tobytes函式相同,你可以將其中一個視為另一個的別名,但建議采用tobytes

    tobytes(surface, format, flipped=False)

    surface 參數

    surface參數是被轉換為bytes位元組序列的Surface表面物件。

    format 參數

    format參數是一個字串,表示轉換所采用的色彩格式,擁有以下有效取值,'P'(采用 8 位調色板表示色彩),'RGB'(使用 24 個 bit 表示色彩,按照紅綠藍的順序),'RGBX'(使用 32 個 bit 表示色彩,按照紅綠藍的順序,末尾的 8 個比特不被使用),'RGBA'(使用 32 個 bit 表示色彩,按照紅綠藍透明度的順序),'ARGB'(使用 32 個 bit 表示色彩,按照透明度紅綠藍的順序),'BGRA'(使用 32 個 bit 表示色彩,按照藍綠紅透明度的順序),'RGBA_PREMULT'(使用 32 個 bit 表示色彩,按照紅綠藍透明度的順序,其中紅綠藍已經預先與透明度進行了計算),'ARGB_PREMULT'(使用 32 個 bit 表示色彩,按照透明度紅綠藍的順序,其中紅綠藍已經預先與透明度進行了計算)。

    flipped 參數

    flipped參數是一個布林值(預設為False),如果為True,則相當於先將Surface物件表示的影像進行垂直翻轉,然後再轉換為bytes位元組序列(這對於 Python PyOpenGL 套件可能是有效的)。

    在下面的範例中,我們使用tobytes函式將Surface物件轉換為bytes物件,然後使用PIL模組(需要安裝)將bytes物件儲存為影像檔案pil.sky.webp

    to_bytes.py
    # 在執行腳本前,請將命令列跳躍至 to_bytes.py 所在的目錄
    from pygame import image
    
    # 將 Surface 物件轉換為 bytes,色彩格式為 RGBA sky = image.load('sky.webp') bs = image.tobytes(sky, 'RGBA')
    # 使用 PIL 讀取 bytes,並將影像儲存為檔案 pil.sky.webp import PIL.Image i = PIL.Image.frombytes('RGBA', (729, 1296), bs) i.save('pil.sky.webp')

    將位元組序列物件轉換為影像

    image模組的frombytes函式,可用於將bytes位元組序列物件轉換為一個表示影像的Surface表面物件。當你使用該函式時,bytes位元組序列物件通常來自於其他 Python 套件,這意味著要將其他套件處理的影像轉換為Surface物件。

    image模組的fromstring函式與frombytes函式相同,你可以將其中一個視為另一個的別名,但建議采用frombytes

    frombytes(bytes, size, format, flipped=False)

    bytes 參數

    bytes參數是被轉換為Surface表面物件的bytes位元組序列。

    size 參數

    size參數是一個形式類似於(width,height)的元組,或形式類似於[width,height]的串列,其中width為影像的寬度,height為影像的高度。

    你不能隨意設定size參數,其表示的大小必須與bytes參數對應的影像的大小相同。

    format 參數

    format參數是一個字串,表示轉換所采用的色彩格式,擁有以下有效取值,'P'(采用 8 位調色板表示色彩),'RGB'(使用 24 個 bit 表示色彩,按照紅綠藍的順序),'RGBX'(使用 32 個 bit 表示色彩,按照紅綠藍的順序,末尾的 8 個比特不被使用),'RGBA'(使用 32 個 bit 表示色彩,按照紅綠藍透明度的順序),'ARGB'(使用 32 個 bit 表示色彩,按照透明度紅綠藍的順序),'BGRA'(使用 32 個 bit 表示色彩,按照藍綠紅透明度的順序)。

    flipped 參數

    flipped參數是一個布林值(預設為False),如果為True,則轉換後的Surface物件所表示的影像會被垂直翻轉。

    在下面的範例中,我們使用frombytes函式,將包含天空影像的bytes物件轉換為了Surface物件,並對影像進行了垂直翻轉。

    from_bytes.py
    # 在執行腳本前,請將命令列跳躍至 from_bytes.py 所在的目錄
    from pygame import image, display
    
    # 使用 PIL 讀取影像檔案,並轉換為 bytes 物件 import PIL.Image bs = PIL.Image.open('sky.webp').tobytes()
    # 將 bytes 物件轉換為 Surface 物件 sky = image.frombytes(bs, (729, 1296), 'RGB', True)
    # 建立遊戲視窗,繪製天空,並等候 2 秒鐘 s = display.set_mode((800, 600)) s.blit(sky, (0, 0)) display.flip()
    import time time.sleep(2)

    將位元組緩沖轉換為影像

    image模組的frombuffer函式,可用於將位元組緩沖區中的內容轉換為一個表示影像的Surface表面物件,該函式的參數的作用與frombytes函式類似,但存在以下不同。

    image模組的frombuffer函式的bytes參數可以是一個BufferProxybytesbytearraymemoryview,或遵守緩沖協定的物件。相對於frombytes函式,frombuffer函式的bytes參數額外支援'BGR'(使用 24 個 bit 表示色彩,按照藍綠紅的順序)。

    frombuffer(bytes, size, format)

    frombuffer 函式擁有更高的執行效率

    相對於frombytes函式,frombuffer函式擁有更高的執行效率,因為沒有分配和複製影像像素資料的過程。

    from_buffer.py
    # 在執行腳本前,請將命令列跳躍至 from_buffer.py 所在的目錄
    from pygame import image, display
    
    # 使用 PIL 讀取影像檔案,並轉換為 bytes 物件 import PIL.Image bs = PIL.Image.open('sky.webp').tobytes()
    # 將 bytes 物件轉換為 Surface 物件 sky = image.frombuffer(bs, (729, 1296), 'RGB', True)
    # 建立遊戲視窗,繪製天空,並等候 2 秒鐘 s = display.set_mode((800, 600)) s.blit(sky, (0, 0)) display.flip()
    import time time.sleep(2)

    取得 SDL_Image 的版本資訊

    image模組的get_sdl_image_version函式,其傳回值是一個元組,該元組包含了 SDL_Image 的版本資訊。

    get_sdl_image_version(linked=True)

    linked 參數

    如果linked參數為True,則函式get_sdl_image_version傳回目前所使用的 SDL_Image 的版本資訊,否則傳回 Pygame 套件在編譯階段所針對的 SDL_Image 版本。

    傳回值

    get_sdl_image_version函式的傳回值是一個形式類似於(major,minor,patch)的 Python 元組,其中major表示主要版本號碼,minor表示次要版本號碼,patch表示修補號碼。

    當你所安裝的 Pygame 版本不支援擴充影像格式時,get_sdl_image_version函式將傳回空值None,這反映了擴充影像格式的實作需要 SDL_Image。

    version.py
    from pygame import image
    
    # 取得 SDL_Image 版本 print(f'目前使用的 SDL_Image 版本:{image.get_sdl_image_version()}') print(f'編譯階段針對的 SDL_Image 版本:{image.get_sdl_image_version(False)}')
    目前使用的 SDL_Image 版本:(2, 0, 5)
    編譯階段針對的 SDL_Image 版本:(2, 0, 5)

    原始碼

    src/zh-hant/image·codebeatme/pygame·GitHub

    講解影片

    Pygame 影像載入,image 模組簡介·YouTube