PDA

View Full Version : converting Bayer's format to bmp format



yogi
05-30-2005, 09:52 AM
I am interfacing cmos image sensor with parallel port using uC

I am having

R G R G..............
B G B G...............

so how to convert it to bmp image format

I know C and Java

I also want to show image on screen just like a webcam, I mainly use this because I wanted it for my robot. I am getting 8 bit intensity data for each color. The sensor which I am using is HDCS-1020(taken from Logitech Quick Cam Express).


Bibin John
www.bibinjohn.tk

nchinoy
05-30-2005, 07:40 PM
umm first and most simple thing i can think of is that you need to know the resolution of the camera... then create a 2-dimesions structure (like array) and start dumping your R,G & B's in the array... So to speak you need to know what is it that it is showing you and where so pixelate your image...

|R|R|R|
--------- would corrrespond to a RED 3x2 block ;)
|R|R|R|

You will need this details at the bare minimum for any format (GIF, JPEG or BMP)... Then you need to read what else does a BMP format require... as in it might have some headers like whats the number of colors used, the resolution etc.... you need to look that up .. Alternatively use JAVA ... make your own binary format, dump all these pixels into a array and use the API to display you pic...

I have done that before as in make my own binary format for an image and then read a GIF write it to my format save it and display it ..... If you want i can look up the code...should be someone on my hardisk ... ummm from good old uni days....

hope that helps....

Nimesh

yogi
05-31-2005, 09:41 AM
my idea is to apply simple interpolation( i saw one code in C)
http://www.tortuga.com.au/products/info/cfa2bmp.html

After interpolation I have three arrays gre[x][y],blu[x][y],red[x][y]
x=176 y=144

I wanted to convert these array into a bmp image. I want that part of code only. Can you give me ur code



Bibin John
www.bibinjohn.tk

titan00
06-09-2005, 08:54 PM
Hi

That sounds like a very interesting project. I myself is working on a similar project. I'm trying to get a uC to make image analisys from a HDCS-1000, very similar to your HDCS-1020.
I'm having a lot problems communication with the chip using it's UART connection. How did you get communication running? Any hints?

Regards
Titan00

vikas
06-10-2005, 09:05 AM
Simple

The BMP format has RBG values stored of the image very simply withough any compression etc ( lookup the BMP format ) for ex a 24 Bit BMP image has 3 bytes represeting a pixel [8:r][8:b][8:g] . This image is stored inverted in the file . xo x=0,y=0 will be the last three bytes the x,y have to stored in the header ( format will have to be looked up by you ) .

nchinoy
06-14-2005, 10:25 AM
my idea is to apply simple interpolation( i saw one code in C)
http://www.tortuga.com.au/products/info/cfa2bmp.html

After interpolation I have three arrays gre[x][y],blu[x][y],red[x][y]
x=176 y=144

I wanted to convert these array into a bmp image. I want that part of code only. Can you give me ur code



Bibin John
www.bibinjohn.tk

I havent stored in BMP format.. but i have code that stores in my own binary format.... and a peice of code from my prof which needs some working on to store in GIF format...

I am trying to attach them here ... but if it doesnt work email me at nchinoy(at)gmail(dot)com and i will attch them to your email....

hope this helps ...

Nimesh

nchinoy
06-14-2005, 10:26 AM
/**
* WriteGIF is a class that takes an Image and saves it to
* a GIF format file.
*
* Based upon gifsave.c, which was written and released by
* Sverre H. Huseby. Ported to Java by Adam Doppelt of Brown
* University.
* Modified and integrated with the ImageProc program for
* CS411X, advanced Java Programming at the University of
* Bridgeport.
*
*/
/*
* Notes added by John Chapman, March 2000
* RMIT students will need to add quantization by reducing
* colours to 256 or less before saving image as a GIF
*/
/* masked out by John Chapman, depends on your file layout
* package vs;
*/
import java.io.*;
import java.awt.*;import java.awt.event.*;
import java.awt.image.*;

