Skip to content

Commit

Permalink
add 16-bits grayscale support for jpeg xl images
Browse files Browse the repository at this point in the history
  • Loading branch information
olokelo committed May 18, 2024
1 parent 0b71605 commit 1f00fb8
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 1 deletion.
Binary file added Tests/images/jxl/16bit_subcutaneous.cropped.jxl
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions Tests/test_file_jxl.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

# cjxl v0.9.2 41b8cdab
# hopper.jxl: cjxl hopper.png hopper.jxl -q 75 -e 8
# 16_bit_binary.jxl: cjxl 16_bit_binary.pgm 16_bit_binary.jxl -q 100 -e 9


class TestUnsupportedJpegXl:
Expand All @@ -40,6 +41,7 @@ def test_unsupported(self) -> None:
class TestFileJpegXl:
def setup_method(self) -> None:
self.rgb_mode = "RGB"
self.i16_mode = "I;16"

def test_version(self) -> None:
_jpegxl.JpegXlDecoderVersion()
Expand All @@ -62,6 +64,20 @@ def test_read_rgb(self) -> None:
# djxl hopper.jxl hopper_jxl_bits.ppm
assert_image_similar_tofile(image, "Tests/images/hopper_jxl_bits.ppm", 1.0)

def test_read_i16(self) -> None:
"""
Can we read 16-bit Grayscale Jpeg XL image?
"""

with Image.open("Tests/images/jxl/16bit_subcutaneous.cropped.jxl") as image:
assert image.mode == self.i16_mode
assert image.size == (128, 64)
assert image.format == "JPEG XL"
image.load()
image.getdata()

assert_image_similar_tofile(image, "Tests/images/jxl/16bit_subcutaneous.cropped.png", 1.0)

def test_JpegXlDecode_with_invalid_args(self) -> None:
"""
Calling decoder functions with no arguments should result in an error.
Expand Down
9 changes: 8 additions & 1 deletion src/_jpegxl.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ void _pil_jxl_get_pixel_format(JxlPixelFormat *pf, const JxlBasicInfo *bi) {
// TODO: floating point mode
char* _pil_jxl_get_mode(const JxlBasicInfo *bi) {

// 16-bit single channel images are supported
if (bi->bits_per_sample == 16 && bi->num_color_channels == 1 &&
bi->alpha_bits == 0 && !bi->alpha_premultiplied
) return "I;16";

// PIL doesn't support high bit depth images
// it will throw an exception but that's for your own good
// you wouldn't want to see distorted image
Expand Down Expand Up @@ -261,7 +266,9 @@ _jxl_decoder_new(PyObject *self, PyObject *args) {
_PIL_JXL_CHECK("JxlDecoderGetBasicInfo");

_pil_jxl_get_pixel_format(&decp->pixel_format, &decp->basic_info);
if (decp->pixel_format.data_type != JXL_TYPE_UINT8) {
if (decp->pixel_format.data_type != JXL_TYPE_UINT8 &&
decp->pixel_format.data_type != JXL_TYPE_UINT16) {

// only 8 bit integer value images are supported for now
PyErr_SetString(PyExc_NotImplementedError,
"unsupported pixel data type");
Expand Down

0 comments on commit 1f00fb8

Please sign in to comment.