kernels/linux-2.4.0/drivers/usb/ibmcam.c
/*
 * usb_ibmcam_model2_parse_lines()
 *
 * This procedure deals with a weird RGB format that is produced by IBM
 * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175,
 * depending on horizontal size of the picture:
 *
 * <--- 160 or 176 pairs of RA,RB bytes ----->
 * *-----------------------------------------* \
 * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx |  \
 * |-----+-----+-----+-----+ ... +-----+-----|   *- This is pair of horizontal lines,
 * | B0  | G0  | B1  | G1  | ... | Bx  | Gx  |  /   total 240 or 288 lines (120 or 144
 * |=====+=====+=====+=====+ ... +=====+=====| /    such pairs).
 *
 * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1
 * defines ONE pixel. Therefore this format yields 176x144 "decoded"
 * resolution at best. I do not know why camera sends such format - the
 * previous model just used I420 and everyone was happy.
 *
 * I do not know what is the difference between RAi and RBi bytes. Both
 * seemingly represent R component, but slightly vary in value (so that
 * the picture looks a bit colored if one or another is used). I use
 * them both as R component in attempt to at least partially recover the
 * lost resolution.
 */
usb_ibmcam_model2_parse_lines()
This procedure deals with a weird RGB format that is produced by IBM
camera model 2 in modes 320x240 and above; 'x' below is 159 or 175,
depending on horizontal size of the picture.



Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1
defines ONE pixel. Therefore this format yields 176x144 "decoded"
resolution at best. I do not know why camera sends such format - the
previous model just used I420 and everyone was happy.

I do not know what is the difference between RAi and RBi bytes. Both
seemingly represent R component, but slightly vary in value (so that
the picture looks a bit colored if one or another is used). I use
them both as R component in attempt to at least partially recover the
lost resolution.
usb_ibmcam_model2_parse_lines () This procedure deals with a weird RGB format that is produced by IBM camera model 2 in modes 320x240 and above ; ' x ' below is 159 or 175 depending on horizontal size of the picture . Each group of FOUR bytes ( RAi RBi Bi Gi ) where i = 0 .. frame_width / 2 - 1 defines ONE pixel . Therefore this format yields 176x144 " decoded " resolution at best . I do not know why camera sends such format - the previous model just used I420 and everyone was happy . I do not know what is the difference between RAi and RBi bytes . Both seemingly represent R component but slightly vary in value ( so that the picture looks a bit colored if one or another is used ) . I use them both as R component in attempt to at least partially recover the lost resolution .
static scan_state_t usb_ibmcam_model2_parse_lines(struct usb_ibmcam *ibmcam, long *pcopylen)
{
	struct ibmcam_frame *frame;
	unsigned char *data, *f, *la, *lb;
	unsigned int len;
	const int v4l_linesize = imgwidth * V4L_BYTES_PER_PIXEL;	
	int i, j, frame_done=0, color_corr;
	color_corr = (ibmcam->vpic.colour) >> 8; 
	data = ibmcam->scratch;
	frame = &ibmcam->frame[ibmcam->curframe];
	len = frame->frmwidth * 2; 
	if (scratch_left(data) < (len+32)) {
		return scan_Out;
	}
	if ((frame->curline + 1) >= V4L_FRAME_HEIGHT)
		return scan_NextFrame;
	if ((frame->curline & 1) == 0) {
		la = data;
		lb = data + frame->frmwidth;
	} else {
		la = data + frame->frmwidth;
		lb = data;
	}
	f = frame->data + (v4l_linesize * frame->curline);
	for (i = 0; i < frame->frmwidth; i++) {
		int y, rv, gv, bv;	
		j = i & (~1);
		if ((flags & FLAGS_DISPLAY_HINTS) && (ibmcam->has_hdr)) {
			if (ibmcam->has_hdr == 1) {
				bv = 0; 
				gv = 0xFF;
				rv = 0xFF;
			} else {
				bv = 0xFF; 
				gv = 0xFF;
				rv = 0;
			}
			ibmcam->has_hdr = 0;
			goto make_pixel;
		}
		rv = la[i];
		gv = lb[j + 1];
		bv = lb[j + 0];
		y = (rv + gv + bv) / 3; 
		if (flags & FLAGS_MONOCHROME) 
			rv = gv = bv = y;
		else if (color_corr != 128) {
			rv -= y;
			gv -= y;
			bv -= y;
			rv = (rv * color_corr) / 128;
			gv = (gv * color_corr) / 128;
			bv = (bv * color_corr) / 128;
			rv += y;
			gv += y;
			bv += y;
			RESTRICT_TO_RANGE(rv, 0, 255);
			RESTRICT_TO_RANGE(gv, 0, 255);
			RESTRICT_TO_RANGE(bv, 0, 255);
		}
	make_pixel:
		IBMCAM_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
		IBMCAM_PUTPIXEL(frame, i, frame->curline+1, rv, gv, bv);
	}
	frame->curline += 2;
	*pcopylen += v4l_linesize * 2;
	data += frame->frmwidth * 2;
	usb_ibmcam_align_scratch(ibmcam, data);
	if (frame_done || (frame->curline >= frame->frmheight))
		return scan_NextFrame;
	else
		return scan_Continue;
}
static scan_state_t usb_ibmcam_model2_parse_lines ( struct usb_ibmcam * ibmcam , long * pcopylen ) { struct ibmcam_frame * frame ; unsigned char * data , * f , * la , * lb ; unsigned int len ; const int v4l_linesize = imgwidth * V4L_BYTES_PER_PIXEL ; int i , j , frame_done = 0 , color_corr ; color_corr = ( ibmcam -> vpic . colour ) >> 8 ; data = ibmcam -> scratch ; frame = & ibmcam -> frame [ ibmcam -> curframe ] ; len = frame -> frmwidth * 2 ; if ( scratch_left ( data ) < ( len + 32 ) ) { return scan_Out ; } if ( ( frame -> curline + 1 ) >= V4L_FRAME_HEIGHT ) return scan_NextFrame ; if ( ( frame -> curline & 1 ) == 0 ) { la = data ; lb = data + frame -> frmwidth ; } else { la = data + frame -> frmwidth ; lb = data ; } f = frame -> data + ( v4l_linesize * frame -> curline ) ; for ( i = 0 ; i < frame -> frmwidth ; i ++ ) { int y , rv , gv , bv ; j = i & ( ~ 1 ) ; if ( ( flags & FLAGS_DISPLAY_HINTS ) && ( ibmcam -> has_hdr ) ) { if ( ibmcam -> has_hdr == 1 ) { bv = 0 ; gv = 0xFF ; rv = 0xFF ; } else { bv = 0xFF ; gv = 0xFF ; rv = 0 ; } ibmcam -> has_hdr = 0 ; goto make_pixel ; } rv = la [ i ] ; gv = lb [ j + 1 ] ; bv = lb [ j + 0 ] ; y = ( rv + gv + bv ) / 3 ; if ( flags & FLAGS_MONOCHROME ) rv = gv = bv = y ; else if ( color_corr != 128 ) { rv -= y ; gv -= y ; bv -= y ; rv = ( rv * color_corr ) / 128 ; gv = ( gv * color_corr ) / 128 ; bv = ( bv * color_corr ) / 128 ; rv += y ; gv += y ; bv += y ; RESTRICT_TO_RANGE ( rv , 0 , 255 ) ; RESTRICT_TO_RANGE ( gv , 0 , 255 ) ; RESTRICT_TO_RANGE ( bv , 0 , 255 ) ; } make_pixel : IBMCAM_PUTPIXEL ( frame , i , frame -> curline , rv , gv , bv ) ; IBMCAM_PUTPIXEL ( frame , i , frame -> curline + 1 , rv , gv , bv ) ; } frame -> curline += 2 ; * pcopylen += v4l_linesize * 2 ; data += frame -> frmwidth * 2 ; usb_ibmcam_align_scratch ( ibmcam , data ) ; if ( frame_done || ( frame -> curline >= frame -> frmheight ) ) return scan_NextFrame ; else return scan_Continue ; }
usb_ibmcam_model2_parse_lines()
 This procedure deals with a weird RGB format that is produced by IBM
 camera model 2 in modes 320x240 and above; 'x' below is 159 or 175,
 depending on horizontal size of the picture:
