diff --git a/ArcFormats/ImageDDS.cs b/ArcFormats/ImageDDS.cs index 71bb0627..7431774c 100644 --- a/ArcFormats/ImageDDS.cs +++ b/ArcFormats/ImageDDS.cs @@ -2,7 +2,7 @@ //! \date Thu Jul 23 18:12:05 2015 //! \brief Direct Draw Surface image format. // -// Copyright (C) 2015 by morkt +// Copyright (C) 2015-2016 by morkt // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -23,8 +23,10 @@ // IN THE SOFTWARE. // +using System; using System.ComponentModel.Composition; using System.IO; +using System.Text; using System.Windows.Media; using GameRes.Utility; @@ -32,8 +34,20 @@ namespace GameRes.Formats.Microsoft { internal class DdsMetaData : ImageMetaData { - public int DataOffset; - public uint PixelFlags; + public int DataOffset; + public DdsPF PixelFlags; + public string FourCC; + } + + [Flags] + internal enum DdsPF : uint + { + AlphaPixels = 1, + Alpha = 2, + FourCC = 4, + Rgb = 0x40, + Yuv = 0x200, + Luminance = 0x20000, } [Export(typeof(ImageFormat))] @@ -51,30 +65,38 @@ namespace GameRes.Formats.Microsoft int dwSize = LittleEndian.ToInt32 (header, 4); if (dwSize < 0x7C) return null; - uint bitflag = LittleEndian.ToUInt32 (header, 0x50); + var bitflags = (DdsPF)LittleEndian.ToUInt32 (header, 0x50); + string four_cc = null; + if (bitflags.HasFlag (DdsPF.FourCC)) + four_cc = Binary.GetCString (header, 0x54, 4, Encoding.ASCII); return new DdsMetaData { Width = LittleEndian.ToUInt32 (header, 0x10), Height = LittleEndian.ToUInt32 (header, 0xC), BPP = LittleEndian.ToInt32 (header, 0x58), - PixelFlags = LittleEndian.ToUInt32 (header, 0x50), + PixelFlags = bitflags, + FourCC = four_cc, DataOffset = 4 + dwSize, }; } public override ImageData Read (Stream stream, ImageMetaData info) { - var meta = info as DdsMetaData; - if (null == meta) - throw new System.ArgumentException ("DdsFormat.Read should be supplied with DdsMetaData", "info"); - stream.Position = meta.DataOffset; + var meta = (DdsMetaData)info; + if (meta.PixelFlags.HasFlag (DdsPF.Yuv | DdsPF.Luminance)) + throw new NotSupportedException ("Not supported DDS texture color format"); + if (!string.IsNullOrEmpty (meta.FourCC)) + throw new NotImplementedException ("Compressed DDS textures not implemented"); PixelFormat format; if (24 == info.BPP) format = PixelFormats.Bgr24; - else if (1 == (meta.PixelFlags & 1)) + else if (16 == info.BPP) + throw new NotImplementedException ("16bpp DDS textures not implemented"); + else if (meta.PixelFlags.HasFlag (DdsPF.AlphaPixels)) format = PixelFormats.Bgra32; else format = PixelFormats.Bgr32; + stream.Position = meta.DataOffset; var pixels = new byte[info.Width*info.Height*((format.BitsPerPixel+7)/8)]; if (pixels.Length != stream.Read (pixels, 0, pixels.Length)) throw new InvalidFormatException ("Unexpected end of file");