Project1

标题: 位图模糊 [打印本页]

作者: RPGzh500223    时间: 2022-4-16 15:45
标题: 位图模糊
边学边练,直接上代码

RUBY 代码复制
  1. class Bitmap
  2.   dll = "Blur.dll"
  3.  
  4.   GetValue = Win32API.new(dll, 'GetValue', 'LLLLL', 'L')
  5.   Blur = Win32API.new(dll, 'bitmapBlur', 'LL', 'V')
  6.   ExpBlur = Win32API.new(dll, 'bitmapExpBlur', 'LLLL', 'V')
  7.   GaussBlur = Win32API.new(dll, 'bitmapGaussBlur', 'LL', 'V')
  8.  
  9.   def to_int
  10.     self.object_id
  11.   end
  12.  
  13.   def hBitmap
  14.     @_hBitmap ||= GetValue.call(self, 16, 8, 44, 0)
  15.   end
  16.  
  17.   def pBits
  18.     @_pBits ||= GetValue.call(self, 16, 8, 16, 0)
  19.   end
  20.  
  21.   def pScan0
  22.     @_pScan0 ||= GetValue.call(self, 16, 8, 12, 0)
  23.   end
  24.  
  25.   def pIHr
  26.     @_pIHr ||= GetValue.call(self, 16, 8, 8, 0)
  27.   end
  28.  
  29.   # 简单快速的模糊,“第一行”与“最后一行”未处理;简单的看作半径1的模糊
  30.   # 具体计算用SSE的pavgb实现
  31.   # width >= 8 && height > 3
  32.   def main_blur!(exchg_times = 0)
  33.     Blur.call(self, exchg_times)
  34.   end
  35.  
  36.   # 网上的算法,效率与半径无关,纯C实现
  37.   def expBlur!(radius = 1, aprec = 16, zprec = 7)
  38.     ExpBlur.call(self, radius, aprec, zprec)
  39.   end
  40.  
  41.   # 网上的算法,效率与半径无关,具体计算用内嵌汇编SSE实现
  42.   # C函数半径参数为单精度,为了避免转换类型,写成百分比数  250 => 2.5
  43.   def gaussBlur!(radius_percent = 100)
  44.     GaussBlur.call(self, radius_percent)
  45.   end
  46.  
  47.  
  48.   BlurEffectGuid = [0x633C80A4, 0x482B1843, 0x28BEF29E, 0xD4FDC534]
  49.   BrightnessContrastEffectGuid = [0xD3A1DBE1,0x4C178EC4,0x97EA4C9F,0x3D341CAD]
  50.   ColorBalanceEffectGuid = [0x537E597D, 0x48DA251E, 0xCA296496, 0xF8706B49]
  51.   ColorCurveEffectGuid = [0xDD6A0022, 0x4A6758E4, 0x8ED49B9D, 0x3DA581B8]
  52.   ColorLUTEffectGuid = [0xA7CE72A9, 0x40D70F7F, 0xC0D0CCB3, 0x12325C2D]
  53.   ColorLookupTableEffectGuid = ColorLUTEffectGuid
  54.   ColorMatrixEffectGuid = [0x718F2615, 0x40E37933, 0x685F11A5, 0x74DD14FE]
  55.   HSLEffectGuid = [0x8B2DD6C3, 0x4D87EB07, 0x0871F0A5, 0x5F9C6AE2]
  56.   HueSaturationLightnessEffectGuid =  HSLEffectGuid   
  57.   LevelsEffectGuid = [0x99C354EC, 0x4F3A2A31, 0xA817348C, 0x253AB303]
  58.   RECEffectGuid = [0x74D29D05, 0x426669A4, 0xC53C4995, 0x32B63628]
  59.   RedEyeCorrectionEffectGuid = RECEffectGuid
  60.   SharpenEffectGuid = [0x63CBF3EE, 0x402CC526, 0xC562718F, 0x4251BF40]
  61.   TintEffectGuid = [0x1077AF00, 0x44412848, 0xAD448994, 0x2C7A2D4C]
  62.  
  63.   #PixelFormat32bppARGB = 0x26200A
  64.   #ImageLockModeRead = 1
  65.   #ImageLockModeWrite = 2
  66.   #ImageLockModeUserInputBuf = 4
  67.  
  68.   gdip = "gdiplus.dll"
  69.  
  70.   GdiplusStartup = Win32API.new(gdip, 'GdiplusStartup', 'PPP', 'I')
  71.   GdiplusShutdown = Win32API.new(gdip, 'GdiplusShutdown', 'L', 'V')
  72.   GdipStartupInput = [1, 0, 0, 0].pack('L4')
  73.  
  74.   CreateBitmapFromHBITMAP =
  75.     Win32API.new(gdip, 'GdipCreateBitmapFromHBITMAP', 'LLP', 'I')
  76.  
  77.   DisposeImage = Win32API.new(gdip, 'GdipDisposeImage', 'L', 'I')
  78.  
  79.   # CreateEffect = Win32API.new(gdip, 'GdipCreateEffect', 'PP', 'I')
  80.   # 该API第一个参数类型Guid,可以看作一个16bytes结构,
  81.   # 需要其所有成员完全进栈,而不是其地址
  82.   # RMXP中没有此结构,所以拓展参数
  83.   CreateEffectGuidP = Win32API.new(gdip, 'GdipCreateEffect', 'LLLLP', 'I')
  84.   CreateEffect = lambda {|guid, buf|
  85.     CreateEffectGuidP.call(guid[0], guid[1], guid[2], guid[3], buf)
  86.   }
  87.  
  88.   BitmapApplyEffect = Win32API.new(gdip, 'GdipBitmapApplyEffect','LLPIPP','I')  
  89.   DeleteEffect = Win32API.new(gdip, 'GdipDeleteEffect', 'L', 'I')
  90.   SetEffectParams = Win32API.new(gdip,'GdipSetEffectParameters', 'LPL', 'I')
  91.  
  92.   BitmapLockBits = Win32API.new(gdip, 'GdipBitmapLockBits', 'LPLLP', 'I')
  93.   BitmapUnlockBits = Win32API.new(gdip, 'GdipBitmapUnlockBits', 'LP', 'I')
  94.  
  95.  
  96.   # 半径越大,效率越低
  97.   def gdiplus_blur!(radius, rx = 0, ry = 0, rw = nil, rh = nil)
  98.     buf = "\0" * 4
  99.  
  100.     GdiplusStartup.call(buf, GdipStartupInput, nil)
  101.     token = buf.unpack('L')[0]
  102.  
  103.     CreateBitmapFromHBITMAP.call(self.hBitmap, 0, buf)
  104.     pBitmap = buf.unpack('L')[0]
  105.  
  106.     CreateEffect.call(BlurEffectGuid, buf)
  107.     pBlurEffect = buf.unpack('L')[0]
  108.  
  109.     # gdiplus 不同效果的效果参数结构不同,自行百度
  110.     blurParams = [radius, 0].pack('fI')
  111.     SetEffectParams.call(pBlurEffect, blurParams, blurParams.size)
  112.  
  113.     w, h = self.width, self.height
  114.     rw, rh = rw || w, rh || h
  115.  
  116.     rect = [rx, ry, rx + rw, ry + rh].pack('iiII')
  117.     BitmapApplyEffect.call(pBitmap, pBlurEffect, rect, 0, nil, nil)
  118.  
  119.     #PixelFormat32bppARGB => 0x26200A
  120.     stride = w * -4
  121.     scan0 = self.pScan0 + rx * 4 + ry * stride
  122.     lockedBmpData = [rw, rh, stride, 0x26200A, scan0, 0].pack('IIiI3')
  123.  
  124.     #ImageLockModeUserInputBuf | ImageLockModeRead => 5
  125.     BitmapLockBits.call(pBitmap, rect, 5, 0x26200A, lockedBmpData)
  126.     BitmapUnlockBits.call(pBitmap, lockedBmpData)
  127.  
  128.     DisposeImage.call(pBitmap)
  129.     DeleteEffect.call(pBlurEffect)
  130.     GdiplusShutdown.call(token)
  131.   end   
  132. end



