bmp2yuv

来源:互联网 发布:宁夏干部网络培训登录 编辑:程序博客网 时间:2024/06/07 03:20

实验原理:

1BMP文件的组成结构

BMP(全称 Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,在绝大多数应用中不采用其他任何压缩,因此BMP文件所占用的空间很大。BMP文件的图像深度可选 1bit4bit 8bit16bit24bit,指存储每个像素所用的位数。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是 Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形软件都支持BMP图像格式。

 

典型的BMP图像文件由四部分组成:

1)位图头文件数据结构,它包含 BMP图像文件的类型、显示内容等信息;

2)位图信息数据结构,它包含有 BMP图像的宽、高、压缩方法,以及定义颜色等信息;

3)调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的 BMP)就不需要调色板;

4)位图数据,这部分的内容根据 BMP位图使用的位数不同而不同,在 24位图中直接使用 RGB,而其他的小于 24位的使用调色板中颜色索引值。

 

实验流程

1. 程序初始化

2. 读取bmp文件,抽取或生成rgb写入缓冲区

3. 调用rgb2yuv函数实现rgb2yuv数据的转换

4. 写入yuv文件

5. 关闭文件,释放缓冲区

 

实验代码:

Main.cpp

#include <stdio.h>

#include <Windows.h>

#include <malloc.h>

#include <memory.h>

#include "rgb2yuv.h"

#include "readrgb.h"

#define u_int8_t   unsigned __int8

#define u_int      unsigned __int32

#define u_int32_t  unsigned __int32

BITMAPFILEHEADER File_header;

BITMAPINFOHEADER Info_header;

void main(int argc, char *argv[])

{

 

     FILE*bmpFile = NULL;

     FILE*yuvFile = NULL;

     FILE*out2huff = NULL;

     char*bmpFileName = NULL;

     char*yuvFileName = NULL;

     //u_intFrames = 40;

     char*diffFileName = NULL;

     BYTE*rgbData=NULL;

     BYTE*y_buf=NULL,

         *u_buf=NULL,*v_buf=NULL;

     intQbits;

 

     bmpFileName= argv[1];

     yuvFileName= argv[2];

     //Frames= atoi(argv[3]);

     diffFileName= argv[3];

     Qbits= atoi(argv[4]);

 

     bmpFile= fopen(bmpFileName, "rb+");

     if(bmpFile == NULL)

     {

         printf("can'tfind the bmp file\n");

     }

     else{

         printf("THEinput bmp file is %s\n", bmpFileName);

     }

 

     yuvFile= fopen(yuvFileName, "wb+");

     if(yuvFile == NULL)

     {

         printf("worryoutput file path\n");

     }

     else

     {

         printf("theoutput yuv file is %s\n", yuvFileName);

     }

 

     //   read file & info header

     if(fread(&File_header, sizeof(BITMAPFILEHEADER), 1, bmpFile) != 1)

     {

         printf("readfile header error!\n");

         exit(0);

     }

     if(File_header.bfType != 0x4D42)

     {

         printf("Notbmp file!\n");

         exit(0);

     }

     else

     {

         printf("thisis a %c%c\n", 0x42,0x4d);//存在问题

     }

    

     if(fread(&Info_header,sizeof(BITMAPINFOHEADER),1,bmpFile)!=1)

     {

         printf("readinfo header error!");

         exit(0);

     }

     //endread header

     rgbData= (unsigned char *)malloc(Info_header.biWidth*Info_header.biHeight * 3);

     memset(rgbData,0, Info_header.biWidth*Info_header.biHeight * 3);

     y_buf= (unsigned char *)malloc(Info_header.biWidth*Info_header.biHeight );

     u_buf= (unsigned char *)malloc(Info_header.biWidth*Info_header.biHeight / 4);

     v_buf= (unsigned char *)malloc(Info_header.biWidth*Info_header.biHeight / 4);

     printf("Thisis a %d bits image!\n", Info_header.biBitCount);

     printf("\nbmpsize: \t%d X %d\n\n", Info_header.biWidth, Info_header.biHeight);

 

     ReadRGB(bmpFile,File_header, Info_header, rgbData);

 

     RGB2YUV(Info_header.biWidth,Info_header.biHeight, rgbData, y_buf, u_buf, v_buf, 0);

 

     /*

         对y灰度值进行DPCM处理

         */

     int* qn = NULL;

     unsignedchar * q = NULL;

     unsignedchar * rebuild = NULL;

     qn= (int *)malloc(Info_header.biWidth*Info_header.biHeight*sizeof(int));

     q= (unsigned char *)malloc(Info_header.biWidth*Info_header.biHeight);

     rebuild= (unsigned char *)malloc(Info_header.biWidth*Info_header.biHeight);

     intscale = 512 / (1 << Qbits);

 

     for(int i = 0; i < Info_header.biHeight; i++)

     {

 

         for(int j = 0; j < Info_header.biWidth; j++)

         {

              if(j == 0)  //第一列灰度值为128

              {

                   qn[i*Info_header.biWidth+ j] = y_buf[i*Info_header.biWidth + j] - 128;             //负反馈

              }

              else{

                   qn[i*Info_header.biWidth+ j] = y_buf[i*Info_header.biWidth + j] - rebuild[i*Info_header.biWidth + j -1];

              }

 

              qn[i*Info_header.biWidth+ j] = qn[i*Info_header.biWidth + j] / scale;//简单量化

 

              if(j == 0){

                   rebuild[i*Info_header.biWidth+ j] = qn[i*Info_header.biWidth + j] * scale + 128;        //重建过程

              }

              else

              {

                   rebuild[i*Info_header.biWidth+ j] = qn[i*Info_header.biWidth + j] * scale + rebuild[i*Info_header.biWidth +j - 1];

              }

 

              q[i*Info_header.biWidth+ j] = qn[i*Info_header.biWidth + j] +128;

         }

 

     }

 

 

 

     //memset(u_buf,128, Info_header.biWidth*Info_header.biHeight);

     //   memset(v_buf, 128,Info_header.biWidth*Info_header.biHeight);

    

         fwrite(rebuild,1, Info_header.biWidth*Info_header.biHeight, yuvFile);

         //fwrite(u_buf,1, Info_header.biWidth*Info_header.biHeight / 4, yuvFile);

         //fwrite(v_buf,1, Info_header.biWidth*Info_header.biHeight / 4, yuvFile);

         out2huff= fopen(diffFileName, "wb");

         fwrite(q,1, Info_header.biWidth*Info_header.biHeight, out2huff);

 

     if(rgbData) free(rgbData);

     if(qn) free(qn);

     if(q) free(q);

     if(rebuild) free(rebuild);

     if(y_buf) free(y_buf);

     if(u_buf) free(u_buf);

     if(v_buf) free(v_buf);

     fclose(out2huff);

     fclose(bmpFile);

     fclose(yuvFile);

}

 

