├── 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 --------------------------------------------------------------------------------