mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-03-14 15:22:13 +03:00
Removed memset and ignoreAlpha (#20)
This commit is contained in:
parent
7de1212c18
commit
e1509ee88b
|
@ -16,6 +16,7 @@ except ImportError:
|
||||||
# Decoder options as module globals, until there is a way to pass parameters
|
# Decoder options as module globals, until there is a way to pass parameters
|
||||||
# to Image.open (see https://github.com/python-pillow/Pillow/issues/569)
|
# to Image.open (see https://github.com/python-pillow/Pillow/issues/569)
|
||||||
DECODE_CODEC_CHOICE = "auto"
|
DECODE_CODEC_CHOICE = "auto"
|
||||||
|
# Decoding is only affected by this for libavif **0.8.4** or greater.
|
||||||
DEFAULT_MAX_THREADS = 0
|
DEFAULT_MAX_THREADS = 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,10 +62,7 @@ class AvifImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def _open(self) -> None:
|
def _open(self) -> None:
|
||||||
if not SUPPORTED:
|
if not SUPPORTED:
|
||||||
msg = (
|
msg = "image file could not be opened because AVIF support not installed"
|
||||||
"image file could not be identified because AVIF "
|
|
||||||
"support not installed"
|
|
||||||
)
|
|
||||||
raise SyntaxError(msg)
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
if DECODE_CODEC_CHOICE != "auto" and not _avif.decoder_codec_available(
|
if DECODE_CODEC_CHOICE != "auto" and not _avif.decoder_codec_available(
|
||||||
|
@ -116,11 +114,11 @@ class AvifImageFile(ImageFile.ImageFile):
|
||||||
def load(self) -> Image.core.PixelAccess | None:
|
def load(self) -> Image.core.PixelAccess | None:
|
||||||
if self.tile:
|
if self.tile:
|
||||||
# We need to load the image data for this frame
|
# We need to load the image data for this frame
|
||||||
data, timescale, tsp_in_ts, dur_in_ts = self._decoder.get_frame(
|
data, timescale, pts_in_timescales, dur_in_timescales = (
|
||||||
self.__frame
|
self._decoder.get_frame(self.__frame)
|
||||||
)
|
)
|
||||||
self.info["timestamp"] = round(1000 * (tsp_in_ts / timescale))
|
self.info["timestamp"] = round(1000 * (pts_in_timescales / timescale))
|
||||||
self.info["duration"] = round(1000 * (dur_in_ts / timescale))
|
self.info["duration"] = round(1000 * (dur_in_timescales / timescale))
|
||||||
|
|
||||||
# Set tile
|
# Set tile
|
||||||
if self.fp and self._exclusive_fp:
|
if self.fp and self._exclusive_fp:
|
||||||
|
@ -212,8 +210,7 @@ def _save(
|
||||||
|
|
||||||
# Setup the AVIF encoder
|
# Setup the AVIF encoder
|
||||||
enc = _avif.AvifEncoder(
|
enc = _avif.AvifEncoder(
|
||||||
im.size[0],
|
im.size,
|
||||||
im.size[1],
|
|
||||||
subsampling,
|
subsampling,
|
||||||
quality,
|
quality,
|
||||||
speed,
|
speed,
|
||||||
|
@ -233,7 +230,7 @@ def _save(
|
||||||
|
|
||||||
# Add each frame
|
# Add each frame
|
||||||
frame_idx = 0
|
frame_idx = 0
|
||||||
frame_dur = 0
|
frame_duration = 0
|
||||||
cur_idx = im.tell()
|
cur_idx = im.tell()
|
||||||
try:
|
try:
|
||||||
for ims in [im] + append_images:
|
for ims in [im] + append_images:
|
||||||
|
@ -252,16 +249,15 @@ def _save(
|
||||||
|
|
||||||
# Update frame duration
|
# Update frame duration
|
||||||
if isinstance(duration, (list, tuple)):
|
if isinstance(duration, (list, tuple)):
|
||||||
frame_dur = duration[frame_idx]
|
frame_duration = duration[frame_idx]
|
||||||
else:
|
else:
|
||||||
frame_dur = duration
|
frame_duration = duration
|
||||||
|
|
||||||
# Append the frame to the animation encoder
|
# Append the frame to the animation encoder
|
||||||
enc.add(
|
enc.add(
|
||||||
frame.tobytes("raw", rawmode),
|
frame.tobytes("raw", rawmode),
|
||||||
frame_dur,
|
frame_duration,
|
||||||
frame.size[0],
|
frame.size,
|
||||||
frame.size[1],
|
|
||||||
rawmode,
|
rawmode,
|
||||||
is_single_frame,
|
is_single_frame,
|
||||||
)
|
)
|
||||||
|
|
48
src/_avif.c
48
src/_avif.c
|
@ -7,7 +7,7 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD avifEncoder *encoder;
|
PyObject_HEAD avifEncoder *encoder;
|
||||||
avifImage *image;
|
avifImage *image;
|
||||||
int frame_index;
|
int first_frame;
|
||||||
} AvifEncoderObject;
|
} AvifEncoderObject;
|
||||||
|
|
||||||
static PyTypeObject AvifEncoder_Type;
|
static PyTypeObject AvifEncoder_Type;
|
||||||
|
@ -16,7 +16,6 @@ static PyTypeObject AvifEncoder_Type;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD avifDecoder *decoder;
|
PyObject_HEAD avifDecoder *decoder;
|
||||||
Py_buffer buffer;
|
Py_buffer buffer;
|
||||||
char *mode;
|
|
||||||
} AvifDecoderObject;
|
} AvifDecoderObject;
|
||||||
|
|
||||||
static PyTypeObject AvifDecoder_Type;
|
static PyTypeObject AvifDecoder_Type;
|
||||||
|
@ -154,7 +153,7 @@ exif_orientation_to_irot_imir(avifImage *image, int orientation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_codec_available(const char *name, uint32_t flags) {
|
_codec_available(const char *name, avifCodecFlags flags) {
|
||||||
avifCodecChoice codec = avifCodecChoiceFromName(name);
|
avifCodecChoice codec = avifCodecChoiceFromName(name);
|
||||||
if (codec == AVIF_CODEC_CHOICE_AUTO) {
|
if (codec == AVIF_CODEC_CHOICE_AUTO) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -252,7 +251,7 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(
|
if (!PyArg_ParseTuple(
|
||||||
args,
|
args,
|
||||||
"IIsiiissiiOOy*y*iy*O",
|
"(II)siiissiiOOy*y*iy*O",
|
||||||
&width,
|
&width,
|
||||||
&height,
|
&height,
|
||||||
&subsampling,
|
&subsampling,
|
||||||
|
@ -372,7 +371,7 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
|
||||||
avifEncoderDestroy(encoder);
|
avifEncoderDestroy(encoder);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
self->frame_index = -1;
|
self->first_frame = 1;
|
||||||
|
|
||||||
avifResult result;
|
avifResult result;
|
||||||
if (icc_buffer.len) {
|
if (icc_buffer.len) {
|
||||||
|
@ -466,10 +465,9 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) {
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
char *mode;
|
char *mode;
|
||||||
PyObject *is_single_frame = NULL;
|
unsigned int is_single_frame;
|
||||||
PyObject *ret = Py_None;
|
PyObject *ret = Py_None;
|
||||||
|
|
||||||
int is_first_frame;
|
|
||||||
avifRGBImage rgb;
|
avifRGBImage rgb;
|
||||||
avifResult result;
|
avifResult result;
|
||||||
|
|
||||||
|
@ -479,7 +477,7 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) {
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(
|
if (!PyArg_ParseTuple(
|
||||||
args,
|
args,
|
||||||
"z#IIIsO",
|
"y#I(II)sp",
|
||||||
(char **)&rgb_bytes,
|
(char **)&rgb_bytes,
|
||||||
&size,
|
&size,
|
||||||
&duration,
|
&duration,
|
||||||
|
@ -491,8 +489,6 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_first_frame = self->frame_index == -1;
|
|
||||||
|
|
||||||
if (image->width != width || image->height != height) {
|
if (image->width != width || image->height != height) {
|
||||||
PyErr_Format(
|
PyErr_Format(
|
||||||
PyExc_ValueError,
|
PyExc_ValueError,
|
||||||
|
@ -505,7 +501,7 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_first_frame) {
|
if (self->first_frame) {
|
||||||
// If we don't have an image populated with yuv planes, this is the first frame
|
// If we don't have an image populated with yuv planes, this is the first frame
|
||||||
frame = image;
|
frame = image;
|
||||||
} else {
|
} else {
|
||||||
|
@ -577,7 +573,7 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t addImageFlags = AVIF_ADD_IMAGE_FLAG_NONE;
|
uint32_t addImageFlags = AVIF_ADD_IMAGE_FLAG_NONE;
|
||||||
if (PyObject_IsTrue(is_single_frame)) {
|
if (is_single_frame) {
|
||||||
addImageFlags |= AVIF_ADD_IMAGE_FLAG_SINGLE;
|
addImageFlags |= AVIF_ADD_IMAGE_FLAG_SINGLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,12 +593,12 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) {
|
||||||
|
|
||||||
end:
|
end:
|
||||||
avifRGBImageFreePixels(&rgb);
|
avifRGBImageFreePixels(&rgb);
|
||||||
if (!is_first_frame) {
|
if (!self->first_frame) {
|
||||||
avifImageDestroy(frame);
|
avifImageDestroy(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == Py_None) {
|
if (ret == Py_None) {
|
||||||
self->frame_index++;
|
self->first_frame = 0;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
} else {
|
} else {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -708,12 +704,6 @@ AvifDecoderNew(PyObject *self_, PyObject *args) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decoder->alphaPresent) {
|
|
||||||
self->mode = "RGBA";
|
|
||||||
} else {
|
|
||||||
self->mode = "RGB";
|
|
||||||
}
|
|
||||||
|
|
||||||
self->decoder = decoder;
|
self->decoder = decoder;
|
||||||
self->buffer = buffer;
|
self->buffer = buffer;
|
||||||
|
|
||||||
|
@ -757,7 +747,7 @@ _decoder_get_info(AvifDecoderObject *self) {
|
||||||
image->width,
|
image->width,
|
||||||
image->height,
|
image->height,
|
||||||
decoder->imageCount,
|
decoder->imageCount,
|
||||||
self->mode,
|
decoder->alphaPresent == AVIF_TRUE ? "RGBA" : "RGB",
|
||||||
NULL == icc ? Py_None : icc,
|
NULL == icc ? Py_None : icc,
|
||||||
NULL == exif ? Py_None : exif,
|
NULL == exif ? Py_None : exif,
|
||||||
irot_imir_to_exif_orientation(image),
|
irot_imir_to_exif_orientation(image),
|
||||||
|
@ -793,7 +783,7 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) {
|
||||||
PyErr_Format(
|
PyErr_Format(
|
||||||
exc_type_for_avif_result(result),
|
exc_type_for_avif_result(result),
|
||||||
"Failed to decode frame %u: %s",
|
"Failed to decode frame %u: %s",
|
||||||
decoder->imageIndex + 1,
|
frame_index,
|
||||||
avifResultToString(result)
|
avifResultToString(result)
|
||||||
);
|
);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -801,17 +791,11 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) {
|
||||||
|
|
||||||
image = decoder->image;
|
image = decoder->image;
|
||||||
|
|
||||||
memset(&rgb, 0, sizeof(rgb));
|
|
||||||
avifRGBImageSetDefaults(&rgb, image);
|
avifRGBImageSetDefaults(&rgb, image);
|
||||||
|
|
||||||
rgb.depth = 8;
|
rgb.depth = 8;
|
||||||
|
rgb.format =
|
||||||
if (decoder->alphaPresent) {
|
decoder->alphaPresent == AVIF_TRUE ? AVIF_RGB_FORMAT_RGBA : AVIF_RGB_FORMAT_RGB;
|
||||||
rgb.format = AVIF_RGB_FORMAT_RGBA;
|
|
||||||
} else {
|
|
||||||
rgb.format = AVIF_RGB_FORMAT_RGB;
|
|
||||||
rgb.ignoreAlpha = AVIF_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = avifRGBImageAllocatePixels(&rgb);
|
result = avifRGBImageAllocatePixels(&rgb);
|
||||||
if (result != AVIF_RESULT_OK) {
|
if (result != AVIF_RESULT_OK) {
|
||||||
|
@ -940,5 +924,9 @@ PyInit__avif(void) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
|
||||||
|
#endif
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user