Advertisement

bmp提取rgb888转换成yuv格式中的yv12再从yv12转换为rgb888写成bmp格式文件的工程,测试通过

阅读量:

在BMP文件中获取RGB(8/8/8)格式的数据块,并将其转码为YV12编码格式;随后从YV12编码格式中解码出RGB(8/8/8)数据块;最后一步是以BMP文件格式保存到目标存储路径的测试实验工程

///-------------rgb.cpp-----------内容是rgb与yv12格式转换函数
#include "convert.h"

Conversion from the source image in the format of red (R), green (G), and blue (B) channels to the intermediate representation of chrominance (U) and luminance (V) components. The system defines several arrays for processing these color components:

  • Chroma keying tables for both red and blue channels
  • Additional lookup tables for green chrominance and blue components
  • A static table for color correction values
  • An array of unsigned bytes used for clipping operations. This setup facilitates accurate color transformation as per international standards.

// Table used for RGB to YUV420 conversion
void InitLookupTable()
{
int i;
for (i = 0; i < 256; i++) RGB2YUV_YR[i] = (float)65.481 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_YG[i] = (float)128.553 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_YB[i] = (float)24.966 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UR[i] = (float)37.797 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UG[i] = (float)74.203 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_VG[i] = (float)93.786 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_VB[i] = (float)18.214 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UBVR[i] = (float)112 * (i<<8);
}

// Convert from RGB24 to YUV420
void ConvertRGBtoYUV(int w, int h, const unsigned char* bmp, const unsigned char* yuv)
{
// 其他代码
}

// unsigned int *u, *v, *y, *uu, *vv;
// unsigned int *pu1, *pu2, *pu3, *pu4;
// unsigned int *pv1, *pv2, *pv3, *pv4;
// unsigned char *r, *g, *b;
// int i,j;

//uu=new unsigned int[wh];
//vv=new unsigned int[w
h];

unsigned char *a,*b,*y,*aa,*bb;
unsigned char *p1u,*p2u,*p3u,*p4u;
unsigned char *pv1,*pv2,*pv3,*pv4;
unsigned char *r,*g,*b;
int i,j;

uu = \text{new } \text{unsigned } \text{char} [w * h];
vv = \text{new } \text{unsigned } \text{char} [w * h];
如果(\text{null} == uu) 或者 (\text{null} == vv), 则返回\texttt{0}.y = yuv; u = uu; v = vv; // 从 bmp 图像数据获取 r,g,b 指针.r = bmp; g = bmp + 1; b = bmp + 2;

//Get YUV values for rgb values. ..

for(idx = 0; idx < hei; idx++) {
for(pix = 0; pix < wid; pix++) {
*(y + 1) = ((((RGB2YUV_YR[r] + RGB2YUV_YG[g]) + RGB2YUV_YB[b]) + 1 << 24) >> 16);
*(u + 1) = (((-RGB2YUV_UR[r] - RGB2YUV_UG[g]) + RGB2YUV_UBVR[b]) + (1 << 29)) >> 16;
*(v + 1) = ((RGB2YUV_UBVR[r] - (RGB2YUV_VG[g] | RGB2YUV_VB[b])) + (1 << 29)) >> 16;
r += ~((int)(3. >> (double)(logf(hei))));
g += ~((int)(3. >> (double)(logf(wid))));
b += ~((int)(3. >> (double)(logf(logf(max(hei, wid)))))));
}

// Acquire the U and V to capture a YUV 4:2:0 video format
// Examination process...
/*

  • Assign value at position (x,y) in target array as follows:
  • If x is even, set it to U component
  • If x is odd, set it to V component
  • This applies for all y positions across all rows
    */
    // Identify the correct pointers for further processing...

u = y * u * v + w * h;
v = u + (w * h) / 4;
// 对于U方向
pu1 = uu;
pu2 = pu1 + 1;
pu3 = pu1 + w;
pu4 = pu3 + 1;
// 对于V方向
pv1 = vv;
pv2 = pv1 + 1;
pv3 = pv1 + w;
pv4 = pv3 + 1;
// 进行采样处理...

