more header parsing/writing work
This commit is contained in:
parent
cdea4674f8
commit
1c0de5b963
102
Scripts/dds.py
102
Scripts/dds.py
@ -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]
|
||||
|
||||
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]
|
||||
|
||||
if DDSFlags.MIPMAPCOUNT in self.flags:
|
||||
self.mipmapcount = dwords[6]
|
||||
self.flags = DDSFlags(header[1])
|
||||
self.height, self.width, self.linear_size, self.depth, self.mipmapcount = header[2:7]
|
||||
|
||||
# read pixelformat
|
||||
self.pixel_flags = DDSPixelFlags(dwords[19])
|
||||
pixelformat = struct.unpack('2I4s5I', file.read(32))
|
||||
|
||||
if DDSPixelFlags.ALPHAPIXELS in self.pixel_flags:
|
||||
# texture has alpha data
|
||||
self.a_bitmask = dwords[25]
|
||||
# check constant
|
||||
if pixelformat[0] != 32:
|
||||
raise ValueError("File is not a valid DDS file: Incorrect pixelformat size")
|
||||
|
||||
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))
|
||||
|
||||
if self.format == 'DX10':
|
||||
dwords = f.read(20)
|
||||
#TODO: actually read the DX10 data
|
||||
# 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))
|
||||
|
||||
#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…
Reference in New Issue
Block a user