texplay 0.2.950 → 0.2.960

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/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ 4/7/10
2
+ version 0.2.960
3
+ * added :transparent pseudo-color
4
+ * added :tolerance option (applies to :trace and :source_select etc
5
+ family)
6
+ * fixed memleak in to_blob
7
+
1
8
  10/6/10
2
9
  version 0.2.950
3
10
  * fixed bug in apply_drawing_mode, wasn't using blended_pixel as source_pixel
data/README.markdown CHANGED
@@ -5,7 +5,7 @@
5
5
  INSTRUCTIONS
6
6
  ============
7
7
 
8
- **TexPlay version 0.2.950**
8
+ **TexPlay version 0.2.960**
9
9
 
10
10
  [Read The Documentation](http://banisterfiend.wordpress.com/2008/08/23/texplay-an-image-manipulation-tool-for-ruby-and-gosu/)
11
11
 
@@ -32,9 +32,9 @@ class W < Gosu::Window
32
32
 
33
33
  @copy2.splice @img, 0, 0, :crop => [@x2 - @rad, @y2 - @rad, @x2 + @rad, @y2 + @rad], :sync_mode => :no_sync
34
34
  @copy.splice @img, 0, 0, :crop => [@x - @rad, @y - @rad, @x + @rad, @y + @rad], :sync_mode => :no_sync
35
- @img.rect @x - @rad, @y - @rad, @x + @rad, @y + @rad, :fill => true, :mode => :overlay, :color => :tyrian
35
+ @img.rect @x - @rad, @y - @rad, @x + @rad, @y + @rad, :fill => true, :mode => :color_dodge, :color => 0xff888888, :alpha_blend => true
36
36
 
37
- @img.rect @x2 - @rad, @y2 - @rad, @x2 + @rad, @y2 + @rad, :fill => true, :mode => :invert, :color => :blue
37
+ @img.rect @x2 - @rad, @y2 - @rad, @x2 + @rad, @y2 + @rad, :fill => true, :mode => :color_dodge, :color => 0xff888888
38
38
 
39
39
  # @img.force_sync [0,0, @img.width, @img.height]
40
40
 
@@ -5,26 +5,26 @@ require 'texplay'
5
5
 
6
6
 
7
7
  class W < Gosu::Window
8
- def initialize
9
- super(500, 500, false, 20)
10
- @img = TexPlay.create_image(self, 500, 500)
11
- @img.rect 100, 100, 200, 300, :color => :red, :fill => true
12
- @img.rect 200, 100, 300, 300, :color => :blue, :fill => true
8
+ def initialize
9
+ super(500, 500, false, 20)
10
+ @img = TexPlay.create_image(self, 500, 500)
11
+ @img.rect 100, 100, 200, 300, :color => :red, :fill => true
12
+ @img.rect 200, 100, 300, 300, :color_control => proc { [0, 0, 1 - (0.5 * rand), 1.0] }, :fill => true
13
13
 
14
14
 
15
- @img.line 0, 0, 500, 500, :dest_ignore => :red
15
+ @img.line 0, 0, 500, 500, :dest_ignore => :red, :dest_select => :blue, :tolerance => 1
16
16
 
17
- @img.circle 200, 100, 50, :fill => true, :dest_select => [:red, :blue], :color => :orange
18
-
19
- end
20
-
21
- def draw
22
- @img.draw 100, 50,1
23
- end
17
+ @img.circle 200, 100, 50, :fill => true, :dest_select => [:red, :blue], :color => :transparent
24
18
 
19
+ end
20
+
21
+ def draw
22
+ @img.draw 100, 50,1
23
+ end
24
+
25
25
  end
26
26
 
27
27
 
28
28
  w = W.new
29
29
  w.show
30
-
30
+
@@ -7,12 +7,14 @@ class W < Gosu::Window
7
7
  def initialize
8
8
  super(500, 500, false, 20)
9
9
  @img = Gosu::Image.new(self, "#{Common::MEDIA}/gob.png")
10
- @sun = Gosu::Image.new(self, "#{Common::MEDIA}/sunset.png")
11
- @img.splice @sun, 0, 0, :mode => :exclusion
10
+ @img.rect 0, 0, @img.width - 1, @img.height - 1
11
+ puts @img.line 1,1, 1, @img.height - 1, :trace => { :while_color => :alpha }
12
+
13
+
12
14
  end
13
15
 
14
16
  def draw
15
- @img.draw 100, 50,1
17
+ @img.draw 50, 50,1
16
18
  end
17
19
  end
18
20
 
@@ -14,16 +14,23 @@
14
14
  /** line_do_action, bresenham's algorithm **/
15
15
  typedef enum { no_mode, until_color, while_color} trace_mode_type;
16
16
 
17
+ /* utility func to manage both kinds of color comparions */
18
+ static bool
19
+ cmp_color_with_or_without_tolerance(rgba c1, rgba c2, action_struct * payload)
20
+ {
21
+ return payload->pen.has_tolerance ? cmp_color_with_tolerance(c1, c2, payload->pen.tolerance) : cmp_color(c1, c2);
22
+ }
23
+
17
24
  static inline bool
18
- is_trace_match(rgba c, rgba trace_color, trace_mode_type trace_mode)
25
+ is_trace_match(action_struct * cur, rgba c, rgba trace_color, trace_mode_type trace_mode)
19
26
  {
20
27
  if(trace_mode == while_color) {
21
- if(!cmp_color(c, trace_color))
22
- return true;
28
+ if(!cmp_color_with_or_without_tolerance(c, trace_color, cur))
29
+ return true;
23
30
  }
24
31
  else if(trace_mode == until_color) {
25
- if(cmp_color(c, trace_color))
26
- return true;
32
+ if(cmp_color_with_or_without_tolerance(c, trace_color, cur))
33
+ return true;
27
34
  }
28
35
 
29
36
  return false;
@@ -98,7 +105,7 @@ line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_ar
98
105
  else {
99
106
  rgba c = get_pixel_color(tex, x, y);
100
107
 
101
- if (is_trace_match(c, trace_color, trace_mode))
108
+ if (is_trace_match(payload, c, trace_color, trace_mode))
102
109
  return (trace_match) { x, y, c };
103
110
  }
104
111
  }
@@ -126,7 +133,7 @@ line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_ar
126
133
  else {
127
134
  rgba c = get_pixel_color(tex, x, y);
128
135
 
129
- if (is_trace_match(c, trace_color, trace_mode))
136
+ if (is_trace_match(payload, c, trace_color, trace_mode))
130
137
  return (trace_match) { x, y, c };
131
138
  }
132
139
  }
