High Quality Jpeg Compression with C#

High quality JPEG compression with c#

It looks like you're setting the quality to 100%. That means that there will be no compression.

If you change the compression level (80, 50, etc.) and you're unsatisifed with the quality, you may want to try a different image library. LEADTools has a good (non-free) engine.

UPDATE: As a commenter mentioned, 100% quality still does not mean lossless compression when using JPEG. Loading the image, doing something to it, and then saving it again will ultimately result in image degradation. If you need to alter and save an image without losing any of the data you need to use a lossless format such as TIFF, PNG or BMP. I'd go with compressed TIFF (since it's still lossless even though it's compressed) or PNG.

What quality level does Image.Save() use for jpeg files?

Using reflector, it turns out Image.Save() boils down to the GDI+ function GdipSaveImageToFile, with the encoderParams NULL. So I think the question is what the JPEG encoder does when it gets a null encoderParams. 75% has been suggested here, but I can't find any solid reference.

EDIT You could probably find out for yourself by running your program above for quality values of 1..100 and comparing them with the jpg saved with the default quality (using, say, fc.exe /B)

Does resizing jpeg images affect their compression?

When you call "bmpOut.Save" you have to pass in some EncoderParameters to tell the method what quality level you would like to save it with.

http://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoderparameters(VS.80).aspx

Quality of a saved JPG in C#

The following code example demonstrates how to create a EncoderParameter using the EncoderParameter constructor. To run this example, paste the code and call the VaryQualityLevel method.

This example requires an image file named TestPhoto.jpg located at c:.

private void VaryQualityLevel()
{
// Get a bitmap.
Bitmap bmp1 = new Bitmap(@"c:\TestPhoto.jpg");
ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

// Create an Encoder object based on the GUID
// for the Quality parameter category.
System.Drawing.Imaging.Encoder myEncoder =
System.Drawing.Imaging.Encoder.Quality;

// Create an EncoderParameters object.
// An EncoderParameters object has an array of EncoderParameter
// objects. In this case, there is only one
// EncoderParameter object in the array.
EncoderParameters myEncoderParameters = new EncoderParameters(1);

EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder,
50L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(@"c:\TestPhotoQualityFifty.jpg", jgpEncoder,
myEncoderParameters);

myEncoderParameter = new EncoderParameter(myEncoder, 100L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(@"c:\TestPhotoQualityHundred.jpg", jgpEncoder,
myEncoderParameters);

// Save the bitmap as a JPG file with zero quality level compression.
myEncoderParameter = new EncoderParameter(myEncoder, 0L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(@"c:\TestPhotoQualityZero.jpg", jgpEncoder,
myEncoderParameters);

}

private ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}

Ref: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoderparameter.aspx

JPEG Compression produces bigger size

What is happening is that your JPEGs are compressed. When you load them into memory they are uncompressed. This uncompressed size is definitely larger than the original JPG.

When you save the image, you are not compressing from the original size but from the larger uncompressed image in memory. The recompression process is not aware of the fact that the image it is compressing came from a compressed image originally. It just runs the algorithm on the image in memory at the compression setting you give.

This is why lossy formats like JPEG show compression artifacts after a few rounds of open/save.

C# lower quality for JPEG image

Here is my functions to compress image as jpeg

    public static System.Drawing.Imaging.ImageCodecInfo GetEncoder(System.Drawing.Imaging.ImageFormat format)
{
System.Drawing.Imaging.ImageCodecInfo[] codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders();

foreach (System.Drawing.Imaging.ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}

public static byte[] GetCompressedImage(System.Drawing.Image img, long quality)
{
System.Drawing.Imaging.ImageCodecInfo ici = GetEncoder(System.Drawing.Imaging.ImageFormat.Jpeg);
System.Drawing.Imaging.EncoderParameters eps = new System.Drawing.Imaging.EncoderParameters(2);
eps.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
eps.Param[1] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)System.Drawing.Imaging.EncoderValue.CompressionLZW);
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, ici, eps);
return ms.ToArray();
}
}

Lossless optimization of JPEG with FreeImage

I think FreeImage only supports lossless transformations (ie FreeImage_JPEGTransform).

This can save to different files, but unfortunately there doesn't appear to be a way to set any save flags on the new file to allow stripping of metadata etc.

I can only suggest you have a look at the source to see if there is anything you can utilise yourself.

How to compress the image size using .NET Core?

I have used Magick.NET library which is available for both .NET and .NET Core to compress images. Refer to its documentation for more details.

In your case you either need to save the image temporarily somewhere and use the path (similar to my example), or convert it to an array of byte in memory and read that since it accept Byte[]

     using (MagickImage image = new MagickImage(@"YourImage.jpg"))
{
image.Format = image.Format; // Get or Set the format of the image.
image.Resize(40, 40); // fit the image into the requested width and height.
image.Quality = 10; // This is the Compression level.
image.Write("YourFinalImage.jpg");
}


Related Topics



Leave a reply



Submit