【问题标题】:Using jpegtran, jpegoptim, or other jpeg optimization/compression in C#在 C# 中使用 jpegtran、jpegoptim 或其他 jpeg 优化/压缩
【发布时间】:2017-04-07 03:46:29
【问题描述】:

我有 100 件(也许是 1000 件)产品,每件产品都有 10 到 30 张图片,这些产品来自我整理的在线商店。我需要在不损失图像质量的情况下尽可能优化图像的文件大小。

我没有直接使用 jpegtran、jpegoptim 或任何其他 jpeg 优化器,但我注意到 punypng 在较大的 jpeg 图像上将文件大小缩小约 4-6%。

在上传期间(通过 jumpoader)已经从图像中删除了元数据,因此这不再是一个选项/问题。

有没有办法让其中一个 jpeg 优化器从 C# 代码运行?

注意:我正在使用带有 IIS7 和 .Net 3.5 的共享 Godaddy 主机

【问题讨论】:

    标签: c# optimization jpeg lossless-compression


    【解决方案1】:

    可能已经晚了 7 年,但我在尝试解决这个问题时遇到了这个问题。我最终设法做到了,这就是解决方案。 对于 PNG,您首先需要使用 NuGet 安装 nQuant。

    包括:

    using System.Web.Hosting;
    using System.IO;
    using System.Diagnostics;
    using nQuant;
    using System.Drawing;
    using System.Drawing.Imaging;
    

    方法:

        public void optimizeImages()
        {
            string folder = 
                Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"assets\temp");
            var files = Directory.EnumerateFiles(folder);
    
            foreach (var file in files)
            {
                switch (Path.GetExtension(file).ToLower())
                {
                    case ".jpg":
                    case ".jpeg":
                        optimizeJPEG(file);
                        break;
                    case ".png":
                        optimizePNG(file);
                        break;
                }
    
            }
    
        }
    
        private void optimizeJPEG(string file)
        {
            string pathToExe = HostingEnvironment.MapPath("~\\adminassets\\exe\\") + "jpegtran.exe";
    
            var proc = new Process
            {
                StartInfo =
                {
                    Arguments = "-optimize \"" + file + "\" \"" + file + "\"",
                    FileName = pathToExe,
                    UseShellExecute = false,
                    CreateNoWindow = false,
                    WindowStyle = ProcessWindowStyle.Hidden,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true
                }
            };
    
            Process jpegTranProcess = proc;
    
            jpegTranProcess.Start();
            jpegTranProcess.WaitForExit();
        }
    
        private void optimizePNG(string file)
        {
            string tempFile = Path.GetDirectoryName(file) + @"\temp-" + Path.GetFileName(file);
            int alphaTransparency = 10;
            int alphaFader = 70;
            var quantizer = new WuQuantizer();
            using (var bitmap = new Bitmap(file))
            {
                using (var quantized = quantizer.QuantizeImage(bitmap, alphaTransparency, alphaFader))
                {
                    quantized.Save(tempFile, ImageFormat.Png);
    
                }
    
            }
            System.IO.File.Delete(file);
            System.IO.File.Move(tempFile, file);
        }
    

    它将从 /assets/temp 文件夹中获取所有文件并优化 jpegs 和 PNG。 我关注 this question 的 png 部分。我从几个来源抓取的 jpeg 部分。包括PicJamImage Optimizer。我使用它的方式是将用户的所有文件上传到临时文件夹,运行此方法,将文件上传到 azure blob 存储,然后删除本地文件。我下载了 jpegtran here

    【讨论】:

      【解决方案2】:

      如果您不喜欢弄乱临时文件,我建议您使用 C++/CLI。

      在 Visual Studio 中创建一个 C++/CLI dll 项目。创建一个静态托管类,并在 C# 中定义您想要使用的函数:

      public ref class JpegTools
      {
      public:
           static array<byte>^ Optimize(array<byte>^ input)
      };
      

      您定义的这些函数可以直接从 C# 调用,并且您可以使用 C++ 提供的所有功能来实现它们。

      array^ 对应于 C# 字节数组。您需要使用 pin_ptr 将字节数组固定在内存中,这样您就可以将数据传递给您选择的非托管 Jpeg 辅助函数。 C++/CLI 充分支持将托管类型编组为本机类型。您还可以使用 gc_new 分配新数组,以返回 CLI 兼容类型。如果您必须在本练习中将字符串从 C# 编组到 C++,请使用 Mfc/Atl 的 CString 类型。

      您可以将所有 jpeg 代码静态链接到 dll 中。 C++ dll 可以混合纯本机代码和 C++/CLI 代码。在我们的 C++/CLI 项目中,通常只有接口源文件知道 CLI 类型,其余的都使用 C++ 类型。

      这样做需要一些额外的工作,但好处是您的代码是编译时类型检查的,并且所有与未管理代码和内存的处理都在 C++ 端处理。它实际上工作得很好,以至于我几乎直接使用 NUnit 使用 C++/CLI 对原生 C++ 代码进行单元测试。

      祝你好运!

      【讨论】:

      • 你失去了我。我什至无法弄清楚如何自己编译 jpegoptim 或 jpegtran。像这样的软件没有作为可下载的 dll 提供的原因是什么?
      • 可能是工具包试图独立于平台。 Dll 仅适用于 Windows。我同意拥有一个 dll 会很方便,但如果有一个,您可能不需要我们的帮助,对吧?如果您没有 C/C++ 经验,那么按照下面的建议从程序运行 .exe 可能更明智。
      • @user180326 你愿意提供一个代码示例吗?答案听起来很有趣,但如果没有代码,它对那些最能帮助的人——那些以前没有桥接 C# 和 C++ 的人——的指导性有限。
      【解决方案3】:

      我会在将图像上传到您的网络服务器之前对它们进行批处理,而不是在提供图像时尝试处理它们。这将减少网络服务器上的负载,让您可以使用任何您想要的匹配图像处理工具。

      【讨论】:

      • 每张图片我需要四种尺寸(拇指、小、中、大)。现在我只需要上传一张图片,所有四种尺寸都是由服务器为我创建的。手动批量处理图像然后上传将不起作用(呃,这将是太多的工作)。我需要一个服务器端解决方案。感谢您的意见。
      • 或者是做图像处理然后上传它们的工具。无论如何,处理应该在上传时完成,而不是在提供图像时。
      • 这是一个网络应用程序;所有工作都需要在上传后完成。处理是目前并将在上传时完成。我只提供静态图像文件...不需要服务器处理。 :o)
      【解决方案4】:

      我确定我回答这个问题已经很晚了,但最近我遇到了无损 jpeg 优化问题,还没有找到任何合适的 jpegtran 实用程序的 C# 实现。因此,我决定自己实现基于修改后 jpegtran 的 C 包装器的无损 jpeg 大小减小例程,您可以找到 here。它来了,使用纯 .Net LibJpeg.NET 的类似实现比 C 包装的解决方案慢得多,所以,我没有将它包含在 repo 中。 wrapper的使用很简单,

      if (JpegTools.Transform(jpeg, out byte[] optimized, copy: false, optimize: true))
      {
        //do smth useful 
      }
      else
      {
        //report on error or use original jpeg
      }
      

      希望有人会觉得它有用。

      【讨论】:

        【解决方案5】:

        为什么不用Process.Start() 打电话给punypng.com?你的 .net 代码没有理由不能运行外部程序,只要处理是在上传时完成的(而不是在提供图像时)

        例如

        • 上传到“上传”文件夹,
        • 有一个 Windows 服务来监视“上传”文件夹中的新文件
        • 当您获得一个新文件时,启动 punypng.com 对其进行处理并将输出放入正确的图像文件夹中。

        【讨论】:

        • punypng.com 是一个网站,可让您上传图像(jpeg、gif、动画 gif 和 png[8,24, & 32])以进行分析,然后进行压缩/优化。然后它会返回文件大小较小的图像的下载链接。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-10-12
        • 2016-11-20
        • 1970-01-01
        • 1970-01-01
        • 2011-03-26
        • 1970-01-01
        • 2016-06-30
        相关资源
        最近更新 更多