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

📄 simple_graphics.c

📁 在SOPC平台上
💻 C
📖 第 1 页 / 共 3 页
字号:
  int addr;
  int bytes_per_line, bytes_per_pixel;
  char* line;
  
  bytes_per_pixel = (frame_buffer->color_depth / 8);
  bytes_per_line = ((Hend - Hstart) * bytes_per_pixel);

  line = malloc(bytes_per_line + 12);

	if(frame_buffer->color_depth == 16)
	{
    for (i = 0; i < bytes_per_line; i+=2) 
    {
      *(line + i) = (unsigned char)color;
      *(line + i + 1) = (unsigned char)(color >> 8);
    }
  }
  else if(frame_buffer->color_depth == 24)
  { 
    for (i = 0; i < bytes_per_line; i+=3) 
    {
      *(line + i) = (unsigned char)color;
      *(line + i + 1) = (unsigned char)(color >> 8);
      *(line + i + 2) = (unsigned char)(color >> 16);
    }
  }
  else if(frame_buffer->color_depth == 32)
  { 
    for (i = 0; i < bytes_per_line; i+=4) 
    {
      // Does the right hand side of this assignment determine the size?
      *(int*)(line + i) = (unsigned int)color;
    }
  }
  
  /* Initial Address */
  addr = (int)(frame_buffer->frame1) + ((Vstart * (frame_buffer->width * bytes_per_pixel)) + (Hstart * bytes_per_pixel));
  
  for (i = Vstart; i < Vend; i++)
  {
    memcpy( (void*)addr, line, bytes_per_line );
    addr += (frame_buffer->width * bytes_per_pixel);
  }
  free (line);
}


/******************************************************************
*  Function: vid_draw_horiz_line
*
*  Purpose: Draws a horizontal line on the screen quickly.
*           Good for filling stuff.
*
******************************************************************/
void vid_draw_horiz_line (short Hstart, short Hend, int V, int color, frame_buffer_struct* frame_buffer)
{

  int i;
  int addr;
  int bytes_per_line;

  char *fast_buffer = malloc(1024 * 3);

  if( Hstart > Hend )
  {
    short temp = Hstart;
    Hstart = Hend;
    Hend = temp;
  }
  
  if(frame_buffer->color_depth == 32)
  { 
    addr = (int)(frame_buffer->frame1) + ((V * (frame_buffer->width * 4)) + (Hstart * 4));
    bytes_per_line = ((Hend - Hstart) * 4);
    for (i = 0; i < bytes_per_line; i+=4) 
    {
      // Does the right hand side of this assignment determine the size?
      *(int*)(fast_buffer + i) = (unsigned int)color;
    }
    memcpy( (void*)addr, fast_buffer, bytes_per_line );
  }
  if(frame_buffer->color_depth == 24)
  { 
    addr = (int)(frame_buffer->frame1) + ((V * (frame_buffer->width * 3)) + (Hstart * 3));
    bytes_per_line = ((Hend - Hstart) * 3);
    for (i = 0; i < bytes_per_line; i+=3) 
    {
      *(fast_buffer + i) = (unsigned char)color;
      *(fast_buffer + i + 1) = (unsigned char)(color >> 8);
      *(fast_buffer + i + 2) = (unsigned char)(color >> 16);
    }
    memcpy( (void*)addr, fast_buffer, bytes_per_line );
  }
  else if(frame_buffer->color_depth == 16)
  {
    addr = (int)(frame_buffer->frame1) + ((V * (frame_buffer->width * 2)) + (Hstart * 2));
    bytes_per_line = ((Hend - Hstart) * 2);
    for (i = 0; i < bytes_per_line; i+=2) 
    {
      *(fast_buffer + i) = (unsigned char)color;
      *(fast_buffer + i + 1) = (unsigned char)(color >> 8);
    }
    memcpy( (void*)addr, fast_buffer, bytes_per_line );
  }
  free(fast_buffer);
}



