32位图像处理简易方法 ( 积分: 200 )

  • 主题发起人 主题发起人 lqcros
  • 开始时间 开始时间
L

lqcros

Unregistered / Unconfirmed
GUEST, unregistred user!
急呀,我要处理32位图像呀
 
急呀,我要处理32位图像呀
 
// 这个东东已被我贴到了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。
 
上面这个类可以配合GraphicEx控件(可以打开许多种图像)使用。
 
具体的现实的意义是什么呢?
 
具体现实的意义就是
如果你在用Delphi 做图像处理软件,就可以用这个库,
这个库实现了最基本的图像的处理方法
如:
实现图像处理的32位图层(随手写的)
type
TLayerList = class(TList)
private

end;

Bitmap32 : TBitmap32;
LayerList := TLayerList.Create;

Bitmap32 := TBitmap32.Create;
Bitmap32.LoadFromFile('1.tga');
LayerList.Items.add(Bitmap32);

//这个就是多幅图层融合
for i := 0 to LayerList.Count -1 do
begin
TBitmap32(LayerList.Items[i ]).DrawTo(0,0, Image1.Picture.Bitmap);
end;


//清空图层
for i := 0 to LayerList.Count -1 do
begin
TBitmap32(LayerList.Items[i ]).Free;
end;

LayerList.Free;
 
这个是图像融合后的效果图

517531131.jpg
 
受教了!THKS!
 
lqcros这个是GR32里的东东吧
 
你说呢,你在GR32里面找得到有相同的吗,
不过有一点是,就是哪个 FillLongword函数,

下面这两个函数引用自 http://www.crazy-bit.com/ 的 PhoXo Core Library (PCL) V2.1
原来他是C++语言,我把他改成delphi语言,因为我觉得delphi里面没有自已控制简单32位图像的程序
CombineAlphaPixel, AlphaBlendPixel;
 
学习了。。。。
 
为什么不写8位和16位的啊???这2种比较常用吧
 
其實已經有第三方控件,就可以處理所有類型圖片。
 
我觉得第三方的控件,自已不好控制里面的程序。
要继承他的话,如果他有错误,我们会连错误都一起继承了。
我不觉得现在8位和16位最流行?
我只觉得在delphi里面24位比较流行。因为delphi里很多处理图像特效时,如反转,模糊,锐化等等,都要把8位和16位转成24位,再处理。
我只不过在24位上面加了一个透明通道的处理
通过这个方法,可以生成许多特效字,如字体纹理、描边、阴影什么的,也可以多幅图像合成
 
至于这个32位图像处理库,很多特效我没有加进去(这样容易理解)
我写这个32位图像处理库是可以扩展的,
现在网上也有很多特效处理程序,你们可以把他们写入到现有的库里,需要什么写什么,
 
//下面这段代码是处理字体的掩码图的,

unit MaskFont;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, trace, Math, mmsystem, PegtopResampleUtils;

const
PIXELCOUNTMAX = 32768;

type

TAAQuality = (aqHighest, aqHigh, aqNormal, aqLow, aqNone);
{* 平滑字体显示精度类型
|<PRE>
aqHighest - 5X5采样的最高显示精度,速度超慢
aqHigh - 4X4采样的最高显示精度,速度较慢
aqNormal - 3X3采样的普通显示精度,最佳性能速度比
aqLow - 2X2采样的低显示精度,速度较快
aqNone - 无平滑效果
|</PRE>}

TBlurStrength = 0..100;
{* 模糊度类型,0为不模糊,100为最大模糊度}

TLogPal = record
lpal: TLogPalette;
dummy: array[0..255] of TPaletteEntry;
end;


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

pRGBArray = ^TRGBArray;
TRGBArray = array[0..PIXELCOUNTMAX] of TRGBTriple;

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

TMaskFont = class(TPersistent)
private
GrayBmp, FMaskBmp, FMaskPathBmp: TBitmap;
FQuality: TAAQuality;
Scale: integer;
AAFont: TFont;

FPathPoints: array of TPoint;
FPathTypes: array of Byte;
FNumber: Integer;
FCounter: Byte;

