展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > Delphi使用OpenGL2d绘图之画图片Bmp的方法

Delphi使用OpenGL2d绘图之画图片Bmp的方法

Delphi结合OpenGL绘制BMP图片需额外下载Gl.pas及Glaux.pas辅助库。实现流程分加载BMP、转换为纹理、绘制三步。两种方法:glDrawPixels直接绘制,位置固定于窗口左下角;纹理映射可通过四边形控制位置与缩放,更灵活。利用TBitmap加载图片,注意数据格式为BGR。

用Delphi结合OpenGL做2D绘图,尤其是想把一张BMP图片画到屏幕上,这事儿说起来简单,但上手时总会遇到几个“坑”。首先,Delphi自带的OpenGL单元封装的是1.0版本,有些函数没声明,所以你得额外下载一个Gl.pas。另外,还需要一个Glaux.pas单元和对应的glaux.dll辅助库。这些资源网上都能找到,文末也提供了打包下载。

一、前言

Delphi使用OpenGL2d绘图之画图片Bmp的方法

对于Delphi来说,要画图片要先处理一下,需要引用别的单元,而Delphi中没带,需要另外下载Gl.pas。网上常见自带的OpenGl单元封装的是1.0版的,有此函数未声明。网上可以找到Gl.pas单元。另外需要一个Glaux.pas单元与glaux.dll,是辅助库。在本文最后会提供下载。

二、实现流程

那么,具体需要哪几步呢?Windows的绘图机制是基于位图的,所以不管是PNG还是JPG,最终都要转成BMP来操作。大体上分为三步:

1. 加载BMP图片:使用auxDIBImageLoadA或其他函数。

2. 转换为纹理:glGenTexturesglBindTextureglTexImage2DglTexParameteri用于设置相关参数。

3. 绘制纹理:glBindTextureglBegin(GL_QUADS)glTexCoord2fglVertex2fglEnd

三、利用glDrawPixels函数绘图

先说说一种比较直接的方法——glDrawPixels。它的参数有五个:

  • width:图像的宽度
  • height:图像的高度
  • format:图像的数据存储格式
  • atype:未知
  • pixels:DIB数据的指针

示例代码如下:

procedure TForm1.Draw;
var
 Bmp: TBitmap;
begin
 Bmp := TBitmap.Create;
 Bmp.LoadFromFile(ExtractFilePath(ParamStr(0)) + '1.bmp');
 // 清空缓冲区
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 // TBitmap的图像数据在内存中是按行倒序连续存放的,通过TBitmap.ScanLine[TBitmap.Height-1]可以取得首地址即图像缓冲区地址
 // bmp图片的颜色是按b g r存储的,所以要选 GL_BGR_EXT做为参数
 glDrawPixels(Bmp.Width, Bmp.Height, GL_BGR_EXT, GL_UNSIGNED_BYTE, Bmp.ScanLine[Bmp.Height - 1]);
 SwapBuffers(FDC);
 Bmp.Free;
end;

用以上方法绘制图片不需要启用纹理映射,可以通过glPixelZoom函数来缩放图片,显示位置在窗口的左下角(暂时不知道如何改变图像位置)。

三、使用纹理绘图

想要控制图片的显示位置与放大缩小,纹理映射是更灵活的方式。具体怎么做呢?

1. 把图片加载到程序里,获取相关的图片信息

将图片加载到纹理中,可参考这篇文章:https://www.jb51.net/article/52125.htm

在Delphi中加载一张位图很简单,有两种常见方式:

(1)通过辅助库的auxDIBImageLoadA函数加载图片,返回一个PTAUX_RGBImageRec数据指针,DIB数据格式为RGB。

 // RGB数据的结构体
 TAUX_RGBImageRec = record
  sizeX, sizeY: GLint;
  data: pointer;
 end;
 PTAUX_RGBImageRec = ^TAUX_RGBImageRec;
var
 p: PTAUX_RGBImageRec;
begin
 p := auxDIBImageLoadA(PAnsiChar(ExtractFilePath(ParamStr(0)) + '1.bmp'));
 // p 怎么释放? Dispose与Freemem都无法操作这个指针
end;

(2)通过TBitmap.LoadFromFile加载图片。这是Delphi自带的,从效率上对比,与auxDIBImageLoadA性能是一样的,但DIB数据格式为BGR,DIB指针为TBitmap.ScanLine[Bmp.Height - 1]

var
 Bmp: TBitmap;
begin
 Bmp := TBitmap.Create;
 TBitmap.LoadFromFile(ExtractFilePath(ParamStr(0)) + '1.bmp');
 // do something
 // 用完释放
 Bmp.Free;
end;

