This source file includes following definitions.
- gdImageCrop
- gdImageCropAuto
- gdImageCropThreshold
- gdGuessBackgroundColorFromCorners
- gdColorMatch
- colors_equal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <gd.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26
27 static int gdGuessBackgroundColorFromCorners(gdImagePtr im, int *color);
28 static int gdColorMatch(gdImagePtr im, int col1, int col2, float threshold);
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 gdImagePtr gdImageCrop(gdImagePtr src, const gdRectPtr crop)
44 {
45 gdImagePtr dst;
46 int y;
47
48
49 if (src->trueColor) {
50 dst = gdImageCreateTrueColor(crop->width, crop->height);
51 if (dst == NULL) {
52 return NULL;
53 }
54 gdImageSaveAlpha(dst, 1);
55 } else {
56 dst = gdImageCreate(crop->width, crop->height);
57 if (dst == NULL) {
58 return NULL;
59 }
60 gdImagePaletteCopy(dst, src);
61 }
62 dst->transparent = src->transparent;
63
64
65 if (crop->x < 0 || crop->x>=src->sx || crop->y<0 || crop->y>=src->sy) {
66 return dst;
67 }
68
69
70 if ((src->sx - crop->width) < crop->x) {
71 crop->width = src->sx - crop->x;
72 }
73 if ((src->sy - crop->height) < crop->y) {
74 crop->height = src->sy - crop->y;
75 }
76
77 #if 0
78 printf("rect->x: %i\nrect->y: %i\nrect->width: %i\nrect->height: %i\n", crop->x, crop->y, crop->width, crop->height);
79 #endif
80 y = crop->y;
81 if (src->trueColor) {
82 unsigned int dst_y = 0;
83 while (y < (crop->y + crop->height)) {
84
85 memcpy(dst->tpixels[dst_y++], src->tpixels[y++] + crop->x, crop->width * 4);
86 }
87 } else {
88 int x;
89 for (y = crop->y; y < (crop->y + crop->height); y++) {
90 for (x = crop->x; x < (crop->x + crop->width); x++) {
91 dst->pixels[y - crop->y][x - crop->x] = src->pixels[y][x];
92 }
93 }
94 }
95 return dst;
96 }
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 gdImagePtr gdImageCropAuto(gdImagePtr im, const unsigned int mode)
115 {
116 const int width = gdImageSX(im);
117 const int height = gdImageSY(im);
118
119 int x,y;
120 int color, corners, match;
121 gdRect crop;
122
123 crop.x = 0;
124 crop.y = 0;
125 crop.width = 0;
126 crop.height = 0;
127
128 switch (mode) {
129 case GD_CROP_TRANSPARENT:
130 color = gdImageGetTransparent(im);
131 break;
132
133 case GD_CROP_BLACK:
134 color = gdImageColorClosestAlpha(im, 0, 0, 0, 0);
135 break;
136
137 case GD_CROP_WHITE:
138 color = gdImageColorClosestAlpha(im, 255, 255, 255, 0);
139 break;
140
141 case GD_CROP_SIDES:
142 corners = gdGuessBackgroundColorFromCorners(im, &color);
143 break;
144
145 case GD_CROP_DEFAULT:
146 default:
147 color = gdImageGetTransparent(im);
148 if (color == -1) {
149 corners = gdGuessBackgroundColorFromCorners(im, &color);
150 }
151 break;
152 }
153
154
155
156
157
158 match = 1;
159 for (y = 0; match && y < height; y++) {
160 for (x = 0; match && x < width; x++) {
161 int c2 = gdImageGetPixel(im, x, y);
162 match = (color == c2);
163 }
164 }
165
166
167
168
169 if (y == height - 1) {
170 return NULL;
171 }
172
173 crop.y = y -1;
174 match = 1;
175 for (y = height - 1; match && y >= 0; y--) {
176 for (x = 0; match && x < width; x++) {
177 match = (color == gdImageGetPixel(im, x,y));
178 }
179 }
180
181 if (y == 0) {
182 crop.height = height - crop.y + 1;
183 } else {
184 crop.height = y - crop.y + 2;
185 }
186
187 match = 1;
188 for (x = 0; match && x < width; x++) {
189 for (y = 0; match && y < crop.y + crop.height - 1; y++) {
190 match = (color == gdImageGetPixel(im, x,y));
191 }
192 }
193 crop.x = x - 1;
194
195 match = 1;
196 for (x = width - 1; match && x >= 0; x--) {
197 for (y = 0; match && y < crop.y + crop.height - 1; y++) {
198 match = (color == gdImageGetPixel(im, x,y));
199 }
200 }
201 crop.width = x - crop.x + 2;
202 if (crop.x <= 0 || crop.y <= 0 || crop.width <= 0 || crop.height <= 0) {
203 return NULL;
204 }
205 return gdImageCrop(im, &crop);
206 }
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 gdImagePtr gdImageCropThreshold(gdImagePtr im, const unsigned int color, const float threshold)
228 {
229 const int width = gdImageSX(im);
230 const int height = gdImageSY(im);
231
232 int x,y;
233 int match;
234 gdRect crop;
235
236 crop.x = 0;
237 crop.y = 0;
238 crop.width = 0;
239 crop.height = 0;
240
241
242 if (threshold > 1.0) {
243 return NULL;
244 }
245
246
247
248
249
250 match = 1;
251 for (y = 0; match && y < height; y++) {
252 for (x = 0; match && x < width; x++) {
253 match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
254 }
255 }
256
257
258
259
260
261 if (y == height - 1) {
262 return NULL;
263 }
264
265 crop.y = y -1;
266 match = 1;
267 for (y = height - 1; match && y >= 0; y--) {
268 for (x = 0; match && x < width; x++) {
269 match = (gdColorMatch(im, color, gdImageGetPixel(im, x, y), threshold)) > 0;
270 }
271 }
272
273 if (y == 0) {
274 crop.height = height - crop.y + 1;
275 } else {
276 crop.height = y - crop.y + 2;
277 }
278
279 match = 1;
280 for (x = 0; match && x < width; x++) {
281 for (y = 0; match && y < crop.y + crop.height - 1; y++) {
282 match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
283 }
284 }
285 crop.x = x - 1;
286
287 match = 1;
288 for (x = width - 1; match && x >= 0; x--) {
289 for (y = 0; match && y < crop.y + crop.height - 1; y++) {
290 match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
291 }
292 }
293 crop.width = x - crop.x + 2;
294
295 return gdImageCrop(im, &crop);
296 }
297
298
299
300
301
302
303
304 static int gdGuessBackgroundColorFromCorners(gdImagePtr im, int *color)
305 {
306 const int tl = gdImageGetPixel(im, 0, 0);
307 const int tr = gdImageGetPixel(im, gdImageSX(im) - 1, 0);
308 const int bl = gdImageGetPixel(im, 0, gdImageSY(im) -1);
309 const int br = gdImageGetPixel(im, gdImageSX(im) - 1, gdImageSY(im) -1);
310
311 if (tr == bl && tr == br) {
312 *color = tr;
313 return 3;
314 } else if (tl == bl && tl == br) {
315 *color = tl;
316 return 3;
317 } else if (tl == tr && tl == br) {
318 *color = tl;
319 return 3;
320 } else if (tl == tr && tl == bl) {
321 *color = tl;
322 return 3;
323 } else if (tl == tr || tl == bl || tl == br) {
324 *color = tl;
325 return 2;
326 } else if (tr == bl) {
327 *color = tr;
328 return 2;
329 } else if (br == bl) {
330 *color = bl;
331 return 2;
332 } else {
333 register int r,b,g,a;
334
335 r = (int)(0.5f + (gdImageRed(im, tl) + gdImageRed(im, tr) + gdImageRed(im, bl) + gdImageRed(im, br)) / 4);
336 g = (int)(0.5f + (gdImageGreen(im, tl) + gdImageGreen(im, tr) + gdImageGreen(im, bl) + gdImageGreen(im, br)) / 4);
337 b = (int)(0.5f + (gdImageBlue(im, tl) + gdImageBlue(im, tr) + gdImageBlue(im, bl) + gdImageBlue(im, br)) / 4);
338 a = (int)(0.5f + (gdImageAlpha(im, tl) + gdImageAlpha(im, tr) + gdImageAlpha(im, bl) + gdImageAlpha(im, br)) / 4);
339 *color = gdImageColorClosestAlpha(im, r, g, b, a);
340 return 0;
341 }
342 }
343
344 static int gdColorMatch(gdImagePtr im, int col1, int col2, float threshold)
345 {
346 const int dr = gdImageRed(im, col1) - gdImageRed(im, col2);
347 const int dg = gdImageGreen(im, col1) - gdImageGreen(im, col2);
348 const int db = gdImageBlue(im, col1) - gdImageBlue(im, col2);
349 const int da = gdImageAlpha(im, col1) - gdImageAlpha(im, col2);
350 const double dist = sqrt(dr * dr + dg * dg + db * db + da * da);
351 const double dist_perc = sqrt(dist / (255^2 + 255^2 + 255^2));
352 return (dist_perc <= threshold);
353
354 }
355
356
357
358
359
360
361
362 #if 0
363 static int colors_equal (const int col1, const in col2)
364 {
365
366 }
367 #endif