/*******************************************************************************
*
* Copyright (c) 1998, Tortuga Technologies Pty Ltd. All rights reserved.
*
* This is unpublished proprietary source code of Tortuga Technologies.
* The copyright notice above does not evidence any actual or intended
* publication of such source code.
*
*******************************************************************************
*
* Filename: $Id: cfa2bmp.html,v 1.1 2002/04/22 10:03:47 jill Exp $
*
* Description: Converts a 96x72x4 bit Bayer Pattern CFA to a 96x72 bitmap
*
* History:
* --------
* $Log: cfa2bmp.html,v $
* Revision 1.1 2002/04/22 10:03:47 jill
* Initial import
*
* Revision 1.2 1998/05/07 10:59:15 graham
* Made common header for functions & increased buffer size to BUFSIZ*15
*
* Revision 1.1 1998/04/28 12:17:22 graham
* Initial version
*
*
******************************************************************************/
/* system includes */
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
/* local includes */
#include "cfa2.h"
/* local definitions */
#define WIDTH 96
#define HEIGHT 72
/******************************************************************************/
/* */
/* Unit: cfa2bmp() */
/* */
/* Description: Converts a 96x72x4bit Bayer Pattern CFA into a 96x72 rgb */
/* bitmap. */
/* */
/* The CFA is first pixel replicated into three colour arrays. */
/* Missing pixels are then re-created through interpolating the */
/* pixels that are present. The data is then fed through a */
/* 1.7 gamma factor array which lightens the image. */
/* */
/* Notes: This routine was developed upon previous work carried out by */
/* "Stephane Charette" <charette@writeme.com> */
/* "Ed Hamrick" http://www.hamrick.com/ */
/* */
/* Parameters: cfa - address of buffer containing the raw cfa data */
/* bmp - address of buffer in which to place the converted */
/* bitmap */
/* */
/* Globals: None. */
/* */
/* Returns: None. */
/* */
/******************************************************************************/
void cfa2bmp( unsigned char *cfa, unsigned char *bmp )
{
unsigned char buf[96][72]; /* full sized buffer to work with */
unsigned char red[96][72]; /* rgb buffers to interpolate into */
unsigned char blu[96][72];
unsigned char gre[96][72];
unsigned char ch; /* local useful variables */
register int i, x, y;
/* hardcoded ".bmp" header 96x72, 24 bits */
static unsigned char bmphead[] = {
0x42, 0x4D, 0x36, 0x24, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x48, 0x00,
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* gamma correction table for gamma = 1.7 used */
/* to lighten the finished thumbnail image */
static unsigned char gamma[] = {
0, 10, 15, 19, 22, 25, 28, 31, 33, 36, 38, 40, 42, 44, 46, 48,
50, 52, 54, 55, 57, 59, 60, 62, 64, 65, 67, 68, 70, 71, 72, 74,
75, 77, 78, 79, 81, 82, 83, 84, 86, 87, 88, 89, 91, 92, 93, 94,
95, 97, 98, 99,100,101,102,103,105,106,107,108,109,110,111,112,
113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
129,130,131,132,133,134,135,135,136,137,138,139,140,141,142,143,
144,144,145,146,147,148,149,150,150,151,152,153,154,155,156,156,
157,158,159,160,160,161,162,163,164,164,165,166,167,168,168,169,
170,171,172,172,173,174,175,175,176,177,178,178,179,180,181,181,
182,183,184,184,185,186,187,187,188,189,190,190,191,192,192,193,
194,195,195,196,197,197,198,199,199,200,201,202,202,203,204,204,
205,206,206,207,208,208,209,210,210,211,212,212,213,214,214,215,
216,216,217,218,218,219,220,220,221,222,222,223,224,224,225,226,
226,227,227,228,229,229,230,231,231,232,233,233,234,234,235,236,
236,237,238,238,239,239,240,241,241,242,242,243,244,244,245,245,
246,247,247,248,248,249,250,250,251,251,252,253,253,254,254,255
};
/* split each byte into two in a local buffer */
for( i = 0, y = 0; y < HEIGHT; y++ )
{
for( x = 0; x < WIDTH; x+=2 )
{
buf[x ][y] = cfa[i ] >> 4;
buf[x+1][y] = cfa[i++] & 0x0F;
}
}
/* replicate pixels from the initial buffer into */
/* red, blue and green matrices... */
for( y = 0; y < HEIGHT; y += 2 )
{
for( x = 0; x < WIDTH; x += 2 )
{
/* grGRgrGR := ggGGggGG rrRRrrRR bbBBbbBB */
/* bgBGbgBG := ggGGggGG rrRRrrRR bbBBbbBB */
/* GRGRGRGR := ... */
gre[x ][y ] = buf[x ][y ];
gre[x+1][y ] = buf[x ][y ];
gre[x ][y+1] = buf[x+1][y+1];
gre[x+1][y+1] = buf[x+1][y+1];
red[x ][y ] = buf[x+1][y ];
red[x+1][y ] = buf[x+1][y ];
red[x ][y+1] = buf[x+1][y ];
red[x+1][y+1] = buf[x+1][y ];
blu[x ][y ] = buf[x ][y+1];
blu[x+1][y ] = buf[x ][y+1];
blu[x ][y+1] = buf[x ][y+1];
blu[x+1][y+1] = buf[x ][y+1];
}
}
/* bailing out here and printing the bitmap produces */
/* a fine but grainy image which becomes blocky on */
/* enlargement, I guess it depends on the requirements */
/* next we interpolate the data trying to recreate the */
/* pixels that are missing adding this to the replicated */
/* data */
/* compute the interpolated red data */
for ( y = 2; y < HEIGHT-2; y += 2 )
{
for ( x = 3; x < WIDTH-2; x += 2 )
{
/* get the left, bottom, corner red pixels */
unsigned char r, rl, rb, rc;
r = buf[x ][y ];
rl = buf[x-2][y ];
rb = buf[x ][y+2];
rc = buf[x-2][y+2];
red[x-1][y ] = (r + rl ) / 2;
red[x ][y+1] = (r + rb ) / 2;
red[x-1][y+1] = (r + rl + rb + rc) / 4;
}
}
/* compute the interpolated green data */
for ( y = 2; y < HEIGHT-2; y += 2 )
{
for ( x = 3; x < WIDTH-2; x += 2 )
{
/* get the left, right, top, bottom green pixels */
unsigned char gl, gr, gt, gb;
gl = buf[x-1][y ];
gr = buf[x+1][y ];
gt = buf[x ][y-1];
gb = buf[x ][y+1];
gre[x][y] = (gl + gr + gt + gb) / 4;
}
}
for ( y = 3; y < HEIGHT-2; y += 2 )
{
for ( x = 2; x < WIDTH-2; x += 2 )
{
/* get the left, right, top, bottom green pixels */
unsigned char gl, gr, gt, gb;
gl = buf[x-1][y ];
gr = buf[x+1][y ];
gt = buf[x ][y-1];
gb = buf[x ][y+1];
gre[x][y] = (gl + gr + gt + gb) / 4;
}
}
/* compute the interpolated blue data */
for ( y = 3; y < HEIGHT-2; y += 2 )
{
for ( x = 2; x < WIDTH-2; x += 2 )
{
/* get the right, top, corner blue pixels */
unsigned char b, br, bt, bc;
b = buf[x ][y ];
br = buf[x+2][y ];
bt = buf[x ][y-2];
bc = buf[x+2][y-2];
blu[x+1][y ] = (b + br ) / 2;
blu[x ][y-1] = (b + bt ) / 2;
blu[x+1][y-1] = (b + br + bt + bc) / 4;
}
}
/* bailing out here and printing the bitmap produces a */
/* much smoother image, perhaps even a little blurry, */
/* I guess this shows the quality of the interpolation */
/* algorithm, if I get time I'd work more on this ... */
/* copy the header to the user supplied buffer */
(void) memcpy( bmp, bmphead, sizeof(bmphead) );
/* now copy out our rgb pixels using a handy dandy */
/* gamma array which lightens and lifts the */
/* thumbnail image */
i = sizeof(bmphead);
for( y = HEIGHT-1; y >= 0; y-- )
{
for( x = 0; x < WIDTH; x++ )
{
ch = blu[x][y];
bmp[i++] = gamma[ (ch * 16) + ch ];
ch = gre[x][y];
bmp[i++] = gamma[ (ch * 16) + ch ];
ch = red[x][y];
bmp[i++] = gamma[ (ch * 16) + ch ];
}
}
return;
}
#ifdef _TOOL
/******************************************************************************/
/* */
/* Unit: main() */
/* */
/* Description: ifdef'd main() to test the cfa2bmp function above */
/* */
/* Notes: This was a real pig to develop */
/* */
/* Parameters: argv[1] - filename of raw bayer pattern cfa data */
/* argv[2] - filename in which to place the bitmap */
/* */
/* Globals: None */
/* */
/* Returns: -1 - Bad argument */
/* 0 - All converted */
/* */
/******************************************************************************/
int main( int argc, char *argv[] )
{
int fd;
unsigned char buffer[3456];
unsigned char bitmap[20790];
/* check the args */
if ( (argv[1] == NULL) || (argv[2] == NULL) )
{
(void) printf( "Usage: %s filename.cfa filename.bmp\n", argv[0] );
exit( -1 );
}
/* read in the thumbnail data */
fd = open( argv[1], O_RDONLY );
if ( fd == -1 )
{
(void) printf( "%s: failed to open \"%s\"", argv[0], argv[1] );
exit( -1 );
}
(void) read( fd, buffer, 3456 );
(void) close( fd );
/* convert the sucker */
cfa2bmp( buffer, bitmap );
/* and write it out */
fd = open( argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666 );
if ( fd == -1 )
{
(void) printf( "%s: failed to open \"%s\"", argv[0], argv[2] );
exit( -1 );
}
(void) write( fd, bitmap, 20790 );
(void) close( fd );
/* phew ! that was hard yakka */
exit( 0 );
}
#endif