termpic 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index.mjs +22 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,6 +39,8 @@ toAnsi(grid); // そのままターミナルに貼れる
|
|
|
39
39
|
| `quadrant` | 2x2 | 明暗2色 | 横の解像度がほしいとき |
|
|
40
40
|
| `braille` | 2x4 | 点と地の2色 | 最も細かい。輪郭がはっきり出る |
|
|
41
41
|
|
|
42
|
+
`quadrant` は、4つの小マスの明度差が小さいマスを単色で塗ります。差が無いのに明暗2色に分けると、平坦な面に無意味な模様が出るためです(実写真で測ると閾値 0.03 でちょうど無くなります)。
|
|
43
|
+
|
|
42
44
|
`braille` は 1 マスに 2x4 の点を持てるので `halfblock` の4倍の解像度になります。点の有無は**画像全体の平均の明度**で決めます。マスごとの中間値で切ると、一様なマスが必ず全点灯になって図地が反転するためです。点の色に加えて点が付かない側の平均も背景色として持たせているので、写真でも図地が反転しません。
|
|
43
45
|
|
|
44
46
|
## 画像から色を抽出する
|
|
@@ -52,7 +54,7 @@ const palette = extractPalette(bitmap, 16);
|
|
|
52
54
|
convert(bitmap, { palette });
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
中央値分割法です。色空間の直方体を最も幅の広い軸の中央値で切る操作を、箱が指定数になるまで繰り返します。画像の色数が要求より少ない場合は、重複を除いた色数だけを返します。
|
|
56
58
|
|
|
57
59
|
## 輪郭を拾う
|
|
58
60
|
|
package/dist/index.mjs
CHANGED
|
@@ -156,10 +156,29 @@ function convert(bitmap, options = {}) {
|
|
|
156
156
|
cells
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* ほぼ一様なマスとみなす明度の幅。
|
|
161
|
+
*
|
|
162
|
+
* これ未満のマスを明暗に二分しても、前景色と背景色がほぼ同じなので
|
|
163
|
+
* 描き分けの意味がなく、平坦な面に無意味な模様が出るだけになる。
|
|
164
|
+
* 実写真で測ると 0.03 で無意味な分割がちょうど無くなり、
|
|
165
|
+
* それ以上に上げると実際の描き分けまで潰れる。
|
|
166
|
+
*/
|
|
167
|
+
const FLAT_CELL_RANGE = .03;
|
|
159
168
|
/** 明るい側と暗い側に二分し、どの小マスが明るい側かをビットで返す */
|
|
160
169
|
function splitByLightness(colors) {
|
|
161
170
|
const levels = colors.map((color) => toOklab(color).L);
|
|
162
|
-
const
|
|
171
|
+
const lowest = Math.min(...levels);
|
|
172
|
+
const highest = Math.max(...levels);
|
|
173
|
+
if (highest - lowest < FLAT_CELL_RANGE) {
|
|
174
|
+
const flat = averageHex(colors);
|
|
175
|
+
return {
|
|
176
|
+
bits: (1 << colors.length) - 1,
|
|
177
|
+
light: flat,
|
|
178
|
+
dark: flat
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const middle = (lowest + highest) / 2;
|
|
163
182
|
let bits = 0;
|
|
164
183
|
const lightGroup = [];
|
|
165
184
|
const darkGroup = [];
|
|
@@ -326,7 +345,7 @@ function extractPalette(bitmap, count = 16, sampleLimit = 2e4) {
|
|
|
326
345
|
...boxes.slice(target + 1)
|
|
327
346
|
];
|
|
328
347
|
}
|
|
329
|
-
|
|
348
|
+
const colors = boxes.filter((box) => box.length > 0).map((box) => {
|
|
330
349
|
const sum = box.reduce((total2, pixel) => ({
|
|
331
350
|
r: total2.r + pixel.r,
|
|
332
351
|
g: total2.g + pixel.g,
|
|
@@ -342,6 +361,7 @@ function extractPalette(bitmap, count = 16, sampleLimit = 2e4) {
|
|
|
342
361
|
b: Math.round(sum.b / box.length)
|
|
343
362
|
});
|
|
344
363
|
});
|
|
364
|
+
return [...new Set(colors)];
|
|
345
365
|
}
|
|
346
366
|
/** 輪郭の向きに割り当てる文字。添字は 0=横 / 1=右下がり / 2=縦 / 3=右上がり */
|
|
347
367
|
const EDGE_CHARS = [
|