Paste Description for scale webcam linux
use for scaling webcam video on a linux machine (something I c.ouldn't find an app for)
- scale webcam linux
- Sunday, January 21st, 2007 at 7:12:41pm MST
- /*
- * 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;
- break;
- case SDLK_t: //toggle sonification on/off
- TOGGLE_threshold = (TOGGLE_threshold + 1) % 2;
- break;
- case SDLK_MINUS:
- if ((int) threshold_value - 8 >= 0) threshold_value-=8;
- break;
- case SDLK_EQUALS: //plus key
- if ((int) threshold_value + 8 <= 255) threshold_value+=8;
- break;
- }
- break;
- case SDL_QUIT:
- exit(0);
- }
- }
- } //END EVENT CODE
- }
- }
advertising
Update the Post
Either update this post and resubmit it with changes, or make a new post.
You may also comment on this post.
Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.