我有100个(可能是1000个)的产品,每个产品的10到30个图像来到我放在一起的在线商店。我需要尽可能地优化图像的文件大小而不会降低图像质量。
我没有直接使用过jpegtran,jpegoptim或任何其他jpeg优化器,但我注意到punypng在较大的jpeg图像上的文件大小缩小了大约4-6%。
上传期间(通过跳转程序)已经从图像中删除了元数据,因此这不再是一个选项/问题。
有没有办法让其中一个jpeg优化器从C#代码运行?
注意:我正在使用IIS7和.Net 3.5的共享Godaddy托管
答案 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部分。包括PicJam和Image 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。