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++ 图像处理的实现过程。

C++图像打开与显示代码解析 - 详解波段选择和数据处理

原文地址: https://www.cveoy.top/t/topic/jlWL 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录