akash-akya / vix

Elixir extension for libvips
MIT License
172 stars 20 forks source link

precompiled: HEIC support not working? #175

Open feld opened 1 week ago

feld commented 1 week ago

I'm seeing this on MacOS and Linux with 0.31.1

iex(3)> Vix.Vips.Image.supported_saver_suffixes()
{:ok,
 [".avif", ".heif", ".heic", ".tiff", ".tif", ".webp", ".jfif", ".jpe", ".jpeg",
  ".jpg", ".png", ".szi", ".dz", ".gif", ".vips", ".v", ".raw", ".mat", ".csv"]}

ok, look like support should be there.

iex(4)> {:ok, image} = Vix.Vips.Image.new_from_file("test/fixtures/image.heic")
iex(5)> Vix.Vips.Image.write_to_stream(image, ".jpg") |> Stream.into(File.stream!("./out.jpeg")) |> Stream.run
** (Vix.Vips.Image.Error) Failed to write to target
    (vix 0.31.1) lib/vix/vips/image.ex:583: anonymous fn/1 in Vix.Vips.Image.write_to_stream/2
    (elixir 1.14.5) lib/stream.ex:1625: Stream.do_resource/5
    (elixir 1.14.5) lib/stream.ex:584: Stream.do_into/4
    (elixir 1.14.5) lib/stream.ex:689: Stream.run/1
    iex:5: (file)

Fails?

On FreeBSD when I am forced to compile against the system provided vips library:

iex(4)> {:ok, image} = Vix.Vips.Image.new_from_file("test/fixtures/image.heic")
{:ok, %Vix.Vips.Image{ref: #Reference<0.1910391208.3904503840.259935>}}
iex(5)> Vix.Vips.Image.write_to_stream(image, ".jpg") |> Stream.into(File.stream!("./out.jpeg")) |> Stream.run
:ok
> file out.jpeg
out.jpeg: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=5, orientation=upper-left, xresolution=74, yresolution=82, resolutionunit=2], baseline, precision 8, 700x476, components 3

So, it worked here on FreeBSD.

Annoyingly on MacOS (homebrew) and Debian, libvips does not come linked against libheif so that adds a big hurdle to working around this 😭

akash-akya commented 1 week ago

@feld is it possible to share the image? Prebuilt binaries does support AVIF images in HEIF container I think. If the image is of HEVC compression then it wont work.

Main reason why it is not bundled with the prebuilt binaries (and with platform packages) is that patent licensing around HEVC/x265 seems to be messy.

You can check the compression by

{:ok, img} = Vix.Vips.Image.new_from_file(path)
Vix.Vips.Image.header_value(img, "heif-compression")
feld commented 1 week ago

Yeah, it's just a basic test file we use

tempImage4xwyni

edit: if github mangled this, here's a link from our repo

https://git.pleroma.social/pleroma/pleroma/-/blob/feat/vips-heif-upload-filter/test/fixtures/image.heic?ref_type=heads

feld commented 1 week ago
iex(1)> {:ok, img} = Vix.Vips.Image.new_from_file("test/fixtures/image.heic")
{:ok, %Vix.Vips.Image{ref: #Reference<0.267671389.4215406613.43045>}}
iex(2)> Vix.Vips.Image.header_value(img, "heif-compression")
{:ok, "hevc"}

you're right about it being HEVC... now the question is, what does Apple normally use? Time to find a sample

feld commented 1 week ago

The files I'm finding from iMessages from friends which are HEIC format also report as HEVC...

I see in the FreeBSD project we're shipping libheif with HEVC enabled. In 2020 we stopped restricting things like LAME encoder with this note:

Patents are a complicated topic, and their regulation varies depending on
jurisdiction. Patents  are not necessarily related to the license and so
should not be connected to the license framework.

As a project we will officially remove all patent limitations within the
ports tree and leave it to the user or consumer to deal with their local
legislation to determine if they can use the software without legal
restrictions.

Approved by:    core

I don't know what to say other than I hope you reconsider and can ship full HEIC/HEIF support as it would make working with this format a lot easier.

feld commented 1 week ago

I was just thinking about this again and I think a reasonable solution may be to make it possible to self-host the Pre-compiled NIF, perhaps by setting an ENV that is obeyed at build time?

akash-akya commented 1 week ago

Perhaps I can make a nix flake with dependencies. User can use that to install libvips and then configure vix to use platform provided libvips. Then again, I might not be actively maintaining it, it will be like a path to install libvips. Ideally the nix flake should work with both Macos & Linux. Does that help?

akash-akya commented 1 week ago

possible to self-host the Pre-compiled NIF

That would be hard. I am using cc_precompiler to handle NIF pre-compilation and it heavily depends on the current package. We basically have to rewrite all that logic to support this type of usecase.