static void imlib_sub_line_op(image_t *img, int line, void *other, void *data, bool vflipped) { bool reverse = ((imlib_sub_line_op_state_t *) data)->reverse; image_t *mask = ((imlib_sub_line_op_state_t *) data)->mask; switch(img->bpp) { case IMAGE_BPP_BINARY: { uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i); int p = reverse ? (otherPixel - dataPixel) : (dataPixel - otherPixel); p = IM_MAX(p, COLOR_BINARY_MIN); IMAGE_PUT_BINARY_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_GRAYSCALE: { uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i); int p = reverse ? (otherPixel - dataPixel) : (dataPixel - otherPixel); p = IM_MAX(p, COLOR_GRAYSCALE_MIN); IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_RGB565: { uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i); int dR = COLOR_RGB565_TO_R5(dataPixel); int dG = COLOR_RGB565_TO_G6(dataPixel); int dB = COLOR_RGB565_TO_B5(dataPixel); int oR = COLOR_RGB565_TO_R5(otherPixel); int oG = COLOR_RGB565_TO_G6(otherPixel); int oB = COLOR_RGB565_TO_B5(otherPixel); int r = reverse ? (oR - dR) : (dR - oR); int g = reverse ? (oG - dG) : (dG - oG); int b = reverse ? (oB - dB) : (dB - oB); r = IM_MAX(r, COLOR_R5_MIN); g = IM_MAX(g, COLOR_G6_MIN); b = IM_MAX(b, COLOR_B5_MIN); IMAGE_PUT_RGB565_PIXEL_FAST(data, i, COLOR_R5_G6_B5_TO_RGB565(r, g, b)); } } break; } default: { break; } } }
static void imlib_add_line_op(image_t *img, int line, void *other, void *data, bool vflipped) { image_t *mask = (image_t *) data; switch(img->bpp) { case IMAGE_BPP_BINARY: { uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i); int p = dataPixel + otherPixel; p = IM_MIN(p, COLOR_BINARY_MAX); IMAGE_PUT_BINARY_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_GRAYSCALE: { uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i); int p = dataPixel + otherPixel; p = IM_MIN(p, COLOR_GRAYSCALE_MAX); IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_RGB565: { uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i); int r = COLOR_RGB565_TO_R5(dataPixel) + COLOR_RGB565_TO_R5(otherPixel); int g = COLOR_RGB565_TO_G6(dataPixel) + COLOR_RGB565_TO_G6(otherPixel); int b = COLOR_RGB565_TO_B5(dataPixel) + COLOR_RGB565_TO_B5(otherPixel); r = IM_MIN(r, COLOR_R5_MAX); g = IM_MIN(g, COLOR_G6_MAX); b = IM_MIN(b, COLOR_B5_MAX); IMAGE_PUT_RGB565_PIXEL_FAST(data, i, COLOR_R5_G6_B5_TO_RGB565(r, g, b)); } } break; } default: { break; } } }
static void imlib_blend_line_op(image_t *img, int line, void *other, void *data, bool vflipped) { float alpha = ((imlib_blend_line_op_t *) data)->alpha, beta = 1 - alpha; image_t *mask = ((imlib_blend_line_op_t *) data)->mask; switch(img->bpp) { case IMAGE_BPP_BINARY: { uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i); int p = (dataPixel * alpha) + (otherPixel * beta); IMAGE_PUT_BINARY_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_GRAYSCALE: { uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i); int p = (dataPixel * alpha) + (otherPixel * beta); IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_RGB565: { uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i); int r = (COLOR_RGB565_TO_R5(dataPixel) * alpha) + (COLOR_RGB565_TO_R5(otherPixel) * beta); int g = (COLOR_RGB565_TO_G6(dataPixel) * alpha) + (COLOR_RGB565_TO_G6(otherPixel) * beta); int b = (COLOR_RGB565_TO_B5(dataPixel) * alpha) + (COLOR_RGB565_TO_B5(otherPixel) * beta); IMAGE_PUT_RGB565_PIXEL_FAST(data, i, COLOR_R5_G6_B5_TO_RGB565(r, g, b)); } } break; } default: { break; } } }
void imlib_negate(image_t *img) { switch(img->bpp) { case IMAGE_BPP_BINARY: { for (int y = 0, yy = img->h; y < yy; y++) { uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y); for (int x = 0, xx = img->w; x < xx; x++) { int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, x); int p = (COLOR_BINARY_MAX - COLOR_BINARY_MIN) - dataPixel; IMAGE_PUT_BINARY_PIXEL_FAST(data, x, p); } } break; } case IMAGE_BPP_GRAYSCALE: { for (int y = 0, yy = img->h; y < yy; y++) { uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); for (int x = 0, xx = img->w; x < xx; x++) { int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, x); int p = (COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN) - dataPixel; IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, x, p); } } break; } case IMAGE_BPP_RGB565: { for (int y = 0, yy = img->h; y < yy; y++) { uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); for (int x = 0, xx = img->w; x < xx; x++) { int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, x); int r = (COLOR_R5_MAX - COLOR_R5_MIN) - COLOR_RGB565_TO_R5(dataPixel); int g = (COLOR_G6_MAX - COLOR_G6_MIN) - COLOR_RGB565_TO_G6(dataPixel); int b = (COLOR_B5_MAX - COLOR_B5_MIN) - COLOR_RGB565_TO_B5(dataPixel); IMAGE_PUT_RGB565_PIXEL_FAST(data, x, COLOR_R5_G6_B5_TO_RGB565(r, g, b)); } } break; } default: { break; } } }
void imlib_gamma_corr(image_t *img, float gamma, float contrast, float brightness) { gamma = IM_DIV(1.0, gamma); switch(img->bpp) { case IMAGE_BPP_BINARY: { float pScale = COLOR_BINARY_MAX - COLOR_BINARY_MIN; float pDiv = 1 / pScale; int *p_lut = fb_alloc((COLOR_BINARY_MAX - COLOR_BINARY_MIN + 1) * sizeof(int)); for (int i = COLOR_BINARY_MIN; i <= COLOR_BINARY_MAX; i++) { int p = ((fast_powf(i * pDiv, gamma) * contrast) + brightness) * pScale; p_lut[i] = IM_MIN(IM_MAX(p , COLOR_BINARY_MIN), COLOR_BINARY_MAX); } for (int y = 0, yy = img->h; y < yy; y++) { uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y); for (int x = 0, xx = img->w; x < xx; x++) { int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, x); int p = p_lut[dataPixel]; IMAGE_PUT_BINARY_PIXEL_FAST(data, x, p); } } fb_free(); break; } case IMAGE_BPP_GRAYSCALE: { float pScale = COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN; float pDiv = 1 / pScale; int *p_lut = fb_alloc((COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN + 1) * sizeof(int)); for (int i = COLOR_GRAYSCALE_MIN; i <= COLOR_GRAYSCALE_MAX; i++) { int p = ((fast_powf(i * pDiv, gamma) * contrast) + brightness) * pScale; p_lut[i] = IM_MIN(IM_MAX(p , COLOR_GRAYSCALE_MIN), COLOR_GRAYSCALE_MAX); } for (int y = 0, yy = img->h; y < yy; y++) { uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); for (int x = 0, xx = img->w; x < xx; x++) { int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, x); int p = p_lut[dataPixel]; IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, x, p); } } fb_free(); break; } case IMAGE_BPP_RGB565: { float rScale = COLOR_R5_MAX - COLOR_R5_MIN; float gScale = COLOR_G6_MAX - COLOR_G6_MIN; float bScale = COLOR_B5_MAX - COLOR_B5_MIN; float rDiv = 1 / rScale; float gDiv = 1 / gScale; float bDiv = 1 / bScale; int *r_lut = fb_alloc((COLOR_R5_MAX - COLOR_R5_MIN + 1) * sizeof(int)); int *g_lut = fb_alloc((COLOR_G6_MAX - COLOR_G6_MIN + 1) * sizeof(int)); int *b_lut = fb_alloc((COLOR_B5_MAX - COLOR_B5_MIN + 1) * sizeof(int)); for (int i = COLOR_R5_MIN; i <= COLOR_R5_MAX; i++) { int r = ((fast_powf(i * rDiv, gamma) * contrast) + brightness) * rScale; r_lut[i] = IM_MIN(IM_MAX(r , COLOR_R5_MIN), COLOR_R5_MAX); } for (int i = COLOR_G6_MIN; i <= COLOR_G6_MAX; i++) { int g = ((fast_powf(i * gDiv, gamma) * contrast) + brightness) * gScale; g_lut[i] = IM_MIN(IM_MAX(g , COLOR_G6_MIN), COLOR_G6_MAX); } for (int i = COLOR_B5_MIN; i <= COLOR_B5_MAX; i++) { int b = ((fast_powf(i * bDiv, gamma) * contrast) + brightness) * bScale; b_lut[i] = IM_MIN(IM_MAX(b , COLOR_B5_MIN), COLOR_B5_MAX); } for (int y = 0, yy = img->h; y < yy; y++) { uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); for (int x = 0, xx = img->w; x < xx; x++) { int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, x); int r = r_lut[COLOR_RGB565_TO_R5(dataPixel)]; int g = g_lut[COLOR_RGB565_TO_G6(dataPixel)]; int b = b_lut[COLOR_RGB565_TO_B5(dataPixel)]; IMAGE_PUT_RGB565_PIXEL_FAST(data, x, COLOR_R5_G6_B5_TO_RGB565(r, g, b)); } } fb_free(); fb_free(); fb_free(); break; } default: { break; } } }
static void imlib_div_line_op(image_t *img, int line, void *other, void *data, bool vflipped) { bool invert = ((imlib_div_line_op_state_t *) data)->invert; bool mod = ((imlib_div_line_op_state_t *) data)->mod; image_t *mask = ((imlib_div_line_op_state_t *) data)->mask; switch(img->bpp) { case IMAGE_BPP_BINARY: { uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); int pScale = COLOR_BINARY_MAX - COLOR_BINARY_MIN; for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i); int p = mod ? IM_MOD((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel)) : IM_DIV((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel)); p = IM_MIN(p, COLOR_BINARY_MAX); IMAGE_PUT_BINARY_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_GRAYSCALE: { uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); int pScale = COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN; for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i); int p = mod ? IM_MOD((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel)) : IM_DIV((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel)); p = IM_MIN(p, COLOR_GRAYSCALE_MAX); IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_RGB565: { uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); int rScale = COLOR_R5_MAX - COLOR_R5_MIN; int gScale = COLOR_G6_MAX - COLOR_G6_MIN; int bScale = COLOR_B5_MAX - COLOR_B5_MIN; for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i); int dR = COLOR_RGB565_TO_R5(dataPixel); int dG = COLOR_RGB565_TO_G6(dataPixel); int dB = COLOR_RGB565_TO_B5(dataPixel); int oR = COLOR_RGB565_TO_R5(otherPixel); int oG = COLOR_RGB565_TO_G6(otherPixel); int oB = COLOR_RGB565_TO_B5(otherPixel); int r = mod ? IM_MOD((invert?oR:dR) * rScale, (invert?dR:oR)) : IM_DIV((invert?oR:dR) * rScale, (invert?dR:oR)); int g = mod ? IM_MOD((invert?oG:dG) * gScale, (invert?dG:oG)) : IM_DIV((invert?oG:dG) * gScale, (invert?dG:oG)); int b = mod ? IM_MOD((invert?oB:dB) * bScale, (invert?dB:oB)) : IM_DIV((invert?oB:dB) * bScale, (invert?dB:oB)); r = IM_MIN(r, COLOR_R5_MAX); g = IM_MIN(g, COLOR_G6_MAX); b = IM_MIN(b, COLOR_B5_MAX); IMAGE_PUT_RGB565_PIXEL_FAST(data, i, COLOR_R5_G6_B5_TO_RGB565(r, g, b)); } } break; } default: { break; } } }
static void imlib_mul_line_op(image_t *img, int line, void *other, void *data, bool vflipped) { bool invert = ((imlib_mul_line_op_state_t *) data)->invert; image_t *mask = ((imlib_mul_line_op_state_t *) data)->mask; switch(img->bpp) { case IMAGE_BPP_BINARY: { uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); float pScale = COLOR_BINARY_MAX - COLOR_BINARY_MIN; float pDiv = 1 / pScale; for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i); int p = invert ? (pScale - ((pScale - dataPixel) * (pScale - otherPixel) * pDiv)) : (dataPixel * otherPixel * pDiv); IMAGE_PUT_BINARY_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_GRAYSCALE: { uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); float pScale = COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN; float pDiv = 1 / pScale; for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i); int p = invert ? (pScale - ((pScale - dataPixel) * (pScale - otherPixel) * pDiv)) : (dataPixel * otherPixel * pDiv); IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, p); } } break; } case IMAGE_BPP_RGB565: { uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); float rScale = COLOR_R5_MAX - COLOR_R5_MIN; float gScale = COLOR_G6_MAX - COLOR_G6_MIN; float bScale = COLOR_B5_MAX - COLOR_B5_MIN; float rDiv = 1 / rScale; float gDiv = 1 / gScale; float bDiv = 1 / bScale; for (int i = 0, j = img->w; i < j; i++) { if ((!mask) || image_get_mask_pixel(mask, i, line)) { int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, i); int otherPixel = IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i); int dR = COLOR_RGB565_TO_R5(dataPixel); int dG = COLOR_RGB565_TO_G6(dataPixel); int dB = COLOR_RGB565_TO_B5(dataPixel); int oR = COLOR_RGB565_TO_R5(otherPixel); int oG = COLOR_RGB565_TO_G6(otherPixel); int oB = COLOR_RGB565_TO_B5(otherPixel); int r = invert ? (rScale - ((rScale - dR) * (rScale - oR) * rDiv)) : (dR * oR * rDiv); int g = invert ? (gScale - ((gScale - dG) * (gScale - oG) * gDiv)) : (dG * oG * gDiv); int b = invert ? (bScale - ((bScale - dB) * (bScale - oB) * bDiv)) : (dB * oB * bDiv); IMAGE_PUT_RGB565_PIXEL_FAST(data, i, COLOR_R5_G6_B5_TO_RGB565(r, g, b)); } } break; } default: { break; } } }
static void imlib_b_and_line_op(image_t *img, int line, uint8_t *other, void *data, bool vflipped) { image_t *mask = (image_t *) data; switch(img->bpp) { case IMAGE_BPP_BINARY: { uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); if(!mask) { for (int i = 0, j = IMAGE_BINARY_LINE_LEN(img); i < j; i++) { data[i] &= ((uint32_t *) other)[i]; } } else { for (int i = 0, j = img->w; i < j; i++) { if (image_get_mask_pixel(mask, i, line)) { IMAGE_PUT_BINARY_PIXEL_FAST(data, i, (IMAGE_GET_BINARY_PIXEL_FAST(data, i) & IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i))); } } } break; } case IMAGE_BPP_GRAYSCALE: { uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); if(!mask) { for (int i = 0, j = IMAGE_GRAYSCALE_LINE_LEN(img); i < j; i++) { data[i] &= ((uint8_t *) other)[i]; } } else { for (int i = 0, j = img->w; i < j; i++) { if (image_get_mask_pixel(mask, i, line)) { IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, (IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i) & IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i))); } } } break; } case IMAGE_BPP_RGB565: { uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); if(!mask) { for (int i = 0, j = IMAGE_RGB565_LINE_LEN(img); i < j; i++) { data[i] &= ((uint16_t *) other)[i]; } } else { for (int i = 0, j = img->w; i < j; i++) { if (image_get_mask_pixel(mask, i, line)) { IMAGE_PUT_RGB565_PIXEL_FAST(data, i, (IMAGE_GET_RGB565_PIXEL_FAST(data, i) & IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i))); } } } break; } default: { break; } } }
static void imlib_erode_dilate(image_t *img, int ksize, int threshold, int e_or_d, image_t *mask) { int brows = ksize + 1; image_t buf; buf.w = img->w; buf.h = brows; buf.bpp = img->bpp; switch(img->bpp) { case IMAGE_BPP_BINARY: { buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows); for (int y = 0, yy = img->h; y < yy; y++) { uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y); uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)); for (int x = 0, xx = img->w; x < xx; x++) { int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x); IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel); if ((mask && (!image_get_mask_pixel(mask, x, y))) || (pixel == e_or_d)) { continue; // Short circuit. } int acc = e_or_d ? 0 : -1; // Don't count center pixel... for (int j = -ksize; j <= ksize; j++) { uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); for (int k = -ksize; k <= ksize; k++) { acc += IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); } } if (!e_or_d) { // Preserve original pixel value... or clear it. if (acc < threshold) IMAGE_CLEAR_BINARY_PIXEL_FAST(buf_row_ptr, x); } else { // Preserve original pixel value... or set it. if (acc > threshold) IMAGE_SET_BINARY_PIXEL_FAST(buf_row_ptr, x); } } if (y >= ksize) { // Transfer buffer lines... memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)), IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)), IMAGE_BINARY_LINE_LEN_BYTES(img)); } } // Copy any remaining lines from the buffer image... for (int y = img->h - ksize, yy = img->h; y < yy; y++) { memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y), IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)), IMAGE_BINARY_LINE_LEN_BYTES(img)); } fb_free(); break; } case IMAGE_BPP_GRAYSCALE: { buf.data = fb_alloc(IMAGE_GRAYSCALE_LINE_LEN_BYTES(img) * brows); for (int y = 0, yy = img->h; y < yy; y++) { uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); uint8_t *buf_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, (y % brows)); for (int x = 0, xx = img->w; x < xx; x++) { int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x); IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, pixel); if ((mask && (!image_get_mask_pixel(mask, x, y))) || (COLOR_GRAYSCALE_TO_BINARY(pixel) == e_or_d)) { continue; // Short circuit. } int acc = e_or_d ? 0 : -1; // Don't count center pixel... for (int j = -ksize; j <= ksize; j++) { uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); for (int k = -ksize; k <= ksize; k++) { acc += COLOR_GRAYSCALE_TO_BINARY(IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, IM_MIN(IM_MAX(x + k, 0), (img->w - 1)))); } } if (!e_or_d) { // Preserve original pixel value... or clear it. if (acc < threshold) IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, COLOR_GRAYSCALE_BINARY_MIN); } else { // Preserve original pixel value... or set it. if (acc > threshold) IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, COLOR_GRAYSCALE_BINARY_MAX); } } if (y >= ksize) { // Transfer buffer lines... memcpy(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, (y - ksize)), IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)), IMAGE_GRAYSCALE_LINE_LEN_BYTES(img)); } } // Copy any remaining lines from the buffer image... for (int y = img->h - ksize, yy = img->h; y < yy; y++) { memcpy(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y), IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, (y % brows)), IMAGE_GRAYSCALE_LINE_LEN_BYTES(img)); } fb_free(); break; } case IMAGE_BPP_RGB565: { buf.data = fb_alloc(IMAGE_RGB565_LINE_LEN_BYTES(img) * brows); for (int y = 0, yy = img->h; y < yy; y++) { uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); uint16_t *buf_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, (y % brows)); for (int x = 0, xx = img->w; x < xx; x++) { int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x); IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, pixel); if ((mask && (!image_get_mask_pixel(mask, x, y))) || (COLOR_RGB565_TO_BINARY(pixel) == e_or_d)) { continue; // Short circuit. } int acc = e_or_d ? 0 : -1; // Don't count center pixel... for (int j = -ksize; j <= ksize; j++) { uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); for (int k = -ksize; k <= ksize; k++) { acc += COLOR_RGB565_TO_BINARY(IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr, IM_MIN(IM_MAX(x + k, 0), (img->w - 1)))); } } if (!e_or_d) { // Preserve original pixel value... or clear it. if (acc < threshold) IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, COLOR_RGB565_BINARY_MIN); } else { // Preserve original pixel value... or set it. if (acc > threshold) IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, COLOR_RGB565_BINARY_MAX); } } if (y >= ksize) { // Transfer buffer lines... memcpy(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, (y - ksize)), IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)), IMAGE_RGB565_LINE_LEN_BYTES(img)); } } // Copy any remaining lines from the buffer image... for (int y = img->h - ksize, yy = img->h; y < yy; y++) { memcpy(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y), IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, (y % brows)), IMAGE_RGB565_LINE_LEN_BYTES(img)); } fb_free(); break; } default: { break; } } }