1. 4FIPS
  2. PHOTOS
  3. VIDEOS
  4. APPS
  5. CODE
  6. FORUMS
  7. ABOUT
#!/usr/bin/env python

# /*
# (c) 2013 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
# THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
# ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=1071
# */

import ctypes as ct
import png

class Texture_format8:
    Rgb = 0
    Rgba = 1
    
class c_Blob(ct.Structure):
    _fields_ = [
        ("tag", ct.c_uint8 * 4),
        ("size", ct.c_uint32)
    ]

class c_Block(ct.Structure):
    _fields_ = [
        ("size", ct.c_uint32),
        ("offset", ct.c_uint32)
    ]

class c_Header(ct.Structure):
    _fields_ = [
        ("version", ct.c_uint8),
        ("reserved0", ct.c_uint8),
        ("reserved1", ct.c_uint8),
        ("format", ct.c_uint8),
        ("width", ct.c_uint32),
        ("height", ct.c_uint32),
        ("size", ct.c_uint32)
    ]

def c_Data_factory(size):
    """Parametrized by 'size'."""
    class c_Data(ct.Structure):
        _fields_ = [
            ("data", ct.c_uint8 * size)
        ]
    return c_Data

def c_Texture_factory(c_Data):
    """Parametrized by 'c_Data'."""
    class c_Texture(ct.Structure):
        _fields_ = [
            ("blob", c_Blob),
            ("header_block", c_Block),
            ("data_block", c_Block),
            ("header", c_Header),
            ("data", c_Data)
        ]
    return c_Texture

def create_texture(width, height, format, pixels):
    c_Data = c_Data_factory(len(pixels))
    c_Texture = c_Texture_factory(c_Data)
    return c_Texture(
        c_Blob(tuple([ord(x) for x in "TEX!"]), ct.sizeof(c_Texture)), # blob [tag, size]
        c_Block(ct.sizeof(c_Header), c_Texture.header.offset), # header_block [size, offset]
        c_Block(ct.sizeof(c_Data), c_Texture.data.offset), # data_block [size, offset]
        c_Header(
            1, # version
            0, # reserved0
            0, # reserved1
            format,
            width,
            height,
            len(pixels) # size
        ),
        c_Data(tuple(pixels))
    )

def load_image(fname):
    r = png.Reader(fname)
    width, height, pixels, meta = r.read_flat()
    bitdepth = meta["bitdepth"]
    assert bitdepth == 8
    planes = meta["planes"]
    assert planes == 3 or planes == 4
    format = Texture_format8.Rgb if planes == 3 else Texture_format8.Rgba
    return width, height, format, pixels

def save_texture(texture, fname):
    with open(fname, "wb") as f:
        f.write(texture)

def main():
    width, height, format, pixels = load_image("texture.png")
    texture = create_texture(width, height, format, pixels)
    save_texture(texture, "texture.blob")

main()