예제 #1
0
/* MapPreviewCanvas::showMap
 * Adjusts zoom and offset to show the whole map
 *******************************************************************/
void MapPreviewCanvas::showMap()
{
	// Find extents of map
	mep_vertex_t m_min(999999.0, 999999.0);
	mep_vertex_t m_max(-999999.0, -999999.0);
	for (unsigned a = 0; a < verts.size(); a++)
	{
		if (verts[a].x < m_min.x)
			m_min.x = verts[a].x;
		if (verts[a].x > m_max.x)
			m_max.x = verts[a].x;
		if (verts[a].y < m_min.y)
			m_min.y = verts[a].y;
		if (verts[a].y > m_max.y)
			m_max.y = verts[a].y;
	}

	// Offset to center of map
	double width = m_max.x - m_min.x;
	double height = m_max.y - m_min.y;
	offset_x = m_min.x + (width * 0.5);
	offset_y = m_min.y + (height * 0.5);

	// Zoom to fit whole map
	double x_scale = ((double)GetClientSize().x) / width;
	double y_scale = ((double)GetClientSize().y) / height;
	zoom = MIN(x_scale, y_scale);
	zoom *= 0.95;
}
예제 #2
0
// -----------------------------------------------------------------------------
// Adjusts zoom and offset to show the whole map
// -----------------------------------------------------------------------------
void MapPreviewCanvas::showMap()
{
	// Find extents of map
	Vertex m_min(999999.0, 999999.0);
	Vertex m_max(-999999.0, -999999.0);
	for (auto& vert : verts_)
	{
		if (vert.x < m_min.x)
			m_min.x = vert.x;
		if (vert.x > m_max.x)
			m_max.x = vert.x;
		if (vert.y < m_min.y)
			m_min.y = vert.y;
		if (vert.y > m_max.y)
			m_max.y = vert.y;
	}

	// Offset to center of map
	double width  = m_max.x - m_min.x;
	double height = m_max.y - m_min.y;
	offset_       = { m_min.x + (width * 0.5), m_min.y + (height * 0.5) };

	// Zoom to fit whole map
	double x_scale = ((double)GetClientSize().x) / width;
	double y_scale = ((double)GetClientSize().y) / height;
	zoom_          = std::min<double>(x_scale, y_scale);
	zoom_ *= 0.95;
}
예제 #3
0
 CDataContainer CIntTypeInfo::serialize() const
 {
    CDataContainer serializedData;
    if (m_min.isDefined())
       serializedData.set("min", m_min());
    if (m_max.isDefined())
       serializedData.set("max", m_max());
    if (m_step.isDefined())
       serializedData.set("step", m_step());
    return serializedData;
 }
예제 #4
0
      //! Get stabilized magnetic field.
      //! @param[in] msg magnetic field message.
      void
      updateField(const IMC::MagneticField& msg)
      {
        // Insert magnetic field into row matrix.
        Math::Matrix mf(1,3);
        mf(0) = msg.x;
        mf(1) = msg.y;
        mf(2) = msg.z;

        // Get stabilized magnetic field.
        Math::Matrix mf_stab = mf * transpose(m_dcm.toDCM());

        // Store maximum and minimum values.
        for (unsigned i = 0; i < 3; i++)
        {
          if (mf_stab(i) > m_max(i))
            m_max(i) = mf_stab(i);
          if (mf_stab(i) < m_min(i))
            m_min(i) = mf_stab(i);
        }
      }