procedure InitGrayBmp;
procedure FreeGrayBmp;
procedure SetQuality(const Value: TAAQuality);
protected
public
constructor Create(AOwner: TFont);
destructor Destroy;override;
procedure DrawMask(Left, Top, W: integer; Text: string);

procedure Blur(Mask: TBitmap; Blur: TBlurStrength);

property MaskBmp: TBitmap read FMaskBmp;
property MaskPathBmp: TBitmap read FMaskPathBmp;

property Quality: TAAQuality read FQuality write SetQuality;
{* 平滑字体绘制精度}
function GetBits: pByteArray;
procedure SetPixel(x, y: integer; color: integer);
function GetPixel(x, y: integer): integer;

end;

procedure InitGrayPal;

var
LogPal: TLogPal;
HGrayPal: HPALETTE = 0;

implementation

//--------------------------------------------------------//
//平滑字体蒙板 //
//--------------------------------------------------------//

//初始化灰度位图
procedure InitGrayPal;
var
i: Integer;
begin
LogPal.lpal.palVersion := $300;
LogPal.lpal.palNumEntries := 256;
for i := 0 to 255 do
begin
LogPal.dummy.peRed := i;
LogPal.dummy.peGreen := i;
LogPal.dummy.peBlue := i;
LogPal.dummy.peFlags := 0;
end;
HGrayPal := CreatePalette(LogPal.lpal);
end;

//设置精度
procedure TMaskFont.SetQuality(const Value: TAAQuality);
begin
FQuality := Value;
case FQuality of
aqHighest: Scale := 5;
aqHigh: Scale := 4;
aqNormal: Scale := 3;
aqLow: Scale := 2;
aqNone: Scale := 1;
else
Scale := 1;
end;
end;

constructor TMaskFont.Create(AOwner: TFont);
begin
InitGrayBmp;
AAFont := AOwner;
end;

destructor TMaskFont.Destroy;
begin
FreeGrayBmp;
inherited;
end;

procedure TMaskFont.InitGrayBmp;
begin
InitGrayPal;
GrayBmp := TBitmap.Create;
GrayBmp.PixelFormat := pf8bit;
GrayBmp.Canvas.Brush.Style := bsSolid;
GrayBmp.Canvas.Brush.Color := clBlack;
GrayBmp.Palette := CopyPalette(HGrayPal);

FMaskBmp := TBitmap.Create;
FMaskBmp.Assign(GrayBmp);
{
FMaskBmp.PixelFormat := pf8bit;
FMaskBmp.Canvas.Brush.Style := bsSolid;
FMaskBmp.Canvas.Brush.Color := clBlack;
FMaskBmp.Palette := CopyPalette(HGrayPal);
}
FMaskPathBmp := TBitmap.Create;
FMaskPathBmp.Assign(GrayBmp);
{
FMaskPathBmp.PixelFormat := pf8bit;
FMaskPathBmp.Canvas.Brush.Style := bsSolid;
FMaskPathBmp.Canvas.Brush.Color := clBlack;
FMaskPathBmp.Palette := CopyPalette(HGrayPal);
}
end;

procedure TMaskFont.FreeGrayBmp;
var
P: HPALETTE;
begin
if GrayBmp <> nil then
begin
P := GrayBmp.Palette;
GrayBmp.Palette := 0;
FreeAndNil(GrayBmp);
DeleteObject(P);
end;

if FMaskBmp <> nil then
begin
P := FMaskBmp.Palette;
FMaskBmp.Palette := 0;
FreeAndNil(FMaskBmp);
DeleteObject(P);
end;

if FMaskPathBmp <> nil then
begin
P := FMaskPathBmp.Palette;
FMaskPathBmp.Palette := 0;
FreeAndNil(FMaskPathBmp);
DeleteObject(P);
end;

DeleteObject(HGrayPal);
end;


//字体模糊
procedure TMaskFont.Blur(Mask: TBitmap; Blur: TBlurStrength);
type
TLine = array[0..4] of Integer;
const
csLine: array[0..4] of TLine = (
(0, 0, 0, 1, 2), (-1, -1, 0, 1, 2), (-2, -1, 0, 1, 2),
(-2, -1, 0, 1, 1), (-2, -1, 0, 0, 0)); //边界处理常量
var
pTempBuff: PByteArray;
pSour: array[0..4] of PByteArray;
pDes: PByteArray;
xLine: TLine;
yLine: TLine;
x, y, i: Integer;
Sum: Integer;
ABlur: Byte;
begin

