Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ jobs:
- name: Check server syntax
run: node --check server/index.mjs

- name: Smoke-test CLI
run: |
node --check bin/opencompress.mjs
npm run cli -- --help
node --input-type=module -e "import sharp from 'sharp'; await sharp({ create: { width: 32, height: 32, channels: 4, background: '#ff0000' } }).png().toFile('/tmp/opencompress-ci.png');"
npm run cli -- /tmp/opencompress-ci.png --format webp --output /tmp/opencompress-cli-output
test -s /tmp/opencompress-cli-output/opencompress-ci.webp

- name: Typecheck strict
run: npm run typecheck:strict

Expand Down
78 changes: 78 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Release

on:
push:
branches:
- 'release/v*'

permissions:
contents: write

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.19.0
cache: npm

- name: Validate release version
shell: bash
run: |
set -euo pipefail
TAG="${GITHUB_REF_NAME#release/}"
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Invalid release branch tag: $TAG" >&2
exit 1
fi
PACKAGE_VERSION="$(node -p "require('./package.json').version")"
if [[ "v${PACKAGE_VERSION}" != "$TAG" ]]; then
echo "package.json version v${PACKAGE_VERSION} does not match $TAG" >&2
exit 1
fi
echo "TAG=$TAG" >> "$GITHUB_ENV"
echo "ARCHIVE=opencompress-${PACKAGE_VERSION}-source.zip" >> "$GITHUB_ENV"

- name: Install dependencies
run: npm ci

- name: Validate source
run: |
node --check server/index.mjs
node --check bin/opencompress.mjs
npm run typecheck:strict
npm run build

- name: Build source archive
shell: bash
run: |
set -euo pipefail
git archive --format=zip --output="$ARCHIVE" HEAD
sha256sum "$ARCHIVE" > "$ARCHIVE.sha256"

- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail
if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG already exists; uploading assets only."
else
gh release create "$TAG" \
--target "$GITHUB_SHA" \
--title "OpenCompress Studio $TAG" \
--notes-file RELEASE_NOTES.md
fi
gh release upload "$TAG" "$ARCHIVE" "$ARCHIVE.sha256" --clobber
57 changes: 54 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ Most image compressors are either single-file tools, cloud services or too gener
- **Safe defaults:** metadata removal and keep-original-if-larger are enabled by design.
- **Optional external comparison:** reSmush.it can be enabled explicitly and automatically falls back to local compression when possible.

## Where it fits

This is a workflow comparison, not a claim that one encoder always produces smaller files. Results depend on image content, codec and settings.

