精华内容
下载资源
问答
  • C语言高级应用

    千次阅读 2008-05-29 08:28:00
    C语言经典编程,希望大家喜欢/*这是一个卫星围绕地球的程序。*/#include#include#include#include#define IMAGE_SIZE 10void draw_image(int x,int y);void putstar(void);main(){ int driver=DETECT; int mode,...
    C语言经典编程,希望大家喜欢
    /*这是一个卫星围绕地球的程序。*/
    #include<graphics.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<conio.h>
    #define IMAGE_SIZE 10
    void draw_image(int x,int y);
    void putstar(void);

    main()
    {
      int driver=DETECT;
      int mode,color;
      void *pt_addr;
      int x,y,maxy,maxx,midy,midx,i;
      unsigned size;
      initgraph(&driver,&mode,"");
      maxx=getmaxx(); /*取允许的最大x 值*/
      maxy=getmaxy(); /*取允许的最大y 值*/
      midx=maxx/2;
      x=0;
      midy=y=maxy/2;
      settextstyle(TRIPLEX_FONT,HORIZ_DIR,4);    /*定义文本字型函数*/
      settextjustify(CENTER_TEXT,CENTER_TEXT);    /**/
      outtextxy(midx,400,"AROUND THE WORLD");
      setbkcolor(BLACK);
      setcolor(RED);
      setlinestyle(SOLID_LINE,0,THICK_WIDTH);
      ellipse(midx,midy,130,50,160,30);
      setlinestyle(SOLID_LINE,0,NORM_WIDTH);
      draw_image(x,y); /*画飞船*/
      size=imagesize(x,y-IMAGE_SIZE,x+(4*IMAGE_SIZE),y+IMAGE_SIZE);
      pt_addr=malloc(size);
      getimage(x,y-IMAGE_SIZE,x+(4*IMAGE_SIZE),y+IMAGE_SIZE,pt_addr);
      putstar();
      setcolor(WHITE);
      setlinestyle(SOLID_LINE,0,NORM_WIDTH);
      rectangle(0,0,maxx,maxy); /*画方框*/
      while (!kbhit())
      {
        putstar();
        setcolor(RED); /*画一个围绕地球的光环*/
        setlinestyle(SOLID_LINE,0,THICK_WIDTH);
        ellipse(midx,midy,130,50,160,30);
        setcolor(BLACK);
        ellipse(midx,midy,130,50,160,30);
        for (i=0;i<=13;i++) /*画地球*/
        {
          setcolor(i%2==0 ? LIGHTBLUE:BLACK);
          ellipse(midx,midy,0,360,100-8*i,100);
          setcolor(LIGHTBLUE);
          ellipse(midx,midy,0,360,100,100-8*i);
        }
        putimage(x,y-IMAGE_SIZE,pt_addr,XOR_PUT);/*恢复原画面*/
        x=x>=maxx?0:x+6;
        putimage(x,y-IMAGE_SIZE,pt_addr,COPY_PUT);/*在另一个位置显示飞船*/
        }
        free(pt_addr);
        closegraph();
        return;
    }


    void draw_image(int x,int y) /*画飞船*/
    {
        int arw[11];
        arw[0]=x+10; arw[1]=y-10;
        arw[2]=x+34; arw[3]=y-6;
        arw[4]=x+34; arw[5]=y+6;
        arw[6]=x+10; arw[7]=y+10;
        arw[8]=x+10; arw[9]=y-10;
        moveto(x+10,y-4);
        setcolor(14);
        setfillstyle(1,4);
        linerel(-3*10,-2*8); /*画尾部天线*/
        moveto(x+10,y+4);
        linerel(-3*10,+2*8);
        moveto(x+10,y);
        linerel(-3*10,0);
        setcolor(3);
        setfillstyle(1,LIGHTBLUE);/*画本体*/
        fillpoly(4,arw);
    }

    void putstar(void) /*画星星*/
    {
        int seed=1858;
        int i,dotx,doty,h,w,color,maxcolor;
        maxcolor=getmaxcolor(); /*得到当前模式和最多颜色数*/
        w=getmaxx();
        h=getmaxy();
        srand(seed);
        for(i=0;i<250;++i)
        {
            dotx=i+random(w-1);
            doty=1+random(h-1);
            color=random(maxcolor);
            setcolor(color);
            putpixel(dotx,doty,color);/*用点表示小星*/
            circle(dotx+1,doty+1,1);/*用圆表示大星*/
        }
        srand(seed);
    }
    展开全文
  • c语言高级应用程序

    2018-01-24 11:21:27
    因为必须要资源分,就给个最低2分吧,主要是想分享一下,欢迎下载,
  • 我自己整理编写的一本关于c语言高级(或者说有意思)的应用开发技巧与方式
  • 实用文案 C 语言程序设计报告 学生管理系统 2010 年 7 月 20 标准文档 实用文案 日 报告人姓名 学号 一 设 计 流 程 密码验证 三次 三 次 正 确 错 误 主菜单 打开文件...机会三次都错误系统自动退出程序 2 菜单操作 程
  • C语言多级指针的实用

    1、多级指针快排

    [摘要] 本节内容取材于实际应用中,有较高的学习价值,故将源程序整理于此,大家可以分析分析,详细的解析将在下面给出。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int getArrayMem(char*** mp, char* myArray1[], int n, char* str, int* count);
    int sortArray(char** p, int count);
    int SortArrayAndGen3Mem(char*** myArray3, char* myArray1[], int n, char* str, int* num);
    int printArray(char** p, int num);
    int freeArray(char*** newFree, int num);
    
    int main(void)
    {
    int ret = 0;
    char **myArray3 = NULL;
    int num3 = 0;
    //第一种内存模型
    char *myArray[] = {"bbbbb", "aaa", "ccccccc"};//指针数组
    char *myp = "1111111ddd";//字符数组
    //要求:将myArray和myp合并为一个字符串存到myArray3里,排序后甩出来
    SortArrayAndGen3Mem(&myArray3, myArray, 3, myp, &num3);
    printf("\n排序之后:\n");
    ret = printArray(myArray3, num3);
    if(0 != ret)
    {
    printf("func printArray() err:%d\n", ret);
    return ret;
    }
    
    if(NULL != myArray3)
    {
    ret = freeArray(&myArray3, num3);
    if(0 != ret)
    {
    printf("func freeArray() err:%d\n", ret);
    return ret;
    }
    }
    system("pause");
    }
    
    int SortArrayAndGen3Mem(char*** myArray3, char* myArray1[], int n, char* str, int* num)
    {
    int i = 0, j = 0, count = 0;
    char** myp = NULL;
    getArrayMem(&myp, myArray1, n, str, &count);
    
    for(i = 0; i < n; i++)
    {
    strcpy(myp[i], myArray1[i]);
    }
    strcpy(myp[i], str);
    printf("排序之前:\n");
    printArray(myp, count);
    sortArray(myp, count);
    *num = count;
    *myArray3 = myp;
    }
    
    int sortArray(char** p, int count)
    {
    char tmp[100];
    int i = 0, j = 0;
    for(i = 0; i < count - 1; i++)
    {
    for(j = i + 1; j < count - 1; j++)
    {
    if(strcmp(p[i], p[j]) > 0)
    { 
    strcpy(tmp, p[i]);
    strcpy(p[i], p[j]);
    strcpy(p[j], tmp);
    }
    }
    
    }
    }
    
    int getArrayMem(char*** mp, char* myArray1[], int n, char* str, int* count)
    {
    int tmpNum = 0, i = 0, tmpCount = 0, rv = 0;
    char** p = NULL;
    tmpNum = n + 1;
    p = (char**)malloc(tmpNum*sizeof(char*));
    if(NULL == p)
    {
    rv = -1;
    printf("func getArrayMem() NULL == p err:%d\n", rv);
    return rv;
    }
    
    for(i = 0; i < n; i++, tmpCount++)
    {
    p[i] = (char*)malloc((strlen(myArray1[i])*sizeof(char))+1);
    if(NULL == p[i])
    {
    rv = -1;
    printf("func getArrayMem() NULL == p[i] err:%d\n", rv);
    return rv;
    }
    }
    p[i] = (char*)malloc((strlen(str)*sizeof(char))+1);
    if(NULL == p[i])
    {
    rv = -1;
    printf("func getArrayMem() NULL == p[i] err:%d\n", rv);
    return rv;
    }
    tmpCount++;
    *count = tmpCount;
    
    *mp = p;
    }
    
    int printArray(char** p, int num)
    {
    int i = 0, rv = 0;
    if(NULL == p)
    {
    rv = -1;
    printf("NULL == p err:%d\n", rv);
    return rv;
    }
    
    for(i = 0; i < num; i++)
    {
    printf("%s\n", p[i]);
    }
    
    return rv;
    }
    
    int freeArray(char*** newFree, int num)
    {
    int rv = 0, i = 0;
    char** tmpArray = NULL;
    tmpArray = *newFree;
    if(NULL == newFree)
    {
    rv = -1;
    printf("ULL == newFree err:%d\n", rv);
    return rv;
    }
    for(i = 0; i < num; i++)
    {
    if(NULL != tmpArray[i])
    {
    free(tmpArray[i]);
    }
    }
    free(tmpArray);
    *newFree = NULL;
    //if(NULL != tmpArray)
    //{
    //free(tmpArray);
    //tmpArray = NULL;
    //}
    
    return rv;
    }

    2、多级指针辅助知识

    引言:我深知大家对于指针是既爱又恨,起初我又何尝不是呢?说爱他是因为大师们都说指针是C的精髓,没有学会指针就没有掌握C的要义;说恨他是因为太危险,一不小心就“爆机”了。容我冒昧的引用林语堂老先生《朱门》里的那句:“只用一样东西,不明白它的道理,实在不高明!”况且处于启蒙的我们,就像侯俊杰先生说的“勿在浮沙筑高台。”

    先说明些东西:

    #include <stdio.h>

    void main()

    {

         char str[]="zllzllzll";

         char *p=str;

         printf("str   = %p        p      = %p   \n",str,p);

         printf("str+1 = %p        &str +1= %p\n",str +1,&str +1);

         printf("p+1   = %p\n",p+1);

    }

    这段程序运行的结果如下(不同的机器稍有偏差,但理论没问题):

    注意:这里的str+与&str+1是不同的;

    解析如下:str与&str的值是一样的,都是指向数组str第一个元素的地址,但是str+1与&str+1却是不一样的。因为str指向的是char类型的指针但&str指向的是char[10]类型的指针,所以(str+1)增加的是1而(&str+1)增加的是10*1=10.

    现在正式开始我们的万里长征

    #include <stdio.h>

    void main()

    {

        int *p1=NULL,*p2=NULL,*p3=NULL,*p4=NULL;

        int temp=8;

        int *p=NULL;

      p4  = (int *)(&temp);//---->其实完全可以写作p4=&temp 

      p3  = (int *)(&p4);  //但编译器很笨,它要检查类型是否

      p2 = (int *)(&p3);  //匹配,所以(int *是我们无耐写给编译器看的

      p1 = (int *)(&p2);  //p1到p其实就是依次取得下一级的变量地址给上一级

      p  = (int *)(&p1);

        printf("%d \n",*(int *)(*(int *)(*(int *)(*(int *)(*p)))));

     }

    对于printf这个函数调用解释一下。之所以上面有很多(int *),是为了告诉编译器从此地址开始取多少位,就像前面说的那样,编译器很笨,它不知道你在想什么,事实上你也不明它是怎么想的。

    怕否?不碍事,慢慢看。现在张结构图,助于理解。

     

    本来这张图已经很直白的表达了我的意思,然我欲当回老者,多啰嗦几句。为此先说明下规则:下面的’----->’以及‘=’这两个的意思是一样的,而非语言本身之所表达的意思。

    /*从上往下看,在配以上图,可谓之妙哉!*/

    *p                      -----> &p1

    *(*p)                   ----->*(&p1) = &p2

    *(*(*p))                 ----->*(&p2) = &p3

    *(*(*(*p)))               ----->*(&p3)=&p4

    *(*(*(*(*p))))            ----->*(&p4)=&temp

    *(*(*(*(*(*p)))))          ----->*(&temp)=temp---->8

    不要烦躁,上面的式子是可以化简的 如:

    printf("%d \n",*(**** (int *****)p));

    来说说思路吧。int那边的5个‘*’,这么解释,源程序中的标号所示的5个语句,每次对p进行取内容时,都需要告诉编译器取4个字节长,共取5次,所以要告诉编译器5次。

    到现在还没出现所谓的n级指针,总是有总见林不见鸟的感觉,可别觉得我在忽悠你呀,这不,下面就来了。。。。。

        int *p1=NULL,*p2=NULL,*p3=NULL,*p4=NULL;

           int temp=8;

           int *****p=NULL;

           p4 = (int *)(&temp);//---->其实完全可以写作p4=&temp

           p3 = (int *)(&p4);  //但编译器很笨,它要检查类型是否

           p2 = (int *)(&p3); //匹配,所以(int *是我们无耐写给编译器看的

           p1 = (int *)(&p2); //p1到p其实就是依次取得下一级的变量地址给上一级

          p  = (int *****)(&p1);//这也实属无耐,VC6.0的类型检查太严了,直接                          //给的error,而在GCC下给个警告而已,然谁又会怪                      // 罪于“苛求”呢?那是好事

        printf("%d \n",*(*(*(*(*p)))));//当然这些括号’(’是可以去掉的,我

                                      //不愿已简洁换取‘涩’,至于你如何如            //何,那是你的事了,呵呵。

        

    释惑:你会问:“这边为什么不用加(int *)?”我会释:“因为定义时 int *****p”就已经告诉编译器了,所以我跟喜欢用这种写法玩多级指针,一来省事,二来还略显牛逼(原谅我的粗俗)。

      这边还用前面的图示,我有点懒,呵呵

    至此多级指针的要义差不多就完了,也没写出什么来。但这几张图足以解释多级指针了,或许你还想知道指针与数组的关系,没事,那是下次文章该做的事。

    问你们个问题:你们C语言老师肯定说过:“指针只能进行减法而不能进行加法运算”这么说对吗?我不知道,或许知道,但你自己着实该自己尝试着分析,以擎高(深)升

    其实,这篇文章是为下次我讲链表做的铺垫,或许当时也是这么玩的,但毕竟不方便,才有了后来的………

    提示你一下:如果把图中的小方框中间在画一条竖线你想到了什么?

    这讲主要是为“C语言高级应用——多级指针快排”那篇做铺垫,下面解决问题时会用到本讲的内容



    展开全文
  • C语言高级应用---操作linux下V4L2摄像头应用程序

    万次阅读 多人点赞 2016-03-28 22:27:48
    我们都知道,想要驱动linux下的摄像头,其实很简单,照着V4L2的手册一步步来写,很快就可以写出来,但是在写之前我们要注意改变系统的一些配置,使系统支持framebuffer,在dev下产生fb0这样的节点,这样我们才能在...

    我们都知道,想要驱动linux下的摄像头,其实很简单,照着V4L2的手册一步步来写,很快就可以写出来,但是在写之前我们要注意改变系统的一些配置,使系统支持framebuffer,在dev下产生fb0这样的节点,这样我们才能在linux系统上操作Camera摄像头,framebuffer在之前的博文已经有说过了,这里就不再提了。

    有需要了解framebuffer的那么请点击:http://baike.baidu.com/view/3351639.htm

           最重要的,我们需要改一个脚本,在/dev/grub.conf,我们来看看怎么改:

    # grub.conf generated by anaconda
    #
    # Note that you do not have to rerun grub after making changes to this file
    # NOTICE:  You have a /boot partition.  This means that
    #          all kernel and initrd paths are relative to /boot/, eg.
    #          root (hd0,0)
    #          kernel /vmlinuz-version ro root=/dev/sdb2
    #          initrd /initrd-[generic-]version.img
    #boot=/dev/sdb
    default=0
    timeout=5
    splashimage=(hd0,0)/grub/splash.xpm.gz
    hiddenmenu
    title CentOS (2.6.32-431.el6.i686)
    	root (hd0,0)
    	kernel /vmlinuz-2.6.32-431.el6.i686 ro root=UUID=2bc12537-d6c1-4e67-b4e5-e9c466205554 nomodeset rd_NO_LUKS  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_MD crashkernel=auto LANG=zh_CN.UTF-8 rd_NO_LVM rd_NO_DM rhgb quiet vga=0x318
    	initrd /initramfs-2.6.32-431.el6.i686.img
    

    通常情况下,要让framebuffer生效,要加一句vga=???(这里是参数),简单介绍一下:

    我写vga=0x318就是默认就设置为1024x768x24bpp模式。当然还有其它的模式:如下图,根据自己的系统来配置。
    色彩 640x400 640x480 800x600 1024x768 1280x1024 1600x1200
    4bits ? ? 0x302 ? ? ?
    8bits 0x300 0x301 0x303 0x305 0x307 0x31C
    15bits ? 0x310 0x313 0x316 0x319 0x31D
    16bits ? 0x311 0x314 0x317 0x31A 0x31E
    24bits ? 0x312 0x315 0x318 0x31B 0x31F
    32bits ? ? ? ? ? ?
    配置完成以后,我们先来了解一下V4L2的主要功能。
    V4L2就使程序有发现设备和操作设备的能力.它主要是用一系列的回调函数来实现这些功能。像设置摄像头的频率、帧频、视频压缩格式和图像参数等等。当然也可以用于其他多媒体的开发,如音频等。
    但是此框架只能运行在Linux操作系统之上。v4L2是针对uvc免驱usb设备的编程框架 ,主要用于采集usb摄像头等,编程模式如下:

    采集方式

    打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:
    extern int ioctl (int __fd, unsigned long int __request, …) __THROW;
    __fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd;
    __request:具体的命令标志符。
    在进行V4L2开发中,一般会用到以下的命令标志符:
    VIDIOC_REQBUFS:分配内存
    VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
    VIDIOC_QUERYCAP:查询驱动功能
    VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
    VIDIOC_S_FMT:设置当前驱动的频捕获格式
    VIDIOC_G_FMT:读取当前驱动的频捕获格式
    VIDIOC_TRY_FMT:验证当前驱动的显示格式
    VIDIOC_CROPCAP:查询驱动的修剪能力
    VIDIOC_S_CROP:设置视频信号的边框
    VIDIOC_G_CROP:读取视频信号的边框
    VIDIOC_QBUF:把数据放回缓存队列
    VIDIOC_DQBUF:把数据从缓存中读取出来
    VIDIOC_STREAMON:开始视频显示函数
    VIDIOC_STREAMOFF:结束视频显示函数
    VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
    这些IO调用,有些是必须的,有些是可选择的。

    V4L2操作流程:点击这个网址,说得很详细了,这里不多说。

    http://baike.baidu.com/view/5494174.htm

    接下来我们来看看实战部分,下面是我自己写的程序接口,可以实现视频采集:生气
    1、project.c
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include "j-yuv.h"
    #include "CameralOpt.h"
    #include "FrameBufferOpt.h"
    
    #define    WIDTH   640
    #define    HIGHT   480
    
    int main(void)
    {
    	char yuyv[WIDTH*HIGHT*2];
    	char bmp[WIDTH*HIGHT*3];
    
    //	set_bmp_header((struct bmp_header_t *)bmp, WIDTH, HIGHT);
    	//初始化摄像头
    	Init_Cameral(WIDTH , HIGHT );
    	//初始化framebuffer
    	Init_FrameBuffer(WIDTH , HIGHT ); 
    
    	//开启摄像头
    	Start_Cameral();
    	//采集一张图片
    	int count = 0 ; 
    	while(1)
    	{
    		Get_Picture(yuyv);
    		yuyv2rgb24(yuyv, bmp, WIDTH, HIGHT);
    		Write_FrameBuffer(bmp);
    //		printf("count:%d \n" , count++);
    	}
    	//关闭摄像头
    	Stop_Cameral();
    	//关闭Framebuffer
    	Exit_Framebuffer();
    	//退出
    	Exit_Cameral();
    	
    	return 0;
    }
    
    
    2、juv.h
    #ifndef __JYUV_H
    #define __JYUV_H
    
    typedef unsigned char  u8;
    typedef unsigned short u16;
    typedef unsigned int   u32;
    
    #pragma pack(1)
    //定义bmp头
    struct bmp_header_t{
        u16        magic;
        u32       file_size;
        u32       RESERVED1;
        u32       offset;         //54 bytes 表示54个偏移量
    
        u32       head_num;    //40
        u32       width;
        u32       height;
        u16       color_planes; //1
        u16       bit_count;
        u32       bit_compression; //0
        u32       image_size; //except the size of header
        u32       h_resolution;
        u32       v_resolution;
        u32       color_num;
        u32       important_colors;
    };
    
    #pragma pack()
    
    void set_bmp_header(struct bmp_header_t * header, u32 width, u32 height);
    int yuyv2rgb24(u8 *yuyv, u8 *rgb, u32 width, u32 height);
    
    #endif /* __JYUV_H */ 
    3、juv.c
    #include "j-yuv.h"
    
    #define BIT_COUNT   24
    
    void set_bmp_header(struct bmp_header_t *header, u32 width, u32 height)
    {
        header->magic = 0x4d42;
        header->image_size = width * height * BIT_COUNT/8;
        header->file_size = header->image_size + 54;
        header->RESERVED1 = 0;
        header->offset = 54;
    
        header->head_num = 40;
        header->width = width;
        header->height = height;
        header->color_planes = 1;
        header->bit_count = BIT_COUNT;
        header->bit_compression = 0;
        header->h_resolution = 0;
        header->v_resolution = 0;
        header->color_num = 0;
        header->important_colors = 0;
    }
    //yuyv转rgb24的算法实现
    int yuyv2rgb24(u8 *yuyv, u8 *rgb, u32 width, u32 height)
    {
        u32 i, in, rgb_index = 0;
        u8 y0, u0, y1, v1;
        int r, g, b;
        u32 out = 0, x, y;
     
        for(in = 0; in < width * height * 2; in += 4)
        {
    	y0 = yuyv[in+0];
    	u0 = yuyv[in+1];
    	y1 = yuyv[in+2];
    	v1 = yuyv[in+3];
    
    	for (i = 0; i < 2; i++)
    	{
    		if (i)
    			y = y1;
    		else
    			y = y0;	
    		r = y + (140 * (v1-128))/100;  //r
    		g = y - (34 * (u0-128))/100 - (71 * (v1-128))/100; //g
     		b = y + (177 * (u0-128))/100; //b
    		if(r > 255)   r = 255;
            	if(g > 255)   g = 255;
            	if(b > 255)   b = 255;
           		if(r < 0)     r = 0;
            	if(g < 0)     g = 0;
    	        if(b < 0)     b = 0;
    
    		y = height - rgb_index/width -1;
    		x = rgb_index%width;
    		rgb[(y*width+x)*3+0] = b;
    		rgb[(y*width+x)*3+1] = g;
    		rgb[(y*width+x)*3+2] = r;
    		rgb_index++;
    	}
        }
        return 0;
    }
    
    
    4、FrameBufferOpt.c
    #include "FrameBufferOpt.h"
    
    static int Frame_fd ; 
    static int *FrameBuffer = NULL ; 
    static int W , H ;
    
    //初始化framebuffer
    int Init_FrameBuffer(int Width , int Higth)
    {
    	W = Width ; 
    	H = Higth ; 
    	Frame_fd = open("/dev/fb" , O_RDWR);
    	if(-1 == Frame_fd)
    	{
    		perror("open frame buffer fail");
    		return -1 ; 
    	}
    
    //根本就不用CPU搬运   用DMA做为搬运工
    FrameBuffer = mmap(0, 1280*1024*4 , PROT_READ | PROT_WRITE , MAP_SHARED , Frame_fd ,0 );
    	if(FrameBuffer == (void *)-1)
    	{
    		perror("memory map fail");
    		return -2 ;
    	}
    	return 0 ; 
    }
    
    //写入framebuffer
    int Write_FrameBuffer(const char *buffer)
    {
    	int row  , col ; 
    	char *p = NULL ; 
    	for(row = 0 ; row <1024 ; row++)
    	{
    		for(col = 0 ; col < 1280 ;  col++)
    		{
    			if((row < H)  && (col < W))
    			{
    				p = (char *)(buffer + (row * W+ col ) * 3); 
    				FrameBuffer[row*1280+col] = RGB((unsigned char)(*(p+2)),(unsigned char)(*(p+1)),(unsigned char )(*p));
    			}
    		}
    	}
    	return 0 ; 
    }
    
    //退出framebuffer
    int Exit_Framebuffer(void)
    {
    	munmap(FrameBuffer ,  W*H*4);
    	close(Frame_fd);
    	return 0 ; 
    }
    
    
    5、FrameBufferOpt.h
    #ifndef  _FRAMEBUFFEROPT_H
    #define  _FRAMEBUFFEROPT_H
    
    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/mman.h>
    
    
    #define    RGB(r,g,b)		((r<<16)|(g<<8)|b)
    
    //初始化ramebuffer
    int Init_FrameBuffer(int Width , int Higth);
    
    //写数据到framebuffer
    int Write_FrameBuffer(const char *buffer);
    
    //退出framebuffer
    int Exit_Framebuffer(void);
    
    
    
    #endif //_FRAMEBUFFEROPT_H
    
    6、CameralOpt.h
    #ifndef  _CAMERALOPT_H
    #define  _CAMERALOPT_H
    
    #include <stdio.h>
    #include <linux/videodev2.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/mman.h>
    
    #define   COUNT  3
    //初始化摄像头
    int Init_Cameral(int Width , int Hight);
    int Exit_Cameral(void); //退出摄像头
    //摄像头开始采集
    int Start_Cameral(void);
    int Stop_Cameral(void);//停止摄像头
    //获取摄像头的数据
    int Get_Picture(char *buffer);
    
    #endif  //_CAMERALOPT_H
    
    7、CameralOpt.c
    #include "CameralOpt.h"
    int video_fd ; 
    int length ; 
    char *yuv[COUNT] ; 
    struct v4l2_buffer  enqueue  , dequeue ;  //定义出入队的操作结构体成员
    
    int Init_Cameral(int Width , int Hight)
    {
    	//参数检查
    	char *videodevname = NULL ; 
    	videodevname = "/dev/video0" ; 
    	
    	//打开设备
    	video_fd = open(videodevname , O_RDWR);
    	if(-1 == video_fd )
    	{
    		perror("open video device fail");
    		return -1 ; 
    	}
    
    	int i ; 
    	int ret ; 
    	struct v4l2_format  format ; 
    	format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
    	format.fmt.pix.width  = Width; 
    	format.fmt.pix.height = Hight; 
    	format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV ;  //我支持的格式是这个
    
    	ret = ioctl(video_fd , VIDIOC_S_FMT , &format);
    	if(ret != 0)
    	{
    		perror("set video format fail");
    		return -2 ; 
    	}
    
    
    	//申请buffer,切割成几个部分
    	//3
    	struct v4l2_requestbuffers  requestbuffer ; 
    	requestbuffer.count = COUNT ; 
    	requestbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
    	requestbuffer.memory = V4L2_MEMORY_MMAP ; 
    
    	ret = ioctl(video_fd , VIDIOC_REQBUFS , &requestbuffer);
    	if(ret != 0)
    	{
    		perror("request buffer fail ");
    		return -3  ;
    	}
    	
    	
    	//querybuffer
    	struct v4l2_buffer querybuffer ; 
    	querybuffer.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
    	querybuffer.memory = V4L2_MEMORY_MMAP ; 
    
    	for(i = 0 ; i < COUNT ; i++)
    	{
    		querybuffer.index = i ; 	
    
    		ret = ioctl(video_fd , VIDIOC_QUERYBUF , &querybuffer);
    		if(ret != 0)
    		{
    			perror("query buffer fail");
    			return -4 ; 
    		}
    	
    //		printf("index:%d length:%d  offset:%d \n" , 
    //		querybuffer.index , querybuffer.length , querybuffer.m.offset);
    		length = querybuffer.length ; 
    
    		//将摄像头内存印射到进程的内存地址
    		yuv[i] = mmap(0,querybuffer.length , PROT_READ | PROT_WRITE , MAP_SHARED , video_fd , querybuffer.m.offset );
    
    
    		//列队
    		
    		struct v4l2_buffer  queuebuffer ; 
    		queuebuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
    		queuebuffer.memory =  V4L2_MEMORY_MMAP ; 
    		queuebuffer.index = i ; 	
    
    		ret = ioctl(video_fd , VIDIOC_QBUF , &queuebuffer);
    		if(ret != 0)
    		{
    			perror("queuebuffer fail");
    			return -5 ; 
    		}
    	}
    	//初始化入队出队
    	enqueue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
    	dequeue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
    	enqueue.memory = V4L2_MEMORY_MMAP ; 
    	dequeue.memory = V4L2_MEMORY_MMAP ; 
    
    	return 0 ; 
    }
    
    int Exit_Cameral(void)
    {
    	int i ; 
    	for(i = 0 ; i < COUNT ; i++)
    		munmap(yuv+i , length);
    	close(video_fd);
    	return 0 ; 
    }
    
    int Start_Cameral(void)
    {
    	//开启摄像头
    	int ret ; 
    	int on = 1 ; 
    	ret = ioctl(video_fd , VIDIOC_STREAMON , &on);
    	if(ret != 0)
    	{
    		perror("start Cameral fail");
    		return -1 ; 
    	}
    	return 0 ; 
    }
    int Stop_Cameral(void)
    {
    	//停止摄像头
    	int ret ; 
    	int off= 1 ; 
    	ret = ioctl(video_fd , VIDIOC_STREAMOFF, &off);
    	if(ret != 0)
    	{
    		perror("stop Cameral fail");
    		return -1 ; 
    	}
    	return 0 ;
    }
    
    int Get_Picture(char *buffer)
    {
    	int ret ; 
    	//出队
    	ret = ioctl(video_fd , VIDIOC_DQBUF , &dequeue);
    	if(ret != 0)
    	{
    		perror("dequeue fail");
    		return -1 ; 
    	}
    
    	//获取图片数据 YUV   yuv[dequeue.index]
    	memcpy(buffer , yuv[dequeue.index] , dequeue.length);
    //	write(yuyv_fd , yuv[dequeue.index] , dequeue.length);
    
    	enqueue.index = dequeue.index ; 
    	ret = ioctl(video_fd , VIDIOC_QBUF , &enqueue);
    	if(ret != 0)
    	{
    		perror("enqueue fail");
    		return -2 ; 
    	}
    	return 0 ; 
    }
    
    


    运行结果:楼主本人大笑大笑,长得丑别喷。大哭
    画面其实是一直在动的,只是我拍了一张图片而已。










    展开全文
  • 目录一、C语言预处理理论1、由源码到可执行程序的过程2、预处理的意义3、预处理器处理的命令(后面有详解)4、gcc当中如何只预处理不编译二、预处理器工作内容详解1、头文件包含 一、C语言预处理理论 1、由源码到可...

    一、C语言预处理理论

    1、由源码到可执行程序的过程

    由粗略到详细

    源码.c——>(编译)elf可执行程序
    源码.c——>(编译)目标文件.o——>(链接)elf可执行程序
    源码.c——>(编译)汇编文件.S——>(汇编)目标文件.o——>(链接)elf可执行程序
    源码.c——>(预处理)预处理过的.i源文件——>(编译)汇编文件.S——>(汇编)目标文件.o——>(链接)elf可执行程序

    预处理用预处理器,编译用编译器,汇编用汇编器,链接用链接器,这几个工具再加上其他一些额外的会用到的可用工具,合起来叫编译工具链gcc就是一个编译工具链

    2、预处理的意义

    为了帮助 编译器 做一些杂事, 让我们的编译器专心工作(只专心于将 .c 文件转化为 .S 文件)

    所以就是为了将分工明确。让编译器的功能更加聚焦

    3、预处理器处理的命令(后面有详解)

    • #include(#include <>和#include ""的区别)
    • 注释
    • #if #elif #endif #ifdef (条件编译)
    • 宏定义

    4、gcc当中如何只预处理不编译

    gcc -E xx.c -o xx.i
    -E 可以设定我们只预处理不编译
    可以实现只预处理不编译。一般情况下没必要只预处理不编译,但有时候这种技巧可以用来帮助我们研究预处理过程,帮助debug程序。

    补充 gcc 的一些其他用法:

    gcc xx.c -o xx可以指定可执行程序的名称
    gcc hello.c -o hello.out :将我们可执行程序指定名称为 hello.out,不指定的话默认是 a.out

    gcc xx.c -c -o xx.o可以指定只编译不连接,也可以生成.o的目标文件
    -c 规定我们只编译不进行链接。

    举例分析:

    • gcc -E a.c -o a.i
      在这里插入图片描述

    总结:
    第一,宏定义语句本身不见了(可见编译器根本就不认识#define,编译器根本不知道还有个宏定义);

    第二,typedef重命名语言还在,说明它和宏定义是有本质区别的(说明typedef是由编译器来处理而不是预处理器处理的);

    二、预处理器工作内容详解

    1、头文件包含

    #include < > 和 #include" "的区别:

    • < >的特点:
      专门用来包含系统提供的头文件(就是系统自带的,不是程序员自己写的)

    规则:

    C语言编译器只会到系统指定目录(编译器中配置的或者操作系统配置的寻找目录,譬如在ubuntu中是/usr/include目录,

    编译器还允许用-I来附加指定其他的包含路径)去寻找这个头文件(隐含意思就是不会找当前目录下),如果找不到就会提示这个头文件不存在。

    举例:
    在这里插入图片描述

    • " "的特点:
      专门用来存放程序员在本文件夹下面,自己写的头文件。

    举例:
    在这里插入图片描述

    2、注释(预处理器将其去掉)

    3、条件编译

    (1)有时候我们希望程序有多种配置,我们在源代码编写时写好了各种配置的代码,然后给个配置开关,在源代码级别去修改配置开关来让程序编译出不同的效果。

    (2)条件编译中用的两种条件判定方法分别是 #ifdef 和 #if
    区别:

    #ifdef XXX判定条件成立与否时主要是看XXX这个符号在本语句之前有没有被定义,
    只要定义了(我们可以直接#define XXX或者#define XXX 12或者#define XXX YYY)这个符号就是成立的。

    #if (条件表达式),它的判定标准是()中的表达式是否为true还是flase,跟C中的if语句有点像。

    三、宏定义

    1、括号问题

    宏定义主要的问题:
    1、宏定义是在预编译阶段,直接替换。 所以我们要注意符号的优先级。
    例如:

    #define X(a,b) a+b
    c = 3*X(a,b)  
    c = 3* a+b;     这并不是我们想要的结果
    

    常规做法:用 “()” 将我们的每个部分都括起来。
    注:我们每个小部分都需要括号。 最后 整体 再加上括号

    #define x(a,b)    ( (a) + (b) )
    

    2、常用的示例

    • 求最大值 (三目运算符, ? 和 :)
      注意逻辑: 先从最里面的开始写, 写一个逻辑括一个括号
    #define MAX(a,b) ( ( (a) > (b) ) ? (a) : (b) )
    
    • SEC_PER_YEAR ------- 一年有多少秒
    #define SEC_PER_YEAR (365* 24* 60*60)
    

    注:直接这样写会溢出
    1、一个数字,直接使用,在c编译器当中,默认是 int 类型,所以我们这个会超过 int 的范围
    2、有符号数 和 无符号数。 ----- 无符号数用 %u 来打印
    3、int :4个字节, long : 8个字节。
    将这个整数,转化为 无符号的long型

    4、 这个 UL 必须放在括号里面。

    #define SEC_PER_YEAR (365* 24* 60*60UL)
    unsigned int l = SEC_PER_YEAR;
    printf("l = %u",l)

    3、带参数的宏, 带参数的函数 的区别

    (1)调用开销:

    • 带参数的宏是直接展开,在预处理阶段就完成, 所以没有任何调用开销。
    • 函数会跳转到我们的函数体当中去执行程序,然后再跳转回来。 ---- 效率比较低

    (2)参数检查

    • 宏定义没有参数检查。 ----- 程序员编写过程中要小心。
    • 函数在编译阶段, 编译器会给我们进行参数类型核对,如果我们发生错误,编译器会提醒报数。

    4、内联函数 inline 关键字的使用

    作用:

    • 本质是一个函数, 有函数的优点, 编译器帮助我们进行 静态类型检查。 (编译器处理,和预处理器没有关系

    • 也有宏定义的优点,就是在代码当中,会原地展开,减小调用开销。

    总结:内联函数就相当于 带着静态类型检查 的参数宏。

    使用情况:
    函数很短,我们既希望减小调用开销,又希望可以进行参数检测。

    5、条件编译

    1、#ifdef
    分析:

    • 如果前面有定义 DEBUG,将 debug(x) 替换成 printf(x)
    • 否则 debug(x) 就会定义成 空(也就是什么也没有)

    在大型程序当中, 我们会有很多调试信息, 所以就会有 debug 版本,和 release 版本。
    debug:加一个宏定义。 release :去掉这个宏定义。

    #define DEBUG
    
    #ifdef DEBUG
    #define debug(x)  printf(x)
    #else
    #define debug(x)
    #endif
    
    void main()
    {
    debug("This is a info");
    }
    
    

    2、undef:注销宏
    意思:就是注销掉 DEBUG 这个宏。

    #define DEBUG
    #undef DEBUG
    

    四、函数

    1、函数的本质

    展开全文
  • 转自:http://blog.csdn.net/morixinguan/article/details/51001713 版权声明:本文为博主原创文章,如有需要,请注明转载...若是侵权用于商业用途,请联系博主,否则将追究责任 目录(?)[-] 采集方式 V4L2操...
  • p[5],c语言编译器,发现p 先和 [5] 结合,所以 p 就是一个数组(4*5=20字节的大小)。 int * (p[6]), 说明在这个数组当中,都是 int * 类型的指针。 int (*p) : 可以看出 p 先和 * 结合,所以它本质是一个指针(4...
  • 1、const修饰指针的4种形式 (1)const关键字,在C语言中用来修饰变量,表示这个变量是常量。 (2)const修饰指针有4种形式,区分清楚这4种即可全部理解const和指针。 第一种:const int *p; p本身不是cosnt的,而p...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,262
精华内容 904
关键字:

c语言高级应用

c语言 订阅