实验二 图像文件的读写和转换(BMP转YUV)

来源:互联网 发布:招python测试工程师 编辑:程序博客网 时间:2024/04/29 20:47

实验二 图像文件的读写和转换(BMPYUV)

一、实验基本原理


1.BMP位图文件格式

BMP(全称Bitmap)Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),采用位映射存储格式,除了图像深度可选(148162432bit)以外,在绝大多数应用中不进行其他任何压缩,因此BMP文件所占用的空间很大。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是 Windows 环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。BMP位图文件默认的文件扩展名是bmp或者dib

BMP文件大体上分为四个部分:

(1)位图头文件数据结构

typedef struct tagBITMAPFILEHEADER {WORD bfType; /* 说明文件的类型 */  DWORD bfSize; /* 说明文件的大小,用字节为单位 */  WORD bfReserved1; /* 保留,设置为0 */  WORD bfReserved2; /* 保留,设置为0 */  DWORD bfOffBits; /* 说明从BITMAPFILEHEADER结构开始到实际的图像数据之间的字节偏移量 */  } BITMAPFILEHEADER;

(2)图信息数据结构

typedef struct tagBITMAPINFOHEADER{DWORD biSize; /* 说明结构体所需字节数 */LONG biWidth; /* 以像素为单位说明图像的宽度 */LONG biHeight; /* 以像素为单位说明图像的高度 */WORD biPlanes; /* 说明位面数,必须为1 */WORD biBitCount; /* 说明位数/像素,1、2、4、8、24 */DWORD biCompression; /* 说明图像是否压缩及压缩类型BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS */DWORD biSizeImage; /* 以字节为单位说明图像大小,必须是4的整数倍*/LONG biXPelsPerMeter; /*目标设备的水平分辨率,像素/米 */LONG biYPelsPerMeter; /*目标设备的垂直分辨率,像素/米 */DWORD biClrUsed; /* 说明图像实际用到的颜色数,如果为0,则颜色数为2的biBitCount次方 */DWORD biClrImportant; /*说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。*/} BITMAPINFOHEADER;

(3)调色板

调色板实际上是一个数组,它所包含的元素与位图所具有的颜色数相同,决定于biClrUsedbiBitCount字段。数组中每个元素的类型是一个RGBQUAD结构。这部分信息并不是所有类型的位图都有,真彩色图如24 bitBMP不需要调色板。

typedef struct tagRGBQUAD{BYTE rgbBlue; /*指定蓝色分量*/BYTE rgbGreen; /*指定绿色分量*/BYTE rgbRed; /*指定红色分量*/BYTE rgbReserved; /*保留,指定为0*/} RGBQUAD;

(1)(2)(3)部分的结构体在#include<windows.h>头文件中已定义。

(4)图像数据字节阵列:即位图数据。

对于用到调色板的位图,图像数据就是该像素颜色在调色板中的索引值(逻辑色),真彩色位图如24bit BMP直接使用实际的RGB值。


2.相关重要知识点

(1) 掩码组:

实验过程中发现,RGB565格式的16bit位图与压缩参数biCompression=3 (BI_BITFIELDS:位域存放方式)32bit位图——这两类图片的头部信息中虽然没有伪彩色图片的调色板信息,但是在调色板的位置存在有指示RGB比特位的掩码组信息,为了简化后续的程序算法我在头文件中定义了两个代表掩码组数据信息的结构体如下:

//define mask structtypedef struct bit32Mask{unsigned int rgbRed;unsigned int rgbGreen;unsigned int rgbBlue;unsigned int reserved;}Mas32;typedef struct bit16Mask{unsigned int rgbRed;unsigned int rgbGreen;unsigned int rgbBlue;}Mas16;

为了能更清楚掩码组的作用,下面以一幅biCompression=332bit位图为例,对掩码组信息解读过程如下简图:


(2) DWORD对齐:

图像的每一扫描行由表示图像像素的连续的字节构成,每一行的字节数取决于图像的颜色数目和用像素表示的图像宽度,特别的规定每一扫描行的字节数必须是4的倍数,即DWORD对齐方式。写入位图文件数据时,如果图像每行像素字节总数[ X biBiCount % 8 != 0 ],系统会自动在每行最后填充若干0值使满足整数字节,接着,如果[每行像素字节数 % 4 != 0 ]系统会自动在每行最后填充若干字节0值使满足DWORD对齐。所以我们对位图加载处理时要注意判断每行数据是否有0值填充,若有0值填充则从位图中读取数据的过程中要注意指针偏移量和即时跳转。

