⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image_filters.cpp

📁 一个开源的Flash 播放器,可以在Windows/Linux 上运行
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	tmp = image::create_rgb(out_width, in_window_h);
	xscale = (float) (out_width - 1) / in_width;
	yscale = (float) (out_height - 1) / in_height;

	// xxxx protect against division by 0
	if (yscale == 0) { yscale = 1.0f; }
	if (xscale == 0) { xscale = 1.0f; }

	/* pre-calculate filter contributions for a row */
	contrib.resize(tmp->m_width);
	if(xscale < 1.0f) {
		width = support / xscale;
		fscale = 1.0f / xscale;
		for (i = 0; i < tmp->m_width; ++i) {
			contrib[i].resize(0);

			center = (float) i / xscale;
			left = int(ceilf(center - width));
			right = int(floorf(center + width));
			for (j = left; j <= right; ++j) {
				weight = center - (float) j;
				weight = (*filter_function)(weight / fscale) / fscale;
				n = iclamp(j, 0, in_window_w - 1);
				contrib[i].push_back(CONTRIB(n, weight));
			}
		}
	} else {
		for (i = 0; i < tmp->m_width; ++i) {
			contrib[i].resize(0);
			center = (float) i / xscale;
			left = int(ceilf(center - support));
			right = int(floorf(center + support));
			for(j = left; j <= right; ++j) {
				weight = center - (float) j;
				weight = (*filter_function)(weight);
				n = iclamp(j, 0, in_window_w - 1);
				contrib[i].push_back(CONTRIB(n, weight));
			}
		}
	}

	/* apply filter to zoom horizontally from src to tmp */
	raster = (Uint8*) my_calloc(in_window_w, 3);
	for (k = 0; k < tmp->m_height; ++k) {
		get_row(raster, in, int(floorf(in_x0)), in_window_w, k);
		for (i = 0; i < tmp->m_width; ++i) {
			float	red = 0.0f;
			float	green = 0.0f;
			float	blue = 0.0f;
			for(j = 0; j < contrib[i].size(); ++j) {
				int	pixel = contrib[i][j].pixel;
				red	+= raster[pixel * 3 + 0] * contrib[i][j].weight;
				green	+= raster[pixel * 3 + 1] * contrib[i][j].weight;
				blue	+= raster[pixel * 3 + 2] * contrib[i][j].weight;
			}
			put_pixel(tmp, i, k, red, green, blue);
		}
	}
	my_cfree(raster);

	contrib.resize(out_height);

	if (yscale < 1.0f) {
		width = support / yscale;
		fscale = 1.0f / yscale;
		for (i = 0; i < out_height; ++i) {
			contrib[i].resize(0);

			center = (float) i / yscale;
			left = int(ceilf(center - width));
			right = int(floorf(center + width));
			for (j = left; j <= right; ++j) {
				weight = center - (float) j;
				weight = (*filter_function)(weight / fscale) / fscale;
				n = iclamp(j, 0, tmp->m_height - 1);
				contrib[i].push_back(CONTRIB(n, weight));
			}
		}
	} else {
		for (i = 0; i < out_height; ++i) {
			contrib[i].resize(0);
			center = (float) i / yscale;
			left = int(ceilf(center - support));
			right = int(floorf(center + support));
			for(j = left; j <= right; ++j) {
				weight = center - (float) j;
				weight = (*filter_function)(weight);
				n = iclamp(j, 0, tmp->m_height - 1);
				contrib[i].push_back(CONTRIB(n, weight));
			}
		}
	}

	/* apply filter to zoom vertically from tmp to dst */
	raster = (Uint8*) my_calloc(tmp->m_height, 3);
	for (k = 0; k < tmp->m_width; ++k) {
		get_column(raster, tmp, k);
		for (i = 0; i < out_height; ++i) {
			float	red = 0.0f;
			float	green = 0.0f;
			float	blue = 0.0f;
			for (j = 0; j < contrib[i].size(); ++j) {
				int	pixel = contrib[i][j].pixel;
				red	+= raster[pixel * 3 + 0] * contrib[i][j].weight;
				green	+= raster[pixel * 3 + 1] * contrib[i][j].weight;
				blue	+= raster[pixel * 3 + 2] * contrib[i][j].weight;
			}
			put_pixel(out, k + out_x0, i + out_y0, red, green, blue);
		}
	}
	my_cfree(raster);

	contrib.resize(0);

	delete tmp;
}


void	resample(image::rgba* out, int out_x0, int out_y0, int out_x1, int out_y1,
		 image::rgba* in, float in_x0, float in_y0, float in_x1, float in_y1)
