Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error handling in _pillow_heif.c #298

Merged
merged 6 commits into from
Oct 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 74 additions & 43 deletions pillow_heif/_pillow_heif.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,6 @@ static PyObject* _CtxWriteImage_create(CtxWriteObject* self, PyObject* args) {
CtxWriteImageObject* ctx_write_image = PyObject_New(CtxWriteImageObject, &CtxWriteImage_Type);
if (!ctx_write_image) {
heif_image_release(image);
PyErr_SetString(PyExc_RuntimeError, "could not create CtxWriteImage object");
return NULL;
}
ctx_write_image->chroma = chroma;
Expand Down Expand Up @@ -738,12 +737,12 @@ PyObject* _CtxDepthImage(struct heif_image_handle* main_handle, heif_item_id dep
int remove_stride, int hdr_to_16bit, PyObject* file_bytes) {
struct heif_image_handle* depth_handle;
if (check_error(heif_image_handle_get_depth_image_handle(main_handle, depth_image_id, &depth_handle))) {
Py_RETURN_NONE;
return NULL;
}
CtxImageObject *ctx_image = PyObject_New(CtxImageObject, &CtxImage_Type);
if (!ctx_image) {
heif_image_handle_release(depth_handle);
Py_RETURN_NONE;
return NULL;
}
if (!heif_image_handle_get_depth_image_representation_info(main_handle, depth_image_id, &ctx_image->depth_metadata))
ctx_image->depth_metadata = NULL;
Expand Down Expand Up @@ -803,7 +802,7 @@ PyObject* _CtxImage(struct heif_image_handle* handle, int hdr_to_8bit,
CtxImageObject *ctx_image = PyObject_New(CtxImageObject, &CtxImage_Type);
if (!ctx_image) {
heif_image_handle_release(handle);
Py_RETURN_NONE;
return NULL;
}
ctx_image->depth_metadata = NULL;
ctx_image->image_type = PhHeifImage;
Expand Down Expand Up @@ -895,8 +894,17 @@ static PyObject* _CtxImage_color_profile(CtxImageObject* self, void* closure) {
return NULL;

PyObject* result = PyDict_New();
if (!result) {
heif_nclx_color_profile_free(nclx_profile);
return NULL;
}
__PyDict_SetItemString(result, "type", PyUnicode_FromString("nclx"));
PyObject* d = PyDict_New();
if (!d) {
heif_nclx_color_profile_free(nclx_profile);
Py_DECREF(result);
return NULL;
}
__PyDict_SetItemString(d, "color_primaries", PyLong_FromLong(nclx_profile->color_primaries));
__PyDict_SetItemString(d, "transfer_characteristics", PyLong_FromLong(nclx_profile->transfer_characteristics));
__PyDict_SetItemString(d, "matrix_coefficients", PyLong_FromLong(nclx_profile->matrix_coefficients));
Expand All @@ -915,6 +923,9 @@ static PyObject* _CtxImage_color_profile(CtxImageObject* self, void* closure) {
}

PyObject* result = PyDict_New();
if (!result) {
return NULL;
}
__PyDict_SetItemString(
result, "type", PyUnicode_FromString(profile_type == heif_color_profile_type_rICC ? "rICC" : "prof"));
size_t size = heif_image_handle_get_raw_color_profile_size(self->handle);
Expand All @@ -925,7 +936,7 @@ static PyObject* _CtxImage_color_profile(CtxImageObject* self, void* closure) {
if (!data) {
Py_DECREF(result);
result = NULL;
PyErr_SetString(PyExc_OSError, "Out of Memory");
PyErr_NoMemory();
}
else {
if (!check_error(heif_image_handle_get_raw_color_profile(self->handle, data)))
Expand Down Expand Up @@ -953,15 +964,13 @@ static PyObject* _CtxImage_metadata(CtxImageObject* self, void* closure) {
return PyList_New(0);

heif_item_id* meta_ids = (heif_item_id*)malloc(n_metas * sizeof(heif_item_id));
if (!meta_ids) {
PyErr_SetString(PyExc_OSError, "Out of Memory");
return NULL;
}
if (!meta_ids)
return PyErr_NoMemory();

n_metas = heif_image_handle_get_list_of_metadata_block_IDs(self->handle, NULL, meta_ids, n_metas);
PyObject* meta_list = PyList_New(n_metas);
if (!meta_list) {
free(meta_ids);
PyErr_SetString(PyExc_OSError, "Out of Memory");
return NULL;
}

Expand All @@ -971,16 +980,25 @@ static PyObject* _CtxImage_metadata(CtxImageObject* self, void* closure) {
content_type = heif_image_handle_get_metadata_content_type(self->handle, meta_ids[i]);
size = heif_image_handle_get_metadata_size(self->handle, meta_ids[i]);
data = malloc(size);
if (data) {
error = heif_image_handle_get_metadata(self->handle, meta_ids[i], data);
if (error.code == heif_error_Ok) {
meta_item_info = PyDict_New();
__PyDict_SetItemString(meta_item_info, "type", PyUnicode_FromString(type));
__PyDict_SetItemString(meta_item_info, "content_type", PyUnicode_FromString(content_type));
__PyDict_SetItemString(meta_item_info, "data", PyBytes_FromStringAndSize((char*)data, size));
if (!data) {
Py_DECREF(meta_list);
free(meta_ids);
return PyErr_NoMemory();
}
error = heif_image_handle_get_metadata(self->handle, meta_ids[i], data);
if (error.code == heif_error_Ok) {
meta_item_info = PyDict_New();
if (!meta_item_info) {
free(data);
Py_DECREF(meta_list);
free(meta_ids);
return NULL;
}
free(data);
__PyDict_SetItemString(meta_item_info, "type", PyUnicode_FromString(type));
__PyDict_SetItemString(meta_item_info, "content_type", PyUnicode_FromString(content_type));
__PyDict_SetItemString(meta_item_info, "data", PyBytes_FromStringAndSize((char*)data, size));
}
free(data);
if (!meta_item_info) {
meta_item_info = Py_None;
Py_INCREF(meta_item_info);
Expand All @@ -992,9 +1010,8 @@ static PyObject* _CtxImage_metadata(CtxImageObject* self, void* closure) {
}
else if (self->image_type == PhHeifDepthImage) {
PyObject* meta = PyDict_New();
if (!meta) {
Py_RETURN_NONE;
}
if (!meta)
return NULL;
if (!self->depth_metadata)
return meta;

Expand Down Expand Up @@ -1033,7 +1050,7 @@ static PyObject* _CtxImage_thumbnails(CtxImageObject* self, void* closure) {
PyObject* images_list = PyList_New(n_images);
if (!images_list) {
free(images_ids);
return PyList_New(0);
return NULL;
}

struct heif_image_handle* handle;
Expand Down Expand Up @@ -1163,21 +1180,24 @@ static PyObject* _CtxImage_depth_image_list(CtxImageObject* self, void* closure)
return PyList_New(0);
heif_item_id* images_ids = (heif_item_id*)malloc(n_images * sizeof(heif_item_id));
if (!images_ids)
return PyList_New(0);
return PyErr_NoMemory();

n_images = heif_image_handle_get_list_of_depth_image_IDs(self->handle, images_ids, n_images);
PyObject* images_list = PyList_New(n_images);
if (!images_list) {
free(images_ids);
return PyList_New(0);
return NULL;
}

for (int i = 0; i < n_images; i++) {
PyList_SET_ITEM(images_list,
i,
_CtxDepthImage(
self->handle, images_ids[i], self->remove_stride, self->hdr_to_16bit, self->file_bytes
));
PyObject* ctx_depth_image = _CtxDepthImage(
self->handle, images_ids[i], self->remove_stride, self->hdr_to_16bit, self->file_bytes);
if (!ctx_depth_image) {
Py_DECREF(images_list);
free(images_ids);
return NULL;
}
PyList_SET_ITEM(images_list, i, ctx_depth_image);
}
free(images_ids);
return images_list;
Expand All @@ -1193,7 +1213,7 @@ static PyObject* _CtxImage_camera_intrinsic_matrix(CtxImageObject* self, void* c
Py_RETURN_NONE;
}
if (check_error(heif_image_handle_get_camera_intrinsic_matrix(self->handle, &camera_intrinsic_matrix))) {
Py_RETURN_NONE;
return NULL;
}
return Py_BuildValue(
"(ddddd)",
Expand All @@ -1218,12 +1238,12 @@ static PyObject* _CtxImage_camera_extrinsic_matrix_rot(CtxImageObject* self, voi
Py_RETURN_NONE;
}
if (check_error(heif_image_handle_get_camera_extrinsic_matrix(self->handle, &camera_extrinsic_matrix))) {
Py_RETURN_NONE;
return NULL;
}
error = heif_camera_extrinsic_matrix_get_rotation_matrix(camera_extrinsic_matrix, rot);
heif_camera_extrinsic_matrix_release(camera_extrinsic_matrix);
if (check_error(error)) {
Py_RETURN_NONE;
return NULL;
}
return Py_BuildValue("(ddddddddd)", rot[0], rot[1], rot[2], rot[3], rot[4], rot[5], rot[6], rot[7], rot[8]);
#else
Expand Down Expand Up @@ -1292,7 +1312,6 @@ static PyObject* _CtxWrite(PyObject* self, PyObject* args) {
if (!ctx_write) {
heif_encoder_release(encoder);
heif_context_free(ctx);
PyErr_SetString(PyExc_RuntimeError, "could not create CtxWrite object");
return NULL;
}
ctx_write->ctx = ctx;
Expand Down Expand Up @@ -1338,15 +1357,13 @@ static PyObject* _load_file(PyObject* self, PyObject* args) {
heif_item_id* images_ids = (heif_item_id*)malloc(n_images * sizeof(heif_item_id));
if (!images_ids) {
heif_context_free(heif_ctx);
PyErr_SetString(PyExc_OSError, "Out of Memory");
return NULL;
return PyErr_NoMemory();
}
n_images = heif_context_get_list_of_top_level_image_IDs(heif_ctx, images_ids, n_images);
PyObject* images_list = PyList_New(n_images);
if (!images_list) {
free(images_ids);
heif_context_free(heif_ctx);
PyErr_SetString(PyExc_OSError, "Out of Memory");
return NULL;
}

Expand All @@ -1365,11 +1382,17 @@ static PyObject* _load_file(PyObject* self, PyObject* args) {
if (error.code == heif_error_Ok) {
error = heif_image_handle_get_preferred_decoding_colorspace(handle, &colorspace, &chroma);
if (error.code == heif_error_Ok) {
PyList_SET_ITEM(images_list,
i,
_CtxImage(handle, hdr_to_8bit,
bgr_mode, remove_stride, hdr_to_16bit, reload_size, primary, heif_bytes,
decoder_id, colorspace, chroma));
PyObject* ctx_image = _CtxImage(
handle, hdr_to_8bit, bgr_mode, remove_stride, hdr_to_16bit, reload_size, primary, heif_bytes,
decoder_id, colorspace, chroma);
if (!ctx_image) {
Py_DECREF(images_list);
heif_image_handle_release(handle);
free(images_ids);
heif_context_free(heif_ctx);
return NULL;
}
PyList_SET_ITEM(images_list, i, ctx_image);
} else {
heif_image_handle_release(handle);
}
Expand All @@ -1386,10 +1409,18 @@ static PyObject* _load_file(PyObject* self, PyObject* args) {

static PyObject* _get_lib_info(PyObject* self) {
PyObject* lib_info_dict = PyDict_New();
if (!lib_info_dict) {
return NULL;
}
PyObject* encoders_dict = PyDict_New();
if (!encoders_dict) {
Py_DECREF(lib_info_dict);
return NULL;
}
PyObject* decoders_dict = PyDict_New();
if ((!lib_info_dict) || (!encoders_dict) || (!decoders_dict)) {
PyErr_SetString(PyExc_OSError, "Out of Memory");
if (!decoders_dict) {
Py_DECREF(encoders_dict);
Py_DECREF(lib_info_dict);
return NULL;
}
__PyDict_SetItemString(lib_info_dict, "libheif", PyUnicode_FromString(heif_get_version()));
Expand Down
Loading