4

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

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

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

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

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

4

5 回答 5

3

可能为时已晚 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。我对 png 部分关注了这个问题。我从几个来源抓取的 jpeg 部分。包括PicJamImage Optimizer。我使用它的方式是将用户的所有文件上传到临时文件夹,运行此方法,将文件上传到 azure blob 存储,然后删除本地文件。我在这里下载了 jpegtran 。

于 2016-07-19T01:04:18.453 回答
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++ 代码进行单元测试。

祝你好运!

于 2009-10-12T18:35:26.000 回答
1

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

于 2009-10-12T11:33:50.610 回答
1

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

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

希望,有人会发现它有用。

于 2017-04-06T19:46:29.050 回答
-1

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

例如

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