2024年5月11日发(作者:)

VFP下图形相关GetPicVal FuncTion

VFP9版本为IMAGE控件加入了PictureVal属性以方便用户通过数据流来加载

图像,在VFP9HELP中具体描述为:

使用一个字符串或对象为图像控件指定一个图像声明描述。

PROCEDURE eVal [= eExpression]

属性值

eExpression

指定一个描述了图像的字符串或对象。如果 eExpression 时一个字符串表达式,

它必须是一个有效的表达式,GDI+ 可使用它来绘制一个图像。例如,它可以是

一个像下列示例中的表达式。

复制代码

cPict = FILETOSTR('')

eVal = cPict

eExpression 也可以是一个指向包含精确二进制数据的备注或 Blob 字段类型

的字符串表达式。例如,你可以使用 APPEND MEMO 命令 将一个图像导入到

一个备注字段。eExpression 不能使用通用型字段,因为通用型字段存储了与二

进制数据内容无关的其它数据。如果 eExpression 是一个对象,该对象使用的

必须是 IPicture 接口格式。IPicture 接口格式与 LOADPICTURE( ) 函数 函数

返回的格式相同。

复制代码

oPict = LOADPICTURE(“”)

eVal = oPict

说明

应用到:Image 控件 (Visual FoxPro)

如果同时指定了两种属性,PictureVal 属性优先于 Picture 属性 (Visual

FoxPro)。

注意:当使用一个存储在备注或 Blob 类型字段中的图像时,Visual FoxPro 仅

使用绘制一个图像所需的存储器。这是在 Visual FoxPro 中显示图像时有效使

用存储器的习惯。可是,使用 PictureVal 属性中的文件引用要求 Visual FoxPro

使用两倍于文件尺寸的存储器。例如,如果你引用了一个 5 MB 的图像文件,

Visual FoxPro 需要约 10MB 的存储量来显示这个文件。

你不能为 PictureVal 属性指定一个掩码(MSK)文件。如果你使用了 BMP 图像

并需要一个掩码,则你应该改用 Picture 属性。也可以使用其它格式的图像,

如一个 GIF,它在内部定义了透明属性。

从上述说明我们可以看出,这个PictureVal属性实际上是按照GDI+的

GdipCreateBitmapFromStream的函数来设计的,如果你加载的是一个位图文

件,那么直接

cPict = FILETOSTR('')

eVal = cPict

就可以了,但如果要加载的不是一个位图文件,如JPG、PNG、GIF等格式文

件,那么直接采用上述方法是不行的,归根结底是因为

GdipCreateBitmapFromStream只支持位图数据流所造成的,那该怎么办呢?好

办,我们只需要用GDI+的GdipSaveImageToStream给

它创建一个数据流即可,Let's Go!

DECLARE INTEGER GdipSaveImageToStream IN Long

nImage, Integer stream, String clsidEncoder, Long encoderParams

DECLARE INTEGER GdipCreateBitmapFromScan0 IN ;

INTEGER nWidth, INTEGER nHeight, INTEGER nStride,;

INTEGER nPixelFormat,;

STRING @cScan0, INTEGER @ nImage

DECLARE INTEGER GdipGetImageHeight IN gdiplus;

INTEGER img,;

INTEGER @imgheight

DECLARE INTEGER GdipGetImageWidth IN gdiplus;

INTEGER img,INTEGER @ imgwidth

DECLARE INTEGER GdipDrawImageRect IN ;

INTEGER nGraphics, INTEGER nImage,

SINGLE,SINGLE,SINGLE,SINGLE

DECLARE INTEGER GdipGetImageGraphicsContext IN ;

INTEGER nImage, INTEGER @ nGraphics

DECLARE INTEGER GdipLoadImageFromFile IN ;

STRING wFilename, INTEGER @nImage

DECLARE INTEGER GdipDeleteGraphics IN ;

INTEGER graphics

DECLARE Long GdipDisposeImage IN Long image

DECLARE Long CreateStreamOnHGlobal IN ole32 Long hGlobal, Long

