Git Product home page Git Product logo

ipx's Introduction

🖼️ IPX

npm version npm downloads

Note

This is the active branch for IPX v2. Check out ipx/v1 for v1 docs.

High performance, secure and easy-to-use image optimizer powered by sharp and svgo.

Used by Nuxt Image and Netlify and open to everyone!

Using CLI

You can use ipx command to start server.

Using npx:

npx ipx serve --dir ./

Usin bun

bun x npx ipx serve --dir ./

The default serve directory is the current working directory.

Programatic API

You can use IPX as a middleware or directly use IPX interface.

import { createIPX, ipxFSStorage, ipxHttpStorage } from "ipx";

const ipx = createIPX({
  storage: ipxFSStorage({ dir: "./public" }),
  httpStorage: ipxHttpStorage({ domains: ["picsum.photos"] }),
});

Example: Using with unjs/h3:

import { listen } from "listhen";
import { createApp, toNodeListener } from "h3";
import {
  createIPX,
  ipxFSStorage,
  ipxHttpStorage,
  createIPXH3Handler,
} from "ipx";

const ipx = createIPX({
  storage: ipxFSStorage({ dir: "./public" }),
  httpStorage: ipxHttpStorage({ domains: ["picsum.photos"] }),
});

const app = createApp().use("/", createIPXH3Handler(ipx));

listen(toNodeListener(app));

Example: Using express:

import { listen } from "listhen";
import express from "express";
import {
  createIPX,
  ipxFSStorage,
  ipxHttpStorage,
  createIPXNodeServer,
} from "ipx";

const ipx = createIPX({
  storage: ipxFSStorage({ dir: "./public" }),
  httpStorage: ipxHttpStorage({ domains: ["picsum.photos"] }),
});

const app = express().use("/", createIPXNodeServer(ipx));

listen(app);

URL Examples

Get original image:

/_/static/buffalo.png

Change format to webp and keep other things same as source:

/f_webp/static/buffalo.png

Keep original format (png) and set width to 200:

/w_200/static/buffalo.png

Resize to 200x200px using embed method and change format to webp:

/embed,f_webp,s_200x200/static/buffalo.png

Config

You can universally customize IPX configuration using IPX_* environment variables.

  • IPX_ALIAS

    • Default: {}

Filesystem Source Options

(enabled by default with CLI only)

IPX_FS_DIR

  • Default: . (current working directory)

IPX_FS_MAX_AGE

  • Default: 300

HTTP(s) Source Options

(enabled by default with CLI only)

IPX_HTTP_DOMAINS

  • Default: []

IPX_HTTP_MAX_AGE

  • Default: 300

IPX_HTTP_FETCH_OPTIONS

  • Default: {}

IPX_HTTP_ALLOW_ALL_DOMAINS

  • Default: false

Modifiers

Property Docs Example Comments
width / w Docs /width_200/buffalo.png
height / h Docs /height_200/buffalo.png
resize / s Docs /s_200x200/buffalo.png
kernel Docs /s_200x200,kernel_nearest/buffalo.png Supported kernel: nearest, cubic, mitchell, lanczos2 and lanczos3 (default).
fit Docs /s_200x200,fit_outside/buffalo.png Sets fit option for resize.
position / pos Docs /s_200x200,pos_top/buffalo.png Sets position option for resize.
trim Docs /trim_100/buffalo.png
extend Docs /extend_{top}_{right}_{bottom}_{left}/buffalo.png Extend / pad / extrude one or more edges of the image with either the provided background colour or pixels derived from the image.
background / b _ /r_45,b_00ff00/buffalo.png
extract Docs /extract_{left}_{top}_{width}_{height}/buffalo.png Extract/crop a region of the image.
format / f Docs /format_webp/buffalo.png Supported format: jpg, jpeg, png, webp, avif, gif, heif, tiff and auto (experimental only with middleware)
quality / q _ /quality_50/buffalo.png Accepted values: 0 to 100
rotate Docs /rotate_45/buffalo.png
enlarge _ /enlarge,s_2000x2000/buffalo.png Allow the image to be upscaled. By default the returned image will never be larger than the source in any dimension, while preserving the requested aspect ratio.
flip Docs /flip/buffalo.png
flop Docs /flop/buffalo.png
sharpen Docs /sharpen_30/buffalo.png
median Docs /median_10/buffalo.png
blur Docs /blur_5/buffalo.png
gamma Docs /gamma_3/buffalo.png
negate Docs /negate/buffalo.png
normalize Docs /normalize/buffalo.png
threshold Docs /threshold_10/buffalo.png
tint Docs /tint_1098123/buffalo.png
grayscale Docs /grayscale/buffalo.png
animated - /animated/buffalo.gif Experimental