/******************************************************************
*  Function: vid_merge_colors
*
*  Purpose: Takes 5-bit color values for each red, green, and blue
*           and merges them into one 16-bit color value.
*
******************************************************************/
int vid_merge_colors(int red, int green, int blue)
{
  // Green actually has 6-bits, but we'll make it's LSB 1 to be consistent.
  return ((blue) | (((green << 1) | 0x1) << 5) | (red << 11));
}

/******************************************************************
*  Function: vid_color_convert24_16
*
*  Purpose: Takes a pointer to a 24-bit (3-byte) 24-bit RGB color 
*           sample and converts it to 16-bits, displayable by the 
*           VGA controller in 16-bit mode
*
******************************************************************/
unsigned short vid_color_convert24_16(char* color24)
{
	unsigned char red, green, blue;
	unsigned short output;
	
	red = *(color24 + 0) & 0xF8;
	green = *(color24 + 1) & 0xFC; // green is actualy 6 bits
	blue = *(color24 + 2) & 0xF8;

	output = ((blue >> 3) | (green << 3) | (red << 8));  
	return output;
}


/******************************************************************
*  Function: vid_color_convert24_16
*
*  Purpose: Takes a pointer to a 24-bit (3-byte) 24-bit RGB color 
*           sample and converts it to 16-bits, displayable by the 
*           VGA controller in 16-bit mode
*
******************************************************************/
int vid_color_convert16_24(unsigned short color16, char* color24)
{
	*(color24 + 0) = color16 >> 11;
	*(color24 + 1) = ((color16 & 0x3E) >> 5);
	*(color24 + 2) = (color16 & 0x1F);
	
	return (0);
}

/******************************************************************
*  Function: vid_copy_line_to_frame_buffer
*
*  Purpose: Copies a scanline from memory to the frame buffer at
*           the specified coordinates.  Converts color depth if
*           necessary.
*
******************************************************************/
int vid_copy_line_to_frame_buffer( int x, int y, char* buffer, int num_pixels, int source_color_depth, frame_buffer_struct* frame_buffer )
{
  unsigned short* temp_line;
  int index_24 = 0;
  int index_16 = 0;
  unsigned int dest_addr;
  unsigned int bytes_in_line;
  
  dest_addr = (int)(frame_buffer->frame1) + 
    ((y * (frame_buffer->width * (frame_buffer->bytes_per_pixel))) + 
    (x * (frame_buffer->bytes_per_pixel)));
  
  bytes_in_line = num_pixels * frame_buffer->bytes_per_pixel;
  
  if(source_color_depth == 24)
  {
    if(frame_buffer->color_depth == 16)
    {
      temp_line = malloc(bytes_in_line);
      while(index_24 < bytes_in_line)
      {
        *(temp_line + index_16) = vid_color_convert24_16_m((char*)(buffer + index_24));
        index_16++;
        index_24+=3;
      }
      memcpy( (void*)dest_addr, (void*)temp_line, bytes_in_line );
      free(temp_line);
    }
    else if(frame_buffer->color_depth == 24)
    {
      memcpy( (void*)dest_addr, (void*)buffer, bytes_in_line );
    }
  }
  else if(source_color_depth == 16)
  {
    if(frame_buffer->color_depth == 24)
    {
      temp_line = malloc(bytes_in_line);
      while(index_16 < num_pixels )
      {
        vid_color_convert16_24((short)*(buffer + index_16), (char*)(temp_line + index_24));
        index_16++;
        index_24+=3;
      }
      memcpy( (void*)dest_addr, (void*)temp_line, bytes_in_line );
      free(temp_line);
      
    }
    else if(frame_buffer->color_depth == 16)
    {
      memcpy( (void*)dest_addr, (void*)buffer, bytes_in_line );
    }
  }
  return(0);
}

