位图模糊
边学边练,直接上代码RUBY 代码
class Bitmap
dll = "Blur.dll"
GetValue = Win32API.new(dll, 'GetValue', 'LLLLL', 'L')
Blur = Win32API.new(dll, 'bitmapBlur', 'LL', 'V')
ExpBlur = Win32API.new(dll, 'bitmapExpBlur', 'LLLL', 'V')
GaussBlur = Win32API.new(dll, 'bitmapGaussBlur', 'LL', 'V')
def to_int
self.object_id
end
def hBitmap
@_hBitmap ||= GetValue.call(self, 16, 8, 44, 0)
end
def pBits
@_pBits ||= GetValue.call(self, 16, 8, 16, 0)
end
def pScan0
@_pScan0 ||= GetValue.call(self, 16, 8, 12, 0)
end
def pIHr
@_pIHr ||= GetValue.call(self, 16, 8, 8, 0)
end
# 简单快速的模糊,“第一行”与“最后一行”未处理;简单的看作半径1的模糊
# 具体计算用SSE的pavgb实现
# width >= 8 && height > 3
def main_blur!(exchg_times = 0)
Blur.call(self, exchg_times)
end
# 网上的算法,效率与半径无关,纯C实现
def expBlur!(radius = 1, aprec = 16, zprec = 7)
ExpBlur.call(self, radius, aprec, zprec)
end
# 网上的算法,效率与半径无关,具体计算用内嵌汇编SSE实现
# C函数半径参数为单精度,为了避免转换类型,写成百分比数250 => 2.5
def gaussBlur!(radius_percent = 100)
GaussBlur.call(self, radius_percent)
end
BlurEffectGuid =
BrightnessContrastEffectGuid =
ColorBalanceEffectGuid =
ColorCurveEffectGuid =
ColorLUTEffectGuid =
ColorLookupTableEffectGuid = ColorLUTEffectGuid
ColorMatrixEffectGuid =
HSLEffectGuid =
HueSaturationLightnessEffectGuid =HSLEffectGuid
LevelsEffectGuid =
RECEffectGuid =
RedEyeCorrectionEffectGuid = RECEffectGuid
SharpenEffectGuid =
TintEffectGuid =
#PixelFormat32bppARGB = 0x26200A
#ImageLockModeRead = 1
#ImageLockModeWrite = 2
#ImageLockModeUserInputBuf = 4
gdip = "gdiplus.dll"
GdiplusStartup = Win32API.new(gdip, 'GdiplusStartup', 'PPP', 'I')
GdiplusShutdown = Win32API.new(gdip, 'GdiplusShutdown', 'L', 'V')
GdipStartupInput = .pack('L4')
CreateBitmapFromHBITMAP =
Win32API.new(gdip, 'GdipCreateBitmapFromHBITMAP', 'LLP', 'I')
DisposeImage = Win32API.new(gdip, 'GdipDisposeImage', 'L', 'I')
# CreateEffect = Win32API.new(gdip, 'GdipCreateEffect', 'PP', 'I')
# 该API第一个参数类型Guid,可以看作一个16bytes结构,
# 需要其所有成员完全进栈,而不是其地址
# RMXP中没有此结构,所以拓展参数
CreateEffectGuidP = Win32API.new(gdip, 'GdipCreateEffect', 'LLLLP', 'I')
CreateEffect = lambda{|guid, buf|
CreateEffectGuidP.call(guid, guid, guid, guid, buf)
}
BitmapApplyEffect = Win32API.new(gdip, 'GdipBitmapApplyEffect','LLPIPP','I')
DeleteEffect = Win32API.new(gdip, 'GdipDeleteEffect', 'L', 'I')
SetEffectParams = Win32API.new(gdip,'GdipSetEffectParameters', 'LPL', 'I')
BitmapLockBits = Win32API.new(gdip, 'GdipBitmapLockBits', 'LPLLP', 'I')
BitmapUnlockBits = Win32API.new(gdip, 'GdipBitmapUnlockBits', 'LP', 'I')
# 半径越大,效率越低
def gdiplus_blur!(radius, rx = 0, ry = 0, rw = nil, rh = nil)
buf = "\0" * 4
GdiplusStartup.call(buf, GdipStartupInput, nil)
token = buf.unpack('L')
CreateBitmapFromHBITMAP.call(self.hBitmap, 0, buf)
pBitmap = buf.unpack('L')
CreateEffect.call(BlurEffectGuid, buf)
pBlurEffect = buf.unpack('L')
# gdiplus 不同效果的效果参数结构不同,自行百度
blurParams = .pack('fI')
SetEffectParams.call(pBlurEffect, blurParams, blurParams.size)
w, h = self.width, self.height
rw, rh = rw || w, rh || h
rect = .pack('iiII')
BitmapApplyEffect.call(pBitmap, pBlurEffect, rect, 0, nil, nil)
#PixelFormat32bppARGB => 0x26200A
stride = w * -4
scan0 = self.pScan0 + rx * 4 + ry * stride
lockedBmpData = .pack('IIiI3')
#ImageLockModeUserInputBuf | ImageLockModeRead => 5
BitmapLockBits.call(pBitmap, rect, 5, 0x26200A, lockedBmpData)
BitmapUnlockBits.call(pBitmap, lockedBmpData)
DisposeImage.call(pBitmap)
DeleteEffect.call(pBlurEffect)
GdiplusShutdown.call(token)
end
end
简单的测试,希望可以回复一下次数
RUBY 代码
src = Bitmap.new(640, 480)# 观看效果的话,换成图片,注释掉下面一行代码
src.fill_rect(src.rect, Color.new(0, 255, 255))
dst = src.clone
sprite = Sprite.new
sprite.bitmap = dst
count, t = 0, Time.now
loopdo
dst.main_blur!(1)
breakifTime.now - t >= 1.0
count += 1
end
str = "blur => #{count}次/秒\n"# 195次/秒……
count, t = 0, Time.now
loopdo
dst.expBlur!(2, 16, 7)
breakifTime.now - t >= 1.0
count += 1
end
str = 1.0
count += 1
end
str = 1.0
count += 1
end
str
页:
[1]