我解码H264的数据后得到rgb565的数据,保存一帧、一帧的位图成功。但是贴图就失败,贴出来全是黑快。求高人指点下?下面贴代码!

theheroonline 2013-07-10 04:48:19

//网上找的代码
//rgb2bmp.h文件

#include <stdio.h>

typedef unsigned char BYTE;

typedef unsigned short WORD;

// BMP图像各部分说明如下

/***********

第一部分 位图文件头

该结构的长度是固定的,为14个字节,各个域的依次如下:

2byte :文件类型,必须是0x4d42,即字符串"BM"。

4byte :整个文件大小

4byte :保留字,为0

4byte :从文件头到实际的位图图像数据的偏移字节数。

*************/

typedef struct

{ long imageSize;

long blank;

long startPosition;

}BmpHead;

/*********************

/*********************

第二部分 位图信息头

该结构的长度也是固定的,为40个字节,各个域的依次说明如下:

4byte :本结构的长度,值为40

4byte :图像的宽度是多少象素。

4byte :图像的高度是多少象素。

2Byte :必须是1。

2Byte :表示颜色时用到的位数,常用的值为1(黑白二色图)、4(16色图)、8(256色图)、24(真彩色图)。

4byte :指定位图是否压缩,有效值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS。Windows位图可采用RLE4和RLE8的压缩格式,BI_RGB表示不压缩。

4byte :指定实际的位图图像数据占用的字节数,可用以下的公式计算出来:

图像数据 = Width' * Height * 表示每个象素颜色占用的byte数(即颜色位数/8,24bit图为3,256色为1)

要注意的是:上述公式中的biWidth'必须是4的整数倍(不是biWidth,而是大于或等于biWidth的最小4的整数倍)。

如果biCompression为BI_RGB,则该项可能为0。

4byte :目标设备的水平分辨率。

4byte :目标设备的垂直分辨率。

4byte :本图像实际用到的颜色数,如果该值为0,则用到的颜色数为2的(颜色位数)次幂,如颜色位数为8,2^8=256,即256色的位图

4byte :指定本图像中重要的颜色数,如果该值为0,则认为所有的颜色都是重要的。

***********************************/

typedef struct
{

long Length;

long width;

long height;

WORD colorPlane;

WORD bitColor;

long zipFormat;

long realSize;

long xPels;

long yPels;

long colorUse;

long colorImportant;

}InfoHead;

/***************************

/***************************

第三部分 调色盘结构 颜色表

对于256色BMP位图,颜色位数为8,需要2^8 = 256个调色盘;

对于24bitBMP位图,各象素RGB值直接保存在图像数据区,不需要调色盘,不存在调色盘区

rgbBlue: 该颜色的蓝色分量。

rgbGreen: 该颜色的绿色分量。

rgbRed: 该颜色的红色分量。

rgbReserved:保留值。

************************/

typedef struct

{ BYTE rgbBlue;

BYTE rgbGreen;

BYTE rgbRed;

BYTE rgbReserved;

/* void show(void)

{

printf("Mix Plate B,G,R:%d %d %dn",rgbBlue,rgbGreen,rgbRed);

}*/

}RGBMixPlate;

/****************************

RGB加上头部信息转换成BMP

参数說明:

rgb_buffer :RGB数据文件中的信息

nData :RGB数据的长度

nWidth :图像宽度的像素数

nHeight :图像高度的像素数

fp1 :所存放的文件

*****************************/

int RGB2BMP(char *rgb_buffer,int nWidth,int nHeight,FILE*fp1)

{

BmpHead m_BMPHeader;

char bfType[2]={'B','M'};

m_BMPHeader.imageSize=3*nWidth*nHeight+54;

m_BMPHeader.blank=0;

m_BMPHeader.startPosition=54;



fwrite(bfType,1,sizeof(bfType),fp1);

fwrite(&m_BMPHeader.imageSize,1,sizeof(m_BMPHeader.imageSize),fp1);

fwrite(&m_BMPHeader.blank,1,sizeof(m_BMPHeader.blank),fp1);

fwrite(&m_BMPHeader.startPosition,1,sizeof(m_BMPHeader.startPosition),fp1);



InfoHead m_BMPInfoHeader;

m_BMPInfoHeader.Length=40;

m_BMPInfoHeader.width=nWidth;

m_BMPInfoHeader.height=nHeight;

m_BMPInfoHeader.colorPlane=1;

m_BMPInfoHeader.bitColor=24;

m_BMPInfoHeader.zipFormat=0;

m_BMPInfoHeader.realSize=3*nWidth*nHeight;

m_BMPInfoHeader.xPels=0;

m_BMPInfoHeader.yPels=0;

m_BMPInfoHeader.colorUse=0;

m_BMPInfoHeader.colorImportant=0;



fwrite(&m_BMPInfoHeader.Length,1,sizeof(m_BMPInfoHeader.Length),fp1);

fwrite(&m_BMPInfoHeader.width,1,sizeof(m_BMPInfoHeader.width),fp1);

fwrite(&m_BMPInfoHeader.height,1,sizeof(m_BMPInfoHeader.height),fp1);

fwrite(&m_BMPInfoHeader.colorPlane,1,sizeof(m_BMPInfoHeader.colorPlane),fp1);

fwrite(&m_BMPInfoHeader.bitColor,1,sizeof(m_BMPInfoHeader.bitColor),fp1);

fwrite(&m_BMPInfoHeader.zipFormat,1,sizeof(m_BMPInfoHeader.zipFormat),fp1);

fwrite(&m_BMPInfoHeader.realSize,1,sizeof(m_BMPInfoHeader.realSize),fp1);

fwrite(&m_BMPInfoHeader.xPels,1,sizeof(m_BMPInfoHeader.xPels),fp1);

fwrite(&m_BMPInfoHeader.yPels,1,sizeof(m_BMPInfoHeader.yPels),fp1);

fwrite(&m_BMPInfoHeader.colorUse,1,sizeof(m_BMPInfoHeader.colorUse),fp1);

fwrite(&m_BMPInfoHeader.colorImportant,1,sizeof(m_BMPInfoHeader.colorImportant),fp1);

fwrite(rgb_buffer,3*nWidth*nHeight,1,fp1);

return 0;

}

