Using jpegtran, jpegoptim, or other jpeg optimization/compression in C#

左心房为你撑大大i 提交于 2019-12-12 08:14:13

问题


I've got 100's (maybe 1000's) of products with 10-30 images of each product coming to an online store I've put together. I need to optimize the images' file sizes as much as possible without loosing image quality.

I haven't used jpegtran, jpegoptim, or any other jpeg optimizer directly but I have noticed that punypng shrinks file sizes down about 4-6% on the larger jpeg images LOSSLESSLY.

Meta data is already stripped from the images during upload (via jumpoader) so that is not an option/problem anymore.

Is there any way to get one of the jpeg optimizers to run from C# code?

Note: I'm using shared Godaddy hosting with IIS7 and .Net 3.5


回答1:


It might be 7 years too late, but I came across this question while trying to solve this problem. I eventually managed to do it and this is the solution. For PNG you first need to install nQuant using NuGet.

include:

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

Methods:

    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);
    }

It will take all files from /assets/temp folder and optimize jpegs and PNG. I followed this question for the png part. The jpeg part I scraped from several sources. Including PicJam and Image Optimizer. The way I use it is by uploading all files from the user to the temp folder, running this method, uploading the files to azure blob storage, and deleting the local files. I downloaded jpegtran here.




回答2:


If you don't like to mess with temporary files, I'd advise to use C++/CLI.

Create a C++/CLI dll project in visual studio. Create one static managed class, and define the functions as you want to use them from C#:

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

These functions you define can be directly called from C#, and you can implement them with all that C++ offers.

array^ corresponds to a C# byte array. You'll need to use pin_ptr<> to pin the byte array in memory, so you can pass on the data to the unmanaged Jpeg helper function of your choice. C++/CLI has ample support for marshalling managed types to native types. You can also allocate new array with gc_new, to return CLI compatible types. If you have to marshall strings from C# to C++ as part of this excercise, use Mfc/Atl's CString type.

You can statically link all the jpeg code into the dll. A C++ dll can be mixed pure native and C++/CLI code. In our C++/CLI projects, typically only the interface source files know about CLI types, all the rest work with with C++ types.

There's some overhead work to get going this way, but the upside is that your code is compile-time typechecked, and all the dealings with unmanged code and memory are dealt with on the C++ side. It actually works so well that I used C++/CLI to unit test native C++ code almost directly with NUnit.

Good luck!




回答3:


I would batch process the images before uploading them to your web server, rather then try to process them while serving them. This will lead to less load on the web server and let you use any match image processing tools you wish.




回答4:


I'm sure that I'm totally late to answer this question, but recently I have faced on lossless jpeg optimization problem and haven't found any suitable C# implementation of jpegtran utility. So, I have decided to implement by myself routines for lossless jpeg size reducing based on C wrapper of modified jpegtran, which you can find here. It comes, that similar realization with use of pure .Net LibJpeg.NET is far more slower than C wrapped solution, so, I haven't included it to the repo. Using of wrapper is quite simple,

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

Hope, someone will find it useful.




回答5:


Why not call punypng.com with Process.Start()? There is no reason why you .net code can't run external programs, provided the processing is done at the time of uploading (rather then when serving the images)

E.g.

  • upload into a "upload" folder,
  • have a windows services that watches for new files in the “upload” folder
  • when you get a new file, start punypng.com to process it and put the output into the correct image folder.


来源:https://stackoverflow.com/questions/1493532/using-jpegtran-jpegoptim-or-other-jpeg-optimization-compression-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!