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

一、前言:

对于Delphi来说,要画图片要先处理一下,需要引用别的单元,而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(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.按流程,我们先把图片加载到程序里,获取相关的图片信息

将图片加载到纹理中,可参考本站:http://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.创建纹理,其中的glGenTextures与glBindTexture,在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 的第一个参数是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();
 Bmp.Free;
 SwapBuffers(FDC);
end;

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

(0)

相关推荐

  • Delphi2007编译的程序在Win7下图标模糊的解决办法

    使用Delphi2007编译GUI程序的时候会发现在Win7的状态栏中显示的程序图标非常模糊,如果原始的图标清晰度怎么样.造成这样结果的原因是因为Delphi2007生成的icon图标只符合XP等系统的要求,没有对Win7进行优化处理.网上有很多处理的方式,后来找到一个最简单有效的方法,就是只设置项目的图标而不要设置Form窗口的图标. 参考资料: Blurred Delphi Form Icon in Windows 7 Taskbar Delphi form icons are blurry

  • delphi实现保存和读取图片的方法

    本文实例讲述了delphi实现保存和读取图片的方法,是非常实用的技巧.分享给大家供大家参考.具体实现方法如下: 首先引用jpeg 1.显示图片: if OpenPictureDialog.Execute then begin img1.Picture.LoadFromFile(OpenPictureDialog.FileName); btnPicture.Text:=OpenPictureDialog.FileName; end; 2.保存图片: var Stream:TMemoryStream

  • Delphi实现图像文本旋转特效完整实例代码

    本文以实例讲述了Delphi实现图像文本旋转特效的解决方法,在本程序中利用的控件主要是Panel 控件.Image 控件.Edit 控件.Label 控件和Button 控件.本程序的关键是利用Delphi 的bmp_rotate()函数来实现旋转图像的功能.并巧妙地调用相关Windows API 函数来实现对文本的旋转特效. 完整的实例代码如下: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics,

  • Delphi基本图像处理方法汇总

    本文实例汇总了Delphi基本图像处理方法.分享给大家供大家参考.具体分析如下: //浮雕 procedure Emboss(SrcBmp,DestBmp:TBitmap;AzimuthChange:integer);overload; var i, j, Gray, Azimuthvalue, R, G, B: integer; SrcRGB, SrcRGB1, SrcRGB2, DestRGB: pRGBTriple; begin for i := 0 to SrcBmp.Height -

  • 在Delphi实现在数据库中存取图像的图文演示无错

    本实例演示如何在数据库中存取图像文件. 向窗体上添加一个TListBox组件.一个TImage组件和一个TTable组件,设计完成的主界面如图1所示. 图1 主界面 本系统中需要设计一个新的基于Paradox 7的数据库Image.db,图2为设计完成的Image.db数据库. 图2 设计完成的数据库 为了方便测试程序,Image.db数据库存储在实例程序所在的路径下. 设置TTable组件的TableName属性为Image.db,Active属性为True. 在程序运行初期,首先会判断Ima

  • delphi实现将BMP格式图形转化为JPG格式图形的方法

    本文实例讲述了delphi实现将BMP格式图形转化为JPG格式图形的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: procedure ConvertBMPtoJPG(SFileName,DFileName:string); Var   J:TJpegImage;   I:TBitmap;   S,D:String; begin   s:=SFileName;   d:=DFileName;   J:=TJpegImage.Create;   I:=TBitmap.Crea

  • Delphi实现图片滚动切换的完整实例代码

    本文以实例介绍了Delphi实现图片滚动切换的方法.该程序可以实现图像的滚动播出,并且通过本代码可控制窗口中的图像向上滚动,通过调节速度滚动条的值还可以调整滚动的速度:点击"停止"按钮,图像即停止滚动. 完整的功能代码如下: unit Unit1; interface uses Windows, Classes, Graphics, Forms, Controls, Menus, Dialogs, StdCtrls, ExtCtrls, SysUtils, ComCtrls, Butt

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

    一.前言: 对于Delphi来说,要画图片要先处理一下,需要引用别的单元,而Delphi中没带,需要另外下载Gl.pas.网上常见自带的OpenGl单元封装的是1.0版的,有此函数未声明.网上可以找到Gl.pas单元.另外需要一个Glaux.pas单元与glaux.dll,是辅助库.在本文最后会提供下载. 二.实现流程: 绘画图片需要以下几个流程.Window本身的绘图是以位图为基础的,png,jpg等,绘画时,可以转为bmp再画. 1.加载bmp图片:使用auxDIBImageLoadA或其他

  • Delphi下OpenGL2d绘图之画点的方法

    一.前言 Delphi图形的绘制可以在glBegin().glEnd()之间完成,绘制的框架代码可以使用Delphi下OpenGL2d绘图的初始化代码,具体内容可参考本站http://www.jb51.net/article/52141.htm.修改的部份为 Draw 函数的内容. 二.画点 使用glPointSize 函数指定栅格化点的直径.默认为1.0,只在GL_POINTS下起作用,关于消锯齿等功能以后再研究.使用glBegin(GL_POINTS)告诉OpenGL画点,参数GL_POIN

  • Delphi下OpenGL2d绘图之画四边形的方法

    一.前言: Delphi实现画四边形的方法基本上与前几遍文字代码是相同的.其区别知识在于glBegin()的参数"GL_QUADS".绘制的框架代码可以使用Delphi下OpenGL2d绘图初始化中的代码,地址为http://www.jb51.net/article/52141.htm.修改的部份为 Draw 函数的内容. 二.画四边形方法: 使用GL_QUADS:绘制由四个顶点组成的一组单独的四边形.顶点4n-3.4n-2.4n-1和4n定义了第n个四边形.总共绘制N/4个四边形.这

  • Delphi下OpenGL2d绘图之画线的方法

    一.前言: Delphi画线方法与画点基本上是相同的.区别在于glBegin()的参数.绘制的框架代码可以参考Delphi下OpenGL2d绘图初始化中的代码,地址为http://www.jb51.net/article/52141.htm.修改的部份为 Draw 函数的内容. 二.画线步骤: GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n条线段,总共绘制N/2条线段 GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个

  • Delphi下OpenGL2d绘图之初始化流程详解

    一.前言: Delphi默认支持OpenGl,可以使用uses OpenGL单元进行引用,之后就可以使用OpenGL的函数.OpenGl是跨平台的,而且Windows很早就支持并集成在系统中,存在于system32中的opengl32.dll,不需要再额外进行安装.虽然windows本身有d3d,但是其能力有限,相关学习资料页相对较少. 通常OpenGL仅仅支持以下几种基本几何图形:点,线和多边形.没有表面或者更高级的图形(比如球状图形)能被作为基本图形元素绘制.但是它们能够用多边形来完美的模仿

  • 对pandas的dataframe绘图并保存的实现方法

    对dataframe绘图并保存: ax = df.plot() fig = ax.get_figure() fig.savefig('fig.png') 可以制定列,对该列各取值作统计: label_dis = df.label.value_counts() ax = label_dis.plot(title='label distribution', kind='bar', figsize=(18, 12)) fig = ax.get_figure() fig.savefig('label_d

  • Android编程绘图操作之弧形绘制方法示例

    本文实例讲述了Android编程绘图操作之弧形绘制方法.分享给大家供大家参考,具体如下: /** * 绘制弧形图案 * @description: * @author ldm * @date 2016-4-25 下午4:37:01 */ public class ArcsActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedIns

  • Delphi在Android下使用Java库的方法

    本文将以Android的USB串口通讯库为例,介绍Delphi如何在Android中使用Java的库. USB串口通讯库地址: https://github.com/felHR85/UsbSerial 一.Java库编译 1.安装Android Studio 2.在Android Studio中将SDK路径指向Delphi的SDK路径(避免重复安装SDK) 3.下载UsbSerial,用Android Studio打开, 3.1Android Studio设置(File->Settings) g

  • Delphi实现获取句柄并发送消息的方法

    本文以实例形式详细说明了Delphi获取句柄并发送消息的方法,具体用法说明如下: 查找另外一个窗口的句柄: handle := FindWindow(nil,PChar('窗口的标题'));//查到窗体句柄 查找子窗体: childHandle := FindWindowEx(handle,0,'子窗体类','子窗体标题'); 另外有个枚举子窗体的API, EnumChildWindows(主创体句柄,@回调函数,用户参数); 用这个函数需要自己写一个回调的函数,比如: function Enu

  • Delphi控件ListView的属性及使用方法详解

    Delphi的ListView组件位于组件板的Win32页,可使用4种图形方式(大图标.小图标.列表.详细列表)来描述选项内容,类似于Windows操作系统中的"我的电脑",数据项图形保存在ImageList组件中. 1.ListView主要属性 (1)ViewStyle属性 ViewStyle属性用于选择数据项的4种显示方式,因此该属性有4个选项值:vsIcon大图标.vsSmallIcon小图标.vsList列表.vsReport详细列表. (2)Items属性 Items属性用于

随机推荐