mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-04-16 23:32:01 +03:00
rename jxl -> jpegxl
This commit is contained in:
parent
6048520fcf
commit
8fa280f6a5
|
@ -4,7 +4,7 @@ import re
|
|||
|
||||
import pytest
|
||||
|
||||
from PIL import Image, JxlImagePlugin, features
|
||||
from PIL import Image, JpegXlImagePlugin, features
|
||||
|
||||
from .helper import (
|
||||
assert_image_similar_tofile,
|
||||
|
@ -12,39 +12,38 @@ from .helper import (
|
|||
)
|
||||
|
||||
try:
|
||||
from PIL import _jxl
|
||||
from PIL import _jpegxl
|
||||
|
||||
HAVE_JXL = True
|
||||
HAVE_JPEGXL = True
|
||||
except ImportError:
|
||||
HAVE_JXL = False
|
||||
HAVE_JPEGXL = False
|
||||
|
||||
# cjxl v0.9.2 41b8cdab
|
||||
# hopper.jxl: cjxl hopper.png hopper.jxl -q 75 -e 8
|
||||
|
||||
|
||||
class TestUnsupportedJxl:
|
||||
class TestUnsupportedJpegXl:
|
||||
def test_unsupported(self) -> None:
|
||||
if HAVE_JXL:
|
||||
JxlImagePlugin.SUPPORTED = False
|
||||
if HAVE_JPEGXL:
|
||||
JpegXlImagePlugin.SUPPORTED = False
|
||||
|
||||
file_path = "Tests/images/hopper.jxl"
|
||||
with pytest.warns(UserWarning):
|
||||
with pytest.raises(OSError):
|
||||
with Image.open(file_path):
|
||||
pass
|
||||
with pytest.raises(OSError):
|
||||
with Image.open(file_path):
|
||||
pass
|
||||
|
||||
if HAVE_JXL:
|
||||
JxlImagePlugin.SUPPORTED = True
|
||||
if HAVE_JPEGXL:
|
||||
JpegXlImagePlugin.SUPPORTED = True
|
||||
|
||||
|
||||
@skip_unless_feature("jxl")
|
||||
class TestFileJxl:
|
||||
@skip_unless_feature("jpegxl")
|
||||
class TestFileJpegXl:
|
||||
def setup_method(self) -> None:
|
||||
self.rgb_mode = "RGB"
|
||||
|
||||
def test_version(self) -> None:
|
||||
_jxl.JxlDecoderVersion()
|
||||
assert re.search(r"\d+\.\d+\.\d+$", features.version_module("jxl"))
|
||||
_jpegxl.JpegXlDecoderVersion()
|
||||
assert re.search(r"\d+\.\d+\.\d+$", features.version_module("jpegxl"))
|
||||
|
||||
def test_read_rgb(self) -> None:
|
||||
"""
|
||||
|
@ -63,10 +62,10 @@ class TestFileJxl:
|
|||
# djxl hopper.jxl hopper_jxl_bits.ppm
|
||||
assert_image_similar_tofile(image, "Tests/images/hopper_jxl_bits.ppm", 1.0)
|
||||
|
||||
def test_JxlDecode_with_invalid_args(self) -> None:
|
||||
def test_JpegXlDecode_with_invalid_args(self) -> None:
|
||||
"""
|
||||
Calling decoder functions with no arguments should result in an error.
|
||||
"""
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
_jxl.PILJxlDecoder()
|
||||
_jpegxl.PILJpegXlDecoder()
|
||||
|
|
|
@ -6,7 +6,7 @@ from PIL import Image
|
|||
|
||||
from .helper import assert_image_similar_tofile
|
||||
|
||||
_webp = pytest.importorskip("PIL._jxl", reason="JXL support not installed")
|
||||
_jpegxl = pytest.importorskip("PIL._jpegxl", reason="JPEG XL support not installed")
|
||||
|
||||
|
||||
def test_read_rgba() -> None:
|
||||
|
|
|
@ -10,7 +10,7 @@ from .helper import (
|
|||
)
|
||||
|
||||
pytestmark = [
|
||||
skip_unless_feature("jxl"),
|
||||
skip_unless_feature("jpegxl"),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ from PIL import Image
|
|||
from .helper import skip_unless_feature
|
||||
|
||||
pytestmark = [
|
||||
skip_unless_feature("jxl"),
|
||||
skip_unless_feature("jpegxl"),
|
||||
]
|
||||
|
||||
ElementTree: ModuleType | None
|
||||
|
|
|
@ -9,8 +9,8 @@ from .helper import PillowLeakTestCase, skip_unless_feature
|
|||
TEST_FILE = "Tests/images/hopper.jxl"
|
||||
|
||||
|
||||
@skip_unless_feature("jxl")
|
||||
class TestJxlLeaks(PillowLeakTestCase):
|
||||
@skip_unless_feature("jpegxl")
|
||||
class TestJpegXlLeaks(PillowLeakTestCase):
|
||||
mem_limit = 6 * 1024 # kb
|
||||
iterations = 1000
|
||||
|
||||
|
|
20
setup.py
20
setup.py
|
@ -286,7 +286,7 @@ class pil_build_ext(build_ext):
|
|||
features = [
|
||||
"zlib",
|
||||
"jpeg",
|
||||
"jxl",
|
||||
"jpegxl",
|
||||
"tiff",
|
||||
"freetype",
|
||||
"raqm",
|
||||
|
@ -695,13 +695,13 @@ class pil_build_ext(build_ext):
|
|||
feature.jpeg2000 = "openjp2"
|
||||
feature.openjpeg_version = ".".join(str(x) for x in best_version)
|
||||
|
||||
if feature.want("jxl"):
|
||||
_dbg("Looking for jxl")
|
||||
if feature.want("jpegxl"):
|
||||
_dbg("Looking for jpegxl")
|
||||
if _find_include_file(self, "jxl/encode.h") and _find_include_file(
|
||||
self, "jxl/decode.h"
|
||||
):
|
||||
if _find_library_file(self, "jxl"):
|
||||
feature.jxl = "jxl jxl_threads"
|
||||
feature.jpegxl = "jxl jxl_threads"
|
||||
|
||||
if feature.want("imagequant"):
|
||||
_dbg("Looking for imagequant")
|
||||
|
@ -786,14 +786,14 @@ class pil_build_ext(build_ext):
|
|||
# alternate Windows name.
|
||||
feature.lcms = "lcms2_static"
|
||||
|
||||
if feature.jxl:
|
||||
if feature.jpegxl:
|
||||
# jxl and jxl_threads are required
|
||||
libs = feature.jxl.split()
|
||||
libs = feature.jpegxl.split()
|
||||
defs = []
|
||||
|
||||
self._update_extension("PIL._jxl", libs, defs)
|
||||
self._update_extension("PIL._jpegxl", libs, defs)
|
||||
else:
|
||||
self._remove_extension("PIL._jxl")
|
||||
self._remove_extension("PIL._jpegxl")
|
||||
|
||||
if feature.want("webp"):
|
||||
_dbg("Looking for webp")
|
||||
|
@ -955,7 +955,7 @@ class pil_build_ext(build_ext):
|
|||
(feature.freetype, "FREETYPE2"),
|
||||
(feature.raqm, "RAQM (Text shaping)", raqm_extra_info),
|
||||
(feature.lcms, "LITTLECMS2"),
|
||||
(feature.jxl, "JXL"),
|
||||
(feature.jpegxl, "JPEG XL"),
|
||||
(feature.webp, "WEBP"),
|
||||
(feature.webpmux, "WEBPMUX"),
|
||||
(feature.xcb, "XCB (X protocol)"),
|
||||
|
@ -1000,7 +1000,7 @@ ext_modules = [
|
|||
Extension("PIL._imaging", files),
|
||||
Extension("PIL._imagingft", ["src/_imagingft.c"]),
|
||||
Extension("PIL._imagingcms", ["src/_imagingcms.c"]),
|
||||
Extension("PIL._jxl", ["src/_jxl.c"]),
|
||||
Extension("PIL._jpegxl", ["src/_jpegxl.c"]),
|
||||
Extension("PIL._webp", ["src/_webp.c"]),
|
||||
Extension("PIL._imagingtk", ["src/_imagingtk.c", "src/Tk/tkImaging.c"]),
|
||||
Extension("PIL._imagingmath", ["src/_imagingmath.c"]),
|
||||
|
|
|
@ -6,7 +6,7 @@ from io import BytesIO
|
|||
from . import Image, ImageFile
|
||||
|
||||
try:
|
||||
from . import _jxl
|
||||
from . import _jpegxl
|
||||
|
||||
SUPPORTED = True
|
||||
except ImportError:
|
||||
|
@ -33,14 +33,14 @@ def _accept(prefix: bytes) -> bool:
|
|||
return is_jxl
|
||||
|
||||
|
||||
class JxlImageFile(ImageFile.ImageFile):
|
||||
class JpegXlImageFile(ImageFile.ImageFile):
|
||||
format = "JPEG XL"
|
||||
format_description = "JPEG XL image"
|
||||
__loaded = 0
|
||||
__logical_frame = 0
|
||||
|
||||
def _open(self) -> None:
|
||||
self._decoder = _jxl.PILJxlDecoder(self.fp.read())
|
||||
self._decoder = _jpegxl.PILJpegXlDecoder(self.fp.read())
|
||||
|
||||
width, height, mode, has_anim, tps_num, tps_denom, n_loops, n_frames = (
|
||||
self._decoder.get_info()
|
||||
|
@ -174,6 +174,6 @@ class JxlImageFile(ImageFile.ImageFile):
|
|||
return self.__logical_frame
|
||||
|
||||
|
||||
Image.register_open(JxlImageFile.format, JxlImageFile, _accept)
|
||||
Image.register_extension(JxlImageFile.format, ".jxl")
|
||||
Image.register_mime(JxlImageFile.format, "image/jxl")
|
||||
Image.register_open(JpegXlImageFile.format, JpegXlImageFile, _accept)
|
||||
Image.register_extension(JpegXlImageFile.format, ".jxl")
|
||||
Image.register_mime(JpegXlImageFile.format, "image/jxl")
|
|
@ -47,7 +47,7 @@ _plugins = [
|
|||
"IptcImagePlugin",
|
||||
"JpegImagePlugin",
|
||||
"Jpeg2KImagePlugin",
|
||||
"JxlImagePlugin",
|
||||
"JpegXlImagePlugin",
|
||||
"McIdasImagePlugin",
|
||||
"MicImagePlugin",
|
||||
"MpegImagePlugin",
|
||||
|
|
|
@ -14,7 +14,7 @@ modules = {
|
|||
"tkinter": ("PIL._tkinter_finder", "tk_version"),
|
||||
"freetype2": ("PIL._imagingft", "freetype2_version"),
|
||||
"littlecms2": ("PIL._imagingcms", "littlecms_version"),
|
||||
"jxl": ("PIL._jxl", "libjxl_version"),
|
||||
"jpegxl": ("PIL._jpegxl", "libjxl_version"),
|
||||
"webp": ("PIL._webp", "webpdecoder_version"),
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ def pilinfo(out=None, supported_formats=True):
|
|||
("transp_webp", "WEBP Transparency"),
|
||||
("webp_mux", "WEBPMUX"),
|
||||
("webp_anim", "WEBP Animation"),
|
||||
("jxl", "JPEG XL"),
|
||||
("jpegxl", "JPEG XL"),
|
||||
("jpg", "JPEG"),
|
||||
("jpg_2000", "OPENJPEG (JPEG2000)"),
|
||||
("zlib", "ZLIB (PNG/ZIP)"),
|
||||
|
|
|
@ -83,13 +83,13 @@ typedef struct {
|
|||
Py_ssize_t n_frames;
|
||||
|
||||
char *mode;
|
||||
} PILJxlDecoderObject;
|
||||
} PILJpegXlDecoderObject;
|
||||
|
||||
static PyTypeObject PILJxlDecoder_Type;
|
||||
static PyTypeObject PILJpegXlDecoder_Type;
|
||||
|
||||
void
|
||||
_jxl_decoder_dealloc(PyObject *self) {
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
|
||||
if (decp->jxl_data) {
|
||||
free(decp->jxl_data);
|
||||
|
@ -131,7 +131,7 @@ _jxl_decoder_dealloc(PyObject *self) {
|
|||
// sets input jxl bitstream loaded into jxl_data
|
||||
// has to be called after every rewind
|
||||
void _jxl_decoder_set_input(PyObject *self) {
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
|
||||
decp->status = JxlDecoderSetInput(decp->decoder, decp->jxl_data,
|
||||
decp->jxl_data_len);
|
||||
|
@ -144,7 +144,7 @@ void _jxl_decoder_set_input(PyObject *self) {
|
|||
PyObject *
|
||||
_jxl_decoder_rewind(PyObject *self) {
|
||||
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
JxlDecoderRewind(decp->decoder);
|
||||
Py_RETURN_NONE;
|
||||
|
||||
|
@ -152,7 +152,7 @@ _jxl_decoder_rewind(PyObject *self) {
|
|||
|
||||
bool
|
||||
_jxl_decoder_count_frames(PyObject *self) {
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
|
||||
decp->n_frames = 0;
|
||||
|
||||
|
@ -179,8 +179,8 @@ PyObject *
|
|||
_jxl_decoder_new(PyObject *self, PyObject *args) {
|
||||
PyBytesObject *jxl_string;
|
||||
|
||||
PILJxlDecoderObject *decp = NULL;
|
||||
decp = PyObject_New(PILJxlDecoderObject, &PILJxlDecoder_Type);
|
||||
PILJpegXlDecoderObject *decp = NULL;
|
||||
decp = PyObject_New(PILJpegXlDecoderObject, &PILJpegXlDecoder_Type);
|
||||
decp->mode = NULL;
|
||||
decp->jxl_data = NULL;
|
||||
decp->jxl_data_len = 0;
|
||||
|
@ -202,7 +202,7 @@ _jxl_decoder_new(PyObject *self, PyObject *args) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// this data needs to be copied to PILJxlDecoderObject
|
||||
// this data needs to be copied to PILJpegXlDecoderObject
|
||||
// so that input bitstream is preserved across calls
|
||||
const uint8_t *_tmp_jxl_data;
|
||||
Py_ssize_t _tmp_jxl_data_len;
|
||||
|
@ -393,7 +393,7 @@ _jxl_decoder_new(PyObject *self, PyObject *args) {
|
|||
|
||||
PyObject *
|
||||
_jxl_decoder_get_info(PyObject *self) {
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
|
||||
return Py_BuildValue(
|
||||
"IIsiIIII",
|
||||
|
@ -411,7 +411,7 @@ _jxl_decoder_get_info(PyObject *self) {
|
|||
PyObject *
|
||||
_jxl_decoder_get_next(PyObject *self) {
|
||||
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
PyObject *bytes;
|
||||
PyObject *ret;
|
||||
JxlFrameHeader fhdr = {};
|
||||
|
@ -500,7 +500,7 @@ _jxl_decoder_get_next(PyObject *self) {
|
|||
|
||||
PyObject *
|
||||
_jxl_decoder_get_icc(PyObject *self) {
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
|
||||
if (!decp->jxl_icc) Py_RETURN_NONE;
|
||||
|
||||
|
@ -509,7 +509,7 @@ _jxl_decoder_get_icc(PyObject *self) {
|
|||
|
||||
PyObject *
|
||||
_jxl_decoder_get_exif(PyObject *self) {
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
|
||||
if (!decp->jxl_exif) Py_RETURN_NONE;
|
||||
|
||||
|
@ -518,15 +518,15 @@ _jxl_decoder_get_exif(PyObject *self) {
|
|||
|
||||
PyObject *
|
||||
_jxl_decoder_get_xmp(PyObject *self) {
|
||||
PILJxlDecoderObject *decp = (PILJxlDecoderObject *)self;
|
||||
PILJpegXlDecoderObject *decp = (PILJpegXlDecoderObject *)self;
|
||||
|
||||
if (!decp->jxl_xmp) Py_RETURN_NONE;
|
||||
|
||||
return PyBytes_FromStringAndSize((const char *)decp->jxl_xmp, decp->jxl_xmp_len);
|
||||
}
|
||||
|
||||
// PILJxlDecoder methods
|
||||
static struct PyMethodDef _jxl_decoder_methods[] = {
|
||||
// PILJpegXlDecoder methods
|
||||
static struct PyMethodDef _jpegxl_decoder_methods[] = {
|
||||
{"get_info", (PyCFunction)_jxl_decoder_get_info, METH_NOARGS, "get_info"},
|
||||
{"get_next", (PyCFunction)_jxl_decoder_get_next, METH_NOARGS, "get_next"},
|
||||
{"get_icc", (PyCFunction)_jxl_decoder_get_icc, METH_NOARGS, "get_icc"},
|
||||
|
@ -536,10 +536,10 @@ static struct PyMethodDef _jxl_decoder_methods[] = {
|
|||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
// PILJxlDecoder type definition
|
||||
static PyTypeObject PILJxlDecoder_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "PILJxlDecoder", /*tp_name */
|
||||
sizeof(PILJxlDecoderObject), /*tp_basicsize */
|
||||
// PILJpegXlDecoder type definition
|
||||
static PyTypeObject PILJpegXlDecoder_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "PILJpegXlDecoder", /*tp_name */
|
||||
sizeof(PILJpegXlDecoderObject), /*tp_basicsize */
|
||||
0, /*tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)_jxl_decoder_dealloc, /*tp_dealloc*/
|
||||
|
@ -565,7 +565,7 @@ static PyTypeObject PILJxlDecoder_Type = {
|
|||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
_jxl_decoder_methods, /*tp_methods*/
|
||||
_jpegxl_decoder_methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
};
|
||||
|
@ -573,13 +573,13 @@ static PyTypeObject PILJxlDecoder_Type = {
|
|||
// Return libjxl decoder version available as integer:
|
||||
// MAJ*1_000_000 + MIN*1_000 + PATCH
|
||||
PyObject *
|
||||
JxlDecoderVersion_wrapper() {
|
||||
JpegXlDecoderVersion_wrapper() {
|
||||
return Py_BuildValue("i", JxlDecoderVersion());
|
||||
}
|
||||
|
||||
// Version as string
|
||||
const char *
|
||||
JxlDecoderVersion_str(void) {
|
||||
JpegXlDecoderVersion_str(void) {
|
||||
static char version[20];
|
||||
int version_number = JxlDecoderVersion();
|
||||
sprintf(
|
||||
|
@ -592,22 +592,22 @@ JxlDecoderVersion_str(void) {
|
|||
return version;
|
||||
}
|
||||
|
||||
static PyMethodDef jxlMethods[] = {
|
||||
{"JxlDecoderVersion", JxlDecoderVersion_wrapper, METH_NOARGS, "JxlVersion"},
|
||||
{"PILJxlDecoder", _jxl_decoder_new, METH_VARARGS, "PILJxlDecoder"},
|
||||
static PyMethodDef jpegxlMethods[] = {
|
||||
{"JpegXlDecoderVersion", JpegXlDecoderVersion_wrapper, METH_NOARGS, "JpegXlVersion"},
|
||||
{"PILJpegXlDecoder", _jxl_decoder_new, METH_VARARGS, "PILJpegXlDecoder"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static int
|
||||
setup_module(PyObject *m) {
|
||||
if (PyType_Ready(&PILJxlDecoder_Type) < 0) {
|
||||
if (PyType_Ready(&PILJpegXlDecoder_Type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO(oloke) ready object types?
|
||||
PyObject *d = PyModule_GetDict(m);
|
||||
|
||||
PyObject *v = PyUnicode_FromString(JxlDecoderVersion_str());
|
||||
PyObject *v = PyUnicode_FromString(JpegXlDecoderVersion_str());
|
||||
PyDict_SetItemString(d, "libjxl_version", v ? v : Py_None);
|
||||
Py_XDECREF(v);
|
||||
|
||||
|
@ -615,15 +615,15 @@ setup_module(PyObject *m) {
|
|||
}
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit__jxl(void) {
|
||||
PyInit__jpegxl(void) {
|
||||
PyObject *m;
|
||||
|
||||
static PyModuleDef module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_jxl", /* m_name */
|
||||
"_jpegxl", /* m_name */
|
||||
NULL, /* m_doc */
|
||||
-1, /* m_size */
|
||||
jxlMethods, /* m_methods */
|
||||
jpegxlMethods, /* m_methods */
|
||||
};
|
||||
|
||||
m = PyModule_Create(&module_def);
|
Loading…
Reference in New Issue
Block a user