@@ -151,7 +158,7 @@ line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_ar
151
158
  else {
152
159
  rgba c = get_pixel_color(tex, x, y);
153
160
 
154
- if (is_trace_match(c, trace_color, trace_mode))
161
+ if (is_trace_match(payload, c, trace_color, trace_mode))
155
162
  return (trace_match) { x, y, c };
156
163
  }
157
164
  }
@@ -337,10 +337,8 @@ m_get_options(VALUE self)
337
337
  static void
338
338
  get_image_chunk_with_size(char * data, texture_info * tex, char * blob)
339
339
  {
340
- int x, y;
341
-
342
- for(y = 0; y < tex->height; y++)
343
- for(x = 0; x < tex->width; x++) {
340
+ for(int y = 0; y < tex->height; y++)
341
+ for(int x = 0; x < tex->width; x++) {
344
342
  int buf_index = 4 * (x + y * tex->width);
345
343
 
346
344
  int offset = calc_pixel_offset(tex, x, y);
@@ -354,8 +352,6 @@ m_to_blob(VALUE self)
354
352
  {
355
353
  texture_info tex;
356
354
  int sidelength;
357
- VALUE blob;
358
- void * new_array = NULL;
359
355
 
360
356
  ADJUST_SELF(self);
361
357
 
@@ -368,12 +364,12 @@ m_to_blob(VALUE self)
368
364
  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &sidelength);
369
365
 
370
366
  /* initialize texture data array, mult. by 4 because {rgba} */
371
- new_array = malloc(sidelength * sidelength * 4);
367
+ char new_array[sidelength * sidelength * 4];
372
368
 
373
369
  /* get texture data from video memory */
374
370
  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,(void*)(new_array));
375
371
 
376
- blob = rb_str_new(NULL, 4 * tex.width * tex.height);
372
+ VALUE blob = rb_str_new(NULL, 4 * tex.width * tex.height);
377
373
 
378
374
  get_image_chunk_with_size(new_array, &tex, RSTRING_PTR(blob));
379
375
 
@@ -147,6 +147,13 @@ set_pixel_color(rgba * pixel_color, texture_info * tex, int x, int y)
147
147
  tex_data[alpha] = pixel_color->alpha;
148
148
  }
149
149
 
150
+ /* utility func to manage both kinds of color comparions */
151
+ static bool
152
+ cmp_color_with_or_without_tolerance(rgba c1, rgba c2, action_struct * payload)
153
+ {
154
+ return payload->pen.has_tolerance ? cmp_color_with_tolerance(c1, c2, payload->pen.tolerance) : cmp_color(c1, c2);
155
+ }
156
+
150
157
  static bool
151
158
  skip_pixel(rgba source_color, action_struct * payload, texture_info * tex, int x, int y)
152
159
  {
@@ -158,18 +165,17 @@ skip_pixel(rgba source_color, action_struct * payload, texture_info * tex, int x
158
165
 
159
166
  if (payload->pen.source_select.size > 0) {
160
167
  for (int i = 0; i < payload->pen.source_select.size; i++) {
161
- if (cmp_color(source_color, payload->pen.source_select.colors[i])) {
162
- color_match = true;
163
- break;
164
- }
165
- }
168
+ if (cmp_color_with_or_without_tolerance(source_color, payload->pen.source_select.colors[i], payload)) {
169
+ color_match = true;
170
+ break;
171
+ }
166
172
  if (!color_match) return true;
173
+ }
167
174
  }
168
-
169
175
 
170
176
  if (payload->pen.source_ignore.size > 0) {
171
177
  for (int i = 0; i < payload->pen.source_ignore.size; i++) {
172
- if (cmp_color(source_color, payload->pen.source_ignore.colors[i]))
178
+ if (cmp_color_with_or_without_tolerance(source_color, payload->pen.source_ignore.colors[i], payload))
173
179
  return true;
174
180
  }
175
181
  }
@@ -177,7 +183,7 @@ skip_pixel(rgba source_color, action_struct * payload, texture_info * tex, int x
177
183
  color_match = false;
178
184
  if (payload->pen.dest_select.size > 0) {
179
185
  for (int i = 0; i < payload->pen.dest_select.size; i++) {
180
- if (cmp_color(dest_color, payload->pen.dest_select.colors[i])) {
186
+ if (cmp_color_with_or_without_tolerance(dest_color, payload->pen.dest_select.colors[i], payload)) {
181
187
  color_match = true;
182
188
  break;
183
189
  }
@@ -187,7 +193,7 @@ skip_pixel(rgba source_color, action_struct * payload, texture_info * tex, int x
187
193
 
188
194
  if (payload->pen.dest_ignore.size > 0) {
189
195
  for (int i = 0; i < payload->pen.dest_ignore.size; i++) {
190
- if (cmp_color(dest_color, payload->pen.dest_ignore.colors[i]))
196
+ if (cmp_color_with_or_without_tolerance(dest_color, payload->pen.dest_ignore.colors[i], payload))
191
197
  return true;
192
198
  }
193
199
  }
@@ -359,6 +365,10 @@ initialize_action_struct(action_struct * cur, VALUE hash_arg, sync sync_mode)
359
365
  cur->pen.source_ignore.size = 0;
360
366
  cur->pen.dest_select.size = 0;
361
367
  cur->pen.dest_ignore.size = 0;
368
+
369
+ /* tolerance */
370
+ cur->pen.has_tolerance = false;
371
+ cur->pen.tolerance = 0.0;
362
372
  }
363
373
 
364
374
  /* TODO: fix this function below, it's too ugly and bulky and weird **/
@@ -400,6 +410,20 @@ process_common_hash_args(action_struct * cur, VALUE * hash_arg, sync sync_mode,
400
410
  cur->pen.has_color_control_transform = true;
401
411
  }
402
412
 
413
+ /* tolerance */
414
+ if(RTEST(get_from_hash(*hash_arg, "tolerance"))) {
415
+ cur->pen.tolerance = NUM2DBL(get_from_hash(*hash_arg, "tolerance"));
416
+
417
+ /* maximum length of hypotonese extended in 4-space (color space) is sqrt(4) */
418
+ if (cur->pen.tolerance >= 2)
419
+ cur->pen.tolerance = 2;
420
+
421
+ if (cur->pen.tolerance < 0)
422
+ cur->pen.tolerance = 0;
423
+
424
+ cur->pen.has_tolerance = true;
425
+ }
426
+
403
427
  /* lerp */
404
428
  if(RTEST(get_from_hash(*hash_arg, "lerp"))) {
405
429
  cur->pen.lerp = NUM2DBL(get_from_hash(*hash_arg, "lerp"));
@@ -56,7 +56,8 @@ typedef enum {
56
56
 
57
57
  /* structs */
58
58
  typedef struct s_rgba {
59
- float red, green, blue, alpha;
59
+ float red, green, blue, alpha;
60
+ float tolerance;
60
61
  } rgba;
61
62
 
62
63
  typedef struct {
@@ -129,10 +130,11 @@ typedef struct action_struct {
129
130
  bool has_drawing_mode;
130
131
  draw_mode drawing_mode;
131
132
 
132
-
133
+ /* tolerance */
134
+ bool has_tolerance;
135
+ float tolerance;
133
136
 
134
137
  /* color selection */
135
-
136
138
  bool has_color_select;
137
139
  rgba_list source_select;
138
140
  rgba_list source_ignore;
data/ext/texplay/utils.c CHANGED
@@ -306,15 +306,64 @@ not_rb_raw_color(VALUE cval)
306
306
  !is_a_num(get_from_array(cval, 0));
307
307
  }
308
308
 
309
+ /** cmp_color related functions **/
310
+ static bool
311
+ is_transparent_color(rgba color1)
312
+ {
313
+ return color1.red == -666 && color1.green == -666 && color1.blue == -666 &&
314
+ color1.alpha == -666;
315
+ }
316
+
317
+ static bool
318
+ special_cmp_color(rgba color1, rgba color2)
319
+ {
320
+ if (is_transparent_color(color1))
321
+ return color2.alpha == 0;
322
+ else if (is_transparent_color(color2))
323
+ return color1.alpha == 0;
324
+ }
325
+
326
+ static bool
327
+ special_cmp_color_with_tolerance(rgba color1, rgba color2, float tolerance)
328
+ {
329
+ if (is_transparent_color(color1))
330
+ return (color1.alpha) <= tolerance;
331
+ else if (is_transparent_color(color2))
332
+ return color2.alpha <= tolerance;
333
+ }
334
+
335
+
336
+ static float
337
+ color_distance_squared(rgba c1, rgba c2)
338
+ {
339
+ return (c1.red - c2.red) * (c1.red - c2.red) +
340
+ (c1.green - c2.green) * (c1.green - c2.green) +
341
+ (c1.blue - c2.blue) * (c1.blue - c2.blue) +
342
+ (c1.alpha - c2.alpha) * (c1.alpha - c2.alpha);
343
+ }
344
+
309
345
 
310
346
  bool
311
- cmp_color(rgba color1, rgba color2)
347
+ cmp_color_with_tolerance(rgba color1, rgba color2, float tolerance)
312
348
  {
349
+ if (color1.red < 0 || color2.red < 0)
350
+ return special_cmp_color_with_tolerance(color1, color2, tolerance);
351
+
352
+ return color_distance_squared(color1, color2) <= (tolerance * tolerance);
353
+ }
313
354
 
355
+ bool
356
+ cmp_color(rgba color1, rgba color2)
357
+ {
358
+ if (color1.red < 0 || color2.red < 0)
359
+ return special_cmp_color(color1, color2);
360
+
314
361
  return (color1.red == color2.red) && (color1.green == color2.green) && (color1.blue == color2.blue)
315
362
  && (color1.alpha == color2.alpha);
316
363
  }
364
+
317
365
 
366
+ /*** these functions are UNSAFE ***/
318
367
  void
319
368
  color_copy(float * source, float * dest)
320
369
  {
@@ -327,6 +376,7 @@ zero_color(float * tex)
327
376
  {
328
377
  memset(tex, 0, 4 * sizeof(float));
329
378
  }
379
+ /*** ***/
330
380
 
331
381
  rgba
332
382
  find_color_from_string(char * try_color)
@@ -372,6 +422,9 @@ find_color_from_string(char * try_color)
372
422
  else if(!strcmp("alpha", try_color)) {
373
423
  cur_color.red = 0.0; cur_color.green = 0.0; cur_color.blue = 0.0; cur_color.alpha = 0.0;
374
424
  }
425
+ else if(!strcmp("transparent", try_color)) {
426
+ cur_color.red = -666; cur_color.green = -666; cur_color.blue = -666; cur_color.alpha = -666;
427
+ }
375
428
  else if(!strcmp("none", try_color)) {
376
429
  cur_color = not_a_color_v;
377
430
  }
@@ -438,7 +491,7 @@ convert_rgba_to_gosu_color(rgba * pix)
438
491
  VALUE
439
492
  gosu_color_class()
440
493
  {
441
- VALUE gcolor_class = 0;
494
+ static VALUE gcolor_class = 0;
442
495
 
443
496
  if (gcolor_class == 0) {
444
497
  VALUE gosu_class = rb_const_get(rb_cObject, rb_intern("Gosu"));
@@ -476,6 +529,8 @@ convert_rb_color_to_rgba(VALUE cval)
476
529
  my_color.alpha = 1;
477
530
 
478
531
  break;
532
+
533
+ /* hex literals */
479
534
  case T_FIXNUM:
480
535
  case T_BIGNUM:
481
536
  return convert_gosu_to_rgba_color(rb_funcall(gosu_color_class(),
data/ext/texplay/utils.h CHANGED
@@ -14,6 +14,7 @@ extern const rgba not_a_color_v;
14
14
  /* color and pixel related functions */
15
15
  rgba find_color_from_string(char * try_color);
16
16
  bool cmp_color(rgba color1, rgba color2);
17
+ bool cmp_color_with_tolerance(rgba color1, rgba color2, float tolerance);
17
18
  void color_copy(float * source, float * dest);
18
19
  rgba get_pixel_color(texture_info * tex, int x, int y) ;
19
20
  float* get_pixel_data(texture_info * tex, int x, int y);
@@ -1,3 +1,3 @@
1
1
  module TexPlay
2
- VERSION = "0.2.950"
2
+ VERSION = "0.2.960"
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 950
9
- version: 0.2.950
8
+ - 960
9
+ version: 0.2.960
10
10
  platform: ruby
11
11
  authors:
12
12
  - John Mair (banisterfiend)
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-10 00:00:00 +02:00
17
+ date: 2010-07-04 00:00:00 +12:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency