michinyon I bought an ov7670 camera module that means some of the pins are routed to a 2.54mm pitch header I think you have bought just the sensor. I am busy right now I will take a picture soon.
Saren it is possible I will have to get back with you on this one though. I am busy right now and don't have any code written right now for using no ram. I do however have a program that is compiled with avr-gcc that sends the image to a frame grabber program that I wrote.
Here is the sender program it is in 3 files main.c ov7670.h ov7670.c
main.c:
http://pastebin.com/dF3pc23TI will warn you that I made some changes to the code but forgot to change the comments like the captureImg function says it missed a byte but now it does not I posted it to paste bin before realising this.
ov7670.h
http://pastebin.com/CqYTwNqnov7670.c
http://pastebin.com/T1nN5Ni4Here is the frame grabber source code
http://pastebin.com/dxMJhZTqThis one is only one file. If on Gnu/Linux you will need to install the development package of SDL or if gentoo just emerge sdl. If on windows get the development library from
http://www.libsdl.org/download-1.2.phpAlso I made an update to my program that captures an image to the sd card it nows saves raw bayer data.
http://pastebin.com/zV0ahzPvThe link is different than the previous code that I posted.
Here is a program to debayer/demosaic the data it is still in very beta needs work
It will also convert yuv422 to rgb (the old image to sd card program saved data in that format)
//to compile type gcc -Wall -Wextra -lm -lpng -o yuv main.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <png.h>
#include <zlib.h>
#include <sys/stat.h>
#define img_w 640
#define img_w_2 1280
#define img_h 480
#define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X)
#define C(Y) ( (Y) - 16 )
#define D(U) ( (U) - 128 )
#define E(V) ( (V) - 128 )
#define YUV2R(Y, U, V) CLIP(( 298 * C(Y) + 409 * E(V) + 128) >> 8)
#define YUV2G(Y, U, V) CLIP(( 298 * C(Y) - 100 * D(U) - 208 * E(V) + 128) >> 8)
#define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U) + 128) >> 8)
char buf[1024];
void showHelp()
{
puts("Yuv422 raw image data to png");
puts("-n x replace x with the image number you want to convert");
puts("-h shows this help file");
puts("-o x replace x with a real integer between 0 and 7 this sets the offset");
}
int savePNG(char * fileName,uint32_t width,uint32_t height,void * ptr)
{
//saves a 24bit png with rgb byte order
png_byte * dat=ptr;//convert to uint8_t
//png_byte **row_pointers = malloc(height*sizeof(png_byte));
//if (row_pointers==0)
// return 1;
FILE * fp=fopen(fileName,"wb");
if (fp==0)
return 1;
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)0,0,0);
if (!png_ptr)
return 1;
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
return 1;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
return 1;
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, width, height,8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);//must be called before other png_set_*() functions
//png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);//since we are doing timelapses we may be dealing with many files it is good to keep disk space usage down
uint32_t y;
//for (y=0;y<height;y++)
// row_pointers[y]=&dat[(y*width*3)];//the rows are contiguous
png_set_user_limits(png_ptr, width, height);
png_write_info(png_ptr, info_ptr);
//puts("saving data 2");
//png_write_image(png_ptr, row_pointers);
for (y=0;y<height;y++)
png_write_row(png_ptr, &dat[(y*width*3)]);
//png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
//free(row_pointers);
fclose(fp);//done with file
return 0;//will return 0 on success non-zero in error
}
void yuv2rgb(uint8_t * yuvDat,uint8_t * out)
{
uint64_t xy;
for (xy=0;xy<(img_w/2)*img_h;xy++)
{
*out++=YUV2R(yuvDat[0],yuvDat[1],yuvDat[3]);
*out++=YUV2G(yuvDat[0],yuvDat[1],yuvDat[3]);
*out++=YUV2B(yuvDat[0],yuvDat[1],yuvDat[3]);
*out++=YUV2R(yuvDat[2],yuvDat[1],yuvDat[3]);
*out++=YUV2G(yuvDat[2],yuvDat[1],yuvDat[3]);
*out++=YUV2B(yuvDat[2],yuvDat[1],yuvDat[3]);
yuvDat+=4;
}
}
void deBayerN(uint8_t * in,uint8_t * out)
{
uint32_t x,y;
for (y=0;y<img_h;y+=2)
{
for (x=0;x<img_w;x+=2)
{
//this will do a 2x2 pixel rectangle
/*R G
G B*/
out[(x*3)]=in[x];//copy red
out[(x*3)+1]=in[x+1];//green
out[(x*3)+2]=in[x+1+img_w];//blue
out[(x*3)+3]=in[x];//red
out[(x*3)+4]=in[x+1];//green
out[(x*3)+5]=in[x+1+img_w];//blue
out[((x+img_w)*3)]=in[x];//red
out[((x+img_w)*3)+1]=in[x+img_w];//green
out[((x+img_w)*3)+2]=in[x+1+img_w];//blue
out[((x+img_w)*3)+3]=in[x];//red
out[((x+img_w)*3)+4]=in[x+img_w];//green
out[((x+img_w)*3)+5]=in[x+img_w+1];//blue
}
out+=img_w*6;
in+=img_w*2;
}
}
void deBayerL (uint8_t * in,uint8_t * out)
{//this is an implementation of http://www.ipol.im/pub/art/2011/g_mhcd/
uint32_t x,y;
for (y=0;y<img_h;y+=2)
{
for (x=0;x<img_w;x+=2)
{
//this will do a 2x2 pixel rectangle
/* B Gb
Gr R
*/
/*R G THIS IS WRONG BUT STANDARD The rows are reversed on omnivision sensors keep this in mind later just get alg working for now
G B*/
//if (x>=2 && x<=img_w-2 && y>=2 && y<=img_h-2)//see if we are able to grab pixels from neighboors
//{
//printf("X %d Y %d x-img_w %d\n",x,y,x-img_w);
out[x*3]=in[x];//red just needs to be copied
//out[(x*3)+1]=((in[x]*4)+(in[x-1]*2)+(in[x+1]*2)+(*(in+x-img_w)*2)+(in[x+img_w]*2)-(in[x-2])-(in[x+2])-(*(in+x-img_w_2))-in[x+img_w_2])/8;//green at red locations
//out[(x*3)+2]=((in[x]*6)+(*(in+x-1-img_w)*2)+(*(in+x+1-img_w)*2)+(*(in+x-1+img_w)*2)+(in[x+1+img_w]*2)-(in[x-2]/3*2)-(in[x+2]/3*2)-(*(in+x-img_w_2)/3*2)-(in[x+img_w_2]/3*2))/8;//Blue at red
//out[(x*3)+4]=
out[(x*3)+4]=in[x+1];//copy green
out[((img_w+x)*3)+1]=in[x+img_w];//copy green
out[((img_w+x)*3)+5]=in[x+img_w+1];//copy blue
/*}
else//we are on the edge defualt to edge safe algorthim
{
out[(x*3)]=in[x];//copy red
out[(x*3)+1]=in[x+1];//green
out[(x*3)+2]=in[x+1+img_w];//blue
out[(x*3)+3]=in[x];//red
out[(x*3)+4]=in[x+1];//green
out[(x*3)+5]=in[x+1+img_w];//blue
out[((x+img_w)*3)]=in[x];//red
out[((x+img_w)*3)+1]=in[x+img_w];//green
out[((x+img_w)*3)+2]=in[x+1+img_w];//blue
out[((x+img_w)*3)+3]=in[x];//red
out[((x+img_w)*3)+4]=in[x+img_w];//green
out[((x+img_w)*3)+5]=in[x+img_w+1];//blue
}*/
}
out+=img_w*6;
in+=img_w*2;
}
}
uint8_t readImg(uint32_t num,uint8_t * dat)
{
sprintf(buf,"F%d.YUV",num);
FILE * myfile = fopen(buf,"rb");
if (myfile==0)
{
printf("Cannot open file %s\n",buf);
return 1;
}
fread(dat,2,img_w*img_h,myfile);
fclose(myfile);
return 0;
}
uint8_t processImg(uint8_t * in,uint8_t * out,uint32_t num,uint8_t alg,uint16_t offset)
{
if (readImg(num,in))
return 1;
uint32_t w,h;
switch (alg)
{
case 2:
deBayerL(in+offset,out);//linear
break;
case 1:
deBayerN(in+offset,out);//nearest neighboor low quality try to avoid using
break;
case 0:
yuv2rgb(in+offset,out);
break;
default:
puts("You must pick an algorithm to save the image as");
return 1;
}
sprintf(buf,"frame %d.png",num);
if (savePNG(buf,img_w,img_h,out))
{
return 1;
puts("Error while saving PNG");
}
return 0;
}
int main(int argc,char ** argv)
{
uint8_t useNum=0;
uint32_t useImg;
uint16_t offset=0;
uint8_t debayer=1;
if (argc>1)
{
//handle arguments
int arg;
for (arg=0;arg<argc;arg++)
{
if (strcmp(argv[arg],"-n") == 0)
{
arg++;
useImg=atoi(argv[arg]);
useNum=1;
continue;
}
if (strcmp(argv[arg],"-o") == 0)
{
arg++;
offset=atoi(argv[arg]);
if (offset>img_w)
{
printf("you must specify a number between 0 and %d for argument -o\n",img_w);
showHelp();
return 1;
}
continue;
}
if (strcmp(argv[arg],"-h") == 0)
{
showHelp();
continue;
}
}
}
uint8_t * Dat;//in case some of the file was not saved we use calloc instead of malloc to garentte that the unsaved pixels are set to 0
if (debayer!=0)
Dat = calloc(img_w*img_h+img_w,1);
else
Dat = calloc(img_w*img_h+img_w,2);
uint8_t * outImg = malloc(img_w*img_h*3);//all bytes in the array will be overwritten no need for calloc
if (useNum)
{
processImg(Dat,outImg,useImg,debayer,offset);
}
else
{
uint32_t imgC;
for (;;imgC++)
{
printf("Saving image %d\n",imgC);
if (processImg(Dat,outImg,imgC,debayer,offset))
return 1;
}
}
free(Dat);
free(outImg);
return 0;
}