fDeleteOnRelease, Long @ppstm&&创建字符流指针

DECLARE integer GetProcessHeap IN WIN32API

DECLARE integer HeapAlloc IN WIN32API Long,Long,Long

DECLARE integer HeapFree IN WIN32API integer,integer,integer

DECLARE ReleaseStgMedium IN ole32 String pmedium

clsidEncoder=0h00F47C55041AD3119A730000F81EF32E &&BMP

PIXELFORMAT_32bppARGB=0x0026200A

FUNCTION GetPicVal(Picfile as String)

STORE 0 TO nimage,lnHeight,lnWidth,NewBitmap,nGraphics,lHStream

GdipLoadImageFromFile(STRCONV(Picfile+CHR(0),5),@nimage)

GdipGetImageHeight(nimage,@lnHeight)&&获取图像高度

GdipGetImageWidth(nimage,@lnWidth)&&获取图像宽度

GdipCreateBitmapFromScan0(lnWidth,lnHeight,0,PIXELFORMAT_32bppAR

GB,0,@NewBitmap)&&这里之所以建立一个32位的位图主要目的是去除位图

数据需要补齐的麻烦

GdipGetImageGraphicsContext(NewBitmap,@nGraphics)

GdipDrawImageRect(nGraphics,nImage,0,0,lnWidth,lnHeight)

GdipDisposeImage(nImage)&&此时nImage已没用,销毁

StreamSize=lnHeight*lnWidth*4+54&&图像数据大小

hProcHeap=GetProcessHeap()&&申请内存

lhMemPtr=HeapAlloc(hProcHeap,0,StreamSize) &&申请内存

CreateStreamOnHGlobal(lhMemPtr,1,@lHStream)&&&&创建字符流指针

GdipSaveImageToStream(NewBitmap,lHStream,@clsidEncoder,0)

RETURN SYS(2600,lhMemPtr,StreamSize)&&返回内存中的数据流

*HeapFree(hProcHeap,0,lhMemPtr)

*ReleaseStgMedium(0h04000000+BINTOC(lHStream, "4rs")+0h00000000)

*GdipDisposeImage(NewBitmap)

*GdipDeleteGraphics(nGraphics)

ENDFUNC

实际上GdipSaveImageToStream是在内存中直接生成了一个标准的位图格式

数据流,这个也为由时候需要直接在内存中处理图形文件创造了便利,

当然我们不用GdipSaveImageToStream函数来创建的话也可以用GetDIBits来

获取内存中的数据:

DECLARE INTEGER GdipCreateBitmapFromFile IN ;

STRING wFilename,;

INTEGER @nBitmap

DECLARE Long GdipCreateHBITMAPFromBitmap IN Long

nativeImage, Long @hbmReturn,Long Argb

DECLARE INTEGER GdipGetImageHeight IN gdiplus;

INTEGER img,;

INTEGER @ imgheight

DECLARE INTEGER GdipGetImageWidth IN gdiplus;

INTEGER img,INTEGER @ imgwidth

DECLARE Long GdipGetImagePixelFormat IN Long nImage,

Long @PixelFormat

DECLARE Long GlobalAlloc IN WIN32API Long nFlags, Long nSize

DECLARE Long RtlZeroMemory IN WIN32API AS ZeroMemory Integer dest,

Integer numBytes

DECLARE Long GetWindowDC IN WIN32API Long hwnd

DECLARE Integer CreateCompatibleDC IN WIN32API Integer hDC

DECLARE Long GetDIBits IN WIN32API Integer hdc,Integer hbmp,Integer

uStartScan,Integer cScanLines,Integer lpvBits,String @lpbi,Integer uUsage

DECLARE Long GlobalFree IN WIN32API Long nHandle

DECLARE Long DeleteDC IN WIN32API Long hdc

DECLARE Integer DeleteObject IN WIN32API Integer hObject

DECLARE Long ReleaseDC IN WIN32API Long hWnd, Long hDC

