IT Cooking

Success is just one script away

ComfyUI: Install Python JPEG-XL Support for Windows

6 min read
You cannot compile jxlpy wheel JPEG-XL for Python on Windows. Hopefully, there is an easy alternative: imagecodecs.
jpeg xl featured meme

jpeg xl featured meme

You cannot compile jxlpy wheel JPEG-XL for Python on Windows. Hopefully, there is an easy alternative: imagecodecs. You likely will never be able to compile jxlpy wheel on Windows. It’s such a niche, no one even ever tried: no information anywhere.

JPEG-XL: Install imagecodecs

Use an alternative project that embeds JXL: imagecodecs. Paired will the Pillow plugin, all is included!

pip install -U imagecodecs pillow pillow-jxl-plugin

And that’s it! To enable it in Python:

import pillow_jxl
# PIL must be loaded after pillow plugins
from PIL import Image, ExifTags
from PIL.PngImagePlugin import PngInfo

 

What version of libjxl is included in imagecodecs ?

# Import the JPEGXL codec:
from imagecodecs import (jpegxl_encode, jpegxl_decode, jpegxl_check, jpegxl_version, JPEGXL)

# Check that the JPEGXL codec is available in the imagecodecs build:
JPEGXL.available
# True

# Print the version of the JPEGXL codec’s underlying OpenJPEG library:
jpeg2k_version()
# 'libjxl 0.9.0'

 

WIP: Try to Install jxlpy with pip

Below is a work in progress I started to get jxlpy wheel compiled on Windows. Impossible is my conclusion, but here are some starters if you want to follow through:

pip install jxlpy

You will get this error:

