|
|
|
Разработка findcolor, findimage, Pure lua |
|
|
cirus |
27.3.2021, 21:21
|
Elder
Сообщений: 3.480
Регистрация: 18.8.2014 Группа: Пользователи Наличность: 26750
Пользователь №: 16.971
Возраст: 29
|
Цитата а в файл сохранить картинку можно? Вариант1 (WriteFile)
Код --lua local ffi = require("ffi") local SRCCOPY = 0x00CC0020 local DIB_RGB_COLORS = 0 local BI_RGB = 0 local GENERIC_WRITE = 0x40000000 local OPEN_ALWAYS = 4 local FILE_ATTRIBUTE_NORMAL = 0x00000080 ffi.cdef[[ typedef long LONG; typedef unsigned short WORD; typedef unsigned long DWORD; typedef DWORD *LPDWORD; typedef unsigned char BYTE; typedef void *LPVOID; typedef const void *LPCVOID; #pragma pack (push, 1) typedef struct { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits;} BITMAPFILEHEADER; #pragma pack (pop) typedef struct {DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant;} BITMAPINFOHEADER; typedef struct {BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved;} RGBQUAD; typedef struct {BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1];} BITMAPINFO; int GetDC(int hWnd); int ReleaseDC(int hWnd, int hDC); int SelectObject(int hdc, int h); int CreateCompatibleDC(int hdc); int CreateCompatibleBitmap(int hdc, int cx, int cy); bool DeleteObject(int ho); bool BitBlt(int hdc, int x, int y, int cx, int cy, int hdcSrc, int x1, int y1, unsigned long rop); int GetDIBits(int hdc, int hbm, unsigned int start, unsigned int cLines, LPVOID lpvBits, BITMAPINFO* lpbmi, unsigned int usage); bool WriteFile(int hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, int lpOverlapped); int CreateFileA(const char* lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, int lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, int hTemplateFile); bool CloseHandle(int hObject); ]]
function screen(path, x, y, x2, y2, handle) local C = ffi.C local hdcWindow = C.GetDC(handle or 0) -- если хендл не указан, то получим скрин с экрана local hdcMemDC = C.CreateCompatibleDC(hdcWindow) local hbmScreen = C.CreateCompatibleBitmap(hdcWindow, x2-x, y2-y) C.SelectObject(hdcMemDC,hbmScreen) C.BitBlt(hdcMemDC, 0, 0, x2-x, y2-y, hdcWindow, x, y, SRCCOPY) -- сохранить в памяти скрин с окна или экрана
local bi = ffi.new('BITMAPINFO', { {ffi.sizeof('BITMAPINFOHEADER'), x2-x, y2-y, 1, 32, BI_RGB,0,0,0,0,0} }) C.GetDIBits(hdcWindow, hbmScreen, 0, y2-y, nil, bi, DIB_RGB_COLORS) -- узнать какого размера нужен массив
local bmpFileHeader = ffi.new('BITMAPFILEHEADER', {0x4d42, bi.bmiHeader.biSizeImage, 0, 0, ffi.sizeof('BITMAPFILEHEADER')+ffi.sizeof('BITMAPINFOHEADER')}) local bits = ffi.new('unsigned char[?]', bi.bmiHeader.biSizeImage) local result = C.GetDIBits(hdcWindow, hbmScreen, 0, y2-y, bits, bi, DIB_RGB_COLORS)
local dwWritten = ffi.new('DWORD[1]') local hFile = C.CreateFileA(path, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,0)
C.WriteFile(hFile, bmpFileHeader, ffi.sizeof('BITMAPFILEHEADER'), dwWritten, 0) C.WriteFile(hFile, bi, ffi.sizeof('BITMAPINFOHEADER'), dwWritten, 0) C.WriteFile(hFile, bits, bi.bmiHeader.biSizeImage, dwWritten, 0) C.CloseHandle(hFile)
C.ReleaseDC(handle or 0, hdcWindow) C.DeleteObject(hdcMemDC) C.DeleteObject(hbmScreen) end
screen([[C:\screen_desktop.bmp]], 200, 200, 500, 500) -- скрин с экрана screen([[C:\screen_window.bmp]], 200, 200, 500, 500, workwindow()) -- скрин с рабочего окна (может быть перекрыто) Вариант2 (fwrite)
Код --lua local ffi = require("ffi") local msvcrt = ffi.load('msvcrt.dll') local SRCCOPY = 0x00CC0020 local DIB_RGB_COLORS = 0 local BI_RGB = 0 ffi.cdef[[ typedef long LONG; typedef unsigned short WORD; typedef unsigned long DWORD; typedef DWORD *LPDWORD; typedef unsigned char BYTE; typedef void *LPVOID; typedef const void *LPCVOID; #pragma pack (push, 1) typedef struct { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits;} BITMAPFILEHEADER; #pragma pack (pop) typedef struct {DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant;} BITMAPINFOHEADER; typedef struct {BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved;} RGBQUAD; typedef struct {BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1];} BITMAPINFO; int GetDC(int hWnd); int ReleaseDC(int hWnd, int hDC); int SelectObject(int hdc, int h); int CreateCompatibleDC(int hdc); int CreateCompatibleBitmap(int hdc, int cx, int cy); bool DeleteObject(int ho); bool BitBlt(int hdc, int x, int y, int cx, int cy, int hdcSrc, int x1, int y1, unsigned long rop); int GetDIBits(int hdc, int hbm, unsigned int start, unsigned int cLines, LPVOID lpvBits, BITMAPINFO* lpbmi, unsigned int usage); int *fopen(const char *filename, const char *mode); int fwrite(const void *buffer, int size, int count, int *stream); int fclose(int *stream); ]]
function screen(path, x, y, x2, y2, handle) local C = ffi.C local hdcWindow = C.GetDC(handle or 0) -- если хендл не указан, то получим скрин с экрана local hdcMemDC = C.CreateCompatibleDC(hdcWindow) local hbmScreen = C.CreateCompatibleBitmap(hdcWindow, x2-x, y2-y) C.SelectObject(hdcMemDC,hbmScreen) C.BitBlt(hdcMemDC, 0, 0, x2-x, y2-y, hdcWindow, x, y, SRCCOPY) -- сохранить в памяти скрин с окна или экрана
local bi = ffi.new('BITMAPINFO', { {ffi.sizeof('BITMAPINFOHEADER'), x2-x, y2-y, 1, 32, BI_RGB,0,0,0,0,0} }) C.GetDIBits(hdcWindow, hbmScreen, 0, y2-y, nil, bi, DIB_RGB_COLORS) -- узнать какого размера нужен массив
local bmpFileHeader = ffi.new('BITMAPFILEHEADER', {0x4d42, bi.bmiHeader.biSizeImage, 0, 0, ffi.sizeof('BITMAPFILEHEADER')+ffi.sizeof('BITMAPINFOHEADER')}) local bits = ffi.new('unsigned char[?]', bi.bmiHeader.biSizeImage) local result = C.GetDIBits(hdcWindow, hbmScreen, 0, y2-y, bits, bi, DIB_RGB_COLORS)
local hFile = msvcrt.fopen(path, "wb") if hFile then msvcrt.fwrite(bmpFileHeader, ffi.sizeof('BITMAPFILEHEADER'), 1, hFile) msvcrt.fwrite(bi, ffi.sizeof('BITMAPINFOHEADER'), 1, hFile) msvcrt.fwrite(bits, bi.bmiHeader.biSizeImage, 1, hFile) msvcrt.fclose(hFile) else log('Файл не открылся') end
C.ReleaseDC(handle or 0, hdcWindow) C.DeleteObject(hdcMemDC) C.DeleteObject(hbmScreen) end
screen([[C:\screen_desktop.bmp]], 200, 200, 500, 500) -- скрин с экрана screen([[C:\screen_window.bmp]], 200, 200, 500, 500, workwindow()) -- скрин с рабочего окна (может быть перекрыто)
|
|
|
|
DarkMaster |
29.3.2021, 17:09
|
Модератор UOPilot
Сообщений: 9.474
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 27747
Пользователь №: 11.279
|
Захват изображения. Вот так вроде похоже на правду. Пока никуда еще в финды не подсовывал. Утрачено реально дофига, но там было очень много моментов, которые надо было понять и осознать. Восстановлю, конечно, шустрее, чем писать с нуля. getimage
Код local ffi=require "ffi" local rmem=ffi.cast local C=ffi.C
local SRCCOPY = 0x00CC0020 local DIB_RGB_COLORS = 0 local BI_RGB = 0 ffi.cdef[[ typedef long LONG; typedef unsigned short WORD; typedef unsigned long DWORD; typedef unsigned char BYTE; typedef void *LPVOID; typedef struct {DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant;} BITMAPINFOHEADER; typedef struct {BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved;} RGBQUAD; typedef struct {BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1];} BITMAPINFO; int GetDC(int hWnd); int ReleaseDC(int hWnd, int hDC); int SelectObject(int hdc, int h); int CreateCompatibleDC(int hdc); int CreateCompatibleBitmap(int hdc, int cx, int cy); bool DeleteObject(int ho); bool BitBlt(int hdc, int x, int y, int cx, int cy, int hdcSrc, int x1, int y1, unsigned long rop); int GetDIBits(int hdc, int hbm, unsigned int start, unsigned int cLines, LPVOID lpvBits, BITMAPINFO* lpbmi, unsigned int usage);
void free(void *ptr); void *malloc(size_t size); ]]
local ext = {} local internal = {} local images = {}
internal.deleteimage_orig = deleteimage ext.getimage = function(x1, y1, x2, y2, handle, abs_flag) if handle > 2 or handle == 1 then local a, w, h, l w = x2-x1 + 1 h = y2-y1 + 1 local hdcWindow = C.GetDC(handle or 0) -- если хендл не указан, то получим скрин с экрана local hdcMemDC = C.CreateCompatibleDC(hdcWindow) local hbmScreen = C.CreateCompatibleBitmap(hdcWindow, w, h) C.SelectObject(hdcMemDC,hbmScreen) C.BitBlt(hdcMemDC, 0, 0, w, h, hdcWindow, x1, y1, SRCCOPY) -- сохранить в памяти скрин с окна или экрана
local bi = ffi.new('BITMAPINFO', { {ffi.sizeof('BITMAPINFOHEADER'), w, -h, 1, 24, BI_RGB,0,0,0,0,0} }) C.GetDIBits(hdcWindow, hbmScreen, 0, h, nil, bi, DIB_RGB_COLORS) -- узнать какого размера нужен массив
local bitmap_address = ffi.gc(C.malloc(bi.bmiHeader.biSizeImage), C.free) local h_copied = C.GetDIBits(hdcWindow, hbmScreen, 0, h, bitmap_address, bi, DIB_RGB_COLORS) -- получить битовый массив
--return h_copied and ffi.cast("int", bitmap_address) or nil, w, h_copied, math.floor(w*3/4+0.75)*4 if h_copied > 0 then a = tonumber(ffi.cast("int", bitmap_address)) images[a] = {} images[a].handle = handle images[a].hdcWindow = hdcWindow images[a].hdcMemDC = hdcMemDC images[a].hbmScreen = hbmScreen images[a].bitmap_address = bitmap_address
return a, w, h_copied, math.floor(w*3/4+0.75)*4 else return nil end else return internal.getimage_orig(x1, y1, x2, y2, handle, abs_flag) end end
ext.deleteimage = function(address) if images[address] then C.ReleaseDC(images[address].handle, images[address].hdcWindow) C.DeleteObject(images[address].hdcMemDC) C.DeleteObject(images[address].hbmScreen) ffi.C.free(ffi.gc(images[address].bitmap_address, nil)) -- Manually free the memory images[address] = nil else deleteimage_orig(address) end end
Скорре всего: Код C.ReleaseDC(images[address].handle, images[address].hdcWindow) C.DeleteObject(images[address].hdcMemDC) C.DeleteObject(images[address].hbmScreen) Можно выкинуть в getimage и прям там уничтожать, но я пока не тестил. Ну и идейно я делаю замену пилотовских функций с полной обратной совместимостью. Т.е. предполагается: deleteimage = ext.deleteimage getimage = ext.getimage без какого-либо ущерба для старых скриптов. Сообщение отредактировал DarkMaster - 29.3.2021, 17:21
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
Cockney |
29.3.2021, 20:33
|
Master
Сообщений: 1.395
Регистрация: 22.6.2013 Группа: Пользователи Наличность: 21104
Пользователь №: 16.156
|
Цитата(DarkMaster @ 29.3.2021, 17:09) Ну и идейно я делаю замену пилотовских функций с полной обратной совместимостью. Т.е. предполагается: deleteimage = ext.deleteimage getimage = ext.getimage без какого-либо ущерба для старых скриптов.
Без ущерба это классно, но по своему опыту создания точно такого же костыля могу сказать, что правильней сделать кучу маленьких функций, засунуть их в условный core неймспейс, а уже потом из них лепить целевую функцию-замену. Где-то на диске валяются потуги, на плюсы была портирована работа с мышью и клавиатурой. Если надо, могу опубликовать, да и кстати, а почему бы не сделать github проект для данного дела. Вроде 21 год, а версионирование через посты форума.
|
|
|
|
DarkMaster |
29.3.2021, 21:00
|
Модератор UOPilot
Сообщений: 9.474
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 27747
Пользователь №: 11.279
|
Цитата Где-то на диске валяются потуги, на плюсы была портирована работа с мышью и клавиатурой. Если надо, могу опубликовать, да и кстати, а почему бы не сделать github проект для данного дела. Вроде 21 год, а версионирование через посты форума. Планов очень много, идей очень много. Я очень не хочу спешить. У меня появилось желание и возможность - я сидел ковырял некоторые баги пилота, некоторые потерянные возможности при переходе на луа. Если бы не sutra, то узнали бы об этом позже по релизу. Появится смысл - все будет. В целом я хочу сделать достаточно сильный упор на луа и возможность адаптации/прикручивания фишечек намного более нативным и спокойно расширяемым пользователем, форумными скриптами и т.д. Но давай не спешить. Сохранится возможность и желание - все будет. Вариант рассказать вагон баек и оставить все как было - меня не устраивает. Цитата Без ущерба это классно, но по своему опыту создания точно такого же костыля могу сказать, что правильней сделать кучу маленьких функций, засунуть их в условный core неймспейс, а уже потом из них лепить целевую функцию-замену. Есть у меня два массивчика: internal и ext. Оба содержат только функции (не забываем про ограничение на 63 элемента в корне неймспейса в рамках луа). Соответственно ext - некоторый интерфейс поставляемый пользователю, internal - вся реальная обработка, куча фукнций для мелочей и т.д.
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|