static void BitmapAssert(BitmapContent bitmap, Color color, int range) { byte[] rgba; if (bitmap is Dxt1BitmapContent) { rgba = DxtUtil.DecompressDxt1(bitmap.GetPixelData(), bitmap.Width, bitmap.Height); } else if (bitmap is Dxt3BitmapContent) { rgba = DxtUtil.DecompressDxt3(bitmap.GetPixelData(), bitmap.Width, bitmap.Height); } else if (bitmap is Dxt5BitmapContent) { rgba = DxtUtil.DecompressDxt5(bitmap.GetPixelData(), bitmap.Width, bitmap.Height); } else { rgba = bitmap.GetPixelData(); } for (var p = 0; p < rgba.Length; p += 4) { Assert.That(rgba[p + 0], Is.EqualTo(color.R).Within(range)); Assert.That(rgba[p + 1], Is.EqualTo(color.G).Within(range)); Assert.That(rgba[p + 2], Is.EqualTo(color.B).Within(range)); Assert.That(rgba[p + 3], Is.EqualTo(color.A).Within(range)); } }
/// <summary> /// Construye el mapa de alturas a partir de la textura especificada /// </summary> /// <param name="terrain">Textura con el mapa de alturas del terreno</param> /// <param name="cellScale">Escala de alturas</param> /// <param name="context">Contexto</param> /// <returns>Devuelve el mapa de alturas generado</returns> private HeightMap BuildHeightMap(Texture2DContent terrain, float cellScale, ContentProcessorContext context) { if (terrain.Mipmaps.Count > 0) { BitmapContent heightMapContent = terrain.Mipmaps[0]; // Sólo se soportan texturas cuadradas if (heightMapContent.Width == heightMapContent.Height) { byte[] pixelData = heightMapContent.GetPixelData(); // Construir el mapa de alturas return(HeightMap.FromData( pixelData, heightMapContent.Height, heightMapContent.Width, cellScale)); } else { //Sólo se soportan texturas cuadradas throw new NotImplementedException(); } } else { throw new PipelineException("El archivo de mapa de alturas no tiene el formato correcto. No se encuentra la imagen"); } }
public static SpriteFont Compile(GraphicsDevice g, string file, out IDisposable gR) { FontDescriptionImporter ei = new FontDescriptionImporter(); FontDescription ec = ei.Import(file, new XNADynImporterContext()); FontDescriptionProcessor ep = new FontDescriptionProcessor(); var cec = ep.Process(ec, new XNADynProcessorContext()); // Get Private Texture Texture2DContent texC = sfcTexture.GetValue(cec) as Texture2DContent; MipmapChain o = txcMipmaps.GetValue(texC, null) as MipmapChain; BitmapContent texBMP = o[0]; SurfaceFormat sf; if (!texBMP.TryGetFormat(out sf)) { throw new InvalidContentException("Could Not Obtain The Surface Format Of The SpriteFont"); } Texture2D texture = new Texture2D(g, texBMP.Width, texBMP.Height, false, sf); texture.SetData(texBMP.GetPixelData()); // Get Private Glyph Data List <Rectangle> glyphs = sfcGlyphs.GetValue(cec) as List <Rectangle>; List <Rectangle> cropping = sfcCropping.GetValue(cec) as List <Rectangle>; List <char> charMap = sfcCharMap.GetValue(cec) as List <char>; int lineSpacing = (int)sfcLineSpacing.GetValue(cec); float spacing = (float)sfcSpacing.GetValue(cec); List <Vector3> kerning = sfcKerning.GetValue(cec) as List <Vector3>; char? defaultChar = sfcDefaultChar.GetValue(cec) as char?; // Invoke Private SpriteFont Constructor gR = texture; return(sfConstructor.Invoke(new object[] { texture, glyphs, cropping, charMap, lineSpacing, spacing, kerning, defaultChar }) as SpriteFont); }
unsafe private static BitmapContent ConvertToColor(BitmapContent input) { var width = input.Width; var height = input.Height; SurfaceFormat format; input.TryGetFormat(out format); var formatSize = DDSImporter.GetBitmapSize(format, width, height); var blocks = formatSize; var inData = input.GetPixelData(); var output = new PixelBitmapContent <Color>(width, height); fixed(byte *p = &inData[0]) { DXT1Block *block = (DXT1Block *)p; //convert DXT1 to color for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int blockIdx = (x / 4) + (y / 4) * (width / 4); int colorIndex = x % 4 + (y % 4) * 4; Color color = block[blockIdx].GetColor(colorIndex); output.SetPixel(x, y, color); } } } return(output); }
public override List <Vertices> Process(TextureContent input, ContentProcessorContext context) { BitmapContent bitmap = input.Faces[0][0]; byte[] bytes = bitmap.GetPixelData(); Debug.Assert(bytes.Length % 4 == 0); // Note(manu): If this were C/C++, we could simply reinterpret the byte-array as a uint-array... uint[] data = new uint[bytes.Length / 4]; for (int dataIndex = 0; dataIndex < data.Length; dataIndex++) { int byteIndex = dataIndex * 4; data[dataIndex] = BitConverter.ToUInt32(bytes, byteIndex); } DateTime vertStart = DateTime.Now; TextureConverter textureConverter = new TextureConverter(data, bitmap.Width) { PolygonDetectionType = PolygonDetectionType, HoleDetection = HoleDetection, MultipartDetection = MultipartDetection, PixelOffsetOptimization = PixelOffsetOptimization, Transform = Matrix.CreateScale(UniformScale * Conversion.RenderScale), // TODO(manu): Use z=1 instead? AlphaTolerance = (byte)AlphaTolerance, HullTolerance = HullTolerance, }; List <Vertices> vertices = textureConverter.DetectVertices(); TimeSpan vertDuration = DateTime.Now - vertStart; Diagnostic(context.Logger, $"Parsing vertices took {vertDuration.TotalSeconds.ToString("0.000")} seconds (VelcroPhysics)."); return(vertices); }
public override List<ScreenLayoutInfo> Process(TextureContent input, ContentProcessorContext context) { BitmapContent bitmap = input.Faces[0][0]; byte[] bytes = bitmap.GetPixelData(); Debug.Assert(bytes.Length % 4 == 0); int mapWidth = bitmap.Width; int mapHeight = bitmap.Height; int numJobs = Environment.ProcessorCount; int numLinesPerJob = mapHeight / numJobs; JobInfo[] jobInfos = new JobInfo[numJobs]; for(int jobIndex = 0; jobIndex < numJobs; jobIndex++) { // Example: Assume numLinesPerJob = 10: jobInfos[jobIndex].rowOffset = jobIndex * numLinesPerJob; // 0, 10, 20, ... jobInfos[jobIndex].rowCount = numLinesPerJob; // 10, 10, 10, ... jobInfos[jobIndex].infos = new List<ScreenLayoutInfo>(); jobInfos[jobIndex].warnings = new List<string>(); } DateTime start = DateTime.Now; #if PARALLEL Parallel.ForEach(Enumerable.Range(0, numJobs), (jobIndex) => #else for(int jobIndex = 0; jobIndex < numJobs; jobIndex++) #endif { int numRowsToProcess = jobInfos[jobIndex].rowCount; for(int localRow = 0; localRow < numRowsToProcess; localRow++) { int row = localRow + jobInfos[jobIndex].rowOffset; ParseLayoutInfos(bytes, row, mapWidth, jobInfos[jobIndex].infos, jobInfos[jobIndex].warnings); } }
internal static void WriteUncompressed(string filename, BitmapContent bitmapContent) { using (var fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write)) using (var writer = new BinaryWriter(fileStream)) { // Signature ("DDS ") writer.Write((byte)0x44); writer.Write((byte)0x44); writer.Write((byte)0x53); writer.Write((byte)0x20); var header = new DdsHeader { dwSize = 124, dwFlags = Ddsd.Caps | Ddsd.Width | Ddsd.Height | Ddsd.Pitch | Ddsd.PixelFormat, dwWidth = (uint)bitmapContent.Width, dwHeight = (uint)bitmapContent.Height, dwPitchOrLinearSize = (uint)(bitmapContent.Width * 4), dwDepth = 0, dwMipMapCount = 0 }; writer.Write(header.dwSize); writer.Write((uint)header.dwFlags); writer.Write(header.dwHeight); writer.Write(header.dwWidth); writer.Write(header.dwPitchOrLinearSize); writer.Write(header.dwDepth); writer.Write(header.dwMipMapCount); // 11 unused and reserved DWORDS. for (int i = 0; i < 11; i++) { writer.Write((uint)0); } if (!bitmapContent.TryGetFormat(out SurfaceFormat format) || format != SurfaceFormat.Rgba32) { throw new NotSupportedException("Unsupported bitmap content!"); } header.ddspf.dwSize = 32; header.ddspf.dwFlags = Ddpf.AlphaPixels | Ddpf.Rgb; header.ddspf.dwFourCC = 0; header.ddspf.dwRgbBitCount = 32; header.ddspf.dwRBitMask = 0x000000ff; header.ddspf.dwGBitMask = 0x0000ff00; header.ddspf.dwBBitMask = 0x00ff0000; header.ddspf.dwABitMask = 0xff000000; // Write the DDS_PIXELFORMAT writer.Write(header.ddspf.dwSize); writer.Write((uint)header.ddspf.dwFlags); writer.Write((uint)header.ddspf.dwFourCC); writer.Write(header.ddspf.dwRgbBitCount); writer.Write(header.ddspf.dwRBitMask); writer.Write(header.ddspf.dwGBitMask); writer.Write(header.ddspf.dwBBitMask); writer.Write(header.ddspf.dwABitMask); header.dwCaps = DdsCaps.Texture; header.dwCaps2 = 0; // Continue reading DDS_HEADER writer.Write((uint)header.dwCaps); writer.Write((uint)header.dwCaps2); // More reserved unused DWORDs. for (int i = 0; i < 3; i++) { writer.Write((uint)0); } // Write out the face data. writer.Write(bitmapContent.GetPixelData()); } }
public override TextureContent Process(TextureContent input, ContentProcessorContext context) { //System.Diagnostics.Debugger.Launch(); input.Validate(); try { using (CompressorOptionsBundle compressor = new CompressorOptionsBundle()) { compressor.InputOptions.ResetTextureLayout(); TextureType textureType = FindTextureType(input); /* * Set options */ compressor.InputOptions.SetTextureLayout(textureType, input.Faces[0][0].Width, input.Faces[0][0].Height, 1); compressor.InputOptions.SetFormat(InputFormat.BGRA_8UB); compressor.InputOptions.SetAlphaMode(AlphaMode); compressor.InputOptions.SetMipmapFilter(MipMapFilter); compressor.InputOptions.SetMipmapGeneration(GenerateMipmaps, MaxMipMapLevel); compressor.InputOptions.SetRoundMode(TextureRoundingMode); compressor.InputOptions.SetWrapMode(WrapMode); compressor.InputOptions.SetGamma(InputGamma, OutputGamma); compressor.InputOptions.SetNormalizeMipmaps(false); compressor.InputOptions.SetNormalMap(false); compressor.InputOptions.SetConvertToNormalMap(false); compressor.CompressionOptions.SetQuality(Quality); GeneralOutputHandler outputHandler; switch (TextureFormat) { case TextureOutputFormat.Colour: compressor.CompressionOptions.SetFormat(Format.RGBA); outputHandler = new PixelOutputHandler <Color>(textureType); break; case TextureOutputFormat.Normals: compressor.CompressionOptions.SetFormat(Format.RGBA); outputHandler = new PixelOutputHandler <Color>(textureType); compressor.InputOptions.SetNormalizeMipmaps(true); compressor.InputOptions.SetNormalMap(true); compressor.InputOptions.SetConvertToNormalMap(ConvertToNormalMap); compressor.InputOptions.SetGamma(1.0f, 1.0f); break; case TextureOutputFormat.DXT1: compressor.CompressionOptions.SetFormat(Format.DXT1); outputHandler = new Dxt1OutputHandler(textureType); break; case TextureOutputFormat.DXT1a: compressor.CompressionOptions.SetFormat(Format.DXT1a); outputHandler = new Dxt1OutputHandler(textureType); break; case TextureOutputFormat.DXT3: compressor.CompressionOptions.SetFormat(Format.DXT3); outputHandler = new Dxt3OutputHandler(textureType); break; case TextureOutputFormat.DXT5: compressor.CompressionOptions.SetFormat(Format.DXT5); outputHandler = new Dxt5OutputHandler(textureType); break; case TextureOutputFormat.DXT5n: //FIXME: We force fastest quality since the normal compression mode is _very_ slow. compressor.CompressionOptions.SetQuality(Quality.Fastest); compressor.CompressionOptions.SetFormat(Format.DXT5n); compressor.InputOptions.SetNormalizeMipmaps(true); compressor.InputOptions.SetNormalMap(true); compressor.InputOptions.SetConvertToNormalMap(ConvertToNormalMap); compressor.InputOptions.SetGamma(1.0f, 1.0f); outputHandler = new Dxt5OutputHandler(textureType); break; default: throw new NotSupportedException("Unknown texture output format: " + TextureFormat); } /* * Set input data */ //TODO: Use a float format when texture tools support it. input.ConvertBitmapType(typeof(PixelBitmapContent <Color>)); for (int i = 0; i < input.Faces.Count; i++) { MipmapChain mipChain = input.Faces[i]; for (int j = 0; j < mipChain.Count; j++) { BitmapContent bitmap = mipChain[j]; byte[] bitmapData = bitmap.GetPixelData(); //FIXME: When we move to XNA 4 the layout of Color will change, hence we need to swizzle the input. compressor.InputOptions.SetMipmapData(bitmapData, bitmap.Width, bitmap.Height, 1, i, j); } } /* * Setup output */ compressor.OutputOptions.SetOutputHandler(outputHandler); compressor.OutputOptions.SetOutputHeader(false); /* * Go! */ compressor.Compressor.SetEnableCuda(EnableCuda); compressor.Compress(); /* * Check the output makes sense. */ outputHandler.OutputTextureContent.Validate(); return(outputHandler.OutputTextureContent); } } catch (TextureToolsException ttexcept) { throw ConvertException(ttexcept); } }