pikl 0.2.8-x86-mswin32 → 0.3.0-x86-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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/pikl.h +617 -465
  8. data/ext/pikl/pikl_affine.c +38 -91
  9. data/ext/pikl/pikl_affine.h +0 -0
  10. data/ext/pikl/pikl_bitmap.c +0 -0
  11. data/ext/pikl/pikl_bitmap.h +0 -0
  12. data/ext/pikl/pikl_blur.c +4 -8
  13. data/ext/pikl/pikl_blur.h +0 -0
  14. data/ext/pikl/pikl_camera.c +218 -0
  15. data/ext/pikl/{pikl_effect3.h → pikl_camera.h} +2 -2
  16. data/ext/pikl/pikl_composite.c +175 -0
  17. data/ext/pikl/pikl_composite.h +12 -0
  18. data/ext/pikl/pikl_decrease.c +110 -45
  19. data/ext/pikl/pikl_decrease.h +0 -7
  20. data/ext/pikl/pikl_divide.c +116 -0
  21. data/ext/pikl/pikl_divide.h +11 -0
  22. data/ext/pikl/pikl_effect.c +583 -151
  23. data/ext/pikl/pikl_effect.h +32 -6
  24. data/ext/pikl/pikl_enhance.c +274 -0
  25. data/ext/pikl/pikl_enhance.h +20 -0
  26. data/ext/pikl/pikl_io.c +174 -23
  27. data/ext/pikl/pikl_io.h +0 -0
  28. data/ext/pikl/pikl_jpeg.c +0 -0
  29. data/ext/pikl/pikl_jpeg.h +0 -0
  30. data/ext/pikl/pikl_pattern.c +383 -357
  31. data/ext/pikl/pikl_pattern.h +0 -0
  32. data/ext/pikl/pikl_pixel.c +173 -0
  33. data/ext/pikl/{pikl_trim.h → pikl_pixel.h} +2 -2
  34. data/ext/pikl/pikl_png.c +0 -0
  35. data/ext/pikl/pikl_png.h +0 -0
  36. data/ext/pikl/pikl_private.h +12 -5
  37. data/ext/pikl/pikl_resize.c +0 -0
  38. data/ext/pikl/pikl_resize.h +0 -0
  39. data/ext/pikl/pikl_rotate.c +409 -51
  40. data/ext/pikl/pikl_rotate.h +8 -0
  41. data/ext/pikl/pikl_scrap.c +263 -483
  42. data/ext/pikl/pikl_scrap.h +0 -0
  43. data/ext/pikl/pikl_special.c +168 -0
  44. data/ext/pikl/{pikl_effect4.h → pikl_special.h} +2 -2
  45. data/ext/pikl/pikl_voronoi.c +320 -0
  46. data/ext/pikl/pikl_voronoi.h +37 -0
  47. data/lib/pikl.rb +4 -2
  48. data/lib/pikl/color.rb +47 -0
  49. data/lib/pikl/const.rb +106 -22
  50. data/lib/pikl/errors.rb +0 -0
  51. data/lib/pikl/ext.rb +115 -8
  52. data/lib/pikl/filter.rb +371 -0
  53. data/lib/pikl/image.rb +124 -117
  54. data/lib/pikl/pikl.dll +0 -0
  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
+