ABlur := Round(Blur * 255 / 100);
for y := 0 to Mask.Height - 1 do //边界处理
begin
if y = 0 then
yLine := csLine[0]
else if y = 1 then
yLine := csLine[1]
else if y = Mask.Height - 2 then
yLine := csLine[3]
else if y = Mask.Height - 1 then
yLine := csLine[4]
else
yLine := csLine[2];
for i := 0 to 4 do
pSour := Mask.ScanLine[yLine + y];
pDes := Mask.ScanLine[y];
for x := 0 to Mask.Width - 1 do //边界处理
begin
if x = 0 then
xLine := csLine[0]
else if x = 1 then
xLine := csLine[1]
else if x = Mask.Width - 2 then
xLine := csLine[3]
else if x = Mask.Width - 1 then
xLine := csLine[4]
else
xLine := csLine[2];
Sum := 0;
for i := 0 to 4 do //5X5均值处理
Inc(Sum, pSour^[x + xLine[0]] + pSour^[x + xLine[1]] +
pSour^[x + xLine[2]] + pSour^[x + xLine[3]] +
pSour^[x + xLine[3]]);
if ABlur = 255 then //模糊度
pDes^[x] := Round(Sum / 25)
else
pDes^[x] := (Round(Sum / 25) - pDes^[x]) * ABlur shr 8 + pDes^[x];
end;
end;

end;


procedure TMaskFont.DrawMask(Left, Top, W: integer; Text: string);
var
x, y, j, i: integer;
tot: integer;
DestScan, BigScan: pByteArray;

LogFont: TLogFont;
OldFont: HFont;

t1: int64;

PointIdx: integer;
LastMove: TPoint;

DestOrigin, Origin: Pointer;
Pitch: Integer;

BytesLineGray: Integer;
BytesLineMask: Integer;

pS1, pS2, pS3, pS4: PByteArray;
pDes: PByteArray;
begin


GrayBmp.Canvas.Brush.Color := clBlack;
GrayBmp.Canvas.FillRect(GrayBmp.Canvas.ClipRect);

GrayBmp.Canvas.Font.Assign(AAFont);

FMaskBmp.Width := GrayBmp.Canvas.TextExtent(Text).cx + Left;
FMaskBmp.Height := GrayBmp.Canvas.TextExtent(Text).cy + Top;

GrayBmp.Width := FMaskBmp.Width * Scale;
GrayBmp.Height := FMaskBmp.Height * Scale;

{
GetObject(GrayBmp.Canvas.Font.Handle, SizeOf(TLogFont), @LogFont);
with LogFont do
begin
lfHeight := lfHeight * Scale;
lfWidth := lfWidth * Scale;
lfQuality := 4;//DEFAULT_QUALITY;
end;
GrayBmp.Canvas.Font.Handle := CreateFontIndirect(LogFont);
}
GrayBmp.Canvas.Font.Size := GrayBmp.Canvas.Font.Size * Scale;



// GrayBmp.Canvas.Font.Color := clWhite;
BeginPath(GrayBmp.Canvas.Handle);
SetBkMode(GrayBmp.Canvas.Handle, TRANSPARENT);
GrayBmp.Canvas.TextOut(0, 0, Text);
EndPath(GrayBmp.Canvas.Handle);

GrayBmp.Canvas.Brush.Color := clWhite;
FillPath(GrayBmp.Canvas.Handle);

{
GrayBmp.PixelFormat := pf32bit;
FMaskBmp.PixelFormat := pf32bit;

Origin := GrayBmp.ScanLine[0];
DestOrigin := FMaskBmp.ScanLine[0];
Pitch := Integer(GrayBmp.ScanLine[1]) - Integer(Origin);

PegtopResample4x32MMX(DestOrigin, Pitch, Classes.Rect(0, 0, GrayBmp.Width, GrayBmp.Height),
Origin, Pitch, 0, 0);


GrayBmp.PixelFormat := pf8bit;
FMaskBmp.PixelFormat := pf8bit;
}



