一、前言

找了不少资料,要画图片要先处理一下,需要引用别的单元,Delphi中没带,需要另外下载Gl.pas。看网上说是自带的OpenGl单元封装的是1.0版的,有此函数未声明。网上可以找到Gl.pas单元。另外需要一个Glaux.pas单元与glaux.dll,据说是辅助库。在本文最后会提供下载。感谢所有作者提供的资料。

二、流程

  绘画图片需要以下几个流程。Window本身的绘图是以位图为基础的,png,jpg等,绘画时,可以转为bmp再画。

  1.加载bmp图片:auxDIBImageLoadA或其他函数

  2.转换为纹理:glGenTextures -> glBindTexture -> glTexImage2D, glTexParameteri用于设置相关参数

  3.绘制纹理:glBindTexture -> glBegin(GL_QUADS) -> glTexCoord2f -> glVertex2f -> glEnd

三、利用glDrawPixels函数绘图

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

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

三、使用纹理绘图

我想按制图片的显示位置与放大缩小,怎么办?可以用以下方法。

1.按流程,我们先把图片加载到程序里,获取相关的图片信息。

将图片加载到纹理中,有几种方法,网上有人写了,建议参考学习:http://www.cnblogs.com/IamEasy_Man/archive/2009/12/14/1624062.html

在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()) + '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()) + '1.bmp');
// do something // 用完释放
Bmp.Free;
end;

2.创建纹理,其中的glGenTextures与glBindTexture,在Gl.pas中。

  // 创建纹理区域
glGenTextures(, @texture);
// 绑定纹理区域
glBindTexture(GL_TEXTURE_2D, texture);
// 使用位图创建图像纹理
glTexImage2D(
GL_TEXTURE_2D, // 纹理是一个2D纹理 GL_TEXTURE_2D
, // 图像的详细程度 默认
, // 数据的成分数。因为图像是由红,绿,蓝三种组成 默认3
Bmp.Width, // 纹理的宽度
Bmp.Height, // 纹理的高度
, // 边框的值 默认
GL_BGR_EXT, // 数据格式 bmp使用 bgr
GL_UNSIGNED_BYTE, // 组成图像的数据是无符号字节类型的
Bmp.ScanLine[Bmp.Height - ] // 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) = then
glEnable(GL_TEXTURE_2D);
// 清空缓冲区
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); l := ;
t := ;
w := ; // 放大为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(, );
glVertex2f(l, t);
glTexCoord2f(, );
glVertex2f(l + w, t);
glTexCoord2f(, );
glVertex2f(l + w, t + w);
glTexCoord2f(, );
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()) + '1.bmp');
// 创建纹理区域
glGenTextures(, @texture);
// 绑定纹理区域
glBindTexture(GL_TEXTURE_2D, texture);
// 使用位图创建图像纹理
glTexImage2D(
GL_TEXTURE_2D, // 纹理是一个2D纹理 GL_TEXTURE_2D
, // 图像的详细程度 默认
, // 数据的成分数。因为图像是由红,绿,蓝三种组成 默认3
Bmp.Width, // 纹理的宽度
Bmp.Height, // 纹理的高度
, // 边框的值 默认
GL_BGR_EXT, // 数据格式 bmp使用 bgr
GL_UNSIGNED_BYTE, // 组成图像的数据是无符号字节类型的
Bmp.ScanLine[Bmp.Height - ] // 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) = then
glEnable(GL_TEXTURE_2D);
// 清空缓冲区
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); l := ;
t := ;
w := ; // 放大为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(, );
glVertex2f(l, t);
glTexCoord2f(, );
glVertex2f(l + w, t);
glTexCoord2f(, );
glVertex2f(l + w, t + w);
glTexCoord2f(, );
glVertex2f(l, t + w);
glEnd(); Bmp.Free;
SwapBuffers(FDC);
end;

效果如下:

源码下载:OpenGL_05.zip,包含Gl.pas与Glaux.pas

2014-07-10

