Skip to content

archik408/image-compressor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ–ΌοΈ Image Compressor

Π’Ρ‹ΡΠΎΠΊΠΎΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ компрСссор ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, написанный Π½Π° Rust ΠΈ скомпилированный Π² WebAssembly для использования Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅.

✨ ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΠΈ

  • πŸš€ Высокая ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ - написан Π½Π° Rust ΠΈ скомпилирован Π² WASM
  • πŸŽ›οΈ НастраиваСмоС качСство - ΠΎΡ‚ 1% Π΄ΠΎ 100% качСства сТатия
  • πŸ“¦ МаксимальноС сТатиС - автоматичСскоС ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΈΠ΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° ΠΈ качСства
  • 🌐 ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ΠΎΠ² - Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π²ΠΎ всСх соврСмСнных Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π°Ρ…
  • πŸ“± ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ² - JPEG, PNG, WebP, GIF, BMP ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅
  • πŸ”§ ΠŸΡ€ΠΎΡΡ‚ΠΎΠΉ API - ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΉ JavaScript интСрфСйс
  • 🎯 Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° - Ρ„Π°ΠΉΠ» остаСтся Π² исходном Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ послС сТатия

πŸ› οΈ Установка ΠΈ сборка

ΠŸΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ трСбования

  • Rust (послСдняя ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½Π°Ρ вСрсия)
  • wasm-pack

Установка wasm-pack

curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

Π‘Π±ΠΎΡ€ΠΊΠ° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°

# ΠšΠ»ΠΎΠ½ΠΈΡ€ΡƒΠΉΡ‚Π΅ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ
git clone <repository-url>
cd image-compressor

# Π‘ΠΎΠ±Π΅Ρ€ΠΈΡ‚Π΅ WASM ΠΌΠΎΠ΄ΡƒΠ»ΡŒ
./build.sh

Или Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ:

wasm-pack build --target web --out-dir pkg --dev

πŸ“– ИспользованиС

Π‘Π°Π·ΠΎΠ²ΠΎΠ΅ использованиС

import ImageCompressor from './js/image-compressor.js';

// Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ
const compressor = new ImageCompressor();
await compressor.init('./pkg/image_compressor.js');

// Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ изобраТСния с качСством 80%
const compressedData = await compressor.compressImage(file, 80);

// МаксимальноС сТатиС
const maxCompressedData = await compressor.compressImageMax(file);

// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Blob для скачивания
const blob = compressor.createBlob(compressedData);
const url = compressor.createObjectURL(blob);

Π Π°Π±ΠΎΡ‚Π° с Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ

// Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Ρ„Π°ΠΉΠ»Π° Ρ‡Π΅Ρ€Π΅Π· input
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];

// Π‘ΠΆΠ°Ρ‚ΠΈΠ΅
const compressedData = await compressor.compressImage(file, 70);

// Π‘ΠΊΠ°Ρ‡ΠΈΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°
const blob = compressor.createBlob(compressedData);
const downloadUrl = compressor.createObjectURL(blob);

const a = document.createElement('a');
a.href = downloadUrl;
a.download = 'compressed-image.jpg';
a.click();

// ОсвобоТдСниС памяти
compressor.revokeObjectURL(downloadUrl);

ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎΠ± ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ

const info = await compressor.getImageInfo(file);
console.log(`Π Π°Π·ΠΌΠ΅Ρ€: ${info.width}x${info.height}`);
console.log(`Π Π°Π·ΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»Π°: ${info.size_bytes} Π±Π°ΠΉΡ‚`);

🎯 API Reference

ImageCompressor

ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ‚ΠΎΡ€

const compressor = new ImageCompressor();

ΠœΠ΅Ρ‚ΠΎΠ΄Ρ‹

init(wasmPath)

Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ WASM ΠΌΠΎΠ΄ΡƒΠ»ΡŒ.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

  • wasmPath (string) - ΠΏΡƒΡ‚ΡŒ ΠΊ скомпилированному WASM ΠΌΠΎΠ΄ΡƒΠ»ΡŽ

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: Promise