License

MIT

ipx's People

Contributors

aaharu avatar aareksio avatar ahmett avatar ascorbic avatar atinux avatar autofix-ci[bot] avatar bobbiegoede avatar carlo697 avatar clemcode avatar danielroe avatar farnabaz avatar jameswragg avatar jarrku avatar kyranet avatar lexpeartha avatar nozomuikuta avatar oritwoen avatar pi0 avatar renovate-bot avatar renovate[bot] avatar sethfalco avatar st4ng avatar stafyniaksacha avatar szafran89 avatar thomorlo avatar thornwalli avatar ucw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ipx's Issues

Persist processed images for specific predefined sizes & formats

Describe the feature

The idea is to persist images that will be consumed a lot so the server doesn't need to reprocess it on each time.

If we are concerned about bloating server storage, we can think of a method to auto delete images that is not used in a specified timeframe (implemented as an option).

Additional information

  • Would you be willing to help implement this feature?

Support for multiple source folders?

Describe the feature

Hello.

There seems to be a use case in Nuxt Image to support multiple source folders, for example nuxt /content and nuxt /assets:

https://twitter.com/mrblot4/status/1649513803745206277

Do you think it would be better to handle this in IPX or Nuxt Image?

I'd be happy to handle any PRs if they fit with the spirit of the library.

Cheers,
Dave

Additional information

  • Would you be willing to help implement this feature?

iiif compatibility

Namaste.
IIIF or International Image Interoperability Framework is ubiquitous api standard for image proxying. It's widespread in humanities, heritage institutions, libraries, so on. Have many high quality tools like mirador, universal viewer, open-sea-dragon with deep zoom view, so on.
It will be great if support is added for iiif-image api.
It should be straight forward to implement.

"Invalid URL" error on domains like: http.cat

Hey! I believe this issue is meant to be here because I tried digging through the source of @nuxt/image-which led to nothing, and I found out that whatever is parsing the new URL() API from our @nuxt/image config.domains throws an Invalid URL error whenever the domain begins with a protocol-like string. For example, I use http.cat for my error pages and put a funny cat status there. After upgrading the image module today, I saw my app wasn't starting because of this error and I started digging, after 20 minutes of searching through compiled .cjs source files, I believe this issue is directly related to your module ipx and its createIPX middleware. Not sure though. But my code works right before that method is called. I also tried digging your source but couldn't find where my domain options reach. I will keep digging and will update this issue if I find more details. I hope this gets fixed.

image

AVIF support

Describe the feature

Hello, do you plan to support AVIF?

Additional information

  • Would you be willing to help implement this feature?

Pluggable sources

Do you have any plans to make sources pluggable?

I want to use other sources, like the S3, Cloud Storage, etc.
But it's needed to folk and add logic to Init sources and getSrc.

IPX `fetchOptions` and `async` token

Hello,

I'm writing again because of the fetchOptions option.

I run into the problem that I need to asynchronously retrieve an auth token, and using nuxt/image and a custom ipx middleware I have no way to generate an actual token on demand or update it.

Meaning in the current state, I can create a token once, and at some point restart the instance.

An alternative would be a proxy middleware, but in this case I run into the fixed IPX options to the alias. The problem here is the random port of Nuxt generate, I would need this in the alias. Finally the IPX can address the proxy to solve the auth problem.

@pi0 Do you have an idea?

Support squoosh

