Giter VIP home page Giter VIP logo

transformimgs's Introduction

logo

TransformImgs

Go Reference Go Report Card Build Status codecov Docker Pulls Docker Automated build

Open Source Image CDN that provides image transformation API and supports the latest image formats, such as WebP, AVIF, Jpeg XL, and network client hints.

Table of Contents

Why?

We wrote a big blog on this, and here is TLDR:

Transformimgs is an image CDN for Web, so API must cover typical use cases, like thumbnails, zoom in product images, etc. Any new API endpoints must solve the above problems.

The goal is to have zero-config API that makes decisions based on the input, so you don't need to provide additional parameters like quality, output format, type of compression, etc.

Therefore, this allows you to configure the integration once. New features, like new image formats, will work with your front end automatically without any changes.

To achieve that goal we should keep API to bare minimum and hide the smartness in the implementation.

Features

  • Resize/optimises/crops raster (PNG and JPEG) images.
  • JpegXL / AVIF / WebP support based on "Accept" header.
  • Vary header support - ready to deploy behind any CDN.
  • Responsive images support including high DPI (retina) displays
  • Save-Data support

Quickstart

There is an example of running API behind reverse proxy with integration example in quickstart/ folder.

To run:

cd quickstart
docker-compose up
open https://localhost

API

The API has 4 HTTP endpoints:

  • /img/{IMG_URL}/optimise - optimises image
  • /img/{IMG_URL}/resize - resizes image
  • /img/{IMG_URL}/fit - resize image to the exact size by resizing and cropping it
  • /img/{IMG_URL}/asis - returns original image

Docs:

  • Swagger-UI - use API key MjUyMTM3OTQyNw__ which allows to transform any image from unsplash.com
  • OpenAPI spec

Running Locally

Docker

The latest docker image published on Docker hub

Starting the server:

$ docker run -p 8080:8080 pixboost/transformimgs [OPTIONS]

To verify:

  • Health check: curl http://localhost:8080/health
  • Transformation: open http://localhost:8080/img/https://images.unsplash.com/photo-1591769225440-811ad7d6eab3/resize?size=600

Options

Everything below is optional and have sensible defaults.

Option Description Default
cache Number of seconds to cache image(0 to disable cache). Used in max-age HTTP response. 2592000 (30 days)
proc Number of images processors to run. Number of CPUs (cores)
disableSaveData If set to true then will disable Save-Data client hint. Should be disabled on CDNs that don't support Save-Data header in Vary. false

Running from source code

Prerequisites:

$ git clone [email protected]:Pixboost/transformimgs.git
$ cd transformimgs
$ ./run.sh 

Using from Go Web Application

You could also easily plugin HTTP route into your existing web application using service.GetRouter method. Here is a quick example of how to do that.

SaaS

We run SaaS version at pixboost.com with generous free tier.

Perks of SaaS version:

  • CDN with HTTP/3 support included
  • Dashboard with usage monitor
  • API Key support with domains allow list
  • AWS S3 integration
  • API workflows for cache busting and warmup
  • Version upgrades

Go modules have been introduced in v6.

Performance tests

There is a JMeter performance test you can run against a service. To run tests:

  • Start a performance test environment:
$ docker-compose -f docker-compose-perf.yml up
  • Run JMeter tests:
$ jmeter -n -t perf-test.jmx -l ./results.jmx -e -o ./results
  • Run JMeter WebP test:
$ jmeter -n -t perf-test-webp.jmx -l ./results-webp.jmx -e -o ./results-webp
  • Run JMeter AVIF test:
$ jmeter -n -t perf-test-avif.jmx -l ./results-avif.jmx -e -o ./results-avif
  • Run JMeter JPEG XL test:
$ jmeter -n -t perf-test-jxl.jmx -l ./results-jxl.jmx -e -o ./results-jxl

Opened tickets for images related features

Contribute

Shout out with any ideas. PRs are more than welcome.

License

MIT

Todo

  • Add JpegXR support (IE supports WEBP)
  • Add Jpeg 2000 support (Safari support WEBP)
  • Client Hints - on hold due to browsers adoption
  • Save-Data header (Added in version 7.0.0)
  • SVG support
  • Consider using Zopfli or Brotli for PNGs
  • JpegXL Support since supported by Safari 17 (Added in version 8.12.0)
  • GIF support (Added in version 6.1.0)

transformimgs's People

Contributors

dooman87 avatar snyk-bot 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

transformimgs's Issues

Add an option to trim image border

The use case:

  • You need to display bunch of logos provided by 3rd parties and they don't align because they all have different transparent borders

DPI support in API

Press Release (not implemented yet):

There is a new feature in open source Image CDN to better support screens with DPI > 1.

Here is the blog post inspiration for the feature: https://jakearchibald.com/2021/serving-sharp-images-to-high-density-screens/

Current State

Currently, there is no support for DPI on API level, and developers use <img> tag with different source sets, e.g.

<img src="https://yourwebsite/image.jpg" srcset="
                https://yourwebsite/image.jpg/resize?size=300 300w,
                https://yourwebsite/image.jpg/resize?size=400 400w,
                https://yourwebsite/image.jpg/resize?size=500 500w,
                https://yourwebsite/image.jpg/resize?size=600 600w,
                https://yourwebsite/image.jpg/resize?size=1200 1200w,
                https://yourwebsite/image.jpg/optimise 2400w"
                alt="image" 
                sizes="(min-width: 768px) 200px,
                            600px" 
                width="2400" height="2400">

In the example above we provide sources for different sizes, so a web browser can pick the correct one based on the image size in the viewport, screen DPI and possible other factors.

