public static byte[] Headerize(TPF.Texture texture) { if (SFEncoding.ASCII.GetString(texture.Bytes, 0, 4) == "DDS ") { return(texture.Bytes); } var dds = new DDS(); byte format = texture.Format; short width = texture.Header.Width; short height = texture.Header.Height; int mipCount = texture.Mipmaps; TPF.TexType type = texture.Type; dds.dwFlags = DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT | DDSD.MIPMAPCOUNT; if (CompressedBPB.ContainsKey(format)) { dds.dwFlags |= DDSD.LINEARSIZE; } else if (UncompressedBPP.ContainsKey(format)) { dds.dwFlags |= DDSD.PITCH; } dds.dwHeight = height; dds.dwWidth = width; if (CompressedBPB.ContainsKey(format)) { dds.dwPitchOrLinearSize = Math.Max(1, (width + 3) / 4) * CompressedBPB[format]; } else if (UncompressedBPP.ContainsKey(format)) { dds.dwPitchOrLinearSize = (width * UncompressedBPP[format] + 7) / 8; } // This line serves only to remind me that I didn't forget about dwDepth, I left it 0 on purpose. dds.dwDepth = 0; if (mipCount == 0) { mipCount = DetermineMipCount(width, height); } dds.dwMipMapCount = mipCount; dds.dwCaps = DDSCAPS.TEXTURE; if (type == TPF.TexType.Cubemap) { dds.dwCaps |= DDSCAPS.COMPLEX; } if (mipCount > 1) { dds.dwCaps |= DDSCAPS.COMPLEX | DDSCAPS.MIPMAP; } if (type == TPF.TexType.Cubemap) { dds.dwCaps2 = CUBEMAP_ALLFACES; } else if (type == TPF.TexType.Volume) { dds.dwCaps2 = DDSCAPS2.VOLUME; } PIXELFORMAT ddspf = dds.ddspf; if (FourCC.ContainsKey(format) || DX10Formats.Contains(format)) { ddspf.dwFlags = DDPF.FOURCC; } if (format == 6) { ddspf.dwFlags |= DDPF.ALPHAPIXELS | DDPF.RGB; } else if (format == 9) { ddspf.dwFlags |= DDPF.ALPHAPIXELS | DDPF.RGB; } else if (format == 10) { ddspf.dwFlags |= DDPF.RGB; } else if (format == 16) { ddspf.dwFlags |= DDPF.ALPHA; } else if (format == 105) { ddspf.dwFlags |= DDPF.ALPHAPIXELS | DDPF.RGB; } if (FourCC.ContainsKey(format)) { ddspf.dwFourCC = FourCC[format]; } else if (DX10Formats.Contains(format)) { ddspf.dwFourCC = "DX10"; } if (format == 6) { ddspf.dwRGBBitCount = 16; ddspf.dwRBitMask = 0b01111100_00000000; ddspf.dwGBitMask = 0b00000011_11100000; ddspf.dwBBitMask = 0b00000000_00011111; ddspf.dwABitMask = 0b10000000_00000000; } else if (format == 9) { ddspf.dwRGBBitCount = 32; ddspf.dwRBitMask = 0x00FF0000; ddspf.dwGBitMask = 0x0000FF00; ddspf.dwBBitMask = 0x000000FF; ddspf.dwABitMask = 0xFF000000; } else if (format == 10) { ddspf.dwRGBBitCount = 24; ddspf.dwRBitMask = 0x00FF0000; ddspf.dwGBitMask = 0x0000FF00; ddspf.dwBBitMask = 0x000000FF; } else if (format == 16) { ddspf.dwRGBBitCount = 8; ddspf.dwABitMask = 0x000000FF; } else if (format == 105) { ddspf.dwRGBBitCount = 32; ddspf.dwRBitMask = 0x000000FF; ddspf.dwGBitMask = 0x0000FF00; ddspf.dwBBitMask = 0x00FF0000; ddspf.dwABitMask = 0xFF000000; } if (DX10Formats.Contains(format)) { dds.header10 = new HEADER_DXT10(); dds.header10.dxgiFormat = (DXGI_FORMAT)texture.Header.DXGIFormat; if (type == TPF.TexType.Cubemap) { dds.header10.miscFlag = RESOURCE_MISC.TEXTURECUBE; } } byte[] bytes = RebuildPixelData(texture.Bytes, format, width, height, mipCount, type); return(dds.Write(bytes)); }
public static byte[] Headerize(TPF.Texture texture) { if (SFEncoding.ASCII.GetString(texture.Bytes, 0, 4) == "DDS ") { return(texture.Bytes); } var dds = new DDS(); byte format = texture.Format; short width = texture.Header.Width; short height = texture.Header.Height; int mipCount = texture.Mipmaps; TPF.TexType type = texture.Type; dds.dwFlags = DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT | DDSD.MIPMAPCOUNT; if (CompressedBPB.ContainsKey(format)) { dds.dwFlags |= DDSD.PITCH; } else if (UncompressedBPP.ContainsKey(format)) { dds.dwFlags |= DDSD.LINEARSIZE; } dds.dwHeight = height; dds.dwWidth = width; if (CompressedBPB.ContainsKey(format)) { dds.dwPitchOrLinearSize = Math.Max(1, (width + 3) / 4) * CompressedBPB[format]; } else if (UncompressedBPP.ContainsKey(format)) { dds.dwPitchOrLinearSize = (width * UncompressedBPP[format] + 7) / 8; } if (mipCount == 0) { mipCount = DetermineMipCount(width, height); } dds.dwMipMapCount = mipCount; dds.dwCaps = DDSCAPS.TEXTURE; if (type == TPF.TexType.Cubemap) { dds.dwCaps |= DDSCAPS.COMPLEX; } if (mipCount > 1) { dds.dwCaps |= DDSCAPS.COMPLEX | DDSCAPS.MIPMAP; } if (type == TPF.TexType.Cubemap) { dds.dwCaps2 = CUBEMAP_ALLFACES; } else if (type == TPF.TexType.Volume) { dds.dwCaps2 = DDSCAPS2.VOLUME; } PIXELFORMAT ddspf = dds.ddspf; if (FourCC.ContainsKey(format) || DX10Formats.Contains(format)) { ddspf.dwFlags = DDPF.FOURCC; } if (format == 6) { ddspf.dwFlags |= DDPF.ALPHAPIXELS | DDPF.RGB; } else if (format == 9) { ddspf.dwFlags |= DDPF.ALPHAPIXELS | DDPF.RGB; } else if (format == 10) { ddspf.dwFlags |= DDPF.RGB; } else if (format == 16) { ddspf.dwFlags |= DDPF.ALPHA; } else if (format == 105) { ddspf.dwFlags |= DDPF.ALPHAPIXELS | DDPF.RGB; } if (format == 0 || format == 1) { ddspf.SetFourCCAsString("DXT1"); } else if (format == 3) { ddspf.SetFourCCAsString("DXT3"); } else if (format == 5) { ddspf.SetFourCCAsString("DXT5"); } else { ddspf.dwFourCC = 0; } if (format == 6) { ddspf.dwRGBBitCount = 16; ddspf.dwRBitMask = 0b01111100_00000000; ddspf.dwGBitMask = 0b00000011_11100000; ddspf.dwBBitMask = 0b00000000_00011111; ddspf.dwABitMask = 0b10000000_00000000; } else if (format == 9) { ddspf.dwRGBBitCount = 32; ddspf.dwRBitMask = 0x00FF0000; ddspf.dwGBitMask = 0x0000FF00; ddspf.dwBBitMask = 0x000000FF; ddspf.dwABitMask = 0xFF000000; } else if (format == 10) { ddspf.dwRGBBitCount = 24; ddspf.dwRBitMask = 0x00FF0000; ddspf.dwGBitMask = 0x0000FF00; ddspf.dwBBitMask = 0x000000FF; } else if (format == 16) { ddspf.dwRGBBitCount = 8; ddspf.dwABitMask = 0x000000FF; } else if (format == 105) { ddspf.dwRGBBitCount = 32; ddspf.dwRBitMask = 0x000000FF; ddspf.dwGBitMask = 0x0000FF00; ddspf.dwBBitMask = 0x00FF0000; ddspf.dwABitMask = 0xFF000000; } if (DX10Formats.Contains(format)) { dds.header10 = new HEADER_DXT10(); dds.header10.dxgiFormat = (DXGI_FORMAT)texture.Header.DXGIFormat; if (type == TPF.TexType.Cubemap) { dds.header10.miscFlag = DDS_RESOURCE_MISC.TEXTURECUBE; } } byte[] bytes = texture.Bytes; int imageCount = type == TPF.TexType.Cubemap ? 6 : 1; List <Image> images = null; if (CompressedBPB.ContainsKey(format)) { images = Image.ReadCompressed(bytes, width, height, imageCount, mipCount, 0x80, CompressedBPB[format]); } else if (UncompressedBPP.ContainsKey(format)) { images = Image.ReadUncompressed(bytes, width, height, imageCount, mipCount, 0x80, UncompressedBPP[format]); } if (format == 10) { int texelSize = -1; int texelWidth = -1; if (format == 10) { texelSize = 4; texelWidth = width; } foreach (Image image in images) { for (int i = 0; i < image.MipLevels.Count; i++) { byte[] swizzled = image.MipLevels[i]; byte[] unswizzled = DeswizzlePS3(swizzled, texelSize, texelWidth / (int)Math.Pow(2, i)); if (format == 10) { byte[] trimmed = new byte[unswizzled.Length / 4 * 3]; for (int j = 0; j < unswizzled.Length / 4; j++) { Array.Reverse(unswizzled, j * 4, 4); Array.Copy(unswizzled, j * 4, trimmed, j * 3, 3); } unswizzled = trimmed; } image.MipLevels[i] = unswizzled; } } } if (images != null) { bytes = Image.Write(images); } return(dds.Write(bytes)); }
private static byte[] RebuildPixelData(byte[] bytes, byte format, short width, short height, int mipCount, TPF.TexType type) { int imageCount = type == TPF.TexType.Cubemap ? 6 : 1; int padDimensions = 1; if (format == 102) { padDimensions = 32; } List <Image> images; if (CompressedBPB.ContainsKey(format)) { images = Image.ReadCompressed(bytes, width, height, padDimensions, imageCount, mipCount, 0x80, CompressedBPB[format]); } else if (UncompressedBPP.ContainsKey(format)) { images = Image.ReadUncompressed(bytes, width, height, padDimensions, imageCount, mipCount, 0x80, UncompressedBPP[format]); } else { throw new NotSupportedException($"Cannot decompose format {format}."); } if (format == 10 || format == 102) { int texelSize = -1; if (format == 10) { texelSize = 4; } else if (format == 102) { texelSize = 16; } foreach (Image image in images) { for (int i = 0; i < image.MipLevels.Count; i++) { int scale = (int)Math.Pow(2, i); image.MipLevels[i] = DeswizzleMipLevel(image.MipLevels[i], format, texelSize, width / scale, height / scale, padDimensions); } } } return(Image.Write(images)); }