Delphi数据库编程教程(六)

原创 2002年12月25日 10:01:00

 第四节  在BLOB中寻找JPEG的开端

      OLE对象类型格式—思路三OLE object type format - take three!)
      现在所有我们需要做的是存储图片到磁盘(存为普通的二进制文件)并了解它里门的内容是什么。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

      所有的图片文件(格式)都有用来唯一的标识图像的文件头。JPG图片文件以所谓的SOI标记开始,该标记的十六进制值是$FFD8。

下面一行代码存储图片字段值到工作目录的相关文件(BlobImage.dat)。在表单的OnCreate事件中放置这条代码,开始工程以后再移除该代码。

      ADOTable1Picture.SaveToFile('BlobImage.dat');

      一旦我们有了这个文件。我们就可以使用Hex editor看它的内容。

Jpeg as OLE object binary file

      你相信吗?MS Access把连接的OLE对象的路径作为对象定义的一部分存储在OLE对象字段中。因为OLE对象的存储定义没有被文档化(!?这直接来自于MS),所以没有办法知道真正的图像数据被写之前能得到什么。

      分两个部分考虑这个问题。第一:我们需要找到'FFD8'并从那儿开始读取图像。第二:'FFD8'不可能总在文件的同一个位置。结论:我们需要一个函数,返回Access数据库中存储为OLE对象的JPG文件的SOI标记的位置。

      正确的方法—思路四(The correct way - take four!)

      提供了Blob类型字段后,我们的函数应返回ADOBlobStream中'FFD8'字符串的位置。ReadBuffer(读缓冲区)从流中一个字节一个字节的读取数据。对ReadBuffer的每个调用都会一个字节一个字节的移动流的位置。当两个字节一起引出SOI标记时,函数返回流的位置。这是这个函数:

   function JpegStartsInBlob(PicField:TBlobField):integer;
   var
    bS     : TADOBlobStream;
    buffer : Word;
    hx     : string;
   begin
    Result := -1;
    bS := TADOBlobStream.Create(PicField, bmRead);
    try
     while (Result = -1) and (bS.Position + 1 < bS.Size) do

     begin
      bS.ReadBuffer(buffer, 1);
      hx:=IntToHex(buffer, 2);
      if hx = 'FF' then begin
       bS.ReadBuffer(buffer, 1);
       hx:=IntToHex(buffer, 2);
      if hx = 'D8' then Result := bS.Position - 2
       else if hx = 'FF' then
             bS.Position := bS.Position-1;
      end; //if
     end; //while
     finally
      bS.Free
     end;  //try
   end;
   一旦我们有了SOI标记的位置,我们就能使用它在ADOBlob流中找到图片的位置。
     uses jpeg;
     ...
     procedure TForm1.btnShowImageClick(Sender: TObject);
     var
      bS  : TADOBlobStream;
      Pic : TJpegImage;
     begin
      bS := TADOBlobStream.Create(AdoTable1Picture, bmRead);
      try
       bS.Seek(JpegStartsInBlob(AdoTable1Picture),soFromBeginning);
       Pic:=TJpegImage.Create;
       try
        Pic.LoadFromStream(bS);
        ADOImage.Picture.Graphic:=Pic;
       finally
        Pic.Free;
       end;
      finally
       bS.Free
      end;
     end;
   运行工程,OK!
   现在谁会说编程没有趣味?

      注:在真正的代码程序中,我们会在TDataSetAfterScroll事件中加入代码用于从当前行中读取和显示图像(它在ADOTable1AfterScroll事件过程中)。当应用程序从一个记录滚到另一个时,AfterScroll事件发生。

    思路五!

    这就是本章的主要内容。现在你可以存储和显示所有你感兴趣的JPG图片。在这篇文章的最后一页,我会提供完整的代码(form1单元);所有的数据安排都放在表单的OnCreate事件中。这确保了所有的三个组件被正确连接—在设计时你不需要使用Object Inspector(对象检视器)。

    我承认,这一章不适合初学者,但世界是残酷的!另一件事:你注意到最后你都不知道怎样改变(或增加一些新的)表中的图片!是的,那又是另一个完整的故事了!