public class WriteGIF {
short width_, height_;
int numColors_;
byte pixels_[], colors_[];

/* masked out as not specific to package used by
* Image Processing in Java
* ScreenDescriptor sd_;
* ImageDescriptor id_;
*/
public static void DoIt(Image img, String fname) throws Exception
{
// encode the image as a GIF
WriteGIF encode = new WriteGIF(img);

/* TODO -> beef up Exception handling */
try
{
OutputStream output = new BufferedOutputStream(
new FileOutputStream(fname));
encode.Write(output);
}
catch(Exception e)
{
System.out.println("Save GIF Exception!");
}
}

public WriteGIF(Image image) throws AWTException
{
width_ = (short)image.getWidth(null);
height_ = (short)image.getHeight(null);

int values[] = new int[width_ * height_];
PixelGrabber grabber = new PixelGrabber(
image, 0, 0, width_, height_, values, 0, width_);

try
{
if(grabber.grabPixels() != true)
throw new AWTException("Grabber returned false: " +
grabber.status());
}
catch (InterruptedException e){};

//--------------------------------------------------------------
// TODO -> Possible Speed up - do it a row at a time, a la ACME
//--------------------------------------------------------------
byte r[][] = new byte[width_][height_];
byte g[][] = new byte[width_][height_];
byte b[][] = new byte[width_][height_];
int index = 0;

for (int y = 0; y < height_; ++y)
{
for (int x = 0; x < width_; ++x)
{
r[x][y] = (byte)((values[index] >> 16) & 0xFF);
g[x][y] = (byte)((values[index] >> 8) & 0xFF);
b[x][y] = (byte)((values[index]) & 0xFF);
++index;
}
}
ToIndexedColor(r, g, b);
}


//--------------------------------------------------------------
// CONSTRUCTOR
//--------------------------------------------------------------
public WriteGIF(byte r[][], byte g[][], byte b[][])
throws AWTException {
width_ = (short)(r.length);
height_ = (short)(r[0].length);

ToIndexedColor(r, g, b);
}

public void Write(OutputStream output) throws IOException
{
BitUtils.WriteString(output, "GIF87a");
ScreenDescriptor sd = new ScreenDescriptor(width_, height_,
numColors_);
sd.Write(output);
output.write(colors_, 0, colors_.length);
ImageDescriptor id = new ImageDescriptor(width_, height_, ',');
id.Write(output);

byte codesize = BitUtils.BitsNeeded(numColors_);
if (codesize == 1) {
++codesize;
}
output.write(codesize);

LZWCompressor.LZWCompress(output, codesize, pixels_);
output.write(0);

id = new ImageDescriptor((byte)0, (byte)0, ';');
id.Write(output);
output.flush();
}

void ToIndexedColor(byte r[][], byte g[][], byte b[][])
throws AWTException {
pixels_ = new byte[width_ * height_];
colors_ = new byte[256 * 3];
int colornum = 0;
for (int x = 0; x < width_; ++x)
{
for (int y = 0; y < height_; ++y)
{
int search;
for (search = 0; search < colornum; ++search)
{
if (colors_[search * 3] == r[x][y] &&
colors_[search * 3 + 1] == g[x][y] &&
colors_[search * 3 + 2] == b[x][y])
{
break;
}
}

// If there are more than 256 colors invoke
// the color quantization procedure.
// RMIT students are expected to have reduced
// colours to 256 or less before saving as GIF
// quantization();
if (search > 255)
{
throw new AWTException("Too many colors.");
}

pixels_[y * width_ + x] = (byte)search;

if (search == colornum)
{
colors_[search * 3] = r[x][y];
colors_[search * 3 + 1] = g[x][y];
colors_[search * 3 + 2] = b[x][y];
++colornum;
}
}
}
numColors_ = 1 << BitUtils.BitsNeeded(colornum);
byte copy[] = new byte[numColors_ * 3];
System.arraycopy(colors_, 0, copy, 0, numColors_ * 3);
colors_ = copy;
}
}

class BitFile
{
OutputStream output_;
byte buffer_[];
int index_, bitsLeft_;

public BitFile(OutputStream output)
{
output_ = output;
buffer_ = new byte[256];
index_ = 0;
bitsLeft_ = 8;
}

public void Flush() throws IOException
{
int numBytes = index_ + (bitsLeft_ == 8 ? 0 : 1);
if (numBytes > 0)
{
output_.write(numBytes);
output_.write(buffer_, 0, numBytes);
buffer_[0] = 0;
index_ = 0;
bitsLeft_ = 8;
}
}

public void WriteBits(int bits, int numbits) throws IOException
{
int bitsWritten = 0;
int numBytes = 255;
do
{
if ((index_ == 254 && bitsLeft_ == 0) || index_ > 254)
{
output_.write(numBytes);
output_.write(buffer_, 0, numBytes);

buffer_[0] = 0;
index_ = 0;
bitsLeft_ = 8;
}

if (numbits <= bitsLeft_)
{
buffer_[index_] |= (bits & ((1 << numbits) - 1)) <<
(8 - bitsLeft_);
bitsWritten += numbits;
bitsLeft_ -= numbits;
numbits = 0;
}
else
{
buffer_[index_] |= (bits & ((1 << bitsLeft_) - 1)) <<
(8 - bitsLeft_);
bitsWritten += bitsLeft_;
bits >>= bitsLeft_;
numbits -= bitsLeft_;
buffer_[++index_] = 0;
bitsLeft_ = 8;
}
} while (numbits != 0);
}
}

