资源简介
学习流媒体技术需要熟悉各种文件格式,了解一些编解码的算法,此程序演示了jpg图片的编码算法,算法流程相对简单,希望能对初学者一些启示和帮助。对各种图片和音视频文件格式感兴趣的朋友,请进群:417099529,一起探讨学习研究,进群时请介绍自己对流媒体哪些方面比较熟悉和擅长。
代码片段和文件信息
#include “StdAfx.h“
#include “JEnc.h“
JEnc::JEnc(void)
{
}
JEnc::~JEnc(void)
{
}
// bmFile:输入文件
// jpgFile:输出文件
// Q:质量
void JEnc::Invoke(string bmFile string jpgFile long Q)
{
FILE* pFile; // 输入文件句柄
if ((pFile = fopen(bmFile.c_str()“rb“)) == NULL) // 打开文件
{
throw(“open bmp file error.“);
}
// 获取jpeg编码需要的bmp数据结构,jpeg要求数据缓冲区的高和宽为8或16的倍数(视采样方式而定)
BMBUFINFO bmBuffInfo = GetBMBuffSize(pFile);
imgWidth = bmBuffInfo.imgWidth; // 图像宽
imgHeight = bmBuffInfo.imgHeight; // 图像高
buffWidth = bmBuffInfo.buffWidth; // 缓冲宽
buffHeight = bmBuffInfo.buffHeight; // 缓冲高
size_t buffSize = buffHeight * buffWidth * 3; // 缓冲长度,因为是24bits所以*3
BYTE* bmData = new BYTE[buffSize]; // 申请内存空间
GetBMData(pFile bmData bmBuffInfo); // 获取数据
fclose(pFile); // 关闭文件
//=====================================
// 计算编码需要的缓冲区,RGB信号需要别分别编码,所以需要3个缓冲区,这里只是1:1:1所以是一样大
size_t yuvBuffSize = buffWidth * buffHeight;
BYTE* pYBuff = new BYTE[yuvBuffSize];
BYTE* pUBuff = new BYTE[yuvBuffSize];
BYTE* pVBuff = new BYTE[yuvBuffSize];
// 将RGB信号转换为YUV信号
BGR2YUV111(bmDatapYBuffpUBuffpVBuff);
// 将信号分割为8x8的块
DivBuff(pYBuff buffWidth buffHeight DCTSIZE DCTSIZE );
DivBuff(pUBuff buffWidth buffHeight DCTSIZE DCTSIZE );
DivBuff(pVBuff buffWidth buffHeight DCTSIZE DCTSIZE );
SetQuantTable(std_Y_QTYQT Q); // 设置Y量化表
SetQuantTable(std_UV_QTUVQT Q); // 设置UV量化表
InitQTForAANDCT(); // 初始化AA&N需要的量化表
pVLITAB=VLI_TAB + 2047; // 设置VLI_TAB的别名
BuildVLITable(); // 计算VLI表
pOutFile = fopen(jpgFile.c_str()“wb“);
// 写入各段
WriteSOI();
WriteAPP0();
WriteDQT();
WriteSOF();
WriteDHT();
WriteSOS();
// 计算Y/UV信号的交直分量的huffman表,这里使用标准的huffman表,并不是计算得出,缺点是文件略长,但是速度快
BuildSTDHuffTab(STD_DC_Y_NRCODESSTD_DC_Y_VALUESSTD_DC_Y_HT);
BuildSTDHuffTab(STD_AC_Y_NRCODESSTD_AC_Y_VALUESSTD_AC_Y_HT);
BuildSTDHuffTab(STD_DC_UV_NRCODESSTD_DC_UV_VALUESSTD_DC_UV_HT);
BuildSTDHuffTab(STD_AC_UV_NRCODESSTD_AC_UV_VALUESSTD_AC_UV_HT);
// 处理单元数据
ProcessData(pYBuffpUBuffpVBuff);
WriteEOI();
fclose(pOutFile);
delete[] bmData;
}
// 获取BMP文件输出缓冲区信息
BMBUFINFO JEnc::GetBMBuffSize(FILE* pFile)
{
BITMAPFILEHEADER bmHead; //文件头信息块
BITMAPINFOHEADER bmInfo; //图像描述信息块
BMBUFINFO bmBuffInfo;
UINT colSize = 0;
UINT rowSize = 0;
fseek(pFile0SEEK_SET); //将读写指针指向文件头部
fread(&bmHeadsizeof(bmHead)1pFile); //读取文件头信息块
fread(&bmInfosizeof(bmInfo)1pFile); //读取位图信息块
// 计算填充后列数,jpeg编码要求缓冲区的高和宽为8或16的倍数
if (bmInfo.biWidth % 8 == 0)
{
colSize = bmInfo.biWidth;
}
else
{
colSize = bmInfo.biWidth + 8 - (bmInfo.biWidth % 8);
}
// 计算填充后行数
if (bmInfo.biHeight % 8 == 0)
{
rowSize = bmInfo.biHeight;
}
else
{
rowSize = bmInfo.biHeight + 8 - (bmInfo.biHeight % 8);
}
bmBuffInfo.BitCount = 24;
属性 大小 日期 时间 名称
----------- --------- ---------- ----- ----
目录 0 2016-06-08 11:46 jpgEncoder\
目录 0 2016-06-08 11:39 jpgEncoder\Debug\
文件 67072 2016-06-08 11:43 jpgEncoder\Debug\jpgEncoder.exe
文件 511312 2016-06-08 11:43 jpgEncoder\Debug\jpgEncoder.ilk
文件 969728 2016-06-08 11:43 jpgEncoder\Debug\jpgEncoder.pdb
目录 0 2016-06-08 11:46 jpgEncoder\jpgEncoder\
文件 897 2016-06-08 10:35 jpgEncoder\jpgEncoder.sln
文件 17408 2016-06-08 11:46 jpgEncoder\jpgEncoder.suo
文件 25498 2016-06-08 11:00 jpgEncoder\jpgEncoder\JEnc.cpp
文件 1561 2016-06-08 11:43 jpgEncoder\jpgEncoder\JEnc.h
文件 5758 2016-06-08 11:43 jpgEncoder\jpgEncoder\Jpeg.h
文件 4617 2016-06-08 10:42 jpgEncoder\jpgEncoder\Jpegformat.h
文件 545 2016-06-08 11:45 jpgEncoder\jpgEncoder\jpgEncoder.cpp
文件 4523 2016-06-08 11:08 jpgEncoder\jpgEncoder\jpgEncoder.vcxproj
文件 1698 2016-06-08 10:42 jpgEncoder\jpgEncoder\jpgEncoder.vcxproj.filters
文件 143 2016-06-08 10:35 jpgEncoder\jpgEncoder\jpgEncoder.vcxproj.user
文件 1736 2016-06-08 10:35 jpgEncoder\jpgEncoder\ReadMe.txt
文件 297 2016-06-08 10:35 jpgEncoder\jpgEncoder\stdafx.cpp
文件 320 2016-06-08 10:35 jpgEncoder\jpgEncoder\stdafx.h
文件 314 2016-06-08 10:35 jpgEncoder\jpgEncoder\targetver.h
文件 597194 2016-06-08 09:52 jpgEncoder\jpgEncoder\test-hua.bmp
评论
共有 条评论