static PyObject* _curve_apply(PyObject *self, PyObject *args) { char *image_mode; PyObject *buffer = NULL, *curve_a = NULL, *curve_r = NULL, *curve_g = NULL, *curve_b = NULL; if (!PyArg_ParseTuple(args, "sOOOOO:apply", &image_mode, &buffer, &curve_a, &curve_r, &curve_g, &curve_b)) { return NULL; } unsigned char *points_a = cubic_spline_interpolation(get_curve(curve_a), PyTuple_Size(curve_a), 256), *points_r = cubic_spline_interpolation(get_curve(curve_r), PyTuple_Size(curve_r), 256), *points_g = cubic_spline_interpolation(get_curve(curve_g), PyTuple_Size(curve_g), 256), *points_b = cubic_spline_interpolation(get_curve(curve_b), PyTuple_Size(curve_b), 256); Py_ssize_t size = PyString_Size(buffer); unsigned char *ptr = (unsigned char *) PyString_AsString(buffer); int num_bytes = bytes_per_pixel(image_mode); int r_idx = rgb_order(image_mode, 'R'), g_idx = rgb_order(image_mode, 'G'), b_idx = rgb_order(image_mode, 'B'), i = 0, r, g, b; size -= num_bytes; for (; i <= size; i += num_bytes) { r = ptr[i + r_idx]; g = ptr[i + g_idx]; b = ptr[i + b_idx]; r = points_r[r]; g = points_g[g]; b = points_b[b]; r = points_a[r]; g = points_a[g]; b = points_a[b]; ptr[i + r_idx] = ADJUST_COLOR(r); ptr[i + g_idx] = ADJUST_COLOR(g); ptr[i + b_idx] = ADJUST_COLOR(b); } free(points_a); free(points_r); free(points_g); free(points_b); Py_INCREF(buffer); return buffer; }
static PyObject* _rgb_apply(PyObject *self, PyObject *args) { PyObject *buffer = NULL, *image_mode = NULL, *delta_r = NULL, *delta_g = NULL, *delta_b = NULL; if (!PyArg_UnpackTuple(args, "apply", 5, 5, &image_mode, &delta_r, &delta_g, &delta_b, &buffer)) { return NULL; } char *image_mode_str = PyString_AsString(image_mode); Py_ssize_t size = PyString_Size(buffer); unsigned char *ptr = (unsigned char *) PyString_AsString(buffer); int delta_r_int = (int) PyInt_AsLong(delta_r), delta_g_int = (int) PyInt_AsLong(delta_g), delta_b_int = (int) PyInt_AsLong(delta_b); delta_r_int = (255 * delta_r_int) / 100; delta_g_int = (255 * delta_g_int) / 100; delta_b_int = (255 * delta_b_int) / 100; int r_idx = rgb_order(image_mode_str, 'R'), g_idx = rgb_order(image_mode_str, 'G'), b_idx = rgb_order(image_mode_str, 'B'), i = 0, r, g, b; size -= 3; for (; i <= size; i += 3) { r = ptr[i + r_idx]; g = ptr[i + g_idx]; b = ptr[i + b_idx]; r += delta_r_int; g += delta_g_int; b += delta_b_int; ptr[i + r_idx] = ADJUST_COLOR(r); ptr[i + g_idx] = ADJUST_COLOR(g); ptr[i + b_idx] = ADJUST_COLOR(b); } Py_INCREF(buffer); return buffer; }
static PyObject* _sharpen_apply(PyObject *self, PyObject *args) { PyObject *buffer_py = NULL, *image_mode = NULL, *amount = NULL, *radius = NULL, *luminance_only = NULL, *width_py = NULL, *height_py = NULL; if (!PyArg_UnpackTuple(args, "apply", 7, 7, &image_mode, &width_py, &height_py, &amount, &radius, &luminance_only, &buffer_py)) { return NULL; } char *image_mode_str = PyString_AsString(image_mode); unsigned char *buffer = (unsigned char *) PyString_AsString(buffer_py); double amount_double = PyFloat_AsDouble(amount), radius_double = PyFloat_AsDouble(radius); char luminance_only_bool = (char) PyObject_IsTrue(luminance_only); int width = (int) PyInt_AsLong(width_py), height = (int) PyInt_AsLong(height_py); int num_bytes = bytes_per_pixel(image_mode_str); int r_idx = rgb_order(image_mode_str, 'R'), g_idx = rgb_order(image_mode_str, 'G'), b_idx = rgb_order(image_mode_str, 'B'); sharpen_info info = { amount_double, radius_double, luminance_only_bool, width, height, buffer, {r_idx, g_idx, b_idx}, num_bytes }; run_sharpen(&info); Py_INCREF(buffer_py); return buffer_py; }
static PyObject* _composite_apply(PyObject *self, PyObject *args) { PyObject *py_image1 = NULL, *py_image2 = NULL, *image_mode = NULL, *w1, *h1, *w2, *h2, *py_x, *py_y, *py_merge = NULL; if (!PyArg_UnpackTuple(args, "apply", 9, 10, &image_mode, &py_image1, &w1, &h1, &py_image2, &w2, &h2, &py_x, &py_y, &py_merge)) { return NULL; } char *image_mode_str = PyString_AsString(image_mode); unsigned char *ptr1 = (unsigned char *) PyString_AsString(py_image1), *aux1 = NULL; unsigned char *ptr2 = (unsigned char *) PyString_AsString(py_image2), *aux2 = NULL; int width1 = (int) PyInt_AsLong(w1), width2 = (int) PyInt_AsLong(w2), height1 = (int) PyInt_AsLong(h1), height2 = (int) PyInt_AsLong(h2), x_pos = (int) PyInt_AsLong(py_x), y_pos = (int) PyInt_AsLong(py_y), merge = 1; if (py_merge) { merge = (int) PyInt_AsLong(py_merge); } int num_bytes = bytes_per_pixel(image_mode_str); int r_idx = rgb_order(image_mode_str, 'R'), g_idx = rgb_order(image_mode_str, 'G'), b_idx = rgb_order(image_mode_str, 'B'), a_idx = rgb_order(image_mode_str, 'A'); int r1, g1, b1, a1, r2, g2, b2, a2, x, y, start_x = 0, start_y = 0; double delta, r, g, b, a; if (x_pos < 0) { start_x = -x_pos; x_pos = 0; } if (y_pos < 0) { start_y = -y_pos; y_pos = 0; } for (y = start_y; y < height2; ++y) { if (y_pos - start_y + y >= height1) { break; } int line_offset1 = ((y_pos + y - start_y) * width1 * num_bytes), line_offset2 = (y * width2 * num_bytes); aux1 = ptr1 + line_offset1 + (x_pos * num_bytes); aux2 = ptr2 + line_offset2 + (start_x * num_bytes); for (x = start_x; x < width2; ++x, aux1 += num_bytes, aux2 += num_bytes) { if (x_pos - start_x + x >= width1) { break; } r1 = aux1[r_idx]; g1 = aux1[g_idx]; b1 = aux1[b_idx]; a1 = aux1[a_idx]; r2 = aux2[r_idx]; g2 = aux2[g_idx]; b2 = aux2[b_idx]; a2 = aux2[a_idx]; a1 = 255 - a1; a2 = 255 - a2; if (merge) { delta = (a2 / MAX_RGB_DOUBLE) * (a1 / MAX_RGB_DOUBLE); a = MAX_RGB_DOUBLE * delta; delta = 1.0 - delta; delta = (delta <= SMALL_DOUBLE) ? 1.0 : (1.0 / delta); r = delta * ALPHA_COMPOSITE_COLOR_CHANNEL(r2, a2, r1, a1); g = delta * ALPHA_COMPOSITE_COLOR_CHANNEL(g2, a2, g1, a1); b = delta * ALPHA_COMPOSITE_COLOR_CHANNEL(b2, a2, b1, a1); } else { if (a1 == 0) { r = r2; g = g2; b = b2; a = a2; } else { r = r1; g = g1; b = b1; a = a1; } } a = 255.0 - a; aux1[r_idx] = ADJUST_COLOR_DOUBLE(r); aux1[g_idx] = ADJUST_COLOR_DOUBLE(g); aux1[b_idx] = ADJUST_COLOR_DOUBLE(b); aux1[a_idx] = ADJUST_COLOR_DOUBLE(a); } } Py_INCREF(py_image1); return py_image1; }
static PyObject* _equalize_apply(PyObject *self, PyObject *args) { PyObject *buffer = NULL, *image_mode = NULL; if (!PyArg_UnpackTuple(args, "apply", 2, 2, &image_mode, &buffer)) { return NULL; } char *image_mode_str = PyString_AsString(image_mode); Py_ssize_t original_size = PyString_Size(buffer); Py_ssize_t size = PyString_Size(buffer); unsigned char *ptr = (unsigned char *) PyString_AsString(buffer); int num_bytes = bytes_per_pixel(image_mode_str); int area = (int)(size / num_bytes); int r_idx = rgb_order(image_mode_str, 'R'), g_idx = rgb_order(image_mode_str, 'G'), b_idx = rgb_order(image_mode_str, 'B'); int redHist[256] = {0}; int redCumFreq[256] = {0}; int greenHist[256] = {0}; int greenCumFreq[256] = {0}; int blueHist[256] = {0}; int blueCumFreq[256] = {0}; int i = 0, r, g, b; size -= num_bytes; for (; i <= size; i += num_bytes) { r = ptr[i + r_idx]; g = ptr[i + g_idx]; b = ptr[i + b_idx]; redHist[r]++; greenHist[g]++; blueHist[b]++; } int rCum = 0, gCum = 0, bCum = 0; for(i = 0; i < 256; i++) { rCum += redHist[i]; gCum += greenHist[i]; bCum += blueHist[i]; if (redHist[i] > 0) { redCumFreq[i] = rCum; } if (greenHist[i] > 0) { greenCumFreq[i] = gCum; } if (blueHist[i] > 0) { blueCumFreq[i] = bCum; } } int rMinCdf=0, gMinCdf=0, bMinCdf=0; i = 0; while (rMinCdf == 0 && gMinCdf == 0 && bMinCdf == 0 && i < 256) { if (rMinCdf == 0 && redCumFreq[i] != 0) { rMinCdf = redCumFreq[i]; } if (gMinCdf == 0 && greenCumFreq[i] != 0) { gMinCdf = greenCumFreq[i]; } if (bMinCdf == 0 && blueCumFreq[i] != 0) { bMinCdf = blueCumFreq[i]; } i++; } size = original_size; size -= num_bytes; for (i = 0; i <= size; i += num_bytes) { r = ptr[i + r_idx]; g = ptr[i + g_idx]; b = ptr[i + b_idx]; // Refer to http://en.wikipedia.org/wiki/Histogram_equalization float rColor = (((float)redCumFreq[r] - rMinCdf) / (area - rMinCdf)) * 255.0f; float gColor = (((float)greenCumFreq[g] - gMinCdf) / (area - gMinCdf)) * 255.0f; float bColor = (((float)blueCumFreq[b] - bMinCdf) / (area - bMinCdf)) * 255.0f; ptr[i + r_idx] = rColor; ptr[i + g_idx] = gColor; ptr[i + b_idx] = bColor; } Py_INCREF(buffer); return buffer; }