binary.c
1 /* This file is part of the OpenMV project. 2 * Copyright (c) 2013-2018 Ibrahim Abdelkader <iabdalkader@openmv.io> & Kwabena W. Agyeman <kwagyeman@openmv.io> 3 * This work is licensed under the MIT license, see the file LICENSE for details. 4 */ 5 6 #include "imlib.h" 7 8 #ifdef IMLIB_ENABLE_BINARY_OPS 9 void imlib_binary(image_t *out, image_t *img, list_t *thresholds, bool invert, bool zero, image_t *mask) 10 { 11 image_t bmp; 12 bmp.w = img->w; 13 bmp.h = img->h; 14 bmp.bpp = IMAGE_BPP_BINARY; 15 bmp.data = fb_alloc0(image_size(&bmp)); 16 17 for (list_lnk_t *it = iterator_start_from_head(thresholds); it; it = iterator_next(it)) { 18 color_thresholds_list_lnk_data_t lnk_data; 19 iterator_get(thresholds, it, &lnk_data); 20 switch(img->bpp) { 21 case IMAGE_BPP_BINARY: { 22 for (int y = 0, yy = img->h; y < yy; y++) { 23 uint32_t *old_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y); 24 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 25 for (int x = 0, xx = img->w; x < xx; x++) { 26 if (COLOR_THRESHOLD_BINARY(IMAGE_GET_BINARY_PIXEL_FAST(old_row_ptr, x), &lnk_data, invert)) { 27 IMAGE_SET_BINARY_PIXEL_FAST(bmp_row_ptr, x); 28 } 29 } 30 } 31 break; 32 } 33 case IMAGE_BPP_GRAYSCALE: { 34 for (int y = 0, yy = img->h; y < yy; y++) { 35 uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); 36 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 37 for (int x = 0, xx = img->w; x < xx; x++) { 38 if (COLOR_THRESHOLD_GRAYSCALE(IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x), &lnk_data, invert)) { 39 IMAGE_SET_BINARY_PIXEL_FAST(bmp_row_ptr, x); 40 } 41 } 42 } 43 break; 44 } 45 case IMAGE_BPP_RGB565: { 46 for (int y = 0, yy = img->h; y < yy; y++) { 47 uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); 48 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 49 for (int x = 0, xx = img->w; x < xx; x++) { 50 if (COLOR_THRESHOLD_RGB565(IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x), &lnk_data, invert)) { 51 IMAGE_SET_BINARY_PIXEL_FAST(bmp_row_ptr, x); 52 } 53 } 54 } 55 break; 56 } 57 default: { 58 break; 59 } 60 } 61 } 62 63 switch(img->bpp) { 64 case IMAGE_BPP_BINARY: { 65 if (!zero) { 66 for (int y = 0, yy = img->h; y < yy; y++) { 67 uint32_t *old_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y); 68 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 69 uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y); 70 for (int x = 0, xx = img->w; x < xx; x++) { 71 int pixel = ((!mask) || image_get_mask_pixel(mask, x, y)) 72 ? IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x) 73 : IMAGE_GET_BINARY_PIXEL_FAST(old_row_ptr, x); 74 IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel); 75 } 76 } 77 } else { 78 for (int y = 0, yy = img->h; y < yy; y++) { 79 uint32_t *old_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y); 80 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 81 uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y); 82 for (int x = 0, xx = img->w; x < xx; x++) { 83 int pixel = IMAGE_GET_BINARY_PIXEL_FAST(old_row_ptr, x); 84 if (((!mask) || image_get_mask_pixel(mask, x, y)) 85 && IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0; 86 IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel); 87 } 88 } 89 } 90 break; 91 } 92 case IMAGE_BPP_GRAYSCALE: { 93 if (out->bpp == IMAGE_BPP_BINARY) { 94 if (!zero) { 95 for (int y = 0, yy = img->h; y < yy; y++) { 96 uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); 97 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 98 uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y); 99 for (int x = 0, xx = img->w; x < xx; x++) { 100 int pixel = ((!mask) || image_get_mask_pixel(mask, x, y)) 101 ? IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x) 102 : COLOR_GRAYSCALE_TO_BINARY(IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x)); 103 IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel); 104 } 105 } 106 } else { 107 for (int y = 0, yy = img->h; y < yy; y++) { 108 uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); 109 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 110 uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y); 111 for (int x = 0, xx = img->w; x < xx; x++) { 112 int pixel = COLOR_GRAYSCALE_TO_BINARY(IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x)); 113 if (((!mask) || image_get_mask_pixel(mask, x, y)) 114 && IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0; 115 IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel); 116 } 117 } 118 } 119 } else { 120 if (!zero) { 121 for (int y = 0, yy = img->h; y < yy; y++) { 122 uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); 123 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 124 uint8_t *out_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(out, y); 125 for (int x = 0, xx = img->w; x < xx; x++) { 126 int pixel = ((!mask) || image_get_mask_pixel(mask, x, y)) 127 ? COLOR_BINARY_TO_GRAYSCALE(IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) 128 : IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x); 129 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(out_row_ptr, x, pixel); 130 } 131 } 132 } else { 133 for (int y = 0, yy = img->h; y < yy; y++) { 134 uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); 135 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 136 uint8_t *out_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(out, y); 137 for (int x = 0, xx = img->w; x < xx; x++) { 138 int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x); 139 if (((!mask) || image_get_mask_pixel(mask, x, y)) 140 && IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0; 141 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(out_row_ptr, x, pixel); 142 } 143 } 144 } 145 } 146 break; 147 } 148 case IMAGE_BPP_RGB565: { 149 if (out->bpp == IMAGE_BPP_BINARY) { 150 if (!zero) { 151 for (int y = 0, yy = img->h; y < yy; y++) { 152 uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); 153 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 154 uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y); 155 for (int x = 0, xx = img->w; x < xx; x++) { 156 int pixel = ((!mask) || image_get_mask_pixel(mask, x, y)) 157 ? IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x) 158 : COLOR_RGB565_TO_BINARY(IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x)); 159 IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel); 160 } 161 } 162 } else { 163 for (int y = 0, yy = img->h; y < yy; y++) { 164 uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); 165 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 166 uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y); 167 for (int x = 0, xx = img->w; x < xx; x++) { 168 int pixel = COLOR_RGB565_TO_BINARY(IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x)); 169 if (((!mask) || image_get_mask_pixel(mask, x, y)) 170 && IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0; 171 IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel); 172 } 173 } 174 } 175 } else { 176 if (!zero) { 177 for (int y = 0, yy = img->h; y < yy; y++) { 178 uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); 179 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 180 uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(out, y); 181 for (int x = 0, xx = img->w; x < xx; x++) { 182 int pixel = ((!mask) || image_get_mask_pixel(mask, x, y)) 183 ? COLOR_BINARY_TO_RGB565(IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) 184 : IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x); 185 IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x, pixel); 186 } 187 } 188 } else { 189 for (int y = 0, yy = img->h; y < yy; y++) { 190 uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); 191 uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y); 192 uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(out, y); 193 for (int x = 0, xx = img->w; x < xx; x++) { 194 int pixel = IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x); 195 if (((!mask) || image_get_mask_pixel(mask, x, y)) 196 && IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0; 197 IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x, pixel); 198 } 199 } 200 } 201 } 202 break; 203 } 204 default: { 205 break; 206 } 207 } 208 209 fb_free(); 210 } 211 212 void imlib_invert(image_t *img) 213 { 214 switch(img->bpp) { 215 case IMAGE_BPP_BINARY: { 216 for (uint32_t *start = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, 0), 217 *end = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, img->h); 218 start < end; start++) { 219 *start = ~*start; 220 } 221 break; 222 } 223 case IMAGE_BPP_GRAYSCALE: { 224 for (uint8_t *start = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, 0), 225 *end = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, img->h); 226 start < end; start++) { 227 *start = ~*start; 228 } 229 break; 230 } 231 case IMAGE_BPP_RGB565: { 232 for (uint16_t *start = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, 0), 233 *end = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, img->h); 234 start < end; start++) { 235 *start = ~*start; 236 } 237 break; 238 } 239 default: { 240 break; 241 } 242 } 243 } 244 245 static void imlib_b_and_line_op(image_t *img, int line, void *other, void *data, bool vflipped) 246 { 247 image_t *mask = (image_t *) data; 248 249 switch(img->bpp) { 250 case IMAGE_BPP_BINARY: { 251 uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); 252 253 if(!mask) { 254 for (int i = 0, j = IMAGE_BINARY_LINE_LEN(img); i < j; i++) { 255 data[i] &= ((uint32_t *) other)[i]; 256 } 257 } else { 258 for (int i = 0, j = img->w; i < j; i++) { 259 if (image_get_mask_pixel(mask, i, line)) { 260 IMAGE_PUT_BINARY_PIXEL_FAST(data, i, 261 (IMAGE_GET_BINARY_PIXEL_FAST(data, i) 262 & IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i))); 263 } 264 } 265 } 266 break; 267 } 268 case IMAGE_BPP_GRAYSCALE: { 269 uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); 270 271 if(!mask) { 272 for (int i = 0, j = IMAGE_GRAYSCALE_LINE_LEN(img); i < j; i++) { 273 data[i] &= ((uint8_t *) other)[i]; 274 } 275 } else { 276 for (int i = 0, j = img->w; i < j; i++) { 277 if (image_get_mask_pixel(mask, i, line)) { 278 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, 279 (IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i) 280 & IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i))); 281 } 282 } 283 } 284 break; 285 } 286 case IMAGE_BPP_RGB565: { 287 uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); 288 289 if(!mask) { 290 for (int i = 0, j = IMAGE_RGB565_LINE_LEN(img); i < j; i++) { 291 data[i] &= ((uint16_t *) other)[i]; 292 } 293 } else { 294 for (int i = 0, j = img->w; i < j; i++) { 295 if (image_get_mask_pixel(mask, i, line)) { 296 IMAGE_PUT_RGB565_PIXEL_FAST(data, i, 297 (IMAGE_GET_RGB565_PIXEL_FAST(data, i) 298 & IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i))); 299 } 300 } 301 } 302 break; 303 } 304 default: { 305 break; 306 } 307 } 308 } 309 310 void imlib_b_and(image_t *img, const char *path, image_t *other, int scalar, image_t *mask) 311 { 312 //imlib_image_operation(img, path, other, scalar, imlib_b_and_line_op, mask); 313 } 314 315 static void imlib_b_nand_line_op(image_t *img, int line, void *other, void *data, bool vflipped) 316 { 317 image_t *mask = (image_t *) data; 318 319 switch(img->bpp) { 320 case IMAGE_BPP_BINARY: { 321 uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); 322 323 if(!mask) { 324 for (int i = 0, j = IMAGE_BINARY_LINE_LEN(img); i < j; i++) { 325 data[i] &= ~((uint32_t *) other)[i]; 326 } 327 } else { 328 for (int i = 0, j = img->w; i < j; i++) { 329 if (image_get_mask_pixel(mask, i, line)) { 330 IMAGE_PUT_BINARY_PIXEL_FAST(data, i, 331 (IMAGE_GET_BINARY_PIXEL_FAST(data, i) 332 & ~IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i))); 333 } 334 } 335 } 336 break; 337 } 338 case IMAGE_BPP_GRAYSCALE: { 339 uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); 340 341 if(!mask) { 342 for (int i = 0, j = IMAGE_GRAYSCALE_LINE_LEN(img); i < j; i++) { 343 data[i] &= ~((uint8_t *) other)[i]; 344 } 345 } else { 346 for (int i = 0, j = img->w; i < j; i++) { 347 if (image_get_mask_pixel(mask, i, line)) { 348 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, 349 (IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i) 350 & ~IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i))); 351 } 352 } 353 } 354 break; 355 } 356 case IMAGE_BPP_RGB565: { 357 uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); 358 359 if(!mask) { 360 for (int i = 0, j = IMAGE_RGB565_LINE_LEN(img); i < j; i++) { 361 data[i] &= ~((uint16_t *) other)[i]; 362 } 363 } else { 364 for (int i = 0, j = img->w; i < j; i++) { 365 if (image_get_mask_pixel(mask, i, line)) { 366 IMAGE_PUT_RGB565_PIXEL_FAST(data, i, 367 (IMAGE_GET_RGB565_PIXEL_FAST(data, i) 368 & ~IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i))); 369 } 370 } 371 } 372 break; 373 } 374 default: { 375 break; 376 } 377 } 378 } 379 380 void imlib_b_nand(image_t *img, const char *path, image_t *other, int scalar, image_t *mask) 381 { 382 //imlib_image_operation(img, path, other, scalar, imlib_b_nand_line_op, mask); 383 } 384 385 static void imlib_b_or_line_op(image_t *img, int line, void *other, void *data, bool vflipped) 386 { 387 image_t *mask = (image_t *) data; 388 389 switch(img->bpp) { 390 case IMAGE_BPP_BINARY: { 391 uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); 392 393 if(!mask) { 394 for (int i = 0, j = IMAGE_BINARY_LINE_LEN(img); i < j; i++) { 395 data[i] |= ((uint32_t *) other)[i]; 396 } 397 } else { 398 for (int i = 0, j = img->w; i < j; i++) { 399 if (image_get_mask_pixel(mask, i, line)) { 400 IMAGE_PUT_BINARY_PIXEL_FAST(data, i, 401 (IMAGE_GET_BINARY_PIXEL_FAST(data, i) 402 | IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i))); 403 } 404 } 405 } 406 break; 407 } 408 case IMAGE_BPP_GRAYSCALE: { 409 uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); 410 411 if(!mask) { 412 for (int i = 0, j = IMAGE_GRAYSCALE_LINE_LEN(img); i < j; i++) { 413 data[i] |= ((uint8_t *) other)[i]; 414 } 415 } else { 416 for (int i = 0, j = img->w; i < j; i++) { 417 if (image_get_mask_pixel(mask, i, line)) { 418 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, 419 (IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i) 420 | IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i))); 421 } 422 } 423 } 424 break; 425 } 426 case IMAGE_BPP_RGB565: { 427 uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); 428 429 if(!mask) { 430 for (int i = 0, j = IMAGE_RGB565_LINE_LEN(img); i < j; i++) { 431 data[i] |= ((uint16_t *) other)[i]; 432 } 433 } else { 434 for (int i = 0, j = img->w; i < j; i++) { 435 if (image_get_mask_pixel(mask, i, line)) { 436 IMAGE_PUT_RGB565_PIXEL_FAST(data, i, 437 (IMAGE_GET_RGB565_PIXEL_FAST(data, i) 438 | IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i))); 439 } 440 } 441 } 442 break; 443 } 444 default: { 445 break; 446 } 447 } 448 } 449 450 void imlib_b_or(image_t *img, const char *path, image_t *other, int scalar, image_t *mask) 451 { 452 //imlib_image_operation(img, path, other, scalar, imlib_b_or_line_op, mask); 453 } 454 455 static void imlib_b_nor_line_op(image_t *img, int line, void *other, void *data, bool vflipped) 456 { 457 image_t *mask = (image_t *) data; 458 459 switch(img->bpp) { 460 case IMAGE_BPP_BINARY: { 461 uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); 462 463 if(!mask) { 464 for (int i = 0, j = IMAGE_BINARY_LINE_LEN(img); i < j; i++) { 465 data[i] |= ~((uint32_t *) other)[i]; 466 } 467 } else { 468 for (int i = 0, j = img->w; i < j; i++) { 469 if (image_get_mask_pixel(mask, i, line)) { 470 IMAGE_PUT_BINARY_PIXEL_FAST(data, i, 471 (IMAGE_GET_BINARY_PIXEL_FAST(data, i) 472 | ~IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i))); 473 } 474 } 475 } 476 break; 477 } 478 case IMAGE_BPP_GRAYSCALE: { 479 uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); 480 481 if(!mask) { 482 for (int i = 0, j = IMAGE_GRAYSCALE_LINE_LEN(img); i < j; i++) { 483 data[i] |= ~((uint8_t *) other)[i]; 484 } 485 } else { 486 for (int i = 0, j = img->w; i < j; i++) { 487 if (image_get_mask_pixel(mask, i, line)) { 488 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, 489 (IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i) 490 | ~IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i))); 491 } 492 } 493 } 494 break; 495 } 496 case IMAGE_BPP_RGB565: { 497 uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); 498 499 if(!mask) { 500 for (int i = 0, j = IMAGE_RGB565_LINE_LEN(img); i < j; i++) { 501 data[i] |= ~((uint16_t *) other)[i]; 502 } 503 } else { 504 for (int i = 0, j = img->w; i < j; i++) { 505 if (image_get_mask_pixel(mask, i, line)) { 506 IMAGE_PUT_RGB565_PIXEL_FAST(data, i, 507 (IMAGE_GET_RGB565_PIXEL_FAST(data, i) 508 | ~IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i))); 509 } 510 } 511 } 512 break; 513 } 514 default: { 515 break; 516 } 517 } 518 } 519 520 void imlib_b_nor(image_t *img, const char *path, image_t *other, int scalar, image_t *mask) 521 { 522 //imlib_image_operation(img, path, other, scalar,imlib_b_nor_line_op, mask); 523 } 524 525 static void imlib_b_xor_line_op(image_t *img, int line, void *other, void *data, bool vflipped) 526 { 527 image_t *mask = (image_t *) data; 528 529 switch(img->bpp) { 530 case IMAGE_BPP_BINARY: { 531 uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); 532 533 if(!mask) { 534 for (int i = 0, j = IMAGE_BINARY_LINE_LEN(img); i < j; i++) { 535 data[i] ^= ((uint32_t *) other)[i]; 536 } 537 } else { 538 for (int i = 0, j = img->w; i < j; i++) { 539 if (image_get_mask_pixel(mask, i, line)) { 540 IMAGE_PUT_BINARY_PIXEL_FAST(data, i, 541 (IMAGE_GET_BINARY_PIXEL_FAST(data, i) 542 ^ IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i))); 543 } 544 } 545 } 546 break; 547 } 548 case IMAGE_BPP_GRAYSCALE: { 549 uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); 550 551 if(!mask) { 552 for (int i = 0, j = IMAGE_GRAYSCALE_LINE_LEN(img); i < j; i++) { 553 data[i] ^= ((uint8_t *) other)[i]; 554 } 555 } else { 556 for (int i = 0, j = img->w; i < j; i++) { 557 if (image_get_mask_pixel(mask, i, line)) { 558 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, 559 (IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i) 560 ^ IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i))); 561 } 562 } 563 } 564 break; 565 } 566 case IMAGE_BPP_RGB565: { 567 uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); 568 569 if(!mask) { 570 for (int i = 0, j = IMAGE_RGB565_LINE_LEN(img); i < j; i++) { 571 data[i] ^= ((uint16_t *) other)[i]; 572 } 573 } else { 574 for (int i = 0, j = img->w; i < j; i++) { 575 if (image_get_mask_pixel(mask, i, line)) { 576 IMAGE_PUT_RGB565_PIXEL_FAST(data, i, 577 (IMAGE_GET_RGB565_PIXEL_FAST(data, i) 578 ^ IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i))); 579 } 580 } 581 } 582 break; 583 } 584 default: { 585 break; 586 } 587 } 588 } 589 590 void imlib_b_xor(image_t *img, const char *path, image_t *other, int scalar, image_t *mask) 591 { 592 //imlib_image_operation(img, path, other, scalar, imlib_b_xor_line_op, mask); 593 } 594 595 static void imlib_b_xnor_line_op(image_t *img, int line, void *other, void *data, bool vflipped) 596 { 597 image_t *mask = (image_t *) data; 598 599 switch(img->bpp) { 600 case IMAGE_BPP_BINARY: { 601 uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line); 602 603 if(!mask) { 604 for (int i = 0, j = IMAGE_BINARY_LINE_LEN(img); i < j; i++) { 605 data[i] ^= ~((uint32_t *) other)[i]; 606 } 607 } else { 608 for (int i = 0, j = img->w; i < j; i++) { 609 if (image_get_mask_pixel(mask, i, line)) { 610 IMAGE_PUT_BINARY_PIXEL_FAST(data, i, 611 (IMAGE_GET_BINARY_PIXEL_FAST(data, i) 612 ^ ~IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i))); 613 } 614 } 615 } 616 break; 617 } 618 case IMAGE_BPP_GRAYSCALE: { 619 uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line); 620 621 if(!mask) { 622 for (int i = 0, j = IMAGE_GRAYSCALE_LINE_LEN(img); i < j; i++) { 623 data[i] ^= ~((uint8_t *) other)[i]; 624 } 625 } else { 626 for (int i = 0, j = img->w; i < j; i++) { 627 if (image_get_mask_pixel(mask, i, line)) { 628 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, 629 (IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i) 630 ^ ~IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i))); 631 } 632 } 633 } 634 break; 635 } 636 case IMAGE_BPP_RGB565: { 637 uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line); 638 639 if(!mask) { 640 for (int i = 0, j = IMAGE_RGB565_LINE_LEN(img); i < j; i++) { 641 data[i] ^= ~((uint16_t *) other)[i]; 642 } 643 } else { 644 for (int i = 0, j = img->w; i < j; i++) { 645 if (image_get_mask_pixel(mask, i, line)) { 646 IMAGE_PUT_RGB565_PIXEL_FAST(data, i, 647 (IMAGE_GET_RGB565_PIXEL_FAST(data, i) 648 ^ ~IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), i))); 649 } 650 } 651 } 652 break; 653 } 654 default: { 655 break; 656 } 657 } 658 } 659 660 void imlib_b_xnor(image_t *img, const char *path, image_t *other, int scalar, image_t *mask) 661 { 662 //imlib_image_operation(img, path, other, scalar, imlib_b_xnor_line_op, mask); 663 } 664 665 static void imlib_erode_dilate(image_t *img, int ksize, int threshold, int e_or_d, image_t *mask) 666 { 667 int brows = ksize + 1; 668 image_t buf; 669 buf.w = img->w; 670 buf.h = brows; 671 buf.bpp = img->bpp; 672 673 switch(img->bpp) { 674 case IMAGE_BPP_BINARY: { 675 buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows); 676 677 for (int y = 0, yy = img->h; y < yy; y++) { 678 uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y); 679 uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)); 680 681 for (int x = 0, xx = img->w; x < xx; x++) { 682 int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x); 683 IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel); 684 685 if ((mask && (!image_get_mask_pixel(mask, x, y))) 686 || (pixel == e_or_d)) { 687 continue; // Short circuit. 688 } 689 690 int acc = e_or_d ? 0 : -1; // Don't count center pixel... 691 692 for (int j = -ksize; j <= ksize; j++) { 693 uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, 694 IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); 695 696 for (int k = -ksize; k <= ksize; k++) { 697 acc += IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, 698 IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); 699 } 700 } 701 702 if (!e_or_d) { 703 // Preserve original pixel value... or clear it. 704 if (acc < threshold) IMAGE_CLEAR_BINARY_PIXEL_FAST(buf_row_ptr, x); 705 } else { 706 // Preserve original pixel value... or set it. 707 if (acc > threshold) IMAGE_SET_BINARY_PIXEL_FAST(buf_row_ptr, x); 708 } 709 } 710 711 if (y >= ksize) { // Transfer buffer lines... 712 memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)), 713 IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)), 714 IMAGE_BINARY_LINE_LEN_BYTES(img)); 715 } 716 } 717 718 // Copy any remaining lines from the buffer image... 719 for (int y = img->h - ksize, yy = img->h; y < yy; y++) { 720 memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y), 721 IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)), 722 IMAGE_BINARY_LINE_LEN_BYTES(img)); 723 } 724 725 fb_free(); 726 break; 727 } 728 case IMAGE_BPP_GRAYSCALE: { 729 buf.data = fb_alloc(IMAGE_GRAYSCALE_LINE_LEN_BYTES(img) * brows); 730 731 for (int y = 0, yy = img->h; y < yy; y++) { 732 uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y); 733 uint8_t *buf_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, (y % brows)); 734 735 for (int x = 0, xx = img->w; x < xx; x++) { 736 int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x); 737 IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, pixel); 738 739 if ((mask && (!image_get_mask_pixel(mask, x, y))) 740 || (COLOR_GRAYSCALE_TO_BINARY(pixel) == e_or_d)) { 741 continue; // Short circuit. 742 } 743 744 int acc = e_or_d ? 0 : -1; // Don't count center pixel... 745 746 for (int j = -ksize; j <= ksize; j++) { 747 uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, 748 IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); 749 750 for (int k = -ksize; k <= ksize; k++) { 751 acc += COLOR_GRAYSCALE_TO_BINARY(IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, 752 IM_MIN(IM_MAX(x + k, 0), (img->w - 1)))); 753 } 754 } 755 756 if (!e_or_d) { 757 // Preserve original pixel value... or clear it. 758 if (acc < threshold) IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, 759 COLOR_GRAYSCALE_BINARY_MIN); 760 } else { 761 // Preserve original pixel value... or set it. 762 if (acc > threshold) IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, 763 COLOR_GRAYSCALE_BINARY_MAX); 764 } 765 } 766 767 if (y >= ksize) { // Transfer buffer lines... 768 memcpy(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, (y - ksize)), 769 IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)), 770 IMAGE_GRAYSCALE_LINE_LEN_BYTES(img)); 771 } 772 } 773 774 // Copy any remaining lines from the buffer image... 775 for (int y = img->h - ksize, yy = img->h; y < yy; y++) { 776 memcpy(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y), 777 IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, (y % brows)), 778 IMAGE_GRAYSCALE_LINE_LEN_BYTES(img)); 779 } 780 781 fb_free(); 782 break; 783 } 784 case IMAGE_BPP_RGB565: { 785 buf.data = fb_alloc(IMAGE_RGB565_LINE_LEN_BYTES(img) * brows); 786 787 for (int y = 0, yy = img->h; y < yy; y++) { 788 uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y); 789 uint16_t *buf_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, (y % brows)); 790 791 for (int x = 0, xx = img->w; x < xx; x++) { 792 int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x); 793 IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, pixel); 794 795 if ((mask && (!image_get_mask_pixel(mask, x, y))) 796 || (COLOR_RGB565_TO_BINARY(pixel) == e_or_d)) { 797 continue; // Short circuit. 798 } 799 800 int acc = e_or_d ? 0 : -1; // Don't count center pixel... 801 802 for (int j = -ksize; j <= ksize; j++) { 803 uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, 804 IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); 805 806 for (int k = -ksize; k <= ksize; k++) { 807 acc += COLOR_RGB565_TO_BINARY(IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr, 808 IM_MIN(IM_MAX(x + k, 0), (img->w - 1)))); 809 } 810 } 811 812 if (!e_or_d) { 813 // Preserve original pixel value... or clear it. 814 if (acc < threshold) IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, 815 COLOR_RGB565_BINARY_MIN); 816 } else { 817 // Preserve original pixel value... or set it. 818 if (acc > threshold) IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, 819 COLOR_RGB565_BINARY_MAX); 820 } 821 } 822 823 if (y >= ksize) { // Transfer buffer lines... 824 memcpy(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, (y - ksize)), 825 IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)), 826 IMAGE_RGB565_LINE_LEN_BYTES(img)); 827 } 828 } 829 830 // Copy any remaining lines from the buffer image... 831 for (int y = img->h - ksize, yy = img->h; y < yy; y++) { 832 memcpy(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y), 833 IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, (y % brows)), 834 IMAGE_RGB565_LINE_LEN_BYTES(img)); 835 } 836 837 fb_free(); 838 break; 839 } 840 default: { 841 break; 842 } 843 } 844 } 845 846 void imlib_erode(image_t *img, int ksize, int threshold, image_t *mask) 847 { 848 // Threshold should be equal to (((ksize*2)+1)*((ksize*2)+1))-1 849 // for normal operation. E.g. for ksize==3 -> threshold==8 850 // Basically you're adjusting the number of data that 851 // must be set in the kernel (besides the center) for the output to be 1. 852 // Erode normally requires all data to be 1. 853 imlib_erode_dilate(img, ksize, threshold, 0, mask); 854 } 855 856 void imlib_dilate(image_t *img, int ksize, int threshold, image_t *mask) 857 { 858 // Threshold should be equal to 0 859 // for normal operation. E.g. for ksize==3 -> threshold==0 860 // Basically you're adjusting the number of data that 861 // must be set in the kernel (besides the center) for the output to be 1. 862 // Dilate normally requires one pixel to be 1. 863 imlib_erode_dilate(img, ksize, threshold, 1, mask); 864 } 865 866 void imlib_open(image_t *img, int ksize, int threshold, image_t *mask) 867 { 868 imlib_erode(img, ksize, (((ksize*2)+1)*((ksize*2)+1))-1 - threshold, mask); 869 imlib_dilate(img, ksize, 0 + threshold, mask); 870 } 871 872 void imlib_close(image_t *img, int ksize, int threshold, image_t *mask) 873 { 874 imlib_dilate(img, ksize, 0 + threshold, mask); 875 imlib_erode(img, ksize, (((ksize*2)+1)*((ksize*2)+1))-1 - threshold, mask); 876 } 877 878 void imlib_top_hat(image_t *img, int ksize, int threshold, image_t *mask) 879 { 880 image_t temp; 881 temp.w = img->w; 882 temp.h = img->h; 883 temp.bpp = img->bpp; 884 temp.data = fb_alloc(image_size(img)); 885 memcpy(temp.data, img->data, image_size(img)); 886 imlib_open(&temp, ksize, threshold, mask); 887 imlib_difference(img, NULL, &temp, 0, mask); 888 fb_free(); 889 } 890 891 void imlib_black_hat(image_t *img, int ksize, int threshold, image_t *mask) 892 { 893 image_t temp; 894 temp.w = img->w; 895 temp.h = img->h; 896 temp.bpp = img->bpp; 897 temp.data = fb_alloc(image_size(img)); 898 memcpy(temp.data, img->data, image_size(img)); 899 imlib_close(&temp, ksize, threshold, mask); 900 imlib_difference(img, NULL, &temp, 0, mask); 901 fb_free(); 902 } 903 #endif