bmp2yuv.cpp


#include<stdio.h> 

#include<math.h> 

#include"BMPtoYUV.h" 

#include<Windows.h> 

 

static float RGBYUV02990[256],RGBYUV05870[256], RGBYUV01140[256]; 

static float RGBYUV01684[256],RGBYUV03316[256]; 

static float RGBYUV04187[256],RGBYUV00813[256]; 

bool MakePalette(FILE * pFile,BITMAPFILEHEADER &file_h, BITMAPINFOHEADER & info_h, RGBQUAD*pRGB_out) 

   /*若图像开始位置与INFOHEADER结束处位置还有pow(2,info_h.biBitCount 

   结构体RGBQUAQ的空间颜色数为2biBitCount次方调色板为数组), 

   则说明该bmp图像有调色板。*/ 

   if ((file_h.bfOffBits - sizeof(BITMAPFILEHEADER) - info_h.biSize) ==sizeof(RGBQUAD)*pow(2, info_h.biBitCount)) 

   { 

       fseek(pFile, sizeof(BITMAPFILEHEADER) + info_h.biSize, 0); 

       fread(pRGB_out, sizeof(RGBQUAD), (unsigned int)pow(2,info_h.biBitCount), pFile); 

       return true; 

   } 

   else 

       return false; 

void ReadRGB(unsigned char * rgbbuf,FILE *bmpfile, BITMAPFILEHEADER &file_h, BITMAPINFOHEADER &info_h) 

   u_int Height = 0, Width = 0; 

   long Loop = 0; 

   unsigned char *bmpbuf = NULL; 

   unsigned char *rgb = NULL; 

   unsigned char mask = 0; 

   int deltaw = 0; 

   rgb = rgbbuf; 

 

   if (((info_h.biWidth  *info_h.biBitCount / 8) % 4) == 0) 

       Width = info_h.biWidth*info_h.biBitCount / 8; 

   else 

       Width = (info_h.biWidth  *info_h.biBitCount + 31) / 32 * 4; 

 

   if ((info_h.biHeight % 2) == 0) 

       Height = info_h.biHeight; 

   else 

       Height = info_h.biHeight +1; 

   deltaw = Width - info_h.biWidth * info_h.biBitCount / 8; 

   bmpbuf = (unsigned char *)malloc(sizeof(unsignedchar)*Height*Width); 

   printf("word_width :%d , word_height: %d \n", Width,Height); 

   RGBQUAD *pRGB = (RGBQUAD *)malloc(sizeof(RGBQUAD) * (unsignedint)pow(2.0, (double)info_h.biBitCount)); 

   if (!MakePalette(bmpfile, file_h, info_h, pRGB)) 

   { 

       printf("No palette!\n"); 

   } 

   fread(bmpbuf, 1, Height*Width, bmpfile); 

   if (info_h.biBitCount == 24) 

   { 

       for (Loop = 0; Loop<Height*Width; Loop++) 

       { 

            if (deltaw != 0) 

            { 

                if (deltaw == 1) 

                { 

                    if ((Loop + 1) % Width == 0) 

                        continue; 

                } 

                else if (deltaw == 2) 

                { 

                    if ((Loop + 1) % Width == 0|| (Loop + 2) % Width == 0) 

                        continue; 

                } 

                else 

                { 

                    if ((Loop + 1) % Width == 0|| (Loop + 2) % Width == 0 || (Loop + 3) % Width == 0) 

                        continue; 

                } 

            } 

            *rgb = *(bmpbuf + Loop); 

            rgb++; 

       } 

   } 

   else if (info_h.biBitCount == 16) 

   { 

       for (Loop = 0; Loop < Height * Width; Loop += 2) 

       { 

            *rgb = (bmpbuf[Loop] & 0x1F)<< 3; 

            *(rgb + 1) = ((bmpbuf[Loop] &0xE0) >> 2) + ((bmpbuf[Loop + 1] & 0x03) << 6); 

            *(rgb + 2) = (bmpbuf[Loop + 1]& 0x7C) << 1; 

            rgb += 3; 

       } 

   } 

   else 

   { 

       for (Loop = 0; Loop < Height*Width; Loop++) 

       { 

            if (deltaw != 0) 

            { 

                if (deltaw == 1) 

                { 

                    if ((Loop + 1) % Width ==0) 

                        continue; 

                } 

                else if (deltaw == 2) 

                { 

                    if ((Loop + 1) % Width == 0|| (Loop + 2) % Width == 0) 

                        continue; 

                } 

                else 

                { 

                    if ((Loop + 1) % Width == 0|| (Loop + 2) % Width == 0 || (Loop + 3) % Width == 0) 

                        continue; 

                } 

            } 

 

            switch (info_h.biBitCount) 

            { 

            case 1: 

                mask = 0x80; 

                break; 

            case 2: 

                mask = 0xC0; 

                break; 

            case 4: 

                mask = 0xF0; 

                break; 

            case 8: 

                mask = 0xFF; 

                break; 

            } 

            int shiftCnt = 1; 

            while (mask) 

            { 

                /*根据从数据中提取出的索引号indexindex为调色板数组下标去查询 

                数据中每info_h.biBitCount位所代表的颜色。 

                while 循环的次数: 

                1bit 图像每字节循环8 

                2bit 图像 每字节循环4次 

                4bit 图像 每字节循环2次 

                8bit 图像 每字节循环1次。 

                */ 

                unsigned char index = 

                    mask == 0xFF ? bmpbuf[Loop]: ((bmpbuf[Loop] & mask) >> (8 - shiftCnt *info_h.biBitCount)); 

                *rgb =pRGB[index].rgbBlue; 

                *(rgb + 1) =pRGB[index].rgbGreen; 

                *(rgb + 2) = pRGB[index].rgbRed; 

                if (info_h.biBitCount == 8)mask = 0; 

                else    mask >>= info_h.biBitCount; 

                rgb += 3; 

                shiftCnt++; 

            } 

       } 

 

   } 

   if (pRGB != NULL) free(pRGB); 

   if (bmpbuf != NULL)free(bmpbuf); 

}  



实验结果:

原bmp图


经转换过的bmp图