pikl 0.2.8 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/extconf.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/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_io.h
CHANGED
File without changes
|
data/ext/pikl/pikl_jpeg.c
CHANGED
File without changes
|
data/ext/pikl/pikl_jpeg.h
CHANGED
File without changes
|
data/ext/pikl/pikl_pattern.c
CHANGED
@@ -1,15 +1,27 @@
|
|
1
1
|
#include "pikl_pattern.h"
|
2
2
|
|
3
|
+
static int tile_rectangle(PKLImage pkl, int msx, int msy, unsigned char level);
|
4
|
+
static int tile_pattern(PKLImage pkl, PKL_TILE_TYPE type, int pw, int ph, unsigned char level);
|
5
|
+
static int tile_pattern_draw(PKLImage pkl, double *wd, int pw, int ph, unsigned char level);
|
6
|
+
static int tile_brick(PKLImage pkl, int msx, int msy, unsigned char level);
|
7
|
+
|
8
|
+
static void pattern_hexagon(int ph, double *wd, double ww, double hh);
|
9
|
+
static void pattern_diamond(int ph, double *wd, double ww, double hh);
|
10
|
+
static void pattern_circle(int ph, double *wd, double ww, double hh);
|
11
|
+
static void pattern_brick(int ph, double *wd, double ww, double hh);
|
12
|
+
|
3
13
|
static int pkl_pattern_draw_line(PKLImage pkl, double *wd, int pw, int ph);
|
4
14
|
static int pkl_pattern_draw_average(PKLImage pkl, double *wd, int pw, int ph);
|
5
15
|
|
6
16
|
//=============================================================================
|
7
|
-
//
|
17
|
+
// pkl_pattern
|
8
18
|
//=============================================================================
|
9
|
-
PKLExport int
|
19
|
+
PKLExport int pkl_pattern(PKLImage pkl, int pw, int ph, PKL_PATTERN_TYPE mode, PKL_PAINT_TYPE type)
|
10
20
|
{
|
11
21
|
double ww, hh, *wd;
|
12
|
-
int
|
22
|
+
int result;
|
23
|
+
|
24
|
+
if(pw<1 || ph<1) return(1);
|
13
25
|
|
14
26
|
wd = malloc(sizeof(double)*ph);
|
15
27
|
if(!wd) return(1);
|
@@ -17,21 +29,22 @@ PKLExport int pkl_pattern_hexagon(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE t
|
|
17
29
|
ww = (double)pw;
|
18
30
|
hh = (double)ph;
|
19
31
|
|
20
|
-
/*
|
21
|
-
|
22
|
-
|
23
|
-
wd
|
24
|
-
|
25
|
-
|
26
|
-
wd
|
27
|
-
|
28
|
-
|
29
|
-
wd
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
/* パターン座標の構築 */
|
33
|
+
switch(mode){
|
34
|
+
case PKL_PATTERN_DIAMOND:
|
35
|
+
pattern_diamond(ph, wd, ww, hh);
|
36
|
+
break;
|
37
|
+
case PKL_PATTERN_CIRCLE:
|
38
|
+
pattern_circle(ph, wd, ww, hh);
|
39
|
+
break;
|
40
|
+
case PKL_PATTERN_BRICK:
|
41
|
+
pattern_brick(ph, wd, ww, hh);
|
42
|
+
break;
|
43
|
+
case PKL_PATTERN_HEXAGON:
|
44
|
+
default:
|
45
|
+
pattern_hexagon(ph, wd, ww, hh);
|
33
46
|
}
|
34
|
-
|
47
|
+
|
35
48
|
/* 塗りタイプ別の処理 */
|
36
49
|
switch(type){
|
37
50
|
case PKL_PAINT_AVE:
|
@@ -47,20 +60,32 @@ PKLExport int pkl_pattern_hexagon(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE t
|
|
47
60
|
}
|
48
61
|
|
49
62
|
//=============================================================================
|
50
|
-
//
|
63
|
+
// pattern_hexagon
|
51
64
|
//=============================================================================
|
52
|
-
|
65
|
+
void pattern_hexagon(int ph, double *wd, double ww, double hh)
|
53
66
|
{
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
67
|
+
int i;
|
68
|
+
for(i=0; i<ph; i++){
|
69
|
+
if((double)i < hh/6.0){
|
70
|
+
wd[i] = ww * (double)i*6.0/hh;
|
71
|
+
}else
|
72
|
+
if((double)i < hh/2.0){
|
73
|
+
wd[i] = ww;
|
74
|
+
}else
|
75
|
+
if((double)i < hh*2.0/3.0){
|
76
|
+
wd[i] = ww*4.0 - ww*(double)i*6.0/hh;
|
77
|
+
}else{
|
78
|
+
wd[i] = 0.0;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
//=============================================================================
|
84
|
+
// pattern_diamond
|
85
|
+
//=============================================================================
|
86
|
+
void pattern_diamond(int ph, double *wd, double ww, double hh)
|
87
|
+
{
|
88
|
+
int i;
|
64
89
|
for(i=0; i<ph; i++){
|
65
90
|
if((double)i < hh/2.0){
|
66
91
|
wd[i] = ww*(double)i*2.0/hh;
|
@@ -68,36 +93,14 @@ PKLExport int pkl_pattern_diamond(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE t
|
|
68
93
|
wd[i] = ww*2.0 - ww*(double)i*2.0/hh;
|
69
94
|
}
|
70
95
|
}
|
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
96
|
}
|
85
97
|
|
86
98
|
//=============================================================================
|
87
|
-
//
|
99
|
+
// pattern_circle
|
88
100
|
//=============================================================================
|
89
|
-
|
101
|
+
void pattern_circle(int ph, double *wd, double ww, double hh)
|
90
102
|
{
|
91
|
-
|
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
|
-
/* パターン座標を構築する */
|
103
|
+
int i;
|
101
104
|
for(i=0; i<ph; i++){
|
102
105
|
if((double)i < hh/2.0){
|
103
106
|
wd[i] = ww*(double)i*2.0/hh - (ww/8.0)*sin((double)i*4.0/hh*M_PI);
|
@@ -105,36 +108,14 @@ PKLExport int pkl_pattern_circle(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE ty
|
|
105
108
|
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
109
|
}
|
107
110
|
}
|
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
111
|
}
|
122
112
|
|
123
113
|
//=============================================================================
|
124
|
-
//
|
114
|
+
// pattern_brick
|
125
115
|
//=============================================================================
|
126
|
-
|
116
|
+
void pattern_brick(int ph, double *wd, double ww, double hh)
|
127
117
|
{
|
128
|
-
|
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
|
-
/* パターン座標を構築する */
|
118
|
+
int i;
|
138
119
|
for(i=0; i<ph; i++){
|
139
120
|
if((double)i < hh/2.0){
|
140
121
|
wd[i] = ww;
|
@@ -142,25 +123,12 @@ PKLExport int pkl_pattern_brick(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE typ
|
|
142
123
|
wd[i] = 0.0;
|
143
124
|
}
|
144
125
|
}
|
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
126
|
}
|
159
127
|
|
160
128
|
//=============================================================================
|
161
129
|
// pkl_pattern_draw_line
|
162
130
|
//=============================================================================
|
163
|
-
|
131
|
+
int pkl_pattern_draw_line(PKLImage pkl, double *wd, int pw, int ph)
|
164
132
|
{
|
165
133
|
unsigned char clipcolor[PKL_CHANNEL], *p;
|
166
134
|
int i, j, s, idx, k, color[PKL_CHANNEL];
|
@@ -215,7 +183,7 @@ static int pkl_pattern_draw_line(PKLImage pkl, double *wd, int pw, int ph)
|
|
215
183
|
//=============================================================================
|
216
184
|
// pkl_pattern_draw_average
|
217
185
|
//=============================================================================
|
218
|
-
|
186
|
+
int pkl_pattern_draw_average(PKLImage pkl, double *wd, int pw, int ph)
|
219
187
|
{
|
220
188
|
unsigned char clipcolor[PKL_CHANNEL], *p;
|
221
189
|
int i, j, s, t, k, color[PKL_CHANNEL];
|
@@ -282,330 +250,388 @@ static int pkl_pattern_draw_average(PKLImage pkl, double *wd, int pw, int ph)
|
|
282
250
|
}
|
283
251
|
|
284
252
|
//=============================================================================
|
285
|
-
//
|
253
|
+
// pkl_tile
|
286
254
|
//=============================================================================
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
255
|
+
PKLExport int pkl_tile(PKLImage pkl, PKL_TILE_TYPE type, int msx, int msy, unsigned char level)
|
256
|
+
{
|
257
|
+
if(msx<=0 || msx>pkl->width || msy<=0 || msy>pkl->height)
|
258
|
+
return(1);
|
259
|
+
|
260
|
+
switch(type){
|
261
|
+
case PKL_TILE_RECT:
|
262
|
+
return tile_rectangle(pkl, msx, msy, level);
|
263
|
+
case PKL_TILE_HEXAGON:
|
264
|
+
case PKL_TILE_DIAMOND:
|
265
|
+
case PKL_TILE_CIRCLE:
|
266
|
+
return tile_pattern(pkl, type, msx, msy, level);
|
267
|
+
case PKL_TILE_BRICK:
|
268
|
+
return tile_brick(pkl, msx, msy, level);
|
269
|
+
}
|
270
|
+
return(1);
|
271
|
+
}
|
293
272
|
|
294
273
|
//=============================================================================
|
295
|
-
//
|
274
|
+
// tile_brick
|
296
275
|
//=============================================================================
|
297
|
-
static
|
276
|
+
static int tile_brick(PKLImage pkl, int msx, int msy, unsigned char level)
|
298
277
|
{
|
299
|
-
|
300
|
-
int
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
278
|
+
unsigned char *wrk, *p;
|
279
|
+
int mpx, mpy; //モザイクの大きさ
|
280
|
+
int mlx, mly; //画像の分割数
|
281
|
+
int i, j, k, sx, sy, ex, ey, px, py, count, offset;
|
282
|
+
long color[PKL_CHANNEL];
|
283
|
+
|
284
|
+
wrk = malloc(pkl->width*pkl->height*pkl->channel);
|
285
|
+
if(!wrk) return(1);
|
286
|
+
memset(wrk, 0, pkl->width*pkl->height*pkl->channel);
|
287
|
+
|
288
|
+
mpx = (msx<1) ? 1 : (msx>=pkl->width) ? pkl->width-1 : msx;
|
289
|
+
mpy = (msy<1) ? 1 : (msy>=pkl->height) ? pkl->height-1 : msy;
|
290
|
+
mlx = (pkl->width+mpx-1)/mpx;
|
291
|
+
mly = (pkl->height+mpy-1)/mpy;
|
292
|
+
|
293
|
+
for(i=0; i<=mly; i++){
|
294
|
+
offset = (i%2) ? 0 : mpx/2;
|
295
|
+
for(j=0; j<=mlx; j++){
|
296
|
+
sx = j*mpx - offset;
|
297
|
+
sx = sx<0 ? 0 : sx;
|
298
|
+
sy = i*mpy;
|
299
|
+
ex = sx+mpx>pkl->width ? pkl->width : sx+mpx;
|
300
|
+
ey = sy+mpy>pkl->height ? pkl->height : sy+mpy;
|
322
301
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
mind = d;
|
332
|
-
minIx = tx;
|
333
|
-
minIy = ty;
|
334
|
-
}
|
302
|
+
//1セルの総和算出
|
303
|
+
count=0;
|
304
|
+
memset(color, 0, sizeof(color));
|
305
|
+
for(py=sy; py<ey; py++){
|
306
|
+
for(px=sx; px<ex; px++){
|
307
|
+
count++;
|
308
|
+
for(k=0; k<pkl->channel; k++)
|
309
|
+
color[k] += pkl->image[(py*pkl->width+px)*pkl->channel+k];
|
335
310
|
}
|
336
311
|
}
|
312
|
+
if(!count) continue;
|
337
313
|
|
314
|
+
//セルの平均色を算出して、セル内のピクセルに適用
|
338
315
|
for(k=0; k<pkl->channel; k++)
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
316
|
+
color[k] = PKL_COLOR_CLIP(color[k]/count);
|
317
|
+
for(py=sy; py<ey; py++){
|
318
|
+
for(px=sx; px<ex; px++){
|
319
|
+
for(k=0; k<pkl->channel; k++)
|
320
|
+
wrk[(py*pkl->width+px)*pkl->channel+k] = color[k];
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
//平均色で塗り終わったら枠線を描く
|
325
|
+
//横方向
|
326
|
+
for(px=sx; px<ex; px++){
|
327
|
+
p = &wrk[(sy*pkl->width+px)*pkl->channel];
|
328
|
+
for(k=0; k<pkl->channel; k++,p++)
|
329
|
+
*p = PKL_MIN(0xff, *p+level);
|
330
|
+
|
331
|
+
p = &wrk[((ey-1)*pkl->width+px)*pkl->channel];
|
332
|
+
for(k=0; k<pkl->channel; k++,p++)
|
333
|
+
*p = PKL_MAX(0, *p-level);
|
334
|
+
}
|
335
|
+
//縦方向
|
336
|
+
for(py=sy; py<ey; py++){
|
337
|
+
p = &wrk[(py*pkl->width+sx)*pkl->channel];
|
338
|
+
for(k=0; k<pkl->channel; k++,p++)
|
339
|
+
*p = PKL_MIN(0xff, *p+level);
|
340
|
+
|
341
|
+
p = &wrk[(py*pkl->width+ex-1)*pkl->channel];
|
342
|
+
for(k=0; k<pkl->channel; k++,p++)
|
343
|
+
*p = PKL_MAX(0, *p-level);
|
344
|
+
}
|
345
|
+
|
344
346
|
}
|
345
347
|
}
|
348
|
+
|
349
|
+
free(pkl->image);
|
350
|
+
pkl->image = wrk;
|
351
|
+
return(0);
|
346
352
|
}
|
347
353
|
|
348
354
|
//=============================================================================
|
349
|
-
//
|
355
|
+
// tile_rectangle
|
350
356
|
//=============================================================================
|
351
|
-
|
357
|
+
static int tile_rectangle(PKLImage pkl, int msx, int msy, unsigned char level)
|
352
358
|
{
|
353
|
-
|
354
|
-
int
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
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
|
-
}
|
359
|
+
unsigned char *p;
|
360
|
+
int i, j, k;
|
361
|
+
|
362
|
+
//モザイク化
|
363
|
+
if(pkl_mosaic(pkl, msx, msy)) return(1);
|
364
|
+
|
365
|
+
//横方向(light)
|
366
|
+
for(i=0; i<pkl->height; i+=msy){
|
367
|
+
for(j=0; j<pkl->width; j++){
|
368
|
+
p = &pkl->image[(i*pkl->width+j)*pkl->channel];
|
369
|
+
for(k=0; k<pkl->channel; k++,p++)
|
370
|
+
*p = PKL_MIN(0xff, *p+level);
|
393
371
|
}
|
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
372
|
}
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
for(
|
405
|
-
|
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
|
-
}
|
373
|
+
|
374
|
+
//横方向(dark)
|
375
|
+
for(i=msy-1; i<pkl->height; i+=msy){
|
376
|
+
for(j=0; j<pkl->width; j++){
|
377
|
+
p = &pkl->image[(i*pkl->width+j)*pkl->channel];
|
378
|
+
for(k=0; k<pkl->channel; k++,p++)
|
379
|
+
*p = PKL_MAX(0, *p-level);
|
414
380
|
}
|
415
381
|
}
|
416
|
-
free(id);
|
417
|
-
free(vptr);
|
418
|
-
return(0);
|
419
|
-
}
|
420
382
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
383
|
+
//縦方向(light)
|
384
|
+
for(i=0; i<pkl->height; i++){
|
385
|
+
for(j=0; j<pkl->width; j+=msx){
|
386
|
+
p = &pkl->image[(i*pkl->width+j)*pkl->channel];
|
387
|
+
for(k=0; k<pkl->channel; k++,p++)
|
388
|
+
*p = PKL_MIN(0xff, *p+level);
|
389
|
+
}
|
390
|
+
}
|
391
|
+
|
392
|
+
//縦方向(dark)
|
393
|
+
for(i=0; i<pkl->height; i++){
|
394
|
+
for(j=msx-1; j<pkl->width; j+=msx){
|
395
|
+
p = &pkl->image[(i*pkl->width+j)*pkl->channel];
|
396
|
+
for(k=0; k<pkl->channel; k++,p++)
|
397
|
+
*p = PKL_MAX(0, *p-level);
|
398
|
+
}
|
399
|
+
}
|
426
400
|
|
427
|
-
|
428
|
-
|
429
|
-
int id; //管理用ID
|
430
|
-
long color[PKL_CHANNEL]; //ターゲット領域の色累積領域
|
431
|
-
int count; //累積ピクセル数
|
432
|
-
int next[VORONOI_CNT]; //隣接する母点のID
|
433
|
-
};
|
401
|
+
return(0);
|
402
|
+
}
|
434
403
|
|
435
404
|
//=============================================================================
|
436
|
-
//
|
405
|
+
// tile_pattern
|
437
406
|
//=============================================================================
|
438
|
-
static int
|
407
|
+
static int tile_pattern(PKLImage pkl, PKL_TILE_TYPE type, int pw, int ph, unsigned char level)
|
439
408
|
{
|
440
|
-
|
441
|
-
|
409
|
+
double ww, hh, *wd;
|
410
|
+
int result=1;
|
411
|
+
|
412
|
+
wd = malloc(sizeof(double)*ph);
|
413
|
+
if(!wd) return(1);
|
414
|
+
|
415
|
+
ww = (double)pw;
|
416
|
+
hh = (double)ph;
|
442
417
|
|
443
|
-
|
444
|
-
|
445
|
-
|
418
|
+
/* パターン座標の構築 */
|
419
|
+
switch(type){
|
420
|
+
case PKL_TILE_HEXAGON:
|
421
|
+
pattern_hexagon(ph, wd, ww, hh); break;
|
422
|
+
case PKL_TILE_DIAMOND:
|
423
|
+
pattern_diamond(ph, wd, ww, hh); break;
|
424
|
+
case PKL_TILE_CIRCLE:
|
425
|
+
pattern_circle(ph, wd, ww, hh); break;
|
426
|
+
default:
|
427
|
+
;;
|
428
|
+
}
|
429
|
+
|
430
|
+
//パターンで塗りつぶしてから枠を描く
|
431
|
+
if(!pkl_pattern_draw_average(pkl, wd, pw, ph))
|
432
|
+
result = tile_pattern_draw(pkl, wd, pw, ph, level);
|
433
|
+
free(wd);
|
434
|
+
return(result);
|
446
435
|
}
|
447
436
|
|
448
437
|
//=============================================================================
|
449
|
-
//
|
438
|
+
// tile_pattern_draw
|
450
439
|
//=============================================================================
|
451
|
-
static
|
440
|
+
static int tile_pattern_draw(PKLImage pkl, double *wd, int pw, int ph, unsigned char level)
|
452
441
|
{
|
453
|
-
|
442
|
+
unsigned char *p;
|
443
|
+
int i, j, t, k, pos;
|
444
|
+
int ys, idx, ptn=0;
|
445
|
+
double ww, hh, rm;
|
454
446
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
447
|
+
ww = (double)pw;
|
448
|
+
hh = (double)ph;
|
449
|
+
|
450
|
+
for(j=0; j<pkl->width+pw; j+=pw){
|
451
|
+
ptn = !ptn;
|
452
|
+
ys = (ptn) ? 0 : (-ph/2);
|
453
|
+
for(i=ys; i<pkl->height; i+=ph){
|
454
|
+
rm=wd[0];
|
455
|
+
|
456
|
+
for(t=i; t<i+ph; t++){
|
457
|
+
if(t<0 || t>=pkl->height) continue;
|
458
|
+
idx = t % ph;
|
459
|
+
rm = ptn ? wd[idx] : ww-wd[idx];
|
460
|
+
|
461
|
+
//first=light
|
462
|
+
pos = j - rm;
|
463
|
+
if(pos>=0 && pos<pkl->width){
|
464
|
+
p = &pkl->image[(t*pkl->width+pos)*pkl->channel];
|
465
|
+
for(k=0; k<pkl->channel; k++,p++)
|
466
|
+
*p = PKL_MIN(0xff, *p+level);
|
467
|
+
}
|
468
|
+
|
469
|
+
//last=dark
|
470
|
+
pos = j + rm - 1;
|
471
|
+
if(pos>=0 && pos<pkl->width){
|
472
|
+
p = &pkl->image[(t*pkl->width+pos)*pkl->channel];
|
473
|
+
for(k=0; k<pkl->channel; k++,p++)
|
474
|
+
*p = PKL_MAX(0, *p-level);
|
475
|
+
}
|
476
|
+
}
|
459
477
|
}
|
460
478
|
}
|
479
|
+
return(0);
|
461
480
|
}
|
462
481
|
|
482
|
+
|
463
483
|
//=============================================================================
|
464
|
-
//
|
484
|
+
// pkl_mosaic
|
465
485
|
//=============================================================================
|
466
|
-
|
486
|
+
PKLExport int pkl_mosaic(PKLImage pkl, int msx, int msy)
|
467
487
|
{
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
dx = kp[pre_id].x-i;
|
490
|
-
dy = kp[pre_id].y-j;
|
491
|
-
min_d = sqrt(dx*dx+dy*dy);
|
488
|
+
unsigned char *wrk;
|
489
|
+
int mpx, mpy; //モザイクの大きさ
|
490
|
+
int mlx, mly; //画像の分割数
|
491
|
+
int i, j, k, sx, sy, ex, ey, px, py, mm;
|
492
|
+
long color[PKL_CHANNEL];
|
493
|
+
|
494
|
+
wrk = malloc(pkl->width*pkl->height*pkl->channel);
|
495
|
+
if(!wrk) return(1);
|
496
|
+
memset(wrk, 0, pkl->width*pkl->height*pkl->channel);
|
497
|
+
|
498
|
+
mpx = (msx<1) ? 1 : (msx>=pkl->width) ? pkl->width-1 : msx;
|
499
|
+
mpy = (msy<1) ? 1 : (msy>=pkl->height) ? pkl->height-1 : msy;
|
500
|
+
mlx = (pkl->width+mpx-1)/mpx;
|
501
|
+
mly = (pkl->height+mpy-1)/mpy;
|
502
|
+
|
503
|
+
for(i=0; i<=mly; i++){
|
504
|
+
for(j=0; j<=mlx; j++){
|
505
|
+
sx = j*mpx;
|
506
|
+
sy = i*mpy;
|
507
|
+
ex = sx+mpx>pkl->width ? pkl->width : sx+mpx;
|
508
|
+
ey = sy+mpy>pkl->height ? pkl->height : sy+mpy;
|
492
509
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
min_d=d;
|
502
|
-
}
|
510
|
+
//1セルの総和算出
|
511
|
+
mm=0;
|
512
|
+
memset(color, 0, sizeof(color));
|
513
|
+
for(py=sy; py<ey; py++){
|
514
|
+
for(px=sx; px<ex; px++){
|
515
|
+
mm++;
|
516
|
+
for(k=0; k<pkl->channel; k++)
|
517
|
+
color[k] += pkl->image[(py*pkl->width+px)*pkl->channel+k];
|
503
518
|
}
|
504
519
|
}
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
}
|
520
|
+
if(!mm) continue;
|
521
|
+
|
522
|
+
//セルの平均色を算出して、セル内のピクセルに適用
|
523
|
+
for(k=0; k<pkl->channel; k++)
|
524
|
+
color[k] = PKL_COLOR_CLIP(color[k]/mm);
|
525
|
+
for(py=sy; py<ey; py++){
|
526
|
+
for(px=sx; px<ex; px++){
|
527
|
+
for(k=0; k<pkl->channel; k++)
|
528
|
+
wrk[(py*pkl->width+px)*pkl->channel+k] = color[k];
|
515
529
|
}
|
516
530
|
}
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
531
|
+
}
|
532
|
+
}
|
533
|
+
|
534
|
+
free(pkl->image);
|
535
|
+
pkl->image = wrk;
|
536
|
+
return(0);
|
537
|
+
}
|
538
|
+
|
539
|
+
//=============================================================================
|
540
|
+
// pkl_pixelate
|
541
|
+
//=============================================================================
|
542
|
+
PKLExport int pkl_pixelate(PKLImage pkl, int ms)
|
543
|
+
{
|
544
|
+
unsigned char *wrk;
|
545
|
+
int mpx, mpy; //モザイクの大きさ
|
546
|
+
int mlx, mly; //画像の分割数
|
547
|
+
int i, j, k, sx, sy, ex, ey, px, py, mm;
|
548
|
+
long color[PKL_CHANNEL];
|
549
|
+
int total;
|
550
|
+
unsigned char p;
|
551
|
+
|
552
|
+
wrk = malloc(pkl->width*pkl->height*pkl->channel);
|
553
|
+
if(!wrk) return(1);
|
554
|
+
|
555
|
+
mpx = (ms<1) ? 1 : (ms>=pkl->width) ? pkl->width-1 : ms;
|
556
|
+
mpy = (ms<1) ? 1 : (ms>=pkl->height) ? pkl->height-1 : ms;
|
557
|
+
mlx = (pkl->width+mpx-1)/mpx;
|
558
|
+
mly = (pkl->height+mpy-1)/mpy;
|
559
|
+
|
560
|
+
for(i=0; i<=mly; i++){
|
561
|
+
for(j=0; j<=mlx; j++){
|
562
|
+
sx = j*mpx;
|
563
|
+
sy = i*mpy;
|
564
|
+
ex = sx+mpx>pkl->width ? pkl->width : sx+mpx;
|
565
|
+
ey = sy+mpy>pkl->height ? pkl->height : sy+mpy;
|
566
|
+
|
567
|
+
//1セルの総和算出
|
568
|
+
mm=0;
|
569
|
+
memset(color, 0, sizeof(color));
|
570
|
+
for(py=sy; py<ey; py++){
|
571
|
+
for(px=sx; px<ex; px++){
|
572
|
+
mm++;
|
573
|
+
for(k=0; k<pkl->channel; k++)
|
574
|
+
color[k] += pkl->image[(py*pkl->width+px)*pkl->channel+k];
|
575
|
+
}
|
521
576
|
}
|
577
|
+
if(!mm) continue;
|
522
578
|
|
523
|
-
|
524
|
-
|
525
|
-
|
579
|
+
//セルの平均色を算出
|
580
|
+
for(k=0; k<pkl->channel; k++)
|
581
|
+
color[k] = PKL_COLOR_CLIP(color[k]/mm);
|
582
|
+
|
583
|
+
total=0;
|
584
|
+
for(k=0; k<pkl->channel; k++)
|
585
|
+
total += color[k];
|
586
|
+
total /=pkl->channel;
|
587
|
+
p = total<128 ? 0 : 255;
|
588
|
+
|
589
|
+
for(py=sy; py<ey; py++){
|
590
|
+
for(px=sx; px<ex; px++){
|
591
|
+
for(k=0; k<pkl->channel; k++)
|
592
|
+
wrk[(py*pkl->width+px)*pkl->channel+k] = p;
|
593
|
+
}
|
594
|
+
}
|
526
595
|
}
|
527
596
|
}
|
597
|
+
|
598
|
+
free(pkl->image);
|
599
|
+
pkl->image = wrk;
|
600
|
+
return(0);
|
528
601
|
}
|
529
602
|
|
530
603
|
//=============================================================================
|
531
|
-
//
|
604
|
+
// pkl_grid
|
532
605
|
//=============================================================================
|
533
|
-
PKLExport int
|
606
|
+
PKLExport int pkl_grid(PKLImage pkl, int msx, int msy, int color)
|
534
607
|
{
|
535
|
-
|
536
|
-
int i, j, k,
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
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];
|
608
|
+
unsigned char *p;
|
609
|
+
int i, j, k, mpx, mpy;
|
610
|
+
|
611
|
+
//一旦モザイク化
|
612
|
+
if(pkl_mosaic(pkl, msx, msy)) return(1);
|
613
|
+
|
614
|
+
mpx = (msx<1) ? 1 : (msx>=pkl->width) ? pkl->width-1 : msx;
|
615
|
+
mpy = (msy<1) ? 1 : (msy>=pkl->height) ? pkl->height-1 : msy;
|
616
|
+
|
617
|
+
for(i=0; i<pkl->height-1; i++){
|
618
|
+
if(i%mpy==0){
|
619
|
+
for(j=0; j<pkl->width; j++){
|
620
|
+
p = &pkl->image[(i*pkl->width+j)*pkl->channel];
|
621
|
+
for(k=0; k<pkl->channel; k++){
|
622
|
+
*p = PKL_COLOR_CLIP(*p+color);
|
623
|
+
p++;
|
624
|
+
}
|
573
625
|
}
|
574
626
|
}
|
575
|
-
|
576
|
-
|
577
|
-
for(i=0; i<count; i++){
|
627
|
+
for(j=mpx; j<pkl->width; j+=mpx){
|
628
|
+
p = &pkl->image[(i*pkl->width+j)*pkl->channel];
|
578
629
|
for(k=0; k<pkl->channel; k++){
|
579
|
-
|
580
|
-
|
630
|
+
*p = PKL_COLOR_CLIP(*p+color);
|
631
|
+
p++;
|
581
632
|
}
|
582
633
|
}
|
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
634
|
}
|
590
635
|
|
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
636
|
return(0);
|
611
637
|
}
|