pikl 0.2.8 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/History.txt +9 -0
  2. data/License.txt +0 -0
  3. data/Manifest.txt +17 -17
  4. data/README.txt +0 -0
  5. data/config/hoe.rb +9 -6
  6. data/config/requirements.rb +0 -0
  7. data/ext/pikl/extconf.rb +0 -0
  8. data/ext/pikl/pikl.h +617 -465
  9. data/ext/pikl/pikl_affine.c +38 -91
  10. data/ext/pikl/pikl_affine.h +0 -0
  11. data/ext/pikl/pikl_bitmap.c +0 -0
  12. data/ext/pikl/pikl_bitmap.h +0 -0
  13. data/ext/pikl/pikl_blur.c +4 -8
  14. data/ext/pikl/pikl_blur.h +0 -0
  15. data/ext/pikl/pikl_camera.c +218 -0
  16. data/ext/pikl/{pikl_effect3.h → pikl_camera.h} +2 -2
  17. data/ext/pikl/pikl_composite.c +175 -0
  18. data/ext/pikl/pikl_composite.h +12 -0
  19. data/ext/pikl/pikl_decrease.c +110 -45
  20. data/ext/pikl/pikl_decrease.h +0 -7
  21. data/ext/pikl/pikl_divide.c +116 -0
  22. data/ext/pikl/pikl_divide.h +11 -0
  23. data/ext/pikl/pikl_effect.c +583 -151
  24. data/ext/pikl/pikl_effect.h +32 -6
  25. data/ext/pikl/pikl_enhance.c +274 -0
  26. data/ext/pikl/pikl_enhance.h +20 -0
  27. data/ext/pikl/pikl_io.c +174 -23
  28. data/ext/pikl/pikl_io.h +0 -0
  29. data/ext/pikl/pikl_jpeg.c +0 -0
  30. data/ext/pikl/pikl_jpeg.h +0 -0
  31. data/ext/pikl/pikl_pattern.c +383 -357
  32. data/ext/pikl/pikl_pattern.h +0 -0
  33. data/ext/pikl/pikl_pixel.c +173 -0
  34. data/ext/pikl/{pikl_trim.h → pikl_pixel.h} +2 -2
  35. data/ext/pikl/pikl_png.c +0 -0
  36. data/ext/pikl/pikl_png.h +0 -0
  37. data/ext/pikl/pikl_private.h +12 -5
  38. data/ext/pikl/pikl_resize.c +0 -0
  39. data/ext/pikl/pikl_resize.h +0 -0
  40. data/ext/pikl/pikl_rotate.c +409 -51
  41. data/ext/pikl/pikl_rotate.h +8 -0
  42. data/ext/pikl/pikl_scrap.c +263 -483
  43. data/ext/pikl/pikl_scrap.h +0 -0
  44. data/ext/pikl/pikl_special.c +168 -0
  45. data/ext/pikl/{pikl_effect4.h → pikl_special.h} +2 -2
  46. data/ext/pikl/pikl_voronoi.c +320 -0
  47. data/ext/pikl/pikl_voronoi.h +37 -0
  48. data/lib/pikl.rb +4 -2
  49. data/lib/pikl/color.rb +47 -0
  50. data/lib/pikl/const.rb +106 -22
  51. data/lib/pikl/errors.rb +0 -0
  52. data/lib/pikl/ext.rb +115 -8
  53. data/lib/pikl/filter.rb +371 -0
  54. data/lib/pikl/image.rb +124 -117
  55. data/lib/pikl/version.rb +2 -2
  56. data/setup.rb +0 -0
  57. data/test/sample.jpg +0 -0
  58. data/test/test_helper.rb +0 -0
  59. data/test/test_pikl_image.rb +0 -14
  60. data/test/test_pikl_image2.rb +541 -0
  61. metadata +35 -23
  62. data/ext/pikl/decrease/fsdither.h +0 -554
  63. data/ext/pikl/decrease/median.c +0 -1179
  64. data/ext/pikl/decrease/median.h +0 -7
  65. data/ext/pikl/decrease/neuquan5.c +0 -563
  66. data/ext/pikl/decrease/neuquant.h +0 -62
  67. data/ext/pikl/decrease/wu.c +0 -447
  68. data/ext/pikl/decrease/wu.h +0 -7
  69. data/ext/pikl/pikl_effect2.c +0 -240
  70. data/ext/pikl/pikl_effect2.h +0 -55
  71. data/ext/pikl/pikl_effect3.c +0 -266
  72. data/ext/pikl/pikl_effect4.c +0 -495
  73. data/ext/pikl/pikl_rotate2.c +0 -312
  74. data/ext/pikl/pikl_rotate2.h +0 -19
  75. data/ext/pikl/pikl_trim.c +0 -28
