more header parsing/writing work

main
Andrew Cassidy 3 years ago
parent cdea4674f8
commit 1c0de5b963

@ -73,67 +73,65 @@ class DDSPixelFlags(enum.IntFlag):
YUV = 0x200
LUMINANCE = 0x20000
class DDSHeader:
def __init__(self, f):
self.read(f)
class DDSFile:
def __init__(self, file = None):
if (file):
self.read_header(file)
def read(self, f):
if f.read(4).decode() != "DDS ":
raise ValueError(
"File is not a valid DDS f: Incorrect magic bytes")
def read_header(self, file):
# read magic bytes
if file.read(4).decode() != 'DDS ':
raise ValueError("File is not a valid DDS file: Incorrect magic bytes")
dwords = struct.unpack('20I4s10I', f.read(124))
# read header
header = struct.unpack('7I44x', file.read(72))
# check constants
if dwords[0] != 124:
raise ValueError(
"File is not a valid DDS file: Incorrect header size")
if dwords[18] != 32:
raise ValueError(
"File is not a valid DDS file: Incorrect pixelformat size")
# check constant
if header[0] != 124:
raise ValueError("File is not a valid DDS file: Incorrect header size")
# read basic info
self.flags = DDSFlags(dwords[1])
self.height, self.width = dwords[2:4]
self.flags = DDSFlags(header[1])
self.height, self.width, self.linear_size, self.depth, self.mipmapcount = header[2:7]
if DDSFlags.PITCH in self.flags:
self.pitch = dwords[4]
else:
self.linear_size = dwords[4]
if DDSFlags.DEPTH in self.flags:
self.depth = dwords[5]
# read pixelformat
pixelformat = struct.unpack('2I4s5I', file.read(32))
if DDSFlags.MIPMAPCOUNT in self.flags:
self.mipmapcount = dwords[6]
# check constant
if pixelformat[0] != 32:
raise ValueError("File is not a valid DDS file: Incorrect pixelformat size")
# read pixelformat
self.pixel_flags = DDSPixelFlags(dwords[19])
if DDSPixelFlags.ALPHAPIXELS in self.pixel_flags:
# texture has alpha data
self.a_bitmask = dwords[25]
if DDSPixelFlags.FOURCC in self.pixel_flags:
# texture is compressed, four_cc contains the format
self.format = dwords[20].decode()
else:
self.format = 'uncompressed'
if (DDSPixelFlags.RGB | DDSPixelFlags.YUV) & self.pixel_flags:
# uncompressed RGB texture
self.rgb_bit_count, self.r_bitmask, self.g_bitmask, self.b_bitmask = dwords[21:25]
elif DDSPixelFlags.ALPHA in self.pixel_flags:
# uncompressed alpha-only texture
self.rgb_bit_count = dwords[21]
self.a_bitmask = dwords[25]
elif DDSPixelFlags.LUMINANCE in self.pixel_flags:
# uncompressed luminance-only texture
self.rgb_bit_count = dwords[21]
self.r_bitmask = dwords[22]
self.pixel_flags = DDSPixelFlags(pixelformat[1])
self.four_cc = pixelformat[2].decode()
self.rgb_bit_count, self.r_bitmask, self.g_bitmask, self.b_bitmask, self.a_bitmask = pixelformat[3:8]
# read caps
self.dw_caps, self.dw_caps2, self.dw_caps3, self.dw_caps4 = dwords[26:30] # read dwCaps flags
self.dw_caps, self.dw_caps2, self.dw_caps3, self.dw_caps4 = struct.unpack('4I', file.read(16))
# read DX10 header
self.is_DX10 = (self.four_cc == 'DX10')
if self.is_DX10:
self.read_dx10header(file)
def read_dx10header(self, file):
dx10header = file.read(20)
#TODO: actually do something with the DX10 data
def write_header(self, file):
file.write('DDS ')
# write header
file.write(struct.pack(
'7I44x', 124, int(self.flags), self.height, self.width,
self.linear_size, self.depth, self.mipmapcount))
# write pixelformat
file.write(struct.pack(
'2I4s5I', 32, int(self.pixel_flags), self.four_cc, self.rgb_bit_count,
self.r_bitmask, self.g_bitmask, self.b_bitmask, self.a_bitmask))
# write caps
file.write(struct.pack(
'4I', self.dw_caps, self.dw_caps2, self.dw_caps3, self.dw_caps4))
if self.format == 'DX10':
dwords = f.read(20)
#TODO: actually read the DX10 data
#TODO: handle DX10 data

@ -13,8 +13,8 @@ modes = parser.add_mutually_exclusive_group()
modes.add_argument('--transparency', '-t', dest='mode', action='store_const', const="transparency", default="none", help = "Generate a list of files that fail the transparency check")
modes.add_argument('--format', '-f', dest='mode', action='store_const', const="format", default="none", help = "Generate a list of files that fail the format check")
parser.add_argument('--convertcmd', type=str, metavar='CMD', default="convert", help="name of imagemagick's convert tool (default: %(default)s)")
parser.add_argument('--infocmd', type=str, metavar='CMD', default="nvddsinfo", help="name of the nvidia dds info tool (default: %(default)s)")
parser.add_argument('--convertcmd', type=str, metavar='CMD', default=dds.convertcmd, help="name of imagemagick's convert tool (default: %(default)s)")
parser.add_argument('--infocmd', type=str, metavar='CMD', default=dds.infocmd, help="name of the nvidia dds info tool (default: %(default)s)")
args = parser.parse_args()

@ -14,8 +14,8 @@ parser.add_argument('--format', type=str, choices=['auto', 'DXT1', 'DXT5'], defa
parser.add_argument('--nomips', '-m', dest='mips', action='store_false', help = "Do not generate mipmaps")
parser.add_argument('--noflip', '-f', dest='flip', action='store_false', help = "Do not flip the image")
parser.add_argument('--keep', '-k', dest='delete', action='store_false', help = "Do not delete originals")
parser.add_argument('--convertcmd', type=str, metavar='CMD', default="convert", help="name of imagemagick's convert tool (default: %(default)s)")
parser.add_argument('--compresscmd', type=str, metavar='CMD', default="nvcompress", help="name of the nvidia dds compress tool (default: %(default)s)")
parser.add_argument('--convertcmd', type=str, metavar='CMD', default=dds.convertcmd, help="name of imagemagick's convert tool (default: %(default)s)")
parser.add_argument('--compresscmd', type=str, metavar='CMD', default=dds.compresscmd, help="name of the nvidia dds compress tool (default: %(default)s)")
args = parser.parse_args()
@ -33,7 +33,7 @@ with tempfile.TemporaryDirectory() as tempDir:
dds.flip(file, tmpOutput)
else:
tmpOutput = file
if (args.format == "auto" and dds.alpha(file) < 255) or args.format == "DXT5":
format = "-bc3"
else:

@ -8,7 +8,7 @@ import dds
parser = argparse.ArgumentParser(description="Converts any number of files from dds to tga.")
parser.add_argument('files', type=str, nargs='*', help = "input dds files")
parser.add_argument('--decompresscmd', type=str, metavar='CMD', default="nvdecompress", help="name of the nvidia dds decompress tool (default: %(default)s)")
parser.add_argument('--decompresscmd', type=str, metavar='CMD', default=dds.decompresscmd, help="name of the nvidia dds decompress tool (default: %(default)s)")
args = parser.parse_args()

Loading…
Cancel
Save