简单的测试,希望可以回复一下次数

RUBY 代码复制
  1. src = Bitmap.new(640, 480)  # 观看效果的话,换成图片,注释掉下面一行代码
  2. src.fill_rect(src.rect, Color.new(0, 255, 255))
  3. dst = src.clone
  4. sprite = Sprite.new
  5. sprite.bitmap = dst
  6.  
  7.  
  8. count, t = 0, Time.now
  9. loop do
  10.   dst.main_blur!(1)
  11.   break if Time.now - t >= 1.0
  12.   count += 1
  13. end
  14. str = "blur => #{count}次/秒\n"  # 195次/秒……
  15.  
  16. count, t = 0, Time.now
  17. loop do
  18.   dst.expBlur!(2, 16, 7)
  19.   break if Time.now - t >= 1.0
  20.   count += 1
  21. end
  22. str << "expblur => #{count}次/秒\n"  # 25次/秒……
  23.  
  24. count, t = 0, Time.now
  25. loop do
  26.   dst.gaussBlur!(200)
  27.   break if Time.now - t >= 1.0
  28.   count += 1
  29. end
  30. str << "gaussblur => #{count}次/秒\n"  # 47次/秒……
  31.  
  32. count, t = 0, Time.now
  33. loop do
  34.   dst.gdiplus_blur!(5)
  35.   break if Time.now - t >= 1.0
  36.   count += 1
  37. end
  38. str << "gdiplus_blur => #{count}次/秒"  # 8次/秒……
  39.  
  40. print str
  41.  
  42.  
  43. loop do
  44.   Graphics.update
  45.   Input.update
  46.   if Input.trigger?(Input::B)
  47.     dst.clear
  48.     dst.blt(0, 0, src, src.rect)
  49.   end
  50.  
  51.   if Input.trigger?(Input::C)
  52.     dst.main_blur!(1)
  53.   end
  54.  
  55.   if Input.trigger?(Input::L)
  56.     dst.gaussBlur!(200)
  57.   end
  58.  
  59.   if Input.trigger?(Input::R)
  60.     dst.expBlur!(2, 16, 7)
  61.   end
  62.  
  63.   if Input.trigger?(Input::RIGHT)
  64.     dst.gdiplus_blur!(5)
  65.   end
  66. end

Blur.zip

5.01 KB, 下载次数: 12

Blur.dll


作者: guoxiaomi    时间: 2022-4-16 19:23
截个图算了





欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1