2. 创建纹理,其中的glGenTexturesglBindTexture在Gl.pas中。

 // 创建纹理区域
 glGenTextures(1, @texture);
 // 绑定纹理区域
 glBindTexture(GL_TEXTURE_2D, texture);
 // 使用位图创建图像纹理
 glTexImage2D(
  GL_TEXTURE_2D,      // 纹理是一个2D纹理 GL_TEXTURE_2D
  0,            // 图像的详细程度 默认 0
  3,            // 数据的成分数。因为图像是由红,绿,蓝三种组成 默认3
  Bmp.Width,        // 纹理的宽度
  Bmp.Height,        // 纹理的高度
  0,            // 边框的值 默认 0
  GL_BGR_EXT,        // 数据格式 bmp使用 bgr
  GL_UNSIGNED_BYTE,     // 组成图像的数据是无符号字节类型的
  Bmp.ScanLine[Bmp.Height - 1] // DIB数据指针
 );
 // 下面两行是让opengl在放大原始的纹理大(GL_TEXTURE_MAG_FILTER)或缩小原始纹理(GL_TEXTURE_MIN_FILTER)时OpenGL采用的滤波方式。
 // GL_LINEAR 使用线性滤波,可以把图片处理处平滑,但需要更多的内存与CPU
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 线形滤波
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 线形滤波

3. 绘制纹理

绘制纹理之前,必须通知OpenGL开启纹理映射:glEnable(GL_TEXTURE_2D)。开启后,非纹理的绘制将不起作用。用完记得关闭。

 // 以下是绘图,利用一个四边形,绘制图片
 // 启用纹理映射
 if glIsEnabled(GL_TEXTURE_2D) = 0 then
  glEnable(GL_TEXTURE_2D);
 // 清空缓冲区
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); 
 l := 10;
 t := 10;
 w := 200; // 放大为200*200的图片
 // 选择纹理 如果场景中使用多个纹理,不能在glBegin() 和 glEnd() 之间绑定纹理
 glBindTexture(GL_TEXTURE_2D, texture);
 glBegin(GL_QUADS);
 // glTexCoord2f 的第一个参数是X坐标。
 // 0.0是纹理的左侧。 0.5是纹理的中点, 1.0是纹理的右侧。
 // glTexCoord2f 的第二个参数是Y坐标。
 // 0.0是纹理的底部。 0.5是纹理的中点, 1.0是纹理的顶部。
 glTexCoord2f(0, 1);
 glVertex2f(l, t);
 glTexCoord2f(1, 1);
 glVertex2f(l + w, t);
 glTexCoord2f(1, 0);
 glVertex2f(l + w, t + w);
 glTexCoord2f(0, 0);
 glVertex2f(l, t + w);
 glEnd();

以上绘制就结束了。下面是一份完整的Draw方法代码,可以不引用辅助库Glaux.pas:

procedure TForm1.Draw;
var
 Bmp: TBitmap;
 texture: GLuint;
 l, t, w: Integer;
begin
 Bmp := TBitmap.Create;
 Bmp.LoadFromFile(ExtractFilePath(ParamStr(0)) + '1.bmp');
 // 创建纹理区域
 glGenTextures(1, @texture);
 // 绑定纹理区域
 glBindTexture(GL_TEXTURE_2D, texture);
 // 使用位图创建图像纹理
 glTexImage2D(
  GL_TEXTURE_2D,      // 纹理是一个2D纹理 GL_TEXTURE_2D
  0,            // 图像的详细程度 默认 0
  3,            // 数据的成分数。因为图像是由红,绿,蓝三种组成 默认3
  Bmp.Width,        // 纹理的宽度
  Bmp.Height,        // 纹理的高度
  0,            // 边框的值 默认 0
  GL_BGR_EXT,        // 数据格式 bmp使用 bgr
  GL_UNSIGNED_BYTE,     // 组成图像的数据是无符号字节类型的
  Bmp.ScanLine[Bmp.Height - 1] // DIB数据指针
 );
 // 下面两行是让opengl在放大原始的纹理大(GL_TEXTURE_MAG_FILTER)或缩小原始纹理(GL_TEXTURE_MIN_FILTER)时OpenGL采用的滤波方式。
 // GL_LINEAR 使用线性滤波,可以把图片处理处平滑,但需要更多的内存与CPU
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 // 以下是绘图,利用一个四边形,绘制图片
 // 启用纹理映射
 if glIsEnabled(GL_TEXTURE_2D) = 0 then
  glEnable(GL_TEXTURE_2D);
 // 清空缓冲区
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); 
 l := 10;
 t := 10;
 w := 200; // 放大为200*200的图片
 // 选择纹理 如果场景中使用多个纹理,不能在glBegin() 和 glEnd() 之间绑定纹理
 glBindTexture(GL_TEXTURE_2D, texture);
 glBegin(GL_QUADS);
 glTexCoord2f(0, 1);
 glVertex2f(l, t);
 glTexCoord2f(1, 1);
 glVertex2f(l + w, t);
 glTexCoord2f(1, 0);
 glVertex2f(l + w, t + w);
 glTexCoord2f(0, 0);
 glVertex2f(l, t + w);
 glEnd();
 Bmp.Free;
 SwapBuffers(FDC);
end;

本实例完整代码可点击此处下载。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发
相关文章 更多
精品专题 更多
本月促销

正软商城本月促销专区,汇集办公、设计、安全、影音、系统工具及AI软件等正版软件优惠活动,提供限时折扣、特价授权和优惠购买信息,活动库存及价格以页面实时展示为准。

装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。