in native-filters/src/main/jni/filters/rounding_filter.c [160:264]
static void toCircle(
JNIEnv* env,
pixel_t* pixelPtr,
const int w,
const int h) {
const int centerX = w / 2;
const int centerY = h / 2;
const int radius = min(w,h) / 2;
if (radius < 1) {
safe_throw_exception(env, "Circle radius too small!");
return;
}
if (w <= 0 || h <= 0 || w > BITMAP_MAX_DIMENSION || h > BITMAP_MAX_DIMENSION) {
safe_throw_exception(env, "Invalid bitmap dimensions!");
return;
}
if (centerX < 0 || centerY < 0 || centerX >= w || centerY >= h) {
safe_throw_exception(env, "Invalid circle center coordinates!");
return;
}
int x = radius - 1;
int y = 0;
const int maxX = centerX + x;
const int maxY = centerY + x;
const int minX = centerX - x;
const int minY = centerY - x;
if (minX < 0 || minY < 0 || maxX >= w || maxY >= h) {
safe_throw_exception(env, "Circle must be fully visible!");
return;
}
int dx = 1;
int dy = 1;
const int rInc = - radius * 2;
int err = dx + rInc;
while (x >= y) {
const int cXpX = centerX + x;
const int cXmX = centerX - x;
const int cXpY = centerX + y;
const int cXmY = centerX - y;
const int cYpX = centerY + x;
const int cYmX = centerY - x;
const int cYpY = centerY + y;
const int cYmY = centerY - y;
if (x < 0 || cXpY >= w || cXmY < 0 || cYpY >= h || cYmY < 0) {
safe_throw_exception(env, "Invalid internal state!");
return;
}
const int offA = w * cYpY;
const int offB = w * cYmY;
const int offC = w * cYpX;
const int offD = w * cYmX;
const size_t leftBytesX = sizeof(pixel_t) * cXmX;
const size_t leftBytesY = sizeof(pixel_t) * cXmY;
const size_t rightBytesX = sizeof(pixel_t) * (w-cXpX);
const size_t rightBytesY = sizeof(pixel_t) * (w-cXpY);
// clear left
memset(pixelPtr + offA, TRANSPARENT_PIXEL_COLOR, leftBytesX);
memset(pixelPtr + offB, TRANSPARENT_PIXEL_COLOR, leftBytesX);
memset(pixelPtr + offC, TRANSPARENT_PIXEL_COLOR, leftBytesY);
memset(pixelPtr + offD, TRANSPARENT_PIXEL_COLOR, leftBytesY);
// clear right
memset(pixelPtr + offA + cXpX, TRANSPARENT_PIXEL_COLOR, rightBytesX);
memset(pixelPtr + offB + cXpX, TRANSPARENT_PIXEL_COLOR, rightBytesX);
memset(pixelPtr + offC + cXpY, TRANSPARENT_PIXEL_COLOR, rightBytesY);
memset(pixelPtr + offD + cXpY, TRANSPARENT_PIXEL_COLOR, rightBytesY);
if (err <= 0) {
y++;
dy += 2;
err += dy;
}
if (err > 0) {
x--;
dx += 2;
err += dx + rInc;
}
}
const size_t lineBytes = sizeof(pixel_t) * w;
// clear top / bottom if height > width
for (int i = centerY - radius; i >= 0; i--) {
memset(pixelPtr + i * w, TRANSPARENT_PIXEL_COLOR, lineBytes);
}
for (int i = centerY + radius; i < h; i++) {
memset(pixelPtr + i * w, TRANSPARENT_PIXEL_COLOR, lineBytes);
}
}