画个圆吧---C语言画圆

http://blog.chinaunix.net/uid-24774106-id-3047520.html

我知道C语言的能力很强,但是对于图形图像类的C语言实现很是好奇,觉得很难。我读书的时候,用C语言画过BMP格式的图像,因为没有任何的压缩,所以图像的数据量比较大,基本上就是RGB 字节流。今天看了Banu blog中的博文 Drawing circles,想起了以前用C语言进行BMP图像的处理。

     写这篇博客,是给自己枯燥的学习带来一些乐趣,C语言也可以干些比较有有趣的事情。代码基本上是照搬Banu,只是,文章画的图像是灰度图像,不够靓丽,我将代码改成了生成彩色图像。不管怎么说,光荣属于Banu,我只是仰望前辈的学习者。

    生成一个文件,后缀为ppm,Linux下的GIMP自然可以解析这种格式。ppm格式和BMP很像,基本属于傻瓜型图像格式,每个像素就是RGB三个字节表示,当然为了声明文件类型,会有文件头。看下WIKI中的介绍。    
Magic Number Type Encoding
P1 Portable bitmap ASCII
P2 Portable graymap ASCII
P3 Portable pixmap ASCII
P4 Portable bitmap Binary
P5 Portable graymap Binary
P6 Portable pixmap Binary

P3 
# The P3 means colors are in ASCII, then 3 columns and 2 rows, 
# then 255 for max color, then RGB triplets
 3 2
 255
 255 0 0       0 255 0        0 0 255 
255 255 0      255 255 255    0 0 0

我们看到了上面虚框中的文件内容,画出来就是下面这个彩色图像。当然,下面的图用一个比较大的正方形来表示一个像素点(255,0,0)表示红色,所以代表第一个像素点的正方形是红色的,依次类推。

OK,下面看下代码:
  1. static void
  2. image_save (const Image *image,
  3.             const char *filename)
  4. {
  5.   FILE *out;

  6.   out = fopen (filename, "wb");
  7.   if (!out)
  8.     return;

  9.   fprintf (out, "P6\n");
  10.   fprintf (out, "%zu %zu\n", image->width, image->height);
  11.   fprintf (out, "255\n");

  12.   fwrite (image->data, 1, image->width * image->height*3, out);

  13.   fclose (out);
  14. }

P6告诉文件解析程序(如GIMP)我是PPM格式的文件(Portable pixmap)。
第二行告诉文件的长和高。
下面是完整的代码,再次强调,荣耀和版权都属于Banu,我只是仰望Banu的学习者
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>

  5. typedef struct {
  6.   size_t width;
  7.   size_t height;
  8.   unsigned char *data;
  9. } Image;

  10. static Image *
  11. image_new (size_t width,
  12.            size_t height)
  13. {
  14.   Image *image;

  15.   image = malloc (sizeof *image);
  16.   image->width = width;
  17.   image->height = height;
  18.   image->data = malloc (width * height*3);

  19.   return image;
  20. }

  21. static void
  22. image_free (Image *image)
  23. {
  24.   free (image->data);
  25.   free (image);
  26. }

  27. static void
  28. image_fill (Image *image,
  29.             unsigned char value)
  30. {
  31.   memset (image->data, value, image->width * image->height*3);
  32. }

  33. /**
  34.  * image_set_pixel:
  35.  *
  36.  * Sets a pixel passed in signed (x, y) coordinates, where (0,0) is at
  37.  * the center of the image.
  38.  **/
  39. static void
  40. image_set_pixel (Image *image,
  41.                  ssize_t x,
  42.                  ssize_t y,
  43.                  unsigned char Rvalue,
  44.                  unsigned char Gvalue,
  45.                  unsigned char Bvalue)
  46. {
  47.   size_t tx, ty;
  48.   unsigned char *p;

  49.   tx = (image->width / 2) + x;
  50.   ty = (image->height / 2) + y;

  51.   p = image->data + (ty * image->width*3) + tx*3;

  52.   *= Rvalue;
  53.     *(p+1) = Gvalue;
  54.     *(p+2) = Bvalue;
  55. }

  56. static void
  57. image_save (const Image *image,
  58.             const char *filename)
  59. {
  60.   FILE *out;

  61.   out = fopen (filename, "wb");
  62.   if (!out)
  63.     return;

  64.   fprintf (out, "P6\n");
  65.   fprintf (out, "%zu %zu\n", image->width, image->height);
  66.   fprintf (out, "255\n");

  67.   fwrite (image->data, 1, image->width * image->height*3, out);

  68.   fclose (out);
  69. }

  70. static void
  71. draw_circle (Image *image,
  72.              int radius,
  73.              unsigned char Rvalue,
  74.                          unsigned char Gvalue,
  75.                          unsigned char Bvalue)
  76. {
  77.   int x, y;

  78.   for (= -radius; y <= radius; y++)
  79.     for (= -radius; x <= radius; x++)
  80.       if ((* x) + (* y) <= (radius * radius))
  81.         image_set_pixel (image, x, y, Rvalue,Gvalue,Bvalue);
  82. }

  83. int
  84. main (int argc, char *argv[])
  85. {
  86.   Image *image;

  87.   image = image_new (600, 600);

  88.   image_fill (image, 0xff);
  89.   draw_circle (image, 200, 0x00,0x00,0xff);
  90.   image_save (image, "circle.ppm");

  91.   image_free (image);

  92.   return 0;
  93. }