compressImage(imageInput, quality)

Π‘ΠΆΠΈΠΌΠ°Π΅Ρ‚ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ с Π·Π°Π΄Π°Π½Π½Ρ‹ΠΌ качСством, сохраняя исходный Ρ„ΠΎΡ€ΠΌΠ°Ρ‚.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

  • imageInput (File|Uint8Array) - Ρ„Π°ΠΉΠ» изобраТСния ΠΈΠ»ΠΈ массив Π±Π°ΠΉΡ‚ΠΎΠ²
  • quality (number) - качСство сТатия ΠΎΡ‚ 1 Π΄ΠΎ 100

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: Promise - сТатыС Π΄Π°Π½Π½Ρ‹Π΅ изобраТСния Π² исходном Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅

ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹:

  • JPEG β†’ JPEG (с настраиваСмым качСством)
  • PNG β†’ PNG (с ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΌ сТатиСм)
  • WebP β†’ JPEG (конвСртация с настраиваСмым качСством)
  • GIF/BMP β†’ PNG (конвСртация)
compressImageMax(imageInput)

Π‘ΠΆΠΈΠΌΠ°Π΅Ρ‚ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ с ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΌ сТатиСм, ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Ρ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΈ качСство.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

  • imageInput (File|Uint8Array) - Ρ„Π°ΠΉΠ» изобраТСния ΠΈΠ»ΠΈ массив Π±Π°ΠΉΡ‚ΠΎΠ²

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: Promise - максимально сТатыС Π΄Π°Π½Π½Ρ‹Π΅

ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΠΈ:

  • Π£ΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€ изобраТСния Π² 2 Ρ€Π°Π·Π°
  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ минимальноС качСство для JPEG
  • БохраняСт Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ PNG Π±Π΅Π· ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ
getImageInfo(imageInput)

ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ± ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

  • imageInput (File|Uint8Array) - Ρ„Π°ΠΉΠ» изобраТСния ΠΈΠ»ΠΈ массив Π±Π°ΠΉΡ‚ΠΎΠ²

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: Promise - ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ с ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠ΅ΠΉ:

{
  width: number,
  height: number,
  format: string,
  size_bytes: number
}
createBlob(data, mimeType)

Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ Blob ΠΈΠ· Uint8Array.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

  • data (Uint8Array) - Π΄Π°Π½Π½Ρ‹Π΅ изобраТСния
  • mimeType (string) - MIME Ρ‚ΠΈΠΏ (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ 'image/jpeg')

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: Blob

createObjectURL(blob)

Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ URL для Blob.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

  • blob (Blob) - Blob ΠΎΠ±ΡŠΠ΅ΠΊΡ‚

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: string - URL

revokeObjectURL(url)

ΠžΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅Ρ‚ URL ΠΎΠ±ΡŠΠ΅ΠΊΡ‚.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

  • url (string) - URL для освобоТдСния

πŸ§ͺ ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ 1: ΠŸΡ€ΠΎΡΡ‚ΠΎΠ΅ сТатиС

<!DOCTYPE html>
<html>
<head>
    <title>Image Compressor Example</title>
</head>
<body>
    <input type="file" id="fileInput" accept="image/*">
    <button onclick="compress()">Π‘ΠΆΠ°Ρ‚ΡŒ</button>
    <img id="result" style="display:none;">

    <script type="module">
        import ImageCompressor from './js/image-compressor.js';

        let compressor;

        async function init() {
            compressor = new ImageCompressor();
            await compressor.init('./pkg/image_compressor.js');
        }

        window.compress = async function() {
            const file = document.getElementById('fileInput').files[0];
            if (!file) return;

            const compressedData = await compressor.compressImage(file, 60);
            const blob = compressor.createBlob(compressedData);
            const url = compressor.createObjectURL(blob);

            const img = document.getElementById('result');
            img.src = url;
            img.style.display = 'block';
        };

        init();
    </script>
</body>
</html>

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ 2: ΠŸΠ°ΠΊΠ΅Ρ‚Π½ΠΎΠ΅ сТатиС

