读取bmp格式图片(二)

准备工作已经完成。

先建立一个bmp.h头文件。

参考代码:http://pengqianhe.googlepages.com/ Author:彭千贺

代码如下:

#ifndef BMP_H_INCLUDED
#define BMP_H_INCLUDED

typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned char BYTE;


// BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。其结构定义如下:
typedef struct tagBITMAPFILEHEADER
{ 
	// bmfh
	WORD bfType;  // 位图文件的类型,必须为BM
	DWORD bfSize;// 位图文件的大小,以字节为单位
	WORD bfReserved1;// 位图文件保留字,必须为0
	WORD bfReserved2;// 位图文件保留字,必须为0
	DWORD bfOffBits;// 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
}BITMAPFILEHEADER;

// BMP位图信息头数据用于说明位图的尺寸等信息。其结构定义如下:
typedef struct tagBITMAPINFOHEADER
{ 
	// bmih
	DWORD biSize;// 本结构所占用字节数
	LONG biWidth;  // 位图的宽度,以像素为单位
	LONG biHeight; // 位图的高度,以像素为单位
	WORD biPlanes; // 目标设备的级别,必须为1
	WORD biBitCount;// 每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
	DWORD biCompression;  // 位图压缩类型,必须是 0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
	DWORD biSizeImage;// 位图的大小,以字节为单位
	LONG biXPelsPerMeter;// 位图水平分辨率,每米像素数
	LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数
	DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
	DWORD biClrImportant;// 位图显示过程中重要的颜色数
}BITMAPINFOHEADER;

// 颜色表用于说明位图中的颜色,有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
// 颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
// 当biBitCount=1,4,8时,分别有2,16,256个表项;    当biBitCount=24时,没有颜色表项。
typedef struct tagRGBQUAD
{ 
	// rgbq
	BYTE rgbBlue;// 蓝色的亮度(值范围为0-255)
	BYTE rgbGreen; // 绿色的亮度(值范围为0-255)  
	BYTE rgbRed;// 红色的亮度(值范围为0-255)  
	BYTE rgbReserved;// 保留,必须为0  
}RGBQUAD; 

// 位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO
{
	BITMAPINFOHEADER bmiHeader;// 位图信息头  
	RGBQUAD bmiColors[1];// 位图信息头  
}BITMAPINFO;
#endif // BMP_H_INCLUDED

然后是主函数:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include <process.h>
#include "BMP.h"

BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
BYTE *imgData;
bool bReadBMFH=false;
bool bReadBMIH=false;
bool bReadPixel=false;
//检查路径是否合法:文件能打开;以 bmp 为后缀名
int CheckFilePath(char *filepath);
//读入位图的文件头
int ReadFileHeader(char *filepath,BITMAPFILEHEADER *bmfh);
//打印位图的文件头
void PrintFileHeader(BITMAPFILEHEADER *bmfh);
//读入位图的信息头
int ReadInfoHeader(char *filepath,BITMAPINFOHEADER *bmih);
//打印位图的信息头
void PrintInfoHeader(BITMAPINFOHEADER *bmih);
//创建 8 位位图的调色板
int CreatePalette(RGBQUAD pal[]);
//读入位图的像素数据
int ReadPixelData(char *filepath,BYTE *imgData);
//计算每行像素所占的字节数
LONG GetLineBytes(int imgWidth,int bitCount);
//打印位图的像素数据
void PrintPixelData(BYTE *imgData,int width,int height,int bitCount);
//打印菜单选项
void PrintMenu();
//另存为位图
int SaveAsImage(char *filepath);
//显示位图
void ShowImage(char * filepath);
//保存文件头
int SaveFileHeader(FILE* fp);
//保存信息头
int SaveInfoHeader(FILE* fp);
//保存调色板
int SaveColorPalette(FILE *fp);
//保存像素数据
int SavePixelData(FILE* fp);

