【问题标题】:Image upload without loss of quality图片上传不损失质量
【发布时间】:2011-12-31 14:19:50
【问题描述】:

我在网站上有一个用户图库,访问者可以上传一些图片。上传图像后,应将其大小调整为一些预定义的预设。此外,原始图像也应保存。对于pngbmp 图像格式,一切正常。但是如果我上传gif格式或者jpeg以一种颜色为主,上传的原图好像被压缩了。

例如:

原文:

已上传:

我在谷歌彻底搜索并找到了一些如何正确上传图片的示例。 最后我写了下一个方法:

void UploadImagePreset(Image image, ImageFormat imgFormat, string imgPath)
{
    using (var uploadStream = imageUploader.CreateUploadStream(imagePath))
    {
        var newWidth = image.Width;
        var newHeight = image.Height;
        using (var outBitmap = new Bitmap(newWidth, newHeight))
        {
            using (var outGraph = Graphics.FromImage(outBitmap))
            {
                outGraph.CompositingQuality = CompositingQuality.HighQuality;
                outGraph.SmoothingMode = SmoothingMode.HighQuality;
                outGraph.PixelOffsetMode = PixelOffsetMode.HighQuality;
                outGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;

                var imageRect = new Rectangle(0, 0, newWidth, newHeight);
                outGraph.DrawImage(image, imageRect);

                outBitmap.Save(uploadStream, imgFormat);
            }
        }
    }
}

但这并没有帮助。上传的图像与上述相同。 我已经尝试像这样指定结果图像的质量:

var encoderParameters = new EncoderParameters();
var encoderParameter = new EncoderParameter(Encoder.Quality, 100);
encoderParameters.Param[0] = encoderParameter;
var encoder = ImageCodecInfo.GetImageEncoders()
    .Where(e => e.FormatID == imgFormat.Guid)
    .FirstOrDefault();
outBitmap.Save(uploadStream, encoder, encoderParameters);

它也不起作用。另外当我上传jpeg图片时出现异常。

有什么方法可以在不压缩或调整大小的情况下上传图片?我花了几个小时试图解决这个问题并坚持下去。

【问题讨论】:

  • 不清楚 - 上传是做什么的?如果它只是来自没有额外客户端代码的浏览器,您应该得到客户端上的确切文件 - 此时您的问题与上传(或 ASP.NET)无关,并且只是与调整大小有关。
  • 我使用 FileUpload 控件没有任何额外的客户端代码
  • 对,所以首先验证一下,如果您保存上传的文件 - 根本不处理它 - 您最终会得到完全相同的文件。当您向自己证明了这一点时,您可以将上传部分排除在外。将问题缩小到尽可能小的范围。

标签: c# asp.net .net image-processing


【解决方案1】:

您正在通过Image 类传递上传的图像 - 这是一个 图像,基于传入的流。

然后使用一些默认参数保存,这将不再反映原始图像。

您应该简单地将传入的流直接保存到磁盘 - 这将产生原始图像的精确副本。

像这样(.NET 4.0):

using (var uploadStream = imageUploader.CreateUploadStream(imagePath))
{
   using(var fileStream = new FileStream(imgPath, FileMode.Create))
   {
       uploadStream.CopyTo(fileStream);
   }
}

或(.NET 4.0 之前):

using (var uploadStream = imageUploader.CreateUploadStream(imagePath))
{
    using(var fileStream = new FileStream(imgPath, FileMode.Create))
    {
        byte[] buffer = new byte[32768];
        int read;
        while ((read = uploadStream.Read(buffer, 0, buffer.Length)) > 0)
        {
            fileStream.Write(buffer, 0, read);
        }
    }
}

改编自this answer

【讨论】:

  • 我使用 .Net 3.5。 Stream 类在这个版本的框架中没有 CopyTo 方法。
  • @IgorBlinnikov - 另一种选择:stackoverflow.com/questions/230128/…
  • 谢谢你,奥德。你的回答很有帮助。问题是我首先从 Stream 创建了 Image 对象,然后保存了 Stream。即使我保存原始 Stream,但不保存 Image 对象,使用 Stream 对象操作也会给结果图像添加噪点。上传后(在创建 Image 对象之前)直接将 Stream 保存到文件解决了我的问题。
  • 我有一个 HttpFileCollection (files[0]) 我正在尝试上传(框架 4.0),但我不明白如何实现第一个 使用 using (var uploadStream = imageUploader.CreateUploadStream(imagePath)) 并且您使用的是 imagePath 然后 imgPath 它们不一样?
  • @Oded 我刚刚发布了一个question 关于我的问题,如果你能看一下那将是惊人的!
【解决方案2】:

我建议使用图像编解码器(您的第二个示例)进行无损图像压缩。

我建议您对代码稍作修改:

Bitmap bm = (Bitmap)Image.FromFile(filePath); 
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); 
ImageCodecInfo codecInfo = null; 
foreach (ImageCodecInfo codec in codecs)
{ 
    if (codec.MimeType == "image/jpeg") 
        codecInfo = codec; 
}
EncoderParameters ep = new EncoderParameters(); 
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100); 
bm.Save("C:\\quality" + x.ToString() + ".jpg", codecInfo, ep);

希望这会有所帮助。

【讨论】:

  • 我必须按原样上传图片。我无法将格式更改为 jpeg。如果用户上传了 *.png 图像,它应该被保存为 png。
猜你喜欢
  • 1970-01-01
  • 2015-09-02
  • 1970-01-01
  • 2012-10-08
  • 2014-03-22
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
相关资源
最近更新 更多