Skip to content

Commit f38d499

Browse files
committed
FEAT: possibility to count average image color using /color
For example having black&white image: ``` i: make image! 2x1 i/1: 0.0.0 ``` One can count average color using: ``` i/color ;== 127.127.127.255 ``` Using `/color:` will set RGB components of all pixels (ignoring alpha channel)
1 parent 19257d8 commit f38d499

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/core/t-image.c

+40
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,39 @@
411411
}
412412
}
413413

414+
/***********************************************************************
415+
**
416+
*/ void Average_Image_Color(REBYTE *rgba, REBVAL *clr, REBINT len)
417+
/*
418+
***********************************************************************/
419+
{
420+
REBU64 r = 0, g = 0, b = 0, a = 0;
421+
REBU64 n = (REBU64)len;
422+
423+
VAL_SET(clr, REB_TUPLE);
424+
VAL_TUPLE_LEN(clr) = 4;
425+
if (n > 0) {
426+
for (; len > 0; len--, rgba += 4) {
427+
r += rgba[C_R];
428+
g += rgba[C_G];
429+
b += rgba[C_B];
430+
a += rgba[C_A];
431+
}
432+
VAL_TUPLE(clr)[0] = (REBYTE)(r / n);
433+
VAL_TUPLE(clr)[1] = (REBYTE)(g / n);
434+
VAL_TUPLE(clr)[2] = (REBYTE)(b / n);
435+
VAL_TUPLE(clr)[3] = (REBYTE)(a / n);
436+
}
437+
else {
438+
// returning transparent black when image is empty
439+
VAL_TUPLE(clr)[0] = 0;
440+
VAL_TUPLE(clr)[1] = 0;
441+
VAL_TUPLE(clr)[2] = 0;
442+
VAL_TUPLE(clr)[3] = 0;
443+
//.. or should it return none instead?
444+
}
445+
}
446+
414447

415448
#ifdef ndef
416449
INLINE REBCNT ARGB_To_BGR(REBCNT i)
@@ -1330,6 +1363,10 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
13301363
Set_Binary(val, nser);
13311364
break;
13321365

1366+
case SYM_COLOR:
1367+
Average_Image_Color(src, val, len);
1368+
break;
1369+
13331370
default:
13341371
return PE_BAD_SELECT;
13351372
}
@@ -1346,6 +1383,9 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
13461383
break;
13471384

13481385
case SYM_RGB:
1386+
case SYM_COLOR:
1387+
// SYM_COLOR as a setter is used to count average color of the image,
1388+
// here we can will all pixels with it for consistency
13491389
if (IS_TUPLE(val)) {
13501390
Fill_Line((REBCNT *)src, TO_PIXEL_TUPLE(val), len, 1);
13511391
} else if (IS_INTEGER(val)) {

src/tests/units/image-test.r3

+23
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,29 @@ Rebol [
111111
===end-group===
112112

113113

114+
===start-group=== "image/color"
115+
116+
--test-- "image/color getter"
117+
;-- counts average image color
118+
img: make image! 2x1
119+
--assert img/color = 255.255.255.255 ; default image color is white
120+
img/1: 0.0.0
121+
--assert img/color = 127.127.127.255
122+
img/2: 50.130.60.200
123+
--assert img/color = 25.65.30.227
124+
125+
--test-- "image/color setter"
126+
;-- just for consistency, fills image as if /rgb would be used
127+
;-- alpha channel is ignored!
128+
; using image state from previous test..
129+
--assert img/rgba = #{000000FF32823CC8}
130+
img/color: 25.65.30.227
131+
--assert img/1 = 25.65.30.255
132+
--assert img/2 = 25.65.30.200
133+
134+
===end-group===
135+
136+
114137
===start-group=== "image pixel assignment validity"
115138
img: make image! 2x2
116139
--test-- "image pixel 3-tuple assignment"

0 commit comments

Comments
 (0)