سؤال

There are several tools to optimize a JPEG without sacrificing quality, such as jpegtran.exe and Smush.it. I've been looking for a way to do it through code (preferably in .NET) and I'm currently settled on FreeImage but I'm not getting the result I want.

There's an JPEG_OPTIMIZE flag but you have to set a quality flag as well and then it's not lossless anymore.

This is what I tried:

var image = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_JPEG, fileIn, FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
FreeImage.Save(FREE_IMAGE_FORMAT.FIF_JPEG, image, fileOut, FREE_IMAGE_SAVE_FLAGS.JPEG_OPTIMIZE);

But it does a compression. I thought FreeImage could optimize (by stripping out metadata etc) but I can't find how to keep the same compression/image quality. What's the proper way to do it?

Edit: There's some confusion about not being able to optimize JPEGs, short answer is yes you can since you can strip out unused metadata. I'm not talking about compression. See these threads or check Michael B's answer.

Library for further lossless jpeg compression

Is there a Windows version of Smush.it available?

Tool for Image compression

Image Optimizer for images used on the web (jpg, gif and png)

Question is: Can it be done with FreeImage, and if so: how?

هل كانت مفيدة؟

المحلول

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.

نصائح أخرى

I see people mostly think about compression, when you mention optimization...

The program that you mentioned (jpegtran) can optimize jpeg images losslessly without decompressing and recompressing the data. That's why you do not loos the quality. What you can do to optimize a jpeg is:

  • optimize the Huffman coding layer of a JPEG file to increase compression,
  • convert between progressive and non-progressive JPEG formats,
  • eliminate non-standard application-specific data inserted by some image programs
  • you can also apply grayscale, rotate or crop without losing the quality, but I guess you are not interested in that.

Source: wikipedia.

I have never done it, so I do not have anything by the hand, but I am quite sure that there is a library that can do that for you. Otherwise crafting something on your own should not be that difficult.

I'm afraid JPEG is a lossy format. Even at a tiny scale. The Quality flag tells it where on the scale you want your lossiness, the more lossy the better the compression, the less lossy the bigger the file.

  • JPEG/2000 can do non lossy formats but isn't quite as supported
  • PNG supports lossless compression.

You can however optimize the JPEG file, but this will still cause a loss of data, it may be meaningless data (ie EXIF information) however it will lose some of these, the size gains are minimal (unless your file is already pretty small). Have a peek here for a tutorial on how to remove EXIF data.

If however your trying to squeeze every last drop of size out of the file you may be better switching to a "better" format (and I use that term loosely as what defined a better or worse format is your own requirements). But there are other formats that support higher compression with less loss.

You can remove the metadata with FreeImage, but, for a jpeg, the image will be re-compressed on saving, with the associated loss of image quality.

' by default, FreeImage will have copied the metadata to the new image
If Not (args.CopyMetadata) Then
    Dim tag As New FreeImageAPI.FITAG
    FreeImage.SetMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib2, Nothing, tag)
    FreeImage.SetMetadata(FREE_IMAGE_MDMODEL.FIMD_IPTC, dib2, Nothing, tag)
    FreeImage.SetMetadata(FREE_IMAGE_MDMODEL.FIMD_XMP, dib2, Nothing, tag)
    ' value of 11 is for FIMD_EXIF_RAW
    FreeImage.SetMetadata(DirectCast(11, FreeImageAPI.FREE_IMAGE_MDMODEL), dib2, Nothing, tag)
    FreeImage.DeleteTag(tag)
End If

If File.Exists(targetFile) Then
    File.Delete(targetFile)
End If

FreeImage.Save(FREE_IMAGE_FORMAT.FIF_JPEG, dib2, targetFile, FREE_IMAGE_SAVE_FLAGS.JPEG_OPTIMIZE Or FREE_IMAGE_SAVE_FLAGS.JPEG_QUALITYGOOD)

If you want to remove metadata from file types other than FIF_JPEG, you should consult the documentation to see which ones are writeable.

To remove the metadata without affecting the image, you will need to look into the jpeg file interchange format and pull out just the data which is required. If you happen to have a Photoshop 6 installation CD (6, not CS6), a document with the relevant information is available when you install the PS6 SDK.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top