s3tc.py :  » Development » Brain-Workshop » brainworkshop » pyglet » image » codecs » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Brain Workshop 
Brain Workshop » brainworkshop » pyglet » image » codecs » s3tc.py
# ----------------------------------------------------------------------------
# pyglet
# Copyright (c) 2006-2008 Alex Holkner
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions 
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright 
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#  * Neither the name of pyglet nor the names of its
#    contributors may be used to endorse or promote products
#    derived from this software without specific prior written
#    permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ----------------------------------------------------------------------------
# $Id:$

'''Software decoder for S3TC compressed texture (i.e., DDS).

http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_compression_s3tc.txt
'''

import ctypes
import re

from pyglet.gl import *
from pyglet.gl import gl_info
from pyglet.image import AbstractImage,Texture

split_8byte = re.compile('.' * 8, flags=re.DOTALL)
split_16byte = re.compile('.' * 16, flags=re.DOTALL)

class PackedImageData(AbstractImage):
    _current_texture = None

    def __init__(self, width, height, format, packed_format, data):
        super(PackedImageData, self).__init__(width, height)
        self.format = format
        self.packed_format = packed_format
        self.data = data

    def unpack(self):
        if self.packed_format == GL_UNSIGNED_SHORT_5_6_5:
            # Unpack to GL_RGB.  Assume self.data is already 16-bit
            i = 0
            out = (c_ubyte * (self.width * self.height * 3))()
            for c in self.data:
                out[i+2] = (c & 0x1f) << 3
                out[i+1] = (c & 0x7e0) >> 3
                out[i] = (c & 0xf800) >> 8
                i += 3
            self.data = out
            self.packed_format = GL_UNSIGNED_BYTE

    def _get_texture(self):
        if self._current_texture:
            return self._current_texture

        texture = Texture.create_for_size(
            GL_TEXTURE_2D, self.width, self.height)
        glBindTexture(texture.target, texture.id)
        glTexParameteri(texture.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

        if not gl_info.have_version(1, 2) or True:
            self.unpack()

        glTexImage2D(texture.target, texture.level,
            self.format, self.width, self.height, 0,
            self.format, self.packed_format, self.data)

        self._current_texture = texture
        return texture
    
    texture = property(_get_texture)

def decode_dxt1_rgb(data, width, height):
    # Decode to 16-bit RGB UNSIGNED_SHORT_5_6_5
    out = (ctypes.c_uint16 * (width * height))()

    # Read 8 bytes at a time
    image_offset = 0
    for c0_lo, c0_hi, c1_lo, c1_hi, b0, b1, b2, b3 in split_8byte.findall(data):
        color0 = ord(c0_lo) | ord(c0_hi) << 8
        color1 = ord(c1_lo) | ord(c1_hi) << 8
        bits = ord(b0) | ord(b1) << 8 | ord(b2) << 16 | ord(b3) << 24

        r0 = color0 & 0x1f
        g0 = (color0 & 0x7e0) >> 5
        b0 = (color0 & 0xf800) >> 11
        r1 = color1 & 0x1f
        g1 = (color1 & 0x7e0) >> 5
        b1 = (color1 & 0xf800) >> 11

        # i is the dest ptr for this block
        i = image_offset
        for y in range(4):
            for x in range(4):
                code = bits & 0x3

                if code == 0:
                    out[i] = color0
                elif code == 1:
                    out[i] = color1
                elif code == 3 and color0 <= color1:
                    out[i] = 0
                else:
                    if code == 2 and color0 > color1:
                        r = (2 * r0 + r1) / 3
                        g = (2 * g0 + g1) / 3
                        b = (2 * b0 + b1) / 3
                    elif code == 3 and color0 > color1:
                        r = (r0 + 2 * r1) / 3
                        g = (g0 + 2 * g1) / 3
                        b = (b0 + 2 * b1) / 3
                    else:
                        assert code == 2 and color0 <= color1
                        r = (r0 + r1) / 2
                        g = (g0 + g1) / 2
                        b = (b0 + b1) / 2
                    out[i] = r | g << 5 | b << 11

                bits >>= 2
                i += 1
            i += width - 4

        # Move dest ptr to next 4x4 block
        advance_row = (image_offset + 4) % width == 0
        image_offset += width * 3 * advance_row + 4

    return PackedImageData(width, height, 
        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, out)

def decode_dxt1_rgba(data, width, height):
    # Decode to GL_RGBA
    out = (ctypes.c_ubyte * (width * height * 4))()
    pitch = width << 2

    # Read 8 bytes at a time
    image_offset = 0
    for c0_lo, c0_hi, c1_lo, c1_hi, b0, b1, b2, b3 in split_8byte.findall(data):
        color0 = ord(c0_lo) | ord(c0_hi) << 8
        color1 = ord(c1_lo) | ord(c1_hi) << 8
        bits = ord(b0) | ord(b1) << 8 | ord(b2) << 16 | ord(b3) << 24

        r0 = color0 & 0x1f
        g0 = (color0 & 0x7e0) >> 5
        b0 = (color0 & 0xf800) >> 11
        r1 = color1 & 0x1f
        g1 = (color1 & 0x7e0) >> 5
        b1 = (color1 & 0xf800) >> 11

        # i is the dest ptr for this block
        i = image_offset
        for y in range(4):
            for x in range(4):
                code = bits & 0x3
                a = 255

                if code == 0:
                    r, g, b = r0, g0, b0
                elif code == 1:
                    r, g, b = r1, g1, b1
                elif code == 3 and color0 <= color1:
                    r = g = b = a = 0
                else:
                    if code == 2 and color0 > color1:
                        r = (2 * r0 + r1) / 3
                        g = (2 * g0 + g1) / 3
                        b = (2 * b0 + b1) / 3
                    elif code == 3 and color0 > color1:
                        r = (r0 + 2 * r1) / 3
                        g = (g0 + 2 * g1) / 3
                        b = (b0 + 2 * b1) / 3
                    else:
                        assert code == 2 and color0 <= color1
                        r = (r0 + r1) / 2
                        g = (g0 + g1) / 2
                        b = (b0 + b1) / 2

                out[i] = b << 3
                out[i+1] = g << 2
                out[i+2] = r << 3
                out[i+3] = a << 4

                bits >>= 2
                i += 4
            i += pitch - 16

        # Move dest ptr to next 4x4 block
        advance_row = (image_offset + 16) % pitch == 0
        image_offset += pitch * 3 * advance_row + 16

    return PackedImageData(width, height, GL_RGBA, GL_UNSIGNED_BYTE, out)


def decode_dxt3(data, width, height):
    # Decode to GL_RGBA
    out = (ctypes.c_ubyte * (width * height * 4))()
    pitch = width << 2

    # Read 16 bytes at a time
    image_offset = 0
    for (a0, a1, a2, a3, a4, a5, a6, a7,
         c0_lo, c0_hi, c1_lo, c1_hi, 
         b0, b1, b2, b3) in split_16byte.findall(data):
        color0 = ord(c0_lo) | ord(c0_hi) << 8
        color1 = ord(c1_lo) | ord(c1_hi) << 8
        bits = ord(b0) | ord(b1) << 8 | ord(b2) << 16 | ord(b3) << 24
        alpha = ord(a0) | ord(a1) << 8 | ord(a2) << 16 | ord(a3) << 24 | \
            ord(a4) << 32 | ord(a5) << 40 | ord(a6) << 48 | ord(a7) << 56

        r0 = color0 & 0x1f
        g0 = (color0 & 0x7e0) >> 5
        b0 = (color0 & 0xf800) >> 11
        r1 = color1 & 0x1f
        g1 = (color1 & 0x7e0) >> 5
        b1 = (color1 & 0xf800) >> 11

        # i is the dest ptr for this block
        i = image_offset
        for y in range(4):
            for x in range(4):
                code = bits & 0x3
                a = alpha & 0xf

                if code == 0:
                    r, g, b = r0, g0, b0
                elif code == 1:
                    r, g, b = r1, g1, b1
                elif code == 3 and color0 <= color1:
                    r = g = b = 0
                else:
                    if code == 2 and color0 > color1:
                        r = (2 * r0 + r1) / 3
                        g = (2 * g0 + g1) / 3
                        b = (2 * b0 + b1) / 3
                    elif code == 3 and color0 > color1:
                        r = (r0 + 2 * r1) / 3
                        g = (g0 + 2 * g1) / 3
                        b = (b0 + 2 * b1) / 3
                    else:
                        assert code == 2 and color0 <= color1
                        r = (r0 + r1) / 2
                        g = (g0 + g1) / 2
                        b = (b0 + b1) / 2

                out[i] = b << 3
                out[i+1] = g << 2
                out[i+2] = r << 3
                out[i+3] = a << 4

                bits >>= 2
                alpha >>= 4
                i += 4
            i += pitch - 16

        # Move dest ptr to next 4x4 block
        advance_row = (image_offset + 16) % pitch == 0
        image_offset += pitch * 3 * advance_row + 16

    return PackedImageData(width, height, GL_RGBA, GL_UNSIGNED_BYTE, out)

def decode_dxt5(data, width, height):
    # Decode to GL_RGBA
    out = (ctypes.c_ubyte * (width * height * 4))()
    pitch = width << 2

    # Read 16 bytes at a time
    image_offset = 0
    for (alpha0, alpha1, ab0, ab1, ab2, ab3, ab4, ab5, 
         c0_lo, c0_hi, c1_lo, c1_hi, 
         b0, b1, b2, b3) in split_16byte.findall(data):
        color0 = ord(c0_lo) | ord(c0_hi) << 8
        color1 = ord(c1_lo) | ord(c1_hi) << 8
        alpha0 = ord(alpha0)
        alpha1 = ord(alpha1)
        bits = ord(b0) | ord(b1) << 8 | ord(b2) << 16 | ord(b3) << 24
        abits = ord(ab0) | ord(ab1) << 8 | ord(ab2) << 16 | ord(ab3) << 24 | \
            ord(ab4) << 32 | ord(ab5) << 40

        r0 = color0 & 0x1f
        g0 = (color0 & 0x7e0) >> 5
        b0 = (color0 & 0xf800) >> 11
        r1 = color1 & 0x1f
        g1 = (color1 & 0x7e0) >> 5
        b1 = (color1 & 0xf800) >> 11

        # i is the dest ptr for this block
        i = image_offset
        for y in range(4):
            for x in range(4):
                code = bits & 0x3
                acode = abits & 0x7

                if code == 0:
                    r, g, b = r0, g0, b0
                elif code == 1:
                    r, g, b = r1, g1, b1
                elif code == 3 and color0 <= color1:
                    r = g = b = 0
                else:
                    if code == 2 and color0 > color1:
                        r = (2 * r0 + r1) / 3
                        g = (2 * g0 + g1) / 3
                        b = (2 * b0 + b1) / 3
                    elif code == 3 and color0 > color1:
                        r = (r0 + 2 * r1) / 3
                        g = (g0 + 2 * g1) / 3
                        b = (b0 + 2 * b1) / 3
                    else:
                        assert code == 2 and color0 <= color1
                        r = (r0 + r1) / 2
                        g = (g0 + g1) / 2
                        b = (b0 + b1) / 2
                
                if acode == 0:
                    a = alpha0
                elif acode == 1:
                    a = alpha1
                elif alpha0 > alpha1:
                    if acode == 2:
                        a = (6 * alpha0 + 1 * alpha1) / 7
                    elif acode == 3:
                        a = (5 * alpha0 + 2 * alpha1) / 7
                    elif acode == 4:
                        a = (4 * alpha0 + 3 * alpha1) / 7
                    elif acode == 5:
                        a = (3 * alpha0 + 4 * alpha1) / 7
                    elif acode == 6:
                        a = (2 * alpha0 + 5 * alpha1) / 7
                    else:
                        assert acode == 7
                        a = (1 * alpha0 + 6 * alpha1) / 7
                else:
                    if acode == 2:
                        a = (4 * alpha0 + 1 * alpha1) / 5
                    elif acode == 3:
                        a = (3 * alpha0 + 2 * alpha1) / 5
                    elif acode == 4:
                        a = (2 * alpha0 + 3 * alpha1) / 5
                    elif acode == 5:
                        a = (1 * alpha0 + 4 * alpha1) / 5
                    elif acode == 6:
                        a = 0
                    else:
                        assert acode == 7
                        a = 255

                out[i] = b << 3
                out[i+1] = g << 2
                out[i+2] = r << 3
                out[i+3] = a

                bits >>= 2
                abits >>= 3
                i += 4
            i += pitch - 16

        # Move dest ptr to next 4x4 block
        advance_row = (image_offset + 16) % pitch == 0
        image_offset += pitch * 3 * advance_row + 16

    return PackedImageData(width, height, GL_RGBA, GL_UNSIGNED_BYTE, out)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.