OV7670_with_AL422B Color & Size Test Program

Dependencies:   mbed

main.cpp

Committer:
diasea
Date:
2013-02-18
Revision:
4:2c412c97678c
Parent:
3:e23726af9d38

File content as of revision 4:2c412c97678c:

#define BITMAPFILE
#undef BAYERBITMAPFILE
#undef HEXFILE
#undef COLORBAR

#include "mbed.h"
#include <algorithm>
#include "ov7670.h"

OV7670 camera(
    p28,p27,       // SDA,SCL(I2C / SCCB)
    p12,p11,p10,   // VSYNC,HREF,WEN(FIFO)
    p24,p15,p25,p16,p26,p17,p29,p18, // D7-D0
    p20,p30,p19) ; // RRST,OE,RCLK

LocalFileSystem local("local");

Serial pc(USBTX,USBRX) ;

int sizex = 0;
int sizey = 0;

#if defined(BITMAPFILE) || defined(BAYERBITMAPFILE)

#define FILEHEADERSIZE 14                   //ファイルヘッダのサイズ
#define INFOHEADERSIZE 40                   //情報ヘッダのサイズ
#define HEADERSIZE (FILEHEADERSIZE+INFOHEADERSIZE)

int create_header(FILE *fp, int width, int height) {
    int real_width;
    unsigned char header_buf[HEADERSIZE]; //ヘッダを格納する
    unsigned int file_size;
    unsigned int offset_to_data;
    unsigned long info_header_size;
    unsigned int planes;
    unsigned int color;
    unsigned long compress;
    unsigned long data_size;
    long xppm;
    long yppm;

    real_width = width*3 + width%4;

    //ここからヘッダ作成
    file_size = height * real_width + HEADERSIZE;
    offset_to_data = HEADERSIZE;
    info_header_size = INFOHEADERSIZE;
    planes = 1;
    color = 24;
    compress = 0;
    data_size = height * real_width;
    xppm = 1;
    yppm = 1;

    header_buf[0] = 'B';
    header_buf[1] = 'M';
    memcpy(header_buf + 2, &file_size, sizeof(file_size));
    header_buf[6] = 0;
    header_buf[7] = 0;
    header_buf[8] = 0;
    header_buf[9] = 0;
    memcpy(header_buf + 10, &offset_to_data, sizeof(offset_to_data));
    memcpy(header_buf + 14, &info_header_size, sizeof(info_header_size));
    memcpy(header_buf + 18, &width, sizeof(width));
    height = height * -1; // データ格納順が逆なので、高さをマイナスとしている
    memcpy(header_buf + 22, &height, sizeof(height));
    memcpy(header_buf + 26, &planes, sizeof(planes));
    memcpy(header_buf + 28, &color, sizeof(color));
    memcpy(header_buf + 30, &compress, sizeof(compress));
    memcpy(header_buf + 34, &data_size, sizeof(data_size));
    memcpy(header_buf + 38, &xppm, sizeof(xppm));
    memcpy(header_buf + 42, &yppm, sizeof(yppm));
    header_buf[46] = 0;
    header_buf[47] = 0;
    header_buf[48] = 0;
    header_buf[49] = 0;
    header_buf[50] = 0;
    header_buf[51] = 0;
    header_buf[52] = 0;
    header_buf[53] = 0;

    //ヘッダの書き込み
    fwrite(header_buf, sizeof(unsigned char), HEADERSIZE, fp);

    return 0;
}
#endif