(3)自下而上扫描:

扫描行是由底向上存储的,:阵列中的第一个字节表示位图左下角的像素,而最后一个字节表示位图右上角的像素。

如下简图

(4) 字节序:

计算机系统存储数据采用的字节序有两种:小尾字节序(Little Endian)和大尾字节序(Big Endian)Intel处理器大多数采用小尾字节序,“低位在前高位在后”,Motorola处理器大多数使用大尾字节序,“高位在前低位在后”。

为更好地理解Little Endian的数据存储格式,这里以一张RGB565 16bitBMP位图为例,对头部信息的解读示意图如下所示:

二、实验流程

实验流程图:

算法并不是很难,这里仅以16bitBMP提取RGB过程作一个简单示意图如下:

三、具体算法源代码

1.BMP2YUV.h

#ifndef BMP2YUV_H_#define BMP2YUV_H_//define mask structtypedef struct bit32Mask{unsigned int rgbRed;unsigned int rgbGreen;unsigned int rgbBlue;unsigned int reserved;}Mas32;typedef struct bit16Mask{unsigned int rgbRed;unsigned int rgbGreen;unsigned int rgbBlue;}Mas16;int BMP2RGB32bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask);int BMP2RGB24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf);int BMP2RGB16bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf,void *mask);int BMP2RGBNOT24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *pRGB);int RGB2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip);void InitLookupTable();void adjust(unsigned char *b, unsigned char *g, unsigned char *r, unsigned char *y, unsigned char *u, unsigned char  *v);#endif

2.main.c