t1 := timegettime;





BytesLineGray := (GrayBmp.Width + 3) div 4 * 4; //扫描线宽度
BytesLineMask := (FMaskBmp.Width + 3) div 4 * 4;

pS1 := GrayBmp.ScanLine[0]; //源灰度图
pS2 := PByteArray(Integer(pS1) - BytesLineGray);
pS3 := PByteArray(Integer(pS2) - BytesLineGray);
pS4 := PByteArray(Integer(pS3) - BytesLineGray);
pDes := FMaskBmp.ScanLine[0];
// pDes := PByteArray(Integer(FMaskBmp.scanLine[0]) + (FMaskBmp.Height - 1) * BytesLineMask);
//目标灰度为源矩形块的平均值
case Quality of
aqHigh:
begin //高精度4X4采样
for i := 0 to FMaskBmp.Height - 1 do
begin
for j := 0 to FmaskBmp.Width - 1 do
begin
x := j * 4;
pDes^[j] :=
(pS1^[x] + pS1^[x + 1] + pS1^[x + 2] + pS1^[x + 3] +
pS2^[x] + pS2^[x + 1] + pS2^[x + 2] + pS2^[x + 3] +
pS3^[x] + pS3^[x + 1] + pS3^[x + 2] + pS3^[x + 3] +
pS4^[x] + pS4^[x + 1] + pS4^[x + 2] + pS4^[x + 3]) shr 4;
end;
pS1 := PByteArray(Integer(pS4) - BytesLineGray);
pS2 := PByteArray(Integer(pS1) - BytesLineGray);
pS3 := PByteArray(Integer(pS2) - BytesLineGray);
pS4 := PByteArray(Integer(pS3) - BytesLineGray);
pDes := PByteArray(Integer(pDes) - BytesLineMask);
end;
end;
aqNormal:
begin //普通精度3X3采样
for i := 0 to FMaskBmp.Height - 1 do
begin
for j := 0 to FMaskBmp.Width - 1 do
begin
x := j * 3;
pDes^[j] :=
(pS1^[x] + pS1^[x + 1] + pS1^[x + 2] shr 1 +
pS2^[x] + pS2^[x + 1] + pS2^[x + 2] +
pS3^[x] shr 1 + pS3^[x + 1] + pS3^[x + 2]) shr 3;
end;
pS1 := PByteArray(Integer(pS3) - BytesLineGray);
pS2 := PByteArray(Integer(pS1) - BytesLineGray);
pS3 := PByteArray(Integer(pS2) - BytesLineGray);
pDes := PByteArray(Integer(pDes) - BytesLineMask);
end;
end;
aqLow:
begin //低精度2X2采样
for i := 0 to FMaskBmp.Height - 1 do
begin
for j := 0 to FMaskBmp.Width - 1 do
begin
x := j * 2;
pDes^[j] :=
(pS1^[x] + pS1^[x + 1] +
pS2^[x] + pS2^[x + 1]) shr 2;
end;
pS1 := PByteArray(Integer(pS2) - BytesLineGray);
pS2 := PByteArray(Integer(pS1) - BytesLineGray);
pDes := PByteArray(Integer(pDes) - BytesLineMask);
end;
end;
aqNone:
begin //无平滑效果
for i := 0 to FMaskBmp.Height - 1 do
begin
CopyMemory(pDes, pS1, FMaskBmp.Width);
pS1 := PByteArray(Integer(pS1) - BytesLineGray);
pDes := PByteArray(Integer(pDes) - BytesLineMask);
end;
end;
end;


tracestring('DrawMask1:'+inttostr(timegettime-t1));


GrayBmp.Canvas.Brush.Color := clBlack;
GrayBmp.Canvas.FillRect(GrayBmp.Canvas.ClipRect);

GrayBmp.Canvas.Font.Assign(AAFont);

FMaskPathBmp.Width := GrayBmp.Canvas.TextExtent(Text).cx + Left;
FMaskPathBmp.Height := GrayBmp.Canvas.TextExtent(Text).cy + Top;

