Алгоритм сжатия картинок

106
09 сентября 2019, 11:20

Необходимо сжать картинку к размеру 204 800 КБ. Реализую сжатие при помощи thumbnailator. Думаю про вариант с .scale(0.5). Если масштабиравать в 2 раза, то и размер в 2 раза уменьшится. Я так думал. Оказалось не так. Пытался вычислить коэффициент сжатия, безуспешно, значение постоянно меняется. Кто сможет подсказать варианты?

Если через цикл for пострадает производительность....

// create static size
        byte[] convertedImage;
        try (
                ByteArrayInputStream input = new ByteArrayInputStream(img);
                ByteArrayOutputStream output = new ByteArrayOutputStream(); 
            ) {
            System.out.println("img.length "+img.length);
            Thumbnails.of(input).scale(1.0).outputFormat("gif").toOutputStream(output);
            convertedImage = output.toByteArray();
            System.out.println("convertedImage "+convertedImage.length);
        }
Answer 1
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import net.coobird.thumbnailator.Thumbnails;
/**
 *
 * @author Алексей
 */
public class Thumb2 {
    private static final double MAX_IMG_SIZE = 204800.00;
    public static byte[] scale(byte[] img) throws IOException {
        byte[] endImage;
        // create static size
        byte[] convertedImage;
        try (
                ByteArrayInputStream input = new ByteArrayInputStream(img);
                ByteArrayOutputStream output = new ByteArrayOutputStream(); 
            ) {
            System.out.println("start.image.length "+img.length);
            Thumbnails.of(input).scale(1.0).outputFormat("gif").toOutputStream(output);
            convertedImage = output.toByteArray();
            System.out.println("after.edit.format.length "+convertedImage.length);
        }
        if (convertedImage.length <= MAX_IMG_SIZE) {
            endImage = convertedImage;
        } else {
            try (
                    ByteArrayInputStream input = new ByteArrayInputStream(convertedImage);
                    ByteArrayOutputStream output = new ByteArrayOutputStream(); 
                ) {
                /*
                изначальный размер картинки: 814 099 Б
                необходимый размер картинки: 204 800 Б
                путем вычислений мы выяснили, что
                нужно срезать 609 299 Б:
                204 800 + x = 814 099
                x = 814 099 - 204 800
                x = 609 299
                дальше мы вычислили на сколько процентов 
                необходимо уманьшить размер картинки, а 
                именно на 74.84335443232334% :
                609 299 : 814 099 = 0.7484335443232334
                @author nick_n_a
                «Два в квадрате - четые. Если без сжатия, то при масштабировании 
                в 2 раза - размер меняется в 4 раза. Потому что к-во пикселей 
                равно ширина*высота, и 0.5ширина*0.5высота=0.25 Учитывая сжатие - 
                могут быть варианты (плюс поправка на заголовки) - По идее ответ - 
                корень квадратный из коефициента отношения реального размера 
                к нужному.»
                теперь необходимо получить scale-коэфициент для вставки
                1.00 - (0.7484335443232334 : 2) = 0.6257832278383833
                консоль:
                start.image.length 1 451 668
                after.edit.format.length 814 099
                convertedImage 362 935
                результат окозался выше на 158 135 Б
                возможно заголовок
                UPDATE:
                еслить удалить .outputFormat("gif"), то
                картинка сжимается до нужных размеров
                start.image.length 1451668
                after.edit.format.length 364646
                endImage 205762
                мо моему скромному мнению разница 
                в 962 Б не существенна
                */
                double startSize = (double) convertedImage.length;
                double destroySize = startSize - MAX_IMG_SIZE;
                double destroyProc = destroySize / startSize;
                double finalCoef = 1.00 - (destroyProc/2);
                Thumbnails.of(input).scale(finalCoef).outputFormat("gif").toOutputStream(output);
                endImage = output.toByteArray();
            }
        }
        System.out.println("endImage "+endImage.length);
        return endImage;
    }
}
READ ALSO
Ошибка such unique or primary key already exists in the table при использовании jpa?

Ошибка such unique or primary key already exists in the table при использовании jpa?

Приложение на sprign+jpa и базой oracle11g Настроен параметр генерации таблицы на основе предложенных сущностей JPA

122
Хранение данных в Android-приложении

Хранение данных в Android-приложении

Планирую создать Android-приложениеЗнаю, что есть множество различных способов хранения информации

140
Чем инверсия управления (Inversion of Control, IoC) отличается от инверсии зависимостей (Dependency Inversion Principle, DIP)?

Чем инверсия управления (Inversion of Control, IoC) отличается от инверсии зависимостей (Dependency Inversion Principle, DIP)?

В литературе встречаются два разных понятия Инверсия управления и Принцип инверсии зависимостей, которые сформулированы одинакаво:

115
Данные из одного списка в другой

Данные из одного списка в другой

У меня есть список Arraylist list(с данными) и

148