OpenGL顯示圖片

来源:http://www.cnblogs.com/charlee44/archive/2016/08/06/5745127.html
-Advertisement-
Play Games

最近想用C++在windows下實現一個基本的圖像查看器功能,目前只想到了使用GDI或OpenGL兩種方式。由於實在不想用GDI的API了,就用OpenGL的方式實現了一下基本的顯示功能。用GDAL讀取圖像,這樣就能與圖像格式無關。OpenGL的glDrawPixels()函數也能實現圖像顯示,但是... ...


最近想用C++在windows下實現一個基本的圖像查看器功能,目前只想到了使用GDI或OpenGL兩種方式。由於實在不想用GDI的API了,就用OpenGL的方式實現了一下基本的顯示功能。

用GDAL讀取圖像,這樣就能與圖像格式無關。OpenGL的glDrawPixels()函數也能實現圖像顯示,但是現在高版本的OpenGL都採用glTexImage2D()貼紋理的方式了,也不用考慮圖像大小是否是2的N次方,或者4位元組對齊的問題。具體實現如下:

// ImageShow.cpp : 定義控制台應用程式的入口點。
//

#include "stdafx.h"
#include "ImageShow.h"

#include <iostream>
#include <gl\glew.h>            // 包含最新的gl.h,glu.h庫
#include <gl\freeglut.h>            // 包含OpenGL實用庫
#include <gdal_priv.h> 

using namespace std;

unsigned int  texture;    // 紋理對象
unsigned char* imgBuf = nullptr;
int imgWidth;
int imgHeight;

void ReadImage()
{
    GDALAllRegister();

    GDALDataset* img = (GDALDataset *)GDALOpen("lena.bmp", GA_ReadOnly);
    //GDALDataset* img = (GDALDataset *)GDALOpen("dst.tif", GA_ReadOnly);
    if (img == nullptr)
    {
        return;
    }   

    imgWidth = img->GetRasterXSize();   //圖像寬度
    imgHeight = img->GetRasterYSize();  //圖像高度
    int bandNum = img->GetRasterCount();    //波段數   
    int depth = GDALGetDataTypeSize(img->GetRasterBand(1)->GetRasterDataType()) / 8;    //圖像深度

    //申請buf
    size_t imgBufNum = (size_t)imgWidth * imgHeight * bandNum * depth;
    size_t imgBufOffset = (size_t)imgWidth * (imgHeight - 1) * bandNum * depth;
    imgBuf = new GByte[imgBufNum];
    //讀取
    img->RasterIO(GF_Read, 0, 0, imgWidth, imgHeight, imgBuf + imgBufOffset, imgWidth, imgHeight,
        GDT_Byte, bandNum, nullptr, bandNum*depth, -imgWidth*bandNum*depth, depth);

    GDALClose(img);
}

void InitGL()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);

    glShadeModel(GL_SMOOTH);      //平滑著色
    glEnable(GL_DEPTH_TEST);       //深度測試
    glEnable(GL_CULL_FACE);    //只渲染某一面
    glFrontFace(GL_CCW);     //逆時針正面
            
    glEnable(GL_TEXTURE_2D);    //啟用2D紋理映射  

    //載入紋理圖像:
    ReadImage();
    
    //生成紋理對象:
    glGenTextures(1, &texture);         
}

void DrawGLScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindTexture(GL_TEXTURE_2D, texture);    //綁定紋理:
    
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //支持4位元組對齊

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);      //S方向上貼圖
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);      //T方向上貼圖
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);       //放大紋理過濾方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);       //縮小紋理過濾方式
        
    glTexImage2D(GL_TEXTURE_2D, 0, 3, imgWidth, imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, imgBuf);  //載入紋理:                                                                                                       

    glMatrixMode(GL_MODELVIEW);                         // 選擇模型觀察矩陣
    glLoadIdentity();                                   // 重置模型觀察矩陣     
    glMatrixMode(GL_PROJECTION);                        // 選擇投影矩陣       
    glLoadIdentity();
        
    glEnable(GL_TEXTURE_2D);    //啟用2D紋理映射
    glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 0.0f);   
    glVertex3f(-0.5f, -0.5f, 0.0f);
    glTexCoord2f(1.0f, 0.0f);   
    glVertex3f(0.5f, -0.5f, 0.0f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(0.5f, 0.5f, 0.0f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-0.5f, 0.5f, 0.0f);
    glEnd();
    glDisable(GL_TEXTURE_2D);

    glutSwapBuffers();
}

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)    // 重置OpenGL視窗大小
{
    glViewport(0, 0, width, height);
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("opengl");
    
    InitGL();   
    glutDisplayFunc(DrawGLScene);
    glutReshapeFunc(ReSizeGLScene);
    //glutKeyboardFunc(keyboard);
    //glutMouseWheelFunc(mouse_wheel);
    //glutIdleFunc(idle);

    glutMainLoop(); 
        
    return 0;
}

最後顯示的情況如下:

另外註意最後需要釋放資源:

glDeleteTextures(1, &texture);
if (imgBuf)
{
    delete[] imgBuf;
    imgBuf = nullptr;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 重載的條件: 1.必須在同一個類中2.方法名必須相同3.參數列表不能相同。 重寫的條件: 1. 在不同的類中 2. 發生方法重寫的兩個方法返回值,方法名,參數列表必須完全一致 3. 子類拋出的異常不能超過父類相應的方法拋出的異常 4. 子類方法的訪問級別不能低於父類相應方法的訪問級別(public, ...
  • 前言:以前總說自己玩mvc,但是對mvc的認識還是不夠透徹,也沒有好好看微軟自帶的mvc項目中的精妙,最近閑了下來,好好看了看。 通過上圖,我們可以清晰地瞭解到MVC 5應用程式的項目結構,接下來我們來依次解釋下他們各自的應用。 App_Data: 該文件夾主要是包含應用程式的本地存儲, 它通常以文 ...
  • 在hibernate中我們知道如果要從資料庫中得到一個對象,通常有兩種方式,一種是通過session.get()方法,另一種就是通過session.load()方法,然後其實這兩種方法在獲得一個實體對象時是有區別的,在查詢性能上兩者是不同的。 一.load載入方式 當使用load方法來得到一個對象時 ...
  • 持久化(Persistence) 即把數據(如記憶體中的對象)保存到可永久保存的存儲設備中(如磁碟)。持久化的主要應用是將記憶體中的對象存儲在關係型的資料庫中,當然也可以存儲在磁碟文件中、XML數據文件中等等。 持久化是將程式數據在持久狀態和瞬時狀態間轉換的機制。 JDBC就是一種持久化機制。文件IO也 ...
  • //fourth day to study python 24. In python , how to create funcation. we can use def to define funcation. such as: def MyFirstFuncation(): print('this ...
  • 請註意以下要點: 1、是否開啟了認證,QQ郵箱、163郵箱均要開啟認證 2、javax.mail.MessagingException: Could not connect to SMTP host: smtp.163.com, port: 25; //連接超時 解決參考:將這個屬性的true加上引 ...
  • stdafx.h: Form1.h ...
  • 1.安裝 Erlang,官網:https://www.erlang.org/ 2.安裝RabbitMQ伺服器,rabbitMQ server,官網http://www.rabbitmq.com/ 註:可以根據不同的需要到官網進行相關下載!!! 3.安裝完成之後需要對其進行配置變數: 創建新的系統變數 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...