private static TextureContent Compress(Type bitmapContentType, Texture texture, ContentIdentity identity) { // Let MonoGame's BitmapContent handle the compression. var description = texture.Description; switch (description.Dimension) { case TextureDimension.Texture1D: case TextureDimension.Texture2D: { var textureContent = new Texture2DContent { Identity = identity }; for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var image = texture.Images[texture.GetImageIndex(mipIndex, 0, 0)]; var sourceBitmap = TextureHelper.ToContent(image); var targetBitmap = (BitmapContent)Activator.CreateInstance(bitmapContentType, image.Width, image.Height); BitmapContent.Copy(sourceBitmap, targetBitmap); textureContent.Mipmaps.Add(targetBitmap); } return textureContent; } case TextureDimension.TextureCube: { var textureContent = new TextureCubeContent { Identity = identity }; for (int faceIndex = 0; faceIndex < 6; faceIndex++) { for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var image = texture.Images[texture.GetImageIndex(mipIndex, faceIndex, 0)]; var sourceBitmap = TextureHelper.ToContent(image); var targetBitmap = (BitmapContent)Activator.CreateInstance(bitmapContentType, image.Width, image.Height); BitmapContent.Copy(sourceBitmap, targetBitmap); textureContent.Faces[faceIndex].Add(targetBitmap); } } return textureContent; } case TextureDimension.Texture3D: { var textureContent = new Texture3DContent { Identity = identity }; for (int zIndex = 0; zIndex < description.Depth; zIndex++) { textureContent.Faces.Add(new MipmapChain()); for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var image = texture.Images[texture.GetImageIndex(mipIndex, 0, zIndex)]; var sourceBitmap = TextureHelper.ToContent(image); var targetBitmap = (BitmapContent)Activator.CreateInstance(bitmapContentType, image.Width, image.Height); BitmapContent.Copy(sourceBitmap, targetBitmap); textureContent.Faces[zIndex].Add(targetBitmap); } } return textureContent; } } throw new InvalidOperationException("Invalid texture dimension."); }
private TextureContent GenerateCubemap(TextureContent input, ContentProcessorContext context) { if (input.Faces[1].Count != 0) { //its already a cubemap return(base.Process(input, context)); } TextureCubeContent cubeContent = new TextureCubeContent(); // Convert the input data to Color format, for ease of processing. input.ConvertBitmapType(typeof(PixelBitmapContent <Color>)); int height = input.Faces[0][0].Height; int width = input.Faces[0][0].Width / 6; //split the image into 6 pieces, setup: X+,X-, Y+,Y-, Z+, Z- cubeContent.Faces[(int)CubeMapFace.PositiveX] = CreateFace(input.Faces[0][0], width, height, 0); cubeContent.Faces[(int)CubeMapFace.NegativeX] = CreateFace(input.Faces[0][0], width, height, width * 1); cubeContent.Faces[(int)CubeMapFace.PositiveY] = CreateFace(input.Faces[0][0], width, height, width * 2); cubeContent.Faces[(int)CubeMapFace.NegativeY] = CreateFace(input.Faces[0][0], width, height, width * 3); cubeContent.Faces[(int)CubeMapFace.PositiveZ] = CreateFace(input.Faces[0][0], width, height, width * 4); cubeContent.Faces[(int)CubeMapFace.NegativeZ] = CreateFace(input.Faces[0][0], width, height, width * 5); // Calculate mipmap data. cubeContent.GenerateMipmaps(true); // Compress the cubemap into DXT1 format. cubeContent.ConvertBitmapType(typeof(Dxt1BitmapContent)); return(cubeContent); }
/// <summary> /// Converts a DigitalRune <see cref="Texture"/> to an XNA <see cref="TextureContent"/>. /// </summary> /// <param name="texture">The <see cref="Texture"/>.</param> /// <param name="identity">The content identity.</param> /// <returns>The <see cref="TextureContent"/>.</returns> public static TextureContent ToContent(Texture texture, ContentIdentity identity) { var description = texture.Description; switch (description.Dimension) { case TextureDimension.Texture1D: case TextureDimension.Texture2D: { var textureContent = new Texture2DContent { Identity = identity }; for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var image = texture.Images[texture.GetImageIndex(mipIndex, 0, 0)]; textureContent.Mipmaps.Add(ToContent(image)); } return(textureContent); } case TextureDimension.TextureCube: { var textureContent = new TextureCubeContent { Identity = identity }; for (int faceIndex = 0; faceIndex < 6; faceIndex++) { for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var image = texture.Images[texture.GetImageIndex(mipIndex, faceIndex, 0)]; textureContent.Faces[faceIndex].Add(ToContent(image)); } } return(textureContent); } case TextureDimension.Texture3D: { var textureContent = new Texture3DContent { Identity = identity }; for (int zIndex = 0; zIndex < description.Depth; zIndex++) { textureContent.Faces.Add(new MipmapChain()); for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var image = texture.Images[texture.GetImageIndex(mipIndex, 0, zIndex)]; textureContent.Faces[zIndex].Add(ToContent(image)); } } return(textureContent); } } throw new InvalidOperationException("Invalid texture dimension."); }
public void TextureCubeContent() { var content = new TextureCubeContent(); Assert.NotNull(content.Faces); Assert.AreEqual(6, content.Faces.Count); Assert.NotNull(content.Faces[0]); Assert.NotNull(content.Faces[1]); Assert.NotNull(content.Faces[2]); Assert.NotNull(content.Faces[3]); Assert.NotNull(content.Faces[4]); Assert.NotNull(content.Faces[5]); Assert.AreEqual(0, content.Faces[0].Count); Assert.AreEqual(0, content.Faces[1].Count); Assert.AreEqual(0, content.Faces[2].Count); Assert.AreEqual(0, content.Faces[3].Count); Assert.AreEqual(0, content.Faces[4].Count); Assert.AreEqual(0, content.Faces[5].Count); var face0 = new MipmapChain(new PixelBitmapContent <Color>(2, 2)); content.Faces[0] = face0; Assert.AreEqual(face0, content.Faces[0]); Assert.AreEqual(1, content.Faces[0].Count); content.Faces[0].Add(new PixelBitmapContent <Color>(1, 1)); Assert.AreEqual(2, content.Faces[0].Count); content.Faces[1].Add(new PixelBitmapContent <Color>(2, 2)); content.Faces[2].Add(new PixelBitmapContent <Color>(2, 2)); content.Faces[3].Add(new PixelBitmapContent <Color>(2, 2)); content.Faces[4].Add(new PixelBitmapContent <Color>(2, 2)); content.Faces[5].Add(new PixelBitmapContent <Color>(2, 2)); Assert.AreEqual(1, content.Faces[1].Count); Assert.AreEqual(1, content.Faces[2].Count); Assert.AreEqual(1, content.Faces[3].Count); Assert.AreEqual(1, content.Faces[4].Count); Assert.AreEqual(1, content.Faces[5].Count); Assert.Throws <NotSupportedException>(() => content.Faces.Clear()); Assert.Throws <NotSupportedException>(() => content.Faces.RemoveAt(0)); Assert.Throws <NotSupportedException>(() => content.Faces.Add(new MipmapChain())); Assert.Throws <NotSupportedException>(() => content.Faces.Insert(0, new MipmapChain())); Assert.Throws <NotSupportedException>(() => content.Faces.Remove(content.Faces[0])); }
internal static TextureContent Import(string filename, ContentImporterContext context) { var identity = new ContentIdentity(filename); TextureContent output = null; using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)) using (var reader = new BinaryReader(fileStream)) { // Signature ("DDS ") if (reader.ReadByte() != 0x44 || reader.ReadByte() != 0x44 || reader.ReadByte() != 0x53 || reader.ReadByte() != 0x20) { throw new ContentLoadException("Invalid file signature"); } var header = new DdsHeader { // Read DDS_HEADER dwSize = reader.ReadUInt32() }; if (header.dwSize != 124) { throw new ContentLoadException("Invalid DDS_HEADER dwSize value"); } header.dwFlags = (Ddsd)reader.ReadUInt32(); header.dwHeight = reader.ReadUInt32(); header.dwWidth = reader.ReadUInt32(); header.dwPitchOrLinearSize = reader.ReadUInt32(); header.dwDepth = reader.ReadUInt32(); header.dwMipMapCount = reader.ReadUInt32(); // The next 11 DWORDs are reserved and unused for (int i = 0; i < 11; ++i) { reader.ReadUInt32(); } // Read DDS_PIXELFORMAT header.ddspf.dwSize = reader.ReadUInt32(); if (header.ddspf.dwSize != 32) { throw new ContentLoadException("Invalid DDS_PIXELFORMAT dwSize value"); } header.ddspf.dwFlags = (Ddpf)reader.ReadUInt32(); header.ddspf.dwFourCC = (FourCC)reader.ReadUInt32(); header.ddspf.dwRgbBitCount = reader.ReadUInt32(); header.ddspf.dwRBitMask = reader.ReadUInt32(); header.ddspf.dwGBitMask = reader.ReadUInt32(); header.ddspf.dwBBitMask = reader.ReadUInt32(); header.ddspf.dwABitMask = reader.ReadUInt32(); // Continue reading DDS_HEADER header.dwCaps = (DdsCaps)reader.ReadUInt32(); header.dwCaps2 = (DdsCaps2)reader.ReadUInt32(); reader.ReadUInt32(); // dwCaps3 unused reader.ReadUInt32(); // dwCaps4 unused reader.ReadUInt32(); // dwReserved2 unused // Check for the existence of the DDS_HEADER_DXT10 struct next if (header.ddspf.dwFlags == Ddpf.FourCC && header.ddspf.dwFourCC == FourCC.Dx10) { throw new ContentLoadException("Unsupported DDS_HEADER_DXT10 struct found"); } int faceCount = 1; int mipMapCount = (int)(header.dwCaps.HasFlag(DdsCaps.MipMap) ? header.dwMipMapCount : 1); if (header.dwCaps2.HasFlag(DdsCaps2.Cubemap)) { if (!header.dwCaps2.HasFlag(DdsCaps2.CubemapAllFaces)) { throw new ContentLoadException("Incomplete cubemap in DDS file"); } faceCount = 6; output = new TextureCubeContent() { Identity = identity }; } else { output = new Texture2DContent() { Identity = identity }; } var format = GetSurfaceFormat(ref header.ddspf, out bool rbSwap); for (int f = 0; f < faceCount; ++f) { int w = (int)header.dwWidth; int h = (int)header.dwHeight; var mipMaps = new MipmapChain(); for (int m = 0; m < mipMapCount; ++m) { var content = CreateBitmapContent(format, w, h); var byteCount = GetBitmapSize(format, w, h); // A 24-bit format is slightly different if (header.ddspf.dwRgbBitCount == 24) { byteCount = 3 * w * h; } var bytes = reader.ReadBytes(byteCount); if (rbSwap) { switch (format) { case SurfaceFormat.Bgr565: ByteSwapBGR565(bytes); break; case SurfaceFormat.Bgra4444: ByteSwapBGRA4444(bytes); break; case SurfaceFormat.Bgra5551: ByteSwapBGRA5551(bytes); break; case SurfaceFormat.Rgba32: if (header.ddspf.dwRgbBitCount == 32) { ByteSwapRGBX(bytes); } else if (header.ddspf.dwRgbBitCount == 24) { ByteSwapRGB(bytes); } break; } } if ((format == SurfaceFormat.Rgba32) && header.ddspf.dwFlags.HasFlag(Ddpf.Rgb) && !header.ddspf.dwFlags.HasFlag(Ddpf.AlphaPixels)) { // Fill or add alpha with opaque if (header.ddspf.dwRgbBitCount == 32) { ByteFillAlpha(bytes); } else if (header.ddspf.dwRgbBitCount == 24) { ByteExpandAlpha(ref bytes); } } content.SetPixelData(bytes); mipMaps.Add(content); w = Math.Max(1, w / 2); h = Math.Max(1, h / 2); } output.Faces[f] = mipMaps; } } return(output); }
static internal TextureContent Import(string filename, ContentImporterContext context) { var identity = new ContentIdentity(filename); TextureContent output = null; using (var reader = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read))) { // Read signature ("DDS ") var valid = reader.ReadByte() == 0x44; valid = valid && reader.ReadByte() == 0x44; valid = valid && reader.ReadByte() == 0x53; valid = valid && reader.ReadByte() == 0x20; if (!valid) { throw new ContentLoadException("Invalid file signature"); } var header = new DdsHeader(); // Read DDS_HEADER header.dwSize = reader.ReadUInt32(); if (header.dwSize != 124) { throw new ContentLoadException("Invalid DDS_HEADER dwSize value"); } header.dwFlags = (Ddsd)reader.ReadUInt32(); header.dwHeight = reader.ReadUInt32(); header.dwWidth = reader.ReadUInt32(); header.dwPitchOrLinearSize = reader.ReadUInt32(); header.dwDepth = reader.ReadUInt32(); header.dwMipMapCount = reader.ReadUInt32(); // The next 11 DWORDs are reserved and unused for (int i = 0; i < 11; ++i) { reader.ReadUInt32(); } // Read DDS_PIXELFORMAT header.ddspf.dwSize = reader.ReadUInt32(); if (header.ddspf.dwSize != 32) { throw new ContentLoadException("Invalid DDS_PIXELFORMAT dwSize value"); } header.ddspf.dwFlags = (Ddpf)reader.ReadUInt32(); header.ddspf.dwFourCC = (FourCC)reader.ReadUInt32(); header.ddspf.dwRgbBitCount = reader.ReadUInt32(); header.ddspf.dwRBitMask = reader.ReadUInt32(); header.ddspf.dwGBitMask = reader.ReadUInt32(); header.ddspf.dwBBitMask = reader.ReadUInt32(); header.ddspf.dwABitMask = reader.ReadUInt32(); // Continue reading DDS_HEADER header.dwCaps = (DdsCaps)reader.ReadUInt32(); header.dwCaps2 = (DdsCaps2)reader.ReadUInt32(); // dwCaps3 unused reader.ReadUInt32(); // dwCaps4 unused reader.ReadUInt32(); // dwReserved2 unused reader.ReadUInt32(); // Check for the existence of the DDS_HEADER_DXT10 struct next if (header.ddspf.dwFlags == Ddpf.FourCC && header.ddspf.dwFourCC == FourCC.Dx10) { throw new ContentLoadException("Unsupported DDS_HEADER_DXT10 struct found"); } int faceCount = 1; int mipMapCount = (int)(header.dwCaps.HasFlag(DdsCaps.MipMap) ? header.dwMipMapCount : 1); if (header.dwCaps.HasFlag(DdsCaps.Complex)) { if (header.dwCaps2.HasFlag(DdsCaps2.Cubemap)) { if (!header.dwCaps2.HasFlag(DdsCaps2.CubemapAllFaces)) { throw new ContentLoadException("Incomplete cubemap in DDS file"); } faceCount = 6; output = new TextureCubeContent() { Identity = identity }; } else { output = new Texture2DContent() { Identity = identity }; } } else { output = new Texture2DContent() { Identity = identity }; } bool rbSwap; var format = GetSurfaceFormat(ref header.ddspf, out rbSwap); for (int f = 0; f < faceCount; ++f) { var w = (int)header.dwWidth; var h = (int)header.dwHeight; var mipMaps = new MipmapChain(); for (int m = 0; m < mipMapCount; ++m) { var content = CreateBitmapContent(format, w, h); var byteCount = GetBitmapSize(format, w, h); var bytes = reader.ReadBytes(byteCount); content.SetPixelData(bytes); mipMaps.Add(content); w = MathHelper.Max(1, w / 2); h = MathHelper.Max(1, h / 2); } output.Faces[f] = mipMaps; } } return(output); }
private TextureCubeContent ImportCubeTexture(FIBITMAP bitmap, ImageType imageType, ContentManager manager) { TextureCubeContent content = new TextureCubeContent(); if (CubeFaces == null || CubeFaces.Length == 0) { int width = (int)FreeImage.GetWidth(bitmap); int height = (int)FreeImage.GetHeight(bitmap); // image is a cube cross if (width > height) // horizontal cross { width = width / 4; height = height / 3; // +x content.Faces[0][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width * 2, height, width * 3, height * 2)); // -x content.Faces[1][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, 0, height, width, height * 2)); // +y content.Faces[2][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width, 0, width * 2, height)); // -y content.Faces[3][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width, height * 2, width * 2, height * 3)); // +z content.Faces[4][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width, height, width * 2, height * 2)); // -z content.Faces[5][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width * 3, height, width * 4, height * 2)); } else // vertical cross { width = width / 3; height = height / 4; // +x content.Faces[0][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width * 2, height, width * 3, height * 2)); // -x content.Faces[1][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, 0, height, width, height * 2)); // +y content.Faces[2][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width, 0, width * 2, height)); // -y content.Faces[3][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width, height * 2, width * 2, height * 3)); // +z content.Faces[4][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width, height, width * 2, height * 2)); // -z content.Faces[5][0] = new BitmapContent(width, height, imageType, FreeImage.Copy(bitmap, width, height * 3, width * 2, height * 4)); } } else { int width = (int)FreeImage.GetWidth(bitmap); int height = (int)FreeImage.GetHeight(bitmap); try { // main image file is +x and CubeFaces contains images for [-x, +y, -y, +z, -z] content.Faces[0][0] = new BitmapContent(width, height, imageType, bitmap); FIBITMAP bitmap2 = FreeImage.LoadEx(CubeFaces[0]); // -x content.Faces[1][0] = new BitmapContent(width, height, imageType, bitmap2); bitmap2 = FreeImage.LoadEx(CubeFaces[1]); // +y content.Faces[2][0] = new BitmapContent(width, height, imageType, bitmap2); bitmap2 = FreeImage.LoadEx(CubeFaces[2]); // -y content.Faces[3][0] = new BitmapContent(width, height, imageType, bitmap2); bitmap2 = FreeImage.LoadEx(CubeFaces[3]); // +z content.Faces[4][0] = new BitmapContent(width, height, imageType, bitmap2); bitmap2 = FreeImage.LoadEx(CubeFaces[4]); // -z content.Faces[5][0] = new BitmapContent(width, height, imageType, bitmap2); } catch (Exception) { manager.Log.Error("Error loading cubemap files."); content = null; } } return(content); }
public override TextureContent Import(string filename, ContentImporterContext context) { TextureContent output; using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var reader = new BinaryReader(stream)) { var header = new DDSHeader(reader); if (header.PixelFormat.Flags == PF_Flags.FOURCC && header.PixelFormat.FourCC == PF_FourCC.DX10) { throw new NotImplementedException("DX10 Header not supported"); } if (header.PitchOrLinearSize != 0) { throw new NotImplementedException(); } if (header.Caps2.HasFlag(DDS_Caps2.CUBEMAP)) { var cube = new TextureCubeContent(); var format = GetFormat(header.PixelFormat); for (int f = 0; f < 6; f++) { var width = header.Width; var height = header.Height; BitmapContent bitmap = CreateBitmap(format, width, height); var size = GetBitmapSize(format, width, height); byte[] src = reader.ReadBytes(size); bitmap.SetPixelData(src); cube.Faces[f].Add(bitmap); if (header.Caps.HasFlag(DDS_Caps.MIPMAP)) { for (int m = 0; m < header.MipMapCount - 1; m++) { width = width / 2; height = height / 2; bitmap = CreateBitmap(format, width, height); size = GetBitmapSize(format, width, height); src = reader.ReadBytes(size); bitmap.SetPixelData(src); cube.Faces[f].Add(bitmap); } } } output = cube; } else { throw new NotImplementedException(header.Caps2 + " not supported"); } reader.Close(); stream.Close(); } } return(output); }