Skip to content

Commit

Permalink
Merge pull request #21 from 343dev/improvement/gif2webp
Browse files Browse the repository at this point in the history
Replace gif2webp with sharp
  • Loading branch information
343dev authored Oct 28, 2024
2 parents a739750 + f933671 commit 71ba3f5
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 296 deletions.
46 changes: 11 additions & 35 deletions .optimiztrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module.exports = {
},
// https://github.com/google/guetzli
lossless: {
quality: 90, // visual quality to aim for, expressed as a JPEG quality value
quality: 90, // visual quality to aim for, expressed as a JPEG quality value; should be >= 84, otherwise the output will have noticeable artifacts
memlimit: 6000, // memory limit in MB; guetzli will fail if unable to stay under the limit
nomemlimit: false, // do not limit memory usage
},
Expand All @@ -39,7 +39,7 @@ module.exports = {
adaptiveFiltering: true,
palette: false,
quality: 100,
effort: 7,
effort: 10,
colors: 256,
dither: 1.0,
},
Expand Down Expand Up @@ -88,67 +88,43 @@ module.exports = {
// https://sharp.pixelplumbing.com/api-output#avif
avif: {
lossy: {
quality: 50, // quality, integer 1-100
quality: 64, // quality, integer 1-100
lossless: false, // use lossless compression
effort: 4, // CPU effort, between 0 (fastest) and 9 (slowest)
chromaSubsampling: '4:4:4', // set to '4:2:0' to use chroma subsampling
},
lossless: {
quality: 50,
quality: 100,
lossless: true,
effort: 4,
effort: 9,
chromaSubsampling: '4:4:4',
},
},

// https://sharp.pixelplumbing.com/api-output#webp
webp: {
lossy: {
quality: 85, // quality, integer 1-100
alphaQuality: 100, // quality of alpha layer, integer 0-100
quality: 82, // quality, integer 1-100
alphaQuality: 82, // quality of alpha layer, integer 0-100
lossless: false, // use lossless compression mode
nearLossless: false, // use near_lossless compression mode
smartSubsample: false, // use high quality chroma subsampling
preset: 'default', // named preset for preprocessing/filtering, one of: default, photo, picture, drawing, icon, text
effort: 4, // CPU effort, between 0 (fastest) and 6 (slowest)
minSize: false, // prevent use of animation key frames to minimise file size (slow)
minSize: true, // prevent use of animation key frames to minimise file size (slow)
mixed: false, // allow mixture of lossy and lossless animation frames (slow)
},
lossless: {
quality: 85,
quality: 100,
alphaQuality: 100,
lossless: true,
nearLossless: false,
smartSubsample: false,
effort: 4,
preset: 'default',
effort: 6,
minSize: false,
mixed: false,
},
},

// https://developers.google.com/speed/webp/docs/gif2webp
webpGif: {
lossy: {
lossy: true, // encode image using lossy compression
mixed: false, // for each frame in the image, pick lossy or lossless compression heuristically
q: 75, // in case of lossy compression, a small factor produces a smaller file with lower quality; best quality is achieved by using a value of 100
m: 6, // compression method (0=fast, 6=slowest)
min_size: true, // minimize output size; can be combined with -q, -m, -lossy or -mixed options
f: 0, // filter strength (0=off..100); for lossy encoding only
metadata: 'xmp', // comma separated list of metadata to copy from the input to the output if present; valid values: all, none, icc, xmp
loop_compatibility: false, // use compatibility mode for Chrome version prior to M62 (inclusive)
mt: true, // use multi-threading if available
},
lossless: {
lossy: false,
mixed: false,
q: 100,
m: false,
min_size: false,
metadata: 'xmp',
loop_compatibility: false,
mt: true,
},
},
},
};
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 10.0.0 (2024-10-28)

Breaking Changes:

- Supported Node.js version updated to 18.18 or higher.
- Replaced “gif2webp” with “sharp” for GIF-to-WebP conversions.
- Removed the “webpGif” section from [.optimiztrc.cjs](.optimiztrc.cjs).
- Fine-tuned params in [.optimiztrc.cjs](.optimiztrc.cjs).


## 9.1.1 (2024-10-22)

- Replaced [imagemin/guetzli-bin](https://github.com/imagemin/guetzli-bin) with [343dev/guetzli](https://github.com/343dev/guetzli).
Expand Down
16 changes: 8 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:18.17.0-bullseye-slim
FROM node:18.18.0-bullseye-slim
LABEL maintainer="Andrey Warkentin (https://github.com/343dev)"

WORKDIR /app
Expand All @@ -8,13 +8,13 @@ COPY . .
ENV NODE_ENV="production"

RUN apt update \
&& apt install --yes --no-install-recommends build-essential libpng16-16 libjpeg62-turbo libjpeg62-turbo-dev libpng-dev pkg-config dh-autoreconf \
&& npm ci \
&& npm link \
&& npm cache clean --force \
&& apt purge --yes build-essential pkg-config libpng-dev libjpeg62-turbo-dev dh-autoreconf \
&& apt autoremove --yes --purge \
&& rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man
&& apt install --yes --no-install-recommends build-essential libpng16-16 libjpeg62-turbo libjpeg62-turbo-dev libpng-dev pkg-config dh-autoreconf \
&& npm ci \
&& npm link \
&& npm cache clean --force \
&& apt purge --yes build-essential pkg-config libpng-dev libjpeg62-turbo-dev dh-autoreconf \
&& apt autoremove --yes --purge \
&& rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man

WORKDIR /src

Expand Down
9 changes: 9 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Migration

## 9.1.1 → 10.0.0

Node.js version must be 18.18 or higher.

The “sharp” module now replaces “gif2webp” for converting GIFs to WebP. Consequently, the “webpGif” section in [.optimiztrc.cjs](.optimiztrc.cjs) has been replaced with a “webp” section. If you use a custom configuration file, please remove any “webpGif” section.

Default settings in Optimizt’s configuration have been updated. Note that in lossless mode, image processing times may increase slightly, but resulting file sizes are expected to be smaller compared to previous versions.


## 8.0.1 → 9.0.0

The main change in the new version is how Optimizt handles file processing. Before, the result was stored in memory until all files were processed. This could cause the app to crash if it ran out of memory, leading to a loss of optimization results. Now, each file is processed one by one, and the result is saved to disk immediately. Logging events also happen in real-time, instead of waiting until all files are done.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ For SVG files, the settings in Lossy and Lossless modes are identical.

## Configuration

Image processing is done using [sharp](https://github.com/lovell/sharp) for [JPEG](https://sharp.pixelplumbing.com/api-output#jpeg), [PNG](https://sharp.pixelplumbing.com/api-output#png), [WebP](https://sharp.pixelplumbing.com/api-output#webp), and [AVIF](https://sharp.pixelplumbing.com/api-output#avif), while SVG is processed by [svgo](https://github.com/svg/svgo).
Image processing is done using [sharp](https://github.com/lovell/sharp) for [JPEG](https://sharp.pixelplumbing.com/api-output#jpeg), [PNG](https://sharp.pixelplumbing.com/api-output#png), [WebP](https://sharp.pixelplumbing.com/api-output#webp), and [AVIF](https://sharp.pixelplumbing.com/api-output#avif).

For GIF, [gifsicle](https://github.com/kohler/gifsicle) is used, and for converting GIF to WebP — [gif2webp](https://developers.google.com/speed/webp/docs/gif2webp).
SVG is processed by [svgo](https://github.com/svg/svgo), while for GIF, [gifsicle](https://github.com/kohler/gifsicle) is used.

> [!NOTE]
> In Lossless mode for JPEG, we use [Guetzli](https://github.com/google/guetzli), which offers high level of compression with good visual quality. However, repeated optimization may degrade visual quality.
Expand Down
4 changes: 2 additions & 2 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ find . -iname \*.jpg -exec optimizt {} +

## Конфигурация

Операции с [JPEG](https://sharp.pixelplumbing.com/api-output#jpeg), [PNG](https://sharp.pixelplumbing.com/api-output#png), [WebP](https://sharp.pixelplumbing.com/api-output#webp) и [AVIF](https://sharp.pixelplumbing.com/api-output#avif) производятся с помощью библиотеки [sharp](https://github.com/lovell/sharp), а SVG обрабатывается с помощью утилиты [svgo](https://github.com/svg/svgo).
Операции с [JPEG](https://sharp.pixelplumbing.com/api-output#jpeg), [PNG](https://sharp.pixelplumbing.com/api-output#png), [WebP](https://sharp.pixelplumbing.com/api-output#webp) и [AVIF](https://sharp.pixelplumbing.com/api-output#avif) производятся с помощью библиотеки [sharp](https://github.com/lovell/sharp).

Для оптимизации GIF используется [gifsicle](https://github.com/kohler/gifsicle), а для конвертации GIF в WebP — [gif2webp](https://developers.google.com/speed/webp/docs/gif2webp).
SVG обрабатывается с помощью утилиты [svgo](https://github.com/svg/svgo), а для оптимизации GIF используется [gifsicle](https://github.com/kohler/gifsicle).

> [!NOTE]
> В режиме Lossless для оптимизации JPEG используется энкодер [Guetzli](https://github.com/google/guetzli), который позволяет получить высокий уровень компрессии и при этом сохранить хорошее визуальное качество изображения. Но, нужно иметь в виду, что при повторной оптимизации файла размер может уменьшаться за счёт деградации визуального качества изображения.
Expand Down
26 changes: 3 additions & 23 deletions convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';

import execBuffer from 'exec-buffer';
import gif2webp from 'gif2webp-bin';
import pLimit from 'p-limit';
import sharp from 'sharp';

Expand All @@ -20,7 +18,6 @@ import {
logProgress,
logProgressVerbose,
} from './lib/log.js';
import { optionsToArguments } from './lib/options-to-arguments.js';
import { parseImageMetadata } from './lib/parse-image-metadata.js';
import { programOptions } from './lib/program-options.js';
import { showTotal } from './lib/show-total.js';
Expand Down Expand Up @@ -53,7 +50,6 @@ export async function convert({ filePaths, config }) {

const avifConfig = getConfig('avif');
const webpConfig = getConfig('webp');
const webpGifConfig = getConfig('webpGif');

const cpuCount = os.cpus().length;
const tasksSimultaneousLimit = pLimit(cpuCount);
Expand All @@ -78,13 +74,11 @@ export async function convert({ filePaths, config }) {
}

if (shouldConvertToWebp) {
const isGif = path.extname(filePath.input).toLowerCase() === '.gif';

accumulator.push(
tasksSimultaneousLimit(
() => processFile({
filePath,
config: (isGif ? webpGifConfig : webpConfig) || {},
config: webpConfig || {},
progressBarContainer,
progressBar,
totalSize,
Expand Down Expand Up @@ -187,23 +181,9 @@ async function processWebp({ fileBuffer, config }) {
const imageMetadata = await parseImageMetadata(fileBuffer);
checkImageFormat(imageMetadata.format);

if (imageMetadata.format === 'gif') {
return execBuffer({
bin: gif2webp,
args: [
...optionsToArguments({
options: config,
prefix: '-',
}),
execBuffer.input,
'-o',
execBuffer.output,
],
input: fileBuffer,
});
}
const isAnimated = imageMetadata.pages > 1;

return sharp(fileBuffer)
return sharp(fileBuffer, { animated: isAnimated })
.rotate() // Rotate image using information from EXIF Orientation tag
.webp(config)
.toBuffer();
Expand Down
Loading

0 comments on commit 71ba3f5

Please sign in to comment.