| Tool | Processing model | Strong fit | OpenCompress difference |
| --- | --- | --- | --- |
| **OpenCompress Studio** | Local Node.js + Sharp by default; optional reSmush.it | Repeatable shop and creator batches | Presets, SEO rename, target-size mode, before/after review and ZIP batch export in one workflow |
| **[Squoosh](https://squoosh.app/)** | Local in the browser | Hands-on visual codec tuning | OpenCompress focuses on repeatable multi-image shop workflows and can also be automated from the CLI |
| **[TinyPNG / TinyJPG](https://tinypng.com/)** | Hosted service/API; images are sent to the service for compression | Managed web/API compression | OpenCompress can keep the complete image workflow local with no account or API key |

Squoosh documents that image processing stays on-device. TinyPNG's API documentation describes uploading image data to its service for compression. OpenCompress is aimed at users who want the local model plus batch-oriented e-commerce tooling.

## Quick start

### Windows
Expand All @@ -49,12 +61,47 @@ npm run dev

Open `http://127.0.0.1:5174`.

## CLI preview

OpenCompress 2.1 also includes a local-only CLI foundation for scripts, CI jobs and large folders. It intentionally does not call reSmush.it or another external image service.

```bash
# Convert a folder to WebP at quality 82
npm run cli -- ./images --format webp --quality 82

# Resize a complete catalog recursively
npm run cli -- ./catalog --recursive --format webp --quality 82 --max-width 1600 --max-height 1600 -o ./optimized

# JPEG output with a white background for transparent inputs
npm run cli -- hero.png --format jpg --quality 90 --background '#ffffff'

# Machine-readable result summary
npm run cli -- ./images --format webp --json
```

CLI options:

```text
-o, --output <dir> Output directory
-f, --format <format> webp, jpg/jpeg or png
-q, --quality <1-100> Lossy output quality
--max-width <px> Maximum output width
--max-height <px> Maximum output height
-r, --recursive Scan nested directories
--allow-larger Keep optimized output even when larger
--background <hex> JPG alpha background
--json Machine-readable JSON summary
```

Run `npm run cli -- --help` for the complete usage text. The CLI currently supports JPG, PNG, WebP, TIFF and BMP inputs. Auto Best, target-size search and reSmush.it remain GUI-only for now.

## Feature highlights

- Batch upload for up to 250 images
- JPG, PNG, WebP, GIF, TIF and BMP input
- JPG, PNG, WebP, GIF, TIF and BMP input in the GUI
- JPG, PNG and WebP output
- Local compression with `sharp`
- Local-only CLI preview for scripts and folder processing
- Auto Best local mode that tests multiple output candidates and keeps the smallest
- Optional reSmush.it API compression
- Auto Compare local vs reSmush.it
Expand All @@ -80,8 +127,9 @@ Open `http://127.0.0.1:5174`.
| **Auto Best local** | Yes | No | Smallest local result without cloud uploads |
| **reSmush.it API** | No | Yes | Explicit external compression |
| **Auto Compare** | No | Yes | Comparing local output with reSmush.it |
| **CLI preview** | Yes | No | Scripts, CI jobs and local folders |

Local-only processing stores temporary job files in `.opencompress/` and removes old jobs automatically after the configured TTL.
Local-only processing stores temporary GUI job files in `.opencompress/` and removes old jobs automatically after the configured TTL. CLI output is written directly to the selected output directory.

> If you bind `OPENCOMPRESS_HOST` to a non-loopback address, the local API becomes reachable from your network. Keep the default `127.0.0.1` unless you intentionally want remote access.

Expand Down Expand Up @@ -134,7 +182,7 @@ If the target cannot be reached, the result is still returned with a warning ins

## reSmush.it support

reSmush.it is optional and is never used by Local only or Auto Best local mode.
reSmush.it is optional and is never used by Local only, Auto Best local or CLI mode.

Supported external inputs:

Expand Down Expand Up @@ -166,6 +214,7 @@ Open `http://127.0.0.1:5174`.
```bash
npm run dev # Local development server with Vite middleware
npm start # Production server using dist/
npm run cli -- --help # Local CLI usage
npm run build # Type-check and build production assets
npm run typecheck # TypeScript checks
npm run typecheck:strict # TypeScript checks including unused-code detection
Expand All @@ -190,6 +239,7 @@ OPENCOMPRESS_USER_AGENT=OpenCompress-Studio/2.1.0

```text
OpenCompress/
├─ bin/ Local CLI preview
├─ src/ React UI
├─ server/ Local Express + Sharp processing API
├─ docs/ Repository media and documentation
Expand All @@ -203,6 +253,7 @@ OpenCompress/

Good next contributions include:

- CLI parity for Auto Best and target-size mode
- Real per-file streaming progress
- Drag-and-drop file sorting
- AVIF export
Expand Down
67 changes: 60 additions & 7 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# OpenCompress Studio 2.1.0

OpenCompress Studio 2.1.0 turns the project into a more complete local-first batch image workflow for shops, creators and automation.

## Highlights

- Private-by-default local compression with Sharp.
- Batch workflow for up to 250 images in the GUI.
- Auto Best local mode for comparing multiple local output candidates.
- Target file-size mode for JPG/WebP output.
- Before/after preview, candidate comparison and detailed savings.
- Shop-focused presets, SEO batch rename and ZIP export.
- New local-only CLI preview for scripts, CI jobs and large folders.

## Added

- Auto Best local mode that tests multiple local output candidates and keeps the smallest result.
Expand All @@ -13,16 +25,57 @@
- Candidate comparison panel for Auto Best and Auto Compare results.
- Expanded results table with format, dimensions, quality, method, status and warnings.
- More specific shop/image presets.
- Local CLI preview with file/folder input, recursive scanning, WebP/JPG/PNG output, quality, resize, JSON summaries and keep-original-if-larger behavior.
- GitHub contribution, security, issue and pull-request templates.
- Dependabot configuration and stronger CI checks.

## Fixed and hardened

- Fresh Windows clones now build before starting production mode.
- Invalid job IDs can no longer collapse to the jobs root during deletion.
- Target-size compression now works when preferred quality is below 35.
- Duplicate filenames map to the correct active preview item.
- Upload count and malformed settings errors return clearer API responses.
- Result downloads use streaming file responses instead of unnecessary whole-file buffering.
- reSmush.it requests now have bounded timeouts and HTTPS result validation.
- Numeric environment settings are validated and bounded.
- CLI image processing is smoke-tested in GitHub Actions with a generated image fixture.

## Changed

- Local compression now reports original and output dimensions/formats.
- Local compression reports original and output dimensions/formats.
- Auto Compare can run in a fair mode with no resize, original format and matching quality.
- ZIP report now includes settings and detailed result metadata.
- README updated for the V2.1 workflow.
- ZIP report includes settings and detailed result metadata.
- README now explains privacy modes, CLI usage and workflow positioning versus Squoosh and TinyPNG/TinyJPG without synthetic benchmark claims.
- Supported Node.js versions are aligned across documentation, launcher and CI.

## CLI preview

```bash
npm ci
npm run cli -- ./images --format webp --quality 82 --max-width 1600 -o ./optimized
```

Run `npm run cli -- --help` for all options. The CLI is local-only in 2.1.0; Auto Best, target-size search and reSmush.it remain GUI-only.

## Privacy notes

- Local only, Auto Best local and CLI modes do not upload images externally.
- reSmush.it remains optional and is used only when explicitly selected in the GUI.
- Temporary GUI jobs live under `.opencompress/` and expire automatically.

## Requirements

- Node.js 20.19+ or 22.12+
- npm 10+

## Install

## Notes
```bash
git clone https://github.com/SLP-DEV1/OpenCompress.git
cd OpenCompress
npm ci
npm run dev
```

- reSmush.it remains optional and uploads selected files to an external API only when explicitly selected.
- Local only and Auto Best local modes do not upload images externally.
- `node_modules/`, `dist/` and `.opencompress/` are excluded from the release package.
Windows users can also run `start.bat` after installing a supported Node.js version.
Loading
Loading