Blame simple/imgfilters/img.inc.c

608c44
608c44
608c44
#define IMG_PRECISION (1e-8)
608c44
608c44
608c44
typedef struct {
608c44
  int w, h;
608c44
  double *data;
608c44
} Img;
608c44
608c44
608c44
void setRgb(double *rgb, double r, double g, double b)
608c44
  { rgb[0] = r; rgb[1] = g; rgb[2] = b; }
608c44
608c44
int colorMin(const double *rgb)
608c44
  { return rgb[0] < rgb[1] ? (rgb[0] < rgb[2] ? 0 : 2) : (rgb[1] < rgb[2] ? 1 : 2); }
608c44
int colorMax(const double *rgb)
608c44
  { return rgb[0] < rgb[1] ? (rgb[1] < rgb[2] ? 2 : 1) : (rgb[0] < rgb[2] ? 2 : 0); }
608c44
608c44
void rgbToHsv(double *hsv, const double *rgb) {
608c44
  int cmin = colorMin(rgb);
608c44
  int cmax = colorMax(rgb);
608c44
  double d = rgb[cmax] - rgb[cmin];
608c44
608c44
  double h = 0;
608c44
  if (d > IMG_PRECISION) {
608c44
    double k = 1.0/d;
608c44
    switch(cmax){
608c44
    case 0: h = (rgb[1] - rgb[2])*k + 0; break;
608c44
    case 1: h = (rgb[2] - rgb[0])*k + 2; break;
608c44
    case 2: h = (rgb[0] - rgb[1])*k + 4; break;
608c44
    }
608c44
    h /= 6; h -= floor(h); h *= 360;
608c44
  }
608c44
  double s = rgb[cmax] > IMG_PRECISION ? d/rgb[cmax] : 0;
608c44
  double v = rgb[cmax];
608c44
  setRgb(hsv, h, s, v);
608c44
}
608c44
608c44
608c44
void hsvToRgb(double *rgb, const double *hsv) {
608c44
  double h = hsv[0], s = hsv[1], v = hsv[2];
608c44
  h -= floor(h/360)*360;
608c44
  h /= 60.0;
608c44
  int i = (int)h;
608c44
  double f = h - i;
608c44
  double p = v*(1 - s);
608c44
  double q = v*(1 - s*f);
608c44
  double t = v*(1 - s*(1 - f));
608c44
  switch(i) {
608c44
  case 0: setRgb(rgb, v, t, p); return;
608c44
  case 1: setRgb(rgb, q, v, p); return;
608c44
  case 2: setRgb(rgb, p, v, t); return;
608c44
  case 3: setRgb(rgb, p, q, v); return;
608c44
  case 4: setRgb(rgb, t, p, v); return;
608c44
  case 5: setRgb(rgb, v, p, q); return;
608c44
  }
608c44
  return setRgb(rgb, v, t, p);
608c44
}
608c44
608c44
608c44
double cubicInterpolation(double p0, double p1, double p2, double p3, double l) {
608c44
  double ll = l*l;
608c44
  double lll = ll*l;
608c44
  return 0.5*( p0*(  -lll + 2*ll - l)
608c44
             + p1*( 3*lll - 5*ll + 2)
608c44
             + p2*(-3*lll + 4*ll + l)
608c44
             + p3*(   lll -   ll    ) );
608c44
}
608c44
608c44
double cubicRow(double *row, int count, double x) {
608c44
  if (count < 0) return 0;
608c44
  if (!(x > 0)) x = 0;
608c44
  if (!(x < count)) x = count;
608c44
  double xi = floor(x);
608c44
  double l = x - xi;
608c44
608c44
  int i = (int)x - 1;
608c44
  double p0 = i < 0 ? row[0] : i >= count ? row[count-1] : row[i]; ++i;
608c44
  double p1 = i < 0 ? row[0] : i >= count ? row[count-1] : row[i]; ++i;
608c44
  double p2 = i < 0 ? row[0] : i >= count ? row[count-1] : row[i]; ++i;
608c44
  double p3 = i < 0 ? row[0] : i >= count ? row[count-1] : row[i]; ++i;
608c44
608c44
  return cubicInterpolation(p0, p1, p2, p3, l);
608c44
}
608c44
608c44
608c44
608c44
void imgDestroy(Img *img) {
608c44
  free(img->data);
608c44
  img->data = NULL;
608c44
  img->w = img->h = 0;
608c44
}
608c44
608c44
608c44
void imgSwap(Img *imgA, Img *imgB) {
608c44
  Img imgC;
608c44
  memcpy(&imgC, imgA, sizeof(imgC));
608c44
  memcpy(imgA, imgB, sizeof(imgC));
608c44
  memcpy(imgB, &imgC, sizeof(imgC));
608c44
}
608c44
608c44
608c44
int imgInit(Img *img, int w, int h) {
608c44
  imgDestroy(img);
608c44
  if (w < 0 || h < 0) return FALSE;
608c44
  img->data = calloc(1, sizeof(double)*4*w*h);
608c44
  if (!img->data) return FALSE;
608c44
  img->w = w;
608c44
  img->h = h;
608c44
  return TRUE;
608c44
}
608c44
608c44
608c44
double* imgPixel(const Img *img, int x, int y) {
608c44
  if (!img->data) return NULL;
608c44
  if (x >= img->w) x = img->w - 1;
608c44
  if (y >= img->h) y = img->h - 1;
608c44
  if (x < 0) x = 0;
608c44
  if (y < 0) y = 0;
608c44
  return img->data + (img->w*y + x)*4;
608c44
}
608c44
608c44
608c44
double* imgNearest(const Img *img, double x, double y)
608c44
  { return imgPixel(img, (int)round(x), (int)round(y)); }
