大头贴中的这个效果是怎样实现的? (美女哦,非看不可!!!) ( 积分: 100 )

  • 主题发起人 龙飞凤舞316
  • 开始时间
没有那么复杂的,根本不用编程来合成的:
只要在电脑屏幕前放1块三棱镜,把屏幕的背景图像和大头者都折射到摄像头,
再显示到屏幕就行了.
 
xuxiaohan:
这么说我们看到的前景(过渡图片)并不是一个窗口,而只是合成以后图像吗?
你的意思是不是说把视频的每一帧都和风景图片合成,再显示出来,试了试,显示出来的效果有点慢,一秒钟合成不了25帧
 
看起来好难呀!现在 不知道谁实现了吗?
 
在delphi的timage组建中有一个transparent属性,如果把次属性设置为true,
就能实现图象的透明了。
透明图象
代码:
声明变量:
private
{priavate declarations}
foreimage,backimage:timage;
procedure drawtransparentbitmap(dc:hdc;image:timage;xstart,ystart:word);
编辑:
procedure tform1.drawtransparentbitmap(dc:hdc;image:timage;xstart,
ystart,ystart:word);
var
transparentcolor:tcolor;
//透明背景颜色
ccolor:tcolorref;
bmandback,bmandobject,bmandmem,bmsave,bmbackold,bmobjectold,
bmmemold,bmsaveold:hbitmap;
hdcmem,hdcback,hdcobject,hdctemp,hdcsave:hdc;
ptsize:tpoint;
begin
transparentcolor:=image.picture.bitmap.canvas.pixels[0,image.height-1];
transparentcolor:=transpatentcolor or $02000000;
hdctemp:=createcompatibledc(dc);
selectobject(hdctemp,image.picture.bitmap.handle);
//选择一个bitmap位图资源
//把位图的尺寸从设备转换到逻辑点
ptsize.x:=image.width;
ptsize.y:=image.height;
dptolp(hdctemp,ptsize,1);
//创建一些设备上下来存储临时的数据
hdcback:=createcompatibledc(dc);
hdcobject:=createcompatibledc(dc);
hdcmem:=createcompatibledc(dc);
hdcsave:=createcompatibledc(dc);
//为每一个设备上下创建一个位图
bmandback:=createbitmap(ptsize.x,ptsize.y,1,1,nil);
bmandobject:=createbitmap(ptsize.x,ptsize.y,1,1,nil);
bmandmem:=createbitmap(dc,ptsize.x,ptsize.y);
bmsave:=cteatecompatiblebitmap(dc,ptsize.x,ptsize.y);
//每个设备上下必须选择一个位图数据来存储象素数据
bmbackold:=selectobject(hdcback,bmandback);
bmobjectold:=selectobject(hdcobject,bmandobject);
bmmemold:=selectobject(hdcmem,bmandmem);
bmsaveold:=selectobject(hdcsave,bmsave);
//设置适当的匹配模式
setmapmode(hdctemp,getmapmode(dc));
//储存发送的位图,因为他将被覆盖
bitblt(hdcsave,0,0,ptsize.x,ptsize.y,hdctemp,0,0,srccopy);
//设置源设备上下的背景的颜色为位图中包含的应该透明的颜色
ccolor:=setbkcolor(hdctemp,transparentcolor);
//通过从源位图到一个单色位图执行一个bitblt函数,为位图创建一个对象屏蔽
bitblt(hdcobject,0,0,ptsize.x,ptsize.y,hdctemp,0,0,srccopy);
//把源设备上下的背景色设回原来的颜色
setbkcolor(hdctemp,ccolor);
//创建对象屏蔽的反颜色
bitblt(hdcback,0,0,ptsize.x,ptsize.y,hdcobject,0,0,notsrccopy);
//把主设备上下的背景色拷贝到目标设备上下中
bitblt(hdcmem,0,0,ptsize.x,ptsize.y,hdc,xstart,ystart,srccopy);
//屏蔽掉位图要放置的位置
bitblt(hdcmem,0,0,ptsize.x,ptsize.y,hdcback,0,0,srcand);
//屏蔽掉位图中透明颜色的象素
bitblt(hdctemp,0,0,ptsize.x,ptsize.y,hdcback,0,0,srcand);
//用目标设备上下文的背景色或位图
bitblt(hdcmem,0,0,ptsize.x,ptsize.y,hdctemp,0,0,srcpaint);
//把目标拷贝到屏幕上
bitble(dc,xstart,ystart,ptsize.x,ptsize.y,hdcmem,0,0,srccopy);
//把原来的位图放在发送的位图里
bitble(hdctemp,0,0,ptsize.x,ptsize.y,hdcsave,0,0,srccopy);
//删除内存设备上下文
deletedc(hdcmem);
deletedc(hdcback);
deletedc(hdcobjeck);
deletedc(hdcsave);
deletedc(hdctemp);
end;
在form1的oncreate事件中添代码:
procedure tform1.formcreate(sender:tobject);
begin
//为两个位图创建图象控制并设置它们的父对象
foreimage:=timage.create(form1);
backimage:=timage.create(form1);
foreimage.parent:=form1;
backimage.parent:=form1;
//装载图象
foreimage.picture.loadfromfile('d:/program files/图象/1.bmp');
foreimage.picture.loadfromfile('d:/program files/图象/1.bmp');
//设置背景色图象大小为它的位图大小
with backimage do
begin
left:=0;
top:=0;
width:=picture.width;
height:=picture.height;
end;
//把前景色图象放在背景色图象的中间
with foreimage do
begin
left:=(badkimage.picture.width-picture.width)div 2;
top:=(badkimage.picture.height-picture.height)div 2;
width:=pictrer.width;
height:=picture.height;
end;
//不显示透明的位图,而是用函数画出来
drawtransparentbitmap(backimage.picture.bitmap.canvas.handle,
foreimage,foreimage.left,foreimage.top);
end;
双击form的 onclose
procedture tform1.formclose(sender:tobject;var action:tcloseaction);
begin
foreimage.free;
backimage.free;
end;
//createbitmap函数:用指定的宽度,高度,颜色面板,象素位数创建一个位图,
hebitmap createbitmap(
int nwidth, //位图宽度
int nheight,//高度
uint cplanes,//颜色面板
unint cbitsperpel,//象素位数
const void *ipvbits//颜色数组的指针位置
);
函数操作成功返回位图句柄,否则返回0
//createcompatiblebitmap函数:创建一个与指定设备上下文相兼容的位图,
hebitmap createcompatiblebitmap(
hdc hdc,//设备上下文句柄
int nwidth,
int nheitht,
);
返回值与createbitmap函数相同。
//createcompatibledc函数:创建一个与设备相兼容的临时内存设备上下文,
hdc createcompatibledc(
hdc hdc
);
//selectobject(
hdc hdc,
hgdiobj hgdiobj //被选定的对象句柄,而且该对象必须已经被创建
);
被选定的对象句柄,而且该对象必须已经被创建,而且是下列之一:bitmap,brush,font,
pen,tegion.同样也可以使用deleteobject函数将这个指针的对象删除,同时释放与该
设备相关的系统资源。
//setmapmaode函数:设置指定设备句柄的匹配模式,
int setmapmaode(
hdc hdc,
int fnmapmode //新的匹配模式,如nglish,mm_himetric.mm_text等
);
//setbkcolor函数:把当前设备的背景色设定为指定的颜色,如果不适应,将使用最近的颜色值,
colorref setbkcolor(
hdc hdc,
colorref crcolor
);
函数操作成功将返回一个colorref类型的颜色值,否则返回clr_invalid.
 
