---
title: 'Đẻ thêm chức năng viết theo Series'
date: '2026-06-25T16:05:05+07:00'
author: XV5HP
tags:
  - halftone-dither
  - ordered-bayer
draft: false
summary: 'Anh có thể làm tính năng gom các bài blog cùng một chủ đề hoặc cùng một chuỗi nội dung lại với nhau không?'
image: /uploads/2026/06/a6e8005efb3356f3.webp
series: lazyblog
part: 3
---

Lòng tham của con người đúng là vô đáy. Lúc đầu chỉ nghĩ tạo LazyBlog để viết blog dạng markdown với cơ chế gắn nhiều tag cho từng bài để dễ theo dõi trong cùng một chủ đề. Anh em bạn dì đưa góp ý hay "Anh có thể làm tính năng gom các bài blog cùng một chủ đề hoặc cùng một chuỗi nội dung lại với nhau không". Như vậy chẳng dễ theo dõi hơn là tag sao? Như bài viết này viết về về chức năng **Series**, được đặt gọn gàng trong loạt bài liên quan tới **LazyBlog**

![](/uploads/2026/06/a6e8005efb3356f3.webp)

Ban đầu nghĩ chỉ cần tạo thêm một gạch đầu dòng `series` ghi theo kiểu slug không dấu như trong file Markdown của bài post   `content/posts/2026-06-18-rtl-sdr-cho-nguoi-moi.md` là xong thôi. Nhưng khi đạt được điều kiện về ăn no mặc ấm, người ta lại đòi thêm ăn ngon mặc đẹp. Nếu các chủ đề có vài dòng miêu tả, hay thêm tấm ảnh đại diện để hiển thị bên ngoài thì khác gì một phòng tranh đâu. 
```
---
title: 'Chức năng Series'
date: '2026-06-25T16:05:05+07:00'
author: XV5HP
draft: false
series: lazyblog
part: 3
---
```

Vì cái ý tưởng như một phòng tranh ở trang hiển thị, đã đẩy đưa chức năng này phải lưu thêm các thông tin **metadata** (manifest)  thì hệ thống mới biết lấy cái gì ở đâu mà hiển thị. Hệ thống lại phức tạp thêm vài trăm dòng code nữa chỉ để giúp con người thoả mãn cái đẹp. Các thông tin này lưu ở `content/series/lazyblog/manifest.json`. Nào là ảnh, nào là tiêu đề, miêu tả, ngày tạo, vân vân mây mây.
```
{
    "title": "Lazyblog",
    "description": "Ghi chép vụn vặt về những câu chuyện tạo ra lazyblog",
    "updated_at": "2026-06-25T16:33:18+07:00"
}
```

Phần chữ thì dễ thể hiện rồi, nhưng sẽ hơi nhàm nên cần chút đặc sắc hơn ở phần thị giác. Mà cái cốt lõi mà tôi mong muốn là ảnh đưa lên phải đồng nhất với phong cách thiết kế của LazyBlog. Tức là, nó cần phải đạt được tiêu chí nhiễu, khó nhìn, nhìn phải Art-Art, chẳng giống ai, mang tính độc nhất, lại phải nhoè nhoè với lớp phủ màu theo màu chủ đạo của giao diện. 

Thế là tôi nhớ tới **halftone dither** — kỹ thuật in báo những năm 60, lấy các chấm đen mật độ khác nhau để giả lập tông xám trên giấy không in được sắc xám. Pipeline tôi viết cho LazyBlog đại khái thế này: ảnh upload lên cho dù nó ở định dạng gì JPG/PNG/WebP hay kích thước nào đều bị thư viện Imagick crop thành một ô vuông 600×600. Việc này sẽ đảm bảo cho layout của series không bị nhảy lung tung. Hình ảnh sau đó đổ sang grayscale. Thằng em Claude bảo nên sử dụng hàm `orderedDitherImage('o4x4,2')` để sử dụng thuật toán ordered Bayer 4×4 chạy native trong libMagick, output 1-bit: mỗi pixel chỉ có thể là đen tuyệt đối hoặc trắng tuyệt đối chứ không có kiểu nhờ nhờ.

![Ảnh gốc ban đầu](/uploads/2026/06/2e862a81f0d1c797.webp)
![Chuyển sang trắng đen](/uploads/2026/06/0511f20171c285ed.webp)
![Áp dụng Ordered Bayer](/uploads/2026/06/67c97801851fa1e7.webp)
![Lớp phủ Amber](/uploads/2026/06/5fcfbdd77b817a2c.webp)
![Lớp phủ Green](/uploads/2026/06/ca9b662b4df0c016.webp)

Thằng em cố tình chọn **Ordered Bayer** chứ không phải **error-diffusion** (Floyd–Steinberg, Atkinson). Bởi vì **error-diffusion** cho ra noise kiểu phim chụp, còn **Ordered Bayer** cho ra lưới chấm răm rắp, đều như nhịp máy in cũ, đúng cái aesthetic  mấy chục năm qua như tôi muốn. Thay vì hiển thị ảnh đen-trắng, tôi bảo thằng em cho thêm một lớp phủ màu phía trước ảnh, ăn theo màu chủ đạo của giao diện LazyBlog. Toàn bộ sự chuyển màu xảy ra ở GPU của trình duyệt, tức là máy tính của bạn sẽ làm công việc ấy thay server của LazyBlog. Cuối cùng sản phẩm là  cái ảnh đại diện của series nhìn vừa "nhoè nhoè vintage". Sau khi khoe với anh em về tính năng mới này, họ chỉ lặng lẽ để lại vài thứ cảm thán trong đoạn hội thoại trao đổi với tôi.

```
[25/6/26 16:19] Cookie Hân Hoan: ngon chưa =))
[25/6/26 16:19] Cookie Hân Hoan: viết thêm vài dòng miêu tả đi =))
[25/6/26 16:19] Em Trung: Oceee a ơi, dạo này có vẻ nó nặng hơn r đấy =)))
```

```
[25/6/26 15:03] Cookie Hân Hoan: cái series để hết cover về ảnh dạng dot
[25/6/26 15:03] Cookie Hân Hoan: =))
[25/6/26 15:39] Vũ Phong: kinh vler sir
[25/6/26 15:39] Vũ Phong: please 😄
[25/6/26 15:39] Vũ Phong: nó bị ghê ghê :v
[25/6/26 15:39] Vũ Phong: âm bản
```