#include <stdio.h>#include <stdlib.h>#include <windows.h> #include <math.h> #include "bmp2yuv.h"#define u_int8_tunsigned __int8#define u_intunsigned __int32#define u_int32_tunsigned __int32int main(int argc,char **argv){int count;BITMAPFILEHEADER File_header;BITMAPINFOHEADER Info_header;RGBQUAD *pRGB = NULL;FILE* bmp = NULL;FILE* yuvFile = NULL;Mas16 *mask16 = NULL;Mas32 *mask32 = NULL;u_int8_t* yBuf = NULL;u_int8_t* uBuf = NULL;u_int8_t* vBuf = NULL;u_int8_t* rgbBuf = NULL;u_int8_t* bmpBuf = NULL;u_int8_t* mask = NULL;u_int frameWidth;/* --width=<uint> */u_int frameHeight;u_int bitcount;u_int py;u_int m;u_int8_t i;int sum = 0;char bmpf[][50] = { "park.bmp", "tree.bmp", "girlstwo.bmp", "02.bmp", "bea.bmp", "street.bmp" };char yuvname[50] = "CometoYUV.yuv";FILE *yuv=NULL;int framenumber;/* build the RAW file */fopen_s(&yuv, yuvname, "wb+");if (yuv == NULL){printf("Fail to Build yuv file\n");exit(0);}else{printf("The output rgb file is %s\n", yuvname);printf("\n");printf("-------------------------------------------------------------------------\n");}for (i = 0; i<6; i++){count = 0;framenumber = atoi(argv[i + 1]);//open the bmp filefopen_s(&bmp, bmpf[i], "rb");if (!bmp){printf("cannot find the specific file %s:\n", bmpf[i]);exit(0);}else{printf("The input bmp file:   %s\n", bmpf[i]);}if (!framenumber){printf("\n写入帧数:0\n");continue;}else{if (fread(&File_header, sizeof(BITMAPFILEHEADER), 1, bmp) != 1){printf("read file header error!");exit(0);}if (File_header.bfType != 0x4D42){printf("Not bmp file!");exit(0);}//printf("this is a 0x%04X:\n", File_header.bfType);if (fread(&Info_header, sizeof(BITMAPINFOHEADER), 1, bmp) != 1){printf("read info header error!");exit(0);}//end read headerframeWidth = Info_header.biWidth;/* --width=<uint> */frameHeight = Info_header.biHeight;py = File_header.bfOffBits;bitcount = Info_header.biBitCount;/* get an output buffer for a frame */if ((frameWidth*bitcount % 8 == 0) && (frameWidth*bitcount / 8 % 4 == 0))//DWORD 对齐{yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);uBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);vBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);/* get an input buffer for a frame */bmpBuf = (u_int8_t*)malloc(frameWidth * frameHeight * bitcount / 8);/* get an output buffer for a frame */rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);if (rgbBuf == NULL || yBuf == NULL || uBuf == NULL || vBuf == NULL || bmpBuf == NULL){printf("no enought memory\n");exit(1);}////////////////////////////////BMP 2 RGBwhile (framenumber){fseek(bmp, py, SEEK_SET);if (!fread(bmpBuf, 1, frameWidth * frameHeight * bitcount / 8, bmp)){printf("the image has problems!");return 0;}if (bitcount == 32){if (Info_header.biCompression==0){ if (BMP2RGB32bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf,0)){printf("32bit BMP2RGB program runs error!");return 0;}}else if (Info_header.biCompression == 3){//取掩码组m = 4*4;mask32 = (Mas32*)malloc(sizeof(Mas32));fseek(bmp, sizeof(BITMAPFILEHEADER) + Info_header.biSize - m, SEEK_SET);fread(mask32, sizeof(Mas32),1, bmp);if (BMP2RGB32bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, mask32)){printf("32bit BMP2RGB program runs error!");return 0;}}}else if (bitcount == 24){//真彩位图if (BMP2RGB24bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf)){printf("24bit BMP2RGB program runs error!");return 0;}}else if (bitcount == 16){//16bit BMP RGB比特位根据biCompression确定if (Info_header.biCompression == 0)//555{if (BMP2RGB16bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, 0)){printf("16bit BMP2RGB program runs error!");return 0;}}else if (Info_header.biCompression == 3){//取掩码组m = 4 * 3;mask16 = (Mas16*)malloc(sizeof(Mas16));fseek(bmp, py-m, SEEK_SET);fread(mask16, 1, m, bmp);if (BMP2RGB16bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, mask16)){printf("16bit BMP2RGB program runs error!");return 0;}}}else{if ((py - sizeof(BITMAPFILEHEADER) - Info_header.biSize) == sizeof(RGBQUAD)*pow(2, bitcount)){//1、2、4、8 bit 有调色板部分m = (unsigned int)pow(2, bitcount);pRGB = (RGBQUAD *)malloc(sizeof(RGBQUAD)*m);fseek(bmp, sizeof(BITMAPFILEHEADER) + Info_header.biSize, SEEK_SET);fread(pRGB, sizeof(RGBQUAD), m, bmp);if (BMP2RGBNOT24bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, pRGB)){printf("BMP 2 RGB program runs error!");return 0;}}}/////////////////////////////RGB2YUVif (RGB2YUV(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf, 0/*flip=0*/))//bmp图像格式从最后一行起逐行扫描{printf("RGB2YUV program runs error!");return 0;}fwrite(yBuf, 1, frameWidth * frameHeight, yuv);fwrite(uBuf, 1, (frameWidth * frameHeight) / 4, yuv);fwrite(vBuf, 1, (frameWidth * frameHeight) / 4, yuv);printf("\r...%d", ++count);framenumber--;}printf("\n写入帧数:%u   %ux%u(%d bit)\n", count, frameWidth, frameHeight, bitcount);sum += count;printf("\n");printf("\n");}}}printf("%d帧YUV写入成功!\n",sum);/* cleanup */fclose(bmp);fclose(yuv);//free the memory   if (yBuf){ free(yBuf); }if (uBuf){ free(uBuf); }if (vBuf){ free(vBuf); }if (rgbBuf){ free(rgbBuf); }if (bmpBuf){ free(bmpBuf); }if (pRGB){ free(pRGB); }if (mask16){ free(mask16); }if (mask32)  { free(mask32); }return 0;}

3.BMP2RGB.c

