sharp icon indicating copy to clipboard operation
sharp copied to clipboard

Metadata: expose `chromaSubsampling` for AVIF

Open tats-u opened this issue 2 years ago • 2 comments

Possible bug

Is this a possible bug in a feature of sharp, unrelated to installation?

  • [x] Running npm install sharp completes without error.
  • [x] Running node -e "require('sharp')" completes without error.

If you cannot confirm both of these, please open an installation issue instead.

Are you using the latest version of sharp?

  • [x] I am using the latest version of sharp as reported by npm view sharp dist-tags.latest.

If you cannot confirm this, please upgrade to the latest version and try again before opening an issue.

If you are using another package which depends on a version of sharp that is not the latest, please open an issue against that package instead.

What is the output of running npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp?

  System:
    OS: Windows 10 10.0.22621
    CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
    Memory: 11.85 GB / 31.68 GB
  Binaries:
    Node: 18.14.0 - ~\scoop\apps\volta\current\appdata\tools\image\node\18.14.0\node.EXE
    Yarn: 1.22.19 - ~\scoop\apps\volta\current\appdata\tools\image\yarn\1.22.19\bin\yarn.CMD
    npm: 9.3.1 - ~\scoop\apps\volta\current\appdata\tools\image\node\18.14.0\npm.CMD
  npmPackages:
    sharp: ^0.31.3 => 0.31.3

What are the steps to reproduce?

  • put JS below and put images at the same directory
  • Run the JS
  • Check the output

What is the expected behaviour?

await sharp("./image.avif").metadata()
await sharp("./lossy.webp").metadata()

should include chromaSubsampling field like JPEG. That of Lossy WebPs is always "4:2:0". Most AVIF use YUV (4:2:0 or 4:4:4).

Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem

import sharp from "sharp";
import YAML from "yaml";

/**
 * @param type {string}
 * @param img {import("sharp").Sharp}
 */

async function printMeta(type, img) {
  const { icc: _icc, iptc: _iptc, ...meta } = await img.metadata();

  console.log(`${type} meta:\n\n${YAML.stringify(meta)}`);
}

await printMeta("AVIF", sharp("./avif.avif"));
await printMeta("WebP", sharp("./webp.webp"));

Please provide sample image(s) that help explain this problem

  • https://e-port.co.jp/wp/wp-content/uploads/b83a40e6b68e9e09c7318f59899df563.jpg.webp
  • https://cdn.glitch.com/f4525b23-4268-473b-a57c-bdb57f3f7494%2FIMG_5666.avif?v=1599083333763 (from https://avif-support-test.glitch.me/)

tats-u avatar Mar 07 '23 15:03 tats-u

For AVIF, libheif exposes subsampling metadata via get_image_chroma_from_configuration but we'd need to add support for this to libvips first. There might be some complexity around different chroma subsampling for alpha vs non-alpha channels.

A libvips PR to expose this would be welcome, if you're able.

For WebP, libwebp does not expose metadata about whether subsampling (a.k.a. "sharp_yuv") was used at compression time, so there's not a lot we can do here (I suspect it will be buried somewhere in the compressed bitstream).

lovell avatar Mar 07 '23 16:03 lovell

we'd need to add support for this to libvips first.

I see.

For WebP, libwebp does not expose metadata about whether subsampling (a.k.a. "sharp_yuv") was used at compression time

4:2:0 for ALL lossy WebP whether sharp YUV is used or not unlike JPEG or AVIF. Lossless ones use a different algorithm.

tats-u avatar Mar 08 '23 09:03 tats-u