usb_ibmcam_model2_parse_lines () This procedure deals with a weird RGB format that is produced by IBM camera model 2 in modes 320x240 and above ; ' x ' below is 159 or 175 depending on horizontal size of the picture :
/* V4L line offset */ /* 0..+255 */ /* Here we deal with pairs of horizontal lines */ /* 2 lines */ /*printk(KERN_DEBUG "len=%d. left=%d.\n",len,scratch_left(data));*/ /* Make sure there's enough data for the entire line */ /*printk(KERN_DEBUG "out of data, need %u.\n", len);*/ /*
	 * Make sure that our writing into output buffer
	 * will not exceed the buffer. Mind that we may write
	 * not into current output scanline but in several after
	 * it as well (if we enlarge image vertically.)
	 */ /*
	 * Now we are sure that entire line (representing all 'frame->frmwidth'
	 * pixels from the camera) is available in the scratch buffer. We
	 * start copying the line left-aligned to the V4L buffer (which
	 * might be larger - not smaller, hopefully). If the camera
	 * line is shorter then we should pad the V4L buffer with something
	 * (black in this case) to complete the line.
	 */ /* Fill the 2-line strip */ /* RGB components */ /* Check for various visual debugging hints (colorized pixels) */ /* Yellow marker */ /* Cyan marker */ /*
		 * Here I use RA and RB components, one per physical pixel.
		 * This causes fine vertical grid on the picture but may improve
		 * horizontal resolution. If you prefer replicating, use this:
		 *   rv = la[j + 0];   ... or ... rv = la[j + 1];
		 * then the pixel will be replicated.
		 */ /* Brightness (badly calculated) */ /* Use monochrome for debugging */ /* Calculate difference between color and brightness */ /* Scale differences */ /* Reapply brightness */ /* Watch for overflows */ /*
	 * Account for number of bytes that we wrote into output V4L frame.
	 * We do it here, after we are done with the scanline, because we
	 * may fill more than one output scanline if we do vertical
	 * enlargement.
	 */