From 03c42f9e0a6d2a2f38a8a88835ebed73cc379a79 Mon Sep 17 00:00:00 2001 From: Alexander Piskun Date: Sun, 3 Jul 2022 18:34:44 +0300 Subject: [PATCH] converting & saving `16` bits to `12` bits --- pillow_heif/_options.py | 13 +- pillow_heif/heif.py | 7 +- pillow_heif/helpers.c | 258 ++++++++++++++++++++++++++++++++-------- pillow_heif/helpers.h | 48 +++++--- pillow_heif/private.py | 211 ++++---------------------------- 5 files changed, 280 insertions(+), 257 deletions(-) diff --git a/pillow_heif/_options.py b/pillow_heif/_options.py index 0482b4d0..098f3abf 100644 --- a/pillow_heif/_options.py +++ b/pillow_heif/_options.py @@ -89,11 +89,21 @@ def ctx_in_memory(self) -> bool: def ctx_in_memory(self, value): self._cfg["ctx_in_memory"] = value + @property + def save_to_12bit(self) -> bool: + """Should 16 bit images be saved to 12 bit instead of 10. Default = ``False``""" + + return self._cfg["save_to_12bit"] + + @save_to_12bit.setter + def save_to_12bit(self, value): + self._cfg["save_to_12bit"] = value + def update(self, **kwargs) -> None: """Method for at once update multiply values in config.""" _keys = kwargs.keys() - for k in ("avif", "strict", "thumbnails", "quality", "ctx_in_memory"): + for k in ("avif", "strict", "thumbnails", "quality", "ctx_in_memory", "save_to_12bit"): if k in _keys: setattr(self, k, kwargs[k]) @@ -105,6 +115,7 @@ def reset(self) -> None: self._cfg["thumbnails"] = True self._cfg["quality"] = None self._cfg["ctx_in_memory"] = True + self._cfg["save_to_12bit"] = False CFG_OPTIONS: PyLibHeifOptions = PyLibHeifOptions() diff --git a/pillow_heif/heif.py b/pillow_heif/heif.py index b7e78a90..d0006d82 100644 --- a/pillow_heif/heif.py +++ b/pillow_heif/heif.py @@ -62,6 +62,8 @@ def __init__(self, heif_ctx: Union[LibHeifCtx, HeifCtxAsDict], handle, for_encod self.mode = heif_ctx.mode if heif_ctx.data: new_mode = MODE_INFO[self.mode][4] if for_encoding else None + if isinstance(new_mode, tuple): + new_mode = new_mode[1] if options().save_to_12bit else new_mode[0] _img = self._create_image(heif_ctx.data, heif_ctx.stride, new_mode) self._img_to_img_data_dict(_img) @@ -224,11 +226,12 @@ def _create_image(self, src_data, src_stride: int, new_mode=None): p_dest_stride = ffi.new("int *") dest_data = lib.heif_image_get_plane(new_img, self._channel(), p_dest_stride) dest_stride = p_dest_stride[0] + src_data = ffi.from_buffer(src_data) if new_mode and new_mode != self.mode: - MODE_CONVERT[self.mode][new_mode](dest_data, src_data, dest_stride, src_stride, height) + MODE_CONVERT[self.mode][new_mode](src_data, src_stride, dest_data, dest_stride, height) self.mode = new_mode else: - lib.copy_image_data(ffi.from_buffer(src_data), src_stride, dest_data, dest_stride, height) + lib.copy_image_data(src_data, src_stride, dest_data, dest_stride, height) return new_img def _get_pure_data(self): diff --git a/pillow_heif/helpers.c b/pillow_heif/helpers.c index 400ab04a..1e10b361 100644 --- a/pillow_heif/helpers.c +++ b/pillow_heif/helpers.c @@ -14,10 +14,13 @@ void copy_image_data(const uint8_t *in, int in_stride, uint8_t *out, int out_str } } -void convert_i16_to_i10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_i16_to_i10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) out_row[i2] = in_row[i2] >> 6; @@ -26,10 +29,29 @@ void convert_i16_to_i10(const uint16_t *in, int in_stride, uint16_t *out, int ou } } -void convert_bgr16_to_rgb10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_i16_to_i12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + for (int i = 0; i < n_rows; i++) { + for (int i2 = 0; i2 < stride_elements; i2++) + out_row[i2] = in_row[i2] >> 4; + in_row += in_stride; + out_row += out_stride; + } +} + +void convert_bgr16_to_rgb10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) +{ + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 2] >> 6; @@ -41,10 +63,14 @@ void convert_bgr16_to_rgb10(const uint16_t *in, int in_stride, uint16_t *out, in } } -void convert_bgra16_to_rgba10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_bgra16_to_rgba10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 2] >> 6; @@ -57,10 +83,14 @@ void convert_bgra16_to_rgba10(const uint16_t *in, int in_stride, uint16_t *out, } } -void convert_rgb16_to_rgb10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgb16_to_rgb10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 0] >> 6; @@ -72,10 +102,14 @@ void convert_rgb16_to_rgb10(const uint16_t *in, int in_stride, uint16_t *out, in } } -void convert_rgba16_to_rgba10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgba16_to_rgba10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 0] >> 6; @@ -88,10 +122,92 @@ void convert_rgba16_to_rgba10(const uint16_t *in, int in_stride, uint16_t *out, } } -void convert_rgba12_to_rgba16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_bgr16_to_rgb12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) +{ + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; + for (int i = 0; i < n_rows; i++) { + for (int i2 = 0; i2 < stride_elements; i2++) { + out_row[i2 * 3 + 0] = in_row[i2 * 3 + 2] >> 4; + out_row[i2 * 3 + 1] = in_row[i2 * 3 + 1] >> 4; + out_row[i2 * 3 + 2] = in_row[i2 * 3 + 0] >> 4; + } + in_row += in_stride; + out_row += out_stride; + } +} + +void convert_bgra16_to_rgba12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) +{ + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; + for (int i = 0; i < n_rows; i++) { + for (int i2 = 0; i2 < stride_elements; i2++) { + out_row[i2 * 4 + 0] = in_row[i2 * 4 + 2] >> 4; + out_row[i2 * 4 + 1] = in_row[i2 * 4 + 1] >> 4; + out_row[i2 * 4 + 2] = in_row[i2 * 4 + 0] >> 4; + out_row[i2 * 4 + 3] = in_row[i2 * 4 + 3] >> 4; + } + in_row += in_stride; + out_row += out_stride; + } +} + +void convert_rgb16_to_rgb12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) +{ + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; + for (int i = 0; i < n_rows; i++) { + for (int i2 = 0; i2 < stride_elements; i2++) { + out_row[i2 * 3 + 0] = in_row[i2 * 3 + 0] >> 4; + out_row[i2 * 3 + 1] = in_row[i2 * 3 + 1] >> 4; + out_row[i2 * 3 + 2] = in_row[i2 * 3 + 2] >> 4; + } + in_row += in_stride; + out_row += out_stride; + } +} + +void convert_rgba16_to_rgba12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) +{ + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; + for (int i = 0; i < n_rows; i++) { + for (int i2 = 0; i2 < stride_elements; i2++) { + out_row[i2 * 4 + 0] = in_row[i2 * 4 + 0] >> 4; + out_row[i2 * 4 + 1] = in_row[i2 * 4 + 1] >> 4; + out_row[i2 * 4 + 2] = in_row[i2 * 4 + 2] >> 4; + out_row[i2 * 4 + 3] = in_row[i2 * 4 + 3] >> 4; + } + in_row += in_stride; + out_row += out_stride; + } +} + +void convert_rgba12_to_rgba16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 0] << 4; @@ -104,10 +220,14 @@ void convert_rgba12_to_rgba16(const uint16_t *in, int in_stride, uint16_t *out, } } -void convert_rgba12_to_bgra16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgba12_to_bgra16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 2] << 4; @@ -120,10 +240,14 @@ void convert_rgba12_to_bgra16(const uint16_t *in, int in_stride, uint16_t *out, } } -void convert_rgb12_to_rgb16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgb12_to_rgb16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 0] << 4; @@ -135,10 +259,14 @@ void convert_rgb12_to_rgb16(const uint16_t *in, int in_stride, uint16_t *out, in } } -void convert_rgb12_to_bgr16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgb12_to_bgr16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 2] << 4; @@ -150,10 +278,14 @@ void convert_rgb12_to_bgr16(const uint16_t *in, int in_stride, uint16_t *out, in } } -void convert_rgba10_to_rgba16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgba10_to_rgba16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 0] << 6; @@ -166,10 +298,14 @@ void convert_rgba10_to_rgba16(const uint16_t *in, int in_stride, uint16_t *out, } } -void convert_rgba10_to_bgra16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgba10_to_bgra16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 2] << 6; @@ -182,10 +318,14 @@ void convert_rgba10_to_bgra16(const uint16_t *in, int in_stride, uint16_t *out, } } -void convert_rgb10_to_rgb16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgb10_to_rgb16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 0] << 6; @@ -197,10 +337,14 @@ void convert_rgb10_to_rgb16(const uint16_t *in, int in_stride, uint16_t *out, in } } -void convert_rgb10_to_bgr16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgb10_to_bgr16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { - const uint16_t* in_row = in; - uint16_t* out_row = out; + const uint16_t* in_row = (uint16_t*)in; + uint16_t* out_row = (uint16_t*)out; + in_stride = in_stride / 2; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 2] << 6; @@ -212,10 +356,13 @@ void convert_rgb10_to_bgr16(const uint16_t *in, int in_stride, uint16_t *out, in } } -void convert_rgba_to_rgba16(const uint8_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgba_to_rgba16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { const uint8_t* in_row = in; - uint16_t* out_row = out; + uint16_t* out_row = (uint16_t*)out; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 0] << 8; @@ -228,10 +375,13 @@ void convert_rgba_to_rgba16(const uint8_t *in, int in_stride, uint16_t *out, int } } -void convert_rgba_to_bgra16(const uint8_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgba_to_bgra16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { const uint8_t* in_row = in; - uint16_t* out_row = out; + uint16_t* out_row = (uint16_t*)out; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 2] << 8; @@ -244,10 +394,13 @@ void convert_rgba_to_bgra16(const uint8_t *in, int in_stride, uint16_t *out, int } } -void convert_rgb_to_rgb16(const uint8_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgb_to_rgb16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { const uint8_t* in_row = in; - uint16_t* out_row = out; + uint16_t* out_row = (uint16_t*)out; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 0] << 8; @@ -259,10 +412,13 @@ void convert_rgb_to_rgb16(const uint8_t *in, int in_stride, uint16_t *out, int o } } -void convert_rgb_to_bgr16(const uint8_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements) +void convert_rgb_to_bgr16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { const uint8_t* in_row = in; - uint16_t* out_row = out; + uint16_t* out_row = (uint16_t*)out; + out_stride = out_stride / 2; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 2] << 8; @@ -274,10 +430,12 @@ void convert_rgb_to_bgr16(const uint8_t *in, int in_stride, uint16_t *out, int o } } -void convert_bgra_rgba(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows, int stride_elements) +void convert_bgra_rgba(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { const uint8_t* in_row = in; uint8_t* out_row = out; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 4; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 4 + 0] = in_row[i2 * 4 + 2]; @@ -290,10 +448,12 @@ void convert_bgra_rgba(const uint8_t *in, int in_stride, uint8_t *out, int out_s } } -void convert_bgr_rgb(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows, int stride_elements) +void convert_bgr_rgb(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows) { const uint8_t* in_row = in; uint8_t* out_row = out; + int stride_elements = out_stride > in_stride ? in_stride : out_stride; + stride_elements = stride_elements / 3; for (int i = 0; i < n_rows; i++) { for (int i2 = 0; i2 < stride_elements; i2++) { out_row[i2 * 3 + 0] = in_row[i2 * 3 + 2]; diff --git a/pillow_heif/helpers.h b/pillow_heif/helpers.h index e6a96252..2ac706b5 100644 --- a/pillow_heif/helpers.h +++ b/pillow_heif/helpers.h @@ -1,39 +1,49 @@ void copy_image_data(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_i16_to_i10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_i16_to_i10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_bgr16_to_rgb10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_i16_to_i12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_bgra16_to_rgba10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_bgr16_to_rgb10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgb16_to_rgb10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_bgra16_to_rgba10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgba16_to_rgba10(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgb16_to_rgb10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgba12_to_rgba16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgba16_to_rgba10(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgba12_to_bgra16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_bgr16_to_rgb12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgb12_to_rgb16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_bgra16_to_rgba12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgb12_to_bgr16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgb16_to_rgb12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgba10_to_rgba16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgba16_to_rgba12(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgba10_to_bgra16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgba12_to_rgba16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgb10_to_rgb16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgba12_to_bgra16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgb10_to_bgr16(const uint16_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgb12_to_rgb16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgba_to_rgba16(const uint8_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgb12_to_bgr16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgba_to_bgra16(const uint8_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgba10_to_rgba16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgb_to_rgb16(const uint8_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgba10_to_bgra16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_rgb_to_bgr16(const uint8_t *in, int in_stride, uint16_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgb10_to_rgb16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_bgra_rgba(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgb10_to_bgr16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); -void convert_bgr_rgb(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows, int stride_elements); +void convert_rgba_to_rgba16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); + +void convert_rgba_to_bgra16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); + +void convert_rgb_to_rgb16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); + +void convert_rgb_to_bgr16(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); + +void convert_bgra_rgba(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); + +void convert_bgr_rgb(const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int n_rows); diff --git a/pillow_heif/private.py b/pillow_heif/private.py index a3bdf12b..66536dec 100644 --- a/pillow_heif/private.py +++ b/pillow_heif/private.py @@ -34,200 +34,39 @@ def get_pure_stride(mode: str, width: int): return width * MODE_INFO[mode][0] * ceil(MODE_INFO[mode][1] / 8) -def convert_i16_to_i10(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = min(source_stride, dest_stride) - lib.convert_i16_to_i10(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_bgr16_to_rgb10(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_bgr16_to_rgb10(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_bgra16_to_rgba10(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_bgra16_to_rgba10(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgb16_to_rgb10(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_rgb16_to_rgb10(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgba16_to_rgba10(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_rgba16_to_rgba10(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgba12_to_rgba16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_rgba12_to_rgba16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgba12_to_bgra16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_rgba12_to_bgra16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgb12_to_rgb16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_rgb12_to_rgb16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgb12_to_bgr16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_rgb12_to_bgr16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgba10_to_rgba16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_rgba10_to_rgba16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgba10_to_bgra16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_rgba10_to_bgra16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgb10_to_rgb16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_rgb10_to_rgb16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgb10_to_bgr16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint16_t*", src_data) - source_stride = int(source_stride / 2) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_rgb10_to_bgr16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgba_to_rgba16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint8_t*", src_data) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_rgba_to_rgba16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgba_to_bgra16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint8_t*", src_data) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_rgba_to_bgra16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgb_to_rgb16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint8_t*", src_data) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_rgb_to_rgb16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_rgb_to_bgr16(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint8_t*", src_data) - p_dest = ffi.cast("uint16_t*", dest_data) - dest_stride = int(dest_stride / 2) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_rgb_to_bgr16(p_src, source_stride, p_dest, dest_stride, height, stride_elements) - - -def convert_between_bgra_and_rgba(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint8_t*", src_data) - stride_elements = int(min(source_stride, dest_stride) / 4) - lib.convert_bgra_rgba(p_src, source_stride, dest_data, dest_stride, height, stride_elements) - - -def convert_between_bgr_and_rgb(dest_data, src_data, dest_stride: int, source_stride: int, height: int): - p_src = ffi.from_buffer("uint8_t*", src_data) - stride_elements = int(min(source_stride, dest_stride) / 3) - lib.convert_bgr_rgb(p_src, source_stride, dest_data, dest_stride, height, stride_elements) - - MODE_CONVERT = { # source_mode: {target_mode: convert_function,} - "BGRA;16": {"RGBA;10": convert_bgra16_to_rgba10}, - "BGR;16": {"RGB;10": convert_bgr16_to_rgb10}, - "RGBA;16": {"RGBA;10": convert_rgba16_to_rgba10}, - "RGB;16": {"RGB;10": convert_rgb16_to_rgb10}, - "L;16": {"L;10": convert_i16_to_i10}, - "I;16": {"L;10": convert_i16_to_i10}, - "I;16L": {"L;10": convert_i16_to_i10}, - "RGBA;12": {"RGBA;16": convert_rgba12_to_rgba16, "BGRA;16": convert_rgba12_to_bgra16}, - "RGB;12": {"RGB;16": convert_rgb12_to_rgb16, "BGR;16": convert_rgb12_to_bgr16}, - "RGBA;10": {"RGBA;16": convert_rgba10_to_rgba16, "BGRA;16": convert_rgba10_to_bgra16}, - "RGB;10": {"RGB;16": convert_rgb10_to_rgb16, "BGR;16": convert_rgb10_to_bgr16}, - "BGRA": {"RGBA": convert_between_bgra_and_rgba}, - "BGR": {"RGB": convert_between_bgr_and_rgb}, + "BGRA;16": {"RGBA;10": lib.convert_bgra16_to_rgba10, "RGBA;12": lib.convert_bgra16_to_rgba12}, + "BGR;16": {"RGB;10": lib.convert_bgr16_to_rgb10, "RGB;12": lib.convert_bgr16_to_rgb12}, + "RGBA;16": {"RGBA;10": lib.convert_rgba16_to_rgba10, "RGBA;12": lib.convert_rgba16_to_rgba12}, + "RGB;16": {"RGB;10": lib.convert_rgb16_to_rgb10, "RGB;12": lib.convert_rgb16_to_rgb12}, + "L;16": {"L;10": lib.convert_i16_to_i10, "L;12": lib.convert_i16_to_i12}, + "I;16": {"L;10": lib.convert_i16_to_i10, "L;12": lib.convert_i16_to_i12}, + "I;16L": {"L;10": lib.convert_i16_to_i10, "L;12": lib.convert_i16_to_i12}, + "RGBA;12": {"RGBA;16": lib.convert_rgba12_to_rgba16, "BGRA;16": lib.convert_rgba12_to_bgra16}, + "RGB;12": {"RGB;16": lib.convert_rgb12_to_rgb16, "BGR;16": lib.convert_rgb12_to_bgr16}, + "RGBA;10": {"RGBA;16": lib.convert_rgba10_to_rgba16, "BGRA;16": lib.convert_rgba10_to_bgra16}, + "RGB;10": {"RGB;16": lib.convert_rgb10_to_rgb16, "BGR;16": lib.convert_rgb10_to_bgr16}, + "BGRA": {"RGBA": lib.convert_bgra_rgba}, + "BGR": {"RGB": lib.convert_bgr_rgb}, "RGBA": { - "BGRA": convert_between_bgra_and_rgba, - "RGBA;16": convert_rgba_to_rgba16, - "BGRA;16": convert_rgba_to_bgra16, + "BGRA": lib.convert_bgra_rgba, + "RGBA;16": lib.convert_rgba_to_rgba16, + "BGRA;16": lib.convert_rgba_to_bgra16, }, - "RGB": {"BGR": convert_between_bgr_and_rgb, "RGB;16": convert_rgb_to_rgb16, "BGR;16": convert_rgb_to_bgr16}, + "RGB": {"BGR": lib.convert_bgr_rgb, "RGB;16": lib.convert_rgb_to_rgb16, "BGR;16": lib.convert_rgb_to_bgr16}, } MODE_INFO = { - # name -> (channels, bits per pixel channel, colorspace, chroma, mode_for_saving, numpy_typestr) - "BGRA;16": (4, 16, HeifColorspace.RGB, HeifChroma.INTERLEAVED_RRGGBBAA_LE, "RGBA;10", " [channels, bits per pixel channel, colorspace, chroma, (mode_for_saving 10,12 bit), numpy_typestr] + "BGRA;16": (4, 16, HeifColorspace.RGB, HeifChroma.INTERLEAVED_RRGGBBAA_LE, ("RGBA;10", "RGBA;12"), "u2"),