pPic 是解码后的BUF,

void CHttpLinkDlg::showTest(char *pPic)
{
unsigned short* rgb_buffer =(unsigned short*)pPic;
int nWidth = m_width;
int nHeight = m_height;
long total = nWidth*nHeight*3;

long nData = nWidth*nHeight;
unsigned char* pVisit =(unsigned char*)malloc(total*sizeof(char));

unsigned char* tmp = pVisit;

long i =0;

unsigned char R,G,B;

while(i<nData)

{

R = *rgb_buffer&0x1f;

G = (*rgb_buffer>>5)&0x3f;

B = (*rgb_buffer>>11)&0x1f;

B = B<<3;

G = G<<2;

R = R<<3;

*pVisit=R;pVisit++;

*pVisit=G;pVisit++;

*pVisit=B;pVisit++;

rgb_buffer++;

i++;
}
/*********** write file *******************/
char newFile[50];
static int a445 = 0;
sprintf(newFile, "B_%04d.bmp", a445++);

FILE *result = fopen(newFile,"wb");

if (result == NULL)

{
return ;
}
RGB2BMP((char *)tmp,nWidth,nHeight,pPic);

fclose(result);
// 显示
// //PlayVideo((char *)tmp,nWidth,nHeight);
// HBITMAP hBmp = (HBITMAP)LoadImage( NULL ,newFile, IMAGE_BITMAP , 0 , 0 , LR_CREATEDIBSECTION | LR_LOADFROMFILE);
// if (hBmp != NULL){
// HDC hdc = ::GetDC(m_PlayWind.m_hWnd);
// HDC mdc = CreateCompatibleDC(hdc);
// HBITMAP hbmOld = (HBITMAP)::SelectObject(mdc,hBmp);
// BitBlt(hdc,0,0,nWidth,nHeight,mdc, 0, 0, SRCCOPY);
// //::SelectObject(mdc, hbmOld);
// ::DeleteDC(mdc);
// //delete [] bufRGBA;
// ::ReleaseDC(m_PlayWind.m_hWnd, hdc);
// }
}

这里保存图片正常,都保存成功了!下面是我贴图的代码,rgb_buffer解码后的buf和上面的showTest(char *pPic)函数里面处理过后的BUF都试过。
int CHttpLinkDlg::PlayVideo(char *rgb_buffer,int nWidth,int nHeight)
{
BITMAPINFO info;
memset(&info.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
info.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
info.bmiHeader.biWidth = nWidth;
info.bmiHeader.biHeight = nHeight;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 16;
info.bmiHeader.biCompression = BI_BITFIELDS;
// info.bmiColors[0] = (BYTE)0xF800;
// info.bmiColors[1] = (BYTE)0x07E0;
// info.bmiColors[2] = (BYTE)0x001F;
HBITMAP hBitmap= CreateDIBSection(NULL, (BITMAPINFO*)&info, DIB_RGB_COLORS, (void**)&rgb_buffer, 0, 0);
if (hBitmap == NULL)
return -1;
HDC hdc = ::GetDC(m_PlayWind.m_hWnd);
HDC mdc = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)::SelectObject(mdc,hBitmap);
BitBlt(hdc,0,0,nWidth,nHeight,mdc, 0, 0, SRCCOPY);
::SelectObject(mdc, hbmOld);
::DeleteDC(mdc);
::ReleaseDC(m_PlayWind.m_hWnd, hdc);
return 0;
}

出来后黑屏。是在没法子了,求高手指点! 解码后的图片也不太正常,但有数据:
...全文
266 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
laviewpbt 2013-07-10
  • 打赏
  • 举报
回复
如果要显示不同格式的16位的图像数据,其实也很简单,有两中方法,第一,是修改CreateDIBSection函数的一个参数类型pBitmapInfo ,把这个默认参数BITMAPINFO修改为BITMAPV4HEADER,这个结构是比较新的BMP信息头,我们稍微修改他的一些成员结构,即修改为如下形式: Private Type BITMAPV4HEADER Size As Long Width As Long Height As Long Planes As Integer BitCount As Integer Compression As Long SizeImage As Long XPelsPerMeter As Long YPelsPerMeter As Long ClrUsed As Long ClrImportant As Long RedMask As Long GreenMask As Long BlueMask As Long AlphaMask As Long End Type 和BITMAPINFO结构相比,他只是多了几个蒙版成员,如果我们实现知道了我们要创建的16位图像的格式,则填充入对应的mask数据,然后在创建DIBSection,显示的时候直接调用Bitblt函数就可以。 第二种方法依旧是在创建DIBSection时,使用修改后的结构体参数,但不填充mask内容,在显示的时候在修改mask,然后调用SetDIBitsToDevice 函数来显示他,当然也要修改SetDIBitsToDevice 的对应的那个参数声明,这种方法实用于先创建一个空白的16位图像,然后由其他高彩色图像向这个空白图像填充数据的情况。
ndy_w 2013-07-10
  • 打赏
  • 举报
回复
?你应该用SetDIBitsToDevice

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