예제 #1
0
int graphics_worker_thread(graphics_worker_arg *arg){
    graphics_state *state = arg->state;
    int x0 = state->worker_pixel_ranges[4*arg->i];
    int y0 = state->worker_pixel_ranges[4*arg->i + 1];
    int x1 = state->worker_pixel_ranges[4*arg->i + 2];
    int y1 = state->worker_pixel_ranges[4*arg->i + 3];

    /* raytrace */
    while(1){
        SDL_SemWait(state->sema_start_render);

        int x, y;
        for(y = y0; y < y1; y++) 
        {
            int ytimesw = y * state->width;
            for(x = x0; x < x1; x++) 
            {
                if(!state->stencil[x + ytimesw]){
                    set_pixel(state, x, ytimesw, 0, 0, 0);
                    continue;
                }

                f3 color = graphics_render_pixel(state, x, y);
                set_pixel(state, x, ytimesw, 
                    (Uint8)(color.x*255.9f),
                    (Uint8)(color.y*255.9f),
                    (Uint8)(color.z*255.9f));
            }
        }

        /* let the main thread know we're done rendering */
        SDL_SemPost(state->sema_finish_render);
    }
    return 0;
}
예제 #2
0
  void PixelMap::load(const Image &image)
  {
    clear();

    size = image.getSize();

    map = new u8*[size.getHeight()];

    for(int y = 0; y < size.getHeight(); y++)
    {
      int linelength;

      linelength = size.getWidth()%8 == 0 ? size.getWidth()/8 : size.getWidth()/8 + 1;

      map[y] = new u8[linelength];
        memset(map[y], 0, sizeof(*map[y]) * linelength);

      for(int x = 0; x < size.getWidth(); x++)
      {
        if(!image.hasColorkey())
          set_pixel(x, y, 1);
        else if(image.getPixel(IntPoint(x, y)) != image.getColorkey())
          set_pixel(x, y, 1);
      }
    }

  }
