| 1 | /* |
|---|
| 2 | * libpipi Proper image processing implementation library |
|---|
| 3 | * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org> |
|---|
| 4 | * All Rights Reserved |
|---|
| 5 | * |
|---|
| 6 | * $Id$ |
|---|
| 7 | * |
|---|
| 8 | * This library is free software. It comes without any warranty, to |
|---|
| 9 | * the extent permitted by applicable law. You can redistribute it |
|---|
| 10 | * and/or modify it under the terms of the Do What The Fuck You Want |
|---|
| 11 | * To Public License, Version 2, as published by Sam Hocevar. See |
|---|
| 12 | * http://sam.zoy.org/wtfpl/COPYING for more details. |
|---|
| 13 | */ |
|---|
| 14 | |
|---|
| 15 | /* |
|---|
| 16 | * convolution_template.h: convolution templates |
|---|
| 17 | * required macros: |
|---|
| 18 | * FUNC1 standard function name |
|---|
| 19 | * FUNC2 separable function name |
|---|
| 20 | * PIXEL pixel type |
|---|
| 21 | * FLAGS 1 (grayscale) |
|---|
| 22 | * 2 (loop) |
|---|
| 23 | */ |
|---|
| 24 | |
|---|
| 25 | static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[]); |
|---|
| 26 | static pipi_image_t *FUNC2(pipi_image_t *src, int m, double hvec[], |
|---|
| 27 | int n, double vvec[]); |
|---|
| 28 | |
|---|
| 29 | static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[]) |
|---|
| 30 | { |
|---|
| 31 | pipi_image_t *dst; |
|---|
| 32 | pipi_pixels_t *srcp, *dstp; |
|---|
| 33 | PIXEL *srcdata, *dstdata; |
|---|
| 34 | int x, y, i, j, w, h; |
|---|
| 35 | |
|---|
| 36 | w = src->w; |
|---|
| 37 | h = src->h; |
|---|
| 38 | |
|---|
| 39 | srcp = FLAG_GRAY ? pipi_getpixels(src, PIPI_PIXELS_Y_F) |
|---|
| 40 | : pipi_getpixels(src, PIPI_PIXELS_RGBA_F); |
|---|
| 41 | srcdata = (PIXEL *)srcp->pixels; |
|---|
| 42 | |
|---|
| 43 | dst = pipi_new(w, h); |
|---|
| 44 | dstp = FLAG_GRAY ? pipi_getpixels(dst, PIPI_PIXELS_Y_F) |
|---|
| 45 | : pipi_getpixels(dst, PIPI_PIXELS_RGBA_F); |
|---|
| 46 | dstdata = (PIXEL *)dstp->pixels; |
|---|
| 47 | |
|---|
| 48 | for(y = 0; y < h; y++) |
|---|
| 49 | { |
|---|
| 50 | for(x = 0; x < w; x++) |
|---|
| 51 | { |
|---|
| 52 | if(FLAG_GRAY) |
|---|
| 53 | { |
|---|
| 54 | double Y = 0.; |
|---|
| 55 | int x2, y2; |
|---|
| 56 | |
|---|
| 57 | for(j = 0; j < n; j++) |
|---|
| 58 | { |
|---|
| 59 | y2 = y + j - n / 2; |
|---|
| 60 | if(y2 < 0) y2 = FLAG_WRAP ? (h - 1 - (-y2 - 1) % h) : 0; |
|---|
| 61 | else if(y2 >= h) y2 = FLAG_WRAP ? y2 % h : h - 1; |
|---|
| 62 | |
|---|
| 63 | for(i = 0; i < m; i++) |
|---|
| 64 | { |
|---|
| 65 | x2 = x + i - m / 2; |
|---|
| 66 | if(x2 < 0) x2 = FLAG_WRAP ? (w - 1 - (-x2 - 1) % w) : 0; |
|---|
| 67 | else if(x2 >= w) x2 = FLAG_WRAP ? x2 % w : w - 1; |
|---|
| 68 | |
|---|
| 69 | Y += mat[j * m + i] * srcdata[y2 * w + x2]; |
|---|
| 70 | } |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | dstdata[y * w + x] = Y; |
|---|
| 74 | } |
|---|
| 75 | else |
|---|
| 76 | { |
|---|
| 77 | double R = 0., G = 0., B = 0.; |
|---|
| 78 | int x2, y2, off = 4 * (y * w + x); |
|---|
| 79 | |
|---|
| 80 | for(j = 0; j < n; j++) |
|---|
| 81 | { |
|---|
| 82 | y2 = y + j - n / 2; |
|---|
| 83 | if(y2 < 0) y2 = FLAG_WRAP ? (h - 1 - (-y2 - 1) % h) : 0; |
|---|
| 84 | else if(y2 >= h) y2 = FLAG_WRAP ? y2 % h : h - 1; |
|---|
| 85 | |
|---|
| 86 | for(i = 0; i < m; i++) |
|---|
| 87 | { |
|---|
| 88 | double f = mat[j * m + i]; |
|---|
| 89 | |
|---|
| 90 | x2 = x + i - m / 2; |
|---|
| 91 | if(x2 < 0) x2 = FLAG_WRAP ? (w - 1 - (-x2 - 1) % w) : 0; |
|---|
| 92 | else if(x2 >= w) x2 = FLAG_WRAP ? x2 % w : w - 1; |
|---|
| 93 | |
|---|
| 94 | R += f * srcdata[(y2 * w + x2) * 4]; |
|---|
| 95 | G += f * srcdata[(y2 * w + x2) * 4 + 1]; |
|---|
| 96 | B += f * srcdata[(y2 * w + x2) * 4 + 2]; |
|---|
| 97 | } |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | dstdata[off] = R; |
|---|
| 101 | dstdata[off + 1] = G; |
|---|
| 102 | dstdata[off + 2] = B; |
|---|
| 103 | } |
|---|
| 104 | } |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | return dst; |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | static pipi_image_t *FUNC2(pipi_image_t *src, |
|---|
| 111 | int m, double hvec[], int n, double vvec[]) |
|---|
| 112 | { |
|---|
| 113 | pipi_image_t *dst; |
|---|
| 114 | pipi_pixels_t *srcp, *dstp; |
|---|
| 115 | PIXEL *srcdata, *dstdata; |
|---|
| 116 | double *buffer; |
|---|
| 117 | int x, y, i, j, w, h; |
|---|
| 118 | |
|---|
| 119 | w = src->w; |
|---|
| 120 | h = src->h; |
|---|
| 121 | |
|---|
| 122 | srcp = FLAG_GRAY ? pipi_getpixels(src, PIPI_PIXELS_Y_F) |
|---|
| 123 | : pipi_getpixels(src, PIPI_PIXELS_RGBA_F); |
|---|
| 124 | srcdata = (PIXEL *)srcp->pixels; |
|---|
| 125 | |
|---|
| 126 | dst = pipi_new(w, h); |
|---|
| 127 | dstp = FLAG_GRAY ? pipi_getpixels(dst, PIPI_PIXELS_Y_F) |
|---|
| 128 | : pipi_getpixels(dst, PIPI_PIXELS_RGBA_F); |
|---|
| 129 | dstdata = (PIXEL *)dstp->pixels; |
|---|
| 130 | |
|---|
| 131 | buffer = malloc(w * h * (FLAG_GRAY ? 1 : 4) * sizeof(double)); |
|---|
| 132 | |
|---|
| 133 | for(y = 0; y < h; y++) |
|---|
| 134 | { |
|---|
| 135 | for(x = 0; x < w; x++) |
|---|
| 136 | { |
|---|
| 137 | if(FLAG_GRAY) |
|---|
| 138 | { |
|---|
| 139 | double Y = 0.; |
|---|
| 140 | int x2; |
|---|
| 141 | |
|---|
| 142 | for(i = 0; i < m; i++) |
|---|
| 143 | { |
|---|
| 144 | x2 = x + i - m / 2; |
|---|
| 145 | if(x2 < 0) x2 = FLAG_WRAP ? (w - 1 - (-x2 - 1) % w) : 0; |
|---|
| 146 | else if(x2 >= w) x2 = FLAG_WRAP ? x2 % w : w - 1; |
|---|
| 147 | |
|---|
| 148 | Y += hvec[i] * srcdata[y * w + x2]; |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | buffer[y * w + x] = Y; |
|---|
| 152 | } |
|---|
| 153 | else |
|---|
| 154 | { |
|---|
| 155 | double R = 0., G = 0., B = 0.; |
|---|
| 156 | int x2, off = 4 * (y * w + x); |
|---|
| 157 | |
|---|
| 158 | for(i = 0; i < m; i++) |
|---|
| 159 | { |
|---|
| 160 | double f = hvec[i]; |
|---|
| 161 | |
|---|
| 162 | x2 = x + i - m / 2; |
|---|
| 163 | if(x2 < 0) x2 = FLAG_WRAP ? (w - 1 - (-x2 - 1) % w) : 0; |
|---|
| 164 | else if(x2 >= w) x2 = FLAG_WRAP ? x2 % w : w - 1; |
|---|
| 165 | |
|---|
| 166 | R += f * srcdata[(y * w + x2) * 4]; |
|---|
| 167 | G += f * srcdata[(y * w + x2) * 4 + 1]; |
|---|
| 168 | B += f * srcdata[(y * w + x2) * 4 + 2]; |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | buffer[off] = R; |
|---|
| 172 | buffer[off + 1] = G; |
|---|
| 173 | buffer[off + 2] = B; |
|---|
| 174 | } |
|---|
| 175 | } |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | for(y = 0; y < h; y++) |
|---|
| 179 | { |
|---|
| 180 | for(x = 0; x < w; x++) |
|---|
| 181 | { |
|---|
| 182 | if(FLAG_GRAY) |
|---|
| 183 | { |
|---|
| 184 | double Y = 0.; |
|---|
| 185 | int y2; |
|---|
| 186 | |
|---|
| 187 | for(j = 0; j < n; j++) |
|---|
| 188 | { |
|---|
| 189 | y2 = y + j - n / 2; |
|---|
| 190 | if(y2 < 0) y2 = FLAG_WRAP ? (h - 1 - (-y2 - 1) % h) : 0; |
|---|
| 191 | else if(y2 >= h) y2 = FLAG_WRAP ? y2 % h : h - 1; |
|---|
| 192 | |
|---|
| 193 | Y += vvec[j] * buffer[y2 * w + x]; |
|---|
| 194 | } |
|---|
| 195 | |
|---|
| 196 | dstdata[y * w + x] = Y; |
|---|
| 197 | } |
|---|
| 198 | else |
|---|
| 199 | { |
|---|
| 200 | double R = 0., G = 0., B = 0.; |
|---|
| 201 | int y2, off = 4 * (y * w + x); |
|---|
| 202 | |
|---|
| 203 | for(j = 0; j < n; j++) |
|---|
| 204 | { |
|---|
| 205 | double f = vvec[j]; |
|---|
| 206 | |
|---|
| 207 | y2 = y + j - n / 2; |
|---|
| 208 | if(y2 < 0) y2 = FLAG_WRAP ? (h - 1 - (-y2 - 1) % h) : 0; |
|---|
| 209 | else if(y2 >= h) y2 = FLAG_WRAP ? y2 % h : h - 1; |
|---|
| 210 | |
|---|
| 211 | R += f * buffer[(y2 * w + x) * 4]; |
|---|
| 212 | G += f * buffer[(y2 * w + x) * 4 + 1]; |
|---|
| 213 | B += f * buffer[(y2 * w + x) * 4 + 2]; |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | dstdata[off] = R; |
|---|
| 217 | dstdata[off + 1] = G; |
|---|
| 218 | dstdata[off + 2] = B; |
|---|
| 219 | } |
|---|
| 220 | } |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | free(buffer); |
|---|
| 224 | |
|---|
| 225 | return dst; |
|---|
| 226 | } |
|---|
| 227 | |
|---|