For instance, if we load the image on mobile device on the screen witth DPI = 3, then the web browser will load 600px variant (3 * 200). On the other hand if we load the same image on desktop with DPI = 1 and the display image width is 600px then the browser will pick the same variant - 600 * 1 = 600px

This approach has performance drawbacks:

  • We cap the maximum width to 2x, so if we deal with screens where DPI > 2 (Samsung Galaxy S6 dpi is 4, for example) we would load an image with maximum width x2
  • When DPI is high, we use lower quality of the result image

To address above limitations we introduced new query parameter ?dpi that you can use with <picture> tag.

New API

There is a new query parameter dpi that accepts float number value, e.g. 1.5, 2, 3.4.

Examples:

  • https://yourwebsite/image.jpg/resize?size=300&dpi=2
  • https://yourwebsite/image.jpg/resize?size=300&dpi=3.5

Using in HTML

The ?dpi query parameter is best used with the picture element where you can pass screen dpi using -webkit-min-device-pixel-ratio media query

<picture>
  <source
      media="(-webkit-min-device-pixel-ratio: 2)"
      src="https://yourwebsite/image.jpg/optimise?dpi=2"
      srcset="
                https://yourwebsite/image.jpg/resize?size=300&dpi=2 300w,
                https://yourwebsite/image.jpg/resize?size=400&dpi=2 400w,
                https://yourwebsite/image.jpg/resize?size=500&dpi=2 500w,
                https://yourwebsite/image.jpg/resize?size=600&dpi=2 600w,
                https://yourwebsite/image.jpg/resize?size=1200&dpi=2 1200w,
                https://yourwebsite/image.jpg/resize?size=1800&dpi=2 1800w,
                https://yourwebsite/image.jpg/optimise?dpi=2 2400w"
      sizes="(min-width: 768px) 200px,
             600px"
  >
  <source
      media="(-webkit-min-device-pixel-ratio: 3)"
      src="https://yourwebsite/image.jpg/optimise?dpi=3"
      srcset="
                https://yourwebsite/image.jpg/resize?size=300&dpi=3 300w,
                https://yourwebsite/image.jpg/resize?size=400&dpi=3 400w,
                https://yourwebsite/image.jpg/resize?size=500&dpi=3 500w,
                https://yourwebsite/image.jpg/resize?size=600&dpi=3 600w,
                https://yourwebsite/image.jpg/resize?size=1200&dpi=3 1200w,
                https://yourwebsite/image.jpg/resize?size=1800&dpi=3 1800w,
                https://yourwebsite/image.jpg/optimise?dpi=3 2400w"
      sizes="(min-width: 768px) 200px,
             600px"
  >
  <img
      src="https://yourwebsite/image.jpg/optimise"
      srcset="
                https://yourwebsite/image.jpg/resize?size=300 300w,
                https://yourwebsite/image.jpg/resize?size=400 400w,
                https://yourwebsite/image.jpg/resize?size=500 500w,
                https://yourwebsite/image.jpg/resize?size=600 600w,
                https://yourwebsite/image.jpg/resize?size=1200 1200w,
                https://yourwebsite/image.jpg/resize?size=1800 1800w,
                https://yourwebsite/image.jpg/optimise 2400w"
      alt="image"
      sizes="(min-width: 768px) 200px,
             600px"
      width="2400" height="2400"
  >
</picture>

Cache input and result image?

Is there currently a plan to support cache storage for input/output images to reduce processing time? We can save produced AVIF/Webp or other optimized/filtered images in a local storage for future use when client sends same/similar requirements. Or is this done in the proxy/CDN layer?

Save-Data header support

Add a configuration flag to reduce quality of the resulting images when Save-Data header is on.

Consideration:

  • Client side control, e.g. add a query param to turn on/off quality reduction for specific images or return empty images?

HTTP Header Description
Can I Use

Browsers Implementation Tickets:

Do transparency intelligently

Understand how PNG's alpha channels and tRNS chunk work. If the alpha mask is binary (that is, either fully transparent or fully opaque), see if the transparent parts correspond to a single color or gray shade; if so, eliminate the alpha channel from the PNG file and use the tRNS chunk (cheap transparency'') instead. Alternatively, see if the total number of color+alpha combinations is 256 or fewer; if so, write a colormapped image with a tRNS chunk. If the user requests that an RGBA image be converted to indexed color, do so intelligently. The combination of PNG's PLTE and tRNS chunks amounts to a palette whose entries are RGBA values. The exact same algorithms that quantize and dither a 24-bit RGB image down to an 8-bit palette-based image can be used to quantize and dither a 32-bit RGBA or 16-bit grayscale+alpha image down to an 8-bit RGBA palette. In particular, you cannot treat color values and transparency values as if they are separate, unrelated entities; attempting to partition the palette into a color part'' and a transparent part'' makes no more sense than attempting to partition a standard RGB palette into red, green, and blue parts. If you do cheap transparency poorly, the user will be forced to use a full alpha channel, quadrupling her file size. For grayscale, an alpha channel merely'' doubles the size. Note that the icicle image in Figure C-1 in the color insert is actually colormapped. Aside from the garish background--which was actually generated by the viewing application--the full-resolution half looks pretty darned good, doesn't it?

PDF support?

Does this application support PDFs as a possible upload media?

I saw that PNGs / JPEGs can be resized, so maybe PDFs are not supported...

Apologies if this was answered online somewhere, I tried to find the answer in the issues and google, but failed...

Clients Hints Support

IMO, the main use of the feature would be using relative images sizing (vw, %) combined with Width client hint which then won't require setting different sizes for different breakpoints.

From the quick look on things there is not much value on implementing with only Chrome supporting it.

Can I Use

Tickets to track in the other browsers:

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.