Convert YUV(4:2:2) format to BMP file by use of OV9655 image sensor.

Thread Starter


Joined Nov 9, 2016
Hello anyone

I working on OV9655 camera module that is connected to stm32f4discover evaluation board. I am able to capture a picture from the OV9655 module where the video output format is based on RGB565 and save as BMP file on SD cart. Now I want to capture a gray scale picture and save it as BMP file. For that purpose do use YUV(4:2:2:) video format

The picture size is 120*160.

As I am is aware does YUV(4:2:2) format consist of 4 byte: Yo,Uo,Y1,Vo that sent out through OV9655 video interface. The OV9655 interface is connected to DCIM interface on STM32F407 microcontroller.

The following register setting is use to up OV9655 image chip to send out YUV(4:2:2) video format.

OV9655 COM7 Register setting:

Bit7=0 no changed

Bit6..4 = 110 30fps VGA with VerioPixel.

Bit 3..2 not used

Bit 1..0 10 YUV RGB data

The OV9655 TSL Register setting:

Bit 7..6 11 PCL output delay set to 6 ns

Bit5 0

Bit4 0 Normal UV output

Bit3.2 00 YUYV output sequence

Bit 1 0

Bit 0 not used

OV9655 COM15 Register:

Bit 7..6 10 Output range [01] to [FE]

Bit 5..4 Normal RGB output

Bit 3..0 Not Used.

But I am not sure about that above setting for OV9655 is correct.
After the picture is grab by used of DCIM on STM32F407 microcontroller do I want to convert it to BMP file. Right now do I use the same code that is use during conversation of RGB565 to transform YUV(4:2:2) format to BMP file. The code work fine during conversation of RGB565 to BMP file.

But is it possible to use the same procedure during the conversation of YUV(4:2:2) format to BMP file?

Can the same BMP header that is use for RGB565 be use on the YUV(4:2:2) video format?

// BMP Header
#ifdef QQVGA
//@brief  Set the QQVGA size(120*160).
uint8_t bmp_header[70] = {
  0x42, 0x4D, // ID field // BM
    0x46, 0x58, 0x02, 0x00, // Size of BMP file 153670 bytes
    0x00, 0x00, 0x00, 0x00, // Not use Application specific
    0x46, 0x00, 0x00, 0x00, // Offset where the pixel array can be found 70
    // DIB Header
    0x28, 0x00, 0x00, 0x00, // Number of bytes in the DIB header (from this point) 40 bytes
    0xA0, 0x00, 0x00, 0x00, // Width of the bitmap in pixel 160
    0x78, 0x00, 0x00, 0x00, // Height of the bitmap in  pixel 120
    0x01,    0x00,             // Plane
    0x10,    0x00,                         // 16 bits number of bits pr pixels
    0x03, 0x00, 0x00, 0x00, // BI_RGB
    0x00, 0x58, 0x02, 0x00, // pixels/meter horizontal
    0x00, 0x00, 0x00, 0x00, // pixels/meter vertical
    0x00, 0x00, 0x00, 0x00, // Number ofcolors in the palette
    0x00, 0x00, 0x00, 0x00, // 0 means all color are important
    // Start of pixel array
    0x00, 0x00, 0x00,       // Red, Pixel(0,1)
    0x00,    0x00, 0xF8,                // write, Pixel(1,1)
    0x00, 0x00,                            // Pading for 4 byte alligment
    0xE0, 0x07, 0x00,             // Blue, Pixel
    0x00, 0x1F, 0x00,             // Green Pixel
  0x00, 0x00,                            // Padding for 4 byte
    0x00, 0x00, 0x00, 0x00

/* write the bmp header */
ret = f_write(&file, bmp_header, 70,(UINT*)&bw);
The code loop that handle the BMP conversation is as follow.
// QQVGA size(120*160).
for (j = 0; j < 120; j++)
      data_temp = frameptr[counter];
      // MSB Byte of 16 bit
      image_buf[i*2+1] = (data_temp&0xff00) >> 8;
      // LSB Byte of 16 bit
      image_buf[i*2+0] = data_temp & 0x00ff;
   ret = f_write(&file, image_buf, 320,(UINT*)&bw);

ret = f_close(&file);

DNA Robotics

Joined Jun 13, 2014
Recommended 8-Bit YUV Formats for Video Rendering

4:2:2 means 2:1 horizontal downsampling, with no vertical downsampling. Every scan line contains four Y samples for every two U or V samples.

Surface origin. For the YUV formats described in this article, the origin (0,0) is always the top left corner of the surface.
In BMP, the first bytes after the header are the bottom left corner of the surface.

I thought I was going to give you an easy answer using the bitmap header from any 120 X 160 gray scale picture & just use the Y luma channel. I guess not. I think it would be easier to convert color to gray scale.