// Rescale the specified portion of the input image into the specified
// portion of the output image.  Coordinates are *inclusive*.
//
// Same as above, but with an alpha channel.
{
	assert(out_x0 <= out_x1);
	assert(out_y0 <= out_y1);
	assert(out_x0 >= 0 && out_x0 < out->m_width);
	assert(out_x1 >= 0 && out_x1 < out->m_width);
	assert(out_y0 >= 0 && out_y0 < out->m_height);
	assert(out_y1 >= 0 && out_y1 < out->m_height);

	float	(*filter_function)(float);
	float	support;

	// Pick a filter function & support.
	assert(default_type >= FILTER0 && default_type < FILTER_COUNT);
	filter_function = filter_table[default_type].filter_function;
	support = filter_table[default_type].support;


	image::rgba*	tmp;		/* intermediate image */
	float	xscale, yscale;		/* zoom scale factors */
	int i, j, k;			/* loop variables */
	int n;				/* pixel number */
	float center; int left, right;	/* filter calculation variables */
	float width, fscale, weight;	/* filter calculation variables */
	Uint8*	raster;			/* a row or column of pixels */

	array< array<CONTRIB> >	contrib;

	int	out_width = out_x1 - out_x0 + 1;
	int	out_height = out_y1 - out_y0 + 1;
	assert(out_width > 0);
	assert(out_height > 0);

	float	in_width = in_x1 - in_x0;
	float	in_height = in_y1 - in_y0;
	assert(in_width > 0);
	assert(in_height > 0);

	int	in_window_w = int(ceilf(in_x1) - floorf(in_x0) + 1);
	int	in_window_h = int(ceilf(in_y1) - floorf(in_y0) + 1);

	/* create intermediate image to hold horizontal zoom */
	tmp = image::create_rgba(out_width, in_window_h);
	xscale = (float) (out_width - 1) / in_width;
	yscale = (float) (out_height - 1) / in_height;

	// xxxx protect against division by 0
	if (yscale == 0) { yscale = 1.0f; }
	if (xscale == 0) { xscale = 1.0f; }

	/* pre-calculate filter contributions for a row */
	contrib.resize(tmp->m_width);
	if(xscale < 1.0f) {
		width = support / xscale;
		fscale = 1.0f / xscale;
		for (i = 0; i < tmp->m_width; ++i) {
			contrib[i].resize(0);

			center = (float) i / xscale;
			left = int(ceilf(center - width));
			right = int(floorf(center + width));
			for (j = left; j <= right; ++j) {
				weight = center - (float) j;
				weight = (*filter_function)(weight / fscale) / fscale;
				n = iclamp(j, 0, in_window_w - 1);
				contrib[i].push_back(CONTRIB(n, weight));
			}
		}
	} else {
		for (i = 0; i < tmp->m_width; ++i) {
			contrib[i].resize(0);
			center = (float) i / xscale;
			left = int(ceilf(center - support));
			right = int(floorf(center + support));
			for(j = left; j <= right; ++j) {
				weight = center - (float) j;
				weight = (*filter_function)(weight);
				n = iclamp(j, 0, in_window_w - 1);
				contrib[i].push_back(CONTRIB(n, weight));
			}
		}
	}

	/* apply filter to zoom horizontally from src to tmp */
	raster = (Uint8*) my_calloc(in_window_w, 4);
	for (k = 0; k < tmp->m_height; ++k) {
		get_row(raster, in, int(floorf(in_x0)), in_window_w, k);
		for (i = 0; i < tmp->m_width; ++i) {
			float	red = 0.0f;
			float	green = 0.0f;
			float	blue = 0.0f;
			float	alpha = 0.0f;
			for(j = 0; j < contrib[i].size(); ++j) {
				int	pixel = contrib[i][j].pixel;
				red	+= raster[pixel * 4 + 0] * contrib[i][j].weight;
				green	+= raster[pixel * 4 + 1] * contrib[i][j].weight;
				blue	+= raster[pixel * 4 + 2] * contrib[i][j].weight;
				alpha	+= raster[pixel * 4 + 3] * contrib[i][j].weight;
			}
			put_pixel(tmp, i, k, red, green, blue, alpha);
		}
	}
	my_cfree(raster);

	contrib.resize(out_height);

	if (yscale < 1.0f) {
		width = support / yscale;
		fscale = 1.0f / yscale;
		for (i = 0; i < out_height; ++i) {
			contrib[i].resize(0);

			center = (float) i / yscale;
			left = int(ceilf(center - width));
			right = int(floorf(center + width));
			for (j = left; j <= right; ++j) {
				weight = center - (float) j;
				weight = (*filter_function)(weight / fscale) / fscale;
				n = iclamp(j, 0, tmp->m_height - 1);
				contrib[i].push_back(CONTRIB(n, weight));
			}
		}
	} else {
		for (i = 0; i < out_height; ++i) {
			contrib[i].resize(0);
			center = (float) i / yscale;
			left = int(ceilf(center - support));
			right = int(floorf(center + support));
			for(j = left; j <= right; ++j) {
				weight = center - (float) j;
				weight = (*filter_function)(weight);
				n = iclamp(j, 0, tmp->m_height - 1);
				contrib[i].push_back(CONTRIB(n, weight));
			}
		}
	}

	/* apply filter to zoom vertically from tmp to dst */
	raster = (Uint8*) my_calloc(tmp->m_height, 4);
	for (k = 0; k < tmp->m_width; ++k) {
		get_column(raster, tmp, k);
		for (i = 0; i < out_height; ++i) {
			float	red = 0.0f;
			float	green = 0.0f;
			float	blue = 0.0f;
			float	alpha = 0.0f;
			for (j = 0; j < contrib[i].size(); ++j) {
				int	pixel = contrib[i][j].pixel;
				red	+= raster[pixel * 4 + 0] * contrib[i][j].weight;
				green	+= raster[pixel * 4 + 1] * contrib[i][j].weight;
				blue	+= raster[pixel * 4 + 2] * contrib[i][j].weight;
				alpha	+= raster[pixel * 4 + 3] * contrib[i][j].weight;
			}
			put_pixel(out, k + out_x0, i + out_y0, red, green, blue, alpha);
		}
	}
	my_cfree(raster);

	contrib.resize(0);

	delete tmp;
}



