注: 本代码非本人所作, 如他人用于其它任何用途均与本人无关.
/*
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
]
=
{
{
0
,
1
,
1
,
2
},
{
1
,
0
,
2
,
1
},
{
2
,
1
,
1
,
0
},
{
1
,
2
,
0
,
1
},
{
0
,
1
,
1
,
2
},
{
1
,
0
,
2
,
1
},
{
2
,
1
,
1
,
0
},
{
1
,
2
,
0
,
1
}};
#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
<
4
)
return
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);
}