visual studio 2019与c语言生成纯色与随机条纹bmp图片并转化为jpg格式(可用于图片生成,插入与测试,主要难点在于压缩图片,图片间不同格式的相互转化)
生成纯色代码如下:
#include
#include
#define w 200
#define h 200
#define MAX_SIZE 1024 * 1024 * 64
#pragma warning(disable:4996)
void WriteBMP(char* img, const char* filename)
{
int l = (w * 3 + 3) / 4 * 4;
int bmi[] = { l * h + 54,0,54,40,w,h,1 | 3 * 8 << 16,0,l * h,0,0,100,0 };
FILE* fp = fopen(filename, "wb");
fprintf(fp, "BM");
fwrite(&bmi, 52, 1, fp);
fwrite(img, 1, l * h, fp);
fclose(fp);
}
int main()
{
char img[w * h * 3];
char rgb[3] = {0};
int iBmpBit = 3;
for (int i = 0; i < w ; i++) {
rgb[0] = 0;
rgb[1] = 0;
rgb[2] = 225;
for (int ii = 1; ii < h; ii++) {
int ntmp = (h - 1 - i) * iBmpBit * w + (ii)*iBmpBit;
for (int j = 0; j < 3; j++)
img[ntmp + j] = rgb[j];
}
}
WriteBMP(img, "test.bmp");
system("test.bmp");
return 0;
}
效果如图:
生成随机条纹代码如下:
#include
#include
#define w 200
#define h 200
#define MAX_SIZE 1024 * 1024 * 64
#pragma warning(disable:4996)
void WriteBMP(char* img, const char* filename)
{
int l = (w * 3 + 3) / 4 * 4;
int bmi[] = { l * h + 54,0,54,40,w,h,1 | 3 * 8 << 16,0,l * h,0,0,100,0 };
FILE* fp = fopen(filename, "wb");
fprintf(fp, "BM");
fwrite(&bmi, 52, 1, fp);
fwrite(img, 1, l * h, fp);
fclose(fp);
}
int main()
{
char img[w * h * 3];
char rgb[3] = {0};
int iBmpBit = 3;
for (int i = 0; i < w ; i++) {
rgb[0] = rand() % 256;
rgb[1] = rand() % 256;
rgb[2] = rand() % 256;
for (int ii = 1; ii < h; ii++) {
int ntmp = (h - 1 - i) * iBmpBit * w + (ii)*iBmpBit;
for (int j = 0; j < 3; j++)
img[ntmp + j] = rgb[j];
}
}
WriteBMP(img, "test.bmp");
system("test.bmp");
return 0;
}
效果如下图:
将bmp转化为jpg格式的代码如下:
#include
#include
#include
#include
#pragma warning(disable:4996)
//BMP像素结构体
typedef struct {
unsigned char B, G, R;
}colorRGB;
typedef struct {
unsigned char B, G, R, a;
}colorRGBa;
typedef struct {
unsigned char length;
unsigned short int value;
}bitstring;
#define PI 3.1415926
//写入文件操作
#define writebyte(b) fputc((b), fp_jpg)
#define writeword(w) writebyte((w)/256);writebyte((w)%256);
colorRGB* RGB_buf; // 24位
colorRGBa* RGBa_buf; // 32位
signed short int ximage, yimage; //图片的长和宽
FILE* fp_jpg; //打开jpg文件
//二进制编码
static bitstring* code_u;
static bitstring* code_d; //长度以及编码
//存储YCbCr
static signed char YDU[64];
static signed char CbDU[64];
static signed char CrDU[64];
static signed short int D2[64];//存储z型编码后的值
static unsigned char bytecode = 0;
static signed char bytepos = 8;
//JPG头SOI1
//图像识别信息2
static struct APP0
{
unsigned short int marker; //段标识和类型FFE0
unsigned short int length; // 段长度 16
unsigned char JFIFsignature[5]; // 存储ASCII码 "JFIF",'\0'
unsigned char versionhi; // 主版本号1
unsigned char versionlo; // 次版本号1
unsigned char xyunits; // 密度单位 0(无单位)
unsigned short int xdensity; // 水平方向的密度 1
unsigned short int ydensity; // 垂直方向的密度 1
unsigned char thumbnwidth; // 略缩图水平像素数目0
unsigned char thumbnheight; // 略缩图垂直像素数目0
}APP0info = { 0xFFE0,16,'J','F','I','F',0,1,1,0,1,1,0,0 };
//定义量化表3
static struct DQT {
unsigned short int marker; // 段标识和类型 0xFFDB
unsigned short int length; // 段长度
unsigned char QTYinfo; // 亮度QT值 00
unsigned char Ytable[64];//内容
unsigned char QTCbinfo; // 色度QT值 01
unsigned char Cbtable[64];
} DQTinfo;
//图像基本信息SOF0 4
static struct SOF0 {
unsigned short int marker; //段标识和类型 0xFFC0
unsigned short int length; // 段长度 17
unsigned char precision;// 每个样本的位数
unsigned short int height; //图片高度
unsigned short int width; //图片宽度
unsigned char nrofcomponents;//组件数量 3
unsigned char IdY; // 亮度= 1
unsigned char HVY; // 采样系数 高位标识水平采样系数,低位表示垂直采样系数
unsigned char QTY; // 量化表号 0
unsigned char IdCb; // 红色分量= 2
unsigned char HVCb;
unsigned char QTCb; // 1
unsigned char IdCr; // 蓝色分量= 3
unsigned char HVCr;
unsigned char QTCr; // Normally equal to QTCb = 1
} SOF0info = { 0xFFC0,17,8,0,0,3,1,0x11,0,2,0x11,1,3,0x11,1 };
//定义huffman表 5
static struct DHT {
unsigned short int marker; //段标识和类型 0xFFC4
unsigned short int length; //段长度 19+n+....
unsigned char HTYDCinfo; // 低4位HT号 第5位HT类型 高3位为0
unsigned char YDC_codes[16]; //HT位表
unsigned char YDC_values[12];// HT值表
unsigned char HTYACinfo; // = 0x10
unsigned char YAC_codes[16];
unsigned char YAC_values[162];
unsigned char HTCbDCinfo; // = 1
unsigned char CbDC_codes[16];
unsigned char CbDC_values[12];
unsigned char HTCbACinfo; // = 0x11
unsigned char CbAC_codes[16];
unsigned char CbAC_values[162];
} DHTinfo;
//扫描行开始 6
static struct SOS {
unsigned short int marker; //段标识和类型 0xFFDA
unsigned short int length; //长度 12
unsigned char nrofcomponents; // 扫描行内组件数量 通常为3
unsigned char IdY; //1
unsigned char HTY; //低4位是AC表号,高4位是DC表号
unsigned char IdCb; //2
unsigned char HTCb; //0x11
unsigned char IdCr; //3
unsigned char HTCr; //0x11
unsigned char Ss, Se, Bf; // not interesting, they should be 0,63,0
} SOSinfo = { 0xFFDA,12,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
//亮度量化表
static unsigned char DQT_Y[64] = {
0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
0x07, 0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14,
0x0d, 0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13,
0x0f, 0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a,
0x1c, 0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22,
0x2c, 0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c,
0x30, 0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39,
0x3d, 0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32
};
//色差量化表
static unsigned char DQT_C[64] = {
0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0d,
0x0d, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32
};
//标准huffman表
static unsigned char dc_y_codes[17] = { 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 };
static unsigned char dc_y_values[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static unsigned char dc_cb_codes[17] = { 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 };
static unsigned char dc_cb_values[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static unsigned char ac_y_codes[17] = { 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d };
static unsigned char ac_y_values[162] = {
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
static unsigned char ac_cb_codes[17] = { 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77 };
static unsigned char ac_cb_values[162] = {
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
//z型编码
static unsigned char z[64] = { 0, 1, 5, 6,14,15,27,28,
2, 4, 7,13,16,26,29,42,
3, 8,12,17,25,30,41,43,
9,11,18,24,31,40,44,53,
10,19,23,32,39,45,52,54,
20,22,33,38,46,51,55,60,
21,34,37,47,50,56,59,61,
35,36,48,49,57,58,62,63 };
//按位取值表
static unsigned short int mark[16] = { 1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768 };
void writefile(bitstring a)
{
unsigned short int values = a.value;
signed char leng_a = a.length;
while (leng_a > 0)
{
if (values & mark[leng_a - 1]) //判断对应位置是否为1
bytecode |= mark[bytepos - 1];//当前最高位至1
leng_a--;
bytepos--;
if (bytepos <= 0)
{
if (bytecode == 0xff)
{
writebyte(0xff);
writebyte(0x00);//说明ff不是段标志
}
else
writebyte(bytecode);
bytecode = 0;
bytepos = 8;
}
}
}
void code_and_write(signed short int* DC, bitstring* DCtable, bitstring* ACtable)
{
signed short int diff;
unsigned char endpos, startpos, i = 1, nz;
diff = D2[0] - *DC; //差值
*DC = D2[0];
//写入直流值
if (diff == 0)
writefile(DCtable[0]); //写入0的huffman编码
else
{
writefile(DCtable[code_d[diff].length]);//写入diff长度的huffman编码
writefile(code_d[diff]); //写入二进制编码
}
//写入交流值
for (endpos = 63; (endpos > 0) && (D2[endpos] == 0); --endpos);
if (endpos == 0)
{
writefile(ACtable[0x00]);
return;
}
while (i <= endpos)
{
startpos = i;
for (; (D2[i] == 0) && (i <= endpos); ++i);
nz = i - startpos;
for (; nz >= 16; nz -= 16)//长度大于16需要分多块
writefile(ACtable[0xf0]);
writefile(ACtable[nz * 16 + code_d[D2[i]].length]);
writefile(code_d[D2[i]]);
++i;
}
if (endpos != 63)
writefile(ACtable[0x00]); //EOB
}
void DCT(signed char data[8][8], unsigned char* fdtbl, signed short int* outdata)
{
float output[8][8], temp;
double ALPHA, BETA;
short u = 0;
short v = 0;
short i = 0;
short j = 0;
for (u = 0; u < 8; u++)
{
for (v = 0; v < 8; v++)
{
if (u == 0)
ALPHA = sqrt(1.0 / 8);
else
ALPHA = sqrt(2.0 / 8);
if (v == 0)
BETA = sqrt(1.0 / 8);
else
BETA = sqrt(2.0 / 8);
float tmp = 0.0;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
tmp += data[i][j] * cos((2 * i + 1) * u * PI / (2.0 * 8)) * cos((2 * j + 1) * v * PI / (2.0 * 8));
}
}
output[u][v] = ALPHA * BETA * tmp;
}
}
// 量化
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
{
temp = output[i][j] / (float)((double)fdtbl[z[i * 8 + j]]);
outdata[i * 8 + j] = (signed short int) ((signed short int)(temp + 16384.5) - 16384);
}
}
void fdct_and_quan(signed char* data, unsigned char* table)
{
float temp;
signed short int D1[64];
signed char mdata[8][8];
unsigned char i, j;
//离散余弦变换
for (i = 0; i < 8; ++i)
for (j = 0; j < 8; ++j)
mdata[i][j] = data[8 * i + j];
DCT(mdata, table, D1);
//z型编码
for (i = 0; i <= 63; i++)
D2[z[i]] = D1[i];
}
void RGBtoYCbCr(unsigned short int x1, unsigned short int y1)
{
unsigned char x, y;
unsigned char pos = 0;
unsigned long location;
unsigned char R, G, B;
location = y1 * ximage + x1;
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
{
R = RGB_buf[location].R;
G = RGB_buf[location].G;
B = RGB_buf[location].B;
YDU[pos] = (signed char)(((signed long int)(65536 * 0.299 + 0.5) * R + (signed long int)(65536 * 0.587 + 0.5) * G + (signed long int)(65536 * 0.114 + 0.5) * B) >> 16) - 128;
CbDU[pos] = (signed char)(((signed long int)(65536 * -0.16874 + 0.5) * R + (signed long int)(65536 * -0.33726 + 0.5) * G + (signed long int)(65536 * 0.5 + 0.5) * B) >> 16);
CrDU[pos] = (signed char)(((signed long int)(65536 * 0.5 + 0.5) * R + (signed long int)(65536 * -0.41869 + 0.5) * G + (signed long int)(65536 * -0.08131 + 0.5) * B) >> 16);
location++; pos++;
}
location += ximage - 8;
}
}
void leng_and_numbercode()
{
signed long int n;
signed long int one = 1, two = 2;
unsigned char leng;
//开辟空间
code_u = (bitstring*)malloc(65535 * sizeof(bitstring));
if (code_u == NULL)
{
printf("存储空间开辟失败");
exit(0);
}
code_d = code_u + 32767;
for (leng = 1; leng <= 15; ++leng)
{
for (n = one; n < two; ++n)
{
code_d[n].length = leng;
code_d[n].value = (unsigned short int)n;
}
for (n = -(two - 1); n <= -one; ++n)
{
code_d[n].length = leng;
code_d[n].value = (unsigned short int)(two - 1 + n);
}
two <<= 1;
one <<= 1;
}
}
void huffman_code(unsigned char* codes, unsigned char* values, bitstring* HT)
{
unsigned char k, j;
unsigned char pos = 0;
unsigned short int codevalue = 0;
for (k = 1; k <= 16; ++k)
{
for (j = 1; j <= codes[k]; ++j)
{
HT[values[pos]].value = codevalue; //编码值
HT[values[pos]].length = k; //长度
pos++;
codevalue++;
}
codevalue *= 2;
}
}
void code_all()
{
//huffman编码表
bitstring YDC[12];
bitstring CbDC[12];
bitstring YAC[256];
bitstring CbAC[256];
//计算各项的huffman表
huffman_code(dc_y_codes, dc_y_values, YDC);
huffman_code(dc_cb_codes, dc_cb_values, CbDC);
huffman_code(ac_y_codes, ac_y_values, YAC);
huffman_code(ac_cb_codes, ac_cb_values, CbAC);
//二进制长度以及编码
leng_and_numbercode();
bitstring fillbit;
signed short int DCY = 0, DCCb = 0, DCCr = 0;//直流系数
unsigned short int x, y;
//8*8一组进行处理
for (y = 0; y < yimage; y += 8)
for (x = 0; x < ximage; x += 8)
{
//printf("1"); //测试
RGBtoYCbCr(x, y);//RGB->YCbCr
fdct_and_quan(YDU, DQTinfo.Ytable);//离散余弦和量化,z型编码
code_and_write(&DCY, YDC, YAC);//编码并写入
fdct_and_quan(CbDU, DQTinfo.Cbtable);
code_and_write(&DCCb, CbDC, CbAC);
fdct_and_quan(CrDU, DQTinfo.Cbtable);
code_and_write(&DCCr, CbDC, CbAC);
//printf("2");
}
//尾部填充0并写入尾部
if (bytepos > 0)
{
fillbit.length = bytepos;
fillbit.value = 0;
writefile(fillbit);
}
writeword(0xffd9);//EOI
//释放空间
free(RGB_buf);
free(RGBa_buf);
fclose(fp_jpg);
}
void writetop()
{
unsigned char i;
//1.SOI
writeword(0xFFD8)
//2.APP0
writeword(APP0info.marker);
writeword(APP0info.length);
writebyte('J');
writebyte('F');
writebyte('I');
writebyte('F');
writebyte(0);
writebyte(APP0info.versionhi);
writebyte(APP0info.versionlo);
writebyte(APP0info.xyunits);
writeword(APP0info.xdensity);
writeword(APP0info.ydensity);
writebyte(APP0info.thumbnwidth);
writebyte(APP0info.thumbnheight);
//3.DQT
writeword(DQTinfo.marker);
writeword(DQTinfo.length);
writebyte(DQTinfo.QTYinfo);
for (i = 0; i < 64; i++)
writebyte(DQTinfo.Ytable[i]);
writebyte(DQTinfo.QTCbinfo);
for (i = 0; i < 64; i++)
writebyte(DQTinfo.Cbtable[i]);
//4.SOF0
writeword(SOF0info.marker);
writeword(SOF0info.length);
writebyte(SOF0info.precision);
writeword(SOF0info.height);
writeword(SOF0info.width);
writebyte(SOF0info.nrofcomponents);
writebyte(SOF0info.IdY);
writebyte(SOF0info.HVY);
writebyte(SOF0info.QTY);
writebyte(SOF0info.IdCb);
writebyte(SOF0info.HVCb);
writebyte(SOF0info.QTCb);
writebyte(SOF0info.IdCr);
writebyte(SOF0info.HVCr);
writebyte(SOF0info.QTCr);
//5.DHT
writeword(DHTinfo.marker);
writeword(DHTinfo.length);
writebyte(DHTinfo.HTYDCinfo);
for (i = 0; i < 16; i++)
writebyte(DHTinfo.YDC_codes[i]);
for (i = 0; i <= 11; i++)
writebyte(DHTinfo.YDC_values[i]);
writebyte(DHTinfo.HTYACinfo);
for (i = 0; i < 16; i++)
writebyte(DHTinfo.YAC_codes[i]);
for (i = 0; i <= 161; i++)
writebyte(DHTinfo.YAC_values[i]);
writebyte(DHTinfo.HTCbDCinfo);
for (i = 0; i < 16; i++)
writebyte(DHTinfo.CbDC_codes[i]);
for (i = 0; i <= 11; i++)
writebyte(DHTinfo.CbDC_values[i]);
writebyte(DHTinfo.HTCbACinfo);
for (i = 0; i < 16; i++)
writebyte(DHTinfo.CbAC_codes[i]);
for (i = 0; i <= 161; i++)
writebyte(DHTinfo.CbAC_values[i]);
//6.SOS
writeword(SOSinfo.marker);
writeword(SOSinfo.length);
writebyte(SOSinfo.nrofcomponents);
writebyte(SOSinfo.IdY);
writebyte(SOSinfo.HTY);
writebyte(SOSinfo.IdCb);
writebyte(SOSinfo.HTCb);
writebyte(SOSinfo.IdCr);
writebyte(SOSinfo.HTCr);
writebyte(SOSinfo.Ss);
writebyte(SOSinfo.Se);
writebyte(SOSinfo.Bf);
}
void init_JPG_and_writ(char* JPG_filename)
{
fp_jpg = fopen(JPG_filename, "wb");//打开jpg文件
int i;
//初始化量化表
DQTinfo.marker = 0xFFDB;
DQTinfo.length = 132;
DQTinfo.QTYinfo = 0;
DQTinfo.QTCbinfo = 1;
for (i = 0; i < 64; ++i)
{
DQTinfo.Ytable[i] = DQT_Y[i];
DQTinfo.Cbtable[i] = DQT_C[i];
}
//初始化huffman表
DHTinfo.marker = 0xFFC4;
DHTinfo.length = 0x01A2;
DHTinfo.HTYDCinfo = 0; //0号直流表
for (i = 0; i < 16; i++)
DHTinfo.YDC_codes[i] = dc_y_codes[i + 1];
for (i = 0; i <= 11; i++)
DHTinfo.YDC_values[i] = dc_y_values[i];
DHTinfo.HTYACinfo = 0x10; //0号交流表
for (i = 0; i < 16; i++)
DHTinfo.YAC_codes[i] = ac_y_codes[i + 1];
for (i = 0; i <= 161; i++)
DHTinfo.YAC_values[i] = ac_y_values[i];
DHTinfo.HTCbDCinfo = 1; //1号直流表
for (i = 0; i < 16; i++)
DHTinfo.CbDC_codes[i] = dc_cb_codes[i + 1];
for (i = 0; i <= 11; i++)
DHTinfo.CbDC_values[i] = dc_cb_values[i];
DHTinfo.HTCbACinfo = 0x11; //1号交流表
for (i = 0; i < 16; i++)
DHTinfo.CbAC_codes[i] = ac_cb_codes[i + 1];
for (i = 0; i <= 161; i++)
DHTinfo.CbAC_values[i] = ac_cb_values[i];
writetop(); //写入文件头
}
void bmp(char* bmp_name)
{
unsigned short int x8, y8; //拓展长度
signed short int y2, a = 0; //用于处理倒序
unsigned char fillbytes; //可被4整除
colorRGB lastcolor;
unsigned short int column, nrline, line_up, line_down;
unsigned char TOPBUF[256]; //存取头部信息
colorRGB* tmpline; //用于交换
FILE* fp_bmp = fopen(bmp_name, "rb");//打开文件
if (fp_bmp == NULL)
{
printf("文件打开失败!");
exit(0);
}
//读取文件头部信息
fread(TOPBUF, 1, 54, fp_bmp);
if ((TOPBUF[0] != 'B') || (TOPBUF[1] != 'M'))
{
printf("文件不是BMP格式!");
exit(0);
}
//图片长和宽
ximage = (unsigned short int)TOPBUF[19] * 256 + TOPBUF[18];//图片长度和宽度
y2 = (short int)TOPBUF[23] * 256 + TOPBUF[22];
yimage = y2;
//长度负值处理
if (y2 <= 0)
{
a = 1;
yimage = -y2;
}
SOF0info.width = ximage;
SOF0info.height = yimage;
if (ximage % 8 != 0)
x8 = (ximage / 8) * 8 + 8;
else
x8 = ximage;
if (yimage % 8 != 0)
y8 = (yimage / 8) * 8 + 8;
else
y8 = yimage;
//建立并存储,填充每一行,转换为RGB
RGB_buf = (colorRGB*)(malloc(3 * x8 * y8));
if (RGB_buf == NULL)
{
printf("存储创建失败!");
exit(0);
}
//处理32位
if (TOPBUF[28] == 32)
{
RGBa_buf = (colorRGBa*)(malloc(4 * x8 * y8));
if (RGBa_buf == NULL)
{
printf("存储创建失败!");
exit(0);
}
for (nrline = 0; nrline < yimage; nrline++)
{
fread(RGBa_buf + nrline * x8, 1, ximage * 4, fp_bmp);
memcpy(&lastcolor, RGBa_buf + nrline * x8 + ximage - 1, 4);
for (column = ximage; column < x8; column++)
memcpy(RGBa_buf + nrline * x8 + column, &lastcolor, 4);
}
for (unsigned long int n = 0; n < x8 * yimage; ++n)
{
//转换为RGB
RGB_buf[n].B = RGBa_buf[n].B;
RGB_buf[n].G = RGBa_buf[n].G;
RGB_buf[n].R = RGBa_buf[n].R;
}
}
//处理24位
else if (TOPBUF[28] == 24)
{
//判断有无填充
if (ximage % 4 != 0)
fillbytes = 4 - (ximage % 4);
else
fillbytes = 0;
for (nrline = 0; nrline < yimage; nrline++)
{
fread(RGB_buf + nrline * x8, 1, ximage * 3, fp_bmp);
fread(TOPBUF, 1, fillbytes, fp_bmp);
memcpy(&lastcolor, RGB_buf + nrline * x8 + ximage - 1, 3);
for (column = ximage; column < x8; column++)
memcpy(RGB_buf + nrline * x8 + column, &lastcolor, 3);
}
}
else
{
printf("信息错误!");
exit(0);
}
ximage = x8;
tmpline = (colorRGB*)malloc(ximage * 8);
if (tmpline == NULL)
{
printf("存储创建失败!");
exit(0);
}
//是否需要逆序处理
if (a == 0)
{
for (line_up = yimage - 1, line_down = 0; line_up > line_down; line_up--, line_down++)
{
memcpy(tmpline, RGB_buf + line_up * ximage, ximage * 3);
memcpy(RGB_buf + line_up * ximage, RGB_buf + line_down * ximage, ximage * 3);
memcpy(RGB_buf + line_down * ximage, tmpline, ximage * 3);
}
}
//填充行
memcpy(tmpline, RGB_buf + (yimage - 1) * ximage, ximage * 3);
for (nrline = yimage; nrline < y8; nrline++)
memcpy(RGB_buf + nrline * ximage, tmpline, ximage * 3);
yimage = y8;
free(tmpline);
fclose(fp_bmp);
}
int main()
{
int mm = 2;
printf(" =========功能:将BMP格式图片转换为JPG格式=========\n");
while (mm != 1)
{
printf("\n");
//输入文件名称
char BMP_filename[64];
char JPG_filename[64];
printf("输入要压缩的BMP格式的图片名称:");
scanf("%s", BMP_filename);
printf("输入压缩完成后JPG格式的图片名称:");
scanf("%s", JPG_filename);
bmp(BMP_filename);//读入bmp信息
init_JPG_and_writ(JPG_filename);//初始化JPG格式并写入
code_all(); //综合变换并写入
printf("\n");
printf("输入'1'退出,输入任意数字继续:");
scanf("%d", &mm);
}
return 0;
}
执行时输入文件的具体路径和替换的图片名称即可。整个过程相当于制作不同格式的图片并相互转化。图片格式转化来源于其它博客,属于转载,其余为修改和原创。
无论如何,这是属于文件操作,主要的痛点在于熟悉文件格式,比如bmp,jpg以及PNG等等,颜色的操作和识别也是一门功课,所以整理集合两份代码,利于大家研究与学习,谢谢阅读。