예제 #3
0
void draw_line(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2) {
	if (x1 == x2) {
		// Draw vertical line
		for (int i = y1; (y2 > y1) ? i <= y2 : i >= y2; (y2 > y1) ? i++ : i-- ) {
			set_pixel(x1, i, 1);
		}
	} else if (y1 == y2) {
		// Draw horizontal line
		for (int i = x1; (x2 > x1) ? i <= x2 : i >= x2; (x2 > x1) ? i++ : i-- ) {
			set_pixel(i, y1, 1);
		}
	} else {
		// Get Bresenhaming...
		float dx = x2-x1;
		float dy = y2-y1;
		float err = 0.0;
		float derr = ABS(dy/dx);

		for (int x = x1, y = y1; (dx > 0) ? x<=x2 : x>=x2; (dx > 0) ? x++ : x--) {
			set_pixel(x, y, 1);
			err += derr;
			while (err >= 0.5 && ((dy > 0) ? y<=y2 : y>=y2) ) {
				set_pixel(x, y, 1);
				y += (dy > 0) - (dy < 0);
				err -= 1.0;
			}
		}
	}
}
예제 #4
0
int main(int argc, char* argv[])
{
	create_image_world();
	
	int image = create_image(100, 100);
	
	for(int x = 0; x < 100; x++)
	{
		for(int y = 0; y < 100; y++)
		{
			if (x == y)
			{
				set_pixel(image, x, y, 255, 0, 0, 255);
			}
			else if (x+y == 100)
			{
				set_pixel(image, x, y, 255, 255, 0, 0);
			}
			else
			{
				set_pixel(image, x, y, 255, 0, 255, 0);
			}
		}
	}
	
	put_image(image, get_screen_width()/2-get_image_width(image)/2, get_screen_height()/2-get_image_height(image)/2);
	
	return p1world_shutdown();	
}
예제 #5
0
void generic_expand_bitmap(u32 x, u32 y, u32 width, u32 height, const u8 *data,
			   u32 pitch, pixel_t pixel0, pixel_t pixel1)
{
    u32 w, x0;
    const u8 *data0;
    int i;
    u8 bits;

    while (height--) {
	w = width;
	x0 = x;
	data0 = data;
	while (w > 7) {
	    bits = *data0++;
	    for (i = 0; i < 8; i++, bits <<= 1)
		set_pixel(x0++, y, bits & 0x80 ? pixel1 : pixel0);
	    w -= 8;
	}
	if (w > 0) {
	    bits = *data0++;
	    while (w-- > 0) {
		set_pixel(x0++, y, bits & 0x80 ? pixel1 : pixel0);
		bits <<= 1;
	    }
	}
	y++;
	data += pitch;
    }
}
예제 #6
0
void draw_box(unsigned char box_num, unsigned char draw_open) {
    // Figure out box information
    unsigned char c_x, c_y, min_x, max_x, min_y, max_y;
    c_x = LCD_X * (box_num%BOXES_W + 0.5f) / ((float) BOXES_W);
    c_y = LCD_Y * (box_num/BOXES_W + 0.5f) / ((float) BOXES_H);
    min_x = c_x-BOX_RADIUS;
    max_x = c_x+BOX_RADIUS;
    min_y = c_y-BOX_RADIUS;
    max_y = c_y+BOX_RADIUS;

    // Draw the open or closed box
    if (draw_open) {
        // Draw the outlined box
        for (unsigned char x=min_x; x<=max_x; x++) {
            for (unsigned char y=min_y; y<=max_y; y++) {
                set_pixel(x, y, (x==min_x || x==max_x || y==min_y || y==max_y) ? 1 : 0);
            }
        }

        // Draw the character
        draw_char(c_x-2, c_y-3, (is_gold[box_num]) ? '$' : 'X');
    } else {
        // Draw the filled box
        for (unsigned char x=min_x; x<=max_x; x++) {
            for (unsigned char y=min_y; y<=max_y; y++) {
                set_pixel(x, y, 1);
            }
        }
    }
}
예제 #7
0
void generic_copy_rect(u32 dx, u32 dy, u32 width, u32 height, u32 sx, u32 sy)
{
    u32 w, dx0, sx0;

    if (dy > sy || (dy == sy && dx > sx)) {
	dx += width;
	dy += height;
	sx += width;
	sy += height;
	while (height--) {
	    dy--;
	    sy--;
	    for (w = width, dx0 = dx, sx0 = sx; w > 0; w--) {
		dx0--;
		sx0--;
		set_pixel(dx0, dy, get_pixel(sx0, sy));
	    }
	}
    } else {
	while (height--) {
	    for (w = width, dx0 = dx, sx0 = sx; w > 0; w--) {
		set_pixel(dx0, dy, get_pixel(sx0, sy));
		dx0++;
		sx0++;
	    }
	    dy++;
	    sy++;
	}
    }
}
예제 #8
0
void draw_label(image a, int r, int c, image label, image prob_label, const float *rgb)
{
    float ratio = (float) label.w / label.h;
    int h = label.h;
    int w = ratio * h;
    image rl = resize_image(label, w, h);
    if (r - h >= 0) r = r - h;
    float ratiop = (float) prob_label.w / prob_label.h;
    int hp = prob_label.h;
    int wp = ratiop * hp;
    image rpl = resize_image(prob_label, wp, hp);

    int i, j, k;
    for(j = 0; j < h && j + r < a.h; ++j){
        for(i = 0; i < w && i + c < a.w; ++i){
            for(k = 0; k < label.c; ++k){
                float val = get_pixel(rl, i, j, k);
                set_pixel(a, i+c+50, j+r, k, rgb[k] * val);
            }
        }
    }
    for(j = 0; j < hp && j + r < a.h; ++j){
        for(i = 0; i < wp && i + c < a.w; ++i){
            for(k = 0; k < prob_label.c; ++k){
                float val = get_pixel(rpl, i, j, k);
                set_pixel(a, i+c, j+r, k, rgb[k] * val);
            }
        }
    }
    free_image(rl);
    free_image(rpl);
}
예제 #9
0
파일: image.c 프로젝트: renmengye/darknet
// http://www.cs.rit.edu/~ncs/color/t_convert.html
void rgb_to_hsv(image im)
{
    assert(im.c == 3);
    int i, j;
    float r, g, b;
    float h, s, v;
    for(j = 0; j < im.h; ++j){
        for(i = 0; i < im.w; ++i){
            r = get_pixel(im, i , j, 0);
            g = get_pixel(im, i , j, 1);
            b = get_pixel(im, i , j, 2);
            float max = three_way_max(r,g,b);
            float min = three_way_min(r,g,b);
            float delta = max - min;
            v = max;
            if(max == 0){
                s = 0;
                h = -1;
            }else{
                s = delta/max;
                if(r == max){
                    h = (g - b) / delta;
                } else if (g == max) {
                    h = 2 + (b - r) / delta;
                } else {
                    h = 4 + (r - g) / delta;
                }
                if (h < 0) h += 6;
            }
            set_pixel(im, i, j, 0, h);
            set_pixel(im, i, j, 1, s);
            set_pixel(im, i, j, 2, v);
        }
    }
}
예제 #10
0
파일: main.c 프로젝트: elkhadiy/cours-tlm
void game_of_life() {
    int x;
    int y;
    for (x = 0; x < SW_VGA_WIDTH; ++x) {
        for (y = 0; y < SW_VGA_HEIGHT; ++y) {
            int n = neighbors(old_img_addr, x, y);
            /* if is alive */
            if (get_pixel(old_img_addr, x, y)) {
                /* underpopulation or overcrowding: die */
                if ((n < 2) || (n > 3)) {
                    set_pixel(new_img_addr, x, y, 0);
                } else {
                    set_pixel(new_img_addr, x, y, 1);
                }
            } else {
                /* perfect conditions: become alive */
                if (n == 3) {
                    set_pixel(new_img_addr, x, y, 1);
                } else {
                    set_pixel(new_img_addr, x, y, 0);
                }
            }
        }
    }
}
예제 #11
0
void generic_draw_line(u32 x1, u32 y1, u32 x2, u32 y2, pixel_t pixel)
{
    int dx, dy, sx, sy, e;

    dx = x2-x1;
    dy = y2-y1;
    if (dy == 0) {
	if (dx < 0) {
	    dx = -dx;
	    x1 = x2;
	}
	draw_hline(x1, y1, dx+1, pixel);
    } else if (dx == 0) {
	if (dy < 0) {
	    dy = -dy;
	    y1 = y2;
	}
	draw_vline(x1, y1, dy+1, pixel);
    } else {
	if (dy < 0) {
	    dy = -dy;
	    sy = -1;
	} else {
	    sy = 1;
	}
	if (dx < 0) {
	    dx = -dx;
	    sx = -1;
	} else {
	    sx = 1;
	}
	if (dx > dy) {
	    e = -dx/2;
	    set_pixel(x1, y1, pixel);
	    while (x1 != x2) {
		e += dy;
		if (e >= 0) {
		    y1 += sy;
		    e -= dx;
		}
		x1 += sx;
		set_pixel(x1, y1, pixel);
	    }
	} else {
	    e = -dy/2;
	    set_pixel(x1, y1, pixel);
	    while (y1 != y2) {
		e += dx;
		if (e >= 0) {
		    x1 += sx;
		    e -= dy;
		}
		y1 += sy;
		set_pixel(x1, y1, pixel);
	    }
	}
    }
}
예제 #12
0
static void fill_circle_points_x(u32 cx, u32 cy, u32 x, u32 y, pixel_t pixel)
{
    if (x == 0) {
	set_pixel(cx, cy-y, pixel);
	set_pixel(cx, cy+y, pixel);
    } else {
	draw_hline(cx-x, cy-y, 2*x+1, pixel);
	draw_hline(cx-x, cy+y, 2*x+1, pixel);
    }
}
예제 #13
0
static void fill_ellipse_points(u32 cx, u32 cy, u32 x, u32 y, pixel_t pixel)
{
    if (x == 0) {
	set_pixel(cx, cy-y, pixel);
	set_pixel(cx, cy+y, pixel);
    } else if (y == 0) {
	draw_hline(cx-x, cy, 2*x+1, pixel);
    } else {
	draw_hline(cx-x, cy-y, 2*x+1, pixel);
	draw_hline(cx-x, cy+y, 2*x+1, pixel);
    }
}
예제 #14
0
void UnaryCompositeLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
                                               const vector<Blob<Dtype>*>& top)
{
    top[0]->CopyFrom(*bottom[0], false);// data is copied
    
    Dtype user_interaction_potential = this->layer_param_.multi_stage_crf_param().user_interaction_potential();
    Dtype dis_mean = this->layer_param_.multi_stage_crf_param().interaction_dis_mean();
    Dtype dis_std  = this->layer_param_.multi_stage_crf_param().interaction_dis_std();
    Dtype dis_cv = dis_mean/dis_std;
    
    const Dtype * bottom_data = bottom[0]->cpu_data();
    const Dtype * image_data = bottom[1]->cpu_data();
    Dtype * top_data = top[0]->mutable_cpu_data();
    Dtype * mask_data = top[1]->mutable_cpu_data();
    int scribble_point = 0;
    for(int n=0; n<num_; n++)
    {
        for(int h=0; h<height_; h++)
        {
            for(int w=0; w<width_; w++)
            {
                int scribble_channel = -1;
                for(int c = 0; c<unary_channels_; c++)
                {
                    int ci = image_channels_-unary_channels_ + c;
                    Dtype d = get_pixel(image_data, num_, image_channels_, height_, width_,
                                        n, ci, h, w);
                    if((d + dis_cv) < 1e-5 && (d + dis_cv) > -1e-5)
                    {
                        scribble_channel = c;
                        scribble_point++;
                        break;
                    }
                }
                
                Dtype mask_value = (scribble_channel>-1)? 1.0 : 0.0;
                set_pixel(mask_data, num_, 1, height_, width_, n, 0, h, w, mask_value);
                if(scribble_channel > -1)
                {
                    for (int c = 0; c<unary_channels_; c++)
                    {
                        Dtype u_value = 0;//get_pixel(bottom_data, num_, unary_channels_, height_, width_,n, c, h, w);
                        u_value = (c == scribble_channel)? u_value + user_interaction_potential :
                                                           u_value - user_interaction_potential;
                        set_pixel(top_data, num_, unary_channels_, height_, width_, n, c, h, w, u_value);
                    }
                }
            } //for w
        } // for h
    } // for n
    LOG(INFO)<<"scribble point: "<<scribble_point;
}
예제 #15
0
void draw_circle(SDL_Surface *surface, int cx, int cy, int radius, Uint32 pixel) {
    double r = (double)radius;

    for(double dy = 1; dy <= r; dy += 1.0) {
        double dx = floor(sqrt((2.0 * r * dy) - (dy * dy)));
        int x = cx - dx;

        for(; x <= cx + dx; x++) {
            set_pixel(surface, x, ((int)(cy + r - dy)), pixel);
            set_pixel(surface, x, ((int)(cy - r + dy)), pixel);
        }
    }
}
예제 #16
0
void draw_world(world* game_world, screen* out) {
  for (int i = 0; i < game_world->height; i++) {
    for (int j = 0; j < game_world->width; j++) {
      set_pixel(i, j, '0', out);
    }
  }

  for (int i = 0; i < game_world->num_walls; i++) {
    point wall = game_world->walls[i];
    set_pixel(wall.y, wall.x, '1', out);
  }

  draw_player(game_world->game_player, out);
  draw_collectible(game_world->pellet, out);
}
예제 #17
0
void flush(){
    for (uint8_t x = 0; x < MATRIX_WIDTH; x++){
	for (uint8_t y = 0; y < MATRIX_HEIGHT; y++){
		set_pixel(x, y, scratch_buffer[x][y], OVERLAY_REPLACE);
	}
    }
}
static void set_pixel_range(uint8_t buf[], int row, int start, int end)
{
    int i;

    for (i = start;  i <= end;  i++)
        set_pixel(buf, row, i);
}
예제 #19
0
void Image2DGrey::load_PGM(const std::string &filename)
{
	std::ifstream file(filename.c_str(), std::ios::in);
	std::string magic_number, line;
	getline(file,magic_number);

	while(file.peek() == '#' && !file.eof())
	{
		getline( file, line);
	}

	int width, height;
	file >> width >> height ;
	resize(width, height);

	int max;
	file >> max;

	for (int y=0;y<get_height();y++)
	{
			for (int x=0;x<get_width();x++)
			{
				int pixel;
				file >> pixel;
				set_pixel(x,y, pixel * 255 / max);
			}
		}
	file.close();
}
예제 #20
0
void draw_sprite_scaled(Sprite *sprt, char *base, int width, int height)
{
	char *dSprt = sprt->map;
	char* bgMap = sprt->bgmap;
	sprt->on_screen = true;
	if(bgMap)
	{
		bgMap = realloc(bgMap, width * height);
		sprt->bgmap = bgMap;
	}
	
	double dx = (double)sprt->width / width;
	double dy = (double)sprt->height / height;
	
	int i,k;
	for(i = 0; i < height; i++)
		for(k = 0; k < width; k++)
		{
			if(bgMap) *(bgMap + width*i + k) = get_pixel(sprt->x+k, sprt->y+i, base); //guarda o valor antigo
			
			int map_x = dx*k + 0.5;
			int map_y = dy*i + 0.5;
			int color = *(dSprt + sprt->width*map_y + map_x);
			if(color != 0) set_pixel(sprt->x+k,sprt->y+i, color, base);  //actualiza com o valor mapeado
		}
}
예제 #21
0
void PerlinNoise::operator()(SDL_Surface * s)
{
    SDL_FillRect(s, NULL, 0);

    int r = rand() % 256;
    int g = rand() % 256;
    int b = rand() % 256;
    for(int x=0; x<s->w; x++)
        for(int y=0; y<s->h; y++)
        {
            float t = Perlin( (int)x, (int)y );
            int value = 128 + 128*t;
            clamp(0, value, 255);
            //std::cout << value << std::endl;

            Color c;
            c.r = r;
            c.g = g;
            c.b = b;
            c.a = value;

            set_pixel(s, x, y, c);
        }

}
예제 #22
0
파일: drawing.c 프로젝트: yeqingyan/tos_tos
/**
 * Draw character on screen
 *
 * @param character     character to draw
 * @param x             character x coordinate
 * @param y             character y coordinate
 */
