C++图像打开与显示代码解析 - 详解波段选择和数据处理
C++ 图像打开与显示代码解析 - 详解波段选择和数据处理
本代码实现了打开图像的功能,其中包括读取头文件、选择波段、创建对话框、显示图像等功能。具体实现如下:
1. 读取头文件
首先打开头文件,获取文件长度,然后逐个读取文件中的内容,根据内容的位置分别获取波段数、样本数、行数、数据类型、文件类型、分类数、RGB三个通道的值等信息。
// 打开图像的部分(读取头文件)
int length;
CFile headfile;
headfile.Open(header, CFile::modeRead);
length = headfile.GetLength();
headfile.Close();
CString hbands, hsamples, hlines, hdatatype, hfiletype, hclassnum, hr, hg, hb, hsensor;
int r, g, b;
r = 0;
g = 100;
b = 100;
char *pIn = new char[length];
fstream fin2(header, ios::in);
// 打开挑选波段的对话框
for (int input = 0; input < length; input++)
{
fin2 >> pIn;
if (input == 1)
{
hbands = pIn;
}
if (input == 3)
{
hsamples = pIn;
}
if (input == 5)
{
hlines = pIn;
}
if (input == 7)
{
hdatatype = pIn;
}
if (input == 9)
{
hfiletype = pIn;
if (hfiletype == "Classification")
{
bClassificationImage = TRUE;
}
}
if (bClassificationImage)
{
if (input == 12)
{
hclassnum = pIn;
m_classnum = atoi(hclassnum);
}
for (int j = 0; j < m_classnum; j++)
{
if (input == 17 + 6 * j)
{
hg = pIn;
g = atoi(hg);
}
if (input == 16 + 6 * j)
{
hr = pIn;
r = atoi(hr);
}
if (input == 18 + 6 * j)
{
hb = pIn;
b = atoi(hb);
ColorChange[j] = RGB(r, g, b);
}
}
}
else
{
if (input == 13)
{
hsensor = pIn;
}
}
}
// 挑选结束
2. 选择波段
调用对话框,让用户选择需要显示的波段。根据用户的选择,确定两个对话框的大小,创建两个对话框,并设置其位置和显示方式。
// 重新设置滚动条
CSize sizeTotal;
sizeTotal.cx = Width;
sizeTotal.cy = Height;
SetScrollSizes(MM_TEXT, sizeTotal);
CString str, str1;
CSelBandsDlg selBands;
selBands.m_sarrBands.Add(m_filename);
for (int i = 1; i <= Bands; i++)
{
str = " 波 段";
str1.Format("%d", i);
str = str + str1;
fBandsString[i] = str;
selBands.m_sarrBands.Add(str);
}
if (selBands.DoModal() == IDOK) // 激活选择波段对话框
{
// 确定两个对话框大小
if (Width >= 400) WBig = 400;
else WBig = Width;
if (Height >= 400) HBig = 400;
else HBig = Height;
ScanXPos = 0;
ScanYPos = HBig;
if ((Width <= 250) && (Height <= 250))
{
WSmall = Width;
HSmall = Height;
fZoomRadio = 1;
}
else
{
fZoomRadio = ((Width / 250) >= (Height / 250)) ? (Width / 250) : (Height / 250);
HSmall = Height / fZoomRadio;
WSmall = Width / fZoomRadio;
}
// 创建两个对话框(要用delete)
bigdlg = new CBigImageDlg;
bigdlg->Create(IDD_BIG_IMAGE_DLG, this);
bigdlg->SetWindowPos(&wndTop, 40, 60, WBig + 9, HBig + 28, NULL);
bigdlg->ShowWindow(SW_SHOW);
str = "123456789";
str1 = "";
int nIndex;
nIndex = selBands.m_static_r.FindOneOf(str);
int fMaxN = nIndex + 6;
while ((nIndex != -1) && (nIndex < fMaxN))
{
str1 += selBands.m_static_r.GetAt(nIndex);
selBands.m_static_r.Delete(nIndex, 1);
nIndex = selBands.m_static_r.FindOneOf(str);
}
red = atoi(str1);
str1 = "";
nIndex = selBands.m_static_g.FindOneOf(str);
while ((nIndex != -1) && (nIndex < fMaxN))
{
str1 += selBands.m_static_g.GetAt(nIndex);
selBands.m_static_g.Delete(nIndex, 1);
nIndex = selBands.m_static_g.FindOneOf(str);
}
green = atoi(str1);
str1 = "";
nIndex = selBands.m_static_b.FindOneOf(str);
while ((nIndex != -1) && (nIndex < fMaxN))
{
str1 += selBands.m_static_b.GetAt(nIndex);
selBands.m_static_b.Delete(nIndex, 1);
nIndex = selBands.m_static_b.FindOneOf(str);
}
blue = atoi(str1);
bi.biWidth = Width / fZoomRadio;
bi.biHeight = Height / fZoomRadio;
fWidthDiff = (bi.biWidth * 8 + 31) / 32 * 4 - bi.biWidth;
bi.biWidth = (bi.biWidth * 8 + 31) / 32 * 4;
bi.biSize = (DWORD)sizeof(BITMAPINFOHEADER);
bi.biBitCount = (DWORD)24;
bi.biPlanes = (DWORD)1;
bi.biCompression = 0;
bi.biSizeImage = bi.biWidth * bi.biHeight;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bgbi.biWidth = WBig;
bgbi.biHeight = HBig;
bgbi.biSizeImage = bgbi.biWidth * bgbi.biHeight;
bgbi.biSize = (DWORD)sizeof(BITMAPINFOHEADER);
bgbi.biBitCount = (DWORD)24;
bgbi.biPlanes = (DWORD)1;
bgbi.biCompression = 0;
bgbi.biXPelsPerMeter = 0;
bgbi.biYPelsPerMeter = 0;
bgbi.biClrUsed = 0;
bgbi.biClrImportant = 0;
pbi = (BITMAPINFO*)HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD));
memcpy(pbi, &bi, sizeof(bi));
m_NewWidth = Width;
m_NewHeight = Height;
// 设置鼠标的状态为等待状态
SetCursor(LoadCursor(NULL, IDC_WAIT));
m_file.SeekToBegin();
// 分类型选择波段
BandsSelection();
m_file.Close();
pDoc->UpdateAllViews(NULL, 0, NULL);
}
}
3. 显示图像
根据选择的波段,对图像进行处理,然后在对话框中显示。其中,若是字节型数据,则按照标准图像的方式进行处理,即先读取缩略图的点,然后对小图像上的数据进行显示;再对大图像进行计算,最后在大图像上显示。
void CBsqViewView::BandsSelection()
{
// 若是字节型数据的话
if (bByteData)
{
// 若是标准图像
if (bStandardImage)
{
lpshowbuf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, 3 * bi.biSizeImage);
pData = (LPSTR)lpshowbuf;
lpbigshowbuf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, bgbi.biSizeImage * 3);
pBigPiDataHead = pBigPiData = (LPSTR)lpbigshowbuf;
// 读缩略图的点(对小图像上的数据进行显示)
for (int i = fZoomRadio; i < Height; i = i + fZoomRadio)
{
for (int j = 0; j < Width - (Width % fZoomRadio); j = j + fZoomRadio) // 要减去余数
{
// 按照BGR的顺序进行存储
// 对蓝色的新的显示映射关系
m_file.SeekToBegin();
m_file.Seek(Width * Height * (blue - 1), CFile::current);
m_file.Seek(Width * (Height - (i + 1)) + j, CFile::current);
m_file.Read(lpshowbufB, 1);
m_file.SeekToBegin();
m_file.Seek(Width * Height * (red - 1), CFile::current);
m_file.Seek(Width * (Height - (i + 1)) + j, CFile::current);
m_file.Read(lpshowbufR, 1);
m_file.SeekToBegin();
m_file.Seek(Width * Height * (green - 1), CFile::current);
m_file.Seek(Width * (Height - (i + 1)) + j, CFile::current);
m_file.Read(lpshowbufG, 1);
if (lpshowbufB[0] <= 63)
*pData = 0;
else
{
if (lpshowbufB[0] == 64)
*pData = 10;
if (lpshowbufR[0] % 3 == 0)
{
if ((lpshowbufB[0] - 63) * 10 +
((lpshowbufB[0] - 63) / 3 - 1) * 2 + 1 > 255)
*pData = (unsigned char)255;
else
*pData = (lpshowbufR[0] - 63) * 10 +
((lpshowbufB[0] - 63) / 3 - 1) * 2 + 1;
}
else
{
if ((lpshowbufB[0] - 1) % 3 == 0)
{
if ((lpshowbufB[0] - 1 - 63) * 10 +
((lpshowbufR[0] - 1 - 63) / 3 - 1) * 2 + 1 + 11 > 255)
*pData = (unsigned char)255;
else
*pData = (lpshowbufB[0] - 1 - 63) * 10 +
((lpshowbufB[0] - 1 - 63) / 3 - 1) * 2 + 1 + 11;
}
if ((lpshowbufB[0] + 1) % 3 == 0)
{
if ((lpshowbufB[0] + 1 - 63) * 10 +
((lpshowbufB[0] + 1 - 63) / 3 - 1) * 2 + 1 - 10 > 255)
*pData = (unsigned char)255;
else
*pData = (lpshowbufB[0] + 1 - 63) * 10 +
((lpshowbufB[0] + 1 - 63) / 3 - 1) * 2 + 1 - 10;
}
}
}
// 对绿色的新的显示映射关系
if (lpshowbufG[0] <= 26)
*(pData + 1) = 0;
else
{
if ((lpshowbufG[0] - 26) * 15 > 255)
*(pData + 1) = (unsigned char)255;
else
*(pData + 1) = (lpshowbufG[0] - 26) * 15;
}
// 对红色的新的显示映射关系
if (lpshowbufR[0] <= 24)
*(pData + 2) = 0;
else
{
if ((lpshowbufR[0] - 24) * 8 - 1 > 255)
*(pData + 2) = (unsigned char)255;
else
*(pData + 2) = (lpshowbufR[0] - 24) * 8 - 1;
}
pData = pData + 3;
// 补齐每行当中的空的像素
if ((j + fZoomRadio) >= Width - (Width % fZoomRadio))
{
for (int a = 0; a < fWidthDiff; a++)
{
*pData = *(pData - 3);
*(pData + 1) = *(pData - 2);
*(pData + 2) = *(pData - 1);
pData = pData + 3;
}
}
}
}
// 对大图像进行计算
for (i = bgbi.biHeight; i > 0; i--)
{
m_file.SeekToBegin();
m_file.Seek(Width * Height * (blue - 1), CFile::current);
m_file.Seek(Width * (i - 1), CFile::current);
m_file.Read(lpshowbufB, bgbi.biWidth);
m_file.SeekToBegin();
m_file.Seek(Width * Height * (red - 1), CFile::current);
m_file.Seek(Width * (i - 1), CFile::current);
m_file.Read(lpshowbufR, bgbi.biWidth);
m_file.SeekToBegin();
m_file.Seek(Width * Height * (green - 1), CFile::current);
m_file.Seek(Width * (i - 1), CFile::current);
m_file.Read(lpshowbufG, bgbi.biWidth);
for (int j = 0; j < bgbi.biWidth; j++)
{
// 按照BGR的顺序进行存储
// 对蓝色的新的显示映射关系
if (lpshowbufB[j] <= 63)
*pBigPiData = 0;
else
{
if (lpshowbufB[j] == 64)
*pBigPiData = 10;
if (lpshowbufR[j] % 3 == 0)
{
if ((lpshowbufB[j] - 63) * 10 +
((lpshowbufB[j] - 63) / 3 - 1) * 2 + 1 > 255)
*pBigPiData = (unsigned char)255;
else
*pBigPiData = (lpshowbufR[j] - 63) * 10 +
((lpshowbufB[j] - 63) / 3 - 1) * 2 + 1;
}
else
{
if ((lpshowbufB[j] - 1) % 3 == 0)
{
if ((lpshowbufB[j] - 1 - 63) * 10 +
((lpshowbufR[j] - 1 - 63) / 3 - 1) * 2 + 1 + 11 > 255)
*pBigPiData = (unsigned char)255;
else
*pBigPiData = (lpshowbufB[j] - 1 - 63) * 10 +
((lpshowbufB[j] - 1 - 63) / 3 - 1) * 2 + 1 + 11;
}
if ((lpshowbufB[j] + 1) % 3 == 0)
{
if ((lpshowbufB[j] + 1 - 63) * 10 +
((lpshowbufB[j] + 1 - 63) / 3 - 1) * 2 + 1 - 10 > 255)
*pBigPiData = (unsigned char)255;
else
*pBigPiData = (lpshowbufB[j] + 1 - 63) * 10 +
((lpshowbufB[j] + 1 - 63) / 3 - 1) * 2 + 1 - 10;
}
}
}
// 对绿色的新的显示映射关系
if (lpshowbufG[j] <= 26)
*(pBigPiData + 1) = 0;
else
{
if ((lpshowbufG[j] - 26) * 15 > 255)
*(pBigPiData + 1) = (unsigned char)255;
else
*(pBigPiData + 1) = (lpshowbufG[j] - 26) * 15;
}
// 对红色的新的显示映射关系
if (lpshowbufR[j] <= 24)
*(pBigPiData + 2) = 0;
else
{
if ((lpshowbufR[j] - 24) * 8 - 1 > 255)
*(pBigPiData + 2) = (unsigned char)255;
else
*(pBigPiData + 2) = (lpshowbufR[j] - 24) * 8 - 1;
}
pBigPiData = pBigPiData + 3;
}
}
return ;
}
}
}
总结
本代码实现了打开图像的功能,其中包括读取头文件、选择波段、创建对话框、显示图像等功能。代码详细地讲解了如何读取头文件信息、创建对话框、以及针对字节型数据进行标准图像处理的具体步骤。希望本文能够帮助你更好地理解 C++ 图像处理的实现过程。
原文地址: https://www.cveoy.top/t/topic/jlWL 著作权归作者所有。请勿转载和采集!