imageops.c (142 lines of code) (raw):
#include "accimage.h"
#include <stdlib.h>
#include <ippi.h>
void image_copy_deinterleave(ImageObject* self, unsigned char* output_buffer) {
unsigned char* channel_buffers[3] = {
output_buffer,
output_buffer + self->height * self->width,
output_buffer + 2 * self->height * self->width
};
IppiSize roi = { self->width, self->height };
IppStatus ipp_status = ippiCopy_8u_C3P3R(
self->buffer + (self->y_offset * self->row_stride + self->x_offset) * self->channels,
self->row_stride * self->channels,
channel_buffers, self->width, roi);
if (ipp_status != ippStsNoErr) {
PyErr_Format(PyExc_SystemError, "ippiCopy_8u_C3P3R failed with status %d", ipp_status);
}
}
void image_copy_deinterleave_float(ImageObject* self, float* output_buffer) {
unsigned char* tmp_buffer = NULL;
IppiSize roi = { self->width, self->height };
tmp_buffer = malloc(self->height * self->width * self->channels);
if (!tmp_buffer) {
PyErr_NoMemory();
goto cleanup;
}
image_copy_deinterleave(self, tmp_buffer);
if (PyErr_Occurred()) {
goto cleanup;
}
IppStatus ipp_status = ippiConvert_8u32f_C3R(
tmp_buffer, self->width * self->channels,
output_buffer, self->width * self->channels * sizeof(float),
roi);
if (ipp_status != ippStsNoErr) {
PyErr_Format(PyExc_SystemError, "ippiConvert_8u32f_C3R failed with status %d", ipp_status);
}
Ipp32f value[3] = {255.0f, 255.0f, 255.0f};
ipp_status = ippiDivC_32f_C3IR(
value, output_buffer, self->width * self->channels * sizeof(float),
roi);
if (ipp_status != ippStsNoErr) {
PyErr_Format(PyExc_SystemError, "ippiDivC_32f_C3IR failed with status %d", ipp_status);
}
cleanup:
free(tmp_buffer);
}
void image_resize(ImageObject* self, int new_height, int new_width, int antialiasing) {
IppStatus ipp_status;
unsigned char* new_buffer = NULL;
IppiSize old_size = { self->width, self->height };
IppiSize new_size = { new_width, new_height };
IppiPoint new_offset = { 0, 0 };
int specification_size = 0, initialization_buffer_size = 0, scratch_buffer_size = 0;
IppiResizeSpec_32f* specification = NULL;
Ipp8u* scratch_buffer = NULL;
Ipp8u* initialization_buffer = NULL;
new_buffer = malloc(new_height * new_width * self->channels);
if (new_buffer == NULL) {
PyErr_NoMemory();
goto cleanup;
}
ipp_status = ippiResizeGetSize_8u(old_size, new_size, ippLinear, antialiasing,
&specification_size, &initialization_buffer_size);
if (ipp_status != ippStsNoErr) {
PyErr_Format(PyExc_SystemError,
"ippiResizeGetSize_8u failed with status %d", ipp_status);
goto cleanup;
}
initialization_buffer = malloc(initialization_buffer_size);
if (initialization_buffer == NULL) {
PyErr_NoMemory();
goto cleanup;
}
specification = malloc(specification_size);
if (specification == NULL) {
PyErr_NoMemory();
goto cleanup;
}
if (antialiasing) {
ipp_status = ippiResizeAntialiasingLinearInit(
old_size, new_size, specification, initialization_buffer);
} else {
ipp_status = ippiResizeLinearInit_8u(old_size, new_size, specification);
}
if (ipp_status != ippStsNoErr) {
PyErr_Format(PyExc_SystemError,
"ippiResizeLinearInit_8u failed with status %d", ipp_status);
goto cleanup;
}
ipp_status = ippiResizeGetBufferSize_8u(specification, new_size, self->channels, &scratch_buffer_size);
if (ipp_status != ippStsNoErr) {
PyErr_Format(PyExc_SystemError,
"ippiResizeGetBufferSize_8u failed with status %d", ipp_status);
goto cleanup;
}
scratch_buffer = malloc(scratch_buffer_size);
if (scratch_buffer == NULL) {
PyErr_NoMemory();
goto cleanup;
}
if (antialiasing) {
ipp_status = ippiResizeAntialiasing_8u_C3R(
self->buffer + (self->y_offset * self->row_stride + self->x_offset) * self->channels,
self->row_stride * self->channels,
new_buffer, new_width * self->channels, new_offset, new_size,
ippBorderRepl, NULL, specification, scratch_buffer);
} else {
ipp_status = ippiResizeLinear_8u_C3R(
self->buffer + (self->y_offset * self->row_stride + self->x_offset) * self->channels,
self->row_stride * self->channels,
new_buffer, new_width * self->channels, new_offset, new_size,
ippBorderRepl, NULL, specification, scratch_buffer);
}
if (ipp_status != ippStsNoErr) {
PyErr_Format(PyExc_SystemError,
"ippiResizeLinear_8u_C3R failed with status %d", ipp_status);
goto cleanup;
}
free(self->buffer);
self->buffer = new_buffer;
new_buffer = NULL;
self->height = new_height;
self->width = new_width;
self->row_stride = new_width;
self->x_offset = 0;
self->y_offset = 0;
cleanup:
free(new_buffer);
free(specification);
free(initialization_buffer);
free(scratch_buffer);
}
void image_flip_left_right(ImageObject* self) {
IppiSize roi = { self->width, self->height };
IppStatus ipp_status = ippiMirror_8u_C3IR(
self->buffer + (self->y_offset * self->row_stride + self->x_offset) * self->channels,
self->row_stride * self->channels,
roi, ippAxsVertical);
if (ipp_status != ippStsNoErr)
PyErr_Format(PyExc_SystemError, "ippiMirror_8u_C3IR failed with status %d", ipp_status);
}