在C#中使用jpegtran,jpegoptim或其他jpeg优化/压缩

时间:2009-09-29 16:09:20

标签: c# optimization jpeg lossless-compression

我有100个(可能是1000个)的产品,每个产品的10到30个图像来到我放在一起的在线商店。我需要尽可能地优化图像的文件大小而不会降低图像质量。

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

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

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

注意:我正在使用IIS7和.Net 3.5的共享Godaddy托管

5 个答案:

答案 0 :(得分: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。 我跟着this question了解了png部分。我从几个来源抓取了jpeg部分。包括PicJamImage Optimizer。我使用它的方法是将所有文件从用户上传到临时文件夹,运行此方法,将文件上传到azure blob存储,以及删除本地文件。我下载了jpegtran here

答案 1 :(得分: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&lt;&gt;将字节数组固定在内存中,这样就可以将数据传递给您选择的非托管Jpeg帮助函数。 C ++ / CLI充分支持将托管类型编组为本机类型。您还可以使用gc_new分配新阵列,以返回CLI兼容类型。如果您必须将C#中的字符串作为此练习的一部分进行编组,请使用Mfc / Atl的CString类型。

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

有一些开销工作​​可以通过这种方式实现,但好处是你的代码是编译时的类型检查,并且在C ++方面处理所有与无人编码和内存的处理。它实际上工作得很好,我使用C ++ / CLI几乎直接使用NUnit对本机C ++代码进行单元测试。

祝你好运!

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:-1)

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

E.g。

  • 上传到“上传”文件夹,
  • 有一个Windows服务,可以在“上传”文件夹中查看新文件
  • 当你收到一个新文件时,启动punypng.com来处理它并将输出放到正确的图像文件夹中。