添加全彩
This commit is contained in:
313
lib/1.lua
313
lib/1.lua
@@ -1,313 +0,0 @@
|
||||
local f1 = {
|
||||
{
|
||||
"\159\143\159\143\139\143",
|
||||
"ffffff",
|
||||
"000000",
|
||||
},
|
||||
{
|
||||
"\128\149\159\137\143\155",
|
||||
"00ffff",
|
||||
"ff0000",
|
||||
},
|
||||
{
|
||||
"\130\151\128\148\148\148",
|
||||
"000000",
|
||||
"ffffff",
|
||||
},
|
||||
{
|
||||
"\136\135\159\133\149\138",
|
||||
"00f00f",
|
||||
"ff0ff0",
|
||||
},
|
||||
}
|
||||
|
||||
local f2 = {
|
||||
{
|
||||
"\159\143\159\143\139\143",
|
||||
"ffffff",
|
||||
"000000",
|
||||
},
|
||||
{
|
||||
"\128\149\151\157\153\151",
|
||||
"00ffff",
|
||||
"ff0000",
|
||||
},
|
||||
{
|
||||
"\130\151\157\140\136\140",
|
||||
"00ffff",
|
||||
"ff0000",
|
||||
},
|
||||
{
|
||||
"\136\135\149\142\134\145",
|
||||
"00f00f",
|
||||
"ff0ff0",
|
||||
},
|
||||
}
|
||||
|
||||
local f3 = {
|
||||
{
|
||||
"\159\143\132\159\128\148",
|
||||
"ff0f00",
|
||||
"00f0ff",
|
||||
},
|
||||
{
|
||||
"\159\133\144\144\129\149",
|
||||
"ff0000",
|
||||
"00ffff",
|
||||
},
|
||||
{
|
||||
"\128\129\144\130\143\157",
|
||||
"0f00f0",
|
||||
"f0ff0f",
|
||||
},
|
||||
{
|
||||
"\130\149\128\131\128\149",
|
||||
"0f0000",
|
||||
"f0ffff",
|
||||
},
|
||||
}
|
||||
|
||||
local f4 = {
|
||||
{
|
||||
"\128\148\128\128\148\128",
|
||||
"000000",
|
||||
"ffffff",
|
||||
},
|
||||
{
|
||||
"\130\151\130\131\151\131",
|
||||
"000000",
|
||||
"ffffff",
|
||||
},
|
||||
{
|
||||
"\136\151\149\131\131\149",
|
||||
"00f000",
|
||||
"ff0fff",
|
||||
},
|
||||
{
|
||||
"\159\149\143\153\153\143",
|
||||
"f0f0ff",
|
||||
"0f0f00",
|
||||
},
|
||||
}
|
||||
|
||||
local n = {" ","ffffff","ffffff"}
|
||||
|
||||
-- 创建 img 表结构
|
||||
local img = {}
|
||||
for i1 = 1, 8 do
|
||||
img[i1] = {}
|
||||
for i2 = 1, 4 do
|
||||
img[i1][i2] = {}
|
||||
end
|
||||
end
|
||||
|
||||
-- ✅ 关键修复:将 logon 改为函数,每次返回新表
|
||||
local function logon()
|
||||
return {
|
||||
" ",
|
||||
"fffffffffffffffffffffffff",
|
||||
"fffffffffffffffffffffffff"
|
||||
}
|
||||
end
|
||||
|
||||
-- 定义 logo 为普通表(不是函数)
|
||||
local logo = {
|
||||
{
|
||||
" \139 ",
|
||||
"fffffff0000000f000fffffff",
|
||||
"ffffffffffffff0ffffffffff"
|
||||
},
|
||||
{
|
||||
" \143\129\149 \132 ",
|
||||
"fffffff0000ff00000fffffff",
|
||||
"fffffffffff00f00fffffffff"
|
||||
},
|
||||
{
|
||||
" \159\135 \149\143\158\135\149 ",
|
||||
"fffffff0ff00000ff0fffffff",
|
||||
"ffffffff00000ff00ffffffff"
|
||||
},
|
||||
{
|
||||
" \149 \143\150\144 \131\133 ",
|
||||
"ffffffff00000f0000fffffff",
|
||||
"fffffff00000f0fffffffffff"
|
||||
},
|
||||
{
|
||||
" \149 \136 \149 \131\144 ",
|
||||
"ffffffff00f00f0f00fffffff",
|
||||
"fffffff0000ff000fffffffff"
|
||||
},
|
||||
{
|
||||
" \138 \131\133 \149 ",
|
||||
"fffffff00000ff0000fffffff",
|
||||
"ffffffff00000000fffffffff"
|
||||
},
|
||||
{
|
||||
" \130\139\144 \149 ",
|
||||
"fffffff000f0000000fffffff",
|
||||
"ffffffffff000000fffffffff"
|
||||
},
|
||||
{
|
||||
" \143\131 \135 ",
|
||||
"fffffff00ff0000000fffffff",
|
||||
"fffffffff000000ffffffffff"
|
||||
},
|
||||
{
|
||||
" \143\131 ",
|
||||
"fffffff00000000000fffffff",
|
||||
"fffffffff000fffffffffffff"
|
||||
},
|
||||
{
|
||||
" \143\135\129 ",
|
||||
"fffffff00000000000fffffff",
|
||||
"fffffffffffffffffffffffff"
|
||||
},
|
||||
}
|
||||
|
||||
local logo1 = {{},{},{},{}}
|
||||
|
||||
-- 第一组
|
||||
for i = 1, 3 do
|
||||
table.insert(logo1[1], logon())
|
||||
end
|
||||
-- 插入 logo 的每一帧
|
||||
for _, frame in ipairs(logo) do
|
||||
table.insert(logo1[1], frame)
|
||||
end
|
||||
for i = 1, 2 do
|
||||
table.insert(logo1[1], logon())
|
||||
end
|
||||
logo1[1].duration = 1
|
||||
|
||||
-- 第二组
|
||||
for i = 1, 2 do
|
||||
table.insert(logo1[2], logon())
|
||||
end
|
||||
for _, frame in ipairs(logo) do
|
||||
table.insert(logo1[2], frame)
|
||||
end
|
||||
for i = 1, 3 do
|
||||
table.insert(logo1[2], logon())
|
||||
end
|
||||
|
||||
-- 第三组
|
||||
table.insert(logo1[3], logon())
|
||||
for _, frame in ipairs(logo) do
|
||||
table.insert(logo1[3], frame)
|
||||
end
|
||||
for i = 1, 4 do
|
||||
table.insert(logo1[3], logon())
|
||||
end
|
||||
|
||||
-- 第四组
|
||||
for _, frame in ipairs(logo) do
|
||||
table.insert(logo1[4], frame)
|
||||
end
|
||||
for i = 1, 5 do
|
||||
table.insert(logo1[4], logon())
|
||||
end
|
||||
|
||||
-- 填充 img 前 4 行
|
||||
for i = 1, 4 do
|
||||
img[i] = logo1[i]
|
||||
end
|
||||
|
||||
-- 清理临时变量
|
||||
logo1 = nil
|
||||
logo = nil
|
||||
|
||||
-- 构建 img[5] 到 img[8]
|
||||
for i=1,3 do
|
||||
img[5][1][i] = n[i] .. f2[4][i] .. n[i] .. f4[4][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[5][2][i] = n[i] .. n[i] .. n[i] .. n[i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[5][3][i] = n[i] .. n[i] .. n[i] .. n[i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[5][4][i] = f1[1][i] .. n[i] .. f3[1][i] .. n[i]
|
||||
end
|
||||
|
||||
for i=1,3 do
|
||||
img[6][1][i] = n[i] .. f2[3][i] .. n[i] .. f4[3][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[6][2][i] = n[i] .. f2[4][i] .. n[i] .. f4[4][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[6][3][i] = f1[1][i] .. n[i] .. f3[1][i] .. n[i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[6][4][i] = f1[2][i] .. n[i] .. f3[2][i] .. n[i]
|
||||
end
|
||||
|
||||
for i=1,3 do
|
||||
img[7][1][i] = n[i] .. f2[2][i] .. n[i] .. f4[2][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[7][2][i] = f1[1][i] .. f2[3][i] .. f3[1][i] .. f4[3][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[7][3][i] = f1[2][i] .. f2[4][i] .. f3[2][i] .. f4[4][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[7][4][i] = f1[3][i] .. n[i] .. f3[3][i] .. n[i]
|
||||
end
|
||||
|
||||
for i=1,3 do
|
||||
img[8][1][i] = f1[1][i] .. f2[1][i] .. f3[1][i] .. f4[1][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[8][2][i] = f1[2][i] .. f2[2][i] .. f3[2][i] .. f4[2][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[8][3][i] = f1[3][i] .. f2[3][i] .. f3[3][i] .. f4[3][i]
|
||||
end
|
||||
for i=1,3 do
|
||||
img[8][4][i] = f1[4][i] .. f2[4][i] .. f3[4][i] .. f4[4][i]
|
||||
end
|
||||
|
||||
-- 清理
|
||||
f1 = nil
|
||||
f2 = nil
|
||||
f3 = nil
|
||||
f4 = nil
|
||||
n = nil
|
||||
|
||||
img.animation = true
|
||||
img.secondsPerFrame = 0.1
|
||||
|
||||
-- ✅ 现在可以安全序列化
|
||||
print(textutils.serialize(img[1]))
|
||||
|
||||
|
||||
local function drawFrame(frame, term)
|
||||
for y, row in ipairs(frame) do
|
||||
term.setCursorPos(1, y)
|
||||
term.blit(table.unpack(row))
|
||||
end
|
||||
if frame.palette then for i = 0, #frame.palette do
|
||||
local c = frame.palette[i]
|
||||
if type(c) == "table" then term.setPaletteColor(2^i, table.unpack(c))
|
||||
else term.setPaletteColor(2^i, c) end
|
||||
end end
|
||||
if img.multiMonitor then term.setTextScale(img.multiMonitor.scale or 0.5) end
|
||||
end
|
||||
|
||||
|
||||
|
||||
term.clear()
|
||||
for i, frame in ipairs(img) do
|
||||
drawFrame(frame, term)
|
||||
if img.animation then sleep(frame.duration or img.secondsPerFrame or 0.05)
|
||||
else read() break end
|
||||
end
|
||||
read()
|
||||
term.setBackgroundColor(colors.black)
|
||||
term.setTextColor(colors.white)
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
for i = 0, 15 do term.setPaletteColor(2^i, term.nativePaletteColor(2^i)) end
|
||||
|
||||
284
lib/1.py
Normal file
284
lib/1.py
Normal file
@@ -0,0 +1,284 @@
|
||||
import json
|
||||
import struct
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Base64 字母表(CC:Tweaked 使用的自定义顺序)
|
||||
B64STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
B64MAP = {ch: i for i, ch in enumerate(B64STR)}
|
||||
|
||||
|
||||
def custom_b64decode(s):
|
||||
"""使用自定义字母表解码 base64 字符串(忽略 '=')"""
|
||||
val = 0
|
||||
bits = 0
|
||||
out = bytearray()
|
||||
for ch in s:
|
||||
if ch == '=':
|
||||
continue
|
||||
val = (val << 6) | B64MAP[ch]
|
||||
bits += 6
|
||||
if bits >= 8:
|
||||
bits -= 8
|
||||
out.append((val >> bits) & 0xFF)
|
||||
return bytes(out)
|
||||
|
||||
|
||||
def decode_frame(data):
|
||||
# 验证头部
|
||||
assert data[:4] == b'\x00\x00\x00\x00', "Invalid frame header (first 4 bytes)"
|
||||
assert data[8:16] == b'\x00\x00\x00\x00\x00\x00\x00\x00', "Invalid frame header (bytes 8-15)"
|
||||
|
||||
width, height = struct.unpack('<HH', data[4:8])
|
||||
total_chars = width * height
|
||||
|
||||
# === 解码字符 RLE 流 ===
|
||||
text_bytes = []
|
||||
pos = 16
|
||||
remaining = total_chars
|
||||
while remaining > 0:
|
||||
char_byte = data[pos]
|
||||
count = data[pos + 1]
|
||||
pos += 2
|
||||
text_bytes.extend([char_byte] * count)
|
||||
remaining -= count
|
||||
assert len(text_bytes) == total_chars, "Character RLE length mismatch"
|
||||
|
||||
# === 解码颜色 RLE 流 ===
|
||||
color_bytes = []
|
||||
remaining = total_chars
|
||||
while remaining > 0:
|
||||
color_byte = data[pos]
|
||||
count = data[pos + 1]
|
||||
pos += 2
|
||||
color_bytes.extend([color_byte] * count)
|
||||
remaining -= count
|
||||
assert len(color_bytes) == total_chars, "Color RLE length mismatch"
|
||||
|
||||
# === 读取调色板(16 色 × RGB)===
|
||||
palette_raw = data[pos:pos + 48]
|
||||
assert len(palette_raw) == 48, "Palette must be 48 bytes"
|
||||
palette = []
|
||||
for i in range(16):
|
||||
r = palette_raw[i * 3]
|
||||
g = palette_raw[i * 3 + 1]
|
||||
b = palette_raw[i * 3 + 2]
|
||||
palette.append([r, g, b])
|
||||
|
||||
# === 构建行数据 ===
|
||||
text_rows = []
|
||||
fg_rows = []
|
||||
bg_rows = []
|
||||
idx = 0
|
||||
for y in range(height):
|
||||
row_text_parts = []
|
||||
row_fg = ''
|
||||
row_bg = ''
|
||||
for x in range(width):
|
||||
b = text_bytes[idx]
|
||||
row_text_parts.append(f"\\{b:03d}") # 如 \130
|
||||
|
||||
c = color_bytes[idx]
|
||||
fg = c & 0x0F
|
||||
bg = (c >> 4) & 0x0F
|
||||
row_fg += f"{fg:x}"
|
||||
row_bg += f"{bg:x}"
|
||||
idx += 1
|
||||
text_rows.append(''.join(row_text_parts))
|
||||
fg_rows.append(row_fg)
|
||||
bg_rows.append(row_bg)
|
||||
|
||||
return {
|
||||
"width": width,
|
||||
"height": height,
|
||||
"text": text_rows,
|
||||
"foreground": fg_rows,
|
||||
"background": bg_rows,
|
||||
"palette": palette
|
||||
}
|
||||
|
||||
|
||||
def encode_frame(frame):
|
||||
width = frame["width"]
|
||||
height = frame["height"]
|
||||
total = width * height
|
||||
|
||||
# === 从 \ddd 序列还原字节 ===
|
||||
full_text = ''.join(frame["text"])
|
||||
text_bytes = []
|
||||
i = 0
|
||||
while i < len(full_text):
|
||||
if full_text[i] == '\\' and i + 4 <= len(full_text):
|
||||
try:
|
||||
num_str = full_text[i+1:i+4]
|
||||
num = int(num_str)
|
||||
if 0 <= num <= 255:
|
||||
text_bytes.append(num)
|
||||
i += 4
|
||||
continue
|
||||
except ValueError:
|
||||
pass
|
||||
raise ValueError(f"Invalid escape sequence at position {i}: expected \\ddd, got {full_text[i:i+5]}")
|
||||
assert len(text_bytes) == total, "Text byte count mismatch"
|
||||
|
||||
# === 编码字符 RLE ===
|
||||
char_rle = []
|
||||
i = 0
|
||||
while i < total:
|
||||
b = text_bytes[i]
|
||||
j = i
|
||||
while j < total and text_bytes[j] == b and (j - i + 1) <= 255:
|
||||
j += 1
|
||||
count = j - i
|
||||
char_rle.extend([b, count])
|
||||
i = j
|
||||
|
||||
# === 构建颜色流 ===
|
||||
color_stream = []
|
||||
for y in range(height):
|
||||
fg_row = frame["foreground"][y]
|
||||
bg_row = frame["background"][y]
|
||||
assert len(fg_row) == len(bg_row) == width, f"Row {y} length mismatch"
|
||||
for x in range(width):
|
||||
fg = int(fg_row[x], 16) & 0x0F
|
||||
bg = int(bg_row[x], 16) & 0x0F
|
||||
color_stream.append((bg << 4) | fg)
|
||||
assert len(color_stream) == total
|
||||
|
||||
# === 编码颜色 RLE ===
|
||||
color_rle = []
|
||||
i = 0
|
||||
while i < total:
|
||||
c = color_stream[i]
|
||||
j = i
|
||||
while j < total and color_stream[j] == c and (j - i + 1) <= 255:
|
||||
j += 1
|
||||
count = j - i
|
||||
color_rle.extend([c, count])
|
||||
i = j
|
||||
|
||||
# === 调色板 ===
|
||||
palette_bytes = []
|
||||
for rgb in frame["palette"]:
|
||||
assert len(rgb) == 3
|
||||
r, g, b = rgb
|
||||
assert 0 <= r <= 255 and 0 <= g <= 255 and 0 <= b <= 255
|
||||
palette_bytes.extend([r, g, b])
|
||||
assert len(palette_bytes) == 48
|
||||
|
||||
# === 拼接二进制数据 ===
|
||||
header = b'\x00\x00\x00\x00' + struct.pack('<HH', width, height) + b'\x00' * 8
|
||||
body = bytes(char_rle) + bytes(color_rle) + bytes(palette_bytes)
|
||||
full_data = header + body
|
||||
|
||||
# === 自定义 Base64 编码 ===
|
||||
b64 = ""
|
||||
val = 0
|
||||
bits = 0
|
||||
for byte in full_data:
|
||||
val = (val << 8) | byte
|
||||
bits += 8
|
||||
while bits >= 6:
|
||||
bits -= 6
|
||||
b64 += B64STR[(val >> bits) & 0x3F]
|
||||
if bits:
|
||||
b64 += B64STR[(val << (6 - bits)) & 0x3F]
|
||||
# 补齐到 4 的倍数(虽然 CC 可能不检查,但保持兼容)
|
||||
while len(b64) % 4:
|
||||
b64 += '='
|
||||
|
||||
# 使用 !CPD 格式(12 位十六进制长度)
|
||||
hex_len = f"{len(b64):012x}"
|
||||
return f"!CPD{hex_len}{b64}"
|
||||
|
||||
|
||||
def vid_to_json(vid_path, json_path):
|
||||
with open(vid_path, 'r', encoding='latin1') as f:
|
||||
lines = [line.rstrip('\n\r') for line in f]
|
||||
|
||||
if not lines or lines[0] != "32Vid 1.1":
|
||||
raise ValueError("Not a valid .32vid file: missing header")
|
||||
|
||||
fps_str = lines[1] if len(lines) > 1 else "0"
|
||||
try:
|
||||
fps = float(fps_str)
|
||||
except ValueError:
|
||||
fps = 0.0
|
||||
|
||||
frame_lines = []
|
||||
for line in lines[2:]:
|
||||
if line.strip() == "":
|
||||
continue
|
||||
if line.startswith("!CP"):
|
||||
frame_lines.append(line)
|
||||
|
||||
frames = []
|
||||
for line in frame_lines:
|
||||
mode = line[3]
|
||||
if mode == 'C':
|
||||
length = int(line[4:8], 16)
|
||||
b64data = line[8:8 + length]
|
||||
elif mode == 'D':
|
||||
length = int(line[4:16], 16)
|
||||
b64data = line[16:16 + length]
|
||||
else:
|
||||
raise ValueError(f"Unknown frame mode: {mode}")
|
||||
|
||||
binary_data = custom_b64decode(b64data)
|
||||
frame = decode_frame(binary_data)
|
||||
frames.append(frame)
|
||||
|
||||
result = {
|
||||
"header": {
|
||||
"magic": "32Vid 1.1",
|
||||
"fps": fps
|
||||
},
|
||||
"frames": frames
|
||||
}
|
||||
|
||||
with open(json_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(result, f, indent=2, ensure_ascii=False)
|
||||
|
||||
|
||||
def json_to_vid(json_path, vid_path):
|
||||
with open(json_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
fps = data["header"]["fps"]
|
||||
frames = data["frames"]
|
||||
|
||||
with open(vid_path, 'w', encoding='latin1') as f:
|
||||
f.write("32Vid 1.1\n")
|
||||
f.write(f"{fps}\n")
|
||||
for frame in frames:
|
||||
line = encode_frame(frame)
|
||||
f.write(line + "\n")
|
||||
|
||||
|
||||
# ======================
|
||||
# CLI 入口
|
||||
# ======================
|
||||
def main():
|
||||
if len(sys.argv) != 4:
|
||||
print("Usage:")
|
||||
print(" python 32vid_converter.py to-json input.32vid output.json")
|
||||
print(" python 32vid_converter.py to-vid input.json output.32vid")
|
||||
sys.exit(1)
|
||||
|
||||
command = sys.argv[1]
|
||||
input_path = sys.argv[2]
|
||||
output_path = sys.argv[3]
|
||||
|
||||
if command == "to-json":
|
||||
vid_to_json(input_path, output_path)
|
||||
print(f"✅ Converted: {input_path} → {output_path}")
|
||||
elif command == "to-vid":
|
||||
json_to_vid(input_path, output_path)
|
||||
print(f"✅ Converted: {input_path} → {output_path}")
|
||||
else:
|
||||
print(f"❌ Unknown command: {command}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
53
lib/ys.lua
53
lib/ys.lua
@@ -1,53 +0,0 @@
|
||||
-- 压缩函数
|
||||
function rleCompress(str)
|
||||
local result = {}
|
||||
local i = 1
|
||||
while i <= #str do
|
||||
local char = str:sub(i, i)
|
||||
local count = 1
|
||||
while i + count <= #str and str:sub(i + count, i + count) == char do
|
||||
count = count + 1
|
||||
end
|
||||
if count > 2 then
|
||||
table.insert(result, ("[%d]%s"):format(count, char))
|
||||
else
|
||||
table.insert(result, char:rep(count))
|
||||
end
|
||||
i = i + count
|
||||
end
|
||||
return table.concat(result)
|
||||
end
|
||||
|
||||
-- 解压函数
|
||||
function rleDecompress(str)
|
||||
local result = {}
|
||||
local i = 1
|
||||
while i <= #str do
|
||||
if str:sub(i, i) == "[" then
|
||||
local j = str:find("]", i)
|
||||
local num = tonumber(str:sub(i+1, j-1))
|
||||
local char = str:sub(j+1, j+1)
|
||||
table.insert(result, char:rep(num))
|
||||
i = j + 2
|
||||
else
|
||||
table.insert(result, str:sub(i, i))
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return table.concat(result)
|
||||
end
|
||||
|
||||
-- 测试
|
||||
file = fs.open("1.bimg","r")
|
||||
original = file.readAll()
|
||||
file.close()
|
||||
|
||||
|
||||
local compressed = rleCompress(original)
|
||||
print("原始:", original)
|
||||
print("压缩:", compressed)
|
||||
print("解压:", rleDecompress(compressed))
|
||||
file = fs.open("12.bimg","w")
|
||||
file.write(compressed)
|
||||
file.close()
|
||||
|
||||
Reference in New Issue
Block a user