就可以在本地查看一个蓝色的圆图像。下图格式是jpg格式的,我用QQ截图工具生成的。
由于CU不支持ppm格式的图像,所以只能传jpg了。


参考文献:
1 Banu 博文 Drawing Circles
2 Wiki
<think>好的,我现在需要帮助用户了解如何用C语言实现绘制形的功能,并且推荐相关的图形库。首先,我需要整理已有的信息,确保回答符合系统级指令的要求。 根据用户提供的引用,有两个来源提到了图形库的使用。引用[1]提到了使用graphics.h库,需要EASYX支持,适用于VC++环境。引用[2]则推荐了Cairo图形库,说明它是一个强大的2D图形库,被GTK+3.0采用。用户的问题集中在绘制形的方法和推荐的图形库,所以需要涵盖这两个方面。 首先,我需要确认用户的环境和需求。用户可能是在不同的开发环境下工作,比如VC++或者其他编译器。graphics.h是较为传统的库,但非标准,需要额外配置。而Cairo则是更现代和跨平台的选择,但可能需要更多的设置步骤。此外,还有其他图形库如SDL2和OpenGL,适用于游戏或更复杂的图形应用,但用户可能只需要基础的绘图功能。 接下来,我需要确保回答结构清晰,分步骤说明不同的方法。例如,可以分点讨论每个图形库的使用方法,包括代码示例和配置说明。同时,需要指出各个库的优缺点,帮助用户根据具体情况选择。例如,EASYX适合初学者和简单图形,而Cairo适合跨平台和高质量渲染。 还需要注意LaTeX格式的正确应用,行内数学表达式用$...$,独立公式用$$...$$。但在这个问题中可能涉及较少数学公式,但如果有参数说明,比如的方程,可能需要使用。例如,心$(x,y)$和半径$r$可以用行内公式。 此外,生成相关问题也是必须的。需要根据回答内容提出相关的问题,例如性能比较、跨平台开发的库推荐,或者如何绘制其他图形形状。 最后,检查引用是否正确添加,确保在提到每个库的时候,对应的引用标识正确。例如,提到graphics.h时引用[^1],提到Cairo时引用[^2]。 现在,需要组织这些信息,确保符合用户可见层的结构要求:分步骤、清晰、可靠。可能的结构如下: 1. 传统方法:graphics.h库,适用于VC++,需要安装EASYX,提供代码示例。 2. 现代方法:Cairo库,跨平台,代码示例及编译命令。 3. 其他推荐库:SDL2和OpenGL,简要介绍适用场景。 4. 总结和选择建议。 同时,确保每个部分都有对应的引用,例如在提到graphics.h时添加,Cairo时[^2]。 需要验证代码示例是否正确。例如,graphics.h的代码是否包含必要的初始化和关闭图形模式的步骤。Cairo的示例代码是否正确生成PNG文件,并且编译命令是否适用不同平台。 可能还需要注意,用户可能对配置过程有疑问,因此需要说明如何安装这些库,比如通过包管理器或下载源码。 最后,生成相关问题,如不同库的比较,跨平台开发的注意事项,或者如何绘制更复杂的图形。</think>以下是使用C语言实现绘制形的解决方案及图形库推荐: ### 一、传统方法:graphics.h库 适用于**Windows平台**的VC++开发环境,需安装EASYX插件: ```c #include <graphics.h> int main() { initgraph(640, 480); // 初始化图形窗口 circle(320, 240, 100); // 心坐标(320,240),半径100 getch(); closegraph(); return 0; } ``` **特点**:简单易用,但兼容性差,仅支持老旧开发环境。 --- ### 二、现代方法:Cairo图形库 跨平台2D图形库,支持高质量渲染[^2]: ```c #include <cairo.h> int main() { cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 640, 480); cairo_t *cr = cairo_create(surface); cairo_set_source_rgb(cr, 1, 0, 0); // 红色 cairo_arc(cr, 320, 240, 100, 0, 2 * M_PI); // 画圆 cairo_stroke(cr); // 描边 cairo_surface_write_to_png(surface, "circle.png"); cairo_destroy(cr); cairo_surface_destroy(surface); return 0; } ``` **编译命令**(Linux): ```bash gcc -o circle circle.c `pkg-config --cflags --libs cairo` ``` --- ### 三、其他推荐图形库 1. **SDL2** 适合游戏开发,跨平台支持: ```c #include <SDL2/SDL.h> int main() { SDL_Init(SDL_INIT_VIDEO); SDL_Window *window = SDL_CreateWindow("Circle", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, 0); SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); for (int y = -100; y <= 100; y++) for (int x = -100; x <= 100; x++) if (x*x + y*y <= 10000) // 的方程$x^2 + y^2 = r^2$ SDL_RenderDrawPoint(renderer, 320 + x, 240 + y); SDL_RenderPresent(renderer); SDL_Delay(3000); SDL_Quit(); return 0; } ``` 2. **OpenGL** 高性能3D/2D渲染,需结合GLUT或GLFW库实现。 --- ### 四、选择建议 | 方法 | 适用场景 | 学习曲线 | 跨平台性 | |-------------|-------------------------|----------|----------| | graphics.h | 教学/简单图形 | 低 | 差 | | Cairo | 矢量图形/高质量输出 | 中 | 优秀 | | SDL2 | 游戏/实时交互 | 中 | 优秀 | | OpenGL | 复杂3D图形/高性能渲染 | 高 | 优秀 | ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值