unsigned int floodfill(image img, int px, int py,
	       rgb_color_p bankscolor,
	       rgb_color_p rcolor)
{
  _ffill_queue head;
  rgb_color thisnode;
  unsigned int pixelcount = 0;
  double tolerance = 0.05;

  if ( (px < 0) || (py < 0) || (px >= img->width) || (py >= img->height) )
    return;

  TAILQ_INIT(&head);

  _ffill_rgbcolor(img, &thisnode, px, py);
  if ( color_distance(&thisnode, bankscolor) <= tolerance ) return;

  _ffill_enqueue(&head, px, py);
  while( head.tqh_first != NULL ) {
    _ffill_node_t *n = head.tqh_first;
    _ffill_rgbcolor(img, &thisnode, n->px, n->py);
    if ( color_distance(&thisnode, bankscolor) > tolerance ) {
      put_pixel_unsafe(img, n->px, n->py, rcolor->red, rcolor->green, rcolor->blue);
      pixelcount++;
    }
    int tx = n->px, ty = n->py;
    _ffill_removehead(&head);
    NSOE(tx - 1, ty);
    NSOE(tx + 1, ty);
    NSOE(tx, ty - 1);
    NSOE(tx, ty + 1);
  }
  return pixelcount;
}
image filter(image im, double *K, int Ks, double divisor, double offset)
{
  image oi;
  unsigned int ix, iy, l;
  int kx, ky;
  double cp[3];

  oi = alloc_img(im->width, im->height);
  if ( oi != NULL ) {
    for(ix=0; ix < im->width; ix++) {
      for(iy=0; iy < im->height; iy++) {
	cp[0] = cp[1] = cp[2] = 0.0;
	for(kx=-Ks; kx <= Ks; kx++) {
	  for(ky=-Ks; ky <= Ks; ky++) {
	    for(l=0; l<3; l++)
	      cp[l] += (K[(kx+Ks) +
                        (ky+Ks)*(2*Ks+1)]/divisor) *
                        ((double)GET_PIXEL_CHECK(im, ix+kx, iy+ky, l)) + offset;
	  }
	}
	for(l=0; l<3; l++)
	  cp[l] = (cp[l]>255.0) ? 255.0 : ((cp[l]<0.0) ? 0.0 : cp[l]) ;
	put_pixel_unsafe(oi, ix, iy,
			 (color_component)cp[0],
			 (color_component)cp[1],
			 (color_component)cp[2]);
      }
    }
    return oi;
  }
  return NULL;
}
void writeppm(char *filename, const int width, const int height, unsigned char *img)
{
    int x, y, px;
    image image;
    FILE  *fp;
    fopen_s(&fp, filename, "wb");    
    image = alloc_img(width, height);
    for (y = 0; y < height; ++y) {
        for (x = 0; x < width; ++x) {
            px = (y * width + x) * 3;
            put_pixel_unsafe(image, x, y, img[px + 0], img[px + 1], img[px + 2]);
        }
    }
    output_ppm(fp, image);
    fclose(fp);
}