All pastes #324188 Raw Edit

scale webcam linux

public c v1 · immutable
#324188 ·published 2007-01-22 02:12 UTC
rendered paste body
/* * cam_hacks.c * does strange things to a video feed * GPL - based on Jaromil's hasciicam * Thank you Rasta Coder! You are the man! *//*    NOTE    I removed the YtoRGB thinghhy because it was causing    some black pixels to become white. It was annoying!        TODO    fix beating    fix 16-bit*/#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <getopt.h>#include <errno.h>#include <fcntl.h>#include <ctype.h>#include <sys/time.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <pwd.h>#include <signal.h>    #include <SDL/SDL.h>    #include <linux/soundcard.h>#include <linux/types.h>#include <linux/videodev.h>        #define IMAGE_WIDTH  300 //the clip is divided up into this number of segments#define IMAGE_HEIGHT 200 //this is the number of frequencies...    #define SCALE 4#define SCREEN_WIDTH IMAGE_WIDTH*SCALE#define SCREEN_HEIGHT IMAGE_HEIGHT*SCALE    char device[256];int quiet = 0;int mode = 0;int useftp = 0;int input = 1;int daemon_mode = 0;int TOGGLE_invert = 0;int TOGGLE_threshold = 0;unsigned char threshold_value = 128;struct geometry {  int w, h, size;  int bright, contrast, gamma; };  struct geometry vid_geo;  /* if width&height have been manually changed */  int whchanged = 0;  char device[256];  int have_tuner = 0;/* v4l */unsigned char *grab_data;struct video_capability grab_cap;struct video_mbuf grab_map;struct video_mmap grab_buf[32];struct video_channel grab_chan;struct video_picture grab_pic;struct video_tuner grab_tuner;int minw, minh, maxw, maxh;int dev = -1;int cur_frame, ok_frame;int palette;/* rgb image is sampled */unsigned char *rgb_surface;void setpixel(SDL_Surface *screen, int x, int y, Uint8 r, Uint8 g, Uint8 b){  Uint8 *ubuff8;  Uint16 *ubuff16;  Uint32 *ubuff32;  Uint32 color;  char c1, c2, c3;    /* Lock the screen, if needed */  if(SDL_MUSTLOCK(screen)) {    if(SDL_LockSurface(screen) < 0)       return;  }    /* Get the color */  color = SDL_MapRGB( screen->format, r, g, b );    /* How we draw the pixel depends on the bitdepth */  switch(screen->format->BytesPerPixel)   {    case 1:       ubuff8 = (Uint8*) screen->pixels;      ubuff8 += (y * screen->pitch) + x;       *ubuff8 = (Uint8) color;      break;    case 2:      ubuff8 = (Uint8*) screen->pixels;      ubuff8 += (y * screen->pitch) + (x*2);      ubuff16 = (Uint16*) ubuff8;      *ubuff16 = (Uint16) color;       break;      case 3:      ubuff8 = (Uint8*) screen->pixels;      ubuff8 += (y * screen->pitch) + (x*3);            if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {        c1 = (color & 0xFF0000) >> 16;        c2 = (color & 0x00FF00) >> 8;        c3 = (color & 0x0000FF);      } else {        c3 = (color & 0xFF0000) >> 16;        c2 = (color & 0x00FF00) >> 8;        c1 = (color & 0x0000FF);	      }      ubuff8[0] = c3;      ubuff8[1] = c2;      ubuff8[2] = c1;      break;          case 4:      ubuff8 = (Uint8*) screen->pixels;      ubuff8 += (y*screen->pitch) + (x*4);      ubuff32 = (Uint32*)ubuff8;      *ubuff32 = color;      break;          default:      fprintf(stderr, "Error: Unknown bitdepth!\n");  }    /* Unlock the screen if needed */  if(SDL_MUSTLOCK(screen)) {    SDL_UnlockSurface(screen);  }}int vid_detect(char *devfile) {  int counter, res;  char *capabilities[] = {    "VID_TYPE_CAPTURE          can capture to memory",    "VID_TYPE_TUNER            has a tuner of some form",    "VID_TYPE_TELETEXT         has teletext capability",    "VID_TYPE_OVERLAY          can overlay its image to video",    "VID_TYPE_CHROMAKEY        overlay is chromakeyed",    "VID_TYPE_CLIPPING         overlay clipping supported",    "VID_TYPE_FRAMERAM         overlay overwrites video memory",    "VID_TYPE_SCALES           supports image scaling",    "VID_TYPE_MONOCHROME       image capture is grey scale only",    "VID_TYPE_SUBCAPTURE       capture can be of only part of the image"  };  if (-1 == (dev = open(devfile,O_RDWR|O_NONBLOCK))) {    perror("!! error in opening video capture device: ");    return -1;  } else {    close(dev);    dev = open(devfile,O_RDWR);  }    res = ioctl(dev,VIDIOCGCAP,&grab_cap);  if(res<0) {    perror("E' QUESTOOO!!!!!! error in VIDIOCGCAP: ");    return -1;  }  fprintf(stderr,"Device detected is %s\n",devfile);  fprintf(stderr,"%s\n",grab_cap.name);  fprintf(stderr,"%u channels detected\n",grab_cap.channels);  fprintf(stderr,"max size w[%u] h[%u] - min size w[%u] h[%u]\n",grab_cap.maxwidth,grab_cap.maxheight,grab_cap.minwidth,grab_cap.minheight);  fprintf(stderr,"Video capabilities:\n");  for (counter=0;counter<11;counter++)    if (grab_cap.type & (1 << counter)) fprintf(stderr,"%s\n",capabilities[counter]);    if (-1 == ioctl(dev, VIDIOCGPICT, &grab_pic)) {    perror("!! ioctl VIDIOCGPICT: ");    exit(1);  }    if (grab_pic.palette & VIDEO_PALETTE_RGB32)    fprintf(stderr,"VIDEO_PALETTE_GREY        device is able to grab 32-bit RGB\n");    if(grab_cap.type & VID_TYPE_TUNER)    /* if the device does'nt has any tuner, so we avoid some ioctl    this should be a fix for many webcams, thanks to Ben Wilson */    have_tuner = 1;    /* set and check the minwidth and minheight */  minw = grab_cap.minwidth;  minh = grab_cap.minheight;  maxw = grab_cap.maxwidth;  maxh = grab_cap.maxheight;  if (ioctl (dev, VIDIOCGMBUF, &grab_map) == -1) {    perror("!! error in ioctl VIDIOCGMBUF: ");    return -1;  }  /* print memory info */  fprintf(stderr,"memory map of %i frames: %i bytes\n",grab_map.frames,grab_map.size);  for(counter=0;counter<grab_map.frames;counter++)    fprintf(stderr,"Offset of frame %i: %i\n",counter,grab_map.offsets[counter]);  return dev;}int vid_init() {  int linespace = 5;  int i;  /* set image source and TV norm */  grab_chan.channel = input = (grab_cap.channels>1) ? 1 : 0;    if(have_tuner) { /* does this only if the device has a tuner */    //   _band = 5; /* default band is europe west */    //   _freq = 0;    /* resets CHAN */    if (-1 == ioctl(dev,VIDIOCGCHAN,&grab_chan))      fprintf(stderr,"!! error in ioctl VIDIOCGCHAN: %s",strerror(errno));    if (-1 == ioctl(dev,VIDIOCSCHAN,&grab_chan))      fprintf(stderr,"error in ioctl VIDIOCSCHAN: %s",strerror(errno));        /* get/set TUNER settings */    if (-1 == ioctl(dev,VIDIOCGTUNER,&grab_tuner))      fprintf(stderr,"error in ioctl VIDIOCGTUNER: %s",strerror(errno));  }  /* init video size from ascii size  1 ascii pixel = 4 video pixel  so video h&w are each double than ascii */  vid_geo.h = IMAGE_HEIGHT;  vid_geo.w = IMAGE_WIDTH;  vid_geo.size = vid_geo.w*vid_geo.h;  palette =VIDEO_PALETTE_RGB24;  rgb_surface = (unsigned char *) malloc (vid_geo.size*3); //we need space for all three channels (3*8 = 24bit)  //#############CONTROLL PALETTE##################  /*VIDEO_PALETTE_RGB24;/*VIDEO_PALETTE_YUV420P;VIDEO_PALETTE_RGB32;/V4L2_PIX_FMT_SBGGR8;V4L2_PIX_FMT_SN9C10X; VIDEO_PALETTE_YUV422;*/  for(i=0; i<grab_map.frames; i++) {    grab_buf[i].format = palette; //RGB24;    grab_buf[i].frame  = i;    grab_buf[i].height = vid_geo.h;    grab_buf[i].width = vid_geo.w;  }     if (-1 == ioctl(dev,VIDIOCMCAPTURE,&grab_buf[0])) {        /*palette=VIDEO_PALETTE_YUV420P;    for(i=0; i<grab_map.frames; i++) {      grab_buf[i].format = palette; //RGB24;    }    if (-1 == ioctl(dev,VIDIOCMCAPTURE,&grab_buf[0])) {      fprintf(stderr,"error in ioctl VIDIOCMCAPTURE: %s",strerror(errno));    }*/    fprintf(stderr,"error: VIDEO_PALETTE_RGB24 doesn't seem to work");  }  grab_data = mmap (0, grab_map.size, PROT_READ | PROT_WRITE, MAP_SHARED, dev, 0);  if (MAP_FAILED == grab_data) {    perror ("Cannot allocate video4linux grabber buffer ");    exit (1); }    /* feed up the mmapped frames */    if (-1 == ioctl(dev,VIDIOCMCAPTURE,&grab_buf[0])) {      fprintf(stderr,"error in ioctl VIDIOCMCAPTURE: %s",strerror(errno));    }		    cur_frame = ok_frame = 0;    return dev;}unsigned char *grab_one () {  int c = 0, cc=0;  /* we use just one frame  no matters about the capability of the cam  this makes grabbing much faster on my webcam  i hope also on yours  ok_frame = cur_frame;  cur_frame = (cur_frame>=grab_map.frames) ? 0 : cur_frame+1;  */  ok_frame = 0; cur_frame = 0;  grab_buf[ok_frame].format = palette;  if (-1 == ioctl(dev,VIDIOCSYNC,&grab_buf[ok_frame])) {    perror("error in ioctl VIDIOCSYNC: ");    return NULL;  }  grab_buf[cur_frame].format = palette;  if (-1 == ioctl(dev,VIDIOCMCAPTURE,&grab_buf[cur_frame])) {    perror("error in ioctl VIDIOCMCAPTURE: ");    return NULL;  }    for (c=0,cc=0;c<vid_geo.size;c++,cc+=3)  {    rgb_surface[c*3] = grab_data[grab_map.offsets[ok_frame] + cc + 2];    //red // was 2    rgb_surface[c*3+1] = grab_data[grab_map.offsets[ok_frame] + cc + 1];  //blue // 1    rgb_surface[c*3+2] = grab_data[grab_map.offsets[ok_frame] + cc + 0];  //green      }    return rgb_surface;}unsigned char get_red(int x, int y){  return rgb_surface[(x+y*IMAGE_WIDTH)*3];}unsigned char get_blue(int x, int y){  return rgb_surface[(x+y*IMAGE_WIDTH)*3+2];}unsigned char get_green(int x, int y){  return rgb_surface[(x+y*IMAGE_WIDTH)*3+1];}unsigned char get_rd(int x, int y){  unsigned char r, g, b;       r = get_red(x,y);       b = get_blue(x,y);       g = get_green(x,y);       return 255 * r / (b + g + r + 1);}unsigned char thresh(unsigned char i){  if (i >= threshold_value) i = 255; else i = 0;  return i;}int main(){  int fd;	/* sound device file descriptor */  int arg;	/* argument for ioctl calls */  int status;   /* return status of system calls */    int row, column;    unsigned char r,g,b,grey,ahh;    float power;    float pointer_x=0, pointer_y=0;  int frame_count = 0;    int found_pointer = 0;      int s_cap = 50;      //BALL  float bx = 10, by = 10, bxs = 3, bys = 0;  float f, dist;    /* Declare SDL Variables */  SDL_Surface *screen;  SDL_Event event;      SDL_Rect temp_rect;    /* Initialize SDL, exit if there is an error. */  if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {    fprintf(stderr, "Could not initialize SDL: %s\n", 	    SDL_GetError());    return -1;  }    /* When the program is through executing, call SDL_Quit */  atexit(SDL_Quit);    /* Grab a surface on the screen */  screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_SWSURFACE|SDL_ANYFORMAT);  if( !screen ) {    fprintf(stderr, "Couldn't create a surface: %s\n",	    SDL_GetError());    return -1;  }      struct stat st;  if( stat("/dev/video",&st) <0)    strcpy(device,"/dev/video0");  else    strcpy(device,"/dev/video");      //***Attempt detection of capture device***  if( vid_detect(device) > 0 ) {    vid_init();  } else    exit(-1);      while (1) { /* loop until Control-C */        //capture a frame from the webcam and store it in a rgb_surfacescale bitmap    grab_one();    found_pointer = 0;           //display the image    for (row = 0; row < IMAGE_HEIGHT; row++)    {      for (column = 0; column < IMAGE_WIDTH; column++)      {       temp_rect.x = column*SCALE;       temp_rect.y = row*SCALE;       temp_rect.w = SCALE;       temp_rect.h = SCALE;              ahh = 0;                     power =             thresh(get_rd(column+1,row-1))           + thresh(get_rd(column+1,row))           + thresh(get_rd(column+1,row+1))           + thresh(get_rd(column,row-1))           + thresh(get_rd(column,row))           + thresh(get_rd(column,row+1))           + thresh(get_rd(column-1,row-1))           + thresh(get_rd(column-1,row))           + thresh(get_rd(column-1,row+1));              power = power / 9;                    /*       power =       get_rd(column+1,row-1)       + get_rd(column+1,row)       + get_rd(column+1,row+1)       + get_rd(column,row-1)       + get_rd(column,row)       + get_rd(column,row+1)       + get_rd(column-1,row-1)       + get_rd(column-1,row)       + get_rd(column-1,row+1);              power = power / 9;                            power =       get_rd(column+1,row-1)       * get_rd(column+1,row)       * get_rd(column+1,row+1)       * get_rd(column,row-1)       * get_rd(column,row)       * get_rd(column,row+1)       * get_rd(column-1,row-1)       * get_rd(column-1,row)       * get_rd(column-1,row+1);              power = pow(power, 1/9);       */              if (power > 130)        {         grey = 255;                  if (found_pointer == 0)         {          found_pointer = 1;          pointer_x = (pointer_x+column*SCALE)/2;          pointer_y = (pointer_y+row*SCALE)/2;          ahh = 255;         }                       } else grey = 0;              //if (grey > threshold_value) grey = 255; else grey + 0;              r = get_red(column,row);       b = get_blue(column,row);       g = get_green(column,row);              //SDL_FillRect( screen, &temp_rect, SDL_MapRGB(screen->format,r*power/255,g*power/255,b*power/255));       SDL_FillRect( screen, &temp_rect, SDL_MapRGB(screen->format,r,g,b));      }        }        //draw pointer    temp_rect.x = pointer_x-5;    temp_rect.y = pointer_y-5;    temp_rect.w = 10;    temp_rect.h = 10;    SDL_FillRect( screen, &temp_rect, SDL_MapRGB(screen->format,0,0,255));        //deal with the ball    bx += bxs; by += bys; //move the ball    bys += 2; //planitary gravity    bxs *= .97; bys *= .97; //dampen motion    if (by > SCREEN_HEIGHT) bys = -bys; //bounce!    if (bx < 0) {bxs = abs(bxs) + .1; bx = 1;}    if (bx > SCREEN_WIDTH) {bxs = -abs(bxs) - .1; by = SCREEN_WIDTH-1;}    //display the "ball"    temp_rect.x = bx-5;    temp_rect.y = by-5;    temp_rect.w = 10;    temp_rect.h = 10;    SDL_FillRect( screen, &temp_rect, SDL_MapRGB(screen->format,0,255,0));    //repel from pointer    dist = sqrt(pow((pointer_x - bx),2) + pow((pointer_y-by),2)); /* Calculate distance */    if (dist < 30) f = -30 / pow(dist,2); //calculate force    bxs += f*(pointer_x-bx); /* Influence object in correct direction */    bys += f*(pointer_y-by);    if (bxs > s_cap) bxs = s_cap;    if (bxs < -s_cap) bxs = -s_cap;    if (bys > s_cap) bys = s_cap;    if (bys < -s_cap) bys = -s_cap;        //make the changes to the screen visable    SDL_Flip(screen);                  //clear screen    SDL_FillRect( screen, NULL, SDL_MapRGB(screen->format,0,0,0) );        //test for events    {      SDL_PumpEvents();      SDL_Event event;      while ( SDL_PollEvent(&event) ) {        switch (event.type) {          case SDL_KEYDOWN:            switch (event.key.keysym.sym) {              case SDLK_i:                TOGGLE_invert = (TOGGLE_invert + 1) % 2;                printf("invert filter = %d\n",TOGGLE_invert);                 break;                case SDLK_t: //toggle sonification on/off                  TOGGLE_threshold = (TOGGLE_threshold + 1) % 2;                  printf("threshold filter = %d\n",TOGGLE_threshold);                   break;              case SDLK_MINUS:                if ((int) threshold_value - 8 >= 0) threshold_value-=8;                printf("threshold value = %d\n", threshold_value);                break;                case SDLK_EQUALS: //plus key                  if ((int) threshold_value + 8 <= 255) threshold_value+=8;                  printf("threshold value = %d\n", threshold_value);                  break;            }            break;          case SDL_QUIT:            exit(0);        }      }    } //END EVENT CODE                  }}