// tulrich: some interesting scaling code from Vitaly.  Looks like a
// fast bilinear scale using fixed point.  I haven't validated this
// myself.  Note: I would see about losing the sax & say arrays, and
// fold that stuff directly into the pixel loops, to get rid of the
// mallocs.

void	zoom(image::rgba* src, image::rgba* dst)
{
  typedef struct
  {
    Uint8 r;
    Uint8 g;
    Uint8 b;
    Uint8 a;
  }
  rgba;

  int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2;
  rgba *c00, *c01, *c10, *c11, *sp, *csp, *dp;
  int sgap, dgap;

  /* For interpolation: assume source dimension is one pixel */
  /* smaller to avoid overflow on right and bottom edge.     */
  sx = (int) (65536.0 * (float) (src->m_width - 1) / (float) dst->m_width);
	sy = (int) (65536.0 * (float) (src->m_height - 1) / (float) dst->m_height);

  /* Allocate memory for row increments */
  sax = (int*) malloc ((dst->m_width + 1) * sizeof (Uint32));
  say = (int*) malloc ((dst->m_height + 1) * sizeof (Uint32));

  /* Precalculate row increments */
  csx = 0;
  csax = sax;
  for (x = 0; x <= dst->m_width; x++)
  {
    *csax = csx;
    csax++;
    csx &= 0xffff;
    csx += sx;
  }
  csy = 0;
  csay = say;
  for (y = 0; y <= dst->m_height; y++)
  {
    *csay = csy;
    csay++;
    csy &= 0xffff;
    csy += sy;
  }

  /* Pointer setup */
  sp = csp = (rgba *) src->m_data;
  dp = (rgba *) dst->m_data;
  sgap = src->m_pitch - src->m_width * 4;
  dgap = dst->m_pitch - dst->m_width * 4;

	/* Interpolating Zoom */
	/* Scan destination */
  csay = say;
  for (y = 0; y < dst->m_height; y++)
	{
	  /* Setup color source pointers */
	  c00 = csp;
	  c01 = csp;
	  c01++;
	  c10 = (rgba *) ((Uint8 *) csp + src->m_pitch);
	  c11 = c10;
	  c11++;
	  csax = sax;
	  for (x = 0; x < dst->m_width; x++)
		{
			/* ABGR ordering */
	    /* Interpolate colors */
	    ex = (*csax & 0xffff);
	    ey = (*csay & 0xffff);
	    t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
	    t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
	    dp->r = (((t2 - t1) * ey) >> 16) + t1;
	    t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
	    t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
	    dp->g = (((t2 - t1) * ey) >> 16) + t1;
	    t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
	    t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
	    dp->b = (((t2 - t1) * ey) >> 16) + t1;
	    t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
	    t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
	    dp->a = (((t2 - t1) * ey) >> 16) + t1;

			/* Advance source pointers */
      csax++;
      int sstep = (*csax >> 16);
      c00 += sstep;
      c01 += sstep;
      c10 += sstep;
      c11 += sstep;
      /* Advance destination pointer */
      dp++;
    }
	  /* Advance source pointer */
		csay++;
	  csp = (rgba *) ((Uint8 *) csp + (*csay >> 16) * src->m_pitch);
  	/* Advance destination pointers */
	  dp = (rgba *) ((Uint8 *) dp + dgap);
	}

  /* Remove temp arrays */
  free (sax);
  free (say);
}



} // end namespace image



// Local Variables:
// mode: C++
// c-basic-offset: 8 
// tab-width: 8
// indent-tabs-mode: t
// End:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -