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.
- data/History.txt +9 -0
- data/License.txt +0 -0
- data/Manifest.txt +17 -17
- data/README.txt +0 -0
- data/config/hoe.rb +9 -6
- data/config/requirements.rb +0 -0
- data/ext/pikl/pikl.h +617 -465
- data/ext/pikl/pikl_affine.c +38 -91
- data/ext/pikl/pikl_affine.h +0 -0
- data/ext/pikl/pikl_bitmap.c +0 -0
- data/ext/pikl/pikl_bitmap.h +0 -0
- data/ext/pikl/pikl_blur.c +4 -8
- data/ext/pikl/pikl_blur.h +0 -0
- data/ext/pikl/pikl_camera.c +218 -0
- data/ext/pikl/{pikl_effect3.h → pikl_camera.h} +2 -2
- data/ext/pikl/pikl_composite.c +175 -0
- data/ext/pikl/pikl_composite.h +12 -0
- data/ext/pikl/pikl_decrease.c +110 -45
- data/ext/pikl/pikl_decrease.h +0 -7
- data/ext/pikl/pikl_divide.c +116 -0
- data/ext/pikl/pikl_divide.h +11 -0
- data/ext/pikl/pikl_effect.c +583 -151
- data/ext/pikl/pikl_effect.h +32 -6
- data/ext/pikl/pikl_enhance.c +274 -0
- data/ext/pikl/pikl_enhance.h +20 -0
- data/ext/pikl/pikl_io.c +174 -23
- data/ext/pikl/pikl_io.h +0 -0
- data/ext/pikl/pikl_jpeg.c +0 -0
- data/ext/pikl/pikl_jpeg.h +0 -0
- data/ext/pikl/pikl_pattern.c +383 -357
- data/ext/pikl/pikl_pattern.h +0 -0
- data/ext/pikl/pikl_pixel.c +173 -0
- data/ext/pikl/{pikl_trim.h → pikl_pixel.h} +2 -2
- data/ext/pikl/pikl_png.c +0 -0
- data/ext/pikl/pikl_png.h +0 -0
- data/ext/pikl/pikl_private.h +12 -5
- data/ext/pikl/pikl_resize.c +0 -0
- data/ext/pikl/pikl_resize.h +0 -0
- data/ext/pikl/pikl_rotate.c +409 -51
- data/ext/pikl/pikl_rotate.h +8 -0
- data/ext/pikl/pikl_scrap.c +263 -483
- data/ext/pikl/pikl_scrap.h +0 -0
- data/ext/pikl/pikl_special.c +168 -0
- data/ext/pikl/{pikl_effect4.h → pikl_special.h} +2 -2
- data/ext/pikl/pikl_voronoi.c +320 -0
- data/ext/pikl/pikl_voronoi.h +37 -0
- data/lib/pikl.rb +4 -2
- data/lib/pikl/color.rb +47 -0
- data/lib/pikl/const.rb +106 -22
- data/lib/pikl/errors.rb +0 -0
- data/lib/pikl/ext.rb +115 -8
- data/lib/pikl/filter.rb +371 -0
- data/lib/pikl/image.rb +124 -117
- data/lib/pikl/pikl.dll +0 -0
- data/lib/pikl/version.rb +2 -2
- data/setup.rb +0 -0
- data/test/sample.jpg +0 -0
- data/test/test_helper.rb +0 -0
- data/test/test_pikl_image.rb +0 -14
- data/test/test_pikl_image2.rb +541 -0
- metadata +35 -23
- data/ext/pikl/decrease/fsdither.h +0 -554
- data/ext/pikl/decrease/median.c +0 -1179
- data/ext/pikl/decrease/median.h +0 -7
- data/ext/pikl/decrease/neuquan5.c +0 -563
- data/ext/pikl/decrease/neuquant.h +0 -62
- data/ext/pikl/decrease/wu.c +0 -447
- data/ext/pikl/decrease/wu.h +0 -7
- data/ext/pikl/pikl_effect2.c +0 -240
- data/ext/pikl/pikl_effect2.h +0 -55
- data/ext/pikl/pikl_effect3.c +0 -266
- data/ext/pikl/pikl_effect4.c +0 -495
- data/ext/pikl/pikl_rotate2.c +0 -312
- data/ext/pikl/pikl_rotate2.h +0 -19
- data/ext/pikl/pikl_trim.c +0 -28
data/ext/pikl/pikl_scrap.h
CHANGED
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
|
+
}
|
@@ -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
|
+
|