Mercurial > pidgin
view plugins/crazychat/camproc.c @ 13202:241c59e3906b
[gaim-migrate @ 15565]
fix sf bug #1413457
Having the horizontal scrollbar set to NEVER was causing weird
bugs with the new status dialog where typing into the imhtml would
cause the window to grow in width and the text would not wrap
(well, it would eventually).
I know having the horizontal scrollbar set to AUTOMATIC was causing
problems in the past, but I played around with it and everything
seems ok to me. If this becomes a problem I'm thinking we can
set it to the horizontal policy to NEVER for editable imhtmls when
using GTK < 2.4.0. I think maybe our use of GTK_WRAP_WORD_CHAR might
be a partial cause of the bug mentioned in the comment that I'm
removing.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 09 Feb 2006 04:40:32 +0000 |
parents | ed017b9c532d |
children |
line wrap: on
line source
/* * camproc.c * basecame * * Created by CS194 on Mon Apr 26 2004. * Copyright (c) 2004 __MyCompanyName__. All rights reserved. * */ #include "camdata.h" #include "Utilities.h" #include "QTUtilities.h" #include "stdio.h" #include "math.h" #include <gtk/gtk.h> #include "cc_interface.h" #include "filter.h" extern int detection_mode; extern mungDataPtr myMungData; extern int x_click; extern int y_click; #define kMinimumIdleDurationInMillis kEventDurationMillisecond #define BailErr(x) {if (x != noErr) goto bail;} #define PRE_CALIBRATE_MODE 0 #define CALIBRATE_MODE 1 #define SCAN_MODE 2 #define CALIB_TOP 190 #define CALIB_BOTTOM 200 #define CALIB_LEFT 200 #define CALIB_RIGHT 210 #define CALIB_RADIUS 5 #define NUM_FRAMES_EYE_SEARCH 50 #define EYE_UNCONFIDENCE_LIMIT 7 #define BLINK_THRESHOLD 75 #define BLINK_LENGTH 10 #define WHITE_THRESH 25 #define WHITE_COUNT_MAX 200 struct input_instance* instance; int scan_region_left; int scan_region_right; int scan_region_top; int scan_region_bottom; int lum_thresh=150; int face_left; int face_right; int face_top; int face_bottom; int old_left_eye_x=50; int old_left_eye_y=50; int old_right_eye_x=50; int old_right_eye_y=50; int left_eye_x; int left_eye_y; int right_eye_x; int right_eye_y; int eye_search_frame_count=0; int bozo_bit=0; int eye_unconfidence=0; int last_eye_count_left=0; int last_eye_count_right=0; int mouth_ctr_x; int mouth_ctr_y; int mouth_size, mouth_left, mouth_right, mouth_top, mouth_bottom; int white_count; guint8 head_size_old; int left_eye_blink_count; int right_eye_blink_count; int left_eye_top, left_eye_bottom, left_eye_right, left_eye_left; int right_eye_top, right_eye_bottom, right_eye_right, right_eye_left; filter_bank *bank; static SeqGrabComponent mSeqGrab = NULL; static SGChannel mSGChanVideo = NULL; static SGDataUPP mMyDataProcPtr = NULL; static EventLoopTimerRef mSGTimerRef = 0; static ImageSequence mDecomSeq = 0; static EventLoopTimerUPP mSGTimerUPP = nil; static Rect mMungRect = {0, 0, 480, 640}; int lower_left_corner_x = 200; int lower_left_corner_y = 200; int upper_right_corner_x = 210; int upper_right_corner_y = 190; static pascal OSErr MiniMungDataProc(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon); static pascal void SGIdlingTimer(EventLoopTimerRef inTimer, void *inUserData); static void DetectLobster(GWorldPtr mungDataOffscreen); int SkinDetect(double Y, double E, double S); void ScanSkin(PixMapHandle p); void drawbox(int top, int bottom, int left, int right, int color); void SkinStats (PixMapHandle p, int top, int bottom, int left, int right); void SetEyeSearchRegions(void); typedef enum {RED, GREEN, BLUE} color; color saved_best=-1; int filenum=0; OSErr CamProc(struct input_instance *inst, filter_bank *f) { OSStatus error; OSErr err = noErr; BailErr(err = InitializeMungData(mMungRect)); bank = f; instance=inst; mMyDataProcPtr = NewSGDataUPP(MiniMungDataProc); mSeqGrab = OpenDefaultComponent(SeqGrabComponentType, 0); BailErr((err = CreateNewSGChannelForRecording( mSeqGrab, mMyDataProcPtr, GetMungDataOffscreen(), // drawing destination &mMungRect, &mSGChanVideo, NULL))); bail: return err; } void QueryCam (void) { SGIdle(mSeqGrab); } static pascal void SGIdlingTimer(EventLoopTimerRef inTimer, void *inUserData) { #pragma unused(inUserData) if (mSeqGrab) { SGIdle(mSeqGrab); } // Reschedule the event loop timer SetEventLoopTimerNextFireTime(inTimer, kMinimumIdleDurationInMillis); } static pascal OSErr MiniMungDataProc(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon) { #pragma unused(offset,chRefCon,time,writeType,refCon) ComponentResult err = noErr; CodecFlags ignore; GWorldPtr gWorld; if (!myMungData) goto bail; gWorld = GetMungDataOffscreen(); if(gWorld) { if (mDecomSeq == 0) // init a decompression sequence { Rect bounds; GetMungDataBoundsRect(&bounds); BailErr( CreateDecompSeqForSGChannelData(c, &bounds, gWorld, &mDecomSeq)); if(1) //if ((!mUseOverlay) && (GetCurrentClamp() == -1) && (!mUseEffect)) { ImageSequence drawSeq; err = CreateDecompSeqForGWorldData( gWorld, &bounds, nil, GetMungDataWindowPort(), &drawSeq); SetMungDataDrawSeq(drawSeq); } } // decompress data to our offscreen gworld BailErr(DecompressSequenceFrameS(mDecomSeq,p,len,0,&ignore,nil)); // image is now in the GWorld - manipulate it at will! //if ((mUseOverlay) || (GetCurrentClamp() != -1) || (mUseEffect)) //{ // use our custom decompressor to "decompress" the data // to the screen with overlays or color clamping // BlitOneMungData(myMungData); //} //else //{ // we are doing a motion detect grab, so // search for lobsters in our image data DetectLobster(gWorld); //} } bail: return err; } void Die() { //RemoveEventLoopTimer(mSGTimerRef); // mSGTimerRef = nil; // DisposeEventLoopTimerUPP(mSGTimerUPP); DoCloseSG(mSeqGrab, mSGChanVideo, mMyDataProcPtr); } float Y_mean=-1; float Y_dev,E_mean,E_dev,S_mean,S_dev; /* extern colorBuf[480][640]; */ extern unsigned int (*colorBuf)[644]; extern struct input_instance input_data; static void DetectLobster(GWorldPtr mungDataOffscreen) { CGrafPtr oldPort; GDHandle oldDevice; int x, y; Rect bounds; PixMapHandle pix = GetGWorldPixMap(mungDataOffscreen); UInt32 * baseAddr; UInt32 reds = 0; Str255 tempString; int minX = 10000, maxX = -10000; int minY = 10000, maxY = -10000; Rect tempRect; float percent; OSErr err; CodecFlags ignore; color best; long R_total=0; long G_total=0; long B_total=0; //fprintf(stderr, "Starting to find some lobsters...\n"); GetPortBounds(mungDataOffscreen, &bounds); OffsetRect(&bounds, -bounds.left, -bounds.top); UInt32 color; int sum_x,sum_y=0; int count=0; int k,j; long R; long G; long B; int search_width=200; int search_height=200; colorBuf = GetPixBaseAddr(pix); switch (detection_mode) { case PRE_CALIBRATE_MODE: //drawbox(CALIB_TOP, CALIB_BOTTOM, CALIB_LEFT, CALIB_RIGHT); break; case CALIBRATE_MODE: SkinStats(pix, y_click-CALIB_RADIUS, y_click+CALIB_RADIUS, x_click-CALIB_RADIUS, x_click+CALIB_RADIUS); scan_region_left=x_click-CALIB_RADIUS;//10; scan_region_right=x_click+CALIB_RADIUS;//630; scan_region_top=y_click-CALIB_RADIUS;//10; scan_region_bottom=y_click+CALIB_RADIUS;//470; ScanSkin(pix); detection_mode=SCAN_MODE; //fprintf(stderr, "scan left: %d scan right: %d \n",scan_region_left,scan_region_right); head_size_old=50; break; case SCAN_MODE: ScanSkin(pix); drawbox(face_top, face_bottom, face_left, face_right,1); //drawbox(scan_region_top, scan_region_bottom, scan_region_left, scan_region_right); drawbox((left_eye_y-5),(left_eye_y+5),(left_eye_x-5),(left_eye_x+5),0); drawbox((right_eye_y-5),(right_eye_y+5),(right_eye_x-5),(right_eye_x+5),0); int face_scale=instance->face.head_size; int mouth_width=face_scale; int mouth_height=face_scale; // if (bozo_bit==1) drawbax((mouth_ctr_y-mouth_height),(mouth_ctr_y+mouth_height),(mouth_ctr_x-mouth_width),(mouth_ctr_x+mouth_width)); filter(&instance->face, bank); break; } //fprintf(stderr, "Lobsters found...\n"); } void ScanSkin(PixMapHandle p) { int y,x,j,k; int right_eye_x_sum,right_eye_y_sum,left_eye_x_sum,left_eye_y_sum,right_eye_pt_count,left_eye_pt_count; right_eye_x_sum=right_eye_y_sum=left_eye_x_sum=left_eye_y_sum=right_eye_pt_count=left_eye_pt_count=0; long R,G,B,sum_x,sum_y; int count; double Y,E,S,lum; double min_lum_mouth=766; double min_lum_left=766; double min_lum_right=766; UInt32 color; UInt32 * baseAddr; int max_horz=0; int max_vert=0; sum_x=sum_y=count=0; int horz_count[480]; int vert_count[640]; memset(horz_count,0,480*sizeof(int)); memset(vert_count,0,640*sizeof(int)); if (eye_search_frame_count<NUM_FRAMES_EYE_SEARCH) eye_search_frame_count++; else if (eye_search_frame_count==NUM_FRAMES_EYE_SEARCH && bozo_bit==0) { bozo_bit=1; //fprintf(stderr, "GOOD You flipped the bozo bit (to good)\n"); } SetEyeSearchRegions(); for (y = scan_region_top; y < scan_region_bottom; y++) // change this to only calculate in bounding box { baseAddr = (UInt32*)(GetPixBaseAddr(p) + y * GetPixRowBytes(p)); for (x = scan_region_left; x < scan_region_right; x++) { color=baseAddr[x]; R = (color & 0x00FF0000) >> 16; G = (color & 0x0000FF00) >> 8; B = (color & 0x000000FF) >> 0; Y=.253*R+.684*G+.063*B; E=.5*R-.5*G; S=.25*R+.25*G-.5*B; lum=R+G+B; if (y>left_eye_top && y<left_eye_bottom) { if (x > left_eye_left && x<left_eye_right) { if (lum < lum_thresh) { left_eye_x_sum+=x; left_eye_y_sum+=y; left_eye_pt_count++; //colorBuf[y][x]=0x0000FF00; } } } if (y>right_eye_top && y<right_eye_bottom) { if (x > right_eye_left && x < right_eye_right) { if (lum < lum_thresh) { right_eye_x_sum+=x; right_eye_y_sum+=y; right_eye_pt_count++; //colorBuf[y][x]=0x0000FF00; } } } if(SkinDetect(Y,E,S)) { sum_x+=x; sum_y+=y; count++; ++horz_count[y]; ++vert_count[x]; if (horz_count[y]>max_horz) max_horz=horz_count[y]; if (vert_count[x]>max_vert) max_vert=vert_count[x]; //colorBuf[y][x]=0x00FF0000; } } } left_eye_x=left_eye_x_sum/left_eye_pt_count; left_eye_y=left_eye_y_sum/left_eye_pt_count; right_eye_x=right_eye_x_sum/right_eye_pt_count; right_eye_y=right_eye_y_sum/right_eye_pt_count; int width=right_eye_x-left_eye_x; int height=right_eye_y-left_eye_y; double face_ang; if (width!=0) face_ang=atan((double)height/width); else face_ang=0; face_ang=face_ang*180/pi; //fprintf(stderr,"face angle: %f \n",face_ang); if ((left_eye_pt_count<5 || right_eye_pt_count<5 || width==0 || face_ang > 30 || face_ang < -30 || left_eye_y < (face_top+.15*(face_bottom-face_top)) || right_eye_y < (face_top+.15*(face_bottom-face_top))) && bozo_bit==1){ eye_unconfidence++; left_eye_x=old_left_eye_x; left_eye_y=old_left_eye_y; right_eye_x=old_right_eye_x; right_eye_y=old_right_eye_y; } else { eye_unconfidence=0; old_left_eye_x=left_eye_x; old_left_eye_y=left_eye_y; old_right_eye_x=right_eye_x; old_right_eye_y=right_eye_y; } if (eye_unconfidence==EYE_UNCONFIDENCE_LIMIT){ bozo_bit=0; eye_search_frame_count=0; //fprintf(stderr, "Recalibrating eyes\n"); } if ((last_eye_count_left-left_eye_pt_count> BLINK_THRESHOLD) && eye_unconfidence==0) { left_eye_blink_count=BLINK_LENGTH; } if (left_eye_blink_count>0){ instance->face.left_eye_open=0; left_eye_blink_count--; } else instance->face.left_eye_open=1; if ((last_eye_count_right-right_eye_pt_count> BLINK_THRESHOLD) && eye_unconfidence==0) { right_eye_blink_count=BLINK_LENGTH; } if (right_eye_blink_count>0){ instance->face.right_eye_open=0; right_eye_blink_count--; } else instance->face.right_eye_open=1; if (instance->face.right_eye_open==0) instance->face.left_eye_open=0; if (instance->face.left_eye_open==0) instance->face.right_eye_open=0; last_eye_count_left=left_eye_pt_count; last_eye_count_right=right_eye_pt_count; float x_shift=0; if (width!=0) x_shift= (float)height/(float)width; // --> note dependence on earlier data here if (bozo_bit==1){ int mouth_search_start_y=face_top+(.6*(face_bottom-face_top)); int mouth_search_end_y=face_bottom; int mouth_search_start_x=(left_eye_x+right_eye_x)/2 + (-x_shift*(mouth_search_start_y-((right_eye_y+left_eye_y)/2))) ; for (y=mouth_search_start_y; y < mouth_search_end_y; y++) { x=mouth_search_start_x+((y - mouth_search_start_y)*(-x_shift)); baseAddr = (UInt32*)(GetPixBaseAddr(p) + y * GetPixRowBytes(p)); //colorBuf[y][x] = 0x0000FF00; color=baseAddr[x]; R = (color & 0x00FF0000) >> 16; G = (color & 0x0000FF00) >> 8; B = (color & 0x000000FF) >> 0; lum=R+G+B; if (lum<min_lum_mouth) { min_lum_mouth=lum; mouth_ctr_x=x; mouth_ctr_y=y; } } mouth_size=(face_right-face_left)*100/640; mouth_left=mouth_ctr_x-mouth_size; if (mouth_left < face_left) mouth_left=face_left; mouth_right=mouth_ctr_x+mouth_size; if (mouth_right > face_right) mouth_right=face_right; mouth_top=mouth_ctr_y-mouth_size; if (mouth_top < face_top) mouth_top=face_top; mouth_bottom=mouth_ctr_y+mouth_size; if (mouth_bottom > face_bottom) mouth_bottom=face_bottom; white_count=0; for (y=mouth_top; y< mouth_bottom; y++){ baseAddr = (UInt32*)(GetPixBaseAddr(p) + y * GetPixRowBytes(p)); for (x=mouth_left; x< mouth_right; x++){ color=baseAddr[x]; R = (color & 0x00FF0000) >> 16; G = (color & 0x0000FF00) >> 8; B = (color & 0x000000FF) >> 0; if ((abs(R-G) < WHITE_THRESH) && (abs(G-B) < WHITE_THRESH) && (abs(R-B) < WHITE_THRESH)) { white_count++; //colorBuf[y][x]=0x0000FF00; } } } } else white_count=10; // This next section finds the face region and sets the face_* parameters. int scan; float thresh=.3; scan=scan_region_left+1; if (scan<0) scan=0; //fprintf(stderr,"threshold value: %d boxtop value: %d \n", (max_horz), horz_count[scan_region_top]); while(1) { if (vert_count[scan]>=(thresh*max_vert)) { face_left=scan; break; } scan++; } scan=scan_region_right-1; if (scan>=640) scan=639; while(1) { if (vert_count[scan]>=(thresh*max_vert)) { face_right=scan; break; } scan--; } scan=scan_region_top+1; if (scan<0) scan=0; while(1) { if (horz_count[scan]>=(thresh*max_horz)) { face_top=scan; break; } scan++; } scan=scan_region_bottom-1; if (scan>=480) scan=479; while(1) { if (horz_count[scan]>=(thresh*max_horz)) { face_bottom=scan; break; } scan--; } // Base scan region on face region here scan_region_left=face_left-10; if (scan_region_left <= 0) scan_region_left=1; scan_region_right=face_right+10; if (scan_region_right >= 640) scan_region_right=639; scan_region_top=face_top-10; if (scan_region_top <= 0) scan_region_top=1; scan_region_bottom=face_bottom+10; if (scan_region_bottom >= 480) scan_region_bottom=479; // Calculate some stats // face size width=face_right-face_left; guint8 temp=width*100/640; instance->face.head_size=temp; // face location temp=((double)100/(double)640)*(double)(face_right+face_left)/2; instance->face.x=temp; temp=((double)100/(double)480)*(double)(face_top+face_bottom)/2; instance->face.y=temp; // face angle-Z instance->face.head_z_rot=face_ang+50; // face angle-Y int center=(face_right+face_left)/2; int right_eye_strad=right_eye_x-center; int left_eye_strad=center-left_eye_x; double y_ang; if (right_eye_strad > left_eye_strad) y_ang= (double)right_eye_strad/(double)left_eye_strad; else y_ang=(double)left_eye_strad/(double)right_eye_strad; y_ang=y_ang*5; if (y_ang >= 10) y_ang=30; if (y_ang <= 1) y_ang=1; if (right_eye_strad > left_eye_strad) y_ang=-y_ang; temp = (guint8) 50 + y_ang; instance->face.head_y_rot=temp; if (abs (temp-50) > 15) instance->face.head_size=head_size_old; else head_size_old=instance->face.head_size; temp = (guint8) 100 * white_count / WHITE_COUNT_MAX; if (temp > 100) temp=100; instance->face.mouth_open = temp; } // draw bounding box for either calibration or face void SetEyeSearchRegions(void) { if (bozo_bit==0) { left_eye_top=face_top+(.25*(face_bottom-face_top)); left_eye_bottom=face_top+(.6*(face_bottom-face_top)); left_eye_right=((face_left+face_right)/2); left_eye_left=face_left+.15*(face_right-face_left); right_eye_top=face_top+(.25*(face_bottom-face_top)); right_eye_bottom=face_top+(.6*(face_bottom-face_top)); right_eye_right=face_right-.15*(face_right-face_left); right_eye_left=((face_left+face_right)/2); } if (bozo_bit==1) { left_eye_top=left_eye_y-20; left_eye_bottom=left_eye_y+20; left_eye_left=left_eye_x-20; left_eye_right=left_eye_x+20; right_eye_top=right_eye_y-20; right_eye_bottom=right_eye_y+20; right_eye_left=right_eye_x-20; right_eye_right=right_eye_x+20; } } void drawbox(int top, int bottom, int left, int right, int color) { int y, x, j; unsigned int col; if (color==1) col=0x00FFFF00; else col=0x00FF00FF; if (top<0) top =0; if (top>=480) top=479; if (bottom<0) bottom =0; if (bottom>=480) bottom=479; if (left<0) left =0; if (left>=640) left=639; if (right<0) right =0; if (right>=640) right=639; if (color==1){ for (y=top; y<bottom; y++) { for (j=0;j<5;j++){ colorBuf[y][left+j] = col; colorBuf[y][right-j] = col; } } for (x=left; x<right; x++) { for (j=0;j<5;j++){ colorBuf[bottom-j][x] = col; colorBuf[top+j][x] = col; } } } else { for (y=top; y<bottom; y++) { for (x=left;x<right;x++){ colorBuf[y][x] = col; colorBuf[y][x] = col; } } } } void SkinStats (PixMapHandle p, int top, int bottom, int left, int right) { double Y_sum,E_sum,S_sum; int R,G,B; int count=0; Y_sum=E_sum=S_sum=0; double Y,E,S; UInt32 color; int x, y; UInt32 * baseAddr; for (y=top; y<bottom; y++) { baseAddr = (UInt32*)(GetPixBaseAddr(p) + y * GetPixRowBytes(p)); for (x=left; x<right; x++) { count++; color=baseAddr[x]; R = (color & 0x00FF0000) >> 16; G = (color & 0x0000FF00) >> 8; B = (color & 0x000000FF) >> 0; Y=.253*R+.684*G+.063*B; E=.5*R-.5*G; S=.25*R+.25*G-.5*B; Y_sum+=Y; E_sum+=E; S_sum+=S; } } Y_mean=Y_sum/count; E_mean=E_sum/count; S_mean=S_sum/count; Y_sum=E_sum=S_sum=0; for (y=top; y<bottom; y++) { baseAddr = (UInt32*)(GetPixBaseAddr(p) + y * GetPixRowBytes(p)); for (x=left; x<right; x++) { color=baseAddr[x]; R = (color & 0x00FF0000) >> 16; G = (color & 0x0000FF00) >> 8; B = (color & 0x000000FF) >> 0; Y=.253*R+.684*G+.063*B; E=.5*R-.5*G; S=.25*R+.25*G-.5*B; Y_sum+=(Y-Y_mean)*(Y-Y_mean); E_sum+=(E-E_mean)*(E-E_mean); S_sum+=(S-S_mean)*(S-S_mean); } } Y_dev=sqrt(Y_sum/(count-1)); E_dev=sqrt(E_sum/(count-1)); S_dev=sqrt(S_sum/(count-1)); //fprintf(stderr,"Y: %f, %f\n E: %f, %f\nS: %f, %f\n",Y_mean,E_mean,S_mean,Y_dev,E_dev,S_dev); } int SkinDetect(double Y, double E, double S) { if (E>(E_mean-(2*E_dev)) && E<(E_mean+(2*E_dev))) return 1; else return 0; }