为什么不用directx3d呢?
 
我也想知道
 
那里有详细实现32位图像合成的原代码(思想原创)
可以配合GraphicEx控件,用GraphicEx控件来打开一个.TGA .PNG .TIF .BMP .PSD
什么的图像


// 这个东东已被我贴到了bbs.cnpack.org里面的Cnpack组里面了
//如有问题請加我QQ:250198418
//我主页:lqcros.go1.wy8.net

32位图像处理库简单实现(原创)
unit Image32;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, ComCtrls, ToolWin, ImgList, Jpeg,Buttons, Math, Trace, mmsystem;

const
PixelCountMax = 32768;


type
TRGBQuad = packed record
rgbBlue: BYTE;
rgbGreen: BYTE;
rgbRed: BYTE;
rgbReserved: BYTE;
end;


PColor32 = ^TColor32;
TColor32 = type Cardinal;

PColor32Array = ^TColor32Array;
TColor32Array = array [0..0] of TColor32;
TArrayOfColor32 = array of TColor32;

pRGBQuadArray = ^TRGBQuadArray;
TRGBQuadArray = array[0..PixelCountMax - 1] of TRGBQuad;

PRGBArray = ^TRGBArray;
{* RGB数组指针}
TRGBArray = array[0..8192] of tagRGBTriple;
{* RGB数组类型}