File without changes
@@ -0,0 +1,168 @@
1
+ #include "pikl_special.h"
2
+
3
+ //=============================================================================
4
+ // pkl_edgeposter
5
+ //=============================================================================
6
+ PKLExport int pkl_edgeposter(PKLImage pkl, int level, double low, double high, double coeff, int edge)
7
+ {
8
+ if(pkl_posterize(pkl, level)) return(1);
9
+ if(pkl_noisecut(pkl)) return(1);
10
+ //if(pkl_brightness(pkl, up)) return(1);
11
+ if(pkl_level(pkl, low, high, coeff)) return(1);
12
+ if(pkl_edgepaint(pkl, edge)) return(1);
13
+ return(0);
14
+ }
15
+
16
+ //=============================================================================
17
+ // pkl_crayon
18
+ //=============================================================================
19
+ PKLExport int pkl_crayon(PKLImage pkl, double factor, int bv1, int bv2, int alpha)
20
+ {
21
+ PKLImage img;
22
+
23
+ //�I���W�i���̃R�s�[������Ă���
24
+ img = pkl_dup(pkl);
25
+
26
+ //�I���W�i������֊s���o
27
+ pkl_rinkaku(pkl, factor);
28
+
29
+ //���x���␳�őN�₩���𑝂�(�{���͍ʓx��������H)
30
+ pkl_level(img, 1.5, 1.5, 1.0);
31
+
32
+ //�g�U����
33
+ if(bv1>1)
34
+ pkl_noise(img, bv1);
35
+ if(bv2>1)
36
+ pkl_noise(img, bv2);
37
+
38
+ //����
39
+ pkl_alphablend(pkl, img, 0, 0, alpha);
40
+
41
+ pkl_close(img);
42
+ return(0);
43
+ }
44
+
45
+ //=============================================================================
46
+ // rinkaku
47
+ //=============================================================================
48
+ PKLExport int pkl_rinkaku(PKLImage pkl, double factor)
49
+ {
50
+ PKLImage g1, g2;
51
+ unsigned char *gray;
52
+ double v, ff[PKL_COLOR];
53
+ int edg, sbl, i, j, k, store;
54
+ int mask25[5*5] =
55
+ { -1, -2, -3, -2, -1,
56
+ -2, -3, -4, -3, -2,
57
+ -3, -4, 60, -4, -3,
58
+ -2, -3, -4, -3, -2,
59
+ -1, -2, -3, -2, -1 };
60
+
61
+ if(factor<5.0 || factor>80.0) return(1);
62
+
63
+ for(i=0; i<PKL_COLOR; i++)
64
+ ff[i] = factor * sin((double)i * M_PI/160);
65
+
66
+ //�O���[�C���[�W�����
67
+ gray = malloc(pkl->width*pkl->height);
68
+ if(!gray) return(1);
69
+
70
+ /* convert grayscale */
71
+ for(i=0; i<pkl->width*pkl->height; i++){
72
+ store=0;
73
+ for(k=0; k<pkl->channel; k++)
74
+ store += pkl->image[i*pkl->channel+k];
75
+ gray[i] = PKL_COLOR_CLIP(store/pkl->channel);
76
+ }
77
+
78
+ //�I���W�i���̃R�s�[�쐬
79
+ g1 = pkl_dup(pkl);
80
+ g2 = pkl_dup(pkl);
81
+
82
+ //�R�s�[1�ɑ΂���
83
+ // �O���[�X�P�[�������֊s���o�����x���␳
84
+ //pkl_gray(g1, PKL_GRAY_AVE);
85
+ free(g1->image);
86
+ g1->image = malloc(pkl->width*pkl->height);
87
+ memcpy(g1->image, gray, pkl->width*pkl->height);
88
+ g1->channel=1;
89
+ g1->color=PKL_GRAYSCALE;
90
+ //pkl_edge(g1, 10);
91
+ pkl_emboss2(g1, mask25, 5, 5, 1.0, 255);
92
+ pkl_level(g1, 0.015, 0.015, 1.0);
93
+
94
+ //�R�s�[2�΂���
95
+ // �֊s���o���O���[�X�P�[���������x���␳
96
+ pkl_contour(g2);
97
+ //pkl_gray(g2, PKL_GRAY_AVE);
98
+ free(g2->image);
99
+ g2->image = malloc(pkl->width*pkl->height);
100
+ memcpy(g2->image, gray, pkl->width*pkl->height);
101
+ g2->channel=1;
102
+ g2->color=PKL_GRAYSCALE;
103
+ pkl_level(g2, 1.5, 1.5, 1.0);
104
+
105
+ for(i=0; i<pkl->height; i++){
106
+ for(j=0; j<pkl->width; j++){
107
+ edg = 255 - g1->image[i*pkl->width+j];
108
+ sbl = 255 - g2->image[i*pkl->width+j];
109
+ v = sqrt(edg * sbl);
110
+ v = v - ff[(int)v];
111
+ for(k=0; k<pkl->channel; k++)
112
+ pkl->image[(i*pkl->width+j)*pkl->channel+k] = PKL_COLOR_CLIP(255-v);
113
+ }
114
+ }
115
+
116
+ free(gray);
117
+ pkl_close(g1);
118
+ pkl_close(g2);
119
+ return(0);
120
+ }
121
+
122
+ //=============================================================================
123
+ // pkl_hydrangea
124
+ //=============================================================================
125
+ PKLExport int pkl_hydrangea(PKLImage pkl, int zone, double low, double high, double coeff, double mil, double env)
126
+ {
127
+ //�{���m�C����
128
+ if(pkl_voronoi_zone(pkl, zone, NULL, 0)) return(1);
129
+
130
+ //���x���␳
131
+ if(pkl_level(pkl, low, high, coeff)) return(1);
132
+
133
+ //�J���[�G���{�X
134
+ if(pkl_color_emboss(pkl, mil, env)) return (1);
135
+
136
+ return(0);
137
+ }
138
+
139
+ //=============================================================================
140
+ // pkl_alphaedge
141
+ //=============================================================================
142
+ PKLExport int pkl_alphaedge(PKLImage pkl, int level, double low, double high, double coeff, int threshold, int alpha)
143
+ {
144
+ PKLImage img;
145
+
146
+ //�|�X�^���C�Y���m�C�Y����
147
+ if(pkl_posterize(pkl, level)) return(1);
148
+ if(pkl_noisecut(pkl)) return(1);
149
+
150
+ //�R�s�[
151
+ img = pkl_dup(pkl);
152
+ //�R�s�[�����x���␳
153
+ if(pkl_level(img, low, high, coeff)) return(1);
154
+
155
+ //�I���W�i����P���J���[�A�b�v
156
+ if(pkl_brightness(pkl, 50)) return(1);
157
+ //�֊s���o
158
+ if(pkl_edge(pkl, threshold)){
159
+ pkl_close(img);
160
+ return(1);
161
+ }
162
+
163
+ //����
164
+ pkl_alphablend(pkl, img, 0, 0, alpha);
165
+
166
+ pkl_close(img);
167
+ return(0);
168
+ }
@@ -1,5 +1,5 @@
1
- #ifndef _LIB_PIKL_EFFECT4_
2
- #define _LIB_PIKL_EFFECT4_
1
+ #ifndef _LIB_PIKL_TEST_
2
+ #define _LIB_PIKL_TEST_
3
3
 
