简体   繁体   中英

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

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

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 .

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!

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.

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.

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)

Eg

  • 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM