CRIMP
Check-in [addbb29380]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Modified the threshold primitives for local thresholding to expose the type of their maps through their name. Extended the set of primitives to allow many more combinations of image- and map-types. Modifed to the threshold::local method to now check the maps for type consistency and usability with the image-type.
Timelines: family | ancestors | descendants | both | ak-experimental
Files: files | file ages | folders
SHA1: addbb29380e16605a76257789ee817dc21404e40
User & Date: andreask 2010-11-01 20:07:39.000
Context
2010-11-01
20:41
Added image division primitives and API on top. check-in: f8de4a07a1 user: andreask tags: ak-experimental
20:07
Modified the threshold primitives for local thresholding to expose the type of their maps through their name. Extended the set of primitives to allow many more combinations of image- and map-types. Modifed to the threshold::local method to now check the maps for type consistency and usability with the image-type. check-in: addbb29380 user: andreask tags: ak-experimental
2010-10-31
04:17
Extended the demo for local adaptive thresholding to showcase niblack's and sauvola's methods (based on local mean/stddev, as provided in the recent commits), and just using local 'mean'. Added the global otsu for comparison too. check-in: ceb9b94a4c user: andreask tags: ak-experimental
Changes
Unified Diff Ignore Whitespace Patch
Changes to crimp_tcl.tcl.
686
687
688
689
690
691
692




693









694
695
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
	    [::crimp map threshold below \
		 [dict get $stat channel $c median]]
    }
    return [::crimp remap $image {*}$maps]
}

proc ::crimp::threshold::local {image args} {




    set type [::crimp::TypeOf $image]









    set f threshold_$type
    if {![::crimp::Has $f]} {
	return -code error "Unable to locally threshold images of type \"$type\""
    }

    # Shrink or extend the set of thresholding maps if too many or not
    # enough were specified, the latter by replicating the last map.

    switch -- $type {
	hsv - rgb {

	    if {[llength $args]} {
		while {[llength $args] < 3} {
		    lappend args [lindex $args end]
		}
	    }
	    if {[llength $args] > 3} {
		set args [lrange $args 0 2]
	    }
	}
	rgba {

	    if {[llength $args]} {
		while {[llength $args] < 4} {
		    lappend args [lindex $args end]
		}
	    }
	    if {[llength $args] > 4} {
		set args [lrange $args 0 3]







>
>
>
>
|
>
>
>
>
>
>
>
>
>
|

|





|
|
>









|
>







686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
	    [::crimp map threshold below \
		 [dict get $stat channel $c median]]
    }
    return [::crimp remap $image {*}$maps]
}

proc ::crimp::threshold::local {image args} {
    if {![llength $args]} {
	return -code error "wrong\#args: expected image map..."
    }

    set itype [::crimp::TypeOf $image]
    set mtype [::crimp::TypeOf [lindex $args 0]]

    foreach map $args {
	set xtype [::crimp::TypeOf $map]
	if {$xtype ne $ntype} {
	    return -code error "Map type mismatch between \"$mtype\" and \"$xtype\", all maps have to have the same type."
	}
    }

    set f threshold_${itype}_$mtype
    if {![::crimp::Has $f]} {
	return -code error "Unable to locally threshold images of type \"$itype\" with maps of type \"$mtype\""
    }

    # Shrink or extend the set of thresholding maps if too many or not
    # enough were specified, the latter by replicating the last map.

    switch -- $itype/$mtype {
	hsv/float - rgb/float -
	hsv/grey8 - rgb/grey8 {
	    if {[llength $args]} {
		while {[llength $args] < 3} {
		    lappend args [lindex $args end]
		}
	    }
	    if {[llength $args] > 3} {
		set args [lrange $args 0 2]
	    }
	}
	rgba/float -
	rgba/grey8 {
	    if {[llength $args]} {
		while {[llength $args] < 4} {
		    lappend args [lindex $args end]
		}
	    }
	    if {[llength $args] > 4} {
		set args [lrange $args 0 3]
Name change from operator/threshold-float.crimp to operator/threshold-float-float.crimp.
1
2
3
4
5
6
7
8
threshold_float
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;
|







1
2
3
4
5
6
7
8
threshold_float_float
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;
Added operator/threshold-float-grey16.crimp.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
threshold_float_grey16
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     float);
crimp_input (thresholdObj, threshold, grey16);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	FLOATP (result, x, y) = FLOATP (image, x, y) >= GREY16 (threshold, x, y) 
	    ? BLACK
	    : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Added operator/threshold-float-grey32.crimp.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
threshold_float_grey32
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     float);
crimp_input (thresholdObj, threshold, grey32);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	FLOATP (result, x, y) = FLOATP (image, x, y) >= GREY32 (threshold, x, y) 
	    ? BLACK
	    : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Added operator/threshold-float-grey8.crimp.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
threshold_float_grey8
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     float);
crimp_input (thresholdObj, threshold, grey8);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	FLOATP (result, x, y) = FLOATP (image, x, y) >= GREY8 (threshold, x, y) 
	    ? BLACK
	    : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Added operator/threshold-grey16-float.crimp.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
threshold_grey16_float
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     grey16);
crimp_input (thresholdObj, threshold, float);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	GREY16 (result, x, y) = GREY16 (image, x, y) >= FLOATP (threshold, x, y) 
	    ? BLACK
	    : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Name change from operator/threshold-grey16.crimp to operator/threshold-grey16-grey16.crimp.
1
2
3
4
5
6
7
8
threshold_grey16
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;
|







1
2
3
4
5
6
7
8
threshold_grey16_grey16
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;
Added operator/threshold-grey32-float.crimp.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
threshold_grey32_float
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     grey32);
crimp_input (thresholdObj, threshold, float);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	GREY32 (result, x, y) = GREY32 (image, x, y) >= FLOATP (threshold, x, y) 
	    ? BLACK
	    : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Name change from operator/threshold-grey32.crimp to operator/threshold-grey32-grey32.crimp.
1
2
3
4
5
6
7
8
threshold_grey32
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;
|







1
2
3
4
5
6
7
8
threshold_grey32_grey32
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;
Added operator/threshold-grey8-float.crimp.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
threshold_grey8_float
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     grey8);
crimp_input (thresholdObj, threshold, float);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	GREY8 (result, x, y) = GREY8 (image, x, y) >= FLOATP (threshold, x, y) 
	    ? BLACK
	    : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Name change from operator/threshold-grey8.crimp to operator/threshold-grey8-grey8.crimp.
1
2
3
4
5
6
7
8
threshold_grey8
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;
|







1
2
3
4
5
6
7
8
threshold_grey8_grey8
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;
Added operator/threshold-hsv-float.crimp.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
threshold_hsv_float
Tcl_Obj* imageObj
Tcl_Obj* thresholdHObj
Tcl_Obj* thresholdSObj
Tcl_Obj* thresholdVObj

crimp_image* image;
crimp_image* thresholdh;
crimp_image* thresholds;
crimp_image* thresholdv;
crimp_image* result;
int          x, y;

crimp_input (imageObj,      image,      hsv);
crimp_input (thresholdHObj, thresholdh, float);
crimp_input (thresholdSObj, thresholds, float);
crimp_input (thresholdVObj, thresholdv, float);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	H (result, x, y) = H (image, x, y) >= FLOATP (thresholdh, x, y) ? BLACK : WHITE;
	S (result, x, y) = S (image, x, y) >= FLOATP (thresholds, x, y) ? BLACK : WHITE;
	V (result, x, y) = V (image, x, y) >= FLOATP (thresholdv, x, y) ? BLACK : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Name change from operator/threshold-hsv.crimp to operator/threshold-hsv-grey8.crimp.
1
2
3
4
5
6
7
8
threshold_hsv
Tcl_Obj* imageObj
Tcl_Obj* thresholdHObj
Tcl_Obj* thresholdSObj
Tcl_Obj* thresholdVObj

crimp_image* image;
crimp_image* thresholdh;
|







1
2
3
4
5
6
7
8
threshold_hsv_grey8
Tcl_Obj* imageObj
Tcl_Obj* thresholdHObj
Tcl_Obj* thresholdSObj
Tcl_Obj* thresholdVObj

crimp_image* image;
crimp_image* thresholdh;
Added operator/threshold-hsv-hsv.crimp.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
threshold_hsv_hsv
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     hsv);
crimp_input (thresholdObj, threshold, hsv);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	H (result, x, y) = H (image, x, y) >= H (threshold, x, y) ? BLACK : WHITE;
	S (result, x, y) = S (image, x, y) >= S (threshold, x, y) ? BLACK : WHITE;
	V (result, x, y) = V (image, x, y) >= V (threshold, x, y) ? BLACK : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Added operator/threshold-rgb-float.crimp.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
threshold_rgb_float
Tcl_Obj* imageObj
Tcl_Obj* thresholdRObj
Tcl_Obj* thresholdGObj
Tcl_Obj* thresholdBObj

crimp_image* image;
crimp_image* thresholdr;
crimp_image* thresholdg;
crimp_image* thresholdb;
crimp_image* result;
int          x, y;

crimp_input (imageObj,      image,      rgb);
crimp_input (thresholdRObj, thresholdr, float);
crimp_input (thresholdGObj, thresholdg, float);
crimp_input (thresholdBObj, thresholdb, float);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	R (result, x, y) = R (image, x, y) >= FLOATP (thresholdr, x, y) ? BLACK : WHITE;
	G (result, x, y) = G (image, x, y) >= FLOATP (thresholdg, x, y) ? BLACK : WHITE;
	B (result, x, y) = B (image, x, y) >= FLOATP (thresholdb, x, y) ? BLACK : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Name change from operator/threshold-rgb.crimp to operator/threshold-rgb-grey8.crimp.
1
2
3
4
5
6
7
8
threshold_rgb
Tcl_Obj* imageObj
Tcl_Obj* thresholdRObj
Tcl_Obj* thresholdGObj
Tcl_Obj* thresholdBObj

crimp_image* image;
crimp_image* thresholdr;
|







1
2
3
4
5
6
7
8
threshold_rgb_grey8
Tcl_Obj* imageObj
Tcl_Obj* thresholdRObj
Tcl_Obj* thresholdGObj
Tcl_Obj* thresholdBObj

crimp_image* image;
crimp_image* thresholdr;
Added operator/threshold-rgb-rgb.crimp.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
threshold_rgb_rgb
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     rgb);
crimp_input (thresholdObj, threshold, rgb);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	R (result, x, y) = R (image, x, y) >= R (threshold, x, y) ? BLACK : WHITE;
	G (result, x, y) = G (image, x, y) >= G (threshold, x, y) ? BLACK : WHITE;
	B (result, x, y) = B (image, x, y) >= B (threshold, x, y) ? BLACK : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Added operator/threshold-rgba-float.crimp.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
threshold_rgba_float
Tcl_Obj* imageObj
Tcl_Obj* thresholdRObj
Tcl_Obj* thresholdGObj
Tcl_Obj* thresholdBObj
Tcl_Obj* thresholdAObj

crimp_image* image;
crimp_image* thresholdr;
crimp_image* thresholdg;
crimp_image* thresholdb;
crimp_image* thresholda;
crimp_image* result;
int          x, y;

crimp_input (imageObj,      image,      rgba);
crimp_input (thresholdRObj, thresholdr, float);
crimp_input (thresholdGObj, thresholdg, float);
crimp_input (thresholdBObj, thresholdb, float);
crimp_input (thresholdAObj, thresholda, float);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	R (result, x, y) = R (image, x, y) >= FLOATP (thresholdr, x, y) ? BLACK : WHITE;
	G (result, x, y) = G (image, x, y) >= FLOATP (thresholdg, x, y) ? BLACK : WHITE;
	B (result, x, y) = B (image, x, y) >= FLOATP (thresholdb, x, y) ? BLACK : WHITE;
	A (result, x, y) = A (image, x, y) >= FLOATP (thresholda, x, y) ? BLACK : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Name change from operator/threshold-rgba.crimp to operator/threshold-rgba-grey8.crimp.
1
2
3
4
5
6
7
8
threshold_rgba
Tcl_Obj* imageObj
Tcl_Obj* thresholdRObj
Tcl_Obj* thresholdGObj
Tcl_Obj* thresholdBObj
Tcl_Obj* thresholdAObj

crimp_image* image;
|







1
2
3
4
5
6
7
8
threshold_rgba_grey8
Tcl_Obj* imageObj
Tcl_Obj* thresholdRObj
Tcl_Obj* thresholdGObj
Tcl_Obj* thresholdBObj
Tcl_Obj* thresholdAObj

crimp_image* image;
Added operator/threshold-rgba-rgba.crimp.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
threshold_rgba_rgba
Tcl_Obj* imageObj
Tcl_Obj* thresholdObj

crimp_image* image;
crimp_image* threshold;
crimp_image* result;
int          x, y;

crimp_input (imageObj,     image,     rgba);
crimp_input (thresholdObj, threshold, rgba);

result = crimp_new_like (image);

for (y = 0; y < image->h; y++) {
    for (x = 0; x < image->w; x++) {

	R (result, x, y) = R (image, x, y) >= R (threshold, x, y) ? BLACK : WHITE;
	G (result, x, y) = G (image, x, y) >= G (threshold, x, y) ? BLACK : WHITE;
	B (result, x, y) = B (image, x, y) >= B (threshold, x, y) ? BLACK : WHITE;
	A (result, x, y) = A (image, x, y) >= A (threshold, x, y) ? BLACK : WHITE;
    }
}

Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */