Skip to content

Commit

Permalink
Add RGB Highlights
Browse files Browse the repository at this point in the history
  • Loading branch information
smasher816 committed Oct 30, 2023
1 parent 16a856a commit df9fb03
Show file tree
Hide file tree
Showing 4 changed files with 331 additions and 24 deletions.
221 changes: 221 additions & 0 deletions blitbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,91 @@ void BB_fill_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsi
}
}

void BB_fill_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color) {
const int rotation = GET_BB_ROTATION(bb);
unsigned int rx, ry, rw, rh;
// Compute rotated rectangle coordinates & size
switch (rotation) {
case 0:
rx = x;
ry = y;
rw = w;
rh = h;
break;
case 1:
rx = bb->w - (y + h);
ry = x;
rw = h;
rh = w;
break;
case 2:
rx = bb->w - (x + w);
ry = bb->h - (y + h);
rw = w;
rh = h;
break;
case 3:
rx = y;
ry = bb->h - (x + w);
rw = h;
rh = w;
break;
}

// Handle any target pitch properly
const int bb_type = GET_BB_TYPE(bb);
switch (bb_type) {
case TYPE_BBRGB16:
// we want to preserve the alpha byte
if (rx == 0 && rw == bb->w) {
// Single step for contiguous scanlines
const uint16_t src = *((uint16_t*) &ColorRGB32_To_Color16(color));
uint16_t * restrict p = (uint16_t *) (bb->data + bb->stride*ry);
size_t px_count = bb->pixel_stride*rh;
while (px_count--) {
*p++ = src;
}
} else {
// Scanline per scanline
const uint16_t src = *((uint16_t*) &ColorRGB32_To_Color16(color));
for (unsigned int j = ry; j < ry+rh; j++) {
uint16_t * restrict p = (uint16_t *) (bb->data + bb->stride*j) + rx;
size_t px_count = rw;
while (px_count--) {
*p++ = src;
}
}
}
break;
case TYPE_BBRGB24:
{
// Scanline per scanline
const ColorRGB24 src = ColorRGB32_To_Color24(color);
for (unsigned int j = ry; j < ry+rh; j++) {
for (unsigned int k = rx; k < rx+rw; k++) {
uint8_t * restrict p = bb->data + bb->stride*j + (k * 3U);
memcpy(p, &src, 3);
}
}
}
break;
case TYPE_BBRGB32:
{
// Scanline per scanline
//const uint32_t src = *((uint32_t*) &color); // This causes odd colors
const uint32_t src = RGB_To_RGB32(color->r, color->g, color->b);
for (unsigned int j = ry; j < ry+rh; j++) {
uint32_t * restrict p = (uint32_t *) (bb->data + bb->stride*j) + rx;
size_t px_count = rw;
while (px_count--) {
*p++ = src;
}
}
}
break;
}
}

void BB_blend_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, Color8A * restrict color) {
const int bb_type = GET_BB_TYPE(bb);
const int bb_rotation = GET_BB_ROTATION(bb);
Expand Down Expand Up @@ -477,6 +562,58 @@ void BB_blend_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, uns
}
}