async function compressMultiple(files, quality) {
    const results = [];
    
    for (const file of files) {
        try {
            const compressedData = await compressor.compressImage(file, quality);
            const blob = compressor.createBlob(compressedData);
            results.push({
                original: file,
                compressed: blob,
                compressionRatio: (1 - compressedData.length / file.size) * 100
            });
        } catch (error) {
            console.error(`Ошибка сТатия ${file.name}:`, error);
        }
    }
    
    return results;
}

πŸ—οΈ АрхитСктура

image-compressor/
β”œβ”€β”€ src/
β”‚   └── lib.rs              # Основной Rust ΠΊΠΎΠ΄
β”œβ”€β”€ js/
β”‚   └── image-compressor.js # JavaScript ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠ°
β”œβ”€β”€ example/
β”‚   └── index.html          # Π”Π΅ΠΌΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
β”œβ”€β”€ pkg/                    # Π‘ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ WASM Ρ„Π°ΠΉΠ»Ρ‹
β”œβ”€β”€ Cargo.toml              # Rust зависимости
β”œβ”€β”€ build.sh                # Π‘ΠΊΡ€ΠΈΠΏΡ‚ сборки
└── README.md               # ДокумСнтация

πŸ”§ Π Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°

Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° Rust ΠΊΠΎΠ΄Π°

Основной ΠΊΠΎΠ΄ находится Π² src/lib.rs:

  • ImageCompressor - основной класс для сТатия
  • compress_image_quick - быстрая функция сТатия
  • compress_image_max_quick - максимальноС сТатиС
  • get_image_info - ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎΠ± ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ

Зависимости

  • wasm-bindgen - для взаимодСйствия с JavaScript
  • image - для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с изобраТСниями
  • serde - для сСриализации Π΄Π°Π½Π½Ρ‹Ρ…

Π‘Π±ΠΎΡ€ΠΊΠ° для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ

wasm-pack build --target web --out-dir pkg --dev

Π‘Π±ΠΎΡ€ΠΊΠ° для ΠΏΡ€ΠΎΠ΄Π°ΠΊΡˆΠ΅Π½Π°

wasm-pack build --target web --out-dir pkg --release

πŸ“Š ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ

  • Π‘ΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ сТатия: ~10-50ms для ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π΄ΠΎ 5MB
  • Π‘ΠΆΠ°Ρ‚ΠΈΠ΅: 60-90% ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΈΠ΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° ΠΏΡ€ΠΈ качСствС 80%
  • ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹: JPEG, PNG, WebP, BMP, GIF
  • ΠœΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€: ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ ΠΏΠ°ΠΌΡΡ‚ΡŒΡŽ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π°

πŸ› ΠžΡ‚Π»Π°Π΄ΠΊΠ°

Π’ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ Π»ΠΎΠ³ΠΈ Π² консоли Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π° для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ:

// Π’ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Ρ‹Π΅ Π»ΠΎΠ³ΠΈ
localStorage.setItem('debug', 'image-compressor');

πŸ“„ ЛицСнзия

MIT License - см. Ρ„Π°ΠΉΠ» LICENSE для Π΄Π΅Ρ‚Π°Π»Π΅ΠΉ.

🀝 Π’ΠΊΠ»Π°Π΄ Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚

  1. Π€ΠΎΡ€ΠΊΠ½ΠΈΡ‚Π΅ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ
  2. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Π²Π΅Ρ‚ΠΊΡƒ для Π½ΠΎΠ²ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ
  3. ВнСситС измСнСния
  4. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ тСсты
  5. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Pull Request

πŸ“ž ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ°

Если Ρƒ вас Π΅ΡΡ‚ΡŒ вопросы ΠΈΠ»ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹:

  1. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ Issues
  2. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Π½ΠΎΠ²Ρ‹ΠΉ Issue с ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Ρ‹ΠΌ описаниСм
  3. ΠŸΡ€ΠΈΠ»ΠΎΠΆΠΈΡ‚Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠΎΠ΄Π° ΠΈ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅

БдСлано с ❀️ на Rust и WebAssembly

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published