Kompresja JPEG nie jest przewidywalna wcześniej. Metoda, którą opisałeś, kompresuj & miara & spróbuj ponownie, to jedyny sposób, jaki znam.
Można spróbować skompresować wiele typowych obrazów o różnych ustawieniach jakości, aby uzyskać optymalny punkt początkowy, a także sposób zgadywania, w jaki sposób zmiany ustawień wpłyną na rozmiar. W ten sposób uzyskasz optymalny rozmiar bez zbyt wielu iteracji.
Można również przekazać obiekt podobny do pliku do funkcji save
, która nie zajmuje się zapisywaniem na dysk, po prostu zlicza bajty. Po określeniu najlepszych ustawień można zapisać go ponownie do rzeczywistego pliku.
Edytuj: Oto implementacja odpowiedniego obiektu pliku zliczającego bajty. Sprawdź po prostu size
.
class file_counter(object):
def __init__(self):
self.position = self.size = 0
def seek(self, offset, whence=0):
if whence == 1:
offset += self.position
elif whence == 2:
offset += self.size
self.position = min(offset, self.size)
def tell(self):
return self.position
def write(self, string):
self.position += len(string)
self.size = max(self.size, self.position)
Edit 2: Oto binarne wyszukiwania przy użyciu wyżej, aby uzyskać optymalne quality
w najmniejszej liczbie prób.
def smaller_than(im, size, guess=70, subsampling=1, low=1, high=100):
while low < high:
counter = file_counter()
im.save(counter, format='JPEG', subsampling=subsampling, quality=guess)
if counter.size < size:
low = guess
else:
high = guess - 1
guess = (low + high + 1) // 2
return low
lepszym sposobem na to jest do binarnego wyszukiwania jakości. Zacznij więc od 50% jakości, następnie sprawdź rozmiar, jeśli jest za mały, spróbuj 75%, spróbuj 25% itd. Dostaniesz się tak blisko jak to tylko możliwe do 500KB, możesz dodatkowo ustawić dodatkowe parametry, np. minimalna jakość lub tolerancja rozmiaru. Powinieneś być w stanie wyzerować do właściwego poziomu kompresji w co najwyżej 7 iteracjach. –