예제 #5
0
/*
	現在の Depth, Field... を評価する。
*/
static uint Real_GetEval(void) // ret: この局面の評価, 0 は返さない。
{
	uint evals[FIELD_W_MAX];
	uint ret;
	uint index;

	if(MaxDepth <= Depth) // ? 探索の上限に達した。-> これ以上先の手は読まない。
		return GetCurrEval();

	// 現局面で決着 -> これ以上先の手は読まない。
	{
		uint winner = GetWinner();

		if(winner == 1)
			return 400000000 + 100 - Depth; // 早い勝利を高く評価

		if(winner == 2)
			return 1;
	}

	GetNextEvals(evals);

	for(index = 0; index < Field_W; index++)
		if(evals[index])
			break;

	if(index == Field_W) // 次の手が無い -> 引き分け
	{
		ret = 300000000;
	}
	else if(Depth % 2) // 相手の手番 -> (自分にとって)最悪手を選ぶ
	{
		ret = UINTMAX;

		for(index = 0; index < Field_W; index++)
			if(evals[index])
				ret = m_min(ret, evals[index]);
	}
	else // 自分の手番 -> 最善手を選ぶ
	{
		ret = 0;

		for(index = 0; index < Field_W; index++)
			if(evals[index])
				ret = m_max(ret, evals[index]);
	}
	if(ret / 100000000 == 2) // ? 未決着コース
		if(IsTaboo())
			ret -= 100000000;

	return ret;
}
예제 #6
0
파일: VDSpiral.hpp 프로젝트: kvahed/codeare
Solution VDSpiral (SpiralParams& sp) {

	GradientParams gp;

	Matrix<double>& fov = sp.fov; 
	Matrix<double>& rad = sp.rad; 
	double k_max, fov_max, dr;
	Matrix<double> r, theta;
	long n = 0;

	assert (numel(rad) >= 2);
	assert (isvec(rad) == isvec(fov));
	assert (numel(rad) == numel(fov));

	k_max   = 5.0 / sp.res;
	fov_max = m_max(fov);

	dr  = sp.shots / (fov_max);
	n   = size(fov,1)*100;
	r   = linspace<double> (0.0, k_max, n);
	
	Matrix<double> x = k_max*rad;
	fov = interp1 (x, fov, r, INTERP::LINEAR);

	dr  = sp.shots / (1500.0 * fov_max);
	n   = ceil (k_max/dr);
	x   = r;
	r   = linspace<double> (0.0, k_max, n);

	fov = interp1 (x, fov, r, INTERP::AKIMA);

	theta = cumsum ((2 * PI * dr / sp.shots) * fov);

	gp.k = Matrix<double> (numel(r), 3);

	for (size_t i = 0; i < numel(r); i++) {
		gp.k(i,0) = r[i] * cos (theta[i]);
		gp.k(i,1) = r[i] * sin (theta[i]);
	}

	gp.mgr     = sp.mgr;
	gp.msr     = sp.msr;
	gp.dt      = sp.dt;
	gp.gunits  = sp.gunits;
	gp.lunits  = sp.lunits;

	Solution s = ComputeGradient (gp);
	
	return s;

}
예제 #7
0
파일: dev_vtty.c 프로젝트: GNS3/dynamips
/* VTTY thread */
static void *vtty_thread_main(void *arg)
{
   vtty_t *vtty;
   struct timeval tv;
   int fd_max,fd_tcp,res;
   fd_set rfds;
   int i;

   for(;;) {
      VTTY_LIST_LOCK();

      /* Build the FD set */
      FD_ZERO(&rfds);
      fd_max = -1;
      for(vtty=vtty_list;vtty;vtty=vtty->next) {

          switch(vtty->type) {
              case VTTY_TYPE_TCP:

                  for(i=0;i<vtty->fd_count;i++)
                      if (vtty->fd_array[i] != -1) {
                          FD_SET(vtty->fd_array[i],&rfds);
                          if (vtty->fd_array[i] > fd_max)
                              fd_max = vtty->fd_array[i];
                      }

                  fd_tcp = fd_pool_set_fds(&vtty->fd_pool,&rfds);
                  fd_max = m_max(fd_tcp,fd_max);
                  break;

              default:
                  if (vtty->fd_array[0] != -1) {
                      FD_SET(vtty->fd_array[0],&rfds);
                      fd_max = m_max(vtty->fd_array[0],fd_max);
                  }
          }

      }
      VTTY_LIST_UNLOCK();

      /* Wait for incoming data */
      tv.tv_sec  = 0;
      tv.tv_usec = 50 * 1000;  /* 50 ms */
      res = select(fd_max+1,&rfds,NULL,NULL,&tv);

      if (res == -1) {
         if (errno != EINTR) {
            perror("vtty_thread: select");
         }
         continue;
      }

      /* Examine active FDs and call user handlers */
      VTTY_LIST_LOCK();
      for(vtty=vtty_list;vtty;vtty=vtty->next) {

         switch(vtty->type) {
            case VTTY_TYPE_TCP:

               /* check incoming connection */
               for(i=0;i<vtty->fd_count;i++) {
                   
                   if (vtty->fd_array[i] == -1)
                       continue;
                   
                   if (!FD_ISSET(vtty->fd_array[i],&rfds))
                       continue;
                   
                   vtty_tcp_conn_accept(vtty, i);
               }

               /* check established connection */
               fd_pool_check_input(&vtty->fd_pool,&rfds,vtty_tcp_input,vtty);
               break;
      
            /* Term, Serial */
            default:
               if (vtty->fd_array[0] != -1 && FD_ISSET(vtty->fd_array[0],&rfds)) {
                  vtty_read_and_store(vtty,&vtty->fd_array[0]);
                  vtty->input_pending = TRUE;
               }
         }
         
         if (vtty->input_pending) {
            if (vtty->read_notifier != NULL)
               vtty->read_notifier(vtty);

            vtty->input_pending = FALSE;
         }

         /* Flush any pending output */
         if (!vtty->managed_flush)
            vtty_flush(vtty);
      }
      VTTY_LIST_UNLOCK();
   }
   
   return NULL;
}
예제 #8
0
// Main
int main(int argc, char ** argv) {

	// Choose the best GPU in case there are multiple available
	choose_GPU();

	// Keep track of the start time of the program
	long long program_start_time = get_time();
	
	if (argc !=3){
	fprintf(stderr, "usage: %s <input file> <number of frames to process>", argv[0]);
	exit(1);
	}
	
	// Let the user specify the number of frames to process
	int num_frames = atoi(argv[2]);
	
	// Open video file
	char *video_file_name = argv[1];
	
	avi_t *cell_file = AVI_open_input_file(video_file_name, 1);
	if (cell_file == NULL)	{
		AVI_print_error("Error with AVI_open_input_file");
		return -1;
	}
	
	int i, j, *crow, *ccol, pair_counter = 0, x_result_len = 0, Iter = 20, ns = 4, k_count = 0, n;
	MAT *cellx, *celly, *A;
	double *GICOV_spots, *t, *G, *x_result, *y_result, *V, *QAX_CENTERS, *QAY_CENTERS;
	double threshold = 1.8, radius = 10.0, delta = 3.0, dt = 0.01, b = 5.0;
	
	// Extract a cropped version of the first frame from the video file
	MAT *image_chopped = get_frame(cell_file, 0, 1, 0);
	printf("Detecting cells in frame 0\n");
	
	// Get gradient matrices in x and y directions
	MAT *grad_x = gradient_x(image_chopped);
	MAT *grad_y = gradient_y(image_chopped);
	
	// Allocate for gicov_mem and strel
	gicov_mem = (float*) malloc(sizeof(float) * grad_x->m * grad_y->n);
	strel = (float*) malloc(sizeof(float) * strel_m * strel_n);

	m_free(image_chopped);

	int grad_m = grad_x->m;
	int grad_n = grad_y->n;
	
#pragma acc data create(sin_angle,cos_angle,theta,tX,tY) \
	create(gicov_mem[0:grad_x->m*grad_y->n])
{
	// Precomputed constants on GPU
	compute_constants();

	// Get GICOV matrices corresponding to image gradients
	long long GICOV_start_time = get_time();
	MAT *gicov = GICOV(grad_x, grad_y);
	long long GICOV_end_time = get_time();

	// Dilate the GICOV matrices
	long long dilate_start_time = get_time();
	MAT *img_dilated = dilate(gicov);
	long long dilate_end_time = get_time();
} /* end acc data */
	
	// Find possible matches for cell centers based on GICOV and record the rows/columns in which they are found
	pair_counter = 0;
	crow = (int *) malloc(gicov->m * gicov->n * sizeof(int));
	ccol = (int *) malloc(gicov->m * gicov->n * sizeof(int));
	for(i = 0; i < gicov->m; i++) {
		for(j = 0; j < gicov->n; j++) {
			if(!double_eq(m_get_val(gicov,i,j), 0.0) && double_eq(m_get_val(img_dilated,i,j), m_get_val(gicov,i,j)))
			{
				crow[pair_counter]=i;
				ccol[pair_counter]=j;
				pair_counter++;
			}
		}
	}

	GICOV_spots = (double *) malloc(sizeof(double) * pair_counter);
	for(i = 0; i < pair_counter; i++)
		GICOV_spots[i] = sqrt(m_get_val(gicov, crow[i], ccol[i]));
	
	G = (double *) calloc(pair_counter, sizeof(double));
	x_result = (double *) calloc(pair_counter, sizeof(double));
	y_result = (double *) calloc(pair_counter, sizeof(double));
	
	x_result_len = 0;
	for (i = 0; i < pair_counter; i++) {
		if ((crow[i] > 29) && (crow[i] < BOTTOM - TOP + 39)) {
			x_result[x_result_len] = ccol[i];
			y_result[x_result_len] = crow[i] - 40;
			G[x_result_len] = GICOV_spots[i];
			x_result_len++;
		}
	}
	
	// Make an array t which holds each "time step" for the possible cells
	t = (double *) malloc(sizeof(double) * 36);
	for (i = 0; i < 36; i++) {
		t[i] = (double)i * 2.0 * PI / 36.0;
	}
	
	// Store cell boundaries (as simple circles) for all cells
	cellx = m_get(x_result_len, 36);
	celly = m_get(x_result_len, 36);
	for(i = 0; i < x_result_len; i++) {
		for(j = 0; j < 36; j++) {
			m_set_val(cellx, i, j, x_result[i] + radius * cos(t[j]));
			m_set_val(celly, i, j, y_result[i] + radius * sin(t[j]));
		}
	}
	
	A = TMatrix(9,4);
	V = (double *) malloc(sizeof(double) * pair_counter);
	QAX_CENTERS = (double * )malloc(sizeof(double) * pair_counter);
	QAY_CENTERS = (double *) malloc(sizeof(double) * pair_counter);
	memset(V, 0, sizeof(double) * pair_counter);
	memset(QAX_CENTERS, 0, sizeof(double) * pair_counter);
	memset(QAY_CENTERS, 0, sizeof(double) * pair_counter);

	// For all possible results, find the ones that are feasibly leukocytes and store their centers
	k_count = 0;
	for (n = 0; n < x_result_len; n++) {
		if ((G[n] < -1 * threshold) || G[n] > threshold) {
			MAT * x, *y;
			VEC * x_row, * y_row;
			x = m_get(1, 36);
			y = m_get(1, 36);

			x_row = v_get(36);
			y_row = v_get(36);

			// Get current values of possible cells from cellx/celly matrices
			x_row = get_row(cellx, n, x_row);
			y_row = get_row(celly, n, y_row);
			uniformseg(x_row, y_row, x, y);

			// Make sure that the possible leukocytes are not too close to the edge of the frame
			if ((m_min(x) > b) && (m_min(y) > b) && (m_max(x) < cell_file->width - b) && (m_max(y) < cell_file->height - b)) {
				MAT * Cx, * Cy, *Cy_temp, * Ix1, * Iy1;
				VEC  *Xs, *Ys, *W, *Nx, *Ny, *X, *Y;
				Cx = m_get(1, 36);
				Cy = m_get(1, 36);
				Cx = mmtr_mlt(A, x, Cx);
				Cy = mmtr_mlt(A, y, Cy);
				
				Cy_temp = m_get(Cy->m, Cy->n);
				
				for (i = 0; i < 9; i++)
					m_set_val(Cy, i, 0, m_get_val(Cy, i, 0) + 40.0);
					
				// Iteratively refine the snake/spline
				for (i = 0; i < Iter; i++) {
					int typeofcell;
					
					if(G[n] > 0.0) typeofcell = 0;
					else typeofcell = 1;
					
					splineenergyform01(Cx, Cy, grad_x, grad_y, ns, delta, 2.0 * dt, typeofcell);
				}
				
				X = getsampling(Cx, ns);
				for (i = 0; i < Cy->m; i++)
					m_set_val(Cy_temp, i, 0, m_get_val(Cy, i, 0) - 40.0);
				Y = getsampling(Cy_temp, ns);
				
				Ix1 = linear_interp2(grad_x, X, Y);
				Iy1 = linear_interp2(grad_x, X, Y);
				Xs = getfdriv(Cx, ns);
				Ys = getfdriv(Cy, ns);
				
				Nx = v_get(Ys->dim);
				for (i = 0; i < Ys->dim; i++)
					v_set_val(Nx, i, v_get_val(Ys, i) / sqrt(v_get_val(Xs, i)*v_get_val(Xs, i) + v_get_val(Ys, i)*v_get_val(Ys, i)));
					
				Ny = v_get(Xs->dim);
				for (i = 0; i < Xs->dim; i++)
					v_set_val(Ny, i, -1.0 * v_get_val(Xs, i) / sqrt(v_get_val(Xs, i)*v_get_val(Xs, i) + v_get_val(Ys, i)*v_get_val(Ys, i)));
					
				W = v_get(Nx->dim);
				for (i = 0; i < Nx->dim; i++)
					v_set_val(W, i, m_get_val(Ix1, 0, i) * v_get_val(Nx, i) + m_get_val(Iy1, 0, i) * v_get_val(Ny, i));
					
				V[n] = mean(W) / std_dev(W);
				
				// Find the cell centers by computing the means of X and Y values for all snaxels of the spline contour
				QAX_CENTERS[k_count] = mean(X);
				QAY_CENTERS[k_count] = mean(Y) + TOP;
				
				k_count++;
				
				// Free memory
				v_free(W);
				v_free(Ny);
				v_free(Nx);
				v_free(Ys);
				v_free(Xs);
				m_free(Iy1);
				m_free(Ix1);
				v_free(Y);
				v_free(X);
				m_free(Cy_temp);
				m_free(Cy);
				m_free(Cx);				
			}

			// Free memory
			v_free(y_row);
			v_free(x_row);
			m_free(y);
			m_free(x);
		}
	}
	
	// Free memory
	free(gicov_mem);
	free(strel);
	free(V);
	free(ccol);
	free(crow);
	free(GICOV_spots);
	free(t);
	free(G);
	free(x_result);
	free(y_result);
	m_free(A);
	m_free(celly);
	m_free(cellx);
	m_free(img_dilated);
	m_free(gicov);
	m_free(grad_y);
	m_free(grad_x);
	
	// Report the total number of cells detected
	printf("Cells detected: %d\n\n", k_count);
	
	// Report the breakdown of the detection runtime
	printf("Detection runtime\n");
	printf("-----------------\n");
	printf("GICOV computation: %.5f seconds\n", ((float) (GICOV_end_time - GICOV_start_time)) / (1000*1000));
	printf("   GICOV dilation: %.5f seconds\n", ((float) (dilate_end_time - dilate_start_time)) / (1000*1000));
	printf("            Total: %.5f seconds\n", ((float) (get_time() - program_start_time)) / (1000*1000));
	
	// Now that the cells have been detected in the first frame,
	//  track the ellipses through subsequent frames
	if (num_frames > 1) printf("\nTracking cells across %d frames\n", num_frames);
	else                printf("\nTracking cells across 1 frame\n");
	long long tracking_start_time = get_time();
	int num_snaxels = 20;
	ellipsetrack(cell_file, QAX_CENTERS, QAY_CENTERS, k_count, radius, num_snaxels, num_frames);
	printf("           Total: %.5f seconds\n", ((float) (get_time() - tracking_start_time)) / (float) (1000*1000*num_frames));	
	
	// Report total program execution time
    printf("\nTotal application run time: %.5f seconds\n", ((float) (get_time() - program_start_time)) / (1000*1000));

	return 0;
}
예제 #9
0
/* MapPreviewCanvas::createImage
 * Draws the map in an image
 * TODO: Factorize code with normal draw() and showMap() functions.
 * TODO: Find a way to generate an arbitrary-sized image through
 * tiled rendering.
 *******************************************************************/
