選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

296 行
7.9 KiB

  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. * convolution.c: generic convolution functions
  16. */
  17. #include "config.h"
  18. #include "common.h"
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <math.h>
  23. #include "pipi.h"
  24. #include "pipi_internals.h"
  25. static pipi_image_t *pipi_convolution_standard(pipi_image_t *src,
  26. int m, int n, double mat[]);
  27. static pipi_image_t *pipi_convolution_separable(pipi_image_t *src,
  28. int m, double hvec[],
  29. int n, double vvec[]);
  30. pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
  31. {
  32. double tmp;
  33. double *hvec, *vvec;
  34. int i, j, besti = -1, bestj = -1;
  35. /* Find the cell with the largest value */
  36. tmp = 0.0;
  37. for(i = 0; i < m * n; i++)
  38. if(mat[i] * mat[i] > tmp)
  39. {
  40. tmp = mat[i] * mat[i];
  41. besti = i % m;
  42. bestj = i / m;
  43. }
  44. /* If the kernel is empty, return an empty picture */
  45. if(tmp == 0.0)
  46. return pipi_new(src->w, src->h);
  47. /* Check whether the matrix rank is 1 */
  48. for(j = 0; j < n; j++)
  49. {
  50. if(j == bestj)
  51. continue;
  52. for(i = 0; i < m; i++)
  53. {
  54. double p, q;
  55. if(i == besti)
  56. continue;
  57. p = mat[j * m + i] * mat[bestj * m + besti];
  58. q = mat[bestj * m + i] * mat[j * m + besti];
  59. if(fabs(p - q) > 0.0001 * 0.0001)
  60. return pipi_convolution_standard(src, m, n, mat);
  61. }
  62. }
  63. /* Matrix rank is 1! Separate the filter */
  64. /* FIXME: memleak */
  65. hvec = malloc(m * sizeof(double));
  66. vvec = malloc(n * sizeof(double));
  67. tmp = sqrt(fabs(mat[bestj * m + besti]));
  68. for(i = 0; i < m; i++)
  69. hvec[i] = mat[bestj * m + i] / tmp;
  70. for(j = 0; j < n; j++)
  71. vvec[j] = mat[j * m + besti] / tmp;
  72. return pipi_convolution_separable(src, m, hvec, n, vvec);
  73. }
  74. static pipi_image_t *pipi_convolution_standard(pipi_image_t *src,
  75. int m, int n, double mat[])
  76. {
  77. pipi_image_t *dst;
  78. pipi_pixels_t *srcp, *dstp;
  79. float *srcdata, *dstdata;
  80. int x, y, i, j, w, h, gray;
  81. w = src->w;
  82. h = src->h;
  83. gray = (src->last_modified == PIPI_PIXELS_Y_F);
  84. srcp = gray ? pipi_getpixels(src, PIPI_PIXELS_Y_F)
  85. : pipi_getpixels(src, PIPI_PIXELS_RGBA_F);
  86. srcdata = (float *)srcp->pixels;
  87. dst = pipi_new(w, h);
  88. dstp = gray ? pipi_getpixels(dst, PIPI_PIXELS_Y_F)
  89. : pipi_getpixels(dst, PIPI_PIXELS_RGBA_F);
  90. dstdata = (float *)dstp->pixels;
  91. for(y = 0; y < h; y++)
  92. {
  93. for(x = 0; x < w; x++)
  94. {
  95. if(gray)
  96. {
  97. double Y = 0.;
  98. int x2, y2;
  99. for(j = 0; j < n; j++)
  100. {
  101. y2 = y + j - n / 2;
  102. if(y2 < 0) y2 = 0;
  103. else if(y2 >= h) y2 = h - 1;
  104. for(i = 0; i < m; i++)
  105. {
  106. x2 = x + i - m / 2;
  107. if(x2 < 0) x2 = 0;
  108. else if(x2 >= w) x2 = w - 1;
  109. Y += mat[j * m + i] * srcdata[y2 * w + x2];
  110. }
  111. }
  112. dstdata[y * w + x] = Y;
  113. }
  114. else
  115. {
  116. double R = 0., G = 0., B = 0.;
  117. int x2, y2, off = 4 * (y * w + x);
  118. for(j = 0; j < n; j++)
  119. {
  120. y2 = y + j - n / 2;
  121. if(y2 < 0) y2 = 0;
  122. else if(y2 >= h) y2 = h - 1;
  123. for(i = 0; i < m; i++)
  124. {
  125. double f = mat[j * m + i];
  126. x2 = x + i - m / 2;
  127. if(x2 < 0) x2 = 0;
  128. else if(x2 >= w) x2 = w - 1;
  129. R += f * srcdata[(y2 * w + x2) * 4];
  130. G += f * srcdata[(y2 * w + x2) * 4 + 1];
  131. B += f * srcdata[(y2 * w + x2) * 4 + 2];
  132. }
  133. }
  134. dstdata[off] = R;
  135. dstdata[off + 1] = G;
  136. dstdata[off + 2] = B;
  137. }
  138. }
  139. }
  140. return dst;
  141. }
  142. static pipi_image_t *pipi_convolution_separable(pipi_image_t *src,
  143. int m, double hvec[],
  144. int n, double vvec[])
  145. {
  146. pipi_image_t *dst;
  147. pipi_pixels_t *srcp, *dstp;
  148. float *srcdata, *dstdata;
  149. double *buffer;
  150. int x, y, i, j, w, h, gray;
  151. w = src->w;
  152. h = src->h;
  153. gray = (src->last_modified == PIPI_PIXELS_Y_F);
  154. srcp = gray ? pipi_getpixels(src, PIPI_PIXELS_Y_F)
  155. : pipi_getpixels(src, PIPI_PIXELS_RGBA_F);
  156. srcdata = (float *)srcp->pixels;
  157. dst = pipi_new(w, h);
  158. dstp = gray ? pipi_getpixels(dst, PIPI_PIXELS_Y_F)
  159. : pipi_getpixels(dst, PIPI_PIXELS_RGBA_F);
  160. dstdata = (float *)dstp->pixels;
  161. buffer = malloc(w * h * (gray ? 1 : 4) * sizeof(double));
  162. for(y = 0; y < h; y++)
  163. {
  164. for(x = 0; x < w; x++)
  165. {
  166. if(gray)
  167. {
  168. double Y = 0.;
  169. int x2;
  170. for(i = 0; i < m; i++)
  171. {
  172. x2 = x + i - m / 2;
  173. if(x2 < 0) x2 = 0;
  174. else if(x2 >= w) x2 = w - 1;
  175. Y += hvec[i] * srcdata[y * w + x2];
  176. }
  177. buffer[y * w + x] = Y;
  178. }
  179. else
  180. {
  181. double R = 0., G = 0., B = 0.;
  182. int x2, off = 4 * (y * w + x);
  183. for(i = 0; i < m; i++)
  184. {
  185. double f = hvec[i];
  186. x2 = x + i - m / 2;
  187. if(x2 < 0) x2 = 0;
  188. else if(x2 >= w) x2 = w - 1;
  189. R += f * srcdata[(y * w + x2) * 4];
  190. G += f * srcdata[(y * w + x2) * 4 + 1];
  191. B += f * srcdata[(y * w + x2) * 4 + 2];
  192. }
  193. buffer[off] = R;
  194. buffer[off + 1] = G;
  195. buffer[off + 2] = B;
  196. }
  197. }
  198. }
  199. for(y = 0; y < h; y++)
  200. {
  201. for(x = 0; x < w; x++)
  202. {
  203. if(gray)
  204. {
  205. double Y = 0.;
  206. int y2;
  207. for(j = 0; j < n; j++)
  208. {
  209. y2 = y + j - n / 2;
  210. if(y2 < 0) y2 = 0;
  211. else if(y2 >= h) y2 = h - 1;
  212. Y += vvec[j] * buffer[y2 * w + x];
  213. }
  214. dstdata[y * w + x] = Y;
  215. }
  216. else
  217. {
  218. double R = 0., G = 0., B = 0.;
  219. int y2, off = 4 * (y * w + x);
  220. for(j = 0; j < n; j++)
  221. {
  222. double f = vvec[j];
  223. y2 = y + j - n / 2;
  224. if(y2 < 0) y2 = 0;
  225. else if(y2 >= h) y2 = h - 1;
  226. R += f * buffer[(y2 * w + x) * 4];
  227. G += f * buffer[(y2 * w + x) * 4 + 1];
  228. B += f * buffer[(y2 * w + x) * 4 + 2];
  229. }
  230. dstdata[off] = R;
  231. dstdata[off + 1] = G;
  232. dstdata[off + 2] = B;
  233. }
  234. }
  235. }
  236. free(buffer);
  237. return dst;
  238. }