Skip to main content
 首页 » 编程设计

python之Python 的 DXT 压缩

2025年05月04日11soundcode

我目前正在处理图像,其中一些是 DXT 压缩的,我需要一种使用 Python 解压缩和压缩这些文件的简单方法。不幸的是,我找不到任何可以为我做这件事的图书馆。

有谁知道一个好的 Python DXT 压缩库,或者压缩库的接口(interface)?

-- dav1d

编辑:

libsquish 是实现此目的的方法,但不幸的是 Python 绑定(bind)不起作用,所以这里是解决方案。

用 C++ 制作一个 squish-Wrapper,它导出内部访问 libsquish 的函数:

#include <squish.h> 
 
typedef unsigned char u8; 
 
extern "C" { 
    void CompressMasked( u8 const* rgba, int mask, void* block, int flags ) { 
        squish::CompressMasked(rgba, mask, block, flags); 
    } 
 
    void Compress( u8 const* rgba, void* block, int flags ) { 
        squish::Compress(rgba, block, flags); 
    } 
 
    void Decompress( u8* rgba, void const* block, int flags ) { 
        squish::Decompress(rgba, block, flags); 
    } 
 
    int GetStorageRequirements( int width, int height, int flags ) { 
        return squish::GetStorageRequirements(width, height, flags); 
    } 
 
    void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags ) { 
        squish::CompressImage(rgba, width, height, blocks, flags); 
    } 
 
    void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags ) { 
        squish::DecompressImage(rgba, width, height, blocks, flags); 
    } 
} 

创建一个动态库(在windows上是dll,在linux上是so,我称之为libsquishc.so)并用ctypes打开它。

我的做法(只导出我需要的功能):

from ctypes import CDLL, c_int, byref, create_string_buffer 
import os.path 
 
libsquish_path = os.path.join(os.path.split(os.path.abspath(__file__))[0], 'libsquishc.so') 
libsquish = CDLL(libsquish_path) 
 
 
DXT1 = 1 << 0  
DXT3 = 1 << 1  
DXT5 = 1 << 2  
 
COLOR_ITERATIVE_CLUSTER_FIT = 1 << 8     
COLOR_CLUSTER_FIT = 1 << 3     
COLOR_RANGE_FIT = 1 << 4 
WEIGHT_COLOR_BY_ALPHA = 1 << 7 
 
 
GetStorageRequirements = libsquish.GetStorageRequirements 
GetStorageRequirements.argtypes = [c_int, c_int, c_int] 
GetStorageRequirements.restype = c_int 
 
def compress_image(rgba, width, height, flags): 
    rgba = create_string_buffer(rgba) 
 
    c = GetStorageRequirements(width, height, flags) 
    buffer = create_string_buffer(c) 
 
    libsquish.Compress(byref(rgba), byref(buffer), c_int(flags)) 
 
    return buffer.raw 
 
def decompress_image(block, width, height, flags): 
    block = create_string_buffer(block) 
 
    c = width*height*4 
    rgba = create_string_buffer(c) 
 
    libsquish.DecompressImage(byref(rgba), c_int(width), c_int(height), byref(block), c_int(flags)) 
 
    return rgba.raw 

请您参考如下方法:

libSquish有a patch to add Python bindings .

编辑:安装程序好像是

  1. 下载squish-1.11.zip
  2. 解压并编译 - 应该生成一个 libsquish.a 文件
  3. 下载并安装Cython (听起来像是你这样做的)
  4. 创建一个临时目录并“应用”补丁——它会删除一堆新文件,这些文件是绑定(bind)代码
  5. 运行安装程序(sudo python setup.py install)

如果您这样做但仍然有错误,那么也许您应该 (a) 分享实际的错误消息,以便我们找出原因,或者 (b) 直接联系补丁作者 - mat (at) kivy.org

Edit2:编译错误很短,我将把它包括在这里:

running install 
running build 
running build_ext 
skipping 'squish.c' Cython extension (up-to-date) 
building 'squish' extension 
gcc -pthread -fno-strict-aliasing -march=i686 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -DNDEBUG -march=i686 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -fPIC -I.. -I/usr/include/python2.7 -c squish.c -o build/temp.linux-i686-2.7/squish.o 
In file included from squish.c:274:0: 
/usr/include/squish.h:32:1: error: unknown type name 'namespace' 
/usr/include/squish.h:32:18: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token 
squish.c: In function '__pyx_pf_6squish_compressImage': 
squish.c:790:22: error: 'squish' undeclared (first use in this function) 
squish.c:790:22: note: each undeclared identifier is reported only once for each function it appears in 
squish.c:790:28: error: expected ';' before ':' token 
squish.c:866:10: error: expected expression before ':' token 
squish.c: In function '__pyx_pf_6squish_2decompressImage': 
squish.c:1202:10: error: expected expression before ':' token 
error: command 'gcc' failed with exit status 1 

squish.h 的相关部分看起来像

#ifndef SQUISH_H 
#define SQUISH_H 
 
//! All squish API functions live in this namespace. 
namespace squish { 
 
// ----------------------------------------------------------------------------- 

它看起来像是在 namespace 关键字上窒息,我想说这意味着它在应该编译为 C++ 时编译为 C。