608c44
608c44
608c44
double imgCubicHCh(const Img *img, int ch, double x, int y) {
608c44
  if (!img->data) return 0;
608c44
  if (!(x > 0)) x = 0;
608c44
  if (!(x < img->w)) x = img->w;
608c44
  double xi = floor(x);
608c44
  int i = (int)xi - 1;
608c44
  double p[] = {
608c44
    imgPixel(img, i+0, y)[ch],
608c44
    imgPixel(img, i+1, y)[ch],
608c44
    imgPixel(img, i+2, y)[ch],
608c44
    imgPixel(img, i+3, y)[ch] };
608c44
  return cubicInterpolation(p[0], p[1], p[2], p[3], x - xi);
608c44
}
608c44
608c44
608c44
double imgCubicVCh(const Img *img, int ch, int x, double y) {
608c44
  if (!img->data) return 0;
608c44
  if (!(y > 0)) x = 0;
608c44
  if (!(y < img->h)) y = img->h;
608c44
  double yi = floor(y);
608c44
  int i = (int)yi - 1;
608c44
  double p[] = {
608c44
    imgPixel(img, i+0, y)[ch],
608c44
    imgPixel(img, i+1, y)[ch],
608c44
    imgPixel(img, i+2, y)[ch],
608c44
    imgPixel(img, i+3, y)[ch] };
608c44
  return cubicInterpolation(p[0], p[1], p[2], p[3], y - yi);
608c44
}
608c44
608c44
608c44
void imgCubicH(const Img *img, double x, int y, double *pix) {
608c44
  if (!img->data) { pix[0] = pix[1] = pix[2] = pix[3] = 0; return; }
608c44
  if (!(x > 0)) x = 0;
608c44
  if (!(x < img->w)) x = img->w;
608c44
  double xi = floor(x);
608c44
  double l = x - xi;
608c44
608c44
  int i = (int)xi - 1;
608c44
  double *p[] = {
608c44
    imgPixel(img, i+0, y),
608c44
    imgPixel(img, i+1, y),
608c44
    imgPixel(img, i+2, y),
608c44
    imgPixel(img, i+3, y) };
608c44
608c44
  pix[0] = cubicInterpolation(p[0][0], p[1][0], p[2][0], p[3][0], l);
608c44
  pix[1] = cubicInterpolation(p[0][1], p[1][1], p[2][1], p[3][1], l);
608c44
  pix[2] = cubicInterpolation(p[0][2], p[1][2], p[2][2], p[3][2], l);
608c44
  pix[3] = cubicInterpolation(p[0][3], p[1][3], p[2][3], p[3][3], l);
608c44
}
608c44
608c44
608c44
void imgCubicV(const Img *img, int x, double y, double *pix) {
608c44
  if (!img->data) { pix[0] = pix[1] = pix[2] = pix[3] = 0; return; }
608c44
  if (!(y > 0)) y = 0;
608c44
  if (!(y < img->h)) y = img->h;
608c44
  double yi = floor(y);
608c44
  double l = y - yi;
608c44
608c44
  int i = (int)yi - 1;
608c44
  double *p[] = {
608c44
    imgPixel(img, x, i+0),
608c44
    imgPixel(img, x, i+1),
608c44
    imgPixel(img, x, i+2),
608c44
    imgPixel(img, x, i+3) };
608c44
608c44
  pix[0] = cubicInterpolation(p[0][0], p[1][0], p[2][0], p[3][0], l);
608c44
  pix[1] = cubicInterpolation(p[0][1], p[1][1], p[2][1], p[3][1], l);
608c44
  pix[2] = cubicInterpolation(p[0][2], p[1][2], p[2][2], p[3][2], l);
608c44
  pix[3] = cubicInterpolation(p[0][3], p[1][3], p[2][3], p[3][3], l);
608c44
}
608c44
608c44
608c44
double imgCubicCh(const Img *img, int ch, double x, double y) {
608c44
  if (!img->data) return 0;
608c44
  if (!(y > 0)) y = 0;
608c44
  if (!(y < img->h)) y = img->h;
608c44
  double yi = floor(y);
608c44
  double l = y - yi;
608c44
608c44
  int i = (int)yi - 1;
608c44
  double p[] = {
608c44
    imgCubicHCh(img, ch, x, i+0),
608c44
    imgCubicHCh(img, ch, x, i+1),
608c44
    imgCubicHCh(img, ch, x, i+2),
608c44
    imgCubicHCh(img, ch, x, i+3) };
608c44
608c44
  return cubicInterpolation(p[0], p[1], p[2], p[3], l);
608c44
}
608c44
608c44
608c44
void imgCubic(const Img *img, double x, double y, double *pix) {
608c44
  if (!img->data) { pix[0] = pix[1] = pix[2] = pix[3] = 0; return; }
608c44
  if (!(y > 0)) y = 0;
608c44
  if (!(y < img->h)) y = img->h;
608c44
  double yi = floor(y);
608c44
  double l = y - yi;
608c44
608c44
  int i = (int)yi - 1;
608c44
  double p[4][4];
608c44
  imgCubicH(img, x, i+0, p[0]);
608c44
  imgCubicH(img, x, i+1, p[1]);
608c44
  imgCubicH(img, x, i+2, p[2]);
608c44
  imgCubicH(img, x, i+3, p[3]);
608c44
608c44
  pix[0] = cubicInterpolation(p[0][0], p[1][0], p[2][0], p[3][0], l);
608c44
  pix[1] = cubicInterpolation(p[0][1], p[1][1], p[2][1], p[3][1], l);
608c44
  pix[2] = cubicInterpolation(p[0][2], p[1][2], p[2][2], p[3][2], l);
608c44
  pix[3] = cubicInterpolation(p[0][3], p[1][3], p[2][3], p[3][3], l);
608c44
}
608c44
608c44
608c44
void imgFromInt(Img *img, int w, int h, const unsigned char *data) {
608c44
  imgInit(img, w, h);
608c44
  if (!img->data || !data) return;
608c44
  for(double *p = img->data, *e = p + 4*img->w*img->h; p < e; ++p)
608c44
    *p = (*data++)/255.0;
608c44
}
608c44
608c44
608c44
unsigned char* imgToInt(Img *img) {
608c44
  if (!img->data) return NULL;
608c44
  unsigned char *data = (unsigned char*)malloc(sizeof(unsigned char)*4*img->w*img->h), *dp = data;
608c44
  for(double *p = img->data, *e = p + 4*img->w*img->h; p < e; ++p)
608c44
    *dp++ = *p > 0 ? (*p < 1 ? (unsigned char)floor(*p*255.9999999) : 255) : 0;
608c44
  return data;
608c44
}
608c44