#DEFINE RGBQUAD_SIZE 4

#DEFINE DIB_RGB_COLORS 0

#DEFINE BFHDR_SIZE 14

#DEFINE BHDR_SIZE 40

#DEFINE GMEM_FIXED 0

#DEFINE BI_RGB 0

#DEFINE ARGB_LightGray 0

LOCAL lhBitmap,lnWidth,lnHeight, lnBitsPerPixel,hBmp,tiPixFmt

STORE 0 TO lhBitmap,lnWidth,lnHeight, lnBitsPerPixel,hBmp,tiPixFmt

PicFile=''&&欲加载的图形文件

GdipCreateBitmapFromFile(STRCONV(PicFile+CHR(0),5),@hBmp)&&加载图

GdipGetImageHeight(hBmp,@lnHeight)&&获取图像高度

GdipGetImageWidth(hBmp,@lnWidth)&&获取图像宽度

GdipCreateHBITMAPFromBitmap(hBmp,@lhBitmap,ARGB_LightGray)

GdipGetImagePixelFormat(hBmp,@tiPixFmt)

lnBitsPerPixel =BITAND(BITRSHIFT(tiPixFmt,8),0xff)

LOCAL lnBytesPerScan, lnBitsSize, lnRgbQuadSize

STORE 0 TO lnBytesPerScan, lnBitsSize, lnRgbQuadSize

lnBytesPerScan = INT((h * PerPixel)/8)

IF MOD(lnBytesPerScan, 4) # 0

lnBytesPerScan = lnBytesPerScan+4-MOD(lnBytesPerScan,4)

ENDIF

LOCAL lcBIHdr, lcRgbQuad, lcBInfo

LOCAL lpBitsArray

lcBIHdr = BINTOC(BHDR_SIZE ,"4RS")+BINTOC(lnWidth,"4RS") +

BINTOC(lnHeight,"4RS")+;

(CHR(MOD(1,256))+CHR(INT(1/256)))+(CHR(MOD(lnBitsPerPixel,256))+CH

R(INT(lnBitsPerPixel/256)))+;

BINTOC(BI_RGB,"4RS") + REPLI(0h00, 20)

IF lnBitsPerPixel<= 8

lnRgbQuadSize = (2^PerPixel)*RGBQUAD_SIZE

lcRgbQuad = REPLI(CHR(0),lnRgbQuadSize)

ELSE

lcRgbQuad=""

ENDIF

lcBInfo= lcBIHdr+lcRgbQuad

lnBitsSize = lnHeight * lnBytesPerScan

lpBitsArray = GlobalAlloc (GMEM_FIXED, lnBitsSize)

ZeroMemory (lpBitsArray, lnBitsSize)

LOCAL hdc, hMemDC, lnFileSize, lnOffBits, eHdr

lhDC = GetWindowDC(_)

lhMemDC = CreateCompatibleDC (lhDC)

ReleaseDC(_, lhDC)

GetDIBits(lhMemDC,lhBitmap,0,lnHeight,lpBitsArray,@lcBInfo,DIB_RGB_CO

LORS)

lnFileSize = BFHDR_SIZE + BHDR_SIZE + lnRgbQuadSize + lnBitsSize

lnOffBits = BFHDR_SIZE + BHDR_SIZE + lnRgbQuadSize

lcBFileHdr = "BM" + BINTOC(Size, "4RS") + BINTOC(0, "4RS") +

BINTOC(its, "4RS")

LOCAL lqBinary

lqBinary = lcBFileHdr+lcBInfo+SYS(2600,lpBitsArray,lnBitsSize)&&取得图像内

存数据

GlobalFree(Array)

DeleteDC(lhMemDC)

DeleteObject(lhBitmap)

**eVal = lqBinary

但从测试的效果来看GdipSaveImageToStream比GetDIBits的获取速度会更

快,为什么呢?

因为GdipSaveImageToStream也是用GetDIBits来获取的,同样的代码VFP

编译运行和C编译运行比差距还是挺大滴,呵呵!