function RedComponent(Color32: TColor32): Integer;
function GreenComponent(Color32: TColor32): Integer;
function BlueComponent(Color32: TColor32): Integer;
function AlphaComponent(Color32: TColor32): Integer;
function Intensity(Color32: TColor32): Integer;
function RGBA(R, G, B: Byte; A: Byte = $FF): TColor32;
function RGBAToColor32(RGBA: TRGBQuad): TColor32;
function Color32ToRGBA(Color32: TColor32): TRGBQuad;

// 汇编语言实现32位填充
procedure FillLongword(var X; Count: Integer; Value: Longword);

// 一些预先设定32位颜色(格式为ARGB)

const
clBlack32 : TColor32 = $FF000000;
clDimGray32 : TColor32 = $FF3F3F3F;
clGray32 : TColor32 = $FF7F7F7F;
clLightGray32 : TColor32 = $FFBFBFBF;
clWhite32 : TColor32 = $FFFFFFFF;
clMaroon32 : TColor32 = $FF7F0000;
clGreen32 : TColor32 = $FF007F00;
clOlive32 : TColor32 = $FF7F7F00;
clNavy32 : TColor32 = $FF00007F;
clPurple32 : TColor32 = $FF7F007F;
clTeal32 : TColor32 = $FF007F7F;
clRed32 : TColor32 = $FFFF0000;
clLime32 : TColor32 = $FF00FF00;
clYellow32 : TColor32 = $FFFFFF00;
clBlue32 : TColor32 = $FF0000FF;
clFuchsia32 : TColor32 = $FFFF00FF;
clAqua32 : TColor32 = $FF00FFFF;

// 一些半透明32位颜色(格式为ARGB)
clTrWhite32 : TColor32 = $7FFFFFFF;
clTrBlack32 : TColor32 = $7F000000;
clTrRed32 : TColor32 = $7FFF0000;
clTrGreen32 : TColor32 = $7F00FF00;
clTrBlue32 : TColor32 = $7F0000FF;

type
TBitmap32 = class(TBitmap)
private

protected
public
constructor Create; override;
destructor Destroy; override;

procedure Assign(Source: TPersistent); override; //重载,设置为32位
procedure LoadFromFile(const Filename: string); override; //重载,设置为32位

// 这两个函数引用自FLIB库//
// 只处理目标ALPHA通道时,两个函数可以替换到用 //

// 注意这里一下, 替换时请在DrawTo,DrawFrom 里面替换就可以了

// CombinAlphaPixel是以目标及源像素的ALPHA通道合成
procedure CombineAlphaPixel(var pDest: TRGBQuad; cr1: TRGBQuad; nAlpha1: integer; cr2: TRGBQuad; nAlpha2: integer);
// AlphaBlendPixel是以目标的ALPHA通道合成
procedure AlphaBlendPixel(var pDest: TRGBQuad; pSrc: TRGBQuad);


function GetBits: PColor32Array;
procedure SetPixel(x, y: integer; color: TColor32);
function GetPixel(x, y: integer): TColor32;
procedure Clear(color: TColor32);overload;
procedure Clear(Bitmap: TBitmap; color: TColor32);overload;
procedure Clear;overload;
procedure FillRect(X1, Y1, X2, Y2: Integer; Value: TColor32);

