40 #define DEFAULT_ALIGNMENT_U8 96 44 uint8_t *buf = calloc(height*stride,
sizeof(uint8_t));
47 image_u8_t tmp = { .
width = width, .height = height, .stride = stride, .buf = buf };
63 if ((stride % alignment) != 0)
64 stride += alignment - (stride % alignment);
71 uint8_t *buf = malloc(in->
height*in->
stride*
sizeof(uint8_t));
110 if (pnm->
max == 255) {
111 for (
int y = 0; y < im->
height; y++)
113 }
else if (pnm->
max == 65535) {
114 for (
int y = 0; y < im->
height; y++)
115 for (
int x = 0; x < im->
width; x++)
127 if (pnm->
max == 255) {
129 for (
int y = 0; y < im->
height; y++) {
130 for (
int x = 0; x < im->
width; x++) {
131 uint8_t gray = (pnm->
buf[y*im->
width*3 + 3*x+0] +
140 }
else if (pnm->
max == 65535) {
141 for (
int y = 0; y < im->
height; y++) {
142 for (
int x = 0; x < im->
width; x++) {
143 int r = pnm->
buf[6*(y*im->
width + x) + 0];
144 int g = pnm->
buf[6*(y*im->
width + x) + 2];
145 int b = pnm->
buf[6*(y*im->
width + x) + 4];
147 im->
buf[y*im->
stride + x] = (r + g + g + b) / 4;
163 int pbmstride = (im->
width + 7) / 8;
165 for (
int y = 0; y < im->
height; y++) {
166 for (
int x = 0; x < im->
width; x++) {
167 int byteidx = y * pbmstride + x / 8;
168 int bitidx = 7 - (x & 7);
171 if ((pnm->
buf[byteidx] >> bitidx) & 1)
189 for (
int y = 0; y < fim->
height; y++) {
190 for (
int x = 0; x < fim->
width; x++) {
192 im->
buf[y*im->
stride + x] = (int) (255 * v);
202 FILE *f = fopen(path,
"wb");
211 fprintf(f,
"P5\n%d %d\n255\n", im->
width, im->
height);
213 for (
int y = 0; y < im->
height; y++) {
231 for (
int y = y0-r; y <= y0+r; y++) {
232 for (
int x = x0-r; x <= x0+r; x++) {
233 float d = (x-x0)*(x-x0) + (y-y0)*(y-y0);
237 if (x >= 0 && x < im->width && y >= 0 && y < im->height) {
238 int idx = y*im->
stride + x;
252 for (
int y = y0-r1; y <= y0+r1; y++) {
253 for (
int x = x0-r1; x <= x0+r1; x++) {
254 float d = (x-x0)*(x-x0) + (y-y0)*(y-y0);
255 if (d < r0 || d > r1)
258 int idx = y*im->
stride + x;
267 double dist = sqrtf((y1-y0)*(y1-y0) + (x1-x0)*(x1-x0));
268 double delta = 0.5 / dist;
271 for (
float f = 0; f <= 1; f += delta) {
272 int x = ((int) (x1 + (x0 - x1) * f));
273 int y = ((int) (y1 + (y0 - y1) * f));
275 if (x < 0 || y < 0 || x >= im->
width || y >= im->
height)
278 int idx = y*im->
stride + x;
290 for (
int y = 0; y < im->
height; y++) {
291 for (
int x = 0; x < im->
width; x++) {
297 static void convolve(
const uint8_t *x, uint8_t *y,
int sz,
const uint8_t *k,
int ksz)
301 for (
int i = 0; i < ksz/2 && i < sz; i++)
304 for (
int i = 0; i < sz - ksz; i++) {
307 for (
int j = 0; j < ksz; j++)
310 y[ksz/2 + i] = acc >> 8;
313 for (
int i = sz - ksz + ksz/2; i < sz; i++)
319 assert((ksz & 1) == 1);
321 for (
int y = 0; y < im->
height; y++) {
323 uint8_t *x = malloc(
sizeof(uint8_t)*im->
stride);
330 for (
int x = 0; x < im->
width; x++) {
331 uint8_t *xb = malloc(
sizeof(uint8_t)*im->
height);
332 uint8_t *yb = malloc(
sizeof(uint8_t)*im->
height);
334 for (
int y = 0; y < im->
height; y++)
340 for (
int y = 0; y < im->
height; y++)
351 assert((ksz & 1) == 1);
354 double *dk = malloc(
sizeof(
double)*ksz);
358 for (
int i = 0; i < ksz; i++) {
360 double v = exp(-.5*
sq(x / sigma));
366 for (
int i = 0; i < ksz; i++)
369 for (
int i = 0; i < ksz; i++)
372 uint8_t *k = malloc(
sizeof(uint8_t)*ksz);
373 for (
int i = 0; i < ksz; i++)
377 for (
int i = 0; i < ksz; i++)
378 printf(
"%d %15f %5d\n", i, dk[i], k[i]);
391 float c = cos(rad), s = sin(rad);
393 float p[][2] = { { 0, 0}, { iwidth, 0 }, { iwidth, iheight }, { 0, iheight} };
395 float xmin = HUGE_VALF, xmax = -HUGE_VALF, ymin = HUGE_VALF, ymax = -HUGE_VALF;
396 float icx = iwidth / 2.0, icy = iheight / 2.0;
398 for (
int i = 0; i < 4; i++) {
399 float px = p[i][0] - icx;
400 float py = p[i][1] - icy;
402 float nx = px*c - py*s;
403 float ny = px*s + py*c;
405 xmin = fmin(xmin, nx);
406 xmax = fmax(xmax, nx);
407 ymin = fmin(ymin, ny);
408 ymax = fmax(ymax, ny);
411 int owidth = ceil(xmax-xmin), oheight = ceil(ymax - ymin);
415 for (
int oy = 0; oy < oheight; oy++) {
416 for (
int ox = 0; ox < owidth; ox++) {
419 float sx = ox - owidth / 2.0 + .5;
420 float sy = oy - oheight / 2.0 + .5;
423 int ix = floor(sx*c + sy*s + icx);
424 int iy = floor(-sx*s + sy*c + icy);
426 if (ix >= 0 && iy >= 0 && ix < iwidth && iy < iheight)
440 if (ffactor == 1.5) {
441 int swidth = width / 3 * 2, sheight = height / 3 * 2;
446 while (sy < sheight) {
448 while (sx < swidth) {
453 uint8_t a = im->
buf[(y+0)*im->
stride + (x+0)];
454 uint8_t b = im->
buf[(y+0)*im->
stride + (x+1)];
455 uint8_t c = im->
buf[(y+0)*im->
stride + (x+2)];
457 uint8_t d = im->
buf[(y+1)*im->
stride + (x+0)];
458 uint8_t e = im->
buf[(y+1)*im->
stride + (x+1)];
459 uint8_t f = im->
buf[(y+1)*im->
stride + (x+2)];
461 uint8_t g = im->
buf[(y+2)*im->
stride + (x+0)];
462 uint8_t h = im->
buf[(y+2)*im->
stride + (x+1)];
463 uint8_t i = im->
buf[(y+2)*im->
stride + (x+2)];
465 decim->
buf[(sy+0)*decim->
stride + (sx + 0)] =
467 decim->
buf[(sy+0)*decim->
stride + (sx + 1)] =
470 decim->
buf[(sy+1)*decim->
stride + (sx + 0)] =
472 decim->
buf[(sy+1)*decim->
stride + (sx + 1)] =
486 int factor = (int) ffactor;
488 int swidth = 1 + (width - 1)/factor;
489 int sheight = 1 + (height - 1)/factor;
492 for (
int y = 0; y < height; y += factor) {
494 for (
int x = 0; x < width; x += factor) {
507 float max_dist = sqrt(max_dist2);
510 double theta = atan2(xy1[1]-xy0[1], xy1[0]-xy0[0]);
511 double v = sin(theta), u = cos(theta);
513 int ix0 =
iclamp(fmin(xy0[0], xy1[0]) - max_dist, 0, im->
width-1);
514 int ix1 =
iclamp(fmax(xy0[0], xy1[0]) + max_dist, 0, im->
width-1);
516 int iy0 =
iclamp(fmin(xy0[1], xy1[1]) - max_dist, 0, im->
height-1);
517 int iy1 =
iclamp(fmax(xy0[1], xy1[1]) + max_dist, 0, im->
height-1);
521 float xy1_line_coord = (xy1[0]-xy0[0])*u + (xy1[1]-xy0[1])*v;
523 float min_line_coord = fmin(0, xy1_line_coord);
524 float max_line_coord = fmax(0, xy1_line_coord);
526 for (
int iy = iy0; iy <= iy1; iy++) {
529 for (
int ix = ix0; ix <= ix1; ix++) {
533 float line_coord = (x - xy0[0])*u + (y - xy0[1])*v;
536 if (line_coord < min_line_coord)
537 line_coord = min_line_coord;
538 else if (line_coord > max_line_coord)
539 line_coord = max_line_coord;
541 float px = xy0[0] + line_coord*u;
542 float py = xy0[1] + line_coord*v;
544 double dist2 = (x-px)*(x-px) + (y-py)*(y-py);
547 int idx = dist2 * lut->
scale;
551 uint8_t lut_value = lut->
values[idx];
552 uint8_t old_value = im->
buf[iy*im->
stride + ix];
553 if (lut_value > old_value)
static int iclamp(int v, int minv, int maxv)
void image_u8_draw_circle(image_u8_t *im, float x0, float y0, float r, int v)
static void convolve(const uint8_t *x, uint8_t *y, int sz, const uint8_t *k, int ksz)
void image_u8_darken(image_u8_t *im)
image_u8_t * image_u8_decimate(image_u8_t *im, float ffactor)
#define PNM_FORMAT_BINARY
image_u8_t * image_u8_create_from_f32(image_f32_t *fim)
image_u8_t * image_u8_create_stride(unsigned int width, unsigned int height, unsigned int stride)
image_u8_t * image_u8_rotate(const image_u8_t *in, double rad, uint8_t pad)
image_u8_t * image_u8_copy(const image_u8_t *in)
image_u8_t * image_u8_create_alignment(unsigned int width, unsigned int height, unsigned int alignment)
int image_u8_write_pnm(const image_u8_t *im, const char *path)
static double sq(double v)
image_u8_t * image_u8_create_from_pnm(const char *path)
void image_u8_gaussian_blur(image_u8_t *im, double sigma, int ksz)
void image_u8_convolve_2D(image_u8_t *im, const uint8_t *k, int ksz)
void image_u8_draw_annulus(image_u8_t *im, float x0, float y0, float r0, float r1, int v)
#define DEFAULT_ALIGNMENT_U8
image_u8_t * image_u8_create(unsigned int width, unsigned int height)
void image_u8_destroy(image_u8_t *im)
image_u8_t * image_u8_create_from_pnm_alignment(const char *path, int alignment)
pnm_t * pnm_create_from_file(const char *path)
void image_u8_fill_line_max(image_u8_t *im, const image_u8_lut_t *lut, const float *xy0, const float *xy1)
void image_u8_draw_line(image_u8_t *im, float x0, float y0, float x1, float y1, int v, int width)
void pnm_destroy(pnm_t *pnm)