dav1d
dav1d

Reputation: 6055

DXT Compression for Python

I am currently working with Images and some are DXT compressed, I need a easy way of decompressing and compressing of these files with Python. Unfortunatly I was unable to find any library which does that for me.

Does anyone know a good DXT-Compression library for Python, or an interface to a compresion library?

-- dav1d

Edit:

libsquish was the way to go here, but unfortunatly the Python-Bindings don't work, so here the solution.

Make a squish-Wrapper in C++ which exports functions which internally access 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);
    }
}

Create a dynamic library (a dll on windows, or a so on linux, I called it libsquishc.so) and open it with ctypes.

My approach (just exports the functions I need):

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

Upvotes: 2

Views: 1790

Answers (2)

Hugh Bothwell
Hugh Bothwell

Reputation: 56684

libSquish has a patch to add Python bindings.

Edit: Installation procedure seems to be

  1. download squish-1.11.zip
  2. unpack and compile - should result in a libsquish.a file
  3. download and install Cython (sounds like you did this)
  4. create a temporary directory and "apply" the patch - it drops a bunch of new files which are the binding code
  5. run setup (sudo python setup.py install)

If you did this and still have errors then maybe you should (a) share the actual error messages so we can figure out why, or (b) contact the patch author directly - mat (at) kivy.org

Edit2: the compile error is short enough that I will include it here:

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

The relevant section of squish.h looks like

#ifndef SQUISH_H
#define SQUISH_H

//! All squish API functions live in this namespace.
namespace squish {

// -----------------------------------------------------------------------------

and it looks like it's choking on the namespace keyword, which I'd say means it's compiling as C when it should be compiled as C++.

Upvotes: 1

xioxox
xioxox

Reputation: 2680

libsquish has some contributed python bindings: http://code.google.com/p/libsquish/issues/detail?id=17 I have not used them, however.

Upvotes: 0

Related Questions