4
4
  #include <stdio.h>
5
5
  #include <stdlib.h>
@@ -0,0 +1,320 @@
1
+ #include "pikl_voronoi.h"
2
+
3
+ //=============================================================================
4
+ // voronoi_zone_query
5
+ //=============================================================================
6
+ static void voronoi_zone_query(PKLImage pkl, struct VoronoiPoint *vptr, int *id, int zone, int xzone, int yzone)
7
+ {
8
+ struct VoronoiPoint *p;
9
+ int i, j, k, tx, ty, xx, yy, minIx, minIy;
10
+ double d, mind;
11
+
12
+ //母点を生成
13
+ #ifdef WIN32
14
+ srand(1);
15
+ #else
16
+ srand48(1);
17
+ #endif
18
+ p = vptr;
19
+ for(i=0; i<yzone; i++){
20
+ for(j=0; j<xzone; j++){
21
+ #ifdef WIN32
22
+ tx = j * zone + rand()%zone;
23
+ ty = i * zone + rand()%zone;
24
+ #else
25
+ tx = j * zone + lrand48()%zone;
26
+ ty = i * zone + lrand48()%zone;
27
+ #endif
28
+ p->x = tx>=pkl->width ? pkl->width-1 : tx;
29
+ p->y = ty>=pkl->height ? pkl->height-1 : ty;
30
+ p++;
31
+ }
32
+ }
33
+
34
+ for(i=0; i<pkl->height; i++){
35
+ yy = i/zone;
36
+ for(j=0; j<pkl->width; j++){
37
+ xx = j/zone;
38
+ mind=10000000;
39
+ minIx=minIy=0;
40
+
41
+ //カレントピクセルに最も近い母点を探す
42
+ for(ty=yy-1; ty<=yy+1; ty++){
43
+ if(ty<0 || ty>yzone-1) continue;
44
+ for(tx=xx-1; tx<=xx+1; tx++){
45
+ if(tx<0 || tx>xzone-1) continue;
46
+ d = (vptr[ty*xzone+tx].x-j)*(vptr[ty*xzone+tx].x-j) +
47
+ (vptr[ty*xzone+tx].y-i)*(vptr[ty*xzone+tx].y-i);
48
+ if(d < mind){
49
+ mind = d;
50
+ minIx = tx;
51
+ minIy = ty;
52
+ }
53
+ }
54
+ }
55
+
56
+ for(k=0; k<pkl->channel; k++)
57
+ vptr[minIy*xzone+minIx].color[k] += pkl->image[(i*pkl->width+j)*pkl->channel+k];
58
+ vptr[minIy*xzone+minIx].count++;
59
+
60
+ //各ピクセルのボロノイIDをセット
61
+ id[i*pkl->width+j] = minIy*xzone+minIx;
62
+ }
63
+ }
64
+ }
65
+
66
+ //=============================================================================
67
+ // pkl_voronoi_zone
68
+ //=============================================================================
69
+ PKLExport int pkl_voronoi_zone(PKLImage pkl, int zone, PKLColor bordercolor, int test)
70
+ {
71
+ struct VoronoiPoint *vptr, *p;
72
+ int xzone, yzone, *id;
73
+ int i, j, k, tx, ty;
74
+
75
+ if(zone < 2) return(1);
76
+ if(zone>=pkl->width || zone>=pkl->height) return(1);
77
+ xzone = pkl->width/zone;
78
+ if((pkl->width%zone) != 0) xzone++;
79
+ yzone = pkl->height/zone;
80
+ if((pkl->height%zone) != 0) yzone++;
81
+
82
+ //ボロノイ管理データ
83
+ vptr = malloc(sizeof(struct VoronoiPoint) * xzone*yzone);
84
+ memset(vptr, 0, sizeof(struct VoronoiPoint) * xzone*yzone);
85
+
86
+ //各座標のボロノイIDを格納するデータ
87
+ id = malloc(sizeof(int) * pkl->width*pkl->height);
88
+
89
+ //ボロノイ管理データを作る
90
+ voronoi_zone_query(pkl, vptr, id, zone, xzone, yzone);
91
+
92
+ if(test){
93
+ if(bordercolor){
94
+ //分割シュミレーション(母点を置く)
95
+ memset(pkl->image, 0xff, pkl->width*pkl->height*pkl->channel);
96
+ for(i=0; i<xzone*yzone; i++)
97
+ memcpy(&pkl->image[(vptr[i].y*pkl->width+vptr[i].x)*pkl->channel], bordercolor->color, pkl->channel);
98
+ }
99
+ }else{
100
+ //各ボロノイポイントの平均色算出
101
+ for(ty=0; ty<yzone; ty++){
102
+ for(tx=0; tx<xzone; tx++){
103
+ if(vptr[ty*xzone+tx].count == 0) continue;
104
+ p = &vptr[ty*xzone+tx];
105
+ for(k=0; k<pkl->channel; k++)
106
+ p->ave[k] = PKL_COLOR_CLIP(p->color[k]/p->count);
107
+ }
108
+ }
109
+ //色を設定
110
+ for(i=0; i<pkl->height; i++)
111
+ for(j=0; j<pkl->width; j++)
112
+ memcpy(&pkl->image[(i*pkl->width+j)*pkl->channel], vptr[id[i*pkl->width+j]].ave, pkl->channel);
113
+ }
114
+
115
+ //境界線を引く
116
+ if(bordercolor){
117
+ int currentId, hit=0;
118
+ for(j=0; j<pkl->height; j++){
119
+ for(i=0; i<pkl->width; i++){
120
+ hit=0;
121
+ currentId = id[j*pkl->width+i];
122
+ if(i-1>=0 && currentId!=id[j*pkl->width+i-1]) hit++;
123
+ if(i+1<pkl->width && currentId!=id[j*pkl->width+i+1]) hit++;
124
+ if(j-1>=0 && currentId!=id[(j-1)*pkl->width+i+1]) hit++;
125
+ if(j+1<pkl->height && currentId!=id[(j+1)*pkl->width+i+1]) hit++;
126
+ if(hit)
127
+ memcpy(&pkl->image[(j*pkl->width+i)*pkl->channel], bordercolor->color, pkl->channel);
128
+ }
129
+ }
130
+ }
131
+ free(id);
132
+ free(vptr);
133
+ return(0);
134
+ }
135
+
136
+ //=============================================================================
137
+ // vcompare
138
+ //=============================================================================
139
+ static int vcompare(const void *a, const void *b)
140
+ {
141
+ struct VORONOI *t1 = (struct VORONOI *)a;
142
+ struct VORONOI *t2 = (struct VORONOI *)b;
143
+
144
+ if(t1->y == t2->y)
145
+ return(t1->x - t2->x);
146
+ return(t1->y - t2->y);
147
+ }
148
+
149
+ //=============================================================================
150
+ // voronoi_setid
151
+ //=============================================================================
152
+ static void voronoi_setid(int *ary, int id)
153
+ {
154
+ int i;
155
+
156
+ for(i=0; i<VORONOI_CNT; i++){
157
+ if(ary[i] == -1){
158
+ ary[i] = id;
159
+ return;
160
+ }
161
+ }
162
+ }
163
+
164
+ //=============================================================================
165
+ // voronoi_count_query
166
+ //=============================================================================
167
+ static void voronoi_count_query(PKLImage pkl, struct VORONOI *kp, int *ip, int count)
168
+ {
169
+ int i, j, k, min_id, pre_id;
170
+ double d, dx, dy, min_d;
171
+
172
+ //母点をランダムに生成する
173
+ #ifdef WIN32
174
+ srand((long)count);
175
+ #else
176
+ srand48((long)count);
177
+ #endif
178
+ for(i=0; i<count; i++){
179
+ #ifdef WIN32
180
+ kp[i].x = rand() % pkl->width;
181
+ kp[i].y = rand() % pkl->height;
182
+ #else
183
+ kp[i].x = lrand48() % pkl->width;
184
+ kp[i].y = lrand48() % pkl->height;
185
+ #endif
186
+ kp[i].id = i;
187
+ }
188
+
189
+ //生成した母点座標を左上から右下に向かってソートする
190
+ qsort(kp, count, sizeof(struct VORONOI), vcompare);
191
+
192
+ min_id = 0; //最初の母点ID
193
+ pre_id = 0; //前ピクセルの母点ID
194
+
195
+ //各母点の最近傍の母点を探索する
196
+ for(j=0; j<pkl->height; j++){
197
+ for(i=0; i<pkl->width; i++){
198
+ // 前ピクセルの母点との距離を求める
199
+ dx = kp[pre_id].x-i;
200
+ dy = kp[pre_id].y-j;
201
+ min_d = sqrt(dx*dx+dy*dy);
202
+
203
+ //現在のピクセルの右上により近い母点があるか検索
204
+ for(k=pre_id-1; k>=0 && (kp[k].y>=j-min_d); k--){
205
+ if(kp[k].x >= i && kp[k].x <= i+min_d){
206
+ dx = kp[k].x-i;
207
+ dy = kp[k].y-j;
208
+ d = sqrt(dx*dx+dy*dy);
209
+ if(d<min_d){
210
+ min_id=k;
211
+ min_d=d;
212
+ }
213
+ }
214
+ }
215
+ //現在のピクセルの右下により近い母点があるか検索
216
+ for(k=pre_id+1; k<count && (kp[k].y<=j+min_d); k++){
217
+ if(kp[k].x >= i && kp[k].x <= i+min_d){
218
+ dx = kp[k].x-i;
219
+ dy = kp[k].y-j;
220
+ d = sqrt(dx*dx+dy*dy);
221
+ if(d<min_d){
222
+ min_id=k;
223
+ min_d=d;
224
+ }
225
+ }
226
+ }
227
+ //最も近くにある母点のIDを設定する
228
+ if(pre_id != min_id){
229
+ voronoi_setid(kp[pre_id].next, min_id);
230
+ voronoi_setid(kp[min_id].next, pre_id);
231
+ }
232
+
233
+ //現在の座標のIDに決定したボロノイ管理IDを設定する
234
+ ip[j*pkl->width+i] = min_id;
235
+ pre_id = min_id;
236
+ }
237
+ }
238
+ }
239
+
240
+ //=============================================================================
241
+ // pkl_voronoi_count
242
+ //=============================================================================
243
+ PKLExport int pkl_voronoi_count(PKLImage pkl, int count, PKLColor bordercolor, int test)
244
+ {
245
+ struct VORONOI *kp;
246
+ int i, j, k, *ip;
247
+
248
+ //母点数の閾値
249
+ if(count < 10) return(1);
250
+
251
+ //各座標の母点IDを格納する領域
252
+ ip = malloc(sizeof(int) * pkl->width * pkl->height);
253
+ memset(ip, -1, sizeof(int) * pkl->width * pkl->height);
254
+
255
+ //母点管理領域(母点数分用意)
256
+ kp = malloc(sizeof(struct VORONOI) * count);
257
+ memset(kp, 0, sizeof(struct VORONOI) * count);
258
+ for(i=0; i<count; i++)
259
+ memset(kp[i].next, -1, sizeof(int)*VORONOI_CNT);
260
+
261
+ //ボロノイ管理データを作る
262
+ voronoi_count_query(pkl, kp, ip, count);
263
+
264
+ if(test){
265
+ if(bordercolor){
266
+ //分割シュミレーション(母点を置く)
267
+ memset(pkl->image, 0xff, pkl->width*pkl->height*pkl->channel);
268
+ for(i=0; i<count; i++)
269
+ memcpy(&pkl->image[(kp[i].y*pkl->width+kp[i].x)*pkl->channel], bordercolor->color, pkl->channel);
270
+ }
271
+ }else{
272
+ //ボロノイ分割されたので、各セルの平均色を算出するためにセルの色を累積する
273
+ for(j=0; j<pkl->height; j++) {
274
+ for(i=0; i<pkl->width; i++) {
275
+ //ipを参照することで、現在の座標がどのIDに所属するかわかる
276
+ if(ip[j*pkl->width+i] == -1) continue;
277
+ //IDごとに色を累積する
278
+ kp[ ip[j*pkl->width+i] ].count++;
279
+ for(k=0; k<pkl->channel; k++)
280
+ kp[ ip[j*pkl->width+i] ].color[k] += pkl->image[(j*pkl->width+i)*pkl->channel+k];
281
+ }
282
+ }
283
+
284
+ //各セルの平均色を作る
285
+ for(i=0; i<count; i++){
286
+ for(k=0; k<pkl->channel; k++){
287
+ if(kp[i].count!=0)
288
+ kp[i].color[k] = PKL_COLOR_CLIP(kp[i].color[k]/kp[i].count);
289
+ }
290
+ }
291
+
292
+ //色を置く
293
+ for(j=0; j<pkl->height; j++)
294
+ for(i=0; i<pkl->width; i++)
295
+ for(k=0; k<pkl->channel; k++)
296
+ pkl->image[(j*pkl->width+i)*pkl->channel+k] = kp[ ip[j*pkl->width+i] ].color[k];
297
+ }
298
+
299
+ //境界線を引く
300
+ if(bordercolor){
301
+ int currentId, hit=0;
302
+ for(j=0; j<pkl->height; j++){
303
+ for(i=0; i<pkl->width; i++){
304
+ hit=0;
305
+ currentId = ip[j*pkl->width+i];
306
+ if(i-1>=0 && currentId!=ip[j*pkl->width+i-1]) hit++;
307
+ if(i+1<pkl->width && currentId!=ip[j*pkl->width+i+1]) hit++;
308
+ if(j-1>=0 && currentId!=ip[(j-1)*pkl->width+i+1]) hit++;
309
+ if(j+1<pkl->height && currentId!=ip[(j+1)*pkl->width+i+1]) hit++;
310
+ if(hit)
311
+ memcpy(&pkl->image[(j*pkl->width+i)*pkl->channel], bordercolor->color, pkl->channel);
312
+ }
313
+ }
314
+ }
315
+
316
+ free(kp);
317
+ free(ip);
318
+ return(0);
319
+ }
320
+