void draw_character(char character, int x, int y) {
  // Get the font binary address by run objdump -t build/font.o
  unsigned char *font_addr = (unsigned char *)&_binary_font_font_bin_start;
  int row;
  unsigned int bits, bit;

  if (character > 127) {
    return;
  }

  // Each character cost 16 bytes in font.bin
  font_addr += CHARACTER_SIZE * character;

  for (row = 0; row < CHARACTER_HEIGHT; row += 1) {
    bits = (unsigned int)peek_b((MEM_ADDR)(font_addr + row));
    bit = CHARACTER_WIDTH;
    do {
      bits = bits << 1;
      bit -= 1;
      if ((bits & 0x100) != 0) {
        set_pixel(x + bit, y);
      } else {
        clear_pixel(x + bit, y);
      }
    } while (bit != 0);
    y += 1;
  }
}
예제 #23
0
  void PixelMap::setPixel(const IntPoint &pixel, bool is)
  {
    if(pixel.getX() >= size.getWidth() || pixel.getY() >= size.getHeight() || pixel.getX() < 0 || pixel.getY() < 0)
      return;

    set_pixel(pixel.getX(), pixel.getY(), is);
  }
예제 #24
0
  void PixelMap::load(const PixelMap &pixelmap)
  {
    if(&pixelmap == this)
      return;

    clear();

    size = pixelmap.size;

    if(pixelmap.map != NULL)
    {
      map = new u8*[size.getHeight()];

      for(int y = 0; y < size.getHeight(); y++)
      {
        int linelength;

        linelength = size.getWidth()%8 == 0 ? size.getWidth()/8 : size.getWidth()/8 + 1;

        map[y] = new u8[linelength];
          memset(map[y], 0, sizeof(*map[y]) * linelength);

        for(int x = 0; x < size.getWidth(); x++)
        {
          if(is_pixel_on_map(pixelmap.map, x, y))
            set_pixel(x, y, 1);
        }
      }
    }
  }