// 主函数
int main()
{
	// 要打开的bmp文件路径存储数组
	char filepath[256];
	// 徐保存的路径存储
	char saveasfilepath[256];
	// 变量与常用参数
	int i;
	int width;
	int height;
	int bitCount;
	// 在头文件已经定义:typedef unsigned long DWORD;
	DWORD dwLineBytes;
	int select;
    int q=0;
	// system 命令即是cmd命令
	system("echo off");
	system("color 2"); // 调整字体颜色
	printf("-----------TIMimage-----------\n");
	printf("Input the path of the BMP file:\n");
	gets(filepath);
	// 测试路径下是否有此文件
	i=CheckFilePath(filepath);
	if(i==-1)
	{
		return -1;
	}
	do
	{
		// 如果路径合法,则打印相关程序功能选项
		PrintMenu();
		scanf("%u",&select);
		// 测试用户选择
		switch(select)
		{
		case 0:
			{
				printf("Input the path of the BMP file:\n");
				scanf("%s",filepath);
				CheckFilePath(filepath);
				break;
			}
		case 1:
			{
				i=ReadFileHeader(filepath,&bmfh);
				if(i!=-1)
				{
					printf("Read the file header successfully.\n");
					bReadBMFH=true;
					break;
				}
				else
				{
					printf("Read the file header failed.\n");
					bReadBMFH=false;
					q=1;
					break;
				}
			}
		case 2:
			{
				i=ReadInfoHeader(filepath,&bmih);
				if(i!=-1)
				{
					printf("Read the info header successfully.\n");
					bReadBMIH=true;
					break;
				}
				else
				{
					printf("Read the info header failed.\n");
					bReadBMIH=false;
					q=1;
					break;
				}
			}
		case 3:
			{
				if(!bReadBMIH)
				{
					printf("Please read the info header at first.\n");
					break;
				}
				height=bmih.biHeight;
				width=bmih.biWidth;
				bitCount=bmih.biBitCount;
				dwLineBytes=GetLineBytes(width,bitCount);
				imgData=(BYTE*)malloc(dwLineBytes*height*sizeof(BYTE));
				if(!imgData)
				{
					printf("Can not allocate memory for the image.\n");
					q=1;
					break;
				}
				i=ReadPixelData(filepath,imgData);
				if(i==-1)
				{
					printf("Read the pixel data failed.\n");
					bReadPixel=false;
					q=1;
					break;
				}
				else
				{
					printf("Read the pixel data successfully.\n");
					bReadPixel=true;
					break;
				}
			}
		case 4:
			{
				if(bReadBMFH)
				{
					PrintFileHeader(&bmfh);
					break;
				}
				else
				{
					printf("Please read the file header at first.\n");
					break;
				}
			}
		case 5:
			{
				if(bReadBMIH)
				{
					PrintInfoHeader(&bmih);
					break;
				}
				else
				{
					printf("Please read the info header at first.\n");
					break;
				}
			}
		case 6:
			{
				if(bReadPixel)
				{
					PrintPixelData(imgData,width,height,bitCount);
					break;
				}
				else
				{
					printf("Please read the pixel data at first.\n");
					break;
				}
			}
		case 7:
			{
				ShowImage(filepath);
				break;
			}
		case 8:
			{
				printf("Input the path(ex. d://poon.bmp) you want to save:\n");
				scanf("%s",saveasfilepath);
				i=SaveAsImage(saveasfilepath);
				if(i==-1)
				{
					printf("Error: failed to save the image.\n");
					break;
				}
				break;
			}
		default:
			q=1;
			break;
		}
		select=9527;
	} 
	while (q==0);
	return 0;
}

// 测试路径或文件是否合法
int CheckFilePath(char *filepath)
{
	FILE *fp;
	int len=strlen(filepath)/sizeof(char); // 求路径的长度
	char ext[3];
	// 如果路径不为空
	if(filepath[0]!=int('\"'))
	{
		// 将路径的后缀复制入ext[];
		strncpy(ext,&filepath[len-3],3);
		// 根据文件后缀,判断文件格式
		if(!(ext[0]=='b' && ext[1]=='m' && ext[2]=='p'))
		{
			printf("Error: The file is not a BMP file.\n");
			printf("Error: The extention of the filename must be 'bmp',not 'BMP'\
				n");
			return -1;
		}
		// 如果格式正确,打开文件
		fp=fopen(filepath,"r");
		// 如果打不开,则路径错误
		if(!fp)
		{
			printf("Error: The path is not correct.\n");
			return -1;
		}
		// 关闭文件
		fclose(fp);
	}
	else
	{
		printf("Error: The path must not include blank space.\n");
		return -1;
	}
	return 0;
}