int main() {
    pc.baud(115200);

    pc.printf("Camera resetting..\r\n");
    camera.Reset();

    pc.printf("Before Init...\r\n");
    camera.PrintRegister();

    pc.printf("Select color format.\r\n") ;
    pc.printf("1: RGB444.\r\n");
    pc.printf("2: RGB555.\r\n");
    pc.printf("3: RGB565.\r\n");
    pc.printf("4: YUV(UYVY).\r\n");
    pc.printf("5: Bayer RGB(BGBG... GRGR...).\r\n");

    while(!pc.readable());
    char color_format = pc.getc();
    switch (color_format) {
        case '1':
            camera.InitRGB444();
            break;
        case '2':
            camera.InitRGB555();
            break;
        case '3':
            camera.InitRGB565();
            break;
        case '4':
            camera.InitYUV();
            break;
        case '5':
            camera.InitBayerRGB();
            break;
    }
    pc.printf("select %c\r\n", color_format);

    pc.printf("Select screen size.\r\n") ;
    switch (color_format) {
        case '5':
            pc.printf("1: VGA(640x480).\r\n");
        case '1':
        case '2':
        case '3':
        case '4':
            pc.printf("2: FIFO nealy limit(544x360).\r\n");
            pc.printf("3: VGA*3/4(480x360).\r\n");
            pc.printf("4: QVGA(320x240).\r\n");
            pc.printf("5: QQVGA(160x120).\r\n");
            break;
    }

    while(!pc.readable());
    char screen_size = pc.getc() ;
    switch (screen_size) {
        case '1':
            sizex = 640;
            sizey = 480;
            camera.InitVGA();
            break;
        case '2':
            sizex = 544;
            sizey = 360;
            camera.InitFIFO_2bytes_color_nealy_limit_size();
            break;
        case '3':
            sizex = 480;
            sizey = 360;
            camera.InitVGA_3_4();
            break;
        case '4':
            sizex = 320;
            sizey = 240;
            camera.InitQVGA();
            break;
        case '5':
            sizex = 160;
            sizey = 120;
            camera.InitQQVGA();
            break;
    }
    pc.printf("select %c\r\n", screen_size);

    camera.InitForFIFOWriteReset();
    camera.InitDefaultReg();

#ifdef COLORBAR
    camera.InitSetColorbar();
#endif

    pc.printf("After Init...\r\n");
    camera.PrintRegister();

    // CAPTURE and SEND LOOP
    while(1)
    {
#if defined(BITMAPFILE) || defined(BAYERBITMAPFILE) || defined(HEXFILE)
        pc.printf("Hit Any Key %dx%d Capture Data.\r\n", sizex, sizey) ;
        while(!pc.readable());
        pc.printf("*\r\n");
        pc.getc();

        int real_width = sizex*3 + sizey%4;

        unsigned char *bmp_line_data; //画像1行分のRGB情報を格納する
        if((bmp_line_data = (unsigned char *)malloc(sizeof(unsigned char)*real_width)) == NULL){
           fprintf(stderr, "Error: Allocation error.\n");
           return 1;
        }

        //RGB情報を4バイトの倍数に合わせている
        for(int i=sizex*3; i<real_width; i++){
            bmp_line_data[i] = 0;
        }
#endif
#if defined(BITMAPFILE) || defined(BAYERBITMAPFILE)
        FILE *fp;
        char *filename = "/local/test.bmp";
        if((fp = fopen(filename, "wb")) == NULL){
            pc.printf("Error: %s could not open.", filename);
            return 1;
        }

        create_header(fp, sizex, sizey);
#endif
#ifdef HEXFILE
        FILE *fp2;
        char *filename2 = "/local/test.txt";
        if((fp2 = fopen(filename2, "w")) == NULL){
            pc.printf("Error: %s could not open.", filename2);
            return 1;
        }
#endif

        camera.CaptureNext();
        while(camera.CaptureDone() == false);
        camera.ReadStart();

        int r=0, g=0, b=0, d1, d2;

        switch (color_format) {
            case '1':
            case '2':
            case '3':

                for (int y=0; y<sizey; y++) {
                    for (int x=0; x<sizex; x++) {
                        d1 = camera.ReadOneByte();
                        d2 = camera.ReadOneByte();

                        switch (color_format) {
                            case '1':
                                // RGB444 to RGB888
                                b = (d1 & 0x0F) << 4;
                                g = (d2 & 0xF0);
                                r = (d2 & 0x0F) << 4;
                                break;
                            case '2':
                                // RGB555 to RGB888
                                b = (d1 & 0x1F) << 3;
                                g = (((d1 & 0xE0) >> 2) | ((d2 & 0x03) << 6));
                                r = (d2 & 0x7c) << 1;
                                break;
                            case '3':
                                // RGB565 to RGB888
                                b = (d1 & 0x1F) << 3;
                                g = (((d1 & 0xE0) >> 3) | ((d2 & 0x07) << 5));
                                r = (d2 & 0xF8);
                                break;                                
                        }
#if defined(BITMAPFILE) || defined(HEXFILE)
                        bmp_line_data[x*3]     = (unsigned char)b;
                        bmp_line_data[x*3 + 1] = (unsigned char)g;
                        bmp_line_data[x*3 + 2] = (unsigned char)r;
#endif
/*
                        // RGB
                        pc.printf ("%2X%2X%2X", r, g, b) ;
*/
                    }
#ifdef BITMAPFILE
                    fwrite(bmp_line_data, sizeof(unsigned char), real_width, fp);
#endif
#ifdef HEXFILE
                    for(int i=0; i<sizex*3; i++){
                        fprintf(fp2, "%02X", bmp_line_data[i]);
                    }
#endif
//                    pc.printf("\r\n") ;
                }
                break;

            case '4':
                int index = 0;
                for (int y=0; y<sizey; y++) {
                    int U0=0, Y0=0, V0=0, Y1=0;
                    for (int x=0; x<sizex; x++) {
                        if(index%2 == 0) {
                            U0 = camera.ReadOneByte();
                            Y0 = camera.ReadOneByte();
                            V0 = camera.ReadOneByte();
                            Y1 = camera.ReadOneByte();

                            b = Y0 + 1.77200 * (U0 - 128);
                            g = Y0 - 0.34414 * (U0 - 128) - 0.71414 * (V0 - 128);
                            r = Y0 + 1.40200 * (V0 - 128);
                        } else {
                            b = Y1 + 1.77200 * (U0 - 128);
                            g = Y1 - 0.34414 * (U0 - 128) - 0.71414 * (V0 - 128);
                            r = Y1 + 1.40200 * (V0 - 128);
                        }

                        b = min(max(b, 0), 255);
                        g = min(max(g, 0), 255);
                        r = min(max(r, 0), 255);

#if defined(BITMAPFILE) || defined(HEXFILE)
                        bmp_line_data[x*3]     = (unsigned char)b;
                        bmp_line_data[x*3 + 1] = (unsigned char)g;
                        bmp_line_data[x*3 + 2] = (unsigned char)r;
#endif
/*
                        // RGB
                        pc.printf ("%2X%2X%2X", r, g, b) ;
*/
                        index++;
                    }
#ifdef BITMAPFILE
                    fwrite(bmp_line_data, sizeof(unsigned char), real_width, fp);
#endif
#ifdef HEXFILE
                    for(int i=0; i<sizex*3; i++){
                        fprintf(fp2, "%02X", bmp_line_data[i]);
                    }
#endif
//                    pc.printf("\r\n") ;
                }
                break;

            case '5':
                unsigned char *bayer_line[2];
                unsigned char *bayer_line_data[2]; //画像1行分のRGB情報を格納する2行分
                for(int i=0; i<2; i++) {
                    if((bayer_line_data[i] = (unsigned char *)malloc(sizeof(unsigned char)*sizex)) == NULL){
                       fprintf(stderr, "Error: Allocation error.\n");
                       return 1;
                    }
                }

                for (int x=0; x<sizex; x++) {
                    // odd line BGBG... even line GRGR...
                    bayer_line_data[0][x] = (unsigned char)camera.ReadOneByte();
#ifdef BAYERBITMAPFILE
                    bmp_line_data[x*3]     = (unsigned char)bayer_line_data[0][x];
                    bmp_line_data[x*3 + 1] = (unsigned char)bayer_line_data[0][x];
                    bmp_line_data[x*3 + 2] = (unsigned char)bayer_line_data[0][x];
#endif
                }
#ifdef BAYERBITMAPFILE
                fwrite(bmp_line_data, sizeof(unsigned char), real_width, fp);
#endif
                bayer_line[1] = bayer_line_data[0];

                for (int y=1; y<sizey; y++) {
                    int line = y%2;

                    for (int x=0; x<sizex; x++) {
                        // odd line BGBG... even line GRGR...
                        bayer_line_data[line][x] = (unsigned char)camera.ReadOneByte();
#ifdef BAYERBITMAPFILE
                        bmp_line_data[x*3]     = (unsigned char)bayer_line_data[line][x];
                        bmp_line_data[x*3 + 1] = (unsigned char)bayer_line_data[line][x];
                        bmp_line_data[x*3 + 2] = (unsigned char)bayer_line_data[line][x];
#endif
                    }
#ifdef BAYERBITMAPFILE
                    fwrite(bmp_line_data, sizeof(unsigned char), real_width, fp);
#endif
                    bayer_line[0] = bayer_line[1];
                    bayer_line[1] = bayer_line_data[line];

                    for (int x=0; x<sizex - 1; x++) {
                        if(y%2==1) {
                            if(x%2==0) {
                                // BG
                                // GR
                                b = bayer_line[0][x];
                                g = ((int)bayer_line[0][x+1] + bayer_line[1][x])>>1;
                                r = bayer_line[1][x+1];
                            } else {
                                // GB
                                // RG
                                b = bayer_line[0][x+1];
                                g = ((int)bayer_line[0][x] + bayer_line[1][x+1])>>1;
                                r = bayer_line[1][x];
                            }
                        } else {
                            if(x%2==0) {
                                // GR
                                // BG
                                b = bayer_line[1][x];
                                g = ((int)bayer_line[0][x] + bayer_line[1][x+1])>>1;
                                r = bayer_line[0][x+1];
                            } else {
                                // RG
                                // GB
                                b = bayer_line[1][x+1];
                                g = ((int)bayer_line[0][x+1] + bayer_line[1][x])>>1;
                                r = bayer_line[0][x];
                            }
                        }
#if defined(BITMAPFILE) || defined(HEXFILE)
                        bmp_line_data[x*3]     = (unsigned char)b;
                        bmp_line_data[x*3 + 1] = (unsigned char)g;
                        bmp_line_data[x*3 + 2] = (unsigned char)r;
#endif
                    }

#ifdef BITMAPFILE
                    fwrite(bmp_line_data, sizeof(unsigned char), real_width, fp);
#endif

#ifdef HEXFILE
                    for(int i=0; i<sizex*3; i++){
                        fprintf(fp2, "%02X", bmp_line_data[i]);
                    }
#endif
                }

                for(int i=0; i<2; i++) {
                    free(bayer_line_data[i]);
                }
#ifdef BITMAPFILE
                fwrite(bmp_line_data, sizeof(unsigned char), real_width, fp);
#endif
                break;
        }
        camera.ReadStop();

#if defined(BITMAPFILE) || defined(BAYERBITMAPFILE)
        free(bmp_line_data);
        fclose(fp);
#endif
#ifdef HEXFILE
        fclose(fp2);
#endif

    }
}