void BB_blend_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color) {
const int bb_type = GET_BB_TYPE(bb);
const int bb_rotation = GET_BB_ROTATION(bb);
const uint8_t alpha = color->alpha;
const uint8_t ainv = alpha ^ 0xFF;
switch (bb_type) {
case TYPE_BBRGB16:
for (unsigned int j = y; j < y + h; j++) {
for (unsigned int i = x; i < x + w; i++) {
ColorRGB16 * restrict dstptr;
BB_GET_PIXEL(bb, bb_rotation, ColorRGB16, i, j, &dstptr);
if (ColorRGB16_GetR(dstptr->v) > 30 && ColorRGB16_GetG(dstptr->v) > 30 && ColorRGB16_GetB(dstptr->v) > 30) {
// Only edit light colors and leave blacks alone. This avoids whitewashing text.
const uint8_t r = (uint8_t) DIV_255(ColorRGB16_GetR(dstptr->v) * ainv + color->r * alpha);
const uint8_t g = (uint8_t) DIV_255(ColorRGB16_GetG(dstptr->v) * ainv + color->g * alpha);
const uint8_t b = (uint8_t) DIV_255(ColorRGB16_GetB(dstptr->v) * ainv + color->b * alpha);
dstptr->v = (uint16_t) RGB_To_RGB16(r, g, b);
}
}
}
break;
case TYPE_BBRGB24:
for (unsigned int j = y; j < y + h; j++) {
for (unsigned int i = x; i < x + w; i++) {
ColorRGB24 * restrict dstptr;
BB_GET_PIXEL(bb, bb_rotation, ColorRGB24, i, j, &dstptr);
if (dstptr->r > 30 && dstptr->g > 30 && dstptr->b > 30) {
// Only edit light colors and leave blacks alone. This avoids whitewashing text.
dstptr->r = (uint8_t) DIV_255(dstptr->r * ainv + color->r * alpha);
dstptr->g = (uint8_t) DIV_255(dstptr->g * ainv + color->r * alpha);
dstptr->b = (uint8_t) DIV_255(dstptr->b * ainv + color->r * alpha);
}
}
}
break;
case TYPE_BBRGB32:
for (unsigned int j = y; j < y + h; j++) {
for (unsigned int i = x; i < x + w; i++) {
ColorRGB32 * restrict dstptr;
BB_GET_PIXEL(bb, bb_rotation, ColorRGB32, i, j, &dstptr);
if (dstptr->r > 30 && dstptr->g > 30 && dstptr->b > 30) {
// Only edit light colors and leave blacks alone. This avoids whitewashing text.
dstptr->r = (uint8_t) DIV_255(dstptr->r * ainv + color->r * alpha);
dstptr->g = (uint8_t) DIV_255(dstptr->g * ainv + color->g * alpha);
dstptr->b = (uint8_t) DIV_255(dstptr->b * ainv + color->b * alpha);
}
}
}
break;
}
}

void BB_invert_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
const int rotation = GET_BB_ROTATION(bb);
unsigned int rx, ry, rw, rh;
Expand Down Expand Up @@ -2467,6 +2604,90 @@ void BB_color_blit_from(BlitBuffer * restrict dst, const BlitBuffer * restrict s
}
}

void BB_color_blit_from_rgb(BlitBuffer * restrict dst, const BlitBuffer * restrict src,
unsigned int dest_x, unsigned int dest_y, unsigned int offs_x, unsigned int offs_y, unsigned int w, unsigned int h, ColorRGB32 * restrict color) {
const int dbb_type = GET_BB_TYPE(dst);
const int sbb_type = GET_BB_TYPE(src);
const int sbb_rotation = GET_BB_ROTATION(src);
const int dbb_rotation = GET_BB_ROTATION(dst);
switch (dbb_type) {
case TYPE_BBRGB16:
for (unsigned int d_y = dest_y, o_y = offs_y; d_y < dest_y + h; d_y++, o_y++) {
for (unsigned int d_x = dest_x, o_x = offs_x; d_x < dest_x + w; d_x++, o_x++) {
uint8_t alpha;
SET_ALPHA_FROM_A(src, sbb_type, sbb_rotation, o_x, o_y, &alpha);
if (alpha == 0) {
// NOP
} else if (alpha == 0xFF) {
ColorRGB16 * restrict dstptr;
BB_GET_PIXEL(dst, dbb_rotation, ColorRGB16, d_x, d_y, &dstptr);
dstptr->v = (uint16_t) RGB_To_RGB16(color->r, color->g, color->b);
} else {
const uint8_t ainv = alpha ^ 0xFF;
ColorRGB16 * restrict dstptr;
BB_GET_PIXEL(dst, dbb_rotation, ColorRGB16, d_x, d_y, &dstptr);
const uint8_t r = (uint8_t) DIV_255(ColorRGB16_GetR(dstptr->v) * ainv + color->r * alpha);
const uint8_t g = (uint8_t) DIV_255(ColorRGB16_GetG(dstptr->v) * ainv + color->g * alpha);
const uint8_t b = (uint8_t) DIV_255(ColorRGB16_GetB(dstptr->v) * ainv + color->b * alpha);
dstptr->v = (uint16_t) RGB_To_RGB16(r, g, b);
}
}
}
break;
case TYPE_BBRGB24:
for (unsigned int d_y = dest_y, o_y = offs_y; d_y < dest_y + h; d_y++, o_y++) {
for (unsigned int d_x = dest_x, o_x = offs_x; d_x < dest_x + w; d_x++, o_x++) {
uint8_t alpha;
SET_ALPHA_FROM_A(src, sbb_type, sbb_rotation, o_x, o_y, &alpha);
if (alpha == 0) {
// NOP
} else if (alpha == 0xFF) {
ColorRGB24 * restrict dstptr;
BB_GET_PIXEL(dst, dbb_rotation, ColorRGB24, d_x, d_y, &dstptr);
dstptr->r = color->r;
dstptr->g = color->g;
dstptr->b = color->b;
} else {
const uint8_t ainv = alpha ^ 0xFF;
ColorRGB24 * restrict dstptr;
BB_GET_PIXEL(dst, dbb_rotation, ColorRGB24, d_x, d_y, &dstptr);
dstptr->r = (uint8_t) DIV_255(dstptr->r * ainv + color->r * alpha);
dstptr->g = (uint8_t) DIV_255(dstptr->g * ainv + color->g * alpha);
dstptr->b = (uint8_t) DIV_255(dstptr->b * ainv + color->b * alpha);
}
}
}
break;
case TYPE_BBRGB32:
for (unsigned int d_y = dest_y, o_y = offs_y; d_y < dest_y + h; d_y++, o_y++) {
for (unsigned int d_x = dest_x, o_x = offs_x; d_x < dest_x + w; d_x++, o_x++) {
// NOTE: GCC *may* throw a -Wmaybe-uninitialized about alpha here,
// because of the lack of default case in the SET_ALPHA_FROM_A switch.
// Not a cause for alarm here :).
uint8_t alpha;
SET_ALPHA_FROM_A(src, sbb_type, sbb_rotation, o_x, o_y, &alpha);
if (alpha == 0) {
// NOP
} else if (alpha == 0xFF) {
ColorRGB32 * restrict dstptr;
BB_GET_PIXEL(dst, dbb_rotation, ColorRGB32, d_x, d_y, &dstptr);
dstptr->r = color->r;
dstptr->g = color->g;
dstptr->b = color->b;
} else {
const uint8_t ainv = alpha ^ 0xFF;
ColorRGB32 * restrict dstptr;
BB_GET_PIXEL(dst, dbb_rotation, ColorRGB32, d_x, d_y, &dstptr);
dstptr->r = (uint8_t) DIV_255(dstptr->r * ainv + color->r * alpha);
dstptr->g = (uint8_t) DIV_255(dstptr->g * ainv + color->g * alpha);
dstptr->b = (uint8_t) DIV_255(dstptr->b * ainv + color->b * alpha);
}
}
}
break;
}
}

void BB_paint_rounded_corner(BlitBuffer * restrict bb, unsigned int off_x, unsigned int off_y, unsigned int w, unsigned int h, unsigned int bw, unsigned int r, uint8_t c) {
/*
if (2*r > h || 2*r > w || r == 0) {
Expand Down
4 changes: 4 additions & 0 deletions blitbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ typedef struct BlitBufferRGB32 {

DLL_PUBLIC void BB_fill(BlitBuffer * restrict bb, uint8_t v);
DLL_PUBLIC void BB_fill_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint8_t v);
DLL_PUBLIC void BB_fill_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
DLL_PUBLIC void BB_blend_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, Color8A * restrict color);
DLL_PUBLIC void BB_blend_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
DLL_PUBLIC void BB_invert_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
DLL_PUBLIC void BB_hatch_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int stripe_width, Color8 * restrict color, uint8_t alpha);
DLL_PUBLIC void BB_blit_to_BB8(const BlitBuffer * restrict src, BlitBuffer * restrict dst,
Expand Down Expand Up @@ -165,6 +167,8 @@ DLL_PUBLIC void BB_invert_blit_from(BlitBuffer * restrict dest, const BlitBuffer
unsigned int offs_x, unsigned int offs_y, unsigned int w, unsigned int h);
DLL_PUBLIC void BB_color_blit_from(BlitBuffer * restrict dest, const BlitBuffer * restrict source, unsigned int dest_x, unsigned int dest_y,
unsigned int offs_x, unsigned int offs_y, unsigned int w, unsigned int h, Color8A * restrict color);
DLL_PUBLIC void BB_color_blit_from_rgb(BlitBuffer * restrict dest, const BlitBuffer * restrict source, unsigned int dest_x, unsigned int dest_y,
unsigned int offs_x, unsigned int offs_y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
DLL_PUBLIC void BB_paint_rounded_corner(BlitBuffer * restrict bb, unsigned int off_x, unsigned int off_y, unsigned int w, unsigned int h,
unsigned int bw, unsigned int r, uint8_t c);
#endif
Loading

0 comments on commit df9fb03

Please sign in to comment.