├── Dockerfile
├── README.md
├── go.mod
├── go.sum
├── main.go
├── submit_gif.jpg
└── test_images
├── big.gif
└── small.gif
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:latest
2 |
3 | LABEL version="1.0"
4 | LABEL maintainer="shindu666@gmail.com"
5 |
6 | RUN apt-get -y update \
7 | && apt-get install -y git curl wget libpng-dev libtool libgif-dev autoconf automake make gcc g++
8 |
9 | RUN curl -O https://storage.googleapis.com/golang/go1.11.1.linux-amd64.tar.gz \
10 | && tar xvf go1.11.1.linux-amd64.tar.gz
11 |
12 | ENV PATH $PATH:/go/bin
13 |
14 | WORKDIR /usr/local/webp
15 | RUN wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.0.tar.gz \
16 | && tar -xvzf libwebp-1.0.0.tar.gz \
17 | && mv libwebp-1.0.0 libwebp && \
18 | rm libwebp-1.0.0.tar.gz && \
19 | cd libwebp && \
20 | ./configure --enable-everything && \
21 | make && \
22 | make install && \
23 | cd .. && \
24 | rm -rf libwebp
25 |
26 | ENV PATH $PATH:/usr/local/webp/libwebp-0.5.0-linux-x86-64/bin
27 |
28 | RUN ldconfig
29 |
30 | RUN mkdir -p /examples
31 |
32 | COPY test_images/* /examples/
33 |
34 | RUN mkdir -p /gif2web_api
35 |
36 | EXPOSE 8080 8080
37 |
38 | COPY go.mod /gif2web_api
39 | COPY main.go /gif2web_api
40 | WORKDIR /gif2web_api
41 |
42 | CMD ["go", "run", "main.go"]
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Webp
2 |
3 | ## Purpose
4 |
5 | This project is supposed to be for learning.
6 |
7 | * Why docker?
8 |
9 | - I dont want to install `webp` related libs to the host machine. Docker is very handy in order to keep environment clean.
10 |
11 |
12 | ## Description
13 |
14 | `gif2webp` converts a GIF image to a WebP image.
15 |
16 | ## Run
17 |
18 | 0. Clone the repository.
19 |
20 | 1. Build and run container:
21 |
22 | ```bash
23 | $> sudo docker build -t gif2webp .
24 | $> sudo docker run -it --rm -p 8080:8080 gif2webp
25 | # You will see:
26 | ... Start gif2web server on 8080
27 | ```
28 |
29 | 2. Submit a `POST` request to `http://localhost:8080/convert?quality=30` with `gif` image. The `quality` parameter can be from `0` to `100`.
30 |
31 |

32 |
33 | The `gif` will be converted to `webp` and sended in response.
34 |
35 | ## Tips
36 |
37 | BTC - 19SYMA2hqRZHRSL4di35Uf7jV87KBKc9bf
38 |
39 | ETH - 0xD7cc10f0d70Fd8f9fB83D4eF9250Fc9201981e3a
40 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module webp_as_service
2 |
3 | require golang.org/x/image v0.0.0-20180926015637-991ec62608f3
4 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | golang.org/x/image v0.0.0-20180926015637-991ec62608f3 h1:5IfA9fqItkh2alJW94tvQk+6+RF9MW2q9DzwE8DBddQ=
2 | golang.org/x/image v0.0.0-20180926015637-991ec62608f3/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
3 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "io"
6 | "log"
7 | "mime/multipart"
8 | "net/http"
9 | "os/exec"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | const (
15 | B uint64 = 1
16 | KB uint64 = 1 << (10 * iota)
17 | MB
18 | GB
19 | TB
20 | PB
21 | EB
22 | )
23 |
24 | const maxSize = 24 * KB
25 |
26 | func main() {
27 | log.Printf("Start gif2web server on 8080")
28 | http.Handle("/convert", gifProcessor())
29 | http.ListenAndServe("0.0.0.0:8080", nil)
30 | }
31 |
32 | func gifProcessor() http.HandlerFunc {
33 | return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
34 | if err := req.ParseMultipartForm(maxSize); nil != err {
35 | log.Printf("Error while parse: %s", err)
36 | w.WriteHeader(http.StatusInternalServerError)
37 | return
38 | }
39 | for _, fheaders := range req.MultipartForm.File {
40 | for _, hdr := range fheaders {
41 | log.Printf("Income file len: %d", hdr.Size)
42 |
43 | var err error
44 | var infile multipart.File
45 | if infile, err = hdr.Open(); err != nil {
46 | log.Printf("[ERROR] Handle open error: %v", err)
47 | w.WriteHeader(http.StatusInternalServerError)
48 | return
49 | }
50 | quality := req.URL.Query().Get("quality")
51 | if quality == "" {
52 | quality = "0"
53 | }
54 | q, err := strconv.ParseInt(quality, 10, 64)
55 | if err != nil || q < 0 || q > 100 {
56 | log.Printf("[ERROR] Bad quality params: %s %v", err, q)
57 | w.WriteHeader(http.StatusInternalServerError)
58 | return
59 | }
60 | cmd := exec.Command("gif2webp", "-mixed", "-q", strconv.Itoa(int(q)), "-o", "-", "--", "-")
61 |
62 | cmd.Stdin = io.Reader(infile)
63 |
64 | var out bytes.Buffer
65 | cmd.Stdout = &out
66 |
67 | var errout bytes.Buffer
68 | cmd.Stderr = &errout
69 |
70 | err = cmd.Run()
71 | if err != nil {
72 | log.Printf("[ERROR] Webp Output: %v, %v, %v\n", err, out.String(), errout.String())
73 | w.WriteHeader(http.StatusInternalServerError)
74 | return
75 | }
76 | output := out.String()
77 | reader := strings.NewReader(output)
78 | imageLen := reader.Len()
79 | log.Printf("Outcome file len: %d", reader.Len())
80 | w.Header().Set("Content-Type", "image/webp")
81 | w.Header().Set("Content-Length", strconv.Itoa(imageLen))
82 | w.WriteHeader(http.StatusOK)
83 | io.Copy(w, reader)
84 | return
85 | }
86 | }
87 |
88 | w.WriteHeader(http.StatusInternalServerError)
89 | })
90 | }
91 |
--------------------------------------------------------------------------------
/submit_gif.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roman-kiselenko/gif2webp-docker/c3fda104399fae0db7aef374e997f82bdbab871c/submit_gif.jpg
--------------------------------------------------------------------------------
/test_images/big.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roman-kiselenko/gif2webp-docker/c3fda104399fae0db7aef374e997f82bdbab871c/test_images/big.gif
--------------------------------------------------------------------------------
/test_images/small.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roman-kiselenko/gif2webp-docker/c3fda104399fae0db7aef374e997f82bdbab871c/test_images/small.gif
--------------------------------------------------------------------------------