Delphi下OpenGL2d绘图(05)-画图片Bmp的更多相关文章

  1. Delphi下OpenGL2d绘图(04)-画四边形

    一.前言 画四边形基本上与前几遍文字代码是相同.区别在于glBegin()的参数“GL_QUADS”.绘制的框架代码可以使用 Delphi下OpenGL2d绘图(01)-初始化 中的代码.修改的部份为 ...

  2. Delphi下OpenGL2d绘图(03)-画线

    一.前言 画线与画点基本上代码是相同.区别在于glBegin()的参数.绘制的框架代码可以使用 Delphi下OpenGL2d绘图(01)-初始化 中的代码.修改的部份为 Draw 函数的内容. 二. ...

  3. Delphi下OpenGL2d绘图(02)-画点

    一.前言 图形的绘制可以使用glBegin().glEnd()之间完成,绘制的框架代码可以使用 Delphi下OpenGL2d绘图(01)-初始化 中的代码.修改的部份为 Draw 函数的内容. 二. ...

  4. Delphi下OpenGL2d绘图(06)-画图(多窗口、多视图、多个DC)

    一.前言 在学习OpenGL的过程中,发现很多函数都是全局的.前面几章中都是在一个窗口DC中画图,那么要在多个窗口画图,需要怎么处理呢?网上方法有多种,这里采用其中一种,利用wglMakeCurren ...

  5. Delphi下OpenGL2d绘图(01)-初始化

    一.前言: Delphi默认支持OpenGl,可以uses OpenGL单元进行引用,便可以使用OpenGL的函数.OpenGl是跨平台的,而且Windows很早就支持并集成在系统中,存在于syste ...

  6. DELPHI下API简述(1800个API)

    DELPHI下API简述 http://zero.cnbct.org/show.asp?id=144 auxGetDevCaps API 获取附属设备容量 auxGetNumDevs API 返回附属 ...

  7. 深入Delphi下的DLL编程

    深入Delphi下的DLL编程 作者:岑心 引 言 相信有些计算机知识的朋友都应该听说过“DLL”.尤其是那些使用过windows操作系统的人,都应该有过多次重装系统的“悲惨”经历——无论再怎样小心, ...

  8. Delphi下使用Oracle Access控件组下TOraSession控件链接

    Delphi下使用Oracle Access控件组下TOraSession控件链接数据库,使用  orsn1.Options.Direct:=true;  orsn1.Server:=IP:Port: ...

  9. DELPHI下的SOCK编程(转)

    DELPHI下的SOCK编程      本文是写给公司新来的程序员的,算是一点培训的教材.本文不会涉及太多的编程细节,只是简单讲解在DELPHI下进行Winsock编程最好了解的知识. 题外话:我认为 ...

随机推荐

  1. asp.net 错误页面自定义

    在我们上网浏览信息的时候,总会有出现404页面的时候,在我们开发的时候也可以自定义这些页面.刚回这次项目中也使用到了,就在网上找到一些方法,今天就把这些方法重新写一遍加深记忆. 在项目的web.con ...

  2. eFrameWork学习笔记-eList

    HTML: <div style="margin:8px;"> <h1>.不分页</h1> <asp:Repeater id=" ...

  3. 使用echarts绘制漂亮的渐变键盘仪表盘

    echarts官方示例和默认样式都比较难看,经过一顿捣鼓实现比较漂亮的渐变仪表盘. 第一步:设置轴线 将图表轴线.label.分割线.隐藏,只保留刻度,然后修改刻度样式达到最终效果.不过要注意的是ax ...

  4. Sublime写作

    下载 Sublime Text 快捷键(MAC环境) sublime text 批量删除空白行 Sublime text3!行首,行尾,批量编辑!

  5. 【OCP-12c】CUUG 071题库考试原题及答案解析(13)

    13.(6-7) choose twoWhich two statements are true regarding operators used with subqueries? (Choose t ...

  6. pymongo 学习

    查看一条记录,返回一条 dict 记录 db.Account.find_one({"UserName":"keyword"}) 查看某一列的一条记录(此时的1, ...

  7. kali linux之steghide

    Steghide  Linux 命令行隐写工具 Steghide是一款开源的隐写术软件,它可以让你在一张图片或者音频文件中隐藏你的秘密信息,而且你不会注意到图片或音频文件发生了任何的改变.而且,你的秘 ...

  8. 高性能缓存服务器Varnish

    一.Varnish概述 Varnish是一款高性能的.开源的反向代理服务器和缓存服务器,计算机系统的除了有内存外,还有CPU的L1.L2,甚至L3级别的缓存,Varnish的设计架构就是利用操作系统的 ...

  9. 工具IDEA 配置springboot+maven项目

    工具IDEA 配置springboot+maven项目 首先安装IDEA,至于怎么安装就不介绍了.. 第一步 配置maven环境 首先安装maven,先在网上下载一个maven包.在IDEA的sett ...

  10. 浅谈Android选项卡(三)

    上一节介绍了TabActivity的简单用法,但是现在的Api中已经不建议使用了,建议使用Fragment来替代以上的功能,下面介绍下使用Fragment和ViewPager的结合使用. http:/ ...