compix 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d31400ba7b637660ef09a34d8c45228d25811274
4
- data.tar.gz: 2c5589a1b5da50cd87e2d4ad50a908168139acf7
3
+ metadata.gz: 573a0eea05badf4bd1964736361513caeed36ecb
4
+ data.tar.gz: 952fc5643ce5a5fd16b9f45d540f7bb101c14ca0
5
5
  SHA512:
6
- metadata.gz: 6676275970f1c794242b386f74f0fc5fd419a96800e758db97d57ce7b79741092638098a9a15a36d683d3f2ebae9d9f589ebb23ebffa0e007db491e30ea13b04
7
- data.tar.gz: 07740fd33ca945ab6c89c7d522ff284561823b3701696a62b45c7806c2b49420e4693715f701ccb34db94cb5cc7cd1960ee2650599139e9309e68a4899a69a9f
6
+ metadata.gz: a0fd67bdf4fbfb99f753aed312fea832dffe4fcb3713565b54cc2337ef115440226a8c5cba4e39e1138b39de9e277f3b04c56446198af423076a06910355d700
7
+ data.tar.gz: 98ec2b5321a0e51d7476db720fab5965afe10ffe691325f937abab55454b8f7dafeb5aed224594f671f7fc71f336ff2e778c47d41744c8d84228903132f033e7
@@ -5,7 +5,7 @@
5
5
 
6
6
  void Init_compix(){
7
7
  VALUE CompixModule = rb_define_module("Compix");
8
- rb_define_singleton_method(CompixModule, "find_subimage", find_subimage, 3);
8
+ rb_define_singleton_method(CompixModule, "find_subimage", find_subimage, -1);
9
9
  }
10
10
 
