如何无需解压解码JPG 直接从多个JPG瓦片生成SVS文件
无需解码JPG瓦片直接生成SVS文件的实现方案
SVS本质是携带Aperio私有标签的多分辨率金字塔TIFF格式文件,采用JPG压缩的SVS瓦片,存储时本身就是将单张JPG的完整压缩码流直接作为TIFF瓦片的原始数据块写入,完全不需要将JPG解码为像素数组再重新编码,可以直接写入原始JPG字节流完成封装,处理效率比解码重编码方案高1~2个数量级。
- 核心实现逻辑
之前使用tifffile耗时久的原因是调用了面向numpy数组的高层读写接口,这类接口会自动触发JPG解码、数组转存、JPG重编码的全流程。tifffile本身提供了底层瓦片写入接口,支持直接传入压缩后的原始字节流,全程不会触发编解码操作。 - 可直接复用的实现代码
注意写入前需要提前记录原SVS的瓦片尺寸、各金字塔层级宽高、JPG压缩参数,所有参数必须和原文件严格匹配,否则生成的SVS无法被病理切片查看软件正常识别。
import tifffile import os # 以下参数请替换为提取瓦片时对应的原SVS实际参数 TILE_SIZE = 256 # SVS常规瓦片边长为256或512 IMAGE_CHANNELS = 3 # 常规明场切片为3通道RGB PYRAMID_CONF = [ # 格式:(层级宽度, 层级高度, 对应层级瓦片存储文件夹路径) (level0_full_width, level0_full_height, "./tiles/level_0"), (level1_width, level1_height, "./tiles/level_1"), # 按实际提取的金字塔层级数量补全即可 ] JPEG_QUALITY = 95 # 和提取的JPG压缩质量保持一致 with tifffile.TiffWriter( "output_restored.svs", bigtiff=True, # SVS文件普遍大于4GB,必须开启BigTIFF支持 shaped=False ) as writer: for level_idx, (level_w, level_h, tile_folder) in enumerate(PYRAMID_CONF): # 按瓦片排列顺序读取所有JPG的原始字节,全程不做解码 raw_tiles = [] for y_pos in range(0, level_h, TILE_SIZE): for x_pos in range(0, level_w, TILE_SIZE): # 这里的瓦片命名规则替换为自身提取时的命名规则 tile_file = os.path.join(tile_folder, f"tile_{x_pos}_{y_pos}.jpg") with open(tile_file, "rb") as f: raw_tiles.append(f.read()) # 直接写入原始JPG字节流,跳过编解码环节 writer.write( data=None, shape=(level_h, level_w, IMAGE_CHANNELS), tile=(TILE_SIZE, TILE_SIZE), compression="jpeg", jpeg_quality=JPEG_QUALITY, photometric="rgb", tiles=raw_tiles, software="Aperio" if level_idx == 0 else None, # 写入SVS要求的厂商标识 subifds=0 if level_idx == 0 else None # 如果提取时保留了原SVS的全部TIFF标签,可在此处原样传入,兼容性更好 )
- 注意事项
- 禁止使用
tifffile.imread/tifffile.imwrite这类高层数组接口,只要传入numpy数组就会强制触发编解码流程,无法跳过解码环节。 - 瓦片读取顺序必须严格按照从左到右、从上到下的行优先顺序排列,顺序错乱会导致生成的切片内容完全错位。
- 如果提取的JPG存在分辨率、采样率和原SVS不匹配的情况,需要先统一JPG的压缩参数,否则写入后的文件可能出现色彩偏移、块效应异常的问题。
- 该方案的处理速度完全取决于磁盘读写性能,没有CPU编解码开销,常规千兆像素级全切片的封装耗时通常在数分钟以内。
- 禁止使用
内容的提问来源于stack exchange,提问作者simpia
相关产品推荐
相关产品推荐

