pikl 0.2.7-x86-mswin32 → 0.2.8-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,12 @@
1
+ #ifndef _LIB_PIKL_EFFECT4_
2
+ #define _LIB_PIKL_EFFECT4_
3
+
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <math.h>
8
+
9
+ #include "pikl.h"
10
+ #include "pikl_private.h"
11
+
12
+ #endif
@@ -0,0 +1,611 @@
1
+ #include "pikl_pattern.h"
2
+
3
+ static int pkl_pattern_draw_line(PKLImage pkl, double *wd, int pw, int ph);
4
+ static int pkl_pattern_draw_average(PKLImage pkl, double *wd, int pw, int ph);
5
+
6
+ //=============================================================================
7
+ // pkl_pattern_hexagon
8
+ //=============================================================================
9
+ PKLExport int pkl_pattern_hexagon(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE type)
10
+ {
11
+ double ww, hh, *wd;
12
+ int i, result;
13
+
14
+ wd = malloc(sizeof(double)*ph);
15
+ if(!wd) return(1);
16
+
17
+ ww = (double)pw;
18
+ hh = (double)ph;
19
+
20
+ /* パターン座標を構築する */
21
+ for(i=0; i<ph; i++){
22
+ if((double)i < hh/6.0){
23
+ wd[i] = ww * (double)i*6.0/hh;
24
+ }else
25
+ if((double)i < hh/2.0){
26
+ wd[i] = ww;
27
+ }else
28
+ if((double)i < hh*2.0/3.0){
29
+ wd[i] = ww*4.0 - ww*(double)i*6.0/hh;
30
+ }else{
31
+ wd[i] = 0.0;
32
+ }
33
+ }
34
+
35
+ /* 塗りタイプ別の処理 */
36
+ switch(type){
37
+ case PKL_PAINT_AVE:
38
+ result = pkl_pattern_draw_average(pkl, wd, pw, ph);
39
+ break;
40
+ case PKL_PAINT_LINE:
41
+ default:
42
+ result = pkl_pattern_draw_line(pkl, wd, pw, ph);
43
+ }
44
+
45
+ free(wd);
46
+ return(result);
47
+ }
48
+
49
+ //=============================================================================
50
+ // pkl_pattern_diamond
51
+ //=============================================================================
52
+ PKLExport int pkl_pattern_diamond(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE type)
53
+ {
54
+ double ww, hh, *wd;
55
+ int i, result;
56
+
57
+ wd = malloc(sizeof(double)*ph);
58
+ if(!wd) return(1);
59
+
60
+ ww = (double)pw;
61
+ hh = (double)ph;
62
+
63
+ /* パターン座標を構築する */
64
+ for(i=0; i<ph; i++){
65
+ if((double)i < hh/2.0){
66
+ wd[i] = ww*(double)i*2.0/hh;
67
+ }else{
68
+ wd[i] = ww*2.0 - ww*(double)i*2.0/hh;
69
+ }
70
+ }
71
+
72
+ /* 塗りタイプ別の処理 */
73
+ switch(type){
74
+ case PKL_PAINT_AVE:
75
+ result = pkl_pattern_draw_average(pkl, wd, pw, ph);
76
+ break;
77
+ case PKL_PAINT_LINE:
78
+ default:
79
+ result = pkl_pattern_draw_line(pkl, wd, pw, ph);
80
+ }
81
+
82
+ free(wd);
83
+ return(result);
84
+ }
85
+
86
+ //=============================================================================
87
+ // pkl_pattern_circle
88
+ //=============================================================================
89
+ PKLExport int pkl_pattern_circle(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE type)
90
+ {
91
+ double ww, hh, *wd;
92
+ int i, result;
93
+
94
+ wd = malloc(sizeof(double)*ph);
95
+ if(!wd) return(1);
96
+
97
+ ww = (double)pw;
98
+ hh = (double)ph;
99
+
100
+ /* パターン座標を構築する */
101
+ for(i=0; i<ph; i++){
102
+ if((double)i < hh/2.0){
103
+ wd[i] = ww*(double)i*2.0/hh - (ww/8.0)*sin((double)i*4.0/hh*M_PI);
104
+ }else{
105
+ wd[i] = ww*2.0 - ww*(double)i*2.0/hh + (ww/8.0)*sin((double)(i-hh/2.0)*4.0/hh*M_PI);
106
+ }
107
+ }
108
+
109
+ /* 塗りタイプ別の処理 */
110
+ switch(type){
111
+ case PKL_PAINT_AVE:
112
+ result = pkl_pattern_draw_average(pkl, wd, pw, ph);
113
+ break;
114
+ case PKL_PAINT_LINE:
115
+ default:
116
+ result = pkl_pattern_draw_line(pkl, wd, pw, ph);
117
+ }
118
+
119
+ free(wd);
120
+ return(result);
121
+ }
122
+
123
+ //=============================================================================
124
+ // pkl_pattern_brick
125
+ //=============================================================================
126
+ PKLExport int pkl_pattern_brick(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE type)
127
+ {
128
+ double ww, hh, *wd;
129
+ int i, result;
130
+
131
+ wd = malloc(sizeof(double)*ph);
132
+ if(!wd) return(1);
133
+
134
+ ww = (double)pw;
135
+ hh = (double)ph;
136
+
137
+ /* パターン座標を構築する */
138
+ for(i=0; i<ph; i++){
139
+ if((double)i < hh/2.0){
140
+ wd[i] = ww;
141
+ }else{
142
+ wd[i] = 0.0;
143
+ }
144
+ }
145
+
146
+ /* 塗りタイプ別の処理 */
147
+ switch(type){
148
+ case PKL_PAINT_AVE:
149
+ result = pkl_pattern_draw_average(pkl, wd, pw, ph);
150
+ break;
151
+ case PKL_PAINT_LINE:
152
+ default:
153
+ result = pkl_pattern_draw_line(pkl, wd, pw, ph);
154
+ }
155
+
156
+ free(wd);
157
+ return(result);
158
+ }
159
+
160
+ //=============================================================================
161
+ // pkl_pattern_draw_line
162
+ //=============================================================================
163
+ static int pkl_pattern_draw_line(PKLImage pkl, double *wd, int pw, int ph)
164
+ {
165
+ unsigned char clipcolor[PKL_CHANNEL], *p;
166
+ int i, j, s, idx, k, color[PKL_CHANNEL];
167
+ double ww, hh, rm;
168
+ int count, ptn=0;
169
+
170
+ if(pw<0 || pw>pkl->width || ph<0 || ph>pkl->height) return(1);
171
+
172
+ ww = (double)pw;
173
+ hh = (double)ph;
174
+
175
+ //x方向に母点分ずつずらしていく
176
+ for(j=0; j<pkl->width+pw; j+=pw){
177
+ //パターンの切り替え
178
+ ptn = !ptn;
179
+
180
+ for(i=0; i<pkl->height; i++){
181
+ memset(color, 0, sizeof(color));
182
+ count=0;
183
+
184
+ //パターン配列のインデックスを算出
185
+ //(余剰を算出すれば、パターン配列を順番に処理できるから)
186
+ idx = i % ph;
187
+
188
+ //パターンを幅=pwの範囲で縦方向に見るので
189
+ //パターン距離(wd)をpwから引くことで横方向の距離を算出できる
190
+ //パターンは繰り返しなので、pw++ごとに切り替えればよい
191
+ rm = ptn ? wd[idx] : ww-wd[idx];
192
+
193
+ //jをパターンの中心として、両側へ広がりのある領域のピクセル平均を取る
194
+ for(s=j-rm; s<=j+rm; s++){
195
+ if(s<0 || s>=pkl->width) continue;
196
+ p = &pkl->image[(i*pkl->width+s)*pkl->channel];
197
+ for(k=0; k<pkl->channel; k++)
198
+ color[k] += *p++;
199
+ count++;
200
+ }
201
+ if(count==0) continue;
202
+ for(k=0; k<pkl->channel; k++)
203
+ clipcolor[k] = PKL_COLOR_CLIP(color[k]/count);
204
+
205
+ //作った色を横方向に適用する
206
+ for(s=j-rm; s<=j+rm; s++){
207
+ if(s<0 || s>=pkl->width) continue;
208
+ memcpy(&pkl->image[(i*pkl->width+s)*pkl->channel], clipcolor, pkl->channel);
209
+ }
210
+ }
211
+ }
212
+ return(0);
213
+ }
214
+
215
+ //=============================================================================
216
+ // pkl_pattern_draw_average
217
+ //=============================================================================
218
+ static int pkl_pattern_draw_average(PKLImage pkl, double *wd, int pw, int ph)
219
+ {
220
+ unsigned char clipcolor[PKL_CHANNEL], *p;
221
+ int i, j, s, t, k, color[PKL_CHANNEL];
222
+ int count, ys, idx, ptn=0;
223
+ double ww, hh, rm;
224
+
225
+ if(pw<0 || pw>pkl->width || ph<0 || ph>pkl->height) return(1);
226
+
227
+ ww = (double)pw;
228
+ hh = (double)ph;
229
+
230
+ for(j=0; j<pkl->width+pw; j+=pw){
231
+ ptn = !ptn;
232
+ ys = (ptn) ? 0 : (-ph/2);
233
+
234
+ for(i=ys; i<pkl->height; i+=ph){
235
+ memset(color, 0, sizeof(color));
236
+ count=0;
237
+ rm=wd[0];
238
+
239
+ for(t=i; t<i+ph; t++){
240
+ if(t<0 || t>=pkl->height) continue;
241
+
242
+ idx = t % ph;
243
+ rm = ptn ? wd[idx] : ww-wd[idx];
244
+ for(s=j-rm; s<=j+rm; s++){
245
+ if(s<0 || s>=pkl->width) continue;
246
+ p = &pkl->image[(t*pkl->width+s)*pkl->channel];
247
+ for(k=0; k<pkl->channel; k++)
248
+ color[k] += *p++;
249
+ count++;
250
+ }
251
+ }
252
+
253
+ /* パターン領域内の平均算出 */
254
+ if(count==0) continue;
255
+ for(k=0; k<pkl->channel; k++)
256
+ clipcolor[k] = PKL_COLOR_CLIP(color[k]/count);
257
+
258
+ /* パターン領域を同一色で塗りつぶす */
259
+ for(t=i; t<i+ph; t++){
260
+ if(t<0 || t>=pkl->height) continue;
261
+ idx = t % ph;
262
+ rm = ptn ? wd[idx] : ww-wd[idx];
263
+
264
+ for(s=j-rm; s<=j+rm; s++){
265
+ if(s<0 || s>=pkl->width) continue;
266
+ memcpy(&pkl->image[(t*pkl->width+s)*pkl->channel], clipcolor, pkl->channel);
267
+ }
268
+
269
+ //境界線
270
+ //if(j-rm-1>=0)
271
+ // memset(&pkl->image[(t*pkl->width+(int)(j-rm-1))*pkl->channel], 0, pkl->channel);
272
+ //if(j+rm+1<pkl->width)
273
+ // memset(&pkl->image[(t*pkl->width+(int)(j+rm+1))*pkl->channel], 0, pkl->channel);
274
+ //if(t-1>=0)
275
+ // memset(&pkl->image[((t-1)*pkl->width+s)*pkl->channel], 0, pkl->channel);
276
+ //if(t+1<pkl->height)
277
+ // memset(&pkl->image[((t+1)*pkl->width+s)*pkl->channel], 0, pkl->channel);
278
+ }
279
+ }
280
+ }
281
+ return(0);
282
+ }
283
+
284
+ //=============================================================================
285
+ // voronoi_type1 datatype
286
+ //=============================================================================
287
+ struct VoronoiPoint {
288
+ int x, y;
289
+ long color[PKL_CHANNEL];
290
+ unsigned char ave[PKL_CHANNEL];
291
+ int count;
292
+ };
293
+
294
+ //=============================================================================
295
+ // voronoi_type1_query
296
+ //=============================================================================
297
+ static void voronoi_type1_query(PKLImage pkl, struct VoronoiPoint *vptr, int *id, int zone, int xzone, int yzone)
298
+ {
299
+ struct VoronoiPoint *p;
300
+ int i, j, k, tx, ty, xx, yy, minIx, minIy;
301
+ double d, mind;
302
+
303
+ //母点を生成
304
+ srand48(1);
305
+ p = vptr;
306
+ for(i=0; i<yzone; i++){
307
+ for(j=0; j<xzone; j++){
308
+ tx = j * zone + lrand48()%zone;
309
+ ty = i * zone + lrand48()%zone;
310
+ p->x = tx>=pkl->width ? pkl->width-1 : tx;
311
+ p->y = ty>=pkl->height ? pkl->height-1 : ty;
312
+ p++;
313
+ }
314
+ }
315
+
316
+ for(i=0; i<pkl->height; i++){
317
+ yy = i/zone;
318
+ for(j=0; j<pkl->width; j++){
319
+ xx = j/zone;
320
+ mind=10000000;
321
+ minIx=minIy=0;
322
+
323
+ //カレントピクセルに最も近い母点を探す
324
+ for(ty=yy-1; ty<=yy+1; ty++){
325
+ if(ty<0 || ty>yzone-1) continue;
326
+ for(tx=xx-1; tx<=xx+1; tx++){
327
+ if(tx<0 || tx>xzone-1) continue;
328
+ d = (vptr[ty*xzone+tx].x-j)*(vptr[ty*xzone+tx].x-j) +
329
+ (vptr[ty*xzone+tx].y-i)*(vptr[ty*xzone+tx].y-i);
330
+ if(d < mind){
331
+ mind = d;
332
+ minIx = tx;
333
+ minIy = ty;
334
+ }
335
+ }
336
+ }
337
+
338
+ for(k=0; k<pkl->channel; k++)
339
+ vptr[minIy*xzone+minIx].color[k] += pkl->image[(i*pkl->width+j)*pkl->channel+k];
340
+ vptr[minIy*xzone+minIx].count++;
341
+
342
+ //各ピクセルのボロノイIDをセット
343
+ id[i*pkl->width+j] = minIy*xzone+minIx;
344
+ }
345
+ }
346
+ }
347
+
348
+ //=============================================================================
349
+ // pkl_voronoi_type1
350
+ //=============================================================================
351
+ PKLExport int pkl_voronoi_type1(PKLImage pkl, int zone, int bordercolor, int test)
352
+ {
353
+ struct VoronoiPoint *vptr, *p;
354
+ int xzone, yzone, *id;
355
+ int i, j, k, tx, ty;
356
+ unsigned char border[PKL_CHANNEL];
357
+
358
+
359
+ if(zone < 2) return(1);
360
+ if(zone>=pkl->width || zone>=pkl->height) return(1);
361
+ xzone = pkl->width/zone;
362
+ if((pkl->width%zone) != 0) xzone++;
363
+ yzone = pkl->height/zone;
364
+ if((pkl->height%zone) != 0) yzone++;
365
+
366
+ for(i=0; i<pkl->channel; i++)
367
+ border[i] = (bordercolor>>((pkl->channel-i)*8) & 0xFF);
368
+
369
+ //ボロノイ管理データ
370
+ vptr = malloc(sizeof(struct VoronoiPoint) * xzone*yzone);
371
+ memset(vptr, 0, sizeof(struct VoronoiPoint) * xzone*yzone);
372
+
373
+ //各座標のボロノイIDを格納するデータ
374
+ id = malloc(sizeof(int) * pkl->width*pkl->height);
375
+
376
+ //ボロノイ管理データを作る
377
+ voronoi_type1_query(pkl, vptr, id, zone, xzone, yzone);
378
+
379
+ if(test){
380
+ //分割シュミレーション(母点を置く)
381
+ memset(pkl->image, 0xff, pkl->width*pkl->height*pkl->channel);
382
+ for(i=0; i<xzone*yzone; i++)
383
+ memcpy(&pkl->image[(vptr[i].y*pkl->width+vptr[i].x)*pkl->channel], border, pkl->channel);
384
+ }else{
385
+ //各ボロノイポイントの平均色算出
386
+ for(ty=0; ty<yzone; ty++){
387
+ for(tx=0; tx<xzone; tx++){
388
+ if(vptr[ty*xzone+tx].count == 0) continue;
389
+ p = &vptr[ty*xzone+tx];
390
+ for(k=0; k<pkl->channel; k++)
391
+ p->ave[k] = PKL_COLOR_CLIP(p->color[k]/p->count);
392
+ }
393
+ }
394
+ //色を設定
395
+ for(i=0; i<pkl->height; i++)
396
+ for(j=0; j<pkl->width; j++)
397
+ memcpy(&pkl->image[(i*pkl->width+j)*pkl->channel], vptr[id[i*pkl->width+j]].ave, pkl->channel);
398
+ }
399
+
400
+ //境界線を引く
401
+ if(bordercolor!=-1){
402
+ int currentId, hit=0;
403
+ for(j=0; j<pkl->height; j++){
404
+ for(i=0; i<pkl->width; i++){
405
+ hit=0;
406
+ currentId = id[j*pkl->width+i];
407
+ if(i-1>=0 && currentId!=id[j*pkl->width+i-1]) hit++;
408
+ if(i+1<pkl->width && currentId!=id[j*pkl->width+i+1]) hit++;
409
+ if(j-1>=0 && currentId!=id[(j-1)*pkl->width+i+1]) hit++;
410
+ if(j+1<pkl->height && currentId!=id[(j+1)*pkl->width+i+1]) hit++;
411
+ if(hit)
412
+ memcpy(&pkl->image[(j*pkl->width+i)*pkl->channel], border, pkl->channel);
413
+ }
414
+ }
415
+ }
416
+ free(id);
417
+ free(vptr);
418
+ return(0);
419
+ }
420
+
421
+ //=============================================================================
422
+ // voronoi_type2 datatype
423
+ //=============================================================================
424
+ //ボロノイの母点管理用(1つの母点から隣接する母点の個数)
425
+ #define VORONOI_CNT 10 //根拠はない
426
+
427
+ struct VORONOI {
428
+ int x, y; //母点座標
429
+ int id; //管理用ID
430
+ long color[PKL_CHANNEL]; //ターゲット領域の色累積領域
431
+ int count; //累積ピクセル数
432
+ int next[VORONOI_CNT]; //隣接する母点のID
433
+ };
434
+
435
+ //=============================================================================
436
+ // vcompare
437
+ //=============================================================================
438
+ static int vcompare(const void *a, const void *b)
439
+ {
440
+ struct VORONOI *t1 = (struct VORONOI *)a;
441
+ struct VORONOI *t2 = (struct VORONOI *)b;
442
+
443
+ if(t1->y == t2->y)
444
+ return(t1->x - t2->x);
445
+ return(t1->y - t2->y);
446
+ }
447
+
448
+ //=============================================================================
449
+ // voronoi_setid
450
+ //=============================================================================
451
+ static void voronoi_setid(int *ary, int id)
452
+ {
453
+ int i;
454
+
455
+ for(i=0; i<VORONOI_CNT; i++){
456
+ if(ary[i] == -1){
457
+ ary[i] = id;
458
+ return;
459
+ }
460
+ }
461
+ }
462
+
463
+ //=============================================================================
464
+ // voronoi_type2_query
465
+ //=============================================================================
466
+ static void voronoi_type2_query(PKLImage pkl, struct VORONOI *kp, int *ip, int count)
467
+ {
468
+ int i, j, k, min_id, pre_id;
469
+ double d, dx, dy, min_d;
470
+
471
+ //母点をランダムに生成する
472
+ srand48((long)count);
473
+ for(i=0; i<count; i++){
474
+ kp[i].x = lrand48() % pkl->width;
475
+ kp[i].y = lrand48() % pkl->height;
476
+ kp[i].id = i;
477
+ }
478
+
479
+ //生成した母点座標を左上から右下に向かってソートする
480
+ qsort(kp, count, sizeof(struct VORONOI), vcompare);
481
+
482
+ min_id = 0; //最初の母点ID
483
+ pre_id = 0; //前ピクセルの母点ID
484
+
485
+ //各母点の最近傍の母点を探索する
486
+ for(j=0; j<pkl->height; j++){
487
+ for(i=0; i<pkl->width; i++){
488
+ // 前ピクセルの母点との距離を求める
489
+ dx = kp[pre_id].x-i;
490
+ dy = kp[pre_id].y-j;
491
+ min_d = sqrt(dx*dx+dy*dy);
492
+
493
+ //現在のピクセルの右上により近い母点があるか検索
494
+ for(k=pre_id-1; k>=0 && (kp[k].y>=j-min_d); k--){
495
+ if(kp[k].x >= i && kp[k].x <= i+min_d){
496
+ dx = kp[k].x-i;
497
+ dy = kp[k].y-j;
498
+ d = sqrt(dx*dx+dy*dy);
499
+ if(d<min_d){
500
+ min_id=k;
501
+ min_d=d;
502
+ }
503
+ }
504
+ }
505
+ //現在のピクセルの右下により近い母点があるか検索
506
+ for(k=pre_id+1; k<count && (kp[k].y<=j+min_d); k++){
507
+ if(kp[k].x >= i && kp[k].x <= i+min_d){
508
+ dx = kp[k].x-i;
509
+ dy = kp[k].y-j;
510
+ d = sqrt(dx*dx+dy*dy);
511
+ if(d<min_d){
512
+ min_id=k;
513
+ min_d=d;
514
+ }
515
+ }
516
+ }
517
+ //最も近くにある母点のIDを設定する
518
+ if(pre_id != min_id){
519
+ voronoi_setid(kp[pre_id].next, min_id);
520
+ voronoi_setid(kp[min_id].next, pre_id);
521
+ }
522
+
523
+ //現在の座標のIDに決定したボロノイ管理IDを設定する
524
+ ip[j*pkl->width+i] = min_id;
525
+ pre_id = min_id;
526
+ }
527
+ }
528
+ }
529
+
530
+ //=============================================================================
531
+ // pkl_voronoi_type2
532
+ //=============================================================================
533
+ PKLExport int pkl_voronoi_type2(PKLImage pkl, int count, int bordercolor, int test)
534
+ {
535
+ struct VORONOI *kp;
536
+ int i, j, k, *ip;
537
+ unsigned char border[PKL_CHANNEL];
538
+
539
+ //母点数の閾値
540
+ if(count < 10) return(1);
541
+
542
+ for(i=0; i<pkl->channel; i++)
543
+ border[i] = (bordercolor>>((pkl->channel-i)*8) & 0xFF);
544
+
545
+ //各座標の母点IDを格納する領域
546
+ ip = malloc(sizeof(int) * pkl->width * pkl->height);
547
+ memset(ip, -1, sizeof(int) * pkl->width * pkl->height);
548
+
549
+ //母点管理領域(母点数分用意)
550
+ kp = malloc(sizeof(struct VORONOI) * count);
551
+ memset(kp, 0, sizeof(struct VORONOI) * count);
552
+ for(i=0; i<count; i++)
553
+ memset(kp[i].next, -1, sizeof(int)*VORONOI_CNT);
554
+
555
+ //ボロノイ管理データを作る
556
+ voronoi_type2_query(pkl, kp, ip, count);
557
+
558
+ if(test){
559
+ //分割シュミレーション(母点を置く)
560
+ memset(pkl->image, 0xff, pkl->width*pkl->height*pkl->channel);
561
+ for(i=0; i<count; i++)
562
+ memcpy(&pkl->image[(kp[i].y*pkl->width+kp[i].x)*pkl->channel], border, pkl->channel);
563
+ }else{
564
+ //ボロノイ分割されたので、各セルの平均色を算出するためにセルの色を累積する
565
+ for(j=0; j<pkl->height; j++) {
566
+ for(i=0; i<pkl->width; i++) {
567
+ //ipを参照することで、現在の座標がどのIDに所属するかわかる
568
+ if(ip[j*pkl->width+i] == -1) continue;
569
+ //IDごとに色を累積する
570
+ kp[ ip[j*pkl->width+i] ].count++;
571
+ for(k=0; k<pkl->channel; k++)
572
+ kp[ ip[j*pkl->width+i] ].color[k] += pkl->image[(j*pkl->width+i)*pkl->channel+k];
573
+ }
574
+ }
575
+
576
+ //各セルの平均色を作る
577
+ for(i=0; i<count; i++){
578
+ for(k=0; k<pkl->channel; k++){
579
+ if(kp[i].count!=0)
580
+ kp[i].color[k] = PKL_COLOR_CLIP(kp[i].color[k]/kp[i].count);
581
+ }
582
+ }
583
+
584
+ //色を置く
585
+ for(j=0; j<pkl->height; j++)
586
+ for(i=0; i<pkl->width; i++)
587
+ for(k=0; k<pkl->channel; k++)
588
+ pkl->image[(j*pkl->width+i)*pkl->channel+k] = kp[ ip[j*pkl->width+i] ].color[k];
589
+ }
590
+
591
+ //境界線を引く
592
+ if(bordercolor!=-1){
593
+ int currentId, hit=0;
594
+ for(j=0; j<pkl->height; j++){
595
+ for(i=0; i<pkl->width; i++){
596
+ hit=0;
597
+ currentId = ip[j*pkl->width+i];
598
+ if(i-1>=0 && currentId!=ip[j*pkl->width+i-1]) hit++;
599
+ if(i+1<pkl->width && currentId!=ip[j*pkl->width+i+1]) hit++;
600
+ if(j-1>=0 && currentId!=ip[(j-1)*pkl->width+i+1]) hit++;
601
+ if(j+1<pkl->height && currentId!=ip[(j+1)*pkl->width+i+1]) hit++;
602
+ if(hit)
603
+ memcpy(&pkl->image[(j*pkl->width+i)*pkl->channel], border, pkl->channel);
604
+ }
605
+ }
606
+ }
607
+
608
+ free(kp);
609
+ free(ip);
610
+ return(0);
611
+ }