예제 #25
0
static IplImage* do_scale(IplImage* im, int s)
{
  /* image pixel binning */
  /* s the scaling factor */

  IplImage* scale_im = NULL;
  CvSize scale_size;
  int x;
  int y;
  int i;
  int j;
  unsigned char rgb[3];

  scale_size.width = im->width * s;
  scale_size.height = im->height * s;
  scale_im = cvCreateImage(scale_size, IPL_DEPTH_8U, 3);

  for (y = 0; y < im->height; ++y)
  {
    for (x = 0; x < im->width; ++x)
    {
      get_pixel(im, x, y, rgb);

      for (i = 0; i < s; ++i)
	for (j = 0; j < s; ++j)
	  set_pixel(scale_im, x * s + i, y * s + j, rgb);
    }
  }

  return scale_im;
}
예제 #26
0
void	blit_pixelarrays(t_bunny_pixelarray *background,
			 t_bunny_pixelarray *buffer,
			 t_bunny_position *pos)
{
  int	x;
  int	y;

  y = pos->y;
  while (y < (pos->y + buffer->clipable.clip_height))
    {
      x = pos->x;
      while (x < (pos->x + buffer->clipable.clip_width))
	{
	  if (x < background->clipable.clip_width &&
	      y < background->clipable.clip_height)
	    {
	      set_pixel(background, get_pixel(buffer,
	      x-pos->x + buffer->clipable.clip_x_position,
	      y-pos->y + buffer->clipable.clip_y_position), x, y);
	    }
	  x++;
	}
      y++;
    }
}
예제 #27
0
void			my_set_circle(t_bunny_pixelarray *pix,
				      t_bunny_position *origin,
				      t_bunny_position *dist,
				      unsigned int color)
{
  double		radius;
  double		mini_radius;
  double		angle;
  t_bunny_position	pos;

  angle = 0;
  dist->x = dist->x - origin->x;
  dist->y = dist->y - origin->y;
  radius = sqrt(pow(dist->x, 2) + pow(dist->y, 2));
  mini_radius = 1;
  while (mini_radius < radius)
    {
      angle = 0;
      while (angle < 360)
	{
	  pos.x = cos(DEGREES_TO_RADIANS(angle)) * mini_radius + origin->x;
	  pos.y = sin(DEGREES_TO_RADIANS(angle)) * mini_radius + origin->y;
	  if (pos.x > 0 && pos.x < pix->clipable.clip_width &&
	      pos.y > 0 && pos.y < pix->clipable.clip_height)
	    set_pixel(pix, color, pos.x, pos.y);
	  angle += 0.10;
	}
      mini_radius += 0.25;
    }
}
예제 #28
0
void change_style(SDL_Surface *src, Uint32 style)
{
    Uint8 rm, gm, bm;
    int x, y;
    SDL_GetRGB(style, src->format, &rm, &gm, &bm);
    if ( SDL_MUSTLOCK(src) ) {
        if ( SDL_LockSurface(src) < 0 ) {
            return;
        }
    }
    for (x = 0; x < src->w; x++) {
        for (y = 0; y < src->h; y++) {
            Uint32 color;
            Uint8 r, g, b;
            int nr, ng, nb;
            color = get_pixel(src, x, y);
            SDL_GetRGB(color, src->format, &r, &g, &b);
            nr = r * rm / 255;
            ng = g * gm / 255;
            nb = b * bm / 255;
            #define check_byte(r) ((r > 0)?((r < 255)?r:255):0)
            nr = check_byte(nr);
            ng = check_byte(ng);
            nb = check_byte(nb);
            #undef check_byte
            color = SDL_MapRGB(src->format, (Uint8)nr, (Uint8)ng, (Uint8)nb);
            set_pixel(src, x, y, color);
        }
    }
    if ( SDL_MUSTLOCK(src) ) {
        SDL_UnlockSurface(src);
    }
}
예제 #29
0
파일: image.c 프로젝트: cuinutanix/2048
void display_image(int row, int col, const void *image)
{
  const u16 *p = image;
  u32 width  = *p++;
  u32 height = *p++;
  u32 pos;

  u16 palette[128];

  for (pos = 0; pos < width * height; ) {
    u16 word = *p++;
    u8 index = word >> 8;

    if ((index & 0x80)) {
      palette[index & 0x7f] = rgb24to16((word << 16) | *p++);
    } else {
      u8 rl = word;
      u16 color = palette[index];

      do {
        set_pixel(row + pos / width, col + pos % width, color);
        pos++;
      } while (rl-- > 0);
    }
  }
}
예제 #30
0
void change_spec(SDL_Surface *src, SDL_Surface *new_spec)
{
    int x, y;
    if ( SDL_MUSTLOCK(src) ) {
        if ( SDL_LockSurface(src) < 0 ) {
            return;
        }
    }
    for (x = 0; x < src->w; x++) {
        for (y = 0; y < src->h; y++) {
            int nr, ng, nb, a;
            Uint8 sr, sg, sb;
            Uint8 nsr, nsg, nsb;
            SDL_GetRGB(get_pixel(src, x, y), src->format, &sr,  &sg,  &sb);
            SDL_GetRGB(get_pixel(new_spec, x, y), new_spec->format, &nsr,  &nsg,  &nsb);
            a = (nsr + nsg + nsb) / 3;
            nr = sr - a + nsr;
            ng = sg - a + nsg;
            nb = sb - a + nsb;
            #define check_byte(r) ((r > 0)?((r < 255)?r:255):0)
            nr = check_byte(nr);
            ng = check_byte(ng);
            nb = check_byte(nb);
            #undef check_byte
            set_pixel(src, x, y, SDL_MapRGB(src->format, nr, ng, nb));
        }
    }
    if ( SDL_MUSTLOCK(src) ) {
        SDL_UnlockSurface(src);
    }
}