Skip to content

Commit

Permalink
Merge pull request #8 from 343dev/feature/rotate
Browse files Browse the repository at this point in the history
v8.0.0
  • Loading branch information
343dev authored Aug 5, 2024
2 parents 4ffb50a + 962ded2 commit 3b3ac94
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 280 deletions.
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
*
!lib/
!.optimiztrc.js
!.optimiztrc.cjs
!cli.js
!index.js
!LICENSE
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

strategy:
matrix:
node-version: [18.x, 20.x]
node-version: [18.17, 20.x]

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .optimiztrc.js → .optimiztrc.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default {
module.exports = {
optimize: {
jpeg: {
// https://sharp.pixelplumbing.com/api-output#jpeg
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 8.0.0 (2024-08-05)

❤️ Thank you for using Optimizt. If you have any suggestions or feedback, please don't hesitate to [open an issue](https://github.com/343dev/optimizt/issues).

Here are the changes in this version:

- Added EXIF Orientation tag support for JPEG.
- Removed convert ratio check for AVIF and WebP.
- Improved JPEG lossless optimization process.
- Changed configuration file format to CJS.

[Migration guide](./MIGRATION.md).


## 7.0.0 (02.02.2024)

SVGO config updated.
Expand Down
11 changes: 11 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Migration

## 7.0.2 → 8.0.0

Optimizt now checks for the EXIF Orientation tag before processing images and rotates the resulting image accordingly.

The compression ratio check has been removed when converting images to AVIF and WebP formats. The `--force` flag is now only used to overwrite existing files.

The lossless optimization process for JPEG images has been improved. Optimization is done by Guetzli, but necessary transformations are applied first using Sharp. This includes converting the color space to sRGB and rotating the image based on the EXIF orientation tag. And the image quality used to degrade after [passing through Sharp](https://github.com/lovell/sharp/issues/2453) because the default quality setting for JPEG was 80. Starting with this version, the quality is set to 100, which should improve the image quality and slightly increase its size compared to previous versions.

The [.optimiztrc](.optimiztrc.cjs) file format has been changed from ESM to CJS. This should make it easier to link an external configuration file using the `--config` flag.


## 6.0.0 → 7.0.0

Previously, when working with SVGO, a custom version of `removeUnknownsAndDefaults` plugin was used, which did not
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ optimizt path/to/picture.jpg

- `--avif` — create AVIF versions for the passed paths instead of compressing them.
- `--webp` — create WebP versions for the passed paths instead of compressing them.
- `-f, --force`force create AVIF and WebP even if output file size increased or file already exists.
- `-f, --force` — create AVIF and WebP even if file already exists.
- `-l, --lossless` — optimize losslessly instead of lossily.
- `-v, --verbose` — show additional info, e.g. skipped files.
- `-c, --config` — use this configuration, overriding default config options if present.
Expand Down Expand Up @@ -93,15 +93,15 @@ For optimizing GIFs, [gifsicle](https://github.com/kohler/gifsicle) is used, and
> a high level of compression and still have a good visual quality. But you should keep in mind that if you optimize
> the file again, the size may decrease at the expense of degrading the visual quality of the image.
The default settings are located in [.optimiztrc.js](./.optimiztrc.js), the file contains a list of supported parameters
The default settings are located in [.optimiztrc.cjs](./.optimiztrc.cjs), the file contains a list of supported parameters
and their brief description.

To disable any of the parameters, you should use `false` for the value.

When running with the `--config path/to/.optimiztrc.js` flag, the settings from the specified configuration file will
When running with the `--config path/to/.optimiztrc.cjs` flag, the settings from the specified configuration file will
be used for image processing.

When running normally, without the `--config` flag, a recursive search for the `.optimiztrc.js` file will be performed
When running normally, without the `--config` flag, a recursive search for the `.optimiztrc.cjs` file will be performed
starting from the current directory and up to the root of the file system. If the file is not found, the default
settings will be applied.

Expand Down Expand Up @@ -370,7 +370,7 @@ on:
paths:
- "**.jpe?g"
- "**.png"

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

Expand Down
16 changes: 8 additions & 8 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ optimizt path/to/picture.jpg

- `--avif` — создать AVIF-версии для переданных изображений, а не сжимать их.
- `--webp` — создать WebP-версии для переданных изображений, а не сжимать их.
- `-f, --force`принудительно создавать AVIF и WebP-версии игнорируя размер итогового файла и его существование.
- `-f, --force`пересоздавать AVIF и WebP-версии, если файл уже существует.
- `-l, --lossless` — оптимизировать без потерь, а не с потерями.
- `-v, --verbose` — выводить дополнительную информацию в ходе работы (например, проигнорированные файлы).
- `-c, --config` — использовать указанный файл конфигурации, вместо настроек по умолчанию.
Expand Down Expand Up @@ -81,26 +81,26 @@ 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 обрабатывается с помощью утилиты
производится с помощью библиотеки [sharp](https://github.com/lovell/sharp), а SVG обрабатывается с помощью утилиты
[svgo](https://github.com/svg/svgo).

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

> 💡 В режиме Lossless для оптимизации JPEG используется энкодер [Guetzli](https://github.com/google/guetzli), который
> позволяет получить высокий уровень компрессии и при этом сохранить хорошее визуальное качество изображения.
> Но, нужно иметь в виду, что при повторной оптимизации файла размер может уменьшаться за счёт деградации визуального
> качества изображения.
Настройки по умолчанию расположены в [.optimiztrc.js](./.optimiztrc.js), файл содержит список поддерживаемых
параметров и их краткое описание.
Настройки по умолчанию расположены в [.optimiztrc.cjs](./.optimiztrc.cjs), файл содержит список поддерживаемых
параметров и их краткое описание.

Для отключения любого из параметров следует использовать значение `false`.

При запуске с флагом `--config path/to/.optimiztrc.js` для обработки изображений будут использоваться настройки
При запуске с флагом `--config path/to/.optimiztrc.cjs` для обработки изображений будут использоваться настройки
из указанного конфигурационного файла.

При обычном запуске, без флага `--config`, будет произведён рекурсивный поиск файла `.optimiztrc.js` начиная
При обычном запуске, без флага `--config`, будет произведён рекурсивный поиск файла `.optimiztrc.cjs` начиная
с текущей директории и до корня файловой системы. Если файл не найден, то будут применены настройки по умолчанию.

## Интеграции
Expand Down Expand Up @@ -374,7 +374,7 @@ on:
paths:
- "**.jpe?g"
- "**.png"

# Разрешаем ручной запуск данного воркфлоу из таба Actions
workflow_dispatch:

Expand Down
51 changes: 22 additions & 29 deletions lib/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,11 @@ export default async function convert({
totalSize.before += fileSize.before;
totalSize.after += isOptimized ? fileSize.after : fileSize.before;

checkResult({
writeResultFile({
fileBuffer,
filePath,
fileSize,
format,
force,
output,
});
}
Expand All @@ -121,43 +120,35 @@ function getOutputFilePath(filePath, format) {
return path.join(dir, `${name}.${format.toLowerCase()}`);
}

function checkResult({ fileBuffer, filePath, fileSize, format, force, output }) {
function writeResultFile({ fileBuffer, filePath, fileSize, format, output }) {
if (!Buffer.isBuffer(fileBuffer) || typeof filePath !== 'string') {
return;
}

const writeFilePath = prepareWriteFilePath(getOutputFilePath(filePath, format), output);
const before = formatBytes(fileSize.before);
const after = formatBytes(fileSize.after);
const ratio = calcRatio(fileSize.before, fileSize.after);
const successMessage = `${before}${format} ${after}. Ratio: ${ratio}%`;
try {
const writeFilePath = prepareWriteFilePath(getOutputFilePath(filePath, format), output);

fs.writeFileSync(writeFilePath, fileBuffer);

const isChanged = !fs.readFileSync(filePath).equals(fileBuffer);
const isOptimised = ratio > 0;
const before = formatBytes(fileSize.before);
const after = formatBytes(fileSize.after);
const ratio = calcRatio(fileSize.before, fileSize.after);

if (isOptimised || force) {
try {
fs.writeFileSync(writeFilePath, fileBuffer, { flag: force ? 'w' : 'wx' });
const successMessage = `${before}${format} ${after}. Ratio: ${ratio}%`;

log(filePath, {
type: 'success',
description: successMessage,
});
} catch (error) {
if (error.message) {
log(filePath, {
type: 'success',
description: successMessage,
type: 'error',
description: error.message,
});
} catch (error) {
if (error.message) {
log(filePath, {
type: 'error',
description: error.message,
});
} else {
console.error(error);
}
} else {
console.error(error);
}
} else {
log(filePath, {
description: `${isChanged ? 'File size increased' : 'Nothing changed'}. Conversion to ${format} skipped`,
verboseOnly: true,
});
}
}

Expand Down Expand Up @@ -208,6 +199,7 @@ async function createAvif({ fileBuffer, lossless, config }) {
}

return sharp(fileBuffer)
.rotate() // Rotate image using information from EXIF Orientation tag
.avif((lossless ? config?.lossless : config?.lossy) || {})
.toBuffer();
}
Expand Down Expand Up @@ -242,6 +234,7 @@ async function createWebp({ fileBuffer, fileExt, lossless, config }) {
}

return sharp(fileBuffer)
.rotate() // Rotate image using information from EXIF Orientation tag
.webp((lossless ? config?.webp?.lossless : config?.webp?.lossy) || {})
.toBuffer();
}
Expand Down
2 changes: 1 addition & 1 deletion lib/find-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const defaultFilename = '.optimiztrc.js';
const defaultFilename = '.optimiztrc.cjs';
const defaultDirname = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const defaultPath = path.join(defaultDirname, defaultFilename);

Expand Down
8 changes: 6 additions & 2 deletions lib/optimize.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import getPlural from './get-plural.js';
import log from './log.js';
import optionsToArguments from './options-to-arguments.js';
import prepareWriteFilePath from './prepare-write-file-path.js';
import setSrgbColorspace from './set-srgb-colorspace.js';
import showTotal from './show-total.js';

export default async function optimize({ paths, lossless: isLossless, output, config }) {
Expand Down Expand Up @@ -159,9 +158,14 @@ async function optimizeByType({ fileBuffer, filePath, isLossless, config }) {
execBuffer.input,
execBuffer.output,
],
input: await setSrgbColorspace(fileBuffer),
input: await sharp(fileBuffer)
.toColorspace('srgb') // Replace colorspace (guetzli works only with sRGB)
.rotate() // Rotate image using information from EXIF Orientation tag
.jpeg({ quality: 100, optimizeCoding: false }) // Applying maximum quality to minimize losses during image processing with sharp
.toBuffer(),
})
: sharp(fileBuffer)
.rotate() // Rotate image using information from EXIF Orientation tag
.jpeg(config?.jpeg?.lossy || {})
.toBuffer();
}
Expand Down
10 changes: 0 additions & 10 deletions lib/set-srgb-colorspace.js

This file was deleted.

Loading

0 comments on commit 3b3ac94

Please sign in to comment.