class LZWStringTable
{
private final static int RES_CODES = 2;
private final static short HASH_FREE = (short)0xFFFF;
private final static short NEXT_FIRST = (short)0xFFFF;
private final static int MAXBITS = 12;
private final static int MAXSTR = (1 << MAXBITS);
private final static short HASHSIZE = 9973;
private final static short HASHSTEP = 2039;

byte strChr_[];
short strNxt_[];
short strHsh_[];
short numStrings_;

public LZWStringTable()
{
strChr_ = new byte[MAXSTR];
strNxt_ = new short[MAXSTR];
strHsh_ = new short[HASHSIZE];
}

public int AddCharString(short index, byte b)
{
int hshidx;

if (numStrings_ >= MAXSTR)
{
return 0xFFFF;
}

hshidx = Hash(index, b);
while (strHsh_[hshidx] != HASH_FREE)
{
hshidx = (hshidx + HASHSTEP) % HASHSIZE;
}

strHsh_[hshidx] = numStrings_;
strChr_[numStrings_] = b;
strNxt_[numStrings_] = (index != HASH_FREE) ? index : NEXT_FIRST;

return numStrings_++;
}

public short FindCharString(short index, byte b)
{
int hshidx, nxtidx;

if (index == HASH_FREE)
{
return b;
}

hshidx = Hash(index, b);
while ((nxtidx = strHsh_[hshidx]) != HASH_FREE)
{
if (strNxt_[nxtidx] == index && strChr_[nxtidx] == b)
{
return (short)nxtidx;
}
hshidx = (hshidx + HASHSTEP) % HASHSIZE;
}

return (short)0xFFFF;
}

public void ClearTable(int codesize)
{
numStrings_ = 0;

for (int q = 0; q < HASHSIZE; q++)
{
strHsh_[q] = HASH_FREE;
}

int w = (1 << codesize) + RES_CODES;
for (int q = 0; q < w; q++)
{
AddCharString((short)0xFFFF, (byte)q);
}
}

static public int Hash(short index, byte lastbyte)
{
return ((int)((short)(lastbyte << 8) ^ index) & 0xFFFF) % HASHSIZE;
}
}

class LZWCompressor
{
public static void LZWCompress(OutputStream output, int codesize,
byte toCompress[]) throws IOException
{
byte c;
short index;
int clearcode, endofinfo, numbits, limit, errcode;
short prefix = (short)0xFFFF;

BitFile bitFile = new BitFile(output);
LZWStringTable strings = new LZWStringTable();

clearcode = 1 << codesize;
endofinfo = clearcode + 1;

numbits = codesize + 1;
limit = (1 << numbits) - 1;

strings.ClearTable(codesize);
bitFile.WriteBits(clearcode, numbits);

for (int loop = 0; loop < toCompress.length; ++loop)
{
c = toCompress[loop];
if ((index = strings.FindCharString(prefix, c)) != -1)
{
prefix = index;
}
else
{
bitFile.WriteBits(prefix, numbits);
if (strings.AddCharString(prefix, c) > limit)
{
if (++numbits > 12)
{
bitFile.WriteBits(clearcode, numbits - 1);
strings.ClearTable(codesize);
numbits = codesize + 1;
}
limit = (1 << numbits) - 1;
}

prefix = (short)((short)c & 0xFF);
}
}

if (prefix != -1)
{
bitFile.WriteBits(prefix, numbits);
}

bitFile.WriteBits(endofinfo, numbits);
bitFile.Flush();
}
}

class ScreenDescriptor
{
public short localScreenWidth_, localScreenHeight_;
private byte byte_;
public byte backgroundColorIndex_, pixelAspectRatio_;

public ScreenDescriptor(short width, short height, int numColors)
{
localScreenWidth_ = width;
localScreenHeight_ = height;
SetGlobalColorTableSize((byte)(BitUtils.BitsNeeded (numColors) - 1));
SetGlobalColorTableFlag((byte)1);
SetSortFlag((byte)0);
SetColorResolution((byte)7);
backgroundColorIndex_ = 0;
pixelAspectRatio_ = 0;
}

public void Write(OutputStream output) throws IOException
{
BitUtils.WriteWord(output, localScreenWidth_);
BitUtils.WriteWord(output, localScreenHeight_);
output.write(byte_);
output.write(backgroundColorIndex_);
output.write(pixelAspectRatio_);
}

public void SetGlobalColorTableSize(byte num)
{
byte_ |= (num & 7);
}

public void SetSortFlag(byte num)
{
byte_ |= (num & 1) << 3;
}

public void SetColorResolution(byte num)
{
byte_ |= (num & 7) << 4;
}

public void SetGlobalColorTableFlag(byte num)
{
byte_ |= (num & 1) << 7;
}
}

