对于我当前的WPF应用程序,我必须缩小一些System.Drawing.Image
(我从PNG文件加载的对象(其中一些具有透明背景)。我尝试了多种方法来调整图像大小他们之后的图像效果很好。但不幸的是,它们都使图像失去透明度。
我的最后一次尝试是使用ImageResizer一个外部库来完成工作,因为我希望它能轻松处理这个问题,但我仍然有同样的问题:原始图像以透明背景显示;显示的已调整大小的图像以黑色背景显示。
这是我使用ImageResizer库的代码:
ImageResizer.Instructions inst = new ImageResizer.Instructions("width=" + newWidth.ToString() + ";height=" + newHeight.ToString() + ";format=png;mode=max");
ImageResizer.ImageJob job = new ImageResizer.ImageJob(originalImage, typeof(System.Drawing.Bitmap), inst);
job.Build();
return job.Result as System.Drawing.Image;
这是我的另外两种方法,它们基本上也提供了相同的结果(图像已调整大小:尚未保留透明度:Nope):
return originalImage.GetThumbnailImage(newWidth, newHeight, null, IntPtr.Zero); // Transparency gets lost
return new System.Drawing.Bitmap(originalImage, new System.Drawing.Size(newWidth, newHeight)); // Transparency gets lost
有关我必须做什么的任何想法,以便在调整大小时保持透明度?
此致
拉尔夫
答案 0 :(得分:2)
ImageResizer 始终保留透明度。
您在图像的编码(或显示)过程中失去透明度,在之后发生您已从ImageResizer手中夺走控制权。传入输出路径或输出流,而不是传入typeof(System.Drawing.Bitmap)
。
var i = new Instructions(){ Width = newWidth,Height = newHeight, OutputFormat= OutputFormat.Png, Mode= FitMode.Max};
new ImageJob(originalImage, "output.png", i).Build();
如果从中获取原始位图,ImageResizer无法控制图像的编码方式。
您没有具体说明您如何使用结果,这非常重要。如果您没有将它们写入磁盘或流,而是显示它们,那么您将在错误的位置查找问题。将结果合成到显示表面上的代码很可能无法将图像视为32位图像,而是忽略了alpha通道。
答案 1 :(得分:1)
即使你正在使用WPF,你也在使用System.Drawing.Image
个对象,所以你可以这样做:
public static Bitmap ResizeImage(Image imgToResize, int newHeight)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercentH = ((float)newHeight / (float)sourceHeight);
int destWidth = Math.Max((int)Math.Round(sourceWidth * nPercentH), 1); // Just in case;
int destHeight = newHeight;
Bitmap b = new Bitmap(destWidth, destHeight);
using (Graphics g = Graphics.FromImage((Image)b))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
}
return b;
}
之后,请务必使用PNG编码器保存:
public static System.Drawing.Imaging.ImageCodecInfo GetEncoder(System.Drawing.Imaging.ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
然后
codec = GetEncoder(ImageFormat.Png);
newBitmap.Save(newFile, codec, null);
(注意我使用的是标准的.Net类库而不是第三方库;希望没问题。)
<强>更新强>
顺便说一下,既然你在WPF工作,为什么不使用WPF的image manipulation?
public static class BitmapHelper
{
public static void SaveToPng(this BitmapSource bitmap, string fileName)
{
var encoder = new PngBitmapEncoder();
SaveUsingEncoder(bitmap, fileName, encoder);
}
public static void SaveUsingEncoder(this BitmapSource bitmap, string fileName, BitmapEncoder encoder)
{
BitmapFrame frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
using (var stream = File.Create(fileName))
{
encoder.Save(stream);
}
}
public static void ImageLoadResizeAndSave(string inFile, string outFile, int newPixelHeight)
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(inFile);
image.EndInit();
var newImage = BitmapHelper.ResizeImageToHeight(image, newPixelHeight);
BitmapHelper.SaveToPng(newImage, outFile);
}
/// <summary>
/// Resize the image to have the selected height, keeping the width proportionate.
/// </summary>
/// <param name="imgToResize"></param>
/// <param name="newHeight"></param>
/// <returns></returns>
public static BitmapSource ResizeImageToHeight(BitmapSource imgToResize, int newPixelHeight)
{
double sourceWidth = imgToResize.PixelWidth;
double sourceHeight = imgToResize.PixelHeight;
var nPercentH = ((double)newPixelHeight / sourceHeight);
double destWidth = Math.Max((int)Math.Round(sourceWidth * nPercentH), 1); // Just in case;
double destHeight = newPixelHeight;
var bitmap = new TransformedBitmap(imgToResize, new ScaleTransform(destWidth / imgToResize.PixelWidth, destHeight / imgToResize.PixelHeight));
return bitmap;
}
}
也许您正在丢失将旧格式的图像转换为WPF格式的透明度?