/// <summary>Must be called for the icons tile.</summary> public void LoadIcons() { using (BitmapResource image = new BitmapResource(imageFile, (maskFile != null ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb))) { if (maskFile != null) { using (BitmapResource mask = new BitmapResource(maskFile, PixelFormat.Format24bppRgb)) { applyMask(image, mask); } } size = new SizeF((float)image.BitmapData.Width, (float)image.BitmapData.Height); for (int i = (int)detailLevel; i > 0; --i) { size = new SizeF(size.Width * 2, size.Height * 2); } int mipMapLevelCount = 1; tiles = new DXTile[mipMapLevelCount + (int)detailLevel][, ]; int mipMapLevel = (int)detailLevel; tiles[mipMapLevel] = new DXTile[1, 1]; tiles[mipMapLevel][0, 0] = new DXTile(this); tiles[mipMapLevel][0, 0].Initialize( image.BitmapData.Scan0, image.BitmapData.Stride, image.BitmapData.PixelFormat, new Point(0 * 254 - 1, 0 * 254 - 1), new Point(Math.Min(0 * 254 + 255, image.BitmapData.Width), Math.Min(0 * 254 + 255, image.BitmapData.Height)), true); } }
private IEnumerable <float> createMipMappedTilesIncrements(BitmapResource image) { int width = image.BitmapData.Width; int height = image.BitmapData.Height; int stride = image.BitmapData.Stride; PixelFormat pixelFormat = image.BitmapData.PixelFormat; int mipMapLevelCount = Math.Max( 3, // at least 3 mip-maps Math.Max( (int)Math.Ceiling(Math.Log(width / 254, 2) + 1), (int)Math.Ceiling(Math.Log(height / 254, 2) + 1))); tiles = new DXTile[mipMapLevelCount + (int)detailLevel][, ]; IntPtr currentMipMapBitmap = image.BitmapData.Scan0; float totalProgress = 0.0f; // between 0 and 1 float nextProgressIncrement = 3.0f / 4.0f; for (int mipMapLevel = (int)detailLevel; mipMapLevel < mipMapLevelCount + (int)detailLevel; ++mipMapLevel) { if (mipMapLevel > (int)detailLevel) { createNextLowerMipMap(currentMipMapBitmap, width, height, stride, pixelFormat); width = (width + 1) / 2; height = (height + 1) / 2; stride = width * (pixelFormat == PixelFormat.Format24bppRgb ? 3 : 4); totalProgress += nextProgressIncrement; nextProgressIncrement *= 0.25f; } if (mipMapLevel >= (int)graphics.Properties.MapsAndCountersDetailLevel) { int columnCount = (width + 253) / 254; int rowCount = (height + 253) / 254; tiles[mipMapLevel] = new DXTile[columnCount, rowCount]; foreach (float progress in createSingleMipMapTilesIncrements(tiles[mipMapLevel], currentMipMapBitmap, width, height, stride, pixelFormat)) { yield return(totalProgress + progress * nextProgressIncrement); } } } }
private IEnumerable <float> createSingleMipMapTilesIncrements(DXTile[,] tiles, IntPtr bitmapBits, int width, int height, int stride, PixelFormat pixelFormat) { int columnCount = tiles.GetLength(0); int rowCount = tiles.GetLength(1); float progress = 0.0f; float progressIncrement = 1.0f / (rowCount * columnCount); for (int r = 0; r < rowCount; ++r) { for (int c = 0; c < columnCount; ++c) { tiles[c, r] = new DXTile(this); tiles[c, r].Initialize( bitmapBits, stride, pixelFormat, new Point(c * 254 - 1, r * 254 - 1), new Point(Math.Min(c * 254 + 255, width), Math.Min(r * 254 + 255, height)), false); progress += progressIncrement; yield return(progress); } } }
/// <summary>Must be called in a loop for the tile set to be fully loaded.</summary> /// <returns>Progress between 0 and 1.</returns> public IEnumerable <float> LoadIncrementally() { if (imageFile.Archive == null || (!imageFile.FileName.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) && !imageFile.FileName.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) || (maskFile != null && !maskFile.FileName.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) && !maskFile.FileName.EndsWith(".png", StringComparison.OrdinalIgnoreCase))) { goto fallBack; } // optimized native code simd-ed multithreaded pipeline { int error; uint skippedMipMapLevels = (uint)Math.Max(0, (int)graphics.Properties.MapsAndCountersDetailLevel - (int)detailLevel); IntPtr imageLoader = ZunTzuLib.CreateImageLoader(imageFile.Archive.FileName, imageFile.FileName, (maskFile != null ? maskFile.FileName : ""), skippedMipMapLevels, 1); try { uint width; uint height; if (0 != (error = ZunTzuLib.GetImageDimensions(imageLoader, out width, out height))) { //throw new ApplicationException(string.Format("Error while loading image: code {0}", error)); goto fallBack; } size = new SizeF((float)width, (float)height); for (int i = (int)detailLevel; i > 0; --i) { size = new SizeF(size.Width * 2, size.Height * 2); } int mipMapLevelCount = Math.Max( 3, // at least 3 mip-maps Math.Max( (int)Math.Ceiling(Math.Log(width / 254, 2) + 1), (int)Math.Ceiling(Math.Log(height / 254, 2) + 1))); tiles = new DXTile[mipMapLevelCount + (int)detailLevel][, ]; uint tileCount = 0; for (int mipMapLevel = (int)detailLevel; mipMapLevel < mipMapLevelCount + (int)detailLevel; ++mipMapLevel) { if (mipMapLevel >= (int)graphics.Properties.MapsAndCountersDetailLevel) { uint columnCount = (width + 253) / 254; uint rowCount = (height + 253) / 254; tiles[mipMapLevel] = new DXTile[columnCount, rowCount]; tileCount += columnCount * rowCount; } width = (width + 1) / 2; height = (height + 1) / 2; } uint mipmapLevel; // regardless of detailLevel (i.e. first mipmap is always zero) uint x; uint y; for (uint i = 0; i < tileCount; ++i) { Texture texture = new Texture(graphics.Device, 256, 256, 1, 0, (maskFile == null ? Format.Dxt1 : Format.Dxt5), Pool.Managed); if (0 != (error = loadNextTexture(imageLoader, texture, out mipmapLevel, out x, out y))) { texture.UnlockRectangle(0); //throw new ApplicationException(string.Format("Error while loading image: code {0}", error)); goto fallBack; } texture.UnlockRectangle(0); DXTile tile = new DXTile(this); tiles[mipmapLevel + (int)detailLevel][x, y] = tile; tile.Initialize(maskFile == null ? Format.Dxt1 : Format.Dxt5, texture); yield return((float)(i + 1) / (float)tileCount); } } finally { ZunTzuLib.FreeImageLoader(imageLoader); } yield break; } fallBack: { BitmapResource image = null; try { if (maskFile != null) { image = new BitmapResource(imageFile, PixelFormat.Format32bppArgb); BitmapResource mask = null; try { mask = new BitmapResource(maskFile, PixelFormat.Format24bppRgb); applyMask(image, mask); } finally { if (mask != null) { mask.Dispose(); } } } else { image = new BitmapResource(imageFile, PixelFormat.Format24bppRgb); } // TODO: find the correct progress for loading the bitmaps yield return(0.0f); size = new SizeF((float)image.BitmapData.Width, (float)image.BitmapData.Height); for (int i = (int)detailLevel; i > 0; --i) { size = new SizeF(size.Width * 2, size.Height * 2); } foreach (float progress in createMipMappedTilesIncrements(image)) { yield return(progress); } } finally { if (image != null) { image.Dispose(); } } } }
/// <summary>This is to get rid of the annoying warning "is never assigned to, and will always have its default value"</summary> private Quad(RectangleF dummy) { Tile = null; Coordinates = TextureCoordinates = dummy; }