Skip to content

Commit bebd882

Browse files
committed
Improved error handling
1 parent a55ea64 commit bebd882

File tree

1 file changed

+89
-14
lines changed

1 file changed

+89
-14
lines changed

src/_avif.c

Lines changed: 89 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -106,30 +106,43 @@ _encoder_codec_available(PyObject *self, PyObject *args) {
106106
return PyBool_FromLong(is_available);
107107
}
108108

109-
static void
109+
static int
110110
_add_codec_specific_options(avifEncoder *encoder, PyObject *opts) {
111111
Py_ssize_t i, size;
112112
PyObject *keyval, *py_key, *py_val;
113113
char *key, *val;
114114
if (!PyTuple_Check(opts)) {
115-
return;
115+
PyErr_SetString(PyExc_ValueError, "Invalid advanced codec options");
116+
return 1;
116117
}
117118
size = PyTuple_GET_SIZE(opts);
118119

119120
for (i = 0; i < size; i++) {
120121
keyval = PyTuple_GetItem(opts, i);
121122
if (!PyTuple_Check(keyval) || PyTuple_GET_SIZE(keyval) != 2) {
122-
return;
123+
PyErr_SetString(PyExc_ValueError, "Invalid advanced codec options");
124+
return 1;
123125
}
124126
py_key = PyTuple_GetItem(keyval, 0);
125127
py_val = PyTuple_GetItem(keyval, 1);
126128
if (!PyBytes_Check(py_key) || !PyBytes_Check(py_val)) {
127-
return;
129+
PyErr_SetString(PyExc_ValueError, "Invalid advanced codec options");
130+
return 1;
128131
}
129132
key = PyBytes_AsString(py_key);
130133
val = PyBytes_AsString(py_val);
131-
avifEncoderSetCodecSpecificOption(encoder, key, val);
134+
135+
avifResult result = avifEncoderSetCodecSpecificOption(encoder, key, val);
136+
if (result != AVIF_RESULT_OK) {
137+
PyErr_Format(
138+
exc_type_for_avif_result(result),
139+
"Setting advanced codec options failed: %s",
140+
avifResultToString(result)
141+
);
142+
return 1;
143+
}
132144
}
145+
return 0;
133146
}
134147

135148
// Encoder functions
@@ -296,9 +309,18 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
296309
encoder->autoTiling = enc_options.autotiling;
297310
#endif
298311

312+
if (advanced != Py_None) {
299313
#if AVIF_VERSION >= 80200
300-
_add_codec_specific_options(encoder, advanced);
314+
if (_add_codec_specific_options(encoder, advanced)) {
315+
return NULL;
316+
}
317+
#else
318+
PyErr_SetString(
319+
PyExc_ValueError, "Advanced codec options require libavif >= 0.8.2"
320+
);
321+
return NULL;
301322
#endif
323+
}
302324

303325
self->encoder = encoder;
304326

@@ -316,14 +338,24 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
316338
image->alphaPremultiplied = enc_options.alpha_premultiplied;
317339
#endif
318340