procedure SetAlphaChannels(Alpha: BYTE);overload; //设置纯色透明通道
procedure SetAlphaChannels(Bitmap: TBitmap; Alpha: Byte);overload; //设置其他图像纯色透明通道
procedure SetAlphaChannels(Mask8: TBitmap);overload; //把MASK设置为透明通道

procedure DrawFrom(DstX, DstY: Integer; Src: TBitmap32); //把32位图像写到自身
procedure DrawTo(DstX, DstY: Integer; Tge: TBitmap32);overload; //把自身写到32位图像
procedure DrawTo(DstX, DstY: Integer; Tge: TBitmap);overload; //把自身写到图像
end;

implementation

procedure FillLongword(var X; Count: Integer; Value: Longword);
asm
// EAX = X
// EDX = Count
// ECX = Value

PUSH EDI

MOV EDI,EAX // Point EDI to destination
MOV EAX,ECX
MOV ECX,EDX
TEST ECX,ECX
JS @exit

REP STOSD // Fill count dwords
@exit:
POP EDI
end;

function RedComponent(Color32: TColor32): Integer;
begin
Result := (Color32 and $00FF0000) shr 16;
end;

function GreenComponent(Color32: TColor32): Integer;
begin
Result := (Color32 and $0000FF00) shr 8;
end;

function BlueComponent(Color32: TColor32): Integer;
begin
Result := Color32 and $000000FF;
end;

function AlphaComponent(Color32: TColor32): Integer;
begin
Result := Color32 shr 24;
end;

function Intensity(Color32: TColor32): Integer;
begin
// (R * 61 + G * 174 + B * 21) / 256
Result := (
(Color32 and $00FF0000) shr 16 * 61 +
(Color32 and $0000FF00) shr 8 * 174 +
(Color32 and $000000FF) * 21
) shr 8;
end;

function RGBA(R, G, B: Byte; A: Byte = $FF): TColor32;
begin
Result := A shl 24 + R shl 16 + G shl 8 + B;
end;

function RGBAToColor32(RGBA: TRGBQuad): TColor32;
begin
Result := RGBA.rgbReserved shl 24 + RGBA.rgbRed shl 16 + RGBA.rgbGreen shl 8 + RGBA.rgbBlue;
end;

function Color32ToRGBA(Color32: TColor32): TRGBQuad;
var
RGBA: TRGBQuad;
begin
RGBA.rgbRed := RedComponent(Color32);
RGBA.rgbRed := GreenComponent(Color32);
RGBA.rgbRed := BlueComponent(Color32);
RGBA.rgbRed := AlphaComponent(Color32);
Result := RGBA;
end;

constructor TBitmap32.Create;
begin
inherited Create;
PixelFormat := pf32bit;
end;

destructor TBitmap32.Destroy;
begin
inherited Destroy;
end;

procedure TBitmap32.LoadFromFile(const Filename: string);
begin
inherited LoadFromFile(FileName);
PixelFormat := pf32bit;
end;

procedure TBitmap32.Assign(Source: TPersistent);
begin
inherited Assign(Source);
PixelFormat := pf32bit;
end;

function TBitmap32.GetBits: PColor32Array;
begin
Result := ScanLine[Height - 1]; //得到Bitmap32图像的起始地址
end;

procedure TBitmap32.DrawFrom(DstX, DstY: Integer; Src: TBitmap32);
var
x, y: integer;
TR, SR: TRect;
Source, Target: pRGBQuadArray;
begin

TR := Rect(0, 0, Width, Height);
SR := Rect(DstX, DstY, DstX + Src.Width, DstY + Src.Height);

if IntersectRect(TR, TR, SR) = false then
exit;

for y := Tr.Top to Tr.Bottom - 1 do
begin
Source := Src.ScanLine[y - Dsty];
Target := ScanLine[y];
for x := TR.Left to Tr.Right - 1 do
begin
CombineAlphaPixel(Target^[x], Target^[x], Target^[x].rgbReserved, Source^[x - DstX], Source^[x- DstX].rgbReserved);
end;
end;
end;

procedure TBitmap32.DrawTo(DstX, DstY: Integer; Tge: TBitmap32);
var
x, y: integer;
TR, SR: TRect;
Source, Target: pRGBQuadArray;
begin

