じ☆ve冰风 发表于 2024-4-20 02:18:36

位图模糊

边学边练,直接上代码

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]
查看完整版本: 位图模糊