// 打印选择项目的调用函数
void PrintMenu()
{
	printf(" -----Choose Your Operation-----\n");
	printf("| 0-----Input the image path |\n");
	printf("| 1-----Read the file header |\n");
	printf("| 2-----Read the info header |\n");
	printf("| 3-----Read the pixel data |\n");
	printf("| 4-----Print the file header |\n");
	printf("| 5-----Print the info header |\n");
	printf("| 6-----Print the pixel data |\n");
	printf("| 7-----View the original image |\n");
	printf("| 8-----Save as the image |\n");
	printf("| other-----Exit the program |\n");
	printf(" -------------------------------\n");
}

// 读取bmp文件头
// 各个信息对应结构体的内容
int ReadFileHeader(char *filepath,BITMAPFILEHEADER *bmfh)
{
	FILE *fp;
	fp=fopen(filepath,"rb");
	if(!fp)
	{
		printf("Can not open the file:%s\n",filepath);
		return -1;
	}
	if(fread(&bmfh->bfType,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not read bfType in the file header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmfh->bfSize,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not read bfSize in the file header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmfh->bfReserved1,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not read bfReserved1 in the file header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmfh->bfReserved2,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not read bfReserved2 in the file header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmfh->bfOffBits,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not read bfOffBits in the file header.\n");
		fclose(fp);
		return -1;
	}
	fclose(fp);
	return 0;
}

// 读取信息头
int ReadInfoHeader(char *filepath,BITMAPINFOHEADER *bmih)
{
	FILE *fp;
	fp=fopen(filepath,"rb");
	if(!fp)
	{
		printf("Can not open the file:%s\n",filepath);
		return -1;
	}
	fseek(fp,14,SEEK_SET);
	if(fread(&bmih->biSize,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not read biSize in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biWidth,sizeof(LONG),1,fp)!=1)
	{
		printf("Can not read biWidth in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biHeight,sizeof(LONG),1,fp)!=1)
	{
		printf("Can not read biHeight in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biPlanes,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not read biPlanes in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biBitCount,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not read biBitCount in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biCompression,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not read biCompression in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biSizeImage,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not read biSizeImage in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biXPelsPerMeter,sizeof(LONG),1,fp)!=1)
	{
		printf("Can not read biXPelsPerMeter in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biYPelsPerMeter,sizeof(LONG),1,fp)!=1)
	{
		printf("Can not read biYPelsPerMeter in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biClrUsed,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not read biClrUsed in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fread(&bmih->biClrImportant,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not read biClrImportant in the info header.\n");
		fclose(fp);
		return -1;
	}
	fclose(fp);
	return 0;
}

//创建 8 位位图的调色板
int CreatePalette(RGBQUAD pal[])
{
	int i;
	if(sizeof(pal)/sizeof(RGBQUAD)!=256)
	{
		printf("The size of the palette must be 256.\n");
		return -1;
	}
	for(i=0;i<256;i++)
	{
		pal[i].rgbBlue=i;
		pal[i].rgbGreen=i;
		pal[i].rgbRed=i;
		pal[i].rgbReserved=0;
	}
	return 0;
}

//读入位图的像素数据
int ReadPixelData(char *filepath,BYTE *imgData)
{
	BITMAPINFOHEADER bmih;
	BITMAPFILEHEADER bmfh;
	BYTE *data;
	FILE *fp;
	int n;
	int width;
	int height;
	int bitCount;
	DWORD dwLineBytes;
	n=ReadFileHeader(filepath,&bmfh);
	if(n==-1)
	{
		printf("Can not read the file header of the BMP file.\n");
		return -1;
	}
	n=ReadInfoHeader(filepath,&bmih);
	if(n==-1)
	{
		printf("Can not read the info header of the BMP file.\n");
		return -1;
	}
	width=bmih.biWidth;
	height=bmih.biHeight;
	bitCount=bmih.biBitCount;
	dwLineBytes=GetLineBytes(width,bitCount);
	if(_msize(imgData)!=(dwLineBytes*height))
	{
		printf("The size you allocate for the pixel data is not right.\n");
		printf("Fittable size: %ld bytes.\n",(dwLineBytes*height));
		printf("Your size: %ld bytes.\n",sizeof(imgData));
		return -1;
	}
	data=(BYTE*)malloc(dwLineBytes*height*sizeof(BYTE));
	if(!data)
	{
		printf("Can not allocate memory for the pixel data.\n");
		return -1;
	}
	fp=fopen(filepath,"rb");
	if(!fp)
	{
		printf("Can not open the file: %s\n",filepath);
		free(data);
		return -1;
	}
	if(bitCount==8)
	{
		fseek(fp,bmfh.bfOffBits,SEEK_SET);
	}
	else if(bitCount==24)
	{
		fseek(fp,bmfh.bfOffBits,SEEK_SET);
	}
	else
	{
		printf("Only Support: 8 or 24 bits.\n");
		free(data);
		fclose(fp);
		return -1;
	}
	n=fread(data,dwLineBytes*height*sizeof(BYTE),1,fp);
	if(n==0)
	{
		if(feof(fp))
		{
		}
		if(ferror(fp))
		{
			printf("Can not read the pixel data.\n");
			free(data);
			fclose(fp);
			return -1;
		}
	}
	memcpy(imgData,data,dwLineBytes*height*sizeof(BYTE));
	free(data);
	fclose(fp);
	return 0;
}
void PrintFileHeader(BITMAPFILEHEADER *bmfh)
{
	printf("The contents in the file header of the BMP file:\n");
	printf("bfOffBits: %ld\n",bmfh->bfOffBits);
	printf("bfReserved1: %ld\n",bmfh->bfReserved1);
	printf("bfReserved2: %ld\n",bmfh->bfReserved2);
	printf("bfSize: %ld\n",bmfh->bfSize);
	printf("bfType: %ld\n",bmfh->bfType);
}
void PrintInfoHeader(BITMAPINFOHEADER *bmih)
{
	printf("The content in the info header of the BMP file:\n");
	printf("biBitCount: %ld\n",bmih->biBitCount);
	printf("biClrImportant: %ld\n",bmih->biClrImportant);
	printf("biClrUsed: %ld\n",bmih->biClrUsed);
	printf("biCompression: %ld\n",bmih->biCompression);
	printf("biHeight: %ld\n",bmih->biHeight);
	printf("biPlanes: %ld\n",bmih->biPlanes);
	printf("biSize: %ld\n",bmih->biSize);
	printf("biSizeImage: %ld\n",bmih->biSizeImage);
	printf("biWidth: %ld\n",bmih->biWidth);
	printf("biXPelsPerMeter: %ld\n",bmih->biXPelsPerMeter);
	printf("biYPelsPerMeter: %ld\n",bmih->biYPelsPerMeter);
}
LONG GetLineBytes(int imgWidth,int bitCount)
{
	return (imgWidth*bitCount+31)/32*4;
}
void PrintPixelData(BYTE *imgData,int width,int height,int bitCount)
{
	int i;
	int j;
	int p;
	DWORD dwLineBytes=GetLineBytes(width,bitCount);
	if(bitCount==8)
	{
		for(i=0;i<height;i++)
		{
			for(j=0;j<width;j++)
			{
				p=*(imgData+dwLineBytes*(height-1-i)+j);
				printf("%d,",p);
			}
			printf("\n");
		}
	}
	else if(bitCount==24)
	{
		for(i=0;i<height;i++)
		{
			for(j=0;j<width*3;j++)
			{
				printf("(");
				p=*(imgData+dwLineBytes*(height-1-i)+j);
				printf("%d,",p);
				j++;
				p=*(imgData+dwLineBytes*(height-1-i)+j);
				printf("%d,",p);
				j++;
				p=*(imgData+dwLineBytes*(height-1-i)+j);
				printf("%d) ",p);
			}
			printf("\n");
		}
	}
	else
	{
		printf("Only supported: 8 or 24 bits.\n");
	}
}

int SaveAsImage(char *filepath)
{
	FILE *fp;
	fp=fopen(filepath,"wb");
	if(!fp)
	{
		printf("Error: can not create the file.\n");
		return -1;
	}
	SaveFileHeader(fp);
	SaveInfoHeader(fp);
	if(bmih.biBitCount==8)
	{
		SaveColorPalette(fp);
	}
	SavePixelData(fp);
	fclose(fp);
	printf("Save As the image successfully.\n");
	return 0;
}
void ShowImage(char * filepath)
{
	char cmd[266];
	strcpy(cmd,"start ");
	strcat(cmd,filepath);
	printf("%s\n",cmd);
	system(cmd);
}
int SaveFileHeader(FILE *fp)
{
	if(!bReadBMFH)
	{
		printf("Please read the file header at first.\n");
		return -1;
	}
	if(fwrite(&bmfh.bfType,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not write bfType in the file header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmfh.bfSize,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not write bfSize in the file header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmfh.bfReserved1,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not write bfReserved1 in the file header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmfh.bfReserved2,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not write bfReserved2 in the file header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmfh.bfOffBits,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not write bfOffBits in the file header.\n");
		fclose(fp);
		return -1;
	}
	return 0;
}
int SaveInfoHeader(FILE *fp)
{
	if(!bReadBMIH)
	{
		printf("Please read the info header at first.\n");
		return -1;
	}
	if(fwrite(&bmih.biSize,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not write biSize in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biWidth,sizeof(LONG),1,fp)!=1)
	{
		printf("Can not write biWidth in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biHeight,sizeof(LONG),1,fp)!=1)
	{
		printf("Can not write biHeight in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biPlanes,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not write biPlanes in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biBitCount,sizeof(WORD),1,fp)!=1)
	{
		printf("Can not write biBitCount in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biCompression,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not write biCompression in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biSizeImage,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not write biSizeImage in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biXPelsPerMeter,sizeof(LONG),1,fp)!=1)
	{
		printf("Can not write biXPelsPerMeter in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biYPelsPerMeter,sizeof(LONG),1,fp)!=1)
	{
		printf("Can not write biYPelsPerMeter in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biClrUsed,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not write biClrUsed in the info header.\n");
		fclose(fp);
		return -1;
	}
	if(fwrite(&bmih.biClrImportant,sizeof(DWORD),1,fp)!=1)
	{
		printf("Can not write biClrImportant in the info header.\n");
		fclose(fp);
		return -1;
	}
	return 0;
}
int SaveColorPalette(FILE *fp)
{
	int i;
	RGBQUAD pal[256];
	if(!bReadBMIH)
	{
		printf("Please read the info header at first.\n");
		return -1;
	}
	if(bmih.biBitCount!=8)
	{
		printf("Only 8 bits image hase color palette.\n");
		return -1;
	}
	for(i=0;i<256;i++)
	{
		pal[i].rgbReserved=0;
		pal[i].rgbBlue=i;
		pal[i].rgbGreen=i;
		pal[i].rgbRed=i;
	}
	if(fwrite(pal,sizeof(RGBQUAD),256,fp)!=256)
	{
		printf("Error: can not write the color palette.\n");
		fclose(fp);
		return -1;
	}
	return 0;
}
int SavePixelData(FILE* fp)
{
	int height=bmih.biHeight;
	DWORD dwLineBytes=GetLineBytes(bmih.biWidth,bmih.biBitCount);
	if(!bReadPixel)
	{
		printf("Please read the pixel data at first.\n");
		return -1;
	}
	if(fwrite(imgData,height*dwLineBytes,1,fp)!=1)
	{
		printf("Error: can not write the pixel data.\n");
		fclose(fp);
		return -1;
	}
	return 0;
}

运行效果:




图片的属性:



读取结果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值