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
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
@@ -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
- // pkl_pattern_hexagon
17
+ // pkl_pattern
8
18
  //=============================================================================
9
- PKLExport int pkl_pattern_hexagon(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE type)
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 i, result;
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
- 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
- }
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
- // pkl_pattern_diamond
63
+ // pattern_hexagon
51
64
  //=============================================================================
52
- PKLExport int pkl_pattern_diamond(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE type)
65
+ void pattern_hexagon(int ph, double *wd, double ww, double hh)
53
66
  {
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
- /* パターン座標を構築する */
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
- // pkl_pattern_circle
99
+ // pattern_circle
88
100
  //=============================================================================
89
- PKLExport int pkl_pattern_circle(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE type)
101
+ void pattern_circle(int ph, double *wd, double ww, double hh)
90
102
  {
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
- /* パターン座標を構築する */
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
- // pkl_pattern_brick
114
+ // pattern_brick
125
115
  //=============================================================================
126
- PKLExport int pkl_pattern_brick(PKLImage pkl, int pw, int ph, PKL_PAINT_TYPE type)
116
+ void pattern_brick(int ph, double *wd, double ww, double hh)
127
117
  {
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
- /* パターン座標を構築する */
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
- static int pkl_pattern_draw_line(PKLImage pkl, double *wd, int pw, int ph)
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
- static int pkl_pattern_draw_average(PKLImage pkl, double *wd, int pw, int ph)
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
- // voronoi_type1 datatype
253
+ // pkl_tile
286
254
  //=============================================================================
287
- struct VoronoiPoint {
288
- int x, y;
289
- long color[PKL_CHANNEL];
290
- unsigned char ave[PKL_CHANNEL];
291
- int count;
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
- // voronoi_type1_query
274
+ // tile_brick
296
275
  //=============================================================================
297
- static void voronoi_type1_query(PKLImage pkl, struct VoronoiPoint *vptr, int *id, int zone, int xzone, int yzone)
276
+ static int tile_brick(PKLImage pkl, int msx, int msy, unsigned char level)
298
277
  {
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;
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
- 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
- }
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
- 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;
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
- // pkl_voronoi_type1
355
+ // tile_rectangle
350
356
  //=============================================================================
351
- PKLExport int pkl_voronoi_type1(PKLImage pkl, int zone, int bordercolor, int test)
357
+ static int tile_rectangle(PKLImage pkl, int msx, int msy, unsigned char level)
352
358
  {
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
- }
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
- 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
- }
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
- // voronoi_type2 datatype
423
- //=============================================================================
424
- //ボロノイの母点管理用(1つの母点から隣接する母点の個数)
425
- #define VORONOI_CNT 10 //根拠はない
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
- 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
- };
401
+ return(0);
402
+ }
434
403
 
435
404
  //=============================================================================
436
- // vcompare
405
+ // tile_pattern
437
406
  //=============================================================================
438
- static int vcompare(const void *a, const void *b)
407
+ static int tile_pattern(PKLImage pkl, PKL_TILE_TYPE type, int pw, int ph, unsigned char level)
439
408
  {
440
- struct VORONOI *t1 = (struct VORONOI *)a;
441
- struct VORONOI *t2 = (struct VORONOI *)b;
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
- if(t1->y == t2->y)
444
- return(t1->x - t2->x);
445
- return(t1->y - t2->y);
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
- // voronoi_setid
438
+ // tile_pattern_draw
450
439
  //=============================================================================
451
- static void voronoi_setid(int *ary, int id)
440
+ static int tile_pattern_draw(PKLImage pkl, double *wd, int pw, int ph, unsigned char level)
452
441
  {
453
- int i;
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
- for(i=0; i<VORONOI_CNT; i++){
456
- if(ary[i] == -1){
457
- ary[i] = id;
458
- return;
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
- // voronoi_type2_query
484
+ // pkl_mosaic
465
485
  //=============================================================================
466
- static void voronoi_type2_query(PKLImage pkl, struct VORONOI *kp, int *ip, int count)
486
+ PKLExport int pkl_mosaic(PKLImage pkl, int msx, int msy)
467
487
  {
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);
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
- 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
- }
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
- 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
- }
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
- //最も近くにある母点の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);
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
- //現在の座標のIDに決定したボロノイ管理IDを設定する
524
- ip[j*pkl->width+i] = min_id;
525
- pre_id = min_id;
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
- // pkl_voronoi_type2
604
+ // pkl_grid
532
605
  //=============================================================================
533
- PKLExport int pkl_voronoi_type2(PKLImage pkl, int count, int bordercolor, int test)
606
+ PKLExport int pkl_grid(PKLImage pkl, int msx, int msy, int color)
534
607
  {
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];
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
- if(kp[i].count!=0)
580
- kp[i].color[k] = PKL_COLOR_CLIP(kp[i].color[k]/kp[i].count);
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
  }