TR := Rect(0, 0, TGe.Width, Tge.Height);
SR := Rect(DstX, DstY, DstX + Width, DstY + Height);

if IntersectRect(TR, TR, SR) = false then
exit;

for y := Tr.Top to Tr.Bottom - 1 do
begin
Target := Tge.ScanLine[y];
Source := ScanLine[y - Dsty];
for x := TR.Left to Tr.Right - 1 do
begin
CombineAlphaPixel(Target^[x], Target^[x], Target^[x].rgbReserved, Source^[x - DstX], Source^[x- DstX].rgbReserved);
end;
end;

end;

procedure TBitmap32.DrawTo(DstX, DstY: Integer; Tge: TBitmap);
var
x, y: integer;
TR, SR: TRect;
Source, Target: pRGBQuadArray;
begin
Tge.PixelFormat := pf32bit;
SetAlphaChannels(Tge, $FF);

Tr := Rect(0, 0, Tge.Width, Tge.Height);
SR := Rect(DstX, DstY, DstX + Width, DstY + Height);

if IntersectRect(Tr, Tr, SR) = false then
exit;

for y := Tr.Top to Tr.Bottom - 1 do
begin
Target := Tge.ScanLine[y];
Source := ScanLine[y - Dsty];
for x := Tr.Left to Tr.Right - 1 do
begin
CombineAlphaPixel(Target^[x], Target^[x], Target^[x].rgbReserved, Source^[x - DstX], Source^[x- DstX].rgbReserved);
end;
end;

end;


procedure TBitmap32.Clear(color: TColor32);
var
x, y: integer;
begin
FillLongword(GetBits^[0], Width * Height, Color);
end;

procedure TBitmap32.Clear(Bitmap: TBitmap; color: TColor32);
var
bits: PColor32Array;
begin
Bitmap.PixelFormat := pf32bit;
bits := Bitmap.ScanLine[Bitmap.Height - 1];

FillLongword(Bits^[0], Width * Height, Color);
end;


procedure TBitmap32.Clear;
begin
Clear(clBlack32);
end;

procedure TBitmap32.FillRect(X1, Y1, X2, Y2: Integer; Value: TColor32);
var
j: Integer;
P: PColor32Array;
begin
for j := Y1 to Y2 - 1 do
begin
P := Pointer(ScanLine[j]);
FillLongword(P[X1], X2 - X1, Value);
end;
end;

procedure TBitmap32.SetAlphaChannels(Alpha: BYTE);
var
x, y: integer;
SS: pRGBQuadArray;
begin
for y := 0 to Height-1 do
begin
SS := ScanLine[y];
for x := 0 to Width-1 do
begin
SS^[x].rgbReserved := Alpha;
end;
end;
end;

procedure TBitmap32.SetAlphaChannels(Mask8: TBitmap);
var
x, y: integer;
DS: pRGBQuadArray;
SS: pByteArray;
begin
for y := 0 to Height-1 do
begin
DS := ScanLine[y];
SS := Mask8.ScanLine[y];
for x := 0 to Width-1 do
begin
DS^[x].rgbReserved := SS^[x];
end;
end;
end;


procedure TBitmap32.SetAlphaChannels(Bitmap: TBitmap; Alpha: Byte);
var
x, y: integer;
SS: pRGBQuadArray;
begin
for y := 0 to Bitmap.Height-1 do
begin
SS := Bitmap.ScanLine[Bitmap.Height - y -1];
for x := 0 to Bitmap.Width-1 do
begin
SS^[x].rgbReserved := Alpha;
end;
end;
end;

procedure TBitmap32.SetPixel(x, y: integer; color: TColor32);
begin
if (X >= 0) and (X < Width) and (Y >= 0) and (Y < Height) then
GetBits^[x + (Height - y -1) * Width] := color;
end;

function TBitmap32.GetPixel(x, y: integer): TColor32;
begin
Result := $00000000;
if (X >= 0) and (X < Width) and (Y >= 0) and (Y < Height) then
Result := GetBits^[x + (Height - y -1) * Width];
end;