/******************************************************************
*  Function: vid_draw_sloped_line
*
*  Purpose: Draws a line between two end points using
*           Bresenham's line drawing algorithm.
*           width parameter is not used.  
*           It is reserved for future use.
*
******************************************************************/
void vid_draw_sloped_line( unsigned short horiz_start, 
                           unsigned short vert_start, 
                           unsigned short horiz_end, 
                           unsigned short vert_end, 
                           unsigned short width, 
                           int color, 
                           frame_buffer_struct* frame_buffer)
{
  // Find the vertical and horizontal distance between the two points
  int horiz_delta = abs(horiz_end-horiz_start);
  int vert_delta = abs(vert_end-vert_start);

  // Find out what direction we are going
  int horiz_incr, vert_incr;
  if (horiz_start > horiz_end) { horiz_incr=-1; } else { horiz_incr=1; }
  if (vert_start > vert_end) { vert_incr=-1; } else { vert_incr=1; }

  // Find out which axis is always incremented when drawing the line
  // If it's the horizontal axis
  if (horiz_delta >= vert_delta) {
    int dPr   = vert_delta<<1;
    int dPru  = dPr - (horiz_delta<<1);
    int P     = dPr - horiz_delta;

    // Process the line, one horizontal point at at time
    for (; horiz_delta >= 0; horiz_delta--) {
      // plot the pixel
      vid_set_pixel(horiz_start, vert_start, color, frame_buffer);
      // If we're moving both up and right
      if (P > 0) {
        horiz_start+=horiz_incr;
        vert_start+=vert_incr;
        P+=dPru;
      } else {
        horiz_start+=horiz_incr;
        P+=dPr;
      }
    }
  // If it's the vertical axis
  } else {
    int dPr   = horiz_delta<<1;
    int dPru  = dPr - (vert_delta<<1);
    int P     = dPr - vert_delta;

    // Process the line, one vertical point at at time
    for (; vert_delta>=0; vert_delta--) {
      // plot the pixel
      vid_set_pixel(horiz_start, vert_start, color, frame_buffer);
      // If we're moving both up and right
      if (P > 0) {
        horiz_start+=horiz_incr;
        vert_start+=vert_incr;
        P+=dPru;
      } else {
        vert_start+=vert_incr;
        P+=dPr;
      }
    }
  }
}



/******************************************************************
*  Function: vid_draw_circle
*
*  Purpose: Draws a circle on the screen with the specified center
*  and radius.  Draws symetric circles only.  The fill parameter
*  tells the function whether or not to fill in the box.  1 = fill,
*  0 = do not fill.
*
******************************************************************/
int vid_draw_circle(int Hcenter, int Vcenter, int radius, int color, char fill, frame_buffer_struct* frame_buffer)
{
  int x = 0;
  int y = radius;
  int p = (5 - radius*4)/4;

  // Start the circle with the top, bottom, left, and right pixels.
  vid_circle_points(Hcenter, Vcenter, x, y, color, fill, frame_buffer);

  // Now start moving out from those points until the lines meet
  while (x < y) {
    x++;
    if (p < 0) {
      p += 2*x+1;
    } else {
      y--;
      p += 2*(x-y)+1;
    }
    vid_circle_points(Hcenter, Vcenter, x, y, color, fill, frame_buffer);
  }
  return (0);
}

/******************************************************************
*  Function: vid_circle_points
*
*  Purpose: Called by vid_draw_circle() to plot the actual points
*  of the circle.  Draws horizontal lines to fill.
*
******************************************************************/

void vid_circle_points(int cx, int cy, int x, int y, int color, char fill, frame_buffer_struct* frame_buffer)
{

    // If we're directly above, below, left and right of center (0 degrees), plot those 4 pixels
    if (x == 0) {
        vid_set_pixel(cx, cy + y, color, frame_buffer);
        vid_set_pixel(cx, cy - y, color, frame_buffer);
        if(fill) {
          vid_draw_line(cx - y, cy, cx + y, cy, 1, color, frame_buffer);
          
        } else {
          vid_set_pixel(cx + y, cy, color, frame_buffer);
          vid_set_pixel(cx - y, cy, color, frame_buffer);
        }

    } else

⌨️ 快捷键说明

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