Skip to content

Commit 4f16809

Browse files
committed
FEAT: more getters/setters for image! type
implements: metaeducation/rebol-issues#2386 Could be optimized and enhanced later. For example it would be good to add also HSV, Hue, Saturation, Lightness etc. For these it would be good not to support only `binary!`, but also `vector!` as an input/output.
1 parent 425fa56 commit 4f16809

File tree

2 files changed

+183
-24
lines changed

2 files changed

+183
-24
lines changed

src/core/t-image.c

+152-24
Original file line numberDiff line numberDiff line change
@@ -189,28 +189,98 @@
189189

190190
/***********************************************************************
191191
**
192-
*/ void RGB_To_Bin(REBYTE *bin, REBYTE *rgba, REBINT len, REBOOL alpha)
192+
*/ void Color_To_Bin(REBYTE *bin, REBYTE *rgba, REBINT len, REBCNT format)
193193
/*
194+
** Convert internal image (integer) to binary string according requested order
195+
**
194196
***********************************************************************/
195197
{
196-
// Convert internal image (integer) to RGB/A order binary string:
197-
if (alpha) {
198+
REBINT c0, c1, c2, c3;
199+
REBINT alpha = 0;
200+
201+
switch(format) {
202+
case SYM_RGB: c0 = C_R; c1 = C_G; c2 = C_B; c3 = C_A; break;
203+
case SYM_RGBA: c0 = C_R; c1 = C_G; c2 = C_B; c3 = C_A; alpha = 1; break;
204+
case SYM_RGBO: c0 = C_R; c1 = C_G; c2 = C_B; c3 = C_A; alpha = -1; break;
205+
case SYM_ARGB: c0 = C_A; c1 = C_R; c2 = C_G; c3 = C_B; alpha = 1; break;
206+
case SYM_ORGB: c0 = C_A; c1 = C_R; c2 = C_G; c3 = C_B; alpha = -1; break;
207+
208+
case SYM_BGRA: c0 = C_B; c1 = C_G; c2 = C_R; c3 = C_A; alpha = 1; break;
209+
case SYM_BGRO: c0 = C_B; c1 = C_G; c2 = C_R; c3 = C_A; alpha = -1; break;
210+
case SYM_ABGR: c0 = C_A; c1 = C_B; c2 = C_G; c3 = C_R; alpha = 1; break;
211+
case SYM_OBGR: c0 = C_A; c1 = C_B; c2 = C_G; c3 = C_R; alpha = -1; break;
212+
case SYM_BGR: c0 = C_B; c1 = C_G; c2 = C_R; c3 = C_A; break;
213+
default: return;
214+
}
215+
216+
if (alpha > 0) {
198217
for (; len > 0; len--, rgba += 4, bin += 4) {
199-
bin[0] = rgba[C_R];
200-
bin[1] = rgba[C_G];
201-
bin[2] = rgba[C_B];
202-
bin[3] = rgba[C_A];
218+
bin[0] = rgba[c0];
219+
bin[1] = rgba[c1];
220+
bin[2] = rgba[c2];
221+
bin[3] = rgba[c3];
222+
}
223+
} else if (alpha < 0) {
224+
if (c0 == C_A) {
225+
for (; len > 0; len--, rgba += 4, bin += 4) {
226+
bin[0] = 255 - rgba[c0];
227+
bin[1] = rgba[c1];
228+
bin[2] = rgba[c2];
229+
bin[3] = rgba[c3];
230+
}
231+
} else {
232+
for (; len > 0; len--, rgba += 4, bin += 4) {
233+
bin[0] = rgba[c0];
234+
bin[1] = rgba[c1];
235+
bin[2] = rgba[c2];
236+
bin[3] = 255 - rgba[c3];
237+
}
203238
}
204239
} else {
205-
// Only the RGB part:
240+
// Result without alpha
206241
for (; len > 0; len--, rgba += 4, bin += 3) {
207-
bin[0] = rgba[C_R];
208-
bin[1] = rgba[C_G];
209-
bin[2] = rgba[C_B];
242+
bin[0] = rgba[c0];
243+
bin[1] = rgba[c1];
244+
bin[2] = rgba[c2];
210245
}
211246
}
212247
}
213248

249+
/***********************************************************************
250+
**
251+
*/ void Bin_To_Color(REBYTE *trg, REBYTE *src, REBINT len, REBCNT format)
252+
/*
253+
** Convert external binary is specified color format to internal image
254+
**
255+
***********************************************************************/
256+
{
257+
REBINT r, g, b, a;
258+
REBINT alpha = 0;
259+
REBCNT *clr = (REBCNT*)trg;
260+
261+
switch(format) {
262+
case SYM_RGBA: r = 0; g = 1; b = 2; a = 3; alpha = 1; break;
263+
case SYM_RGBO: r = 0; g = 1; b = 2; a = 3; alpha = -1; break;
264+
case SYM_ARGB: a = 0; r = 1; g = 2; b = 3; alpha = 1; break;
265+
case SYM_ORGB: a = 0; r = 1; g = 2; b = 3; alpha = -1; break;
266+
267+
case SYM_BGRA: b = 0; g = 1; r = 2; a = 3; alpha = 1; break;
268+
case SYM_BGRO: b = 0; g = 1; r = 2; a = 3; alpha = -1; break;
269+
case SYM_ABGR: a = 0; b = 1; g = 2; r = 3; alpha = 1; break;
270+
case SYM_OBGR: a = 0; b = 1; g = 2; r = 3; alpha = -1; break;
271+
default: return;
272+
}
273+
274+
if (alpha > 0) {
275+
for (; len > 0; len--, src += 4, clr++) {
276+
clr[0] = TO_PIXEL_COLOR(src[r], src[g], src[b], src[a]);
277+
}
278+
} else {
279+
for (; len > 0; len--, src += 4, clr++) {
280+
clr[0] = TO_PIXEL_COLOR(src[r], src[g], src[b], 255 - src[a]);
281+
}
282+
}
283+
}
214284

215285
/***********************************************************************
216286
**
@@ -249,25 +319,34 @@
249319

250320
/***********************************************************************
251321
**
252-
*/ void Alpha_To_Bin(REBYTE *bin, REBYTE *rgba, REBINT len)
322+
*/ void Alpha_To_Bin(REBYTE *bin, REBYTE *rgba, REBINT len, REBCNT type)
253323
/*
254324
***********************************************************************/
255325
{
256-
for (; len > 0; len--, rgba += 4)
257-
*bin++ = rgba[C_A];
326+
if (type == SYM_ALPHA) {
327+
for (; len > 0; len--, rgba += 4)
328+
*bin++ = rgba[C_A];
329+
} else { // SYM_OPACITY
330+
for (; len > 0; len--, rgba += 4)
331+
*bin++ = 255 - rgba[C_A];
332+
}
258333
}
259334

260-
261335
/***********************************************************************
262336
**
263-
*/ void Bin_To_Alpha(REBYTE *rgba, REBCNT size, REBYTE *bin, REBINT len)
337+
*/ void Bin_To_Alpha(REBYTE *rgba, REBCNT size, REBYTE *bin, REBINT len, REBCNT type)
264338
/*
265339
***********************************************************************/
266340
{
267341
if (len > (REBINT)size) len = size; // avoid over-run
268342

269-
for (; len > 0; len--, rgba += 4)
270-
rgba[C_A] = *bin++;
343+
if (type == SYM_ALPHA) {
344+
for (; len > 0; len--, rgba += 4)
345+
rgba[C_A] = *bin++;
346+
} else { // SYM_OPACITY
347+
for (; len > 0; len--, rgba += 4)
348+
rgba[C_A] = 255 - *bin++;
349+
}
271350
}
272351

273352

@@ -288,6 +367,14 @@
288367
return 0;
289368
}
290369

370+
/***********************************************************************
371+
**
372+
*/ void Tuple_To_Color(REBCNT format, REBVAL *tuple, REBCNT *rgba)
373+
/*
374+
***********************************************************************/
375+
{
376+
Bin_To_Color((REBYTE*)rgba, VAL_TUPLE(tuple), 1, format);
377+
}
291378

292379
/***********************************************************************
293380
**
@@ -474,7 +561,7 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
474561

475562
// Load alpha channel data:
476563
if (IS_BINARY(block)) {
477-
Bin_To_Alpha(ip, size, VAL_BIN_DATA(block), VAL_LEN(block));
564+
Bin_To_Alpha(ip, size, VAL_BIN_DATA(block), VAL_LEN(block), SYM_ALPHA);
478565
// VAL_IMAGE_TRANSP(value)=VITT_ALPHA;
479566
block++;
480567
}
@@ -1182,6 +1269,7 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
11821269
REBSER *nser;
11831270
REBSER *series = VAL_SERIES(data);
11841271
REBCNT *dp;
1272+
REBCNT sym;
11851273

11861274
len = VAL_TAIL(data) - index;
11871275
len = MAX(len, 0);
@@ -1192,9 +1280,10 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
11921280
else if (IS_DECIMAL(sel)) n = (REBINT)VAL_DECIMAL(sel);
11931281
else if (IS_LOGIC(sel)) n = (VAL_LOGIC(sel) ? 1 : 2);
11941282
else if (IS_WORD(sel)) {
1283+
sym = VAL_WORD_CANON(sel);
11951284
if (val == 0) {
11961285
val = pvs->value = pvs->store;
1197-
switch (VAL_WORD_CANON(sel)) {
1286+
switch (sym) {
11981287

11991288
case SYM_SIZE:
12001289
VAL_SET(val, REB_PAIR);
@@ -1203,16 +1292,32 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
12031292
break;
12041293

12051294
case SYM_RGB:
1295+
case SYM_BGR:
12061296
nser = Make_Binary(len * 3);
12071297
SERIES_TAIL(nser) = len * 3;
1208-
RGB_To_Bin(QUAD_HEAD(nser), src, len, FALSE);
1298+
Color_To_Bin(QUAD_HEAD(nser), src, len, sym);
1299+
Set_Binary(val, nser);
1300+
break;
1301+
1302+
case SYM_RGBA:
1303+
case SYM_RGBO:
1304+
case SYM_BGRA:
1305+
case SYM_BGRO:
1306+
case SYM_ARGB:
1307+
case SYM_ABGR:
1308+
case SYM_ORGB:
1309+
case SYM_OBGR:
1310+
nser = Make_Binary(len * 4);
1311+
SERIES_TAIL(nser) = len * 4;
1312+
Color_To_Bin(QUAD_HEAD(nser), src, len, sym);
12091313
Set_Binary(val, nser);
12101314
break;
12111315

12121316
case SYM_ALPHA:
1317+
case SYM_OPACITY:
12131318
nser = Make_Binary(len);
12141319
SERIES_TAIL(nser) = len;
1215-
Alpha_To_Bin(QUAD_HEAD(nser), src, len);
1320+
Alpha_To_Bin(QUAD_HEAD(nser), src, len, sym);
12161321
Set_Binary(val, nser);
12171322
break;
12181323

@@ -1223,7 +1328,7 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
12231328

12241329
} else {
12251330

1226-
switch (VAL_WORD_CANON(sel)) {
1331+
switch (sym) {
12271332

12281333
case SYM_SIZE:
12291334
if (!IS_PAIR(val) || !VAL_PAIR_X(val)) return PE_BAD_SET;
@@ -1243,13 +1348,36 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
12431348
} else return PE_BAD_SET;
12441349
break;
12451350

1351+
case SYM_RGBA:
1352+
case SYM_RGBO:
1353+
case SYM_BGRA:
1354+
case SYM_BGRO:
1355+
case SYM_ARGB:
1356+
case SYM_ABGR:
1357+
case SYM_ORGB:
1358+
case SYM_OBGR:
1359+
if (IS_TUPLE(val)) {
1360+
if (VAL_TUPLE_LEN(val) != 4) return PE_BAD_ARGUMENT;
1361+
REBCNT color = 0;
1362+
Tuple_To_Color(sym, val, &color);
1363+
Fill_Line((REBCNT *)src, color, len, FALSE);
1364+
} else if (IS_INTEGER(val)) {
1365+
n = VAL_INT32(val);
1366+
if (n < 0 || n > 255) return PE_BAD_RANGE;
1367+
Fill_Line((REBCNT *)src, TO_PIXEL_COLOR(n,n,n,n), len, FALSE);
1368+
} else if (IS_BINARY(val)) {
1369+
Bin_To_Color(src, VAL_BIN_DATA(val), VAL_LEN(val) / 4, sym);
1370+
} else return PE_BAD_SET;
1371+
break;
1372+
12461373
case SYM_ALPHA:
1374+
case SYM_OPACITY:
12471375
if (IS_INTEGER(val)) {
12481376
n = VAL_INT32(val);
12491377
if (n < 0 || n > 255) return PE_BAD_RANGE;
12501378
Fill_Alpha_Line(src, (REBYTE)n, len);
12511379
} else if (IS_BINARY(val)) {
1252-
Bin_To_Alpha(src, len, VAL_BIN_DATA(val), VAL_LEN(val));
1380+
Bin_To_Alpha(src, len, VAL_BIN_DATA(val), VAL_LEN(val), sym);
12531381
} else return PE_BAD_SET;
12541382
break;
12551383

src/tests/units/image-test.r3

+31
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,38 @@ Rebol [
8181
--assert error? try [img/1: #"^(260)"]
8282
===end-group===
8383

84+
===start-group=== "raw image data getters"
85+
img: make image! 2x1 img/1: 1.2.3.100 img/2: 4.5.6.200
86+
tests: [
87+
rgba #{01020364040506C8}
88+
rgbo #{0102039B04050637}
89+
argb #{64010203C8040506}
90+
orgb #{9B01020337040506}
91+
bgra #{03020164060504C8}
92+
bgro #{0302019B06050437}
93+
abgr #{64030201C8060504}
94+
obgr #{9B03020137060504}
95+
opacity #{9B37}
96+
alpha #{64C8}
97+
]
98+
foreach [format bin] tests [
99+
--test-- reform ["get raw image" format "data"]
100+
--assert img/:format = bin
101+
]
102+
===end-group===
103+
104+
===start-group=== "raw image data setters"
105+
foreach [format bin] tests [
106+
--test-- reform ["set raw image" format "data"]
107+
img/1: 1.2.3
108+
img/:format: bin
109+
--assert img/1 = 1.2.3.100
110+
]
111+
===end-group===
112+
113+
84114
===start-group=== "image pixel assignment validity"
115+
img: make image! 2x2
85116
--test-- "image pixel 3-tuple assignment"
86117
--assert 255.255.255 = img/1: 255.255.255
87118
--test-- "image pixel 4-tuple assignment"

0 commit comments

Comments
 (0)