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 28, 2023
1 parent 16a856a commit ab2d287
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 7 deletions.
133 changes: 133 additions & 0 deletions blitbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,89 @@ 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;
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;
}
}

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 +560,56 @@ 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);
// 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
2 changes: 2 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
26 changes: 19 additions & 7 deletions ffi/blitbuffer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ typedef struct BlitBufferRGB32 {

void BB_fill(BlitBuffer * restrict bb, uint8_t v);
void BB_fill_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint8_t v);
void BB_fill_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
void BB_blend_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, Color8A * restrict color);
void BB_blend_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
void BB_invert_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
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);
void BB_blit_to(const BlitBuffer * restrict source, BlitBuffer * restrict dest, unsigned int dest_x, unsigned int dest_y,
Expand Down Expand Up @@ -1497,8 +1499,13 @@ function BB_mt.__index:paintRect(x, y, w, h, value, setter)
h, y = BB.checkBounds(h, y, 0, self:getHeight(), 0xFFFF)
if w <= 0 or h <= 0 then return end
if self:canUseCbb() and setter == self.setPixel then
cblitbuffer.BB_fill_rect(ffi.cast(P_BlitBuffer, self),
x, y, w, h, value:getColor8().a)
if ffi.istype(ColorRGB32, value) then
cblitbuffer.BB_fill_rect_color(ffi.cast(P_BlitBuffer, self),
x, y, w, h, value:getColorRGB32())
else
cblitbuffer.BB_fill_rect(ffi.cast(P_BlitBuffer, self),
x, y, w, h, value:getColor8().a)
end
else
-- We can only do fast filling when there's no complex processing involved (i.e., simple setPixel only)
if setter == self.setPixel then
Expand Down Expand Up @@ -1926,16 +1933,21 @@ lighten color values in rectangular area
@param y Y coordinate
@param w width
@param h height
@param by lighten by this factor (default: 0.5)
@param color color to overlay (default: 0x80, 50% gray)
--]]
function BB_mt.__index:lightenRect(x, y, w, h, by)
local color = Color8A(0, 0xFF*(by or 0.5))
function BB_mt.__index:lightenRect(x, y, w, h, color)
color = color or Color8A(0xFF, 0x80)
if self:canUseCbb() then
w, x = BB.checkBounds(w, x, 0, self:getWidth(), 0xFFFF)
h, y = BB.checkBounds(h, y, 0, self:getHeight(), 0xFFFF)
if w <= 0 or h <= 0 then return end
cblitbuffer.BB_blend_rect(ffi.cast(P_BlitBuffer, self),
x, y, w, h, color)
if ffi.istype(ColorRGB32, color) then
cblitbuffer.BB_blend_rect_color(ffi.cast(P_BlitBuffer, self),
x, y, w, h, color)
else
cblitbuffer.BB_blend_rect(ffi.cast(P_BlitBuffer, self),
x, y, w, h, color)
end
else
self:paintRect(x, y, w, h, color, self.setPixelBlend)
end
Expand Down

0 comments on commit ab2d287

Please sign in to comment.