class ImageDescriptor
{
public byte separator_;
public short leftPosition_, topPosition_, width_, height_;
private byte byte_;

public ImageDescriptor(short width, short height, char separator)
{
separator_ = (byte)separator;
leftPosition_ = 0;
topPosition_ = 0;
width_ = width;
height_ = height;
SetLocalColorTableSize((byte)0);
SetReserved((byte)0);
SetSortFlag((byte)0);
SetInterlaceFlag((byte)0);
SetLocalColorTableFlag((byte)0);
}

public void Write(OutputStream output) throws IOException
{
output.write(separator_);
BitUtils.WriteWord(output, leftPosition_);
BitUtils.WriteWord(output, topPosition_);
BitUtils.WriteWord(output, width_);
BitUtils.WriteWord(output, height_);
output.write(byte_);
}

public void SetLocalColorTableSize(byte num)
{
byte_ |= (num & 7);
}

public void SetReserved(byte num)
{
byte_ |= (num & 3) << 3;
}

public void SetSortFlag(byte num)
{
byte_ |= (num & 1) << 5;
}

public void SetInterlaceFlag(byte num)
{
byte_ |= (num & 1) << 6;
}

public void SetLocalColorTableFlag(byte num)
{
byte_ |= (num & 1) << 7;
}
}

class BitUtils
{
public static byte BitsNeeded(int n)
{
byte ret = 1;

if (n-- == 0)
{
return 0;
}

while ((n >>= 1) != 0)
{
++ret;
}

return ret;
}

public static void WriteWord(OutputStream output, short w)
throws IOException
{
output.write(w & 0xFF);
output.write((w >> 8) & 0xFF);
}

static void WriteString(OutputStream output,
String string) throws IOException
{
for (int loop = 0; loop < string.length(); ++loop)
{
output.write((byte)(string.charAt(loop)));
}
}
}

nchinoy
06-14-2005, 10:31 AM
This is my code .... stores in binary format...
import java.net.URL;
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
import java.awt.event.*;
import java.io.*;

public class WriteBfc extends Applet
{
FileOutputStream fos;
DataOutputStream ds;

public void WriteBfc(String fname, int []pixel, int w, int h)
{
FileOutputStream fos;
DataOutputStream ds;

try
{
fos = new FileOutputStream(fname);
ds = new DataOutputStream(fos);

String a = "FC - BINARY 32 , Nimesh Chinoy";

ds.writeByte('#');

for(int i=0; i<a.length();i++)
{
ds.writeChar( a.charAt(i));
}
ds.writeByte('#'); //End if the Header
ds.writeByte(4); // The number of bytes for each pixel
ds.writeInt(w); // width of the image that follows
ds.writeInt(h); // height of the image that follows

// The real pixel values that constitute the image

for(int i = 0;i<pixel.length;i++)
{
ds.writeInt(pixel[i]);
}
}
catch ( IOException ioe)
{
System.out.println("I/O Error " + ioe);
}

}
}

This is my code to read the above binary format...

import java.net.URL;
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
import java.awt.event.*;
import java.io.*;

public class ReadBinary extends Applet
{
public Image ReadB(String fname)
{

FileInputStream fis;
DataInputStream dis;
int value = 0;
int index = 0;
Image cropped;
int width = 200 , height = 200;
int pixel[] = new int[width*height];



try
{
fis = new FileInputStream(fname);
dis = new DataInputStream(fis);
System.out.println("file" + fname);
value = dis.readByte();
System.out.println("Read " + (char)value);



if(value == '#')
{

value = dis.readByte();
while (value != '#')
{

value = dis.readByte();
System.out.print(" "+ (char)value);
}
}

System.out.print(" number of data channels is :" );

value = dis.readByte();
System.out.print(value );
System.out.println("");


System.out.print(" Width is :" );
width = dis.readInt();
System.out.print(width);
System.out.println("");
height = dis.readInt();
System.out.print("Height is :" + height);
System.out.println("");

pixel = new int[width*height];
for(index = 0; index <pixel.length; index++)
{
pixel[index] = dis.readInt();
}


}

catch (EOFException eof)
{
System.out.println("EOF REACHED");
}

catch ( IOException ioe)
{
System.out.println(" IO Error " + ioe);
}

ImageProducer ip = new MemoryImageSource(width,height,pixel,0,width);

cropped = createImage(ip);
return cropped;

}

}


Hope you realise this code was written way back in the early days of JAVA so to speak (Y2K)... So you might find a few things really outdated ... ;-) Hope it still helps ...

Nimesh