#include "stdlib.h"#include "bmp2yuv.h"#include <windows.h> #include <math.h> int BMP2RGB32bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask){long i;unsigned char *bmp, *rgb;Mas32 *mas;long size = x_dim*y_dim;bmp = (unsigned char *)bmpbuf;rgb = (unsigned char *)rgbbuf;mas = (Mas32 *)mask;if (mask == NULL){for (i = 0; i < size; i++){*(rgb + 0) = *(bmp + 0);*(rgb + 1) = *(bmp + 1);*(rgb + 2) = *(bmp + 2);rgb += 3;bmp += 4;}return 0;}else{//根据掩码确定RGB比特位int Gkey, Bkey, Rkey;if (mas->rgbGreen == 0)Gkey= 0;else if (mas->rgbGreen == 0xFF000000)Gkey = 3;else if (mas->rgbGreen == 0xFF0000)Gkey = 2;else if (mas->rgbGreen == 0xFF00)Gkey = 1;elsereturn 1;if (mas->rgbBlue == 0)   Bkey = 0;else if (mas->rgbBlue == 0xFF000000)Bkey = 3;else if (mas->rgbBlue == 0xFF0000)Bkey = 2;else if (mas->rgbBlue == 0xFF00)Bkey = 1;elsereturn 1;if (mas->rgbRed == 0)Rkey = 0;else if (mas->rgbRed == 0xFF000000)Rkey = 3;else if (mas->rgbRed == 0xFF0000)Rkey = 2;else if (mas->rgbRed == 0xFF00)Rkey = 1;elsereturn 1;for (i = 0; i < size; i++){*(rgb + 0) = *(bmp + Bkey);*(rgb + 1) = *(bmp + Gkey);*(rgb + 2) = *(bmp + Rkey);rgb += 3;bmp += 4;}return 0;}}int BMP2RGB24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf){long i;unsigned char *rgb;// , *raw;unsigned char *bmp;long size = x_dim*y_dim;rgb = (unsigned char *)rgbbuf;bmp = (unsigned char *)bmpbuf;for (i = 0; i < size*3; i++){*(rgb + i) = *(bmp + i);}return 0;}int BMP2RGB16bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask){long loop;unsigned char *Data, *rgbDataOut;long size = x_dim*y_dim*bitcount / 8;Data = (unsigned char*)bmpbuf;rgbDataOut = (unsigned char*)rgbbuf;Mas16 *mas;mas = (Mas16 *)mask;if (mask == NULL){for (loop = 0; loop < size; loop += 2){*rgbDataOut = (*(Data + loop) & 0x1F) << 3;*(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 2) + ((*(Data + loop + 1) & 0x03) << 6);*(rgbDataOut + 2) = (*(Data + loop + 1) & 0x7C) << 1;rgbDataOut += 3;}}else//555 OR 565决定于rgbGreen的比特位{if (mas->rgbGreen == 0x07E0){for (loop = 0; loop < size; loop += 2){*rgbDataOut = (*(Data + loop) & 0x1F) << 3;*(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 3) + ((*(Data + loop + 1) & 0x07) << 5);*(rgbDataOut + 2) = (*(Data + loop + 1) & 0xF8);rgbDataOut += 3;}}else{for (loop = 0; loop < size; loop += 2){*rgbDataOut = (*(Data + loop) & 0x1F) << 3;*(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 2) + ((*(Data + loop + 1) & 0x03) << 6);*(rgbDataOut + 2) = (*(Data + loop + 1) & 0x7C) << 1;rgbDataOut += 3;}}}return 0;}int BMP2RGBNOT24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *ppRGB)//1\4\8 bit BMP{unsigned char *rgb;unsigned char *bmp;unsigned char index;bmp = (unsigned char *)bmpbuf;rgb = (unsigned char *)rgbbuf;int shiftCnt;unsigned char mask;long loop = 0;unsigned char *Data, *rgbDataOut;RGBQUAD* p;long size = x_dim*y_dim*bitcount/8;Data = (unsigned char*)bmpbuf;rgbDataOut = (unsigned char*)rgbbuf;p = (RGBQUAD*)ppRGB;for (loop = 0; loop<size; loop++){shiftCnt = 1;mask = (unsigned char)pow(2, bitcount) - 1;mask = mask << (8-bitcount);while (mask){//索引号的确定index = (mask == 0xFF) ? *(Data + loop) : (*(Data + loop) & mask) >> (8 - shiftCnt * bitcount);*rgbDataOut = (p + index)->rgbBlue;*(rgbDataOut + 1) = (p + index)->rgbGreen;*(rgbDataOut + 2) = (p + index)->rgbRed;if (bitcount == 8)mask = 0;elsemask >>= bitcount;rgbDataOut += 3;shiftCnt++;}}return 0;}

4.RGB2YUV.c

