我仍然是 C++ 的菜鸟,我目前正在尝试创建一个程序,该程序手动将 256 色位图加载到数组并打印出控制台中每个像素的值。在大多数情况下,这些价值观似乎是不正确的。
我的其他输出(例如信息标题内的值)都很好biSizeImage
,除了 5 字节。这不应该是 25 字节吗?
出于测试目的,我拍摄了两张 5 x 5 的图像。其中一个是全黑的,另一个是全白的。
我希望黑色的输出类似于:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
但我得到:
0 0 0 0 0
0 0 0 0 0
3452816845 3452816845 3452816845 3452816845 3452816845
3452816845 3452816845 3452816845 3452816845 3452816845
3452816845 3452816845 3452816845 3452816845 3452816845
有了全白的图片,我的结果就更加奇怪了:
4294967295 255 4294967295 255 4294967295
255 4294967295 255 4294967295 255
3452816845 3452816845 3452816845 3452816845 3452816845
3452816845 3452816845 3452816845 3452816845 3452816845
3452816845 3452816845 3452816845 3452816845 3452816845
下面你可以看到我当前的代码:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
using namespace std;
#pragma pack(push,1)
typedef struct tagBITMAPFILEHEADER {
unsigned short bfType; // Specifies the type of file. This member must be BM. (0x4D42)
unsigned int bfSize; // Specifies the size of the file, in bytes.
short bfReserved1; // Reserved; must be set to zero.
short bfReserved2; // Reserved; must be set to zero.
unsigned int bfOffBits; // Specifies the byte offset from the BITMAPFILEHEADER structure to the actual bitmap data in the file.
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
unsigned int biSize; // Specifies the number of bytes required by the BITMAPINFOHEADER structure.
int biWidth; // Specifies the width of the bitmap, in pixels.
int biHeight; // Specifies the height of the bitmap, in pixels.
unsigned short biPlanes; // Specifies the number of planes for the target device. This member must be set to 1.
unsigned short biBitCount; // Specifies the number of bits per pixel. This value must be 1,4, 8, or 24.
unsigned int biCompression; // Specifies the type of compression for a compressed bitmap. Itcan be one of the following values: BI_RGB, BI_RLE8, BI_RLE4
unsigned int biSizeImage; // Specifies the size, in bytes, of the image. It is valid to set this member to zero if the bitmap is in the BI_RGB format.
int biXPelsPerMeter; // Specifies the horizontal resolution, in pixels per meter, of the target device for the bitmap.
int biYPelsPerMeter; // Specifies the vertical resolution, in pixels per meter, of the target device for the bitmap.
unsigned int biClrUsed; // Specifies the number of color indexes in the color table actually used by the bitmap.
unsigned int biClrImportant; // Specifies the number of color indexes that are considered important for displaying the bitmap. If this value is zero, all colors are important.
} BITMAPINFOHEADER;
typedef struct tagRGBPIXEL{
unsigned char b;
unsigned char g;
unsigned char r;
} rgbPIXEL;
#pragma pack(pop)
typedef struct tagBITMAP{
BITMAPFILEHEADER FILEHEADER;
BITMAPINFOHEADER INFOHEADER;
rgbPIXEL* IMAGEDATA;
}BITMAP;
void main (){
string sImageLocation = "C:/BMP.bmp";
BITMAP bmpImage;
FILE* fbmpImage = NULL;
unsigned int ImagePixelAmount = 0;
bool bImageLoaded = false;
do{
//Open the image file
fopen_s(&fbmpImage, sImageLocation.c_str(), "rb");
//Check whether the image could be loaded successfully or not
if(fbmpImage == NULL){
cout << "Loading the image file failed!" << " " << endl;
}
if(fbmpImage != NULL){
cout << "Loaded the image file successfully!" << endl;
bImageLoaded = true;
}
cout << endl;
cout << endl;
cout << endl;
//Read the BITMAP FILE HEADER
fseek(fbmpImage, 0, SEEK_SET);
fread(&bmpImage.FILEHEADER, sizeof(BITMAPFILEHEADER), 1, fbmpImage);
//Check if the image is a valid bitmap file
if(bmpImage.FILEHEADER.bfType != 19778){
bImageLoaded = false;
cout << "Image is not a valid Bitmap file!" << endl;
fclose(fbmpImage);
}
}while(bImageLoaded = false);
//Show the information of the BITMAP FILE HEADER in the consol
cout << "Bitmap File Header Data Values:" << endl;
cout << endl;
cout << "Image Type: " << bmpImage.FILEHEADER.bfType << endl;
cout << "Image Size: " << bmpImage.FILEHEADER.bfSize << " Bytes" << endl;
cout << "Reserved: " << bmpImage.FILEHEADER.bfReserved1 << endl;
cout << "Reserved: " << bmpImage.FILEHEADER.bfReserved2 << endl;
cout << "Byte Offset: " << bmpImage.FILEHEADER.bfOffBits << endl;
cout << endl;
cout << endl;
cout << endl;
//Read the BITMAP INFO HEADER
fread(&bmpImage.INFOHEADER, sizeof(BITMAPINFOHEADER), 1, fbmpImage);
cout << "Bitmap Info Header Data Values: " << endl;
cout << endl;
cout << "Size of Bitmap Info Header: " << bmpImage.INFOHEADER.biSize << " Bytes" << endl;
cout << "Width of Bitmap: " << bmpImage.INFOHEADER.biWidth << " Pixel" << endl;
cout << "Height of Bitmap: " << bmpImage.INFOHEADER.biHeight << " Pixel" << endl;
cout << "Size of Image Data: " << bmpImage.INFOHEADER.biHeight << " Bytes" << endl;
cout << "Bit Count: " << bmpImage.INFOHEADER.biBitCount << " Bits Per Pixel" << endl;
cout << "Amount of color indexes: " << bmpImage.INFOHEADER.biClrUsed << endl;
cout << "Compression: " << bmpImage.INFOHEADER.biCompression << endl;
cout << endl;
cout << endl;
cout << endl;
ImagePixelAmount = bmpImage.INFOHEADER.biHeight * bmpImage.INFOHEADER.biWidth;
//Create space in memory and read in pixel data from the image
bmpImage.IMAGEDATA = (rgbPIXEL*)malloc(sizeof(rgbPIXEL) * ImagePixelAmount);
cout << "Memory for image created" << endl;
fseek(fbmpImage, bmpImage.FILEHEADER.bfOffBits, SEEK_SET);
fread(bmpImage.IMAGEDATA, ImagePixelAmount * sizeof(rgbPIXEL), 1, fbmpImage);
fclose(fbmpImage);
//Show the pixel data in the consol in numbers instead of ASCII-symbols
for(int y =0; y < bmpImage.INFOHEADER.biHeight; y++){
for(int x = 0; x < bmpImage.INFOHEADER.biWidth; x++){
cout << "Red: " <<(unsigned int) bmpImage.IMAGEDATA[y * bmpImage.INFOHEADER.biWidth + x].r << " ";
cout << "Green: " <<(unsigned int) bmpImage.IMAGEDATA[y * bmpImage.INFOHEADER.biWidth + x].g << " ";
cout << "Blue: " <<(unsigned int) bmpImage.IMAGEDATA[y * bmpImage.INFOHEADER.biWidth + x].b << " ";
}
cout << endl;
}
cout << endl;
cout << endl;
cout << endl;
cout << "Press any key to quit the programm" << endl;
_getch();
return;
}
更新:
根据 Hans Passant 的说法,我将代码更改为加载 24 位位图。使用红色位图,我会假设每个像素的打印值是red = 255, green = 0 and blue = 0
. 但是,我收到的每个像素的实际值是red = 237, green = 28 and blue = 36
. 对于任何其他图像,我都有同样的麻烦。