11
11
  bool compare_pixels(PIXEL pone, PIXEL ptwo, int threshold){
@@ -23,7 +23,7 @@ bool compare_pixels(PIXEL pone, PIXEL ptwo, int threshold){
23
23
  return true;
24
24
  }
25
25
 
26
- int compare_at(PIXEL *pixelsSmall, PIXEL *pixelsBig, int thres, int bigXoffset, int bigYoffset,
26
+ int compare_at(PIXEL *pixelsSmall, PIXEL *pixelsBig, int color_threshold, int bigXoffset, int bigYoffset,
27
27
  int siwidth, int siheight, int sswidth, int ssheight){
28
28
  PIXEL firstPixel;
29
29
  PIXEL secPixel;
@@ -41,7 +41,7 @@ int compare_at(PIXEL *pixelsSmall, PIXEL *pixelsBig, int thres, int bigXoffset,
41
41
  break;
42
42
  }
43
43
  secPixel = pixelsBig[bigCoord];
44
- if(compare_pixels(firstPixel, secPixel, thres)){
44
+ if(compare_pixels(firstPixel, secPixel, color_threshold)){
45
45
  match++;
46
46
  }
47
47
  else {
@@ -55,57 +55,49 @@ int compare_at(PIXEL *pixelsSmall, PIXEL *pixelsBig, int thres, int bigXoffset,
55
55
  return match;
56
56
  }
57
57
 
58
- PIXEL* image_to_bytearray(PIXEL *bytearray_ptr, VALUE image){
59
- VALUE pixels = rb_funcall(image, rb_intern("pixels"), 0);
60
- int x, y;
61
-
62
- int width = NUM2INT(rb_funcall(image, rb_intern("width"), 0));
63
- int height = NUM2INT(rb_funcall(image, rb_intern("height"), 0));
58
+ // (VALUE self, VALUE subimage, VALUE bigimage, VALUE options)
59
+ VALUE find_subimage(int argc, VALUE* argv, VALUE self){
60
+ VALUE subimage = argv[0];
61
+ VALUE image = argv[1];
62
+ VALUE options_hash;
63
+ int color_threshold = 0;
64
+ double pixels_threshold = 0;
65
+ int xstart = 0;
66
+ int ystart = 0 ;
64
67
 
65
- for(y = 0 ; y < height ; y++){
66
- for(x = 0 ; x < width ; x++){
67
- bytearray_ptr[y * width + x] = NUM2UINT(rb_ary_entry(pixels, y * width + x));
68
- }
68
+ if(argc == 3){
69
+ options_hash = argv[2];
70
+ color_threshold = integer_from_hash(options_hash, "threshold", 0, 0, 255);
71
+ xstart = integer_from_hash(options_hash, "start_coordinate_x", 0, 0, INT_MAX);
72
+ ystart = integer_from_hash(options_hash, "start_coordinate_y", 0, 0, INT_MAX);
73
+ pixels_threshold = float_from_hash(options_hash, "pixels_threshold", 0.85, 0.0, 1.0);
69
74
  }
70
- return bytearray_ptr;
71
- }
72
75
 
73
- VALUE find_subimage(VALUE self, VALUE subimage, VALUE bigimage, VALUE threshold){
74
76
  VALUE subimage_match_obj;
75
77
 
76
78
  int siwidth = NUM2INT(rb_funcall(subimage, rb_intern("width"), 0));
77
79
  int siheight = NUM2INT(rb_funcall(subimage, rb_intern("height"), 0));
78
- int sswidth = NUM2INT(rb_funcall(bigimage, rb_intern("width"), 0));
79
- int ssheight = NUM2INT(rb_funcall(bigimage, rb_intern("height"), 0));
80
+ int sswidth = NUM2INT(rb_funcall(image, rb_intern("width"), 0));
81
+ int ssheight = NUM2INT(rb_funcall(image, rb_intern("height"), 0));
80
82
 
81
83
  PIXEL *bytearray_subimg = malloc(siwidth * siheight * sizeof(PIXEL));
82
84
  PIXEL *bytearray_big_image = malloc(sswidth * ssheight * sizeof(PIXEL));
83
-
84
- int thres = NUM2UINT(threshold);
85
+
85
86
  int match = 0;
86
87
  int maxmatch = 0;
87
88
  int maxX = -1;
88
89
  int maxY = -1;
89
- //int xLeftLimit = NUM2INT(rb_ary_entry(minCoord, 0));
90
- //int yTopLimit = NUM2INT(rb_ary_entry(minCoord, 1));
91
- //int xRightLimit = NUM2INT(rb_ary_entry(maxCoord, 0));
92
- //int yBottomLimit = NUM2INT(rb_ary_entry(maxCoord, 1));
93
- // I didn't want to break backwards compatibility, so while this is less legible
94
- // and slower if old version of compix is used, it will still work.
95
- // The third and fourth entry in the array specifies from where to start checking the big image.
96
- // Used for e.g. findAllSubImages in rubypng
97
- int xstart = 0; //NUM2INT(rb_ary_entry(minCoord, 2));
98
- int ystart = 0 ; //NUM2INT(rb_ary_entry(minCoord, 3));
90
+
99
91
  int x, y;
100
92
  int compPix = siwidth * siheight;
101
93
 
102
94
  // Create bytearrays for pixels
103
95
  bytearray_subimg = image_to_bytearray(bytearray_subimg, subimage);
104
- bytearray_big_image = image_to_bytearray(bytearray_big_image, bigimage);
96
+ bytearray_big_image = image_to_bytearray(bytearray_big_image, image);
105
97
 
106
98
  for(y = ystart ; y <= ssheight - siheight; y++){
107
99
  for(x = xstart ; x <= sswidth - siwidth; x++){
108
- match = compare_at(bytearray_subimg, bytearray_big_image, thres, x, y,
100
+ match = compare_at(bytearray_subimg, bytearray_big_image, color_threshold, x, y,
109
101
  siwidth, siheight, sswidth, ssheight);
110
102
  if(match > maxmatch){
111
103
  maxmatch = match;
@@ -113,20 +105,12 @@ VALUE find_subimage(VALUE self, VALUE subimage, VALUE bigimage, VALUE threshold)
113
105
  maxY = y;
114
106
  }
115
107
  }
108
+ xstart = 0;
116
109
  }
117
110
 
118
111
  free(bytearray_subimg);
119
112
  free(bytearray_big_image);
120
113
 
121
- subimage_match_obj = initialize_subimage_match_obj(maxX, maxY, compPix, maxmatch);
114
+ subimage_match_obj = initialize_subimage_match_obj(maxX, maxY, compPix, maxmatch, siwidth, siheight, pixels_threshold);
122
115
  return subimage_match_obj;
123
116
  }
124
-
125
- VALUE initialize_subimage_match_obj(int coord_x, int coord_y, int pixels_compared, int pixels_matched){
126
- VALUE mCompixModule = rb_const_get(rb_cObject, rb_intern("Compix"));
127
- VALUE cSubimageMatch = rb_const_get(mCompixModule, rb_intern("SubimageMatch"));
128
-
129
- VALUE match_obj = rb_funcall(cSubimageMatch, rb_intern("new"), 4, INT2NUM(coord_x), INT2NUM(coord_y),
130
- INT2NUM(pixels_compared), INT2NUM(pixels_matched));
131
- return match_obj;
132
- }
@@ -3,29 +3,16 @@
3
3
 
4
4
  #include <ruby.h>
5
5
  #include <stdbool.h>
6
+ #include "compix_helpers.h"
6
7
 
7
8
 
8
-
9
- // Types and macros from OilyPNG for compatibility
10
- typedef uint32_t PIXEL; // Pixels use 32 bits unsigned integers
11
- typedef unsigned char BYTE; // Bytes use 8 bits unsigned integers
12
- #define R_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0xff000000) >> 24))
13
- #define G_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x00ff0000) >> 16))
14
- #define B_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x0000ff00) >> 8))
15
- #define A_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x000000ff)))
16
-
17
9
  void Init_compix();
18
10
 
19
- VALUE find_subimage(VALUE self, VALUE subimage, VALUE bigimage, VALUE threshold);
20
-
21
- VALUE initialize_subimage_match_obj(int coord_x, int coord_y, int pixels_compared, int pixels_matched);
11
+ VALUE find_subimage(int argc, VALUE* argv, VALUE self);
22
12
 
23
13
  int compare_at(PIXEL *pixelsSmall, PIXEL *pixelsBig, int thres, int bigXoffset, int bigYoffset,
24
14
  int siwidth, int siheight, int sswidth, int ssheight);
25
15
 
26
16
  bool compare_pixels(PIXEL pone, PIXEL ptwo, int threshold);
27
17
 
28
- // The bytearray_ptr should be allocated for the correct size.
29
- PIXEL* image_to_bytearray(PIXEL *bytearray_ptr, VALUE image);
30
-
31
18
  #endif
@@ -0,0 +1,51 @@
1
+ #include "compix_helpers.h"
2
+
3
+ PIXEL* image_to_bytearray(PIXEL *bytearray_ptr, VALUE image){
4
+ VALUE pixels = rb_funcall(image, rb_intern("pixels"), 0);
5
+ int x, y;
6
+
7
+ int width = NUM2INT(rb_funcall(image, rb_intern("width"), 0));
8
+ int height = NUM2INT(rb_funcall(image, rb_intern("height"), 0));
9
+
10
+ for(y = 0 ; y < height ; y++){
11
+ for(x = 0 ; x < width ; x++){
12
+ bytearray_ptr[y * width + x] = NUM2UINT(rb_ary_entry(pixels, y * width + x));
13
+ }
14
+ }
15
+ return bytearray_ptr;
16
+ }
17
+
18
+ int integer_from_hash(VALUE hash, char* key, int default_value, int min_value, int max_value){
19
+ VALUE val = rb_hash_aref(hash, RB_SYM(key));
20
+ if( TYPE(val) != T_NIL ) {
21
+ int c_value = NUM2INT(val);
22
+ if ( c_value < min_value || c_value > max_value ){
23
+ rb_raise(rb_eArgError, "argument '%s' has value %d. Allowed range is %d..%d", key, c_value, min_value, max_value);
24
+ }
25
+ return c_value;
26
+ }
27
+ return default_value;
28
+ }
29
+
30
+ double float_from_hash(VALUE hash, char* key, double default_value, double min_value, double max_value){
31
+ VALUE val = rb_hash_aref(hash, RB_SYM(key));
32
+ if( TYPE(val) != T_NIL ) {
33
+ double c_value = NUM2DBL(val);
34
+ if ( c_value < min_value || c_value > max_value ){
35
+ rb_raise(rb_eArgError, "argument '%s' has value %d. Allowed range is %d..%d", key, c_value, min_value, max_value);
36
+ }
37
+ return c_value;
38
+ }
39
+ return default_value;
40
+ }
41
+
42
+ VALUE initialize_subimage_match_obj(int coord_x, int coord_y, int pixels_compared, int pixels_matched,
43
+ int subimage_width, int subimage_height, float limit_for_match) {
44
+ VALUE mCompixModule = rb_const_get(rb_cObject, rb_intern("Compix"));
45
+ VALUE cSubimageMatch = rb_const_get(mCompixModule, rb_intern("SubimageMatch"));
46
+
47
+ VALUE match_obj = rb_funcall(cSubimageMatch, rb_intern("new"), 7, INT2NUM(coord_x), INT2NUM(coord_y),
48
+ INT2NUM(pixels_compared), INT2NUM(pixels_matched),
49
+ INT2NUM(subimage_width), INT2NUM(subimage_height), DBL2NUM(limit_for_match));
50
+ return match_obj;
51
+ }
@@ -0,0 +1,32 @@
1
+ #ifndef COMPIX_HELPERS_H
2
+ #define COMPIX_HELPERS_H
3
+
4
+ #include <ruby.h>
5
+ #include <stdbool.h>
6
+
7
+
8
+ // Types and macros from OilyPNG for compatibility
9
+ typedef uint32_t PIXEL; // Pixels use 32 bits unsigned integers
10
+ typedef unsigned char BYTE; // Bytes use 8 bits unsigned integers
11
+ #define R_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0xff000000) >> 24))
12
+ #define G_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x00ff0000) >> 16))
13
+ #define B_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x0000ff00) >> 8))
14
+ #define A_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x000000ff)))
15
+
16
+ // Symbols for options for method find_subimage
17
+ #define RB_SYM(string) ID2SYM(rb_intern(string))
18
+
19
+
20
+
21
+ // The bytearray_ptr should be allocated for the correct size.
22
+ PIXEL* image_to_bytearray(PIXEL *bytearray_ptr, VALUE image);
23
+
24
+ int integer_from_hash(VALUE hash, char* key, int default_value, int min_value, int max_value);
25
+
26
+ double float_from_hash(VALUE hash, char* key, double default_value, double min_value, double max_value);
27
+
28
+ VALUE initialize_subimage_match_obj(int coord_x, int coord_y, int pixels_compared, int pixels_matched,
29
+ int subimage_width, int subimage_height, float limit_for_match);
30
+
31
+
32
+ #endif
@@ -2,5 +2,25 @@ require 'compix.so'
2
2
  require 'compix/match.rb'
3
3
 
4
4
  module Compix
5
+ def self.find_all_instances_of_subimage(subimage, image, options={})
6
+ options[:start_coordinate_x] ||= 0
7
+ options[:start_coordinate_y] ||= 0
8
+ matches = []
5
9
 
10
+ subimage_match = self.find_subimage(subimage, image, options)
11
+ while subimage_match.match?
12
+ skip = false
13
+ matches.each do |match|
14
+ if match.overlaped_by?(subimage_match)
15
+ skip = true
16
+ break
17
+ end
18
+ end
19
+ matches << subimage_match unless skip
20
+ options[:start_coordinate_y] = subimage_match.coordinate_y
21
+ options[:start_coordinate_x] = subimage_match.coordinate_x + subimage.width
22
+ subimage_match = self.find_subimage(subimage, image, options)
23
+ end
24
+ matches
25
+ end
6
26
  end
@@ -1,15 +1,19 @@
1
1
  require 'chunky_png'
2
2
 
3
+ DEFAULT_PERCENT = 0.85
3
4
 
4
5
  class Compix::SubimageMatch
5
- attr_reader :coordinate_x, :coordinate_y, :pixels_compared, :pixels_matched
6
+ attr_reader :coordinate_x, :coordinate_y, :pixels_compared, :pixels_matched, :width, :height
6
7
 
7
- def initialize(coord_x, coord_y, pixels_compared, pixels_matched)
8
+ def initialize(coord_x, coord_y, pixels_compared, pixels_matched, width, height, limit_for_match=DEFAULT_PERCENT)
8
9
  raise ArgumentError.new("Matched more pixels ('#{pixels_matched}') than compared ('#{pixels_compared}')") if pixels_compared < pixels_matched
9
10
  @coordinate_x = coord_x
10
11
  @coordinate_y = coord_y
11
12
  @pixels_compared = pixels_compared
12
13
  @pixels_matched = pixels_matched
14
+ @width = width
15
+ @height = height
16
+ @match = limit_for_match <= self.match_percentage
13
17
  end
14
18
 
15
19
  def match_percentage
@@ -17,11 +21,29 @@ class Compix::SubimageMatch
17
21
  pixels_matched.to_f / pixels_compared
18
22
  end
19
23
 
24
+ def match?
25
+ @match
26
+ end
27
+
20
28
  def eql?(other)
21
29
  other.class.eql?(self.class) && other.state.eql?(self.state)
22
30
  end
23
31
 
32
+ def overlaped_by?(other)
33
+ return false if other.coordinate_x + other.width <= @coordinate_x
34
+ return false if other.coordinate_x >= @coordinate_x + @width
35
+ return false if other.coordinate_y + other.height <= @coordinate_y
36
+ return false if other.coordinate_y >= @coordinate_y + @height
37
+ true
38
+ end
39
+
24
40
  def state
25
41
  [@coordinate_x, @coordinate_y, @pixels_compared, @pixels_matched]
26
42
  end
43
+
44
+ def coordinate_middle
45
+ x = @coordinate_x + @width / 2
46
+ y = @coordinate_y + @height / 2
47
+ return [x, y]
48
+ end
27
49
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: compix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Appelberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-29 00:00:00.000000000 Z
11
+ date: 2014-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -75,6 +75,8 @@ extra_rdoc_files: []
75
75
  files:
76
76
  - ext/compix/compix.c
77
77
  - ext/compix/compix.h
78
+ - ext/compix/compix_helpers.c
79
+ - ext/compix/compix_helpers.h
78
80
  - ext/compix/extconf.rb
79
81
  - lib/compix.rb
80
82
  - lib/compix/match.rb