Go를 사용하여 이미지에서 애니메이션 Gif 생성

개시하다


이 글은 Go Advent Calendar 2017 13일째 되는 글이다.
골랑이 이것저것 슬랙의 이모지를 할 때 이런 기사를 봤어요.
슬랙으로 초밥을 돌리는 기술.
gif 애니메이션의 구조를 조금 알 수 있는 시기이기 때문에 이게 Golang에서 gif 애니메이션화부터 업로드까지 단숨에 이루어질지도 모르지...?그렇게 생각하면서도 손을 대지 않았다.
이번에는 좋은 기회라서 gif 애니메이션 도구를 만들어 봤어요.
다음은 샘플입니다.


죄송합니다. 사이즈가 너무 커요!

개요


소스는 아래와 같다.
gif_anime_creator_go
다음 형식의 이미지를 애니메이션 Gif로 변환할 수 있습니다.
  • jpg
  • png
  • gif
  • 애니메이션 Gif도 간단하다. 그림이 오른쪽에서 왼쪽으로 위에서 아래로 흐른다.
    시작 방향과 끝 방향을 선택할 수 있기 때문에 샘플처럼 아래에서 나와 아래로 움츠릴 수도 있다.

    사용법


    gif_anime_creator_go [-start=position] [-end=position] image_file
    position에left,right,top,bottom을 넣을 수 있습니다.
    기본값은left와right입니다. 왼쪽에서 오른쪽으로 이동합니다.
    자유롭게 조합할 수 있으니 마음대로 이동하세요!
    배포용 실행 파일이 준비되지 않았기 때문에 잠시 후에 준비하겠습니다.

    걸려 넘어진 곳


    개발에서 좌절한 점을 소개하다.
    1. 이미지를 잘 이동하지 못함
    SubImage로 이미지를 자른 후 이동한 위치부터 그리면 될 것 같은데 한번 해보면 동작이 이상해져요.
    상상 속의 동작이 없어서 나는 그 속에 푹 빠졌다.
    해결책
    어려운 일을 할 필요가 없다.
    만약 그림을 그릴 때 위치를 틀리게 하면 다 그릴 수 있다.
    점이 x축(음수)일 때는 왼쪽으로, +(더하기)일 때는 오른쪽으로 이동합니다.
    Y축의 경우 - 위, +는 아래입니다.
    // Pointは(x,y)で表現されるので、ここをずらすだけでよい
    draw.Draw(Palette, Rectangle, Image, Point, draw.Src)
    
    2. 배경색 불투명
    이거 고민이 많았는데...
    팔레트에 투명색이 없다는 점은 초기에 알았지만, 자연스러워 보이기 위해 색상을 줄이면서도 투명색을 추가하는 방법을 몰라서 상당히 고민했는데...
    해결책
    나 이거 썼어.
    soniakeys/quant
    지정한 수량의 색을 줄일 수 있기 때문에 255색으로 줄인 후에 투명색을 추가하면 색 문제를 해결할 수 있다.
    이상의 프로그램 라이브러리는 이 문장을 참고하였다.
    Go 언어로 이미지 색상 줄이기
    (gif 애니메이션이 만들어졌는지 궁금하다.)
    3. 잔상 남기기
    gif 애니메이션의 제작은 매우 좋았지만 잔상을 남겼다. 마치 순식간에 감옥에서 사람을 죽이는 것과 같다.
    이전의 경험에서gif는 차분만 그리는 것을 알았지만 처음에는 어떻게 해야 할지 몰랐다.
    해결책
    gif 애니메이션은 프레임마다 몇 가지 그리기 모드가 있는데 모드에 따라 차분만 그립니다.
    Golang의 Gif에서 EncodeAll을 실행할 때 기본적으로 최적화(차분만)됩니다.
    이 점을 나는 전혀 이해하지 못한다.gif 애니메이션을 본 방법이 마침내 이해되었다.
    ※ 참고 링크
    GIF Animation and Disposal Methods - GIF Animation Studio
    Cover Sheet for the GIF89a Specification
    Golang의 GIF struct를 보면 Disposal이 있습니다.
    특히 아무것도 지정하지 않으면 0을 설정한다고 적혀 있다.
    type GIF struct {
            Image     []*image.Paletted // The successive images.
            Delay     []int             // The successive delay times, one per frame, in 100ths of a second.
            LoopCount int               // The loop count.
            // Disposal is the successive disposal methods, one per frame. For
            // backwards compatibility, a nil Disposal is valid to pass to EncodeAll,
            // and implies that each frame's disposal method is 0 (no disposal
            // specified).
            Disposal []byte
    
    이 같은 자료를 확인해 2를 디스패치에 설치Restore to background color해 동작을 시작했기 때문에 잔상이 전혀 남지 않았다.
    4. 그림에 수수께끼 같은 투명색
    몇 개의 그림을gif 애니메이션으로 만들 때 그림에 투명한 색이 나타나서 이상했다.draw.FloydSteinberg.Draw로 그린 거라 어떻게 하면 좋을지 고민이에요.
    해결책
    정지draw.FloydSteinberg.Draw, 사용draw.Draw 후에는 일어나지 않습니다.
    하지만 플라이드 스트린버그는 화질이 더 좋아 조금 완성됐을 때 외관이 나빠졌다.
    이것에 관해서는 지금 좋은 방법을 몰라서 당분간은 이렇게...

    남은 과제


    슬랙으로 순환하려고 했는데 이렇게 배열하면 제대로 연결이 안 돼.
    이와 관련해 향후 추가 기능을 할 계획이다.
    또 슬랙에 올리는 도구와 협업할 수 없기 때문에 저도 이걸 만들고 싶어요.

    감상


    처음엔 이해가 많이 안 될 줄 알았는데 그렇게 오래 걸리지 않아도 되는데 해보니까 여기저기 걸려 넘어져서 예상보다 시간이 더 걸렸어요.
    역시 해보면 배울 게 많군.

    참조 링크


    본문에서 언급한 내용 외에 다음과 같은 링크를 참고하였다.
    감사합니다.
    Go 언어로 애니메이션 GIF 만들기
    앞으로도 뭔가 하고 싶어요.m

    좋은 웹페이지 즐겨찾기