Delphi xe7并行编程快速入门

现在多数设备、计算机都有多个CPU单元,即使是手机也是多核的。但要在开发中使用多核的优势,却需要一些技巧,花费时间编写额外的代码。好了,现在可以使用Delphi做并行编程了。在Delphi、C++ B...
  • henreash
  • henreash
  • 2014年11月20日 16:19
  • 6856

Winpcap网络编程六之Winpcap学习教程,获取已安装设备的高级信息

上一 我们展示了如何获取适配器的基本信息 (如设备的名称和描述)。 事实上,WinPcap提供了其他更高级的信息。 特别需要指出的是, 由 pcap_findalldevs_ex() 返回的每一个...
  • u010467643
  • u010467643
  • 2014年10月08日 20:28
  • 2844

Delphi使用ADO组件访问ACCESS数据入门例程

在form上添加控件 一.方法一: 1.增加一个ADOConnection控件,点击ConnectionString属性,选Use Connection string 下面的例子中...
  • qq173684423
  • qq173684423
  • 2015年04月09日 13:17
  • 2243

Kinect2和六轴机械臂的实时映射(初步)

本文暂时不贴代码,只是总结一下这两天的思路,做的过程中遇到的问题,尝试的各种方法以及结果。首先说下现阶段想要的一个效果吧:利用Kinect2采集人的骨架参数,实时映射到机械臂的几个自由度让其模仿人右臂...
  • zmdsjtu
  • zmdsjtu
  • 2016年11月17日 16:00
  • 2490

几种编程语言的优缺点

圣经记载:在远古的时候,人类都使用一种语言,全世界的人决定一起造一座通天的塔,就是巴别塔,后来被上帝知道了,上帝就让人们使用不同的语言,这个塔就没能造起来。 巴别塔不建自毁,与其说上帝的分化将人类的语...
  • dbyoung
  • dbyoung
  • 2017年01月22日 09:57
  • 1288

小波变换教程(六)

小波变换网文精粹:小波变换教程(六) 原文:ROBI POLIKAR. THE ENGINEER'S ULTIMATE GUIDE TO WAVELET ANALYSIS:The Wavelet...
  • alihouzi
  • alihouzi
  • 2015年04月22日 09:19
  • 1118

Delphi 多线程编程(1)

本文的内容取自万一博客,并重新加以整理,在此留存仅仅是方便自己学习和查阅。所有代码均亲自测试 delphi7下测试有效。图片均为自己制作。 多线程应该是编程工作者的基础技能, 但这个基础我从来没...
  • lailai186
  • lailai186
  • 2013年04月09日 07:55
  • 2586

FireDAC简易教程

FireDAC简易教程(Delphi)   一、VCL下的FireDAC   1.创建数据库连接: 新建一个VCL Forms Application工程,放置一个TFDConnection控件,设置...
  • ooooh
  • ooooh
  • 2016年01月20日 21:31
  • 5030

Delphi使用线程TThread查询数据库

网上查了很多资料,看了很多关于线程TThread的使用,并动手操作,但均未能达到想要的效果。我所要的效果是,线程执行耗时的操作而不影响主程序,用户使用没有卡顿的感觉。知道是使用线程编程解决,后来经过不...
  • Michael__mai
  • Michael__mai
  • 2015年12月12日 10:27
  • 1889

Delphi ADOQuery连接数据库的查询、插入、删除、修改

//查询记录 procedure TForm1.Button1Click(Sender: TObject); begin ADOQuery.Close; ADOQuery.SQL.Clear; ADO...
  • chinazhd
  • chinazhd
  • 2015年04月14日 21:04
  • 13822
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Delphi数据库编程教程(六)
举报原因:
原因补充:

(最多只允许输入30个字)