void MapPreviewCanvas::createImage(ArchiveEntry& ae, int width, int height)
{
	// Find extents of map
	mep_vertex_t m_min(999999.0, 999999.0);
	mep_vertex_t m_max(-999999.0, -999999.0);
	for (unsigned a = 0; a < verts.size(); a++)
	{
		if (verts[a].x < m_min.x)
			m_min.x = verts[a].x;
		if (verts[a].x > m_max.x)
			m_max.x = verts[a].x;
		if (verts[a].y < m_min.y)
			m_min.y = verts[a].y;
		if (verts[a].y > m_max.y)
			m_max.y = verts[a].y;
	}
	double mapwidth = m_max.x - m_min.x;
	double mapheight = m_max.y - m_min.y;

	if (width == 0) width = -5;
	if (height == 0) height = -5;
	if (width < 0)
		width = mapwidth / abs(width);
	if (height < 0)
		height = mapheight / abs(height);

	// Setup colours
	rgba_t col_save_background = ColourConfiguration::getColour("map_image_background");
	rgba_t col_save_line_1s = ColourConfiguration::getColour("map_image_line_1s");
	rgba_t col_save_line_2s = ColourConfiguration::getColour("map_image_line_2s");
	rgba_t col_save_line_special = ColourConfiguration::getColour("map_image_line_special");
	rgba_t col_save_line_macro = ColourConfiguration::getColour("map_image_line_macro");

	// Setup OpenGL rigmarole
	GLuint texID, fboID;
	if (GLEW_ARB_framebuffer_object)
	{
		glGenTextures(1, &texID);
		glBindTexture(GL_TEXTURE_2D, texID);
		// We don't use mipmaps, but OpenGL will refuse to attach
		// the texture to the framebuffer if they are not present
		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
		glBindTexture(GL_TEXTURE_2D, 0);
		glGenFramebuffersEXT(1, &fboID);
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texID, 0);
		GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	}

	glViewport(0, 0, width, height);

	// Setup the screen projection
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, width, 0, height, -1, 1);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// Clear
	glClearColor(((double)col_save_background.r)/255.f, ((double)col_save_background.g)/255.f,
	             ((double)col_save_background.b)/255.f, ((double)col_save_background.a)/255.f);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	// Translate to inside of pixel (otherwise inaccuracies can occur on certain gl implementations)
	if (OpenGL::accuracyTweak())
		glTranslatef(0.375f, 0.375f, 0);

	// Zoom/offset to show full map
	// Offset to center of map
	offset_x = m_min.x + (mapwidth * 0.5);
	offset_y = m_min.y + (mapheight * 0.5);

	// Zoom to fit whole map
	double x_scale = ((double)width) / mapwidth;
	double y_scale = ((double)height) / mapheight;
	zoom = MIN(x_scale, y_scale);
	zoom *= 0.95;

	// Translate to middle of canvas
	glTranslated(width>>1, height>>1, 0);

	// Zoom
	glScaled(zoom, zoom, 1);

	// Translate to offset
	glTranslated(-offset_x, -offset_y, 0);

	// Setup drawing
	glDisable(GL_TEXTURE_2D);
	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
	glLineWidth(map_image_thickness);
	glEnable(GL_LINE_SMOOTH);

	// Draw lines
	for (unsigned a = 0; a < lines.size(); a++)
	{
		mep_line_t line = lines[a];

		// Check ends
		if (line.v1 >= verts.size() || line.v2 >= verts.size())
			continue;

		// Get vertices
		mep_vertex_t v1 = verts[lines[a].v1];
		mep_vertex_t v2 = verts[lines[a].v2];

		// Set colour
		if (line.special)
			OpenGL::setColour(col_save_line_special);
		else if (line.macro)
			OpenGL::setColour(col_save_line_macro);
		else if (line.twosided)
			OpenGL::setColour(col_save_line_2s);
		else
			OpenGL::setColour(col_save_line_1s);

		// Draw line
		glBegin(GL_LINES);
		glVertex2d(v1.x, v1.y);
		glVertex2d(v2.x, v2.y);
		glEnd();
	}

	glLineWidth(1.0f);
	glDisable(GL_LINE_SMOOTH);

	uint8_t* ImageBuffer = new uint8_t[width * height * 4];
	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ImageBuffer);

	if (GLEW_ARB_framebuffer_object)
	{
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		glDeleteTextures( 1, &texID );
		glDeleteFramebuffersEXT( 1, &fboID );
	}
	SImage img;
	img.setImageData(ImageBuffer, width, height, RGBA);
	img.mirror(true);
	MemChunk mc;
	SIFormat::getFormat("png")->saveImage(img, mc);
	ae.importMemChunk(mc);
}