赞 | 68 |
VIP | 0 |
好人卡 | 0 |
积分 | 65 |
经验 | 0 |
最后登录 | 2023-7-2 |
在线时间 | 119 小时 |
Lv4.逐梦者
- 梦石
- 0
- 星屑
- 6483
- 在线时间
- 119 小时
- 注册时间
- 2020-1-8
- 帖子
- 234
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
参考资料:RPG Maker的Bitmap类的结构
还有一个英文网站,我找不到了……
module CWP CallWndProc = Win32API.new('user32', 'CallWindowProc', 'PLLLL', 'L') CodeMove = [139,68,36,4,133,192,116,23,209,224,185,2,0,0,0,139,20,140,133, 210,116,9,139,4,16,65,131,249,5,117,240,194,16,0].pack('C*') def self.move(obj, offsetA=16, offsetB=0, offsetC=0) CallWndProc.call(CodeMove, obj, offsetA, offsetB, offsetC) end end class Bitmap def to_int self.object_id end def hBitmap @_hBitmap ||= CWP.move(self, 16, 8, 44) end def pBits @_pBits ||= CWP.move(self, 16, 8, 16) end def pScan0 @_pScan0 ||= CWP.move(self, 16, 8, 12) end def pIHr @_pIHr ||= CWP.move(self, 16, 8, 8) # 或者 CWP.move(self, 16, 8, 32) end end module WIN32API @@default_w = 640 @@default_h = 480 threadID = Win32API.new('kernel32', 'GetCurrentThreadId', 'V', 'L').call() hwnd = Win32API.new('user32', 'GetForegroundWindow', 'V', 'L').call() _GetWndTidPid = Win32API.new('user32','GetWindowThreadProcessId', 'LP', 'L') _FindWindowEx = Win32API.new('user32', 'FindWindowEx', 'LLPP', 'L') while _GetWndTidPid.call(hwnd, nil) != threadID hwnd = _FindWindowEx.call(0, hwnd, "RGSS Player", nil) end Hwnd = hwnd GetDC = Win32API.new('user32', 'GetDC', 'L', 'L') ReleaseDC = Win32API.new('user32', 'ReleaseDC', 'LL', 'L') CreateCompatibleDC = Win32API.new('gdi32', 'CreateCompatibleDC', 'L', 'L') DeleteDC = Win32API.new('gdi32', 'DeleteDC', 'L', 'I') DeleteObject = Win32API.new('gdi32', 'DeleteObject', 'L', 'I') SelectObject = Win32API.new('gdi32', 'SelectObject', 'LL', 'L') BitBlt = Win32API.new('gdi32', 'BitBlt', 'LIIIILIIL', 'I') StretchBlt = Win32API.new('gdi32', 'StretchBlt', 'LIIIILIIIIL', 'I') SetStretchBltMode = Win32API.new('gdi32', 'SetStretchBltMode', 'LI', 'I') SetBrushOrgEx = Win32API.new('gdi32', 'SetBrushOrgEx', 'LIIP', 'I') SRCCOPY = 0xCC0020 SRCPAINT = 0xEE0086 STRETCH_HALFTONE = 4 def self.snap_to_bitmap(src_x = 0, src_y = 0, src_w = @@default_w, src_h = @@default_h, dest_w = @@default_w, dest_h = @@default_h) bitmap = Bitmap.new(dest_w, dest_h) hDC = GetDC.call(Hwnd) mCDC = CreateCompatibleDC.call(hDC) oldBitmap = SelectObject.call(mCDC, bitmap.hBitmap) if src_w == dest_w && src_h == dest_h BitBlt.call(mCDC, 0, 0, dest_w, dest_h, hDC, 0, 0, SRCCOPY) else SetStretchBltMode.call(mCDC, STRETCH_HALFTONE) SetBrushOrgEx.call(mCDC, 0, 0, nil) StretchBlt.call(mCDC, 0, 0, dest_w, dest_h, hDC, src_x, src_y, src_w, src_h, SRCPAINT) end SelectObject.call(mCDC, oldBitmap) DeleteDC.call(mCDC) ReleaseDC.call(Hwnd, hDC) bitmap end MultiByteToWideChar = Win32API.new('kernel32', 'MultiByteToWideChar', 'ILPIPI', 'I') CP_UTF8 = 65001 def self.utf16(text) len = MultiByteToWideChar.call(CP_UTF8, 0, text, -1, nil, 0) buf = "\0" * (len * 2) MultiByteToWideChar.call(CP_UTF8, 0, text, -1, buf, len) buf end GdiplusStartup = Win32API.new('gdiplus', 'GdiplusStartup', 'PPP', 'I') GdiplusShutdown = Win32API.new('gdiplus', 'GdiplusShutdown', 'L', 'V') GdipStartupInput = [1, 0, 0, 0].pack('L4') GdipCreateBitmapFromGdiDib = Win32API.new('gdiplus', 'GdipCreateBitmapFromGdiDib', 'LLP', 'I') GdipDisposeImage = Win32API.new('gdiplus', 'GdipDisposeImage', 'L', 'I') GdipSaveImageToFile = Win32API.new('gdiplus', 'GdipSaveImageToFile', 'LPPP', 'I') fixed = [6660, 4563, 154, 115, 0, 0, 248, 30, 243, 46].pack('SSC8') ClsidEncoder = { :bmp => [1434252288].pack('L') << fixed, :jpg => [1434252289].pack('L') << fixed, :png => [1434252294].pack('L') << fixed } def self.save_bitmap_to_pic(rgss_bitmap, filename, type=:png) buf = "\0" * 4 GdiplusStartup.call(buf, GdipStartupInput, nil) token = buf.unpack('L')[0] GdipCreateBitmapFromGdiDib.call(rgss_bitmap.pIHr, rgss_bitmap.pBits, buf) pBitmap = buf.unpack('L')[0] GdipSaveImageToFile.call(pBitmap, self.utf16(filename), ClsidEncoder[type] || ClsidEncoder[:png], nil) GdipDisposeImage.call(pBitmap) GdiplusShutdown.call(token) end end
module CWP
CallWndProc = Win32API.new('user32', 'CallWindowProc', 'PLLLL', 'L')
CodeMove = [139,68,36,4,133,192,116,23,209,224,185,2,0,0,0,139,20,140,133,
210,116,9,139,4,16,65,131,249,5,117,240,194,16,0].pack('C*')
def self.move(obj, offsetA=16, offsetB=0, offsetC=0)
CallWndProc.call(CodeMove, obj, offsetA, offsetB, offsetC)
end
end
class Bitmap
def to_int
self.object_id
end
def hBitmap
@_hBitmap ||= CWP.move(self, 16, 8, 44)
end
def pBits
@_pBits ||= CWP.move(self, 16, 8, 16)
end
def pScan0
@_pScan0 ||= CWP.move(self, 16, 8, 12)
end
def pIHr
@_pIHr ||= CWP.move(self, 16, 8, 8) # 或者 CWP.move(self, 16, 8, 32)
end
end
module WIN32API
@@default_w = 640
@@default_h = 480
threadID = Win32API.new('kernel32', 'GetCurrentThreadId', 'V', 'L').call()
hwnd = Win32API.new('user32', 'GetForegroundWindow', 'V', 'L').call()
_GetWndTidPid = Win32API.new('user32','GetWindowThreadProcessId', 'LP', 'L')
_FindWindowEx = Win32API.new('user32', 'FindWindowEx', 'LLPP', 'L')
while _GetWndTidPid.call(hwnd, nil) != threadID
hwnd = _FindWindowEx.call(0, hwnd, "RGSS Player", nil)
end
Hwnd = hwnd
GetDC = Win32API.new('user32', 'GetDC', 'L', 'L')
ReleaseDC = Win32API.new('user32', 'ReleaseDC', 'LL', 'L')
CreateCompatibleDC = Win32API.new('gdi32', 'CreateCompatibleDC', 'L', 'L')
DeleteDC = Win32API.new('gdi32', 'DeleteDC', 'L', 'I')
DeleteObject = Win32API.new('gdi32', 'DeleteObject', 'L', 'I')
SelectObject = Win32API.new('gdi32', 'SelectObject', 'LL', 'L')
BitBlt = Win32API.new('gdi32', 'BitBlt', 'LIIIILIIL', 'I')
StretchBlt = Win32API.new('gdi32', 'StretchBlt', 'LIIIILIIIIL', 'I')
SetStretchBltMode = Win32API.new('gdi32', 'SetStretchBltMode', 'LI', 'I')
SetBrushOrgEx = Win32API.new('gdi32', 'SetBrushOrgEx', 'LIIP', 'I')
SRCCOPY = 0xCC0020
SRCPAINT = 0xEE0086
STRETCH_HALFTONE = 4
def self.snap_to_bitmap(src_x = 0, src_y = 0, src_w = @@default_w,
src_h = @@default_h, dest_w = @@default_w, dest_h = @@default_h)
bitmap = Bitmap.new(dest_w, dest_h)
hDC = GetDC.call(Hwnd)
mCDC = CreateCompatibleDC.call(hDC)
oldBitmap = SelectObject.call(mCDC, bitmap.hBitmap)
if src_w == dest_w && src_h == dest_h
BitBlt.call(mCDC, 0, 0, dest_w, dest_h, hDC, 0, 0, SRCCOPY)
else
SetStretchBltMode.call(mCDC, STRETCH_HALFTONE)
SetBrushOrgEx.call(mCDC, 0, 0, nil)
StretchBlt.call(mCDC, 0, 0, dest_w, dest_h, hDC, src_x, src_y, src_w,
src_h, SRCPAINT)
end
SelectObject.call(mCDC, oldBitmap)
DeleteDC.call(mCDC)
ReleaseDC.call(Hwnd, hDC)
bitmap
end
MultiByteToWideChar =
Win32API.new('kernel32', 'MultiByteToWideChar', 'ILPIPI', 'I')
CP_UTF8 = 65001
def self.utf16(text)
len = MultiByteToWideChar.call(CP_UTF8, 0, text, -1, nil, 0)
buf = "\0" * (len * 2)
MultiByteToWideChar.call(CP_UTF8, 0, text, -1, buf, len)
buf
end
GdiplusStartup = Win32API.new('gdiplus', 'GdiplusStartup', 'PPP', 'I')
GdiplusShutdown = Win32API.new('gdiplus', 'GdiplusShutdown', 'L', 'V')
GdipStartupInput = [1, 0, 0, 0].pack('L4')
GdipCreateBitmapFromGdiDib =
Win32API.new('gdiplus', 'GdipCreateBitmapFromGdiDib', 'LLP', 'I')
GdipDisposeImage = Win32API.new('gdiplus', 'GdipDisposeImage', 'L', 'I')
GdipSaveImageToFile =
Win32API.new('gdiplus', 'GdipSaveImageToFile', 'LPPP', 'I')
fixed = [6660, 4563, 154, 115, 0, 0, 248, 30, 243, 46].pack('SSC8')
ClsidEncoder = {
:bmp => [1434252288].pack('L') << fixed,
:jpg => [1434252289].pack('L') << fixed,
:png => [1434252294].pack('L') << fixed
}
def self.save_bitmap_to_pic(rgss_bitmap, filename, type=:png)
buf = "\0" * 4
GdiplusStartup.call(buf, GdipStartupInput, nil)
token = buf.unpack('L')[0]
GdipCreateBitmapFromGdiDib.call(rgss_bitmap.pIHr, rgss_bitmap.pBits, buf)
pBitmap = buf.unpack('L')[0]
GdipSaveImageToFile.call(pBitmap, self.utf16(filename),
ClsidEncoder[type] || ClsidEncoder[:png], nil)
GdipDisposeImage.call(pBitmap)
GdiplusShutdown.call(token)
end
end
以前只会用论坛上的Bitmap#address方法,并不知道其含义,具体可以看看链接中的解释(代码需鼠标手动拉开……)。
全部为Win32API的调用,主要为基本过程,并没有对方法的参数及API返回值做判断,
具体参数类型及取值参照变量名,有需求请自行修改。
WIN32API.snap_to_bitmap
由gdi实现,截屏为位图的功能,可局部缩放。
用到 Bitmap#hBitmap(完全可以把RGSSBitmap当作GDI的Bitmap对象使用)
示例:以屏幕左上角 Rect(0, 0, 320, 240) 区域图像生成 640×480 大小的位图对象
bitmap = WIN32API.snap_to_bitmap(0, 0, 320, 240, 640, 480)
#bitmap.dispose
WIN32API.save_bitmap_to_pic
由gdi+实现,保存位图为图片(png,jpg,bmp)。
用到 Bitmap#pIHr(GDI中的BITMAPINFOHEADER); Bitmap#pBits(RGSSBitmap中图像数据内存的起始地址)
示例:以bitmap对象保存为名为 “截屏.jpeg” 的图片文件
# bitmap
WIN32API.save_bitmap_to_pic(bitmap, "截屏.jpeg", :jpg)
# bitmap.dispose |
|