GrayBmp.Width := FMaskPathBmp.Width * Scale;
GrayBmp.Height := FMaskPathBmp.Height * Scale;

// TraceString(IntToStr(GrayBmp.Canvas.TextExtent(Text).cx));
{
GetObject(GrayBmp.Canvas.Font.Handle, SizeOf(TLogFont), @LogFont);
with LogFont do
begin
lfHeight := lfHeight * Scale;
lfWidth := lfWidth * Scale;
lfQuality := DEFAULT_QUALITY;
end;

GrayBmp.Canvas.Font.Handle := CreateFontIndirect(LogFont);
}
GrayBmp.Canvas.Font.Size := GrayBmp.Canvas.Font.Size * Scale;

BeginPath(GrayBmp.Canvas.Handle);
SetBkMode(GrayBmp.Canvas.Handle, TRANSPARENT);
GrayBmp.Canvas.TextOut(0, 0, Text);
EndPath(GrayBmp.Canvas.Handle);

// if not FlattenPath(Canvas.Handle) then Exit;
// FlattenPath(GrayBmp.Canvas.Handle);
FNumber := GetPath(GrayBmp.Canvas.Handle, Pointer(nil^), Pointer(nil^), 0);
SetLength(FPathPoints, FNumber);
SetLength(FPathTypes, FNumber);
FNumber := GetPath(GrayBmp.Canvas.Handle, FPathPoints[0], FPathTypes[0], FNumber);

PointIdx := 0;

GrayBmp.Canvas.Pen.Color := clWhite;
GrayBmp.Canvas.Pen.Width := w;

// StrokePath(GrayBmp.Canvas.Handle);

//+++ 描边//
while PointIdx < FNumber do begin

case FPathTypes[PointIdx] of PT_MOVETO:
begin
GrayBmp.Canvas.MoveTo(FPathPoints[PointIdx].X, FPathPoints[PointIdx].Y);
LastMove := FPathPoints[PointIdx];
inc(PointIdx, 1);
end;
PT_LINETO:
begin
GrayBmp.Canvas.LineTo(FPathPoints[PointIdx].X, FPathPoints[PointIdx].Y);
inc(PointIdx, 1);
end;
PT_BEZIERTO:
begin
PolyBezierTo(GrayBmp.Canvas.Handle, FPathPoints[PointIdx], 3);
inc(PointIdx, 3);
end;
PT_LINETO or PT_CLOSEFIGURE:
begin
GrayBmp.Canvas.LineTo(FPathPoints[PointIdx].X, FPathPoints[PointIdx].y);
GrayBmp.Canvas.LineTo(LastMove.x, LastMove.y);
inc(PointIdx, 1);
end;
PT_BEZIERTO or PT_CLOSEFIGURE:
begin
PolyBezierTo(GrayBmp.Canvas.Handle, FPathPoints[PointIdx], 3);
GrayBmp.Canvas.LineTo(LastMove.x, LastMove.y);
inc(PointIdx, 3);
end;
end;
end;


SetLength(FPathPoints, 0);
SetLength(FPathTypes, 0);


{

for y := 0 to GrayBmp.Height Div Scale -1 do
begin
DestScan := FMaskPathBmp.ScanLine[y];
for x := 0 to GrayBmp.Width Div Scale -1 do
begin
tot := 0;

for j := 0 to Scale - 1 do
begin
BigScan := pByteArray(GrayBmp.ScanLine[Scale * y + j] );
for i := 0 to Scale -1 do
begin
tot := tot + BigScan[Scale * x+i];
end;
end;
DestScan[x] := tot div (Scale * Scale);
end;
end;

}

BytesLineGray := (GrayBmp.Width + 3) div 4 * 4; //扫描线宽度
BytesLineMask := (FMaskPathBmp.Width + 3) div 4 * 4;

