我参考论坛里的大佬写的代码能解一部分的包,但是有一部分sct解出来有轮廓但是颜色不对,有一部分是干脆都大半看不见,想请大佬们看看什么问题 ,文件在夸克网盘
链接: https://pan.quark.cn/s/5d841601a0a0
这是我参考大佬写的,只有一部分的解出来,还有些解不出来,请大佬们看看
from pathlib import Path
from io import BufferedReader
from lz4.block import decompress as decLz4Block
import numpy as np
from PIL import Image
from texture2ddecoder import decode_astc as dastc
import sys
import subprocess
def process_file(file_path: str) → bool:
try:
with open(file_path, 'rb') as f:
\# 1. 基础头部解析(保留类型分析)
if f.read(4) != b'SCT2':
print(f"非SCT2格式: {file_path}")
return False
data_length = int.from_bytes(f.read(4), 'little')
f.read(4) # CRC
offset = int.from_bytes(f.read(4), 'little')
tex_type = int.from_bytes(f.read(4), 'little') # 保留类型判断
f.read(4) # 未知字段
width = int.from_bytes(f.read(2), 'little')
height = int.from_bytes(f.read(2), 'little')
crop_w = int.from_bytes(f.read(2), 'little')
crop_h = int.from_bytes(f.read(2), 'little')
act_w = crop_w if 0 < crop_w <= 2048 else min(width, 2048)
act_h = crop_h if 0 < crop_h <= 2048 else min(height, 2048)
\# 2. 读取数据区
f.seek(offset)
raw_data = f.read(data_length) # 读取完整数据区
\# 3. 尝试所有可能的解压组合(核心:处理多层压缩)
decompress_results = try_decompress(raw_data)
for algo, data in decompress_results:
\# 4. 尝试ASTC解码(多块大小)
block_sizes = \[(4,4), (8,8), (6,6),(5,5), (10,10), (3,3), (7,7)\]
for block in block_sizes:
try:
img_buffer = dastc(data, act_w, act_h, block\[0\], block\[1\])
except:
continue
\# 5. 验证解码结果(字节长度校验)
expected_len = act_w \* act_h \* 4 # RGBA格式预期长度
if len(img_buffer) != expected_len:
continue # 长度不符,跳过
\# 6. 尝试所有通道顺序
channel_orders = \[
\[0,1,2,3\], \[2,1,0,3\], \[1,0,2,3\], \[2,0,1,3\]
\]
for order in channel_orders:
img_array = np.frombuffer(img_buffer, dtype=np.uint8)
img_array = img_array.reshape((act_h, act_w, 4))\[:, :, order\]
\# 7. 保存尝试结果(方便对比)
save_path = f"{file_path\[:-3\]}\_{algo}\_{block\[0\]}x{block\[1\]}\_{order}.png"
Image.fromarray(img_array).save(save_path)
print(f"生成尝试结果: {save_path}")
return True # 成功生成一个有效结果即返回
\# 所有尝试失败
print(f"所有解码组合均失败: {file_path}")
return False
except Exception as e:
print(f"处理错误: {file_path}, {str(e)}")
return False
# 2. 批量处理函数,用命令行参数传递文件路径(避免函数导入)
def batch_convert(dat_path: str):
path = Path(dat_path)
sct_files = \[str(f) for f in path.glob('\*.sct') if f.is_file()\]
if not sct_files:
print("No .sct files found")
return
for file in sct_files:
print(f"\\nProcessing: {file}")
\# 修正路径格式
file_path_fixed = file.replace('\\\\', '/')
\# 关键:通过命令行参数传递文件路径,子进程直接执行process_file
\# 将处理逻辑作为字符串传递,避免导入函数
cmd = f"""
import sys
from lz4.block import decompress as decLz4Block
import numpy as np
from PIL import Image
from texture2ddecoder import decode_astc as dastc
def process_file(file_path):
try:
with open(file_path, 'rb') as f:
if f.read(4) != b'SCT2':
print(f"Failed {{file_path}}: Not SCT2")
return False
header_pos = f.tell()
data_length = int.from_bytes(f.read(4), 'little')
f.read(4)
offset = int.from_bytes(f.read(4), 'little')
tex_type = int.from_bytes(f.read(4), 'little')
f.read(4)
width = int.from_bytes(f.read(2), 'little')
height = int.from_bytes(f.read(2), 'little')
f.read(4)
MAX_DIMENSION = 2048
if width > MAX_DIMENSION or height > MAX_DIMENSION:
width, height = MAX_DIMENSION, MAX_DIMENSION
try:
f.seek(offset)
dec_len = int.from_bytes(f.read(4), 'little')
com_len = int.from_bytes(f.read(4), 'little')
if com_len == data_length - 80 and tex_type == 4:
compress_data = f.read(com_len)
data = decLz4Block(compress_data, uncompressed_size=dec_len)
img_buffer = dastc(data, width, height, 4, 4)
img_array = np.frombuffer(img_buffer, dtype=np.uint8).reshape((height, width, 4))
img_array = img_array\[:, :, \[2, 1, 0, 3\]\]
Image.fromarray(img_array).save(f'{{file_path\[:-3\]}}png')
print(f"Success {{file_path}}")
return True
except:
pass
try:
f.seek(header_pos + 20)
width = int.from_bytes(f.read(2), 'little')
height = int.from_bytes(f.read(2), 'little')
width = MAX_DIMENSION if width <=0 or width > MAX_DIMENSION else width
height = MAX_DIMENSION if height <=0 or height > MAX_DIMENSION else height
block_size = 4
block_count_x = (width + block_size - 1) // block_size
block_count_y = (height + block_size - 1) // block_size
theoretical_length = block_count_x \* block_count_y \* 16
f.seek(72)
remaining_length = data_length - 72
actual_read_length = min(theoretical_length, remaining_length, 10\*1024\*1024)
data = f.read(actual_read_length)
if len(data) < 16:
raise ValueError("Data too short")
try:
img_buffer = dastc(data, width, height, 4, 4)
except:
img_buffer = dastc(data, width, height, 8, 8)
img_array = np.frombuffer(img_buffer, dtype=np.uint8).reshape((height, width, 4))
img_array = img_array\[:, :, \[2, 1, 0, 3\]\]
Image.fromarray(img_array).save(f'{{file_path\[:-3\]}}png')
print(f"Success {{file_path}}")
return True
except Exception as e:
print(f"Failed {{file_path}}: {{str(e)}}")
return False
except Exception as e:
print(f"Failed {{file_path}}: {{str(e)}}")
return False
process_file(‘{file_path_fixed}’)
“”"
\# 执行子进程
result = subprocess.run(
\[sys.executable, "-c", cmd\],
capture_output=True,
text=True
)
\# 打印结果
if result.stdout:
print(result.stdout)
if result.stderr:
print(f"Error: {result.stderr}")
continue
if _name_ == ‘_main_’:
target_dir = r'D:\\jiemi\\czn'
batch_convert(target_dir)