图像上传/设置DPI但确保文件大小<= 200k

时间:2011-12-13 18:45:56

标签: c# image image-processing image-uploading

我有一个表单(使用MVC2),它有一个图像上传脚本,但存储在服务器上的最终图像的规则非常严格。我可以强制文件到我想要的尺寸,但它总是超过所需的文件大小...所以我可以允许一个低于200k的图像,但是一旦我的代码处理完毕,它会稍微大一点。

这些是我必须遵守的规则:

  • 照片应该是彩色的
  • 允许的图像类型 照片是.JPG或.GIF
  • 图像的最大尺寸为200kb
  • 徽章上的照片尺寸为274像素 (宽)x 354像素(高)@ 200dpi(每英寸像素深度)

这就是我目前的情况:

[HttpPost]
public ActionResult ImageUpload(HttpPostedFileBase fileBase)
{
    ImageService imageService = new ImageService();

    if (fileBase != null  && fileBase.ContentLength > 0 && fileBase.ContentLength < 204800 && fileBase.ContentType.Contains("image/"))
    {
            string profileUploadPath = "~/Resources/images";

            Path.GetExtension(fileBase.ContentType);
            var newGuid = Guid.NewGuid();
            var extension = Path.GetExtension(fileBase.FileName);

            if (extension.ToLower() != ".jpg" && extension.ToLower() != ".gif") // only allow these types
            {
                return View("WrongFileType", extension);
            }

            EncoderParameters encodingParameters = new EncoderParameters(1);
            encodingParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 70L); // Set the JPG Quality percentage

            ImageCodecInfo jpgEncoder = imageService.GetEncoderInfo("image/jpeg");
            var uploadedimage = Image.FromStream(fileBase.InputStream, true, true);

            Bitmap originalImage = new Bitmap(uploadedimage);
            Bitmap newImage = new Bitmap(originalImage, 274, 354);

            Graphics g = Graphics.FromImage(newImage);
            g.InterpolationMode = InterpolationMode.HighQualityBilinear;
            g.DrawImage(originalImage, 0, 0, newImage.Width, newImage.Height);

            var streamLarge = new MemoryStream();
            newImage.Save(streamLarge, jpgEncoder, encodingParameters);

            var fileExtension = Path.GetExtension(extension);
            var ImageName = newGuid + fileExtension;

            newImage.Save(Server.MapPath(profileUploadPath) + ImageName);
            //newImage.WriteAllBytes(Server.MapPath(profileUploadPath) + ImageName, streamLarge.ToArray());

            originalImage.Dispose();
            newImage.Dispose();
            streamLarge.Dispose();

            return View("Success");
        }
    return View("InvalidImage");
}

添加: 图像将在卡上打印,因此DPI非常重要。但我意识到200k对于打印图像来说不是很多..这些都不是我的商业规则!因为它代表了这个代码上传了大约200k的图像,最终耗资238k(ish)

3 个答案:

答案 0 :(得分:3)

提前计算jpeg的大小非常困难。话虽如此,你不需要压缩它。

让我们看看一些指标:

  

274 * 354 = 96996像素。如果你有每像素8位和3种颜色   通道(即24位颜色)然后你有:

     

274 * 354 * 8 * 3 = 2,327,904位= 290988字节= 284.17 kb。

     

200 / 284.17~0.70。

您只需将其缩小至原始尺寸的70%。

可悲的是,在这一点上,我们达到了我在这个领域的知识极限!但我认为,即使以最高质量的设置保存,通过保存为jpeg,它仍将处于正确的尺寸范围内。

我猜测将质量设置为70,看看会发生什么。

编辑:DPI设置

显然,您只需要更改EXIF数据。请参阅此答案:https://stackoverflow.com/a/4427411/234415

答案 1 :(得分:2)

您应该尝试JPEG质量设置。您当前将其设置为90,80可能就足够了,并且会生成较小的文件。

答案 2 :(得分:1)

我发现代码存在一些问题:

  • 您正在使用GetThumbnailImage创建缩略图,但这不适用于此类较大的缩略图。它最高可达120x120像素。如果图像具有嵌入式缩略图,则将使用该缩略图而不是缩小整个图像,因此您将缩小较小的图像,但存在明显的质量问题。
  • 您正在将缩略图保存到内存流中,然后将其丢弃。
  • 您正在将缩略图保存到文件而不指定编码器,这意味着它将保存为低压缩JPEG图像或PNG图像,这就是您获得更大文件大小的原因。
  • 您永远不会处置uploadedImage对象。

注意:在网络上显示图像时,分辨率(PPI / DPI)无关。