Golang đại pháp – 1.4 Xử lý ảnh GIF
golang
49
Go
50
White

nhaancs viết ngày 03/01/2018

Bài viết được đăng tải đầu tiên tại: http://nhaancs.com/golang-dai-phap-1-4-xu-ly-anh-gif/

golang dai phap

Chương trình tiếp theo sẽ trình bày các ứng dụng cơ bản của package image. Chúng ta sẽ tạo ra các hình ảnh bit-map và mã hoá chúng lại với nhau thành ảnh động GIF. Chương trình mới này giới thiệu từ khoá const, kiểu structcomposite literal. Không giống như hầu hết các ví dụ trước, lần này chúng ta dùng các tính toán trên số thực. Chúng ta chỉ nói sơ qua về các chủ đề trên, các phần sau sẽ nói chi tiết hơn, mục đích chủ yếu của phần này là giới thiệu về Go và chức năng của các thư viện liên quan.

// Chương trình Lissajous tạo ra ảnh động GIF
package main 

import(
    "image"
    "image/color"
    "image/gif"
    "io"
    "math"
    "math/rand"
    "os"
)
// bảng màu
var palatte = []color.Color{color.White, color.Black}

const (
    whiteIndex = 0 // first color in palatte
    blackIndex = 1 // next color in palatte
)

func main() {
    lissajous(os.Stdout)
}

func lissajous(out io.Writer) {
    const (
        cycles = 5 // number of complete x oscillator revolutions
        res = 0.001 // angular resolution 
        size = 100 // image canvas cover [-size .. +size]
        nframes = 64 // number of animation frames
        delay = 8 // delay between frames in 10ms units
    )

    freq := rand.Float64()*3.0 // relative frequency of y oscillator 
    anim := gif.GIF{LoopCount: nframes}
    phase := 0.0 // phase difference

    for i := 0; i < nframes; i++ {
        rect := image.Rect(0, 0, 2*size + 1, 2*size + 1)
        img := image.NewPaletted(rect, palatte)

        for t := 0.0; t < cycles*2*math.Pi; t += res {
            x := math.Sin(t)
            y := math.Sin(t*freq + phase)
            img.SetColorIndex(size + int(x*size + 0.5), size + int(y*size + 0.5), blackIndex) 
        }

        phase += 1
        anim.Delay = append(anim.Delay, delay)
        anim.Image = append(anim.Image, img)
    } 

    gif.EncodeAll(out, &anim) // NOTE: ignoring endcode errors 
}

Sau khi import package có đường dẫn bao gồm nhiều phần như image/color thì chúng ta gọi đến package đó bằng phần sau cùng, ví dụ biến color.White thuộc về package image/color.

Các hằng số được khai báo với từ khoá const có giá trị không đổi trong lúc biên dịch. Giống như var, chúng ta có thể khai báo hằng số ở cấp độ package hay khai báo bên trong hàm. Giá trị của constant phải thuộc một trong các kiểu number, string, boolean.

Biểu thức []color.Color{...}gif.GIF{...}composite literal, đây là một cách ngắn gọn để khởi tạo giá trị cho các kiểu kết hợp như . Trong hai ví dụ trên, đầu tiên là slice, sau đó là struct.

gif.GIF là kiểu struct. struct là một nhóm các giá trị, gọi là field, thường các field có các kiểu khác nhau được tập hợp lại trong một đối tượng. Biến anim là một struct kiểu gif.GIF. gif.GIF{LoopCount: nframes} là một composite literal set giá trị cho field loopCount bằng nframes; các field khác có giá trị zero theo kiểu của chúng. Một field của struct có thể được truy xuất bằng dấu chấm như sau: anim.Delay = append(anim.Delay, delay).

Function lissajous có hai vòng lặp lồng nhau. Vòng lặp bên ngoài lặp 64 lần, mỗi lần tạo ra 1 frame cho ảnh động. Nó tạo ra một hình ảnh mới có kích thước 201x201 với bảng màu gồm hai màu trắng và đen. Tất cả các pixel đều được thiết lập về giá trị zero của bảng màu (màu thứ 0 trong bảng màu mà chúng ta khai báo - màu trắng). Mỗi hình sẽ được truyền vào vòng lặp thứ 2 tạo ra một hình mới với một số pixel chuyển sang màu đen. Các kết quả được nối lại với các frame của anim bằng hàm append, thời giang delay được xác định là 80ms. Cuối cùng các frame và thời gian delay được mã hoá về định dạng GIF và được ghi vào output stream out. out có kiểu io.Writer giúp chúng ta có thể ghi kết qua ra nhiều nguồn khác nhau.

Vòng lặp bên trongtrong xử lý 2 đao động. Dao động theo trục x là hình sin, dao động theo trục y cũng là dao động hình sin nhưng tần số dao động trục x là một số ngẫu nhiên từ 0 đến 3 và pha dao động của trục x bang đầu là 0, sau đó tăng theo từng frame của ảnh. Vòng lặp kết thúc khi dao động theo trục x hoàn tấ 5 chu kỳ.Tại mỗi bước, hàm setColorIndex được gọi để tô màu cho pixel ứng với (x, y) thành màu đen (có vị trí 1 trong bảng màu).

Sau cùng, hàm lissajous được gọi trong main.

Chạy chương trình:

$ go build lissajous.go

$ ./lissajous > out.gif

Bài tập dành cho bạn:

Exercise 1.5: Thay đổi bảng màu của lissajous từ đen thành xanh lá cây. để tạo màu cho web, dùng color.RGBA{0xRR, 0xGG, 0xBB, 0xff}. Tìm hiểu thêm về các thành phần của hệ màu RGBA.

Exercise 1.6: Chỉnh sửa chương trình lissajous để tạo ra hình ảnh nhiều màu bằng các thêm các màu khác vào bảng màu và hiển thị chúng bằng cách thay dồi tham số thứ ba của hàm setColorIndex.

Reference: The Go Programming Language

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

nhaancs

11 bài viết.
4 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
2 0
Bài viết được đăng tải đầu tiên tại: http://nhaancs.com/golangdaiphap23khaibaobien/ Khai báo với từ khoá var tạo ra 1 biến có kiểu xác định, gán...
nhaancs viết 6 tháng trước
2 0
Bài viết liên quan
White
16 0
Crawl dữ liệu Crawl là một vấn đề hay gặp trong quá trình làm software. Ví dụ lấy tin tức, tin giảm giá, vé xem phim... là những dạng của crawl. Mộ...
Thach Le viết hơn 2 năm trước
16 0
White
44 7
Là một người thường xuyên đọc Quora, có một điểm cá nhân tôi thấy rất ấn tượng ở quora chính là khả năng autocomplete với tốc độ ánh sáng. (Ảnh) ...
huydx viết 6 tháng trước
44 7
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
11 bài viết.
4 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!