redeye 1.0.0
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.
- checksums.yaml +7 -0
- data/README.md +5 -0
- data/Rakefile +48 -0
- data/ext/redeye/extconf.rb +102 -0
- data/ext/redeye/redeye.c +885 -0
- data/ext/redeye/redeye.cr +650 -0
- data/ext/redeye/redeye.rd +23 -0
- data/lib/redeye.rb +2 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6f0acad32d2e9ee0122e452c3cff1f4823cd4193
|
4
|
+
data.tar.gz: fbc4592fd714bf7bbddd1a4e0631484e8f56b590
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d481371139a391fa4b863e11b65b8b6599da2cf7d021a25f92250a2f835d018cda834c490baa5b72a6d479ca58a64bc07092ffc7c4d8fae60c425680a264f2df
|
7
|
+
data.tar.gz: 6211f766b9827c43c6001e7f0b30ac9ce47b1389059fa590a93e70a10cd34f7117e1d091f8c2b03037ea7fc1b33d1f4d888fb618e5606f6c0c9204f30e8cd2ec
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'rake-compiler'
|
3
|
+
require 'rake/extensiontask'
|
4
|
+
BASE_DIR = Dir.pwd
|
5
|
+
require 'rubygems/package_task'
|
6
|
+
require 'rake/testtask'
|
7
|
+
|
8
|
+
exts = []
|
9
|
+
|
10
|
+
namespace :prepare do
|
11
|
+
FileList["ext/*/*.cr"].each do |cr|
|
12
|
+
dir = File.dirname(cr)
|
13
|
+
name = File.basename(dir)
|
14
|
+
desc "Generate source for #{name}"
|
15
|
+
task(name.intern) do
|
16
|
+
sh 'rubber-generate', '--build-dir', dir, cr
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
spec = Gem::Specification.new do |s|
|
22
|
+
s.name = "redeye"
|
23
|
+
s.author = "Geoff Youngs"
|
24
|
+
s.email = "git@intersect-uk.co.uk"
|
25
|
+
s.version = "1.0.0"
|
26
|
+
s.homepage = "http://github.com/geoffyoungs/redeye"
|
27
|
+
s.summary = "Redeye correction for Gdk::Pixbuf"
|
28
|
+
s.add_dependency("rubber-generate", ">= 0.0.17")
|
29
|
+
s.add_dependency("glib2", ">= 1.1.9")
|
30
|
+
s.add_dependency("gdk_pixbuf2", ">= 1.1.9")
|
31
|
+
s.platform = Gem::Platform::RUBY
|
32
|
+
s.extensions = FileList["ext/*/extconf.rb"]
|
33
|
+
s.files = FileList['ext/*/*.{c,h,cr,rd}'] + ['Rakefile', 'README.md'] + FileList['lib/**/*.rb']
|
34
|
+
s.description = <<-EOF
|
35
|
+
Redeye correction methods for redeye
|
36
|
+
EOF
|
37
|
+
end
|
38
|
+
Gem::PackageTask.new(spec) do |pkg|
|
39
|
+
pkg.need_tar = true
|
40
|
+
end
|
41
|
+
Rake::ExtensionTask.new("redeye", spec)
|
42
|
+
|
43
|
+
Rake::TestTask.new do |t|
|
44
|
+
t.test_files = FileList['test/*_test.rb']
|
45
|
+
end
|
46
|
+
|
47
|
+
task :default, :compile
|
48
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
use_gems = false
|
3
|
+
begin
|
4
|
+
require 'mkmf-gnome2'
|
5
|
+
rescue LoadError
|
6
|
+
use_gems = true
|
7
|
+
end
|
8
|
+
|
9
|
+
if use_gems or Object.const_defined?('Gem')
|
10
|
+
require 'rubygems'
|
11
|
+
gem 'glib2'
|
12
|
+
require 'mkmf-gnome2'
|
13
|
+
%w[rbglib.h rbgtk.h rbpango.h rbatk.h].each do |header|
|
14
|
+
Gem.find_files(header).each do |f|
|
15
|
+
$CFLAGS += " '-I#{File.dirname(f)}'"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
# Look for headers in {gem_root}/ext/{package}
|
20
|
+
if use_gems
|
21
|
+
%w[
|
22
|
+
glib2 gdk_pixbuf2 atk gtk2 ].each do |package|
|
23
|
+
require package
|
24
|
+
$CFLAGS += " -I"+Gem.loaded_specs[package].full_gem_path+"/ext/"+package
|
25
|
+
end
|
26
|
+
end
|
27
|
+
if RbConfig::CONFIG.has_key?('rubyhdrdir')
|
28
|
+
$CFLAGS += " -I" + RbConfig::CONFIG['rubyhdrdir']+'/ruby'
|
29
|
+
end
|
30
|
+
|
31
|
+
$CFLAGS += " -I."
|
32
|
+
have_func("rb_errinfo")
|
33
|
+
PKGConfig.have_package("gtk+-2.0") or exit(-1)
|
34
|
+
have_header("gdk-pixbuf/gdk-pixbuf.h") or exit(-1)
|
35
|
+
|
36
|
+
STDOUT.print("checking for new allocation framework... ") # for ruby-1.7
|
37
|
+
if Object.respond_to? :allocate
|
38
|
+
STDOUT.print "yes
|
39
|
+
"
|
40
|
+
$defs << "-DHAVE_OBJECT_ALLOCATE"
|
41
|
+
else
|
42
|
+
STDOUT.print "no
|
43
|
+
"
|
44
|
+
end
|
45
|
+
|
46
|
+
top = File.expand_path(File.dirname(__FILE__) + '/..') # XXX
|
47
|
+
$CFLAGS += " " + ['glib/src'].map{|d|
|
48
|
+
"-I" + File.join(top, d)
|
49
|
+
}.join(" ")
|
50
|
+
|
51
|
+
have_func("rb_define_alloc_func") # for ruby-1.8
|
52
|
+
|
53
|
+
#set_output_lib('libruby-redeye.a')
|
54
|
+
if /cygwin|mingw/ =~ RUBY_PLATFORM
|
55
|
+
top = "../.."
|
56
|
+
[
|
57
|
+
["glib/src", "ruby-glib2"],
|
58
|
+
].each{|d,l|
|
59
|
+
$LDFLAGS << sprintf(" -L%s/%s", top, d)
|
60
|
+
$libs << sprintf(" -l%s", l)
|
61
|
+
}
|
62
|
+
end
|
63
|
+
begin
|
64
|
+
srcdir = File.expand_path(File.dirname($0))
|
65
|
+
|
66
|
+
begin
|
67
|
+
|
68
|
+
obj_ext = "."+$OBJEXT
|
69
|
+
|
70
|
+
$libs = $libs.split(/ /).uniq.join(' ')
|
71
|
+
$source_files = Dir.glob(sprintf("%s/*.c", srcdir)).map{|fname|
|
72
|
+
fname[0, srcdir.length+1] = ''
|
73
|
+
fname
|
74
|
+
}
|
75
|
+
$objs = $source_files.collect do |item|
|
76
|
+
item.gsub(/.c$/, obj_ext)
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# create Makefile
|
81
|
+
#
|
82
|
+
$defs << "-DRUBY_REDEYE_COMPILATION"
|
83
|
+
# $CFLAGS << $defs.join(' ')
|
84
|
+
create_makefile("redeye", srcdir)
|
85
|
+
raise Interrupt if not FileTest.exist? "Makefile"
|
86
|
+
|
87
|
+
File.open("Makefile", "a") do |mfile|
|
88
|
+
$source_files.each do |e|
|
89
|
+
mfile.print sprintf("%s: %s
|
90
|
+
", e.gsub(/.c$/, obj_ext), e)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
ensure
|
94
|
+
#Dir.chdir ".."
|
95
|
+
end
|
96
|
+
|
97
|
+
#create_top_makefile()
|
98
|
+
rescue Interrupt
|
99
|
+
print " [error] " + $!.to_s + "
|
100
|
+
"
|
101
|
+
end
|
102
|
+
|
data/ext/redeye/redeye.c
ADDED
@@ -0,0 +1,885 @@
|
|
1
|
+
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
2
|
+
/* Includes */
|
3
|
+
#include <ruby.h>
|
4
|
+
#include <stdlib.h>
|
5
|
+
#include <stdio.h>
|
6
|
+
#include <string.h>
|
7
|
+
#include "gdk-pixbuf/gdk-pixbuf.h"
|
8
|
+
|
9
|
+
/* Setup types */
|
10
|
+
/* Try not to clash with other definitions of bool... */
|
11
|
+
typedef int rubber_bool;
|
12
|
+
#define bool rubber_bool
|
13
|
+
|
14
|
+
/* Prototypes */
|
15
|
+
#include "rbglib.h"
|
16
|
+
|
17
|
+
#include "rbgtk.h"
|
18
|
+
|
19
|
+
#if defined(G_PLATFORM_WIN32) && !defined(RUBY_GTK2_STATIC_COMPILATION)
|
20
|
+
# ifdef RUBY_GTK2_COMPILATION
|
21
|
+
# define RUBY_GTK2_VAR __declspec(dllexport)
|
22
|
+
# else
|
23
|
+
# define RUBY_GTK2_VAR extern __declspec(dllimport)
|
24
|
+
# endif
|
25
|
+
#else
|
26
|
+
# define RUBY_GTK2_VAR extern
|
27
|
+
#endif
|
28
|
+
|
29
|
+
RUBY_GTK2_VAR VALUE mGtk;
|
30
|
+
RUBY_GTK2_VAR VALUE mGdk;
|
31
|
+
|
32
|
+
#define RBGTK_INITIALIZE(obj,gtkobj) (rbgtk_initialize_gtkobject(obj, GTK_OBJECT(gtkobj)))
|
33
|
+
static VALUE cRedEye;
|
34
|
+
static VALUE
|
35
|
+
RedEye___alloc__(VALUE self);
|
36
|
+
static VALUE
|
37
|
+
RedEye_initialize(VALUE self, VALUE __v_pixbuf, VALUE __v_minX, VALUE __v_minY, VALUE __v_maxX, VALUE __v_maxY);
|
38
|
+
static VALUE
|
39
|
+
RedEye_identify_blobs(int __p_argc, VALUE *__p_argv, VALUE self);
|
40
|
+
static VALUE
|
41
|
+
RedEye_correct_blob(VALUE self, VALUE __v_blob_id);
|
42
|
+
static VALUE
|
43
|
+
RedEye_highlight_blob(int __p_argc, VALUE *__p_argv, VALUE self);
|
44
|
+
static VALUE
|
45
|
+
RedEye_preview_blob(int __p_argc, VALUE *__p_argv, VALUE self);
|
46
|
+
static VALUE
|
47
|
+
RedEye_preview(VALUE self);
|
48
|
+
static VALUE
|
49
|
+
RedEye_pixbuf(VALUE self);
|
50
|
+
static VALUE structRegion;
|
51
|
+
|
52
|
+
/* Inline C code */
|
53
|
+
|
54
|
+
|
55
|
+
#define assert(x) if (!(x)) { rb_raise(rb_eRuntimeError, "Assertion: '%s' failed.", #x); }
|
56
|
+
|
57
|
+
typedef struct {
|
58
|
+
char red,green,blue;
|
59
|
+
} rgb_t;
|
60
|
+
|
61
|
+
typedef struct {
|
62
|
+
int minX, maxX, minY, maxY;
|
63
|
+
int width, height;
|
64
|
+
int noPixels, mergeWith;
|
65
|
+
} region_info;
|
66
|
+
|
67
|
+
typedef struct {
|
68
|
+
struct {
|
69
|
+
int minX, maxX, minY, maxY;
|
70
|
+
int width, height;
|
71
|
+
} area;
|
72
|
+
struct {
|
73
|
+
int *data;
|
74
|
+
region_info *region;
|
75
|
+
int len, size;
|
76
|
+
} regions;
|
77
|
+
int *mask;
|
78
|
+
GdkPixbuf *pixbuf, *preview;
|
79
|
+
} redeyeop_t;
|
80
|
+
|
81
|
+
#define MIN_RED_VAL 20
|
82
|
+
|
83
|
+
static inline VALUE
|
84
|
+
unref_pixbuf(GdkPixbuf *pixbuf)
|
85
|
+
{
|
86
|
+
volatile VALUE pb = Qnil;
|
87
|
+
|
88
|
+
pb = GOBJ2RVAL(pixbuf);
|
89
|
+
|
90
|
+
g_object_unref(pixbuf);
|
91
|
+
|
92
|
+
return pb;
|
93
|
+
}
|
94
|
+
|
95
|
+
static void identify_possible_redeye_pixels(redeyeop_t *op,
|
96
|
+
double green_sensitivity, double blue_sensitivity,
|
97
|
+
int min_red_val)
|
98
|
+
{
|
99
|
+
guchar *data = gdk_pixbuf_get_pixels(op->pixbuf);
|
100
|
+
int rowstride = gdk_pixbuf_get_rowstride(op->pixbuf);
|
101
|
+
int pixWidth = gdk_pixbuf_get_has_alpha(op->pixbuf) ? 4 : 3;
|
102
|
+
|
103
|
+
int y, ry = 0, x, rx = 0;
|
104
|
+
for ( y = op->area.minY; y < op->area.maxY; y++ )
|
105
|
+
{
|
106
|
+
guchar *thisLine = data + (rowstride * y);
|
107
|
+
guchar *pixel;
|
108
|
+
|
109
|
+
pixel = thisLine + (op->area.minX * pixWidth);
|
110
|
+
rx = 0;
|
111
|
+
|
112
|
+
for ( x = op->area.minX; x < op->area.maxX; x++ )
|
113
|
+
{
|
114
|
+
|
115
|
+
int r,g,b;
|
116
|
+
|
117
|
+
r = pixel[0];
|
118
|
+
g = pixel[1];
|
119
|
+
b = pixel[2];
|
120
|
+
|
121
|
+
gboolean threshMet;
|
122
|
+
|
123
|
+
threshMet = (((double)r) > (green_sensitivity * (double)g)) &&
|
124
|
+
(((double)r) > (blue_sensitivity * (double)b)) &&
|
125
|
+
(r > min_red_val);
|
126
|
+
|
127
|
+
if(threshMet)
|
128
|
+
op->mask[ rx + ry ] = r;
|
129
|
+
else
|
130
|
+
op->mask[ rx + ry ] = 0; /* MEMZERO should have done its job ? */
|
131
|
+
|
132
|
+
pixel += pixWidth;
|
133
|
+
rx ++;
|
134
|
+
}
|
135
|
+
|
136
|
+
ry += op->area.width;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
|
141
|
+
inline int group_at(redeyeop_t *op, int px, int py)
|
142
|
+
{
|
143
|
+
int index, region;
|
144
|
+
|
145
|
+
if (px < 0 || py < 0)
|
146
|
+
return 0;
|
147
|
+
|
148
|
+
index = px + ( py * op->area.width );
|
149
|
+
|
150
|
+
if (index < 0)
|
151
|
+
return 0;
|
152
|
+
if (index > (op->area.width * op->area.height))
|
153
|
+
return 0;
|
154
|
+
|
155
|
+
region = op->regions.data[ index ];
|
156
|
+
if (region > 0) {
|
157
|
+
if (op->regions.region[ region ].mergeWith) {
|
158
|
+
return op->regions.region[ region ].mergeWith;
|
159
|
+
} else {
|
160
|
+
return region;
|
161
|
+
}
|
162
|
+
} else {
|
163
|
+
return 0;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
#define group_for(x,y) group_at(op, x, y)
|
168
|
+
|
169
|
+
static void identify_blob_groupings(redeyeop_t *op)
|
170
|
+
{
|
171
|
+
volatile int next_blob_id = 1, blob_id, y, x;
|
172
|
+
|
173
|
+
|
174
|
+
for( y = 0; y < op->area.height; y++ )
|
175
|
+
{
|
176
|
+
for ( x = 0; x < op->area.width; x++ )
|
177
|
+
{
|
178
|
+
if (op->mask[ x + (y * op->area.width) ] > 0) {
|
179
|
+
gboolean existing = FALSE;
|
180
|
+
int sx, sy, group = 0;
|
181
|
+
// Target pixel is true
|
182
|
+
blob_id = 0;
|
183
|
+
|
184
|
+
for (sy = y; sy >= y - 1; sy --) {
|
185
|
+
sx = (sy == y) ? x : x + 1;
|
186
|
+
for (; sx >= (x - 1); sx --) {
|
187
|
+
/*if ((sx >= x) && (sy >= y))
|
188
|
+
goto blob_scan_done;*/
|
189
|
+
|
190
|
+
if (sx >= 0 && sy >= 0)
|
191
|
+
group = group_for(sx, sy);
|
192
|
+
|
193
|
+
if (group) {
|
194
|
+
existing = TRUE;
|
195
|
+
if (blob_id) {
|
196
|
+
int target = MIN(blob_id, group);
|
197
|
+
int from = MAX(blob_id, group);
|
198
|
+
|
199
|
+
if (op->regions.region[target].mergeWith > 0) {
|
200
|
+
// Already merged
|
201
|
+
target = op->regions.region[target].mergeWith;
|
202
|
+
}
|
203
|
+
op->regions.region[from].mergeWith = target;
|
204
|
+
|
205
|
+
// Merge blob_id & group
|
206
|
+
}
|
207
|
+
blob_id = group;
|
208
|
+
}
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
if (blob_id == 0)
|
213
|
+
{ // Allocate new group
|
214
|
+
blob_id = next_blob_id;
|
215
|
+
op->regions.region[blob_id].minX = x;
|
216
|
+
op->regions.region[blob_id].maxX = x;
|
217
|
+
op->regions.region[blob_id].minY = y;
|
218
|
+
op->regions.region[blob_id].maxY = y;
|
219
|
+
op->regions.region[blob_id].width = 1;
|
220
|
+
op->regions.region[blob_id].height = 1;
|
221
|
+
op->regions.region[blob_id].noPixels = 1;
|
222
|
+
op->regions.region[blob_id].mergeWith = 0;
|
223
|
+
|
224
|
+
next_blob_id ++;
|
225
|
+
op->regions.len = next_blob_id;
|
226
|
+
|
227
|
+
if (next_blob_id >= op->regions.size) {
|
228
|
+
int extra, new_size;
|
229
|
+
|
230
|
+
/*
|
231
|
+
* Realloc in increasingly large chunks to reduce memory fragmentation
|
232
|
+
*/
|
233
|
+
extra = op->regions.size;
|
234
|
+
new_size = op->regions.size + extra;
|
235
|
+
|
236
|
+
REALLOC_N(op->regions.region, region_info, new_size);
|
237
|
+
|
238
|
+
op->regions.size = new_size;
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
if (existing)
|
243
|
+
{
|
244
|
+
op->regions.region[blob_id].minX = MIN(x, op->regions.region[blob_id].minX);
|
245
|
+
op->regions.region[blob_id].maxX = MAX(x, op->regions.region[blob_id].maxX);
|
246
|
+
op->regions.region[blob_id].minY = MIN(y, op->regions.region[blob_id].minY);
|
247
|
+
op->regions.region[blob_id].maxY = MAX(y, op->regions.region[blob_id].maxY);
|
248
|
+
op->regions.region[blob_id].width = op->regions.region[blob_id].maxX -
|
249
|
+
op->regions.region[blob_id].minX + 1;
|
250
|
+
op->regions.region[blob_id].height = op->regions.region[blob_id].maxY -
|
251
|
+
op->regions.region[blob_id].minY + 1;
|
252
|
+
op->regions.region[blob_id].noPixels ++;
|
253
|
+
}
|
254
|
+
|
255
|
+
op->regions.data[ x + (y * op->area.width) ] = blob_id;
|
256
|
+
}
|
257
|
+
}
|
258
|
+
}
|
259
|
+
/*FILE *fp = fopen("regions.txt","w");*/
|
260
|
+
for (y = 0; y < op->area.height; y++) {
|
261
|
+
for (x = 0; x < op->area.width; x++) {
|
262
|
+
int g = group_at(op, x, y); // Returns the merged group...
|
263
|
+
op->regions.data[ x + (y * op->area.width) ] = g;
|
264
|
+
/*
|
265
|
+
if (op->regions.len <= 0xf || 1)
|
266
|
+
{
|
267
|
+
if (g == 0)
|
268
|
+
fprintf(fp, " ");
|
269
|
+
else
|
270
|
+
fprintf(fp, "%x", g);
|
271
|
+
}
|
272
|
+
else
|
273
|
+
{
|
274
|
+
if (g == 0)
|
275
|
+
fprintf(fp, " ");
|
276
|
+
else
|
277
|
+
fprintf(fp, "%x ", g);
|
278
|
+
}*/
|
279
|
+
}
|
280
|
+
/*fprintf(fp, "\n");*/
|
281
|
+
}
|
282
|
+
/*fclose(fp);*/
|
283
|
+
}
|
284
|
+
#define NO_REGIONS_DEFAULT 20
|
285
|
+
#define MIN_ID 1
|
286
|
+
|
287
|
+
|
288
|
+
static redeyeop_t *new_redeye(void)
|
289
|
+
{
|
290
|
+
redeyeop_t *ptr = ALLOC(redeyeop_t);
|
291
|
+
MEMZERO(ptr, redeyeop_t, 1);
|
292
|
+
return ptr;
|
293
|
+
}
|
294
|
+
|
295
|
+
static void free_redeye(redeyeop_t *ptr)
|
296
|
+
{
|
297
|
+
if (ptr->mask)
|
298
|
+
free(ptr->mask);
|
299
|
+
if (ptr->regions.data);
|
300
|
+
free(ptr->regions.data);
|
301
|
+
if (ptr->regions.region);
|
302
|
+
free(ptr->regions.region);
|
303
|
+
if (ptr->pixbuf)
|
304
|
+
g_object_unref(ptr->pixbuf);
|
305
|
+
if (ptr->preview)
|
306
|
+
g_object_unref(ptr->preview);
|
307
|
+
free(ptr);
|
308
|
+
}
|
309
|
+
|
310
|
+
|
311
|
+
inline gboolean in_region(redeyeop_t *op, int x, int y, int blob_id)
|
312
|
+
{
|
313
|
+
int index;
|
314
|
+
|
315
|
+
if ( x < op->area.minX || x > op->area.maxX ||
|
316
|
+
y < op->area.minY || y > op->area.maxY )
|
317
|
+
return FALSE;
|
318
|
+
|
319
|
+
index = (x - op->area.minX) + ((y - op->area.minY) * op->area.width);
|
320
|
+
|
321
|
+
return op->regions.data[index] == blob_id;
|
322
|
+
}
|
323
|
+
|
324
|
+
inline double alpha_level_for_pixel(redeyeop_t *op, int x, int y, int blob_id)
|
325
|
+
{
|
326
|
+
int j = 0, c = 0, xm, ym;
|
327
|
+
|
328
|
+
if (in_region(op, x, y, blob_id))
|
329
|
+
return 1.0;
|
330
|
+
|
331
|
+
for ( xm = -2; xm <= 2; xm++ )
|
332
|
+
{
|
333
|
+
for ( ym = -2; ym <= 2; ym ++ )
|
334
|
+
{
|
335
|
+
c ++;
|
336
|
+
if (xm == 0 && ym == 0)
|
337
|
+
continue;
|
338
|
+
if (in_region(op, x+xm, y+ym, blob_id))
|
339
|
+
j ++;
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
return ((double)j)/((double)c);
|
344
|
+
}
|
345
|
+
|
346
|
+
inline char col(double val)
|
347
|
+
{
|
348
|
+
if (val < 0) return 0;
|
349
|
+
if (val > 255) return 255;
|
350
|
+
return val;
|
351
|
+
|
352
|
+
}
|
353
|
+
|
354
|
+
static GdkPixbuf *redeye_preview(redeyeop_t *op, gboolean reset)
|
355
|
+
{
|
356
|
+
int width, height;
|
357
|
+
width = op->area.width;
|
358
|
+
height = op->area.height;
|
359
|
+
|
360
|
+
if (width + op->area.minX > gdk_pixbuf_get_width(op->pixbuf)) {
|
361
|
+
width = gdk_pixbuf_get_width(op->pixbuf) - op->area.minX;
|
362
|
+
}
|
363
|
+
if (height + op->area.minY > gdk_pixbuf_get_height(op->pixbuf)) {
|
364
|
+
height = gdk_pixbuf_get_height(op->pixbuf) - op->area.minY;
|
365
|
+
}
|
366
|
+
|
367
|
+
if ( op->preview == NULL )
|
368
|
+
{
|
369
|
+
GdkPixbuf *sub = NULL;
|
370
|
+
sub = gdk_pixbuf_new_subpixbuf(op->pixbuf, op->area.minX, op->area.minY,
|
371
|
+
width, height);
|
372
|
+
|
373
|
+
op->preview = gdk_pixbuf_copy(sub);
|
374
|
+
g_object_unref(sub);
|
375
|
+
} else if (reset) {
|
376
|
+
gdk_pixbuf_copy_area(op->pixbuf, op->area.minX, op->area.minY,
|
377
|
+
width, height, op->preview, 0, 0);
|
378
|
+
}
|
379
|
+
|
380
|
+
return op->preview;
|
381
|
+
}
|
382
|
+
|
383
|
+
static void desaturate_blob(redeyeop_t *op, int blob_id)
|
384
|
+
{
|
385
|
+
int y, x;
|
386
|
+
int minX, minY, maxX, maxY;
|
387
|
+
|
388
|
+
minY = MAX(0, op->area.minY + op->regions.region[blob_id].minY - 1);
|
389
|
+
maxY = MIN(op->area.maxY + op->regions.region[blob_id].maxY + 1,
|
390
|
+
gdk_pixbuf_get_height(op->pixbuf)-1);
|
391
|
+
minX = MAX(0, op->area.minX + op->regions.region[blob_id].minX - 1);
|
392
|
+
maxX = MIN(op->area.maxX + op->regions.region[blob_id].maxX + 1,
|
393
|
+
gdk_pixbuf_get_width(op->pixbuf)-1);
|
394
|
+
|
395
|
+
guchar *data = gdk_pixbuf_get_pixels(op->pixbuf);
|
396
|
+
int rowstride = gdk_pixbuf_get_rowstride(op->pixbuf);
|
397
|
+
int pixWidth = gdk_pixbuf_get_has_alpha(op->pixbuf) ? 4 : 3;
|
398
|
+
|
399
|
+
for ( y = minY; y <= maxY; y++ )
|
400
|
+
{
|
401
|
+
guchar *thisLine = data + (rowstride * y);
|
402
|
+
guchar *pixel;
|
403
|
+
|
404
|
+
pixel = thisLine + (minX * pixWidth);
|
405
|
+
|
406
|
+
for ( x = minX; x <= maxX; x++ )
|
407
|
+
{
|
408
|
+
|
409
|
+
double alpha = alpha_level_for_pixel(op, x, y, blob_id);
|
410
|
+
int r,g,b,grey;
|
411
|
+
|
412
|
+
r = pixel[0];
|
413
|
+
g = pixel[1];
|
414
|
+
b = pixel[2];
|
415
|
+
|
416
|
+
if (alpha > 0)
|
417
|
+
{
|
418
|
+
grey = alpha * ((double)( 5 * (double)r + 60 * (double)g + 30 * (double)b)) / 100.0 +
|
419
|
+
(1 - alpha) * r;
|
420
|
+
|
421
|
+
pixel[0] = col((grey * alpha) + (1-alpha) * r);
|
422
|
+
pixel[1] = col((grey * alpha) + (1-alpha) * g);
|
423
|
+
pixel[2] = col((grey * alpha) + (1-alpha) * b);
|
424
|
+
}
|
425
|
+
|
426
|
+
pixel += pixWidth;
|
427
|
+
}
|
428
|
+
}
|
429
|
+
|
430
|
+
}
|
431
|
+
|
432
|
+
static void highlight_blob(redeyeop_t *op, int blob_id, int colour)
|
433
|
+
{
|
434
|
+
int y, x;
|
435
|
+
int minX, minY, maxX, maxY;
|
436
|
+
int hr, hg, hb;
|
437
|
+
|
438
|
+
hr = (colour >> 16) & 0xff;
|
439
|
+
hg = (colour >> 8) & 0xff;
|
440
|
+
hb = (colour) & 0xff;
|
441
|
+
|
442
|
+
minY = MAX(0, op->area.minY - 1);
|
443
|
+
maxY = MIN(op->area.maxY + 1, gdk_pixbuf_get_height(op->pixbuf)-1);
|
444
|
+
minX = MAX(0, op->area.minX - 1);
|
445
|
+
maxX = MIN(op->area.maxX + 1, gdk_pixbuf_get_width(op->pixbuf)-1);
|
446
|
+
|
447
|
+
guchar *data = gdk_pixbuf_get_pixels(op->pixbuf);
|
448
|
+
int rowstride = gdk_pixbuf_get_rowstride(op->pixbuf);
|
449
|
+
int pixWidth = gdk_pixbuf_get_has_alpha(op->pixbuf) ? 4 : 3;
|
450
|
+
|
451
|
+
for ( y = minY; y <= maxY; y++ )
|
452
|
+
{
|
453
|
+
guchar *thisLine = data + (rowstride * y);
|
454
|
+
guchar *pixel;
|
455
|
+
|
456
|
+
pixel = thisLine + (minX * pixWidth);
|
457
|
+
|
458
|
+
for ( x = minX; x <= maxX; x++ )
|
459
|
+
{
|
460
|
+
|
461
|
+
double alpha = alpha_level_for_pixel(op, x, y, blob_id);
|
462
|
+
int r,g,b;
|
463
|
+
|
464
|
+
r = (pixel[0]);
|
465
|
+
g = (pixel[1]);
|
466
|
+
b = (pixel[2]);
|
467
|
+
|
468
|
+
|
469
|
+
if (alpha > 0)
|
470
|
+
{
|
471
|
+
|
472
|
+
pixel[0] = col((1-alpha) * r + (alpha * hr));
|
473
|
+
pixel[1] = col((1-alpha) * g + (alpha * hg));
|
474
|
+
pixel[2] = col((1-alpha) * b + (alpha * hb));
|
475
|
+
}
|
476
|
+
|
477
|
+
pixel += pixWidth;
|
478
|
+
}
|
479
|
+
}
|
480
|
+
|
481
|
+
}
|
482
|
+
|
483
|
+
|
484
|
+
static void preview_blob(redeyeop_t *op, int blob_id, int colour, gboolean reset_preview)
|
485
|
+
{
|
486
|
+
int y, x;
|
487
|
+
int minX, minY, maxX, maxY;
|
488
|
+
int hr, hg, hb;
|
489
|
+
|
490
|
+
redeye_preview(op, reset_preview);
|
491
|
+
|
492
|
+
hr = (colour >> 16) & 0xff;
|
493
|
+
hg = (colour >> 8) & 0xff;
|
494
|
+
hb = (colour) & 0xff;
|
495
|
+
|
496
|
+
minY = 0;
|
497
|
+
maxY = gdk_pixbuf_get_height(op->preview)-1;
|
498
|
+
minX = 0;
|
499
|
+
maxX = gdk_pixbuf_get_width(op->preview)-1;
|
500
|
+
|
501
|
+
guchar *data = gdk_pixbuf_get_pixels(op->preview);
|
502
|
+
int rowstride = gdk_pixbuf_get_rowstride(op->preview);
|
503
|
+
int pixWidth = gdk_pixbuf_get_has_alpha(op->preview) ? 4 : 3;
|
504
|
+
|
505
|
+
for ( y = minY; y <= maxY; y++ )
|
506
|
+
{
|
507
|
+
guchar *thisLine = data + (rowstride * y);
|
508
|
+
guchar *pixel;
|
509
|
+
|
510
|
+
pixel = thisLine + (minX * pixWidth);
|
511
|
+
|
512
|
+
for ( x = minX; x <= maxX; x++ )
|
513
|
+
{
|
514
|
+
|
515
|
+
double alpha = alpha_level_for_pixel(op, x + op->area.minX, y + op->area.minY, blob_id);
|
516
|
+
int r,g,b;
|
517
|
+
|
518
|
+
r = (pixel[0]);
|
519
|
+
g = (pixel[1]);
|
520
|
+
b = (pixel[2]);
|
521
|
+
|
522
|
+
|
523
|
+
if (alpha > 0)
|
524
|
+
{
|
525
|
+
|
526
|
+
pixel[0] = col((1-alpha) * r + (alpha * hr));
|
527
|
+
pixel[1] = col((1-alpha) * g + (alpha * hg));
|
528
|
+
pixel[2] = col((1-alpha) * b + (alpha * hb));
|
529
|
+
}
|
530
|
+
|
531
|
+
pixel += pixWidth;
|
532
|
+
}
|
533
|
+
}
|
534
|
+
|
535
|
+
}
|
536
|
+
|
537
|
+
|
538
|
+
/* Code */
|
539
|
+
static VALUE
|
540
|
+
RedEye___alloc__(VALUE self)
|
541
|
+
{
|
542
|
+
VALUE __p_retval = Qnil;
|
543
|
+
|
544
|
+
#line 536 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
545
|
+
do { __p_retval = Data_Wrap_Struct(self, NULL, free_redeye, new_redeye()); goto out; } while(0);
|
546
|
+
out:
|
547
|
+
return __p_retval;
|
548
|
+
}
|
549
|
+
|
550
|
+
static VALUE
|
551
|
+
RedEye_initialize(VALUE self, VALUE __v_pixbuf, VALUE __v_minX, VALUE __v_minY, VALUE __v_maxX, VALUE __v_maxY)
|
552
|
+
{
|
553
|
+
GdkPixbuf * pixbuf; GdkPixbuf * __orig_pixbuf;
|
554
|
+
int minX; int __orig_minX;
|
555
|
+
int minY; int __orig_minY;
|
556
|
+
int maxX; int __orig_maxX;
|
557
|
+
int maxY; int __orig_maxY;
|
558
|
+
__orig_pixbuf = pixbuf = GDK_PIXBUF(RVAL2GOBJ(__v_pixbuf));
|
559
|
+
__orig_minX = minX = NUM2INT(__v_minX);
|
560
|
+
__orig_minY = minY = NUM2INT(__v_minY);
|
561
|
+
__orig_maxX = maxX = NUM2INT(__v_maxX);
|
562
|
+
__orig_maxY = maxY = NUM2INT(__v_maxY);
|
563
|
+
|
564
|
+
#line 540 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
565
|
+
|
566
|
+
do {
|
567
|
+
redeyeop_t * op ;
|
568
|
+
Data_Get_Struct(self, redeyeop_t, op);
|
569
|
+
op->pixbuf = pixbuf;
|
570
|
+
op->preview = NULL;
|
571
|
+
g_object_ref(op->pixbuf);
|
572
|
+
op->area.minX = minX;
|
573
|
+
op->area.maxX = maxX;
|
574
|
+
op->area.minY = minY;
|
575
|
+
op->area.maxY = maxY;
|
576
|
+
op->area.width = maxX - minX + 1;
|
577
|
+
op->area.height = maxY - minY + 1;
|
578
|
+
assert(op->pixbuf != NULL);
|
579
|
+
assert(op->area.maxX <= gdk_pixbuf_get_width(op->pixbuf));
|
580
|
+
assert(op->area.minX >= 0);
|
581
|
+
assert(op->area.minX < op->area.maxX);
|
582
|
+
assert(op->area.maxY <= gdk_pixbuf_get_height(op->pixbuf));
|
583
|
+
assert(op->area.minY >= 0);
|
584
|
+
assert(op->area.minY < op->area.maxY);
|
585
|
+
op->mask = ALLOC_N(int, op->area.width * op->area.height);
|
586
|
+
op->regions.data = ALLOC_N(int, op->area.width * op->area.height);
|
587
|
+
op->regions.region = ALLOC_N(region_info, NO_REGIONS_DEFAULT);
|
588
|
+
op->regions.len = 0;
|
589
|
+
op->regions.size = NO_REGIONS_DEFAULT;
|
590
|
+
|
591
|
+
|
592
|
+
} while(0);
|
593
|
+
|
594
|
+
;
|
595
|
+
return Qnil;
|
596
|
+
}
|
597
|
+
|
598
|
+
static VALUE
|
599
|
+
RedEye_identify_blobs(int __p_argc, VALUE *__p_argv, VALUE self)
|
600
|
+
{
|
601
|
+
VALUE __p_retval = Qnil;
|
602
|
+
VALUE __v_green_sensitivity = Qnil;
|
603
|
+
double green_sensitivity; double __orig_green_sensitivity;
|
604
|
+
VALUE __v_blue_sensitivity = Qnil;
|
605
|
+
double blue_sensitivity; double __orig_blue_sensitivity;
|
606
|
+
VALUE __v_min_red_val = Qnil;
|
607
|
+
int min_red_val; int __orig_min_red_val;
|
608
|
+
|
609
|
+
/* Scan arguments */
|
610
|
+
rb_scan_args(__p_argc, __p_argv, "03",&__v_green_sensitivity, &__v_blue_sensitivity, &__v_min_red_val);
|
611
|
+
|
612
|
+
/* Set defaults */
|
613
|
+
if (__p_argc > 0)
|
614
|
+
__orig_green_sensitivity = green_sensitivity = NUM2DBL(__v_green_sensitivity);
|
615
|
+
else
|
616
|
+
green_sensitivity = 2.0;
|
617
|
+
|
618
|
+
if (__p_argc > 1)
|
619
|
+
__orig_blue_sensitivity = blue_sensitivity = NUM2DBL(__v_blue_sensitivity);
|
620
|
+
else
|
621
|
+
blue_sensitivity = 0.0;
|
622
|
+
|
623
|
+
if (__p_argc > 2)
|
624
|
+
__orig_min_red_val = min_red_val = NUM2INT(__v_min_red_val);
|
625
|
+
else
|
626
|
+
min_red_val = MIN_RED_VAL;
|
627
|
+
|
628
|
+
|
629
|
+
#line 575 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
630
|
+
|
631
|
+
do {
|
632
|
+
redeyeop_t * op ;
|
633
|
+
Data_Get_Struct(self, redeyeop_t, op);
|
634
|
+
MEMZERO(op->mask, int, op->area.width * op->area.height);
|
635
|
+
MEMZERO(op->regions.data, int, op->area.width * op->area.height);
|
636
|
+
identify_possible_redeye_pixels(op, green_sensitivity, blue_sensitivity, min_red_val);
|
637
|
+
identify_blob_groupings(op);
|
638
|
+
volatile VALUE ary =
|
639
|
+
rb_ary_new2(op->regions.len);
|
640
|
+
int i ;
|
641
|
+
for (i = MIN_ID;
|
642
|
+
i < op->regions.len;
|
643
|
+
i++) { region_info * r =
|
644
|
+
&op->regions.region[i];
|
645
|
+
/* Ignore CCD noise */ if (r->noPixels < 2) continue;
|
646
|
+
rb_ary_push(ary, rb_struct_new(structRegion, self, INT2NUM(i), INT2NUM(r->minX), INT2NUM(r->minY), INT2NUM(r->maxX), INT2NUM(r->maxY), INT2NUM(r->width), INT2NUM(r->height), INT2NUM(r->noPixels)));
|
647
|
+
} do { __p_retval = ary; goto out; } while(0);
|
648
|
+
|
649
|
+
} while(0);
|
650
|
+
|
651
|
+
out:
|
652
|
+
return __p_retval;
|
653
|
+
}
|
654
|
+
|
655
|
+
static VALUE
|
656
|
+
RedEye_correct_blob(VALUE self, VALUE __v_blob_id)
|
657
|
+
{
|
658
|
+
int blob_id; int __orig_blob_id;
|
659
|
+
__orig_blob_id = blob_id = NUM2INT(__v_blob_id);
|
660
|
+
|
661
|
+
#line 600 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
662
|
+
|
663
|
+
do {
|
664
|
+
redeyeop_t * op ;
|
665
|
+
Data_Get_Struct(self, redeyeop_t, op);
|
666
|
+
if (op->regions.len <= blob_id) rb_raise(rb_eIndexError, "Only %i blobs in region - %i is invalid", op->regions.len, blob_id);
|
667
|
+
desaturate_blob(op, blob_id);
|
668
|
+
|
669
|
+
|
670
|
+
} while(0);
|
671
|
+
|
672
|
+
return Qnil;
|
673
|
+
}
|
674
|
+
|
675
|
+
static VALUE
|
676
|
+
RedEye_highlight_blob(int __p_argc, VALUE *__p_argv, VALUE self)
|
677
|
+
{
|
678
|
+
VALUE __v_blob_id = Qnil;
|
679
|
+
int blob_id; int __orig_blob_id;
|
680
|
+
VALUE __v_col = Qnil;
|
681
|
+
int col; int __orig_col;
|
682
|
+
|
683
|
+
/* Scan arguments */
|
684
|
+
rb_scan_args(__p_argc, __p_argv, "11",&__v_blob_id, &__v_col);
|
685
|
+
|
686
|
+
/* Set defaults */
|
687
|
+
__orig_blob_id = blob_id = NUM2INT(__v_blob_id);
|
688
|
+
|
689
|
+
if (__p_argc > 1)
|
690
|
+
__orig_col = col = NUM2INT(__v_col);
|
691
|
+
else
|
692
|
+
col = 0x00ff00;
|
693
|
+
|
694
|
+
|
695
|
+
#line 612 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
696
|
+
|
697
|
+
do {
|
698
|
+
redeyeop_t * op ;
|
699
|
+
Data_Get_Struct(self, redeyeop_t, op);
|
700
|
+
if (op->regions.len <= blob_id) rb_raise(rb_eIndexError, "Only %i blobs in region - %i is invalid", op->regions.len, blob_id);
|
701
|
+
highlight_blob(op, blob_id, col);
|
702
|
+
|
703
|
+
|
704
|
+
} while(0);
|
705
|
+
|
706
|
+
return Qnil;
|
707
|
+
}
|
708
|
+
|
709
|
+
static VALUE
|
710
|
+
RedEye_preview_blob(int __p_argc, VALUE *__p_argv, VALUE self)
|
711
|
+
{
|
712
|
+
VALUE __p_retval = Qnil;
|
713
|
+
VALUE __v_blob_id = Qnil;
|
714
|
+
int blob_id; int __orig_blob_id;
|
715
|
+
VALUE __v_col = Qnil;
|
716
|
+
int col; int __orig_col;
|
717
|
+
VALUE __v_reset_preview = Qnil;
|
718
|
+
gboolean reset_preview; gboolean __orig_reset_preview;
|
719
|
+
|
720
|
+
/* Scan arguments */
|
721
|
+
rb_scan_args(__p_argc, __p_argv, "12",&__v_blob_id, &__v_col, &__v_reset_preview);
|
722
|
+
|
723
|
+
/* Set defaults */
|
724
|
+
__orig_blob_id = blob_id = NUM2INT(__v_blob_id);
|
725
|
+
|
726
|
+
if (__p_argc > 1)
|
727
|
+
__orig_col = col = NUM2INT(__v_col);
|
728
|
+
else
|
729
|
+
col = 0x00ff00;
|
730
|
+
|
731
|
+
if (__p_argc > 2)
|
732
|
+
__orig_reset_preview = reset_preview = RTEST(__v_reset_preview);
|
733
|
+
else
|
734
|
+
reset_preview = TRUE;
|
735
|
+
|
736
|
+
|
737
|
+
#line 623 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
738
|
+
|
739
|
+
do {
|
740
|
+
redeyeop_t * op ;
|
741
|
+
Data_Get_Struct(self, redeyeop_t, op);
|
742
|
+
if (op->regions.len <= blob_id) rb_raise(rb_eIndexError, "Only %i blobs in region - %i is invalid", op->regions.len, blob_id);
|
743
|
+
preview_blob(op, blob_id, col, reset_preview);
|
744
|
+
do { __p_retval = GOBJ2RVAL(GDK_PIXBUF(op->preview)); goto out; } while(0);
|
745
|
+
|
746
|
+
} while(0);
|
747
|
+
|
748
|
+
out:
|
749
|
+
return __p_retval;
|
750
|
+
}
|
751
|
+
|
752
|
+
static VALUE
|
753
|
+
RedEye_preview(VALUE self)
|
754
|
+
{
|
755
|
+
VALUE __p_retval = Qnil;
|
756
|
+
|
757
|
+
#line 635 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
758
|
+
|
759
|
+
do {
|
760
|
+
redeyeop_t * op ;
|
761
|
+
Data_Get_Struct(self, redeyeop_t, op);
|
762
|
+
do { __p_retval = GOBJ2RVAL(GDK_PIXBUF(redeye_preview(op, FALSE))); goto out; } while(0);
|
763
|
+
|
764
|
+
} while(0);
|
765
|
+
|
766
|
+
out:
|
767
|
+
return __p_retval;
|
768
|
+
}
|
769
|
+
|
770
|
+
static VALUE
|
771
|
+
RedEye_pixbuf(VALUE self)
|
772
|
+
{
|
773
|
+
VALUE __p_retval = Qnil;
|
774
|
+
|
775
|
+
#line 642 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
776
|
+
|
777
|
+
do {
|
778
|
+
redeyeop_t * op ;
|
779
|
+
Data_Get_Struct(self, redeyeop_t, op);
|
780
|
+
do { __p_retval = GOBJ2RVAL(GDK_PIXBUF(op->pixbuf)); goto out; } while(0);
|
781
|
+
|
782
|
+
} while(0);
|
783
|
+
|
784
|
+
out:
|
785
|
+
return __p_retval;
|
786
|
+
}
|
787
|
+
|
788
|
+
static VALUE
|
789
|
+
Region_ratio(VALUE self)
|
790
|
+
{
|
791
|
+
VALUE __p_retval = Qnil;
|
792
|
+
|
793
|
+
#line 497 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
794
|
+
int width,height;
|
795
|
+
double min,max,ratio;
|
796
|
+
width = NUM2INT(rb_struct_getmember(self, rb_intern("width")));
|
797
|
+
height = NUM2INT(rb_struct_getmember(self, rb_intern("height")));
|
798
|
+
min = (double)MIN(width,height);
|
799
|
+
max = (double)MAX(width,height);
|
800
|
+
ratio = (min / max);
|
801
|
+
do { __p_retval = rb_float_new(ratio); goto out; } while(0);
|
802
|
+
out:
|
803
|
+
return __p_retval;
|
804
|
+
}
|
805
|
+
|
806
|
+
static VALUE
|
807
|
+
Region_density(VALUE self)
|
808
|
+
{
|
809
|
+
VALUE __p_retval = Qnil;
|
810
|
+
|
811
|
+
#line 507 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
812
|
+
|
813
|
+
do {
|
814
|
+
int noPixels, width, height;
|
815
|
+
double density ;
|
816
|
+
noPixels = NUM2INT(rb_struct_getmember(self, rb_intern("noPixels")));
|
817
|
+
width = NUM2INT(rb_struct_getmember(self, rb_intern("width")));
|
818
|
+
height = NUM2INT(rb_struct_getmember(self, rb_intern("height")));
|
819
|
+
density = ((double)noPixels / (double)(width * height));
|
820
|
+
do { __p_retval = rb_float_new(density); goto out; } while(0);
|
821
|
+
|
822
|
+
} while(0);
|
823
|
+
|
824
|
+
out:
|
825
|
+
return __p_retval;
|
826
|
+
}
|
827
|
+
|
828
|
+
static VALUE
|
829
|
+
Region_squareish_query(int __p_argc, VALUE *__p_argv, VALUE self)
|
830
|
+
{
|
831
|
+
VALUE __p_retval = Qnil;
|
832
|
+
VALUE __v_min_ratio = Qnil;
|
833
|
+
double min_ratio; double __orig_min_ratio;
|
834
|
+
VALUE __v_min_density = Qnil;
|
835
|
+
double min_density; double __orig_min_density;
|
836
|
+
|
837
|
+
/* Scan arguments */
|
838
|
+
rb_scan_args(__p_argc, __p_argv, "02",&__v_min_ratio, &__v_min_density);
|
839
|
+
|
840
|
+
/* Set defaults */
|
841
|
+
if (__p_argc > 0)
|
842
|
+
__orig_min_ratio = min_ratio = NUM2DBL(__v_min_ratio);
|
843
|
+
else
|
844
|
+
min_ratio = 0.5;
|
845
|
+
|
846
|
+
if (__p_argc > 1)
|
847
|
+
__orig_min_density = min_density = NUM2DBL(__v_min_density);
|
848
|
+
else
|
849
|
+
min_density = 0.5;
|
850
|
+
|
851
|
+
|
852
|
+
#line 518 "/home/geoff/Projects/redeye/ext/redeye/redeye.cr"
|
853
|
+
int noPixels, width, height;
|
854
|
+
double min, max, ratio, density;
|
855
|
+
noPixels = NUM2INT(rb_struct_getmember(self, rb_intern("noPixels")));
|
856
|
+
width = NUM2INT(rb_struct_getmember(self, rb_intern("width")));
|
857
|
+
height = NUM2INT(rb_struct_getmember(self, rb_intern("height")));
|
858
|
+
min = (double)MIN(width,height);
|
859
|
+
max = (double)MAX(width,height);
|
860
|
+
ratio = (min / max);
|
861
|
+
density = ((double)noPixels / (double)(width * height));
|
862
|
+
do { __p_retval = ((((ratio >= min_ratio) && (density > min_density))) ? Qtrue : Qfalse); goto out; } while(0);
|
863
|
+
out:
|
864
|
+
return __p_retval;
|
865
|
+
}
|
866
|
+
|
867
|
+
/* Init */
|
868
|
+
void
|
869
|
+
Init_redeye(void)
|
870
|
+
{
|
871
|
+
cRedEye = rb_define_class("RedEye", rb_cObject);
|
872
|
+
rb_define_alloc_func(cRedEye, RedEye___alloc__);
|
873
|
+
rb_define_method(cRedEye, "initialize", RedEye_initialize, 5);
|
874
|
+
rb_define_method(cRedEye, "identify_blobs", RedEye_identify_blobs, -1);
|
875
|
+
rb_define_method(cRedEye, "correct_blob", RedEye_correct_blob, 1);
|
876
|
+
rb_define_method(cRedEye, "highlight_blob", RedEye_highlight_blob, -1);
|
877
|
+
rb_define_method(cRedEye, "preview_blob", RedEye_preview_blob, -1);
|
878
|
+
rb_define_method(cRedEye, "preview", RedEye_preview, 0);
|
879
|
+
rb_define_method(cRedEye, "pixbuf", RedEye_pixbuf, 0);
|
880
|
+
structRegion = rb_struct_define("Region", "op", "id", "minX", "minY", "maxX", "maxY", "width", "height", "noPixels", NULL);
|
881
|
+
rb_define_const(cRedEye, "Region", structRegion);
|
882
|
+
rb_define_method(structRegion, "ratio", Region_ratio, 0);
|
883
|
+
rb_define_method(structRegion, "density", Region_density, 0);
|
884
|
+
rb_define_method(structRegion, "squareish?", Region_squareish_query, -1);
|
885
|
+
}
|