#include "stdlib.h"#include "bmp2yuv.h"static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];static float RGBYUV01684[256], RGBYUV03316[256];static float RGBYUV04187[256], RGBYUV00813[256];int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip){static int init_done = 0;long i, j, size;unsigned char *r, *g, *b;unsigned char *y, *u, *v;unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;unsigned char *y_buffer, *u_buffer, *v_buffer;unsigned char *sub_u_buf, *sub_v_buf;if (init_done == 0){InitLookupTable();init_done = 1;}// check to see if x_dim and y_dim are divisible by 2if ((x_dim % 2) || (y_dim % 2)) return 1;size = x_dim * y_dim;// allocate memoryy_buffer = (unsigned char *)y_out;sub_u_buf = (unsigned char *)u_out;sub_v_buf = (unsigned char *)v_out;u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));if (!(u_buffer && v_buffer)){if (u_buffer) free(u_buffer);if (v_buffer) free(v_buffer);return 2;}b = (unsigned char *)bmp;y = y_buffer;u = u_buffer;v = v_buffer;// convert RGB to YUVif (!flip) {for (j = 0; j < y_dim; j ++){y = y_buffer + (y_dim - j - 1) * x_dim;u = u_buffer + (y_dim - j - 1) * x_dim;v = v_buffer + (y_dim - j - 1) * x_dim;for (i = 0; i < x_dim; i ++) {g = b + 1;r = b + 2;adjust(b, g, r, y, u, v);b += 3;y ++;u ++;v ++;}}} else {for (i = 0; i < size; i++){g = b + 1;r = b + 2;adjust(b, g, r, y, u,v);b += 3;y ++;u ++;v ++;}}// subsample UVfor (j = 0; j < y_dim/2; j ++){psu = sub_u_buf + j * x_dim / 2;psv = sub_v_buf + j * x_dim / 2;pu1 = u_buffer + 2 * j * x_dim;pu2 = u_buffer + (2 * j + 1) * x_dim;pv1 = v_buffer + 2 * j * x_dim;pv2 = v_buffer + (2 * j + 1) * x_dim;for (i = 0; i < x_dim/2; i ++){*psu = (*pu1 + *(pu1+1) + *pu2 + *(pu2+1)) / 4;*psv = (*pv1 + *(pv1+1) + *pv2 + *(pv2+1)) / 4;psu ++;psv ++;pu1 += 2;pu2 += 2;pv1 += 2;pv2 += 2;}}free(u_buffer);free(v_buffer);return 0;}void InitLookupTable(){int i;for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;}void adjust(unsigned char *b, unsigned char *g, unsigned char *r, unsigned char *y, unsigned char *u, unsigned char  *v){float temp = 0;temp = (float)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);temp = temp>235 ? 235 : temp;temp = temp<16 ? 16 : temp;*y = (unsigned char)temp;temp = (float)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);temp = temp>240 ? 240 : temp;temp = temp<16 ? 16 : temp;*u = (unsigned char)temp;temp = (float)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);temp = temp>240 ? 240 : temp;temp = temp<16 ? 16 : temp;*v = (unsigned char)temp;}

四、实验结果

根据实验指导书要求:生成带有个人logo的多张bmp图片(测试程序使用6幅图片),程序执行时可在命令行中设置每个画面出现的帧数,最后形成的YUV文件不少于200帧。


测试图片源文件均来自网络,后续测试中所用的1481632bit位图是利用画图板/PS软件由原图转换得到。


由命令行设置每幅图片播放帧数:

程序执行结果如下图所示:


生成的YUV文件取其中六帧截图如下:对于148 bit颜色深度的BMP位图到明显颜色内容的失真。

五、实验总结

缓冲区分配、结构体操作、倒序读写文件、函数定义等操作是这次实验应该重点掌握的内容。

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 监控拍我我偷钱怎么办 网吧上网密码忘记了怎么办 比熊犬晚上叫怎么办 刚买的狗一直叫怎么办 酒驾罚款2年没交怎么办 法院判罚款没有钱怎么办 有人朝你吐口水怎么办 孕妇用了六神花露水怎么办 出车祸人不赔钱怎么办 交通事故对方保险不签字怎么办 肇事车主联系不上怎么办 商标被别人申请无效宣告怎么办 淘宝上传宝贝没有品牌怎么办 萌虎白卡借款2000逾期了怎么办 最里面的牙齿烂了怎么办 金龙沉底不游怎么办 龙鱼尾巴烂了怎么办 微博忘了登录名和密码怎么办 新浪微博密码忘了怎么办 vivo手机用户密码忘了怎么办 微博登录名忘记了怎么办 微信忘记密码钱怎么办 微信密码申诉失败怎么办 微博密码被盗了怎么办 对公密码器丢了怎么办 手机qq忘记旧密码怎么办 qq旧密码忘记了怎么办 微博账户密码忘记了怎么办 三星盖乐世s3忘记密码了怎么办 微博登录密码忘记了怎么办 助学贷款密码忘了怎么办 助学贷款的密码忘了怎么办 助学贷款登录密码忘了怎么办 抖音换了手机登不了怎么办 微信忘记密码申诉失败怎么办 银行卡短信通知没了怎么办 斗鱼手机号被绑定了怎么办 网易邮箱不记得账号怎么办 qq号被盗申诉不回来怎么办 号被盗了申诉不回来怎么办 富士康离职后工资卡号没填怎么办?