protected bool writeData(IntPtr data, int length) { var dataBuffer = new byte[length]; Marshal.Copy(data, dataBuffer, 0, length); DxtBitmapContent texContent = null; switch (_format) { case Format.DXT1: texContent = new Dxt1BitmapContent(_levelWidth, _levelHeight); break; case Format.DXT3: texContent = new Dxt3BitmapContent(_levelWidth, _levelHeight); break; case Format.DXT5: texContent = new Dxt5BitmapContent(_levelWidth, _levelHeight); break; } if (_content.Faces[0].Count == _currentMipLevel) _content.Faces[0].Add(texContent); else _content.Faces[0][_currentMipLevel] = texContent; _content.Faces[0][_currentMipLevel].SetPixelData(dataBuffer); return true; }
/// <summary> /// 指定された単色ビットマップ画像をDXT3テクスチャへ変換する /// </summary> /// <param name="source">変換元画像</param> /// <param name="color0">単色カラー</param> /// <returns>DXT3圧縮された画像</returns> public static Dxt3BitmapContent Compress(PixelBitmapContent<Color> source, Color color0) { // DXT3ブロックデータを格納するためのバッファを確保 byte[] outputData = new byte[source.Width * source.Height]; // 単色カラーをBGR565に変換する ushort packedColor = new Bgr565(color0.ToVector3()).PackedValue; // 指定された画像を圧縮ブロック単位に処理をする int outputIndex = 0; for (int blockY = 0; blockY < source.Height; blockY += 4) { for (int blockX = 0; blockX < source.Width; blockX += 4) { CompressDxt3Block(source, blockX, blockY, packedColor, outputData, outputIndex); outputIndex += 16; } } // DXT3テクスチャの生成と圧縮したブロックデータの設定 var result = new Dxt3BitmapContent(source.Width, source.Height); result.SetPixelData(outputData); return result; }
protected bool writeData(IntPtr data, int length) { var dataBuffer = new byte[length]; Marshal.Copy(data, dataBuffer, 0, length); DxtBitmapContent texContent = null; switch (_format) { case Format.DXT1: texContent = new Dxt1BitmapContent(_levelWidth, _levelHeight); break; case Format.DXT3: texContent = new Dxt3BitmapContent(_levelWidth, _levelHeight); break; case Format.DXT5: texContent = new Dxt5BitmapContent(_levelWidth, _levelHeight); break; } if (_content.Faces[0].Count == _currentMipLevel) { _content.Faces[0].Add(texContent); } else { _content.Faces[0][_currentMipLevel] = texContent; } _content.Faces[0][_currentMipLevel].SetPixelData(dataBuffer); return(true); }
// Compress the greyscale font texture page using a specially-formulated DXT3 mode static public unsafe void CompressFontDXT3(TextureContent content) { if (content.Faces.Count > 1) { throw new PipelineException("Font textures should only have one face"); } var block = new Vector4[16]; for (int i = 0; i < content.Faces[0].Count; ++i) { var face = content.Faces[0][i]; var xBlocks = (face.Width + 3) / 4; var yBlocks = (face.Height + 3) / 4; var dxt3Size = xBlocks * yBlocks * 16; var buffer = new byte[dxt3Size]; var bytes = face.GetPixelData(); fixed(byte *b = bytes) { Vector4 *colors = (Vector4 *)b; int w = 0; int h = 0; int x = 0; int y = 0; while (h < (face.Height & ~3)) { w = 0; x = 0; var h0 = h * face.Width; var h1 = h0 + face.Width; var h2 = h1 + face.Width; var h3 = h2 + face.Width; while (w < (face.Width & ~3)) { block[0] = colors[w + h0]; block[1] = colors[w + h0 + 1]; block[2] = colors[w + h0 + 2]; block[3] = colors[w + h0 + 3]; block[4] = colors[w + h1]; block[5] = colors[w + h1 + 1]; block[6] = colors[w + h1 + 2]; block[7] = colors[w + h1 + 3]; block[8] = colors[w + h2]; block[9] = colors[w + h2 + 1]; block[10] = colors[w + h2 + 2]; block[11] = colors[w + h2 + 3]; block[12] = colors[w + h3]; block[13] = colors[w + h3 + 1]; block[14] = colors[w + h3 + 2]; block[15] = colors[w + h3 + 3]; int offset = (x + y * xBlocks) * 16; CompressFontDXT3Block(block, buffer, offset); w += 4; ++x; } // Do partial block at end of row if (w < face.Width) { var cols = face.Width - w; Array.Clear(block, 0, 16); for (int r = 0; r < 4; ++r) { h0 = (h + r) * face.Width; for (int c = 0; c < cols; ++c) { block[(r * 4) + c] = colors[w + h0 + c]; } } int offset = (x + y * xBlocks) * 16; CompressFontDXT3Block(block, buffer, offset); } h += 4; ++y; } // Do last partial row if (h < face.Height) { var rows = face.Height - h; w = 0; x = 0; while (w < (face.Width & ~3)) { Array.Clear(block, 0, 16); for (int r = 0; r < rows; ++r) { var h0 = (h + r) * face.Width; block[(r * 4) + 0] = colors[w + h0 + 0]; block[(r * 4) + 1] = colors[w + h0 + 1]; block[(r * 4) + 2] = colors[w + h0 + 2]; block[(r * 4) + 3] = colors[w + h0 + 3]; } int offset = (x + y * xBlocks) * 16; CompressFontDXT3Block(block, buffer, offset); w += 4; ++x; } // Do last partial block if (w < face.Width) { var cols = face.Width - w; Array.Clear(block, 0, 16); for (int r = 0; r < rows; ++r) { var h0 = (h + r) * face.Width; for (int c = 0; c < cols; ++c) { block[(r * 4) + c] = colors[w + h0 + c]; } } int offset = (x + y * xBlocks) * 16; CompressFontDXT3Block(block, buffer, offset); } } } var dxt3 = new Dxt3BitmapContent(face.Width, face.Height); dxt3.SetPixelData(buffer); content.Faces[0][i] = dxt3; } }
/// <summary> /// Converts a DigitalRune <see cref="Image"/> to an XNA <see cref="BitmapContent"/>. /// </summary> /// <param name="image">The <see cref="Image"/>.</param> /// <returns>The <see cref="BitmapContent"/>.</returns> public static BitmapContent ToContent(Image image) { BitmapContent content; switch (image.Format) { case DataFormat.R8G8B8A8_UNORM: case DataFormat.R8G8B8A8_UNORM_SRGB: content = new PixelBitmapContent<Color>(image.Width, image.Height); break; case DataFormat.B5G6R5_UNORM: content = new PixelBitmapContent<Bgr565>(image.Width, image.Height); break; #if !MONOGAME case DataFormat.B5G5R5A1_UNORM: content = new PixelBitmapContent<Bgra5551>(image.Width, image.Height); break; #endif case DataFormat.B4G4R4A4_UNORM: content = new PixelBitmapContent<Bgra4444>(image.Width, image.Height); break; case DataFormat.BC1_UNORM: case DataFormat.BC1_UNORM_SRGB: content = new Dxt1BitmapContent(image.Width, image.Height); break; case DataFormat.BC2_UNORM: case DataFormat.BC2_UNORM_SRGB: content = new Dxt3BitmapContent(image.Width, image.Height); break; case DataFormat.BC3_UNORM: case DataFormat.BC3_UNORM_SRGB: content = new Dxt5BitmapContent(image.Width, image.Height); break; case DataFormat.R8G8_SNORM: content = new PixelBitmapContent<NormalizedByte2>(image.Width, image.Height); break; case DataFormat.R8G8B8A8_SNORM: content = new PixelBitmapContent<NormalizedByte4>(image.Width, image.Height); break; #if !MONOGAME case DataFormat.R10G10B10A2_UNORM: content = new PixelBitmapContent<Rgba1010102>(image.Width, image.Height); break; case DataFormat.R16G16_UNORM: content = new PixelBitmapContent<Rg32>(image.Width, image.Height); break; case DataFormat.R16G16B16A16_UNORM: content = new PixelBitmapContent<Rgba64>(image.Width, image.Height); break; case DataFormat.A8_UNORM: case DataFormat.R8_UNORM: content = new PixelBitmapContent<Alpha8>(image.Width, image.Height); break; #endif case DataFormat.R32_FLOAT: content = new PixelBitmapContent<float>(image.Width, image.Height); break; case DataFormat.R32G32_FLOAT: content = new PixelBitmapContent<Vector2>(image.Width, image.Height); break; case DataFormat.R32G32B32A32_FLOAT: content = new PixelBitmapContent<Vector4>(image.Width, image.Height); break; case DataFormat.R16_FLOAT: content = new PixelBitmapContent<HalfSingle>(image.Width, image.Height); break; case DataFormat.R16G16_FLOAT: content = new PixelBitmapContent<HalfVector2>(image.Width, image.Height); break; case DataFormat.R16G16B16A16_FLOAT: content = new PixelBitmapContent<HalfVector4>(image.Width, image.Height); break; #if MONOGAME case DataFormat.PVRTCI_2bpp_RGB: content = new PvrtcRgb2BitmapContent(image.Width, image.Height); break; case DataFormat.PVRTCI_4bpp_RGB: content = new PvrtcRgb4BitmapContent(image.Width, image.Height); break; case DataFormat.PVRTCI_2bpp_RGBA: content = new PvrtcRgba2BitmapContent(image.Width, image.Height); break; case DataFormat.PVRTCI_4bpp_RGBA: content = new PvrtcRgba4BitmapContent(image.Width, image.Height); break; case DataFormat.ETC1: content = new Etc1BitmapContent(image.Width, image.Height); break; //case DataFormat.ATC_RGB: Not supported in MonoGame. case DataFormat.ATC_RGBA_EXPLICIT_ALPHA: content = new AtcExplicitBitmapContent(image.Width, image.Height); break; case DataFormat.ATC_RGBA_INTERPOLATED_ALPHA: content = new AtcInterpolatedBitmapContent(image.Width, image.Height); break; #endif default: string message = string.Format("The texture format {0} is not supported in MonoGame.", image.Format); throw new NotSupportedException(message); // Not supported: // SurfaceFormat.HdrBlendable // Only needed as render target format. // SurfaceFormat.Bgr32 // Only used as WPF render target. // SurfaceFormat.Bgra32 // Only used as WPF render target. // SurfaceFormat.Dxt1a } Debug.Assert(content != null); #if !MONOGAME // content.GetPixelData() is null in MonoGame. Debug.Assert(image.Data.Length == content.GetPixelData().Length); #endif content.SetPixelData(image.Data); return content; }