341+
avifResult result;
319342
if (PyBytes_GET_SIZE(icc_bytes)) {
320343
self->icc_bytes = icc_bytes;
321344
Py_INCREF(icc_bytes);
322-
avifImageSetProfileICC(
345+
346+
result = avifImageSetProfileICC(
323347
image,
324348
(uint8_t *)PyBytes_AS_STRING(icc_bytes),
325349
PyBytes_GET_SIZE(icc_bytes)
326350
);
351+
if (result != AVIF_RESULT_OK) {
352+
PyErr_Format(
353+
exc_type_for_avif_result(result),
354+
"Setting ICC profile failed: %s",
355+
avifResultToString(result)
356+
);
357+
return NULL;
358+
}
327359
} else {
328360
image->colorPrimaries = AVIF_COLOR_PRIMARIES_BT709;
329361
image->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_SRGB;
@@ -332,20 +364,38 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
332364
if (PyBytes_GET_SIZE(exif_bytes)) {
333365
self->exif_bytes = exif_bytes;
334366
Py_INCREF(exif_bytes);
335-
avifImageSetMetadataExif(
367+
368+
result = avifImageSetMetadataExif(
336369
image,
337370
(uint8_t *)PyBytes_AS_STRING(exif_bytes),
338371
PyBytes_GET_SIZE(exif_bytes)
339372
);
373+
if (result != AVIF_RESULT_OK) {
374+
PyErr_Format(
375+
exc_type_for_avif_result(result),
376+
"Setting EXIF data failed: %s",
377+
avifResultToString(result)
378+
);
379+
return NULL;
380+
}
340381
}
341382
if (PyBytes_GET_SIZE(xmp_bytes)) {
342383
self->xmp_bytes = xmp_bytes;
343384
Py_INCREF(xmp_bytes);
344-
avifImageSetMetadataXMP(
385+
386+
result = avifImageSetMetadataXMP(
345387
image,
346388
(uint8_t *)PyBytes_AS_STRING(xmp_bytes),
347389
PyBytes_GET_SIZE(xmp_bytes)
348390
);
391+
if (result != AVIF_RESULT_OK) {
392+
PyErr_Format(
393+
exc_type_for_avif_result(result),
394+
"Setting XMP data failed: %s",
395+
avifResultToString(result)
396+
);
397+
return NULL;
398+
}
349399
}
350400

351401
self->image = image;
@@ -449,7 +499,15 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) {
449499
rgb.format = AVIF_RGB_FORMAT_RGB;
450500
}
451501

452-
avifRGBImageAllocatePixels(&rgb);
502+
result = avifRGBImageAllocatePixels(&rgb);
503+
if (result != AVIF_RESULT_OK) {
504+
PyErr_Format(
505+
exc_type_for_avif_result(result),
506+
"Pixel allocation failed: %s",
507+
avifResultToString(result)
508+
);
509+
return NULL;
510+
}
453511

454512
if (rgb.rowBytes * rgb.height != size) {
455513
PyErr_Format(
@@ -599,14 +657,24 @@ AvifDecoderNew(PyObject *self_, PyObject *args) {
599657
#endif
600658
self->decoder->codecChoice = codec;
601659

602-
avifDecoderSetIOMemory(
660+
result = avifDecoderSetIOMemory(
603661
self->decoder,
604662
(uint8_t *)PyBytes_AS_STRING(self->data),
605663
PyBytes_GET_SIZE(self->data)
606664
);
665+
if (result != AVIF_RESULT_OK) {
666+
PyErr_Format(
667+
exc_type_for_avif_result(result),
668+
"Setting IO memory failed: %s",
669+
avifResultToString(result)
670+
);
671+
avifDecoderDestroy(self->decoder);
672+
self->decoder = NULL;
673+
Py_DECREF(self);
674+
return NULL;
675+
}
607676

608677
result = avifDecoderParse(self->decoder);
609-
610678
if (result != AVIF_RESULT_OK) {
611679
PyErr_Format(
612680
exc_type_for_avif_result(result),
@@ -697,7 +765,6 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) {
697765
}
698766

699767
result = avifDecoderNthImage(decoder, frame_index);
700-
701768
if (result != AVIF_RESULT_OK) {
702769
PyErr_Format(
703770
exc_type_for_avif_result(result),
@@ -729,7 +796,15 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) {
729796
return NULL;
730797
}
731798

732-
avifRGBImageAllocatePixels(&rgb);
799+
result = avifRGBImageAllocatePixels(&rgb);
800+
if (result != AVIF_RESULT_OK) {
801+
PyErr_Format(
802+
exc_type_for_avif_result(result),
803+
"Pixel allocation failed: %s",
804+
avifResultToString(result)
805+
);
806+
return NULL;
807+
}
733808

734809
Py_BEGIN_ALLOW_THREADS result = avifImageYUVToRGB(image, &rgb);
735810
Py_END_ALLOW_THREADS

0 commit comments

Comments
 (0)