squoosh is a wasm alternative to sharp. While sharp is much faster and supporting modern formats, it has its own downsides:

  • NodeJS dependency. Cannot be used in environments like Deno or Cloudflare workers
  • Native dependency. This reduces the portability of the library. Both bundle distribution and target-machine (if there is no pre-built version for a specific node version, installation requires building with node-gyp) (example nuxt/image#204)

We can keep sharp as an opt-in dependency and install/use squoosh by default. This needs a refactor for handlers to create a shared interface. (as a result, we lose some existing features)

Note: squoosh api seems is not released on npm nor documented! We might use/redistribute http://npmjs.com/package/@squoosh/cli, inspire and inline source similar to vercel/next.js#22253, or publish as squoosh.
Related: GoogleChromeLabs/squoosh#934 / GoogleChromeLabs/squoosh#1002 (PR depends on NodeJS API like worker_threads therefore removing first point)

IPX crashes with ERR_INVALID_CHAR

Steps to reproduce:

  1. Start IPX, npx ipx
  2. Submit a request such as GET /test/%00, or GET /test/%01, etc
  3. IPX crashes with error:
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

TypeError [ERR_INVALID_CHAR]: Invalid character in statusMessage
    at new NodeError (node:internal/errors:363:5)
    at ServerResponse.writeHead (node:_http_server:323:11)
    at ServerResponse._implicitHeader (node:_http_server:266:8)
    at write_ (node:_http_outgoing:764:9)
    at ServerResponse.end (node:_http_outgoing:853:5)
    at /ipxissue/node_modules/ipx/dist/cli.js:543:11 {
  code: 'ERR_INVALID_CHAR'
}

This is impacting nuxt/image and thus any apps using it.
I haven't had a chance to review IPX's source; will look tomorrow and submit a PR if I can get to the bottom of it.

DeprecationWarning: response.buffer() require update

Error:
(node:43925) [node-fetch#buffer] DeprecationWarning: Please use 'response.arrayBuffer()' instead of 'response.buffer()' 09:03:53
(Use node --trace-deprecation ... to show where the warning was created)

Node:
v17.8.0

This dependency generate warning:

"ohmyfetch": "^0.4.15",

In it:
https://github.com/unjs/ohmyfetch/blob/26641a4405826de6281e357bdd665df692d0f340/package.json#L47

Where fix require apply and test:

getData: cachedPromise(() => response.buffer())

Show after Node upgrade

Ability to change the modifiers' separator

Modifiers' separator is hardcoded as comma. This might be a problem in <picture> tag where comma-separated list can be used in source's srcset to define list of possible images based on size.

Problematic code:

<picture>
	<source srcset="http://localhost:3000/embed,f_webp,s_200x200/static/buffalo.png" type="image/webp">
	<img src="http://localhost:3000/s_200x200/static/buffalo.png">
</picture>

The line <source srcset="http://localhost:3000/embed,f_webp,s_200x200/static/buffalo.png" type="image/webp"> is actually read by browsers like 3 different URLs:

  1. http://localhost:3000/embed
  2. f_webp
  3. s_200x200/static/buffalo.png

Suggestion:

Introduce new env variable IPX_SEPARATOR.

Change this line

for (const p of modifiersStr.split(',')) {
to something like this:

  // Read modifiers from first segment
  if (modifiersStr !== '_') {
    for (const p of modifiersStr.split(getEnv('IPX_SEPARATOR', ','))) {
      const [key, value = ''] = p.split('_')
      modifiers[key] = decode(value)
    }
  }

Note:

URL encoded comma %2C won't help in this case.

I'm more than happy to make a PR if you find this solution suitable and wanted.

Support `withoutEnlargement` resizing option

It would be useful to support the withoutEnlargement option. Auto-generated srcsets often contain very large sizes, but can gracefully handle smaller sizes if those are returned instead, saving bandwidth and processor time.

This could either be a modifier in the URL or an option passed to the constructor. I'm happy to open a PR if there is a decision on the API.

Can't use ipx in serverMiddleware with @nuxt/bridge

When adding /server/middleware/ipx.js to nuxt.config.js (as indicated at https://image.nuxtjs.org/providers/ipx/#advanced-custom-servermiddleware) while using @nuxt/bridge...

import { createIPX, createIPXMiddleware } from 'ipx'
const ipx = createIPX({
  dir: '',
  domains: [],
  alias: {},
  sharp: {},
})
export default createIPXMiddleware(ipx)

it results in an error:

 WARN  [worker] Named export 'stat' not found. The requested module 'fs-extra' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'fs-extra';
const { stat, readFile } = pkg;


  import { stat, readFile } from 'fs-extra';
  ^^^^
  SyntaxError: Named export 'stat' not found. The requested module 'fs-extra' is a CommonJS module, which may not support all module.exports as named exports.
  CommonJS modules can always be imported via the default export, for example using:

  import pkg from 'fs-extra';
  const { stat, readFile } = pkg;

  at ModuleJob._instantiate (internal/modules/esm/module_job.js:121:21)
  at async ModuleJob.run (internal/modules/esm/module_job.js:166:5)
  at async Loader.import (internal/modules/esm/loader.js:178:24)
  at async Object.loadESM (internal/process/esm_loader.js:68:5)

Background modifier is not working

The background modifier doesn't seem to work, here are the URLs I tried :

/img/1.jpeg?fit=contain&s=300_100&b=FF0000
/img/1.jpeg?fit=contain&s=300_100&background=FF0000
/img/1.jpeg?fit=contain&s=300_100&bg=FF0000

Etag from request header and generate problem

I have problem when working with ipx etag.
I read ipx repository and it support etag but it not working as expected.
I explored that etag from request header and etag are different when generated

Please check it

image

image

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

github-actions
.github/workflows/autofix.yml
  • actions/checkout v4
  • actions/setup-node v4
  • autofix-ci/action ea32e3a12414e6d3183163c3424a7d7a8631ad84
.github/workflows/ci.yml
  • actions/checkout v4@0ad4b8fadaa221de15dcec353f45205ec38ea70b
  • actions/setup-node v4
  • codecov/codecov-action v4
npm
package.json
  • @fastify/accept-negotiator ^1.1.0
  • citty ^0.1.6
  • consola ^3.2.3
  • defu ^6.1.4
  • destr ^2.0.3
  • etag ^1.8.1
  • h3 ^1.11.1
  • image-meta ^0.2.0
  • listhen ^1.7.2
  • ofetch ^1.3.4
  • pathe ^1.1.2
  • sharp ^0.33.3
  • svgo ^3.2.0
  • ufo ^1.5.3
  • unstorage ^1.10.2
  • xss ^1.0.15
  • @types/etag ^1.8.3
  • @types/is-valid-path ^0.1.2
  • @vitest/coverage-v8 ^1.5.2
  • changelogen ^0.5.5
  • eslint ^8.57.0
  • eslint-config-unjs ^0.2.1
  • jiti ^1.21.0
  • prettier ^3.2.5
  • serve-handler ^6.1.5
  • typescript ^5.4.5
  • unbuild ^2.0.0
  • vitest ^1.5.2
  • pnpm 9.0.6

  • Check this box to trigger a request for Renovate to run again on this repository

Support aspect-ratio resizing

Could there be any upsides with implementing a solution that forces image to be resized at a certain aspect-ratio?

e.g.: aspect-ratio prop and focal-point prop

[v2] apply quality without resizing

The nuxt image module uses ipx to provide the image processing endpoint and it passes through a quality option like q=65 in the url. From what I can tell this is ignored at the ipx end. Is it possible to use this to tell sharp to resize/process at a specific quality level?

Support auto-rotation based on EXIF data

If sharp's rotate() function is called without arguments then it will try to automatically rotate the image based on exif data. ipx currently doesn't support this, and can only do explicit rotation. It would be good if it either allowed rotate to be called without an angle, or if auto-rotation was the default (which would be my suggestion)

Error upgrading to v0.9.1: Segmentation fault (core dumped)

I get this error when calling the ipx endpoint using version 0.9.1 together with the nuxtjs image module as a custom middleware . 0.8.0 worked fine without any problems.

Segmentation fault (core dumped)
npm ERR! code ELIFECYCLE
npm ERR! errno 139
npm ERR! lcr@ dev: `nuxt`
npm ERR! Exit status 139
npm ERR! 
npm ERR! Failed at the lcr@ dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/niklas/.npm/_logs/2021-11-13T13_51_21_220Z-debug.log

debug.log

0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'run', 'dev' ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'predev', 'dev', 'postdev' ]
5 info lifecycle lcr@~predev: lcr@
6 info lifecycle lcr@~dev: lcr@
7 verbose lifecycle lcr@~dev: unsafe-perm in lifecycle true
8 verbose lifecycle lcr@~dev: PATH: /usr/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/home/niklas/code/www/node_modules/.bin:/home/niklas/.sdkman/candidates/maven/current/bin:/home/niklas/.sdkman/candidates/java/current/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/niklas/.bin:/home/niklas/.bin
9 verbose lifecycle lcr@~dev: CWD: /home/niklas/code/www
10 silly lifecycle lcr@~dev: Args: [ '-c', 'nuxt' ]
11 silly lifecycle lcr@~dev: Returned: code: 139  signal: null
12 info lifecycle lcr@~dev: Failed to exec dev script
13 verbose stack Error: lcr@ dev: `nuxt`
13 verbose stack Exit status 139
13 verbose stack     at EventEmitter.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:332:16)
13 verbose stack     at EventEmitter.emit (events.js:400:28)
13 verbose stack     at ChildProcess.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack     at ChildProcess.emit (events.js:400:28)
13 verbose stack     at maybeClose (internal/child_process.js:1058:16)
13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:293:5)
14 verbose pkgid lcr@
15 verbose cwd /home/niklas/code/www
16 verbose Linux 5.8.0-63-generic
17 verbose argv "/usr/bin/node" "/usr/bin/npm" "run" "dev"
18 verbose node v14.18.1
19 verbose npm  v6.14.15
20 error code ELIFECYCLE
21 error errno 139
22 error lcr@ dev: `nuxt`
22 error Exit status 139
23 error Failed at the lcr@ dev script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 139, true ]