pS1 := GrayBmp.ScanLine[0]; //源灰度图
pS2 := PByteArray(Integer(pS1) - BytesLineGray);
pS3 := PByteArray(Integer(pS2) - BytesLineGray);
pS4 := PByteArray(Integer(pS3) - BytesLineGray);
pDes := FMaskPathBmp.ScanLine[0];
// pDes := PByteArray(Integer(FMaskBmp.scanLine[0]) + (FMaskBmp.Height - 1) * BytesLineMask);
//目标灰度为源矩形块的平均值
case Quality of
aqHigh:
begin //高精度4X4采样
for i := 0 to FMaskPathBmp.Height - 1 do
begin
for j := 0 to FmaskPathBmp.Width - 1 do
begin
x := j * 4;
pDes^[j] :=
(pS1^[x] + pS1^[x + 1] + pS1^[x + 2] + pS1^[x + 3] +
pS2^[x] + pS2^[x + 1] + pS2^[x + 2] + pS2^[x + 3] +
pS3^[x] + pS3^[x + 1] + pS3^[x + 2] + pS3^[x + 3] +
pS4^[x] + pS4^[x + 1] + pS4^[x + 2] + pS4^[x + 3]) shr 4;
end;
pS1 := PByteArray(Integer(pS4) - BytesLineGray);
pS2 := PByteArray(Integer(pS1) - BytesLineGray);
pS3 := PByteArray(Integer(pS2) - BytesLineGray);
pS4 := PByteArray(Integer(pS3) - BytesLineGray);
pDes := PByteArray(Integer(pDes) - BytesLineMask);
end;
end;
aqNormal:
begin //普通精度3X3采样
for i := 0 to FMaskPathBmp.Height - 1 do
begin
for j := 0 to FMaskPathBmp.Width - 1 do
begin
x := j * 3;
pDes^[j] :=
(pS1^[x] + pS1^[x + 1] + pS1^[x + 2] shr 1 +
pS2^[x] + pS2^[x + 1] + pS2^[x + 2] +
pS3^[x] shr 1 + pS3^[x + 1] + pS3^[x + 2]) shr 3;
end;
pS1 := PByteArray(Integer(pS3) - BytesLineGray);
pS2 := PByteArray(Integer(pS1) - BytesLineGray);
pS3 := PByteArray(Integer(pS2) - BytesLineGray);
pDes := PByteArray(Integer(pDes) - BytesLineMask);
end;
end;
aqLow:
begin //低精度2X2采样
for i := 0 to FMaskPathBmp.Height - 1 do
begin
for j := 0 to FMaskPathBmp.Width - 1 do
begin
x := j * 2;
pDes^[j] :=
(pS1^[x] + pS1^[x + 1] +
pS2^[x] + pS2^[x + 1]) shr 2;
end;
pS1 := PByteArray(Integer(pS2) - BytesLineGray);
pS2 := PByteArray(Integer(pS1) - BytesLineGray);
pDes := PByteArray(Integer(pDes) - BytesLineMask);
end;
end;
aqNone:
begin //无平滑效果
for i := 0 to FMaskPathBmp.Height - 1 do
begin
CopyMemory(pDes, pS1, FMaskPathBmp.Width);
pS1 := PByteArray(Integer(pS1) - BytesLineGray);
pDes := PByteArray(Integer(pDes) - BytesLineMask);
end;
end;
end;

end;


function TMaskFont.GetBits: pByteArray;
begin
// DestScan := Image1.Picture.Bitmap.ScanLine[Image1.Picture.Bitmap.Height-1]; //取得图像缓冲区首地址
// Integer(BitMap.ScanLine[0]) + FIX_WIDTH*3 为图像缓冲区结束地址
Result := FMaskBmp.ScanLine[FMaskBmp.Height - 1];
end;

procedure TMaskFont.SetPixel(x, y: integer; color: integer);
begin
GetBits^[x + (MaskBmp.Height - y -1) * BytesPerScanline(MaskBmp.Width, 8, 32)] := color;
end;
function TMaskFont.GetPixel(x, y: integer): integer;
begin
Result := GetBits^[(MaskBmp.Height - y -1) * BytesPerScanline(MaskBmp.Width, 8, 32) + x];
end;


end.
 
// 32位图像处理平滑字体示例 (我的个人网站可以下载)
http://lqcros.go1.wy8.net
 
真的很不错,谢谢了
 
看了几个方法基本和GR32一模一样啊
 
后退
顶部