Collecting jxlpy
  Using cached jxlpy-0.9.5.tar.gz (107 kB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
ERROR: Exception:
Traceback (most recent call last):
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\cli\base_command.py", line 180, in exc_logging_wrapper
    status = run_func(*args)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\cli\req_command.py", line 245, in wrapper
    return func(self, options, args)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\commands\install.py", line 377, in run
    requirement_set = resolver.resolve(
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\resolver.py", line 95, in resolve
    result = self._result = resolver.resolve(
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_vendor\resolvelib\resolvers.py", line 546, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_vendor\resolvelib\resolvers.py", line 397, in resolve
    self._add_to_criteria(self.state.criteria, r, parent=None)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_vendor\resolvelib\resolvers.py", line 173, in _add_to_criteria
    if not criterion.candidates:
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_vendor\resolvelib\structs.py", line 156, in __bool__
    return bool(self._sequence)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 155, in __bool__
    return any(self)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 143, in <genexpr>
    return (c for c in iterator if id(c) not in self._incompatible_ids)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 47, in _iter_built
    candidate = func()
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\factory.py", line 182, in _make_candidate_from_link
    base: Optional[BaseCandidate] = self._make_base_candidate_from_link(
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\factory.py", line 228, in _make_base_candidate_from_link
    self._link_candidate_cache[link] = LinkCandidate(
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 290, in __init__
    super().__init__(
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 156, in __init__
    self.dist = self._prepare()
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 222, in _prepare
    dist = self._prepare_distribution()
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 301, in _prepare_distribution
    return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\operations\prepare.py", line 525, in prepare_linked_requirement
    return self._prepare_linked_requirement(req, parallel_builds)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\operations\prepare.py", line 640, in _prepare_linked_requirement
    dist = _get_prepared_distribution(
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\operations\prepare.py", line 71, in _get_prepared_distribution
    abstract_dist.prepare_distribution_metadata(
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\distributions\sdist.py", line 54, in prepare_distribution_metadata
    self._install_build_reqs(finder)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\distributions\sdist.py", line 124, in _install_build_reqs
    build_reqs = self._get_build_requires_wheel()
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\distributions\sdist.py", line 101, in _get_build_requires_wheel
    return backend.get_requires_for_build_wheel()
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_internal\utils\misc.py", line 745, in get_requires_for_build_wheel
    return super().get_requires_for_build_wheel(config_settings=cs)
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_vendor\pyproject_hooks\_impl.py", line 166, in get_requires_for_build_wheel
    return self._call_hook('get_requires_for_build_wheel', {
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_vendor\pyproject_hooks\_impl.py", line 321, in _call_hook
    raise BackendUnavailable(data.get('traceback', ''))
pip._vendor.pyproject_hooks._impl.BackendUnavailable: Traceback (most recent call last):
  File "E:\GPT\sd.webui\system\python\lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 77, in _build_backend
    obj = import_module(mod_path)
  File "importlib\__init__.py", line 126, in import_module
 File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 992, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 883, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "C:\users\eric\pip-build-env-b0uzs8cl\overlay\Lib\site-packages\setuptools\__init__.py", line 8, in <module>
import _distutils_hack.override # noqa: F401
File "E:\GPT\sd.webui\system\python\lib\site-packages\_distutils_hack\override.py", line 1, in <module>
__import__('_distutils_hack').do_override()
File "E:\GPT\sd.webui\system\python\lib\site-packages\_distutils_hack\__init__.py", line 70, in do_override
ensure_local_distutils()
File "E:\GPT\sd.webui\system\python\lib\site-packages\_distutils_hack\__init__.py", line 56, in ensure_local_distutils
core = importlib.import_module('distutils.core')
File "importlib\__init__.py", line 126, in import_module
File "C:\users\eric\pip-build-env-b0uzs8cl\overlay\Lib\site-packages\setuptools\_distutils\core.py", line 14, in <module>
from .config import PyPIRCCommand
File "C:\users\eric\pip-build-env-b0uzs8cl\overlay\Lib\site-packages\setuptools\_distutils\config.py", line 7, in <module>
import email.message
File "email\message.py", line 15, in <module>
File "email\utils.py", line 29, in <module>
File "socket.py", line 51, in <module>

Requisite 1: Make sure pip is upgraded

python.exe -m pip install --upgrade pip

Now, install extra requirements:

pip install -U setuptools wheel Cython pillow auditwheel 

Requisite 2: Make sure MSVC VisualStudio2022 is Accessible

If your MSVC installation is custom, don’t forget to add it to your PATH. Adapt the paths below to your environment:

set VisualStudio2022=E:\GPT\VisualStudio\2022\BuildTools\VC\Tools\MSVC\14.38.33130\bin\Hostx64\x64;E:\GPT\VisualStudio\2022\BuildTools\Common7\IDE\VC\VCPackages;E:\GPT\VisualStudio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\TestWindow;E:\GPT\VisualStudio\2022\BuildTools\MSBuild\Current\bin\Roslyn;E:\GPT\VisualStudio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin;E:\GPT\VisualStudio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja;E:\GPT\VisualStudio\2022\BuildTools\Common7\IDE\VC\Linux\bin\ConnectionManagerExe
set PATH=%PATH%;%VisualStudio2022%

Solution: follow official jxlpy instructions and compile it

jxlpy · PyPI instructions clearly state that libjxl is Alhpa, has bugs, and may need to be compiled locally. Actually, if you read the very need for libjxl, it clearly states that this won’t be installed via pip. therefore, follow the strings:

  • jxlpy · PyPI tells you to install libjxl first
  • libjxl tells you to download the libjxl Windopws binaries from the releases page 
  • download jxl-x64-windows-static.zip and extract it where you store your portable binaries
    • add the path in your PATH so it’s accessible anywhere. example:
    • set PATH=E:\wintools\multimedia\jxl-x64-windows-static;%PATH% or edit your user/system PATH via systempropertiesadvanced

Now, test it by creating a JPEG-XL file:

cjxl input.png output.jxl

JPEG XL encoder v0.10.2 e148959 [AVX2,SSE2]
Encoding [VarDCT, d1.000, effort: 7]
Compressed to 62018 bytes (1.893 bpp).
512 x 512,  6.208 MP/s [6.21, 6.21], , 1 reps, 8 threads.

Now, clone and compile jxlpy:

git clone https://github.com/olokelo/jxlpy
cd jxlpy
pip wheel .

You will likely get the same error as before.

If anyone finds out how do do this, please let me know.

Alternative to jxlpy:

Alternative to jxlpy: pyvips

TO DO: test this one too: GitHub – libvips/pyvips: python binding for libvips using cffi

 

Leave a Reply

Your email address will not be published. Required fields are marked *