Bayer转换算法[转]

代码
注: 本代码非本人所作, 如他人用于其它任何用途均与本人无关.

/* raw.h */
#ifndef __RAW_H__ 
#define __RAW_H__ 
 
#define GP_OK 1 
 
typedef 
enum { 
    BAYER_TILE_RGGB 
= 0
    BAYER_TILE_GRBG 
= 1
    BAYER_TILE_BGGR 
= 2
    BAYER_TILE_GBRG 
= 3
    BAYER_TILE_RGGB_INTERLACED 
= 4
    BAYER_TILE_GRBG_INTERLACED 
= 5
    BAYER_TILE_BGGR_INTERLACED 
= 6
    BAYER_TILE_GBRG_INTERLACED 
= 7
} BayerTile; 
 
int gp_bayer_expand (unsigned char *input, int w, int h, unsigned char *output, 
                     BayerTile tile); 
int gp_bayer_decode (unsigned char *input, int w, int h, unsigned char *output, 
             BayerTile tile); 
int gp_bayer_interpolate (unsigned char *image, int w, int h, BayerTile tile); 
#endif 

/* raw.c */
#include 
"raw.h"    
   
static const int tile_colours[8][4= {   
    {
0112},   
    {
1021},   
    {
2110},   
    {
1201},   
    {
0112},   
    {
1021},   
    {
2110},   
    {
1201}};   
   
#define RED 0    
#define GREEN 1    
#define BLUE 2    
   
static int   
gp_bayer_accrue (unsigned 
char *image, int w, int h, int x0, int y0,   
        
int x1, int y1, int x2, int y2, int x3, int y3, int colour);   
   
int   
gp_bayer_expand (unsigned 
char *input, int w, int h, unsigned char *output,   
         BayerTile tile)   
{   
    
int x, y, i;   
    
int colour, bayer;   
    unsigned 
char *ptr = input;   
   
    
switch (tile) {   
   
        
case BAYER_TILE_RGGB:   
        
case BAYER_TILE_GRBG:   
        
case BAYER_TILE_BGGR:   
        
case BAYER_TILE_GBRG:   
   
            
for (y = 0; y < h; ++y)   
                
for (x = 0; x < w; ++x, ++ptr)    
                {   
                    bayer 
= (x&1?0:1+ (y&1?0:2);   
   
                    colour 
= tile_colours[tile][bayer];   
   
                    i 
= (y * w + x) * 3;   
   
                    output[i
+RED]    = 0;   
                    output[i
+GREEN]  = 0;   
                    output[i
+BLUE]   = 0;   
                    output[i
+colour] = *ptr;   
                }   
            
break;   
   
        
case BAYER_TILE_RGGB_INTERLACED:   
        
case BAYER_TILE_GRBG_INTERLACED:   
        
case BAYER_TILE_BGGR_INTERLACED:   
        
case BAYER_TILE_GBRG_INTERLACED:   
   
   
            
for (y = 0; y < h; ++y, ptr+=w)   
                
for (x = 0; x < w; ++x)    
                {   
                    bayer 
= (x&1?0:1+ (y&1?0:2);   
   
                    colour 
= tile_colours[tile][bayer];   
       
                    i 
= (y * w + x) * 3;   
   
                    output[i
+RED]    = 0;   
                    output[i
+GREEN]  = 0;   
                    output[i
+BLUE]   = 0;   
                    output[i
+colour] = (x&1)? ptr[x>>1]:ptr[(w>>1)+(x>>1)];   
                }   
            
break;   
    }   
   
    
return (GP_OK);   
}   
   
#define AD(x, y, w) ((y)*(w)*3+3*(x))    
   
int   
gp_bayer_interpolate (unsigned 
char *image, int w, int h, BayerTile tile)   
{   
    
int x, y, bayer;   
    
int p0, p1, p2, p3;   
    
int value, div ;   
   
    
switch (tile) {   
    
default:   
    
case BAYER_TILE_RGGB:   
    
case BAYER_TILE_RGGB_INTERLACED:   
        p0 
= 0; p1 = 1; p2 = 2; p3 = 3;   
        
break;   
    
case BAYER_TILE_GRBG:   
    
case BAYER_TILE_GRBG_INTERLACED:   
        p0 
= 1; p1 = 0; p2 = 3; p3 = 2;   
        
break;   
    
case BAYER_TILE_BGGR:   
    
case BAYER_TILE_BGGR_INTERLACED:   
        p0 
= 3; p1 = 2; p2 = 1; p3 = 0;   
        
break;   
    
case BAYER_TILE_GBRG:   
    
case BAYER_TILE_GBRG_INTERLACED:   
        p0 
= 2; p1 = 3; p2 = 0; p3 = 1;   
        
break;   
    }   
   
    
for (y = 0; y < h; y++)   
        
for (x = 0; x < w; x++) {   
            bayer 
= (x&1?0:1+ (y&1?0:2);   
   
            
if ( bayer == p0 ) {   
   
                
/* red. green lrtb, blue diagonals */   
                image[AD(x,y,w)
+GREEN] =   
                    gp_bayer_accrue(image, w, h, x
-1, y, x+1, y, x, y-1, x, y+1, GREEN) ;   
   
                image[AD(x,y,w)
+BLUE] =   
                    gp_bayer_accrue(image, w, h, x
+1, y+1, x-1, y-1, x-1, y+1, x+1, y-1, BLUE) ;   
   
            } 
else if (bayer == p1) {   
   
                
/* green. red lr, blue tb */   
                div 
= value = 0;   
                
if (x < (w - 1)) {   
                    value 
+= image[AD(x+1,y,w)+RED];   
                    div
++;   
                }   
                
if (x) {   
                    value 
+= image[AD(x-1,y,w)+RED];   
                    div
++;   
                }   
                image[AD(x,y,w)
+RED] = value / div;   
   
                div 
= value = 0;   
                
if (y < (h - 1)) {   
                    value 
+= image[AD(x,y+1,w)+BLUE];   
                    div
++;   
                }   
                
if (y) {   
                    value 
+= image[AD(x,y-1,w)+BLUE];   
                    div
++;   
                }   
                image[AD(x,y,w)
+BLUE] = value / div;   
   
            } 
else if ( bayer == p2 ) {   
   
                
/* green. blue lr, red tb */   
                div 
= value = 0;   
   
                
if (x < (w - 1)) {   
                    value 
+= image[AD(x+1,y,w)+BLUE];   
                    div
++;   
                }   
                
if (x) {   
                    value 
+= image[AD(x-1,y,w)+BLUE];   
                    div
++;   
                }   
                image[AD(x,y,w)
+BLUE] = value / div;   
   
                div 
= value = 0;   
                
if (y < (h - 1)) {   
                    value 
+= image[AD(x,y+1,w)+RED];   
                    div
++;   
                }   
                
if (y) {   
                    value 
+= image[AD(x,y-1,w)+RED];   
                    div
++;   
                }   
                image[AD(x,y,w)
+RED] = value / div;   
   
            } 
else {   
   
                
/* blue. green lrtb, red diagonals */   
                image[AD(x,y,w)
+GREEN] =   
                    gp_bayer_accrue (image, w, h, x
-1, y, x+1, y, x, y-1, x, y+1, GREEN) ;   
   
                image[AD(x,y,w)
+RED] =   
                    gp_bayer_accrue (image, w, h, x
+1, y+1, x-1, y-1, x-1, y+1, x+1, y-1, RED) ;   
            }   
        }   
   
    
return (GP_OK);   
}   
   
static int   
gp_bayer_accrue (unsigned 
char *image, int w, int h, int x0, int y0,   
        
int x1, int y1, int x2, int y2, int x3, int y3, int colour)   
{   
int x [4] ;   
    
int y [4] ;   
    
int value [4] ;   
    
int above [4] ;   
    
int counter   ;   
    
int sum_of_values;   
    
int average ;   
    
int i ;   
    x[
0= x0 ; x[1= x1 ; x[2= x2 ; x[3= x3 ;   
    y[
0= y0 ; y[1= y1 ; y[2= y2 ; y[3= y3 ;   
       
    counter 
= sum_of_values = 0 ;   
    
if(colour == GREEN)   
    {   
        
for (i = 0 ; i < 4 ; i++)   
        {   
if ((x[i] >= 0&& (x[i] < w) && (y[i] >= 0&& (y[i] < h))   
            {   
                value [i] 
= image[AD(x[i],y[i],w) + colour] ;   
                counter
++;   
            }   
            
else   
            {   
                value [i] 
= -1 ;   
            }   
        }   
        
if(counter == 4)   
        {      
            
int hdiff ;   
            
int vdiff ;   
            hdiff 
= value [1- value [0] ;   
            hdiff 
*= hdiff ;    /* Make value positive by squaring */   
            vdiff 
= value [3- value [2] ;   
            vdiff 
*= vdiff ;    /* Make value positive by squaring */   
            
if(hdiff > 2*vdiff)   
            {   
                
return (value [3+ value [2])/2 ;   
            }   
            
if(vdiff > 2*hdiff)   
            {   
                
return (value [1+ value [0])/2 ;   
            }   
        }   
    }   
       
    
/* for blue and red */   
    counter 
= sum_of_values = 0 ;   
    
for (i = 0 ; i < 4 ; i++)   
    {   
if ((x[i] >= 0&& (x[i] < w) && (y[i] >= 0&& (y[i] < h))   
        {   value [i] 
= image[AD(x[i],y[i],w) + colour] ;   
            sum_of_values 
+= value [i] ;   
            counter
++ ;   
        }   
    }   
    average 
= sum_of_values / counter ;   
    
if (counter < 4return average ;   
    
/* Less than four surrounding - just take average */   
    counter 
= 0 ;   
    
for (i = 0 ; i < 4 ; i++)   
    {   above[i] 
= value[i] > average ;   
        
if (above[i]) counter++ ;   
    }   
    
/* Note: counter == 0 indicates all values the same */   
    
if ((counter == 2|| (counter == 0)) return average ;   
    sum_of_values 
= 0 ;   
    
for (i = 0 ; i < 4 ; i++)   
    {   
if ((counter == 3== above[i])   
        {   sum_of_values 
+= value[i] ; }   
    }   
    
return sum_of_values / 3 ;   
}   
   
int   
gp_bayer_decode (unsigned 
char *input, int w, int h, unsigned char *output,   
         BayerTile tile)   
{   
    gp_bayer_expand (input, w, h, output, tile);   
    gp_bayer_interpolate (output, w, h, tile);   
   
    
return (GP_OK);   
}
原文地址:https://www.cnblogs.com/lin1270/p/1893654.html