procedure TBitmap32.AlphaBlendPixel(var pDest: TRGBQuad; pSrc: TRGBQuad);
begin
if (pSrc.rgbReserved = $FF) then
begin
PRGBArray(pDest) := PRGBArray(pSrc);
exit;
end;

if (pSrc.rgbReserved = 0) then
exit;
// 以下用不着判断[0,0xFF],我验算过了

if (PRGBArray(pSrc) <> PRGBArray(pDest)) then
begin
pDest.rgbBlue := (PSrc.rgbBlue - pDest.rgbBlue) * pSrc.rgbReserved div $FF + pDest.rgbBlue;
pDest.rgbGreen := (PSrc.rgbGreen - pDest.rgbGreen) * pSrc.rgbReserved div $FF + pDest.rgbGreen;
pDest.rgbRed := (PSrc.rgbRed - pDest.rgbRed) * pSrc.rgbReserved div $FF + pDest.rgbRed;
end;
end

//===================================================================
// 计算两个32bit象素的等效象素,这个函数非常重要(speed),安全检查就不做了
// cr1:背景 cr2:前景

procedure TBitmap32.CombineAlphaPixel(var pDest: TRGBQuad; cr1: TRGBQuad; nAlpha1: integer; cr2: TRGBQuad; nAlpha2: integer);
var
nTmp1, nTmp12, nTemp, nTmp2: integer;
begin
if ((nAlpha1 <> 0) or (nAlpha2 <> 0)) then
begin
if (nAlpha2 = 0) then
begin
pDest.rgbBlue := cr1.rgbBlue ;
pDest.rgbGreen := cr1.rgbGreen ;
pDest.rgbRed := cr1.rgbRed ;
pDest.rgbReserved := nAlpha1 ;
exit;
end;
if ((nAlpha1 = 0) or (nAlpha2 = $FF)) then
begin
pDest.rgbBlue := cr2.rgbBlue ;
pDest.rgbGreen := cr2.rgbGreen ;
pDest.rgbRed := cr2.rgbRed ;
pDest.rgbReserved := nAlpha2 ;
exit;
end;

// 以下用不着判断[0,0xFF],我验算过了
nTmp1 := $FF * nAlpha1;
nTmp2 := $FF * nAlpha2 ;
nTmp12 := nAlpha1 * nAlpha2;
nTemp := nTmp1 + nTmp2 - nTmp12 ;
pDest.rgbBlue := (nTmp2 * cr2.rgbBlue + (nTmp1 - nTmp12) * cr1.rgbBlue) div nTemp ;
pDest.rgbGreen := (nTmp2 * cr2.rgbGreen + (nTmp1 - nTmp12) * cr1.rgbGreen) div nTemp ;
pDest.rgbRed := (nTmp2 * cr2.rgbRed + (nTmp1 - nTmp12) * cr1.rgbRed) div nTemp ;
pDest.rgbReserved := nTemp div $FF ;

// 下面的代码是未优化过的,可读性更好些
{
nTemp := $FF * (nAlpha1 + nAlpha2) - nAlpha1*nAlpha2 ;
pDest.rgbBlue := min($FF, ($FF * cr2.rgbBlue * nAlpha2 + ($FF - nAlpha2) * cr1.rgbBlue * nAlpha1) div nTemp) ;
pDest.rgbGreen := min($FF, ($FF * cr2.rgbGreen * nAlpha2 + ($FF - nAlpha2) * cr1.rgbGreen * nAlpha1) div nTemp) ;
pDest.rgbRed := min($FF, ($FF * cr2.rgbRed * nAlpha2 + ($FF - nAlpha2) * cr1.rgbRed * nAlpha1) div nTemp) ;
pDest.rgbReserved := nTemp div $FF ;
}
end
else
begin
pDest.rgbBlue := $FF;
pDest.rgbGreen := $FF;
pDest.rgbRed := $FF;
pDest.rgbReserved := 0 ;
end;
end;


end.


代码说明
TBitmap可以设置 [pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, pfCustom]9种格式,这里为了处理32位图像只用了pf32Bit。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
919
DelphiTeacher的专栏
D
I
回复
0
查看
686
import
I
I
回复
0
查看
535
import
I
顶部