Home > Blockchain >  Fastest way to find the best level of compression of an image
Fastest way to find the best level of compression of an image

Time:10-10

I wrote a function (in Python) that saves an image with a certain quality level (0 to 100, higher is better). Depending on the quality level, the final file is bigger or smaller (in byte).

I need to write a function that selects the best possible quality level for an image, keeping it under a maximum file size (in byte). The only way I can do it is by attempts.

The simplest approach is: save the file with a certain quality and if it is bigger than expected then reduce the quality and so forth. Unfortunately this approach is very time consuming. Even if I reduce the quality by five points at each iteration, the risk is that I have to save the same file 21 times before I find the right quality.

Another solution is: try with the half of the previous quality and focus on the lower range or on the higher range of quality according to the result. Let me clarify:

  1. assuming that quality can be between 0 and 100, try with quality = 50
  2. if file size is higher than expected, focus on the lower quality range (e.g. 0-49) otherwise on the higher one (e.g. 51-100).
  3. set the quality value in the middle of the considered range and save the file (e.g. 25 if lower range and 75 if higher range); return to 2
  4. exit when the range is smaller than 5

This second solution requires always 6 iterations.

Here it is a Python implementation:

limit_file_size = 512 # maximum file size, change this for different results

q_max = 100
q_min = 0
quality = q_min   (q_max - q_min) // 2

while True:
    file_size = save_file(quality)

    if (q_max - q_min) <= 5: break

    if file_size > limit_file_size:
        q_max = quality
    else:
        q_min = quality

    quality = q_min   (q_max - q_min) // 2

Please note that function save_file is not provided for brevity, a fake implementation of it can be the following:

import math
def save_file(quality):
    return int(math.sqrt(quality))*100

How to reduce the amount of cycles required by the above function to converge to a valid solution?

CodePudding user response:

You can try to do a binary search function like you mentioned and save the result in a dictionary so that next iteration it will check if the file size quality was calculated already like that:

# { file_size : quality }
{ 512 : 100 , 256 : 100, 1024 : 27 }

Note that each image has different dimensions, color depth, format etc so you may get a range of results, I suggest to play with it and create sub keys in the properties that have the most impact for example:

{ format : { file_size : quality } }

CodePudding user response:

You could make some kind of simple ML (Machine Learning) approach. Train model that given:

  • image size for quality 50
  • limit_file_size

as input will produce best quality you seek, or at least narrow down your search so that you need 2-3 iterations instead of 6.

So you would have to gather training (and validation) data, train the model that will be simple and fast (should be fasterer than save_file).

I think this is best approach in terms of determining this quality as fast as possible, but requires a lot of work (specially if you have no experience in ML).

  • Related