BitmapSource GetWPFBitmap(MipMap mip, int maxDimension, bool ShowAlpha) { BitmapSource bmp = null; if (maxDimension != 0) { // Choose a mip of the correct size, if available. var sizedMip = MipMaps.Where(m => (m.Height <= maxDimension && m.Width <= maxDimension) || (m.Width <= maxDimension && m.Height <= maxDimension)); if (sizedMip.Any()) { var mip1 = sizedMip.First(); bmp = mip1.ToImage(); } else { double scale = (double)maxDimension / (Height > Width ? Height : Width); mip = ImageEngine.Resize(mip, scale); bmp = mip.ToImage(); } } else { bmp = mip.ToImage(); } if (!ShowAlpha) { bmp = new FormatConvertedBitmap(bmp, System.Windows.Media.PixelFormats.Bgr32, null, 0); } bmp.Freeze(); return(bmp); }
/// <summary> /// Loads useful information from image stream using Windows 8.1+ codecs. /// </summary> /// <param name="stream">Stream containing entire file. NOT just pixels.</param> /// <param name="decodeWidth">Width to decode as. Aspect ratio unchanged if decodeHeight = 0.</param> /// <param name="decodeHeight">Height to decode as. Aspect ratio unchanged if decodeWidth = 0.</param> /// <param name="isDDS">True = image is a DDS.</param> /// <returns>BGRA Pixel Data as stream.</returns> internal static List <MipMap> LoadWithCodecs(Stream stream, int decodeWidth, int decodeHeight, bool isDDS) { if (!WindowsCodecsAvailable) { return(null); } List <MipMap> mipmaps = new List <MipMap>(); bool alternateDecodeDimensions = decodeWidth != 0 || decodeHeight != 0; if (isDDS) { // KFreon: Attempt to load any mipmaps stream.Seek(0, SeekOrigin.Begin); var decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.IgnoreColorProfile, BitmapCacheOption.OnDemand); foreach (var mipmap in decoder.Frames) { // KFreon: Skip mipmaps that are too big if asked to load a smaller image if (alternateDecodeDimensions) { if (mipmap.Width > decodeWidth || mipmap.Height > decodeHeight) { continue; } } mipmaps.Add(new MipMap(mipmap)); } if (mipmaps.Count == 0) { // KFreon: No mips, so resize largest var mip = new MipMap(decoder.Frames[0]); // KFreon: Keep aspect ratio. Take smallest scaling value. double hScale = decodeHeight != 0 ? decodeHeight * 1f / mip.Height : 1; double wScale = decodeWidth != 0 ? decodeWidth * 1f / mip.Width : 1; double scale = hScale < wScale ? hScale : wScale; mip = ImageEngine.Resize(mip, scale, false); mipmaps.Add(mip); } } else { // KFreon: No Mipmaps BitmapImage bmp = AttemptUsingWindowsCodecs(stream, decodeWidth, decodeHeight); if (bmp == null) { return(null); } mipmaps.Add(new MipMap(bmp)); } return(mipmaps); }
/// <summary> /// Creates a WPF Bitmap from largest mipmap. /// Does NOT require that image remains alive. /// </summary> /// <param name="mergeAlpha">Only valid if maxDimension set. True = flattens alpha, directly affecting RGB.</param> /// <param name="maxDimension">Resizes image or uses a mipmap if available.</param> /// <returns>WPF bitmap of largest mipmap.</returns> public BitmapSource GetWPFBitmap(int maxDimension = 0, bool mergeAlpha = false) { MipMap mip = MipMaps[0]; if (maxDimension != 0) { // Choose a mip of the correct size, if available. var sizedMip = MipMaps.Where(m => (m.Height == maxDimension && m.Width <= maxDimension) || (m.Width == maxDimension && m.Height <= maxDimension)); if (sizedMip.Any()) { mip = sizedMip.First(); } else { double scale = maxDimension * 1f / (Height > Width ? Height : Width); mip = ImageEngine.Resize(mip, scale, mergeAlpha); } } mip.BaseImage.Freeze(); return(mip.BaseImage); }
/// <summary> /// Creates a GDI+ bitmap from largest mipmap. /// Does NOT require that image remains alive. /// </summary> /// <param name="ignoreAlpha">True = Previews image without alpha channel.</param> /// <param name="maxDimension">Largest size to display.</param> /// <param name="mergeAlpha">ONLY valid when maxDimension is set. True = flattens alpha, directly affecting RGB.</param> /// <returns>GDI+ bitmap of largest mipmap.</returns> public System.Drawing.Bitmap GetGDIBitmap(bool ignoreAlpha, bool mergeAlpha, int maxDimension = 0) { MipMap mip = MipMaps[0]; if (maxDimension != 0) { // Choose a mip of the correct size, if available. var sizedMip = MipMaps.Where(m => (m.Height == maxDimension && m.Width <= maxDimension) || (m.Width == maxDimension && m.Height <= maxDimension)); if (sizedMip.Any()) { mip = sizedMip.First(); } else { double scale = maxDimension * 1f / (Height > Width ? Height : Width); mip = ImageEngine.Resize(mip, scale, mergeAlpha); } } mip.BaseImage.Freeze(); return(UsefulThings.WinForms.Imaging.CreateBitmap(mip.BaseImage, ignoreAlpha)); }
/// <summary> /// Scales top mipmap and DESTROYS ALL OTHERS. /// </summary> /// <param name="scale">Scaling factor. </param> public void Resize(double scale) { MipMap closestMip = null; double newScale = 0; double desiredSize = MipMaps[0].Width * scale; double min = double.MaxValue; foreach (var mip in MipMaps) { double temp = Math.Abs(mip.Width - desiredSize); if (temp < min) { closestMip = mip; min = temp; } } newScale = desiredSize / closestMip.Width; MipMaps[0] = ImageEngine.Resize(closestMip, newScale); MipMaps.RemoveRange(1, NumMipMaps - 1); }
/// <summary> /// Scales top mipmap and DESTROYS ALL OTHERS. /// </summary> /// <param name="scale">Scaling factor. </param> /// <param name="mergeAlpha">True = flattens alpha, directly affecting RGB.</param> public void Resize(double scale, bool mergeAlpha) { MipMaps[0] = ImageEngine.Resize(MipMaps[0], scale, mergeAlpha); MipMaps.RemoveRange(1, NumMipMaps - 1); }
/// <summary> /// Loads useful information from image stream using Windows 8.1+ codecs. /// </summary> /// <param name="stream">Stream containing entire file. NOT just pixels.</param> /// <param name="decodeWidth">Width to decode as. Aspect ratio unchanged if decodeHeight = 0.</param> /// <param name="decodeHeight">Height to decode as. Aspect ratio unchanged if decodeWidth = 0.</param> /// <param name="isDDS">True = image is a DDS.</param> /// <param name="scale">DOMINANT. DecodeWidth and DecodeHeight ignored if this is > 0. Amount to scale by. Range 0-1.</param> /// <param name="formatDetails">Details about the format being loaded.</param> /// <returns>BGRA Pixel Data as stream.</returns> internal static List <MipMap> LoadWithCodecs(Stream stream, int decodeWidth, int decodeHeight, double scale, bool isDDS, ImageFormats.ImageEngineFormatDetails formatDetails) { if (isDDS && !ImageEngine.WindowsWICCodecsAvailable) { return(null); } bool alternateDecodeDimensions = decodeHeight != 0 || decodeWidth != 0 || scale != 0; int alternateWidth = decodeWidth; int alternateHeight = decodeHeight; List <MipMap> mipmaps = new List <MipMap>(); if (isDDS) { // KFreon: Attempt to load any mipmaps stream.Seek(0, SeekOrigin.Begin); var decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.IgnoreColorProfile, BitmapCacheOption.OnDemand); // Setup alternateDimensions if required if (scale != 0) { alternateHeight = (int)(decoder.Frames[0].Height * scale); alternateWidth = (int)(decoder.Frames[0].Width * scale); } foreach (var mipmap in decoder.Frames) { // KFreon: Skip mipmaps that are too big if asked to load a smaller image if (alternateDecodeDimensions) { if ((alternateWidth != 0 && mipmap.Width > alternateWidth) || (alternateHeight != 0 && mipmap.Height > alternateHeight)) { continue; } } mipmaps.Add(new MipMap(mipmap.GetPixelsAsBGRA32(), mipmap.PixelWidth, mipmap.PixelHeight, formatDetails)); } if (mipmaps.Count == 0) { // KFreon: Image has no mips, so resize largest var frame = decoder.Frames[0]; var mip = new MipMap(frame.GetPixelsAsBGRA32(), frame.PixelWidth, frame.PixelHeight, formatDetails); // Calculate scale if required if (scale == 0) { double xScale = alternateWidth * 1.0 / frame.PixelWidth; double yScale = alternateHeight * 1.0 / frame.PixelHeight; scale = xScale == 0 ? yScale : xScale; } mip = ImageEngine.Resize(mip, scale); mipmaps.Add(mip); } } else { // KFreon: No Mipmaps BitmapImage bmp = AttemptUsingWindowsCodecs(stream, alternateWidth, alternateHeight); if (bmp == null) { return(null); } bmp.Freeze(); mipmaps.Add(new MipMap(bmp.GetPixelsAsBGRA32(), bmp.PixelWidth, bmp.PixelHeight, formatDetails)); } return(mipmaps); }