Support image optimization

sharp supports several features that can optimize the filesize of output images. These can give significant improvements, but can be very expensive operations so should not be the default. The options are palette for png, and a number of options for jpeg that are enabled with the mozjpeg option.

IPX Forbidden error V0.7.2

I'm using nuxt/image with the custom IPX Server middleware and always get an IPX Forbidden error although the domain is set in

const ipx = createIPX({
  domains: ['...'],
})

As soon as I downgrade to 0.6.7 everything is working fine. Was there a bigger change since 0.6.7?

persistent cache

Support abstract persistent cache for both input source and converted images. (implies supporting ttl)

Related: #46

Support local cache for http sources

It would be good if this could support a local cache for files loaded over HTTP. Ideally it could save the ETag too. Most environments have some form of cache available, even serverless functions which can use /tmp.

Add content aware image cropping

Describe the feature

At first I'd just like to say that you guys did a very good job with the project! :)

I'm lacking one feature from ipx that prevents me from moving to it completely and that is content aware image cropping. While doing research on the topic, I've stumbled upon https://github.com/jwagner/smartcrop-sharp. It's a working library that provides just that. Maybe it's a good starting point?

Additional information

  • Would you be willing to help implement this feature?

heic support

Describe the feature

sharp and libvips do support heic

can you add it's support too?

Additional information

  • Would you be willing to help implement this feature?

Add a possibility to pass a fallback image url to the options

In my project, I need to get images via ipx, and if there is no such image, I would love to get some placeholder that I would have specified in options. So, is there any way to add such a thing, so the initialization would look like

import { createIPX, createIPXMiddleware } from "ipx";

const ipx = createIPX({
  /* other options */
  fallbackUrl: '/path/to/the/image.png'
});
const app = express();
app.use("/image", createIPXMiddleware(ipx));

Or is there already a way I could handle such 404 errors myself?

Auto-detect animated sources

Currently, if you want animated output you need to specifically choose it. It would be good if animated webp input images could automatically generate animated output. I'm not sure what the overhead would be of just passing animated to the sharp constructor every time.

Set options for https.Agent

Anybody knows how can i set https.Agent options like "rejectUnauthorized" and "timeout" in IPXOptions{fetchOptions}? Agent creates in /src/sources/http.ts in function createHTTPSource.

v0.9.0 install error

I got error when installing latest 0.9.0 version, 0.8.0 works fine

npm ERR! code ENOENT
npm ERR! syscall chmod
npm ERR! path **/node_modules/ipx/dist/cli.js
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, chmod '**/node_modules/ipx/dist/cli.js'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.