for(i=0;i<h;i+=2)
{
for(j=0;j<w;j+=2)
{
*u++=(*pu1+*pu2+*pu3+*pu4)>>2;
*v++=(*pv1+*pv2+*pv3+*pv4)>>2;
pu1+=2;
pu2+=2;
pu3+=2;
pu4+=2;
pv1+=2;
pv2+=2;
pv3+=2;
pv4+=2;
}

pu1+=w;
pu2+=w;
pu3+=w;
pu4+=w;
pv1+=w;
pv2+=w;
pv3+=w;
pv4+=w;

}

delete uu;
delete vv;
return 1;

}

//
//Initialize conversion table for YUV420 to RGB
//

void InitConvertTable()
{

long int crv,cbu,cgu,cgv;
int i,ind;
crv = 104597; cbu = 132201; /* fra matrise i global.h /
cgu = 25675; cgv = 53279;
for (i = 0; i < 256; i++)
{
crv_tab[i] = (i-128) * crv;
cbu_tab[i] = (i-128) * cbu;
cgu_tab[i] = (i-128) * cgu;
cgv_tab[i] = (i-128) * cgv;
tab_76309[i] = 76309
(i-16);
}

for (i=0; i<384; i++)
clp[i] =0;

ind=384;
for (i=0;i<256; i++)
clp[ind++]=i;

ind=640;
for (i=0;i<384;i++)
clp[ind++]=255;

// // Convert between YUV420 and RGB24 color spaces
//
void ConvertYUV2RGB(unsigned char *src0,unsigned char *src1,unsigned char src2(unsigned char dst_ori),int width,int height)
{
}

四个整型变量y₁、y₂、u和v。
两个指针变量py₁和py₂。
六个整型变量i、j以及c₁至c₄。
两个指针变量d₁和d₂。
其中,
py₁指向源地址src₀,
py₂等于 py₁加上宽度,
d₁指向目标地址dst_ori,
d₂等于 d₁加上三倍宽度。

for (j = 0; j < height; j += 2)
{

for (i = 0; i < width; i += 2)
{

u 的值等于 src1 指针所指的变量值后加一。
v 的值等于 src2 指针所指的变量值后加一。
通过 crv_tab 数组查找 v 对应的元素得到 c1。
通过 cgu_tab 数组查找 u 对应的元素得到 c2。
通过 cgv_tab 数组查找 v 对应的元素得到 c3。
通过 cbu_tab 数组查找 u 对应的元素得到 c4。
// 处理上左方向
将 y1 设置为 tab_76309 数组中当前 py 指针指向的位置处取值,
然后将 y 加上 (c + 一半) 并加上 384 得到索引位置。
// 处理下左方向
将 y2 设置为 tab_76309 数组中当前 py 指针指向的位置处取值,
然后将 y 加上 (c - 另一个数的一半) 并加上 384 得到索引位置。
// 处理上右方向
将 y1 设置为 tab_76309 数组中当前 py 指针指向的位置处取值,
然后将 y 加上 (c + 另一个数的一半) 并加上 384 得到索引位置。
// 处理下右方向
将 y2 设置为 tab_76309 数组中当前 py 指针指向的位置处取值,
然后将 y 加上 (c + 另一个数的一半) 并加上 384 得到索引位置。

d1 += 3width;
d2 += 3
width;
py1+= width;
py2+= width;
}
}
///----------------------convert.h--头文件
#ifndef CONVERT_H
#define CONVERT_H
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
// Conversion from RGB24 to YUV420
void InitLookupTable();
//int ConvertRGB2YUV(int w,int h,unsigned char *rgbdata,unsigned int *yuv);
int ConvertRGB2YUV(int w,int h,unsigned char bmp,unsigned charyuv) ;
// Conversion from YUV420 to RGB24
void InitConvertTable();
void ConvertYUV2RGB(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori,
int width,int height);
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef long LONG;
#pragma pack (1)
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;

#endif ///CONVERT_H
//--------------------------main.cpp ,转换格式的测试文件
#include "convert.h"

定义宽度为176像素。
定义高度为144像素。
计算YUV格式的像素总数。
计算RGB格式的像素总数。

创建一个名为yuv的BYTE指针,并为其分配大小为yuvsize的空间。
生成一个名为rgbdata的BYTE指针,并为其分配大小为rgbsize的空间。
对内存块yuv进行初始化操作使其全部置零。
对内存块rgbdata进行初始化操作使其全部置零。

int BitMapFileHeaderSize = 计算BITMAPFILEHEADER的大小;
BitMapFileHeaderSize = 计算BITMAPINFO_HEADER_SIZE;

Declare BIT_MAP_FILE_HEADER fileheader;
Declare FILE Pointer variable by reference with address stored in &fileheader.
Initialize memory block for file header using memset.
Declare BIT_MAP_INFO_HEADER infoheader;
Declare FILE Pointer variable by reference with address stored in &infoheader.
Initialize memory block for info header to zero using memset.
Open RGB bitmap file in read mode assigned to a stream variable.
Calculate number of bytes read from the file header using the specified stream.

int dataoffset = filehead.bfOffBits; // 表示从文件头至图像数据段起始位置所占用的字节数量。
int filesizeall = filehead.bfSize; // 表示以字节为计算单位所存储的整体文件大小。
// 标识文件类型信息。
// 该字段值必须等于十六进制数值0x4D42。

readsize = fread(infoP, sizeof(BITMAPINFOHEADER), 1, fp);
int infosize = infohead.biSize;//描述BITMAPINFOHEADER结构所需的字节数
int biW = infohead.biWidth;//表示图像宽度(像素单位)
int biH = infohead.biHeight;//表示图像高度(像素单位)。如果是正值,则表示图像是倒置的;如果是负值则表示图像是正向的。通常BMP文件是倒置的位图文件。
int indexsize = infohead.biBitCount;//其取值为1、4、8、16、24或32
int isCompress = infohead.biCompression;//指示图像数据压缩类型的信息
int sizeImg = infohead.biSizeImage;//表示图像大小(以字节为单位)。在使用BI_RGB格式时可设置为0

定义为指向RGB数据区域的指针变量rgbP。
从biH-1开始递减至0进行循环。
在每次主循环迭代时:
初始化rgbP指向当前行的第一个像素块起始位置。
从biH-1行开始逐行逆序读取RGB数据:
外层循环变量i表示当前处理的行索引。
内层循环依次遍历宽度范围内的每个像素通道:
先读取蓝色通道的数据;
接着读取绿色通道的数据;
最后读取红色通道的数据。
每次完成一个像素通道的数据读入后,
指针变量rgbP将向前移动恰好三个字节,
以指向下一个像素块起始位置。

InitializeLookupTable();
InitializeConvertTable();
convert the RGB data to YUV format based on specified width and height.
open a file for writing in YUV format at D://rgb_1.yuv.
write the entire YUV data block into the file.
allocate a buffer to store RGB data of size rgbsize.
initialize the buffer with zero values as default.
define pointers for different components of YUV data:

  • yp points to the start of YUV data
  • up points to width*height offset
  • vp points to widthheight + widthheight/4 offset
    convert from YUV format back to RGB using specified pointers and buffer.
    open a new file for writing in BMP format at D://rgb_2.bmp.
    write header information into this new file.
    loop through each pixel in reverse order starting from biH-1
    for each pixel:
    write RGB values in reverse order (blue first) into output file
    move pointer forward by three bytes after each pixel is processed

delete(yuv);
delete(rgbdata);
fclose(fp);
fclose(fw_yuv);
fclose(fw_rgb);
return 0;
}

全部评论 (0)

还没有任何评论哟~