第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何將gif分割成圖像

如何將gif分割成圖像

Go
ibeautiful 2021-11-15 20:50:19
如何在go中將gif拆分為圖像?image/gif 的 DecodeAll 返回 GIF,其中包含一個調色板數(shù)組。但是不知道如何將每個調色板轉換為圖像?
查看完整描述

2 回答

?
慕無忌1623718

TA貢獻1744條經驗 獲得超4個贊

考慮以下事項:

幀可以包含透明像素或區(qū)域,一個很好的例子是維基百科上的這張圖像(我猜)每幀都有這些全色塊之一,其余的幀是透明的。


這給您帶來了一個問題:特別是對于不使用多個幀來創(chuàng)建真彩色靜態(tài)圖像的動畫 GIF,DecodeAll返回的幀不是您實際看到的幀,例如,如果您在瀏覽器中打開圖像。


您必須以與瀏覽器相同的方式處理圖像,即將舊框架保留在某種畫布上并用新框架覆蓋。但此并非總是如此。GIF 幀可以,AFAIK,包含處理方法,指定您應該如何(或如果?)處理幀。


無論如何,為了達到您的目的,在大多數(shù)情況下也適用的最簡單方法是


import (

    "errors"

    "fmt"

    "image"

    "image/draw"

    "image/gif"

    "image/png"

    "io"

    "os"

)


// Decode reads and analyzes the given reader as a GIF image

func SplitAnimatedGIF(reader io.Reader) (err error) {

    defer func() {

        if r := recover(); r != nil {

            err = fmt.Errorf("Error while decoding: %s", r)

        }

    }()


    gif, err := gif.DecodeAll(reader)


    if err != nil {

        return err

    }


    imgWidth, imgHeight := getGifDimensions(gif)


    overpaintImage := image.NewRGBA(image.Rect(0, 0, imgWidth, imgHeight))

    draw.Draw(overpaintImage, overpaintImage.Bounds(), gif.Image[0], image.ZP, draw.Src)


    for i, srcImg := range gif.Image {

        draw.Draw(overpaintImage, overpaintImage.Bounds(), srcImg, image.ZP, draw.Over)


        // save current frame "stack". This will overwrite an existing file with that name

        file, err := os.Create(fmt.Sprintf("%s%d%s", "<some path>", i, ".png"))

        if err != nil {

            return err

        }


        err = png.Encode(file, overpaintImage)

        if err != nil {

            return err

        }


        file.Close()

    }


    return nil

}


func getGifDimensions(gif *gif.GIF) (x, y int) {

    var lowestX int

    var lowestY int

    var highestX int

    var highestY int


    for _, img := range gif.Image {

        if img.Rect.Min.X < lowestX {

            lowestX = img.Rect.Min.X

        }

        if img.Rect.Min.Y < lowestY {

            lowestY = img.Rect.Min.Y

        }

        if img.Rect.Max.X > highestX {

            highestX = img.Rect.Max.X

        }

        if img.Rect.Max.Y > highestY {

            highestY = img.Rect.Max.Y

        }

    }


    return highestX - lowestX, highestY - lowestY

}

(未經測試,但應該可以工作)


請注意,gif.DecodeAll可能并且會經常發(fā)生恐慌,因為互聯(lián)網上的許多 GIF 圖像都有些損壞。您的瀏覽器會嘗試解碼它們,例如,將用黑色替換缺失的顏色。image/gif不會那樣做,而是恐慌。這就是為什么我們defer將recover.


此外,我使用 的getGifDimensions原因與上述類似:單幀不必是您在瀏覽器中看到的內容。在這種情況下,幀僅比完整圖像小,這就是為什么我們必須迭代所有幀并獲得圖像的“真實”尺寸。


如果你真的真的想這樣做是正確的,你應該閱讀GIF規(guī)范GIF87aGIF89a的讓人覺得這篇文章是一個更容易理解。從中,您應該決定如何處理框架以及在重繪時如何處理透明度。

編輯:如果您在線拆分一些 GIF,則可以輕松觀察到前面提到的一些效果,例如這個這個- 玩弄“忽略優(yōu)化”和“使用前一幀的細節(jié)重新繪制每一幀”以了解我的意思。


查看完整回答
反對 回復 2021-11-15
?
喵喵時光機

TA貢獻1846條經驗 獲得超7個贊

image.Image是一個接口,并*image.Paletted實現(xiàn)了該接口,例如,如果您想將 GIF 的每一幀保存到 PNG 文件中,您只需對每個圖像進行編碼:


for i, frame := range img.Image {

    frameFile, err := os.OpenFile(fmt.Sprintf("%d.png", i+1), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)

    if err != nil {

        log.Fatal(err)

    }

    err = png.Encode(frameFile, frame)

    if err != nil {

        log.Fatal(err)

    }

    // Not using defer here because we're in a loop, not a function.

    frameFile.Close()

}


查看完整回答
反對 回復 2021-11-15
  • 2 回答
  • 0 關注
  • 218 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號