loaders: JPG: Fix bussy loop on corrupted file.
[gfxprim.git] / libs / filters / GP_Edge.c
blobded2cde930fa7058e0e41625dbe0e4495ce105e3
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
18 * *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
23 #include <math.h>
25 #include "core/GP_Debug.h"
26 #include "core/GP_GetPutPixel.h"
28 #include "filters/GP_Linear.h"
29 #include "filters/GP_EdgeDetection.h"
32 * Apply prewitt operator.
34 static int prewitt(const GP_Pixmap *src, GP_Pixmap *dx, GP_Pixmap *dy,
35 GP_ProgressCallback *callback)
37 float smooth_kern[3] = {1, 1, 1,};
38 float grad_kern[3] = {-1, 0, 1};
40 if (GP_FilterVHLinearConvolution_Raw(src, 0, 0, src->w, src->h,
41 dx, 0, 0,
42 smooth_kern, 3, 1,
43 grad_kern, 3, 1, callback))
44 return 1;
46 if (GP_FilterVHLinearConvolution_Raw(src, 0, 0, src->w, src->h,
47 dy, 0, 0,
48 grad_kern, 3, 1,
49 smooth_kern, 3, 1, callback))
50 return 1;
52 return 0;
56 * Apply sobel operator.
58 static int sobel(const GP_Pixmap *src, GP_Pixmap *dx, GP_Pixmap *dy,
59 GP_ProgressCallback *callback)
61 float dx_kern[] = {
62 -1, 0, 1,
63 -2, 0, 2,
64 -1, 0, 1,
67 GP_ConvolutionParams dx_conv = {
68 .src = src,
69 .x_src = 0,
70 .y_src = 0,
71 .w_src = src->w,
72 .h_src = src->h,
73 .dst = dx,
74 .x_dst = 0,
75 .y_dst = 0,
76 .kernel = dx_kern,
77 .kw = 3,
78 .kh = 3,
79 .kern_div = 1,
80 .callback = callback,
83 if (GP_FilterConvolution_Raw(&dx_conv))
84 return 1;
86 float dy_kern[] = {
87 -1, -2, -1,
88 0, 0, 0,
89 1, 2, 1,
92 GP_ConvolutionParams dy_conv = {
93 .src = src,
94 .x_src = 0,
95 .y_src = 0,
96 .w_src = src->w,
97 .h_src = src->h,
98 .dst = dy,
99 .x_dst = 0,
100 .y_dst = 0,
101 .kernel = dy_kern,
102 .kw = 3,
103 .kh = 3,
104 .kern_div = 1,
105 .callback = callback,
108 if (GP_FilterConvolution_Raw(&dy_conv))
109 return 1;
111 return 0;
114 static int edge_detect(const GP_Pixmap *src,
115 GP_Pixmap **E, GP_Pixmap **Phi, int type,
116 GP_ProgressCallback *callback)
118 //TODO
119 GP_ASSERT(src->pixel_type == GP_PIXEL_RGB888);
121 GP_Pixmap *dx, *dy;
123 dx = GP_PixmapCopy(src, 0);
124 dy = GP_PixmapCopy(src, 0);
126 if (dx == NULL || dy == NULL)
127 goto err0;
129 switch (type) {
130 case 0:
131 if (sobel(src, dx, dy, callback))
132 goto err0;
133 break;
134 case 1:
135 if (prewitt(src, dx, dy, callback))
136 goto err0;
137 break;
138 default:
139 goto err0;
142 uint32_t i, j;
144 for (i = 0; i < src->w; i++) {
145 for (j = 0; j < src->h; j++) {
146 GP_Pixel pix_x = GP_GetPixel_Raw_24BPP(dx, i, j);
147 GP_Pixel pix_y = GP_GetPixel_Raw_24BPP(dy, i, j);
148 int Rx, Gx, Bx;
149 int Ry, Gy, By;
150 int RE, GE, BE;
151 int RPhi, GPhi, BPhi;
153 Rx = GP_Pixel_GET_R_RGB888(pix_x);
154 Gx = GP_Pixel_GET_G_RGB888(pix_x);
155 Bx = GP_Pixel_GET_B_RGB888(pix_x);
157 Ry = GP_Pixel_GET_R_RGB888(pix_y);
158 Gy = GP_Pixel_GET_G_RGB888(pix_y);
159 By = GP_Pixel_GET_B_RGB888(pix_y);
161 RE = sqrt(Rx*Rx + Ry*Ry) + 0.5;
162 GE = sqrt(Gx*Gx + Gy*Gy) + 0.5;
163 BE = sqrt(Bx*Bx + By*By) + 0.5;
165 GP_PutPixel_Raw_24BPP(dx, i, j,
166 GP_Pixel_CREATE_RGB888(RE, GE, BE));
168 if (Rx != 0 && Ry != 0)
169 RPhi = ((atan2(Rx, Ry) + M_PI) * 255)/(2*M_PI);
170 else
171 RPhi = 0;
173 if (Gx != 0 && Gy != 0)
174 GPhi = ((atan2(Gx, Gy) + M_PI) * 255)/(2*M_PI);
175 else
176 GPhi = 0;
178 if (Bx != 0 && By != 0)
179 BPhi = ((atan2(Bx, By) + M_PI) * 255)/(2*M_PI);
180 else
181 BPhi = 0;
183 GP_PutPixel_Raw_24BPP(dy, i, j,
184 GP_Pixel_CREATE_RGB888(RPhi, GPhi, BPhi));
188 if (Phi != NULL)
189 *Phi = dy;
190 else
191 GP_PixmapFree(dy);
193 if (E != NULL)
194 *E = dx;
195 else
196 GP_PixmapFree(dx);
198 return 0;
199 err0:
200 GP_PixmapFree(dx);
201 GP_PixmapFree(dy);
202 return 1;
205 int GP_FilterEdgeSobel(const GP_Pixmap *src,
206 GP_Pixmap **E, GP_Pixmap **Phi,
207 GP_ProgressCallback *callback)
209 GP_DEBUG(1, "Sobel edge detection image %ux%u", src->w, src->h);
211 return edge_detect(src, E, Phi, 0, callback);
214 int GP_FilterEdgePrewitt(const GP_Pixmap *src,
215 GP_Pixmap **E, GP_Pixmap **Phi,
216 GP_ProgressCallback *callback)
218 GP_DEBUG(1, "Prewitt edge detection image %ux%u", src->w, src->h);
220 return edge_detect(src, E, Phi, 1, callback);