/// <summary> /// Loads DDS that has no header - primarily for ME3Explorer. DDS data is standard, just without a header. /// ASSUMES VALID DDS DATA. Also, single mipmap only. /// </summary> /// <param name="rawDDSData">Standard DDS data but lacking header.</param> /// <param name="surfaceFormat">Surface format of DDS.</param> /// <param name="width">Width of image.</param> /// <param name="height">Height of image.</param> public ImageEngineImage(byte[] rawDDSData, ImageEngineFormat surfaceFormat, int width, int height) { Format = new Format(surfaceFormat); DDSGeneral.DDS_HEADER tempHeader = null; MipMaps = ImageEngine.LoadImage(rawDDSData, surfaceFormat, width, height, out tempHeader); header = tempHeader; }
private void LoadFromStream(Stream stream, string extension = null, int desiredMaxDimension = 0, bool enforceResize = true) { Format format = new Format(); // KFreon: Load image and save useful information including BGRA pixel data - may be processed from original into this form. DDSGeneral.DDS_HEADER tempheader = null; MipMaps = ImageEngine.LoadImage(stream, out format, extension, desiredMaxDimension, enforceResize, out tempheader, false); header = tempheader; Format = format; }
private void LoadFromFile(string imagePath, int desiredMaxDimension = 0, bool enforceResize = true) { Format format = new Format(); FilePath = imagePath; // KFreon: Load image and save useful information including BGRA pixel data - may be processed from original into this form. DDSGeneral.DDS_HEADER tempheader = null; MipMaps = ImageEngine.LoadImage(imagePath, out format, desiredMaxDimension, enforceResize, out tempheader, false); // KFreon: Can't pass properties as out :( header = tempheader; Format = format; }
/// <summary> /// Generates a thumbnail image as quickly and efficiently as possible. /// </summary> /// <param name="stream">Full image stream.</param> /// <param name="maxHeight">Max height to decode at. 0 means ignored, and aspect respected.</param> /// <param name="maxWidth">Max width to decode at. 0 means ignored, and aspect respected.</param> /// <param name="mergeAlpha">DXT1 only. True = Flatten alpha into RGB.</param> /// <param name="requireTransparency">True = uses PNG compression instead of JPG.</param> public static MemoryStream GenerateThumbnailToStream(Stream stream, int maxWidth, int maxHeight, bool mergeAlpha = false, bool requireTransparency = false) { Format format = new Format(); DDSGeneral.DDS_HEADER header = null; var mipmaps = LoadImage(stream, out format, null, maxWidth, maxHeight, true, out header, mergeAlpha); MemoryStream ms = new MemoryStream(); bool result = Save(mipmaps, requireTransparency ? ImageEngineFormat.PNG : ImageEngineFormat.JPG, ms, MipHandling.KeepTopOnly, mergeAlpha, maxHeight > maxWidth ? maxHeight : maxWidth); if (!result) { ms = null; } return(ms); }
private MemoryStream buildDdsImage(int mipMapIndex, out ImageEngineFormat imageFormat) { DomainPropertyByteValue formatProp = PropertyHeader.GetProperty("Format").FirstOrDefault()?.Value as DomainPropertyByteValue; imageFormat = ImageEngineFormat.Unknown; if (formatProp == null) { return(null); } string format = formatProp.PropertyString.Replace("PF_", null); switch (format) { case "DXT1": { imageFormat = ImageEngineFormat.DDS_DXT1; break; } case "DXT5": { imageFormat = ImageEngineFormat.DDS_DXT5; break; } case "G8": { imageFormat = ImageEngineFormat.DDS_G8_L8; break; } case "A8R8G8B8": { imageFormat = ImageEngineFormat.DDS_ARGB; break; } default: { return(null); } } DomainMipMap mipMap = MipMaps[mipMapIndex]; DDSGeneral.DDS_HEADER header = DDSGeneral.Build_DDS_Header(0, mipMap.Height, mipMap.Width, imageFormat); MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); DDSGeneral.Write_DDS_Header(header, writer); stream.Write(mipMap.ImageData, 0, mipMap.ImageData.Length); stream.Flush(); stream.Position = 0; return(stream); }
/// <summary> /// Loads image from file. /// </summary> /// <param name="imagePath">Path to image file.</param> /// <param name="Format">Detected format.</param> /// <param name="enforceResize">True = image resized to desiredMaxDimension if no suitable mipmap.</param> /// <param name="header">DDS header of image.</param> /// <param name="desiredMaxDimension">Largest dimension to load as.</param> /// <param name="mergeAlpha">True = Flattens alpha down, directly affecting RGB.</param> /// <returns>List of Mipmaps.</returns> internal static List <MipMap> LoadImage(string imagePath, out Format Format, int desiredMaxDimension, bool enforceResize, out DDSGeneral.DDS_HEADER header, bool mergeAlpha) { using (FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read, FileShare.Read)) return(LoadImage(fs, out Format, Path.GetExtension(imagePath), desiredMaxDimension, enforceResize, out header, mergeAlpha)); }
internal static List <MipMap> LoadImage(byte[] rawDDSData, ImageEngineFormat surfaceFormat, int width, int height, out DDSGeneral.DDS_HEADER header) { header = DDSGeneral.Build_DDS_Header(1, height, width, surfaceFormat); List <MipMap> MipMaps = null; // Create new fully formatted DDS i.e. one with a header. MemoryStream stream = new MemoryStream(); BinaryWriter bw = new BinaryWriter(stream); DDSGeneral.Write_DDS_Header(header, bw); bw.Write(rawDDSData); switch (surfaceFormat) { case ImageEngineFormat.DDS_DXT1: case ImageEngineFormat.DDS_DXT2: case ImageEngineFormat.DDS_DXT3: case ImageEngineFormat.DDS_DXT4: case ImageEngineFormat.DDS_DXT5: if (WindowsWICCodecsAvailable) { MipMaps = WIC_Codecs.LoadWithCodecs(stream, 0, 0, true); } else { MipMaps = DDSGeneral.LoadDDS(stream, header, new Format(surfaceFormat), 0); } break; case ImageEngineFormat.DDS_ARGB: case ImageEngineFormat.DDS_A8L8: case ImageEngineFormat.DDS_RGB: case ImageEngineFormat.DDS_ATI1: case ImageEngineFormat.DDS_ATI2_3Dc: case ImageEngineFormat.DDS_G8_L8: case ImageEngineFormat.DDS_V8U8: MipMaps = DDSGeneral.LoadDDS(stream, header, new Format(surfaceFormat), 0); break; default: throw new InvalidDataException("Image format is unknown."); } bw.Dispose(); // Also disposes MemoryStream return(MipMaps); }
/// <summary> /// Loads image from stream. /// </summary> /// <param name="stream">Full image stream.</param> /// <param name="Format">Detected Format.</param> /// <param name="extension">File Extension. Used to determine format more easily.</param> /// <param name="maxWidth">Maximum width to allow when loading. Resized if enforceResize = true.</param> /// <param name="maxHeight">Maximum height to allow when loading. Resized if enforceResize = true.</param> /// <param name="enforceResize">True = Resizes image to match either maxWidth or maxHeight.</param> /// <param name="header">DDS header of image.</param> /// <param name="mergeAlpha">ONLY valid when enforceResize is true. True = Flattens alpha down, directly affecting RGB.</param> /// <returns>List of Mipmaps.</returns> internal static List <MipMap> LoadImage(Stream stream, out Format Format, string extension, int maxWidth, int maxHeight, bool enforceResize, out DDSGeneral.DDS_HEADER header, bool mergeAlpha) { // KFreon: See if image is built-in codec agnostic. header = null; Format = ImageFormats.ParseFormat(stream, extension, ref header); List <MipMap> MipMaps = null; switch (Format.SurfaceFormat) { case ImageEngineFormat.BMP: case ImageEngineFormat.JPG: case ImageEngineFormat.PNG: MipMaps = WIC_Codecs.LoadWithCodecs(stream, maxWidth, maxHeight, false); break; case ImageEngineFormat.DDS_DXT1: case ImageEngineFormat.DDS_DXT2: case ImageEngineFormat.DDS_DXT3: case ImageEngineFormat.DDS_DXT4: case ImageEngineFormat.DDS_DXT5: if (WindowsWICCodecsAvailable) { MipMaps = WIC_Codecs.LoadWithCodecs(stream, maxWidth, maxHeight, true); } else { MipMaps = DDSGeneral.LoadDDS(stream, header, Format, maxHeight > maxWidth ? maxHeight : maxWidth); } break; case ImageEngineFormat.DDS_ARGB: case ImageEngineFormat.DDS_A8L8: case ImageEngineFormat.DDS_RGB: case ImageEngineFormat.DDS_ATI1: case ImageEngineFormat.DDS_ATI2_3Dc: case ImageEngineFormat.DDS_G8_L8: case ImageEngineFormat.DDS_V8U8: MipMaps = DDSGeneral.LoadDDS(stream, header, Format, maxHeight > maxWidth ? maxHeight : maxWidth); break; case ImageEngineFormat.TGA: var img = new TargaImage(stream); byte[] pixels = UsefulThings.WinForms.Imaging.GetPixelDataFromBitmap(img.Image); WriteableBitmap wbmp = UsefulThings.WPF.Images.CreateWriteableBitmap(pixels, img.Image.Width, img.Image.Height); var mip1 = new MipMap(wbmp); MipMaps = new List <MipMap>() { mip1 }; img.Dispose(); break; default: throw new InvalidDataException("Image format is unknown."); } if (MipMaps == null || MipMaps.Count == 0) { throw new InvalidDataException("No mipmaps loaded."); } // KFreon: No resizing requested if (maxHeight == 0 && maxWidth == 0) { return(MipMaps); } // KFreon: Test if we need to resize var top = MipMaps.First(); if (top.Width == maxWidth || top.Height == maxHeight) { return(MipMaps); } int max = maxWidth > maxHeight ? maxWidth : maxHeight; // KFreon: Attempt to resize var sizedMips = MipMaps.Where(m => m.Width > m.Height ? m.Width <= max : m.Height <= max); if (sizedMips != null && sizedMips.Any()) // KFreon: If there's already a mip, return that. { MipMaps = sizedMips.ToList(); } else if (enforceResize) { // Get top mip and clear others. var mip = MipMaps[0]; MipMaps.Clear(); MipMap output = null; int divisor = mip.Width > mip.Height ? mip.Width / max : mip.Height / max; output = Resize(mip, 1f / divisor, mergeAlpha); MipMaps.Add(output); } return(MipMaps); }
/// <summary> /// Loads image from stream. /// </summary> /// <param name="stream">Full image stream.</param> /// <param name="Format">Detected format.</param> /// <param name="extension">File extension. Used to determine format more easily.</param> /// <param name="mergeAlpha">ONLY valid when enforceResize is true. True = Flattens alpha down, directly affecting RGB.</param> /// <param name="enforceResize">True = image resized to desiredMaxDimension if no suitable mipmap.</param> /// <param name="header">DDS header of image.</param> /// <param name="desiredMaxDimension">Largest dimension to load as. ASSUMES SQUARE.</param> /// <returns>List of Mipmaps.</returns> internal static List <MipMap> LoadImage(Stream stream, out Format Format, string extension, int desiredMaxDimension, bool enforceResize, out DDSGeneral.DDS_HEADER header, bool mergeAlpha) { return(LoadImage(stream, out Format, extension, desiredMaxDimension, desiredMaxDimension, enforceResize, out header, mergeAlpha)); }